xref: /dflybsd-src/contrib/gcc-8.0/gcc/genautomata.c (revision 38fd149817dfbff97799f62fcb70be98c4e32523)
1*38fd1498Szrj /* Pipeline hazard description translator.
2*38fd1498Szrj    Copyright (C) 2000-2018 Free Software Foundation, Inc.
3*38fd1498Szrj 
4*38fd1498Szrj    Written by Vladimir Makarov <vmakarov@redhat.com>
5*38fd1498Szrj 
6*38fd1498Szrj This file is part of GCC.
7*38fd1498Szrj 
8*38fd1498Szrj GCC is free software; you can redistribute it and/or modify it
9*38fd1498Szrj under the terms of the GNU General Public License as published by the
10*38fd1498Szrj Free Software Foundation; either version 3, or (at your option) any
11*38fd1498Szrj later version.
12*38fd1498Szrj 
13*38fd1498Szrj GCC is distributed in the hope that it will be useful, but WITHOUT
14*38fd1498Szrj ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15*38fd1498Szrj FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16*38fd1498Szrj for more details.
17*38fd1498Szrj 
18*38fd1498Szrj You should have received a copy of the GNU General Public License
19*38fd1498Szrj along with GCC; see the file COPYING3.  If not see
20*38fd1498Szrj <http://www.gnu.org/licenses/>.  */
21*38fd1498Szrj 
22*38fd1498Szrj /* References:
23*38fd1498Szrj 
24*38fd1498Szrj    1. The finite state automaton based pipeline hazard recognizer and
25*38fd1498Szrj       instruction scheduler in GCC.  V. Makarov.  Proceedings of GCC
26*38fd1498Szrj       summit, 2003.
27*38fd1498Szrj 
28*38fd1498Szrj    2. Detecting pipeline structural hazards quickly. T. Proebsting,
29*38fd1498Szrj       C. Fraser. Proceedings of ACM SIGPLAN-SIGACT Symposium on
30*38fd1498Szrj       Principles of Programming Languages, pages 280--286, 1994.
31*38fd1498Szrj 
32*38fd1498Szrj       This article is a good start point to understand usage of finite
33*38fd1498Szrj       state automata for pipeline hazard recognizers.  But I'd
34*38fd1498Szrj       recommend the 1st and 3rd article for more deep understanding.
35*38fd1498Szrj 
36*38fd1498Szrj    3. Efficient Instruction Scheduling Using Finite State Automata:
37*38fd1498Szrj       V. Bala and N. Rubin, Proceedings of MICRO-28.  This is the best
38*38fd1498Szrj       article about usage of finite state automata for pipeline hazard
39*38fd1498Szrj       recognizers.
40*38fd1498Szrj 
41*38fd1498Szrj    The current implementation is described in the 1st article and it
42*38fd1498Szrj    is different from the 3rd article in the following:
43*38fd1498Szrj 
44*38fd1498Szrj    1. New operator `|' (alternative) is permitted in functional unit
45*38fd1498Szrj       reservation which can be treated deterministically and
46*38fd1498Szrj       non-deterministically.
47*38fd1498Szrj 
48*38fd1498Szrj    2. Possibility of usage of nondeterministic automata too.
49*38fd1498Szrj 
50*38fd1498Szrj    3. Possibility to query functional unit reservations for given
51*38fd1498Szrj       automaton state.
52*38fd1498Szrj 
53*38fd1498Szrj    4. Several constructions to describe impossible reservations
54*38fd1498Szrj       (`exclusion_set', `presence_set', `final_presence_set',
55*38fd1498Szrj       `absence_set', and `final_absence_set').
56*38fd1498Szrj 
57*38fd1498Szrj    5. No reverse automata are generated.  Trace instruction scheduling
58*38fd1498Szrj       requires this.  It can be easily added in the future if we
59*38fd1498Szrj       really need this.
60*38fd1498Szrj 
61*38fd1498Szrj    6. Union of automaton states are not generated yet.  It is planned
62*38fd1498Szrj       to be implemented.  Such feature is needed to make more accurate
63*38fd1498Szrj       interlock insn scheduling to get state describing functional
64*38fd1498Szrj       unit reservation in a joint CFG point.  */
65*38fd1498Szrj 
66*38fd1498Szrj /* This file code processes constructions of machine description file
67*38fd1498Szrj    which describes automaton used for recognition of processor pipeline
68*38fd1498Szrj    hazards by insn scheduler and can be used for other tasks (such as
69*38fd1498Szrj    VLIW insn packing.
70*38fd1498Szrj 
71*38fd1498Szrj    The translator functions `gen_cpu_unit', `gen_query_cpu_unit',
72*38fd1498Szrj    `gen_bypass', `gen_excl_set', `gen_presence_set',
73*38fd1498Szrj    `gen_final_presence_set', `gen_absence_set',
74*38fd1498Szrj    `gen_final_absence_set', `gen_automaton', `gen_automata_option',
75*38fd1498Szrj    `gen_reserv', `gen_insn_reserv' are called from file
76*38fd1498Szrj    `genattrtab.c'.  They transform RTL constructions describing
77*38fd1498Szrj    automata in .md file into internal representation convenient for
78*38fd1498Szrj    further processing.
79*38fd1498Szrj 
80*38fd1498Szrj    The translator major function `expand_automata' processes the
81*38fd1498Szrj    description internal representation into finite state automaton.
82*38fd1498Szrj    It can be divided on:
83*38fd1498Szrj 
84*38fd1498Szrj      o checking correctness of the automaton pipeline description
85*38fd1498Szrj        (major function is `check_all_description').
86*38fd1498Szrj 
87*38fd1498Szrj      o generating automaton (automata) from the description (major
88*38fd1498Szrj        function is `make_automaton').
89*38fd1498Szrj 
90*38fd1498Szrj      o optional transformation of nondeterministic finite state
91*38fd1498Szrj        automata into deterministic ones if the alternative operator
92*38fd1498Szrj        `|' is treated nondeterministically in the description (major
93*38fd1498Szrj        function is NDFA_to_DFA).
94*38fd1498Szrj 
95*38fd1498Szrj      o optional minimization of the finite state automata by merging
96*38fd1498Szrj        equivalent automaton states (major function is `minimize_DFA').
97*38fd1498Szrj 
98*38fd1498Szrj      o forming tables (some as comb vectors) and attributes
99*38fd1498Szrj        representing the automata (functions output_..._table).
100*38fd1498Szrj 
101*38fd1498Szrj    Function `write_automata' outputs the created finite state
102*38fd1498Szrj    automaton as different tables and functions which works with the
103*38fd1498Szrj    automata to inquire automaton state and to change its state.  These
104*38fd1498Szrj    function are used by gcc instruction scheduler and may be some
105*38fd1498Szrj    other gcc code.  */
106*38fd1498Szrj 
107*38fd1498Szrj #include "bconfig.h"
108*38fd1498Szrj #include "system.h"
109*38fd1498Szrj #include "coretypes.h"
110*38fd1498Szrj #include "tm.h"
111*38fd1498Szrj #include "rtl.h"
112*38fd1498Szrj #include "obstack.h"
113*38fd1498Szrj #include "errors.h"
114*38fd1498Szrj #include "gensupport.h"
115*38fd1498Szrj 
116*38fd1498Szrj #include <math.h>
117*38fd1498Szrj #include "fnmatch.h"
118*38fd1498Szrj 
119*38fd1498Szrj #ifndef CHAR_BIT
120*38fd1498Szrj #define CHAR_BIT 8
121*38fd1498Szrj #endif
122*38fd1498Szrj 
123*38fd1498Szrj /* Positions in machine description file.  Now they are not used.  But
124*38fd1498Szrj    they could be used in the future for better diagnostic messages.  */
125*38fd1498Szrj typedef int pos_t;
126*38fd1498Szrj 
127*38fd1498Szrj /* The following is element of vector of current (and planned in the
128*38fd1498Szrj    future) functional unit reservations.  */
129*38fd1498Szrj typedef unsigned HOST_WIDE_INT set_el_t;
130*38fd1498Szrj 
131*38fd1498Szrj /* Reservations of function units are represented by value of the following
132*38fd1498Szrj    type.  */
133*38fd1498Szrj typedef set_el_t *reserv_sets_t;
134*38fd1498Szrj typedef const set_el_t *const_reserv_sets_t;
135*38fd1498Szrj 
136*38fd1498Szrj /* The following structure describes a ticker.  */
137*38fd1498Szrj struct ticker
138*38fd1498Szrj {
139*38fd1498Szrj   /* The following member value is time of the ticker creation with
140*38fd1498Szrj      taking into account time when the ticker is off.  Active time of
141*38fd1498Szrj      the ticker is current time minus the value.  */
142*38fd1498Szrj   int modified_creation_time;
143*38fd1498Szrj   /* The following member value is time (incremented by one) when the
144*38fd1498Szrj      ticker was off.  Zero value means that now the ticker is on.  */
145*38fd1498Szrj   int incremented_off_time;
146*38fd1498Szrj };
147*38fd1498Szrj 
148*38fd1498Szrj /* The ticker is represented by the following type.  */
149*38fd1498Szrj typedef struct ticker ticker_t;
150*38fd1498Szrj 
151*38fd1498Szrj /* The following type describes elements of output vectors.  */
152*38fd1498Szrj typedef HOST_WIDE_INT vect_el_t;
153*38fd1498Szrj 
154*38fd1498Szrj /* Forward declaration of structures of internal representation of
155*38fd1498Szrj    pipeline description based on NDFA.  */
156*38fd1498Szrj 
157*38fd1498Szrj struct unit_decl;
158*38fd1498Szrj struct bypass_decl;
159*38fd1498Szrj struct result_decl;
160*38fd1498Szrj struct automaton_decl;
161*38fd1498Szrj struct unit_pattern_rel_decl;
162*38fd1498Szrj struct reserv_decl;
163*38fd1498Szrj struct insn_reserv_decl;
164*38fd1498Szrj struct decl;
165*38fd1498Szrj struct unit_regexp;
166*38fd1498Szrj struct result_regexp;
167*38fd1498Szrj struct reserv_regexp;
168*38fd1498Szrj struct nothing_regexp;
169*38fd1498Szrj struct sequence_regexp;
170*38fd1498Szrj struct repeat_regexp;
171*38fd1498Szrj struct allof_regexp;
172*38fd1498Szrj struct oneof_regexp;
173*38fd1498Szrj struct regexp;
174*38fd1498Szrj struct description;
175*38fd1498Szrj struct unit_set_el;
176*38fd1498Szrj struct pattern_set_el;
177*38fd1498Szrj struct pattern_reserv;
178*38fd1498Szrj struct state;
179*38fd1498Szrj struct alt_state;
180*38fd1498Szrj struct arc;
181*38fd1498Szrj struct ainsn;
182*38fd1498Szrj struct automaton;
183*38fd1498Szrj struct state_ainsn_table;
184*38fd1498Szrj 
185*38fd1498Szrj /* The following typedefs are for brevity.  */
186*38fd1498Szrj typedef struct unit_decl *unit_decl_t;
187*38fd1498Szrj typedef const struct unit_decl *const_unit_decl_t;
188*38fd1498Szrj typedef struct decl *decl_t;
189*38fd1498Szrj typedef const struct decl *const_decl_t;
190*38fd1498Szrj typedef struct regexp *regexp_t;
191*38fd1498Szrj typedef struct unit_set_el *unit_set_el_t;
192*38fd1498Szrj typedef struct pattern_set_el *pattern_set_el_t;
193*38fd1498Szrj typedef struct pattern_reserv *pattern_reserv_t;
194*38fd1498Szrj typedef struct alt_state *alt_state_t;
195*38fd1498Szrj typedef struct state *state_t;
196*38fd1498Szrj typedef const struct state *const_state_t;
197*38fd1498Szrj typedef struct arc *arc_t;
198*38fd1498Szrj typedef struct ainsn *ainsn_t;
199*38fd1498Szrj typedef struct automaton *automaton_t;
200*38fd1498Szrj typedef struct automata_list_el *automata_list_el_t;
201*38fd1498Szrj typedef const struct automata_list_el *const_automata_list_el_t;
202*38fd1498Szrj typedef struct state_ainsn_table *state_ainsn_table_t;
203*38fd1498Szrj 
204*38fd1498Szrj /* Undefined position.  */
205*38fd1498Szrj static pos_t no_pos = 0;
206*38fd1498Szrj 
207*38fd1498Szrj /* All IR is stored in the following obstack.  */
208*38fd1498Szrj static struct obstack irp;
209*38fd1498Szrj 
210*38fd1498Szrj 
211*38fd1498Szrj /* Declare vector types for various data structures: */
212*38fd1498Szrj 
213*38fd1498Szrj 
214*38fd1498Szrj typedef vec<vect_el_t> vla_hwint_t;
215*38fd1498Szrj 
216*38fd1498Szrj /* Forward declarations of functions used before their definitions, only.  */
217*38fd1498Szrj static regexp_t gen_regexp_sequence    (const char *);
218*38fd1498Szrj static void reserv_sets_or             (reserv_sets_t, reserv_sets_t,
219*38fd1498Szrj 				        reserv_sets_t);
220*38fd1498Szrj static reserv_sets_t get_excl_set      (reserv_sets_t);
221*38fd1498Szrj static int check_presence_pattern_sets (reserv_sets_t,
222*38fd1498Szrj 					reserv_sets_t, int);
223*38fd1498Szrj static int check_absence_pattern_sets  (reserv_sets_t, reserv_sets_t,
224*38fd1498Szrj 					int);
225*38fd1498Szrj static arc_t first_out_arc             (const_state_t);
226*38fd1498Szrj static arc_t next_out_arc              (arc_t);
227*38fd1498Szrj 
228*38fd1498Szrj 
229*38fd1498Szrj 
230*38fd1498Szrj /* Options with the following names can be set up in automata_option
231*38fd1498Szrj    construction.  Because the strings occur more one time we use the
232*38fd1498Szrj    macros.  */
233*38fd1498Szrj 
234*38fd1498Szrj #define NO_MINIMIZATION_OPTION "-no-minimization"
235*38fd1498Szrj #define TIME_OPTION "-time"
236*38fd1498Szrj #define STATS_OPTION "-stats"
237*38fd1498Szrj #define V_OPTION "-v"
238*38fd1498Szrj #define W_OPTION "-w"
239*38fd1498Szrj #define NDFA_OPTION "-ndfa"
240*38fd1498Szrj #define COLLAPSE_OPTION "-collapse-ndfa"
241*38fd1498Szrj #define NO_COMB_OPTION "-no-comb-vect"
242*38fd1498Szrj #define PROGRESS_OPTION "-progress"
243*38fd1498Szrj 
244*38fd1498Szrj /* The following flags are set up by function `initiate_automaton_gen'.  */
245*38fd1498Szrj 
246*38fd1498Szrj /* Make automata with nondeterministic reservation by insns (`-ndfa').  */
247*38fd1498Szrj static int ndfa_flag;
248*38fd1498Szrj 
249*38fd1498Szrj /* When making an NDFA, produce additional transitions that collapse
250*38fd1498Szrj    NDFA state into a deterministic one suitable for querying CPU units.
251*38fd1498Szrj    Provide advance-state transitions only for deterministic states.  */
252*38fd1498Szrj static int collapse_flag;
253*38fd1498Szrj 
254*38fd1498Szrj /* Do not make minimization of DFA (`-no-minimization').  */
255*38fd1498Szrj static int no_minimization_flag;
256*38fd1498Szrj 
257*38fd1498Szrj /* Do not try to generate a comb vector (`-no-comb-vect').  */
258*38fd1498Szrj static int no_comb_flag;
259*38fd1498Szrj 
260*38fd1498Szrj /* Value of this variable is number of automata being generated.  The
261*38fd1498Szrj    actual number of automata may be less this value if there is not
262*38fd1498Szrj    sufficient number of units.  This value is defined by argument of
263*38fd1498Szrj    option `-split' or by constructions automaton if the value is zero
264*38fd1498Szrj    (it is default value of the argument).  */
265*38fd1498Szrj static int split_argument;
266*38fd1498Szrj 
267*38fd1498Szrj /* Flag of output time statistics (`-time').  */
268*38fd1498Szrj static int time_flag;
269*38fd1498Szrj 
270*38fd1498Szrj /* Flag of automata statistics (`-stats').  */
271*38fd1498Szrj static int stats_flag;
272*38fd1498Szrj 
273*38fd1498Szrj /* Flag of creation of description file which contains description of
274*38fd1498Szrj    result automaton and statistics information (`-v').  */
275*38fd1498Szrj static int v_flag;
276*38fd1498Szrj 
277*38fd1498Szrj /* Flag of output of a progress bar showing how many states were
278*38fd1498Szrj    generated so far for automaton being processed (`-progress').  */
279*38fd1498Szrj static int progress_flag;
280*38fd1498Szrj 
281*38fd1498Szrj /* Flag of generating warning instead of error for non-critical errors
282*38fd1498Szrj    (`-w').  */
283*38fd1498Szrj static int w_flag;
284*38fd1498Szrj 
285*38fd1498Szrj 
286*38fd1498Szrj /* Output file for pipeline hazard recognizer (PHR) being generated.
287*38fd1498Szrj    The value is NULL if the file is not defined.  */
288*38fd1498Szrj static FILE *output_file;
289*38fd1498Szrj 
290*38fd1498Szrj /* Description file of PHR.  The value is NULL if the file is not
291*38fd1498Szrj    created.  */
292*38fd1498Szrj static FILE *output_description_file;
293*38fd1498Szrj 
294*38fd1498Szrj /* PHR description file name.  */
295*38fd1498Szrj static char *output_description_file_name;
296*38fd1498Szrj 
297*38fd1498Szrj /* Value of the following variable is node representing description
298*38fd1498Szrj    being processed.  This is start point of IR.  */
299*38fd1498Szrj static struct description *description;
300*38fd1498Szrj 
301*38fd1498Szrj 
302*38fd1498Szrj 
303*38fd1498Szrj /* This page contains description of IR structure (nodes).  */
304*38fd1498Szrj 
305*38fd1498Szrj enum decl_mode
306*38fd1498Szrj {
307*38fd1498Szrj   dm_unit,
308*38fd1498Szrj   dm_bypass,
309*38fd1498Szrj   dm_automaton,
310*38fd1498Szrj   dm_excl,
311*38fd1498Szrj   dm_presence,
312*38fd1498Szrj   dm_absence,
313*38fd1498Szrj   dm_reserv,
314*38fd1498Szrj   dm_insn_reserv
315*38fd1498Szrj };
316*38fd1498Szrj 
317*38fd1498Szrj /* This describes define_cpu_unit and define_query_cpu_unit (see file
318*38fd1498Szrj    rtl.def).  */
319*38fd1498Szrj struct unit_decl
320*38fd1498Szrj {
321*38fd1498Szrj   const char *name;
322*38fd1498Szrj   /* NULL if the automaton name is absent.  */
323*38fd1498Szrj   const char *automaton_name;
324*38fd1498Szrj   /* If the following value is not zero, the cpu unit reservation is
325*38fd1498Szrj      described in define_query_cpu_unit.  */
326*38fd1498Szrj   char query_p;
327*38fd1498Szrj 
328*38fd1498Szrj   /* The following fields are defined by checker.  */
329*38fd1498Szrj 
330*38fd1498Szrj   /* The following field value is nonzero if the unit is used in an
331*38fd1498Szrj      regexp.  */
332*38fd1498Szrj   char unit_is_used;
333*38fd1498Szrj 
334*38fd1498Szrj   /* The following field value is order number (0, 1, ...) of given
335*38fd1498Szrj      unit.  */
336*38fd1498Szrj   int unit_num;
337*38fd1498Szrj   /* The following field value is corresponding declaration of
338*38fd1498Szrj      automaton which was given in description.  If the field value is
339*38fd1498Szrj      NULL then automaton in the unit declaration was absent.  */
340*38fd1498Szrj   struct automaton_decl *automaton_decl;
341*38fd1498Szrj   /* The following field value is maximal cycle number (1, ...) on
342*38fd1498Szrj      which given unit occurs in insns.  Zero value means that given
343*38fd1498Szrj      unit is not used in insns.  */
344*38fd1498Szrj   int max_occ_cycle_num;
345*38fd1498Szrj   /* The following field value is minimal cycle number (0, ...) on
346*38fd1498Szrj      which given unit occurs in insns.  -1 value means that given
347*38fd1498Szrj      unit is not used in insns.  */
348*38fd1498Szrj   int min_occ_cycle_num;
349*38fd1498Szrj   /* The following list contains units which conflict with given
350*38fd1498Szrj      unit.  */
351*38fd1498Szrj   unit_set_el_t excl_list;
352*38fd1498Szrj   /* The following list contains patterns which are required to
353*38fd1498Szrj      reservation of given unit.  */
354*38fd1498Szrj   pattern_set_el_t presence_list;
355*38fd1498Szrj   pattern_set_el_t final_presence_list;
356*38fd1498Szrj   /* The following list contains patterns which should be not present
357*38fd1498Szrj      in reservation for given unit.  */
358*38fd1498Szrj   pattern_set_el_t absence_list;
359*38fd1498Szrj   pattern_set_el_t final_absence_list;
360*38fd1498Szrj   /* The following is used only when `query_p' has nonzero value.
361*38fd1498Szrj      This is query number for the unit.  */
362*38fd1498Szrj   int query_num;
363*38fd1498Szrj   /* The following is the last cycle on which the unit was checked for
364*38fd1498Szrj      correct distributions of units to automata in a regexp.  */
365*38fd1498Szrj   int last_distribution_check_cycle;
366*38fd1498Szrj 
367*38fd1498Szrj   /* The following fields are defined by automaton generator.  */
368*38fd1498Szrj 
369*38fd1498Szrj   /* The following field value is number of the automaton to which
370*38fd1498Szrj      given unit belongs.  */
371*38fd1498Szrj   int corresponding_automaton_num;
372*38fd1498Szrj   /* If the following value is not zero, the cpu unit is present in a
373*38fd1498Szrj      `exclusion_set' or in right part of a `presence_set',
374*38fd1498Szrj      `final_presence_set', `absence_set', and
375*38fd1498Szrj      `final_absence_set'define_query_cpu_unit.  */
376*38fd1498Szrj   char in_set_p;
377*38fd1498Szrj };
378*38fd1498Szrj 
379*38fd1498Szrj /* This describes define_bypass (see file rtl.def).  */
380*38fd1498Szrj struct bypass_decl
381*38fd1498Szrj {
382*38fd1498Szrj   int latency;
383*38fd1498Szrj   const char *out_pattern;
384*38fd1498Szrj   const char *in_pattern;
385*38fd1498Szrj   const char *bypass_guard_name;
386*38fd1498Szrj 
387*38fd1498Szrj   /* The following fields are defined by checker.  */
388*38fd1498Szrj 
389*38fd1498Szrj   /* output and input insns of given bypass.  */
390*38fd1498Szrj   struct insn_reserv_decl *out_insn_reserv;
391*38fd1498Szrj   struct insn_reserv_decl *in_insn_reserv;
392*38fd1498Szrj   /* The next bypass for given output insn.  */
393*38fd1498Szrj   struct bypass_decl *next;
394*38fd1498Szrj };
395*38fd1498Szrj 
396*38fd1498Szrj /* This describes define_automaton (see file rtl.def).  */
397*38fd1498Szrj struct automaton_decl
398*38fd1498Szrj {
399*38fd1498Szrj   const char *name;
400*38fd1498Szrj 
401*38fd1498Szrj   /* The following fields are defined by automaton generator.  */
402*38fd1498Szrj 
403*38fd1498Szrj   /* The following field value is nonzero if the automaton is used in
404*38fd1498Szrj      an regexp definition.  */
405*38fd1498Szrj   char automaton_is_used;
406*38fd1498Szrj 
407*38fd1498Szrj   /* The following fields are defined by checker.  */
408*38fd1498Szrj 
409*38fd1498Szrj   /* The following field value is the corresponding automaton.  This
410*38fd1498Szrj      field is not NULL only if the automaton is present in unit
411*38fd1498Szrj      declarations and the automatic partition on automata is not
412*38fd1498Szrj      used.  */
413*38fd1498Szrj   automaton_t corresponding_automaton;
414*38fd1498Szrj };
415*38fd1498Szrj 
416*38fd1498Szrj /* This describes exclusion relations: exclusion_set (see file
417*38fd1498Szrj    rtl.def).  */
418*38fd1498Szrj struct excl_rel_decl
419*38fd1498Szrj {
420*38fd1498Szrj   int all_names_num;
421*38fd1498Szrj   int first_list_length;
422*38fd1498Szrj   char *names [1];
423*38fd1498Szrj };
424*38fd1498Szrj 
425*38fd1498Szrj /* This describes unit relations: [final_]presence_set or
426*38fd1498Szrj    [final_]absence_set (see file rtl.def).  */
427*38fd1498Szrj struct unit_pattern_rel_decl
428*38fd1498Szrj {
429*38fd1498Szrj   int final_p;
430*38fd1498Szrj   int names_num;
431*38fd1498Szrj   int patterns_num;
432*38fd1498Szrj   char **names;
433*38fd1498Szrj   char ***patterns;
434*38fd1498Szrj };
435*38fd1498Szrj 
436*38fd1498Szrj /* This describes define_reservation (see file rtl.def).  */
437*38fd1498Szrj struct reserv_decl
438*38fd1498Szrj {
439*38fd1498Szrj   const char *name;
440*38fd1498Szrj   regexp_t regexp;
441*38fd1498Szrj 
442*38fd1498Szrj   /* The following fields are defined by checker.  */
443*38fd1498Szrj 
444*38fd1498Szrj   /* The following field value is nonzero if the unit is used in an
445*38fd1498Szrj      regexp.  */
446*38fd1498Szrj   char reserv_is_used;
447*38fd1498Szrj   /* The following field is used to check up cycle in expression
448*38fd1498Szrj      definition.  */
449*38fd1498Szrj   int loop_pass_num;
450*38fd1498Szrj };
451*38fd1498Szrj 
452*38fd1498Szrj /* This describes define_insn_reservation (see file rtl.def).  */
453*38fd1498Szrj struct insn_reserv_decl
454*38fd1498Szrj {
455*38fd1498Szrj   rtx condexp;
456*38fd1498Szrj   int default_latency;
457*38fd1498Szrj   regexp_t regexp;
458*38fd1498Szrj   const char *name;
459*38fd1498Szrj 
460*38fd1498Szrj   /* The following fields are defined by checker.  */
461*38fd1498Szrj 
462*38fd1498Szrj   /* The following field value is order number (0, 1, ...) of given
463*38fd1498Szrj      insn.  */
464*38fd1498Szrj   int insn_num;
465*38fd1498Szrj   /* The following field value is list of bypasses in which given insn
466*38fd1498Szrj      is output insn.  Bypasses with the same input insn stay one after
467*38fd1498Szrj      another in the list in the same order as their occurrences in the
468*38fd1498Szrj      description but the bypass without a guard stays always the last
469*38fd1498Szrj      in a row of bypasses with the same input insn.  */
470*38fd1498Szrj   struct bypass_decl *bypass_list;
471*38fd1498Szrj 
472*38fd1498Szrj   /* The following fields are defined by automaton generator.  */
473*38fd1498Szrj 
474*38fd1498Szrj   /* The following field is the insn regexp transformed that
475*38fd1498Szrj      the regexp has not optional regexp, repetition regexp, and an
476*38fd1498Szrj      reservation name (i.e. reservation identifiers are changed by the
477*38fd1498Szrj      corresponding regexp) and all alternations are the top level
478*38fd1498Szrj      of the regexp.  The value can be NULL only if it is special
479*38fd1498Szrj      insn `cycle advancing'.  */
480*38fd1498Szrj   regexp_t transformed_regexp;
481*38fd1498Szrj   /* The following field value is list of arcs marked given
482*38fd1498Szrj      insn.  The field is used in transformation NDFA -> DFA.  */
483*38fd1498Szrj   arc_t arcs_marked_by_insn;
484*38fd1498Szrj   /* The two following fields are used during minimization of a finite state
485*38fd1498Szrj      automaton.  */
486*38fd1498Szrj   /* The field value is number of equivalence class of state into
487*38fd1498Szrj      which arc marked by given insn enters from a state (fixed during
488*38fd1498Szrj      an automaton minimization).  */
489*38fd1498Szrj   int equiv_class_num;
490*38fd1498Szrj   /* The following member value is the list to automata which can be
491*38fd1498Szrj      changed by the insn issue.  */
492*38fd1498Szrj   automata_list_el_t important_automata_list;
493*38fd1498Szrj   /* The following member is used to process insn once for output.  */
494*38fd1498Szrj   int processed_p;
495*38fd1498Szrj };
496*38fd1498Szrj 
497*38fd1498Szrj /* This contains a declaration mentioned above.  */
498*38fd1498Szrj struct decl
499*38fd1498Szrj {
500*38fd1498Szrj   /* What node in the union? */
501*38fd1498Szrj   enum decl_mode mode;
502*38fd1498Szrj   pos_t pos;
503*38fd1498Szrj   union
504*38fd1498Szrj   {
505*38fd1498Szrj     struct unit_decl unit;
506*38fd1498Szrj     struct bypass_decl bypass;
507*38fd1498Szrj     struct automaton_decl automaton;
508*38fd1498Szrj     struct excl_rel_decl excl;
509*38fd1498Szrj     struct unit_pattern_rel_decl presence;
510*38fd1498Szrj     struct unit_pattern_rel_decl absence;
511*38fd1498Szrj     struct reserv_decl reserv;
512*38fd1498Szrj     struct insn_reserv_decl insn_reserv;
513*38fd1498Szrj   } decl;
514*38fd1498Szrj };
515*38fd1498Szrj 
516*38fd1498Szrj /* The following structures represent parsed reservation strings.  */
517*38fd1498Szrj enum regexp_mode
518*38fd1498Szrj {
519*38fd1498Szrj   rm_unit,
520*38fd1498Szrj   rm_reserv,
521*38fd1498Szrj   rm_nothing,
522*38fd1498Szrj   rm_sequence,
523*38fd1498Szrj   rm_repeat,
524*38fd1498Szrj   rm_allof,
525*38fd1498Szrj   rm_oneof
526*38fd1498Szrj };
527*38fd1498Szrj 
528*38fd1498Szrj /* Cpu unit in reservation.  */
529*38fd1498Szrj struct unit_regexp
530*38fd1498Szrj {
531*38fd1498Szrj   const char *name;
532*38fd1498Szrj   unit_decl_t unit_decl;
533*38fd1498Szrj };
534*38fd1498Szrj 
535*38fd1498Szrj /* Define_reservation in a reservation.  */
536*38fd1498Szrj struct reserv_regexp
537*38fd1498Szrj {
538*38fd1498Szrj   const char *name;
539*38fd1498Szrj   struct reserv_decl *reserv_decl;
540*38fd1498Szrj };
541*38fd1498Szrj 
542*38fd1498Szrj /* Absence of reservation (represented by string `nothing').  */
543*38fd1498Szrj struct nothing_regexp
544*38fd1498Szrj {
545*38fd1498Szrj   /* This used to be empty but ISO C doesn't allow that.  */
546*38fd1498Szrj   char unused;
547*38fd1498Szrj };
548*38fd1498Szrj 
549*38fd1498Szrj /* Representation of reservations separated by ',' (see file
550*38fd1498Szrj    rtl.def).  */
551*38fd1498Szrj struct sequence_regexp
552*38fd1498Szrj {
553*38fd1498Szrj   int regexps_num;
554*38fd1498Szrj   regexp_t regexps [1];
555*38fd1498Szrj };
556*38fd1498Szrj 
557*38fd1498Szrj /* Representation of construction `repeat' (see file rtl.def).  */
558*38fd1498Szrj struct repeat_regexp
559*38fd1498Szrj {
560*38fd1498Szrj   int repeat_num;
561*38fd1498Szrj   regexp_t regexp;
562*38fd1498Szrj };
563*38fd1498Szrj 
564*38fd1498Szrj /* Representation of reservations separated by '+' (see file
565*38fd1498Szrj    rtl.def).  */
566*38fd1498Szrj struct allof_regexp
567*38fd1498Szrj {
568*38fd1498Szrj   int regexps_num;
569*38fd1498Szrj   regexp_t regexps [1];
570*38fd1498Szrj };
571*38fd1498Szrj 
572*38fd1498Szrj /* Representation of reservations separated by '|' (see file
573*38fd1498Szrj    rtl.def).  */
574*38fd1498Szrj struct oneof_regexp
575*38fd1498Szrj {
576*38fd1498Szrj   int regexps_num;
577*38fd1498Szrj   regexp_t regexps [1];
578*38fd1498Szrj };
579*38fd1498Szrj 
580*38fd1498Szrj /* Representation of a reservation string.  */
581*38fd1498Szrj struct regexp
582*38fd1498Szrj {
583*38fd1498Szrj   /* What node in the union? */
584*38fd1498Szrj   enum regexp_mode mode;
585*38fd1498Szrj   pos_t pos;
586*38fd1498Szrj   union
587*38fd1498Szrj   {
588*38fd1498Szrj     struct unit_regexp unit;
589*38fd1498Szrj     struct reserv_regexp reserv;
590*38fd1498Szrj     struct nothing_regexp nothing;
591*38fd1498Szrj     struct sequence_regexp sequence;
592*38fd1498Szrj     struct repeat_regexp repeat;
593*38fd1498Szrj     struct allof_regexp allof;
594*38fd1498Szrj     struct oneof_regexp oneof;
595*38fd1498Szrj   } regexp;
596*38fd1498Szrj };
597*38fd1498Szrj 
598*38fd1498Szrj /* Represents description of pipeline hazard description based on
599*38fd1498Szrj    NDFA.  */
600*38fd1498Szrj struct description
601*38fd1498Szrj {
602*38fd1498Szrj   int decls_num, normal_decls_num;
603*38fd1498Szrj 
604*38fd1498Szrj   /* The following fields are defined by checker.  */
605*38fd1498Szrj 
606*38fd1498Szrj   /* The following fields values are correspondingly number of all
607*38fd1498Szrj      units, query units, and insns in the description.  */
608*38fd1498Szrj   int units_num;
609*38fd1498Szrj   int query_units_num;
610*38fd1498Szrj   int insns_num;
611*38fd1498Szrj   /* The following field value is max length (in cycles) of
612*38fd1498Szrj      reservations of insns.  The field value is defined only for
613*38fd1498Szrj      correct programs.  */
614*38fd1498Szrj   int max_insn_reserv_cycles;
615*38fd1498Szrj 
616*38fd1498Szrj   /* The following fields are defined by automaton generator.  */
617*38fd1498Szrj 
618*38fd1498Szrj   /* The following field value is the first automaton.  */
619*38fd1498Szrj   automaton_t first_automaton;
620*38fd1498Szrj 
621*38fd1498Szrj   /* The following field is created by pipeline hazard parser and
622*38fd1498Szrj      contains all declarations.  We allocate additional entries for
623*38fd1498Szrj      two special insns which are added by the automaton generator.  */
624*38fd1498Szrj   decl_t decls [1];
625*38fd1498Szrj };
626*38fd1498Szrj 
627*38fd1498Szrj 
628*38fd1498Szrj /* The following nodes are created in automaton checker.  */
629*38fd1498Szrj 
630*38fd1498Szrj /* The following nodes represent exclusion set for cpu units.  Each
631*38fd1498Szrj    element is accessed through only one excl_list.  */
632*38fd1498Szrj struct unit_set_el
633*38fd1498Szrj {
634*38fd1498Szrj   unit_decl_t unit_decl;
635*38fd1498Szrj   unit_set_el_t next_unit_set_el;
636*38fd1498Szrj };
637*38fd1498Szrj 
638*38fd1498Szrj /* The following nodes represent presence or absence pattern for cpu
639*38fd1498Szrj    units.  Each element is accessed through only one presence_list or
640*38fd1498Szrj    absence_list.  */
641*38fd1498Szrj struct pattern_set_el
642*38fd1498Szrj {
643*38fd1498Szrj   /* The number of units in unit_decls.  */
644*38fd1498Szrj   int units_num;
645*38fd1498Szrj   /* The units forming the pattern.  */
646*38fd1498Szrj   struct unit_decl **unit_decls;
647*38fd1498Szrj   pattern_set_el_t next_pattern_set_el;
648*38fd1498Szrj };
649*38fd1498Szrj 
650*38fd1498Szrj 
651*38fd1498Szrj /* The following nodes are created in automaton generator.  */
652*38fd1498Szrj 
653*38fd1498Szrj 
654*38fd1498Szrj /* The following nodes represent presence or absence pattern for cpu
655*38fd1498Szrj    units.  Each element is accessed through only one element of
656*38fd1498Szrj    unit_presence_set_table or unit_absence_set_table.  */
657*38fd1498Szrj struct pattern_reserv
658*38fd1498Szrj {
659*38fd1498Szrj   reserv_sets_t reserv;
660*38fd1498Szrj   pattern_reserv_t next_pattern_reserv;
661*38fd1498Szrj };
662*38fd1498Szrj 
663*38fd1498Szrj /* The following node type describes state automaton.  The state may
664*38fd1498Szrj    be deterministic or non-deterministic.  Non-deterministic state has
665*38fd1498Szrj    several component states which represent alternative cpu units
666*38fd1498Szrj    reservations.  The state also is used for describing a
667*38fd1498Szrj    deterministic reservation of automaton insn.  */
668*38fd1498Szrj struct state
669*38fd1498Szrj {
670*38fd1498Szrj   /* The following member value is nonzero if there is a transition by
671*38fd1498Szrj      cycle advancing.  */
672*38fd1498Szrj   int new_cycle_p;
673*38fd1498Szrj   /* The following field is list of processor unit reservations on
674*38fd1498Szrj      each cycle.  */
675*38fd1498Szrj   reserv_sets_t reservs;
676*38fd1498Szrj   /* The following field is unique number of given state between other
677*38fd1498Szrj      states.  */
678*38fd1498Szrj   int unique_num;
679*38fd1498Szrj   /* The following field value is automaton to which given state
680*38fd1498Szrj      belongs.  */
681*38fd1498Szrj   automaton_t automaton;
682*38fd1498Szrj   /* The following field value is the first arc output from given
683*38fd1498Szrj      state.  */
684*38fd1498Szrj   arc_t first_out_arc;
685*38fd1498Szrj   unsigned int num_out_arcs;
686*38fd1498Szrj   /* The following field is used to form NDFA.  */
687*38fd1498Szrj   char it_was_placed_in_stack_for_NDFA_forming;
688*38fd1498Szrj   /* The following field is used to form DFA.  */
689*38fd1498Szrj   char it_was_placed_in_stack_for_DFA_forming;
690*38fd1498Szrj   /* The following field is used to transform NDFA to DFA and DFA
691*38fd1498Szrj      minimization.  The field value is not NULL if the state is a
692*38fd1498Szrj      compound state.  In this case the value of field `unit_sets_list'
693*38fd1498Szrj      is NULL.  All states in the list are in the hash table.  The list
694*38fd1498Szrj      is formed through field `next_sorted_alt_state'.  We should
695*38fd1498Szrj      support only one level of nesting state.  */
696*38fd1498Szrj   alt_state_t component_states;
697*38fd1498Szrj   /* The following field is used for passing graph of states.  */
698*38fd1498Szrj   int pass_num;
699*38fd1498Szrj   /* The list of states belonging to one equivalence class is formed
700*38fd1498Szrj      with the aid of the following field.  */
701*38fd1498Szrj   state_t next_equiv_class_state;
702*38fd1498Szrj   /* The two following fields are used during minimization of a finite
703*38fd1498Szrj      state automaton.  */
704*38fd1498Szrj   int equiv_class_num_1, equiv_class_num_2;
705*38fd1498Szrj   /* The following field is used during minimization of a finite state
706*38fd1498Szrj      automaton.  The field value is state corresponding to equivalence
707*38fd1498Szrj      class to which given state belongs.  */
708*38fd1498Szrj   state_t equiv_class_state;
709*38fd1498Szrj   unsigned int *presence_signature;
710*38fd1498Szrj   /* The following field value is the order number of given state.
711*38fd1498Szrj      The states in final DFA is enumerated with the aid of the
712*38fd1498Szrj      following field.  */
713*38fd1498Szrj   int order_state_num;
714*38fd1498Szrj   /* This member is used for passing states for searching minimal
715*38fd1498Szrj      delay time.  */
716*38fd1498Szrj   int state_pass_num;
717*38fd1498Szrj   /* The following member is used to evaluate min issue delay of insn
718*38fd1498Szrj      for a state.  */
719*38fd1498Szrj   int min_insn_issue_delay;
720*38fd1498Szrj };
721*38fd1498Szrj 
722*38fd1498Szrj /* Automaton arc.  */
723*38fd1498Szrj struct arc
724*38fd1498Szrj {
725*38fd1498Szrj   /* The following field refers for the state into which given arc
726*38fd1498Szrj      enters.  */
727*38fd1498Szrj   state_t to_state;
728*38fd1498Szrj   /* The following field describes that the insn issue (with cycle
729*38fd1498Szrj      advancing for special insn `cycle advancing' and without cycle
730*38fd1498Szrj      advancing for others) makes transition from given state to
731*38fd1498Szrj      another given state.  */
732*38fd1498Szrj   ainsn_t insn;
733*38fd1498Szrj   /* The following field value is the next arc output from the same
734*38fd1498Szrj      state.  */
735*38fd1498Szrj   arc_t next_out_arc;
736*38fd1498Szrj   /* List of arcs marked given insn is formed with the following
737*38fd1498Szrj      field.  The field is used in transformation NDFA -> DFA.  */
738*38fd1498Szrj   arc_t next_arc_marked_by_insn;
739*38fd1498Szrj };
740*38fd1498Szrj 
741*38fd1498Szrj /* The following node type describes a deterministic alternative in
742*38fd1498Szrj    non-deterministic state which characterizes cpu unit reservations
743*38fd1498Szrj    of automaton insn or which is part of NDFA.  */
744*38fd1498Szrj struct alt_state
745*38fd1498Szrj {
746*38fd1498Szrj   /* The following field is a deterministic state which characterizes
747*38fd1498Szrj      unit reservations of the instruction.  */
748*38fd1498Szrj   state_t state;
749*38fd1498Szrj   /* The following field refers to the next state which characterizes
750*38fd1498Szrj      unit reservations of the instruction.  */
751*38fd1498Szrj   alt_state_t next_alt_state;
752*38fd1498Szrj   /* The following field refers to the next state in sorted list.  */
753*38fd1498Szrj   alt_state_t next_sorted_alt_state;
754*38fd1498Szrj };
755*38fd1498Szrj 
756*38fd1498Szrj /* The following node type describes insn of automaton.  They are
757*38fd1498Szrj    labels of FA arcs.  */
758*38fd1498Szrj struct ainsn
759*38fd1498Szrj {
760*38fd1498Szrj   /* The following field value is the corresponding insn declaration
761*38fd1498Szrj      of description.  */
762*38fd1498Szrj   struct insn_reserv_decl *insn_reserv_decl;
763*38fd1498Szrj   /* The following field value is the next insn declaration for an
764*38fd1498Szrj      automaton.  */
765*38fd1498Szrj   ainsn_t next_ainsn;
766*38fd1498Szrj   /* The following field is states which characterize automaton unit
767*38fd1498Szrj      reservations of the instruction.  The value can be NULL only if it
768*38fd1498Szrj      is special insn `cycle advancing'.  */
769*38fd1498Szrj   alt_state_t alt_states;
770*38fd1498Szrj   /* The following field is sorted list of states which characterize
771*38fd1498Szrj      automaton unit reservations of the instruction.  The value can be
772*38fd1498Szrj      NULL only if it is special insn `cycle advancing'.  */
773*38fd1498Szrj   alt_state_t sorted_alt_states;
774*38fd1498Szrj   /* The following field refers the next automaton insn with
775*38fd1498Szrj      the same reservations.  */
776*38fd1498Szrj   ainsn_t next_same_reservs_insn;
777*38fd1498Szrj   /* The following field is flag of the first automaton insn with the
778*38fd1498Szrj      same reservations in the declaration list.  Only arcs marked such
779*38fd1498Szrj      insn is present in the automaton.  This significantly decreases
780*38fd1498Szrj      memory requirements especially when several automata are
781*38fd1498Szrj      formed.  */
782*38fd1498Szrj   char first_insn_with_same_reservs;
783*38fd1498Szrj   /* The following member has nonzero value if there is arc from state of
784*38fd1498Szrj      the automaton marked by the ainsn.  */
785*38fd1498Szrj   char arc_exists_p;
786*38fd1498Szrj   /* Cyclic list of insns of an equivalence class is formed with the
787*38fd1498Szrj      aid of the following field.  */
788*38fd1498Szrj   ainsn_t next_equiv_class_insn;
789*38fd1498Szrj   /* The following field value is nonzero if the insn declaration is
790*38fd1498Szrj      the first insn declaration with given equivalence number.  */
791*38fd1498Szrj   char first_ainsn_with_given_equivalence_num;
792*38fd1498Szrj   /* The following field is number of class of equivalence of insns.
793*38fd1498Szrj      It is necessary because many insns may be equivalent with the
794*38fd1498Szrj      point of view of pipeline hazards.  */
795*38fd1498Szrj   int insn_equiv_class_num;
796*38fd1498Szrj   /* The following member value is TRUE if there is an arc in the
797*38fd1498Szrj      automaton marked by the insn into another state.  In other
798*38fd1498Szrj      words, the insn can change the state of the automaton.  */
799*38fd1498Szrj   int important_p;
800*38fd1498Szrj };
801*38fd1498Szrj 
802*38fd1498Szrj /* The following describes an automaton for PHR.  */
803*38fd1498Szrj struct automaton
804*38fd1498Szrj {
805*38fd1498Szrj   /* The following field value is the list of insn declarations for
806*38fd1498Szrj      given automaton.  */
807*38fd1498Szrj   ainsn_t ainsn_list;
808*38fd1498Szrj   /* Pointers to the ainsns corresponding to the special reservations.  */
809*38fd1498Szrj   ainsn_t advance_ainsn, collapse_ainsn;
810*38fd1498Szrj 
811*38fd1498Szrj   /* The following field value is the corresponding automaton
812*38fd1498Szrj      declaration.  This field is not NULL only if the automatic
813*38fd1498Szrj      partition on automata is not used.  */
814*38fd1498Szrj   struct automaton_decl *corresponding_automaton_decl;
815*38fd1498Szrj   /* The following field value is the next automaton.  */
816*38fd1498Szrj   automaton_t next_automaton;
817*38fd1498Szrj   /* The following field is start state of FA.  There are not unit
818*38fd1498Szrj      reservations in the state.  */
819*38fd1498Szrj   state_t start_state;
820*38fd1498Szrj   /* The following field value is number of equivalence classes of
821*38fd1498Szrj      insns (see field `insn_equiv_class_num' in
822*38fd1498Szrj      `insn_reserv_decl').  */
823*38fd1498Szrj   int insn_equiv_classes_num;
824*38fd1498Szrj   /* The following field value is number of states of final DFA.  */
825*38fd1498Szrj   int achieved_states_num;
826*38fd1498Szrj   /* The following field value is the order number (0, 1, ...) of
827*38fd1498Szrj      given automaton.  */
828*38fd1498Szrj   int automaton_order_num;
829*38fd1498Szrj   /* The following fields contain statistics information about
830*38fd1498Szrj      building automaton.  */
831*38fd1498Szrj   int NDFA_states_num, DFA_states_num;
832*38fd1498Szrj   /* The following field value is defined only if minimization of DFA
833*38fd1498Szrj      is used.  */
834*38fd1498Szrj   int minimal_DFA_states_num;
835*38fd1498Szrj   int NDFA_arcs_num, DFA_arcs_num;
836*38fd1498Szrj   /* The following field value is defined only if minimization of DFA
837*38fd1498Szrj      is used.  */
838*38fd1498Szrj   int minimal_DFA_arcs_num;
839*38fd1498Szrj   /* The following member refers for two table state x ainsn -> int.
840*38fd1498Szrj      ??? Above sentence is incomprehensible.  */
841*38fd1498Szrj   state_ainsn_table_t trans_table;
842*38fd1498Szrj   /* The following member value is maximal value of min issue delay
843*38fd1498Szrj      for insns of the automaton.  */
844*38fd1498Szrj   int max_min_delay;
845*38fd1498Szrj   /* Usually min issue delay is small and we can place several (2, 4,
846*38fd1498Szrj      8) elements in one vector element.  So the compression factor can
847*38fd1498Szrj      be 1 (no compression), 2, 4, 8.  */
848*38fd1498Szrj   int min_issue_delay_table_compression_factor;
849*38fd1498Szrj   /* Total number of locked states in this automaton.  */
850*38fd1498Szrj   int locked_states;
851*38fd1498Szrj };
852*38fd1498Szrj 
853*38fd1498Szrj /* The following is the element of the list of automata.  */
854*38fd1498Szrj struct automata_list_el
855*38fd1498Szrj {
856*38fd1498Szrj   /* The automaton itself.  */
857*38fd1498Szrj   automaton_t automaton;
858*38fd1498Szrj   /* The next automata set element.  */
859*38fd1498Szrj   automata_list_el_t next_automata_list_el;
860*38fd1498Szrj };
861*38fd1498Szrj 
862*38fd1498Szrj /* The following structure describes a table state X ainsn -> int(>= 0).  */
863*38fd1498Szrj struct state_ainsn_table
864*38fd1498Szrj {
865*38fd1498Szrj   /* Automaton to which given table belongs.  */
866*38fd1498Szrj   automaton_t automaton;
867*38fd1498Szrj   /* The following tree vectors for comb vector implementation of the
868*38fd1498Szrj      table.  */
869*38fd1498Szrj   vla_hwint_t comb_vect;
870*38fd1498Szrj   vla_hwint_t check_vect;
871*38fd1498Szrj   vla_hwint_t base_vect;
872*38fd1498Szrj   /* This is simple implementation of the table.  */
873*38fd1498Szrj   vla_hwint_t full_vect;
874*38fd1498Szrj   /* Minimal and maximal values of the previous vectors.  */
875*38fd1498Szrj   int min_comb_vect_el_value, max_comb_vect_el_value;
876*38fd1498Szrj   int min_base_vect_el_value, max_base_vect_el_value;
877*38fd1498Szrj };
878*38fd1498Szrj 
879*38fd1498Szrj /* Macros to access members of unions.  Use only them for access to
880*38fd1498Szrj    union members of declarations and regexps.  */
881*38fd1498Szrj 
882*38fd1498Szrj #if CHECKING_P && (GCC_VERSION >= 2007)
883*38fd1498Szrj 
884*38fd1498Szrj #define DECL_UNIT(d) __extension__					\
885*38fd1498Szrj (({ __typeof (d) const _decl = (d);					\
886*38fd1498Szrj      if (_decl->mode != dm_unit)					\
887*38fd1498Szrj        decl_mode_check_failed (_decl->mode, "dm_unit",			\
888*38fd1498Szrj 			       __FILE__, __LINE__, __FUNCTION__);	\
889*38fd1498Szrj      &(_decl)->decl.unit; }))
890*38fd1498Szrj 
891*38fd1498Szrj #define DECL_BYPASS(d) __extension__					\
892*38fd1498Szrj (({ __typeof (d) const _decl = (d);					\
893*38fd1498Szrj      if (_decl->mode != dm_bypass)					\
894*38fd1498Szrj        decl_mode_check_failed (_decl->mode, "dm_bypass",		\
895*38fd1498Szrj 			       __FILE__, __LINE__, __FUNCTION__);	\
896*38fd1498Szrj      &(_decl)->decl.bypass; }))
897*38fd1498Szrj 
898*38fd1498Szrj #define DECL_AUTOMATON(d) __extension__					\
899*38fd1498Szrj (({ __typeof (d) const _decl = (d);					\
900*38fd1498Szrj      if (_decl->mode != dm_automaton)					\
901*38fd1498Szrj        decl_mode_check_failed (_decl->mode, "dm_automaton",		\
902*38fd1498Szrj 			       __FILE__, __LINE__, __FUNCTION__);	\
903*38fd1498Szrj      &(_decl)->decl.automaton; }))
904*38fd1498Szrj 
905*38fd1498Szrj #define DECL_EXCL(d) __extension__					\
906*38fd1498Szrj (({ __typeof (d) const _decl = (d);					\
907*38fd1498Szrj      if (_decl->mode != dm_excl)					\
908*38fd1498Szrj        decl_mode_check_failed (_decl->mode, "dm_excl",			\
909*38fd1498Szrj 			       __FILE__, __LINE__, __FUNCTION__);	\
910*38fd1498Szrj      &(_decl)->decl.excl; }))
911*38fd1498Szrj 
912*38fd1498Szrj #define DECL_PRESENCE(d) __extension__					\
913*38fd1498Szrj (({ __typeof (d) const _decl = (d);					\
914*38fd1498Szrj      if (_decl->mode != dm_presence)					\
915*38fd1498Szrj        decl_mode_check_failed (_decl->mode, "dm_presence",		\
916*38fd1498Szrj 			       __FILE__, __LINE__, __FUNCTION__);	\
917*38fd1498Szrj      &(_decl)->decl.presence; }))
918*38fd1498Szrj 
919*38fd1498Szrj #define DECL_ABSENCE(d) __extension__					\
920*38fd1498Szrj (({ __typeof (d) const _decl = (d);					\
921*38fd1498Szrj      if (_decl->mode != dm_absence)					\
922*38fd1498Szrj        decl_mode_check_failed (_decl->mode, "dm_absence",		\
923*38fd1498Szrj 			       __FILE__, __LINE__, __FUNCTION__);	\
924*38fd1498Szrj      &(_decl)->decl.absence; }))
925*38fd1498Szrj 
926*38fd1498Szrj #define DECL_RESERV(d) __extension__					\
927*38fd1498Szrj (({ __typeof (d) const _decl = (d);					\
928*38fd1498Szrj      if (_decl->mode != dm_reserv)					\
929*38fd1498Szrj        decl_mode_check_failed (_decl->mode, "dm_reserv",		\
930*38fd1498Szrj 			       __FILE__, __LINE__, __FUNCTION__);	\
931*38fd1498Szrj      &(_decl)->decl.reserv; }))
932*38fd1498Szrj 
933*38fd1498Szrj #define DECL_INSN_RESERV(d) __extension__				\
934*38fd1498Szrj (({ __typeof (d) const _decl = (d);					\
935*38fd1498Szrj      if (_decl->mode != dm_insn_reserv)					\
936*38fd1498Szrj        decl_mode_check_failed (_decl->mode, "dm_insn_reserv",		\
937*38fd1498Szrj 			       __FILE__, __LINE__, __FUNCTION__);	\
938*38fd1498Szrj      &(_decl)->decl.insn_reserv; }))
939*38fd1498Szrj 
940*38fd1498Szrj static const char *decl_name (enum decl_mode);
941*38fd1498Szrj static void decl_mode_check_failed (enum decl_mode, const char *,
942*38fd1498Szrj 				    const char *, int, const char *)
943*38fd1498Szrj      ATTRIBUTE_NORETURN;
944*38fd1498Szrj 
945*38fd1498Szrj /* Return string representation of declaration mode MODE.  */
946*38fd1498Szrj static const char *
decl_name(enum decl_mode mode)947*38fd1498Szrj decl_name (enum decl_mode mode)
948*38fd1498Szrj {
949*38fd1498Szrj   static char str [100];
950*38fd1498Szrj 
951*38fd1498Szrj   if (mode == dm_unit)
952*38fd1498Szrj     return "dm_unit";
953*38fd1498Szrj   else if (mode == dm_bypass)
954*38fd1498Szrj     return "dm_bypass";
955*38fd1498Szrj   else if (mode == dm_automaton)
956*38fd1498Szrj     return "dm_automaton";
957*38fd1498Szrj   else if (mode == dm_excl)
958*38fd1498Szrj     return "dm_excl";
959*38fd1498Szrj   else if (mode == dm_presence)
960*38fd1498Szrj     return "dm_presence";
961*38fd1498Szrj   else if (mode == dm_absence)
962*38fd1498Szrj     return "dm_absence";
963*38fd1498Szrj   else if (mode == dm_reserv)
964*38fd1498Szrj     return "dm_reserv";
965*38fd1498Szrj   else if (mode == dm_insn_reserv)
966*38fd1498Szrj     return "dm_insn_reserv";
967*38fd1498Szrj   else
968*38fd1498Szrj     sprintf (str, "unknown (%d)", (int) mode);
969*38fd1498Szrj   return str;
970*38fd1498Szrj }
971*38fd1498Szrj 
972*38fd1498Szrj /* The function prints message about unexpected declaration and finish
973*38fd1498Szrj    the program.  */
974*38fd1498Szrj static void
decl_mode_check_failed(enum decl_mode mode,const char * expected_mode_str,const char * file,int line,const char * func)975*38fd1498Szrj decl_mode_check_failed (enum decl_mode mode, const char *expected_mode_str,
976*38fd1498Szrj 			const char *file, int line, const char *func)
977*38fd1498Szrj {
978*38fd1498Szrj   fprintf
979*38fd1498Szrj     (stderr,
980*38fd1498Szrj      "\n%s: %d: error in %s: DECL check: expected decl %s, have %s\n",
981*38fd1498Szrj      file, line, func, expected_mode_str, decl_name (mode));
982*38fd1498Szrj   exit (1);
983*38fd1498Szrj }
984*38fd1498Szrj 
985*38fd1498Szrj 
986*38fd1498Szrj #define REGEXP_UNIT(r) __extension__					\
987*38fd1498Szrj (({ struct regexp *const _regexp = (r);					\
988*38fd1498Szrj      if (_regexp->mode != rm_unit)					\
989*38fd1498Szrj        regexp_mode_check_failed (_regexp->mode, "rm_unit",		\
990*38fd1498Szrj 			       __FILE__, __LINE__, __FUNCTION__);	\
991*38fd1498Szrj      &(_regexp)->regexp.unit; }))
992*38fd1498Szrj 
993*38fd1498Szrj #define REGEXP_RESERV(r) __extension__					\
994*38fd1498Szrj (({ struct regexp *const _regexp = (r);					\
995*38fd1498Szrj      if (_regexp->mode != rm_reserv)					\
996*38fd1498Szrj        regexp_mode_check_failed (_regexp->mode, "rm_reserv",		\
997*38fd1498Szrj 			       __FILE__, __LINE__, __FUNCTION__);	\
998*38fd1498Szrj      &(_regexp)->regexp.reserv; }))
999*38fd1498Szrj 
1000*38fd1498Szrj #define REGEXP_SEQUENCE(r) __extension__				\
1001*38fd1498Szrj (({ struct regexp *const _regexp = (r);					\
1002*38fd1498Szrj      if (_regexp->mode != rm_sequence)					\
1003*38fd1498Szrj        regexp_mode_check_failed (_regexp->mode, "rm_sequence",		\
1004*38fd1498Szrj 			       __FILE__, __LINE__, __FUNCTION__);	\
1005*38fd1498Szrj      &(_regexp)->regexp.sequence; }))
1006*38fd1498Szrj 
1007*38fd1498Szrj #define REGEXP_REPEAT(r) __extension__					\
1008*38fd1498Szrj (({ struct regexp *const _regexp = (r);					\
1009*38fd1498Szrj      if (_regexp->mode != rm_repeat)					\
1010*38fd1498Szrj        regexp_mode_check_failed (_regexp->mode, "rm_repeat",		\
1011*38fd1498Szrj 			       __FILE__, __LINE__, __FUNCTION__);	\
1012*38fd1498Szrj      &(_regexp)->regexp.repeat; }))
1013*38fd1498Szrj 
1014*38fd1498Szrj #define REGEXP_ALLOF(r) __extension__					\
1015*38fd1498Szrj (({ struct regexp *const _regexp = (r);					\
1016*38fd1498Szrj      if (_regexp->mode != rm_allof)					\
1017*38fd1498Szrj        regexp_mode_check_failed (_regexp->mode, "rm_allof",		\
1018*38fd1498Szrj 			       __FILE__, __LINE__, __FUNCTION__);	\
1019*38fd1498Szrj      &(_regexp)->regexp.allof; }))
1020*38fd1498Szrj 
1021*38fd1498Szrj #define REGEXP_ONEOF(r) __extension__					\
1022*38fd1498Szrj (({ struct regexp *const _regexp = (r);					\
1023*38fd1498Szrj      if (_regexp->mode != rm_oneof)					\
1024*38fd1498Szrj        regexp_mode_check_failed (_regexp->mode, "rm_oneof",		\
1025*38fd1498Szrj 			       __FILE__, __LINE__, __FUNCTION__);	\
1026*38fd1498Szrj      &(_regexp)->regexp.oneof; }))
1027*38fd1498Szrj 
1028*38fd1498Szrj static const char *regexp_name (enum regexp_mode);
1029*38fd1498Szrj static void regexp_mode_check_failed (enum regexp_mode, const char *,
1030*38fd1498Szrj 				      const char *, int,
1031*38fd1498Szrj 				      const char *) ATTRIBUTE_NORETURN;
1032*38fd1498Szrj 
1033*38fd1498Szrj 
1034*38fd1498Szrj /* Return string representation of regexp mode MODE.  */
1035*38fd1498Szrj static const char *
regexp_name(enum regexp_mode mode)1036*38fd1498Szrj regexp_name (enum regexp_mode mode)
1037*38fd1498Szrj {
1038*38fd1498Szrj   switch (mode)
1039*38fd1498Szrj     {
1040*38fd1498Szrj     case rm_unit:
1041*38fd1498Szrj       return "rm_unit";
1042*38fd1498Szrj     case rm_reserv:
1043*38fd1498Szrj       return "rm_reserv";
1044*38fd1498Szrj     case rm_nothing:
1045*38fd1498Szrj       return "rm_nothing";
1046*38fd1498Szrj     case rm_sequence:
1047*38fd1498Szrj       return "rm_sequence";
1048*38fd1498Szrj     case rm_repeat:
1049*38fd1498Szrj       return "rm_repeat";
1050*38fd1498Szrj     case rm_allof:
1051*38fd1498Szrj       return "rm_allof";
1052*38fd1498Szrj     case rm_oneof:
1053*38fd1498Szrj       return "rm_oneof";
1054*38fd1498Szrj     default:
1055*38fd1498Szrj       gcc_unreachable ();
1056*38fd1498Szrj     }
1057*38fd1498Szrj }
1058*38fd1498Szrj 
1059*38fd1498Szrj /* The function prints message about unexpected regexp and finish the
1060*38fd1498Szrj    program.  */
1061*38fd1498Szrj static void
regexp_mode_check_failed(enum regexp_mode mode,const char * expected_mode_str,const char * file,int line,const char * func)1062*38fd1498Szrj regexp_mode_check_failed (enum regexp_mode mode,
1063*38fd1498Szrj 			  const char *expected_mode_str,
1064*38fd1498Szrj 			  const char *file, int line, const char *func)
1065*38fd1498Szrj {
1066*38fd1498Szrj   fprintf
1067*38fd1498Szrj     (stderr,
1068*38fd1498Szrj      "\n%s: %d: error in %s: REGEXP check: expected decl %s, have %s\n",
1069*38fd1498Szrj      file, line, func, expected_mode_str, regexp_name (mode));
1070*38fd1498Szrj   exit (1);
1071*38fd1498Szrj }
1072*38fd1498Szrj 
1073*38fd1498Szrj #else /* #if CHECKING_P && (GCC_VERSION >= 2007) */
1074*38fd1498Szrj 
1075*38fd1498Szrj #define DECL_UNIT(d) (&(d)->decl.unit)
1076*38fd1498Szrj #define DECL_BYPASS(d) (&(d)->decl.bypass)
1077*38fd1498Szrj #define DECL_AUTOMATON(d) (&(d)->decl.automaton)
1078*38fd1498Szrj #define DECL_EXCL(d) (&(d)->decl.excl)
1079*38fd1498Szrj #define DECL_PRESENCE(d) (&(d)->decl.presence)
1080*38fd1498Szrj #define DECL_ABSENCE(d) (&(d)->decl.absence)
1081*38fd1498Szrj #define DECL_RESERV(d) (&(d)->decl.reserv)
1082*38fd1498Szrj #define DECL_INSN_RESERV(d) (&(d)->decl.insn_reserv)
1083*38fd1498Szrj 
1084*38fd1498Szrj #define REGEXP_UNIT(r) (&(r)->regexp.unit)
1085*38fd1498Szrj #define REGEXP_RESERV(r) (&(r)->regexp.reserv)
1086*38fd1498Szrj #define REGEXP_SEQUENCE(r) (&(r)->regexp.sequence)
1087*38fd1498Szrj #define REGEXP_REPEAT(r) (&(r)->regexp.repeat)
1088*38fd1498Szrj #define REGEXP_ALLOF(r) (&(r)->regexp.allof)
1089*38fd1498Szrj #define REGEXP_ONEOF(r) (&(r)->regexp.oneof)
1090*38fd1498Szrj 
1091*38fd1498Szrj #endif /* #if CHECKING_P && (GCC_VERSION >= 2007) */
1092*38fd1498Szrj 
1093*38fd1498Szrj #define XCREATENODE(T) ((T *) create_node (sizeof (T)))
1094*38fd1498Szrj #define XCREATENODEVEC(T, N) ((T *) create_node (sizeof (T) * (N)))
1095*38fd1498Szrj #define XCREATENODEVAR(T, S) ((T *) create_node ((S)))
1096*38fd1498Szrj 
1097*38fd1498Szrj #define XCOPYNODE(T, P) ((T *) copy_node ((P), sizeof (T)))
1098*38fd1498Szrj #define XCOPYNODEVEC(T, P, N) ((T *) copy_node ((P), sizeof (T) * (N)))
1099*38fd1498Szrj #define XCOPYNODEVAR(T, P, S) ((T *) copy_node ((P), (S)))
1100*38fd1498Szrj 
1101*38fd1498Szrj /* Create IR structure (node).  */
1102*38fd1498Szrj static void *
create_node(size_t size)1103*38fd1498Szrj create_node (size_t size)
1104*38fd1498Szrj {
1105*38fd1498Szrj   void *result;
1106*38fd1498Szrj 
1107*38fd1498Szrj   obstack_blank (&irp, size);
1108*38fd1498Szrj   result = obstack_base (&irp);
1109*38fd1498Szrj   obstack_finish (&irp);
1110*38fd1498Szrj   /* Default values of members are NULL and zero.  */
1111*38fd1498Szrj   memset (result, 0, size);
1112*38fd1498Szrj   return result;
1113*38fd1498Szrj }
1114*38fd1498Szrj 
1115*38fd1498Szrj /* Copy IR structure (node).  */
1116*38fd1498Szrj static void *
copy_node(const void * from,size_t size)1117*38fd1498Szrj copy_node (const void *from, size_t size)
1118*38fd1498Szrj {
1119*38fd1498Szrj   void *const result = create_node (size);
1120*38fd1498Szrj   memcpy (result, from, size);
1121*38fd1498Szrj   return result;
1122*38fd1498Szrj }
1123*38fd1498Szrj 
1124*38fd1498Szrj /* The function checks that NAME does not contain quotes (`"').  */
1125*38fd1498Szrj static const char *
check_name(const char * name,pos_t pos ATTRIBUTE_UNUSED)1126*38fd1498Szrj check_name (const char * name, pos_t pos ATTRIBUTE_UNUSED)
1127*38fd1498Szrj {
1128*38fd1498Szrj   const char *str;
1129*38fd1498Szrj 
1130*38fd1498Szrj   for (str = name; *str != '\0'; str++)
1131*38fd1498Szrj     if (*str == '\"')
1132*38fd1498Szrj       error ("Name `%s' contains quotes", name);
1133*38fd1498Szrj   return name;
1134*38fd1498Szrj }
1135*38fd1498Szrj 
1136*38fd1498Szrj /* Pointers to all declarations during IR generation are stored in the
1137*38fd1498Szrj    following.  */
1138*38fd1498Szrj static vec<decl_t> decls;
1139*38fd1498Szrj 
1140*38fd1498Szrj /* Given a pointer to a (char *) and a separator, return an alloc'ed
1141*38fd1498Szrj    string containing the next separated element, taking parentheses
1142*38fd1498Szrj    into account if PAR_FLAG has nonzero value.  Advance the pointer to
1143*38fd1498Szrj    after the string scanned, or the end-of-string.  Return NULL if at
1144*38fd1498Szrj    end of string.  */
1145*38fd1498Szrj static char *
next_sep_el(const char ** pstr,int sep,int par_flag)1146*38fd1498Szrj next_sep_el (const char **pstr, int sep, int par_flag)
1147*38fd1498Szrj {
1148*38fd1498Szrj   char *out_str;
1149*38fd1498Szrj   const char *p;
1150*38fd1498Szrj   int pars_num;
1151*38fd1498Szrj   int n_spaces;
1152*38fd1498Szrj 
1153*38fd1498Szrj   /* Remove leading whitespaces.  */
1154*38fd1498Szrj   while (ISSPACE ((int) **pstr))
1155*38fd1498Szrj     (*pstr)++;
1156*38fd1498Szrj 
1157*38fd1498Szrj   if (**pstr == '\0')
1158*38fd1498Szrj     return NULL;
1159*38fd1498Szrj 
1160*38fd1498Szrj   n_spaces = 0;
1161*38fd1498Szrj   for (pars_num = 0, p = *pstr; *p != '\0'; p++)
1162*38fd1498Szrj     {
1163*38fd1498Szrj       if (par_flag && *p == '(')
1164*38fd1498Szrj 	pars_num++;
1165*38fd1498Szrj       else if (par_flag && *p == ')')
1166*38fd1498Szrj 	pars_num--;
1167*38fd1498Szrj       else if (pars_num == 0 && *p == sep)
1168*38fd1498Szrj 	break;
1169*38fd1498Szrj       if (pars_num == 0 && ISSPACE ((int) *p))
1170*38fd1498Szrj 	n_spaces++;
1171*38fd1498Szrj       else
1172*38fd1498Szrj 	{
1173*38fd1498Szrj 	  for (; n_spaces != 0; n_spaces--)
1174*38fd1498Szrj 	    obstack_1grow (&irp, p [-n_spaces]);
1175*38fd1498Szrj 	  obstack_1grow (&irp, *p);
1176*38fd1498Szrj 	}
1177*38fd1498Szrj     }
1178*38fd1498Szrj   obstack_1grow (&irp, '\0');
1179*38fd1498Szrj   out_str = (char *) obstack_base (&irp);
1180*38fd1498Szrj   obstack_finish (&irp);
1181*38fd1498Szrj 
1182*38fd1498Szrj   *pstr = p;
1183*38fd1498Szrj   if (**pstr == sep)
1184*38fd1498Szrj     (*pstr)++;
1185*38fd1498Szrj 
1186*38fd1498Szrj   return out_str;
1187*38fd1498Szrj }
1188*38fd1498Szrj 
1189*38fd1498Szrj /* Given a string and a separator, return the number of separated
1190*38fd1498Szrj    elements in it, taking parentheses into account if PAR_FLAG has
1191*38fd1498Szrj    nonzero value.  Return 0 for the null string, -1 if parentheses is
1192*38fd1498Szrj    not balanced.  */
1193*38fd1498Szrj static int
n_sep_els(const char * s,int sep,int par_flag)1194*38fd1498Szrj n_sep_els (const char *s, int sep, int par_flag)
1195*38fd1498Szrj {
1196*38fd1498Szrj   int n;
1197*38fd1498Szrj   int pars_num;
1198*38fd1498Szrj 
1199*38fd1498Szrj   if (*s == '\0')
1200*38fd1498Szrj     return 0;
1201*38fd1498Szrj 
1202*38fd1498Szrj   for (pars_num = 0, n = 1; *s; s++)
1203*38fd1498Szrj     if (par_flag && *s == '(')
1204*38fd1498Szrj       pars_num++;
1205*38fd1498Szrj     else if (par_flag && *s == ')')
1206*38fd1498Szrj       pars_num--;
1207*38fd1498Szrj     else if (pars_num == 0 && *s == sep)
1208*38fd1498Szrj       n++;
1209*38fd1498Szrj 
1210*38fd1498Szrj   return (pars_num != 0 ? -1 : n);
1211*38fd1498Szrj }
1212*38fd1498Szrj 
1213*38fd1498Szrj /* Given a string and a separator, return vector of strings which are
1214*38fd1498Szrj    elements in the string and number of elements through els_num.
1215*38fd1498Szrj    Take parentheses into account if PAREN_P has nonzero value.  The
1216*38fd1498Szrj    function also inserts the end marker NULL at the end of vector.
1217*38fd1498Szrj    Return 0 for the null string, -1 if parentheses are not balanced.  */
1218*38fd1498Szrj static char **
get_str_vect(const char * str,int * els_num,int sep,int paren_p)1219*38fd1498Szrj get_str_vect (const char *str, int *els_num, int sep, int paren_p)
1220*38fd1498Szrj {
1221*38fd1498Szrj   int i;
1222*38fd1498Szrj   char **vect;
1223*38fd1498Szrj   const char **pstr;
1224*38fd1498Szrj   char *trail;
1225*38fd1498Szrj 
1226*38fd1498Szrj   *els_num = n_sep_els (str, sep, paren_p);
1227*38fd1498Szrj   if (*els_num <= 0)
1228*38fd1498Szrj     return NULL;
1229*38fd1498Szrj   obstack_blank (&irp, sizeof (char *) * (*els_num + 1));
1230*38fd1498Szrj   vect = (char **) obstack_base (&irp);
1231*38fd1498Szrj   obstack_finish (&irp);
1232*38fd1498Szrj   pstr = &str;
1233*38fd1498Szrj   for (i = 0; i < *els_num; i++)
1234*38fd1498Szrj     vect [i] = next_sep_el (pstr, sep, paren_p);
1235*38fd1498Szrj   trail = next_sep_el (pstr, sep, paren_p);
1236*38fd1498Szrj   gcc_assert (!trail);
1237*38fd1498Szrj   vect [i] = NULL;
1238*38fd1498Szrj   return vect;
1239*38fd1498Szrj }
1240*38fd1498Szrj 
1241*38fd1498Szrj /* Process a DEFINE_CPU_UNIT.
1242*38fd1498Szrj 
1243*38fd1498Szrj    This gives information about a unit contained in CPU.  We fill a
1244*38fd1498Szrj    struct unit_decl with information used later by `expand_automata'.  */
1245*38fd1498Szrj static void
gen_cpu_unit(md_rtx_info * info)1246*38fd1498Szrj gen_cpu_unit (md_rtx_info *info)
1247*38fd1498Szrj {
1248*38fd1498Szrj   decl_t decl;
1249*38fd1498Szrj   char **str_cpu_units;
1250*38fd1498Szrj   int vect_length;
1251*38fd1498Szrj   int i;
1252*38fd1498Szrj 
1253*38fd1498Szrj   rtx def = info->def;
1254*38fd1498Szrj   str_cpu_units = get_str_vect (XSTR (def, 0), &vect_length, ',', FALSE);
1255*38fd1498Szrj   if (str_cpu_units == NULL)
1256*38fd1498Szrj     fatal_at (info->loc, "invalid string `%s' in %s",
1257*38fd1498Szrj 	      XSTR (def, 0), GET_RTX_NAME (GET_CODE (def)));
1258*38fd1498Szrj   for (i = 0; i < vect_length; i++)
1259*38fd1498Szrj     {
1260*38fd1498Szrj       decl = XCREATENODE (struct decl);
1261*38fd1498Szrj       decl->mode = dm_unit;
1262*38fd1498Szrj       decl->pos = 0;
1263*38fd1498Szrj       DECL_UNIT (decl)->name = check_name (str_cpu_units [i], decl->pos);
1264*38fd1498Szrj       DECL_UNIT (decl)->automaton_name = XSTR (def, 1);
1265*38fd1498Szrj       DECL_UNIT (decl)->query_p = 0;
1266*38fd1498Szrj       DECL_UNIT (decl)->min_occ_cycle_num = -1;
1267*38fd1498Szrj       DECL_UNIT (decl)->in_set_p = 0;
1268*38fd1498Szrj       decls.safe_push (decl);
1269*38fd1498Szrj     }
1270*38fd1498Szrj }
1271*38fd1498Szrj 
1272*38fd1498Szrj /* Process a DEFINE_QUERY_CPU_UNIT.
1273*38fd1498Szrj 
1274*38fd1498Szrj    This gives information about a unit contained in CPU.  We fill a
1275*38fd1498Szrj    struct unit_decl with information used later by `expand_automata'.  */
1276*38fd1498Szrj static void
gen_query_cpu_unit(md_rtx_info * info)1277*38fd1498Szrj gen_query_cpu_unit (md_rtx_info *info)
1278*38fd1498Szrj {
1279*38fd1498Szrj   decl_t decl;
1280*38fd1498Szrj   char **str_cpu_units;
1281*38fd1498Szrj   int vect_length;
1282*38fd1498Szrj   int i;
1283*38fd1498Szrj 
1284*38fd1498Szrj   rtx def = info->def;
1285*38fd1498Szrj   str_cpu_units = get_str_vect (XSTR (def, 0), &vect_length, ',',
1286*38fd1498Szrj 				FALSE);
1287*38fd1498Szrj   if (str_cpu_units == NULL)
1288*38fd1498Szrj     fatal_at (info->loc, "invalid string `%s' in %s",
1289*38fd1498Szrj 	      XSTR (def, 0), GET_RTX_NAME (GET_CODE (def)));
1290*38fd1498Szrj   for (i = 0; i < vect_length; i++)
1291*38fd1498Szrj     {
1292*38fd1498Szrj       decl = XCREATENODE (struct decl);
1293*38fd1498Szrj       decl->mode = dm_unit;
1294*38fd1498Szrj       decl->pos = 0;
1295*38fd1498Szrj       DECL_UNIT (decl)->name = check_name (str_cpu_units [i], decl->pos);
1296*38fd1498Szrj       DECL_UNIT (decl)->automaton_name = XSTR (def, 1);
1297*38fd1498Szrj       DECL_UNIT (decl)->query_p = 1;
1298*38fd1498Szrj       decls.safe_push (decl);
1299*38fd1498Szrj     }
1300*38fd1498Szrj }
1301*38fd1498Szrj 
1302*38fd1498Szrj /* Process a DEFINE_BYPASS.
1303*38fd1498Szrj 
1304*38fd1498Szrj    This gives information about a unit contained in the CPU.  We fill
1305*38fd1498Szrj    in a struct bypass_decl with information used later by
1306*38fd1498Szrj    `expand_automata'.  */
1307*38fd1498Szrj static void
gen_bypass(md_rtx_info * info)1308*38fd1498Szrj gen_bypass (md_rtx_info *info)
1309*38fd1498Szrj {
1310*38fd1498Szrj   decl_t decl;
1311*38fd1498Szrj   char **out_patterns;
1312*38fd1498Szrj   int out_length;
1313*38fd1498Szrj   char **in_patterns;
1314*38fd1498Szrj   int in_length;
1315*38fd1498Szrj   int i, j;
1316*38fd1498Szrj 
1317*38fd1498Szrj   rtx def = info->def;
1318*38fd1498Szrj   out_patterns = get_str_vect (XSTR (def, 1), &out_length, ',', FALSE);
1319*38fd1498Szrj   if (out_patterns == NULL)
1320*38fd1498Szrj     fatal_at (info->loc, "invalid string `%s' in %s",
1321*38fd1498Szrj 	      XSTR (def, 1), GET_RTX_NAME (GET_CODE (def)));
1322*38fd1498Szrj   in_patterns = get_str_vect (XSTR (def, 2), &in_length, ',', FALSE);
1323*38fd1498Szrj   if (in_patterns == NULL)
1324*38fd1498Szrj     fatal_at (info->loc, "invalid string `%s' in %s",
1325*38fd1498Szrj 	      XSTR (def, 2), GET_RTX_NAME (GET_CODE (def)));
1326*38fd1498Szrj   for (i = 0; i < out_length; i++)
1327*38fd1498Szrj     for (j = 0; j < in_length; j++)
1328*38fd1498Szrj       {
1329*38fd1498Szrj 	decl = XCREATENODE (struct decl);
1330*38fd1498Szrj 	decl->mode = dm_bypass;
1331*38fd1498Szrj 	decl->pos = 0;
1332*38fd1498Szrj 	DECL_BYPASS (decl)->latency = XINT (def, 0);
1333*38fd1498Szrj 	DECL_BYPASS (decl)->out_pattern = out_patterns[i];
1334*38fd1498Szrj 	DECL_BYPASS (decl)->in_pattern = in_patterns[j];
1335*38fd1498Szrj 	DECL_BYPASS (decl)->bypass_guard_name = XSTR (def, 3);
1336*38fd1498Szrj 	decls.safe_push (decl);
1337*38fd1498Szrj       }
1338*38fd1498Szrj }
1339*38fd1498Szrj 
1340*38fd1498Szrj /* Process an EXCLUSION_SET.
1341*38fd1498Szrj 
1342*38fd1498Szrj    This gives information about a cpu unit conflicts.  We fill a
1343*38fd1498Szrj    struct excl_rel_decl (excl) with information used later by
1344*38fd1498Szrj    `expand_automata'.  */
1345*38fd1498Szrj static void
gen_excl_set(md_rtx_info * info)1346*38fd1498Szrj gen_excl_set (md_rtx_info *info)
1347*38fd1498Szrj {
1348*38fd1498Szrj   decl_t decl;
1349*38fd1498Szrj   char **first_str_cpu_units;
1350*38fd1498Szrj   char **second_str_cpu_units;
1351*38fd1498Szrj   int first_vect_length;
1352*38fd1498Szrj   int length;
1353*38fd1498Szrj   int i;
1354*38fd1498Szrj 
1355*38fd1498Szrj   rtx def = info->def;
1356*38fd1498Szrj   first_str_cpu_units
1357*38fd1498Szrj     = get_str_vect (XSTR (def, 0), &first_vect_length, ',', FALSE);
1358*38fd1498Szrj   if (first_str_cpu_units == NULL)
1359*38fd1498Szrj     fatal_at (info->loc, "invalid string `%s' in %s",
1360*38fd1498Szrj 	      XSTR (def, 0), GET_RTX_NAME (GET_CODE (def)));
1361*38fd1498Szrj   second_str_cpu_units = get_str_vect (XSTR (def, 1), &length, ',',
1362*38fd1498Szrj 				       FALSE);
1363*38fd1498Szrj   if (second_str_cpu_units == NULL)
1364*38fd1498Szrj     fatal_at (info->loc, "invalid string `%s' in %s",
1365*38fd1498Szrj 	      XSTR (def, 1), GET_RTX_NAME (GET_CODE (def)));
1366*38fd1498Szrj   length += first_vect_length;
1367*38fd1498Szrj   decl = XCREATENODEVAR (struct decl, (sizeof (struct decl)
1368*38fd1498Szrj 				       + (length - 1) * sizeof (char *)));
1369*38fd1498Szrj   decl->mode = dm_excl;
1370*38fd1498Szrj   decl->pos = 0;
1371*38fd1498Szrj   DECL_EXCL (decl)->all_names_num = length;
1372*38fd1498Szrj   DECL_EXCL (decl)->first_list_length = first_vect_length;
1373*38fd1498Szrj   for (i = 0; i < length; i++)
1374*38fd1498Szrj     if (i < first_vect_length)
1375*38fd1498Szrj       DECL_EXCL (decl)->names [i] = first_str_cpu_units [i];
1376*38fd1498Szrj     else
1377*38fd1498Szrj       DECL_EXCL (decl)->names [i]
1378*38fd1498Szrj 	= second_str_cpu_units [i - first_vect_length];
1379*38fd1498Szrj   decls.safe_push (decl);
1380*38fd1498Szrj }
1381*38fd1498Szrj 
1382*38fd1498Szrj /* Process a PRESENCE_SET, a FINAL_PRESENCE_SET, an ABSENCE_SET,
1383*38fd1498Szrj    FINAL_ABSENCE_SET (it is depended on PRESENCE_P and FINAL_P).
1384*38fd1498Szrj 
1385*38fd1498Szrj    This gives information about a cpu unit reservation requirements.
1386*38fd1498Szrj    We fill a struct unit_pattern_rel_decl with information used later
1387*38fd1498Szrj    by `expand_automata'.  */
1388*38fd1498Szrj static void
gen_presence_absence_set(md_rtx_info * info,int presence_p,int final_p)1389*38fd1498Szrj gen_presence_absence_set (md_rtx_info *info, int presence_p, int final_p)
1390*38fd1498Szrj {
1391*38fd1498Szrj   decl_t decl;
1392*38fd1498Szrj   char **str_cpu_units;
1393*38fd1498Szrj   char **str_pattern_lists;
1394*38fd1498Szrj   char ***str_patterns;
1395*38fd1498Szrj   int cpu_units_length;
1396*38fd1498Szrj   int length;
1397*38fd1498Szrj   int patterns_length;
1398*38fd1498Szrj   int i;
1399*38fd1498Szrj 
1400*38fd1498Szrj   rtx def = info->def;
1401*38fd1498Szrj   str_cpu_units = get_str_vect (XSTR (def, 0), &cpu_units_length, ',',
1402*38fd1498Szrj 				FALSE);
1403*38fd1498Szrj   if (str_cpu_units == NULL)
1404*38fd1498Szrj     fatal_at (info->loc, "invalid string `%s' in %s",
1405*38fd1498Szrj 	      XSTR (def, 0), GET_RTX_NAME (GET_CODE (def)));
1406*38fd1498Szrj   str_pattern_lists = get_str_vect (XSTR (def, 1),
1407*38fd1498Szrj 				    &patterns_length, ',', FALSE);
1408*38fd1498Szrj   if (str_pattern_lists == NULL)
1409*38fd1498Szrj     fatal_at (info->loc, "invalid string `%s' in %s",
1410*38fd1498Szrj 	      XSTR (def, 1), GET_RTX_NAME (GET_CODE (def)));
1411*38fd1498Szrj   str_patterns = XOBNEWVEC (&irp, char **, patterns_length);
1412*38fd1498Szrj   for (i = 0; i < patterns_length; i++)
1413*38fd1498Szrj     {
1414*38fd1498Szrj       str_patterns [i] = get_str_vect (str_pattern_lists [i],
1415*38fd1498Szrj 				       &length, ' ', FALSE);
1416*38fd1498Szrj       gcc_assert (str_patterns [i]);
1417*38fd1498Szrj     }
1418*38fd1498Szrj   decl = XCREATENODE (struct decl);
1419*38fd1498Szrj   decl->pos = 0;
1420*38fd1498Szrj   if (presence_p)
1421*38fd1498Szrj     {
1422*38fd1498Szrj       decl->mode = dm_presence;
1423*38fd1498Szrj       DECL_PRESENCE (decl)->names_num = cpu_units_length;
1424*38fd1498Szrj       DECL_PRESENCE (decl)->names = str_cpu_units;
1425*38fd1498Szrj       DECL_PRESENCE (decl)->patterns = str_patterns;
1426*38fd1498Szrj       DECL_PRESENCE (decl)->patterns_num = patterns_length;
1427*38fd1498Szrj       DECL_PRESENCE (decl)->final_p = final_p;
1428*38fd1498Szrj     }
1429*38fd1498Szrj   else
1430*38fd1498Szrj     {
1431*38fd1498Szrj       decl->mode = dm_absence;
1432*38fd1498Szrj       DECL_ABSENCE (decl)->names_num = cpu_units_length;
1433*38fd1498Szrj       DECL_ABSENCE (decl)->names = str_cpu_units;
1434*38fd1498Szrj       DECL_ABSENCE (decl)->patterns = str_patterns;
1435*38fd1498Szrj       DECL_ABSENCE (decl)->patterns_num = patterns_length;
1436*38fd1498Szrj       DECL_ABSENCE (decl)->final_p = final_p;
1437*38fd1498Szrj     }
1438*38fd1498Szrj   decls.safe_push (decl);
1439*38fd1498Szrj }
1440*38fd1498Szrj 
1441*38fd1498Szrj /* Process a PRESENCE_SET.
1442*38fd1498Szrj 
1443*38fd1498Szrj    This gives information about a cpu unit reservation requirements.
1444*38fd1498Szrj    We fill a struct unit_pattern_rel_decl (presence) with information
1445*38fd1498Szrj    used later by `expand_automata'.  */
1446*38fd1498Szrj static void
gen_presence_set(md_rtx_info * info)1447*38fd1498Szrj gen_presence_set (md_rtx_info *info)
1448*38fd1498Szrj {
1449*38fd1498Szrj   gen_presence_absence_set (info, TRUE, FALSE);
1450*38fd1498Szrj }
1451*38fd1498Szrj 
1452*38fd1498Szrj /* Process a FINAL_PRESENCE_SET.
1453*38fd1498Szrj 
1454*38fd1498Szrj    This gives information about a cpu unit reservation requirements.
1455*38fd1498Szrj    We fill a struct unit_pattern_rel_decl (presence) with information
1456*38fd1498Szrj    used later by `expand_automata'.  */
1457*38fd1498Szrj static void
gen_final_presence_set(md_rtx_info * info)1458*38fd1498Szrj gen_final_presence_set (md_rtx_info *info)
1459*38fd1498Szrj {
1460*38fd1498Szrj   gen_presence_absence_set (info, TRUE, TRUE);
1461*38fd1498Szrj }
1462*38fd1498Szrj 
1463*38fd1498Szrj /* Process an ABSENCE_SET.
1464*38fd1498Szrj 
1465*38fd1498Szrj    This gives information about a cpu unit reservation requirements.
1466*38fd1498Szrj    We fill a struct unit_pattern_rel_decl (absence) with information
1467*38fd1498Szrj    used later by `expand_automata'.  */
1468*38fd1498Szrj static void
gen_absence_set(md_rtx_info * info)1469*38fd1498Szrj gen_absence_set (md_rtx_info *info)
1470*38fd1498Szrj {
1471*38fd1498Szrj   gen_presence_absence_set (info, FALSE, FALSE);
1472*38fd1498Szrj }
1473*38fd1498Szrj 
1474*38fd1498Szrj /* Process a FINAL_ABSENCE_SET.
1475*38fd1498Szrj 
1476*38fd1498Szrj    This gives information about a cpu unit reservation requirements.
1477*38fd1498Szrj    We fill a struct unit_pattern_rel_decl (absence) with information
1478*38fd1498Szrj    used later by `expand_automata'.  */
1479*38fd1498Szrj static void
gen_final_absence_set(md_rtx_info * info)1480*38fd1498Szrj gen_final_absence_set (md_rtx_info *info)
1481*38fd1498Szrj {
1482*38fd1498Szrj   gen_presence_absence_set (info, FALSE, TRUE);
1483*38fd1498Szrj }
1484*38fd1498Szrj 
1485*38fd1498Szrj /* Process a DEFINE_AUTOMATON.
1486*38fd1498Szrj 
1487*38fd1498Szrj    This gives information about a finite state automaton used for
1488*38fd1498Szrj    recognizing pipeline hazards.  We fill a struct automaton_decl
1489*38fd1498Szrj    with information used later by `expand_automata'.  */
1490*38fd1498Szrj static void
gen_automaton(md_rtx_info * info)1491*38fd1498Szrj gen_automaton (md_rtx_info *info)
1492*38fd1498Szrj {
1493*38fd1498Szrj   decl_t decl;
1494*38fd1498Szrj   char **str_automata;
1495*38fd1498Szrj   int vect_length;
1496*38fd1498Szrj   int i;
1497*38fd1498Szrj 
1498*38fd1498Szrj   rtx def = info->def;
1499*38fd1498Szrj   str_automata = get_str_vect (XSTR (def, 0), &vect_length, ',', FALSE);
1500*38fd1498Szrj   if (str_automata == NULL)
1501*38fd1498Szrj     fatal_at (info->loc, "invalid string `%s' in %s",
1502*38fd1498Szrj 	      XSTR (def, 0), GET_RTX_NAME (GET_CODE (def)));
1503*38fd1498Szrj   for (i = 0; i < vect_length; i++)
1504*38fd1498Szrj     {
1505*38fd1498Szrj       decl = XCREATENODE (struct decl);
1506*38fd1498Szrj       decl->mode = dm_automaton;
1507*38fd1498Szrj       decl->pos = 0;
1508*38fd1498Szrj       DECL_AUTOMATON (decl)->name = check_name (str_automata [i], decl->pos);
1509*38fd1498Szrj       decls.safe_push (decl);
1510*38fd1498Szrj     }
1511*38fd1498Szrj }
1512*38fd1498Szrj 
1513*38fd1498Szrj /* Process an AUTOMATA_OPTION.
1514*38fd1498Szrj 
1515*38fd1498Szrj    This gives information how to generate finite state automaton used
1516*38fd1498Szrj    for recognizing pipeline hazards.  */
1517*38fd1498Szrj static void
gen_automata_option(md_rtx_info * info)1518*38fd1498Szrj gen_automata_option (md_rtx_info *info)
1519*38fd1498Szrj {
1520*38fd1498Szrj   const char *option = XSTR (info->def, 0);
1521*38fd1498Szrj   if (strcmp (option, NO_MINIMIZATION_OPTION + 1) == 0)
1522*38fd1498Szrj     no_minimization_flag = 1;
1523*38fd1498Szrj   else if (strcmp (option, TIME_OPTION + 1) == 0)
1524*38fd1498Szrj     time_flag = 1;
1525*38fd1498Szrj   else if (strcmp (option, STATS_OPTION + 1) == 0)
1526*38fd1498Szrj     stats_flag = 1;
1527*38fd1498Szrj   else if (strcmp (option, V_OPTION + 1) == 0)
1528*38fd1498Szrj     v_flag = 1;
1529*38fd1498Szrj   else if (strcmp (option, W_OPTION + 1) == 0)
1530*38fd1498Szrj     w_flag = 1;
1531*38fd1498Szrj   else if (strcmp (option, NDFA_OPTION + 1) == 0)
1532*38fd1498Szrj     ndfa_flag = 1;
1533*38fd1498Szrj   else if (strcmp (option, COLLAPSE_OPTION + 1) == 0)
1534*38fd1498Szrj     collapse_flag = 1;
1535*38fd1498Szrj   else if (strcmp (option, NO_COMB_OPTION + 1) == 0)
1536*38fd1498Szrj     no_comb_flag = 1;
1537*38fd1498Szrj   else if (strcmp (option, PROGRESS_OPTION + 1) == 0)
1538*38fd1498Szrj     progress_flag = 1;
1539*38fd1498Szrj   else
1540*38fd1498Szrj     fatal_at (info->loc, "invalid option `%s' in %s",
1541*38fd1498Szrj 	      option, GET_RTX_NAME (GET_CODE (info->def)));
1542*38fd1498Szrj }
1543*38fd1498Szrj 
1544*38fd1498Szrj /* Name in reservation to denote absence reservation.  */
1545*38fd1498Szrj #define NOTHING_NAME "nothing"
1546*38fd1498Szrj 
1547*38fd1498Szrj /* The following string contains original reservation string being
1548*38fd1498Szrj    parsed.  */
1549*38fd1498Szrj static const char *reserv_str;
1550*38fd1498Szrj 
1551*38fd1498Szrj /* Parse an element in STR.  */
1552*38fd1498Szrj static regexp_t
gen_regexp_el(const char * str)1553*38fd1498Szrj gen_regexp_el (const char *str)
1554*38fd1498Szrj {
1555*38fd1498Szrj   regexp_t regexp;
1556*38fd1498Szrj   char *dstr;
1557*38fd1498Szrj   int len;
1558*38fd1498Szrj 
1559*38fd1498Szrj   if (*str == '(')
1560*38fd1498Szrj     {
1561*38fd1498Szrj       len = strlen (str);
1562*38fd1498Szrj       if (str [len - 1] != ')')
1563*38fd1498Szrj 	fatal ("garbage after ) in reservation `%s'", reserv_str);
1564*38fd1498Szrj       dstr = XALLOCAVAR (char, len - 1);
1565*38fd1498Szrj       memcpy (dstr, str + 1, len - 2);
1566*38fd1498Szrj       dstr [len-2] = '\0';
1567*38fd1498Szrj       regexp = gen_regexp_sequence (dstr);
1568*38fd1498Szrj     }
1569*38fd1498Szrj   else if (strcmp (str, NOTHING_NAME) == 0)
1570*38fd1498Szrj     {
1571*38fd1498Szrj       regexp = XCREATENODE (struct regexp);
1572*38fd1498Szrj       regexp->mode = rm_nothing;
1573*38fd1498Szrj     }
1574*38fd1498Szrj   else
1575*38fd1498Szrj     {
1576*38fd1498Szrj       regexp = XCREATENODE (struct regexp);
1577*38fd1498Szrj       regexp->mode = rm_unit;
1578*38fd1498Szrj       REGEXP_UNIT (regexp)->name = str;
1579*38fd1498Szrj     }
1580*38fd1498Szrj   return regexp;
1581*38fd1498Szrj }
1582*38fd1498Szrj 
1583*38fd1498Szrj /* Parse construction `repeat' in STR.  */
1584*38fd1498Szrj static regexp_t
gen_regexp_repeat(const char * str)1585*38fd1498Szrj gen_regexp_repeat (const char *str)
1586*38fd1498Szrj {
1587*38fd1498Szrj   regexp_t regexp;
1588*38fd1498Szrj   regexp_t repeat;
1589*38fd1498Szrj   char **repeat_vect;
1590*38fd1498Szrj   int els_num;
1591*38fd1498Szrj   int i;
1592*38fd1498Szrj 
1593*38fd1498Szrj   repeat_vect = get_str_vect (str, &els_num, '*', TRUE);
1594*38fd1498Szrj   if (repeat_vect == NULL)
1595*38fd1498Szrj     fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1596*38fd1498Szrj   if (els_num > 1)
1597*38fd1498Szrj     {
1598*38fd1498Szrj       regexp = gen_regexp_el (repeat_vect [0]);
1599*38fd1498Szrj       for (i = 1; i < els_num; i++)
1600*38fd1498Szrj 	{
1601*38fd1498Szrj 	  repeat = XCREATENODE (struct regexp);
1602*38fd1498Szrj 	  repeat->mode = rm_repeat;
1603*38fd1498Szrj 	  REGEXP_REPEAT (repeat)->regexp = regexp;
1604*38fd1498Szrj 	  REGEXP_REPEAT (repeat)->repeat_num = atoi (repeat_vect [i]);
1605*38fd1498Szrj           if (REGEXP_REPEAT (repeat)->repeat_num <= 1)
1606*38fd1498Szrj             fatal ("repetition `%s' <= 1 in reservation `%s'",
1607*38fd1498Szrj                    str, reserv_str);
1608*38fd1498Szrj           regexp = repeat;
1609*38fd1498Szrj 	}
1610*38fd1498Szrj       return regexp;
1611*38fd1498Szrj     }
1612*38fd1498Szrj   else
1613*38fd1498Szrj     return gen_regexp_el (repeat_vect[0]);
1614*38fd1498Szrj }
1615*38fd1498Szrj 
1616*38fd1498Szrj /* Parse reservation STR which possibly contains separator '+'.  */
1617*38fd1498Szrj static regexp_t
gen_regexp_allof(const char * str)1618*38fd1498Szrj gen_regexp_allof (const char *str)
1619*38fd1498Szrj {
1620*38fd1498Szrj   regexp_t allof;
1621*38fd1498Szrj   char **allof_vect;
1622*38fd1498Szrj   int els_num;
1623*38fd1498Szrj   int i;
1624*38fd1498Szrj 
1625*38fd1498Szrj   allof_vect = get_str_vect (str, &els_num, '+', TRUE);
1626*38fd1498Szrj   if (allof_vect == NULL)
1627*38fd1498Szrj     fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1628*38fd1498Szrj   if (els_num > 1)
1629*38fd1498Szrj     {
1630*38fd1498Szrj       allof = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
1631*38fd1498Szrj 			      + sizeof (regexp_t) * (els_num - 1));
1632*38fd1498Szrj       allof->mode = rm_allof;
1633*38fd1498Szrj       REGEXP_ALLOF (allof)->regexps_num = els_num;
1634*38fd1498Szrj       for (i = 0; i < els_num; i++)
1635*38fd1498Szrj 	REGEXP_ALLOF (allof)->regexps [i] = gen_regexp_repeat (allof_vect [i]);
1636*38fd1498Szrj       return allof;
1637*38fd1498Szrj     }
1638*38fd1498Szrj   else
1639*38fd1498Szrj     return gen_regexp_repeat (allof_vect[0]);
1640*38fd1498Szrj }
1641*38fd1498Szrj 
1642*38fd1498Szrj /* Parse reservation STR which possibly contains separator '|'.  */
1643*38fd1498Szrj static regexp_t
gen_regexp_oneof(const char * str)1644*38fd1498Szrj gen_regexp_oneof (const char *str)
1645*38fd1498Szrj {
1646*38fd1498Szrj   regexp_t oneof;
1647*38fd1498Szrj   char **oneof_vect;
1648*38fd1498Szrj   int els_num;
1649*38fd1498Szrj   int i;
1650*38fd1498Szrj 
1651*38fd1498Szrj   oneof_vect = get_str_vect (str, &els_num, '|', TRUE);
1652*38fd1498Szrj   if (oneof_vect == NULL)
1653*38fd1498Szrj     fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1654*38fd1498Szrj   if (els_num > 1)
1655*38fd1498Szrj     {
1656*38fd1498Szrj       oneof = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
1657*38fd1498Szrj 			      + sizeof (regexp_t) * (els_num - 1));
1658*38fd1498Szrj       oneof->mode = rm_oneof;
1659*38fd1498Szrj       REGEXP_ONEOF (oneof)->regexps_num = els_num;
1660*38fd1498Szrj       for (i = 0; i < els_num; i++)
1661*38fd1498Szrj 	REGEXP_ONEOF (oneof)->regexps [i] = gen_regexp_allof (oneof_vect [i]);
1662*38fd1498Szrj       return oneof;
1663*38fd1498Szrj     }
1664*38fd1498Szrj   else
1665*38fd1498Szrj     return gen_regexp_allof (oneof_vect[0]);
1666*38fd1498Szrj }
1667*38fd1498Szrj 
1668*38fd1498Szrj /* Parse reservation STR which possibly contains separator ','.  */
1669*38fd1498Szrj static regexp_t
gen_regexp_sequence(const char * str)1670*38fd1498Szrj gen_regexp_sequence (const char *str)
1671*38fd1498Szrj {
1672*38fd1498Szrj   regexp_t sequence;
1673*38fd1498Szrj   char **sequence_vect;
1674*38fd1498Szrj   int els_num;
1675*38fd1498Szrj   int i;
1676*38fd1498Szrj 
1677*38fd1498Szrj   sequence_vect = get_str_vect (str, &els_num, ',', TRUE);
1678*38fd1498Szrj   if (els_num == -1)
1679*38fd1498Szrj     fatal ("unbalanced parentheses in reservation `%s'", str);
1680*38fd1498Szrj   if (sequence_vect == NULL)
1681*38fd1498Szrj     fatal ("invalid reservation `%s'", str);
1682*38fd1498Szrj   if (els_num > 1)
1683*38fd1498Szrj     {
1684*38fd1498Szrj       sequence = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
1685*38fd1498Szrj 				 + sizeof (regexp_t) * (els_num - 1));
1686*38fd1498Szrj       sequence->mode = rm_sequence;
1687*38fd1498Szrj       REGEXP_SEQUENCE (sequence)->regexps_num = els_num;
1688*38fd1498Szrj       for (i = 0; i < els_num; i++)
1689*38fd1498Szrj 	REGEXP_SEQUENCE (sequence)->regexps [i]
1690*38fd1498Szrj           = gen_regexp_oneof (sequence_vect [i]);
1691*38fd1498Szrj       return sequence;
1692*38fd1498Szrj     }
1693*38fd1498Szrj   else
1694*38fd1498Szrj     return gen_regexp_oneof (sequence_vect[0]);
1695*38fd1498Szrj }
1696*38fd1498Szrj 
1697*38fd1498Szrj /* Parse construction reservation STR.  */
1698*38fd1498Szrj static regexp_t
gen_regexp(const char * str)1699*38fd1498Szrj gen_regexp (const char *str)
1700*38fd1498Szrj {
1701*38fd1498Szrj   reserv_str = str;
1702*38fd1498Szrj   return gen_regexp_sequence (str);
1703*38fd1498Szrj }
1704*38fd1498Szrj 
1705*38fd1498Szrj /* Process a DEFINE_RESERVATION.
1706*38fd1498Szrj 
1707*38fd1498Szrj    This gives information about a reservation of cpu units.  We fill
1708*38fd1498Szrj    in a struct reserv_decl with information used later by
1709*38fd1498Szrj    `expand_automata'.  */
1710*38fd1498Szrj static void
gen_reserv(md_rtx_info * info)1711*38fd1498Szrj gen_reserv (md_rtx_info *info)
1712*38fd1498Szrj {
1713*38fd1498Szrj   decl_t decl;
1714*38fd1498Szrj 
1715*38fd1498Szrj   rtx def = info->def;
1716*38fd1498Szrj   decl = XCREATENODE (struct decl);
1717*38fd1498Szrj   decl->mode = dm_reserv;
1718*38fd1498Szrj   decl->pos = 0;
1719*38fd1498Szrj   DECL_RESERV (decl)->name = check_name (XSTR (def, 0), decl->pos);
1720*38fd1498Szrj   DECL_RESERV (decl)->regexp = gen_regexp (XSTR (def, 1));
1721*38fd1498Szrj   decls.safe_push (decl);
1722*38fd1498Szrj }
1723*38fd1498Szrj 
1724*38fd1498Szrj /* Process a DEFINE_INSN_RESERVATION.
1725*38fd1498Szrj 
1726*38fd1498Szrj    This gives information about the reservation of cpu units by an
1727*38fd1498Szrj    insn.  We fill a struct insn_reserv_decl with information used
1728*38fd1498Szrj    later by `expand_automata'.  */
1729*38fd1498Szrj static void
gen_insn_reserv(md_rtx_info * info)1730*38fd1498Szrj gen_insn_reserv (md_rtx_info *info)
1731*38fd1498Szrj {
1732*38fd1498Szrj   decl_t decl;
1733*38fd1498Szrj 
1734*38fd1498Szrj   rtx def = info->def;
1735*38fd1498Szrj   decl = XCREATENODE (struct decl);
1736*38fd1498Szrj   decl->mode = dm_insn_reserv;
1737*38fd1498Szrj   decl->pos = 0;
1738*38fd1498Szrj   DECL_INSN_RESERV (decl)->name
1739*38fd1498Szrj     = check_name (XSTR (def, 0), decl->pos);
1740*38fd1498Szrj   DECL_INSN_RESERV (decl)->default_latency = XINT (def, 1);
1741*38fd1498Szrj   DECL_INSN_RESERV (decl)->condexp = XEXP (def, 2);
1742*38fd1498Szrj   DECL_INSN_RESERV (decl)->regexp = gen_regexp (XSTR (def, 3));
1743*38fd1498Szrj   decls.safe_push (decl);
1744*38fd1498Szrj }
1745*38fd1498Szrj 
1746*38fd1498Szrj 
1747*38fd1498Szrj 
1748*38fd1498Szrj /* The function evaluates hash value (0..UINT_MAX) of string.  */
1749*38fd1498Szrj static unsigned
string_hash(const char * string)1750*38fd1498Szrj string_hash (const char *string)
1751*38fd1498Szrj {
1752*38fd1498Szrj   unsigned result, i;
1753*38fd1498Szrj 
1754*38fd1498Szrj   for (result = i = 0;*string++ != '\0'; i++)
1755*38fd1498Szrj     result += ((unsigned char) *string << (i % CHAR_BIT));
1756*38fd1498Szrj   return result;
1757*38fd1498Szrj }
1758*38fd1498Szrj 
1759*38fd1498Szrj 
1760*38fd1498Szrj 
1761*38fd1498Szrj /* This page contains abstract data `table of automaton declarations'.
1762*38fd1498Szrj    Elements of the table is nodes representing automaton declarations.
1763*38fd1498Szrj    Key of the table elements is name of given automaton.  Remember
1764*38fd1498Szrj    that automaton names have own space.  */
1765*38fd1498Szrj 
1766*38fd1498Szrj /* The function evaluates hash value of an automaton declaration.  The
1767*38fd1498Szrj    function is used by abstract data `hashtab'.  The function returns
1768*38fd1498Szrj    hash value (0..UINT_MAX) of given automaton declaration.  */
1769*38fd1498Szrj static hashval_t
automaton_decl_hash(const void * automaton_decl)1770*38fd1498Szrj automaton_decl_hash (const void *automaton_decl)
1771*38fd1498Szrj {
1772*38fd1498Szrj   const_decl_t const decl = (const_decl_t) automaton_decl;
1773*38fd1498Szrj 
1774*38fd1498Szrj   gcc_assert (decl->mode != dm_automaton
1775*38fd1498Szrj 	      || DECL_AUTOMATON (decl)->name);
1776*38fd1498Szrj   return string_hash (DECL_AUTOMATON (decl)->name);
1777*38fd1498Szrj }
1778*38fd1498Szrj 
1779*38fd1498Szrj /* The function tests automaton declarations on equality of their
1780*38fd1498Szrj    keys.  The function is used by abstract data `hashtab'.  The
1781*38fd1498Szrj    function returns 1 if the declarations have the same key, 0
1782*38fd1498Szrj    otherwise.  */
1783*38fd1498Szrj static int
automaton_decl_eq_p(const void * automaton_decl_1,const void * automaton_decl_2)1784*38fd1498Szrj automaton_decl_eq_p (const void* automaton_decl_1,
1785*38fd1498Szrj 		     const void* automaton_decl_2)
1786*38fd1498Szrj {
1787*38fd1498Szrj   const_decl_t const decl1 = (const_decl_t) automaton_decl_1;
1788*38fd1498Szrj   const_decl_t const decl2 = (const_decl_t) automaton_decl_2;
1789*38fd1498Szrj 
1790*38fd1498Szrj   gcc_assert (decl1->mode == dm_automaton
1791*38fd1498Szrj 	      && DECL_AUTOMATON (decl1)->name
1792*38fd1498Szrj 	      && decl2->mode == dm_automaton
1793*38fd1498Szrj 	      && DECL_AUTOMATON (decl2)->name);
1794*38fd1498Szrj   return strcmp (DECL_AUTOMATON (decl1)->name,
1795*38fd1498Szrj 		 DECL_AUTOMATON (decl2)->name) == 0;
1796*38fd1498Szrj }
1797*38fd1498Szrj 
1798*38fd1498Szrj /* The automaton declaration table itself is represented by the
1799*38fd1498Szrj    following variable.  */
1800*38fd1498Szrj static htab_t automaton_decl_table;
1801*38fd1498Szrj 
1802*38fd1498Szrj /* The function inserts automaton declaration into the table.  The
1803*38fd1498Szrj    function does nothing if an automaton declaration with the same key
1804*38fd1498Szrj    exists already in the table.  The function returns automaton
1805*38fd1498Szrj    declaration node in the table with the same key as given automaton
1806*38fd1498Szrj    declaration node.  */
1807*38fd1498Szrj static decl_t
insert_automaton_decl(decl_t automaton_decl)1808*38fd1498Szrj insert_automaton_decl (decl_t automaton_decl)
1809*38fd1498Szrj {
1810*38fd1498Szrj   void **entry_ptr;
1811*38fd1498Szrj 
1812*38fd1498Szrj   entry_ptr = htab_find_slot (automaton_decl_table, automaton_decl, INSERT);
1813*38fd1498Szrj   if (*entry_ptr == NULL)
1814*38fd1498Szrj     *entry_ptr = (void *) automaton_decl;
1815*38fd1498Szrj   return (decl_t) *entry_ptr;
1816*38fd1498Szrj }
1817*38fd1498Szrj 
1818*38fd1498Szrj /* The following variable value is node representing automaton
1819*38fd1498Szrj    declaration.  The node used for searching automaton declaration
1820*38fd1498Szrj    with given name.  */
1821*38fd1498Szrj static struct decl work_automaton_decl;
1822*38fd1498Szrj 
1823*38fd1498Szrj /* The function searches for automaton declaration in the table with
1824*38fd1498Szrj    the same key as node representing name of the automaton
1825*38fd1498Szrj    declaration.  The function returns node found in the table, NULL if
1826*38fd1498Szrj    such node does not exist in the table.  */
1827*38fd1498Szrj static decl_t
find_automaton_decl(const char * name)1828*38fd1498Szrj find_automaton_decl (const char *name)
1829*38fd1498Szrj {
1830*38fd1498Szrj   void *entry;
1831*38fd1498Szrj 
1832*38fd1498Szrj   work_automaton_decl.mode = dm_automaton;
1833*38fd1498Szrj   DECL_AUTOMATON (&work_automaton_decl)->name = name;
1834*38fd1498Szrj   entry = htab_find (automaton_decl_table, &work_automaton_decl);
1835*38fd1498Szrj   return (decl_t) entry;
1836*38fd1498Szrj }
1837*38fd1498Szrj 
1838*38fd1498Szrj /* The function creates empty automaton declaration table and node
1839*38fd1498Szrj    representing automaton declaration and used for searching automaton
1840*38fd1498Szrj    declaration with given name.  The function must be called only once
1841*38fd1498Szrj    before any work with the automaton declaration table.  */
1842*38fd1498Szrj static void
initiate_automaton_decl_table(void)1843*38fd1498Szrj initiate_automaton_decl_table (void)
1844*38fd1498Szrj {
1845*38fd1498Szrj   work_automaton_decl.mode = dm_automaton;
1846*38fd1498Szrj   automaton_decl_table = htab_create (10, automaton_decl_hash,
1847*38fd1498Szrj 				      automaton_decl_eq_p, (htab_del) 0);
1848*38fd1498Szrj }
1849*38fd1498Szrj 
1850*38fd1498Szrj /* The function deletes the automaton declaration table.  Only call of
1851*38fd1498Szrj    function `initiate_automaton_decl_table' is possible immediately
1852*38fd1498Szrj    after this function call.  */
1853*38fd1498Szrj static void
finish_automaton_decl_table(void)1854*38fd1498Szrj finish_automaton_decl_table (void)
1855*38fd1498Szrj {
1856*38fd1498Szrj   htab_delete (automaton_decl_table);
1857*38fd1498Szrj }
1858*38fd1498Szrj 
1859*38fd1498Szrj 
1860*38fd1498Szrj 
1861*38fd1498Szrj /* This page contains abstract data `table of insn declarations'.
1862*38fd1498Szrj    Elements of the table is nodes representing insn declarations.  Key
1863*38fd1498Szrj    of the table elements is name of given insn (in corresponding
1864*38fd1498Szrj    define_insn_reservation).  Remember that insn names have own
1865*38fd1498Szrj    space.  */
1866*38fd1498Szrj 
1867*38fd1498Szrj /* The function evaluates hash value of an insn declaration.  The
1868*38fd1498Szrj    function is used by abstract data `hashtab'.  The function returns
1869*38fd1498Szrj    hash value (0..UINT_MAX) of given insn declaration.  */
1870*38fd1498Szrj static hashval_t
insn_decl_hash(const void * insn_decl)1871*38fd1498Szrj insn_decl_hash (const void *insn_decl)
1872*38fd1498Szrj {
1873*38fd1498Szrj   const_decl_t const decl = (const_decl_t) insn_decl;
1874*38fd1498Szrj 
1875*38fd1498Szrj   gcc_assert (decl->mode == dm_insn_reserv
1876*38fd1498Szrj 	      && DECL_INSN_RESERV (decl)->name);
1877*38fd1498Szrj   return string_hash (DECL_INSN_RESERV (decl)->name);
1878*38fd1498Szrj }
1879*38fd1498Szrj 
1880*38fd1498Szrj /* The function tests insn declarations on equality of their keys.
1881*38fd1498Szrj    The function is used by abstract data `hashtab'.  The function
1882*38fd1498Szrj    returns 1 if declarations have the same key, 0 otherwise.  */
1883*38fd1498Szrj static int
insn_decl_eq_p(const void * insn_decl_1,const void * insn_decl_2)1884*38fd1498Szrj insn_decl_eq_p (const void *insn_decl_1, const void *insn_decl_2)
1885*38fd1498Szrj {
1886*38fd1498Szrj   const_decl_t const decl1 = (const_decl_t) insn_decl_1;
1887*38fd1498Szrj   const_decl_t const decl2 = (const_decl_t) insn_decl_2;
1888*38fd1498Szrj 
1889*38fd1498Szrj   gcc_assert (decl1->mode == dm_insn_reserv
1890*38fd1498Szrj 	      && DECL_INSN_RESERV (decl1)->name
1891*38fd1498Szrj 	      && decl2->mode == dm_insn_reserv
1892*38fd1498Szrj 	      && DECL_INSN_RESERV (decl2)->name);
1893*38fd1498Szrj   return strcmp (DECL_INSN_RESERV (decl1)->name,
1894*38fd1498Szrj                  DECL_INSN_RESERV (decl2)->name) == 0;
1895*38fd1498Szrj }
1896*38fd1498Szrj 
1897*38fd1498Szrj /* The insn declaration table itself is represented by the following
1898*38fd1498Szrj    variable.  The table does not contain insn reservation
1899*38fd1498Szrj    declarations.  */
1900*38fd1498Szrj static htab_t insn_decl_table;
1901*38fd1498Szrj 
1902*38fd1498Szrj /* The function inserts insn declaration into the table.  The function
1903*38fd1498Szrj    does nothing if an insn declaration with the same key exists
1904*38fd1498Szrj    already in the table.  The function returns insn declaration node
1905*38fd1498Szrj    in the table with the same key as given insn declaration node.  */
1906*38fd1498Szrj static decl_t
insert_insn_decl(decl_t insn_decl)1907*38fd1498Szrj insert_insn_decl (decl_t insn_decl)
1908*38fd1498Szrj {
1909*38fd1498Szrj   void **entry_ptr;
1910*38fd1498Szrj 
1911*38fd1498Szrj   entry_ptr = htab_find_slot (insn_decl_table, insn_decl, INSERT);
1912*38fd1498Szrj   if (*entry_ptr == NULL)
1913*38fd1498Szrj     *entry_ptr = (void *) insn_decl;
1914*38fd1498Szrj   return (decl_t) *entry_ptr;
1915*38fd1498Szrj }
1916*38fd1498Szrj 
1917*38fd1498Szrj /* The following variable value is node representing insn reservation
1918*38fd1498Szrj    declaration.  The node used for searching insn reservation
1919*38fd1498Szrj    declaration with given name.  */
1920*38fd1498Szrj static struct decl work_insn_decl;
1921*38fd1498Szrj 
1922*38fd1498Szrj /* The function searches for insn reservation declaration in the table
1923*38fd1498Szrj    with the same key as node representing name of the insn reservation
1924*38fd1498Szrj    declaration.  The function returns node found in the table, NULL if
1925*38fd1498Szrj    such node does not exist in the table.  */
1926*38fd1498Szrj static decl_t
find_insn_decl(const char * name)1927*38fd1498Szrj find_insn_decl (const char *name)
1928*38fd1498Szrj {
1929*38fd1498Szrj   void *entry;
1930*38fd1498Szrj 
1931*38fd1498Szrj   work_insn_decl.mode = dm_insn_reserv;
1932*38fd1498Szrj   DECL_INSN_RESERV (&work_insn_decl)->name = name;
1933*38fd1498Szrj   entry = htab_find (insn_decl_table, &work_insn_decl);
1934*38fd1498Szrj   return (decl_t) entry;
1935*38fd1498Szrj }
1936*38fd1498Szrj 
1937*38fd1498Szrj /* The function creates empty insn declaration table and node
1938*38fd1498Szrj    representing insn declaration and used for searching insn
1939*38fd1498Szrj    declaration with given name.  The function must be called only once
1940*38fd1498Szrj    before any work with the insn declaration table.  */
1941*38fd1498Szrj static void
initiate_insn_decl_table(void)1942*38fd1498Szrj initiate_insn_decl_table (void)
1943*38fd1498Szrj {
1944*38fd1498Szrj   work_insn_decl.mode = dm_insn_reserv;
1945*38fd1498Szrj   insn_decl_table = htab_create (10, insn_decl_hash, insn_decl_eq_p,
1946*38fd1498Szrj 				 (htab_del) 0);
1947*38fd1498Szrj }
1948*38fd1498Szrj 
1949*38fd1498Szrj /* The function deletes the insn declaration table.  Only call of
1950*38fd1498Szrj    function `initiate_insn_decl_table' is possible immediately after
1951*38fd1498Szrj    this function call.  */
1952*38fd1498Szrj static void
finish_insn_decl_table(void)1953*38fd1498Szrj finish_insn_decl_table (void)
1954*38fd1498Szrj {
1955*38fd1498Szrj   htab_delete (insn_decl_table);
1956*38fd1498Szrj }
1957*38fd1498Szrj 
1958*38fd1498Szrj 
1959*38fd1498Szrj 
1960*38fd1498Szrj /* This page contains abstract data `table of declarations'.  Elements
1961*38fd1498Szrj    of the table is nodes representing declarations (of units and
1962*38fd1498Szrj    reservations).  Key of the table elements is names of given
1963*38fd1498Szrj    declarations.  */
1964*38fd1498Szrj 
1965*38fd1498Szrj /* The function evaluates hash value of a declaration.  The function
1966*38fd1498Szrj    is used by abstract data `hashtab'.  The function returns hash
1967*38fd1498Szrj    value (0..UINT_MAX) of given declaration.  */
1968*38fd1498Szrj static hashval_t
decl_hash(const void * decl)1969*38fd1498Szrj decl_hash (const void *decl)
1970*38fd1498Szrj {
1971*38fd1498Szrj   const_decl_t const d = (const_decl_t) decl;
1972*38fd1498Szrj 
1973*38fd1498Szrj   gcc_assert ((d->mode == dm_unit && DECL_UNIT (d)->name)
1974*38fd1498Szrj 	      || (d->mode == dm_reserv && DECL_RESERV (d)->name));
1975*38fd1498Szrj   return string_hash (d->mode == dm_unit
1976*38fd1498Szrj 		      ? DECL_UNIT (d)->name : DECL_RESERV (d)->name);
1977*38fd1498Szrj }
1978*38fd1498Szrj 
1979*38fd1498Szrj /* The function tests declarations on equality of their keys.  The
1980*38fd1498Szrj    function is used by abstract data 'hashtab'.  The function
1981*38fd1498Szrj    returns 1 if the declarations have the same key, 0 otherwise.  */
1982*38fd1498Szrj static int
decl_eq_p(const void * decl_1,const void * decl_2)1983*38fd1498Szrj decl_eq_p (const void *decl_1, const void *decl_2)
1984*38fd1498Szrj {
1985*38fd1498Szrj   const_decl_t const d1 = (const_decl_t) decl_1;
1986*38fd1498Szrj   const_decl_t const d2 = (const_decl_t) decl_2;
1987*38fd1498Szrj 
1988*38fd1498Szrj   gcc_assert ((d1->mode == dm_unit && DECL_UNIT (d1)->name)
1989*38fd1498Szrj 	      || (d1->mode == dm_reserv && DECL_RESERV (d1)->name));
1990*38fd1498Szrj   gcc_assert ((d2->mode == dm_unit && DECL_UNIT (d2)->name)
1991*38fd1498Szrj 	      || (d2->mode == dm_reserv && DECL_RESERV (d2)->name));
1992*38fd1498Szrj   return strcmp ((d1->mode == dm_unit
1993*38fd1498Szrj                   ? DECL_UNIT (d1)->name : DECL_RESERV (d1)->name),
1994*38fd1498Szrj                  (d2->mode == dm_unit
1995*38fd1498Szrj                   ? DECL_UNIT (d2)->name : DECL_RESERV (d2)->name)) == 0;
1996*38fd1498Szrj }
1997*38fd1498Szrj 
1998*38fd1498Szrj /* The declaration table itself is represented by the following
1999*38fd1498Szrj    variable.  */
2000*38fd1498Szrj static htab_t decl_table;
2001*38fd1498Szrj 
2002*38fd1498Szrj /* The function inserts declaration into the table.  The function does
2003*38fd1498Szrj    nothing if a declaration with the same key exists already in the
2004*38fd1498Szrj    table.  The function returns declaration node in the table with the
2005*38fd1498Szrj    same key as given declaration node.  */
2006*38fd1498Szrj 
2007*38fd1498Szrj static decl_t
insert_decl(decl_t decl)2008*38fd1498Szrj insert_decl (decl_t decl)
2009*38fd1498Szrj {
2010*38fd1498Szrj   void **entry_ptr;
2011*38fd1498Szrj 
2012*38fd1498Szrj   entry_ptr = htab_find_slot (decl_table, decl, INSERT);
2013*38fd1498Szrj   if (*entry_ptr == NULL)
2014*38fd1498Szrj     *entry_ptr = (void *) decl;
2015*38fd1498Szrj   return (decl_t) *entry_ptr;
2016*38fd1498Szrj }
2017*38fd1498Szrj 
2018*38fd1498Szrj /* The following variable value is node representing declaration.  The
2019*38fd1498Szrj    node used for searching declaration with given name.  */
2020*38fd1498Szrj static struct decl work_decl;
2021*38fd1498Szrj 
2022*38fd1498Szrj /* The function searches for declaration in the table with the same
2023*38fd1498Szrj    key as node representing name of the declaration.  The function
2024*38fd1498Szrj    returns node found in the table, NULL if such node does not exist
2025*38fd1498Szrj    in the table.  */
2026*38fd1498Szrj static decl_t
find_decl(const char * name)2027*38fd1498Szrj find_decl (const char *name)
2028*38fd1498Szrj {
2029*38fd1498Szrj   void *entry;
2030*38fd1498Szrj 
2031*38fd1498Szrj   work_decl.mode = dm_unit;
2032*38fd1498Szrj   DECL_UNIT (&work_decl)->name = name;
2033*38fd1498Szrj   entry = htab_find (decl_table, &work_decl);
2034*38fd1498Szrj   return (decl_t) entry;
2035*38fd1498Szrj }
2036*38fd1498Szrj 
2037*38fd1498Szrj /* The function creates empty declaration table and node representing
2038*38fd1498Szrj    declaration and used for searching declaration with given name.
2039*38fd1498Szrj    The function must be called only once before any work with the
2040*38fd1498Szrj    declaration table.  */
2041*38fd1498Szrj static void
initiate_decl_table(void)2042*38fd1498Szrj initiate_decl_table (void)
2043*38fd1498Szrj {
2044*38fd1498Szrj   work_decl.mode = dm_unit;
2045*38fd1498Szrj   decl_table = htab_create (10, decl_hash, decl_eq_p, (htab_del) 0);
2046*38fd1498Szrj }
2047*38fd1498Szrj 
2048*38fd1498Szrj /* The function deletes the declaration table.  Only call of function
2049*38fd1498Szrj    `initiate_declaration_table' is possible immediately after this
2050*38fd1498Szrj    function call.  */
2051*38fd1498Szrj static void
finish_decl_table(void)2052*38fd1498Szrj finish_decl_table (void)
2053*38fd1498Szrj {
2054*38fd1498Szrj   htab_delete (decl_table);
2055*38fd1498Szrj }
2056*38fd1498Szrj 
2057*38fd1498Szrj 
2058*38fd1498Szrj 
2059*38fd1498Szrj /* This page contains checker of pipeline hazard description.  */
2060*38fd1498Szrj 
2061*38fd1498Szrj /* Checking NAMES in an exclusion clause vector and returning formed
2062*38fd1498Szrj    unit_set_el_list.  */
2063*38fd1498Szrj static unit_set_el_t
process_excls(char ** names,int num,pos_t excl_pos ATTRIBUTE_UNUSED)2064*38fd1498Szrj process_excls (char **names, int num, pos_t excl_pos ATTRIBUTE_UNUSED)
2065*38fd1498Szrj {
2066*38fd1498Szrj   unit_set_el_t el_list;
2067*38fd1498Szrj   unit_set_el_t last_el;
2068*38fd1498Szrj   unit_set_el_t new_el;
2069*38fd1498Szrj   decl_t decl_in_table;
2070*38fd1498Szrj   int i;
2071*38fd1498Szrj 
2072*38fd1498Szrj   el_list = NULL;
2073*38fd1498Szrj   last_el = NULL;
2074*38fd1498Szrj   for (i = 0; i < num; i++)
2075*38fd1498Szrj     {
2076*38fd1498Szrj       decl_in_table = find_decl (names [i]);
2077*38fd1498Szrj       if (decl_in_table == NULL)
2078*38fd1498Szrj 	error ("unit `%s' in exclusion is not declared", names [i]);
2079*38fd1498Szrj       else if (decl_in_table->mode != dm_unit)
2080*38fd1498Szrj 	error ("`%s' in exclusion is not unit", names [i]);
2081*38fd1498Szrj       else
2082*38fd1498Szrj 	{
2083*38fd1498Szrj 	  new_el = XCREATENODE (struct unit_set_el);
2084*38fd1498Szrj 	  new_el->unit_decl = DECL_UNIT (decl_in_table);
2085*38fd1498Szrj 	  new_el->next_unit_set_el = NULL;
2086*38fd1498Szrj 	  if (last_el == NULL)
2087*38fd1498Szrj 	    el_list = last_el = new_el;
2088*38fd1498Szrj 	  else
2089*38fd1498Szrj 	    {
2090*38fd1498Szrj 	      last_el->next_unit_set_el = new_el;
2091*38fd1498Szrj 	      last_el = last_el->next_unit_set_el;
2092*38fd1498Szrj 	    }
2093*38fd1498Szrj 	}
2094*38fd1498Szrj     }
2095*38fd1498Szrj   return el_list;
2096*38fd1498Szrj }
2097*38fd1498Szrj 
2098*38fd1498Szrj /* The function adds each element from SOURCE_LIST to the exclusion
2099*38fd1498Szrj    list of the each element from DEST_LIST.  Checking situation "unit
2100*38fd1498Szrj    excludes itself".  */
2101*38fd1498Szrj static void
add_excls(unit_set_el_t dest_list,unit_set_el_t source_list,pos_t excl_pos ATTRIBUTE_UNUSED)2102*38fd1498Szrj add_excls (unit_set_el_t dest_list, unit_set_el_t source_list,
2103*38fd1498Szrj 	   pos_t excl_pos ATTRIBUTE_UNUSED)
2104*38fd1498Szrj {
2105*38fd1498Szrj   unit_set_el_t dst;
2106*38fd1498Szrj   unit_set_el_t src;
2107*38fd1498Szrj   unit_set_el_t curr_el;
2108*38fd1498Szrj   unit_set_el_t prev_el;
2109*38fd1498Szrj   unit_set_el_t copy;
2110*38fd1498Szrj 
2111*38fd1498Szrj   for (dst = dest_list; dst != NULL; dst = dst->next_unit_set_el)
2112*38fd1498Szrj     for (src = source_list; src != NULL; src = src->next_unit_set_el)
2113*38fd1498Szrj       {
2114*38fd1498Szrj 	if (dst->unit_decl == src->unit_decl)
2115*38fd1498Szrj 	  {
2116*38fd1498Szrj 	    error ("unit `%s' excludes itself", src->unit_decl->name);
2117*38fd1498Szrj 	    continue;
2118*38fd1498Szrj 	  }
2119*38fd1498Szrj 	if (dst->unit_decl->automaton_name != NULL
2120*38fd1498Szrj 	    && src->unit_decl->automaton_name != NULL
2121*38fd1498Szrj 	    && strcmp (dst->unit_decl->automaton_name,
2122*38fd1498Szrj 		       src->unit_decl->automaton_name) != 0)
2123*38fd1498Szrj 	  {
2124*38fd1498Szrj 	    error ("units `%s' and `%s' in exclusion set belong to different automata",
2125*38fd1498Szrj 		   src->unit_decl->name, dst->unit_decl->name);
2126*38fd1498Szrj 	    continue;
2127*38fd1498Szrj 	  }
2128*38fd1498Szrj 	for (curr_el = dst->unit_decl->excl_list, prev_el = NULL;
2129*38fd1498Szrj 	     curr_el != NULL;
2130*38fd1498Szrj 	     prev_el = curr_el, curr_el = curr_el->next_unit_set_el)
2131*38fd1498Szrj 	  if (curr_el->unit_decl == src->unit_decl)
2132*38fd1498Szrj 	    break;
2133*38fd1498Szrj 	if (curr_el == NULL)
2134*38fd1498Szrj 	  {
2135*38fd1498Szrj 	    /* Element not found - insert.  */
2136*38fd1498Szrj 	    copy = XCOPYNODE (struct unit_set_el, src);
2137*38fd1498Szrj 	    copy->next_unit_set_el = NULL;
2138*38fd1498Szrj 	    if (prev_el == NULL)
2139*38fd1498Szrj 	      dst->unit_decl->excl_list = copy;
2140*38fd1498Szrj 	    else
2141*38fd1498Szrj 	      prev_el->next_unit_set_el = copy;
2142*38fd1498Szrj 	}
2143*38fd1498Szrj     }
2144*38fd1498Szrj }
2145*38fd1498Szrj 
2146*38fd1498Szrj /* Checking NAMES in presence/absence clause and returning the
2147*38fd1498Szrj    formed unit_set_el_list.  The function is called only after
2148*38fd1498Szrj    processing all exclusion sets.  */
2149*38fd1498Szrj static unit_set_el_t
process_presence_absence_names(char ** names,int num,pos_t req_pos ATTRIBUTE_UNUSED,int presence_p,int final_p)2150*38fd1498Szrj process_presence_absence_names (char **names, int num,
2151*38fd1498Szrj 				pos_t req_pos ATTRIBUTE_UNUSED,
2152*38fd1498Szrj 				int presence_p, int final_p)
2153*38fd1498Szrj {
2154*38fd1498Szrj   unit_set_el_t el_list;
2155*38fd1498Szrj   unit_set_el_t last_el;
2156*38fd1498Szrj   unit_set_el_t new_el;
2157*38fd1498Szrj   decl_t decl_in_table;
2158*38fd1498Szrj   int i;
2159*38fd1498Szrj 
2160*38fd1498Szrj   el_list = NULL;
2161*38fd1498Szrj   last_el = NULL;
2162*38fd1498Szrj   for (i = 0; i < num; i++)
2163*38fd1498Szrj     {
2164*38fd1498Szrj       decl_in_table = find_decl (names [i]);
2165*38fd1498Szrj       if (decl_in_table == NULL)
2166*38fd1498Szrj 	error ((presence_p
2167*38fd1498Szrj 		? (final_p
2168*38fd1498Szrj 		   ? "unit `%s' in final presence set is not declared"
2169*38fd1498Szrj 		   : "unit `%s' in presence set is not declared")
2170*38fd1498Szrj 		: (final_p
2171*38fd1498Szrj 		   ? "unit `%s' in final absence set is not declared"
2172*38fd1498Szrj 		   : "unit `%s' in absence set is not declared")), names [i]);
2173*38fd1498Szrj       else if (decl_in_table->mode != dm_unit)
2174*38fd1498Szrj 	error ((presence_p
2175*38fd1498Szrj 		? (final_p
2176*38fd1498Szrj 		   ? "`%s' in final presence set is not unit"
2177*38fd1498Szrj 		   : "`%s' in presence set is not unit")
2178*38fd1498Szrj 		: (final_p
2179*38fd1498Szrj 		   ? "`%s' in final absence set is not unit"
2180*38fd1498Szrj 		   : "`%s' in absence set is not unit")), names [i]);
2181*38fd1498Szrj       else
2182*38fd1498Szrj 	{
2183*38fd1498Szrj 	  new_el = XCREATENODE (struct unit_set_el);
2184*38fd1498Szrj 	  new_el->unit_decl = DECL_UNIT (decl_in_table);
2185*38fd1498Szrj 	  new_el->next_unit_set_el = NULL;
2186*38fd1498Szrj 	  if (last_el == NULL)
2187*38fd1498Szrj 	    el_list = last_el = new_el;
2188*38fd1498Szrj 	  else
2189*38fd1498Szrj 	    {
2190*38fd1498Szrj 	      last_el->next_unit_set_el = new_el;
2191*38fd1498Szrj 	      last_el = last_el->next_unit_set_el;
2192*38fd1498Szrj 	    }
2193*38fd1498Szrj 	}
2194*38fd1498Szrj     }
2195*38fd1498Szrj   return el_list;
2196*38fd1498Szrj }
2197*38fd1498Szrj 
2198*38fd1498Szrj /* Checking NAMES in patterns of a presence/absence clause and
2199*38fd1498Szrj    returning the formed pattern_set_el_list.  The function is called
2200*38fd1498Szrj    only after processing all exclusion sets.  */
2201*38fd1498Szrj static pattern_set_el_t
process_presence_absence_patterns(char *** patterns,int num,pos_t req_pos ATTRIBUTE_UNUSED,int presence_p,int final_p)2202*38fd1498Szrj process_presence_absence_patterns (char ***patterns, int num,
2203*38fd1498Szrj 				   pos_t req_pos ATTRIBUTE_UNUSED,
2204*38fd1498Szrj 				   int presence_p, int final_p)
2205*38fd1498Szrj {
2206*38fd1498Szrj   pattern_set_el_t el_list;
2207*38fd1498Szrj   pattern_set_el_t last_el;
2208*38fd1498Szrj   pattern_set_el_t new_el;
2209*38fd1498Szrj   decl_t decl_in_table;
2210*38fd1498Szrj   int i, j;
2211*38fd1498Szrj 
2212*38fd1498Szrj   el_list = NULL;
2213*38fd1498Szrj   last_el = NULL;
2214*38fd1498Szrj   for (i = 0; i < num; i++)
2215*38fd1498Szrj     {
2216*38fd1498Szrj       for (j = 0; patterns [i] [j] != NULL; j++)
2217*38fd1498Szrj 	;
2218*38fd1498Szrj       new_el = XCREATENODEVAR (struct pattern_set_el,
2219*38fd1498Szrj 			       sizeof (struct pattern_set_el)
2220*38fd1498Szrj 			       + sizeof (struct unit_decl *) * j);
2221*38fd1498Szrj       new_el->unit_decls
2222*38fd1498Szrj 	= (struct unit_decl **) ((char *) new_el
2223*38fd1498Szrj 				 + sizeof (struct pattern_set_el));
2224*38fd1498Szrj       new_el->next_pattern_set_el = NULL;
2225*38fd1498Szrj       if (last_el == NULL)
2226*38fd1498Szrj 	el_list = last_el = new_el;
2227*38fd1498Szrj       else
2228*38fd1498Szrj 	{
2229*38fd1498Szrj 	  last_el->next_pattern_set_el = new_el;
2230*38fd1498Szrj 	  last_el = last_el->next_pattern_set_el;
2231*38fd1498Szrj 	}
2232*38fd1498Szrj       new_el->units_num = 0;
2233*38fd1498Szrj       for (j = 0; patterns [i] [j] != NULL; j++)
2234*38fd1498Szrj 	{
2235*38fd1498Szrj 	  decl_in_table = find_decl (patterns [i] [j]);
2236*38fd1498Szrj 	  if (decl_in_table == NULL)
2237*38fd1498Szrj 	    error ((presence_p
2238*38fd1498Szrj 		    ? (final_p
2239*38fd1498Szrj 		       ? "unit `%s' in final presence set is not declared"
2240*38fd1498Szrj 		       : "unit `%s' in presence set is not declared")
2241*38fd1498Szrj 		    : (final_p
2242*38fd1498Szrj 		       ? "unit `%s' in final absence set is not declared"
2243*38fd1498Szrj 		       : "unit `%s' in absence set is not declared")),
2244*38fd1498Szrj 		   patterns [i] [j]);
2245*38fd1498Szrj 	  else if (decl_in_table->mode != dm_unit)
2246*38fd1498Szrj 	    error ((presence_p
2247*38fd1498Szrj 		    ? (final_p
2248*38fd1498Szrj 		       ? "`%s' in final presence set is not unit"
2249*38fd1498Szrj 		       : "`%s' in presence set is not unit")
2250*38fd1498Szrj 		    : (final_p
2251*38fd1498Szrj 		       ? "`%s' in final absence set is not unit"
2252*38fd1498Szrj 		       : "`%s' in absence set is not unit")),
2253*38fd1498Szrj 		   patterns [i] [j]);
2254*38fd1498Szrj 	  else
2255*38fd1498Szrj 	    {
2256*38fd1498Szrj 	      new_el->unit_decls [new_el->units_num]
2257*38fd1498Szrj 		= DECL_UNIT (decl_in_table);
2258*38fd1498Szrj 	      new_el->units_num++;
2259*38fd1498Szrj 	    }
2260*38fd1498Szrj 	}
2261*38fd1498Szrj     }
2262*38fd1498Szrj   return el_list;
2263*38fd1498Szrj }
2264*38fd1498Szrj 
2265*38fd1498Szrj /* The function adds each element from PATTERN_LIST to presence (if
2266*38fd1498Szrj    PRESENCE_P) or absence list of the each element from DEST_LIST.
2267*38fd1498Szrj    Checking situations "unit requires own absence", and "unit excludes
2268*38fd1498Szrj    and requires presence of ...", "unit requires absence and presence
2269*38fd1498Szrj    of ...", "units in (final) presence set belong to different
2270*38fd1498Szrj    automata", and "units in (final) absence set belong to different
2271*38fd1498Szrj    automata".  Remember that we process absence sets only after all
2272*38fd1498Szrj    presence sets.  */
2273*38fd1498Szrj static void
add_presence_absence(unit_set_el_t dest_list,pattern_set_el_t pattern_list,pos_t req_pos ATTRIBUTE_UNUSED,int presence_p,int final_p)2274*38fd1498Szrj add_presence_absence (unit_set_el_t dest_list,
2275*38fd1498Szrj 		      pattern_set_el_t pattern_list,
2276*38fd1498Szrj 		      pos_t req_pos ATTRIBUTE_UNUSED,
2277*38fd1498Szrj 		      int presence_p, int final_p)
2278*38fd1498Szrj {
2279*38fd1498Szrj   unit_set_el_t dst;
2280*38fd1498Szrj   pattern_set_el_t pat;
2281*38fd1498Szrj   struct unit_decl *unit;
2282*38fd1498Szrj   unit_set_el_t curr_excl_el;
2283*38fd1498Szrj   pattern_set_el_t curr_pat_el;
2284*38fd1498Szrj   pattern_set_el_t prev_el;
2285*38fd1498Szrj   pattern_set_el_t copy;
2286*38fd1498Szrj   int i;
2287*38fd1498Szrj   int no_error_flag;
2288*38fd1498Szrj 
2289*38fd1498Szrj   for (dst = dest_list; dst != NULL; dst = dst->next_unit_set_el)
2290*38fd1498Szrj     for (pat = pattern_list; pat != NULL; pat = pat->next_pattern_set_el)
2291*38fd1498Szrj       {
2292*38fd1498Szrj 	for (i = 0; i < pat->units_num; i++)
2293*38fd1498Szrj 	  {
2294*38fd1498Szrj 	    unit = pat->unit_decls [i];
2295*38fd1498Szrj 	    if (dst->unit_decl == unit && pat->units_num == 1 && !presence_p)
2296*38fd1498Szrj 	      {
2297*38fd1498Szrj 		error ("unit `%s' requires own absence", unit->name);
2298*38fd1498Szrj 		continue;
2299*38fd1498Szrj 	      }
2300*38fd1498Szrj 	    if (dst->unit_decl->automaton_name != NULL
2301*38fd1498Szrj 		&& unit->automaton_name != NULL
2302*38fd1498Szrj 		&& strcmp (dst->unit_decl->automaton_name,
2303*38fd1498Szrj 			   unit->automaton_name) != 0)
2304*38fd1498Szrj 	      {
2305*38fd1498Szrj 		error ((presence_p
2306*38fd1498Szrj 			? (final_p
2307*38fd1498Szrj 			   ? "units `%s' and `%s' in final presence set belong to different automata"
2308*38fd1498Szrj 			   : "units `%s' and `%s' in presence set belong to different automata")
2309*38fd1498Szrj 			: (final_p
2310*38fd1498Szrj 			   ? "units `%s' and `%s' in final absence set belong to different automata"
2311*38fd1498Szrj 			   : "units `%s' and `%s' in absence set belong to different automata")),
2312*38fd1498Szrj 		       unit->name, dst->unit_decl->name);
2313*38fd1498Szrj 		continue;
2314*38fd1498Szrj 	      }
2315*38fd1498Szrj 	    no_error_flag = 1;
2316*38fd1498Szrj 	    if (presence_p)
2317*38fd1498Szrj 	      for (curr_excl_el = dst->unit_decl->excl_list;
2318*38fd1498Szrj 		   curr_excl_el != NULL;
2319*38fd1498Szrj 		   curr_excl_el = curr_excl_el->next_unit_set_el)
2320*38fd1498Szrj 		{
2321*38fd1498Szrj 		  if (unit == curr_excl_el->unit_decl && pat->units_num == 1)
2322*38fd1498Szrj 		    {
2323*38fd1498Szrj 		      if (!w_flag)
2324*38fd1498Szrj 			{
2325*38fd1498Szrj 			  error ("unit `%s' excludes and requires presence of `%s'",
2326*38fd1498Szrj 				 dst->unit_decl->name, unit->name);
2327*38fd1498Szrj 			  no_error_flag = 0;
2328*38fd1498Szrj 			}
2329*38fd1498Szrj 		      else
2330*38fd1498Szrj 			warning ("unit `%s' excludes and requires presence of `%s'",
2331*38fd1498Szrj 			   dst->unit_decl->name, unit->name);
2332*38fd1498Szrj 		    }
2333*38fd1498Szrj 		}
2334*38fd1498Szrj 	    else if (pat->units_num == 1)
2335*38fd1498Szrj 	      for (curr_pat_el = dst->unit_decl->presence_list;
2336*38fd1498Szrj 		   curr_pat_el != NULL;
2337*38fd1498Szrj 		   curr_pat_el = curr_pat_el->next_pattern_set_el)
2338*38fd1498Szrj 		if (curr_pat_el->units_num == 1
2339*38fd1498Szrj 		    && unit == curr_pat_el->unit_decls [0])
2340*38fd1498Szrj 		  {
2341*38fd1498Szrj 		    if (!w_flag)
2342*38fd1498Szrj 		      {
2343*38fd1498Szrj 			error ("unit `%s' requires absence and presence of `%s'",
2344*38fd1498Szrj 			       dst->unit_decl->name, unit->name);
2345*38fd1498Szrj 			no_error_flag = 0;
2346*38fd1498Szrj 		      }
2347*38fd1498Szrj 		    else
2348*38fd1498Szrj 		      warning ("unit `%s' requires absence and presence of `%s'",
2349*38fd1498Szrj 			       dst->unit_decl->name, unit->name);
2350*38fd1498Szrj 		  }
2351*38fd1498Szrj 	    if (no_error_flag)
2352*38fd1498Szrj 	      {
2353*38fd1498Szrj 		for (prev_el = (presence_p
2354*38fd1498Szrj 				? (final_p
2355*38fd1498Szrj 				   ? dst->unit_decl->final_presence_list
2356*38fd1498Szrj 				   : dst->unit_decl->presence_list)
2357*38fd1498Szrj 				: (final_p
2358*38fd1498Szrj 				   ? dst->unit_decl->final_absence_list
2359*38fd1498Szrj 				   : dst->unit_decl->absence_list));
2360*38fd1498Szrj 		     prev_el != NULL && prev_el->next_pattern_set_el != NULL;
2361*38fd1498Szrj 		     prev_el = prev_el->next_pattern_set_el)
2362*38fd1498Szrj 		  ;
2363*38fd1498Szrj 		copy = XCOPYNODE (struct pattern_set_el, pat);
2364*38fd1498Szrj 		copy->next_pattern_set_el = NULL;
2365*38fd1498Szrj 		if (prev_el == NULL)
2366*38fd1498Szrj 		  {
2367*38fd1498Szrj 		    if (presence_p)
2368*38fd1498Szrj 		      {
2369*38fd1498Szrj 			if (final_p)
2370*38fd1498Szrj 			  dst->unit_decl->final_presence_list = copy;
2371*38fd1498Szrj 			else
2372*38fd1498Szrj 			  dst->unit_decl->presence_list = copy;
2373*38fd1498Szrj 		      }
2374*38fd1498Szrj 		    else if (final_p)
2375*38fd1498Szrj 		      dst->unit_decl->final_absence_list = copy;
2376*38fd1498Szrj 		    else
2377*38fd1498Szrj 		      dst->unit_decl->absence_list = copy;
2378*38fd1498Szrj 		  }
2379*38fd1498Szrj 		else
2380*38fd1498Szrj 		  prev_el->next_pattern_set_el = copy;
2381*38fd1498Szrj 	      }
2382*38fd1498Szrj 	  }
2383*38fd1498Szrj       }
2384*38fd1498Szrj }
2385*38fd1498Szrj 
2386*38fd1498Szrj 
2387*38fd1498Szrj /* The function inserts BYPASS in the list of bypasses of the
2388*38fd1498Szrj    corresponding output insn.  The order of bypasses in the list is
2389*38fd1498Szrj    described in a comment for member `bypass_list' (see above).  If
2390*38fd1498Szrj    there is already the same bypass in the list the function reports
2391*38fd1498Szrj    this and does nothing.  */
2392*38fd1498Szrj static void
insert_bypass(struct bypass_decl * bypass)2393*38fd1498Szrj insert_bypass (struct bypass_decl *bypass)
2394*38fd1498Szrj {
2395*38fd1498Szrj   struct bypass_decl *curr, *last;
2396*38fd1498Szrj   struct insn_reserv_decl *out_insn_reserv = bypass->out_insn_reserv;
2397*38fd1498Szrj   struct insn_reserv_decl *in_insn_reserv = bypass->in_insn_reserv;
2398*38fd1498Szrj 
2399*38fd1498Szrj   for (curr = out_insn_reserv->bypass_list, last = NULL;
2400*38fd1498Szrj        curr != NULL;
2401*38fd1498Szrj        last = curr, curr = curr->next)
2402*38fd1498Szrj     if (curr->in_insn_reserv == in_insn_reserv)
2403*38fd1498Szrj       {
2404*38fd1498Szrj 	if ((bypass->bypass_guard_name != NULL
2405*38fd1498Szrj 	     && curr->bypass_guard_name != NULL
2406*38fd1498Szrj 	     && ! strcmp (bypass->bypass_guard_name, curr->bypass_guard_name))
2407*38fd1498Szrj 	    || bypass->bypass_guard_name == curr->bypass_guard_name)
2408*38fd1498Szrj 	  {
2409*38fd1498Szrj 	    if (bypass->bypass_guard_name == NULL)
2410*38fd1498Szrj 	      {
2411*38fd1498Szrj 		if (!w_flag)
2412*38fd1498Szrj 		  error ("the same bypass `%s - %s' is already defined",
2413*38fd1498Szrj 			 bypass->out_pattern, bypass->in_pattern);
2414*38fd1498Szrj 		else
2415*38fd1498Szrj 		  warning ("the same bypass `%s - %s' is already defined",
2416*38fd1498Szrj 			   bypass->out_pattern, bypass->in_pattern);
2417*38fd1498Szrj 	      }
2418*38fd1498Szrj 	    else if (!w_flag)
2419*38fd1498Szrj 	      error ("the same bypass `%s - %s' (guard %s) is already defined",
2420*38fd1498Szrj 		     bypass->out_pattern, bypass->in_pattern,
2421*38fd1498Szrj 		     bypass->bypass_guard_name);
2422*38fd1498Szrj 	    else
2423*38fd1498Szrj 	      warning
2424*38fd1498Szrj 		("the same bypass `%s - %s' (guard %s) is already defined",
2425*38fd1498Szrj 		 bypass->out_pattern, bypass->in_pattern,
2426*38fd1498Szrj 		 bypass->bypass_guard_name);
2427*38fd1498Szrj 	    return;
2428*38fd1498Szrj 	  }
2429*38fd1498Szrj 	if (curr->bypass_guard_name == NULL)
2430*38fd1498Szrj 	  break;
2431*38fd1498Szrj 	if (curr->next == NULL || curr->next->in_insn_reserv != in_insn_reserv)
2432*38fd1498Szrj 	  {
2433*38fd1498Szrj 	    last = curr;
2434*38fd1498Szrj 	    break;
2435*38fd1498Szrj 	  }
2436*38fd1498Szrj 
2437*38fd1498Szrj       }
2438*38fd1498Szrj   if (last == NULL)
2439*38fd1498Szrj     {
2440*38fd1498Szrj       bypass->next = out_insn_reserv->bypass_list;
2441*38fd1498Szrj       out_insn_reserv->bypass_list = bypass;
2442*38fd1498Szrj     }
2443*38fd1498Szrj   else
2444*38fd1498Szrj     {
2445*38fd1498Szrj       bypass->next = last->next;
2446*38fd1498Szrj       last->next = bypass;
2447*38fd1498Szrj     }
2448*38fd1498Szrj }
2449*38fd1498Szrj 
2450*38fd1498Szrj /* BYPASS is a define_bypass decl that includes glob pattern PATTERN.
2451*38fd1498Szrj    Call FN (BYPASS, INSN, DATA) for each matching instruction INSN.  */
2452*38fd1498Szrj 
2453*38fd1498Szrj static void
for_each_matching_insn(decl_t bypass,const char * pattern,void (* fn)(decl_t,decl_t,void *),void * data)2454*38fd1498Szrj for_each_matching_insn (decl_t bypass, const char *pattern,
2455*38fd1498Szrj 			void (*fn) (decl_t, decl_t, void *), void *data)
2456*38fd1498Szrj {
2457*38fd1498Szrj   decl_t insn_reserv;
2458*38fd1498Szrj   bool matched_p;
2459*38fd1498Szrj   int i;
2460*38fd1498Szrj 
2461*38fd1498Szrj   matched_p = false;
2462*38fd1498Szrj   if (strpbrk (pattern, "*?["))
2463*38fd1498Szrj     for (i = 0; i < description->decls_num; i++)
2464*38fd1498Szrj       {
2465*38fd1498Szrj 	insn_reserv = description->decls[i];
2466*38fd1498Szrj 	if (insn_reserv->mode == dm_insn_reserv
2467*38fd1498Szrj 	    && fnmatch (pattern, DECL_INSN_RESERV (insn_reserv)->name, 0) == 0)
2468*38fd1498Szrj 	  {
2469*38fd1498Szrj 	    fn (bypass, insn_reserv, data);
2470*38fd1498Szrj 	    matched_p = true;
2471*38fd1498Szrj 	  }
2472*38fd1498Szrj       }
2473*38fd1498Szrj   else
2474*38fd1498Szrj     {
2475*38fd1498Szrj       insn_reserv = find_insn_decl (pattern);
2476*38fd1498Szrj       if (insn_reserv)
2477*38fd1498Szrj 	{
2478*38fd1498Szrj 	  fn (bypass, insn_reserv, data);
2479*38fd1498Szrj 	  matched_p = true;
2480*38fd1498Szrj 	}
2481*38fd1498Szrj     }
2482*38fd1498Szrj   if (!matched_p)
2483*38fd1498Szrj     error ("there is no insn reservation that matches `%s'", pattern);
2484*38fd1498Szrj }
2485*38fd1498Szrj 
2486*38fd1498Szrj /* A subroutine of process_bypass that is called for each pair
2487*38fd1498Szrj    of matching instructions.  OUT_INSN_RESERV is the output
2488*38fd1498Szrj    instruction and DATA is the input instruction.  */
2489*38fd1498Szrj 
2490*38fd1498Szrj static void
process_bypass_2(decl_t model,decl_t out_insn_reserv,void * data)2491*38fd1498Szrj process_bypass_2 (decl_t model, decl_t out_insn_reserv, void *data)
2492*38fd1498Szrj {
2493*38fd1498Szrj   struct bypass_decl *bypass;
2494*38fd1498Szrj   decl_t in_insn_reserv;
2495*38fd1498Szrj 
2496*38fd1498Szrj   in_insn_reserv = (decl_t) data;
2497*38fd1498Szrj   if (strcmp (DECL_INSN_RESERV (in_insn_reserv)->name,
2498*38fd1498Szrj 	      DECL_BYPASS (model)->in_pattern) == 0
2499*38fd1498Szrj       && strcmp (DECL_INSN_RESERV (out_insn_reserv)->name,
2500*38fd1498Szrj 		 DECL_BYPASS (model)->out_pattern) == 0)
2501*38fd1498Szrj     bypass = DECL_BYPASS (model);
2502*38fd1498Szrj   else
2503*38fd1498Szrj     {
2504*38fd1498Szrj       bypass = XCNEW (struct bypass_decl);
2505*38fd1498Szrj       bypass->latency = DECL_BYPASS (model)->latency;
2506*38fd1498Szrj       bypass->out_pattern = DECL_INSN_RESERV (out_insn_reserv)->name;
2507*38fd1498Szrj       bypass->in_pattern = DECL_INSN_RESERV (in_insn_reserv)->name;
2508*38fd1498Szrj       bypass->bypass_guard_name = DECL_BYPASS (model)->bypass_guard_name;
2509*38fd1498Szrj     }
2510*38fd1498Szrj   bypass->out_insn_reserv = DECL_INSN_RESERV (out_insn_reserv);
2511*38fd1498Szrj   bypass->in_insn_reserv = DECL_INSN_RESERV (in_insn_reserv);
2512*38fd1498Szrj   insert_bypass (bypass);
2513*38fd1498Szrj }
2514*38fd1498Szrj 
2515*38fd1498Szrj /* A subroutine of process_bypass that is called for each input
2516*38fd1498Szrj    instruction IN_INSN_RESERV.  */
2517*38fd1498Szrj 
2518*38fd1498Szrj static void
process_bypass_1(decl_t bypass,decl_t in_insn_reserv,void * data ATTRIBUTE_UNUSED)2519*38fd1498Szrj process_bypass_1 (decl_t bypass, decl_t in_insn_reserv,
2520*38fd1498Szrj 		  void *data ATTRIBUTE_UNUSED)
2521*38fd1498Szrj {
2522*38fd1498Szrj   for_each_matching_insn (bypass, DECL_BYPASS (bypass)->out_pattern,
2523*38fd1498Szrj 			  process_bypass_2, in_insn_reserv);
2524*38fd1498Szrj }
2525*38fd1498Szrj 
2526*38fd1498Szrj /* Process define_bypass decl BYPASS, inserting a bypass for each specific
2527*38fd1498Szrj    pair of insn reservations.  */
2528*38fd1498Szrj 
2529*38fd1498Szrj static void
process_bypass(decl_t bypass)2530*38fd1498Szrj process_bypass (decl_t bypass)
2531*38fd1498Szrj {
2532*38fd1498Szrj   for_each_matching_insn (bypass, DECL_BYPASS (bypass)->in_pattern,
2533*38fd1498Szrj 			  process_bypass_1, NULL);
2534*38fd1498Szrj }
2535*38fd1498Szrj 
2536*38fd1498Szrj /* The function processes pipeline description declarations, checks
2537*38fd1498Szrj    their correctness, and forms exclusion/presence/absence sets.  */
2538*38fd1498Szrj static void
process_decls(void)2539*38fd1498Szrj process_decls (void)
2540*38fd1498Szrj {
2541*38fd1498Szrj   decl_t decl;
2542*38fd1498Szrj   decl_t automaton_decl;
2543*38fd1498Szrj   decl_t decl_in_table;
2544*38fd1498Szrj   int automaton_presence;
2545*38fd1498Szrj   int i;
2546*38fd1498Szrj 
2547*38fd1498Szrj   /* Checking repeated automata declarations.  */
2548*38fd1498Szrj   automaton_presence = 0;
2549*38fd1498Szrj   for (i = 0; i < description->decls_num; i++)
2550*38fd1498Szrj     {
2551*38fd1498Szrj       decl = description->decls [i];
2552*38fd1498Szrj       if (decl->mode == dm_automaton)
2553*38fd1498Szrj 	{
2554*38fd1498Szrj 	  automaton_presence = 1;
2555*38fd1498Szrj 	  decl_in_table = insert_automaton_decl (decl);
2556*38fd1498Szrj 	  if (decl_in_table != decl)
2557*38fd1498Szrj 	    {
2558*38fd1498Szrj 	      if (!w_flag)
2559*38fd1498Szrj 		error ("repeated declaration of automaton `%s'",
2560*38fd1498Szrj 		       DECL_AUTOMATON (decl)->name);
2561*38fd1498Szrj 	      else
2562*38fd1498Szrj 		warning ("repeated declaration of automaton `%s'",
2563*38fd1498Szrj 			 DECL_AUTOMATON (decl)->name);
2564*38fd1498Szrj 	    }
2565*38fd1498Szrj 	}
2566*38fd1498Szrj     }
2567*38fd1498Szrj   /* Checking undeclared automata, repeated declarations (except for
2568*38fd1498Szrj      automata) and correctness of their attributes (insn latency times
2569*38fd1498Szrj      etc.).  */
2570*38fd1498Szrj   for (i = 0; i < description->decls_num; i++)
2571*38fd1498Szrj     {
2572*38fd1498Szrj       decl = description->decls [i];
2573*38fd1498Szrj       if (decl->mode == dm_insn_reserv)
2574*38fd1498Szrj 	{
2575*38fd1498Szrj 	  if (DECL_INSN_RESERV (decl)->default_latency < 0)
2576*38fd1498Szrj 	    error ("define_insn_reservation `%s' has negative latency time",
2577*38fd1498Szrj 		   DECL_INSN_RESERV (decl)->name);
2578*38fd1498Szrj 	  DECL_INSN_RESERV (decl)->insn_num = description->insns_num;
2579*38fd1498Szrj 	  description->insns_num++;
2580*38fd1498Szrj 	  decl_in_table = insert_insn_decl (decl);
2581*38fd1498Szrj 	  if (decl_in_table != decl)
2582*38fd1498Szrj 	    error ("`%s' is already used as insn reservation name",
2583*38fd1498Szrj 		   DECL_INSN_RESERV (decl)->name);
2584*38fd1498Szrj 	}
2585*38fd1498Szrj       else if (decl->mode == dm_bypass)
2586*38fd1498Szrj 	{
2587*38fd1498Szrj 	  if (DECL_BYPASS (decl)->latency < 0)
2588*38fd1498Szrj 	    error ("define_bypass `%s - %s' has negative latency time",
2589*38fd1498Szrj 		   DECL_BYPASS (decl)->out_pattern,
2590*38fd1498Szrj 		   DECL_BYPASS (decl)->in_pattern);
2591*38fd1498Szrj 	}
2592*38fd1498Szrj       else if (decl->mode == dm_unit || decl->mode == dm_reserv)
2593*38fd1498Szrj 	{
2594*38fd1498Szrj 	  if (decl->mode == dm_unit)
2595*38fd1498Szrj 	    {
2596*38fd1498Szrj 	      DECL_UNIT (decl)->automaton_decl = NULL;
2597*38fd1498Szrj 	      if (DECL_UNIT (decl)->automaton_name != NULL)
2598*38fd1498Szrj 		{
2599*38fd1498Szrj 		  automaton_decl
2600*38fd1498Szrj                     = find_automaton_decl (DECL_UNIT (decl)->automaton_name);
2601*38fd1498Szrj 		  if (automaton_decl == NULL)
2602*38fd1498Szrj 		    error ("automaton `%s' is not declared",
2603*38fd1498Szrj 			   DECL_UNIT (decl)->automaton_name);
2604*38fd1498Szrj 		  else
2605*38fd1498Szrj 		    {
2606*38fd1498Szrj 		      DECL_AUTOMATON (automaton_decl)->automaton_is_used = 1;
2607*38fd1498Szrj 		      DECL_UNIT (decl)->automaton_decl
2608*38fd1498Szrj 			= DECL_AUTOMATON (automaton_decl);
2609*38fd1498Szrj 		    }
2610*38fd1498Szrj 		}
2611*38fd1498Szrj 	      else if (automaton_presence)
2612*38fd1498Szrj 		error ("define_unit `%s' without automaton when one defined",
2613*38fd1498Szrj 		       DECL_UNIT (decl)->name);
2614*38fd1498Szrj 	      DECL_UNIT (decl)->unit_num = description->units_num;
2615*38fd1498Szrj 	      description->units_num++;
2616*38fd1498Szrj 	      if (strcmp (DECL_UNIT (decl)->name, NOTHING_NAME) == 0)
2617*38fd1498Szrj 		{
2618*38fd1498Szrj 		  error ("`%s' is declared as cpu unit", NOTHING_NAME);
2619*38fd1498Szrj 		  continue;
2620*38fd1498Szrj 		}
2621*38fd1498Szrj 	      decl_in_table = find_decl (DECL_UNIT (decl)->name);
2622*38fd1498Szrj 	    }
2623*38fd1498Szrj 	  else
2624*38fd1498Szrj 	    {
2625*38fd1498Szrj 	      if (strcmp (DECL_RESERV (decl)->name, NOTHING_NAME) == 0)
2626*38fd1498Szrj 		{
2627*38fd1498Szrj 		  error ("`%s' is declared as cpu reservation", NOTHING_NAME);
2628*38fd1498Szrj 		  continue;
2629*38fd1498Szrj 		}
2630*38fd1498Szrj 	      decl_in_table = find_decl (DECL_RESERV (decl)->name);
2631*38fd1498Szrj 	    }
2632*38fd1498Szrj 	  if (decl_in_table == NULL)
2633*38fd1498Szrj 	    decl_in_table = insert_decl (decl);
2634*38fd1498Szrj 	  else
2635*38fd1498Szrj 	    {
2636*38fd1498Szrj 	      if (decl->mode == dm_unit)
2637*38fd1498Szrj 		error ("repeated declaration of unit `%s'",
2638*38fd1498Szrj 		       DECL_UNIT (decl)->name);
2639*38fd1498Szrj 	      else
2640*38fd1498Szrj 		error ("repeated declaration of reservation `%s'",
2641*38fd1498Szrj 		       DECL_RESERV (decl)->name);
2642*38fd1498Szrj 	    }
2643*38fd1498Szrj 	}
2644*38fd1498Szrj     }
2645*38fd1498Szrj   /* Check bypasses and form list of bypasses for each (output)
2646*38fd1498Szrj      insn.  */
2647*38fd1498Szrj   for (i = 0; i < description->decls_num; i++)
2648*38fd1498Szrj     {
2649*38fd1498Szrj       decl = description->decls [i];
2650*38fd1498Szrj       if (decl->mode == dm_bypass)
2651*38fd1498Szrj 	process_bypass (decl);
2652*38fd1498Szrj     }
2653*38fd1498Szrj 
2654*38fd1498Szrj   /* Check exclusion set declarations and form exclusion sets.  */
2655*38fd1498Szrj   for (i = 0; i < description->decls_num; i++)
2656*38fd1498Szrj     {
2657*38fd1498Szrj       decl = description->decls [i];
2658*38fd1498Szrj       if (decl->mode == dm_excl)
2659*38fd1498Szrj 	{
2660*38fd1498Szrj 	  unit_set_el_t unit_set_el_list;
2661*38fd1498Szrj 	  unit_set_el_t unit_set_el_list_2;
2662*38fd1498Szrj 
2663*38fd1498Szrj 	  unit_set_el_list
2664*38fd1498Szrj             = process_excls (DECL_EXCL (decl)->names,
2665*38fd1498Szrj 			     DECL_EXCL (decl)->first_list_length, decl->pos);
2666*38fd1498Szrj 	  unit_set_el_list_2
2667*38fd1498Szrj 	    = process_excls (&DECL_EXCL (decl)->names
2668*38fd1498Szrj 			     [DECL_EXCL (decl)->first_list_length],
2669*38fd1498Szrj                              DECL_EXCL (decl)->all_names_num
2670*38fd1498Szrj                              - DECL_EXCL (decl)->first_list_length,
2671*38fd1498Szrj                              decl->pos);
2672*38fd1498Szrj 	  add_excls (unit_set_el_list, unit_set_el_list_2, decl->pos);
2673*38fd1498Szrj 	  add_excls (unit_set_el_list_2, unit_set_el_list, decl->pos);
2674*38fd1498Szrj 	}
2675*38fd1498Szrj     }
2676*38fd1498Szrj 
2677*38fd1498Szrj   /* Check presence set declarations and form presence sets.  */
2678*38fd1498Szrj   for (i = 0; i < description->decls_num; i++)
2679*38fd1498Szrj     {
2680*38fd1498Szrj       decl = description->decls [i];
2681*38fd1498Szrj       if (decl->mode == dm_presence)
2682*38fd1498Szrj 	{
2683*38fd1498Szrj 	  unit_set_el_t unit_set_el_list;
2684*38fd1498Szrj 	  pattern_set_el_t pattern_set_el_list;
2685*38fd1498Szrj 
2686*38fd1498Szrj 	  unit_set_el_list
2687*38fd1498Szrj             = process_presence_absence_names
2688*38fd1498Szrj 	      (DECL_PRESENCE (decl)->names, DECL_PRESENCE (decl)->names_num,
2689*38fd1498Szrj 	       decl->pos, TRUE, DECL_PRESENCE (decl)->final_p);
2690*38fd1498Szrj 	  pattern_set_el_list
2691*38fd1498Szrj 	    = process_presence_absence_patterns
2692*38fd1498Szrj 	      (DECL_PRESENCE (decl)->patterns,
2693*38fd1498Szrj 	       DECL_PRESENCE (decl)->patterns_num,
2694*38fd1498Szrj 	       decl->pos, TRUE, DECL_PRESENCE (decl)->final_p);
2695*38fd1498Szrj 	  add_presence_absence (unit_set_el_list, pattern_set_el_list,
2696*38fd1498Szrj 				decl->pos, TRUE,
2697*38fd1498Szrj 				DECL_PRESENCE (decl)->final_p);
2698*38fd1498Szrj 	}
2699*38fd1498Szrj     }
2700*38fd1498Szrj 
2701*38fd1498Szrj   /* Check absence set declarations and form absence sets.  */
2702*38fd1498Szrj   for (i = 0; i < description->decls_num; i++)
2703*38fd1498Szrj     {
2704*38fd1498Szrj       decl = description->decls [i];
2705*38fd1498Szrj       if (decl->mode == dm_absence)
2706*38fd1498Szrj 	{
2707*38fd1498Szrj 	  unit_set_el_t unit_set_el_list;
2708*38fd1498Szrj 	  pattern_set_el_t pattern_set_el_list;
2709*38fd1498Szrj 
2710*38fd1498Szrj 	  unit_set_el_list
2711*38fd1498Szrj             = process_presence_absence_names
2712*38fd1498Szrj 	      (DECL_ABSENCE (decl)->names, DECL_ABSENCE (decl)->names_num,
2713*38fd1498Szrj 	       decl->pos, FALSE, DECL_ABSENCE (decl)->final_p);
2714*38fd1498Szrj 	  pattern_set_el_list
2715*38fd1498Szrj 	    = process_presence_absence_patterns
2716*38fd1498Szrj 	      (DECL_ABSENCE (decl)->patterns,
2717*38fd1498Szrj 	       DECL_ABSENCE (decl)->patterns_num,
2718*38fd1498Szrj 	       decl->pos, FALSE, DECL_ABSENCE (decl)->final_p);
2719*38fd1498Szrj 	  add_presence_absence (unit_set_el_list, pattern_set_el_list,
2720*38fd1498Szrj 				decl->pos, FALSE,
2721*38fd1498Szrj 				DECL_ABSENCE (decl)->final_p);
2722*38fd1498Szrj 	}
2723*38fd1498Szrj     }
2724*38fd1498Szrj }
2725*38fd1498Szrj 
2726*38fd1498Szrj /* The following function checks that declared automaton is used.  If
2727*38fd1498Szrj    the automaton is not used, the function fixes error/warning.  The
2728*38fd1498Szrj    following function must be called only after `process_decls'.  */
2729*38fd1498Szrj static void
check_automaton_usage(void)2730*38fd1498Szrj check_automaton_usage (void)
2731*38fd1498Szrj {
2732*38fd1498Szrj   decl_t decl;
2733*38fd1498Szrj   int i;
2734*38fd1498Szrj 
2735*38fd1498Szrj   for (i = 0; i < description->decls_num; i++)
2736*38fd1498Szrj     {
2737*38fd1498Szrj       decl = description->decls [i];
2738*38fd1498Szrj       if (decl->mode == dm_automaton
2739*38fd1498Szrj 	  && !DECL_AUTOMATON (decl)->automaton_is_used)
2740*38fd1498Szrj 	{
2741*38fd1498Szrj 	  if (!w_flag)
2742*38fd1498Szrj 	    error ("automaton `%s' is not used", DECL_AUTOMATON (decl)->name);
2743*38fd1498Szrj 	  else
2744*38fd1498Szrj 	    warning ("automaton `%s' is not used",
2745*38fd1498Szrj 		     DECL_AUTOMATON (decl)->name);
2746*38fd1498Szrj 	}
2747*38fd1498Szrj     }
2748*38fd1498Szrj }
2749*38fd1498Szrj 
2750*38fd1498Szrj /* The following recursive function processes all regexp in order to
2751*38fd1498Szrj    fix usage of units or reservations and to fix errors of undeclared
2752*38fd1498Szrj    name.  The function may change unit_regexp onto reserv_regexp.
2753*38fd1498Szrj    Remember that reserv_regexp does not exist before the function
2754*38fd1498Szrj    call.  */
2755*38fd1498Szrj static regexp_t
process_regexp(regexp_t regexp)2756*38fd1498Szrj process_regexp (regexp_t regexp)
2757*38fd1498Szrj {
2758*38fd1498Szrj   decl_t decl_in_table;
2759*38fd1498Szrj   regexp_t new_regexp;
2760*38fd1498Szrj   int i;
2761*38fd1498Szrj 
2762*38fd1498Szrj   switch (regexp->mode)
2763*38fd1498Szrj     {
2764*38fd1498Szrj     case rm_unit:
2765*38fd1498Szrj       decl_in_table = find_decl (REGEXP_UNIT (regexp)->name);
2766*38fd1498Szrj       if (decl_in_table == NULL)
2767*38fd1498Szrj         error ("undeclared unit or reservation `%s'",
2768*38fd1498Szrj 	       REGEXP_UNIT (regexp)->name);
2769*38fd1498Szrj       else
2770*38fd1498Szrj 	switch (decl_in_table->mode)
2771*38fd1498Szrj 	  {
2772*38fd1498Szrj 	  case dm_unit:
2773*38fd1498Szrj 	    DECL_UNIT (decl_in_table)->unit_is_used = 1;
2774*38fd1498Szrj 	    REGEXP_UNIT (regexp)->unit_decl = DECL_UNIT (decl_in_table);
2775*38fd1498Szrj 	    break;
2776*38fd1498Szrj 
2777*38fd1498Szrj 	  case dm_reserv:
2778*38fd1498Szrj 	    DECL_RESERV (decl_in_table)->reserv_is_used = 1;
2779*38fd1498Szrj 	    new_regexp = XCREATENODE (struct regexp);
2780*38fd1498Szrj 	    new_regexp->mode = rm_reserv;
2781*38fd1498Szrj 	    new_regexp->pos = regexp->pos;
2782*38fd1498Szrj 	    REGEXP_RESERV (new_regexp)->name = REGEXP_UNIT (regexp)->name;
2783*38fd1498Szrj 	    REGEXP_RESERV (new_regexp)->reserv_decl
2784*38fd1498Szrj 	      = DECL_RESERV (decl_in_table);
2785*38fd1498Szrj 	    regexp = new_regexp;
2786*38fd1498Szrj 	    break;
2787*38fd1498Szrj 
2788*38fd1498Szrj 	  default:
2789*38fd1498Szrj 	    gcc_unreachable ();
2790*38fd1498Szrj 	}
2791*38fd1498Szrj       break;
2792*38fd1498Szrj     case rm_sequence:
2793*38fd1498Szrj       for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
2794*38fd1498Szrj 	REGEXP_SEQUENCE (regexp)->regexps [i]
2795*38fd1498Szrj 	  = process_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
2796*38fd1498Szrj       break;
2797*38fd1498Szrj     case rm_allof:
2798*38fd1498Szrj       for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
2799*38fd1498Szrj 	REGEXP_ALLOF (regexp)->regexps [i]
2800*38fd1498Szrj 	  = process_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
2801*38fd1498Szrj       break;
2802*38fd1498Szrj     case rm_oneof:
2803*38fd1498Szrj       for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
2804*38fd1498Szrj 	REGEXP_ONEOF (regexp)->regexps [i]
2805*38fd1498Szrj 	  = process_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
2806*38fd1498Szrj       break;
2807*38fd1498Szrj     case rm_repeat:
2808*38fd1498Szrj       REGEXP_REPEAT (regexp)->regexp
2809*38fd1498Szrj 	= process_regexp (REGEXP_REPEAT (regexp)->regexp);
2810*38fd1498Szrj       break;
2811*38fd1498Szrj     case rm_nothing:
2812*38fd1498Szrj       break;
2813*38fd1498Szrj     default:
2814*38fd1498Szrj       gcc_unreachable ();
2815*38fd1498Szrj     }
2816*38fd1498Szrj   return regexp;
2817*38fd1498Szrj }
2818*38fd1498Szrj 
2819*38fd1498Szrj /* The following function processes regexp of define_reservation and
2820*38fd1498Szrj    define_insn_reservation with the aid of function
2821*38fd1498Szrj    `process_regexp'.  */
2822*38fd1498Szrj static void
process_regexp_decls(void)2823*38fd1498Szrj process_regexp_decls (void)
2824*38fd1498Szrj {
2825*38fd1498Szrj   decl_t decl;
2826*38fd1498Szrj   int i;
2827*38fd1498Szrj 
2828*38fd1498Szrj   for (i = 0; i < description->decls_num; i++)
2829*38fd1498Szrj     {
2830*38fd1498Szrj       decl = description->decls [i];
2831*38fd1498Szrj       if (decl->mode == dm_reserv)
2832*38fd1498Szrj 	DECL_RESERV (decl)->regexp
2833*38fd1498Szrj 	  = process_regexp (DECL_RESERV (decl)->regexp);
2834*38fd1498Szrj       else if (decl->mode == dm_insn_reserv)
2835*38fd1498Szrj 	DECL_INSN_RESERV (decl)->regexp
2836*38fd1498Szrj 	  = process_regexp (DECL_INSN_RESERV (decl)->regexp);
2837*38fd1498Szrj     }
2838*38fd1498Szrj }
2839*38fd1498Szrj 
2840*38fd1498Szrj /* The following function checks that declared unit is used.  If the
2841*38fd1498Szrj    unit is not used, the function fixes errors/warnings.  The
2842*38fd1498Szrj    following function must be called only after `process_decls',
2843*38fd1498Szrj    `process_regexp_decls'.  */
2844*38fd1498Szrj static void
check_usage(void)2845*38fd1498Szrj check_usage (void)
2846*38fd1498Szrj {
2847*38fd1498Szrj   decl_t decl;
2848*38fd1498Szrj   int i;
2849*38fd1498Szrj 
2850*38fd1498Szrj   for (i = 0; i < description->decls_num; i++)
2851*38fd1498Szrj     {
2852*38fd1498Szrj       decl = description->decls [i];
2853*38fd1498Szrj       if (decl->mode == dm_unit && !DECL_UNIT (decl)->unit_is_used)
2854*38fd1498Szrj 	{
2855*38fd1498Szrj 	  if (!w_flag)
2856*38fd1498Szrj 	    error ("unit `%s' is not used", DECL_UNIT (decl)->name);
2857*38fd1498Szrj 	  else
2858*38fd1498Szrj 	    warning ("unit `%s' is not used", DECL_UNIT (decl)->name);
2859*38fd1498Szrj 	}
2860*38fd1498Szrj       else if (decl->mode == dm_reserv && !DECL_RESERV (decl)->reserv_is_used)
2861*38fd1498Szrj 	{
2862*38fd1498Szrj 	  if (!w_flag)
2863*38fd1498Szrj 	    error ("reservation `%s' is not used", DECL_RESERV (decl)->name);
2864*38fd1498Szrj 	  else
2865*38fd1498Szrj 	    warning ("reservation `%s' is not used", DECL_RESERV (decl)->name);
2866*38fd1498Szrj 	}
2867*38fd1498Szrj     }
2868*38fd1498Szrj }
2869*38fd1498Szrj 
2870*38fd1498Szrj /* The following variable value is number of reservation being
2871*38fd1498Szrj    processed on loop recognition.  */
2872*38fd1498Szrj static int curr_loop_pass_num;
2873*38fd1498Szrj 
2874*38fd1498Szrj /* The following recursive function returns nonzero value if REGEXP
2875*38fd1498Szrj    contains given decl or reservations in given regexp refers for
2876*38fd1498Szrj    given decl.  */
2877*38fd1498Szrj static int
loop_in_regexp(regexp_t regexp,decl_t start_decl)2878*38fd1498Szrj loop_in_regexp (regexp_t regexp, decl_t start_decl)
2879*38fd1498Szrj {
2880*38fd1498Szrj   int i;
2881*38fd1498Szrj 
2882*38fd1498Szrj   if (regexp == NULL)
2883*38fd1498Szrj     return 0;
2884*38fd1498Szrj   switch (regexp->mode)
2885*38fd1498Szrj     {
2886*38fd1498Szrj       case rm_unit:
2887*38fd1498Szrj 	return 0;
2888*38fd1498Szrj 
2889*38fd1498Szrj     case rm_reserv:
2890*38fd1498Szrj       if (start_decl->mode == dm_reserv
2891*38fd1498Szrj           && REGEXP_RESERV (regexp)->reserv_decl == DECL_RESERV (start_decl))
2892*38fd1498Szrj         return 1;
2893*38fd1498Szrj       else if (REGEXP_RESERV (regexp)->reserv_decl->loop_pass_num
2894*38fd1498Szrj 	       == curr_loop_pass_num)
2895*38fd1498Szrj         /* declaration has been processed.  */
2896*38fd1498Szrj         return 0;
2897*38fd1498Szrj       else
2898*38fd1498Szrj         {
2899*38fd1498Szrj 	  REGEXP_RESERV (regexp)->reserv_decl->loop_pass_num
2900*38fd1498Szrj             = curr_loop_pass_num;
2901*38fd1498Szrj           return loop_in_regexp (REGEXP_RESERV (regexp)->reserv_decl->regexp,
2902*38fd1498Szrj                                  start_decl);
2903*38fd1498Szrj         }
2904*38fd1498Szrj 
2905*38fd1498Szrj     case rm_sequence:
2906*38fd1498Szrj       for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
2907*38fd1498Szrj 	if (loop_in_regexp (REGEXP_SEQUENCE (regexp)->regexps [i], start_decl))
2908*38fd1498Szrj 	  return 1;
2909*38fd1498Szrj       return 0;
2910*38fd1498Szrj 
2911*38fd1498Szrj     case rm_allof:
2912*38fd1498Szrj       for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
2913*38fd1498Szrj 	if (loop_in_regexp (REGEXP_ALLOF (regexp)->regexps [i], start_decl))
2914*38fd1498Szrj 	  return 1;
2915*38fd1498Szrj       return 0;
2916*38fd1498Szrj 
2917*38fd1498Szrj     case rm_oneof:
2918*38fd1498Szrj       for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
2919*38fd1498Szrj 	if (loop_in_regexp (REGEXP_ONEOF (regexp)->regexps [i], start_decl))
2920*38fd1498Szrj 	  return 1;
2921*38fd1498Szrj       return 0;
2922*38fd1498Szrj 
2923*38fd1498Szrj     case rm_repeat:
2924*38fd1498Szrj       return loop_in_regexp (REGEXP_REPEAT (regexp)->regexp, start_decl);
2925*38fd1498Szrj 
2926*38fd1498Szrj     case rm_nothing:
2927*38fd1498Szrj       return 0;
2928*38fd1498Szrj 
2929*38fd1498Szrj     default:
2930*38fd1498Szrj       gcc_unreachable ();
2931*38fd1498Szrj     }
2932*38fd1498Szrj }
2933*38fd1498Szrj 
2934*38fd1498Szrj /* The following function fixes errors "cycle in definition ...".  The
2935*38fd1498Szrj    function uses function `loop_in_regexp' for that.  */
2936*38fd1498Szrj static void
check_loops_in_regexps(void)2937*38fd1498Szrj check_loops_in_regexps (void)
2938*38fd1498Szrj {
2939*38fd1498Szrj   decl_t decl;
2940*38fd1498Szrj   int i;
2941*38fd1498Szrj 
2942*38fd1498Szrj   for (i = 0; i < description->decls_num; i++)
2943*38fd1498Szrj     {
2944*38fd1498Szrj       decl = description->decls [i];
2945*38fd1498Szrj       if (decl->mode == dm_reserv)
2946*38fd1498Szrj 	DECL_RESERV (decl)->loop_pass_num = 0;
2947*38fd1498Szrj     }
2948*38fd1498Szrj   for (i = 0; i < description->decls_num; i++)
2949*38fd1498Szrj     {
2950*38fd1498Szrj       decl = description->decls [i];
2951*38fd1498Szrj       curr_loop_pass_num = i;
2952*38fd1498Szrj 
2953*38fd1498Szrj       if (decl->mode == dm_reserv)
2954*38fd1498Szrj 	  {
2955*38fd1498Szrj 	    DECL_RESERV (decl)->loop_pass_num = curr_loop_pass_num;
2956*38fd1498Szrj 	    if (loop_in_regexp (DECL_RESERV (decl)->regexp, decl))
2957*38fd1498Szrj 	      {
2958*38fd1498Szrj 		gcc_assert (DECL_RESERV (decl)->regexp);
2959*38fd1498Szrj 		error ("cycle in definition of reservation `%s'",
2960*38fd1498Szrj 		       DECL_RESERV (decl)->name);
2961*38fd1498Szrj 	      }
2962*38fd1498Szrj 	  }
2963*38fd1498Szrj     }
2964*38fd1498Szrj }
2965*38fd1498Szrj 
2966*38fd1498Szrj /* The function recursively processes IR of reservation and defines
2967*38fd1498Szrj    max and min cycle for reservation of unit.  */
2968*38fd1498Szrj static void
process_regexp_cycles(regexp_t regexp,int max_start_cycle,int min_start_cycle,int * max_finish_cycle,int * min_finish_cycle)2969*38fd1498Szrj process_regexp_cycles (regexp_t regexp, int max_start_cycle,
2970*38fd1498Szrj 		       int min_start_cycle, int *max_finish_cycle,
2971*38fd1498Szrj 		       int *min_finish_cycle)
2972*38fd1498Szrj {
2973*38fd1498Szrj   int i;
2974*38fd1498Szrj 
2975*38fd1498Szrj   switch (regexp->mode)
2976*38fd1498Szrj     {
2977*38fd1498Szrj     case rm_unit:
2978*38fd1498Szrj       if (REGEXP_UNIT (regexp)->unit_decl->max_occ_cycle_num < max_start_cycle)
2979*38fd1498Szrj 	REGEXP_UNIT (regexp)->unit_decl->max_occ_cycle_num = max_start_cycle;
2980*38fd1498Szrj       if (REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num > min_start_cycle
2981*38fd1498Szrj 	  || REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num == -1)
2982*38fd1498Szrj 	REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num = min_start_cycle;
2983*38fd1498Szrj       *max_finish_cycle = max_start_cycle;
2984*38fd1498Szrj       *min_finish_cycle = min_start_cycle;
2985*38fd1498Szrj       break;
2986*38fd1498Szrj 
2987*38fd1498Szrj     case rm_reserv:
2988*38fd1498Szrj       process_regexp_cycles (REGEXP_RESERV (regexp)->reserv_decl->regexp,
2989*38fd1498Szrj 			     max_start_cycle, min_start_cycle,
2990*38fd1498Szrj 			     max_finish_cycle, min_finish_cycle);
2991*38fd1498Szrj       break;
2992*38fd1498Szrj 
2993*38fd1498Szrj     case rm_repeat:
2994*38fd1498Szrj       for (i = 0; i < REGEXP_REPEAT (regexp)->repeat_num; i++)
2995*38fd1498Szrj 	{
2996*38fd1498Szrj 	  process_regexp_cycles (REGEXP_REPEAT (regexp)->regexp,
2997*38fd1498Szrj 				 max_start_cycle, min_start_cycle,
2998*38fd1498Szrj 				 max_finish_cycle, min_finish_cycle);
2999*38fd1498Szrj 	  max_start_cycle = *max_finish_cycle + 1;
3000*38fd1498Szrj 	  min_start_cycle = *min_finish_cycle + 1;
3001*38fd1498Szrj 	}
3002*38fd1498Szrj       break;
3003*38fd1498Szrj 
3004*38fd1498Szrj     case rm_sequence:
3005*38fd1498Szrj       for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
3006*38fd1498Szrj 	{
3007*38fd1498Szrj 	  process_regexp_cycles (REGEXP_SEQUENCE (regexp)->regexps [i],
3008*38fd1498Szrj 				 max_start_cycle, min_start_cycle,
3009*38fd1498Szrj 				 max_finish_cycle, min_finish_cycle);
3010*38fd1498Szrj 	  max_start_cycle = *max_finish_cycle + 1;
3011*38fd1498Szrj 	  min_start_cycle = *min_finish_cycle + 1;
3012*38fd1498Szrj 	}
3013*38fd1498Szrj       break;
3014*38fd1498Szrj 
3015*38fd1498Szrj     case rm_allof:
3016*38fd1498Szrj       {
3017*38fd1498Szrj 	int max_cycle = 0;
3018*38fd1498Szrj 	int min_cycle = 0;
3019*38fd1498Szrj 
3020*38fd1498Szrj 	for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
3021*38fd1498Szrj 	  {
3022*38fd1498Szrj 	    process_regexp_cycles (REGEXP_ALLOF (regexp)->regexps [i],
3023*38fd1498Szrj 				   max_start_cycle, min_start_cycle,
3024*38fd1498Szrj 				   max_finish_cycle, min_finish_cycle);
3025*38fd1498Szrj 	    if (max_cycle < *max_finish_cycle)
3026*38fd1498Szrj 	      max_cycle = *max_finish_cycle;
3027*38fd1498Szrj 	    if (i == 0 || min_cycle > *min_finish_cycle)
3028*38fd1498Szrj 	      min_cycle = *min_finish_cycle;
3029*38fd1498Szrj 	  }
3030*38fd1498Szrj 	*max_finish_cycle = max_cycle;
3031*38fd1498Szrj 	*min_finish_cycle = min_cycle;
3032*38fd1498Szrj       }
3033*38fd1498Szrj       break;
3034*38fd1498Szrj 
3035*38fd1498Szrj     case rm_oneof:
3036*38fd1498Szrj       {
3037*38fd1498Szrj 	int max_cycle = 0;
3038*38fd1498Szrj 	int min_cycle = 0;
3039*38fd1498Szrj 
3040*38fd1498Szrj 	for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
3041*38fd1498Szrj 	  {
3042*38fd1498Szrj 	    process_regexp_cycles (REGEXP_ONEOF (regexp)->regexps [i],
3043*38fd1498Szrj 				   max_start_cycle, min_start_cycle,
3044*38fd1498Szrj 				   max_finish_cycle, min_finish_cycle);
3045*38fd1498Szrj 	    if (max_cycle < *max_finish_cycle)
3046*38fd1498Szrj 	      max_cycle = *max_finish_cycle;
3047*38fd1498Szrj 	    if (i == 0 || min_cycle > *min_finish_cycle)
3048*38fd1498Szrj 	      min_cycle = *min_finish_cycle;
3049*38fd1498Szrj 	  }
3050*38fd1498Szrj 	*max_finish_cycle = max_cycle;
3051*38fd1498Szrj 	*min_finish_cycle = min_cycle;
3052*38fd1498Szrj       }
3053*38fd1498Szrj       break;
3054*38fd1498Szrj 
3055*38fd1498Szrj     case rm_nothing:
3056*38fd1498Szrj       *max_finish_cycle = max_start_cycle;
3057*38fd1498Szrj       *min_finish_cycle = min_start_cycle;
3058*38fd1498Szrj       break;
3059*38fd1498Szrj 
3060*38fd1498Szrj     default:
3061*38fd1498Szrj       gcc_unreachable ();
3062*38fd1498Szrj     }
3063*38fd1498Szrj }
3064*38fd1498Szrj 
3065*38fd1498Szrj /* The following function is called only for correct program.  The
3066*38fd1498Szrj    function defines max reservation of insns in cycles.  */
3067*38fd1498Szrj static void
evaluate_max_reserv_cycles(void)3068*38fd1498Szrj evaluate_max_reserv_cycles (void)
3069*38fd1498Szrj {
3070*38fd1498Szrj   int max_insn_cycles_num;
3071*38fd1498Szrj   int min_insn_cycles_num;
3072*38fd1498Szrj   decl_t decl;
3073*38fd1498Szrj   int i;
3074*38fd1498Szrj 
3075*38fd1498Szrj   description->max_insn_reserv_cycles = 0;
3076*38fd1498Szrj   for (i = 0; i < description->decls_num; i++)
3077*38fd1498Szrj     {
3078*38fd1498Szrj       decl = description->decls [i];
3079*38fd1498Szrj       if (decl->mode == dm_insn_reserv)
3080*38fd1498Szrj       {
3081*38fd1498Szrj         process_regexp_cycles (DECL_INSN_RESERV (decl)->regexp, 0, 0,
3082*38fd1498Szrj 			       &max_insn_cycles_num, &min_insn_cycles_num);
3083*38fd1498Szrj         if (description->max_insn_reserv_cycles < max_insn_cycles_num)
3084*38fd1498Szrj 	  description->max_insn_reserv_cycles = max_insn_cycles_num;
3085*38fd1498Szrj       }
3086*38fd1498Szrj     }
3087*38fd1498Szrj   description->max_insn_reserv_cycles++;
3088*38fd1498Szrj }
3089*38fd1498Szrj 
3090*38fd1498Szrj /* The following function calls functions for checking all
3091*38fd1498Szrj    description.  */
3092*38fd1498Szrj static void
check_all_description(void)3093*38fd1498Szrj check_all_description (void)
3094*38fd1498Szrj {
3095*38fd1498Szrj   process_decls ();
3096*38fd1498Szrj   check_automaton_usage ();
3097*38fd1498Szrj   process_regexp_decls ();
3098*38fd1498Szrj   check_usage ();
3099*38fd1498Szrj   check_loops_in_regexps ();
3100*38fd1498Szrj   if (!have_error)
3101*38fd1498Szrj     evaluate_max_reserv_cycles ();
3102*38fd1498Szrj }
3103*38fd1498Szrj 
3104*38fd1498Szrj 
3105*38fd1498Szrj 
3106*38fd1498Szrj /* The page contains abstract data `ticker'.  This data is used to
3107*38fd1498Szrj    report time of different phases of building automata.  It is
3108*38fd1498Szrj    possibly to write a description for which automata will be built
3109*38fd1498Szrj    during several minutes even on fast machine.  */
3110*38fd1498Szrj 
3111*38fd1498Szrj /* The following function creates ticker and makes it active.  */
3112*38fd1498Szrj static ticker_t
create_ticker(void)3113*38fd1498Szrj create_ticker (void)
3114*38fd1498Szrj {
3115*38fd1498Szrj   ticker_t ticker;
3116*38fd1498Szrj 
3117*38fd1498Szrj   ticker.modified_creation_time = get_run_time ();
3118*38fd1498Szrj   ticker.incremented_off_time = 0;
3119*38fd1498Szrj   return ticker;
3120*38fd1498Szrj }
3121*38fd1498Szrj 
3122*38fd1498Szrj /* The following function switches off given ticker.  */
3123*38fd1498Szrj static void
ticker_off(ticker_t * ticker)3124*38fd1498Szrj ticker_off (ticker_t *ticker)
3125*38fd1498Szrj {
3126*38fd1498Szrj   if (ticker->incremented_off_time == 0)
3127*38fd1498Szrj     ticker->incremented_off_time = get_run_time () + 1;
3128*38fd1498Szrj }
3129*38fd1498Szrj 
3130*38fd1498Szrj /* The following function switches on given ticker.  */
3131*38fd1498Szrj static void
ticker_on(ticker_t * ticker)3132*38fd1498Szrj ticker_on (ticker_t *ticker)
3133*38fd1498Szrj {
3134*38fd1498Szrj   if (ticker->incremented_off_time != 0)
3135*38fd1498Szrj     {
3136*38fd1498Szrj       ticker->modified_creation_time
3137*38fd1498Szrj         += get_run_time () - ticker->incremented_off_time + 1;
3138*38fd1498Szrj       ticker->incremented_off_time = 0;
3139*38fd1498Szrj     }
3140*38fd1498Szrj }
3141*38fd1498Szrj 
3142*38fd1498Szrj /* The following function returns current time in milliseconds since
3143*38fd1498Szrj    the moment when given ticker was created.  */
3144*38fd1498Szrj static int
active_time(ticker_t ticker)3145*38fd1498Szrj active_time (ticker_t ticker)
3146*38fd1498Szrj {
3147*38fd1498Szrj   if (ticker.incremented_off_time != 0)
3148*38fd1498Szrj     return ticker.incremented_off_time - 1 - ticker.modified_creation_time;
3149*38fd1498Szrj   else
3150*38fd1498Szrj     return get_run_time () - ticker.modified_creation_time;
3151*38fd1498Szrj }
3152*38fd1498Szrj 
3153*38fd1498Szrj /* The following function returns string representation of active time
3154*38fd1498Szrj    of given ticker.  The result is string representation of seconds
3155*38fd1498Szrj    with accuracy of 1/100 second.  Only result of the last call of the
3156*38fd1498Szrj    function exists.  Therefore the following code is not correct
3157*38fd1498Szrj 
3158*38fd1498Szrj       printf ("parser time: %s\ngeneration time: %s\n",
3159*38fd1498Szrj               active_time_string (parser_ticker),
3160*38fd1498Szrj               active_time_string (generation_ticker));
3161*38fd1498Szrj 
3162*38fd1498Szrj    Correct code has to be the following
3163*38fd1498Szrj 
3164*38fd1498Szrj       printf ("parser time: %s\n", active_time_string (parser_ticker));
3165*38fd1498Szrj       printf ("generation time: %s\n",
3166*38fd1498Szrj               active_time_string (generation_ticker));
3167*38fd1498Szrj 
3168*38fd1498Szrj */
3169*38fd1498Szrj static void
print_active_time(FILE * f,ticker_t ticker)3170*38fd1498Szrj print_active_time (FILE *f, ticker_t ticker)
3171*38fd1498Szrj {
3172*38fd1498Szrj   int msecs;
3173*38fd1498Szrj 
3174*38fd1498Szrj   msecs = active_time (ticker);
3175*38fd1498Szrj   fprintf (f, "%d.%06d", msecs / 1000000, msecs % 1000000);
3176*38fd1498Szrj }
3177*38fd1498Szrj 
3178*38fd1498Szrj 
3179*38fd1498Szrj 
3180*38fd1498Szrj /* The following variable value is number of automaton which are
3181*38fd1498Szrj    really being created.  This value is defined on the base of
3182*38fd1498Szrj    argument of option `-split'.  If the variable has zero value the
3183*38fd1498Szrj    number of automata is defined by the constructions `%automaton'.
3184*38fd1498Szrj    This case occurs when option `-split' is absent or has zero
3185*38fd1498Szrj    argument.  If constructions `define_automaton' is absent only one
3186*38fd1498Szrj    automaton is created.  */
3187*38fd1498Szrj static int automata_num;
3188*38fd1498Szrj 
3189*38fd1498Szrj /* The following variable values are times of
3190*38fd1498Szrj        o transformation of regular expressions
3191*38fd1498Szrj        o building NDFA (DFA if !ndfa_flag)
3192*38fd1498Szrj        o NDFA -> DFA   (simply the same automaton if !ndfa_flag)
3193*38fd1498Szrj        o DFA minimization
3194*38fd1498Szrj        o building insn equivalence classes
3195*38fd1498Szrj        o all previous ones
3196*38fd1498Szrj        o code output */
3197*38fd1498Szrj static ticker_t transform_time;
3198*38fd1498Szrj static ticker_t NDFA_time;
3199*38fd1498Szrj static ticker_t NDFA_to_DFA_time;
3200*38fd1498Szrj static ticker_t minimize_time;
3201*38fd1498Szrj static ticker_t equiv_time;
3202*38fd1498Szrj static ticker_t automaton_generation_time;
3203*38fd1498Szrj static ticker_t output_time;
3204*38fd1498Szrj 
3205*38fd1498Szrj /* The following variable values are times of
3206*38fd1498Szrj        all checking
3207*38fd1498Szrj        all generation
3208*38fd1498Szrj        all pipeline hazard translator work */
3209*38fd1498Szrj static ticker_t check_time;
3210*38fd1498Szrj static ticker_t generation_time;
3211*38fd1498Szrj static ticker_t all_time;
3212*38fd1498Szrj 
3213*38fd1498Szrj 
3214*38fd1498Szrj 
3215*38fd1498Szrj /* Pseudo insn decl which denotes advancing cycle.  */
3216*38fd1498Szrj static decl_t advance_cycle_insn_decl;
3217*38fd1498Szrj /* Pseudo insn decl which denotes collapsing the NDFA state.  */
3218*38fd1498Szrj static decl_t collapse_ndfa_insn_decl;
3219*38fd1498Szrj 
3220*38fd1498Szrj /* Create and record a decl for the special advance-cycle transition.  */
3221*38fd1498Szrj static void
add_advance_cycle_insn_decl(void)3222*38fd1498Szrj add_advance_cycle_insn_decl (void)
3223*38fd1498Szrj {
3224*38fd1498Szrj   advance_cycle_insn_decl = XCREATENODE (struct decl);
3225*38fd1498Szrj   advance_cycle_insn_decl->mode = dm_insn_reserv;
3226*38fd1498Szrj   advance_cycle_insn_decl->pos = no_pos;
3227*38fd1498Szrj   DECL_INSN_RESERV (advance_cycle_insn_decl)->regexp = NULL;
3228*38fd1498Szrj   DECL_INSN_RESERV (advance_cycle_insn_decl)->name = "$advance_cycle";
3229*38fd1498Szrj   DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num
3230*38fd1498Szrj     = description->insns_num;
3231*38fd1498Szrj   description->decls [description->decls_num] = advance_cycle_insn_decl;
3232*38fd1498Szrj   description->decls_num++;
3233*38fd1498Szrj   description->insns_num++;
3234*38fd1498Szrj }
3235*38fd1498Szrj 
3236*38fd1498Szrj /* Create and record a decl for the special collapse-NDFA transition.  */
3237*38fd1498Szrj static void
add_collapse_ndfa_insn_decl(void)3238*38fd1498Szrj add_collapse_ndfa_insn_decl (void)
3239*38fd1498Szrj {
3240*38fd1498Szrj   collapse_ndfa_insn_decl = XCREATENODE (struct decl);
3241*38fd1498Szrj   collapse_ndfa_insn_decl->mode = dm_insn_reserv;
3242*38fd1498Szrj   collapse_ndfa_insn_decl->pos = no_pos;
3243*38fd1498Szrj   DECL_INSN_RESERV (collapse_ndfa_insn_decl)->regexp = NULL;
3244*38fd1498Szrj   DECL_INSN_RESERV (collapse_ndfa_insn_decl)->name = "$collapse_ndfa";
3245*38fd1498Szrj   DECL_INSN_RESERV (collapse_ndfa_insn_decl)->insn_num
3246*38fd1498Szrj     = description->insns_num;
3247*38fd1498Szrj   description->decls [description->decls_num] = collapse_ndfa_insn_decl;
3248*38fd1498Szrj   description->decls_num++;
3249*38fd1498Szrj   description->insns_num++;
3250*38fd1498Szrj }
3251*38fd1498Szrj 
3252*38fd1498Szrj /* True if DECL is either of the two special decls we created.  */
3253*38fd1498Szrj static bool
special_decl_p(struct insn_reserv_decl * decl)3254*38fd1498Szrj special_decl_p (struct insn_reserv_decl *decl)
3255*38fd1498Szrj {
3256*38fd1498Szrj   return (decl == DECL_INSN_RESERV (advance_cycle_insn_decl)
3257*38fd1498Szrj 	  || (collapse_flag
3258*38fd1498Szrj 	      && decl == DECL_INSN_RESERV (collapse_ndfa_insn_decl)));
3259*38fd1498Szrj }
3260*38fd1498Szrj 
3261*38fd1498Szrj 
3262*38fd1498Szrj /* Abstract data `alternative states' which represents
3263*38fd1498Szrj    nondeterministic nature of the description (see comments for
3264*38fd1498Szrj    structures alt_state and state).  */
3265*38fd1498Szrj 
3266*38fd1498Szrj /* List of free states.  */
3267*38fd1498Szrj static alt_state_t first_free_alt_state;
3268*38fd1498Szrj 
3269*38fd1498Szrj #ifndef NDEBUG
3270*38fd1498Szrj /* The following variables is maximal number of allocated nodes
3271*38fd1498Szrj    alt_state.  */
3272*38fd1498Szrj static int allocated_alt_states_num = 0;
3273*38fd1498Szrj #endif
3274*38fd1498Szrj 
3275*38fd1498Szrj /* The following function returns free node alt_state.  It may be new
3276*38fd1498Szrj    allocated node or node freed earlier.  */
3277*38fd1498Szrj static alt_state_t
get_free_alt_state(void)3278*38fd1498Szrj get_free_alt_state (void)
3279*38fd1498Szrj {
3280*38fd1498Szrj   alt_state_t result;
3281*38fd1498Szrj 
3282*38fd1498Szrj   if (first_free_alt_state != NULL)
3283*38fd1498Szrj     {
3284*38fd1498Szrj       result = first_free_alt_state;
3285*38fd1498Szrj       first_free_alt_state = first_free_alt_state->next_alt_state;
3286*38fd1498Szrj     }
3287*38fd1498Szrj   else
3288*38fd1498Szrj     {
3289*38fd1498Szrj #ifndef NDEBUG
3290*38fd1498Szrj       allocated_alt_states_num++;
3291*38fd1498Szrj #endif
3292*38fd1498Szrj       result = XCREATENODE (struct alt_state);
3293*38fd1498Szrj     }
3294*38fd1498Szrj   result->state = NULL;
3295*38fd1498Szrj   result->next_alt_state = NULL;
3296*38fd1498Szrj   result->next_sorted_alt_state = NULL;
3297*38fd1498Szrj   return result;
3298*38fd1498Szrj }
3299*38fd1498Szrj 
3300*38fd1498Szrj /* The function frees node ALT_STATE.  */
3301*38fd1498Szrj static void
free_alt_state(alt_state_t alt_state)3302*38fd1498Szrj free_alt_state (alt_state_t alt_state)
3303*38fd1498Szrj {
3304*38fd1498Szrj   if (alt_state == NULL)
3305*38fd1498Szrj     return;
3306*38fd1498Szrj   alt_state->next_alt_state = first_free_alt_state;
3307*38fd1498Szrj   first_free_alt_state = alt_state;
3308*38fd1498Szrj }
3309*38fd1498Szrj 
3310*38fd1498Szrj /* The function frees list started with node ALT_STATE_LIST.  */
3311*38fd1498Szrj static void
free_alt_states(alt_state_t alt_states_list)3312*38fd1498Szrj free_alt_states (alt_state_t alt_states_list)
3313*38fd1498Szrj {
3314*38fd1498Szrj   alt_state_t curr_alt_state;
3315*38fd1498Szrj   alt_state_t next_alt_state;
3316*38fd1498Szrj 
3317*38fd1498Szrj   for (curr_alt_state = alt_states_list;
3318*38fd1498Szrj        curr_alt_state != NULL;
3319*38fd1498Szrj        curr_alt_state = next_alt_state)
3320*38fd1498Szrj     {
3321*38fd1498Szrj       next_alt_state = curr_alt_state->next_alt_state;
3322*38fd1498Szrj       free_alt_state (curr_alt_state);
3323*38fd1498Szrj     }
3324*38fd1498Szrj }
3325*38fd1498Szrj 
3326*38fd1498Szrj /* The function compares unique numbers of alt states.  */
3327*38fd1498Szrj static int
alt_state_cmp(const void * alt_state_ptr_1,const void * alt_state_ptr_2)3328*38fd1498Szrj alt_state_cmp (const void *alt_state_ptr_1, const void *alt_state_ptr_2)
3329*38fd1498Szrj {
3330*38fd1498Szrj   if ((*(const alt_state_t *) alt_state_ptr_1)->state->unique_num
3331*38fd1498Szrj       == (*(const alt_state_t *) alt_state_ptr_2)->state->unique_num)
3332*38fd1498Szrj     return 0;
3333*38fd1498Szrj   else if ((*(const alt_state_t *) alt_state_ptr_1)->state->unique_num
3334*38fd1498Szrj 	   < (*(const alt_state_t *) alt_state_ptr_2)->state->unique_num)
3335*38fd1498Szrj     return -1;
3336*38fd1498Szrj   else
3337*38fd1498Szrj     return 1;
3338*38fd1498Szrj }
3339*38fd1498Szrj 
3340*38fd1498Szrj /* The function sorts ALT_STATES_LIST and removes duplicated alt
3341*38fd1498Szrj    states from the list.  The comparison key is alt state unique
3342*38fd1498Szrj    number.  */
3343*38fd1498Szrj 
3344*38fd1498Szrj static alt_state_t
uniq_sort_alt_states(alt_state_t alt_states_list)3345*38fd1498Szrj uniq_sort_alt_states (alt_state_t alt_states_list)
3346*38fd1498Szrj {
3347*38fd1498Szrj   alt_state_t curr_alt_state;
3348*38fd1498Szrj   size_t i;
3349*38fd1498Szrj   size_t prev_unique_state_ind;
3350*38fd1498Szrj   alt_state_t result;
3351*38fd1498Szrj 
3352*38fd1498Szrj   if (alt_states_list == 0)
3353*38fd1498Szrj     return 0;
3354*38fd1498Szrj   if (alt_states_list->next_alt_state == 0)
3355*38fd1498Szrj     return alt_states_list;
3356*38fd1498Szrj 
3357*38fd1498Szrj   auto_vec<alt_state_t, 150> alt_states;
3358*38fd1498Szrj   for (curr_alt_state = alt_states_list;
3359*38fd1498Szrj        curr_alt_state != NULL;
3360*38fd1498Szrj        curr_alt_state = curr_alt_state->next_alt_state)
3361*38fd1498Szrj     alt_states.safe_push (curr_alt_state);
3362*38fd1498Szrj 
3363*38fd1498Szrj   alt_states.qsort (alt_state_cmp);
3364*38fd1498Szrj 
3365*38fd1498Szrj   prev_unique_state_ind = 0;
3366*38fd1498Szrj   for (i = 1; i < alt_states.length (); i++)
3367*38fd1498Szrj     if (alt_states[prev_unique_state_ind]->state != alt_states[i]->state)
3368*38fd1498Szrj       {
3369*38fd1498Szrj 	prev_unique_state_ind++;
3370*38fd1498Szrj 	alt_states[prev_unique_state_ind] = alt_states[i];
3371*38fd1498Szrj       }
3372*38fd1498Szrj   alt_states.truncate (prev_unique_state_ind + 1);
3373*38fd1498Szrj 
3374*38fd1498Szrj   for (i = 1; i < alt_states.length (); i++)
3375*38fd1498Szrj     alt_states[i-1]->next_sorted_alt_state
3376*38fd1498Szrj       = alt_states[i];
3377*38fd1498Szrj   alt_states.last ()->next_sorted_alt_state = 0;
3378*38fd1498Szrj 
3379*38fd1498Szrj   result = alt_states[0];
3380*38fd1498Szrj 
3381*38fd1498Szrj   return result;
3382*38fd1498Szrj }
3383*38fd1498Szrj 
3384*38fd1498Szrj /* The function checks equality of alt state lists.  Remember that the
3385*38fd1498Szrj    lists must be already sorted by the previous function.  */
3386*38fd1498Szrj static int
alt_states_eq(alt_state_t alt_states_1,alt_state_t alt_states_2)3387*38fd1498Szrj alt_states_eq (alt_state_t alt_states_1, alt_state_t alt_states_2)
3388*38fd1498Szrj {
3389*38fd1498Szrj   while (alt_states_1 != NULL && alt_states_2 != NULL
3390*38fd1498Szrj          && alt_state_cmp (&alt_states_1, &alt_states_2) == 0)
3391*38fd1498Szrj     {
3392*38fd1498Szrj       alt_states_1 = alt_states_1->next_sorted_alt_state;
3393*38fd1498Szrj       alt_states_2 = alt_states_2->next_sorted_alt_state;
3394*38fd1498Szrj     }
3395*38fd1498Szrj   return alt_states_1 == alt_states_2;
3396*38fd1498Szrj }
3397*38fd1498Szrj 
3398*38fd1498Szrj /* Initialization of the abstract data.  */
3399*38fd1498Szrj static void
initiate_alt_states(void)3400*38fd1498Szrj initiate_alt_states (void)
3401*38fd1498Szrj {
3402*38fd1498Szrj   first_free_alt_state = NULL;
3403*38fd1498Szrj }
3404*38fd1498Szrj 
3405*38fd1498Szrj /* Finishing work with the abstract data.  */
3406*38fd1498Szrj static void
finish_alt_states(void)3407*38fd1498Szrj finish_alt_states (void)
3408*38fd1498Szrj {
3409*38fd1498Szrj }
3410*38fd1498Szrj 
3411*38fd1498Szrj 
3412*38fd1498Szrj 
3413*38fd1498Szrj /* The page contains macros for work with bits strings.  We could use
3414*38fd1498Szrj    standard gcc bitmap or sbitmap but it would result in difficulties
3415*38fd1498Szrj    of building canadian cross.  */
3416*38fd1498Szrj 
3417*38fd1498Szrj /* Set bit number bitno in the bit string.  The macro is not side
3418*38fd1498Szrj    effect proof.  */
3419*38fd1498Szrj #define bitmap_set_bit(bitstring, bitno)					  \
3420*38fd1498Szrj   ((bitstring)[(bitno) / (sizeof (*(bitstring)) * CHAR_BIT)] |=		  \
3421*38fd1498Szrj 	(HOST_WIDE_INT)1 << (bitno) % (sizeof (*(bitstring)) * CHAR_BIT))
3422*38fd1498Szrj 
3423*38fd1498Szrj #define CLEAR_BIT(bitstring, bitno)					  \
3424*38fd1498Szrj   ((bitstring)[(bitno) / (sizeof (*(bitstring)) * CHAR_BIT)] &=		  \
3425*38fd1498Szrj 	~((HOST_WIDE_INT)1 << (bitno) % (sizeof (*(bitstring)) * CHAR_BIT)))
3426*38fd1498Szrj 
3427*38fd1498Szrj /* Test if bit number bitno in the bitstring is set.  The macro is not
3428*38fd1498Szrj    side effect proof.  */
3429*38fd1498Szrj #define bitmap_bit_p(bitstring, bitno)					  \
3430*38fd1498Szrj   ((bitstring)[(bitno) / (sizeof (*(bitstring)) * CHAR_BIT)] >>		  \
3431*38fd1498Szrj 	(bitno) % (sizeof (*(bitstring)) * CHAR_BIT) & 1)
3432*38fd1498Szrj 
3433*38fd1498Szrj 
3434*38fd1498Szrj 
3435*38fd1498Szrj /* This page contains abstract data `state'.  */
3436*38fd1498Szrj 
3437*38fd1498Szrj /* Maximal length of reservations in cycles (>= 1).  */
3438*38fd1498Szrj static int max_cycles_num;
3439*38fd1498Szrj 
3440*38fd1498Szrj /* Number of set elements (see type set_el_t) needed for
3441*38fd1498Szrj    representation of one cycle reservation.  It is depended on units
3442*38fd1498Szrj    number.  */
3443*38fd1498Szrj static int els_in_cycle_reserv;
3444*38fd1498Szrj 
3445*38fd1498Szrj /* Number of set elements (see type set_el_t) needed for
3446*38fd1498Szrj    representation of maximal length reservation.  Deterministic
3447*38fd1498Szrj    reservation is stored as set (bit string) of length equal to the
3448*38fd1498Szrj    variable value * number of bits in set_el_t.  */
3449*38fd1498Szrj static int els_in_reservs;
3450*38fd1498Szrj 
3451*38fd1498Szrj /* Array of pointers to unit declarations.  */
3452*38fd1498Szrj static unit_decl_t *units_array;
3453*38fd1498Szrj 
3454*38fd1498Szrj /* Temporary reservation of maximal length.  */
3455*38fd1498Szrj static reserv_sets_t temp_reserv;
3456*38fd1498Szrj 
3457*38fd1498Szrj /* The state table itself is represented by the following variable.  */
3458*38fd1498Szrj static htab_t state_table;
3459*38fd1498Szrj 
3460*38fd1498Szrj /* Linked list of free 'state' structures to be recycled.  The
3461*38fd1498Szrj    next_equiv_class_state pointer is borrowed for a free list.  */
3462*38fd1498Szrj static state_t first_free_state;
3463*38fd1498Szrj 
3464*38fd1498Szrj static int curr_unique_state_num;
3465*38fd1498Szrj 
3466*38fd1498Szrj #ifndef NDEBUG
3467*38fd1498Szrj /* The following variables is maximal number of allocated nodes
3468*38fd1498Szrj    `state'.  */
3469*38fd1498Szrj static int allocated_states_num = 0;
3470*38fd1498Szrj #endif
3471*38fd1498Szrj 
3472*38fd1498Szrj /* Allocate new reservation set.  */
3473*38fd1498Szrj static reserv_sets_t
alloc_empty_reserv_sets(void)3474*38fd1498Szrj alloc_empty_reserv_sets (void)
3475*38fd1498Szrj {
3476*38fd1498Szrj   reserv_sets_t result;
3477*38fd1498Szrj 
3478*38fd1498Szrj   obstack_blank (&irp, els_in_reservs * sizeof (set_el_t));
3479*38fd1498Szrj   result = (reserv_sets_t) obstack_base (&irp);
3480*38fd1498Szrj   obstack_finish (&irp);
3481*38fd1498Szrj   memset (result, 0, els_in_reservs * sizeof (set_el_t));
3482*38fd1498Szrj   return result;
3483*38fd1498Szrj }
3484*38fd1498Szrj 
3485*38fd1498Szrj /* Hash value of reservation set.  */
3486*38fd1498Szrj static unsigned
reserv_sets_hash_value(reserv_sets_t reservs)3487*38fd1498Szrj reserv_sets_hash_value (reserv_sets_t reservs)
3488*38fd1498Szrj {
3489*38fd1498Szrj   set_el_t hash_value;
3490*38fd1498Szrj   unsigned result;
3491*38fd1498Szrj   int reservs_num, i;
3492*38fd1498Szrj   set_el_t *reserv_ptr;
3493*38fd1498Szrj 
3494*38fd1498Szrj   hash_value = 0;
3495*38fd1498Szrj   reservs_num = els_in_reservs;
3496*38fd1498Szrj   reserv_ptr = reservs;
3497*38fd1498Szrj   i = 0;
3498*38fd1498Szrj   while (reservs_num != 0)
3499*38fd1498Szrj     {
3500*38fd1498Szrj       reservs_num--;
3501*38fd1498Szrj       hash_value += ((*reserv_ptr >> i)
3502*38fd1498Szrj 		     | (*reserv_ptr << (((sizeof (set_el_t) * CHAR_BIT) - 1) & -i)));
3503*38fd1498Szrj       i++;
3504*38fd1498Szrj       if (i == sizeof (set_el_t) * CHAR_BIT)
3505*38fd1498Szrj 	i = 0;
3506*38fd1498Szrj       reserv_ptr++;
3507*38fd1498Szrj     }
3508*38fd1498Szrj   if (sizeof (set_el_t) <= sizeof (unsigned))
3509*38fd1498Szrj     return hash_value;
3510*38fd1498Szrj   result = 0;
3511*38fd1498Szrj   for (i = sizeof (set_el_t); i > 0; i -= sizeof (unsigned) - 1)
3512*38fd1498Szrj     {
3513*38fd1498Szrj       result += (unsigned) hash_value;
3514*38fd1498Szrj       hash_value >>= (sizeof (unsigned) - 1) * CHAR_BIT;
3515*38fd1498Szrj     }
3516*38fd1498Szrj   return result;
3517*38fd1498Szrj }
3518*38fd1498Szrj 
3519*38fd1498Szrj /* Comparison of given reservation sets.  */
3520*38fd1498Szrj static int
reserv_sets_cmp(const_reserv_sets_t reservs_1,const_reserv_sets_t reservs_2)3521*38fd1498Szrj reserv_sets_cmp (const_reserv_sets_t reservs_1, const_reserv_sets_t reservs_2)
3522*38fd1498Szrj {
3523*38fd1498Szrj   int reservs_num;
3524*38fd1498Szrj   const set_el_t *reserv_ptr_1;
3525*38fd1498Szrj   const set_el_t *reserv_ptr_2;
3526*38fd1498Szrj 
3527*38fd1498Szrj   gcc_assert (reservs_1 && reservs_2);
3528*38fd1498Szrj   reservs_num = els_in_reservs;
3529*38fd1498Szrj   reserv_ptr_1 = reservs_1;
3530*38fd1498Szrj   reserv_ptr_2 = reservs_2;
3531*38fd1498Szrj   while (reservs_num != 0 && *reserv_ptr_1 == *reserv_ptr_2)
3532*38fd1498Szrj     {
3533*38fd1498Szrj       reservs_num--;
3534*38fd1498Szrj       reserv_ptr_1++;
3535*38fd1498Szrj       reserv_ptr_2++;
3536*38fd1498Szrj     }
3537*38fd1498Szrj   if (reservs_num == 0)
3538*38fd1498Szrj     return 0;
3539*38fd1498Szrj   else if (*reserv_ptr_1 < *reserv_ptr_2)
3540*38fd1498Szrj     return -1;
3541*38fd1498Szrj   else
3542*38fd1498Szrj     return 1;
3543*38fd1498Szrj }
3544*38fd1498Szrj 
3545*38fd1498Szrj /* The function checks equality of the reservation sets.  */
3546*38fd1498Szrj static int
reserv_sets_eq(const_reserv_sets_t reservs_1,const_reserv_sets_t reservs_2)3547*38fd1498Szrj reserv_sets_eq (const_reserv_sets_t reservs_1, const_reserv_sets_t reservs_2)
3548*38fd1498Szrj {
3549*38fd1498Szrj   return reserv_sets_cmp (reservs_1, reservs_2) == 0;
3550*38fd1498Szrj }
3551*38fd1498Szrj 
3552*38fd1498Szrj /* Set up in the reservation set that unit with UNIT_NUM is used on
3553*38fd1498Szrj    CYCLE_NUM.  */
3554*38fd1498Szrj static void
set_unit_reserv(reserv_sets_t reservs,int cycle_num,int unit_num)3555*38fd1498Szrj set_unit_reserv (reserv_sets_t reservs, int cycle_num, int unit_num)
3556*38fd1498Szrj {
3557*38fd1498Szrj   gcc_assert (cycle_num < max_cycles_num);
3558*38fd1498Szrj   bitmap_set_bit (reservs, cycle_num * els_in_cycle_reserv
3559*38fd1498Szrj            * sizeof (set_el_t) * CHAR_BIT + unit_num);
3560*38fd1498Szrj }
3561*38fd1498Szrj 
3562*38fd1498Szrj /* Set up in the reservation set RESERVS that unit with UNIT_NUM is
3563*38fd1498Szrj    used on CYCLE_NUM.  */
3564*38fd1498Szrj static int
test_unit_reserv(reserv_sets_t reservs,int cycle_num,int unit_num)3565*38fd1498Szrj test_unit_reserv (reserv_sets_t reservs, int cycle_num, int unit_num)
3566*38fd1498Szrj {
3567*38fd1498Szrj   gcc_assert (cycle_num < max_cycles_num);
3568*38fd1498Szrj   return bitmap_bit_p (reservs, cycle_num * els_in_cycle_reserv
3569*38fd1498Szrj 		   * sizeof (set_el_t) * CHAR_BIT + unit_num);
3570*38fd1498Szrj }
3571*38fd1498Szrj 
3572*38fd1498Szrj /* The function checks that the reservation sets are intersected,
3573*38fd1498Szrj    i.e. there is a unit reservation on a cycle in both reservation
3574*38fd1498Szrj    sets.  */
3575*38fd1498Szrj static int
reserv_sets_are_intersected(reserv_sets_t operand_1,reserv_sets_t operand_2)3576*38fd1498Szrj reserv_sets_are_intersected (reserv_sets_t operand_1,
3577*38fd1498Szrj 			     reserv_sets_t operand_2)
3578*38fd1498Szrj {
3579*38fd1498Szrj   set_el_t *el_ptr_1;
3580*38fd1498Szrj   set_el_t *el_ptr_2;
3581*38fd1498Szrj   set_el_t *cycle_ptr_1;
3582*38fd1498Szrj   set_el_t *cycle_ptr_2;
3583*38fd1498Szrj 
3584*38fd1498Szrj   gcc_assert (operand_1 && operand_2);
3585*38fd1498Szrj   for (el_ptr_1 = operand_1, el_ptr_2 = operand_2;
3586*38fd1498Szrj        el_ptr_1 < operand_1 + els_in_reservs;
3587*38fd1498Szrj        el_ptr_1++, el_ptr_2++)
3588*38fd1498Szrj     if (*el_ptr_1 & *el_ptr_2)
3589*38fd1498Szrj       return 1;
3590*38fd1498Szrj   reserv_sets_or (temp_reserv, operand_1, operand_2);
3591*38fd1498Szrj   for (cycle_ptr_1 = operand_1, cycle_ptr_2 = operand_2;
3592*38fd1498Szrj        cycle_ptr_1 < operand_1 + els_in_reservs;
3593*38fd1498Szrj        cycle_ptr_1 += els_in_cycle_reserv, cycle_ptr_2 += els_in_cycle_reserv)
3594*38fd1498Szrj     {
3595*38fd1498Szrj       for (el_ptr_1 = cycle_ptr_1, el_ptr_2 = get_excl_set (cycle_ptr_2);
3596*38fd1498Szrj 	   el_ptr_1 < cycle_ptr_1 + els_in_cycle_reserv;
3597*38fd1498Szrj 	   el_ptr_1++, el_ptr_2++)
3598*38fd1498Szrj 	if (*el_ptr_1 & *el_ptr_2)
3599*38fd1498Szrj 	  return 1;
3600*38fd1498Szrj       if (!check_presence_pattern_sets (cycle_ptr_1, cycle_ptr_2, FALSE))
3601*38fd1498Szrj 	return 1;
3602*38fd1498Szrj       if (!check_presence_pattern_sets (temp_reserv + (cycle_ptr_2
3603*38fd1498Szrj 						       - operand_2),
3604*38fd1498Szrj 					cycle_ptr_2, TRUE))
3605*38fd1498Szrj 	return 1;
3606*38fd1498Szrj       if (!check_absence_pattern_sets (cycle_ptr_1, cycle_ptr_2, FALSE))
3607*38fd1498Szrj 	return 1;
3608*38fd1498Szrj       if (!check_absence_pattern_sets (temp_reserv + (cycle_ptr_2 - operand_2),
3609*38fd1498Szrj 				       cycle_ptr_2, TRUE))
3610*38fd1498Szrj 	return 1;
3611*38fd1498Szrj     }
3612*38fd1498Szrj   return 0;
3613*38fd1498Szrj }
3614*38fd1498Szrj 
3615*38fd1498Szrj /* The function sets up RESULT bits by bits of OPERAND shifted on one
3616*38fd1498Szrj    cpu cycle.  The remaining bits of OPERAND (representing the last
3617*38fd1498Szrj    cycle unit reservations) are not changed.  */
3618*38fd1498Szrj static void
reserv_sets_shift(reserv_sets_t result,reserv_sets_t operand)3619*38fd1498Szrj reserv_sets_shift (reserv_sets_t result, reserv_sets_t operand)
3620*38fd1498Szrj {
3621*38fd1498Szrj   int i;
3622*38fd1498Szrj 
3623*38fd1498Szrj   gcc_assert (result && operand && result != operand);
3624*38fd1498Szrj   for (i = els_in_cycle_reserv; i < els_in_reservs; i++)
3625*38fd1498Szrj     result [i - els_in_cycle_reserv] = operand [i];
3626*38fd1498Szrj }
3627*38fd1498Szrj 
3628*38fd1498Szrj /* OR of the reservation sets.  */
3629*38fd1498Szrj static void
reserv_sets_or(reserv_sets_t result,reserv_sets_t operand_1,reserv_sets_t operand_2)3630*38fd1498Szrj reserv_sets_or (reserv_sets_t result, reserv_sets_t operand_1,
3631*38fd1498Szrj 		reserv_sets_t operand_2)
3632*38fd1498Szrj {
3633*38fd1498Szrj   set_el_t *el_ptr_1;
3634*38fd1498Szrj   set_el_t *el_ptr_2;
3635*38fd1498Szrj   set_el_t *result_set_el_ptr;
3636*38fd1498Szrj 
3637*38fd1498Szrj   gcc_assert (result && operand_1 && operand_2);
3638*38fd1498Szrj   for (el_ptr_1 = operand_1, el_ptr_2 = operand_2, result_set_el_ptr = result;
3639*38fd1498Szrj        el_ptr_1 < operand_1 + els_in_reservs;
3640*38fd1498Szrj        el_ptr_1++, el_ptr_2++, result_set_el_ptr++)
3641*38fd1498Szrj     *result_set_el_ptr = *el_ptr_1 | *el_ptr_2;
3642*38fd1498Szrj }
3643*38fd1498Szrj 
3644*38fd1498Szrj /* AND of the reservation sets.  */
3645*38fd1498Szrj static void
reserv_sets_and(reserv_sets_t result,reserv_sets_t operand_1,reserv_sets_t operand_2)3646*38fd1498Szrj reserv_sets_and (reserv_sets_t result, reserv_sets_t operand_1,
3647*38fd1498Szrj 		reserv_sets_t operand_2)
3648*38fd1498Szrj {
3649*38fd1498Szrj   set_el_t *el_ptr_1;
3650*38fd1498Szrj   set_el_t *el_ptr_2;
3651*38fd1498Szrj   set_el_t *result_set_el_ptr;
3652*38fd1498Szrj 
3653*38fd1498Szrj   gcc_assert (result && operand_1 && operand_2);
3654*38fd1498Szrj   for (el_ptr_1 = operand_1, el_ptr_2 = operand_2, result_set_el_ptr = result;
3655*38fd1498Szrj        el_ptr_1 < operand_1 + els_in_reservs;
3656*38fd1498Szrj        el_ptr_1++, el_ptr_2++, result_set_el_ptr++)
3657*38fd1498Szrj     *result_set_el_ptr = *el_ptr_1 & *el_ptr_2;
3658*38fd1498Szrj }
3659*38fd1498Szrj 
3660*38fd1498Szrj /* The function outputs string representation of units reservation on
3661*38fd1498Szrj    cycle START_CYCLE in the reservation set.  The function uses repeat
3662*38fd1498Szrj    construction if REPETITION_NUM > 1.  */
3663*38fd1498Szrj static void
output_cycle_reservs(FILE * f,reserv_sets_t reservs,int start_cycle,int repetition_num)3664*38fd1498Szrj output_cycle_reservs (FILE *f, reserv_sets_t reservs, int start_cycle,
3665*38fd1498Szrj 		      int repetition_num)
3666*38fd1498Szrj {
3667*38fd1498Szrj   int unit_num;
3668*38fd1498Szrj   int reserved_units_num;
3669*38fd1498Szrj 
3670*38fd1498Szrj   reserved_units_num = 0;
3671*38fd1498Szrj   for (unit_num = 0; unit_num < description->units_num; unit_num++)
3672*38fd1498Szrj     if (bitmap_bit_p (reservs, start_cycle * els_in_cycle_reserv
3673*38fd1498Szrj                   * sizeof (set_el_t) * CHAR_BIT + unit_num))
3674*38fd1498Szrj       reserved_units_num++;
3675*38fd1498Szrj   gcc_assert (repetition_num > 0);
3676*38fd1498Szrj   if (repetition_num != 1 && reserved_units_num > 1)
3677*38fd1498Szrj     fprintf (f, "(");
3678*38fd1498Szrj   reserved_units_num = 0;
3679*38fd1498Szrj   for (unit_num = 0;
3680*38fd1498Szrj        unit_num < description->units_num;
3681*38fd1498Szrj        unit_num++)
3682*38fd1498Szrj     if (bitmap_bit_p (reservs, start_cycle * els_in_cycle_reserv
3683*38fd1498Szrj 		  * sizeof (set_el_t) * CHAR_BIT + unit_num))
3684*38fd1498Szrj       {
3685*38fd1498Szrj         if (reserved_units_num != 0)
3686*38fd1498Szrj           fprintf (f, "+");
3687*38fd1498Szrj         reserved_units_num++;
3688*38fd1498Szrj         fprintf (f, "%s", units_array [unit_num]->name);
3689*38fd1498Szrj       }
3690*38fd1498Szrj   if (reserved_units_num == 0)
3691*38fd1498Szrj     fprintf (f, NOTHING_NAME);
3692*38fd1498Szrj   gcc_assert (repetition_num > 0);
3693*38fd1498Szrj   if (repetition_num != 1 && reserved_units_num > 1)
3694*38fd1498Szrj     fprintf (f, ")");
3695*38fd1498Szrj   if (repetition_num != 1)
3696*38fd1498Szrj     fprintf (f, "*%d", repetition_num);
3697*38fd1498Szrj }
3698*38fd1498Szrj 
3699*38fd1498Szrj /* The function outputs string representation of units reservation in
3700*38fd1498Szrj    the reservation set.  */
3701*38fd1498Szrj static void
output_reserv_sets(FILE * f,reserv_sets_t reservs)3702*38fd1498Szrj output_reserv_sets (FILE *f, reserv_sets_t reservs)
3703*38fd1498Szrj {
3704*38fd1498Szrj   int start_cycle = 0;
3705*38fd1498Szrj   int cycle;
3706*38fd1498Szrj   int repetition_num;
3707*38fd1498Szrj 
3708*38fd1498Szrj   repetition_num = 0;
3709*38fd1498Szrj   for (cycle = 0; cycle < max_cycles_num; cycle++)
3710*38fd1498Szrj     if (repetition_num == 0)
3711*38fd1498Szrj       {
3712*38fd1498Szrj         repetition_num++;
3713*38fd1498Szrj         start_cycle = cycle;
3714*38fd1498Szrj       }
3715*38fd1498Szrj     else if (memcmp
3716*38fd1498Szrj              ((char *) reservs + start_cycle * els_in_cycle_reserv
3717*38fd1498Szrj 	      * sizeof (set_el_t),
3718*38fd1498Szrj               (char *) reservs + cycle * els_in_cycle_reserv
3719*38fd1498Szrj 	      * sizeof (set_el_t),
3720*38fd1498Szrj 	      els_in_cycle_reserv * sizeof (set_el_t)) == 0)
3721*38fd1498Szrj       repetition_num++;
3722*38fd1498Szrj     else
3723*38fd1498Szrj       {
3724*38fd1498Szrj         if (start_cycle != 0)
3725*38fd1498Szrj           fprintf (f, ", ");
3726*38fd1498Szrj         output_cycle_reservs (f, reservs, start_cycle, repetition_num);
3727*38fd1498Szrj         repetition_num = 1;
3728*38fd1498Szrj         start_cycle = cycle;
3729*38fd1498Szrj       }
3730*38fd1498Szrj   if (start_cycle < max_cycles_num)
3731*38fd1498Szrj     {
3732*38fd1498Szrj       if (start_cycle != 0)
3733*38fd1498Szrj         fprintf (f, ", ");
3734*38fd1498Szrj       output_cycle_reservs (f, reservs, start_cycle, repetition_num);
3735*38fd1498Szrj     }
3736*38fd1498Szrj }
3737*38fd1498Szrj 
3738*38fd1498Szrj /* The following function returns free node state for AUTOMATON.  It
3739*38fd1498Szrj    may be new allocated node or node freed earlier.  The function also
3740*38fd1498Szrj    allocates reservation set if WITH_RESERVS has nonzero value.  */
3741*38fd1498Szrj static state_t
get_free_state(int with_reservs,automaton_t automaton)3742*38fd1498Szrj get_free_state (int with_reservs, automaton_t automaton)
3743*38fd1498Szrj {
3744*38fd1498Szrj   state_t result;
3745*38fd1498Szrj 
3746*38fd1498Szrj   gcc_assert (max_cycles_num > 0 && automaton);
3747*38fd1498Szrj   if (first_free_state)
3748*38fd1498Szrj     {
3749*38fd1498Szrj       result = first_free_state;
3750*38fd1498Szrj       first_free_state = result->next_equiv_class_state;
3751*38fd1498Szrj 
3752*38fd1498Szrj       result->next_equiv_class_state = NULL;
3753*38fd1498Szrj       result->automaton = automaton;
3754*38fd1498Szrj       result->first_out_arc = NULL;
3755*38fd1498Szrj       result->it_was_placed_in_stack_for_NDFA_forming = 0;
3756*38fd1498Szrj       result->it_was_placed_in_stack_for_DFA_forming = 0;
3757*38fd1498Szrj       result->component_states = NULL;
3758*38fd1498Szrj     }
3759*38fd1498Szrj   else
3760*38fd1498Szrj     {
3761*38fd1498Szrj #ifndef NDEBUG
3762*38fd1498Szrj       allocated_states_num++;
3763*38fd1498Szrj #endif
3764*38fd1498Szrj       result = XCREATENODE (struct state);
3765*38fd1498Szrj       result->automaton = automaton;
3766*38fd1498Szrj       result->first_out_arc = NULL;
3767*38fd1498Szrj       result->unique_num = curr_unique_state_num;
3768*38fd1498Szrj       curr_unique_state_num++;
3769*38fd1498Szrj     }
3770*38fd1498Szrj   if (with_reservs)
3771*38fd1498Szrj     {
3772*38fd1498Szrj       if (result->reservs == NULL)
3773*38fd1498Szrj         result->reservs = alloc_empty_reserv_sets ();
3774*38fd1498Szrj       else
3775*38fd1498Szrj         memset (result->reservs, 0, els_in_reservs * sizeof (set_el_t));
3776*38fd1498Szrj     }
3777*38fd1498Szrj   return result;
3778*38fd1498Szrj }
3779*38fd1498Szrj 
3780*38fd1498Szrj /* The function frees node STATE.  */
3781*38fd1498Szrj static void
free_state(state_t state)3782*38fd1498Szrj free_state (state_t state)
3783*38fd1498Szrj {
3784*38fd1498Szrj   free_alt_states (state->component_states);
3785*38fd1498Szrj   state->next_equiv_class_state = first_free_state;
3786*38fd1498Szrj   first_free_state = state;
3787*38fd1498Szrj }
3788*38fd1498Szrj 
3789*38fd1498Szrj /* Hash value of STATE.  If STATE represents deterministic state it is
3790*38fd1498Szrj    simply hash value of the corresponding reservation set.  Otherwise
3791*38fd1498Szrj    it is formed from hash values of the component deterministic
3792*38fd1498Szrj    states.  One more key is order number of state automaton.  */
3793*38fd1498Szrj static hashval_t
state_hash(const void * state)3794*38fd1498Szrj state_hash (const void *state)
3795*38fd1498Szrj {
3796*38fd1498Szrj   unsigned int hash_value;
3797*38fd1498Szrj   alt_state_t alt_state;
3798*38fd1498Szrj 
3799*38fd1498Szrj   if (((const_state_t) state)->component_states == NULL)
3800*38fd1498Szrj     hash_value = reserv_sets_hash_value (((const_state_t) state)->reservs);
3801*38fd1498Szrj   else
3802*38fd1498Szrj     {
3803*38fd1498Szrj       hash_value = 0;
3804*38fd1498Szrj       for (alt_state = ((const_state_t) state)->component_states;
3805*38fd1498Szrj            alt_state != NULL;
3806*38fd1498Szrj            alt_state = alt_state->next_sorted_alt_state)
3807*38fd1498Szrj         hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
3808*38fd1498Szrj                        | (hash_value << CHAR_BIT))
3809*38fd1498Szrj                       + alt_state->state->unique_num);
3810*38fd1498Szrj     }
3811*38fd1498Szrj   hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
3812*38fd1498Szrj                  | (hash_value << CHAR_BIT))
3813*38fd1498Szrj                 + ((const_state_t) state)->automaton->automaton_order_num);
3814*38fd1498Szrj   return hash_value;
3815*38fd1498Szrj }
3816*38fd1498Szrj 
3817*38fd1498Szrj /* Return nonzero value if the states are the same.  */
3818*38fd1498Szrj static int
state_eq_p(const void * state_1,const void * state_2)3819*38fd1498Szrj state_eq_p (const void *state_1, const void *state_2)
3820*38fd1498Szrj {
3821*38fd1498Szrj   alt_state_t alt_state_1;
3822*38fd1498Szrj   alt_state_t alt_state_2;
3823*38fd1498Szrj 
3824*38fd1498Szrj   if (((const_state_t) state_1)->automaton != ((const_state_t) state_2)->automaton)
3825*38fd1498Szrj     return 0;
3826*38fd1498Szrj   else if (((const_state_t) state_1)->component_states == NULL
3827*38fd1498Szrj            && ((const_state_t) state_2)->component_states == NULL)
3828*38fd1498Szrj     return reserv_sets_eq (((const_state_t) state_1)->reservs,
3829*38fd1498Szrj 			   ((const_state_t) state_2)->reservs);
3830*38fd1498Szrj   else if (((const_state_t) state_1)->component_states != NULL
3831*38fd1498Szrj            && ((const_state_t) state_2)->component_states != NULL)
3832*38fd1498Szrj     {
3833*38fd1498Szrj       for (alt_state_1 = ((const_state_t) state_1)->component_states,
3834*38fd1498Szrj            alt_state_2 = ((const_state_t) state_2)->component_states;
3835*38fd1498Szrj            alt_state_1 != NULL && alt_state_2 != NULL;
3836*38fd1498Szrj            alt_state_1 = alt_state_1->next_sorted_alt_state,
3837*38fd1498Szrj 	   alt_state_2 = alt_state_2->next_sorted_alt_state)
3838*38fd1498Szrj         /* All state in the list must be already in the hash table.
3839*38fd1498Szrj            Also the lists must be sorted.  */
3840*38fd1498Szrj         if (alt_state_1->state != alt_state_2->state)
3841*38fd1498Szrj           return 0;
3842*38fd1498Szrj       return alt_state_1 == alt_state_2;
3843*38fd1498Szrj     }
3844*38fd1498Szrj   else
3845*38fd1498Szrj     return 0;
3846*38fd1498Szrj }
3847*38fd1498Szrj 
3848*38fd1498Szrj /* Insert STATE into the state table.  */
3849*38fd1498Szrj static state_t
insert_state(state_t state)3850*38fd1498Szrj insert_state (state_t state)
3851*38fd1498Szrj {
3852*38fd1498Szrj   void **entry_ptr;
3853*38fd1498Szrj 
3854*38fd1498Szrj   entry_ptr = htab_find_slot (state_table, (void *) state, INSERT);
3855*38fd1498Szrj   if (*entry_ptr == NULL)
3856*38fd1498Szrj     *entry_ptr = (void *) state;
3857*38fd1498Szrj   return (state_t) *entry_ptr;
3858*38fd1498Szrj }
3859*38fd1498Szrj 
3860*38fd1498Szrj /* Add reservation of unit with UNIT_NUM on cycle CYCLE_NUM to
3861*38fd1498Szrj    deterministic STATE.  */
3862*38fd1498Szrj static void
set_state_reserv(state_t state,int cycle_num,int unit_num)3863*38fd1498Szrj set_state_reserv (state_t state, int cycle_num, int unit_num)
3864*38fd1498Szrj {
3865*38fd1498Szrj   set_unit_reserv (state->reservs, cycle_num, unit_num);
3866*38fd1498Szrj }
3867*38fd1498Szrj 
3868*38fd1498Szrj /* Return nonzero value if the deterministic states contains a
3869*38fd1498Szrj    reservation of the same cpu unit on the same cpu cycle.  */
3870*38fd1498Szrj static int
intersected_state_reservs_p(state_t state1,state_t state2)3871*38fd1498Szrj intersected_state_reservs_p (state_t state1, state_t state2)
3872*38fd1498Szrj {
3873*38fd1498Szrj   gcc_assert (state1->automaton == state2->automaton);
3874*38fd1498Szrj   return reserv_sets_are_intersected (state1->reservs, state2->reservs);
3875*38fd1498Szrj }
3876*38fd1498Szrj 
3877*38fd1498Szrj /* Return deterministic state (inserted into the table) which
3878*38fd1498Szrj    representing the automaton state which is union of reservations of
3879*38fd1498Szrj    the deterministic states masked by RESERVS.  */
3880*38fd1498Szrj static state_t
states_union(state_t state1,state_t state2,reserv_sets_t reservs)3881*38fd1498Szrj states_union (state_t state1, state_t state2, reserv_sets_t reservs)
3882*38fd1498Szrj {
3883*38fd1498Szrj   state_t result;
3884*38fd1498Szrj   state_t state_in_table;
3885*38fd1498Szrj 
3886*38fd1498Szrj   gcc_assert (state1->automaton == state2->automaton);
3887*38fd1498Szrj   result = get_free_state (1, state1->automaton);
3888*38fd1498Szrj   reserv_sets_or (result->reservs, state1->reservs, state2->reservs);
3889*38fd1498Szrj   reserv_sets_and (result->reservs, result->reservs, reservs);
3890*38fd1498Szrj   state_in_table = insert_state (result);
3891*38fd1498Szrj   if (result != state_in_table)
3892*38fd1498Szrj     {
3893*38fd1498Szrj       free_state (result);
3894*38fd1498Szrj       result = state_in_table;
3895*38fd1498Szrj     }
3896*38fd1498Szrj   return result;
3897*38fd1498Szrj }
3898*38fd1498Szrj 
3899*38fd1498Szrj /* Return deterministic state (inserted into the table) which
3900*38fd1498Szrj    represent the automaton state is obtained from deterministic STATE
3901*38fd1498Szrj    by advancing cpu cycle and masking by RESERVS.  */
3902*38fd1498Szrj static state_t
state_shift(state_t state,reserv_sets_t reservs)3903*38fd1498Szrj state_shift (state_t state, reserv_sets_t reservs)
3904*38fd1498Szrj {
3905*38fd1498Szrj   state_t result;
3906*38fd1498Szrj   state_t state_in_table;
3907*38fd1498Szrj 
3908*38fd1498Szrj   result = get_free_state (1, state->automaton);
3909*38fd1498Szrj   reserv_sets_shift (result->reservs, state->reservs);
3910*38fd1498Szrj   reserv_sets_and (result->reservs, result->reservs, reservs);
3911*38fd1498Szrj   state_in_table = insert_state (result);
3912*38fd1498Szrj   if (result != state_in_table)
3913*38fd1498Szrj     {
3914*38fd1498Szrj       free_state (result);
3915*38fd1498Szrj       result = state_in_table;
3916*38fd1498Szrj     }
3917*38fd1498Szrj   return result;
3918*38fd1498Szrj }
3919*38fd1498Szrj 
3920*38fd1498Szrj /* Initialization of the abstract data.  */
3921*38fd1498Szrj static void
initiate_states(void)3922*38fd1498Szrj initiate_states (void)
3923*38fd1498Szrj {
3924*38fd1498Szrj   decl_t decl;
3925*38fd1498Szrj   int i;
3926*38fd1498Szrj 
3927*38fd1498Szrj   if (description->units_num)
3928*38fd1498Szrj     units_array = XNEWVEC (unit_decl_t, description->units_num);
3929*38fd1498Szrj   else
3930*38fd1498Szrj     units_array = 0;
3931*38fd1498Szrj 
3932*38fd1498Szrj   for (i = 0; i < description->decls_num; i++)
3933*38fd1498Szrj     {
3934*38fd1498Szrj       decl = description->decls [i];
3935*38fd1498Szrj       if (decl->mode == dm_unit)
3936*38fd1498Szrj 	units_array [DECL_UNIT (decl)->unit_num] = DECL_UNIT (decl);
3937*38fd1498Szrj     }
3938*38fd1498Szrj   max_cycles_num = description->max_insn_reserv_cycles;
3939*38fd1498Szrj   els_in_cycle_reserv
3940*38fd1498Szrj     = ((description->units_num + sizeof (set_el_t) * CHAR_BIT - 1)
3941*38fd1498Szrj        / (sizeof (set_el_t) * CHAR_BIT));
3942*38fd1498Szrj   els_in_reservs = els_in_cycle_reserv * max_cycles_num;
3943*38fd1498Szrj   curr_unique_state_num = 0;
3944*38fd1498Szrj   initiate_alt_states ();
3945*38fd1498Szrj   state_table = htab_create (1500, state_hash, state_eq_p, (htab_del) 0);
3946*38fd1498Szrj   temp_reserv = alloc_empty_reserv_sets ();
3947*38fd1498Szrj }
3948*38fd1498Szrj 
3949*38fd1498Szrj /* Finishing work with the abstract data.  */
3950*38fd1498Szrj static void
finish_states(void)3951*38fd1498Szrj finish_states (void)
3952*38fd1498Szrj {
3953*38fd1498Szrj   free (units_array);
3954*38fd1498Szrj   units_array = 0;
3955*38fd1498Szrj   htab_delete (state_table);
3956*38fd1498Szrj   first_free_state = NULL;
3957*38fd1498Szrj   finish_alt_states ();
3958*38fd1498Szrj }
3959*38fd1498Szrj 
3960*38fd1498Szrj 
3961*38fd1498Szrj 
3962*38fd1498Szrj /* Abstract data `arcs'.  */
3963*38fd1498Szrj 
3964*38fd1498Szrj /* List of free arcs.  */
3965*38fd1498Szrj static arc_t first_free_arc;
3966*38fd1498Szrj 
3967*38fd1498Szrj #ifndef NDEBUG
3968*38fd1498Szrj /* The following variables is maximal number of allocated nodes
3969*38fd1498Szrj    `arc'.  */
3970*38fd1498Szrj static int allocated_arcs_num = 0;
3971*38fd1498Szrj #endif
3972*38fd1498Szrj 
3973*38fd1498Szrj /* The function frees node ARC.  */
3974*38fd1498Szrj static void
free_arc(arc_t arc)3975*38fd1498Szrj free_arc (arc_t arc)
3976*38fd1498Szrj {
3977*38fd1498Szrj   arc->next_out_arc = first_free_arc;
3978*38fd1498Szrj   first_free_arc = arc;
3979*38fd1498Szrj }
3980*38fd1498Szrj 
3981*38fd1498Szrj /* The function removes and frees ARC staring from FROM_STATE.  */
3982*38fd1498Szrj static void
remove_arc(state_t from_state,arc_t arc)3983*38fd1498Szrj remove_arc (state_t from_state, arc_t arc)
3984*38fd1498Szrj {
3985*38fd1498Szrj   arc_t prev_arc;
3986*38fd1498Szrj   arc_t curr_arc;
3987*38fd1498Szrj 
3988*38fd1498Szrj   gcc_assert (arc);
3989*38fd1498Szrj   for (prev_arc = NULL, curr_arc = from_state->first_out_arc;
3990*38fd1498Szrj        curr_arc != NULL;
3991*38fd1498Szrj        prev_arc = curr_arc, curr_arc = curr_arc->next_out_arc)
3992*38fd1498Szrj     if (curr_arc == arc)
3993*38fd1498Szrj       break;
3994*38fd1498Szrj   gcc_assert (curr_arc);
3995*38fd1498Szrj   if (prev_arc == NULL)
3996*38fd1498Szrj     from_state->first_out_arc = arc->next_out_arc;
3997*38fd1498Szrj   else
3998*38fd1498Szrj     prev_arc->next_out_arc = arc->next_out_arc;
3999*38fd1498Szrj   from_state->num_out_arcs--;
4000*38fd1498Szrj   free_arc (arc);
4001*38fd1498Szrj }
4002*38fd1498Szrj 
4003*38fd1498Szrj /* The functions returns arc with given characteristics (or NULL if
4004*38fd1498Szrj    the arc does not exist).  */
4005*38fd1498Szrj static arc_t
find_arc(state_t from_state,state_t to_state,ainsn_t insn)4006*38fd1498Szrj find_arc (state_t from_state, state_t to_state, ainsn_t insn)
4007*38fd1498Szrj {
4008*38fd1498Szrj   arc_t arc;
4009*38fd1498Szrj 
4010*38fd1498Szrj   for (arc = first_out_arc (from_state); arc != NULL; arc = next_out_arc (arc))
4011*38fd1498Szrj     if (arc->insn == insn
4012*38fd1498Szrj 	&& (arc->to_state == to_state
4013*38fd1498Szrj 	    || (collapse_flag
4014*38fd1498Szrj 		/* Any arc is good enough for a collapse-ndfa transition.  */
4015*38fd1498Szrj 		&& (insn->insn_reserv_decl
4016*38fd1498Szrj 		    == DECL_INSN_RESERV (collapse_ndfa_insn_decl)))))
4017*38fd1498Szrj       return arc;
4018*38fd1498Szrj   return NULL;
4019*38fd1498Szrj }
4020*38fd1498Szrj 
4021*38fd1498Szrj /* The function adds arc from FROM_STATE to TO_STATE marked by AINSN,
4022*38fd1498Szrj    unless such an arc already exists.  */
4023*38fd1498Szrj static void
add_arc(state_t from_state,state_t to_state,ainsn_t ainsn)4024*38fd1498Szrj add_arc (state_t from_state, state_t to_state, ainsn_t ainsn)
4025*38fd1498Szrj {
4026*38fd1498Szrj   arc_t new_arc;
4027*38fd1498Szrj 
4028*38fd1498Szrj   new_arc = find_arc (from_state, to_state, ainsn);
4029*38fd1498Szrj   if (new_arc != NULL)
4030*38fd1498Szrj     return;
4031*38fd1498Szrj   if (first_free_arc == NULL)
4032*38fd1498Szrj     {
4033*38fd1498Szrj #ifndef NDEBUG
4034*38fd1498Szrj       allocated_arcs_num++;
4035*38fd1498Szrj #endif
4036*38fd1498Szrj       new_arc = XCREATENODE (struct arc);
4037*38fd1498Szrj       new_arc->to_state = NULL;
4038*38fd1498Szrj       new_arc->insn = NULL;
4039*38fd1498Szrj       new_arc->next_out_arc = NULL;
4040*38fd1498Szrj     }
4041*38fd1498Szrj   else
4042*38fd1498Szrj     {
4043*38fd1498Szrj       new_arc = first_free_arc;
4044*38fd1498Szrj       first_free_arc =  first_free_arc->next_out_arc;
4045*38fd1498Szrj     }
4046*38fd1498Szrj   new_arc->to_state = to_state;
4047*38fd1498Szrj   new_arc->insn = ainsn;
4048*38fd1498Szrj   ainsn->arc_exists_p = 1;
4049*38fd1498Szrj   new_arc->next_out_arc = from_state->first_out_arc;
4050*38fd1498Szrj   from_state->first_out_arc = new_arc;
4051*38fd1498Szrj   from_state->num_out_arcs++;
4052*38fd1498Szrj   new_arc->next_arc_marked_by_insn = NULL;
4053*38fd1498Szrj }
4054*38fd1498Szrj 
4055*38fd1498Szrj /* The function returns the first arc starting from STATE.  */
4056*38fd1498Szrj static arc_t
first_out_arc(const_state_t state)4057*38fd1498Szrj first_out_arc (const_state_t state)
4058*38fd1498Szrj {
4059*38fd1498Szrj   return state->first_out_arc;
4060*38fd1498Szrj }
4061*38fd1498Szrj 
4062*38fd1498Szrj /* The function returns next out arc after ARC.  */
4063*38fd1498Szrj static arc_t
next_out_arc(arc_t arc)4064*38fd1498Szrj next_out_arc (arc_t arc)
4065*38fd1498Szrj {
4066*38fd1498Szrj   return arc->next_out_arc;
4067*38fd1498Szrj }
4068*38fd1498Szrj 
4069*38fd1498Szrj /* Initialization of the abstract data.  */
4070*38fd1498Szrj static void
initiate_arcs(void)4071*38fd1498Szrj initiate_arcs (void)
4072*38fd1498Szrj {
4073*38fd1498Szrj   first_free_arc = NULL;
4074*38fd1498Szrj }
4075*38fd1498Szrj 
4076*38fd1498Szrj /* Finishing work with the abstract data.  */
4077*38fd1498Szrj static void
finish_arcs(void)4078*38fd1498Szrj finish_arcs (void)
4079*38fd1498Szrj {
4080*38fd1498Szrj }
4081*38fd1498Szrj 
4082*38fd1498Szrj 
4083*38fd1498Szrj 
4084*38fd1498Szrj /* Abstract data `automata lists'.  */
4085*38fd1498Szrj 
4086*38fd1498Szrj /* List of free states.  */
4087*38fd1498Szrj static automata_list_el_t first_free_automata_list_el;
4088*38fd1498Szrj 
4089*38fd1498Szrj /* The list being formed.  */
4090*38fd1498Szrj static automata_list_el_t current_automata_list;
4091*38fd1498Szrj 
4092*38fd1498Szrj /* Hash table of automata lists.  */
4093*38fd1498Szrj static htab_t automata_list_table;
4094*38fd1498Szrj 
4095*38fd1498Szrj /* The following function returns free automata list el.  It may be
4096*38fd1498Szrj    new allocated node or node freed earlier.  */
4097*38fd1498Szrj static automata_list_el_t
get_free_automata_list_el(void)4098*38fd1498Szrj get_free_automata_list_el (void)
4099*38fd1498Szrj {
4100*38fd1498Szrj   automata_list_el_t result;
4101*38fd1498Szrj 
4102*38fd1498Szrj   if (first_free_automata_list_el != NULL)
4103*38fd1498Szrj     {
4104*38fd1498Szrj       result = first_free_automata_list_el;
4105*38fd1498Szrj       first_free_automata_list_el
4106*38fd1498Szrj 	= first_free_automata_list_el->next_automata_list_el;
4107*38fd1498Szrj     }
4108*38fd1498Szrj   else
4109*38fd1498Szrj     result = XCREATENODE (struct automata_list_el);
4110*38fd1498Szrj   result->automaton = NULL;
4111*38fd1498Szrj   result->next_automata_list_el = NULL;
4112*38fd1498Szrj   return result;
4113*38fd1498Szrj }
4114*38fd1498Szrj 
4115*38fd1498Szrj /* The function frees node AUTOMATA_LIST_EL.  */
4116*38fd1498Szrj static void
free_automata_list_el(automata_list_el_t automata_list_el)4117*38fd1498Szrj free_automata_list_el (automata_list_el_t automata_list_el)
4118*38fd1498Szrj {
4119*38fd1498Szrj   if (automata_list_el == NULL)
4120*38fd1498Szrj     return;
4121*38fd1498Szrj   automata_list_el->next_automata_list_el = first_free_automata_list_el;
4122*38fd1498Szrj   first_free_automata_list_el = automata_list_el;
4123*38fd1498Szrj }
4124*38fd1498Szrj 
4125*38fd1498Szrj /* The function frees list AUTOMATA_LIST.  */
4126*38fd1498Szrj static void
free_automata_list(automata_list_el_t automata_list)4127*38fd1498Szrj free_automata_list (automata_list_el_t automata_list)
4128*38fd1498Szrj {
4129*38fd1498Szrj   automata_list_el_t curr_automata_list_el;
4130*38fd1498Szrj   automata_list_el_t next_automata_list_el;
4131*38fd1498Szrj 
4132*38fd1498Szrj   for (curr_automata_list_el = automata_list;
4133*38fd1498Szrj        curr_automata_list_el != NULL;
4134*38fd1498Szrj        curr_automata_list_el = next_automata_list_el)
4135*38fd1498Szrj     {
4136*38fd1498Szrj       next_automata_list_el = curr_automata_list_el->next_automata_list_el;
4137*38fd1498Szrj       free_automata_list_el (curr_automata_list_el);
4138*38fd1498Szrj     }
4139*38fd1498Szrj }
4140*38fd1498Szrj 
4141*38fd1498Szrj /* Hash value of AUTOMATA_LIST.  */
4142*38fd1498Szrj static hashval_t
automata_list_hash(const void * automata_list)4143*38fd1498Szrj automata_list_hash (const void *automata_list)
4144*38fd1498Szrj {
4145*38fd1498Szrj   unsigned int hash_value;
4146*38fd1498Szrj   const_automata_list_el_t curr_automata_list_el;
4147*38fd1498Szrj 
4148*38fd1498Szrj   hash_value = 0;
4149*38fd1498Szrj   for (curr_automata_list_el = (const_automata_list_el_t) automata_list;
4150*38fd1498Szrj        curr_automata_list_el != NULL;
4151*38fd1498Szrj        curr_automata_list_el = curr_automata_list_el->next_automata_list_el)
4152*38fd1498Szrj     hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
4153*38fd1498Szrj 		   | (hash_value << CHAR_BIT))
4154*38fd1498Szrj 		  + curr_automata_list_el->automaton->automaton_order_num);
4155*38fd1498Szrj   return hash_value;
4156*38fd1498Szrj }
4157*38fd1498Szrj 
4158*38fd1498Szrj /* Return nonzero value if the automata_lists are the same.  */
4159*38fd1498Szrj static int
automata_list_eq_p(const void * automata_list_1,const void * automata_list_2)4160*38fd1498Szrj automata_list_eq_p (const void *automata_list_1, const void *automata_list_2)
4161*38fd1498Szrj {
4162*38fd1498Szrj   const_automata_list_el_t automata_list_el_1;
4163*38fd1498Szrj   const_automata_list_el_t automata_list_el_2;
4164*38fd1498Szrj 
4165*38fd1498Szrj   for (automata_list_el_1 = (const_automata_list_el_t) automata_list_1,
4166*38fd1498Szrj 	 automata_list_el_2 = (const_automata_list_el_t) automata_list_2;
4167*38fd1498Szrj        automata_list_el_1 != NULL && automata_list_el_2 != NULL;
4168*38fd1498Szrj        automata_list_el_1 = automata_list_el_1->next_automata_list_el,
4169*38fd1498Szrj 	 automata_list_el_2 = automata_list_el_2->next_automata_list_el)
4170*38fd1498Szrj     if (automata_list_el_1->automaton != automata_list_el_2->automaton)
4171*38fd1498Szrj       return 0;
4172*38fd1498Szrj   return automata_list_el_1 == automata_list_el_2;
4173*38fd1498Szrj }
4174*38fd1498Szrj 
4175*38fd1498Szrj /* Initialization of the abstract data.  */
4176*38fd1498Szrj static void
initiate_automata_lists(void)4177*38fd1498Szrj initiate_automata_lists (void)
4178*38fd1498Szrj {
4179*38fd1498Szrj   first_free_automata_list_el = NULL;
4180*38fd1498Szrj   automata_list_table = htab_create (1500, automata_list_hash,
4181*38fd1498Szrj 				     automata_list_eq_p, (htab_del) 0);
4182*38fd1498Szrj }
4183*38fd1498Szrj 
4184*38fd1498Szrj /* The following function starts new automata list and makes it the
4185*38fd1498Szrj    current one.  */
4186*38fd1498Szrj static void
automata_list_start(void)4187*38fd1498Szrj automata_list_start (void)
4188*38fd1498Szrj {
4189*38fd1498Szrj   current_automata_list = NULL;
4190*38fd1498Szrj }
4191*38fd1498Szrj 
4192*38fd1498Szrj /* The following function adds AUTOMATON to the current list.  */
4193*38fd1498Szrj static void
automata_list_add(automaton_t automaton)4194*38fd1498Szrj automata_list_add (automaton_t automaton)
4195*38fd1498Szrj {
4196*38fd1498Szrj   automata_list_el_t el;
4197*38fd1498Szrj 
4198*38fd1498Szrj   el = get_free_automata_list_el ();
4199*38fd1498Szrj   el->automaton = automaton;
4200*38fd1498Szrj   el->next_automata_list_el = current_automata_list;
4201*38fd1498Szrj   current_automata_list = el;
4202*38fd1498Szrj }
4203*38fd1498Szrj 
4204*38fd1498Szrj /* The following function finishes forming the current list, inserts
4205*38fd1498Szrj    it into the table and returns it.  */
4206*38fd1498Szrj static automata_list_el_t
automata_list_finish(void)4207*38fd1498Szrj automata_list_finish (void)
4208*38fd1498Szrj {
4209*38fd1498Szrj   void **entry_ptr;
4210*38fd1498Szrj 
4211*38fd1498Szrj   if (current_automata_list == NULL)
4212*38fd1498Szrj     return NULL;
4213*38fd1498Szrj   entry_ptr = htab_find_slot (automata_list_table,
4214*38fd1498Szrj 			      (void *) current_automata_list, INSERT);
4215*38fd1498Szrj   if (*entry_ptr == NULL)
4216*38fd1498Szrj     *entry_ptr = (void *) current_automata_list;
4217*38fd1498Szrj   else
4218*38fd1498Szrj     free_automata_list (current_automata_list);
4219*38fd1498Szrj   current_automata_list = NULL;
4220*38fd1498Szrj   return (automata_list_el_t) *entry_ptr;
4221*38fd1498Szrj }
4222*38fd1498Szrj 
4223*38fd1498Szrj /* Finishing work with the abstract data.  */
4224*38fd1498Szrj static void
finish_automata_lists(void)4225*38fd1498Szrj finish_automata_lists (void)
4226*38fd1498Szrj {
4227*38fd1498Szrj   htab_delete (automata_list_table);
4228*38fd1498Szrj }
4229*38fd1498Szrj 
4230*38fd1498Szrj 
4231*38fd1498Szrj 
4232*38fd1498Szrj /* The page contains abstract data for work with exclusion sets (see
4233*38fd1498Szrj    exclusion_set in file rtl.def).  */
4234*38fd1498Szrj 
4235*38fd1498Szrj /* The following variable refers to an exclusion set returned by
4236*38fd1498Szrj    get_excl_set.  This is bit string of length equal to cpu units
4237*38fd1498Szrj    number.  If exclusion set for given unit contains 1 for a unit,
4238*38fd1498Szrj    then simultaneous reservation of the units is prohibited.  */
4239*38fd1498Szrj static reserv_sets_t excl_set;
4240*38fd1498Szrj 
4241*38fd1498Szrj /* The array contains exclusion sets for each unit.  */
4242*38fd1498Szrj static reserv_sets_t *unit_excl_set_table;
4243*38fd1498Szrj 
4244*38fd1498Szrj /* The following function forms the array containing exclusion sets
4245*38fd1498Szrj    for each unit.  */
4246*38fd1498Szrj static void
initiate_excl_sets(void)4247*38fd1498Szrj initiate_excl_sets (void)
4248*38fd1498Szrj {
4249*38fd1498Szrj   decl_t decl;
4250*38fd1498Szrj   reserv_sets_t unit_excl_set;
4251*38fd1498Szrj   unit_set_el_t el;
4252*38fd1498Szrj   int i;
4253*38fd1498Szrj 
4254*38fd1498Szrj   obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4255*38fd1498Szrj   excl_set = (reserv_sets_t) obstack_base (&irp);
4256*38fd1498Szrj   obstack_finish (&irp);
4257*38fd1498Szrj   obstack_blank (&irp, description->units_num * sizeof (reserv_sets_t));
4258*38fd1498Szrj   unit_excl_set_table = (reserv_sets_t *) obstack_base (&irp);
4259*38fd1498Szrj   obstack_finish (&irp);
4260*38fd1498Szrj   /* Evaluate unit exclusion sets.  */
4261*38fd1498Szrj   for (i = 0; i < description->decls_num; i++)
4262*38fd1498Szrj     {
4263*38fd1498Szrj       decl = description->decls [i];
4264*38fd1498Szrj       if (decl->mode == dm_unit)
4265*38fd1498Szrj 	{
4266*38fd1498Szrj 	  obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4267*38fd1498Szrj 	  unit_excl_set = (reserv_sets_t) obstack_base (&irp);
4268*38fd1498Szrj 	  obstack_finish (&irp);
4269*38fd1498Szrj 	  memset (unit_excl_set, 0, els_in_cycle_reserv * sizeof (set_el_t));
4270*38fd1498Szrj 	  for (el = DECL_UNIT (decl)->excl_list;
4271*38fd1498Szrj 	       el != NULL;
4272*38fd1498Szrj 	       el = el->next_unit_set_el)
4273*38fd1498Szrj 	    {
4274*38fd1498Szrj 	      bitmap_set_bit (unit_excl_set, el->unit_decl->unit_num);
4275*38fd1498Szrj 	      el->unit_decl->in_set_p = TRUE;
4276*38fd1498Szrj 	    }
4277*38fd1498Szrj           unit_excl_set_table [DECL_UNIT (decl)->unit_num] = unit_excl_set;
4278*38fd1498Szrj         }
4279*38fd1498Szrj     }
4280*38fd1498Szrj }
4281*38fd1498Szrj 
4282*38fd1498Szrj /* The function sets up and return EXCL_SET which is union of
4283*38fd1498Szrj    exclusion sets for each unit in IN_SET.  */
4284*38fd1498Szrj static reserv_sets_t
get_excl_set(reserv_sets_t in_set)4285*38fd1498Szrj get_excl_set (reserv_sets_t in_set)
4286*38fd1498Szrj {
4287*38fd1498Szrj   int el;
4288*38fd1498Szrj   unsigned int i;
4289*38fd1498Szrj   int start_unit_num;
4290*38fd1498Szrj   int unit_num;
4291*38fd1498Szrj 
4292*38fd1498Szrj   memset (excl_set, 0, els_in_cycle_reserv * sizeof (set_el_t));
4293*38fd1498Szrj   for (el = 0; el < els_in_cycle_reserv; el++)
4294*38fd1498Szrj     if (in_set[el])
4295*38fd1498Szrj       for (i = 0; i < CHAR_BIT * sizeof (set_el_t); i++)
4296*38fd1498Szrj 	if ((in_set[el] >> i) & 1)
4297*38fd1498Szrj 	  {
4298*38fd1498Szrj 	    start_unit_num = el * CHAR_BIT * sizeof (set_el_t) + i;
4299*38fd1498Szrj 	    if (start_unit_num >= description->units_num)
4300*38fd1498Szrj 	      return excl_set;
4301*38fd1498Szrj 	    for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4302*38fd1498Szrj 	      {
4303*38fd1498Szrj 		excl_set [unit_num]
4304*38fd1498Szrj 		  |= unit_excl_set_table [start_unit_num] [unit_num];
4305*38fd1498Szrj 	      }
4306*38fd1498Szrj 	  }
4307*38fd1498Szrj   return excl_set;
4308*38fd1498Szrj }
4309*38fd1498Szrj 
4310*38fd1498Szrj 
4311*38fd1498Szrj 
4312*38fd1498Szrj /* The page contains abstract data for work with presence/absence
4313*38fd1498Szrj    pattern sets (see presence_set/absence_set in file rtl.def).  */
4314*38fd1498Szrj 
4315*38fd1498Szrj /* The following arrays contain correspondingly presence, final
4316*38fd1498Szrj    presence, absence, and final absence patterns for each unit.  */
4317*38fd1498Szrj static pattern_reserv_t *unit_presence_set_table;
4318*38fd1498Szrj static pattern_reserv_t *unit_final_presence_set_table;
4319*38fd1498Szrj static pattern_reserv_t *unit_absence_set_table;
4320*38fd1498Szrj static pattern_reserv_t *unit_final_absence_set_table;
4321*38fd1498Szrj 
4322*38fd1498Szrj /* The following function forms list of reservation sets for given
4323*38fd1498Szrj    PATTERN_LIST.  */
4324*38fd1498Szrj static pattern_reserv_t
form_reserv_sets_list(pattern_set_el_t pattern_list)4325*38fd1498Szrj form_reserv_sets_list (pattern_set_el_t pattern_list)
4326*38fd1498Szrj {
4327*38fd1498Szrj   pattern_set_el_t el;
4328*38fd1498Szrj   pattern_reserv_t first, curr, prev;
4329*38fd1498Szrj   int i;
4330*38fd1498Szrj 
4331*38fd1498Szrj   prev = first = NULL;
4332*38fd1498Szrj   for (el = pattern_list; el != NULL; el = el->next_pattern_set_el)
4333*38fd1498Szrj     {
4334*38fd1498Szrj       curr = XCREATENODE (struct pattern_reserv);
4335*38fd1498Szrj       curr->reserv = alloc_empty_reserv_sets ();
4336*38fd1498Szrj       curr->next_pattern_reserv = NULL;
4337*38fd1498Szrj       for (i = 0; i < el->units_num; i++)
4338*38fd1498Szrj 	{
4339*38fd1498Szrj 	  bitmap_set_bit (curr->reserv, el->unit_decls [i]->unit_num);
4340*38fd1498Szrj 	  el->unit_decls [i]->in_set_p = TRUE;
4341*38fd1498Szrj 	}
4342*38fd1498Szrj       if (prev != NULL)
4343*38fd1498Szrj 	prev->next_pattern_reserv = curr;
4344*38fd1498Szrj       else
4345*38fd1498Szrj 	first = curr;
4346*38fd1498Szrj       prev = curr;
4347*38fd1498Szrj     }
4348*38fd1498Szrj   return first;
4349*38fd1498Szrj }
4350*38fd1498Szrj 
4351*38fd1498Szrj  /* The following function forms the array containing presence and
4352*38fd1498Szrj    absence pattern sets for each unit.  */
4353*38fd1498Szrj static void
initiate_presence_absence_pattern_sets(void)4354*38fd1498Szrj initiate_presence_absence_pattern_sets (void)
4355*38fd1498Szrj {
4356*38fd1498Szrj   decl_t decl;
4357*38fd1498Szrj   int i;
4358*38fd1498Szrj 
4359*38fd1498Szrj   obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4360*38fd1498Szrj   unit_presence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4361*38fd1498Szrj   obstack_finish (&irp);
4362*38fd1498Szrj   obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4363*38fd1498Szrj   unit_final_presence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4364*38fd1498Szrj   obstack_finish (&irp);
4365*38fd1498Szrj   obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4366*38fd1498Szrj   unit_absence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4367*38fd1498Szrj   obstack_finish (&irp);
4368*38fd1498Szrj   obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4369*38fd1498Szrj   unit_final_absence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4370*38fd1498Szrj   obstack_finish (&irp);
4371*38fd1498Szrj   /* Evaluate unit presence/absence sets.  */
4372*38fd1498Szrj   for (i = 0; i < description->decls_num; i++)
4373*38fd1498Szrj     {
4374*38fd1498Szrj       decl = description->decls [i];
4375*38fd1498Szrj       if (decl->mode == dm_unit)
4376*38fd1498Szrj 	{
4377*38fd1498Szrj           unit_presence_set_table [DECL_UNIT (decl)->unit_num]
4378*38fd1498Szrj 	    = form_reserv_sets_list (DECL_UNIT (decl)->presence_list);
4379*38fd1498Szrj           unit_final_presence_set_table [DECL_UNIT (decl)->unit_num]
4380*38fd1498Szrj 	    = form_reserv_sets_list (DECL_UNIT (decl)->final_presence_list);
4381*38fd1498Szrj           unit_absence_set_table [DECL_UNIT (decl)->unit_num]
4382*38fd1498Szrj 	    = form_reserv_sets_list (DECL_UNIT (decl)->absence_list);
4383*38fd1498Szrj           unit_final_absence_set_table [DECL_UNIT (decl)->unit_num]
4384*38fd1498Szrj 	    = form_reserv_sets_list (DECL_UNIT (decl)->final_absence_list);
4385*38fd1498Szrj         }
4386*38fd1498Szrj     }
4387*38fd1498Szrj }
4388*38fd1498Szrj 
4389*38fd1498Szrj /* The function checks that CHECKED_SET satisfies all presence pattern
4390*38fd1498Szrj    sets for units in ORIGINAL_SET.  The function returns TRUE if it
4391*38fd1498Szrj    is ok.  */
4392*38fd1498Szrj static int
check_presence_pattern_sets(reserv_sets_t checked_set,reserv_sets_t original_set,int final_p)4393*38fd1498Szrj check_presence_pattern_sets (reserv_sets_t checked_set,
4394*38fd1498Szrj 			     reserv_sets_t original_set,
4395*38fd1498Szrj 			     int final_p)
4396*38fd1498Szrj {
4397*38fd1498Szrj   int el;
4398*38fd1498Szrj   unsigned int i;
4399*38fd1498Szrj   int start_unit_num;
4400*38fd1498Szrj   int unit_num;
4401*38fd1498Szrj   int presence_p;
4402*38fd1498Szrj   pattern_reserv_t pat_reserv;
4403*38fd1498Szrj 
4404*38fd1498Szrj   for (el = 0; el < els_in_cycle_reserv; el++)
4405*38fd1498Szrj     if (original_set[el])
4406*38fd1498Szrj       for (i = 0; i < CHAR_BIT * sizeof (set_el_t); i++)
4407*38fd1498Szrj 	if ((original_set[el] >> i) & 1)
4408*38fd1498Szrj 	  {
4409*38fd1498Szrj 	    start_unit_num = el * CHAR_BIT * sizeof (set_el_t) + i;
4410*38fd1498Szrj 	    if (start_unit_num >= description->units_num)
4411*38fd1498Szrj 	      break;
4412*38fd1498Szrj 	    if ((final_p
4413*38fd1498Szrj 		 && unit_final_presence_set_table [start_unit_num] == NULL)
4414*38fd1498Szrj 		|| (!final_p
4415*38fd1498Szrj 		    && unit_presence_set_table [start_unit_num] == NULL))
4416*38fd1498Szrj 	      continue;
4417*38fd1498Szrj 	    presence_p = FALSE;
4418*38fd1498Szrj 	    for (pat_reserv = (final_p
4419*38fd1498Szrj 			       ? unit_final_presence_set_table [start_unit_num]
4420*38fd1498Szrj 			       : unit_presence_set_table [start_unit_num]);
4421*38fd1498Szrj 		 pat_reserv != NULL;
4422*38fd1498Szrj 		 pat_reserv = pat_reserv->next_pattern_reserv)
4423*38fd1498Szrj 	      {
4424*38fd1498Szrj 		for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4425*38fd1498Szrj 		  if ((checked_set [unit_num] & pat_reserv->reserv [unit_num])
4426*38fd1498Szrj 		      != pat_reserv->reserv [unit_num])
4427*38fd1498Szrj 		    break;
4428*38fd1498Szrj 		presence_p = presence_p || unit_num >= els_in_cycle_reserv;
4429*38fd1498Szrj 	      }
4430*38fd1498Szrj 	    if (!presence_p)
4431*38fd1498Szrj 	      return FALSE;
4432*38fd1498Szrj 	  }
4433*38fd1498Szrj   return TRUE;
4434*38fd1498Szrj }
4435*38fd1498Szrj 
4436*38fd1498Szrj /* The function checks that CHECKED_SET satisfies all absence pattern
4437*38fd1498Szrj    sets for units in ORIGINAL_SET.  The function returns TRUE if it
4438*38fd1498Szrj    is ok.  */
4439*38fd1498Szrj static int
check_absence_pattern_sets(reserv_sets_t checked_set,reserv_sets_t original_set,int final_p)4440*38fd1498Szrj check_absence_pattern_sets (reserv_sets_t checked_set,
4441*38fd1498Szrj 			    reserv_sets_t original_set,
4442*38fd1498Szrj 			    int final_p)
4443*38fd1498Szrj {
4444*38fd1498Szrj   int el;
4445*38fd1498Szrj   unsigned int i;
4446*38fd1498Szrj   int start_unit_num;
4447*38fd1498Szrj   int unit_num;
4448*38fd1498Szrj   pattern_reserv_t pat_reserv;
4449*38fd1498Szrj 
4450*38fd1498Szrj   for (el = 0; el < els_in_cycle_reserv; el++)
4451*38fd1498Szrj     if (original_set[el])
4452*38fd1498Szrj       for (i = 0; i < CHAR_BIT * sizeof (set_el_t); i++)
4453*38fd1498Szrj 	if ((original_set[el] >> i) & 1)
4454*38fd1498Szrj 	  {
4455*38fd1498Szrj 	    start_unit_num = el * CHAR_BIT * sizeof (set_el_t) + i;
4456*38fd1498Szrj 	    if (start_unit_num >= description->units_num)
4457*38fd1498Szrj 	      break;
4458*38fd1498Szrj 	    for (pat_reserv = (final_p
4459*38fd1498Szrj 			       ? unit_final_absence_set_table [start_unit_num]
4460*38fd1498Szrj 			       : unit_absence_set_table [start_unit_num]);
4461*38fd1498Szrj 		 pat_reserv != NULL;
4462*38fd1498Szrj 		 pat_reserv = pat_reserv->next_pattern_reserv)
4463*38fd1498Szrj 	      {
4464*38fd1498Szrj 		for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4465*38fd1498Szrj 		  if ((checked_set [unit_num] & pat_reserv->reserv [unit_num])
4466*38fd1498Szrj 		      != pat_reserv->reserv [unit_num]
4467*38fd1498Szrj 		      && pat_reserv->reserv [unit_num])
4468*38fd1498Szrj 		    break;
4469*38fd1498Szrj 		if (unit_num >= els_in_cycle_reserv)
4470*38fd1498Szrj 		  return FALSE;
4471*38fd1498Szrj 	      }
4472*38fd1498Szrj 	  }
4473*38fd1498Szrj   return TRUE;
4474*38fd1498Szrj }
4475*38fd1498Szrj 
4476*38fd1498Szrj 
4477*38fd1498Szrj 
4478*38fd1498Szrj /* This page contains code for transformation of original reservations
4479*38fd1498Szrj    described in .md file.  The main goal of transformations is
4480*38fd1498Szrj    simplifying reservation and lifting up all `|' on the top of IR
4481*38fd1498Szrj    reservation representation.  */
4482*38fd1498Szrj 
4483*38fd1498Szrj 
4484*38fd1498Szrj /* The following function makes copy of IR representation of
4485*38fd1498Szrj    reservation.  The function also substitutes all reservations
4486*38fd1498Szrj    defined by define_reservation by corresponding value during making
4487*38fd1498Szrj    the copy.  */
4488*38fd1498Szrj static regexp_t
copy_insn_regexp(regexp_t regexp)4489*38fd1498Szrj copy_insn_regexp (regexp_t regexp)
4490*38fd1498Szrj {
4491*38fd1498Szrj   regexp_t  result;
4492*38fd1498Szrj   int i;
4493*38fd1498Szrj 
4494*38fd1498Szrj   switch (regexp->mode)
4495*38fd1498Szrj     {
4496*38fd1498Szrj     case rm_reserv:
4497*38fd1498Szrj       result = copy_insn_regexp (REGEXP_RESERV (regexp)->reserv_decl->regexp);
4498*38fd1498Szrj       break;
4499*38fd1498Szrj 
4500*38fd1498Szrj     case rm_unit:
4501*38fd1498Szrj       result = XCOPYNODE (struct regexp, regexp);
4502*38fd1498Szrj       break;
4503*38fd1498Szrj 
4504*38fd1498Szrj     case rm_repeat:
4505*38fd1498Szrj       result = XCOPYNODE (struct regexp, regexp);
4506*38fd1498Szrj       REGEXP_REPEAT (result)->regexp
4507*38fd1498Szrj         = copy_insn_regexp (REGEXP_REPEAT (regexp)->regexp);
4508*38fd1498Szrj       break;
4509*38fd1498Szrj 
4510*38fd1498Szrj     case rm_sequence:
4511*38fd1498Szrj       result = XCOPYNODEVAR (struct regexp, regexp,
4512*38fd1498Szrj 			     sizeof (struct regexp) + sizeof (regexp_t)
4513*38fd1498Szrj 			     * (REGEXP_SEQUENCE (regexp)->regexps_num - 1));
4514*38fd1498Szrj       for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4515*38fd1498Szrj 	REGEXP_SEQUENCE (result)->regexps [i]
4516*38fd1498Szrj 	  = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4517*38fd1498Szrj       break;
4518*38fd1498Szrj 
4519*38fd1498Szrj     case rm_allof:
4520*38fd1498Szrj       result = XCOPYNODEVAR (struct regexp, regexp,
4521*38fd1498Szrj 			     sizeof (struct regexp) + sizeof (regexp_t)
4522*38fd1498Szrj 			     * (REGEXP_ALLOF (regexp)->regexps_num - 1));
4523*38fd1498Szrj       for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4524*38fd1498Szrj 	REGEXP_ALLOF (result)->regexps [i]
4525*38fd1498Szrj 	  = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4526*38fd1498Szrj       break;
4527*38fd1498Szrj 
4528*38fd1498Szrj     case rm_oneof:
4529*38fd1498Szrj       result = XCOPYNODEVAR (struct regexp, regexp,
4530*38fd1498Szrj 			     sizeof (struct regexp) + sizeof (regexp_t)
4531*38fd1498Szrj 			     * (REGEXP_ONEOF (regexp)->regexps_num - 1));
4532*38fd1498Szrj       for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4533*38fd1498Szrj 	REGEXP_ONEOF (result)->regexps [i]
4534*38fd1498Szrj 	  = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4535*38fd1498Szrj       break;
4536*38fd1498Szrj 
4537*38fd1498Szrj     case rm_nothing:
4538*38fd1498Szrj       result = XCOPYNODE (struct regexp, regexp);
4539*38fd1498Szrj       break;
4540*38fd1498Szrj 
4541*38fd1498Szrj     default:
4542*38fd1498Szrj       gcc_unreachable ();
4543*38fd1498Szrj     }
4544*38fd1498Szrj   return result;
4545*38fd1498Szrj }
4546*38fd1498Szrj 
4547*38fd1498Szrj /* The following variable is set up 1 if a transformation has been
4548*38fd1498Szrj    applied.  */
4549*38fd1498Szrj static int regexp_transformed_p;
4550*38fd1498Szrj 
4551*38fd1498Szrj /* The function makes transformation
4552*38fd1498Szrj    A*N -> A, A, ...  */
4553*38fd1498Szrj static regexp_t
transform_1(regexp_t regexp)4554*38fd1498Szrj transform_1 (regexp_t regexp)
4555*38fd1498Szrj {
4556*38fd1498Szrj   int i;
4557*38fd1498Szrj   int repeat_num;
4558*38fd1498Szrj   regexp_t operand;
4559*38fd1498Szrj   pos_t pos;
4560*38fd1498Szrj 
4561*38fd1498Szrj   if (regexp->mode == rm_repeat)
4562*38fd1498Szrj     {
4563*38fd1498Szrj       repeat_num = REGEXP_REPEAT (regexp)->repeat_num;
4564*38fd1498Szrj       gcc_assert (repeat_num > 1);
4565*38fd1498Szrj       operand = REGEXP_REPEAT (regexp)->regexp;
4566*38fd1498Szrj       pos = regexp->mode;
4567*38fd1498Szrj       regexp = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4568*38fd1498Szrj 			       + sizeof (regexp_t) * (repeat_num - 1));
4569*38fd1498Szrj       regexp->mode = rm_sequence;
4570*38fd1498Szrj       regexp->pos = pos;
4571*38fd1498Szrj       REGEXP_SEQUENCE (regexp)->regexps_num = repeat_num;
4572*38fd1498Szrj       for (i = 0; i < repeat_num; i++)
4573*38fd1498Szrj 	REGEXP_SEQUENCE (regexp)->regexps [i] = copy_insn_regexp (operand);
4574*38fd1498Szrj       regexp_transformed_p = 1;
4575*38fd1498Szrj     }
4576*38fd1498Szrj   return regexp;
4577*38fd1498Szrj }
4578*38fd1498Szrj 
4579*38fd1498Szrj /* The function makes transformations
4580*38fd1498Szrj    ...,(A,B,...),C,... -> ...,A,B,...,C,...
4581*38fd1498Szrj    ...+(A+B+...)+C+... -> ...+A+B+...+C+...
4582*38fd1498Szrj    ...|(A|B|...)|C|... -> ...|A|B|...|C|...  */
4583*38fd1498Szrj static regexp_t
transform_2(regexp_t regexp)4584*38fd1498Szrj transform_2 (regexp_t regexp)
4585*38fd1498Szrj {
4586*38fd1498Szrj   if (regexp->mode == rm_sequence)
4587*38fd1498Szrj     {
4588*38fd1498Szrj       regexp_t sequence = NULL;
4589*38fd1498Szrj       regexp_t result;
4590*38fd1498Szrj       int sequence_index = 0;
4591*38fd1498Szrj       int i, j;
4592*38fd1498Szrj 
4593*38fd1498Szrj       for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4594*38fd1498Szrj 	if (REGEXP_SEQUENCE (regexp)->regexps [i]->mode == rm_sequence)
4595*38fd1498Szrj 	  {
4596*38fd1498Szrj 	    sequence_index = i;
4597*38fd1498Szrj 	    sequence = REGEXP_SEQUENCE (regexp)->regexps [i];
4598*38fd1498Szrj 	    break;
4599*38fd1498Szrj 	  }
4600*38fd1498Szrj       if (i < REGEXP_SEQUENCE (regexp)->regexps_num)
4601*38fd1498Szrj 	{
4602*38fd1498Szrj 	  gcc_assert (REGEXP_SEQUENCE (sequence)->regexps_num > 1
4603*38fd1498Szrj 		      && REGEXP_SEQUENCE (regexp)->regexps_num > 1);
4604*38fd1498Szrj 	  result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4605*38fd1498Szrj 				   + sizeof (regexp_t)
4606*38fd1498Szrj 				   * (REGEXP_SEQUENCE (regexp)->regexps_num
4607*38fd1498Szrj 				      + REGEXP_SEQUENCE (sequence)->regexps_num
4608*38fd1498Szrj 				      - 2));
4609*38fd1498Szrj 	  result->mode = rm_sequence;
4610*38fd1498Szrj 	  result->pos = regexp->pos;
4611*38fd1498Szrj 	  REGEXP_SEQUENCE (result)->regexps_num
4612*38fd1498Szrj             = (REGEXP_SEQUENCE (regexp)->regexps_num
4613*38fd1498Szrj                + REGEXP_SEQUENCE (sequence)->regexps_num - 1);
4614*38fd1498Szrj 	  for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4615*38fd1498Szrj             if (i < sequence_index)
4616*38fd1498Szrj               REGEXP_SEQUENCE (result)->regexps [i]
4617*38fd1498Szrj                 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4618*38fd1498Szrj             else if (i > sequence_index)
4619*38fd1498Szrj               REGEXP_SEQUENCE (result)->regexps
4620*38fd1498Szrj                 [i + REGEXP_SEQUENCE (sequence)->regexps_num - 1]
4621*38fd1498Szrj                 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4622*38fd1498Szrj             else
4623*38fd1498Szrj               for (j = 0; j < REGEXP_SEQUENCE (sequence)->regexps_num; j++)
4624*38fd1498Szrj                 REGEXP_SEQUENCE (result)->regexps [i + j]
4625*38fd1498Szrj                   = copy_insn_regexp (REGEXP_SEQUENCE (sequence)->regexps [j]);
4626*38fd1498Szrj 	  regexp_transformed_p = 1;
4627*38fd1498Szrj 	  regexp = result;
4628*38fd1498Szrj 	}
4629*38fd1498Szrj     }
4630*38fd1498Szrj   else if (regexp->mode == rm_allof)
4631*38fd1498Szrj     {
4632*38fd1498Szrj       regexp_t allof = NULL;
4633*38fd1498Szrj       regexp_t result;
4634*38fd1498Szrj       int allof_index = 0;
4635*38fd1498Szrj       int i, j;
4636*38fd1498Szrj 
4637*38fd1498Szrj       for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4638*38fd1498Szrj 	if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_allof)
4639*38fd1498Szrj 	  {
4640*38fd1498Szrj 	    allof_index = i;
4641*38fd1498Szrj 	    allof = REGEXP_ALLOF (regexp)->regexps [i];
4642*38fd1498Szrj 	    break;
4643*38fd1498Szrj 	  }
4644*38fd1498Szrj       if (i < REGEXP_ALLOF (regexp)->regexps_num)
4645*38fd1498Szrj 	{
4646*38fd1498Szrj 	  gcc_assert (REGEXP_ALLOF (allof)->regexps_num > 1
4647*38fd1498Szrj 		      && REGEXP_ALLOF (regexp)->regexps_num > 1);
4648*38fd1498Szrj 	  result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4649*38fd1498Szrj 				   + sizeof (regexp_t)
4650*38fd1498Szrj 				   * (REGEXP_ALLOF (regexp)->regexps_num
4651*38fd1498Szrj 				      + REGEXP_ALLOF (allof)->regexps_num - 2));
4652*38fd1498Szrj 	  result->mode = rm_allof;
4653*38fd1498Szrj 	  result->pos = regexp->pos;
4654*38fd1498Szrj 	  REGEXP_ALLOF (result)->regexps_num
4655*38fd1498Szrj             = (REGEXP_ALLOF (regexp)->regexps_num
4656*38fd1498Szrj                + REGEXP_ALLOF (allof)->regexps_num - 1);
4657*38fd1498Szrj 	  for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4658*38fd1498Szrj             if (i < allof_index)
4659*38fd1498Szrj               REGEXP_ALLOF (result)->regexps [i]
4660*38fd1498Szrj                 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4661*38fd1498Szrj             else if (i > allof_index)
4662*38fd1498Szrj               REGEXP_ALLOF (result)->regexps
4663*38fd1498Szrj                 [i + REGEXP_ALLOF (allof)->regexps_num - 1]
4664*38fd1498Szrj                 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4665*38fd1498Szrj             else
4666*38fd1498Szrj               for (j = 0; j < REGEXP_ALLOF (allof)->regexps_num; j++)
4667*38fd1498Szrj                 REGEXP_ALLOF (result)->regexps [i + j]
4668*38fd1498Szrj                   = copy_insn_regexp (REGEXP_ALLOF (allof)->regexps [j]);
4669*38fd1498Szrj 	  regexp_transformed_p = 1;
4670*38fd1498Szrj 	  regexp = result;
4671*38fd1498Szrj 	}
4672*38fd1498Szrj     }
4673*38fd1498Szrj   else if (regexp->mode == rm_oneof)
4674*38fd1498Szrj     {
4675*38fd1498Szrj       regexp_t oneof = NULL;
4676*38fd1498Szrj       regexp_t result;
4677*38fd1498Szrj       int oneof_index = 0;
4678*38fd1498Szrj       int i, j;
4679*38fd1498Szrj 
4680*38fd1498Szrj       for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4681*38fd1498Szrj 	if (REGEXP_ONEOF (regexp)->regexps [i]->mode == rm_oneof)
4682*38fd1498Szrj 	  {
4683*38fd1498Szrj 	    oneof_index = i;
4684*38fd1498Szrj 	    oneof = REGEXP_ONEOF (regexp)->regexps [i];
4685*38fd1498Szrj 	    break;
4686*38fd1498Szrj 	  }
4687*38fd1498Szrj       if (i < REGEXP_ONEOF (regexp)->regexps_num)
4688*38fd1498Szrj 	{
4689*38fd1498Szrj 	  gcc_assert (REGEXP_ONEOF (oneof)->regexps_num > 1
4690*38fd1498Szrj 		      && REGEXP_ONEOF (regexp)->regexps_num > 1);
4691*38fd1498Szrj 	  result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4692*38fd1498Szrj 				   + sizeof (regexp_t)
4693*38fd1498Szrj 				   * (REGEXP_ONEOF (regexp)->regexps_num
4694*38fd1498Szrj 				      + REGEXP_ONEOF (oneof)->regexps_num - 2));
4695*38fd1498Szrj 	  result->mode = rm_oneof;
4696*38fd1498Szrj 	  result->pos = regexp->pos;
4697*38fd1498Szrj 	  REGEXP_ONEOF (result)->regexps_num
4698*38fd1498Szrj 	    = (REGEXP_ONEOF (regexp)->regexps_num
4699*38fd1498Szrj                + REGEXP_ONEOF (oneof)->regexps_num - 1);
4700*38fd1498Szrj 	  for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4701*38fd1498Szrj             if (i < oneof_index)
4702*38fd1498Szrj               REGEXP_ONEOF (result)->regexps [i]
4703*38fd1498Szrj                 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4704*38fd1498Szrj             else if (i > oneof_index)
4705*38fd1498Szrj               REGEXP_ONEOF (result)->regexps
4706*38fd1498Szrj                 [i + REGEXP_ONEOF (oneof)->regexps_num - 1]
4707*38fd1498Szrj                 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4708*38fd1498Szrj             else
4709*38fd1498Szrj               for (j = 0; j < REGEXP_ONEOF (oneof)->regexps_num; j++)
4710*38fd1498Szrj                 REGEXP_ONEOF (result)->regexps [i + j]
4711*38fd1498Szrj                   = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [j]);
4712*38fd1498Szrj 	  regexp_transformed_p = 1;
4713*38fd1498Szrj 	  regexp = result;
4714*38fd1498Szrj 	}
4715*38fd1498Szrj     }
4716*38fd1498Szrj   return regexp;
4717*38fd1498Szrj }
4718*38fd1498Szrj 
4719*38fd1498Szrj /* The function makes transformations
4720*38fd1498Szrj    ...,A|B|...,C,... -> (...,A,C,...)|(...,B,C,...)|...
4721*38fd1498Szrj    ...+(A|B|...)+C+... -> (...+A+C+...)|(...+B+C+...)|...
4722*38fd1498Szrj    ...+(A,B,...)+C+... -> (...+A+C+...),B,...
4723*38fd1498Szrj    ...+(A,B,...)+(C,D,...) -> (A+C),(B+D),...  */
4724*38fd1498Szrj static regexp_t
transform_3(regexp_t regexp)4725*38fd1498Szrj transform_3 (regexp_t regexp)
4726*38fd1498Szrj {
4727*38fd1498Szrj   if (regexp->mode == rm_sequence)
4728*38fd1498Szrj     {
4729*38fd1498Szrj       regexp_t oneof = NULL;
4730*38fd1498Szrj       int oneof_index = 0;
4731*38fd1498Szrj       regexp_t result;
4732*38fd1498Szrj       regexp_t sequence;
4733*38fd1498Szrj       int i, j;
4734*38fd1498Szrj 
4735*38fd1498Szrj       for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4736*38fd1498Szrj 	if (REGEXP_SEQUENCE (regexp)->regexps [i]->mode == rm_oneof)
4737*38fd1498Szrj 	  {
4738*38fd1498Szrj 	    oneof_index = i;
4739*38fd1498Szrj 	    oneof = REGEXP_SEQUENCE (regexp)->regexps [i];
4740*38fd1498Szrj 	    break;
4741*38fd1498Szrj 	  }
4742*38fd1498Szrj       if (i < REGEXP_SEQUENCE (regexp)->regexps_num)
4743*38fd1498Szrj 	{
4744*38fd1498Szrj 	  gcc_assert (REGEXP_ONEOF (oneof)->regexps_num > 1
4745*38fd1498Szrj 		      && REGEXP_SEQUENCE (regexp)->regexps_num > 1);
4746*38fd1498Szrj 	  result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4747*38fd1498Szrj 				   + sizeof (regexp_t)
4748*38fd1498Szrj 				   * (REGEXP_ONEOF (oneof)->regexps_num - 1));
4749*38fd1498Szrj 	  result->mode = rm_oneof;
4750*38fd1498Szrj 	  result->pos = regexp->pos;
4751*38fd1498Szrj 	  REGEXP_ONEOF (result)->regexps_num
4752*38fd1498Szrj 	    = REGEXP_ONEOF (oneof)->regexps_num;
4753*38fd1498Szrj 	  for (i = 0; i < REGEXP_ONEOF (result)->regexps_num; i++)
4754*38fd1498Szrj 	    {
4755*38fd1498Szrj 	      sequence
4756*38fd1498Szrj                 = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4757*38fd1498Szrj 				  + sizeof (regexp_t)
4758*38fd1498Szrj 				  * (REGEXP_SEQUENCE (regexp)->regexps_num - 1));
4759*38fd1498Szrj 	      sequence->mode = rm_sequence;
4760*38fd1498Szrj 	      sequence->pos = regexp->pos;
4761*38fd1498Szrj 	      REGEXP_SEQUENCE (sequence)->regexps_num
4762*38fd1498Szrj                 = REGEXP_SEQUENCE (regexp)->regexps_num;
4763*38fd1498Szrj               REGEXP_ONEOF (result)->regexps [i] = sequence;
4764*38fd1498Szrj 	      for (j = 0; j < REGEXP_SEQUENCE (sequence)->regexps_num; j++)
4765*38fd1498Szrj 		if (j != oneof_index)
4766*38fd1498Szrj 		  REGEXP_SEQUENCE (sequence)->regexps [j]
4767*38fd1498Szrj 		    = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [j]);
4768*38fd1498Szrj 		else
4769*38fd1498Szrj 		  REGEXP_SEQUENCE (sequence)->regexps [j]
4770*38fd1498Szrj 		    = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [i]);
4771*38fd1498Szrj 	    }
4772*38fd1498Szrj 	  regexp_transformed_p = 1;
4773*38fd1498Szrj 	  regexp = result;
4774*38fd1498Szrj 	}
4775*38fd1498Szrj     }
4776*38fd1498Szrj   else if (regexp->mode == rm_allof)
4777*38fd1498Szrj     {
4778*38fd1498Szrj       regexp_t oneof = NULL;
4779*38fd1498Szrj       regexp_t seq;
4780*38fd1498Szrj       int oneof_index = 0;
4781*38fd1498Szrj       int max_seq_length, allof_length;
4782*38fd1498Szrj       regexp_t result;
4783*38fd1498Szrj       regexp_t allof = NULL;
4784*38fd1498Szrj       regexp_t allof_op = NULL;
4785*38fd1498Szrj       int i, j;
4786*38fd1498Szrj 
4787*38fd1498Szrj       for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4788*38fd1498Szrj 	if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_oneof)
4789*38fd1498Szrj 	  {
4790*38fd1498Szrj 	    oneof_index = i;
4791*38fd1498Szrj 	    oneof = REGEXP_ALLOF (regexp)->regexps [i];
4792*38fd1498Szrj 	    break;
4793*38fd1498Szrj 	  }
4794*38fd1498Szrj       if (i < REGEXP_ALLOF (regexp)->regexps_num)
4795*38fd1498Szrj 	{
4796*38fd1498Szrj 	  gcc_assert (REGEXP_ONEOF (oneof)->regexps_num > 1
4797*38fd1498Szrj 		      && REGEXP_ALLOF (regexp)->regexps_num > 1);
4798*38fd1498Szrj 	  result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4799*38fd1498Szrj 				   + sizeof (regexp_t)
4800*38fd1498Szrj 				   * (REGEXP_ONEOF (oneof)->regexps_num - 1));
4801*38fd1498Szrj 	  result->mode = rm_oneof;
4802*38fd1498Szrj 	  result->pos = regexp->pos;
4803*38fd1498Szrj 	  REGEXP_ONEOF (result)->regexps_num
4804*38fd1498Szrj 	    = REGEXP_ONEOF (oneof)->regexps_num;
4805*38fd1498Szrj 	  for (i = 0; i < REGEXP_ONEOF (result)->regexps_num; i++)
4806*38fd1498Szrj 	    {
4807*38fd1498Szrj 	      allof
4808*38fd1498Szrj 		= XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4809*38fd1498Szrj 				  + sizeof (regexp_t)
4810*38fd1498Szrj 				  * (REGEXP_ALLOF (regexp)->regexps_num - 1));
4811*38fd1498Szrj 	      allof->mode = rm_allof;
4812*38fd1498Szrj 	      allof->pos = regexp->pos;
4813*38fd1498Szrj 	      REGEXP_ALLOF (allof)->regexps_num
4814*38fd1498Szrj                 = REGEXP_ALLOF (regexp)->regexps_num;
4815*38fd1498Szrj               REGEXP_ONEOF (result)->regexps [i] = allof;
4816*38fd1498Szrj 	      for (j = 0; j < REGEXP_ALLOF (allof)->regexps_num; j++)
4817*38fd1498Szrj 		if (j != oneof_index)
4818*38fd1498Szrj 		  REGEXP_ALLOF (allof)->regexps [j]
4819*38fd1498Szrj 		    = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [j]);
4820*38fd1498Szrj 		else
4821*38fd1498Szrj 		  REGEXP_ALLOF (allof)->regexps [j]
4822*38fd1498Szrj 		    = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [i]);
4823*38fd1498Szrj 	    }
4824*38fd1498Szrj 	  regexp_transformed_p = 1;
4825*38fd1498Szrj 	  regexp = result;
4826*38fd1498Szrj 	}
4827*38fd1498Szrj       max_seq_length = 0;
4828*38fd1498Szrj       if (regexp->mode == rm_allof)
4829*38fd1498Szrj 	for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4830*38fd1498Szrj 	  {
4831*38fd1498Szrj 	    switch (REGEXP_ALLOF (regexp)->regexps [i]->mode)
4832*38fd1498Szrj 	      {
4833*38fd1498Szrj 	      case rm_sequence:
4834*38fd1498Szrj 		seq = REGEXP_ALLOF (regexp)->regexps [i];
4835*38fd1498Szrj 		if (max_seq_length < REGEXP_SEQUENCE (seq)->regexps_num)
4836*38fd1498Szrj 		  max_seq_length = REGEXP_SEQUENCE (seq)->regexps_num;
4837*38fd1498Szrj 		break;
4838*38fd1498Szrj 
4839*38fd1498Szrj 	      case rm_unit:
4840*38fd1498Szrj 	      case rm_nothing:
4841*38fd1498Szrj 		break;
4842*38fd1498Szrj 
4843*38fd1498Szrj 	      default:
4844*38fd1498Szrj 		max_seq_length = 0;
4845*38fd1498Szrj 		goto break_for;
4846*38fd1498Szrj 	      }
4847*38fd1498Szrj 	  }
4848*38fd1498Szrj     break_for:
4849*38fd1498Szrj       if (max_seq_length != 0)
4850*38fd1498Szrj 	{
4851*38fd1498Szrj 	  gcc_assert (max_seq_length != 1
4852*38fd1498Szrj 		      && REGEXP_ALLOF (regexp)->regexps_num > 1);
4853*38fd1498Szrj 	  result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4854*38fd1498Szrj 				   + sizeof (regexp_t) * (max_seq_length - 1));
4855*38fd1498Szrj 	  result->mode = rm_sequence;
4856*38fd1498Szrj 	  result->pos = regexp->pos;
4857*38fd1498Szrj 	  REGEXP_SEQUENCE (result)->regexps_num = max_seq_length;
4858*38fd1498Szrj 	  for (i = 0; i < max_seq_length; i++)
4859*38fd1498Szrj 	    {
4860*38fd1498Szrj 	      allof_length = 0;
4861*38fd1498Szrj 	      for (j = 0; j < REGEXP_ALLOF (regexp)->regexps_num; j++)
4862*38fd1498Szrj 		switch (REGEXP_ALLOF (regexp)->regexps [j]->mode)
4863*38fd1498Szrj 		  {
4864*38fd1498Szrj 		  case rm_sequence:
4865*38fd1498Szrj 		    if (i < (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4866*38fd1498Szrj 					      ->regexps [j])->regexps_num))
4867*38fd1498Szrj 		      {
4868*38fd1498Szrj 			allof_op
4869*38fd1498Szrj 			  = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4870*38fd1498Szrj 					      ->regexps [j])
4871*38fd1498Szrj 			     ->regexps [i]);
4872*38fd1498Szrj 			allof_length++;
4873*38fd1498Szrj 		      }
4874*38fd1498Szrj 		    break;
4875*38fd1498Szrj 		  case rm_unit:
4876*38fd1498Szrj 		  case rm_nothing:
4877*38fd1498Szrj 		    if (i == 0)
4878*38fd1498Szrj 		      {
4879*38fd1498Szrj 			allof_op = REGEXP_ALLOF (regexp)->regexps [j];
4880*38fd1498Szrj 			allof_length++;
4881*38fd1498Szrj 		      }
4882*38fd1498Szrj 		    break;
4883*38fd1498Szrj 		  default:
4884*38fd1498Szrj 		    break;
4885*38fd1498Szrj 		  }
4886*38fd1498Szrj 
4887*38fd1498Szrj 	      if (allof_length == 1)
4888*38fd1498Szrj 		REGEXP_SEQUENCE (result)->regexps [i] = allof_op;
4889*38fd1498Szrj 	      else
4890*38fd1498Szrj 		{
4891*38fd1498Szrj 		  allof = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4892*38fd1498Szrj 					  + sizeof (regexp_t)
4893*38fd1498Szrj 					  * (allof_length - 1));
4894*38fd1498Szrj 		  allof->mode = rm_allof;
4895*38fd1498Szrj 		  allof->pos = regexp->pos;
4896*38fd1498Szrj 		  REGEXP_ALLOF (allof)->regexps_num = allof_length;
4897*38fd1498Szrj 		  REGEXP_SEQUENCE (result)->regexps [i] = allof;
4898*38fd1498Szrj 		  allof_length = 0;
4899*38fd1498Szrj 		  for (j = 0; j < REGEXP_ALLOF (regexp)->regexps_num; j++)
4900*38fd1498Szrj 		    if (REGEXP_ALLOF (regexp)->regexps [j]->mode == rm_sequence
4901*38fd1498Szrj 			&& (i <
4902*38fd1498Szrj 			    (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4903*38fd1498Szrj 					      ->regexps [j])->regexps_num)))
4904*38fd1498Szrj 		      {
4905*38fd1498Szrj 			allof_op = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4906*38fd1498Szrj 						     ->regexps [j])
4907*38fd1498Szrj 				    ->regexps [i]);
4908*38fd1498Szrj 			REGEXP_ALLOF (allof)->regexps [allof_length]
4909*38fd1498Szrj 			  = allof_op;
4910*38fd1498Szrj 			allof_length++;
4911*38fd1498Szrj 		      }
4912*38fd1498Szrj 		    else if (i == 0
4913*38fd1498Szrj 			     && (REGEXP_ALLOF (regexp)->regexps [j]->mode
4914*38fd1498Szrj 				 == rm_unit
4915*38fd1498Szrj 				 || (REGEXP_ALLOF (regexp)->regexps [j]->mode
4916*38fd1498Szrj 				     == rm_nothing)))
4917*38fd1498Szrj 		      {
4918*38fd1498Szrj 			allof_op = REGEXP_ALLOF (regexp)->regexps [j];
4919*38fd1498Szrj 			REGEXP_ALLOF (allof)->regexps [allof_length]
4920*38fd1498Szrj 			  = allof_op;
4921*38fd1498Szrj 			allof_length++;
4922*38fd1498Szrj 		      }
4923*38fd1498Szrj 		}
4924*38fd1498Szrj 	    }
4925*38fd1498Szrj 	  regexp_transformed_p = 1;
4926*38fd1498Szrj 	  regexp = result;
4927*38fd1498Szrj 	}
4928*38fd1498Szrj     }
4929*38fd1498Szrj   return regexp;
4930*38fd1498Szrj }
4931*38fd1498Szrj 
4932*38fd1498Szrj /* The function traverses IR of reservation and applies transformations
4933*38fd1498Szrj    implemented by FUNC.  */
4934*38fd1498Szrj static regexp_t
regexp_transform_func(regexp_t regexp,regexp_t (* func)(regexp_t regexp))4935*38fd1498Szrj regexp_transform_func (regexp_t regexp, regexp_t (*func) (regexp_t regexp))
4936*38fd1498Szrj {
4937*38fd1498Szrj   int i;
4938*38fd1498Szrj 
4939*38fd1498Szrj   switch (regexp->mode)
4940*38fd1498Szrj     {
4941*38fd1498Szrj     case rm_sequence:
4942*38fd1498Szrj       for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4943*38fd1498Szrj 	REGEXP_SEQUENCE (regexp)->regexps [i]
4944*38fd1498Szrj 	  = regexp_transform_func (REGEXP_SEQUENCE (regexp)->regexps [i],
4945*38fd1498Szrj 				   func);
4946*38fd1498Szrj       break;
4947*38fd1498Szrj 
4948*38fd1498Szrj     case rm_allof:
4949*38fd1498Szrj       for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4950*38fd1498Szrj 	REGEXP_ALLOF (regexp)->regexps [i]
4951*38fd1498Szrj 	  = regexp_transform_func (REGEXP_ALLOF (regexp)->regexps [i], func);
4952*38fd1498Szrj       break;
4953*38fd1498Szrj 
4954*38fd1498Szrj     case rm_oneof:
4955*38fd1498Szrj       for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4956*38fd1498Szrj 	REGEXP_ONEOF (regexp)->regexps [i]
4957*38fd1498Szrj 	  = regexp_transform_func (REGEXP_ONEOF (regexp)->regexps [i], func);
4958*38fd1498Szrj       break;
4959*38fd1498Szrj 
4960*38fd1498Szrj     case rm_repeat:
4961*38fd1498Szrj       REGEXP_REPEAT (regexp)->regexp
4962*38fd1498Szrj 	= regexp_transform_func (REGEXP_REPEAT (regexp)->regexp, func);
4963*38fd1498Szrj       break;
4964*38fd1498Szrj 
4965*38fd1498Szrj     case rm_nothing:
4966*38fd1498Szrj     case rm_unit:
4967*38fd1498Szrj       break;
4968*38fd1498Szrj 
4969*38fd1498Szrj     default:
4970*38fd1498Szrj       gcc_unreachable ();
4971*38fd1498Szrj     }
4972*38fd1498Szrj   return (*func) (regexp);
4973*38fd1498Szrj }
4974*38fd1498Szrj 
4975*38fd1498Szrj /* The function applies all transformations for IR representation of
4976*38fd1498Szrj    reservation REGEXP.  */
4977*38fd1498Szrj static regexp_t
transform_regexp(regexp_t regexp)4978*38fd1498Szrj transform_regexp (regexp_t regexp)
4979*38fd1498Szrj {
4980*38fd1498Szrj   regexp = regexp_transform_func (regexp, transform_1);
4981*38fd1498Szrj   do
4982*38fd1498Szrj     {
4983*38fd1498Szrj       regexp_transformed_p = 0;
4984*38fd1498Szrj       regexp = regexp_transform_func (regexp, transform_2);
4985*38fd1498Szrj       regexp = regexp_transform_func (regexp, transform_3);
4986*38fd1498Szrj     }
4987*38fd1498Szrj   while (regexp_transformed_p);
4988*38fd1498Szrj   return regexp;
4989*38fd1498Szrj }
4990*38fd1498Szrj 
4991*38fd1498Szrj /* The function applies all transformations for reservations of all
4992*38fd1498Szrj    insn declarations.  */
4993*38fd1498Szrj static void
transform_insn_regexps(void)4994*38fd1498Szrj transform_insn_regexps (void)
4995*38fd1498Szrj {
4996*38fd1498Szrj   decl_t decl;
4997*38fd1498Szrj   int i;
4998*38fd1498Szrj 
4999*38fd1498Szrj   transform_time = create_ticker ();
5000*38fd1498Szrj   add_advance_cycle_insn_decl ();
5001*38fd1498Szrj   if (collapse_flag)
5002*38fd1498Szrj     add_collapse_ndfa_insn_decl ();
5003*38fd1498Szrj   if (progress_flag)
5004*38fd1498Szrj     fprintf (stderr, "Reservation transformation...");
5005*38fd1498Szrj   for (i = 0; i < description->normal_decls_num; i++)
5006*38fd1498Szrj     {
5007*38fd1498Szrj       decl = description->decls [i];
5008*38fd1498Szrj       if (decl->mode == dm_insn_reserv)
5009*38fd1498Szrj 	DECL_INSN_RESERV (decl)->transformed_regexp
5010*38fd1498Szrj 	  = transform_regexp (copy_insn_regexp
5011*38fd1498Szrj 			      (DECL_INSN_RESERV (decl)->regexp));
5012*38fd1498Szrj     }
5013*38fd1498Szrj   if (progress_flag)
5014*38fd1498Szrj     fprintf (stderr, "done\n");
5015*38fd1498Szrj   ticker_off (&transform_time);
5016*38fd1498Szrj }
5017*38fd1498Szrj 
5018*38fd1498Szrj 
5019*38fd1498Szrj 
5020*38fd1498Szrj /* The following variable value is TRUE if the first annotated message
5021*38fd1498Szrj    about units to automata distribution has been output.  */
5022*38fd1498Szrj static int annotation_message_reported_p;
5023*38fd1498Szrj 
5024*38fd1498Szrj /* The vector contains all decls which are automata.  */
5025*38fd1498Szrj static vec<decl_t> automaton_decls;
5026*38fd1498Szrj 
5027*38fd1498Szrj /* The following structure describes usage of a unit in a reservation.  */
5028*38fd1498Szrj struct unit_usage
5029*38fd1498Szrj {
5030*38fd1498Szrj   unit_decl_t unit_decl;
5031*38fd1498Szrj   /* The following forms a list of units used on the same cycle in the
5032*38fd1498Szrj      same alternative.  The list is ordered by the correspdoning unit
5033*38fd1498Szrj      declarations and there is no unit declaration duplication in the
5034*38fd1498Szrj      list.  */
5035*38fd1498Szrj   struct unit_usage *next;
5036*38fd1498Szrj };
5037*38fd1498Szrj typedef struct unit_usage *unit_usage_t;
5038*38fd1498Szrj 
5039*38fd1498Szrj 
5040*38fd1498Szrj /* Obstack for unit_usage structures.  */
5041*38fd1498Szrj static struct obstack unit_usages;
5042*38fd1498Szrj 
5043*38fd1498Szrj /* VLA for representation of array of pointers to unit usage
5044*38fd1498Szrj    structures.  There is an element for each combination of
5045*38fd1498Szrj    (alternative number, cycle).  Unit usages on given cycle in
5046*38fd1498Szrj    alternative with given number are referred through element with
5047*38fd1498Szrj    index equals to the cycle * number of all alternatives in the
5048*38fd1498Szrj    regexp + the alternative number.  */
5049*38fd1498Szrj static vec<unit_usage_t> cycle_alt_unit_usages;
5050*38fd1498Szrj 
5051*38fd1498Szrj /* The following function creates the structure unit_usage for UNIT on
5052*38fd1498Szrj    CYCLE in REGEXP alternative with ALT_NUM.  The structure is made
5053*38fd1498Szrj    accessed through cycle_alt_unit_usages.  */
5054*38fd1498Szrj static void
store_alt_unit_usage(regexp_t regexp,regexp_t unit,int cycle,int alt_num)5055*38fd1498Szrj store_alt_unit_usage (regexp_t regexp, regexp_t unit, int cycle,
5056*38fd1498Szrj 		      int alt_num)
5057*38fd1498Szrj {
5058*38fd1498Szrj   size_t length;
5059*38fd1498Szrj   unit_decl_t unit_decl;
5060*38fd1498Szrj   unit_usage_t unit_usage_ptr, curr, prev;
5061*38fd1498Szrj   int index;
5062*38fd1498Szrj 
5063*38fd1498Szrj   gcc_assert (regexp && regexp->mode == rm_oneof
5064*38fd1498Szrj 	      && alt_num < REGEXP_ONEOF (regexp)->regexps_num);
5065*38fd1498Szrj   unit_decl = REGEXP_UNIT (unit)->unit_decl;
5066*38fd1498Szrj 
5067*38fd1498Szrj   length = (cycle + 1) * REGEXP_ONEOF (regexp)->regexps_num;
5068*38fd1498Szrj   while (cycle_alt_unit_usages.length () < length)
5069*38fd1498Szrj     cycle_alt_unit_usages.safe_push (NULL);
5070*38fd1498Szrj 
5071*38fd1498Szrj   index = cycle * REGEXP_ONEOF (regexp)->regexps_num + alt_num;
5072*38fd1498Szrj   prev = NULL;
5073*38fd1498Szrj   for (curr = cycle_alt_unit_usages[index];
5074*38fd1498Szrj        curr != NULL;
5075*38fd1498Szrj        prev = curr, curr = curr->next)
5076*38fd1498Szrj     if (curr->unit_decl >= unit_decl)
5077*38fd1498Szrj       break;
5078*38fd1498Szrj   if (curr != NULL && curr->unit_decl == unit_decl)
5079*38fd1498Szrj     return;
5080*38fd1498Szrj   obstack_blank (&unit_usages, sizeof (struct unit_usage));
5081*38fd1498Szrj   unit_usage_ptr = (struct unit_usage *) obstack_base (&unit_usages);
5082*38fd1498Szrj   obstack_finish (&unit_usages);
5083*38fd1498Szrj   unit_usage_ptr->unit_decl = unit_decl;
5084*38fd1498Szrj   unit_decl->last_distribution_check_cycle = -1; /* undefined */
5085*38fd1498Szrj   unit_usage_ptr->next = curr;
5086*38fd1498Szrj   if (prev == NULL)
5087*38fd1498Szrj     cycle_alt_unit_usages[index] = unit_usage_ptr;
5088*38fd1498Szrj   else
5089*38fd1498Szrj     prev->next = unit_usage_ptr;
5090*38fd1498Szrj }
5091*38fd1498Szrj 
5092*38fd1498Szrj /* Return true if unit UNIT_DECL is present on the LIST.  */
5093*38fd1498Szrj static bool
unit_present_on_list_p(unit_usage_t list,unit_decl_t unit_decl)5094*38fd1498Szrj unit_present_on_list_p (unit_usage_t list, unit_decl_t unit_decl)
5095*38fd1498Szrj {
5096*38fd1498Szrj   while (list != NULL)
5097*38fd1498Szrj     {
5098*38fd1498Szrj       if (list->unit_decl == unit_decl)
5099*38fd1498Szrj 	return true;
5100*38fd1498Szrj       list = list->next;
5101*38fd1498Szrj     }
5102*38fd1498Szrj   return false;
5103*38fd1498Szrj }
5104*38fd1498Szrj 
5105*38fd1498Szrj /* The function returns true if reservations of alternatives ALT1 and
5106*38fd1498Szrj    ALT2 are equal after excluding reservations of units of
5107*38fd1498Szrj    EXCLUDED_AUTOMATON_DECL.  */
5108*38fd1498Szrj static bool
equal_alternatives_p(int alt1,int alt2,int n_alts,struct automaton_decl * excluded_automaton_decl)5109*38fd1498Szrj equal_alternatives_p (int alt1, int alt2, int n_alts,
5110*38fd1498Szrj 		      struct automaton_decl *excluded_automaton_decl)
5111*38fd1498Szrj {
5112*38fd1498Szrj   int i;
5113*38fd1498Szrj   unit_usage_t list1, list2;
5114*38fd1498Szrj 
5115*38fd1498Szrj   for (i = 0;
5116*38fd1498Szrj        i < (int) cycle_alt_unit_usages.length ();
5117*38fd1498Szrj        i += n_alts)
5118*38fd1498Szrj     {
5119*38fd1498Szrj       for (list1 = cycle_alt_unit_usages[i + alt1],
5120*38fd1498Szrj 	     list2 = cycle_alt_unit_usages[i + alt2];;
5121*38fd1498Szrj 	   list1 = list1->next, list2 = list2->next)
5122*38fd1498Szrj 	{
5123*38fd1498Szrj 	  while (list1 != NULL
5124*38fd1498Szrj 		 && list1->unit_decl->automaton_decl == excluded_automaton_decl)
5125*38fd1498Szrj 	    list1 = list1->next;
5126*38fd1498Szrj 	  while (list2 != NULL
5127*38fd1498Szrj 		 && list2->unit_decl->automaton_decl == excluded_automaton_decl)
5128*38fd1498Szrj 	    list2 = list2->next;
5129*38fd1498Szrj 	  if (list1 == NULL || list2 == NULL)
5130*38fd1498Szrj 	    {
5131*38fd1498Szrj 	      if (list1 != list2)
5132*38fd1498Szrj 		return false;
5133*38fd1498Szrj 	      else
5134*38fd1498Szrj 		break;
5135*38fd1498Szrj 	    }
5136*38fd1498Szrj 	  if (list1->unit_decl != list2->unit_decl)
5137*38fd1498Szrj 	    return false;
5138*38fd1498Szrj 	}
5139*38fd1498Szrj     }
5140*38fd1498Szrj   return true;
5141*38fd1498Szrj }
5142*38fd1498Szrj 
5143*38fd1498Szrj 
5144*38fd1498Szrj /* The function processes given REGEXP to find units with the wrong
5145*38fd1498Szrj    distribution.  */
5146*38fd1498Szrj static void
check_regexp_units_distribution(const char * insn_reserv_name,regexp_t regexp)5147*38fd1498Szrj check_regexp_units_distribution (const char *insn_reserv_name,
5148*38fd1498Szrj 				 regexp_t regexp)
5149*38fd1498Szrj {
5150*38fd1498Szrj   int i, j, k, cycle, start, n_alts, alt, alt2;
5151*38fd1498Szrj   bool annotation_reservation_message_reported_p;
5152*38fd1498Szrj   regexp_t seq, allof, unit;
5153*38fd1498Szrj   struct unit_usage *unit_usage_ptr;
5154*38fd1498Szrj 
5155*38fd1498Szrj   if (regexp == NULL || regexp->mode != rm_oneof)
5156*38fd1498Szrj     return;
5157*38fd1498Szrj   /* Store all unit usages in the regexp:  */
5158*38fd1498Szrj   obstack_init (&unit_usages);
5159*38fd1498Szrj   cycle_alt_unit_usages.create (10);
5160*38fd1498Szrj 
5161*38fd1498Szrj   for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
5162*38fd1498Szrj     {
5163*38fd1498Szrj       seq = REGEXP_ONEOF (regexp)->regexps [i];
5164*38fd1498Szrj       switch (seq->mode)
5165*38fd1498Szrj 	{
5166*38fd1498Szrj 	case rm_sequence:
5167*38fd1498Szrj 	  for (j = 0; j < REGEXP_SEQUENCE (seq)->regexps_num; j++)
5168*38fd1498Szrj 	    {
5169*38fd1498Szrj 	      allof = REGEXP_SEQUENCE (seq)->regexps [j];
5170*38fd1498Szrj 	      switch (allof->mode)
5171*38fd1498Szrj 		{
5172*38fd1498Szrj 		case rm_allof:
5173*38fd1498Szrj 		  for (k = 0; k < REGEXP_ALLOF (allof)->regexps_num; k++)
5174*38fd1498Szrj 		    {
5175*38fd1498Szrj 		      unit = REGEXP_ALLOF (allof)->regexps [k];
5176*38fd1498Szrj 		      if (unit->mode == rm_unit)
5177*38fd1498Szrj 			store_alt_unit_usage (regexp, unit, j, i);
5178*38fd1498Szrj 		      else
5179*38fd1498Szrj 			gcc_assert (unit->mode == rm_nothing);
5180*38fd1498Szrj 		    }
5181*38fd1498Szrj 		  break;
5182*38fd1498Szrj 
5183*38fd1498Szrj 		case rm_unit:
5184*38fd1498Szrj 		  store_alt_unit_usage (regexp, allof, j, i);
5185*38fd1498Szrj 		  break;
5186*38fd1498Szrj 
5187*38fd1498Szrj 		case rm_nothing:
5188*38fd1498Szrj 		  break;
5189*38fd1498Szrj 
5190*38fd1498Szrj 		default:
5191*38fd1498Szrj 		  gcc_unreachable ();
5192*38fd1498Szrj 		}
5193*38fd1498Szrj 	    }
5194*38fd1498Szrj 	  break;
5195*38fd1498Szrj 
5196*38fd1498Szrj 	case rm_allof:
5197*38fd1498Szrj 	  for (k = 0; k < REGEXP_ALLOF (seq)->regexps_num; k++)
5198*38fd1498Szrj 	    {
5199*38fd1498Szrj 	      unit = REGEXP_ALLOF (seq)->regexps [k];
5200*38fd1498Szrj 	      switch (unit->mode)
5201*38fd1498Szrj 		{
5202*38fd1498Szrj 		case rm_unit:
5203*38fd1498Szrj 		  store_alt_unit_usage (regexp, unit, 0, i);
5204*38fd1498Szrj 		  break;
5205*38fd1498Szrj 
5206*38fd1498Szrj 		case rm_nothing:
5207*38fd1498Szrj 		  break;
5208*38fd1498Szrj 
5209*38fd1498Szrj 		default:
5210*38fd1498Szrj 		  gcc_unreachable ();
5211*38fd1498Szrj 		}
5212*38fd1498Szrj 	    }
5213*38fd1498Szrj 	  break;
5214*38fd1498Szrj 
5215*38fd1498Szrj 	case rm_unit:
5216*38fd1498Szrj 	  store_alt_unit_usage (regexp, seq, 0, i);
5217*38fd1498Szrj 	  break;
5218*38fd1498Szrj 
5219*38fd1498Szrj 	case rm_nothing:
5220*38fd1498Szrj 	  break;
5221*38fd1498Szrj 
5222*38fd1498Szrj 	default:
5223*38fd1498Szrj 	  gcc_unreachable ();
5224*38fd1498Szrj 	}
5225*38fd1498Szrj     }
5226*38fd1498Szrj   /* Check distribution:  */
5227*38fd1498Szrj   for (i = 0; i < (int) cycle_alt_unit_usages.length (); i++)
5228*38fd1498Szrj     for (unit_usage_ptr = cycle_alt_unit_usages[i];
5229*38fd1498Szrj 	 unit_usage_ptr != NULL;
5230*38fd1498Szrj 	 unit_usage_ptr = unit_usage_ptr->next)
5231*38fd1498Szrj       unit_usage_ptr->unit_decl->last_distribution_check_cycle = -1;
5232*38fd1498Szrj   n_alts = REGEXP_ONEOF (regexp)->regexps_num;
5233*38fd1498Szrj   auto_vec<int> marked (n_alts);
5234*38fd1498Szrj   for (i = 0; i < n_alts; i++)
5235*38fd1498Szrj     marked.safe_push (0);
5236*38fd1498Szrj   annotation_reservation_message_reported_p = false;
5237*38fd1498Szrj   for (i = 0; i < (int) cycle_alt_unit_usages.length (); i++)
5238*38fd1498Szrj     {
5239*38fd1498Szrj       cycle = i / n_alts;
5240*38fd1498Szrj       start = cycle * n_alts;
5241*38fd1498Szrj       for (unit_usage_ptr = cycle_alt_unit_usages[i];
5242*38fd1498Szrj 	   unit_usage_ptr != NULL;
5243*38fd1498Szrj 	   unit_usage_ptr = unit_usage_ptr->next)
5244*38fd1498Szrj 	{
5245*38fd1498Szrj 	  if (unit_usage_ptr->unit_decl->last_distribution_check_cycle == cycle)
5246*38fd1498Szrj 	    continue;
5247*38fd1498Szrj 	  unit_usage_ptr->unit_decl->last_distribution_check_cycle = cycle;
5248*38fd1498Szrj 	  for (alt = 0; alt < n_alts; alt++)
5249*38fd1498Szrj 	    if (! unit_present_on_list_p (cycle_alt_unit_usages[start + alt],
5250*38fd1498Szrj 					  unit_usage_ptr->unit_decl))
5251*38fd1498Szrj 	      break;
5252*38fd1498Szrj 	  if (alt >= n_alts)
5253*38fd1498Szrj 	    continue;
5254*38fd1498Szrj 	  memset (marked.address (), 0, n_alts * sizeof (int));
5255*38fd1498Szrj 	  for (alt = 0; alt < n_alts; alt++)
5256*38fd1498Szrj 	    {
5257*38fd1498Szrj 	      if (! unit_present_on_list_p (cycle_alt_unit_usages[start + alt],
5258*38fd1498Szrj 					    unit_usage_ptr->unit_decl))
5259*38fd1498Szrj 		continue;
5260*38fd1498Szrj 	      for (j = 0;
5261*38fd1498Szrj 		   j < (int) cycle_alt_unit_usages.length ();
5262*38fd1498Szrj 		   j++)
5263*38fd1498Szrj 		{
5264*38fd1498Szrj 		  alt2 = j % n_alts;
5265*38fd1498Szrj 		  if (! unit_present_on_list_p
5266*38fd1498Szrj 		        (cycle_alt_unit_usages[start + alt2],
5267*38fd1498Szrj 			 unit_usage_ptr->unit_decl)
5268*38fd1498Szrj 		      && equal_alternatives_p (alt, alt2, n_alts,
5269*38fd1498Szrj 					       unit_usage_ptr
5270*38fd1498Szrj 					       ->unit_decl->automaton_decl))
5271*38fd1498Szrj 		    {
5272*38fd1498Szrj 		      marked[alt] = 1;
5273*38fd1498Szrj 		      marked[alt2] = 1;
5274*38fd1498Szrj 		    }
5275*38fd1498Szrj 		}
5276*38fd1498Szrj 	    }
5277*38fd1498Szrj 	  for (alt = 0; alt < n_alts && marked[alt]; alt++)
5278*38fd1498Szrj 	    ;
5279*38fd1498Szrj 	  if (alt < n_alts && 0)
5280*38fd1498Szrj 	    {
5281*38fd1498Szrj 	      if (! annotation_message_reported_p)
5282*38fd1498Szrj 		{
5283*38fd1498Szrj 		  fprintf (stderr, "\n");
5284*38fd1498Szrj 		  error ("The following units do not satisfy units-automata distribution rule");
5285*38fd1498Szrj 		  error ("(Unit presence on one alt and its absence on other alt\n");
5286*38fd1498Szrj 		  error (" result in different other automata reservations)");
5287*38fd1498Szrj 		  annotation_message_reported_p = TRUE;
5288*38fd1498Szrj 		}
5289*38fd1498Szrj 	      if (! annotation_reservation_message_reported_p)
5290*38fd1498Szrj 		{
5291*38fd1498Szrj 		  error ("Reserv %s:", insn_reserv_name);
5292*38fd1498Szrj 		  annotation_reservation_message_reported_p = true;
5293*38fd1498Szrj 		}
5294*38fd1498Szrj 	      error ("  Unit %s, cycle %d, alt %d, another alt %d",
5295*38fd1498Szrj 		     unit_usage_ptr->unit_decl->name, cycle, i % n_alts, alt);
5296*38fd1498Szrj 	    }
5297*38fd1498Szrj 	}
5298*38fd1498Szrj     }
5299*38fd1498Szrj   cycle_alt_unit_usages.release ();
5300*38fd1498Szrj   obstack_free (&unit_usages, NULL);
5301*38fd1498Szrj }
5302*38fd1498Szrj 
5303*38fd1498Szrj /* The function finds units which violates units to automata
5304*38fd1498Szrj    distribution rule.  If the units exist, report about them.  */
5305*38fd1498Szrj static void
check_unit_distributions_to_automata(void)5306*38fd1498Szrj check_unit_distributions_to_automata (void)
5307*38fd1498Szrj {
5308*38fd1498Szrj   decl_t decl;
5309*38fd1498Szrj   int i;
5310*38fd1498Szrj 
5311*38fd1498Szrj   if (progress_flag)
5312*38fd1498Szrj     fprintf (stderr, "Check unit distributions to automata...");
5313*38fd1498Szrj   automaton_decls.create (0);
5314*38fd1498Szrj   for (i = 0; i < description->decls_num; i++)
5315*38fd1498Szrj     {
5316*38fd1498Szrj       decl = description->decls [i];
5317*38fd1498Szrj       if (decl->mode == dm_automaton)
5318*38fd1498Szrj 	automaton_decls.safe_push (decl);
5319*38fd1498Szrj     }
5320*38fd1498Szrj   if (automaton_decls.length () > 1)
5321*38fd1498Szrj     {
5322*38fd1498Szrj       annotation_message_reported_p = FALSE;
5323*38fd1498Szrj       for (i = 0; i < description->decls_num; i++)
5324*38fd1498Szrj 	{
5325*38fd1498Szrj 	  decl = description->decls [i];
5326*38fd1498Szrj 	  if (decl->mode == dm_insn_reserv)
5327*38fd1498Szrj 	    check_regexp_units_distribution
5328*38fd1498Szrj 	      (DECL_INSN_RESERV (decl)->name,
5329*38fd1498Szrj 	       DECL_INSN_RESERV (decl)->transformed_regexp);
5330*38fd1498Szrj 	}
5331*38fd1498Szrj     }
5332*38fd1498Szrj   automaton_decls.release ();
5333*38fd1498Szrj   if (progress_flag)
5334*38fd1498Szrj     fprintf (stderr, "done\n");
5335*38fd1498Szrj }
5336*38fd1498Szrj 
5337*38fd1498Szrj 
5338*38fd1498Szrj 
5339*38fd1498Szrj /* The page contains code for building alt_states (see comments for
5340*38fd1498Szrj    IR) describing all possible insns reservations of an automaton.  */
5341*38fd1498Szrj 
5342*38fd1498Szrj /* Current state being formed for which the current alt_state
5343*38fd1498Szrj    refers.  */
5344*38fd1498Szrj static state_t state_being_formed;
5345*38fd1498Szrj 
5346*38fd1498Szrj /* Current alt_state being formed.  */
5347*38fd1498Szrj static alt_state_t alt_state_being_formed;
5348*38fd1498Szrj 
5349*38fd1498Szrj /* This recursive function processes `,' and units in reservation
5350*38fd1498Szrj    REGEXP for forming alt_states of AUTOMATON.  It is believed that
5351*38fd1498Szrj    CURR_CYCLE is start cycle of all reservation REGEXP.  */
5352*38fd1498Szrj static int
process_seq_for_forming_states(regexp_t regexp,automaton_t automaton,int curr_cycle)5353*38fd1498Szrj process_seq_for_forming_states (regexp_t regexp, automaton_t automaton,
5354*38fd1498Szrj 				int curr_cycle)
5355*38fd1498Szrj {
5356*38fd1498Szrj   int i;
5357*38fd1498Szrj 
5358*38fd1498Szrj   if (regexp == NULL)
5359*38fd1498Szrj     return curr_cycle;
5360*38fd1498Szrj 
5361*38fd1498Szrj   switch (regexp->mode)
5362*38fd1498Szrj     {
5363*38fd1498Szrj     case rm_unit:
5364*38fd1498Szrj       if (REGEXP_UNIT (regexp)->unit_decl->corresponding_automaton_num
5365*38fd1498Szrj           == automaton->automaton_order_num)
5366*38fd1498Szrj         set_state_reserv (state_being_formed, curr_cycle,
5367*38fd1498Szrj                           REGEXP_UNIT (regexp)->unit_decl->unit_num);
5368*38fd1498Szrj       return curr_cycle;
5369*38fd1498Szrj 
5370*38fd1498Szrj     case rm_sequence:
5371*38fd1498Szrj       for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
5372*38fd1498Szrj 	curr_cycle
5373*38fd1498Szrj 	  = process_seq_for_forming_states
5374*38fd1498Szrj 	    (REGEXP_SEQUENCE (regexp)->regexps [i], automaton, curr_cycle) + 1;
5375*38fd1498Szrj       return curr_cycle;
5376*38fd1498Szrj 
5377*38fd1498Szrj     case rm_allof:
5378*38fd1498Szrj       {
5379*38fd1498Szrj 	int finish_cycle = 0;
5380*38fd1498Szrj 	int cycle;
5381*38fd1498Szrj 
5382*38fd1498Szrj 	for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
5383*38fd1498Szrj 	  {
5384*38fd1498Szrj 	    cycle = process_seq_for_forming_states (REGEXP_ALLOF (regexp)
5385*38fd1498Szrj 						    ->regexps [i],
5386*38fd1498Szrj 						    automaton, curr_cycle);
5387*38fd1498Szrj 	    if (finish_cycle < cycle)
5388*38fd1498Szrj 	      finish_cycle = cycle;
5389*38fd1498Szrj 	  }
5390*38fd1498Szrj 	return finish_cycle;
5391*38fd1498Szrj       }
5392*38fd1498Szrj 
5393*38fd1498Szrj     case rm_nothing:
5394*38fd1498Szrj       return curr_cycle;
5395*38fd1498Szrj 
5396*38fd1498Szrj     default:
5397*38fd1498Szrj       gcc_unreachable ();
5398*38fd1498Szrj     }
5399*38fd1498Szrj }
5400*38fd1498Szrj 
5401*38fd1498Szrj /* This recursive function finishes forming ALT_STATE of AUTOMATON and
5402*38fd1498Szrj    inserts alt_state into the table.  */
5403*38fd1498Szrj static void
finish_forming_alt_state(alt_state_t alt_state,automaton_t automaton ATTRIBUTE_UNUSED)5404*38fd1498Szrj finish_forming_alt_state (alt_state_t alt_state,
5405*38fd1498Szrj 			  automaton_t automaton ATTRIBUTE_UNUSED)
5406*38fd1498Szrj {
5407*38fd1498Szrj   state_t state_in_table;
5408*38fd1498Szrj   state_t corresponding_state;
5409*38fd1498Szrj 
5410*38fd1498Szrj   corresponding_state = alt_state->state;
5411*38fd1498Szrj   state_in_table = insert_state (corresponding_state);
5412*38fd1498Szrj   if (state_in_table != corresponding_state)
5413*38fd1498Szrj     {
5414*38fd1498Szrj       free_state (corresponding_state);
5415*38fd1498Szrj       alt_state->state = state_in_table;
5416*38fd1498Szrj     }
5417*38fd1498Szrj }
5418*38fd1498Szrj 
5419*38fd1498Szrj /* The following variable value is current automaton insn for whose
5420*38fd1498Szrj    reservation the alt states are created.  */
5421*38fd1498Szrj static ainsn_t curr_ainsn;
5422*38fd1498Szrj 
5423*38fd1498Szrj /* This recursive function processes `|' in reservation REGEXP for
5424*38fd1498Szrj    forming alt_states of AUTOMATON.  List of the alt states should
5425*38fd1498Szrj    have the same order as in the description.  */
5426*38fd1498Szrj static void
process_alts_for_forming_states(regexp_t regexp,automaton_t automaton,int inside_oneof_p)5427*38fd1498Szrj process_alts_for_forming_states (regexp_t regexp, automaton_t automaton,
5428*38fd1498Szrj 				 int inside_oneof_p)
5429*38fd1498Szrj {
5430*38fd1498Szrj   int i;
5431*38fd1498Szrj 
5432*38fd1498Szrj   if (regexp->mode != rm_oneof)
5433*38fd1498Szrj     {
5434*38fd1498Szrj       alt_state_being_formed = get_free_alt_state ();
5435*38fd1498Szrj       state_being_formed = get_free_state (1, automaton);
5436*38fd1498Szrj       alt_state_being_formed->state = state_being_formed;
5437*38fd1498Szrj       /* We inserts in reverse order but we process alternatives also
5438*38fd1498Szrj          in reverse order.  So we have the same order of alternative
5439*38fd1498Szrj          as in the description.  */
5440*38fd1498Szrj       alt_state_being_formed->next_alt_state = curr_ainsn->alt_states;
5441*38fd1498Szrj       curr_ainsn->alt_states = alt_state_being_formed;
5442*38fd1498Szrj       (void) process_seq_for_forming_states (regexp, automaton, 0);
5443*38fd1498Szrj       finish_forming_alt_state (alt_state_being_formed, automaton);
5444*38fd1498Szrj     }
5445*38fd1498Szrj   else
5446*38fd1498Szrj     {
5447*38fd1498Szrj       gcc_assert (!inside_oneof_p);
5448*38fd1498Szrj       /* We processes it in reverse order to get list with the same
5449*38fd1498Szrj 	 order as in the description.  See also the previous
5450*38fd1498Szrj 	 commentary.  */
5451*38fd1498Szrj       for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
5452*38fd1498Szrj 	process_alts_for_forming_states (REGEXP_ONEOF (regexp)->regexps [i],
5453*38fd1498Szrj 					 automaton, 1);
5454*38fd1498Szrj     }
5455*38fd1498Szrj }
5456*38fd1498Szrj 
5457*38fd1498Szrj /* Create nodes alt_state for all AUTOMATON insns.  */
5458*38fd1498Szrj static void
create_alt_states(automaton_t automaton)5459*38fd1498Szrj create_alt_states (automaton_t automaton)
5460*38fd1498Szrj {
5461*38fd1498Szrj   struct insn_reserv_decl *reserv_decl;
5462*38fd1498Szrj 
5463*38fd1498Szrj   for (curr_ainsn = automaton->ainsn_list;
5464*38fd1498Szrj        curr_ainsn != NULL;
5465*38fd1498Szrj        curr_ainsn = curr_ainsn->next_ainsn)
5466*38fd1498Szrj     {
5467*38fd1498Szrj       reserv_decl = curr_ainsn->insn_reserv_decl;
5468*38fd1498Szrj       if (!special_decl_p (reserv_decl))
5469*38fd1498Szrj         {
5470*38fd1498Szrj           curr_ainsn->alt_states = NULL;
5471*38fd1498Szrj           process_alts_for_forming_states (reserv_decl->transformed_regexp,
5472*38fd1498Szrj 					   automaton, 0);
5473*38fd1498Szrj           curr_ainsn->sorted_alt_states
5474*38fd1498Szrj 	    = uniq_sort_alt_states (curr_ainsn->alt_states);
5475*38fd1498Szrj         }
5476*38fd1498Szrj     }
5477*38fd1498Szrj }
5478*38fd1498Szrj 
5479*38fd1498Szrj 
5480*38fd1498Szrj 
5481*38fd1498Szrj /* The page contains major code for building DFA(s) for fast pipeline
5482*38fd1498Szrj    hazards recognition.  */
5483*38fd1498Szrj 
5484*38fd1498Szrj /* The function forms list of ainsns of AUTOMATON with the same
5485*38fd1498Szrj    reservation.  */
5486*38fd1498Szrj 
5487*38fd1498Szrj static void
form_ainsn_with_same_reservs(automaton_t automaton)5488*38fd1498Szrj form_ainsn_with_same_reservs (automaton_t automaton)
5489*38fd1498Szrj {
5490*38fd1498Szrj   ainsn_t curr_ainsn;
5491*38fd1498Szrj   size_t i;
5492*38fd1498Szrj   auto_vec<ainsn_t, 150> last_insns;
5493*38fd1498Szrj 
5494*38fd1498Szrj   for (curr_ainsn = automaton->ainsn_list;
5495*38fd1498Szrj        curr_ainsn != NULL;
5496*38fd1498Szrj        curr_ainsn = curr_ainsn->next_ainsn)
5497*38fd1498Szrj     if (special_decl_p (curr_ainsn->insn_reserv_decl))
5498*38fd1498Szrj       {
5499*38fd1498Szrj         curr_ainsn->next_same_reservs_insn = NULL;
5500*38fd1498Szrj         curr_ainsn->first_insn_with_same_reservs = 1;
5501*38fd1498Szrj       }
5502*38fd1498Szrj     else
5503*38fd1498Szrj       {
5504*38fd1498Szrj         for (i = 0; i < last_insns.length (); i++)
5505*38fd1498Szrj           if (alt_states_eq
5506*38fd1498Szrj               (curr_ainsn->sorted_alt_states,
5507*38fd1498Szrj                last_insns[i]->sorted_alt_states))
5508*38fd1498Szrj             break;
5509*38fd1498Szrj         curr_ainsn->next_same_reservs_insn = NULL;
5510*38fd1498Szrj         if (i < last_insns.length ())
5511*38fd1498Szrj           {
5512*38fd1498Szrj             curr_ainsn->first_insn_with_same_reservs = 0;
5513*38fd1498Szrj 	    last_insns[i]->next_same_reservs_insn = curr_ainsn;
5514*38fd1498Szrj             last_insns[i] = curr_ainsn;
5515*38fd1498Szrj           }
5516*38fd1498Szrj         else
5517*38fd1498Szrj           {
5518*38fd1498Szrj             last_insns.safe_push (curr_ainsn);
5519*38fd1498Szrj             curr_ainsn->first_insn_with_same_reservs = 1;
5520*38fd1498Szrj           }
5521*38fd1498Szrj       }
5522*38fd1498Szrj }
5523*38fd1498Szrj 
5524*38fd1498Szrj /* Forming unit reservations which can affect creating the automaton
5525*38fd1498Szrj    states achieved from a given state.  It permits to build smaller
5526*38fd1498Szrj    automata in many cases.  We would have the same automata after
5527*38fd1498Szrj    the minimization without such optimization, but the automaton
5528*38fd1498Szrj    right after the building could be huge.  So in other words, usage
5529*38fd1498Szrj    of reservs_matter means some minimization during building the
5530*38fd1498Szrj    automaton.  */
5531*38fd1498Szrj static reserv_sets_t
form_reservs_matter(automaton_t automaton)5532*38fd1498Szrj form_reservs_matter (automaton_t automaton)
5533*38fd1498Szrj {
5534*38fd1498Szrj   int cycle, unit;
5535*38fd1498Szrj   reserv_sets_t reservs_matter = alloc_empty_reserv_sets ();
5536*38fd1498Szrj 
5537*38fd1498Szrj   for (cycle = 0; cycle < max_cycles_num; cycle++)
5538*38fd1498Szrj     for (unit = 0; unit < description->units_num; unit++)
5539*38fd1498Szrj       if (units_array [unit]->automaton_decl
5540*38fd1498Szrj 	  == automaton->corresponding_automaton_decl
5541*38fd1498Szrj 	  && (cycle >= units_array [unit]->min_occ_cycle_num
5542*38fd1498Szrj 	      /* We can not remove queried unit from reservations.  */
5543*38fd1498Szrj 	      || units_array [unit]->query_p
5544*38fd1498Szrj 	      /* We can not remove units which are used
5545*38fd1498Szrj 		 `exclusion_set', `presence_set',
5546*38fd1498Szrj 		 `final_presence_set', `absence_set', and
5547*38fd1498Szrj 		 `final_absence_set'.  */
5548*38fd1498Szrj 	      || units_array [unit]->in_set_p))
5549*38fd1498Szrj 	set_unit_reserv (reservs_matter, cycle, unit);
5550*38fd1498Szrj   return reservs_matter;
5551*38fd1498Szrj }
5552*38fd1498Szrj 
5553*38fd1498Szrj /* The following function creates all states of nondeterministic AUTOMATON.  */
5554*38fd1498Szrj static void
make_automaton(automaton_t automaton)5555*38fd1498Szrj make_automaton (automaton_t automaton)
5556*38fd1498Szrj {
5557*38fd1498Szrj   ainsn_t ainsn;
5558*38fd1498Szrj   struct insn_reserv_decl *insn_reserv_decl;
5559*38fd1498Szrj   alt_state_t alt_state;
5560*38fd1498Szrj   state_t state;
5561*38fd1498Szrj   state_t start_state;
5562*38fd1498Szrj   state_t state2;
5563*38fd1498Szrj   auto_vec<state_t, 150> state_stack;
5564*38fd1498Szrj   int states_n;
5565*38fd1498Szrj   reserv_sets_t reservs_matter = form_reservs_matter (automaton);
5566*38fd1498Szrj 
5567*38fd1498Szrj   /* Create the start state (empty state).  */
5568*38fd1498Szrj   start_state = insert_state (get_free_state (1, automaton));
5569*38fd1498Szrj   automaton->start_state = start_state;
5570*38fd1498Szrj   start_state->it_was_placed_in_stack_for_NDFA_forming = 1;
5571*38fd1498Szrj   state_stack.safe_push (start_state);
5572*38fd1498Szrj   states_n = 1;
5573*38fd1498Szrj   while (state_stack.length () != 0)
5574*38fd1498Szrj     {
5575*38fd1498Szrj       state = state_stack.pop ();
5576*38fd1498Szrj       for (ainsn = automaton->ainsn_list;
5577*38fd1498Szrj 	   ainsn != NULL;
5578*38fd1498Szrj 	   ainsn = ainsn->next_ainsn)
5579*38fd1498Szrj         if (ainsn->first_insn_with_same_reservs)
5580*38fd1498Szrj           {
5581*38fd1498Szrj             insn_reserv_decl = ainsn->insn_reserv_decl;
5582*38fd1498Szrj             if (!special_decl_p (insn_reserv_decl))
5583*38fd1498Szrj               {
5584*38fd1498Szrj 		/* We process alt_states in the same order as they are
5585*38fd1498Szrj                    present in the description.  */
5586*38fd1498Szrj                 for (alt_state = ainsn->alt_states;
5587*38fd1498Szrj                      alt_state != NULL;
5588*38fd1498Szrj                      alt_state = alt_state->next_alt_state)
5589*38fd1498Szrj                   {
5590*38fd1498Szrj                     state2 = alt_state->state;
5591*38fd1498Szrj                     if (!intersected_state_reservs_p (state, state2))
5592*38fd1498Szrj                       {
5593*38fd1498Szrj                         state2 = states_union (state, state2, reservs_matter);
5594*38fd1498Szrj                         if (!state2->it_was_placed_in_stack_for_NDFA_forming)
5595*38fd1498Szrj                           {
5596*38fd1498Szrj                             state2->it_was_placed_in_stack_for_NDFA_forming
5597*38fd1498Szrj 			      = 1;
5598*38fd1498Szrj                             state_stack.safe_push (state2);
5599*38fd1498Szrj 			    states_n++;
5600*38fd1498Szrj 			    if (progress_flag && states_n % 100 == 0)
5601*38fd1498Szrj 			      fprintf (stderr, ".");
5602*38fd1498Szrj                           }
5603*38fd1498Szrj 			add_arc (state, state2, ainsn);
5604*38fd1498Szrj 			if (!ndfa_flag)
5605*38fd1498Szrj 			  break;
5606*38fd1498Szrj                       }
5607*38fd1498Szrj                   }
5608*38fd1498Szrj               }
5609*38fd1498Szrj           }
5610*38fd1498Szrj       /* Add transition to advance cycle.  */
5611*38fd1498Szrj       state2 = state_shift (state, reservs_matter);
5612*38fd1498Szrj       if (!state2->it_was_placed_in_stack_for_NDFA_forming)
5613*38fd1498Szrj         {
5614*38fd1498Szrj           state2->it_was_placed_in_stack_for_NDFA_forming = 1;
5615*38fd1498Szrj           state_stack.safe_push (state2);
5616*38fd1498Szrj 	  states_n++;
5617*38fd1498Szrj 	  if (progress_flag && states_n % 100 == 0)
5618*38fd1498Szrj 	    fprintf (stderr, ".");
5619*38fd1498Szrj         }
5620*38fd1498Szrj       add_arc (state, state2, automaton->advance_ainsn);
5621*38fd1498Szrj     }
5622*38fd1498Szrj }
5623*38fd1498Szrj 
5624*38fd1498Szrj /* Form lists of all arcs of STATE marked by the same ainsn.  */
5625*38fd1498Szrj static void
form_arcs_marked_by_insn(state_t state)5626*38fd1498Szrj form_arcs_marked_by_insn (state_t state)
5627*38fd1498Szrj {
5628*38fd1498Szrj   decl_t decl;
5629*38fd1498Szrj   arc_t arc;
5630*38fd1498Szrj   int i;
5631*38fd1498Szrj 
5632*38fd1498Szrj   for (i = 0; i < description->decls_num; i++)
5633*38fd1498Szrj     {
5634*38fd1498Szrj       decl = description->decls [i];
5635*38fd1498Szrj       if (decl->mode == dm_insn_reserv)
5636*38fd1498Szrj 	DECL_INSN_RESERV (decl)->arcs_marked_by_insn = NULL;
5637*38fd1498Szrj     }
5638*38fd1498Szrj   for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5639*38fd1498Szrj     {
5640*38fd1498Szrj       gcc_assert (arc->insn);
5641*38fd1498Szrj       arc->next_arc_marked_by_insn
5642*38fd1498Szrj 	= arc->insn->insn_reserv_decl->arcs_marked_by_insn;
5643*38fd1498Szrj       arc->insn->insn_reserv_decl->arcs_marked_by_insn = arc;
5644*38fd1498Szrj     }
5645*38fd1498Szrj }
5646*38fd1498Szrj 
5647*38fd1498Szrj /* The function creates composed state (see comments for IR) from
5648*38fd1498Szrj    ORIGINAL_STATE and list of arcs ARCS_MARKED_BY_INSN marked by the
5649*38fd1498Szrj    same insn.  If the composed state is not in STATE_STACK yet, it is
5650*38fd1498Szrj    pushed into STATE_STACK.  */
5651*38fd1498Szrj 
5652*38fd1498Szrj static int
create_composed_state(state_t original_state,arc_t arcs_marked_by_insn,vec<state_t> * state_stack)5653*38fd1498Szrj create_composed_state (state_t original_state, arc_t arcs_marked_by_insn,
5654*38fd1498Szrj 		       vec<state_t> *state_stack)
5655*38fd1498Szrj {
5656*38fd1498Szrj   state_t state;
5657*38fd1498Szrj   alt_state_t alt_state, curr_alt_state;
5658*38fd1498Szrj   alt_state_t new_alt_state;
5659*38fd1498Szrj   arc_t curr_arc;
5660*38fd1498Szrj   arc_t next_arc;
5661*38fd1498Szrj   state_t state_in_table;
5662*38fd1498Szrj   state_t temp_state;
5663*38fd1498Szrj   alt_state_t canonical_alt_states_list;
5664*38fd1498Szrj   int alts_number;
5665*38fd1498Szrj   int new_state_p = 0;
5666*38fd1498Szrj 
5667*38fd1498Szrj   if (arcs_marked_by_insn == NULL)
5668*38fd1498Szrj     return new_state_p;
5669*38fd1498Szrj   if (arcs_marked_by_insn->next_arc_marked_by_insn == NULL)
5670*38fd1498Szrj     state = arcs_marked_by_insn->to_state;
5671*38fd1498Szrj   else
5672*38fd1498Szrj     {
5673*38fd1498Szrj       gcc_assert (ndfa_flag);
5674*38fd1498Szrj       /* Create composed state.  */
5675*38fd1498Szrj       state = get_free_state (0, arcs_marked_by_insn->to_state->automaton);
5676*38fd1498Szrj       curr_alt_state = NULL;
5677*38fd1498Szrj       for (curr_arc = arcs_marked_by_insn;
5678*38fd1498Szrj            curr_arc != NULL;
5679*38fd1498Szrj            curr_arc = curr_arc->next_arc_marked_by_insn)
5680*38fd1498Szrj 	if (curr_arc->to_state->component_states == NULL)
5681*38fd1498Szrj 	  {
5682*38fd1498Szrj 	    new_alt_state = get_free_alt_state ();
5683*38fd1498Szrj 	    new_alt_state->next_alt_state = curr_alt_state;
5684*38fd1498Szrj 	    new_alt_state->state = curr_arc->to_state;
5685*38fd1498Szrj 	    curr_alt_state = new_alt_state;
5686*38fd1498Szrj 	  }
5687*38fd1498Szrj 	else
5688*38fd1498Szrj 	  for (alt_state = curr_arc->to_state->component_states;
5689*38fd1498Szrj 	       alt_state != NULL;
5690*38fd1498Szrj 	       alt_state = alt_state->next_sorted_alt_state)
5691*38fd1498Szrj 	    {
5692*38fd1498Szrj 	      new_alt_state = get_free_alt_state ();
5693*38fd1498Szrj 	      new_alt_state->next_alt_state = curr_alt_state;
5694*38fd1498Szrj 	      new_alt_state->state = alt_state->state;
5695*38fd1498Szrj 	      gcc_assert (!alt_state->state->component_states);
5696*38fd1498Szrj 	      curr_alt_state = new_alt_state;
5697*38fd1498Szrj 	    }
5698*38fd1498Szrj       /* There are not identical sets in the alt state list.  */
5699*38fd1498Szrj       canonical_alt_states_list = uniq_sort_alt_states (curr_alt_state);
5700*38fd1498Szrj       if (canonical_alt_states_list->next_sorted_alt_state == NULL)
5701*38fd1498Szrj         {
5702*38fd1498Szrj           temp_state = state;
5703*38fd1498Szrj           state = canonical_alt_states_list->state;
5704*38fd1498Szrj           free_state (temp_state);
5705*38fd1498Szrj         }
5706*38fd1498Szrj       else
5707*38fd1498Szrj         {
5708*38fd1498Szrj           state->component_states = canonical_alt_states_list;
5709*38fd1498Szrj           state_in_table = insert_state (state);
5710*38fd1498Szrj           if (state_in_table != state)
5711*38fd1498Szrj             {
5712*38fd1498Szrj               gcc_assert
5713*38fd1498Szrj 		(state_in_table->it_was_placed_in_stack_for_DFA_forming);
5714*38fd1498Szrj               free_state (state);
5715*38fd1498Szrj               state = state_in_table;
5716*38fd1498Szrj             }
5717*38fd1498Szrj           else
5718*38fd1498Szrj             {
5719*38fd1498Szrj               gcc_assert (!state->it_was_placed_in_stack_for_DFA_forming);
5720*38fd1498Szrj 	      new_state_p = 1;
5721*38fd1498Szrj               for (curr_alt_state = state->component_states;
5722*38fd1498Szrj                    curr_alt_state != NULL;
5723*38fd1498Szrj                    curr_alt_state = curr_alt_state->next_sorted_alt_state)
5724*38fd1498Szrj                 for (curr_arc = first_out_arc (curr_alt_state->state);
5725*38fd1498Szrj                      curr_arc != NULL;
5726*38fd1498Szrj                      curr_arc = next_out_arc (curr_arc))
5727*38fd1498Szrj 		  if (!collapse_flag
5728*38fd1498Szrj 		      /* When producing collapse-NDFA transitions, we
5729*38fd1498Szrj 			 only add advance-cycle transitions to the
5730*38fd1498Szrj 			 collapsed states.  */
5731*38fd1498Szrj 		      || (curr_arc->insn->insn_reserv_decl
5732*38fd1498Szrj 			  != DECL_INSN_RESERV (advance_cycle_insn_decl)))
5733*38fd1498Szrj 		    add_arc (state, curr_arc->to_state, curr_arc->insn);
5734*38fd1498Szrj             }
5735*38fd1498Szrj           arcs_marked_by_insn->to_state = state;
5736*38fd1498Szrj           for (alts_number = 0,
5737*38fd1498Szrj 	       curr_arc = arcs_marked_by_insn->next_arc_marked_by_insn;
5738*38fd1498Szrj                curr_arc != NULL;
5739*38fd1498Szrj                curr_arc = next_arc)
5740*38fd1498Szrj             {
5741*38fd1498Szrj               next_arc = curr_arc->next_arc_marked_by_insn;
5742*38fd1498Szrj               remove_arc (original_state, curr_arc);
5743*38fd1498Szrj 	      alts_number++;
5744*38fd1498Szrj             }
5745*38fd1498Szrj         }
5746*38fd1498Szrj     }
5747*38fd1498Szrj   if (!state->it_was_placed_in_stack_for_DFA_forming)
5748*38fd1498Szrj     {
5749*38fd1498Szrj       state->it_was_placed_in_stack_for_DFA_forming = 1;
5750*38fd1498Szrj       state_stack->safe_push (state);
5751*38fd1498Szrj     }
5752*38fd1498Szrj   return new_state_p;
5753*38fd1498Szrj }
5754*38fd1498Szrj 
5755*38fd1498Szrj /* The function transforms nondeterministic AUTOMATON into
5756*38fd1498Szrj    deterministic.  */
5757*38fd1498Szrj 
5758*38fd1498Szrj static void
NDFA_to_DFA(automaton_t automaton)5759*38fd1498Szrj NDFA_to_DFA (automaton_t automaton)
5760*38fd1498Szrj {
5761*38fd1498Szrj   state_t start_state;
5762*38fd1498Szrj   state_t state;
5763*38fd1498Szrj   decl_t decl;
5764*38fd1498Szrj   auto_vec<state_t> state_stack;
5765*38fd1498Szrj   int i;
5766*38fd1498Szrj   int states_n;
5767*38fd1498Szrj 
5768*38fd1498Szrj   /* Create the start state (empty state).  */
5769*38fd1498Szrj   start_state = automaton->start_state;
5770*38fd1498Szrj   start_state->it_was_placed_in_stack_for_DFA_forming = 1;
5771*38fd1498Szrj   state_stack.safe_push (start_state);
5772*38fd1498Szrj   states_n = 1;
5773*38fd1498Szrj   while (state_stack.length () != 0)
5774*38fd1498Szrj     {
5775*38fd1498Szrj       state = state_stack.pop ();
5776*38fd1498Szrj       form_arcs_marked_by_insn (state);
5777*38fd1498Szrj       for (i = 0; i < description->decls_num; i++)
5778*38fd1498Szrj 	{
5779*38fd1498Szrj 	  decl = description->decls [i];
5780*38fd1498Szrj 	  if (decl->mode == dm_insn_reserv
5781*38fd1498Szrj 	      && decl != collapse_ndfa_insn_decl
5782*38fd1498Szrj 	      && create_composed_state
5783*38fd1498Szrj 	         (state, DECL_INSN_RESERV (decl)->arcs_marked_by_insn,
5784*38fd1498Szrj 		  &state_stack))
5785*38fd1498Szrj 	    {
5786*38fd1498Szrj 	      states_n++;
5787*38fd1498Szrj 	      if (progress_flag && states_n % 100 == 0)
5788*38fd1498Szrj 		fprintf (stderr, ".");
5789*38fd1498Szrj 	    }
5790*38fd1498Szrj 	}
5791*38fd1498Szrj       /* Add a transition to collapse the NDFA.  */
5792*38fd1498Szrj       if (collapse_flag)
5793*38fd1498Szrj 	{
5794*38fd1498Szrj 	  if (state->component_states != NULL)
5795*38fd1498Szrj 	    {
5796*38fd1498Szrj 	      state_t state2 = state->component_states->state;
5797*38fd1498Szrj 	      if (!state2->it_was_placed_in_stack_for_DFA_forming)
5798*38fd1498Szrj 		{
5799*38fd1498Szrj 		  state2->it_was_placed_in_stack_for_DFA_forming = 1;
5800*38fd1498Szrj 		  state_stack.safe_push (state2);
5801*38fd1498Szrj 		}
5802*38fd1498Szrj 	      add_arc (state, state2, automaton->collapse_ainsn);
5803*38fd1498Szrj 	    }
5804*38fd1498Szrj 	  else
5805*38fd1498Szrj 	    add_arc (state, state, automaton->collapse_ainsn);
5806*38fd1498Szrj 	}
5807*38fd1498Szrj     }
5808*38fd1498Szrj }
5809*38fd1498Szrj 
5810*38fd1498Szrj /* The following variable value is current number (1, 2, ...) of passing
5811*38fd1498Szrj    graph of states.  */
5812*38fd1498Szrj static int curr_state_graph_pass_num;
5813*38fd1498Szrj 
5814*38fd1498Szrj /* This recursive function passes all states achieved from START_STATE
5815*38fd1498Szrj    and applies APPLIED_FUNC to them.  */
5816*38fd1498Szrj static void
pass_state_graph(state_t start_state,void (* applied_func)(state_t state))5817*38fd1498Szrj pass_state_graph (state_t start_state, void (*applied_func) (state_t state))
5818*38fd1498Szrj {
5819*38fd1498Szrj   arc_t arc;
5820*38fd1498Szrj 
5821*38fd1498Szrj   if (start_state->pass_num == curr_state_graph_pass_num)
5822*38fd1498Szrj     return;
5823*38fd1498Szrj   start_state->pass_num = curr_state_graph_pass_num;
5824*38fd1498Szrj   (*applied_func) (start_state);
5825*38fd1498Szrj   for (arc = first_out_arc (start_state);
5826*38fd1498Szrj        arc != NULL;
5827*38fd1498Szrj        arc = next_out_arc (arc))
5828*38fd1498Szrj     pass_state_graph (arc->to_state, applied_func);
5829*38fd1498Szrj }
5830*38fd1498Szrj 
5831*38fd1498Szrj /* This recursive function passes all states of AUTOMATON and applies
5832*38fd1498Szrj    APPLIED_FUNC to them.  */
5833*38fd1498Szrj static void
pass_states(automaton_t automaton,void (* applied_func)(state_t state))5834*38fd1498Szrj pass_states (automaton_t automaton, void (*applied_func) (state_t state))
5835*38fd1498Szrj {
5836*38fd1498Szrj   curr_state_graph_pass_num++;
5837*38fd1498Szrj   pass_state_graph (automaton->start_state, applied_func);
5838*38fd1498Szrj }
5839*38fd1498Szrj 
5840*38fd1498Szrj /* The function initializes code for passing of all states.  */
5841*38fd1498Szrj static void
initiate_pass_states(void)5842*38fd1498Szrj initiate_pass_states (void)
5843*38fd1498Szrj {
5844*38fd1498Szrj   curr_state_graph_pass_num = 0;
5845*38fd1498Szrj }
5846*38fd1498Szrj 
5847*38fd1498Szrj /* The following vla is used for storing pointers to all achieved
5848*38fd1498Szrj    states.  */
5849*38fd1498Szrj static vec<state_t> all_achieved_states;
5850*38fd1498Szrj 
5851*38fd1498Szrj /* This function is called by function pass_states to add an achieved
5852*38fd1498Szrj    STATE.  */
5853*38fd1498Szrj static void
add_achieved_state(state_t state)5854*38fd1498Szrj add_achieved_state (state_t state)
5855*38fd1498Szrj {
5856*38fd1498Szrj   all_achieved_states.safe_push (state);
5857*38fd1498Szrj }
5858*38fd1498Szrj 
5859*38fd1498Szrj /* The function sets up equivalence numbers of insns which mark all
5860*38fd1498Szrj    out arcs of STATE by equiv_class_num_1 (if ODD_ITERATION_FLAG has
5861*38fd1498Szrj    nonzero value) or by equiv_class_num_2 of the destination state.  */
5862*38fd1498Szrj static void
set_out_arc_insns_equiv_num(state_t state,int odd_iteration_flag)5863*38fd1498Szrj set_out_arc_insns_equiv_num (state_t state, int odd_iteration_flag)
5864*38fd1498Szrj {
5865*38fd1498Szrj   arc_t arc;
5866*38fd1498Szrj 
5867*38fd1498Szrj   for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5868*38fd1498Szrj     {
5869*38fd1498Szrj       gcc_assert (!arc->insn->insn_reserv_decl->equiv_class_num);
5870*38fd1498Szrj       arc->insn->insn_reserv_decl->equiv_class_num
5871*38fd1498Szrj 	= (odd_iteration_flag
5872*38fd1498Szrj            ? arc->to_state->equiv_class_num_1
5873*38fd1498Szrj 	   : arc->to_state->equiv_class_num_2);
5874*38fd1498Szrj       gcc_assert (arc->insn->insn_reserv_decl->equiv_class_num);
5875*38fd1498Szrj     }
5876*38fd1498Szrj }
5877*38fd1498Szrj 
5878*38fd1498Szrj /* The function clears equivalence numbers and alt_states in all insns
5879*38fd1498Szrj    which mark all out arcs of STATE.  */
5880*38fd1498Szrj static void
clear_arc_insns_equiv_num(state_t state)5881*38fd1498Szrj clear_arc_insns_equiv_num (state_t state)
5882*38fd1498Szrj {
5883*38fd1498Szrj   arc_t arc;
5884*38fd1498Szrj 
5885*38fd1498Szrj   for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5886*38fd1498Szrj     arc->insn->insn_reserv_decl->equiv_class_num = 0;
5887*38fd1498Szrj }
5888*38fd1498Szrj 
5889*38fd1498Szrj 
5890*38fd1498Szrj /* The following function returns TRUE if STATE reserves the unit with
5891*38fd1498Szrj    UNIT_NUM on the first cycle.  */
5892*38fd1498Szrj static int
first_cycle_unit_presence(state_t state,int unit_num)5893*38fd1498Szrj first_cycle_unit_presence (state_t state, int unit_num)
5894*38fd1498Szrj {
5895*38fd1498Szrj   alt_state_t alt_state;
5896*38fd1498Szrj 
5897*38fd1498Szrj   if (state->component_states == NULL)
5898*38fd1498Szrj     return test_unit_reserv (state->reservs, 0, unit_num);
5899*38fd1498Szrj   else
5900*38fd1498Szrj     {
5901*38fd1498Szrj       for (alt_state = state->component_states;
5902*38fd1498Szrj 	   alt_state != NULL;
5903*38fd1498Szrj 	   alt_state = alt_state->next_sorted_alt_state)
5904*38fd1498Szrj 	if (test_unit_reserv (alt_state->state->reservs, 0, unit_num))
5905*38fd1498Szrj 	  return true;
5906*38fd1498Szrj     }
5907*38fd1498Szrj   return false;
5908*38fd1498Szrj }
5909*38fd1498Szrj 
5910*38fd1498Szrj /* This fills in the presence_signature[] member of STATE.  */
5911*38fd1498Szrj static void
cache_presence(state_t state)5912*38fd1498Szrj cache_presence (state_t state)
5913*38fd1498Szrj {
5914*38fd1498Szrj   int i, num = 0;
5915*38fd1498Szrj   unsigned int sz;
5916*38fd1498Szrj   sz = (description->query_units_num + sizeof (int) * CHAR_BIT - 1)
5917*38fd1498Szrj         / (sizeof (int) * CHAR_BIT);
5918*38fd1498Szrj 
5919*38fd1498Szrj   state->presence_signature = XCREATENODEVEC (unsigned int, sz);
5920*38fd1498Szrj   for (i = 0; i < description->units_num; i++)
5921*38fd1498Szrj     if (units_array [i]->query_p)
5922*38fd1498Szrj       {
5923*38fd1498Szrj 	int presence1_p = first_cycle_unit_presence (state, i);
5924*38fd1498Szrj 	state->presence_signature[num / (sizeof (int) * CHAR_BIT)]
5925*38fd1498Szrj 	  |= (!!presence1_p) << (num % (sizeof (int) * CHAR_BIT));
5926*38fd1498Szrj 	num++;
5927*38fd1498Szrj       }
5928*38fd1498Szrj }
5929*38fd1498Szrj 
5930*38fd1498Szrj /* The function returns nonzero value if STATE is not equivalent to
5931*38fd1498Szrj    ANOTHER_STATE from the same current partition on equivalence
5932*38fd1498Szrj    classes.  Another state has ANOTHER_STATE_OUT_ARCS_NUM number of
5933*38fd1498Szrj    output arcs.  Iteration of making equivalence partition is defined
5934*38fd1498Szrj    by ODD_ITERATION_FLAG.  */
5935*38fd1498Szrj static int
state_is_differed(state_t state,state_t another_state,int odd_iteration_flag)5936*38fd1498Szrj state_is_differed (state_t state, state_t another_state,
5937*38fd1498Szrj 		   int odd_iteration_flag)
5938*38fd1498Szrj {
5939*38fd1498Szrj   arc_t arc;
5940*38fd1498Szrj   unsigned int sz, si;
5941*38fd1498Szrj 
5942*38fd1498Szrj   gcc_assert (state->num_out_arcs == another_state->num_out_arcs);
5943*38fd1498Szrj 
5944*38fd1498Szrj   sz = (description->query_units_num + sizeof (int) * CHAR_BIT - 1)
5945*38fd1498Szrj 	/ (sizeof (int) * CHAR_BIT);
5946*38fd1498Szrj 
5947*38fd1498Szrj   for (si = 0; si < sz; si++)
5948*38fd1498Szrj     gcc_assert (state->presence_signature[si]
5949*38fd1498Szrj 		== another_state->presence_signature[si]);
5950*38fd1498Szrj 
5951*38fd1498Szrj   for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5952*38fd1498Szrj     {
5953*38fd1498Szrj       if ((odd_iteration_flag
5954*38fd1498Szrj            ? arc->to_state->equiv_class_num_1
5955*38fd1498Szrj 	   : arc->to_state->equiv_class_num_2)
5956*38fd1498Szrj           != arc->insn->insn_reserv_decl->equiv_class_num)
5957*38fd1498Szrj         return 1;
5958*38fd1498Szrj     }
5959*38fd1498Szrj 
5960*38fd1498Szrj   return 0;
5961*38fd1498Szrj }
5962*38fd1498Szrj 
5963*38fd1498Szrj /* Compares two states pointed to by STATE_PTR_1 and STATE_PTR_2
5964*38fd1498Szrj    and return -1, 0 or 1.  This function can be used as predicate for
5965*38fd1498Szrj    qsort().  It requires the member presence_signature[] of both
5966*38fd1498Szrj    states be filled.  */
5967*38fd1498Szrj static int
compare_states_for_equiv(const void * state_ptr_1,const void * state_ptr_2)5968*38fd1498Szrj compare_states_for_equiv (const void *state_ptr_1,
5969*38fd1498Szrj 			  const void *state_ptr_2)
5970*38fd1498Szrj {
5971*38fd1498Szrj   const_state_t const s1 = *(const_state_t const*)state_ptr_1;
5972*38fd1498Szrj   const_state_t const s2 = *(const_state_t const*)state_ptr_2;
5973*38fd1498Szrj   unsigned int sz, si;
5974*38fd1498Szrj   if (s1->num_out_arcs < s2->num_out_arcs)
5975*38fd1498Szrj     return -1;
5976*38fd1498Szrj   else if (s1->num_out_arcs > s2->num_out_arcs)
5977*38fd1498Szrj     return 1;
5978*38fd1498Szrj 
5979*38fd1498Szrj   sz = (description->query_units_num + sizeof (int) * CHAR_BIT - 1)
5980*38fd1498Szrj 	/ (sizeof (int) * CHAR_BIT);
5981*38fd1498Szrj 
5982*38fd1498Szrj   for (si = 0; si < sz; si++)
5983*38fd1498Szrj     if (s1->presence_signature[si] < s2->presence_signature[si])
5984*38fd1498Szrj       return -1;
5985*38fd1498Szrj     else if (s1->presence_signature[si] > s2->presence_signature[si])
5986*38fd1498Szrj       return 1;
5987*38fd1498Szrj   return 0;
5988*38fd1498Szrj }
5989*38fd1498Szrj 
5990*38fd1498Szrj /* The function makes initial partition of STATES on equivalent
5991*38fd1498Szrj    classes and saves it into CLASSES.  This function requires the input
5992*38fd1498Szrj    to be sorted via compare_states_for_equiv().  */
5993*38fd1498Szrj static int
init_equiv_class(vec<state_t> states,vec<state_t> * classes)5994*38fd1498Szrj init_equiv_class (vec<state_t> states, vec<state_t> *classes)
5995*38fd1498Szrj {
5996*38fd1498Szrj   size_t i;
5997*38fd1498Szrj   state_t prev = 0;
5998*38fd1498Szrj   int class_num = 1;
5999*38fd1498Szrj 
6000*38fd1498Szrj   classes->create (150);
6001*38fd1498Szrj   for (i = 0; i < states.length (); i++)
6002*38fd1498Szrj     {
6003*38fd1498Szrj       state_t state = states[i];
6004*38fd1498Szrj       if (prev)
6005*38fd1498Szrj         {
6006*38fd1498Szrj 	  if (compare_states_for_equiv (&prev, &state) != 0)
6007*38fd1498Szrj 	    {
6008*38fd1498Szrj 	      classes->safe_push (prev);
6009*38fd1498Szrj 	      class_num++;
6010*38fd1498Szrj 	      prev = NULL;
6011*38fd1498Szrj 	    }
6012*38fd1498Szrj         }
6013*38fd1498Szrj       state->equiv_class_num_1 = class_num;
6014*38fd1498Szrj       state->next_equiv_class_state = prev;
6015*38fd1498Szrj       prev = state;
6016*38fd1498Szrj     }
6017*38fd1498Szrj   if (prev)
6018*38fd1498Szrj     classes->safe_push (prev);
6019*38fd1498Szrj   return class_num;
6020*38fd1498Szrj }
6021*38fd1498Szrj 
6022*38fd1498Szrj /* The function copies pointers to equivalent states from vla FROM
6023*38fd1498Szrj    into vla TO.  */
6024*38fd1498Szrj static void
copy_equiv_class(vec<state_t> * to,vec<state_t> from)6025*38fd1498Szrj copy_equiv_class (vec<state_t> *to, vec<state_t> from)
6026*38fd1498Szrj {
6027*38fd1498Szrj   to->release ();
6028*38fd1498Szrj   *to = from.copy ();
6029*38fd1498Szrj }
6030*38fd1498Szrj 
6031*38fd1498Szrj /* The function processes equivalence class given by its first state,
6032*38fd1498Szrj    FIRST_STATE, on odd iteration if ODD_ITERATION_FLAG.  If there
6033*38fd1498Szrj    are not equivalent states, the function partitions the class
6034*38fd1498Szrj    removing nonequivalent states and placing them in
6035*38fd1498Szrj    *NEXT_ITERATION_CLASSES, increments *NEW_EQUIV_CLASS_NUM_PTR ans
6036*38fd1498Szrj    assigns it to the state equivalence number.  If the class has been
6037*38fd1498Szrj    partitioned, the function returns nonzero value.  */
6038*38fd1498Szrj static int
partition_equiv_class(state_t first_state,int odd_iteration_flag,vec<state_t> * next_iteration_classes,int * new_equiv_class_num_ptr)6039*38fd1498Szrj partition_equiv_class (state_t first_state, int odd_iteration_flag,
6040*38fd1498Szrj 		       vec<state_t> *next_iteration_classes,
6041*38fd1498Szrj 		       int *new_equiv_class_num_ptr)
6042*38fd1498Szrj {
6043*38fd1498Szrj   state_t new_equiv_class;
6044*38fd1498Szrj   int partition_p;
6045*38fd1498Szrj   state_t curr_state;
6046*38fd1498Szrj   state_t prev_state;
6047*38fd1498Szrj   state_t next_state;
6048*38fd1498Szrj 
6049*38fd1498Szrj   partition_p = 0;
6050*38fd1498Szrj 
6051*38fd1498Szrj   while (first_state != NULL)
6052*38fd1498Szrj     {
6053*38fd1498Szrj       new_equiv_class = NULL;
6054*38fd1498Szrj       if (first_state->next_equiv_class_state != NULL)
6055*38fd1498Szrj 	{
6056*38fd1498Szrj 	  /* There are more one states in the class equivalence.  */
6057*38fd1498Szrj 	  set_out_arc_insns_equiv_num (first_state, odd_iteration_flag);
6058*38fd1498Szrj 	  for (prev_state = first_state,
6059*38fd1498Szrj 		 curr_state = first_state->next_equiv_class_state;
6060*38fd1498Szrj 	       curr_state != NULL;
6061*38fd1498Szrj 	       curr_state = next_state)
6062*38fd1498Szrj 	    {
6063*38fd1498Szrj 	      next_state = curr_state->next_equiv_class_state;
6064*38fd1498Szrj 	      if (state_is_differed (curr_state, first_state,
6065*38fd1498Szrj 				     odd_iteration_flag))
6066*38fd1498Szrj 		{
6067*38fd1498Szrj 		  /* Remove curr state from the class equivalence.  */
6068*38fd1498Szrj 		  prev_state->next_equiv_class_state = next_state;
6069*38fd1498Szrj 		  /* Add curr state to the new class equivalence.  */
6070*38fd1498Szrj 		  curr_state->next_equiv_class_state = new_equiv_class;
6071*38fd1498Szrj 		  if (new_equiv_class == NULL)
6072*38fd1498Szrj 		    (*new_equiv_class_num_ptr)++;
6073*38fd1498Szrj 		  if (odd_iteration_flag)
6074*38fd1498Szrj 		    curr_state->equiv_class_num_2 = *new_equiv_class_num_ptr;
6075*38fd1498Szrj 		  else
6076*38fd1498Szrj 		    curr_state->equiv_class_num_1 = *new_equiv_class_num_ptr;
6077*38fd1498Szrj 		  new_equiv_class = curr_state;
6078*38fd1498Szrj 		  partition_p = 1;
6079*38fd1498Szrj 		}
6080*38fd1498Szrj 	      else
6081*38fd1498Szrj 		prev_state = curr_state;
6082*38fd1498Szrj 	    }
6083*38fd1498Szrj 	  clear_arc_insns_equiv_num (first_state);
6084*38fd1498Szrj 	}
6085*38fd1498Szrj       if (new_equiv_class != NULL)
6086*38fd1498Szrj 	next_iteration_classes->safe_push (new_equiv_class);
6087*38fd1498Szrj       first_state = new_equiv_class;
6088*38fd1498Szrj     }
6089*38fd1498Szrj   return partition_p;
6090*38fd1498Szrj }
6091*38fd1498Szrj 
6092*38fd1498Szrj /* The function finds equivalent states of AUTOMATON.  */
6093*38fd1498Szrj static void
evaluate_equiv_classes(automaton_t automaton,vec<state_t> * equiv_classes)6094*38fd1498Szrj evaluate_equiv_classes (automaton_t automaton, vec<state_t> *equiv_classes)
6095*38fd1498Szrj {
6096*38fd1498Szrj   int new_equiv_class_num;
6097*38fd1498Szrj   int odd_iteration_flag;
6098*38fd1498Szrj   int finish_flag;
6099*38fd1498Szrj   vec<state_t> next_iteration_classes;
6100*38fd1498Szrj   size_t i;
6101*38fd1498Szrj 
6102*38fd1498Szrj   all_achieved_states.create (1500);
6103*38fd1498Szrj   pass_states (automaton, add_achieved_state);
6104*38fd1498Szrj   pass_states (automaton, cache_presence);
6105*38fd1498Szrj   all_achieved_states.qsort (compare_states_for_equiv);
6106*38fd1498Szrj 
6107*38fd1498Szrj   odd_iteration_flag = 0;
6108*38fd1498Szrj   new_equiv_class_num = init_equiv_class (all_achieved_states,
6109*38fd1498Szrj   					  &next_iteration_classes);
6110*38fd1498Szrj 
6111*38fd1498Szrj   do
6112*38fd1498Szrj     {
6113*38fd1498Szrj       odd_iteration_flag = !odd_iteration_flag;
6114*38fd1498Szrj       finish_flag = 1;
6115*38fd1498Szrj       copy_equiv_class (equiv_classes, next_iteration_classes);
6116*38fd1498Szrj 
6117*38fd1498Szrj       /* Transfer equiv numbers for the next iteration.  */
6118*38fd1498Szrj       for (i = 0; i < all_achieved_states.length (); i++)
6119*38fd1498Szrj 	if (odd_iteration_flag)
6120*38fd1498Szrj 	  all_achieved_states[i]->equiv_class_num_2
6121*38fd1498Szrj 	    = all_achieved_states[i]->equiv_class_num_1;
6122*38fd1498Szrj 	else
6123*38fd1498Szrj 	  all_achieved_states[i]->equiv_class_num_1
6124*38fd1498Szrj 	    = all_achieved_states[i]->equiv_class_num_2;
6125*38fd1498Szrj 
6126*38fd1498Szrj       for (i = 0; i < equiv_classes->length (); i++)
6127*38fd1498Szrj 	if (partition_equiv_class ((*equiv_classes)[i],
6128*38fd1498Szrj 				   odd_iteration_flag,
6129*38fd1498Szrj 				   &next_iteration_classes,
6130*38fd1498Szrj 				   &new_equiv_class_num))
6131*38fd1498Szrj 	  finish_flag = 0;
6132*38fd1498Szrj     }
6133*38fd1498Szrj   while (!finish_flag);
6134*38fd1498Szrj   next_iteration_classes.release ();
6135*38fd1498Szrj   all_achieved_states.release ();
6136*38fd1498Szrj }
6137*38fd1498Szrj 
6138*38fd1498Szrj /* The function merges equivalent states of AUTOMATON.  */
6139*38fd1498Szrj static void
merge_states(automaton_t automaton,vec<state_t> equiv_classes)6140*38fd1498Szrj merge_states (automaton_t automaton, vec<state_t> equiv_classes)
6141*38fd1498Szrj {
6142*38fd1498Szrj   state_t curr_state;
6143*38fd1498Szrj   state_t new_state;
6144*38fd1498Szrj   state_t first_class_state;
6145*38fd1498Szrj   alt_state_t alt_states;
6146*38fd1498Szrj   alt_state_t alt_state, new_alt_state;
6147*38fd1498Szrj   arc_t curr_arc;
6148*38fd1498Szrj   arc_t next_arc;
6149*38fd1498Szrj   size_t i;
6150*38fd1498Szrj 
6151*38fd1498Szrj   /* Create states corresponding to equivalence classes containing two
6152*38fd1498Szrj      or more states.  */
6153*38fd1498Szrj   for (i = 0; i < equiv_classes.length (); i++)
6154*38fd1498Szrj     {
6155*38fd1498Szrj       curr_state = equiv_classes[i];
6156*38fd1498Szrj       if (curr_state->next_equiv_class_state != NULL)
6157*38fd1498Szrj 	{
6158*38fd1498Szrj 	  /* There are more one states in the class equivalence.  */
6159*38fd1498Szrj 	  /* Create new compound state.  */
6160*38fd1498Szrj 	  new_state = get_free_state (0, automaton);
6161*38fd1498Szrj 	  alt_states = NULL;
6162*38fd1498Szrj 	  first_class_state = curr_state;
6163*38fd1498Szrj 	  for (curr_state = first_class_state;
6164*38fd1498Szrj 	       curr_state != NULL;
6165*38fd1498Szrj 	       curr_state = curr_state->next_equiv_class_state)
6166*38fd1498Szrj 	    {
6167*38fd1498Szrj 	      curr_state->equiv_class_state = new_state;
6168*38fd1498Szrj 	      if (curr_state->component_states == NULL)
6169*38fd1498Szrj 		{
6170*38fd1498Szrj 		  new_alt_state = get_free_alt_state ();
6171*38fd1498Szrj 		  new_alt_state->state = curr_state;
6172*38fd1498Szrj 		  new_alt_state->next_alt_state = alt_states;
6173*38fd1498Szrj 		  alt_states = new_alt_state;
6174*38fd1498Szrj 		}
6175*38fd1498Szrj 	      else
6176*38fd1498Szrj 		for (alt_state = curr_state->component_states;
6177*38fd1498Szrj 		     alt_state != NULL;
6178*38fd1498Szrj 		     alt_state = alt_state->next_sorted_alt_state)
6179*38fd1498Szrj 		  {
6180*38fd1498Szrj 		    new_alt_state = get_free_alt_state ();
6181*38fd1498Szrj 		    new_alt_state->state = alt_state->state;
6182*38fd1498Szrj 		    new_alt_state->next_alt_state = alt_states;
6183*38fd1498Szrj 		    alt_states = new_alt_state;
6184*38fd1498Szrj 		  }
6185*38fd1498Szrj 	    }
6186*38fd1498Szrj 	  /* It is important that alt states were sorted before and
6187*38fd1498Szrj 	     after merging to have the same querying results.  */
6188*38fd1498Szrj 	  new_state->component_states = uniq_sort_alt_states (alt_states);
6189*38fd1498Szrj 	}
6190*38fd1498Szrj       else
6191*38fd1498Szrj 	curr_state->equiv_class_state = curr_state;
6192*38fd1498Szrj     }
6193*38fd1498Szrj 
6194*38fd1498Szrj   for (i = 0; i < equiv_classes.length (); i++)
6195*38fd1498Szrj     {
6196*38fd1498Szrj       curr_state = equiv_classes[i];
6197*38fd1498Szrj       if (curr_state->next_equiv_class_state != NULL)
6198*38fd1498Szrj 	{
6199*38fd1498Szrj 	  first_class_state = curr_state;
6200*38fd1498Szrj 	  /* Create new arcs output from the state corresponding to
6201*38fd1498Szrj 	     equiv class.  */
6202*38fd1498Szrj 	  for (curr_arc = first_out_arc (first_class_state);
6203*38fd1498Szrj 	       curr_arc != NULL;
6204*38fd1498Szrj 	       curr_arc = next_out_arc (curr_arc))
6205*38fd1498Szrj 	    add_arc (first_class_state->equiv_class_state,
6206*38fd1498Szrj 		     curr_arc->to_state->equiv_class_state,
6207*38fd1498Szrj 		     curr_arc->insn);
6208*38fd1498Szrj 	  /* Delete output arcs from states of given class equivalence.  */
6209*38fd1498Szrj 	  for (curr_state = first_class_state;
6210*38fd1498Szrj 	       curr_state != NULL;
6211*38fd1498Szrj 	       curr_state = curr_state->next_equiv_class_state)
6212*38fd1498Szrj 	    {
6213*38fd1498Szrj 	      if (automaton->start_state == curr_state)
6214*38fd1498Szrj 		automaton->start_state = curr_state->equiv_class_state;
6215*38fd1498Szrj 	      /* Delete the state and its output arcs.  */
6216*38fd1498Szrj 	      for (curr_arc = first_out_arc (curr_state);
6217*38fd1498Szrj 		   curr_arc != NULL;
6218*38fd1498Szrj 		   curr_arc = next_arc)
6219*38fd1498Szrj 		{
6220*38fd1498Szrj 		  next_arc = next_out_arc (curr_arc);
6221*38fd1498Szrj 		  free_arc (curr_arc);
6222*38fd1498Szrj 		}
6223*38fd1498Szrj 	    }
6224*38fd1498Szrj 	}
6225*38fd1498Szrj       else
6226*38fd1498Szrj 	{
6227*38fd1498Szrj 	  /* Change `to_state' of arcs output from the state of given
6228*38fd1498Szrj 	     equivalence class.  */
6229*38fd1498Szrj 	  for (curr_arc = first_out_arc (curr_state);
6230*38fd1498Szrj 	       curr_arc != NULL;
6231*38fd1498Szrj 	       curr_arc = next_out_arc (curr_arc))
6232*38fd1498Szrj 	    curr_arc->to_state = curr_arc->to_state->equiv_class_state;
6233*38fd1498Szrj 	}
6234*38fd1498Szrj     }
6235*38fd1498Szrj }
6236*38fd1498Szrj 
6237*38fd1498Szrj /* The function sets up new_cycle_p for states if there is arc to the
6238*38fd1498Szrj    state marked by advance_cycle_insn_decl.  */
6239*38fd1498Szrj static void
set_new_cycle_flags(state_t state)6240*38fd1498Szrj set_new_cycle_flags (state_t state)
6241*38fd1498Szrj {
6242*38fd1498Szrj   arc_t arc;
6243*38fd1498Szrj 
6244*38fd1498Szrj   for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6245*38fd1498Szrj     if (arc->insn->insn_reserv_decl
6246*38fd1498Szrj 	== DECL_INSN_RESERV (advance_cycle_insn_decl))
6247*38fd1498Szrj       arc->to_state->new_cycle_p = 1;
6248*38fd1498Szrj }
6249*38fd1498Szrj 
6250*38fd1498Szrj /* The top level function for minimization of deterministic
6251*38fd1498Szrj    AUTOMATON.  */
6252*38fd1498Szrj static void
minimize_DFA(automaton_t automaton)6253*38fd1498Szrj minimize_DFA (automaton_t automaton)
6254*38fd1498Szrj {
6255*38fd1498Szrj   auto_vec<state_t> equiv_classes;
6256*38fd1498Szrj 
6257*38fd1498Szrj   evaluate_equiv_classes (automaton, &equiv_classes);
6258*38fd1498Szrj   merge_states (automaton, equiv_classes);
6259*38fd1498Szrj   pass_states (automaton, set_new_cycle_flags);
6260*38fd1498Szrj }
6261*38fd1498Szrj 
6262*38fd1498Szrj /* Values of two variables are counted number of states and arcs in an
6263*38fd1498Szrj    automaton.  */
6264*38fd1498Szrj static int curr_counted_states_num;
6265*38fd1498Szrj static int curr_counted_arcs_num;
6266*38fd1498Szrj 
6267*38fd1498Szrj /* The function is called by function `pass_states' to count states
6268*38fd1498Szrj    and arcs of an automaton.  */
6269*38fd1498Szrj static void
incr_states_and_arcs_nums(state_t state)6270*38fd1498Szrj incr_states_and_arcs_nums (state_t state)
6271*38fd1498Szrj {
6272*38fd1498Szrj   arc_t arc;
6273*38fd1498Szrj 
6274*38fd1498Szrj   curr_counted_states_num++;
6275*38fd1498Szrj   for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6276*38fd1498Szrj     curr_counted_arcs_num++;
6277*38fd1498Szrj }
6278*38fd1498Szrj 
6279*38fd1498Szrj /* The function counts states and arcs of AUTOMATON.  */
6280*38fd1498Szrj static void
count_states_and_arcs(automaton_t automaton,int * states_num,int * arcs_num)6281*38fd1498Szrj count_states_and_arcs (automaton_t automaton, int *states_num,
6282*38fd1498Szrj 		       int *arcs_num)
6283*38fd1498Szrj {
6284*38fd1498Szrj   curr_counted_states_num = 0;
6285*38fd1498Szrj   curr_counted_arcs_num = 0;
6286*38fd1498Szrj   pass_states (automaton, incr_states_and_arcs_nums);
6287*38fd1498Szrj   *states_num = curr_counted_states_num;
6288*38fd1498Szrj   *arcs_num = curr_counted_arcs_num;
6289*38fd1498Szrj }
6290*38fd1498Szrj 
6291*38fd1498Szrj /* The function builds one DFA AUTOMATON for fast pipeline hazards
6292*38fd1498Szrj    recognition after checking and simplifying IR of the
6293*38fd1498Szrj    description.  */
6294*38fd1498Szrj static void
build_automaton(automaton_t automaton)6295*38fd1498Szrj build_automaton (automaton_t automaton)
6296*38fd1498Szrj {
6297*38fd1498Szrj   int states_num;
6298*38fd1498Szrj   int arcs_num;
6299*38fd1498Szrj 
6300*38fd1498Szrj   ticker_on (&NDFA_time);
6301*38fd1498Szrj   if (progress_flag)
6302*38fd1498Szrj     {
6303*38fd1498Szrj       if (automaton->corresponding_automaton_decl == NULL)
6304*38fd1498Szrj 	fprintf (stderr, "Create anonymous automaton");
6305*38fd1498Szrj       else
6306*38fd1498Szrj 	fprintf (stderr, "Create automaton `%s'",
6307*38fd1498Szrj 		 automaton->corresponding_automaton_decl->name);
6308*38fd1498Szrj       fprintf (stderr, " (1 dot is 100 new states):");
6309*38fd1498Szrj     }
6310*38fd1498Szrj   make_automaton (automaton);
6311*38fd1498Szrj   if (progress_flag)
6312*38fd1498Szrj     fprintf (stderr, " done\n");
6313*38fd1498Szrj   ticker_off (&NDFA_time);
6314*38fd1498Szrj   count_states_and_arcs (automaton, &states_num, &arcs_num);
6315*38fd1498Szrj   automaton->NDFA_states_num = states_num;
6316*38fd1498Szrj   automaton->NDFA_arcs_num = arcs_num;
6317*38fd1498Szrj   ticker_on (&NDFA_to_DFA_time);
6318*38fd1498Szrj   if (progress_flag)
6319*38fd1498Szrj     {
6320*38fd1498Szrj       if (automaton->corresponding_automaton_decl == NULL)
6321*38fd1498Szrj 	fprintf (stderr, "Make anonymous DFA");
6322*38fd1498Szrj       else
6323*38fd1498Szrj 	fprintf (stderr, "Make DFA `%s'",
6324*38fd1498Szrj 		 automaton->corresponding_automaton_decl->name);
6325*38fd1498Szrj       fprintf (stderr, " (1 dot is 100 new states):");
6326*38fd1498Szrj     }
6327*38fd1498Szrj   NDFA_to_DFA (automaton);
6328*38fd1498Szrj   if (progress_flag)
6329*38fd1498Szrj     fprintf (stderr, " done\n");
6330*38fd1498Szrj   ticker_off (&NDFA_to_DFA_time);
6331*38fd1498Szrj   count_states_and_arcs (automaton, &states_num, &arcs_num);
6332*38fd1498Szrj   automaton->DFA_states_num = states_num;
6333*38fd1498Szrj   automaton->DFA_arcs_num = arcs_num;
6334*38fd1498Szrj   if (!no_minimization_flag)
6335*38fd1498Szrj     {
6336*38fd1498Szrj       ticker_on (&minimize_time);
6337*38fd1498Szrj       if (progress_flag)
6338*38fd1498Szrj 	{
6339*38fd1498Szrj 	  if (automaton->corresponding_automaton_decl == NULL)
6340*38fd1498Szrj 	    fprintf (stderr, "Minimize anonymous DFA...");
6341*38fd1498Szrj 	  else
6342*38fd1498Szrj 	    fprintf (stderr, "Minimize DFA `%s'...",
6343*38fd1498Szrj 		     automaton->corresponding_automaton_decl->name);
6344*38fd1498Szrj 	}
6345*38fd1498Szrj       minimize_DFA (automaton);
6346*38fd1498Szrj       if (progress_flag)
6347*38fd1498Szrj 	fprintf (stderr, "done\n");
6348*38fd1498Szrj       ticker_off (&minimize_time);
6349*38fd1498Szrj       count_states_and_arcs (automaton, &states_num, &arcs_num);
6350*38fd1498Szrj       automaton->minimal_DFA_states_num = states_num;
6351*38fd1498Szrj       automaton->minimal_DFA_arcs_num = arcs_num;
6352*38fd1498Szrj     }
6353*38fd1498Szrj }
6354*38fd1498Szrj 
6355*38fd1498Szrj 
6356*38fd1498Szrj 
6357*38fd1498Szrj /* The page contains code for enumeration  of all states of an automaton.  */
6358*38fd1498Szrj 
6359*38fd1498Szrj /* Variable used for enumeration of all states of an automaton.  Its
6360*38fd1498Szrj    value is current number of automaton states.  */
6361*38fd1498Szrj static int curr_state_order_num;
6362*38fd1498Szrj 
6363*38fd1498Szrj /* The function is called by function `pass_states' for enumerating
6364*38fd1498Szrj    states.  */
6365*38fd1498Szrj static void
set_order_state_num(state_t state)6366*38fd1498Szrj set_order_state_num (state_t state)
6367*38fd1498Szrj {
6368*38fd1498Szrj   state->order_state_num = curr_state_order_num;
6369*38fd1498Szrj   curr_state_order_num++;
6370*38fd1498Szrj }
6371*38fd1498Szrj 
6372*38fd1498Szrj /* The function enumerates all states of AUTOMATON.  */
6373*38fd1498Szrj static void
enumerate_states(automaton_t automaton)6374*38fd1498Szrj enumerate_states (automaton_t automaton)
6375*38fd1498Szrj {
6376*38fd1498Szrj   curr_state_order_num = 0;
6377*38fd1498Szrj   pass_states (automaton, set_order_state_num);
6378*38fd1498Szrj   automaton->achieved_states_num = curr_state_order_num;
6379*38fd1498Szrj }
6380*38fd1498Szrj 
6381*38fd1498Szrj 
6382*38fd1498Szrj 
6383*38fd1498Szrj /* The page contains code for finding equivalent automaton insns
6384*38fd1498Szrj    (ainsns).  */
6385*38fd1498Szrj 
6386*38fd1498Szrj /* The function inserts AINSN into cyclic list
6387*38fd1498Szrj    CYCLIC_EQUIV_CLASS_INSN_LIST of ainsns.  */
6388*38fd1498Szrj static ainsn_t
insert_ainsn_into_equiv_class(ainsn_t ainsn,ainsn_t cyclic_equiv_class_insn_list)6389*38fd1498Szrj insert_ainsn_into_equiv_class (ainsn_t ainsn,
6390*38fd1498Szrj 			       ainsn_t cyclic_equiv_class_insn_list)
6391*38fd1498Szrj {
6392*38fd1498Szrj   if (cyclic_equiv_class_insn_list == NULL)
6393*38fd1498Szrj     ainsn->next_equiv_class_insn = ainsn;
6394*38fd1498Szrj   else
6395*38fd1498Szrj     {
6396*38fd1498Szrj       ainsn->next_equiv_class_insn
6397*38fd1498Szrj         = cyclic_equiv_class_insn_list->next_equiv_class_insn;
6398*38fd1498Szrj       cyclic_equiv_class_insn_list->next_equiv_class_insn = ainsn;
6399*38fd1498Szrj     }
6400*38fd1498Szrj   return ainsn;
6401*38fd1498Szrj }
6402*38fd1498Szrj 
6403*38fd1498Szrj /* The function deletes equiv_class_insn into cyclic list of
6404*38fd1498Szrj    equivalent ainsns.  */
6405*38fd1498Szrj static void
delete_ainsn_from_equiv_class(ainsn_t equiv_class_insn)6406*38fd1498Szrj delete_ainsn_from_equiv_class (ainsn_t equiv_class_insn)
6407*38fd1498Szrj {
6408*38fd1498Szrj   ainsn_t curr_equiv_class_insn;
6409*38fd1498Szrj   ainsn_t prev_equiv_class_insn;
6410*38fd1498Szrj 
6411*38fd1498Szrj   prev_equiv_class_insn = equiv_class_insn;
6412*38fd1498Szrj   for (curr_equiv_class_insn = equiv_class_insn->next_equiv_class_insn;
6413*38fd1498Szrj        curr_equiv_class_insn != equiv_class_insn;
6414*38fd1498Szrj        curr_equiv_class_insn = curr_equiv_class_insn->next_equiv_class_insn)
6415*38fd1498Szrj     prev_equiv_class_insn = curr_equiv_class_insn;
6416*38fd1498Szrj   if (prev_equiv_class_insn != equiv_class_insn)
6417*38fd1498Szrj     prev_equiv_class_insn->next_equiv_class_insn
6418*38fd1498Szrj       = equiv_class_insn->next_equiv_class_insn;
6419*38fd1498Szrj }
6420*38fd1498Szrj 
6421*38fd1498Szrj /* The function processes AINSN of a state in order to find equivalent
6422*38fd1498Szrj    ainsns.  INSN_ARCS_ARRAY is table: code of insn -> out arc of the
6423*38fd1498Szrj    state.  */
6424*38fd1498Szrj static void
process_insn_equiv_class(ainsn_t ainsn,arc_t * insn_arcs_array)6425*38fd1498Szrj process_insn_equiv_class (ainsn_t ainsn, arc_t *insn_arcs_array)
6426*38fd1498Szrj {
6427*38fd1498Szrj   ainsn_t next_insn;
6428*38fd1498Szrj   ainsn_t curr_insn;
6429*38fd1498Szrj   ainsn_t cyclic_insn_list;
6430*38fd1498Szrj   arc_t arc;
6431*38fd1498Szrj 
6432*38fd1498Szrj   gcc_assert (insn_arcs_array [ainsn->insn_reserv_decl->insn_num]);
6433*38fd1498Szrj   curr_insn = ainsn;
6434*38fd1498Szrj   /* New class of ainsns which are not equivalent to given ainsn.  */
6435*38fd1498Szrj   cyclic_insn_list = NULL;
6436*38fd1498Szrj   do
6437*38fd1498Szrj     {
6438*38fd1498Szrj       next_insn = curr_insn->next_equiv_class_insn;
6439*38fd1498Szrj       arc = insn_arcs_array [curr_insn->insn_reserv_decl->insn_num];
6440*38fd1498Szrj       if (arc == NULL
6441*38fd1498Szrj           || (insn_arcs_array [ainsn->insn_reserv_decl->insn_num]->to_state
6442*38fd1498Szrj               != arc->to_state))
6443*38fd1498Szrj         {
6444*38fd1498Szrj           delete_ainsn_from_equiv_class (curr_insn);
6445*38fd1498Szrj           cyclic_insn_list = insert_ainsn_into_equiv_class (curr_insn,
6446*38fd1498Szrj 							    cyclic_insn_list);
6447*38fd1498Szrj         }
6448*38fd1498Szrj       curr_insn = next_insn;
6449*38fd1498Szrj     }
6450*38fd1498Szrj   while (curr_insn != ainsn);
6451*38fd1498Szrj }
6452*38fd1498Szrj 
6453*38fd1498Szrj /* The function processes STATE in order to find equivalent ainsns.  */
6454*38fd1498Szrj static void
process_state_for_insn_equiv_partition(state_t state)6455*38fd1498Szrj process_state_for_insn_equiv_partition (state_t state)
6456*38fd1498Szrj {
6457*38fd1498Szrj   arc_t arc;
6458*38fd1498Szrj   arc_t *insn_arcs_array = XCNEWVEC (arc_t, description->insns_num);
6459*38fd1498Szrj 
6460*38fd1498Szrj   /* Process insns of the arcs.  */
6461*38fd1498Szrj   for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6462*38fd1498Szrj     insn_arcs_array [arc->insn->insn_reserv_decl->insn_num] = arc;
6463*38fd1498Szrj   for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6464*38fd1498Szrj     process_insn_equiv_class (arc->insn, insn_arcs_array);
6465*38fd1498Szrj 
6466*38fd1498Szrj   free (insn_arcs_array);
6467*38fd1498Szrj }
6468*38fd1498Szrj 
6469*38fd1498Szrj /* The function searches for equivalent ainsns of AUTOMATON.  */
6470*38fd1498Szrj static void
set_insn_equiv_classes(automaton_t automaton)6471*38fd1498Szrj set_insn_equiv_classes (automaton_t automaton)
6472*38fd1498Szrj {
6473*38fd1498Szrj   ainsn_t ainsn;
6474*38fd1498Szrj   ainsn_t first_insn;
6475*38fd1498Szrj   ainsn_t curr_insn;
6476*38fd1498Szrj   ainsn_t cyclic_insn_list;
6477*38fd1498Szrj   ainsn_t insn_with_same_reservs;
6478*38fd1498Szrj   int equiv_classes_num;
6479*38fd1498Szrj 
6480*38fd1498Szrj   /* All insns are included in one equivalence class.  */
6481*38fd1498Szrj   cyclic_insn_list = NULL;
6482*38fd1498Szrj   for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6483*38fd1498Szrj     if (ainsn->first_insn_with_same_reservs)
6484*38fd1498Szrj       cyclic_insn_list = insert_ainsn_into_equiv_class (ainsn,
6485*38fd1498Szrj 							cyclic_insn_list);
6486*38fd1498Szrj   /* Process insns in order to make equivalence partition.  */
6487*38fd1498Szrj   pass_states (automaton, process_state_for_insn_equiv_partition);
6488*38fd1498Szrj   /* Enumerate equiv classes.  */
6489*38fd1498Szrj   for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6490*38fd1498Szrj     /* Set undefined value.  */
6491*38fd1498Szrj     ainsn->insn_equiv_class_num = -1;
6492*38fd1498Szrj   equiv_classes_num = 0;
6493*38fd1498Szrj   for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6494*38fd1498Szrj     if (ainsn->insn_equiv_class_num < 0)
6495*38fd1498Szrj       {
6496*38fd1498Szrj         first_insn = ainsn;
6497*38fd1498Szrj         gcc_assert (first_insn->first_insn_with_same_reservs);
6498*38fd1498Szrj         first_insn->first_ainsn_with_given_equivalence_num = 1;
6499*38fd1498Szrj         curr_insn = first_insn;
6500*38fd1498Szrj         do
6501*38fd1498Szrj           {
6502*38fd1498Szrj             for (insn_with_same_reservs = curr_insn;
6503*38fd1498Szrj                  insn_with_same_reservs != NULL;
6504*38fd1498Szrj                  insn_with_same_reservs
6505*38fd1498Szrj 		   = insn_with_same_reservs->next_same_reservs_insn)
6506*38fd1498Szrj               insn_with_same_reservs->insn_equiv_class_num = equiv_classes_num;
6507*38fd1498Szrj             curr_insn = curr_insn->next_equiv_class_insn;
6508*38fd1498Szrj           }
6509*38fd1498Szrj         while (curr_insn != first_insn);
6510*38fd1498Szrj         equiv_classes_num++;
6511*38fd1498Szrj       }
6512*38fd1498Szrj   automaton->insn_equiv_classes_num = equiv_classes_num;
6513*38fd1498Szrj }
6514*38fd1498Szrj 
6515*38fd1498Szrj 
6516*38fd1498Szrj 
6517*38fd1498Szrj /* This page contains code for creating DFA(s) and calls functions
6518*38fd1498Szrj    building them.  */
6519*38fd1498Szrj 
6520*38fd1498Szrj 
6521*38fd1498Szrj /* The following value is used to prevent floating point overflow for
6522*38fd1498Szrj    estimating an automaton bound.  The value should be less DBL_MAX on
6523*38fd1498Szrj    the host machine.  We use here approximate minimum of maximal
6524*38fd1498Szrj    double floating point value required by ANSI C standard.  It
6525*38fd1498Szrj    will work for non ANSI sun compiler too.  */
6526*38fd1498Szrj 
6527*38fd1498Szrj #define MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND  1.0E37
6528*38fd1498Szrj 
6529*38fd1498Szrj /* The function estimate size of the single DFA used by PHR (pipeline
6530*38fd1498Szrj    hazards recognizer).  */
6531*38fd1498Szrj static double
estimate_one_automaton_bound(void)6532*38fd1498Szrj estimate_one_automaton_bound (void)
6533*38fd1498Szrj {
6534*38fd1498Szrj   decl_t decl;
6535*38fd1498Szrj   double one_automaton_estimation_bound;
6536*38fd1498Szrj   double root_value;
6537*38fd1498Szrj   int i;
6538*38fd1498Szrj 
6539*38fd1498Szrj   one_automaton_estimation_bound = 1.0;
6540*38fd1498Szrj   for (i = 0; i < description->decls_num; i++)
6541*38fd1498Szrj     {
6542*38fd1498Szrj       decl = description->decls [i];
6543*38fd1498Szrj       if (decl->mode == dm_unit)
6544*38fd1498Szrj 	{
6545*38fd1498Szrj 	  root_value = exp (log (DECL_UNIT (decl)->max_occ_cycle_num
6546*38fd1498Szrj 				 - DECL_UNIT (decl)->min_occ_cycle_num + 1.0)
6547*38fd1498Szrj                             / automata_num);
6548*38fd1498Szrj 	  if (MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND / root_value
6549*38fd1498Szrj 	      > one_automaton_estimation_bound)
6550*38fd1498Szrj 	    one_automaton_estimation_bound *= root_value;
6551*38fd1498Szrj 	}
6552*38fd1498Szrj     }
6553*38fd1498Szrj   return one_automaton_estimation_bound;
6554*38fd1498Szrj }
6555*38fd1498Szrj 
6556*38fd1498Szrj /* The function compares unit declarations according to their maximal
6557*38fd1498Szrj    cycle in reservations.  */
6558*38fd1498Szrj static int
compare_max_occ_cycle_nums(const void * unit_decl_1,const void * unit_decl_2)6559*38fd1498Szrj compare_max_occ_cycle_nums (const void *unit_decl_1,
6560*38fd1498Szrj 			    const void *unit_decl_2)
6561*38fd1498Szrj {
6562*38fd1498Szrj   if ((DECL_UNIT (*(const_decl_t const*) unit_decl_1)->max_occ_cycle_num)
6563*38fd1498Szrj       < (DECL_UNIT (*(const_decl_t const*) unit_decl_2)->max_occ_cycle_num))
6564*38fd1498Szrj     return 1;
6565*38fd1498Szrj   else if ((DECL_UNIT (*(const_decl_t const*) unit_decl_1)->max_occ_cycle_num)
6566*38fd1498Szrj 	   == (DECL_UNIT (*(const_decl_t const*) unit_decl_2)->max_occ_cycle_num))
6567*38fd1498Szrj     return 0;
6568*38fd1498Szrj   else
6569*38fd1498Szrj     return -1;
6570*38fd1498Szrj }
6571*38fd1498Szrj 
6572*38fd1498Szrj /* The function makes heuristic assigning automata to units.  Actually
6573*38fd1498Szrj    efficacy of the algorithm has been checked yet??? */
6574*38fd1498Szrj 
6575*38fd1498Szrj static void
units_to_automata_heuristic_distr(void)6576*38fd1498Szrj units_to_automata_heuristic_distr (void)
6577*38fd1498Szrj {
6578*38fd1498Szrj   double estimation_bound;
6579*38fd1498Szrj   int automaton_num;
6580*38fd1498Szrj   int rest_units_num;
6581*38fd1498Szrj   double bound_value;
6582*38fd1498Szrj   unit_decl_t *unit_decls;
6583*38fd1498Szrj   int i, j;
6584*38fd1498Szrj 
6585*38fd1498Szrj   if (description->units_num == 0)
6586*38fd1498Szrj     return;
6587*38fd1498Szrj   estimation_bound = estimate_one_automaton_bound ();
6588*38fd1498Szrj   unit_decls = XNEWVEC (unit_decl_t, description->units_num);
6589*38fd1498Szrj 
6590*38fd1498Szrj   for (i = 0, j = 0; i < description->decls_num; i++)
6591*38fd1498Szrj     if (description->decls[i]->mode == dm_unit)
6592*38fd1498Szrj       unit_decls[j++] = DECL_UNIT (description->decls[i]);
6593*38fd1498Szrj   gcc_assert (j == description->units_num);
6594*38fd1498Szrj 
6595*38fd1498Szrj   qsort (unit_decls, description->units_num,
6596*38fd1498Szrj          sizeof (unit_decl_t), compare_max_occ_cycle_nums);
6597*38fd1498Szrj 
6598*38fd1498Szrj   automaton_num = 0;
6599*38fd1498Szrj   bound_value = unit_decls[0]->max_occ_cycle_num;
6600*38fd1498Szrj   unit_decls[0]->corresponding_automaton_num = automaton_num;
6601*38fd1498Szrj 
6602*38fd1498Szrj   for (i = 1; i < description->units_num; i++)
6603*38fd1498Szrj     {
6604*38fd1498Szrj       rest_units_num = description->units_num - i + 1;
6605*38fd1498Szrj       gcc_assert (automata_num - automaton_num - 1 <= rest_units_num);
6606*38fd1498Szrj       if (automaton_num < automata_num - 1
6607*38fd1498Szrj           && ((automata_num - automaton_num - 1 == rest_units_num)
6608*38fd1498Szrj               || (bound_value
6609*38fd1498Szrj                   > (estimation_bound
6610*38fd1498Szrj 		     / unit_decls[i]->max_occ_cycle_num))))
6611*38fd1498Szrj         {
6612*38fd1498Szrj           bound_value = unit_decls[i]->max_occ_cycle_num;
6613*38fd1498Szrj           automaton_num++;
6614*38fd1498Szrj         }
6615*38fd1498Szrj       else
6616*38fd1498Szrj         bound_value *= unit_decls[i]->max_occ_cycle_num;
6617*38fd1498Szrj       unit_decls[i]->corresponding_automaton_num = automaton_num;
6618*38fd1498Szrj     }
6619*38fd1498Szrj   gcc_assert (automaton_num == automata_num - 1);
6620*38fd1498Szrj   free (unit_decls);
6621*38fd1498Szrj }
6622*38fd1498Szrj 
6623*38fd1498Szrj /* The functions creates automaton insns for each automata.  Automaton
6624*38fd1498Szrj    insn is simply insn for given automaton which makes reservation
6625*38fd1498Szrj    only of units of the automaton.  */
6626*38fd1498Szrj static void
create_ainsns(automaton_t automaton)6627*38fd1498Szrj create_ainsns (automaton_t automaton)
6628*38fd1498Szrj {
6629*38fd1498Szrj   decl_t decl;
6630*38fd1498Szrj   ainsn_t first_ainsn;
6631*38fd1498Szrj   ainsn_t curr_ainsn;
6632*38fd1498Szrj   ainsn_t prev_ainsn;
6633*38fd1498Szrj   int i;
6634*38fd1498Szrj 
6635*38fd1498Szrj   first_ainsn = NULL;
6636*38fd1498Szrj   prev_ainsn = NULL;
6637*38fd1498Szrj   for (i = 0; i < description->decls_num; i++)
6638*38fd1498Szrj     {
6639*38fd1498Szrj       decl = description->decls [i];
6640*38fd1498Szrj       if (decl->mode == dm_insn_reserv)
6641*38fd1498Szrj 	{
6642*38fd1498Szrj 	  curr_ainsn = XCREATENODE (struct ainsn);
6643*38fd1498Szrj 	  curr_ainsn->insn_reserv_decl = DECL_INSN_RESERV (decl);
6644*38fd1498Szrj 	  curr_ainsn->important_p = FALSE;
6645*38fd1498Szrj 	  curr_ainsn->next_ainsn = NULL;
6646*38fd1498Szrj 	  if (prev_ainsn == NULL)
6647*38fd1498Szrj 	    first_ainsn = curr_ainsn;
6648*38fd1498Szrj 	  else
6649*38fd1498Szrj 	    prev_ainsn->next_ainsn = curr_ainsn;
6650*38fd1498Szrj 	  if (decl == advance_cycle_insn_decl)
6651*38fd1498Szrj 	    automaton->advance_ainsn = curr_ainsn;
6652*38fd1498Szrj 	  else if (decl == collapse_ndfa_insn_decl)
6653*38fd1498Szrj 	    automaton->collapse_ainsn = curr_ainsn;
6654*38fd1498Szrj 	  prev_ainsn = curr_ainsn;
6655*38fd1498Szrj 	}
6656*38fd1498Szrj     }
6657*38fd1498Szrj   automaton->ainsn_list = first_ainsn;
6658*38fd1498Szrj }
6659*38fd1498Szrj 
6660*38fd1498Szrj /* The function assigns automata to units according to constructions
6661*38fd1498Szrj    `define_automaton' in the description.  */
6662*38fd1498Szrj static void
units_to_automata_distr(void)6663*38fd1498Szrj units_to_automata_distr (void)
6664*38fd1498Szrj {
6665*38fd1498Szrj   decl_t decl;
6666*38fd1498Szrj   int i;
6667*38fd1498Szrj 
6668*38fd1498Szrj   for (i = 0; i < description->decls_num; i++)
6669*38fd1498Szrj     {
6670*38fd1498Szrj       decl = description->decls [i];
6671*38fd1498Szrj       if (decl->mode == dm_unit)
6672*38fd1498Szrj 	{
6673*38fd1498Szrj 	  if (DECL_UNIT (decl)->automaton_decl == NULL
6674*38fd1498Szrj 	      || (DECL_UNIT (decl)->automaton_decl->corresponding_automaton
6675*38fd1498Szrj 		  == NULL))
6676*38fd1498Szrj 	    /* Distribute to the first automaton.  */
6677*38fd1498Szrj 	    DECL_UNIT (decl)->corresponding_automaton_num = 0;
6678*38fd1498Szrj 	  else
6679*38fd1498Szrj 	    DECL_UNIT (decl)->corresponding_automaton_num
6680*38fd1498Szrj 	      = (DECL_UNIT (decl)->automaton_decl
6681*38fd1498Szrj                  ->corresponding_automaton->automaton_order_num);
6682*38fd1498Szrj 	}
6683*38fd1498Szrj     }
6684*38fd1498Szrj }
6685*38fd1498Szrj 
6686*38fd1498Szrj /* The function creates DFA(s) for fast pipeline hazards recognition
6687*38fd1498Szrj    after checking and simplifying IR of the description.  */
6688*38fd1498Szrj static void
create_automata(void)6689*38fd1498Szrj create_automata (void)
6690*38fd1498Szrj {
6691*38fd1498Szrj   automaton_t curr_automaton;
6692*38fd1498Szrj   automaton_t prev_automaton;
6693*38fd1498Szrj   decl_t decl;
6694*38fd1498Szrj   int curr_automaton_num;
6695*38fd1498Szrj   int i;
6696*38fd1498Szrj 
6697*38fd1498Szrj   if (automata_num != 0)
6698*38fd1498Szrj     {
6699*38fd1498Szrj       units_to_automata_heuristic_distr ();
6700*38fd1498Szrj       for (prev_automaton = NULL, curr_automaton_num = 0;
6701*38fd1498Szrj            curr_automaton_num < automata_num;
6702*38fd1498Szrj            curr_automaton_num++, prev_automaton = curr_automaton)
6703*38fd1498Szrj         {
6704*38fd1498Szrj 	  curr_automaton = XCREATENODE (struct automaton);
6705*38fd1498Szrj 	  create_ainsns (curr_automaton);
6706*38fd1498Szrj 	  curr_automaton->corresponding_automaton_decl = NULL;
6707*38fd1498Szrj 	  curr_automaton->next_automaton = NULL;
6708*38fd1498Szrj           curr_automaton->automaton_order_num = curr_automaton_num;
6709*38fd1498Szrj           if (prev_automaton == NULL)
6710*38fd1498Szrj             description->first_automaton = curr_automaton;
6711*38fd1498Szrj           else
6712*38fd1498Szrj             prev_automaton->next_automaton = curr_automaton;
6713*38fd1498Szrj         }
6714*38fd1498Szrj     }
6715*38fd1498Szrj   else
6716*38fd1498Szrj     {
6717*38fd1498Szrj       curr_automaton_num = 0;
6718*38fd1498Szrj       prev_automaton = NULL;
6719*38fd1498Szrj       for (i = 0; i < description->decls_num; i++)
6720*38fd1498Szrj 	{
6721*38fd1498Szrj 	  decl = description->decls [i];
6722*38fd1498Szrj 	  if (decl->mode == dm_automaton
6723*38fd1498Szrj 	      && DECL_AUTOMATON (decl)->automaton_is_used)
6724*38fd1498Szrj 	    {
6725*38fd1498Szrj 	      curr_automaton = XCREATENODE (struct automaton);
6726*38fd1498Szrj 	      create_ainsns (curr_automaton);
6727*38fd1498Szrj 	      curr_automaton->corresponding_automaton_decl
6728*38fd1498Szrj 		= DECL_AUTOMATON (decl);
6729*38fd1498Szrj 	      curr_automaton->next_automaton = NULL;
6730*38fd1498Szrj 	      DECL_AUTOMATON (decl)->corresponding_automaton = curr_automaton;
6731*38fd1498Szrj 	      curr_automaton->automaton_order_num = curr_automaton_num;
6732*38fd1498Szrj 	      if (prev_automaton == NULL)
6733*38fd1498Szrj 		description->first_automaton = curr_automaton;
6734*38fd1498Szrj 	      else
6735*38fd1498Szrj 		prev_automaton->next_automaton = curr_automaton;
6736*38fd1498Szrj 	      curr_automaton_num++;
6737*38fd1498Szrj 	      prev_automaton = curr_automaton;
6738*38fd1498Szrj 	    }
6739*38fd1498Szrj 	}
6740*38fd1498Szrj       if (curr_automaton_num == 0)
6741*38fd1498Szrj 	{
6742*38fd1498Szrj 	  curr_automaton = XCREATENODE (struct automaton);
6743*38fd1498Szrj 	  create_ainsns (curr_automaton);
6744*38fd1498Szrj 	  curr_automaton->corresponding_automaton_decl = NULL;
6745*38fd1498Szrj 	  curr_automaton->next_automaton = NULL;
6746*38fd1498Szrj 	  description->first_automaton = curr_automaton;
6747*38fd1498Szrj 	}
6748*38fd1498Szrj       units_to_automata_distr ();
6749*38fd1498Szrj     }
6750*38fd1498Szrj   NDFA_time = create_ticker ();
6751*38fd1498Szrj   ticker_off (&NDFA_time);
6752*38fd1498Szrj   NDFA_to_DFA_time = create_ticker ();
6753*38fd1498Szrj   ticker_off (&NDFA_to_DFA_time);
6754*38fd1498Szrj   minimize_time = create_ticker ();
6755*38fd1498Szrj   ticker_off (&minimize_time);
6756*38fd1498Szrj   equiv_time = create_ticker ();
6757*38fd1498Szrj   ticker_off (&equiv_time);
6758*38fd1498Szrj   for (curr_automaton = description->first_automaton;
6759*38fd1498Szrj        curr_automaton != NULL;
6760*38fd1498Szrj        curr_automaton = curr_automaton->next_automaton)
6761*38fd1498Szrj     {
6762*38fd1498Szrj       if (progress_flag)
6763*38fd1498Szrj 	{
6764*38fd1498Szrj 	  if (curr_automaton->corresponding_automaton_decl == NULL)
6765*38fd1498Szrj 	    fprintf (stderr, "Prepare anonymous automaton creation ... ");
6766*38fd1498Szrj 	  else
6767*38fd1498Szrj 	    fprintf (stderr, "Prepare automaton `%s' creation...",
6768*38fd1498Szrj 		     curr_automaton->corresponding_automaton_decl->name);
6769*38fd1498Szrj 	}
6770*38fd1498Szrj       create_alt_states (curr_automaton);
6771*38fd1498Szrj       form_ainsn_with_same_reservs (curr_automaton);
6772*38fd1498Szrj       if (progress_flag)
6773*38fd1498Szrj 	fprintf (stderr, "done\n");
6774*38fd1498Szrj       build_automaton (curr_automaton);
6775*38fd1498Szrj       enumerate_states (curr_automaton);
6776*38fd1498Szrj       ticker_on (&equiv_time);
6777*38fd1498Szrj       set_insn_equiv_classes (curr_automaton);
6778*38fd1498Szrj       ticker_off (&equiv_time);
6779*38fd1498Szrj     }
6780*38fd1498Szrj }
6781*38fd1498Szrj 
6782*38fd1498Szrj 
6783*38fd1498Szrj 
6784*38fd1498Szrj /* This page contains code for forming string representation of
6785*38fd1498Szrj    regexp.  The representation is formed on IR obstack.  So you should
6786*38fd1498Szrj    not work with IR obstack between regexp_representation and
6787*38fd1498Szrj    finish_regexp_representation calls.  */
6788*38fd1498Szrj 
6789*38fd1498Szrj /* This recursive function forms string representation of regexp
6790*38fd1498Szrj    (without tailing '\0').  */
6791*38fd1498Szrj static void
form_regexp(regexp_t regexp)6792*38fd1498Szrj form_regexp (regexp_t regexp)
6793*38fd1498Szrj {
6794*38fd1498Szrj   int i;
6795*38fd1498Szrj 
6796*38fd1498Szrj   switch (regexp->mode)
6797*38fd1498Szrj     {
6798*38fd1498Szrj     case rm_unit: case rm_reserv:
6799*38fd1498Szrj       {
6800*38fd1498Szrj 	const char *name = (regexp->mode == rm_unit
6801*38fd1498Szrj 			    ? REGEXP_UNIT (regexp)->name
6802*38fd1498Szrj 			    : REGEXP_RESERV (regexp)->name);
6803*38fd1498Szrj 
6804*38fd1498Szrj 	obstack_grow (&irp, name, strlen (name));
6805*38fd1498Szrj 	break;
6806*38fd1498Szrj       }
6807*38fd1498Szrj 
6808*38fd1498Szrj     case rm_sequence:
6809*38fd1498Szrj       for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
6810*38fd1498Szrj 	{
6811*38fd1498Szrj 	  if (i != 0)
6812*38fd1498Szrj 	    obstack_1grow (&irp, ',');
6813*38fd1498Szrj 	  form_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
6814*38fd1498Szrj 	}
6815*38fd1498Szrj       break;
6816*38fd1498Szrj 
6817*38fd1498Szrj     case rm_allof:
6818*38fd1498Szrj       obstack_1grow (&irp, '(');
6819*38fd1498Szrj       for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
6820*38fd1498Szrj 	{
6821*38fd1498Szrj 	  if (i != 0)
6822*38fd1498Szrj             obstack_1grow (&irp, '+');
6823*38fd1498Szrj 	  if (REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_sequence
6824*38fd1498Szrj               || REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_oneof)
6825*38fd1498Szrj             obstack_1grow (&irp, '(');
6826*38fd1498Szrj 	  form_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
6827*38fd1498Szrj 	  if (REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_sequence
6828*38fd1498Szrj               || REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_oneof)
6829*38fd1498Szrj             obstack_1grow (&irp, ')');
6830*38fd1498Szrj         }
6831*38fd1498Szrj       obstack_1grow (&irp, ')');
6832*38fd1498Szrj       break;
6833*38fd1498Szrj 
6834*38fd1498Szrj     case rm_oneof:
6835*38fd1498Szrj       for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
6836*38fd1498Szrj 	{
6837*38fd1498Szrj 	  if (i != 0)
6838*38fd1498Szrj 	    obstack_1grow (&irp, '|');
6839*38fd1498Szrj 	  if (REGEXP_ONEOF (regexp)->regexps[i]->mode == rm_sequence)
6840*38fd1498Szrj 	    obstack_1grow (&irp, '(');
6841*38fd1498Szrj 	  form_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
6842*38fd1498Szrj 	  if (REGEXP_ONEOF (regexp)->regexps[i]->mode == rm_sequence)
6843*38fd1498Szrj           obstack_1grow (&irp, ')');
6844*38fd1498Szrj 	}
6845*38fd1498Szrj       break;
6846*38fd1498Szrj 
6847*38fd1498Szrj     case rm_repeat:
6848*38fd1498Szrj       {
6849*38fd1498Szrj 	char digits [30];
6850*38fd1498Szrj 
6851*38fd1498Szrj 	if (REGEXP_REPEAT (regexp)->regexp->mode == rm_sequence
6852*38fd1498Szrj 	    || REGEXP_REPEAT (regexp)->regexp->mode == rm_allof
6853*38fd1498Szrj 	    || REGEXP_REPEAT (regexp)->regexp->mode == rm_oneof)
6854*38fd1498Szrj 	  obstack_1grow (&irp, '(');
6855*38fd1498Szrj 	form_regexp (REGEXP_REPEAT (regexp)->regexp);
6856*38fd1498Szrj 	if (REGEXP_REPEAT (regexp)->regexp->mode == rm_sequence
6857*38fd1498Szrj 	    || REGEXP_REPEAT (regexp)->regexp->mode == rm_allof
6858*38fd1498Szrj 	    || REGEXP_REPEAT (regexp)->regexp->mode == rm_oneof)
6859*38fd1498Szrj 	  obstack_1grow (&irp, ')');
6860*38fd1498Szrj 	sprintf (digits, "*%d", REGEXP_REPEAT (regexp)->repeat_num);
6861*38fd1498Szrj 	obstack_grow (&irp, digits, strlen (digits));
6862*38fd1498Szrj 	break;
6863*38fd1498Szrj       }
6864*38fd1498Szrj 
6865*38fd1498Szrj     case rm_nothing:
6866*38fd1498Szrj       obstack_grow (&irp, NOTHING_NAME, strlen (NOTHING_NAME));
6867*38fd1498Szrj       break;
6868*38fd1498Szrj 
6869*38fd1498Szrj     default:
6870*38fd1498Szrj       gcc_unreachable ();
6871*38fd1498Szrj     }
6872*38fd1498Szrj }
6873*38fd1498Szrj 
6874*38fd1498Szrj /* The function returns string representation of REGEXP on IR
6875*38fd1498Szrj    obstack.  */
6876*38fd1498Szrj static const char *
regexp_representation(regexp_t regexp)6877*38fd1498Szrj regexp_representation (regexp_t regexp)
6878*38fd1498Szrj {
6879*38fd1498Szrj   form_regexp (regexp);
6880*38fd1498Szrj   obstack_1grow (&irp, '\0');
6881*38fd1498Szrj   return (char *) obstack_base (&irp);
6882*38fd1498Szrj }
6883*38fd1498Szrj 
6884*38fd1498Szrj /* The function frees memory allocated for last formed string
6885*38fd1498Szrj    representation of regexp.  */
6886*38fd1498Szrj static void
finish_regexp_representation(void)6887*38fd1498Szrj finish_regexp_representation (void)
6888*38fd1498Szrj {
6889*38fd1498Szrj   int length = obstack_object_size (&irp);
6890*38fd1498Szrj 
6891*38fd1498Szrj   obstack_blank_fast (&irp, -length);
6892*38fd1498Szrj }
6893*38fd1498Szrj 
6894*38fd1498Szrj 
6895*38fd1498Szrj 
6896*38fd1498Szrj /* This page contains code for output PHR (pipeline hazards recognizer).  */
6897*38fd1498Szrj 
6898*38fd1498Szrj /* The function outputs minimal C type which is sufficient for
6899*38fd1498Szrj    representation numbers in range min_range_value and
6900*38fd1498Szrj    max_range_value.  Because host machine and build machine may be
6901*38fd1498Szrj    different, we use here minimal values required by ANSI C standard
6902*38fd1498Szrj    instead of UCHAR_MAX, SHRT_MAX, SHRT_MIN, etc.  This is a good
6903*38fd1498Szrj    approximation.  */
6904*38fd1498Szrj 
6905*38fd1498Szrj static void
output_range_type(FILE * f,long int min_range_value,long int max_range_value)6906*38fd1498Szrj output_range_type (FILE *f, long int min_range_value,
6907*38fd1498Szrj 		   long int max_range_value)
6908*38fd1498Szrj {
6909*38fd1498Szrj   if (min_range_value >= 0 && max_range_value <= 255)
6910*38fd1498Szrj     fprintf (f, "unsigned char");
6911*38fd1498Szrj   else if (min_range_value >= -127 && max_range_value <= 127)
6912*38fd1498Szrj     fprintf (f, "signed char");
6913*38fd1498Szrj   else if (min_range_value >= 0 && max_range_value <= 65535)
6914*38fd1498Szrj     fprintf (f, "unsigned short");
6915*38fd1498Szrj   else if (min_range_value >= -32767 && max_range_value <= 32767)
6916*38fd1498Szrj     fprintf (f, "short");
6917*38fd1498Szrj   else
6918*38fd1498Szrj     fprintf (f, "int");
6919*38fd1498Szrj }
6920*38fd1498Szrj 
6921*38fd1498Szrj /* The function outputs all initialization values of VECT.  */
6922*38fd1498Szrj static void
output_vect(vla_hwint_t vect)6923*38fd1498Szrj output_vect (vla_hwint_t vect)
6924*38fd1498Szrj {
6925*38fd1498Szrj   int els_on_line;
6926*38fd1498Szrj   size_t vect_length = vect.length ();
6927*38fd1498Szrj   size_t i;
6928*38fd1498Szrj 
6929*38fd1498Szrj   els_on_line = 1;
6930*38fd1498Szrj   if (vect_length == 0)
6931*38fd1498Szrj     fputs ("0 /* This is dummy el because the vect is empty */", output_file);
6932*38fd1498Szrj   else
6933*38fd1498Szrj     for (i = 0; i < vect_length; i++)
6934*38fd1498Szrj       {
6935*38fd1498Szrj 	fprintf (output_file, "%5ld", (long) vect[i]);
6936*38fd1498Szrj 	if (els_on_line == 10)
6937*38fd1498Szrj 	  {
6938*38fd1498Szrj 	    els_on_line = 0;
6939*38fd1498Szrj 	    fputs (",\n", output_file);
6940*38fd1498Szrj 	  }
6941*38fd1498Szrj 	else if (i < vect_length-1)
6942*38fd1498Szrj 	  fputs (", ", output_file);
6943*38fd1498Szrj 	els_on_line++;
6944*38fd1498Szrj       }
6945*38fd1498Szrj }
6946*38fd1498Szrj 
6947*38fd1498Szrj /* The following is name of the structure which represents DFA(s) for
6948*38fd1498Szrj    PHR.  */
6949*38fd1498Szrj #define CHIP_NAME "DFA_chip"
6950*38fd1498Szrj 
6951*38fd1498Szrj /* The following is name of member which represents state of a DFA for
6952*38fd1498Szrj    PHR.  */
6953*38fd1498Szrj static void
output_chip_member_name(FILE * f,automaton_t automaton)6954*38fd1498Szrj output_chip_member_name (FILE *f, automaton_t automaton)
6955*38fd1498Szrj {
6956*38fd1498Szrj   if (automaton->corresponding_automaton_decl == NULL)
6957*38fd1498Szrj     fprintf (f, "automaton_state_%d", automaton->automaton_order_num);
6958*38fd1498Szrj   else
6959*38fd1498Szrj     fprintf (f, "%s_automaton_state",
6960*38fd1498Szrj              automaton->corresponding_automaton_decl->name);
6961*38fd1498Szrj }
6962*38fd1498Szrj 
6963*38fd1498Szrj /* The following is name of temporary variable which stores state of a
6964*38fd1498Szrj    DFA for PHR.  */
6965*38fd1498Szrj static void
output_temp_chip_member_name(FILE * f,automaton_t automaton)6966*38fd1498Szrj output_temp_chip_member_name (FILE *f, automaton_t automaton)
6967*38fd1498Szrj {
6968*38fd1498Szrj   fprintf (f, "_");
6969*38fd1498Szrj   output_chip_member_name (f, automaton);
6970*38fd1498Szrj }
6971*38fd1498Szrj 
6972*38fd1498Szrj /* This is name of macro value which is code of pseudo_insns
6973*38fd1498Szrj    representing advancing cpu cycle and collapsing the NDFA.
6974*38fd1498Szrj    Its value is used as internal code unknown insn.  */
6975*38fd1498Szrj #define ADVANCE_CYCLE_VALUE_NAME "DFA__ADVANCE_CYCLE"
6976*38fd1498Szrj #define COLLAPSE_NDFA_VALUE_NAME "NDFA__COLLAPSE"
6977*38fd1498Szrj 
6978*38fd1498Szrj /* Output name of translate vector for given automaton.  */
6979*38fd1498Szrj static void
output_translate_vect_name(FILE * f,automaton_t automaton)6980*38fd1498Szrj output_translate_vect_name (FILE *f, automaton_t automaton)
6981*38fd1498Szrj {
6982*38fd1498Szrj   if (automaton->corresponding_automaton_decl == NULL)
6983*38fd1498Szrj     fprintf (f, "translate_%d", automaton->automaton_order_num);
6984*38fd1498Szrj   else
6985*38fd1498Szrj     fprintf (f, "%s_translate", automaton->corresponding_automaton_decl->name);
6986*38fd1498Szrj }
6987*38fd1498Szrj 
6988*38fd1498Szrj /* Output name for simple transition table representation.  */
6989*38fd1498Szrj static void
output_trans_full_vect_name(FILE * f,automaton_t automaton)6990*38fd1498Szrj output_trans_full_vect_name (FILE *f, automaton_t automaton)
6991*38fd1498Szrj {
6992*38fd1498Szrj   if (automaton->corresponding_automaton_decl == NULL)
6993*38fd1498Szrj     fprintf (f, "transitions_%d", automaton->automaton_order_num);
6994*38fd1498Szrj   else
6995*38fd1498Szrj     fprintf (f, "%s_transitions",
6996*38fd1498Szrj 	     automaton->corresponding_automaton_decl->name);
6997*38fd1498Szrj }
6998*38fd1498Szrj 
6999*38fd1498Szrj /* Output name of comb vector of the transition table for given
7000*38fd1498Szrj    automaton.  */
7001*38fd1498Szrj static void
output_trans_comb_vect_name(FILE * f,automaton_t automaton)7002*38fd1498Szrj output_trans_comb_vect_name (FILE *f, automaton_t automaton)
7003*38fd1498Szrj {
7004*38fd1498Szrj   if (automaton->corresponding_automaton_decl == NULL)
7005*38fd1498Szrj     fprintf (f, "transitions_%d", automaton->automaton_order_num);
7006*38fd1498Szrj   else
7007*38fd1498Szrj     fprintf (f, "%s_transitions",
7008*38fd1498Szrj              automaton->corresponding_automaton_decl->name);
7009*38fd1498Szrj }
7010*38fd1498Szrj 
7011*38fd1498Szrj /* Output name of check vector of the transition table for given
7012*38fd1498Szrj    automaton.  */
7013*38fd1498Szrj static void
output_trans_check_vect_name(FILE * f,automaton_t automaton)7014*38fd1498Szrj output_trans_check_vect_name (FILE *f, automaton_t automaton)
7015*38fd1498Szrj {
7016*38fd1498Szrj   if (automaton->corresponding_automaton_decl == NULL)
7017*38fd1498Szrj     fprintf (f, "check_%d", automaton->automaton_order_num);
7018*38fd1498Szrj   else
7019*38fd1498Szrj     fprintf (f, "%s_check", automaton->corresponding_automaton_decl->name);
7020*38fd1498Szrj }
7021*38fd1498Szrj 
7022*38fd1498Szrj /* Output name of base vector of the transition table for given
7023*38fd1498Szrj    automaton.  */
7024*38fd1498Szrj static void
output_trans_base_vect_name(FILE * f,automaton_t automaton)7025*38fd1498Szrj output_trans_base_vect_name (FILE *f, automaton_t automaton)
7026*38fd1498Szrj {
7027*38fd1498Szrj   if (automaton->corresponding_automaton_decl == NULL)
7028*38fd1498Szrj     fprintf (f, "base_%d", automaton->automaton_order_num);
7029*38fd1498Szrj   else
7030*38fd1498Szrj     fprintf (f, "%s_base", automaton->corresponding_automaton_decl->name);
7031*38fd1498Szrj }
7032*38fd1498Szrj 
7033*38fd1498Szrj /* Output name of simple min issue delay table representation.  */
7034*38fd1498Szrj static void
output_min_issue_delay_vect_name(FILE * f,automaton_t automaton)7035*38fd1498Szrj output_min_issue_delay_vect_name (FILE *f, automaton_t automaton)
7036*38fd1498Szrj {
7037*38fd1498Szrj   if (automaton->corresponding_automaton_decl == NULL)
7038*38fd1498Szrj     fprintf (f, "min_issue_delay_%d", automaton->automaton_order_num);
7039*38fd1498Szrj   else
7040*38fd1498Szrj     fprintf (f, "%s_min_issue_delay",
7041*38fd1498Szrj              automaton->corresponding_automaton_decl->name);
7042*38fd1498Szrj }
7043*38fd1498Szrj 
7044*38fd1498Szrj /* Output name of deadlock vector for given automaton.  */
7045*38fd1498Szrj static void
output_dead_lock_vect_name(FILE * f,automaton_t automaton)7046*38fd1498Szrj output_dead_lock_vect_name (FILE *f, automaton_t automaton)
7047*38fd1498Szrj {
7048*38fd1498Szrj   if (automaton->corresponding_automaton_decl == NULL)
7049*38fd1498Szrj     fprintf (f, "dead_lock_%d", automaton->automaton_order_num);
7050*38fd1498Szrj   else
7051*38fd1498Szrj     fprintf (f, "%s_dead_lock", automaton->corresponding_automaton_decl->name);
7052*38fd1498Szrj }
7053*38fd1498Szrj 
7054*38fd1498Szrj /* Output name of reserved units table for AUTOMATON into file F.  */
7055*38fd1498Szrj static void
output_reserved_units_table_name(FILE * f,automaton_t automaton)7056*38fd1498Szrj output_reserved_units_table_name (FILE *f, automaton_t automaton)
7057*38fd1498Szrj {
7058*38fd1498Szrj   if (automaton->corresponding_automaton_decl == NULL)
7059*38fd1498Szrj     fprintf (f, "reserved_units_%d", automaton->automaton_order_num);
7060*38fd1498Szrj   else
7061*38fd1498Szrj     fprintf (f, "%s_reserved_units",
7062*38fd1498Szrj 	     automaton->corresponding_automaton_decl->name);
7063*38fd1498Szrj }
7064*38fd1498Szrj 
7065*38fd1498Szrj /* Name of the PHR interface macro.  */
7066*38fd1498Szrj #define CPU_UNITS_QUERY_MACRO_NAME "CPU_UNITS_QUERY"
7067*38fd1498Szrj 
7068*38fd1498Szrj /* Names of an internal functions: */
7069*38fd1498Szrj #define INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME "internal_min_issue_delay"
7070*38fd1498Szrj 
7071*38fd1498Szrj /* This is external type of DFA(s) state.  */
7072*38fd1498Szrj #define STATE_TYPE_NAME "state_t"
7073*38fd1498Szrj 
7074*38fd1498Szrj #define INTERNAL_TRANSITION_FUNC_NAME "internal_state_transition"
7075*38fd1498Szrj 
7076*38fd1498Szrj #define INTERNAL_RESET_FUNC_NAME "internal_reset"
7077*38fd1498Szrj 
7078*38fd1498Szrj #define INTERNAL_DEAD_LOCK_FUNC_NAME "internal_state_dead_lock_p"
7079*38fd1498Szrj 
7080*38fd1498Szrj #define INTERNAL_INSN_LATENCY_FUNC_NAME "internal_insn_latency"
7081*38fd1498Szrj 
7082*38fd1498Szrj /* Name of cache of insn dfa codes.  */
7083*38fd1498Szrj #define DFA_INSN_CODES_VARIABLE_NAME "dfa_insn_codes"
7084*38fd1498Szrj 
7085*38fd1498Szrj /* Name of length of cache of insn dfa codes.  */
7086*38fd1498Szrj #define DFA_INSN_CODES_LENGTH_VARIABLE_NAME "dfa_insn_codes_length"
7087*38fd1498Szrj 
7088*38fd1498Szrj /* Names of the PHR interface functions: */
7089*38fd1498Szrj #define SIZE_FUNC_NAME "state_size"
7090*38fd1498Szrj 
7091*38fd1498Szrj #define TRANSITION_FUNC_NAME "state_transition"
7092*38fd1498Szrj 
7093*38fd1498Szrj #define MIN_ISSUE_DELAY_FUNC_NAME "min_issue_delay"
7094*38fd1498Szrj 
7095*38fd1498Szrj #define MIN_INSN_CONFLICT_DELAY_FUNC_NAME "min_insn_conflict_delay"
7096*38fd1498Szrj 
7097*38fd1498Szrj #define DEAD_LOCK_FUNC_NAME "state_dead_lock_p"
7098*38fd1498Szrj 
7099*38fd1498Szrj #define RESET_FUNC_NAME "state_reset"
7100*38fd1498Szrj 
7101*38fd1498Szrj #define INSN_LATENCY_FUNC_NAME "insn_latency"
7102*38fd1498Szrj 
7103*38fd1498Szrj #define PRINT_RESERVATION_FUNC_NAME "print_reservation"
7104*38fd1498Szrj 
7105*38fd1498Szrj #define GET_CPU_UNIT_CODE_FUNC_NAME "get_cpu_unit_code"
7106*38fd1498Szrj 
7107*38fd1498Szrj #define CPU_UNIT_RESERVATION_P_FUNC_NAME "cpu_unit_reservation_p"
7108*38fd1498Szrj 
7109*38fd1498Szrj #define INSN_HAS_DFA_RESERVATION_P_FUNC_NAME "insn_has_dfa_reservation_p"
7110*38fd1498Szrj 
7111*38fd1498Szrj #define DFA_CLEAN_INSN_CACHE_FUNC_NAME  "dfa_clean_insn_cache"
7112*38fd1498Szrj 
7113*38fd1498Szrj #define DFA_CLEAR_SINGLE_INSN_CACHE_FUNC_NAME "dfa_clear_single_insn_cache"
7114*38fd1498Szrj 
7115*38fd1498Szrj #define DFA_START_FUNC_NAME  "dfa_start"
7116*38fd1498Szrj 
7117*38fd1498Szrj #define DFA_FINISH_FUNC_NAME "dfa_finish"
7118*38fd1498Szrj 
7119*38fd1498Szrj /* Names of parameters of the PHR interface functions.  */
7120*38fd1498Szrj #define STATE_NAME "state"
7121*38fd1498Szrj 
7122*38fd1498Szrj #define INSN_PARAMETER_NAME "insn"
7123*38fd1498Szrj 
7124*38fd1498Szrj #define INSN2_PARAMETER_NAME "insn2"
7125*38fd1498Szrj 
7126*38fd1498Szrj #define CHIP_PARAMETER_NAME "chip"
7127*38fd1498Szrj 
7128*38fd1498Szrj #define FILE_PARAMETER_NAME "f"
7129*38fd1498Szrj 
7130*38fd1498Szrj #define CPU_UNIT_NAME_PARAMETER_NAME "cpu_unit_name"
7131*38fd1498Szrj 
7132*38fd1498Szrj #define CPU_CODE_PARAMETER_NAME "cpu_unit_code"
7133*38fd1498Szrj 
7134*38fd1498Szrj /* Names of the variables whose values are internal insn code of rtx
7135*38fd1498Szrj    insn.  */
7136*38fd1498Szrj #define INTERNAL_INSN_CODE_NAME "insn_code"
7137*38fd1498Szrj 
7138*38fd1498Szrj #define INTERNAL_INSN2_CODE_NAME "insn2_code"
7139*38fd1498Szrj 
7140*38fd1498Szrj /* Names of temporary variables in some functions.  */
7141*38fd1498Szrj #define TEMPORARY_VARIABLE_NAME "temp"
7142*38fd1498Szrj 
7143*38fd1498Szrj #define I_VARIABLE_NAME "i"
7144*38fd1498Szrj 
7145*38fd1498Szrj /* Name of result variable in some functions.  */
7146*38fd1498Szrj #define RESULT_VARIABLE_NAME "res"
7147*38fd1498Szrj 
7148*38fd1498Szrj /* Name of function (attribute) to translate insn into internal insn
7149*38fd1498Szrj    code.  */
7150*38fd1498Szrj #define INTERNAL_DFA_INSN_CODE_FUNC_NAME "internal_dfa_insn_code"
7151*38fd1498Szrj 
7152*38fd1498Szrj /* Name of function (attribute) to translate insn into internal insn
7153*38fd1498Szrj    code with caching.  */
7154*38fd1498Szrj #define DFA_INSN_CODE_FUNC_NAME "dfa_insn_code"
7155*38fd1498Szrj 
7156*38fd1498Szrj /* Output C type which is used for representation of codes of states
7157*38fd1498Szrj    of AUTOMATON.  */
7158*38fd1498Szrj static void
output_state_member_type(FILE * f,automaton_t automaton)7159*38fd1498Szrj output_state_member_type (FILE *f, automaton_t automaton)
7160*38fd1498Szrj {
7161*38fd1498Szrj   output_range_type (f, 0, automaton->achieved_states_num);
7162*38fd1498Szrj }
7163*38fd1498Szrj 
7164*38fd1498Szrj /* Output definition of the structure representing current DFA(s)
7165*38fd1498Szrj    state(s).  */
7166*38fd1498Szrj static void
output_chip_definitions(void)7167*38fd1498Szrj output_chip_definitions (void)
7168*38fd1498Szrj {
7169*38fd1498Szrj   automaton_t automaton;
7170*38fd1498Szrj 
7171*38fd1498Szrj   fprintf (output_file, "struct %s\n{\n", CHIP_NAME);
7172*38fd1498Szrj   for (automaton = description->first_automaton;
7173*38fd1498Szrj        automaton != NULL;
7174*38fd1498Szrj        automaton = automaton->next_automaton)
7175*38fd1498Szrj     {
7176*38fd1498Szrj       fprintf (output_file, "  ");
7177*38fd1498Szrj       output_state_member_type (output_file, automaton);
7178*38fd1498Szrj       fprintf (output_file, " ");
7179*38fd1498Szrj       output_chip_member_name (output_file, automaton);
7180*38fd1498Szrj       fprintf (output_file, ";\n");
7181*38fd1498Szrj     }
7182*38fd1498Szrj   fprintf (output_file, "};\n\n");
7183*38fd1498Szrj #if 0
7184*38fd1498Szrj   fprintf (output_file, "static struct %s %s;\n\n", CHIP_NAME, CHIP_NAME);
7185*38fd1498Szrj #endif
7186*38fd1498Szrj }
7187*38fd1498Szrj 
7188*38fd1498Szrj 
7189*38fd1498Szrj /* The function outputs translate vector of internal insn code into
7190*38fd1498Szrj    insn equivalence class number.  The equivalence class number is
7191*38fd1498Szrj    used to access to table and vectors representing DFA(s).  */
7192*38fd1498Szrj static void
output_translate_vect(automaton_t automaton)7193*38fd1498Szrj output_translate_vect (automaton_t automaton)
7194*38fd1498Szrj {
7195*38fd1498Szrj   ainsn_t ainsn;
7196*38fd1498Szrj   int insn_value;
7197*38fd1498Szrj   vla_hwint_t translate_vect;
7198*38fd1498Szrj 
7199*38fd1498Szrj   translate_vect.create (description->insns_num);
7200*38fd1498Szrj 
7201*38fd1498Szrj   for (insn_value = 0; insn_value < description->insns_num; insn_value++)
7202*38fd1498Szrj     /* Undefined value */
7203*38fd1498Szrj     translate_vect.quick_push (automaton->insn_equiv_classes_num);
7204*38fd1498Szrj 
7205*38fd1498Szrj   for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
7206*38fd1498Szrj     translate_vect[ainsn->insn_reserv_decl->insn_num] =
7207*38fd1498Szrj 	  ainsn->insn_equiv_class_num;
7208*38fd1498Szrj 
7209*38fd1498Szrj   fprintf (output_file,
7210*38fd1498Szrj            "/* Vector translating external insn codes to internal ones.*/\n");
7211*38fd1498Szrj   fprintf (output_file, "static const ");
7212*38fd1498Szrj   output_range_type (output_file, 0, automaton->insn_equiv_classes_num);
7213*38fd1498Szrj   fprintf (output_file, " ");
7214*38fd1498Szrj   output_translate_vect_name (output_file, automaton);
7215*38fd1498Szrj   fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7216*38fd1498Szrj   output_vect (translate_vect);
7217*38fd1498Szrj   fprintf (output_file, "};\n\n");
7218*38fd1498Szrj   translate_vect.release ();
7219*38fd1498Szrj }
7220*38fd1498Szrj 
7221*38fd1498Szrj /* The value in a table state x ainsn -> something which represents
7222*38fd1498Szrj    undefined value.  */
7223*38fd1498Szrj static int undefined_vect_el_value;
7224*38fd1498Szrj 
7225*38fd1498Szrj /* The following function returns nonzero value if the best
7226*38fd1498Szrj    representation of the table is comb vector.  */
7227*38fd1498Szrj static int
comb_vect_p(state_ainsn_table_t tab)7228*38fd1498Szrj comb_vect_p (state_ainsn_table_t tab)
7229*38fd1498Szrj {
7230*38fd1498Szrj   if (no_comb_flag)
7231*38fd1498Szrj     return false;
7232*38fd1498Szrj   return  (2 * tab->full_vect.length () > 5 * tab->comb_vect.length ());
7233*38fd1498Szrj }
7234*38fd1498Szrj 
7235*38fd1498Szrj /* The following function creates new table for AUTOMATON.  */
7236*38fd1498Szrj static state_ainsn_table_t
create_state_ainsn_table(automaton_t automaton)7237*38fd1498Szrj create_state_ainsn_table (automaton_t automaton)
7238*38fd1498Szrj {
7239*38fd1498Szrj   state_ainsn_table_t tab;
7240*38fd1498Szrj   int full_vect_length;
7241*38fd1498Szrj   int i;
7242*38fd1498Szrj 
7243*38fd1498Szrj   tab = XCREATENODE (struct state_ainsn_table);
7244*38fd1498Szrj   tab->automaton = automaton;
7245*38fd1498Szrj 
7246*38fd1498Szrj   tab->comb_vect.create (10000);
7247*38fd1498Szrj   tab->check_vect.create (10000);
7248*38fd1498Szrj 
7249*38fd1498Szrj   tab->base_vect.create (0);
7250*38fd1498Szrj   tab->base_vect.safe_grow (automaton->achieved_states_num);
7251*38fd1498Szrj 
7252*38fd1498Szrj   full_vect_length = (automaton->insn_equiv_classes_num
7253*38fd1498Szrj                       * automaton->achieved_states_num);
7254*38fd1498Szrj   tab->full_vect.create (full_vect_length);
7255*38fd1498Szrj   for (i = 0; i < full_vect_length; i++)
7256*38fd1498Szrj     tab->full_vect.quick_push (undefined_vect_el_value);
7257*38fd1498Szrj 
7258*38fd1498Szrj   tab->min_base_vect_el_value = 0;
7259*38fd1498Szrj   tab->max_base_vect_el_value = 0;
7260*38fd1498Szrj   tab->min_comb_vect_el_value = 0;
7261*38fd1498Szrj   tab->max_comb_vect_el_value = 0;
7262*38fd1498Szrj   return tab;
7263*38fd1498Szrj }
7264*38fd1498Szrj 
7265*38fd1498Szrj /* The following function outputs the best C representation of the
7266*38fd1498Szrj    table TAB of given TABLE_NAME.  */
7267*38fd1498Szrj static void
output_state_ainsn_table(state_ainsn_table_t tab,const char * table_name,void (* output_full_vect_name_func)(FILE *,automaton_t),void (* output_comb_vect_name_func)(FILE *,automaton_t),void (* output_check_vect_name_func)(FILE *,automaton_t),void (* output_base_vect_name_func)(FILE *,automaton_t))7268*38fd1498Szrj output_state_ainsn_table (state_ainsn_table_t tab, const char *table_name,
7269*38fd1498Szrj 			  void (*output_full_vect_name_func) (FILE *, automaton_t),
7270*38fd1498Szrj 			  void (*output_comb_vect_name_func) (FILE *, automaton_t),
7271*38fd1498Szrj 			  void (*output_check_vect_name_func) (FILE *, automaton_t),
7272*38fd1498Szrj 			  void (*output_base_vect_name_func) (FILE *, automaton_t))
7273*38fd1498Szrj {
7274*38fd1498Szrj   if (!comb_vect_p (tab))
7275*38fd1498Szrj     {
7276*38fd1498Szrj       fprintf (output_file, "/* Vector for %s.  */\n", table_name);
7277*38fd1498Szrj       fprintf (output_file, "static const ");
7278*38fd1498Szrj       output_range_type (output_file, tab->min_comb_vect_el_value,
7279*38fd1498Szrj                          tab->max_comb_vect_el_value);
7280*38fd1498Szrj       fprintf (output_file, " ");
7281*38fd1498Szrj       (*output_full_vect_name_func) (output_file, tab->automaton);
7282*38fd1498Szrj       fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7283*38fd1498Szrj       output_vect (tab->full_vect);
7284*38fd1498Szrj       fprintf (output_file, "};\n\n");
7285*38fd1498Szrj     }
7286*38fd1498Szrj   else
7287*38fd1498Szrj     {
7288*38fd1498Szrj       fprintf (output_file, "/* Comb vector for %s.  */\n", table_name);
7289*38fd1498Szrj       fprintf (output_file, "static const ");
7290*38fd1498Szrj       output_range_type (output_file, tab->min_comb_vect_el_value,
7291*38fd1498Szrj                          tab->max_comb_vect_el_value);
7292*38fd1498Szrj       fprintf (output_file, " ");
7293*38fd1498Szrj       (*output_comb_vect_name_func) (output_file, tab->automaton);
7294*38fd1498Szrj       fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7295*38fd1498Szrj       output_vect (tab->comb_vect);
7296*38fd1498Szrj       fprintf (output_file, "};\n\n");
7297*38fd1498Szrj       fprintf (output_file, "/* Check vector for %s.  */\n", table_name);
7298*38fd1498Szrj       fprintf (output_file, "static const ");
7299*38fd1498Szrj       output_range_type (output_file, 0, tab->automaton->achieved_states_num);
7300*38fd1498Szrj       fprintf (output_file, " ");
7301*38fd1498Szrj       (*output_check_vect_name_func) (output_file, tab->automaton);
7302*38fd1498Szrj       fprintf (output_file, "[] = {\n");
7303*38fd1498Szrj       output_vect (tab->check_vect);
7304*38fd1498Szrj       fprintf (output_file, "};\n\n");
7305*38fd1498Szrj       fprintf (output_file, "/* Base vector for %s.  */\n", table_name);
7306*38fd1498Szrj       fprintf (output_file, "static const ");
7307*38fd1498Szrj       output_range_type (output_file, tab->min_base_vect_el_value,
7308*38fd1498Szrj                          tab->max_base_vect_el_value);
7309*38fd1498Szrj       fprintf (output_file, " ");
7310*38fd1498Szrj       (*output_base_vect_name_func) (output_file, tab->automaton);
7311*38fd1498Szrj       fprintf (output_file, "[] = {\n");
7312*38fd1498Szrj       output_vect (tab->base_vect);
7313*38fd1498Szrj       fprintf (output_file, "};\n\n");
7314*38fd1498Szrj     }
7315*38fd1498Szrj }
7316*38fd1498Szrj 
7317*38fd1498Szrj /* The following function adds vector VECT to table TAB as its line
7318*38fd1498Szrj    with number VECT_NUM.  */
7319*38fd1498Szrj static void
add_vect(state_ainsn_table_t tab,int vect_num,vla_hwint_t vect)7320*38fd1498Szrj add_vect (state_ainsn_table_t tab, int vect_num, vla_hwint_t vect)
7321*38fd1498Szrj {
7322*38fd1498Szrj   int vect_length;
7323*38fd1498Szrj   size_t real_vect_length;
7324*38fd1498Szrj   int comb_vect_index;
7325*38fd1498Szrj   int comb_vect_els_num;
7326*38fd1498Szrj   int vect_index;
7327*38fd1498Szrj   int first_unempty_vect_index;
7328*38fd1498Szrj   int additional_els_num;
7329*38fd1498Szrj   int no_state_value;
7330*38fd1498Szrj   vect_el_t vect_el;
7331*38fd1498Szrj   int i;
7332*38fd1498Szrj   unsigned long vect_mask, comb_vect_mask;
7333*38fd1498Szrj 
7334*38fd1498Szrj   vect_length = vect.length ();
7335*38fd1498Szrj   gcc_assert (vect_length);
7336*38fd1498Szrj   gcc_assert (vect.last () != undefined_vect_el_value);
7337*38fd1498Szrj   real_vect_length = tab->automaton->insn_equiv_classes_num;
7338*38fd1498Szrj   /* Form full vector in the table: */
7339*38fd1498Szrj   {
7340*38fd1498Szrj     size_t full_base = tab->automaton->insn_equiv_classes_num * vect_num;
7341*38fd1498Szrj     if (tab->full_vect.length () < full_base + vect_length)
7342*38fd1498Szrj       tab->full_vect.safe_grow (full_base + vect_length);
7343*38fd1498Szrj     for (i = 0; i < vect_length; i++)
7344*38fd1498Szrj       tab->full_vect[full_base + i] = vect[i];
7345*38fd1498Szrj   }
7346*38fd1498Szrj 
7347*38fd1498Szrj   /* The comb_vect min/max values are also used for the full vector, so
7348*38fd1498Szrj      compute them now.  */
7349*38fd1498Szrj   for (vect_index = 0; vect_index < vect_length; vect_index++)
7350*38fd1498Szrj     if (vect[vect_index] != undefined_vect_el_value)
7351*38fd1498Szrj       {
7352*38fd1498Szrj 	vect_el_t x = vect[vect_index];
7353*38fd1498Szrj         gcc_assert (x >= 0);
7354*38fd1498Szrj         if (tab->max_comb_vect_el_value < x)
7355*38fd1498Szrj           tab->max_comb_vect_el_value = x;
7356*38fd1498Szrj         if (tab->min_comb_vect_el_value > x)
7357*38fd1498Szrj           tab->min_comb_vect_el_value = x;
7358*38fd1498Szrj       }
7359*38fd1498Szrj   if (no_comb_flag)
7360*38fd1498Szrj     return;
7361*38fd1498Szrj 
7362*38fd1498Szrj   /* Form comb vector in the table: */
7363*38fd1498Szrj   gcc_assert (tab->comb_vect.length () == tab->check_vect.length ());
7364*38fd1498Szrj 
7365*38fd1498Szrj   comb_vect_els_num = tab->comb_vect.length ();
7366*38fd1498Szrj   for (first_unempty_vect_index = 0;
7367*38fd1498Szrj        first_unempty_vect_index < vect_length;
7368*38fd1498Szrj        first_unempty_vect_index++)
7369*38fd1498Szrj     if (vect[first_unempty_vect_index]
7370*38fd1498Szrj 	!= undefined_vect_el_value)
7371*38fd1498Szrj       break;
7372*38fd1498Szrj 
7373*38fd1498Szrj   /* Search for the place in comb vect for the inserted vect.  */
7374*38fd1498Szrj 
7375*38fd1498Szrj   /* Slow case.  */
7376*38fd1498Szrj   if (vect_length - first_unempty_vect_index >= SIZEOF_LONG * CHAR_BIT)
7377*38fd1498Szrj     {
7378*38fd1498Szrj       for (comb_vect_index = 0;
7379*38fd1498Szrj            comb_vect_index < comb_vect_els_num;
7380*38fd1498Szrj            comb_vect_index++)
7381*38fd1498Szrj         {
7382*38fd1498Szrj           for (vect_index = first_unempty_vect_index;
7383*38fd1498Szrj                vect_index < vect_length
7384*38fd1498Szrj                && vect_index + comb_vect_index < comb_vect_els_num;
7385*38fd1498Szrj                vect_index++)
7386*38fd1498Szrj             if (vect[vect_index]
7387*38fd1498Szrj 		!= undefined_vect_el_value
7388*38fd1498Szrj                 && (tab->comb_vect[vect_index + comb_vect_index]
7389*38fd1498Szrj 		    != undefined_vect_el_value))
7390*38fd1498Szrj               break;
7391*38fd1498Szrj           if (vect_index >= vect_length
7392*38fd1498Szrj               || vect_index + comb_vect_index >= comb_vect_els_num)
7393*38fd1498Szrj             break;
7394*38fd1498Szrj         }
7395*38fd1498Szrj       goto found;
7396*38fd1498Szrj     }
7397*38fd1498Szrj 
7398*38fd1498Szrj   /* Fast case.  */
7399*38fd1498Szrj   vect_mask = 0;
7400*38fd1498Szrj   for (vect_index = first_unempty_vect_index;
7401*38fd1498Szrj        vect_index < vect_length;
7402*38fd1498Szrj        vect_index++)
7403*38fd1498Szrj     {
7404*38fd1498Szrj       vect_mask = vect_mask << 1;
7405*38fd1498Szrj       if (vect[vect_index] != undefined_vect_el_value)
7406*38fd1498Szrj 	vect_mask |= 1;
7407*38fd1498Szrj     }
7408*38fd1498Szrj 
7409*38fd1498Szrj   /* Search for the place in comb vect for the inserted vect.  */
7410*38fd1498Szrj   comb_vect_index = 0;
7411*38fd1498Szrj   if (comb_vect_els_num == 0)
7412*38fd1498Szrj     goto found;
7413*38fd1498Szrj 
7414*38fd1498Szrj   comb_vect_mask = 0;
7415*38fd1498Szrj   for (vect_index = first_unempty_vect_index;
7416*38fd1498Szrj        vect_index < vect_length && vect_index < comb_vect_els_num;
7417*38fd1498Szrj        vect_index++)
7418*38fd1498Szrj     {
7419*38fd1498Szrj       comb_vect_mask <<= 1;
7420*38fd1498Szrj       if (vect_index + comb_vect_index < comb_vect_els_num
7421*38fd1498Szrj 	  && tab->comb_vect[vect_index + comb_vect_index]
7422*38fd1498Szrj 	     != undefined_vect_el_value)
7423*38fd1498Szrj 	comb_vect_mask |= 1;
7424*38fd1498Szrj     }
7425*38fd1498Szrj   if ((vect_mask & comb_vect_mask) == 0)
7426*38fd1498Szrj     goto found;
7427*38fd1498Szrj 
7428*38fd1498Szrj   for (comb_vect_index = 1, i = vect_length; i < comb_vect_els_num;
7429*38fd1498Szrj        comb_vect_index++, i++)
7430*38fd1498Szrj     {
7431*38fd1498Szrj       comb_vect_mask = (comb_vect_mask << 1) | 1;
7432*38fd1498Szrj       comb_vect_mask ^= (tab->comb_vect[i]
7433*38fd1498Szrj 			 == undefined_vect_el_value);
7434*38fd1498Szrj       if ((vect_mask & comb_vect_mask) == 0)
7435*38fd1498Szrj 	goto found;
7436*38fd1498Szrj     }
7437*38fd1498Szrj   for ( ; comb_vect_index < comb_vect_els_num; comb_vect_index++)
7438*38fd1498Szrj     {
7439*38fd1498Szrj       comb_vect_mask <<= 1;
7440*38fd1498Szrj       if ((vect_mask & comb_vect_mask) == 0)
7441*38fd1498Szrj 	goto found;
7442*38fd1498Szrj     }
7443*38fd1498Szrj 
7444*38fd1498Szrj  found:
7445*38fd1498Szrj   /* Slot was found.  */
7446*38fd1498Szrj   additional_els_num = comb_vect_index + real_vect_length - comb_vect_els_num;
7447*38fd1498Szrj   if (additional_els_num < 0)
7448*38fd1498Szrj     additional_els_num = 0;
7449*38fd1498Szrj   /* Expand comb and check vectors.  */
7450*38fd1498Szrj   vect_el = undefined_vect_el_value;
7451*38fd1498Szrj   no_state_value = tab->automaton->achieved_states_num;
7452*38fd1498Szrj   while (additional_els_num > 0)
7453*38fd1498Szrj     {
7454*38fd1498Szrj       tab->comb_vect.safe_push (vect_el);
7455*38fd1498Szrj       tab->check_vect.safe_push (no_state_value);
7456*38fd1498Szrj       additional_els_num--;
7457*38fd1498Szrj     }
7458*38fd1498Szrj   gcc_assert (tab->comb_vect.length ()
7459*38fd1498Szrj 	      >= comb_vect_index + real_vect_length);
7460*38fd1498Szrj   /* Fill comb and check vectors.  */
7461*38fd1498Szrj   for (vect_index = 0; vect_index < vect_length; vect_index++)
7462*38fd1498Szrj     if (vect[vect_index] != undefined_vect_el_value)
7463*38fd1498Szrj       {
7464*38fd1498Szrj 	vect_el_t x = vect[vect_index];
7465*38fd1498Szrj         gcc_assert (tab->comb_vect[comb_vect_index + vect_index]
7466*38fd1498Szrj 		    == undefined_vect_el_value);
7467*38fd1498Szrj         gcc_assert (x >= 0);
7468*38fd1498Szrj 	tab->comb_vect[comb_vect_index + vect_index] = x;
7469*38fd1498Szrj 	tab->check_vect[comb_vect_index + vect_index] = vect_num;
7470*38fd1498Szrj       }
7471*38fd1498Szrj   if (tab->max_comb_vect_el_value < undefined_vect_el_value)
7472*38fd1498Szrj     tab->max_comb_vect_el_value = undefined_vect_el_value;
7473*38fd1498Szrj   if (tab->min_comb_vect_el_value > undefined_vect_el_value)
7474*38fd1498Szrj     tab->min_comb_vect_el_value = undefined_vect_el_value;
7475*38fd1498Szrj   if (tab->max_base_vect_el_value < comb_vect_index)
7476*38fd1498Szrj     tab->max_base_vect_el_value = comb_vect_index;
7477*38fd1498Szrj   if (tab->min_base_vect_el_value > comb_vect_index)
7478*38fd1498Szrj     tab->min_base_vect_el_value = comb_vect_index;
7479*38fd1498Szrj 
7480*38fd1498Szrj   tab->base_vect[vect_num] = comb_vect_index;
7481*38fd1498Szrj }
7482*38fd1498Szrj 
7483*38fd1498Szrj /* Return number of out arcs of STATE.  */
7484*38fd1498Szrj static int
out_state_arcs_num(const_state_t state)7485*38fd1498Szrj out_state_arcs_num (const_state_t state)
7486*38fd1498Szrj {
7487*38fd1498Szrj   int result;
7488*38fd1498Szrj   arc_t arc;
7489*38fd1498Szrj 
7490*38fd1498Szrj   result = 0;
7491*38fd1498Szrj   for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
7492*38fd1498Szrj     {
7493*38fd1498Szrj       gcc_assert (arc->insn);
7494*38fd1498Szrj       if (arc->insn->first_ainsn_with_given_equivalence_num)
7495*38fd1498Szrj         result++;
7496*38fd1498Szrj     }
7497*38fd1498Szrj   return result;
7498*38fd1498Szrj }
7499*38fd1498Szrj 
7500*38fd1498Szrj /* Compare number of possible transitions from the states.  */
7501*38fd1498Szrj static int
compare_transition_els_num(const void * state_ptr_1,const void * state_ptr_2)7502*38fd1498Szrj compare_transition_els_num (const void *state_ptr_1,
7503*38fd1498Szrj 			    const void *state_ptr_2)
7504*38fd1498Szrj {
7505*38fd1498Szrj   const int transition_els_num_1
7506*38fd1498Szrj     = out_state_arcs_num (*(const_state_t const*) state_ptr_1);
7507*38fd1498Szrj   const int transition_els_num_2
7508*38fd1498Szrj     = out_state_arcs_num (*(const_state_t const*) state_ptr_2);
7509*38fd1498Szrj 
7510*38fd1498Szrj   if (transition_els_num_1 < transition_els_num_2)
7511*38fd1498Szrj     return 1;
7512*38fd1498Szrj   else if (transition_els_num_1 == transition_els_num_2)
7513*38fd1498Szrj     return 0;
7514*38fd1498Szrj   else
7515*38fd1498Szrj     return -1;
7516*38fd1498Szrj }
7517*38fd1498Szrj 
7518*38fd1498Szrj /* The function adds element EL_VALUE to vector VECT for a table state
7519*38fd1498Szrj    x AINSN.  */
7520*38fd1498Szrj static void
add_vect_el(vla_hwint_t & vect,ainsn_t ainsn,int el_value)7521*38fd1498Szrj add_vect_el (vla_hwint_t &vect, ainsn_t ainsn, int el_value)
7522*38fd1498Szrj {
7523*38fd1498Szrj   int equiv_class_num;
7524*38fd1498Szrj   int vect_index;
7525*38fd1498Szrj 
7526*38fd1498Szrj   gcc_assert (ainsn);
7527*38fd1498Szrj   equiv_class_num = ainsn->insn_equiv_class_num;
7528*38fd1498Szrj   for (vect_index = vect.length ();
7529*38fd1498Szrj        vect_index <= equiv_class_num;
7530*38fd1498Szrj        vect_index++)
7531*38fd1498Szrj     vect.safe_push (undefined_vect_el_value);
7532*38fd1498Szrj   vect[equiv_class_num] = el_value;
7533*38fd1498Szrj }
7534*38fd1498Szrj 
7535*38fd1498Szrj /* This is for forming vector of states of an automaton.  */
7536*38fd1498Szrj static vec<state_t> output_states_vect;
7537*38fd1498Szrj 
7538*38fd1498Szrj /* The function is called by function pass_states.  The function adds
7539*38fd1498Szrj    STATE to `output_states_vect'.  */
7540*38fd1498Szrj static void
add_states_vect_el(state_t state)7541*38fd1498Szrj add_states_vect_el (state_t state)
7542*38fd1498Szrj {
7543*38fd1498Szrj   output_states_vect.safe_push (state);
7544*38fd1498Szrj }
7545*38fd1498Szrj 
7546*38fd1498Szrj /* Form and output vectors (comb, check, base or full vector)
7547*38fd1498Szrj    representing transition table of AUTOMATON.  */
7548*38fd1498Szrj static void
output_trans_table(automaton_t automaton)7549*38fd1498Szrj output_trans_table (automaton_t automaton)
7550*38fd1498Szrj {
7551*38fd1498Szrj   size_t i;
7552*38fd1498Szrj   arc_t arc;
7553*38fd1498Szrj   vla_hwint_t transition_vect = vla_hwint_t ();
7554*38fd1498Szrj 
7555*38fd1498Szrj   undefined_vect_el_value = automaton->achieved_states_num;
7556*38fd1498Szrj   automaton->trans_table = create_state_ainsn_table (automaton);
7557*38fd1498Szrj   /* Create vect of pointers to states ordered by num of transitions
7558*38fd1498Szrj      from the state (state with the maximum num is the first).  */
7559*38fd1498Szrj   output_states_vect.create (0);
7560*38fd1498Szrj   pass_states (automaton, add_states_vect_el);
7561*38fd1498Szrj   output_states_vect.qsort (compare_transition_els_num);
7562*38fd1498Szrj 
7563*38fd1498Szrj   for (i = 0; i < output_states_vect.length (); i++)
7564*38fd1498Szrj     {
7565*38fd1498Szrj       transition_vect.truncate (0);
7566*38fd1498Szrj       for (arc = first_out_arc (output_states_vect[i]);
7567*38fd1498Szrj 	   arc != NULL;
7568*38fd1498Szrj 	   arc = next_out_arc (arc))
7569*38fd1498Szrj         {
7570*38fd1498Szrj           gcc_assert (arc->insn);
7571*38fd1498Szrj           if (arc->insn->first_ainsn_with_given_equivalence_num)
7572*38fd1498Szrj             add_vect_el (transition_vect, arc->insn,
7573*38fd1498Szrj                          arc->to_state->order_state_num);
7574*38fd1498Szrj         }
7575*38fd1498Szrj       add_vect (automaton->trans_table,
7576*38fd1498Szrj 		output_states_vect[i]->order_state_num,
7577*38fd1498Szrj 		transition_vect);
7578*38fd1498Szrj     }
7579*38fd1498Szrj   output_state_ainsn_table
7580*38fd1498Szrj     (automaton->trans_table, "state transitions",
7581*38fd1498Szrj      output_trans_full_vect_name, output_trans_comb_vect_name,
7582*38fd1498Szrj      output_trans_check_vect_name, output_trans_base_vect_name);
7583*38fd1498Szrj 
7584*38fd1498Szrj   output_states_vect.release ();
7585*38fd1498Szrj   transition_vect.release ();
7586*38fd1498Szrj }
7587*38fd1498Szrj 
7588*38fd1498Szrj /* Form and output vectors representing minimal issue delay table of
7589*38fd1498Szrj    AUTOMATON.  The table is state x ainsn -> minimal issue delay of
7590*38fd1498Szrj    the ainsn.  */
7591*38fd1498Szrj static void
output_min_issue_delay_table(automaton_t automaton)7592*38fd1498Szrj output_min_issue_delay_table (automaton_t automaton)
7593*38fd1498Szrj {
7594*38fd1498Szrj   vla_hwint_t min_issue_delay_vect;
7595*38fd1498Szrj   vla_hwint_t compressed_min_issue_delay_vect;
7596*38fd1498Szrj   ainsn_t ainsn;
7597*38fd1498Szrj   size_t i;
7598*38fd1498Szrj   size_t min_issue_delay_len, compressed_min_issue_delay_len;
7599*38fd1498Szrj   size_t cfactor;
7600*38fd1498Szrj   int changed;
7601*38fd1498Szrj 
7602*38fd1498Szrj   /* Create vect of pointers to states ordered by num of transitions
7603*38fd1498Szrj      from the state (state with the maximum num is the first).  */
7604*38fd1498Szrj   output_states_vect.create (0);
7605*38fd1498Szrj   pass_states (automaton, add_states_vect_el);
7606*38fd1498Szrj 
7607*38fd1498Szrj   min_issue_delay_len = (output_states_vect.length ()
7608*38fd1498Szrj 			 * automaton->insn_equiv_classes_num);
7609*38fd1498Szrj   min_issue_delay_vect.create (min_issue_delay_len);
7610*38fd1498Szrj   for (i = 0; i < min_issue_delay_len; i++)
7611*38fd1498Szrj     min_issue_delay_vect.quick_push (-1);
7612*38fd1498Szrj 
7613*38fd1498Szrj   automaton->max_min_delay = 0;
7614*38fd1498Szrj 
7615*38fd1498Szrj   do
7616*38fd1498Szrj     {
7617*38fd1498Szrj       size_t state_no;
7618*38fd1498Szrj 
7619*38fd1498Szrj       changed = 0;
7620*38fd1498Szrj 
7621*38fd1498Szrj       for (state_no = 0; state_no < output_states_vect.length ();
7622*38fd1498Szrj            state_no++)
7623*38fd1498Szrj 	{
7624*38fd1498Szrj 	  state_t s = output_states_vect[state_no];
7625*38fd1498Szrj 	  arc_t arc;
7626*38fd1498Szrj 
7627*38fd1498Szrj 	  for (arc = first_out_arc (s); arc; arc = next_out_arc (arc))
7628*38fd1498Szrj 	    {
7629*38fd1498Szrj 	      int k;
7630*38fd1498Szrj 
7631*38fd1498Szrj 	      size_t asn = s->order_state_num
7632*38fd1498Szrj 	                   * automaton->insn_equiv_classes_num
7633*38fd1498Szrj 	                   + arc->insn->insn_equiv_class_num;
7634*38fd1498Szrj 
7635*38fd1498Szrj 	      if (min_issue_delay_vect[asn])
7636*38fd1498Szrj 		{
7637*38fd1498Szrj 		  min_issue_delay_vect[asn] = (vect_el_t) 0;
7638*38fd1498Szrj 		  changed = 1;
7639*38fd1498Szrj 		}
7640*38fd1498Szrj 
7641*38fd1498Szrj 	      for (k = 0; k < automaton->insn_equiv_classes_num; k++)
7642*38fd1498Szrj 		{
7643*38fd1498Szrj 		  size_t n0, n1;
7644*38fd1498Szrj 		  vect_el_t delay0, delay1;
7645*38fd1498Szrj 
7646*38fd1498Szrj 		  n0 = s->order_state_num
7647*38fd1498Szrj 		       * automaton->insn_equiv_classes_num
7648*38fd1498Szrj 		       + k;
7649*38fd1498Szrj 		  n1 = arc->to_state->order_state_num
7650*38fd1498Szrj 		       * automaton->insn_equiv_classes_num
7651*38fd1498Szrj 		       + k;
7652*38fd1498Szrj 		  delay0 = min_issue_delay_vect[n0];
7653*38fd1498Szrj 		  delay1 = min_issue_delay_vect[n1];
7654*38fd1498Szrj 		  if (delay1 != -1)
7655*38fd1498Szrj 		    {
7656*38fd1498Szrj 		      if (arc->insn->insn_reserv_decl
7657*38fd1498Szrj 		          == DECL_INSN_RESERV (advance_cycle_insn_decl))
7658*38fd1498Szrj 			delay1++;
7659*38fd1498Szrj 		      if (delay1 < delay0 || delay0 == -1)
7660*38fd1498Szrj 			{
7661*38fd1498Szrj 			  min_issue_delay_vect[n0] = delay1;
7662*38fd1498Szrj 			  changed = 1;
7663*38fd1498Szrj 			}
7664*38fd1498Szrj 		    }
7665*38fd1498Szrj 		}
7666*38fd1498Szrj 	    }
7667*38fd1498Szrj 	}
7668*38fd1498Szrj     }
7669*38fd1498Szrj   while (changed);
7670*38fd1498Szrj 
7671*38fd1498Szrj   automaton->max_min_delay = 0;
7672*38fd1498Szrj 
7673*38fd1498Szrj   for (ainsn = automaton->ainsn_list; ainsn; ainsn = ainsn->next_ainsn)
7674*38fd1498Szrj     if (ainsn->first_ainsn_with_given_equivalence_num)
7675*38fd1498Szrj       {
7676*38fd1498Szrj 	for (i = 0; i < output_states_vect.length (); i++)
7677*38fd1498Szrj 	  {
7678*38fd1498Szrj 	    state_t s = output_states_vect[i];
7679*38fd1498Szrj 	    size_t np = s->order_state_num
7680*38fd1498Szrj 	                * automaton->insn_equiv_classes_num
7681*38fd1498Szrj 	                + ainsn->insn_equiv_class_num;
7682*38fd1498Szrj 	    vect_el_t x = min_issue_delay_vect[np];
7683*38fd1498Szrj 
7684*38fd1498Szrj 	    if (automaton->max_min_delay < x)
7685*38fd1498Szrj 	      automaton->max_min_delay = x;
7686*38fd1498Szrj 	    if (x == -1)
7687*38fd1498Szrj 	      min_issue_delay_vect[np] = (vect_el_t) 0;
7688*38fd1498Szrj 	  }
7689*38fd1498Szrj       }
7690*38fd1498Szrj 
7691*38fd1498Szrj   fprintf (output_file, "/* Vector of min issue delay of insns.  */\n");
7692*38fd1498Szrj   fprintf (output_file, "static const ");
7693*38fd1498Szrj   output_range_type (output_file, 0, automaton->max_min_delay);
7694*38fd1498Szrj   fprintf (output_file, " ");
7695*38fd1498Szrj   output_min_issue_delay_vect_name (output_file, automaton);
7696*38fd1498Szrj   fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7697*38fd1498Szrj   /* Compress the vector.  */
7698*38fd1498Szrj   if (automaton->max_min_delay < 2)
7699*38fd1498Szrj     cfactor = 8;
7700*38fd1498Szrj   else if (automaton->max_min_delay < 4)
7701*38fd1498Szrj     cfactor = 4;
7702*38fd1498Szrj   else if (automaton->max_min_delay < 16)
7703*38fd1498Szrj     cfactor = 2;
7704*38fd1498Szrj   else
7705*38fd1498Szrj     cfactor = 1;
7706*38fd1498Szrj   automaton->min_issue_delay_table_compression_factor = cfactor;
7707*38fd1498Szrj 
7708*38fd1498Szrj   compressed_min_issue_delay_len = (min_issue_delay_len+cfactor-1) / cfactor;
7709*38fd1498Szrj   compressed_min_issue_delay_vect.create (compressed_min_issue_delay_len);
7710*38fd1498Szrj 
7711*38fd1498Szrj   for (i = 0; i < compressed_min_issue_delay_len; i++)
7712*38fd1498Szrj     compressed_min_issue_delay_vect.quick_push (0);
7713*38fd1498Szrj 
7714*38fd1498Szrj   for (i = 0; i < min_issue_delay_len; i++)
7715*38fd1498Szrj     {
7716*38fd1498Szrj       size_t ci = i / cfactor;
7717*38fd1498Szrj       vect_el_t x = min_issue_delay_vect[i];
7718*38fd1498Szrj       vect_el_t cx = compressed_min_issue_delay_vect[ci];
7719*38fd1498Szrj 
7720*38fd1498Szrj       cx |= x << (8 - (i % cfactor + 1) * (8 / cfactor));
7721*38fd1498Szrj       compressed_min_issue_delay_vect[ci] = cx;
7722*38fd1498Szrj     }
7723*38fd1498Szrj   output_vect (compressed_min_issue_delay_vect);
7724*38fd1498Szrj   fprintf (output_file, "};\n\n");
7725*38fd1498Szrj   output_states_vect.release ();
7726*38fd1498Szrj   min_issue_delay_vect.release ();
7727*38fd1498Szrj   compressed_min_issue_delay_vect.release ();
7728*38fd1498Szrj }
7729*38fd1498Szrj 
7730*38fd1498Szrj /* Form and output vector representing the locked states of
7731*38fd1498Szrj    AUTOMATON.  */
7732*38fd1498Szrj static void
output_dead_lock_vect(automaton_t automaton)7733*38fd1498Szrj output_dead_lock_vect (automaton_t automaton)
7734*38fd1498Szrj {
7735*38fd1498Szrj   size_t i;
7736*38fd1498Szrj   arc_t arc;
7737*38fd1498Szrj   vla_hwint_t dead_lock_vect = vla_hwint_t ();
7738*38fd1498Szrj 
7739*38fd1498Szrj   /* Create vect of pointers to states ordered by num of
7740*38fd1498Szrj      transitions from the state (state with the maximum num is the
7741*38fd1498Szrj      first).  */
7742*38fd1498Szrj   automaton->locked_states = 0;
7743*38fd1498Szrj   output_states_vect.create (0);
7744*38fd1498Szrj   pass_states (automaton, add_states_vect_el);
7745*38fd1498Szrj 
7746*38fd1498Szrj   dead_lock_vect.safe_grow (output_states_vect.length ());
7747*38fd1498Szrj   for (i = 0; i < output_states_vect.length (); i++)
7748*38fd1498Szrj     {
7749*38fd1498Szrj       state_t s = output_states_vect[i];
7750*38fd1498Szrj       arc = first_out_arc (s);
7751*38fd1498Szrj       gcc_assert (arc);
7752*38fd1498Szrj       if (next_out_arc (arc) == NULL
7753*38fd1498Szrj 	  && (arc->insn->insn_reserv_decl
7754*38fd1498Szrj 	      == DECL_INSN_RESERV (advance_cycle_insn_decl)))
7755*38fd1498Szrj 	{
7756*38fd1498Szrj 	  dead_lock_vect[s->order_state_num] = 1;
7757*38fd1498Szrj 	  automaton->locked_states++;
7758*38fd1498Szrj 	}
7759*38fd1498Szrj       else
7760*38fd1498Szrj 	dead_lock_vect[s->order_state_num] = (vect_el_t) 0;
7761*38fd1498Szrj     }
7762*38fd1498Szrj   if (automaton->locked_states == 0)
7763*38fd1498Szrj     return;
7764*38fd1498Szrj 
7765*38fd1498Szrj   fprintf (output_file, "/* Vector for locked state flags.  */\n");
7766*38fd1498Szrj   fprintf (output_file, "static const ");
7767*38fd1498Szrj   output_range_type (output_file, 0, 1);
7768*38fd1498Szrj   fprintf (output_file, " ");
7769*38fd1498Szrj   output_dead_lock_vect_name (output_file, automaton);
7770*38fd1498Szrj   fprintf (output_file, "[] = {\n");
7771*38fd1498Szrj   output_vect (dead_lock_vect);
7772*38fd1498Szrj   fprintf (output_file, "};\n\n");
7773*38fd1498Szrj   output_states_vect.release ();
7774*38fd1498Szrj   dead_lock_vect.release ();
7775*38fd1498Szrj }
7776*38fd1498Szrj 
7777*38fd1498Szrj /* Form and output vector representing reserved units of the states of
7778*38fd1498Szrj    AUTOMATON.  */
7779*38fd1498Szrj static void
output_reserved_units_table(automaton_t automaton)7780*38fd1498Szrj output_reserved_units_table (automaton_t automaton)
7781*38fd1498Szrj {
7782*38fd1498Szrj   vla_hwint_t reserved_units_table = vla_hwint_t ();
7783*38fd1498Szrj   int state_byte_size;
7784*38fd1498Szrj   int reserved_units_size;
7785*38fd1498Szrj   size_t n;
7786*38fd1498Szrj   int i;
7787*38fd1498Szrj 
7788*38fd1498Szrj   if (description->query_units_num == 0)
7789*38fd1498Szrj     return;
7790*38fd1498Szrj 
7791*38fd1498Szrj   /* Create vect of pointers to states.  */
7792*38fd1498Szrj   output_states_vect.create (0);
7793*38fd1498Szrj   pass_states (automaton, add_states_vect_el);
7794*38fd1498Szrj   /* Create vector.  */
7795*38fd1498Szrj   state_byte_size = (description->query_units_num + 7) / 8;
7796*38fd1498Szrj   reserved_units_size = (output_states_vect.length ()
7797*38fd1498Szrj 			 * state_byte_size);
7798*38fd1498Szrj 
7799*38fd1498Szrj   reserved_units_table.create (reserved_units_size);
7800*38fd1498Szrj 
7801*38fd1498Szrj   for (i = 0; i < reserved_units_size; i++)
7802*38fd1498Szrj     reserved_units_table.quick_push (0);
7803*38fd1498Szrj   for (n = 0; n < output_states_vect.length (); n++)
7804*38fd1498Szrj     {
7805*38fd1498Szrj       state_t s = output_states_vect[n];
7806*38fd1498Szrj       for (i = 0; i < description->units_num; i++)
7807*38fd1498Szrj 	if (units_array [i]->query_p
7808*38fd1498Szrj 	    && first_cycle_unit_presence (s, i))
7809*38fd1498Szrj 	  {
7810*38fd1498Szrj 	    int ri = (s->order_state_num * state_byte_size
7811*38fd1498Szrj 		      + units_array [i]->query_num / 8);
7812*38fd1498Szrj 	    vect_el_t x = reserved_units_table[ri];
7813*38fd1498Szrj 
7814*38fd1498Szrj 	    x += 1 << (units_array [i]->query_num % 8);
7815*38fd1498Szrj 	    reserved_units_table[ri] = x;
7816*38fd1498Szrj 	  }
7817*38fd1498Szrj     }
7818*38fd1498Szrj   fprintf (output_file, "\n#if %s\n", CPU_UNITS_QUERY_MACRO_NAME);
7819*38fd1498Szrj   fprintf (output_file, "/* Vector for reserved units of states.  */\n");
7820*38fd1498Szrj   fprintf (output_file, "static const ");
7821*38fd1498Szrj   output_range_type (output_file, 0, 255);
7822*38fd1498Szrj   fprintf (output_file, " ");
7823*38fd1498Szrj   output_reserved_units_table_name (output_file, automaton);
7824*38fd1498Szrj   fprintf (output_file, "[] = {\n");
7825*38fd1498Szrj   output_vect (reserved_units_table);
7826*38fd1498Szrj   fprintf (output_file, "};\n#endif /* #if %s */\n\n",
7827*38fd1498Szrj 	   CPU_UNITS_QUERY_MACRO_NAME);
7828*38fd1498Szrj 
7829*38fd1498Szrj   output_states_vect.release ();
7830*38fd1498Szrj   reserved_units_table.release ();
7831*38fd1498Szrj }
7832*38fd1498Szrj 
7833*38fd1498Szrj /* The function outputs all tables representing DFA(s) used for fast
7834*38fd1498Szrj    pipeline hazards recognition.  */
7835*38fd1498Szrj static void
output_tables(void)7836*38fd1498Szrj output_tables (void)
7837*38fd1498Szrj {
7838*38fd1498Szrj   automaton_t automaton;
7839*38fd1498Szrj 
7840*38fd1498Szrj   for (automaton = description->first_automaton;
7841*38fd1498Szrj        automaton != NULL;
7842*38fd1498Szrj        automaton = automaton->next_automaton)
7843*38fd1498Szrj     {
7844*38fd1498Szrj       output_translate_vect (automaton);
7845*38fd1498Szrj       output_trans_table (automaton);
7846*38fd1498Szrj       output_min_issue_delay_table (automaton);
7847*38fd1498Szrj       output_dead_lock_vect (automaton);
7848*38fd1498Szrj       output_reserved_units_table (automaton);
7849*38fd1498Szrj     }
7850*38fd1498Szrj   fprintf (output_file, "\n#define %s %d\n\n", ADVANCE_CYCLE_VALUE_NAME,
7851*38fd1498Szrj            DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
7852*38fd1498Szrj   if (collapse_flag)
7853*38fd1498Szrj     fprintf (output_file, "\n#define %s %d\n\n", COLLAPSE_NDFA_VALUE_NAME,
7854*38fd1498Szrj 	     DECL_INSN_RESERV (collapse_ndfa_insn_decl)->insn_num);
7855*38fd1498Szrj }
7856*38fd1498Szrj 
7857*38fd1498Szrj /* The function outputs definition and value of PHR interface variable
7858*38fd1498Szrj    `max_insn_queue_index'.  Its value is not less than maximal queue
7859*38fd1498Szrj    length needed for the insn scheduler.  */
7860*38fd1498Szrj static void
output_max_insn_queue_index_def(void)7861*38fd1498Szrj output_max_insn_queue_index_def (void)
7862*38fd1498Szrj {
7863*38fd1498Szrj   int i, max, latency;
7864*38fd1498Szrj   decl_t decl;
7865*38fd1498Szrj 
7866*38fd1498Szrj   max = description->max_insn_reserv_cycles;
7867*38fd1498Szrj   for (i = 0; i < description->decls_num; i++)
7868*38fd1498Szrj     {
7869*38fd1498Szrj       decl = description->decls [i];
7870*38fd1498Szrj       if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
7871*38fd1498Szrj 	{
7872*38fd1498Szrj 	  latency = DECL_INSN_RESERV (decl)->default_latency;
7873*38fd1498Szrj 	  if (latency > max)
7874*38fd1498Szrj 	    max = latency;
7875*38fd1498Szrj 	}
7876*38fd1498Szrj       else if (decl->mode == dm_bypass)
7877*38fd1498Szrj 	{
7878*38fd1498Szrj 	  latency = DECL_BYPASS (decl)->latency;
7879*38fd1498Szrj 	  if (latency > max)
7880*38fd1498Szrj 	    max = latency;
7881*38fd1498Szrj 	}
7882*38fd1498Szrj     }
7883*38fd1498Szrj   for (i = 0; (1 << i) <= max; i++)
7884*38fd1498Szrj     ;
7885*38fd1498Szrj   gcc_assert (i >= 0);
7886*38fd1498Szrj   fprintf (output_file, "\nconst int max_insn_queue_index = %d;\n\n",
7887*38fd1498Szrj 	   (1 << i) - 1);
7888*38fd1498Szrj }
7889*38fd1498Szrj 
7890*38fd1498Szrj /* The function outputs switch cases for insn reservations using
7891*38fd1498Szrj    function *output_automata_list_code.  */
7892*38fd1498Szrj static void
output_insn_code_cases(void (* output_automata_list_code)(automata_list_el_t))7893*38fd1498Szrj output_insn_code_cases (void (*output_automata_list_code)
7894*38fd1498Szrj 			(automata_list_el_t))
7895*38fd1498Szrj {
7896*38fd1498Szrj   decl_t decl, decl2;
7897*38fd1498Szrj   int i, j;
7898*38fd1498Szrj 
7899*38fd1498Szrj   for (i = 0; i < description->decls_num; i++)
7900*38fd1498Szrj     {
7901*38fd1498Szrj       decl = description->decls [i];
7902*38fd1498Szrj       if (decl->mode == dm_insn_reserv)
7903*38fd1498Szrj 	DECL_INSN_RESERV (decl)->processed_p = FALSE;
7904*38fd1498Szrj     }
7905*38fd1498Szrj   for (i = 0; i < description->decls_num; i++)
7906*38fd1498Szrj     {
7907*38fd1498Szrj       decl = description->decls [i];
7908*38fd1498Szrj       if (decl->mode == dm_insn_reserv
7909*38fd1498Szrj 	  && !DECL_INSN_RESERV (decl)->processed_p)
7910*38fd1498Szrj 	{
7911*38fd1498Szrj 	  for (j = i; j < description->decls_num; j++)
7912*38fd1498Szrj 	    {
7913*38fd1498Szrj 	      decl2 = description->decls [j];
7914*38fd1498Szrj 	      if (decl2->mode == dm_insn_reserv
7915*38fd1498Szrj 		  && (DECL_INSN_RESERV (decl2)->important_automata_list
7916*38fd1498Szrj 		      == DECL_INSN_RESERV (decl)->important_automata_list))
7917*38fd1498Szrj 		{
7918*38fd1498Szrj 		  DECL_INSN_RESERV (decl2)->processed_p = TRUE;
7919*38fd1498Szrj 		  fprintf (output_file, "    case %d: /* %s */\n",
7920*38fd1498Szrj 			   DECL_INSN_RESERV (decl2)->insn_num,
7921*38fd1498Szrj 			   DECL_INSN_RESERV (decl2)->name);
7922*38fd1498Szrj 		}
7923*38fd1498Szrj 	    }
7924*38fd1498Szrj 	  (*output_automata_list_code)
7925*38fd1498Szrj 	    (DECL_INSN_RESERV (decl)->important_automata_list);
7926*38fd1498Szrj 	}
7927*38fd1498Szrj     }
7928*38fd1498Szrj }
7929*38fd1498Szrj 
7930*38fd1498Szrj 
7931*38fd1498Szrj /* The function outputs a code for evaluation of a minimal delay of
7932*38fd1498Szrj    issue of insns which have reservations in given AUTOMATA_LIST.  */
7933*38fd1498Szrj static void
output_automata_list_min_issue_delay_code(automata_list_el_t automata_list)7934*38fd1498Szrj output_automata_list_min_issue_delay_code (automata_list_el_t automata_list)
7935*38fd1498Szrj {
7936*38fd1498Szrj   automata_list_el_t el;
7937*38fd1498Szrj   automaton_t automaton;
7938*38fd1498Szrj 
7939*38fd1498Szrj   for (el = automata_list; el != NULL; el = el->next_automata_list_el)
7940*38fd1498Szrj     {
7941*38fd1498Szrj       automaton = el->automaton;
7942*38fd1498Szrj       fprintf (output_file, "\n      %s = ", TEMPORARY_VARIABLE_NAME);
7943*38fd1498Szrj       output_min_issue_delay_vect_name (output_file, automaton);
7944*38fd1498Szrj       fprintf (output_file,
7945*38fd1498Szrj 	       (automaton->min_issue_delay_table_compression_factor != 1
7946*38fd1498Szrj 		? " [(" : " ["));
7947*38fd1498Szrj       output_translate_vect_name (output_file, automaton);
7948*38fd1498Szrj       fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
7949*38fd1498Szrj       fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7950*38fd1498Szrj       output_chip_member_name (output_file, automaton);
7951*38fd1498Szrj       fprintf (output_file, " * %d", automaton->insn_equiv_classes_num);
7952*38fd1498Szrj       if (automaton->min_issue_delay_table_compression_factor == 1)
7953*38fd1498Szrj 	fprintf (output_file, "];\n");
7954*38fd1498Szrj       else
7955*38fd1498Szrj 	{
7956*38fd1498Szrj 	  fprintf (output_file, ") / %d];\n",
7957*38fd1498Szrj 		   automaton->min_issue_delay_table_compression_factor);
7958*38fd1498Szrj 	  fprintf (output_file, "      %s = (%s >> (8 - ((",
7959*38fd1498Szrj 		   TEMPORARY_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
7960*38fd1498Szrj 	  output_translate_vect_name (output_file, automaton);
7961*38fd1498Szrj 	  fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
7962*38fd1498Szrj 	  fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7963*38fd1498Szrj 	  output_chip_member_name (output_file, automaton);
7964*38fd1498Szrj 	  fprintf (output_file, " * %d)", automaton->insn_equiv_classes_num);
7965*38fd1498Szrj 	  fprintf
7966*38fd1498Szrj 	    (output_file, " %% %d + 1) * %d)) & %d;\n",
7967*38fd1498Szrj 	     automaton->min_issue_delay_table_compression_factor,
7968*38fd1498Szrj 	     8 / automaton->min_issue_delay_table_compression_factor,
7969*38fd1498Szrj 	     (1 << (8 / automaton->min_issue_delay_table_compression_factor))
7970*38fd1498Szrj 	     - 1);
7971*38fd1498Szrj 	}
7972*38fd1498Szrj       if (el == automata_list)
7973*38fd1498Szrj 	fprintf (output_file, "      %s = %s;\n",
7974*38fd1498Szrj 		 RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
7975*38fd1498Szrj       else
7976*38fd1498Szrj 	{
7977*38fd1498Szrj 	  fprintf (output_file, "      if (%s > %s)\n",
7978*38fd1498Szrj 		   TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
7979*38fd1498Szrj 	  fprintf (output_file, "        %s = %s;\n",
7980*38fd1498Szrj 		   RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
7981*38fd1498Szrj 	}
7982*38fd1498Szrj     }
7983*38fd1498Szrj   fprintf (output_file, "      break;\n\n");
7984*38fd1498Szrj }
7985*38fd1498Szrj 
7986*38fd1498Szrj /* Output function `internal_min_issue_delay'.  */
7987*38fd1498Szrj static void
output_internal_min_issue_delay_func(void)7988*38fd1498Szrj output_internal_min_issue_delay_func (void)
7989*38fd1498Szrj {
7990*38fd1498Szrj   fprintf (output_file,
7991*38fd1498Szrj 	   "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
7992*38fd1498Szrj 	   INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7993*38fd1498Szrj 	   CHIP_NAME, CHIP_PARAMETER_NAME);
7994*38fd1498Szrj   fprintf (output_file, "{\n  int %s ATTRIBUTE_UNUSED;\n  int %s = -1;\n",
7995*38fd1498Szrj 	   TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
7996*38fd1498Szrj   fprintf (output_file, "\n  switch (%s)\n    {\n", INTERNAL_INSN_CODE_NAME);
7997*38fd1498Szrj   output_insn_code_cases (output_automata_list_min_issue_delay_code);
7998*38fd1498Szrj   fprintf (output_file,
7999*38fd1498Szrj 	   "\n    default:\n      %s = -1;\n      break;\n    }\n",
8000*38fd1498Szrj 	   RESULT_VARIABLE_NAME);
8001*38fd1498Szrj   fprintf (output_file, "  return %s;\n", RESULT_VARIABLE_NAME);
8002*38fd1498Szrj   fprintf (output_file, "}\n\n");
8003*38fd1498Szrj }
8004*38fd1498Szrj 
8005*38fd1498Szrj /* The function outputs a code changing state after issue of insns
8006*38fd1498Szrj    which have reservations in given AUTOMATA_LIST.  */
8007*38fd1498Szrj static void
output_automata_list_transition_code(automata_list_el_t automata_list)8008*38fd1498Szrj output_automata_list_transition_code (automata_list_el_t automata_list)
8009*38fd1498Szrj {
8010*38fd1498Szrj   automata_list_el_t el, next_el;
8011*38fd1498Szrj 
8012*38fd1498Szrj   fprintf (output_file, "      {\n");
8013*38fd1498Szrj   if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
8014*38fd1498Szrj     for (el = automata_list;; el = next_el)
8015*38fd1498Szrj       {
8016*38fd1498Szrj         next_el = el->next_automata_list_el;
8017*38fd1498Szrj         if (next_el == NULL)
8018*38fd1498Szrj           break;
8019*38fd1498Szrj         fprintf (output_file, "        ");
8020*38fd1498Szrj         output_state_member_type (output_file, el->automaton);
8021*38fd1498Szrj 	fprintf (output_file, " ");
8022*38fd1498Szrj         output_temp_chip_member_name (output_file, el->automaton);
8023*38fd1498Szrj         fprintf (output_file, ";\n");
8024*38fd1498Szrj       }
8025*38fd1498Szrj   for (el = automata_list; el != NULL; el = el->next_automata_list_el)
8026*38fd1498Szrj     if (comb_vect_p (el->automaton->trans_table))
8027*38fd1498Szrj       {
8028*38fd1498Szrj 	fprintf (output_file, "\n        %s = ", TEMPORARY_VARIABLE_NAME);
8029*38fd1498Szrj 	output_trans_base_vect_name (output_file, el->automaton);
8030*38fd1498Szrj 	fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
8031*38fd1498Szrj 	output_chip_member_name (output_file, el->automaton);
8032*38fd1498Szrj 	fprintf (output_file, "] + ");
8033*38fd1498Szrj 	output_translate_vect_name (output_file, el->automaton);
8034*38fd1498Szrj 	fprintf (output_file, " [%s];\n", INTERNAL_INSN_CODE_NAME);
8035*38fd1498Szrj 	fprintf (output_file, "        if (");
8036*38fd1498Szrj 	output_trans_check_vect_name (output_file, el->automaton);
8037*38fd1498Szrj 	fprintf (output_file, " [%s] != %s->",
8038*38fd1498Szrj 		 TEMPORARY_VARIABLE_NAME, CHIP_PARAMETER_NAME);
8039*38fd1498Szrj 	output_chip_member_name (output_file, el->automaton);
8040*38fd1498Szrj 	fprintf (output_file, ")\n");
8041*38fd1498Szrj 	fprintf (output_file, "          return %s (%s, %s);\n",
8042*38fd1498Szrj 		 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8043*38fd1498Szrj 		 CHIP_PARAMETER_NAME);
8044*38fd1498Szrj 	fprintf (output_file, "        else\n");
8045*38fd1498Szrj 	fprintf (output_file, "          ");
8046*38fd1498Szrj 	if (el->next_automata_list_el != NULL)
8047*38fd1498Szrj 	  output_temp_chip_member_name (output_file, el->automaton);
8048*38fd1498Szrj 	else
8049*38fd1498Szrj 	  {
8050*38fd1498Szrj 	    fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
8051*38fd1498Szrj 	    output_chip_member_name (output_file, el->automaton);
8052*38fd1498Szrj 	  }
8053*38fd1498Szrj 	fprintf (output_file, " = ");
8054*38fd1498Szrj 	output_trans_comb_vect_name (output_file, el->automaton);
8055*38fd1498Szrj 	fprintf (output_file, " [%s];\n", TEMPORARY_VARIABLE_NAME);
8056*38fd1498Szrj       }
8057*38fd1498Szrj     else
8058*38fd1498Szrj       {
8059*38fd1498Szrj 	fprintf (output_file, "\n        %s = ", TEMPORARY_VARIABLE_NAME);
8060*38fd1498Szrj 	output_trans_full_vect_name (output_file, el->automaton);
8061*38fd1498Szrj 	fprintf (output_file, " [");
8062*38fd1498Szrj 	output_translate_vect_name (output_file, el->automaton);
8063*38fd1498Szrj 	fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
8064*38fd1498Szrj 	fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
8065*38fd1498Szrj 	output_chip_member_name (output_file, el->automaton);
8066*38fd1498Szrj 	fprintf (output_file, " * %d];\n",
8067*38fd1498Szrj 		 el->automaton->insn_equiv_classes_num);
8068*38fd1498Szrj 	fprintf (output_file, "        if (%s >= %d)\n",
8069*38fd1498Szrj 		 TEMPORARY_VARIABLE_NAME, el->automaton->achieved_states_num);
8070*38fd1498Szrj 	fprintf (output_file, "          return %s (%s, %s);\n",
8071*38fd1498Szrj 		 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8072*38fd1498Szrj 		 CHIP_PARAMETER_NAME);
8073*38fd1498Szrj 	fprintf (output_file, "        else\n          ");
8074*38fd1498Szrj 	if (el->next_automata_list_el != NULL)
8075*38fd1498Szrj 	  output_temp_chip_member_name (output_file, el->automaton);
8076*38fd1498Szrj 	else
8077*38fd1498Szrj 	  {
8078*38fd1498Szrj 	    fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
8079*38fd1498Szrj 	    output_chip_member_name (output_file, el->automaton);
8080*38fd1498Szrj 	  }
8081*38fd1498Szrj 	fprintf (output_file, " = %s;\n", TEMPORARY_VARIABLE_NAME);
8082*38fd1498Szrj       }
8083*38fd1498Szrj   if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
8084*38fd1498Szrj     for (el = automata_list;; el = next_el)
8085*38fd1498Szrj       {
8086*38fd1498Szrj         next_el = el->next_automata_list_el;
8087*38fd1498Szrj         if (next_el == NULL)
8088*38fd1498Szrj           break;
8089*38fd1498Szrj         fprintf (output_file, "        %s->", CHIP_PARAMETER_NAME);
8090*38fd1498Szrj         output_chip_member_name (output_file, el->automaton);
8091*38fd1498Szrj         fprintf (output_file, " = ");
8092*38fd1498Szrj         output_temp_chip_member_name (output_file, el->automaton);
8093*38fd1498Szrj         fprintf (output_file, ";\n");
8094*38fd1498Szrj       }
8095*38fd1498Szrj   fprintf (output_file, "        return -1;\n");
8096*38fd1498Szrj   fprintf (output_file, "      }\n");
8097*38fd1498Szrj }
8098*38fd1498Szrj 
8099*38fd1498Szrj /* Output function `internal_state_transition'.  */
8100*38fd1498Szrj static void
output_internal_trans_func(void)8101*38fd1498Szrj output_internal_trans_func (void)
8102*38fd1498Szrj {
8103*38fd1498Szrj   fprintf (output_file,
8104*38fd1498Szrj 	   "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
8105*38fd1498Szrj 	   INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8106*38fd1498Szrj 	   CHIP_NAME, CHIP_PARAMETER_NAME);
8107*38fd1498Szrj   fprintf (output_file, "{\n  int %s ATTRIBUTE_UNUSED;\n", TEMPORARY_VARIABLE_NAME);
8108*38fd1498Szrj   fprintf (output_file, "\n  switch (%s)\n    {\n", INTERNAL_INSN_CODE_NAME);
8109*38fd1498Szrj   output_insn_code_cases (output_automata_list_transition_code);
8110*38fd1498Szrj   fprintf (output_file, "\n    default:\n      return -1;\n    }\n");
8111*38fd1498Szrj   fprintf (output_file, "}\n\n");
8112*38fd1498Szrj }
8113*38fd1498Szrj 
8114*38fd1498Szrj /* Output code
8115*38fd1498Szrj 
8116*38fd1498Szrj   gcc_checking_assert (insn != 0);
8117*38fd1498Szrj   insn_code = dfa_insn_code (insn);
8118*38fd1498Szrj   if (insn_code >= DFA__ADVANCE_CYCLE)
8119*38fd1498Szrj     return code;
8120*38fd1498Szrj 
8121*38fd1498Szrj   where insn denotes INSN_NAME, insn_code denotes INSN_CODE_NAME, and
8122*38fd1498Szrj   code denotes CODE.  */
8123*38fd1498Szrj static void
output_internal_insn_code_evaluation(const char * insn_name,const char * insn_code_name,int code)8124*38fd1498Szrj output_internal_insn_code_evaluation (const char *insn_name,
8125*38fd1498Szrj 				      const char *insn_code_name,
8126*38fd1498Szrj 				      int code)
8127*38fd1498Szrj {
8128*38fd1498Szrj   fprintf (output_file, "  gcc_checking_assert (%s != 0);\n"
8129*38fd1498Szrj            "  %s = %s (%s);\n"
8130*38fd1498Szrj            "  if (%s >= %s)\n    return %d;\n",
8131*38fd1498Szrj            insn_name,
8132*38fd1498Szrj            insn_code_name, DFA_INSN_CODE_FUNC_NAME, insn_name,
8133*38fd1498Szrj            insn_code_name, ADVANCE_CYCLE_VALUE_NAME, code);
8134*38fd1498Szrj }
8135*38fd1498Szrj 
8136*38fd1498Szrj 
8137*38fd1498Szrj /* This function outputs `dfa_insn_code' and its helper function
8138*38fd1498Szrj    `dfa_insn_code_enlarge'.  */
8139*38fd1498Szrj static void
output_dfa_insn_code_func(void)8140*38fd1498Szrj output_dfa_insn_code_func (void)
8141*38fd1498Szrj {
8142*38fd1498Szrj   /* Emacs c-mode gets really confused if there's a { or } in column 0
8143*38fd1498Szrj      inside a string, so don't do that.  */
8144*38fd1498Szrj   fprintf (output_file, "\
8145*38fd1498Szrj static void\n\
8146*38fd1498Szrj dfa_insn_code_enlarge (int uid)\n\
8147*38fd1498Szrj {\n\
8148*38fd1498Szrj   int i = %s;\n\
8149*38fd1498Szrj   %s = 2 * uid;\n\
8150*38fd1498Szrj   %s = XRESIZEVEC (int, %s,\n\
8151*38fd1498Szrj                  %s);\n\
8152*38fd1498Szrj   for (; i < %s; i++)\n\
8153*38fd1498Szrj     %s[i] = -1;\n}\n\n",
8154*38fd1498Szrj 	   DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8155*38fd1498Szrj 	   DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8156*38fd1498Szrj 	   DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
8157*38fd1498Szrj 	   DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8158*38fd1498Szrj 	   DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8159*38fd1498Szrj 	   DFA_INSN_CODES_VARIABLE_NAME);
8160*38fd1498Szrj   fprintf (output_file, "\
8161*38fd1498Szrj static inline int\n%s (rtx_insn *%s)\n\
8162*38fd1498Szrj {\n\
8163*38fd1498Szrj   int uid = INSN_UID (%s);\n\
8164*38fd1498Szrj   int %s;\n\n",
8165*38fd1498Szrj 	   DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME,
8166*38fd1498Szrj 	   INSN_PARAMETER_NAME, INTERNAL_INSN_CODE_NAME);
8167*38fd1498Szrj 
8168*38fd1498Szrj   fprintf (output_file,
8169*38fd1498Szrj 	   "  if (uid >= %s)\n    dfa_insn_code_enlarge (uid);\n\n",
8170*38fd1498Szrj 	   DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8171*38fd1498Szrj   fprintf (output_file, "  %s = %s[uid];\n",
8172*38fd1498Szrj 	   INTERNAL_INSN_CODE_NAME, DFA_INSN_CODES_VARIABLE_NAME);
8173*38fd1498Szrj   fprintf (output_file, "\
8174*38fd1498Szrj   if (%s < 0)\n\
8175*38fd1498Szrj     {\n\
8176*38fd1498Szrj       %s = %s (%s);\n\
8177*38fd1498Szrj       %s[uid] = %s;\n\
8178*38fd1498Szrj     }\n",
8179*38fd1498Szrj 	   INTERNAL_INSN_CODE_NAME,
8180*38fd1498Szrj 	   INTERNAL_INSN_CODE_NAME,
8181*38fd1498Szrj 	   INTERNAL_DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME,
8182*38fd1498Szrj 	   DFA_INSN_CODES_VARIABLE_NAME, INTERNAL_INSN_CODE_NAME);
8183*38fd1498Szrj   fprintf (output_file, "  return %s;\n}\n\n", INTERNAL_INSN_CODE_NAME);
8184*38fd1498Szrj }
8185*38fd1498Szrj 
8186*38fd1498Szrj /* The function outputs PHR interface function `state_transition'.  */
8187*38fd1498Szrj static void
output_trans_func(void)8188*38fd1498Szrj output_trans_func (void)
8189*38fd1498Szrj {
8190*38fd1498Szrj   fprintf (output_file, "int\n%s (%s %s, rtx %s)\n",
8191*38fd1498Szrj 	   TRANSITION_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME,
8192*38fd1498Szrj 	   INSN_PARAMETER_NAME);
8193*38fd1498Szrj   fprintf (output_file, "{\n  int %s;\n", INTERNAL_INSN_CODE_NAME);
8194*38fd1498Szrj   fprintf (output_file, "\n  if (%s == 0)\n", INSN_PARAMETER_NAME);
8195*38fd1498Szrj   fprintf (output_file, "    %s = %s;\n",
8196*38fd1498Szrj 	   INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8197*38fd1498Szrj   if (collapse_flag)
8198*38fd1498Szrj     {
8199*38fd1498Szrj       fprintf (output_file, "  else if (%s == const0_rtx)\n",
8200*38fd1498Szrj 	       INSN_PARAMETER_NAME);
8201*38fd1498Szrj       fprintf (output_file, "    %s = %s;\n",
8202*38fd1498Szrj 	       INTERNAL_INSN_CODE_NAME, COLLAPSE_NDFA_VALUE_NAME);
8203*38fd1498Szrj     }
8204*38fd1498Szrj   fprintf (output_file, "  else\n    {\n");
8205*38fd1498Szrj   fprintf (output_file, "      %s = %s (as_a <rtx_insn *> (%s));\n",
8206*38fd1498Szrj 	   INTERNAL_INSN_CODE_NAME, DFA_INSN_CODE_FUNC_NAME,
8207*38fd1498Szrj 	   INSN_PARAMETER_NAME);
8208*38fd1498Szrj   fprintf (output_file, "      if (%s > %s)\n        return -1;\n    }\n",
8209*38fd1498Szrj 	   INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8210*38fd1498Szrj   fprintf (output_file, "  return %s (%s, (struct %s *) %s);\n}\n\n",
8211*38fd1498Szrj 	   INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME, STATE_NAME);
8212*38fd1498Szrj }
8213*38fd1498Szrj 
8214*38fd1498Szrj /* Output function `min_issue_delay'.  */
8215*38fd1498Szrj static void
output_min_issue_delay_func(void)8216*38fd1498Szrj output_min_issue_delay_func (void)
8217*38fd1498Szrj {
8218*38fd1498Szrj   fprintf (output_file, "int\n%s (%s %s, rtx_insn *%s)\n",
8219*38fd1498Szrj 	   MIN_ISSUE_DELAY_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME,
8220*38fd1498Szrj 	   INSN_PARAMETER_NAME);
8221*38fd1498Szrj   fprintf (output_file, "{\n  int %s;\n", INTERNAL_INSN_CODE_NAME);
8222*38fd1498Szrj   fprintf (output_file, "\n  if (%s != 0)\n    {\n", INSN_PARAMETER_NAME);
8223*38fd1498Szrj   fprintf (output_file, "      %s = %s (%s);\n", INTERNAL_INSN_CODE_NAME,
8224*38fd1498Szrj 	   DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME);
8225*38fd1498Szrj   fprintf (output_file, "      if (%s > %s)\n        return 0;\n",
8226*38fd1498Szrj 	   INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8227*38fd1498Szrj   fprintf (output_file, "    }\n  else\n    %s = %s;\n",
8228*38fd1498Szrj 	   INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8229*38fd1498Szrj   fprintf (output_file, "\n  return %s (%s, (struct %s *) %s);\n",
8230*38fd1498Szrj 	   INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8231*38fd1498Szrj 	   CHIP_NAME, STATE_NAME);
8232*38fd1498Szrj   fprintf (output_file, "}\n\n");
8233*38fd1498Szrj }
8234*38fd1498Szrj 
8235*38fd1498Szrj /* Output function `internal_dead_lock'.  */
8236*38fd1498Szrj static void
output_internal_dead_lock_func(void)8237*38fd1498Szrj output_internal_dead_lock_func (void)
8238*38fd1498Szrj {
8239*38fd1498Szrj   automaton_t automaton;
8240*38fd1498Szrj 
8241*38fd1498Szrj   fprintf (output_file, "static int\n%s (struct %s *ARG_UNUSED (%s))\n",
8242*38fd1498Szrj 	   INTERNAL_DEAD_LOCK_FUNC_NAME, CHIP_NAME, CHIP_PARAMETER_NAME);
8243*38fd1498Szrj   fprintf (output_file, "{\n");
8244*38fd1498Szrj   for (automaton = description->first_automaton;
8245*38fd1498Szrj        automaton != NULL;
8246*38fd1498Szrj        automaton = automaton->next_automaton)
8247*38fd1498Szrj     if (automaton->locked_states)
8248*38fd1498Szrj       {
8249*38fd1498Szrj 	fprintf (output_file, "  if (");
8250*38fd1498Szrj 	output_dead_lock_vect_name (output_file, automaton);
8251*38fd1498Szrj 	fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
8252*38fd1498Szrj 	output_chip_member_name (output_file, automaton);
8253*38fd1498Szrj 	fprintf (output_file, "])\n    return 1/* TRUE */;\n");
8254*38fd1498Szrj       }
8255*38fd1498Szrj   fprintf (output_file, "  return 0/* FALSE */;\n}\n\n");
8256*38fd1498Szrj }
8257*38fd1498Szrj 
8258*38fd1498Szrj /* The function outputs PHR interface function `state_dead_lock_p'.  */
8259*38fd1498Szrj static void
output_dead_lock_func(void)8260*38fd1498Szrj output_dead_lock_func (void)
8261*38fd1498Szrj {
8262*38fd1498Szrj   fprintf (output_file, "int\n%s (%s %s)\n",
8263*38fd1498Szrj 	   DEAD_LOCK_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME);
8264*38fd1498Szrj   fprintf (output_file, "{\n  return %s ((struct %s *) %s);\n}\n\n",
8265*38fd1498Szrj 	   INTERNAL_DEAD_LOCK_FUNC_NAME, CHIP_NAME, STATE_NAME);
8266*38fd1498Szrj }
8267*38fd1498Szrj 
8268*38fd1498Szrj /* Output function `internal_reset'.  */
8269*38fd1498Szrj static void
output_internal_reset_func(void)8270*38fd1498Szrj output_internal_reset_func (void)
8271*38fd1498Szrj {
8272*38fd1498Szrj   fprintf (output_file, "static inline void\n%s (struct %s *%s)\n",
8273*38fd1498Szrj 	   INTERNAL_RESET_FUNC_NAME, CHIP_NAME, CHIP_PARAMETER_NAME);
8274*38fd1498Szrj   fprintf (output_file, "{\n  memset (%s, 0, sizeof (struct %s));\n}\n\n",
8275*38fd1498Szrj 	   CHIP_PARAMETER_NAME, CHIP_NAME);
8276*38fd1498Szrj }
8277*38fd1498Szrj 
8278*38fd1498Szrj /* The function outputs PHR interface function `state_size'.  */
8279*38fd1498Szrj static void
output_size_func(void)8280*38fd1498Szrj output_size_func (void)
8281*38fd1498Szrj {
8282*38fd1498Szrj   fprintf (output_file, "int\n%s (void)\n", SIZE_FUNC_NAME);
8283*38fd1498Szrj   fprintf (output_file, "{\n  return sizeof (struct %s);\n}\n\n", CHIP_NAME);
8284*38fd1498Szrj }
8285*38fd1498Szrj 
8286*38fd1498Szrj /* The function outputs PHR interface function `state_reset'.  */
8287*38fd1498Szrj static void
output_reset_func(void)8288*38fd1498Szrj output_reset_func (void)
8289*38fd1498Szrj {
8290*38fd1498Szrj   fprintf (output_file, "void\n%s (%s %s)\n",
8291*38fd1498Szrj 	   RESET_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME);
8292*38fd1498Szrj   fprintf (output_file, "{\n  %s ((struct %s *) %s);\n}\n\n", INTERNAL_RESET_FUNC_NAME,
8293*38fd1498Szrj 	   CHIP_NAME, STATE_NAME);
8294*38fd1498Szrj }
8295*38fd1498Szrj 
8296*38fd1498Szrj /* Output function `min_insn_conflict_delay'.  */
8297*38fd1498Szrj static void
output_min_insn_conflict_delay_func(void)8298*38fd1498Szrj output_min_insn_conflict_delay_func (void)
8299*38fd1498Szrj {
8300*38fd1498Szrj   fprintf (output_file,
8301*38fd1498Szrj 	   "int\n%s (%s %s, rtx_insn *%s, rtx_insn *%s)\n",
8302*38fd1498Szrj 	   MIN_INSN_CONFLICT_DELAY_FUNC_NAME, STATE_TYPE_NAME,
8303*38fd1498Szrj 	   STATE_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8304*38fd1498Szrj   fprintf (output_file, "{\n  struct %s %s;\n  int %s, %s, transition;\n",
8305*38fd1498Szrj 	   CHIP_NAME, CHIP_NAME, INTERNAL_INSN_CODE_NAME,
8306*38fd1498Szrj 	   INTERNAL_INSN2_CODE_NAME);
8307*38fd1498Szrj   output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8308*38fd1498Szrj 					INTERNAL_INSN_CODE_NAME, 0);
8309*38fd1498Szrj   output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
8310*38fd1498Szrj 					INTERNAL_INSN2_CODE_NAME, 0);
8311*38fd1498Szrj   fprintf (output_file, "  memcpy (&%s, %s, sizeof (%s));\n",
8312*38fd1498Szrj 	   CHIP_NAME, STATE_NAME, CHIP_NAME);
8313*38fd1498Szrj   fprintf (output_file, "  %s (&%s);\n", INTERNAL_RESET_FUNC_NAME, CHIP_NAME);
8314*38fd1498Szrj   fprintf (output_file, "  transition = %s (%s, &%s);\n",
8315*38fd1498Szrj 	   INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME);
8316*38fd1498Szrj   fprintf (output_file, "  gcc_assert (transition <= 0);\n");
8317*38fd1498Szrj   fprintf (output_file, "  return %s (%s, &%s);\n",
8318*38fd1498Szrj 	   INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN2_CODE_NAME,
8319*38fd1498Szrj 	   CHIP_NAME);
8320*38fd1498Szrj   fprintf (output_file, "}\n\n");
8321*38fd1498Szrj }
8322*38fd1498Szrj 
8323*38fd1498Szrj /* Output the array holding default latency values.  These are used in
8324*38fd1498Szrj    insn_latency and maximal_insn_latency function implementations.  */
8325*38fd1498Szrj static void
output_default_latencies(void)8326*38fd1498Szrj output_default_latencies (void)
8327*38fd1498Szrj {
8328*38fd1498Szrj   int i, j, col;
8329*38fd1498Szrj   decl_t decl;
8330*38fd1498Szrj   const char *tabletype = "unsigned char";
8331*38fd1498Szrj 
8332*38fd1498Szrj   /* Find the smallest integer type that can hold all the default
8333*38fd1498Szrj      latency values.  */
8334*38fd1498Szrj   for (i = 0; i < description->decls_num; i++)
8335*38fd1498Szrj     if (description->decls[i]->mode == dm_insn_reserv)
8336*38fd1498Szrj       {
8337*38fd1498Szrj 	decl = description->decls[i];
8338*38fd1498Szrj 	if (DECL_INSN_RESERV (decl)->default_latency > UCHAR_MAX
8339*38fd1498Szrj 	    && tabletype[0] != 'i')  /* Don't shrink it.  */
8340*38fd1498Szrj 	  tabletype = "unsigned short";
8341*38fd1498Szrj 	if (DECL_INSN_RESERV (decl)->default_latency > USHRT_MAX)
8342*38fd1498Szrj 	  tabletype = "int";
8343*38fd1498Szrj       }
8344*38fd1498Szrj 
8345*38fd1498Szrj   fprintf (output_file, "  static const %s default_latencies[] =\n    {",
8346*38fd1498Szrj 	   tabletype);
8347*38fd1498Szrj 
8348*38fd1498Szrj   for (i = 0, j = 0, col = 7; i < description->normal_decls_num; i++)
8349*38fd1498Szrj     if (description->decls[i]->mode == dm_insn_reserv)
8350*38fd1498Szrj       {
8351*38fd1498Szrj 	if ((col = (col+1) % 8) == 0)
8352*38fd1498Szrj 	  fputs ("\n     ", output_file);
8353*38fd1498Szrj 	decl = description->decls[i];
8354*38fd1498Szrj 	gcc_assert (j++ == DECL_INSN_RESERV (decl)->insn_num);
8355*38fd1498Szrj 	fprintf (output_file, "% 4d,",
8356*38fd1498Szrj 		 DECL_INSN_RESERV (decl)->default_latency);
8357*38fd1498Szrj       }
8358*38fd1498Szrj   gcc_assert (j == description->insns_num - (collapse_flag ? 2 : 1));
8359*38fd1498Szrj   fputs ("\n    };\n", output_file);
8360*38fd1498Szrj }
8361*38fd1498Szrj 
8362*38fd1498Szrj /* Output function `internal_insn_latency'.  */
8363*38fd1498Szrj static void
output_internal_insn_latency_func(void)8364*38fd1498Szrj output_internal_insn_latency_func (void)
8365*38fd1498Szrj {
8366*38fd1498Szrj   int i;
8367*38fd1498Szrj   decl_t decl;
8368*38fd1498Szrj   struct bypass_decl *bypass;
8369*38fd1498Szrj 
8370*38fd1498Szrj   fprintf (output_file, "static int\n"
8371*38fd1498Szrj 	   "%s (int %s ATTRIBUTE_UNUSED, int %s ATTRIBUTE_UNUSED,\n"
8372*38fd1498Szrj 	   "\trtx_insn *%s ATTRIBUTE_UNUSED, rtx_insn *%s ATTRIBUTE_UNUSED)\n",
8373*38fd1498Szrj 	   INTERNAL_INSN_LATENCY_FUNC_NAME,
8374*38fd1498Szrj 	   INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME,
8375*38fd1498Szrj 	   INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8376*38fd1498Szrj   fprintf (output_file, "{\n");
8377*38fd1498Szrj 
8378*38fd1498Szrj   if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8379*38fd1498Szrj     {
8380*38fd1498Szrj       fputs ("  return 0;\n}\n\n", output_file);
8381*38fd1498Szrj       return;
8382*38fd1498Szrj     }
8383*38fd1498Szrj 
8384*38fd1498Szrj   fprintf (output_file, "  switch (%s)\n    {\n", INTERNAL_INSN_CODE_NAME);
8385*38fd1498Szrj   for (i = 0; i < description->decls_num; i++)
8386*38fd1498Szrj     if (description->decls[i]->mode == dm_insn_reserv
8387*38fd1498Szrj 	&& DECL_INSN_RESERV (description->decls[i])->bypass_list)
8388*38fd1498Szrj       {
8389*38fd1498Szrj 	decl = description->decls [i];
8390*38fd1498Szrj 	fprintf (output_file,
8391*38fd1498Szrj 		 "    case %d:\n      switch (%s)\n        {\n",
8392*38fd1498Szrj 		 DECL_INSN_RESERV (decl)->insn_num,
8393*38fd1498Szrj 		 INTERNAL_INSN2_CODE_NAME);
8394*38fd1498Szrj 	for (bypass = DECL_INSN_RESERV (decl)->bypass_list;
8395*38fd1498Szrj 	     bypass != NULL;
8396*38fd1498Szrj 	     bypass = bypass->next)
8397*38fd1498Szrj 	  {
8398*38fd1498Szrj 	    gcc_assert (bypass->in_insn_reserv->insn_num
8399*38fd1498Szrj 			!= (DECL_INSN_RESERV
8400*38fd1498Szrj 			    (advance_cycle_insn_decl)->insn_num));
8401*38fd1498Szrj 	    fprintf (output_file, "        case %d:\n",
8402*38fd1498Szrj 		     bypass->in_insn_reserv->insn_num);
8403*38fd1498Szrj 	    for (;;)
8404*38fd1498Szrj 	      {
8405*38fd1498Szrj 		if (bypass->bypass_guard_name == NULL)
8406*38fd1498Szrj 		  {
8407*38fd1498Szrj 		    gcc_assert (bypass->next == NULL
8408*38fd1498Szrj 				|| (bypass->in_insn_reserv
8409*38fd1498Szrj 				    != bypass->next->in_insn_reserv));
8410*38fd1498Szrj 		    fprintf (output_file, "          return %d;\n",
8411*38fd1498Szrj 			     bypass->latency);
8412*38fd1498Szrj 		  }
8413*38fd1498Szrj 		else
8414*38fd1498Szrj 		  {
8415*38fd1498Szrj 		    fprintf (output_file,
8416*38fd1498Szrj 			     "          if (%s (%s, %s))\n",
8417*38fd1498Szrj 			     bypass->bypass_guard_name, INSN_PARAMETER_NAME,
8418*38fd1498Szrj 			     INSN2_PARAMETER_NAME);
8419*38fd1498Szrj 		    fprintf (output_file, "            return %d;\n",
8420*38fd1498Szrj 			     bypass->latency);
8421*38fd1498Szrj 		  }
8422*38fd1498Szrj 		if (bypass->next == NULL
8423*38fd1498Szrj 		    || bypass->in_insn_reserv != bypass->next->in_insn_reserv)
8424*38fd1498Szrj 		  break;
8425*38fd1498Szrj 		bypass = bypass->next;
8426*38fd1498Szrj 	      }
8427*38fd1498Szrj 	    if (bypass->bypass_guard_name != NULL)
8428*38fd1498Szrj 	      fprintf (output_file, "          break;\n");
8429*38fd1498Szrj 	  }
8430*38fd1498Szrj 	fputs ("        }\n      break;\n", output_file);
8431*38fd1498Szrj       }
8432*38fd1498Szrj 
8433*38fd1498Szrj   fprintf (output_file, "    }\n  return default_latencies[%s];\n}\n\n",
8434*38fd1498Szrj 	   INTERNAL_INSN_CODE_NAME);
8435*38fd1498Szrj }
8436*38fd1498Szrj 
8437*38fd1498Szrj /* Output function `internal_maximum_insn_latency'.  */
8438*38fd1498Szrj static void
output_internal_maximal_insn_latency_func(void)8439*38fd1498Szrj output_internal_maximal_insn_latency_func (void)
8440*38fd1498Szrj {
8441*38fd1498Szrj   decl_t decl;
8442*38fd1498Szrj   struct bypass_decl *bypass;
8443*38fd1498Szrj   int i;
8444*38fd1498Szrj   int max;
8445*38fd1498Szrj 
8446*38fd1498Szrj   fprintf (output_file, "static int\n%s (int %s ATTRIBUTE_UNUSED)\n",
8447*38fd1498Szrj 	   "internal_maximal_insn_latency", INTERNAL_INSN_CODE_NAME);
8448*38fd1498Szrj   fprintf (output_file, "{\n");
8449*38fd1498Szrj 
8450*38fd1498Szrj   if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8451*38fd1498Szrj     {
8452*38fd1498Szrj       fputs ("  return 0;\n}\n\n", output_file);
8453*38fd1498Szrj       return;
8454*38fd1498Szrj     }
8455*38fd1498Szrj 
8456*38fd1498Szrj   fprintf (output_file, "  switch (%s)\n    {\n", INTERNAL_INSN_CODE_NAME);
8457*38fd1498Szrj   for (i = 0; i < description->decls_num; i++)
8458*38fd1498Szrj     if (description->decls[i]->mode == dm_insn_reserv
8459*38fd1498Szrj 	&& DECL_INSN_RESERV (description->decls[i])->bypass_list)
8460*38fd1498Szrj       {
8461*38fd1498Szrj 	decl = description->decls [i];
8462*38fd1498Szrj         max = DECL_INSN_RESERV (decl)->default_latency;
8463*38fd1498Szrj 	fprintf (output_file,
8464*38fd1498Szrj 		 "    case %d: {",
8465*38fd1498Szrj 		 DECL_INSN_RESERV (decl)->insn_num);
8466*38fd1498Szrj 	for (bypass = DECL_INSN_RESERV (decl)->bypass_list;
8467*38fd1498Szrj 	     bypass != NULL;
8468*38fd1498Szrj 	     bypass = bypass->next)
8469*38fd1498Szrj 	  {
8470*38fd1498Szrj 	    if (bypass->latency > max)
8471*38fd1498Szrj               max = bypass->latency;
8472*38fd1498Szrj 	  }
8473*38fd1498Szrj 	fprintf (output_file, " return %d; }\n      break;\n", max);
8474*38fd1498Szrj       }
8475*38fd1498Szrj 
8476*38fd1498Szrj   fprintf (output_file, "    }\n  return default_latencies[%s];\n}\n\n",
8477*38fd1498Szrj 	   INTERNAL_INSN_CODE_NAME);
8478*38fd1498Szrj }
8479*38fd1498Szrj 
8480*38fd1498Szrj /* The function outputs PHR interface function `insn_latency'.  */
8481*38fd1498Szrj static void
output_insn_latency_func(void)8482*38fd1498Szrj output_insn_latency_func (void)
8483*38fd1498Szrj {
8484*38fd1498Szrj   fprintf (output_file, "int\n%s (rtx_insn *%s, rtx_insn *%s)\n",
8485*38fd1498Szrj 	   INSN_LATENCY_FUNC_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8486*38fd1498Szrj   fprintf (output_file, "{\n  int %s, %s;\n",
8487*38fd1498Szrj 	   INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME);
8488*38fd1498Szrj   output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8489*38fd1498Szrj 					INTERNAL_INSN_CODE_NAME, 0);
8490*38fd1498Szrj   output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
8491*38fd1498Szrj 					INTERNAL_INSN2_CODE_NAME, 0);
8492*38fd1498Szrj   fprintf (output_file, "  return %s (%s, %s, %s, %s);\n}\n\n",
8493*38fd1498Szrj 	   INTERNAL_INSN_LATENCY_FUNC_NAME,
8494*38fd1498Szrj 	   INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME,
8495*38fd1498Szrj 	   INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8496*38fd1498Szrj }
8497*38fd1498Szrj 
8498*38fd1498Szrj /* The function outputs PHR interface function `maximal_insn_latency'.  */
8499*38fd1498Szrj static void
output_maximal_insn_latency_func(void)8500*38fd1498Szrj output_maximal_insn_latency_func (void)
8501*38fd1498Szrj {
8502*38fd1498Szrj   fprintf (output_file, "int\n%s (rtx_insn *%s)\n",
8503*38fd1498Szrj 	   "maximal_insn_latency", INSN_PARAMETER_NAME);
8504*38fd1498Szrj   fprintf (output_file, "{\n  int %s;\n",
8505*38fd1498Szrj 	   INTERNAL_INSN_CODE_NAME);
8506*38fd1498Szrj   output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8507*38fd1498Szrj 					INTERNAL_INSN_CODE_NAME, 0);
8508*38fd1498Szrj   fprintf (output_file, "  return %s (%s);\n}\n\n",
8509*38fd1498Szrj 	   "internal_maximal_insn_latency", INTERNAL_INSN_CODE_NAME);
8510*38fd1498Szrj }
8511*38fd1498Szrj 
8512*38fd1498Szrj /* The function outputs PHR interface function `print_reservation'.  */
8513*38fd1498Szrj static void
output_print_reservation_func(void)8514*38fd1498Szrj output_print_reservation_func (void)
8515*38fd1498Szrj {
8516*38fd1498Szrj   decl_t decl;
8517*38fd1498Szrj   int i, j;
8518*38fd1498Szrj 
8519*38fd1498Szrj   fprintf (output_file,
8520*38fd1498Szrj 	   "void\n%s (FILE *%s, rtx_insn *%s ATTRIBUTE_UNUSED)\n{\n",
8521*38fd1498Szrj            PRINT_RESERVATION_FUNC_NAME, FILE_PARAMETER_NAME,
8522*38fd1498Szrj            INSN_PARAMETER_NAME);
8523*38fd1498Szrj 
8524*38fd1498Szrj   if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8525*38fd1498Szrj     {
8526*38fd1498Szrj       fprintf (output_file, "  fputs (\"%s\", %s);\n}\n\n",
8527*38fd1498Szrj 	       NOTHING_NAME, FILE_PARAMETER_NAME);
8528*38fd1498Szrj       return;
8529*38fd1498Szrj     }
8530*38fd1498Szrj 
8531*38fd1498Szrj 
8532*38fd1498Szrj   fputs ("  static const char *const reservation_names[] =\n    {",
8533*38fd1498Szrj 	 output_file);
8534*38fd1498Szrj 
8535*38fd1498Szrj   for (i = 0, j = 0; i < description->normal_decls_num; i++)
8536*38fd1498Szrj     {
8537*38fd1498Szrj       decl = description->decls [i];
8538*38fd1498Szrj       if (decl->mode == dm_insn_reserv)
8539*38fd1498Szrj 	{
8540*38fd1498Szrj 	  gcc_assert (j == DECL_INSN_RESERV (decl)->insn_num);
8541*38fd1498Szrj 	  j++;
8542*38fd1498Szrj 
8543*38fd1498Szrj 	  fprintf (output_file, "\n      \"%s\",",
8544*38fd1498Szrj 		   regexp_representation (DECL_INSN_RESERV (decl)->regexp));
8545*38fd1498Szrj 	  finish_regexp_representation ();
8546*38fd1498Szrj 	}
8547*38fd1498Szrj     }
8548*38fd1498Szrj   gcc_assert (j == description->insns_num - (collapse_flag ? 2 : 1));
8549*38fd1498Szrj 
8550*38fd1498Szrj   fprintf (output_file, "\n      \"%s\"\n    };\n  int %s;\n\n",
8551*38fd1498Szrj 	   NOTHING_NAME, INTERNAL_INSN_CODE_NAME);
8552*38fd1498Szrj 
8553*38fd1498Szrj   fprintf (output_file, "  if (%s == 0)\n    %s = %s;\n",
8554*38fd1498Szrj 	   INSN_PARAMETER_NAME,
8555*38fd1498Szrj 	   INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8556*38fd1498Szrj   fprintf (output_file, "  else\n\
8557*38fd1498Szrj     {\n\
8558*38fd1498Szrj       %s = %s (%s);\n\
8559*38fd1498Szrj       if (%s > %s)\n\
8560*38fd1498Szrj         %s = %s;\n\
8561*38fd1498Szrj     }\n",
8562*38fd1498Szrj 	   INTERNAL_INSN_CODE_NAME, DFA_INSN_CODE_FUNC_NAME,
8563*38fd1498Szrj 	       INSN_PARAMETER_NAME,
8564*38fd1498Szrj 	   INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8565*38fd1498Szrj 	   INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8566*38fd1498Szrj 
8567*38fd1498Szrj   fprintf (output_file, "  fputs (reservation_names[%s], %s);\n}\n\n",
8568*38fd1498Szrj 	   INTERNAL_INSN_CODE_NAME, FILE_PARAMETER_NAME);
8569*38fd1498Szrj }
8570*38fd1498Szrj 
8571*38fd1498Szrj /* The following function is used to sort unit declaration by their
8572*38fd1498Szrj    names.  */
8573*38fd1498Szrj static int
units_cmp(const void * unit1,const void * unit2)8574*38fd1498Szrj units_cmp (const void *unit1, const void *unit2)
8575*38fd1498Szrj {
8576*38fd1498Szrj   const_unit_decl_t const u1 = *(const_unit_decl_t const*) unit1;
8577*38fd1498Szrj   const_unit_decl_t const u2 = *(const_unit_decl_t const*) unit2;
8578*38fd1498Szrj 
8579*38fd1498Szrj   return strcmp (u1->name, u2->name);
8580*38fd1498Szrj }
8581*38fd1498Szrj 
8582*38fd1498Szrj /* The following macro value is name of struct containing unit name
8583*38fd1498Szrj    and unit code.  */
8584*38fd1498Szrj #define NAME_CODE_STRUCT_NAME  "name_code"
8585*38fd1498Szrj 
8586*38fd1498Szrj /* The following macro value is name of table of struct name_code.  */
8587*38fd1498Szrj #define NAME_CODE_TABLE_NAME   "name_code_table"
8588*38fd1498Szrj 
8589*38fd1498Szrj /* The following macro values are member names for struct name_code.  */
8590*38fd1498Szrj #define NAME_MEMBER_NAME       "name"
8591*38fd1498Szrj #define CODE_MEMBER_NAME       "code"
8592*38fd1498Szrj 
8593*38fd1498Szrj /* The following macro values are local variable names for function
8594*38fd1498Szrj    `get_cpu_unit_code'.  */
8595*38fd1498Szrj #define CMP_VARIABLE_NAME      "cmp"
8596*38fd1498Szrj #define LOW_VARIABLE_NAME      "l"
8597*38fd1498Szrj #define MIDDLE_VARIABLE_NAME   "m"
8598*38fd1498Szrj #define HIGH_VARIABLE_NAME     "h"
8599*38fd1498Szrj 
8600*38fd1498Szrj /* The following function outputs function to obtain internal cpu unit
8601*38fd1498Szrj    code by the cpu unit name.  */
8602*38fd1498Szrj static void
output_get_cpu_unit_code_func(void)8603*38fd1498Szrj output_get_cpu_unit_code_func (void)
8604*38fd1498Szrj {
8605*38fd1498Szrj   int i;
8606*38fd1498Szrj   unit_decl_t *units;
8607*38fd1498Szrj 
8608*38fd1498Szrj   fprintf (output_file, "int\n%s (const char *%s)\n",
8609*38fd1498Szrj 	   GET_CPU_UNIT_CODE_FUNC_NAME, CPU_UNIT_NAME_PARAMETER_NAME);
8610*38fd1498Szrj   fprintf (output_file, "{\n  struct %s {const char *%s; int %s;};\n",
8611*38fd1498Szrj 	   NAME_CODE_STRUCT_NAME, NAME_MEMBER_NAME, CODE_MEMBER_NAME);
8612*38fd1498Szrj   fprintf (output_file, "  int %s, %s, %s, %s;\n", CMP_VARIABLE_NAME,
8613*38fd1498Szrj 	   LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8614*38fd1498Szrj   fprintf (output_file, "  static struct %s %s [] =\n    {\n",
8615*38fd1498Szrj 	   NAME_CODE_STRUCT_NAME, NAME_CODE_TABLE_NAME);
8616*38fd1498Szrj   units = XNEWVEC (unit_decl_t, description->units_num);
8617*38fd1498Szrj   memcpy (units, units_array, sizeof (unit_decl_t) * description->units_num);
8618*38fd1498Szrj   qsort (units, description->units_num, sizeof (unit_decl_t), units_cmp);
8619*38fd1498Szrj   for (i = 0; i < description->units_num; i++)
8620*38fd1498Szrj     if (units [i]->query_p)
8621*38fd1498Szrj       fprintf (output_file, "      {\"%s\", %d},\n",
8622*38fd1498Szrj 	       units[i]->name, units[i]->query_num);
8623*38fd1498Szrj   fprintf (output_file, "    };\n\n");
8624*38fd1498Szrj   fprintf (output_file, "  /* The following is binary search: */\n");
8625*38fd1498Szrj   fprintf (output_file, "  %s = 0;\n", LOW_VARIABLE_NAME);
8626*38fd1498Szrj   fprintf (output_file, "  %s = sizeof (%s) / sizeof (struct %s) - 1;\n",
8627*38fd1498Szrj 	   HIGH_VARIABLE_NAME, NAME_CODE_TABLE_NAME, NAME_CODE_STRUCT_NAME);
8628*38fd1498Szrj   fprintf (output_file, "  while (%s <= %s)\n    {\n",
8629*38fd1498Szrj 	   LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8630*38fd1498Szrj   fprintf (output_file, "      %s = (%s + %s) / 2;\n",
8631*38fd1498Szrj 	   MIDDLE_VARIABLE_NAME, LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8632*38fd1498Szrj   fprintf (output_file, "      %s = strcmp (%s, %s [%s].%s);\n",
8633*38fd1498Szrj 	   CMP_VARIABLE_NAME, CPU_UNIT_NAME_PARAMETER_NAME,
8634*38fd1498Szrj 	   NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, NAME_MEMBER_NAME);
8635*38fd1498Szrj   fprintf (output_file, "      if (%s < 0)\n", CMP_VARIABLE_NAME);
8636*38fd1498Szrj   fprintf (output_file, "        %s = %s - 1;\n",
8637*38fd1498Szrj 	   HIGH_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
8638*38fd1498Szrj   fprintf (output_file, "      else if (%s > 0)\n", CMP_VARIABLE_NAME);
8639*38fd1498Szrj   fprintf (output_file, "        %s = %s + 1;\n",
8640*38fd1498Szrj 	   LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
8641*38fd1498Szrj   fprintf (output_file, "      else\n");
8642*38fd1498Szrj   fprintf (output_file, "        return %s [%s].%s;\n    }\n",
8643*38fd1498Szrj 	   NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, CODE_MEMBER_NAME);
8644*38fd1498Szrj   fprintf (output_file, "  return -1;\n}\n\n");
8645*38fd1498Szrj   free (units);
8646*38fd1498Szrj }
8647*38fd1498Szrj 
8648*38fd1498Szrj /* The following function outputs function to check reservation of cpu
8649*38fd1498Szrj    unit (its internal code will be passed as the function argument) in
8650*38fd1498Szrj    given cpu state.  */
8651*38fd1498Szrj static void
output_cpu_unit_reservation_p(void)8652*38fd1498Szrj output_cpu_unit_reservation_p (void)
8653*38fd1498Szrj {
8654*38fd1498Szrj   automaton_t automaton;
8655*38fd1498Szrj 
8656*38fd1498Szrj   fprintf (output_file, "int\n%s (%s %s, int %s)\n",
8657*38fd1498Szrj 	   CPU_UNIT_RESERVATION_P_FUNC_NAME,
8658*38fd1498Szrj 	   STATE_TYPE_NAME, STATE_NAME,
8659*38fd1498Szrj 	   CPU_CODE_PARAMETER_NAME);
8660*38fd1498Szrj   fprintf (output_file, "{\n  gcc_assert (%s >= 0 && %s < %d);\n",
8661*38fd1498Szrj 	   CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME,
8662*38fd1498Szrj 	   description->query_units_num);
8663*38fd1498Szrj   if (description->query_units_num > 0)
8664*38fd1498Szrj     for (automaton = description->first_automaton;
8665*38fd1498Szrj 	 automaton != NULL;
8666*38fd1498Szrj 	 automaton = automaton->next_automaton)
8667*38fd1498Szrj       {
8668*38fd1498Szrj 	fprintf (output_file, "  if ((");
8669*38fd1498Szrj 	output_reserved_units_table_name (output_file, automaton);
8670*38fd1498Szrj 	fprintf (output_file, " [((struct %s *) %s)->", CHIP_NAME, STATE_NAME);
8671*38fd1498Szrj 	output_chip_member_name (output_file, automaton);
8672*38fd1498Szrj 	fprintf (output_file, " * %d + %s / 8] >> (%s %% 8)) & 1)\n",
8673*38fd1498Szrj 		 (description->query_units_num + 7) / 8,
8674*38fd1498Szrj 		 CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME);
8675*38fd1498Szrj 	fprintf (output_file, "    return 1;\n");
8676*38fd1498Szrj       }
8677*38fd1498Szrj   fprintf (output_file, "  return 0;\n}\n\n");
8678*38fd1498Szrj }
8679*38fd1498Szrj 
8680*38fd1498Szrj /* The following function outputs a function to check if insn
8681*38fd1498Szrj    has a dfa reservation.  */
8682*38fd1498Szrj static void
output_insn_has_dfa_reservation_p(void)8683*38fd1498Szrj output_insn_has_dfa_reservation_p (void)
8684*38fd1498Szrj {
8685*38fd1498Szrj   fprintf (output_file,
8686*38fd1498Szrj 	   "bool\n%s (rtx_insn *%s ATTRIBUTE_UNUSED)\n{\n",
8687*38fd1498Szrj            INSN_HAS_DFA_RESERVATION_P_FUNC_NAME,
8688*38fd1498Szrj            INSN_PARAMETER_NAME);
8689*38fd1498Szrj 
8690*38fd1498Szrj   if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8691*38fd1498Szrj     {
8692*38fd1498Szrj       fprintf (output_file, "  return false;\n}\n\n");
8693*38fd1498Szrj       return;
8694*38fd1498Szrj     }
8695*38fd1498Szrj 
8696*38fd1498Szrj   fprintf (output_file, "  int %s;\n\n", INTERNAL_INSN_CODE_NAME);
8697*38fd1498Szrj 
8698*38fd1498Szrj   fprintf (output_file, "  if (%s == 0)\n    %s = %s;\n",
8699*38fd1498Szrj 	   INSN_PARAMETER_NAME,
8700*38fd1498Szrj 	   INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8701*38fd1498Szrj   fprintf (output_file, "  else\n\
8702*38fd1498Szrj     {\n\
8703*38fd1498Szrj       %s = %s (%s);\n\
8704*38fd1498Szrj       if (%s > %s)\n\
8705*38fd1498Szrj         %s = %s;\n\
8706*38fd1498Szrj     }\n\n",
8707*38fd1498Szrj 	   INTERNAL_INSN_CODE_NAME, DFA_INSN_CODE_FUNC_NAME,
8708*38fd1498Szrj 	       INSN_PARAMETER_NAME,
8709*38fd1498Szrj 	   INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8710*38fd1498Szrj 	   INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8711*38fd1498Szrj 
8712*38fd1498Szrj   fprintf (output_file, "  return %s != %s;\n}\n\n",
8713*38fd1498Szrj 	   INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8714*38fd1498Szrj }
8715*38fd1498Szrj 
8716*38fd1498Szrj /* The function outputs PHR interface functions `dfa_clean_insn_cache'
8717*38fd1498Szrj    and 'dfa_clear_single_insn_cache'.  */
8718*38fd1498Szrj static void
output_dfa_clean_insn_cache_func(void)8719*38fd1498Szrj output_dfa_clean_insn_cache_func (void)
8720*38fd1498Szrj {
8721*38fd1498Szrj   fprintf (output_file,
8722*38fd1498Szrj 	   "void\n%s (void)\n{\n  int %s;\n\n",
8723*38fd1498Szrj 	   DFA_CLEAN_INSN_CACHE_FUNC_NAME, I_VARIABLE_NAME);
8724*38fd1498Szrj   fprintf (output_file,
8725*38fd1498Szrj 	   "  for (%s = 0; %s < %s; %s++)\n    %s [%s] = -1;\n}\n\n",
8726*38fd1498Szrj 	   I_VARIABLE_NAME, I_VARIABLE_NAME,
8727*38fd1498Szrj 	   DFA_INSN_CODES_LENGTH_VARIABLE_NAME, I_VARIABLE_NAME,
8728*38fd1498Szrj 	   DFA_INSN_CODES_VARIABLE_NAME, I_VARIABLE_NAME);
8729*38fd1498Szrj 
8730*38fd1498Szrj   fprintf (output_file,
8731*38fd1498Szrj            "void\n%s (rtx_insn *%s)\n{\n  int %s;\n\n",
8732*38fd1498Szrj            DFA_CLEAR_SINGLE_INSN_CACHE_FUNC_NAME, INSN_PARAMETER_NAME,
8733*38fd1498Szrj 	   I_VARIABLE_NAME);
8734*38fd1498Szrj   fprintf (output_file,
8735*38fd1498Szrj            "  %s = INSN_UID (%s);\n  if (%s < %s)\n    %s [%s] = -1;\n}\n\n",
8736*38fd1498Szrj            I_VARIABLE_NAME, INSN_PARAMETER_NAME, I_VARIABLE_NAME,
8737*38fd1498Szrj 	   DFA_INSN_CODES_LENGTH_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
8738*38fd1498Szrj 	   I_VARIABLE_NAME);
8739*38fd1498Szrj }
8740*38fd1498Szrj 
8741*38fd1498Szrj /* The function outputs PHR interface function `dfa_start'.  */
8742*38fd1498Szrj static void
output_dfa_start_func(void)8743*38fd1498Szrj output_dfa_start_func (void)
8744*38fd1498Szrj {
8745*38fd1498Szrj   fprintf (output_file,
8746*38fd1498Szrj 	   "void\n%s (void)\n{\n  %s = get_max_uid ();\n",
8747*38fd1498Szrj 	   DFA_START_FUNC_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8748*38fd1498Szrj   fprintf (output_file, "  %s = XNEWVEC (int, %s);\n",
8749*38fd1498Szrj 	   DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8750*38fd1498Szrj   fprintf (output_file, "  %s ();\n}\n\n", DFA_CLEAN_INSN_CACHE_FUNC_NAME);
8751*38fd1498Szrj }
8752*38fd1498Szrj 
8753*38fd1498Szrj /* The function outputs PHR interface function `dfa_finish'.  */
8754*38fd1498Szrj static void
output_dfa_finish_func(void)8755*38fd1498Szrj output_dfa_finish_func (void)
8756*38fd1498Szrj {
8757*38fd1498Szrj   fprintf (output_file, "void\n%s (void)\n{\n  free (%s);\n}\n\n",
8758*38fd1498Szrj 	   DFA_FINISH_FUNC_NAME, DFA_INSN_CODES_VARIABLE_NAME);
8759*38fd1498Szrj }
8760*38fd1498Szrj 
8761*38fd1498Szrj 
8762*38fd1498Szrj 
8763*38fd1498Szrj /* The page contains code for output description file (readable
8764*38fd1498Szrj    representation of original description and generated DFA(s).  */
8765*38fd1498Szrj 
8766*38fd1498Szrj /* The function outputs string representation of IR reservation.  */
8767*38fd1498Szrj static void
output_regexp(regexp_t regexp)8768*38fd1498Szrj output_regexp (regexp_t regexp)
8769*38fd1498Szrj {
8770*38fd1498Szrj   fprintf (output_description_file, "%s", regexp_representation (regexp));
8771*38fd1498Szrj   finish_regexp_representation ();
8772*38fd1498Szrj }
8773*38fd1498Szrj 
8774*38fd1498Szrj /* Output names of units in LIST separated by comma.  */
8775*38fd1498Szrj static void
output_unit_set_el_list(unit_set_el_t list)8776*38fd1498Szrj output_unit_set_el_list (unit_set_el_t list)
8777*38fd1498Szrj {
8778*38fd1498Szrj   unit_set_el_t el;
8779*38fd1498Szrj 
8780*38fd1498Szrj   for (el = list; el != NULL; el = el->next_unit_set_el)
8781*38fd1498Szrj     {
8782*38fd1498Szrj       if (el != list)
8783*38fd1498Szrj 	fprintf (output_description_file, ", ");
8784*38fd1498Szrj       fprintf (output_description_file, "%s", el->unit_decl->name);
8785*38fd1498Szrj     }
8786*38fd1498Szrj }
8787*38fd1498Szrj 
8788*38fd1498Szrj /* Output patterns in LIST separated by comma.  */
8789*38fd1498Szrj static void
output_pattern_set_el_list(pattern_set_el_t list)8790*38fd1498Szrj output_pattern_set_el_list (pattern_set_el_t list)
8791*38fd1498Szrj {
8792*38fd1498Szrj   pattern_set_el_t el;
8793*38fd1498Szrj   int i;
8794*38fd1498Szrj 
8795*38fd1498Szrj   for (el = list; el != NULL; el = el->next_pattern_set_el)
8796*38fd1498Szrj     {
8797*38fd1498Szrj       if (el != list)
8798*38fd1498Szrj 	fprintf (output_description_file, ", ");
8799*38fd1498Szrj       for (i = 0; i < el->units_num; i++)
8800*38fd1498Szrj 	fprintf (output_description_file, (i == 0 ? "%s" : " %s"),
8801*38fd1498Szrj 		 el->unit_decls [i]->name);
8802*38fd1498Szrj     }
8803*38fd1498Szrj }
8804*38fd1498Szrj 
8805*38fd1498Szrj /* The function outputs string representation of IR define_reservation
8806*38fd1498Szrj    and define_insn_reservation.  */
8807*38fd1498Szrj static void
output_description(void)8808*38fd1498Szrj output_description (void)
8809*38fd1498Szrj {
8810*38fd1498Szrj   decl_t decl;
8811*38fd1498Szrj   int i;
8812*38fd1498Szrj 
8813*38fd1498Szrj   for (i = 0; i < description->decls_num; i++)
8814*38fd1498Szrj     {
8815*38fd1498Szrj       decl = description->decls [i];
8816*38fd1498Szrj       if (decl->mode == dm_unit)
8817*38fd1498Szrj 	{
8818*38fd1498Szrj 	  if (DECL_UNIT (decl)->excl_list != NULL)
8819*38fd1498Szrj 	    {
8820*38fd1498Szrj 	      fprintf (output_description_file, "unit %s exclusion_set: ",
8821*38fd1498Szrj 		       DECL_UNIT (decl)->name);
8822*38fd1498Szrj 	      output_unit_set_el_list (DECL_UNIT (decl)->excl_list);
8823*38fd1498Szrj 	      fprintf (output_description_file, "\n");
8824*38fd1498Szrj 	    }
8825*38fd1498Szrj 	  if (DECL_UNIT (decl)->presence_list != NULL)
8826*38fd1498Szrj 	    {
8827*38fd1498Szrj 	      fprintf (output_description_file, "unit %s presence_set: ",
8828*38fd1498Szrj 		       DECL_UNIT (decl)->name);
8829*38fd1498Szrj 	      output_pattern_set_el_list (DECL_UNIT (decl)->presence_list);
8830*38fd1498Szrj 	      fprintf (output_description_file, "\n");
8831*38fd1498Szrj 	    }
8832*38fd1498Szrj 	  if (DECL_UNIT (decl)->final_presence_list != NULL)
8833*38fd1498Szrj 	    {
8834*38fd1498Szrj 	      fprintf (output_description_file, "unit %s final_presence_set: ",
8835*38fd1498Szrj 		       DECL_UNIT (decl)->name);
8836*38fd1498Szrj 	      output_pattern_set_el_list
8837*38fd1498Szrj 		(DECL_UNIT (decl)->final_presence_list);
8838*38fd1498Szrj 	      fprintf (output_description_file, "\n");
8839*38fd1498Szrj 	    }
8840*38fd1498Szrj 	  if (DECL_UNIT (decl)->absence_list != NULL)
8841*38fd1498Szrj 	    {
8842*38fd1498Szrj 	      fprintf (output_description_file, "unit %s absence_set: ",
8843*38fd1498Szrj 		       DECL_UNIT (decl)->name);
8844*38fd1498Szrj 	      output_pattern_set_el_list (DECL_UNIT (decl)->absence_list);
8845*38fd1498Szrj 	      fprintf (output_description_file, "\n");
8846*38fd1498Szrj 	    }
8847*38fd1498Szrj 	  if (DECL_UNIT (decl)->final_absence_list != NULL)
8848*38fd1498Szrj 	    {
8849*38fd1498Szrj 	      fprintf (output_description_file, "unit %s final_absence_set: ",
8850*38fd1498Szrj 		       DECL_UNIT (decl)->name);
8851*38fd1498Szrj 	      output_pattern_set_el_list
8852*38fd1498Szrj 		(DECL_UNIT (decl)->final_absence_list);
8853*38fd1498Szrj 	      fprintf (output_description_file, "\n");
8854*38fd1498Szrj 	    }
8855*38fd1498Szrj 	}
8856*38fd1498Szrj     }
8857*38fd1498Szrj   fprintf (output_description_file, "\n");
8858*38fd1498Szrj   for (i = 0; i < description->normal_decls_num; i++)
8859*38fd1498Szrj     {
8860*38fd1498Szrj       decl = description->decls [i];
8861*38fd1498Szrj       if (decl->mode == dm_reserv)
8862*38fd1498Szrj 	{
8863*38fd1498Szrj           fprintf (output_description_file, "reservation %s: ",
8864*38fd1498Szrj 		   DECL_RESERV (decl)->name);
8865*38fd1498Szrj           output_regexp (DECL_RESERV (decl)->regexp);
8866*38fd1498Szrj           fprintf (output_description_file, "\n");
8867*38fd1498Szrj         }
8868*38fd1498Szrj       else if (decl->mode == dm_insn_reserv)
8869*38fd1498Szrj         {
8870*38fd1498Szrj           fprintf (output_description_file, "insn reservation %s ",
8871*38fd1498Szrj 		   DECL_INSN_RESERV (decl)->name);
8872*38fd1498Szrj           print_rtl (output_description_file,
8873*38fd1498Szrj 		     DECL_INSN_RESERV (decl)->condexp);
8874*38fd1498Szrj           fprintf (output_description_file, ": ");
8875*38fd1498Szrj           output_regexp (DECL_INSN_RESERV (decl)->regexp);
8876*38fd1498Szrj           fprintf (output_description_file, "\n");
8877*38fd1498Szrj         }
8878*38fd1498Szrj       else if (decl->mode == dm_bypass)
8879*38fd1498Szrj 	fprintf (output_description_file, "bypass %d %s %s\n",
8880*38fd1498Szrj 		 DECL_BYPASS (decl)->latency,
8881*38fd1498Szrj 		 DECL_BYPASS (decl)->out_pattern,
8882*38fd1498Szrj 		 DECL_BYPASS (decl)->in_pattern);
8883*38fd1498Szrj     }
8884*38fd1498Szrj   fprintf (output_description_file, "\n\f\n");
8885*38fd1498Szrj }
8886*38fd1498Szrj 
8887*38fd1498Szrj /* The function outputs name of AUTOMATON.  */
8888*38fd1498Szrj static void
output_automaton_name(FILE * f,automaton_t automaton)8889*38fd1498Szrj output_automaton_name (FILE *f, automaton_t automaton)
8890*38fd1498Szrj {
8891*38fd1498Szrj   if (automaton->corresponding_automaton_decl == NULL)
8892*38fd1498Szrj     fprintf (f, "#%d", automaton->automaton_order_num);
8893*38fd1498Szrj   else
8894*38fd1498Szrj     fprintf (f, "`%s'", automaton->corresponding_automaton_decl->name);
8895*38fd1498Szrj }
8896*38fd1498Szrj 
8897*38fd1498Szrj /* Maximal length of line for pretty printing into description
8898*38fd1498Szrj    file.  */
8899*38fd1498Szrj #define MAX_LINE_LENGTH 70
8900*38fd1498Szrj 
8901*38fd1498Szrj /* The function outputs units name belonging to AUTOMATON.  */
8902*38fd1498Szrj static void
output_automaton_units(automaton_t automaton)8903*38fd1498Szrj output_automaton_units (automaton_t automaton)
8904*38fd1498Szrj {
8905*38fd1498Szrj   decl_t decl;
8906*38fd1498Szrj   const char *name;
8907*38fd1498Szrj   int curr_line_length;
8908*38fd1498Szrj   int there_is_an_automaton_unit;
8909*38fd1498Szrj   int i;
8910*38fd1498Szrj 
8911*38fd1498Szrj   fprintf (output_description_file, "\n  Corresponding units:\n");
8912*38fd1498Szrj   fprintf (output_description_file, "    ");
8913*38fd1498Szrj   curr_line_length = 4;
8914*38fd1498Szrj   there_is_an_automaton_unit = 0;
8915*38fd1498Szrj   for (i = 0; i < description->decls_num; i++)
8916*38fd1498Szrj     {
8917*38fd1498Szrj       decl = description->decls [i];
8918*38fd1498Szrj       if (decl->mode == dm_unit
8919*38fd1498Szrj           && (DECL_UNIT (decl)->corresponding_automaton_num
8920*38fd1498Szrj 	      == automaton->automaton_order_num))
8921*38fd1498Szrj 	{
8922*38fd1498Szrj 	  there_is_an_automaton_unit = 1;
8923*38fd1498Szrj 	  name = DECL_UNIT (decl)->name;
8924*38fd1498Szrj 	  if (curr_line_length + strlen (name) + 1 > MAX_LINE_LENGTH )
8925*38fd1498Szrj 	    {
8926*38fd1498Szrj 	      curr_line_length = strlen (name) + 4;
8927*38fd1498Szrj 	      fprintf (output_description_file, "\n    ");
8928*38fd1498Szrj 	    }
8929*38fd1498Szrj 	  else
8930*38fd1498Szrj 	    {
8931*38fd1498Szrj 	      curr_line_length += strlen (name) + 1;
8932*38fd1498Szrj 	      fprintf (output_description_file, " ");
8933*38fd1498Szrj 	    }
8934*38fd1498Szrj 	  fprintf (output_description_file, "%s", name);
8935*38fd1498Szrj 	}
8936*38fd1498Szrj     }
8937*38fd1498Szrj   if (!there_is_an_automaton_unit)
8938*38fd1498Szrj     fprintf (output_description_file, "<None>");
8939*38fd1498Szrj   fprintf (output_description_file, "\n\n");
8940*38fd1498Szrj }
8941*38fd1498Szrj 
8942*38fd1498Szrj /* The following variable is used for forming array of all possible cpu unit
8943*38fd1498Szrj    reservations described by the current DFA state.  */
8944*38fd1498Szrj static vec<reserv_sets_t> state_reservs;
8945*38fd1498Szrj 
8946*38fd1498Szrj /* The function forms `state_reservs' for STATE.  */
8947*38fd1498Szrj static void
add_state_reservs(state_t state)8948*38fd1498Szrj add_state_reservs (state_t state)
8949*38fd1498Szrj {
8950*38fd1498Szrj   alt_state_t curr_alt_state;
8951*38fd1498Szrj 
8952*38fd1498Szrj   if (state->component_states != NULL)
8953*38fd1498Szrj     for (curr_alt_state = state->component_states;
8954*38fd1498Szrj          curr_alt_state != NULL;
8955*38fd1498Szrj          curr_alt_state = curr_alt_state->next_sorted_alt_state)
8956*38fd1498Szrj       add_state_reservs (curr_alt_state->state);
8957*38fd1498Szrj   else
8958*38fd1498Szrj     state_reservs.safe_push (state->reservs);
8959*38fd1498Szrj }
8960*38fd1498Szrj 
8961*38fd1498Szrj /* The function outputs readable representation of all out arcs of
8962*38fd1498Szrj    STATE.  */
8963*38fd1498Szrj static void
output_state_arcs(state_t state)8964*38fd1498Szrj output_state_arcs (state_t state)
8965*38fd1498Szrj {
8966*38fd1498Szrj   arc_t arc;
8967*38fd1498Szrj   ainsn_t ainsn;
8968*38fd1498Szrj   const char *insn_name;
8969*38fd1498Szrj   int curr_line_length;
8970*38fd1498Szrj 
8971*38fd1498Szrj   for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
8972*38fd1498Szrj     {
8973*38fd1498Szrj       ainsn = arc->insn;
8974*38fd1498Szrj       gcc_assert (ainsn->first_insn_with_same_reservs);
8975*38fd1498Szrj       fprintf (output_description_file, "    ");
8976*38fd1498Szrj       curr_line_length = 7;
8977*38fd1498Szrj       fprintf (output_description_file, "%2d: ", ainsn->insn_equiv_class_num);
8978*38fd1498Szrj       do
8979*38fd1498Szrj         {
8980*38fd1498Szrj           insn_name = ainsn->insn_reserv_decl->name;
8981*38fd1498Szrj           if (curr_line_length + strlen (insn_name) > MAX_LINE_LENGTH)
8982*38fd1498Szrj             {
8983*38fd1498Szrj               if (ainsn != arc->insn)
8984*38fd1498Szrj                 {
8985*38fd1498Szrj                   fprintf (output_description_file, ",\n      ");
8986*38fd1498Szrj                   curr_line_length = strlen (insn_name) + 6;
8987*38fd1498Szrj                 }
8988*38fd1498Szrj               else
8989*38fd1498Szrj                 curr_line_length += strlen (insn_name);
8990*38fd1498Szrj             }
8991*38fd1498Szrj           else
8992*38fd1498Szrj             {
8993*38fd1498Szrj               curr_line_length += strlen (insn_name);
8994*38fd1498Szrj               if (ainsn != arc->insn)
8995*38fd1498Szrj                 {
8996*38fd1498Szrj                   curr_line_length += 2;
8997*38fd1498Szrj                   fprintf (output_description_file, ", ");
8998*38fd1498Szrj                 }
8999*38fd1498Szrj             }
9000*38fd1498Szrj           fprintf (output_description_file, "%s", insn_name);
9001*38fd1498Szrj           ainsn = ainsn->next_same_reservs_insn;
9002*38fd1498Szrj         }
9003*38fd1498Szrj       while (ainsn != NULL);
9004*38fd1498Szrj       fprintf (output_description_file, "    %d \n",
9005*38fd1498Szrj 	       arc->to_state->order_state_num);
9006*38fd1498Szrj     }
9007*38fd1498Szrj   fprintf (output_description_file, "\n");
9008*38fd1498Szrj }
9009*38fd1498Szrj 
9010*38fd1498Szrj /* The following function is used for sorting possible cpu unit
9011*38fd1498Szrj    reservation of a DFA state.  */
9012*38fd1498Szrj static int
state_reservs_cmp(const void * reservs_ptr_1,const void * reservs_ptr_2)9013*38fd1498Szrj state_reservs_cmp (const void *reservs_ptr_1, const void *reservs_ptr_2)
9014*38fd1498Szrj {
9015*38fd1498Szrj   return reserv_sets_cmp (*(const_reserv_sets_t const*) reservs_ptr_1,
9016*38fd1498Szrj                           *(const_reserv_sets_t const*) reservs_ptr_2);
9017*38fd1498Szrj }
9018*38fd1498Szrj 
9019*38fd1498Szrj /* The following function is used for sorting possible cpu unit
9020*38fd1498Szrj    reservation of a DFA state.  */
9021*38fd1498Szrj static void
remove_state_duplicate_reservs(void)9022*38fd1498Szrj remove_state_duplicate_reservs (void)
9023*38fd1498Szrj {
9024*38fd1498Szrj   size_t i, j;
9025*38fd1498Szrj 
9026*38fd1498Szrj   for (i = 1, j = 0; i < state_reservs.length (); i++)
9027*38fd1498Szrj     if (reserv_sets_cmp (state_reservs[j], state_reservs[i]))
9028*38fd1498Szrj       {
9029*38fd1498Szrj 	j++;
9030*38fd1498Szrj 	state_reservs[j] = state_reservs[i];
9031*38fd1498Szrj       }
9032*38fd1498Szrj   state_reservs.truncate (j + 1);
9033*38fd1498Szrj }
9034*38fd1498Szrj 
9035*38fd1498Szrj /* The following function output readable representation of DFA(s)
9036*38fd1498Szrj    state used for fast recognition of pipeline hazards.  State is
9037*38fd1498Szrj    described by possible (current and scheduled) cpu unit
9038*38fd1498Szrj    reservations.  */
9039*38fd1498Szrj static void
output_state(state_t state)9040*38fd1498Szrj output_state (state_t state)
9041*38fd1498Szrj {
9042*38fd1498Szrj   size_t i;
9043*38fd1498Szrj 
9044*38fd1498Szrj   state_reservs.create (0);
9045*38fd1498Szrj 
9046*38fd1498Szrj   fprintf (output_description_file, "  State #%d", state->order_state_num);
9047*38fd1498Szrj   fprintf (output_description_file,
9048*38fd1498Szrj 	   state->new_cycle_p ? " (new cycle)\n" : "\n");
9049*38fd1498Szrj   add_state_reservs (state);
9050*38fd1498Szrj   state_reservs.qsort (state_reservs_cmp);
9051*38fd1498Szrj   remove_state_duplicate_reservs ();
9052*38fd1498Szrj   for (i = 0; i < state_reservs.length (); i++)
9053*38fd1498Szrj     {
9054*38fd1498Szrj       fprintf (output_description_file, "    ");
9055*38fd1498Szrj       output_reserv_sets (output_description_file, state_reservs[i]);
9056*38fd1498Szrj       fprintf (output_description_file, "\n");
9057*38fd1498Szrj     }
9058*38fd1498Szrj   fprintf (output_description_file, "\n");
9059*38fd1498Szrj   output_state_arcs (state);
9060*38fd1498Szrj   state_reservs.release ();
9061*38fd1498Szrj }
9062*38fd1498Szrj 
9063*38fd1498Szrj /* The following function output readable representation of
9064*38fd1498Szrj    DFAs used for fast recognition of pipeline hazards.  */
9065*38fd1498Szrj static void
output_automaton_descriptions(void)9066*38fd1498Szrj output_automaton_descriptions (void)
9067*38fd1498Szrj {
9068*38fd1498Szrj   automaton_t automaton;
9069*38fd1498Szrj 
9070*38fd1498Szrj   for (automaton = description->first_automaton;
9071*38fd1498Szrj        automaton != NULL;
9072*38fd1498Szrj        automaton = automaton->next_automaton)
9073*38fd1498Szrj     {
9074*38fd1498Szrj       fprintf (output_description_file, "\nAutomaton ");
9075*38fd1498Szrj       output_automaton_name (output_description_file, automaton);
9076*38fd1498Szrj       fprintf (output_description_file, "\n");
9077*38fd1498Szrj       output_automaton_units (automaton);
9078*38fd1498Szrj       pass_states (automaton, output_state);
9079*38fd1498Szrj     }
9080*38fd1498Szrj }
9081*38fd1498Szrj 
9082*38fd1498Szrj 
9083*38fd1498Szrj 
9084*38fd1498Szrj /* The page contains top level function for generation DFA(s) used for
9085*38fd1498Szrj    PHR.  */
9086*38fd1498Szrj 
9087*38fd1498Szrj /* The function outputs statistics about work of different phases of
9088*38fd1498Szrj    DFA generator.  */
9089*38fd1498Szrj static void
output_statistics(FILE * f)9090*38fd1498Szrj output_statistics (FILE *f)
9091*38fd1498Szrj {
9092*38fd1498Szrj   automaton_t automaton;
9093*38fd1498Szrj   int states_num;
9094*38fd1498Szrj #ifndef NDEBUG
9095*38fd1498Szrj   int transition_comb_vect_els = 0;
9096*38fd1498Szrj   int transition_full_vect_els = 0;
9097*38fd1498Szrj   int min_issue_delay_vect_els = 0;
9098*38fd1498Szrj   int locked_states = 0;
9099*38fd1498Szrj #endif
9100*38fd1498Szrj 
9101*38fd1498Szrj   for (automaton = description->first_automaton;
9102*38fd1498Szrj        automaton != NULL;
9103*38fd1498Szrj        automaton = automaton->next_automaton)
9104*38fd1498Szrj     {
9105*38fd1498Szrj       fprintf (f, "\nAutomaton ");
9106*38fd1498Szrj       output_automaton_name (f, automaton);
9107*38fd1498Szrj       fprintf (f, "\n    %5d NDFA states,          %5d NDFA arcs\n",
9108*38fd1498Szrj 	       automaton->NDFA_states_num, automaton->NDFA_arcs_num);
9109*38fd1498Szrj       fprintf (f, "    %5d DFA states,           %5d DFA arcs\n",
9110*38fd1498Szrj 	       automaton->DFA_states_num, automaton->DFA_arcs_num);
9111*38fd1498Szrj       states_num = automaton->DFA_states_num;
9112*38fd1498Szrj       if (!no_minimization_flag)
9113*38fd1498Szrj 	{
9114*38fd1498Szrj 	  fprintf (f, "    %5d minimal DFA states,   %5d minimal DFA arcs\n",
9115*38fd1498Szrj 		   automaton->minimal_DFA_states_num,
9116*38fd1498Szrj 		   automaton->minimal_DFA_arcs_num);
9117*38fd1498Szrj 	  states_num = automaton->minimal_DFA_states_num;
9118*38fd1498Szrj 	}
9119*38fd1498Szrj       fprintf (f, "    %5d all insns      %5d insn equivalence classes\n",
9120*38fd1498Szrj 	       description->insns_num, automaton->insn_equiv_classes_num);
9121*38fd1498Szrj       fprintf (f, "    %d locked states\n", automaton->locked_states);
9122*38fd1498Szrj #ifndef NDEBUG
9123*38fd1498Szrj       fprintf
9124*38fd1498Szrj 	(f, "%5ld transition comb vector els, %5ld trans table els: %s\n",
9125*38fd1498Szrj 	 (long) automaton->trans_table->comb_vect.length (),
9126*38fd1498Szrj 	 (long) automaton->trans_table->full_vect.length (),
9127*38fd1498Szrj 	 (comb_vect_p (automaton->trans_table)
9128*38fd1498Szrj 	  ? "use comb vect" : "use simple vect"));
9129*38fd1498Szrj       fprintf
9130*38fd1498Szrj         (f, "%5ld min delay table els, compression factor %d\n",
9131*38fd1498Szrj          (long) states_num * automaton->insn_equiv_classes_num,
9132*38fd1498Szrj 	 automaton->min_issue_delay_table_compression_factor);
9133*38fd1498Szrj       transition_comb_vect_els
9134*38fd1498Szrj 	+= automaton->trans_table->comb_vect.length ();
9135*38fd1498Szrj       transition_full_vect_els
9136*38fd1498Szrj         += automaton->trans_table->full_vect.length ();
9137*38fd1498Szrj       min_issue_delay_vect_els
9138*38fd1498Szrj 	+= states_num * automaton->insn_equiv_classes_num;
9139*38fd1498Szrj       locked_states
9140*38fd1498Szrj 	+= automaton->locked_states;
9141*38fd1498Szrj #endif
9142*38fd1498Szrj     }
9143*38fd1498Szrj #ifndef NDEBUG
9144*38fd1498Szrj   fprintf (f, "\n%5d all allocated states,     %5d all allocated arcs\n",
9145*38fd1498Szrj 	   allocated_states_num, allocated_arcs_num);
9146*38fd1498Szrj   fprintf (f, "%5d all allocated alternative states\n",
9147*38fd1498Szrj 	   allocated_alt_states_num);
9148*38fd1498Szrj   fprintf (f, "%5d all transition comb vector els, %5d all trans table els\n",
9149*38fd1498Szrj 	   transition_comb_vect_els, transition_full_vect_els);
9150*38fd1498Szrj   fprintf (f, "%5d all min delay table els\n", min_issue_delay_vect_els);
9151*38fd1498Szrj   fprintf (f, "%5d all locked states\n", locked_states);
9152*38fd1498Szrj #endif
9153*38fd1498Szrj }
9154*38fd1498Szrj 
9155*38fd1498Szrj /* The function output times of work of different phases of DFA
9156*38fd1498Szrj    generator.  */
9157*38fd1498Szrj static void
output_time_statistics(FILE * f)9158*38fd1498Szrj output_time_statistics (FILE *f)
9159*38fd1498Szrj {
9160*38fd1498Szrj   fprintf (f, "\n  transformation: ");
9161*38fd1498Szrj   print_active_time (f, transform_time);
9162*38fd1498Szrj   fprintf (f, (!ndfa_flag ? ", building DFA: " : ", building NDFA: "));
9163*38fd1498Szrj   print_active_time (f, NDFA_time);
9164*38fd1498Szrj   if (ndfa_flag)
9165*38fd1498Szrj     {
9166*38fd1498Szrj       fprintf (f, ", NDFA -> DFA: ");
9167*38fd1498Szrj       print_active_time (f, NDFA_to_DFA_time);
9168*38fd1498Szrj     }
9169*38fd1498Szrj   fprintf (f, "\n  DFA minimization: ");
9170*38fd1498Szrj   print_active_time (f, minimize_time);
9171*38fd1498Szrj   fprintf (f, ", making insn equivalence: ");
9172*38fd1498Szrj   print_active_time (f, equiv_time);
9173*38fd1498Szrj   fprintf (f, "\n all automaton generation: ");
9174*38fd1498Szrj   print_active_time (f, automaton_generation_time);
9175*38fd1498Szrj   fprintf (f, ", output: ");
9176*38fd1498Szrj   print_active_time (f, output_time);
9177*38fd1498Szrj   fprintf (f, "\n");
9178*38fd1498Szrj }
9179*38fd1498Szrj 
9180*38fd1498Szrj /* The function generates DFA (deterministic finite state automaton)
9181*38fd1498Szrj    for fast recognition of pipeline hazards.  No errors during
9182*38fd1498Szrj    checking must be fixed before this function call.  */
9183*38fd1498Szrj static void
generate(void)9184*38fd1498Szrj generate (void)
9185*38fd1498Szrj {
9186*38fd1498Szrj   automata_num = split_argument;
9187*38fd1498Szrj   if (description->units_num < automata_num)
9188*38fd1498Szrj     automata_num = description->units_num;
9189*38fd1498Szrj   initiate_states ();
9190*38fd1498Szrj   initiate_arcs ();
9191*38fd1498Szrj   initiate_automata_lists ();
9192*38fd1498Szrj   initiate_pass_states ();
9193*38fd1498Szrj   initiate_excl_sets ();
9194*38fd1498Szrj   initiate_presence_absence_pattern_sets ();
9195*38fd1498Szrj   automaton_generation_time = create_ticker ();
9196*38fd1498Szrj   create_automata ();
9197*38fd1498Szrj   ticker_off (&automaton_generation_time);
9198*38fd1498Szrj }
9199*38fd1498Szrj 
9200*38fd1498Szrj 
9201*38fd1498Szrj 
9202*38fd1498Szrj /* This page mainly contains top level functions of pipeline hazards
9203*38fd1498Szrj    description translator.  */
9204*38fd1498Szrj 
9205*38fd1498Szrj /* The following macro value is suffix of name of description file of
9206*38fd1498Szrj    pipeline hazards description translator.  */
9207*38fd1498Szrj #define STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX ".dfa"
9208*38fd1498Szrj 
9209*38fd1498Szrj /* The function returns suffix of given file name.  The returned
9210*38fd1498Szrj    string can not be changed.  */
9211*38fd1498Szrj static const char *
file_name_suffix(const char * file_name)9212*38fd1498Szrj file_name_suffix (const char *file_name)
9213*38fd1498Szrj {
9214*38fd1498Szrj   const char *last_period;
9215*38fd1498Szrj 
9216*38fd1498Szrj   for (last_period = NULL; *file_name != '\0'; file_name++)
9217*38fd1498Szrj     if (*file_name == '.')
9218*38fd1498Szrj       last_period = file_name;
9219*38fd1498Szrj   return (last_period == NULL ? file_name : last_period);
9220*38fd1498Szrj }
9221*38fd1498Szrj 
9222*38fd1498Szrj /* The function returns base name of given file name, i.e. pointer to
9223*38fd1498Szrj    first char after last `/' (or `\' for WIN32) in given file name,
9224*38fd1498Szrj    given file name itself if the directory name is absent.  The
9225*38fd1498Szrj    returned string can not be changed.  */
9226*38fd1498Szrj static const char *
base_file_name(const char * file_name)9227*38fd1498Szrj base_file_name (const char *file_name)
9228*38fd1498Szrj {
9229*38fd1498Szrj   int directory_name_length;
9230*38fd1498Szrj 
9231*38fd1498Szrj   directory_name_length = strlen (file_name);
9232*38fd1498Szrj #ifdef WIN32
9233*38fd1498Szrj   while (directory_name_length >= 0 && file_name[directory_name_length] != '/'
9234*38fd1498Szrj          && file_name[directory_name_length] != '\\')
9235*38fd1498Szrj #else
9236*38fd1498Szrj   while (directory_name_length >= 0 && file_name[directory_name_length] != '/')
9237*38fd1498Szrj #endif
9238*38fd1498Szrj     directory_name_length--;
9239*38fd1498Szrj   return file_name + directory_name_length + 1;
9240*38fd1498Szrj }
9241*38fd1498Szrj 
9242*38fd1498Szrj /* A function passed as argument to init_rtx_reader_args_cb.  It parses the
9243*38fd1498Szrj    options available for genautomata.  Returns true if the option was
9244*38fd1498Szrj    recognized.  */
9245*38fd1498Szrj static bool
parse_automata_opt(const char * str)9246*38fd1498Szrj parse_automata_opt (const char *str)
9247*38fd1498Szrj {
9248*38fd1498Szrj   if (strcmp (str, NO_MINIMIZATION_OPTION) == 0)
9249*38fd1498Szrj     no_minimization_flag = 1;
9250*38fd1498Szrj   else if (strcmp (str, TIME_OPTION) == 0)
9251*38fd1498Szrj     time_flag = 1;
9252*38fd1498Szrj   else if (strcmp (str, STATS_OPTION) == 0)
9253*38fd1498Szrj     stats_flag = 1;
9254*38fd1498Szrj   else if (strcmp (str, V_OPTION) == 0)
9255*38fd1498Szrj     v_flag = 1;
9256*38fd1498Szrj   else if (strcmp (str, W_OPTION) == 0)
9257*38fd1498Szrj     w_flag = 1;
9258*38fd1498Szrj   else if (strcmp (str, NDFA_OPTION) == 0)
9259*38fd1498Szrj     ndfa_flag = 1;
9260*38fd1498Szrj   else if (strcmp (str, COLLAPSE_OPTION) == 0)
9261*38fd1498Szrj     collapse_flag = 1;
9262*38fd1498Szrj   else if (strcmp (str, PROGRESS_OPTION) == 0)
9263*38fd1498Szrj     progress_flag = 1;
9264*38fd1498Szrj   else if (strcmp (str, "-split") == 0)
9265*38fd1498Szrj     {
9266*38fd1498Szrj       fatal ("option `-split' has not been implemented yet\n");
9267*38fd1498Szrj       /* split_argument = atoi (argument_vect [i + 1]); */
9268*38fd1498Szrj     }
9269*38fd1498Szrj   else
9270*38fd1498Szrj     return false;
9271*38fd1498Szrj 
9272*38fd1498Szrj   return true;
9273*38fd1498Szrj }
9274*38fd1498Szrj 
9275*38fd1498Szrj /* The following is top level function to initialize the work of
9276*38fd1498Szrj    pipeline hazards description translator.  */
9277*38fd1498Szrj static void
initiate_automaton_gen(const char ** argv)9278*38fd1498Szrj initiate_automaton_gen (const char **argv)
9279*38fd1498Szrj {
9280*38fd1498Szrj   const char *base_name;
9281*38fd1498Szrj 
9282*38fd1498Szrj   /* Initialize IR storage.  */
9283*38fd1498Szrj   obstack_init (&irp);
9284*38fd1498Szrj   initiate_automaton_decl_table ();
9285*38fd1498Szrj   initiate_insn_decl_table ();
9286*38fd1498Szrj   initiate_decl_table ();
9287*38fd1498Szrj   output_file = stdout;
9288*38fd1498Szrj   output_description_file = NULL;
9289*38fd1498Szrj   base_name = base_file_name (argv[1]);
9290*38fd1498Szrj   obstack_grow (&irp, base_name,
9291*38fd1498Szrj 		strlen (base_name) - strlen (file_name_suffix (base_name)));
9292*38fd1498Szrj   obstack_grow (&irp, STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX,
9293*38fd1498Szrj 		strlen (STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX) + 1);
9294*38fd1498Szrj   obstack_1grow (&irp, '\0');
9295*38fd1498Szrj   output_description_file_name = (char *) obstack_base (&irp);
9296*38fd1498Szrj   obstack_finish (&irp);
9297*38fd1498Szrj }
9298*38fd1498Szrj 
9299*38fd1498Szrj /* The following function checks existence at least one arc marked by
9300*38fd1498Szrj    each insn.  */
9301*38fd1498Szrj static void
check_automata_insn_issues(void)9302*38fd1498Szrj check_automata_insn_issues (void)
9303*38fd1498Szrj {
9304*38fd1498Szrj   automaton_t automaton;
9305*38fd1498Szrj   ainsn_t ainsn, reserv_ainsn;
9306*38fd1498Szrj 
9307*38fd1498Szrj   for (automaton = description->first_automaton;
9308*38fd1498Szrj        automaton != NULL;
9309*38fd1498Szrj        automaton = automaton->next_automaton)
9310*38fd1498Szrj     {
9311*38fd1498Szrj       for (ainsn = automaton->ainsn_list;
9312*38fd1498Szrj 	   ainsn != NULL;
9313*38fd1498Szrj 	   ainsn = ainsn->next_ainsn)
9314*38fd1498Szrj 	if (ainsn->first_insn_with_same_reservs && !ainsn->arc_exists_p
9315*38fd1498Szrj 	    && ainsn != automaton->collapse_ainsn)
9316*38fd1498Szrj 	  {
9317*38fd1498Szrj 	    for (reserv_ainsn = ainsn;
9318*38fd1498Szrj 		 reserv_ainsn != NULL;
9319*38fd1498Szrj 		 reserv_ainsn = reserv_ainsn->next_same_reservs_insn)
9320*38fd1498Szrj 	      if (automaton->corresponding_automaton_decl != NULL)
9321*38fd1498Szrj 		{
9322*38fd1498Szrj 		  if (!w_flag)
9323*38fd1498Szrj 		    error ("Automaton `%s': Insn `%s' will never be issued",
9324*38fd1498Szrj 			   automaton->corresponding_automaton_decl->name,
9325*38fd1498Szrj 			   reserv_ainsn->insn_reserv_decl->name);
9326*38fd1498Szrj 		  else
9327*38fd1498Szrj 		    warning ("Automaton `%s': Insn `%s' will never be issued",
9328*38fd1498Szrj 			     automaton->corresponding_automaton_decl->name,
9329*38fd1498Szrj 			     reserv_ainsn->insn_reserv_decl->name);
9330*38fd1498Szrj 		}
9331*38fd1498Szrj 	      else
9332*38fd1498Szrj 		{
9333*38fd1498Szrj 		  if (!w_flag)
9334*38fd1498Szrj 		    error ("Insn `%s' will never be issued",
9335*38fd1498Szrj 			   reserv_ainsn->insn_reserv_decl->name);
9336*38fd1498Szrj 		  else
9337*38fd1498Szrj 		    warning ("Insn `%s' will never be issued",
9338*38fd1498Szrj 			     reserv_ainsn->insn_reserv_decl->name);
9339*38fd1498Szrj 		}
9340*38fd1498Szrj 	  }
9341*38fd1498Szrj     }
9342*38fd1498Szrj }
9343*38fd1498Szrj 
9344*38fd1498Szrj /* The following vla is used for storing pointers to all achieved
9345*38fd1498Szrj    states.  */
9346*38fd1498Szrj static vec<state_t> automaton_states;
9347*38fd1498Szrj 
9348*38fd1498Szrj /* This function is called by function pass_states to add an achieved
9349*38fd1498Szrj    STATE.  */
9350*38fd1498Szrj static void
add_automaton_state(state_t state)9351*38fd1498Szrj add_automaton_state (state_t state)
9352*38fd1498Szrj {
9353*38fd1498Szrj   automaton_states.safe_push (state);
9354*38fd1498Szrj }
9355*38fd1498Szrj 
9356*38fd1498Szrj /* The following function forms list of important automata (whose
9357*38fd1498Szrj    states may be changed after the insn issue) for each insn.  */
9358*38fd1498Szrj static void
form_important_insn_automata_lists(void)9359*38fd1498Szrj form_important_insn_automata_lists (void)
9360*38fd1498Szrj {
9361*38fd1498Szrj   automaton_t automaton;
9362*38fd1498Szrj   decl_t decl;
9363*38fd1498Szrj   ainsn_t ainsn;
9364*38fd1498Szrj   arc_t arc;
9365*38fd1498Szrj   int i;
9366*38fd1498Szrj   size_t n;
9367*38fd1498Szrj 
9368*38fd1498Szrj   automaton_states.create (0);
9369*38fd1498Szrj   /* Mark important ainsns.  */
9370*38fd1498Szrj   for (automaton = description->first_automaton;
9371*38fd1498Szrj        automaton != NULL;
9372*38fd1498Szrj        automaton = automaton->next_automaton)
9373*38fd1498Szrj     {
9374*38fd1498Szrj       automaton_states.truncate (0);
9375*38fd1498Szrj       pass_states (automaton, add_automaton_state);
9376*38fd1498Szrj       for (n = 0; n < automaton_states.length (); n++)
9377*38fd1498Szrj 	{
9378*38fd1498Szrj 	  state_t s = automaton_states[n];
9379*38fd1498Szrj 	  for (arc = first_out_arc (s);
9380*38fd1498Szrj 	       arc != NULL;
9381*38fd1498Szrj 	       arc = next_out_arc (arc))
9382*38fd1498Szrj 	    if (arc->to_state != s)
9383*38fd1498Szrj 	      {
9384*38fd1498Szrj 		gcc_assert (arc->insn->first_insn_with_same_reservs);
9385*38fd1498Szrj 		for (ainsn = arc->insn;
9386*38fd1498Szrj 		     ainsn != NULL;
9387*38fd1498Szrj 		     ainsn = ainsn->next_same_reservs_insn)
9388*38fd1498Szrj 		  ainsn->important_p = TRUE;
9389*38fd1498Szrj 	      }
9390*38fd1498Szrj 	}
9391*38fd1498Szrj     }
9392*38fd1498Szrj   automaton_states.release ();
9393*38fd1498Szrj 
9394*38fd1498Szrj   /* Create automata sets for the insns.  */
9395*38fd1498Szrj   for (i = 0; i < description->decls_num; i++)
9396*38fd1498Szrj     {
9397*38fd1498Szrj       decl = description->decls [i];
9398*38fd1498Szrj       if (decl->mode == dm_insn_reserv)
9399*38fd1498Szrj 	{
9400*38fd1498Szrj 	  automata_list_start ();
9401*38fd1498Szrj 	  for (automaton = description->first_automaton;
9402*38fd1498Szrj 	       automaton != NULL;
9403*38fd1498Szrj 	       automaton = automaton->next_automaton)
9404*38fd1498Szrj 	    for (ainsn = automaton->ainsn_list;
9405*38fd1498Szrj 		 ainsn != NULL;
9406*38fd1498Szrj 		 ainsn = ainsn->next_ainsn)
9407*38fd1498Szrj 	      if (ainsn->important_p
9408*38fd1498Szrj 		  && ainsn->insn_reserv_decl == DECL_INSN_RESERV (decl))
9409*38fd1498Szrj 		{
9410*38fd1498Szrj 		  automata_list_add (automaton);
9411*38fd1498Szrj 		  break;
9412*38fd1498Szrj 		}
9413*38fd1498Szrj 	  DECL_INSN_RESERV (decl)->important_automata_list
9414*38fd1498Szrj 	    = automata_list_finish ();
9415*38fd1498Szrj 	}
9416*38fd1498Szrj     }
9417*38fd1498Szrj }
9418*38fd1498Szrj 
9419*38fd1498Szrj 
9420*38fd1498Szrj /* The following is top level function to generate automat(a,on) for
9421*38fd1498Szrj    fast recognition of pipeline hazards.  */
9422*38fd1498Szrj static void
expand_automata(void)9423*38fd1498Szrj expand_automata (void)
9424*38fd1498Szrj {
9425*38fd1498Szrj   int i;
9426*38fd1498Szrj 
9427*38fd1498Szrj   description = XCREATENODEVAR (struct description,
9428*38fd1498Szrj 				sizeof (struct description)
9429*38fd1498Szrj 				/* Two entries for special insns.  */
9430*38fd1498Szrj 				+ sizeof (decl_t) * (decls.length () + 1));
9431*38fd1498Szrj   description->decls_num = decls.length ();
9432*38fd1498Szrj   description->normal_decls_num = description->decls_num;
9433*38fd1498Szrj   description->query_units_num = 0;
9434*38fd1498Szrj   for (i = 0; i < description->decls_num; i++)
9435*38fd1498Szrj     {
9436*38fd1498Szrj       description->decls [i] = decls[i];
9437*38fd1498Szrj       if (description->decls [i]->mode == dm_unit
9438*38fd1498Szrj 	  && DECL_UNIT (description->decls [i])->query_p)
9439*38fd1498Szrj         DECL_UNIT (description->decls [i])->query_num
9440*38fd1498Szrj 	  = description->query_units_num++;
9441*38fd1498Szrj     }
9442*38fd1498Szrj   all_time = create_ticker ();
9443*38fd1498Szrj   check_time = create_ticker ();
9444*38fd1498Szrj   if (progress_flag)
9445*38fd1498Szrj     fprintf (stderr, "Check description...");
9446*38fd1498Szrj   check_all_description ();
9447*38fd1498Szrj   if (progress_flag)
9448*38fd1498Szrj     fprintf (stderr, "done\n");
9449*38fd1498Szrj   ticker_off (&check_time);
9450*38fd1498Szrj   generation_time = create_ticker ();
9451*38fd1498Szrj   if (!have_error)
9452*38fd1498Szrj     {
9453*38fd1498Szrj       transform_insn_regexps ();
9454*38fd1498Szrj       check_unit_distributions_to_automata ();
9455*38fd1498Szrj     }
9456*38fd1498Szrj   if (!have_error)
9457*38fd1498Szrj     {
9458*38fd1498Szrj       generate ();
9459*38fd1498Szrj       check_automata_insn_issues ();
9460*38fd1498Szrj     }
9461*38fd1498Szrj   if (!have_error)
9462*38fd1498Szrj     {
9463*38fd1498Szrj       form_important_insn_automata_lists ();
9464*38fd1498Szrj     }
9465*38fd1498Szrj   ticker_off (&generation_time);
9466*38fd1498Szrj }
9467*38fd1498Szrj 
9468*38fd1498Szrj /* The following is top level function to output PHR and to finish
9469*38fd1498Szrj    work with pipeline description translator.  */
9470*38fd1498Szrj static void
write_automata(void)9471*38fd1498Szrj write_automata (void)
9472*38fd1498Szrj {
9473*38fd1498Szrj   output_time = create_ticker ();
9474*38fd1498Szrj   if (progress_flag)
9475*38fd1498Szrj     fprintf (stderr, "Forming and outputting automata tables...");
9476*38fd1498Szrj   output_tables ();
9477*38fd1498Szrj   if (progress_flag)
9478*38fd1498Szrj     {
9479*38fd1498Szrj       fprintf (stderr, "done\n");
9480*38fd1498Szrj       fprintf (stderr, "Output functions to work with automata...");
9481*38fd1498Szrj     }
9482*38fd1498Szrj   output_chip_definitions ();
9483*38fd1498Szrj   output_max_insn_queue_index_def ();
9484*38fd1498Szrj   output_internal_min_issue_delay_func ();
9485*38fd1498Szrj   output_internal_trans_func ();
9486*38fd1498Szrj   /* Cache of insn dfa codes: */
9487*38fd1498Szrj   fprintf (output_file, "\nstatic int *%s;\n", DFA_INSN_CODES_VARIABLE_NAME);
9488*38fd1498Szrj   fprintf (output_file, "\nstatic int %s;\n\n",
9489*38fd1498Szrj 	   DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
9490*38fd1498Szrj   output_dfa_insn_code_func ();
9491*38fd1498Szrj   output_trans_func ();
9492*38fd1498Szrj   output_min_issue_delay_func ();
9493*38fd1498Szrj   output_internal_dead_lock_func ();
9494*38fd1498Szrj   output_dead_lock_func ();
9495*38fd1498Szrj   output_size_func ();
9496*38fd1498Szrj   output_internal_reset_func ();
9497*38fd1498Szrj   output_reset_func ();
9498*38fd1498Szrj   output_min_insn_conflict_delay_func ();
9499*38fd1498Szrj   output_default_latencies ();
9500*38fd1498Szrj   output_internal_insn_latency_func ();
9501*38fd1498Szrj   output_insn_latency_func ();
9502*38fd1498Szrj   output_internal_maximal_insn_latency_func ();
9503*38fd1498Szrj   output_maximal_insn_latency_func ();
9504*38fd1498Szrj   output_print_reservation_func ();
9505*38fd1498Szrj   /* Output function get_cpu_unit_code.  */
9506*38fd1498Szrj   fprintf (output_file, "\n#if %s\n\n", CPU_UNITS_QUERY_MACRO_NAME);
9507*38fd1498Szrj   output_get_cpu_unit_code_func ();
9508*38fd1498Szrj   output_cpu_unit_reservation_p ();
9509*38fd1498Szrj   output_insn_has_dfa_reservation_p ();
9510*38fd1498Szrj   fprintf (output_file, "\n#endif /* #if %s */\n\n",
9511*38fd1498Szrj 	   CPU_UNITS_QUERY_MACRO_NAME);
9512*38fd1498Szrj   output_dfa_clean_insn_cache_func ();
9513*38fd1498Szrj   output_dfa_start_func ();
9514*38fd1498Szrj   output_dfa_finish_func ();
9515*38fd1498Szrj   if (progress_flag)
9516*38fd1498Szrj     fprintf (stderr, "done\n");
9517*38fd1498Szrj   if (v_flag)
9518*38fd1498Szrj     {
9519*38fd1498Szrj       output_description_file = fopen (output_description_file_name, "w");
9520*38fd1498Szrj       if (output_description_file == NULL)
9521*38fd1498Szrj 	{
9522*38fd1498Szrj 	  perror (output_description_file_name);
9523*38fd1498Szrj 	  exit (FATAL_EXIT_CODE);
9524*38fd1498Szrj 	}
9525*38fd1498Szrj       if (progress_flag)
9526*38fd1498Szrj 	fprintf (stderr, "Output automata description...");
9527*38fd1498Szrj       output_description ();
9528*38fd1498Szrj       output_automaton_descriptions ();
9529*38fd1498Szrj       if (progress_flag)
9530*38fd1498Szrj 	fprintf (stderr, "done\n");
9531*38fd1498Szrj       output_statistics (output_description_file);
9532*38fd1498Szrj     }
9533*38fd1498Szrj   if (stats_flag)
9534*38fd1498Szrj     output_statistics (stderr);
9535*38fd1498Szrj   ticker_off (&output_time);
9536*38fd1498Szrj   if (time_flag)
9537*38fd1498Szrj     output_time_statistics (stderr);
9538*38fd1498Szrj   finish_states ();
9539*38fd1498Szrj   finish_arcs ();
9540*38fd1498Szrj   finish_automata_lists ();
9541*38fd1498Szrj   if (time_flag)
9542*38fd1498Szrj     {
9543*38fd1498Szrj       fprintf (stderr, "Summary:\n");
9544*38fd1498Szrj       fprintf (stderr, "  check time ");
9545*38fd1498Szrj       print_active_time (stderr, check_time);
9546*38fd1498Szrj       fprintf (stderr, ", generation time ");
9547*38fd1498Szrj       print_active_time (stderr, generation_time);
9548*38fd1498Szrj       fprintf (stderr, ", all time ");
9549*38fd1498Szrj       print_active_time (stderr, all_time);
9550*38fd1498Szrj       fprintf (stderr, "\n");
9551*38fd1498Szrj     }
9552*38fd1498Szrj   /* Finish all work.  */
9553*38fd1498Szrj   if (output_description_file != NULL)
9554*38fd1498Szrj     {
9555*38fd1498Szrj       fflush (output_description_file);
9556*38fd1498Szrj       if (ferror (stdout) != 0)
9557*38fd1498Szrj 	fatal ("Error in writing DFA description file %s: %s",
9558*38fd1498Szrj                output_description_file_name, xstrerror (errno));
9559*38fd1498Szrj       fclose (output_description_file);
9560*38fd1498Szrj     }
9561*38fd1498Szrj   finish_automaton_decl_table ();
9562*38fd1498Szrj   finish_insn_decl_table ();
9563*38fd1498Szrj   finish_decl_table ();
9564*38fd1498Szrj   obstack_free (&irp, NULL);
9565*38fd1498Szrj   if (have_error && output_description_file != NULL)
9566*38fd1498Szrj     remove (output_description_file_name);
9567*38fd1498Szrj }
9568*38fd1498Szrj 
9569*38fd1498Szrj int
main(int argc,const char ** argv)9570*38fd1498Szrj main (int argc, const char **argv)
9571*38fd1498Szrj {
9572*38fd1498Szrj   progname = "genautomata";
9573*38fd1498Szrj 
9574*38fd1498Szrj   if (!init_rtx_reader_args_cb (argc, argv, parse_automata_opt))
9575*38fd1498Szrj     return (FATAL_EXIT_CODE);
9576*38fd1498Szrj 
9577*38fd1498Szrj   initiate_automaton_gen (argv);
9578*38fd1498Szrj   md_rtx_info info;
9579*38fd1498Szrj   while (read_md_rtx (&info))
9580*38fd1498Szrj     switch (GET_CODE (info.def))
9581*38fd1498Szrj       {
9582*38fd1498Szrj       case DEFINE_CPU_UNIT:
9583*38fd1498Szrj 	gen_cpu_unit (&info);
9584*38fd1498Szrj 	break;
9585*38fd1498Szrj 
9586*38fd1498Szrj       case DEFINE_QUERY_CPU_UNIT:
9587*38fd1498Szrj 	gen_query_cpu_unit (&info);
9588*38fd1498Szrj 	break;
9589*38fd1498Szrj 
9590*38fd1498Szrj       case DEFINE_BYPASS:
9591*38fd1498Szrj 	gen_bypass (&info);
9592*38fd1498Szrj 	break;
9593*38fd1498Szrj 
9594*38fd1498Szrj       case EXCLUSION_SET:
9595*38fd1498Szrj 	gen_excl_set (&info);
9596*38fd1498Szrj 	break;
9597*38fd1498Szrj 
9598*38fd1498Szrj       case PRESENCE_SET:
9599*38fd1498Szrj 	gen_presence_set (&info);
9600*38fd1498Szrj 	break;
9601*38fd1498Szrj 
9602*38fd1498Szrj       case FINAL_PRESENCE_SET:
9603*38fd1498Szrj 	gen_final_presence_set (&info);
9604*38fd1498Szrj 	break;
9605*38fd1498Szrj 
9606*38fd1498Szrj       case ABSENCE_SET:
9607*38fd1498Szrj 	gen_absence_set (&info);
9608*38fd1498Szrj 	break;
9609*38fd1498Szrj 
9610*38fd1498Szrj       case FINAL_ABSENCE_SET:
9611*38fd1498Szrj 	gen_final_absence_set (&info);
9612*38fd1498Szrj 	break;
9613*38fd1498Szrj 
9614*38fd1498Szrj       case DEFINE_AUTOMATON:
9615*38fd1498Szrj 	gen_automaton (&info);
9616*38fd1498Szrj 	break;
9617*38fd1498Szrj 
9618*38fd1498Szrj       case AUTOMATA_OPTION:
9619*38fd1498Szrj 	gen_automata_option (&info);
9620*38fd1498Szrj 	break;
9621*38fd1498Szrj 
9622*38fd1498Szrj       case DEFINE_RESERVATION:
9623*38fd1498Szrj 	gen_reserv (&info);
9624*38fd1498Szrj 	break;
9625*38fd1498Szrj 
9626*38fd1498Szrj       case DEFINE_INSN_RESERVATION:
9627*38fd1498Szrj 	gen_insn_reserv (&info);
9628*38fd1498Szrj 	break;
9629*38fd1498Szrj 
9630*38fd1498Szrj       default:
9631*38fd1498Szrj 	break;
9632*38fd1498Szrj       }
9633*38fd1498Szrj 
9634*38fd1498Szrj   if (have_error)
9635*38fd1498Szrj     return FATAL_EXIT_CODE;
9636*38fd1498Szrj 
9637*38fd1498Szrj   if (decls.length () > 0)
9638*38fd1498Szrj     {
9639*38fd1498Szrj       expand_automata ();
9640*38fd1498Szrj       if (!have_error)
9641*38fd1498Szrj 	{
9642*38fd1498Szrj 	  puts ("/* Generated automatically by the program `genautomata'\n"
9643*38fd1498Szrj 		"   from the machine description file `md'.  */\n\n"
9644*38fd1498Szrj 		"#define IN_TARGET_CODE 1\n"
9645*38fd1498Szrj 		"#include \"config.h\"\n"
9646*38fd1498Szrj 		"#include \"system.h\"\n"
9647*38fd1498Szrj 		"#include \"coretypes.h\"\n"
9648*38fd1498Szrj 		"#include \"tm.h\"\n"
9649*38fd1498Szrj 		"#include \"alias.h\"\n"
9650*38fd1498Szrj 		"#include \"tree.h\"\n"
9651*38fd1498Szrj 		"#include \"varasm.h\"\n"
9652*38fd1498Szrj 		"#include \"stor-layout.h\"\n"
9653*38fd1498Szrj 		"#include \"calls.h\"\n"
9654*38fd1498Szrj 		"#include \"rtl.h\"\n"
9655*38fd1498Szrj 		"#include \"memmodel.h\"\n"
9656*38fd1498Szrj 		"#include \"tm_p.h\"\n"
9657*38fd1498Szrj 		"#include \"insn-config.h\"\n"
9658*38fd1498Szrj 		"#include \"recog.h\"\n"
9659*38fd1498Szrj 		"#include \"regs.h\"\n"
9660*38fd1498Szrj 		"#include \"output.h\"\n"
9661*38fd1498Szrj 		"#include \"insn-attr.h\"\n"
9662*38fd1498Szrj                 "#include \"diagnostic-core.h\"\n"
9663*38fd1498Szrj 		"#include \"flags.h\"\n"
9664*38fd1498Szrj 		"#include \"function.h\"\n"
9665*38fd1498Szrj 		"#include \"emit-rtl.h\"\n");
9666*38fd1498Szrj 	         /* FIXME: emit-rtl.h can go away once crtl is in rtl.h.  */
9667*38fd1498Szrj 
9668*38fd1498Szrj 	  write_automata ();
9669*38fd1498Szrj 	}
9670*38fd1498Szrj     }
9671*38fd1498Szrj   else
9672*38fd1498Szrj     {
9673*38fd1498Szrj       puts ("/* Generated automatically by the program `genautomata'\n"
9674*38fd1498Szrj 	    "   from the machine description file `md'.  */\n\n"
9675*38fd1498Szrj 	    "/* There is no automaton, but ISO C forbids empty\n"
9676*38fd1498Szrj 	    "   translation units, so include a header file with some\n"
9677*38fd1498Szrj 	    "   declarations, and its pre-requisite header file.  */\n"
9678*38fd1498Szrj 	    "#include \"config.h\"\n"
9679*38fd1498Szrj 	    "#include \"system.h\"\n");
9680*38fd1498Szrj     }
9681*38fd1498Szrj 
9682*38fd1498Szrj   fflush (stdout);
9683*38fd1498Szrj   return (ferror (stdout) != 0 || have_error
9684*38fd1498Szrj 	  ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
9685*38fd1498Szrj }
9686