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