1*38fd1498Szrj /* Pipeline hazard description translator.
2*38fd1498Szrj Copyright (C) 2000-2018 Free Software Foundation, Inc.
3*38fd1498Szrj
4*38fd1498Szrj Written by Vladimir Makarov <vmakarov@redhat.com>
5*38fd1498Szrj
6*38fd1498Szrj This file is part of GCC.
7*38fd1498Szrj
8*38fd1498Szrj GCC is free software; you can redistribute it and/or modify it
9*38fd1498Szrj under the terms of the GNU General Public License as published by the
10*38fd1498Szrj Free Software Foundation; either version 3, or (at your option) any
11*38fd1498Szrj later version.
12*38fd1498Szrj
13*38fd1498Szrj GCC is distributed in the hope that it will be useful, but WITHOUT
14*38fd1498Szrj ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15*38fd1498Szrj FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16*38fd1498Szrj for more details.
17*38fd1498Szrj
18*38fd1498Szrj You should have received a copy of the GNU General Public License
19*38fd1498Szrj along with GCC; see the file COPYING3. If not see
20*38fd1498Szrj <http://www.gnu.org/licenses/>. */
21*38fd1498Szrj
22*38fd1498Szrj /* References:
23*38fd1498Szrj
24*38fd1498Szrj 1. The finite state automaton based pipeline hazard recognizer and
25*38fd1498Szrj instruction scheduler in GCC. V. Makarov. Proceedings of GCC
26*38fd1498Szrj summit, 2003.
27*38fd1498Szrj
28*38fd1498Szrj 2. Detecting pipeline structural hazards quickly. T. Proebsting,
29*38fd1498Szrj C. Fraser. Proceedings of ACM SIGPLAN-SIGACT Symposium on
30*38fd1498Szrj Principles of Programming Languages, pages 280--286, 1994.
31*38fd1498Szrj
32*38fd1498Szrj This article is a good start point to understand usage of finite
33*38fd1498Szrj state automata for pipeline hazard recognizers. But I'd
34*38fd1498Szrj recommend the 1st and 3rd article for more deep understanding.
35*38fd1498Szrj
36*38fd1498Szrj 3. Efficient Instruction Scheduling Using Finite State Automata:
37*38fd1498Szrj V. Bala and N. Rubin, Proceedings of MICRO-28. This is the best
38*38fd1498Szrj article about usage of finite state automata for pipeline hazard
39*38fd1498Szrj recognizers.
40*38fd1498Szrj
41*38fd1498Szrj The current implementation is described in the 1st article and it
42*38fd1498Szrj is different from the 3rd article in the following:
43*38fd1498Szrj
44*38fd1498Szrj 1. New operator `|' (alternative) is permitted in functional unit
45*38fd1498Szrj reservation which can be treated deterministically and
46*38fd1498Szrj non-deterministically.
47*38fd1498Szrj
48*38fd1498Szrj 2. Possibility of usage of nondeterministic automata too.
49*38fd1498Szrj
50*38fd1498Szrj 3. Possibility to query functional unit reservations for given
51*38fd1498Szrj automaton state.
52*38fd1498Szrj
53*38fd1498Szrj 4. Several constructions to describe impossible reservations
54*38fd1498Szrj (`exclusion_set', `presence_set', `final_presence_set',
55*38fd1498Szrj `absence_set', and `final_absence_set').
56*38fd1498Szrj
57*38fd1498Szrj 5. No reverse automata are generated. Trace instruction scheduling
58*38fd1498Szrj requires this. It can be easily added in the future if we
59*38fd1498Szrj really need this.
60*38fd1498Szrj
61*38fd1498Szrj 6. Union of automaton states are not generated yet. It is planned
62*38fd1498Szrj to be implemented. Such feature is needed to make more accurate
63*38fd1498Szrj interlock insn scheduling to get state describing functional
64*38fd1498Szrj unit reservation in a joint CFG point. */
65*38fd1498Szrj
66*38fd1498Szrj /* This file code processes constructions of machine description file
67*38fd1498Szrj which describes automaton used for recognition of processor pipeline
68*38fd1498Szrj hazards by insn scheduler and can be used for other tasks (such as
69*38fd1498Szrj VLIW insn packing.
70*38fd1498Szrj
71*38fd1498Szrj The translator functions `gen_cpu_unit', `gen_query_cpu_unit',
72*38fd1498Szrj `gen_bypass', `gen_excl_set', `gen_presence_set',
73*38fd1498Szrj `gen_final_presence_set', `gen_absence_set',
74*38fd1498Szrj `gen_final_absence_set', `gen_automaton', `gen_automata_option',
75*38fd1498Szrj `gen_reserv', `gen_insn_reserv' are called from file
76*38fd1498Szrj `genattrtab.c'. They transform RTL constructions describing
77*38fd1498Szrj automata in .md file into internal representation convenient for
78*38fd1498Szrj further processing.
79*38fd1498Szrj
80*38fd1498Szrj The translator major function `expand_automata' processes the
81*38fd1498Szrj description internal representation into finite state automaton.
82*38fd1498Szrj It can be divided on:
83*38fd1498Szrj
84*38fd1498Szrj o checking correctness of the automaton pipeline description
85*38fd1498Szrj (major function is `check_all_description').
86*38fd1498Szrj
87*38fd1498Szrj o generating automaton (automata) from the description (major
88*38fd1498Szrj function is `make_automaton').
89*38fd1498Szrj
90*38fd1498Szrj o optional transformation of nondeterministic finite state
91*38fd1498Szrj automata into deterministic ones if the alternative operator
92*38fd1498Szrj `|' is treated nondeterministically in the description (major
93*38fd1498Szrj function is NDFA_to_DFA).
94*38fd1498Szrj
95*38fd1498Szrj o optional minimization of the finite state automata by merging
96*38fd1498Szrj equivalent automaton states (major function is `minimize_DFA').
97*38fd1498Szrj
98*38fd1498Szrj o forming tables (some as comb vectors) and attributes
99*38fd1498Szrj representing the automata (functions output_..._table).
100*38fd1498Szrj
101*38fd1498Szrj Function `write_automata' outputs the created finite state
102*38fd1498Szrj automaton as different tables and functions which works with the
103*38fd1498Szrj automata to inquire automaton state and to change its state. These
104*38fd1498Szrj function are used by gcc instruction scheduler and may be some
105*38fd1498Szrj other gcc code. */
106*38fd1498Szrj
107*38fd1498Szrj #include "bconfig.h"
108*38fd1498Szrj #include "system.h"
109*38fd1498Szrj #include "coretypes.h"
110*38fd1498Szrj #include "tm.h"
111*38fd1498Szrj #include "rtl.h"
112*38fd1498Szrj #include "obstack.h"
113*38fd1498Szrj #include "errors.h"
114*38fd1498Szrj #include "gensupport.h"
115*38fd1498Szrj
116*38fd1498Szrj #include <math.h>
117*38fd1498Szrj #include "fnmatch.h"
118*38fd1498Szrj
119*38fd1498Szrj #ifndef CHAR_BIT
120*38fd1498Szrj #define CHAR_BIT 8
121*38fd1498Szrj #endif
122*38fd1498Szrj
123*38fd1498Szrj /* Positions in machine description file. Now they are not used. But
124*38fd1498Szrj they could be used in the future for better diagnostic messages. */
125*38fd1498Szrj typedef int pos_t;
126*38fd1498Szrj
127*38fd1498Szrj /* The following is element of vector of current (and planned in the
128*38fd1498Szrj future) functional unit reservations. */
129*38fd1498Szrj typedef unsigned HOST_WIDE_INT set_el_t;
130*38fd1498Szrj
131*38fd1498Szrj /* Reservations of function units are represented by value of the following
132*38fd1498Szrj type. */
133*38fd1498Szrj typedef set_el_t *reserv_sets_t;
134*38fd1498Szrj typedef const set_el_t *const_reserv_sets_t;
135*38fd1498Szrj
136*38fd1498Szrj /* The following structure describes a ticker. */
137*38fd1498Szrj struct ticker
138*38fd1498Szrj {
139*38fd1498Szrj /* The following member value is time of the ticker creation with
140*38fd1498Szrj taking into account time when the ticker is off. Active time of
141*38fd1498Szrj the ticker is current time minus the value. */
142*38fd1498Szrj int modified_creation_time;
143*38fd1498Szrj /* The following member value is time (incremented by one) when the
144*38fd1498Szrj ticker was off. Zero value means that now the ticker is on. */
145*38fd1498Szrj int incremented_off_time;
146*38fd1498Szrj };
147*38fd1498Szrj
148*38fd1498Szrj /* The ticker is represented by the following type. */
149*38fd1498Szrj typedef struct ticker ticker_t;
150*38fd1498Szrj
151*38fd1498Szrj /* The following type describes elements of output vectors. */
152*38fd1498Szrj typedef HOST_WIDE_INT vect_el_t;
153*38fd1498Szrj
154*38fd1498Szrj /* Forward declaration of structures of internal representation of
155*38fd1498Szrj pipeline description based on NDFA. */
156*38fd1498Szrj
157*38fd1498Szrj struct unit_decl;
158*38fd1498Szrj struct bypass_decl;
159*38fd1498Szrj struct result_decl;
160*38fd1498Szrj struct automaton_decl;
161*38fd1498Szrj struct unit_pattern_rel_decl;
162*38fd1498Szrj struct reserv_decl;
163*38fd1498Szrj struct insn_reserv_decl;
164*38fd1498Szrj struct decl;
165*38fd1498Szrj struct unit_regexp;
166*38fd1498Szrj struct result_regexp;
167*38fd1498Szrj struct reserv_regexp;
168*38fd1498Szrj struct nothing_regexp;
169*38fd1498Szrj struct sequence_regexp;
170*38fd1498Szrj struct repeat_regexp;
171*38fd1498Szrj struct allof_regexp;
172*38fd1498Szrj struct oneof_regexp;
173*38fd1498Szrj struct regexp;
174*38fd1498Szrj struct description;
175*38fd1498Szrj struct unit_set_el;
176*38fd1498Szrj struct pattern_set_el;
177*38fd1498Szrj struct pattern_reserv;
178*38fd1498Szrj struct state;
179*38fd1498Szrj struct alt_state;
180*38fd1498Szrj struct arc;
181*38fd1498Szrj struct ainsn;
182*38fd1498Szrj struct automaton;
183*38fd1498Szrj struct state_ainsn_table;
184*38fd1498Szrj
185*38fd1498Szrj /* The following typedefs are for brevity. */
186*38fd1498Szrj typedef struct unit_decl *unit_decl_t;
187*38fd1498Szrj typedef const struct unit_decl *const_unit_decl_t;
188*38fd1498Szrj typedef struct decl *decl_t;
189*38fd1498Szrj typedef const struct decl *const_decl_t;
190*38fd1498Szrj typedef struct regexp *regexp_t;
191*38fd1498Szrj typedef struct unit_set_el *unit_set_el_t;
192*38fd1498Szrj typedef struct pattern_set_el *pattern_set_el_t;
193*38fd1498Szrj typedef struct pattern_reserv *pattern_reserv_t;
194*38fd1498Szrj typedef struct alt_state *alt_state_t;
195*38fd1498Szrj typedef struct state *state_t;
196*38fd1498Szrj typedef const struct state *const_state_t;
197*38fd1498Szrj typedef struct arc *arc_t;
198*38fd1498Szrj typedef struct ainsn *ainsn_t;
199*38fd1498Szrj typedef struct automaton *automaton_t;
200*38fd1498Szrj typedef struct automata_list_el *automata_list_el_t;
201*38fd1498Szrj typedef const struct automata_list_el *const_automata_list_el_t;
202*38fd1498Szrj typedef struct state_ainsn_table *state_ainsn_table_t;
203*38fd1498Szrj
204*38fd1498Szrj /* Undefined position. */
205*38fd1498Szrj static pos_t no_pos = 0;
206*38fd1498Szrj
207*38fd1498Szrj /* All IR is stored in the following obstack. */
208*38fd1498Szrj static struct obstack irp;
209*38fd1498Szrj
210*38fd1498Szrj
211*38fd1498Szrj /* Declare vector types for various data structures: */
212*38fd1498Szrj
213*38fd1498Szrj
214*38fd1498Szrj typedef vec<vect_el_t> vla_hwint_t;
215*38fd1498Szrj
216*38fd1498Szrj /* Forward declarations of functions used before their definitions, only. */
217*38fd1498Szrj static regexp_t gen_regexp_sequence (const char *);
218*38fd1498Szrj static void reserv_sets_or (reserv_sets_t, reserv_sets_t,
219*38fd1498Szrj reserv_sets_t);
220*38fd1498Szrj static reserv_sets_t get_excl_set (reserv_sets_t);
221*38fd1498Szrj static int check_presence_pattern_sets (reserv_sets_t,
222*38fd1498Szrj reserv_sets_t, int);
223*38fd1498Szrj static int check_absence_pattern_sets (reserv_sets_t, reserv_sets_t,
224*38fd1498Szrj int);
225*38fd1498Szrj static arc_t first_out_arc (const_state_t);
226*38fd1498Szrj static arc_t next_out_arc (arc_t);
227*38fd1498Szrj
228*38fd1498Szrj
229*38fd1498Szrj
230*38fd1498Szrj /* Options with the following names can be set up in automata_option
231*38fd1498Szrj construction. Because the strings occur more one time we use the
232*38fd1498Szrj macros. */
233*38fd1498Szrj
234*38fd1498Szrj #define NO_MINIMIZATION_OPTION "-no-minimization"
235*38fd1498Szrj #define TIME_OPTION "-time"
236*38fd1498Szrj #define STATS_OPTION "-stats"
237*38fd1498Szrj #define V_OPTION "-v"
238*38fd1498Szrj #define W_OPTION "-w"
239*38fd1498Szrj #define NDFA_OPTION "-ndfa"
240*38fd1498Szrj #define COLLAPSE_OPTION "-collapse-ndfa"
241*38fd1498Szrj #define NO_COMB_OPTION "-no-comb-vect"
242*38fd1498Szrj #define PROGRESS_OPTION "-progress"
243*38fd1498Szrj
244*38fd1498Szrj /* The following flags are set up by function `initiate_automaton_gen'. */
245*38fd1498Szrj
246*38fd1498Szrj /* Make automata with nondeterministic reservation by insns (`-ndfa'). */
247*38fd1498Szrj static int ndfa_flag;
248*38fd1498Szrj
249*38fd1498Szrj /* When making an NDFA, produce additional transitions that collapse
250*38fd1498Szrj NDFA state into a deterministic one suitable for querying CPU units.
251*38fd1498Szrj Provide advance-state transitions only for deterministic states. */
252*38fd1498Szrj static int collapse_flag;
253*38fd1498Szrj
254*38fd1498Szrj /* Do not make minimization of DFA (`-no-minimization'). */
255*38fd1498Szrj static int no_minimization_flag;
256*38fd1498Szrj
257*38fd1498Szrj /* Do not try to generate a comb vector (`-no-comb-vect'). */
258*38fd1498Szrj static int no_comb_flag;
259*38fd1498Szrj
260*38fd1498Szrj /* Value of this variable is number of automata being generated. The
261*38fd1498Szrj actual number of automata may be less this value if there is not
262*38fd1498Szrj sufficient number of units. This value is defined by argument of
263*38fd1498Szrj option `-split' or by constructions automaton if the value is zero
264*38fd1498Szrj (it is default value of the argument). */
265*38fd1498Szrj static int split_argument;
266*38fd1498Szrj
267*38fd1498Szrj /* Flag of output time statistics (`-time'). */
268*38fd1498Szrj static int time_flag;
269*38fd1498Szrj
270*38fd1498Szrj /* Flag of automata statistics (`-stats'). */
271*38fd1498Szrj static int stats_flag;
272*38fd1498Szrj
273*38fd1498Szrj /* Flag of creation of description file which contains description of
274*38fd1498Szrj result automaton and statistics information (`-v'). */
275*38fd1498Szrj static int v_flag;
276*38fd1498Szrj
277*38fd1498Szrj /* Flag of output of a progress bar showing how many states were
278*38fd1498Szrj generated so far for automaton being processed (`-progress'). */
279*38fd1498Szrj static int progress_flag;
280*38fd1498Szrj
281*38fd1498Szrj /* Flag of generating warning instead of error for non-critical errors
282*38fd1498Szrj (`-w'). */
283*38fd1498Szrj static int w_flag;
284*38fd1498Szrj
285*38fd1498Szrj
286*38fd1498Szrj /* Output file for pipeline hazard recognizer (PHR) being generated.
287*38fd1498Szrj The value is NULL if the file is not defined. */
288*38fd1498Szrj static FILE *output_file;
289*38fd1498Szrj
290*38fd1498Szrj /* Description file of PHR. The value is NULL if the file is not
291*38fd1498Szrj created. */
292*38fd1498Szrj static FILE *output_description_file;
293*38fd1498Szrj
294*38fd1498Szrj /* PHR description file name. */
295*38fd1498Szrj static char *output_description_file_name;
296*38fd1498Szrj
297*38fd1498Szrj /* Value of the following variable is node representing description
298*38fd1498Szrj being processed. This is start point of IR. */
299*38fd1498Szrj static struct description *description;
300*38fd1498Szrj
301*38fd1498Szrj
302*38fd1498Szrj
303*38fd1498Szrj /* This page contains description of IR structure (nodes). */
304*38fd1498Szrj
305*38fd1498Szrj enum decl_mode
306*38fd1498Szrj {
307*38fd1498Szrj dm_unit,
308*38fd1498Szrj dm_bypass,
309*38fd1498Szrj dm_automaton,
310*38fd1498Szrj dm_excl,
311*38fd1498Szrj dm_presence,
312*38fd1498Szrj dm_absence,
313*38fd1498Szrj dm_reserv,
314*38fd1498Szrj dm_insn_reserv
315*38fd1498Szrj };
316*38fd1498Szrj
317*38fd1498Szrj /* This describes define_cpu_unit and define_query_cpu_unit (see file
318*38fd1498Szrj rtl.def). */
319*38fd1498Szrj struct unit_decl
320*38fd1498Szrj {
321*38fd1498Szrj const char *name;
322*38fd1498Szrj /* NULL if the automaton name is absent. */
323*38fd1498Szrj const char *automaton_name;
324*38fd1498Szrj /* If the following value is not zero, the cpu unit reservation is
325*38fd1498Szrj described in define_query_cpu_unit. */
326*38fd1498Szrj char query_p;
327*38fd1498Szrj
328*38fd1498Szrj /* The following fields are defined by checker. */
329*38fd1498Szrj
330*38fd1498Szrj /* The following field value is nonzero if the unit is used in an
331*38fd1498Szrj regexp. */
332*38fd1498Szrj char unit_is_used;
333*38fd1498Szrj
334*38fd1498Szrj /* The following field value is order number (0, 1, ...) of given
335*38fd1498Szrj unit. */
336*38fd1498Szrj int unit_num;
337*38fd1498Szrj /* The following field value is corresponding declaration of
338*38fd1498Szrj automaton which was given in description. If the field value is
339*38fd1498Szrj NULL then automaton in the unit declaration was absent. */
340*38fd1498Szrj struct automaton_decl *automaton_decl;
341*38fd1498Szrj /* The following field value is maximal cycle number (1, ...) on
342*38fd1498Szrj which given unit occurs in insns. Zero value means that given
343*38fd1498Szrj unit is not used in insns. */
344*38fd1498Szrj int max_occ_cycle_num;
345*38fd1498Szrj /* The following field value is minimal cycle number (0, ...) on
346*38fd1498Szrj which given unit occurs in insns. -1 value means that given
347*38fd1498Szrj unit is not used in insns. */
348*38fd1498Szrj int min_occ_cycle_num;
349*38fd1498Szrj /* The following list contains units which conflict with given
350*38fd1498Szrj unit. */
351*38fd1498Szrj unit_set_el_t excl_list;
352*38fd1498Szrj /* The following list contains patterns which are required to
353*38fd1498Szrj reservation of given unit. */
354*38fd1498Szrj pattern_set_el_t presence_list;
355*38fd1498Szrj pattern_set_el_t final_presence_list;
356*38fd1498Szrj /* The following list contains patterns which should be not present
357*38fd1498Szrj in reservation for given unit. */
358*38fd1498Szrj pattern_set_el_t absence_list;
359*38fd1498Szrj pattern_set_el_t final_absence_list;
360*38fd1498Szrj /* The following is used only when `query_p' has nonzero value.
361*38fd1498Szrj This is query number for the unit. */
362*38fd1498Szrj int query_num;
363*38fd1498Szrj /* The following is the last cycle on which the unit was checked for
364*38fd1498Szrj correct distributions of units to automata in a regexp. */
365*38fd1498Szrj int last_distribution_check_cycle;
366*38fd1498Szrj
367*38fd1498Szrj /* The following fields are defined by automaton generator. */
368*38fd1498Szrj
369*38fd1498Szrj /* The following field value is number of the automaton to which
370*38fd1498Szrj given unit belongs. */
371*38fd1498Szrj int corresponding_automaton_num;
372*38fd1498Szrj /* If the following value is not zero, the cpu unit is present in a
373*38fd1498Szrj `exclusion_set' or in right part of a `presence_set',
374*38fd1498Szrj `final_presence_set', `absence_set', and
375*38fd1498Szrj `final_absence_set'define_query_cpu_unit. */
376*38fd1498Szrj char in_set_p;
377*38fd1498Szrj };
378*38fd1498Szrj
379*38fd1498Szrj /* This describes define_bypass (see file rtl.def). */
380*38fd1498Szrj struct bypass_decl
381*38fd1498Szrj {
382*38fd1498Szrj int latency;
383*38fd1498Szrj const char *out_pattern;
384*38fd1498Szrj const char *in_pattern;
385*38fd1498Szrj const char *bypass_guard_name;
386*38fd1498Szrj
387*38fd1498Szrj /* The following fields are defined by checker. */
388*38fd1498Szrj
389*38fd1498Szrj /* output and input insns of given bypass. */
390*38fd1498Szrj struct insn_reserv_decl *out_insn_reserv;
391*38fd1498Szrj struct insn_reserv_decl *in_insn_reserv;
392*38fd1498Szrj /* The next bypass for given output insn. */
393*38fd1498Szrj struct bypass_decl *next;
394*38fd1498Szrj };
395*38fd1498Szrj
396*38fd1498Szrj /* This describes define_automaton (see file rtl.def). */
397*38fd1498Szrj struct automaton_decl
398*38fd1498Szrj {
399*38fd1498Szrj const char *name;
400*38fd1498Szrj
401*38fd1498Szrj /* The following fields are defined by automaton generator. */
402*38fd1498Szrj
403*38fd1498Szrj /* The following field value is nonzero if the automaton is used in
404*38fd1498Szrj an regexp definition. */
405*38fd1498Szrj char automaton_is_used;
406*38fd1498Szrj
407*38fd1498Szrj /* The following fields are defined by checker. */
408*38fd1498Szrj
409*38fd1498Szrj /* The following field value is the corresponding automaton. This
410*38fd1498Szrj field is not NULL only if the automaton is present in unit
411*38fd1498Szrj declarations and the automatic partition on automata is not
412*38fd1498Szrj used. */
413*38fd1498Szrj automaton_t corresponding_automaton;
414*38fd1498Szrj };
415*38fd1498Szrj
416*38fd1498Szrj /* This describes exclusion relations: exclusion_set (see file
417*38fd1498Szrj rtl.def). */
418*38fd1498Szrj struct excl_rel_decl
419*38fd1498Szrj {
420*38fd1498Szrj int all_names_num;
421*38fd1498Szrj int first_list_length;
422*38fd1498Szrj char *names [1];
423*38fd1498Szrj };
424*38fd1498Szrj
425*38fd1498Szrj /* This describes unit relations: [final_]presence_set or
426*38fd1498Szrj [final_]absence_set (see file rtl.def). */
427*38fd1498Szrj struct unit_pattern_rel_decl
428*38fd1498Szrj {
429*38fd1498Szrj int final_p;
430*38fd1498Szrj int names_num;
431*38fd1498Szrj int patterns_num;
432*38fd1498Szrj char **names;
433*38fd1498Szrj char ***patterns;
434*38fd1498Szrj };
435*38fd1498Szrj
436*38fd1498Szrj /* This describes define_reservation (see file rtl.def). */
437*38fd1498Szrj struct reserv_decl
438*38fd1498Szrj {
439*38fd1498Szrj const char *name;
440*38fd1498Szrj regexp_t regexp;
441*38fd1498Szrj
442*38fd1498Szrj /* The following fields are defined by checker. */
443*38fd1498Szrj
444*38fd1498Szrj /* The following field value is nonzero if the unit is used in an
445*38fd1498Szrj regexp. */
446*38fd1498Szrj char reserv_is_used;
447*38fd1498Szrj /* The following field is used to check up cycle in expression
448*38fd1498Szrj definition. */
449*38fd1498Szrj int loop_pass_num;
450*38fd1498Szrj };
451*38fd1498Szrj
452*38fd1498Szrj /* This describes define_insn_reservation (see file rtl.def). */
453*38fd1498Szrj struct insn_reserv_decl
454*38fd1498Szrj {
455*38fd1498Szrj rtx condexp;
456*38fd1498Szrj int default_latency;
457*38fd1498Szrj regexp_t regexp;
458*38fd1498Szrj const char *name;
459*38fd1498Szrj
460*38fd1498Szrj /* The following fields are defined by checker. */
461*38fd1498Szrj
462*38fd1498Szrj /* The following field value is order number (0, 1, ...) of given
463*38fd1498Szrj insn. */
464*38fd1498Szrj int insn_num;
465*38fd1498Szrj /* The following field value is list of bypasses in which given insn
466*38fd1498Szrj is output insn. Bypasses with the same input insn stay one after
467*38fd1498Szrj another in the list in the same order as their occurrences in the
468*38fd1498Szrj description but the bypass without a guard stays always the last
469*38fd1498Szrj in a row of bypasses with the same input insn. */
470*38fd1498Szrj struct bypass_decl *bypass_list;
471*38fd1498Szrj
472*38fd1498Szrj /* The following fields are defined by automaton generator. */
473*38fd1498Szrj
474*38fd1498Szrj /* The following field is the insn regexp transformed that
475*38fd1498Szrj the regexp has not optional regexp, repetition regexp, and an
476*38fd1498Szrj reservation name (i.e. reservation identifiers are changed by the
477*38fd1498Szrj corresponding regexp) and all alternations are the top level
478*38fd1498Szrj of the regexp. The value can be NULL only if it is special
479*38fd1498Szrj insn `cycle advancing'. */
480*38fd1498Szrj regexp_t transformed_regexp;
481*38fd1498Szrj /* The following field value is list of arcs marked given
482*38fd1498Szrj insn. The field is used in transformation NDFA -> DFA. */
483*38fd1498Szrj arc_t arcs_marked_by_insn;
484*38fd1498Szrj /* The two following fields are used during minimization of a finite state
485*38fd1498Szrj automaton. */
486*38fd1498Szrj /* The field value is number of equivalence class of state into
487*38fd1498Szrj which arc marked by given insn enters from a state (fixed during
488*38fd1498Szrj an automaton minimization). */
489*38fd1498Szrj int equiv_class_num;
490*38fd1498Szrj /* The following member value is the list to automata which can be
491*38fd1498Szrj changed by the insn issue. */
492*38fd1498Szrj automata_list_el_t important_automata_list;
493*38fd1498Szrj /* The following member is used to process insn once for output. */
494*38fd1498Szrj int processed_p;
495*38fd1498Szrj };
496*38fd1498Szrj
497*38fd1498Szrj /* This contains a declaration mentioned above. */
498*38fd1498Szrj struct decl
499*38fd1498Szrj {
500*38fd1498Szrj /* What node in the union? */
501*38fd1498Szrj enum decl_mode mode;
502*38fd1498Szrj pos_t pos;
503*38fd1498Szrj union
504*38fd1498Szrj {
505*38fd1498Szrj struct unit_decl unit;
506*38fd1498Szrj struct bypass_decl bypass;
507*38fd1498Szrj struct automaton_decl automaton;
508*38fd1498Szrj struct excl_rel_decl excl;
509*38fd1498Szrj struct unit_pattern_rel_decl presence;
510*38fd1498Szrj struct unit_pattern_rel_decl absence;
511*38fd1498Szrj struct reserv_decl reserv;
512*38fd1498Szrj struct insn_reserv_decl insn_reserv;
513*38fd1498Szrj } decl;
514*38fd1498Szrj };
515*38fd1498Szrj
516*38fd1498Szrj /* The following structures represent parsed reservation strings. */
517*38fd1498Szrj enum regexp_mode
518*38fd1498Szrj {
519*38fd1498Szrj rm_unit,
520*38fd1498Szrj rm_reserv,
521*38fd1498Szrj rm_nothing,
522*38fd1498Szrj rm_sequence,
523*38fd1498Szrj rm_repeat,
524*38fd1498Szrj rm_allof,
525*38fd1498Szrj rm_oneof
526*38fd1498Szrj };
527*38fd1498Szrj
528*38fd1498Szrj /* Cpu unit in reservation. */
529*38fd1498Szrj struct unit_regexp
530*38fd1498Szrj {
531*38fd1498Szrj const char *name;
532*38fd1498Szrj unit_decl_t unit_decl;
533*38fd1498Szrj };
534*38fd1498Szrj
535*38fd1498Szrj /* Define_reservation in a reservation. */
536*38fd1498Szrj struct reserv_regexp
537*38fd1498Szrj {
538*38fd1498Szrj const char *name;
539*38fd1498Szrj struct reserv_decl *reserv_decl;
540*38fd1498Szrj };
541*38fd1498Szrj
542*38fd1498Szrj /* Absence of reservation (represented by string `nothing'). */
543*38fd1498Szrj struct nothing_regexp
544*38fd1498Szrj {
545*38fd1498Szrj /* This used to be empty but ISO C doesn't allow that. */
546*38fd1498Szrj char unused;
547*38fd1498Szrj };
548*38fd1498Szrj
549*38fd1498Szrj /* Representation of reservations separated by ',' (see file
550*38fd1498Szrj rtl.def). */
551*38fd1498Szrj struct sequence_regexp
552*38fd1498Szrj {
553*38fd1498Szrj int regexps_num;
554*38fd1498Szrj regexp_t regexps [1];
555*38fd1498Szrj };
556*38fd1498Szrj
557*38fd1498Szrj /* Representation of construction `repeat' (see file rtl.def). */
558*38fd1498Szrj struct repeat_regexp
559*38fd1498Szrj {
560*38fd1498Szrj int repeat_num;
561*38fd1498Szrj regexp_t regexp;
562*38fd1498Szrj };
563*38fd1498Szrj
564*38fd1498Szrj /* Representation of reservations separated by '+' (see file
565*38fd1498Szrj rtl.def). */
566*38fd1498Szrj struct allof_regexp
567*38fd1498Szrj {
568*38fd1498Szrj int regexps_num;
569*38fd1498Szrj regexp_t regexps [1];
570*38fd1498Szrj };
571*38fd1498Szrj
572*38fd1498Szrj /* Representation of reservations separated by '|' (see file
573*38fd1498Szrj rtl.def). */
574*38fd1498Szrj struct oneof_regexp
575*38fd1498Szrj {
576*38fd1498Szrj int regexps_num;
577*38fd1498Szrj regexp_t regexps [1];
578*38fd1498Szrj };
579*38fd1498Szrj
580*38fd1498Szrj /* Representation of a reservation string. */
581*38fd1498Szrj struct regexp
582*38fd1498Szrj {
583*38fd1498Szrj /* What node in the union? */
584*38fd1498Szrj enum regexp_mode mode;
585*38fd1498Szrj pos_t pos;
586*38fd1498Szrj union
587*38fd1498Szrj {
588*38fd1498Szrj struct unit_regexp unit;
589*38fd1498Szrj struct reserv_regexp reserv;
590*38fd1498Szrj struct nothing_regexp nothing;
591*38fd1498Szrj struct sequence_regexp sequence;
592*38fd1498Szrj struct repeat_regexp repeat;
593*38fd1498Szrj struct allof_regexp allof;
594*38fd1498Szrj struct oneof_regexp oneof;
595*38fd1498Szrj } regexp;
596*38fd1498Szrj };
597*38fd1498Szrj
598*38fd1498Szrj /* Represents description of pipeline hazard description based on
599*38fd1498Szrj NDFA. */
600*38fd1498Szrj struct description
601*38fd1498Szrj {
602*38fd1498Szrj int decls_num, normal_decls_num;
603*38fd1498Szrj
604*38fd1498Szrj /* The following fields are defined by checker. */
605*38fd1498Szrj
606*38fd1498Szrj /* The following fields values are correspondingly number of all
607*38fd1498Szrj units, query units, and insns in the description. */
608*38fd1498Szrj int units_num;
609*38fd1498Szrj int query_units_num;
610*38fd1498Szrj int insns_num;
611*38fd1498Szrj /* The following field value is max length (in cycles) of
612*38fd1498Szrj reservations of insns. The field value is defined only for
613*38fd1498Szrj correct programs. */
614*38fd1498Szrj int max_insn_reserv_cycles;
615*38fd1498Szrj
616*38fd1498Szrj /* The following fields are defined by automaton generator. */
617*38fd1498Szrj
618*38fd1498Szrj /* The following field value is the first automaton. */
619*38fd1498Szrj automaton_t first_automaton;
620*38fd1498Szrj
621*38fd1498Szrj /* The following field is created by pipeline hazard parser and
622*38fd1498Szrj contains all declarations. We allocate additional entries for
623*38fd1498Szrj two special insns which are added by the automaton generator. */
624*38fd1498Szrj decl_t decls [1];
625*38fd1498Szrj };
626*38fd1498Szrj
627*38fd1498Szrj
628*38fd1498Szrj /* The following nodes are created in automaton checker. */
629*38fd1498Szrj
630*38fd1498Szrj /* The following nodes represent exclusion set for cpu units. Each
631*38fd1498Szrj element is accessed through only one excl_list. */
632*38fd1498Szrj struct unit_set_el
633*38fd1498Szrj {
634*38fd1498Szrj unit_decl_t unit_decl;
635*38fd1498Szrj unit_set_el_t next_unit_set_el;
636*38fd1498Szrj };
637*38fd1498Szrj
638*38fd1498Szrj /* The following nodes represent presence or absence pattern for cpu
639*38fd1498Szrj units. Each element is accessed through only one presence_list or
640*38fd1498Szrj absence_list. */
641*38fd1498Szrj struct pattern_set_el
642*38fd1498Szrj {
643*38fd1498Szrj /* The number of units in unit_decls. */
644*38fd1498Szrj int units_num;
645*38fd1498Szrj /* The units forming the pattern. */
646*38fd1498Szrj struct unit_decl **unit_decls;
647*38fd1498Szrj pattern_set_el_t next_pattern_set_el;
648*38fd1498Szrj };
649*38fd1498Szrj
650*38fd1498Szrj
651*38fd1498Szrj /* The following nodes are created in automaton generator. */
652*38fd1498Szrj
653*38fd1498Szrj
654*38fd1498Szrj /* The following nodes represent presence or absence pattern for cpu
655*38fd1498Szrj units. Each element is accessed through only one element of
656*38fd1498Szrj unit_presence_set_table or unit_absence_set_table. */
657*38fd1498Szrj struct pattern_reserv
658*38fd1498Szrj {
659*38fd1498Szrj reserv_sets_t reserv;
660*38fd1498Szrj pattern_reserv_t next_pattern_reserv;
661*38fd1498Szrj };
662*38fd1498Szrj
663*38fd1498Szrj /* The following node type describes state automaton. The state may
664*38fd1498Szrj be deterministic or non-deterministic. Non-deterministic state has
665*38fd1498Szrj several component states which represent alternative cpu units
666*38fd1498Szrj reservations. The state also is used for describing a
667*38fd1498Szrj deterministic reservation of automaton insn. */
668*38fd1498Szrj struct state
669*38fd1498Szrj {
670*38fd1498Szrj /* The following member value is nonzero if there is a transition by
671*38fd1498Szrj cycle advancing. */
672*38fd1498Szrj int new_cycle_p;
673*38fd1498Szrj /* The following field is list of processor unit reservations on
674*38fd1498Szrj each cycle. */
675*38fd1498Szrj reserv_sets_t reservs;
676*38fd1498Szrj /* The following field is unique number of given state between other
677*38fd1498Szrj states. */
678*38fd1498Szrj int unique_num;
679*38fd1498Szrj /* The following field value is automaton to which given state
680*38fd1498Szrj belongs. */
681*38fd1498Szrj automaton_t automaton;
682*38fd1498Szrj /* The following field value is the first arc output from given
683*38fd1498Szrj state. */
684*38fd1498Szrj arc_t first_out_arc;
685*38fd1498Szrj unsigned int num_out_arcs;
686*38fd1498Szrj /* The following field is used to form NDFA. */
687*38fd1498Szrj char it_was_placed_in_stack_for_NDFA_forming;
688*38fd1498Szrj /* The following field is used to form DFA. */
689*38fd1498Szrj char it_was_placed_in_stack_for_DFA_forming;
690*38fd1498Szrj /* The following field is used to transform NDFA to DFA and DFA
691*38fd1498Szrj minimization. The field value is not NULL if the state is a
692*38fd1498Szrj compound state. In this case the value of field `unit_sets_list'
693*38fd1498Szrj is NULL. All states in the list are in the hash table. The list
694*38fd1498Szrj is formed through field `next_sorted_alt_state'. We should
695*38fd1498Szrj support only one level of nesting state. */
696*38fd1498Szrj alt_state_t component_states;
697*38fd1498Szrj /* The following field is used for passing graph of states. */
698*38fd1498Szrj int pass_num;
699*38fd1498Szrj /* The list of states belonging to one equivalence class is formed
700*38fd1498Szrj with the aid of the following field. */
701*38fd1498Szrj state_t next_equiv_class_state;
702*38fd1498Szrj /* The two following fields are used during minimization of a finite
703*38fd1498Szrj state automaton. */
704*38fd1498Szrj int equiv_class_num_1, equiv_class_num_2;
705*38fd1498Szrj /* The following field is used during minimization of a finite state
706*38fd1498Szrj automaton. The field value is state corresponding to equivalence
707*38fd1498Szrj class to which given state belongs. */
708*38fd1498Szrj state_t equiv_class_state;
709*38fd1498Szrj unsigned int *presence_signature;
710*38fd1498Szrj /* The following field value is the order number of given state.
711*38fd1498Szrj The states in final DFA is enumerated with the aid of the
712*38fd1498Szrj following field. */
713*38fd1498Szrj int order_state_num;
714*38fd1498Szrj /* This member is used for passing states for searching minimal
715*38fd1498Szrj delay time. */
716*38fd1498Szrj int state_pass_num;
717*38fd1498Szrj /* The following member is used to evaluate min issue delay of insn
718*38fd1498Szrj for a state. */
719*38fd1498Szrj int min_insn_issue_delay;
720*38fd1498Szrj };
721*38fd1498Szrj
722*38fd1498Szrj /* Automaton arc. */
723*38fd1498Szrj struct arc
724*38fd1498Szrj {
725*38fd1498Szrj /* The following field refers for the state into which given arc
726*38fd1498Szrj enters. */
727*38fd1498Szrj state_t to_state;
728*38fd1498Szrj /* The following field describes that the insn issue (with cycle
729*38fd1498Szrj advancing for special insn `cycle advancing' and without cycle
730*38fd1498Szrj advancing for others) makes transition from given state to
731*38fd1498Szrj another given state. */
732*38fd1498Szrj ainsn_t insn;
733*38fd1498Szrj /* The following field value is the next arc output from the same
734*38fd1498Szrj state. */
735*38fd1498Szrj arc_t next_out_arc;
736*38fd1498Szrj /* List of arcs marked given insn is formed with the following
737*38fd1498Szrj field. The field is used in transformation NDFA -> DFA. */
738*38fd1498Szrj arc_t next_arc_marked_by_insn;
739*38fd1498Szrj };
740*38fd1498Szrj
741*38fd1498Szrj /* The following node type describes a deterministic alternative in
742*38fd1498Szrj non-deterministic state which characterizes cpu unit reservations
743*38fd1498Szrj of automaton insn or which is part of NDFA. */
744*38fd1498Szrj struct alt_state
745*38fd1498Szrj {
746*38fd1498Szrj /* The following field is a deterministic state which characterizes
747*38fd1498Szrj unit reservations of the instruction. */
748*38fd1498Szrj state_t state;
749*38fd1498Szrj /* The following field refers to the next state which characterizes
750*38fd1498Szrj unit reservations of the instruction. */
751*38fd1498Szrj alt_state_t next_alt_state;
752*38fd1498Szrj /* The following field refers to the next state in sorted list. */
753*38fd1498Szrj alt_state_t next_sorted_alt_state;
754*38fd1498Szrj };
755*38fd1498Szrj
756*38fd1498Szrj /* The following node type describes insn of automaton. They are
757*38fd1498Szrj labels of FA arcs. */
758*38fd1498Szrj struct ainsn
759*38fd1498Szrj {
760*38fd1498Szrj /* The following field value is the corresponding insn declaration
761*38fd1498Szrj of description. */
762*38fd1498Szrj struct insn_reserv_decl *insn_reserv_decl;
763*38fd1498Szrj /* The following field value is the next insn declaration for an
764*38fd1498Szrj automaton. */
765*38fd1498Szrj ainsn_t next_ainsn;
766*38fd1498Szrj /* The following field is states which characterize automaton unit
767*38fd1498Szrj reservations of the instruction. The value can be NULL only if it
768*38fd1498Szrj is special insn `cycle advancing'. */
769*38fd1498Szrj alt_state_t alt_states;
770*38fd1498Szrj /* The following field is sorted list of states which characterize
771*38fd1498Szrj automaton unit reservations of the instruction. The value can be
772*38fd1498Szrj NULL only if it is special insn `cycle advancing'. */
773*38fd1498Szrj alt_state_t sorted_alt_states;
774*38fd1498Szrj /* The following field refers the next automaton insn with
775*38fd1498Szrj the same reservations. */
776*38fd1498Szrj ainsn_t next_same_reservs_insn;
777*38fd1498Szrj /* The following field is flag of the first automaton insn with the
778*38fd1498Szrj same reservations in the declaration list. Only arcs marked such
779*38fd1498Szrj insn is present in the automaton. This significantly decreases
780*38fd1498Szrj memory requirements especially when several automata are
781*38fd1498Szrj formed. */
782*38fd1498Szrj char first_insn_with_same_reservs;
783*38fd1498Szrj /* The following member has nonzero value if there is arc from state of
784*38fd1498Szrj the automaton marked by the ainsn. */
785*38fd1498Szrj char arc_exists_p;
786*38fd1498Szrj /* Cyclic list of insns of an equivalence class is formed with the
787*38fd1498Szrj aid of the following field. */
788*38fd1498Szrj ainsn_t next_equiv_class_insn;
789*38fd1498Szrj /* The following field value is nonzero if the insn declaration is
790*38fd1498Szrj the first insn declaration with given equivalence number. */
791*38fd1498Szrj char first_ainsn_with_given_equivalence_num;
792*38fd1498Szrj /* The following field is number of class of equivalence of insns.
793*38fd1498Szrj It is necessary because many insns may be equivalent with the
794*38fd1498Szrj point of view of pipeline hazards. */
795*38fd1498Szrj int insn_equiv_class_num;
796*38fd1498Szrj /* The following member value is TRUE if there is an arc in the
797*38fd1498Szrj automaton marked by the insn into another state. In other
798*38fd1498Szrj words, the insn can change the state of the automaton. */
799*38fd1498Szrj int important_p;
800*38fd1498Szrj };
801*38fd1498Szrj
802*38fd1498Szrj /* The following describes an automaton for PHR. */
803*38fd1498Szrj struct automaton
804*38fd1498Szrj {
805*38fd1498Szrj /* The following field value is the list of insn declarations for
806*38fd1498Szrj given automaton. */
807*38fd1498Szrj ainsn_t ainsn_list;
808*38fd1498Szrj /* Pointers to the ainsns corresponding to the special reservations. */
809*38fd1498Szrj ainsn_t advance_ainsn, collapse_ainsn;
810*38fd1498Szrj
811*38fd1498Szrj /* The following field value is the corresponding automaton
812*38fd1498Szrj declaration. This field is not NULL only if the automatic
813*38fd1498Szrj partition on automata is not used. */
814*38fd1498Szrj struct automaton_decl *corresponding_automaton_decl;
815*38fd1498Szrj /* The following field value is the next automaton. */
816*38fd1498Szrj automaton_t next_automaton;
817*38fd1498Szrj /* The following field is start state of FA. There are not unit
818*38fd1498Szrj reservations in the state. */
819*38fd1498Szrj state_t start_state;
820*38fd1498Szrj /* The following field value is number of equivalence classes of
821*38fd1498Szrj insns (see field `insn_equiv_class_num' in
822*38fd1498Szrj `insn_reserv_decl'). */
823*38fd1498Szrj int insn_equiv_classes_num;
824*38fd1498Szrj /* The following field value is number of states of final DFA. */
825*38fd1498Szrj int achieved_states_num;
826*38fd1498Szrj /* The following field value is the order number (0, 1, ...) of
827*38fd1498Szrj given automaton. */
828*38fd1498Szrj int automaton_order_num;
829*38fd1498Szrj /* The following fields contain statistics information about
830*38fd1498Szrj building automaton. */
831*38fd1498Szrj int NDFA_states_num, DFA_states_num;
832*38fd1498Szrj /* The following field value is defined only if minimization of DFA
833*38fd1498Szrj is used. */
834*38fd1498Szrj int minimal_DFA_states_num;
835*38fd1498Szrj int NDFA_arcs_num, DFA_arcs_num;
836*38fd1498Szrj /* The following field value is defined only if minimization of DFA
837*38fd1498Szrj is used. */
838*38fd1498Szrj int minimal_DFA_arcs_num;
839*38fd1498Szrj /* The following member refers for two table state x ainsn -> int.
840*38fd1498Szrj ??? Above sentence is incomprehensible. */
841*38fd1498Szrj state_ainsn_table_t trans_table;
842*38fd1498Szrj /* The following member value is maximal value of min issue delay
843*38fd1498Szrj for insns of the automaton. */
844*38fd1498Szrj int max_min_delay;
845*38fd1498Szrj /* Usually min issue delay is small and we can place several (2, 4,
846*38fd1498Szrj 8) elements in one vector element. So the compression factor can
847*38fd1498Szrj be 1 (no compression), 2, 4, 8. */
848*38fd1498Szrj int min_issue_delay_table_compression_factor;
849*38fd1498Szrj /* Total number of locked states in this automaton. */
850*38fd1498Szrj int locked_states;
851*38fd1498Szrj };
852*38fd1498Szrj
853*38fd1498Szrj /* The following is the element of the list of automata. */
854*38fd1498Szrj struct automata_list_el
855*38fd1498Szrj {
856*38fd1498Szrj /* The automaton itself. */
857*38fd1498Szrj automaton_t automaton;
858*38fd1498Szrj /* The next automata set element. */
859*38fd1498Szrj automata_list_el_t next_automata_list_el;
860*38fd1498Szrj };
861*38fd1498Szrj
862*38fd1498Szrj /* The following structure describes a table state X ainsn -> int(>= 0). */
863*38fd1498Szrj struct state_ainsn_table
864*38fd1498Szrj {
865*38fd1498Szrj /* Automaton to which given table belongs. */
866*38fd1498Szrj automaton_t automaton;
867*38fd1498Szrj /* The following tree vectors for comb vector implementation of the
868*38fd1498Szrj table. */
869*38fd1498Szrj vla_hwint_t comb_vect;
870*38fd1498Szrj vla_hwint_t check_vect;
871*38fd1498Szrj vla_hwint_t base_vect;
872*38fd1498Szrj /* This is simple implementation of the table. */
873*38fd1498Szrj vla_hwint_t full_vect;
874*38fd1498Szrj /* Minimal and maximal values of the previous vectors. */
875*38fd1498Szrj int min_comb_vect_el_value, max_comb_vect_el_value;
876*38fd1498Szrj int min_base_vect_el_value, max_base_vect_el_value;
877*38fd1498Szrj };
878*38fd1498Szrj
879*38fd1498Szrj /* Macros to access members of unions. Use only them for access to
880*38fd1498Szrj union members of declarations and regexps. */
881*38fd1498Szrj
882*38fd1498Szrj #if CHECKING_P && (GCC_VERSION >= 2007)
883*38fd1498Szrj
884*38fd1498Szrj #define DECL_UNIT(d) __extension__ \
885*38fd1498Szrj (({ __typeof (d) const _decl = (d); \
886*38fd1498Szrj if (_decl->mode != dm_unit) \
887*38fd1498Szrj decl_mode_check_failed (_decl->mode, "dm_unit", \
888*38fd1498Szrj __FILE__, __LINE__, __FUNCTION__); \
889*38fd1498Szrj &(_decl)->decl.unit; }))
890*38fd1498Szrj
891*38fd1498Szrj #define DECL_BYPASS(d) __extension__ \
892*38fd1498Szrj (({ __typeof (d) const _decl = (d); \
893*38fd1498Szrj if (_decl->mode != dm_bypass) \
894*38fd1498Szrj decl_mode_check_failed (_decl->mode, "dm_bypass", \
895*38fd1498Szrj __FILE__, __LINE__, __FUNCTION__); \
896*38fd1498Szrj &(_decl)->decl.bypass; }))
897*38fd1498Szrj
898*38fd1498Szrj #define DECL_AUTOMATON(d) __extension__ \
899*38fd1498Szrj (({ __typeof (d) const _decl = (d); \
900*38fd1498Szrj if (_decl->mode != dm_automaton) \
901*38fd1498Szrj decl_mode_check_failed (_decl->mode, "dm_automaton", \
902*38fd1498Szrj __FILE__, __LINE__, __FUNCTION__); \
903*38fd1498Szrj &(_decl)->decl.automaton; }))
904*38fd1498Szrj
905*38fd1498Szrj #define DECL_EXCL(d) __extension__ \
906*38fd1498Szrj (({ __typeof (d) const _decl = (d); \
907*38fd1498Szrj if (_decl->mode != dm_excl) \
908*38fd1498Szrj decl_mode_check_failed (_decl->mode, "dm_excl", \
909*38fd1498Szrj __FILE__, __LINE__, __FUNCTION__); \
910*38fd1498Szrj &(_decl)->decl.excl; }))
911*38fd1498Szrj
912*38fd1498Szrj #define DECL_PRESENCE(d) __extension__ \
913*38fd1498Szrj (({ __typeof (d) const _decl = (d); \
914*38fd1498Szrj if (_decl->mode != dm_presence) \
915*38fd1498Szrj decl_mode_check_failed (_decl->mode, "dm_presence", \
916*38fd1498Szrj __FILE__, __LINE__, __FUNCTION__); \
917*38fd1498Szrj &(_decl)->decl.presence; }))
918*38fd1498Szrj
919*38fd1498Szrj #define DECL_ABSENCE(d) __extension__ \
920*38fd1498Szrj (({ __typeof (d) const _decl = (d); \
921*38fd1498Szrj if (_decl->mode != dm_absence) \
922*38fd1498Szrj decl_mode_check_failed (_decl->mode, "dm_absence", \
923*38fd1498Szrj __FILE__, __LINE__, __FUNCTION__); \
924*38fd1498Szrj &(_decl)->decl.absence; }))
925*38fd1498Szrj
926*38fd1498Szrj #define DECL_RESERV(d) __extension__ \
927*38fd1498Szrj (({ __typeof (d) const _decl = (d); \
928*38fd1498Szrj if (_decl->mode != dm_reserv) \
929*38fd1498Szrj decl_mode_check_failed (_decl->mode, "dm_reserv", \
930*38fd1498Szrj __FILE__, __LINE__, __FUNCTION__); \
931*38fd1498Szrj &(_decl)->decl.reserv; }))
932*38fd1498Szrj
933*38fd1498Szrj #define DECL_INSN_RESERV(d) __extension__ \
934*38fd1498Szrj (({ __typeof (d) const _decl = (d); \
935*38fd1498Szrj if (_decl->mode != dm_insn_reserv) \
936*38fd1498Szrj decl_mode_check_failed (_decl->mode, "dm_insn_reserv", \
937*38fd1498Szrj __FILE__, __LINE__, __FUNCTION__); \
938*38fd1498Szrj &(_decl)->decl.insn_reserv; }))
939*38fd1498Szrj
940*38fd1498Szrj static const char *decl_name (enum decl_mode);
941*38fd1498Szrj static void decl_mode_check_failed (enum decl_mode, const char *,
942*38fd1498Szrj const char *, int, const char *)
943*38fd1498Szrj ATTRIBUTE_NORETURN;
944*38fd1498Szrj
945*38fd1498Szrj /* Return string representation of declaration mode MODE. */
946*38fd1498Szrj static const char *
decl_name(enum decl_mode mode)947*38fd1498Szrj decl_name (enum decl_mode mode)
948*38fd1498Szrj {
949*38fd1498Szrj static char str [100];
950*38fd1498Szrj
951*38fd1498Szrj if (mode == dm_unit)
952*38fd1498Szrj return "dm_unit";
953*38fd1498Szrj else if (mode == dm_bypass)
954*38fd1498Szrj return "dm_bypass";
955*38fd1498Szrj else if (mode == dm_automaton)
956*38fd1498Szrj return "dm_automaton";
957*38fd1498Szrj else if (mode == dm_excl)
958*38fd1498Szrj return "dm_excl";
959*38fd1498Szrj else if (mode == dm_presence)
960*38fd1498Szrj return "dm_presence";
961*38fd1498Szrj else if (mode == dm_absence)
962*38fd1498Szrj return "dm_absence";
963*38fd1498Szrj else if (mode == dm_reserv)
964*38fd1498Szrj return "dm_reserv";
965*38fd1498Szrj else if (mode == dm_insn_reserv)
966*38fd1498Szrj return "dm_insn_reserv";
967*38fd1498Szrj else
968*38fd1498Szrj sprintf (str, "unknown (%d)", (int) mode);
969*38fd1498Szrj return str;
970*38fd1498Szrj }
971*38fd1498Szrj
972*38fd1498Szrj /* The function prints message about unexpected declaration and finish
973*38fd1498Szrj the program. */
974*38fd1498Szrj static void
decl_mode_check_failed(enum decl_mode mode,const char * expected_mode_str,const char * file,int line,const char * func)975*38fd1498Szrj decl_mode_check_failed (enum decl_mode mode, const char *expected_mode_str,
976*38fd1498Szrj const char *file, int line, const char *func)
977*38fd1498Szrj {
978*38fd1498Szrj fprintf
979*38fd1498Szrj (stderr,
980*38fd1498Szrj "\n%s: %d: error in %s: DECL check: expected decl %s, have %s\n",
981*38fd1498Szrj file, line, func, expected_mode_str, decl_name (mode));
982*38fd1498Szrj exit (1);
983*38fd1498Szrj }
984*38fd1498Szrj
985*38fd1498Szrj
986*38fd1498Szrj #define REGEXP_UNIT(r) __extension__ \
987*38fd1498Szrj (({ struct regexp *const _regexp = (r); \
988*38fd1498Szrj if (_regexp->mode != rm_unit) \
989*38fd1498Szrj regexp_mode_check_failed (_regexp->mode, "rm_unit", \
990*38fd1498Szrj __FILE__, __LINE__, __FUNCTION__); \
991*38fd1498Szrj &(_regexp)->regexp.unit; }))
992*38fd1498Szrj
993*38fd1498Szrj #define REGEXP_RESERV(r) __extension__ \
994*38fd1498Szrj (({ struct regexp *const _regexp = (r); \
995*38fd1498Szrj if (_regexp->mode != rm_reserv) \
996*38fd1498Szrj regexp_mode_check_failed (_regexp->mode, "rm_reserv", \
997*38fd1498Szrj __FILE__, __LINE__, __FUNCTION__); \
998*38fd1498Szrj &(_regexp)->regexp.reserv; }))
999*38fd1498Szrj
1000*38fd1498Szrj #define REGEXP_SEQUENCE(r) __extension__ \
1001*38fd1498Szrj (({ struct regexp *const _regexp = (r); \
1002*38fd1498Szrj if (_regexp->mode != rm_sequence) \
1003*38fd1498Szrj regexp_mode_check_failed (_regexp->mode, "rm_sequence", \
1004*38fd1498Szrj __FILE__, __LINE__, __FUNCTION__); \
1005*38fd1498Szrj &(_regexp)->regexp.sequence; }))
1006*38fd1498Szrj
1007*38fd1498Szrj #define REGEXP_REPEAT(r) __extension__ \
1008*38fd1498Szrj (({ struct regexp *const _regexp = (r); \
1009*38fd1498Szrj if (_regexp->mode != rm_repeat) \
1010*38fd1498Szrj regexp_mode_check_failed (_regexp->mode, "rm_repeat", \
1011*38fd1498Szrj __FILE__, __LINE__, __FUNCTION__); \
1012*38fd1498Szrj &(_regexp)->regexp.repeat; }))
1013*38fd1498Szrj
1014*38fd1498Szrj #define REGEXP_ALLOF(r) __extension__ \
1015*38fd1498Szrj (({ struct regexp *const _regexp = (r); \
1016*38fd1498Szrj if (_regexp->mode != rm_allof) \
1017*38fd1498Szrj regexp_mode_check_failed (_regexp->mode, "rm_allof", \
1018*38fd1498Szrj __FILE__, __LINE__, __FUNCTION__); \
1019*38fd1498Szrj &(_regexp)->regexp.allof; }))
1020*38fd1498Szrj
1021*38fd1498Szrj #define REGEXP_ONEOF(r) __extension__ \
1022*38fd1498Szrj (({ struct regexp *const _regexp = (r); \
1023*38fd1498Szrj if (_regexp->mode != rm_oneof) \
1024*38fd1498Szrj regexp_mode_check_failed (_regexp->mode, "rm_oneof", \
1025*38fd1498Szrj __FILE__, __LINE__, __FUNCTION__); \
1026*38fd1498Szrj &(_regexp)->regexp.oneof; }))
1027*38fd1498Szrj
1028*38fd1498Szrj static const char *regexp_name (enum regexp_mode);
1029*38fd1498Szrj static void regexp_mode_check_failed (enum regexp_mode, const char *,
1030*38fd1498Szrj const char *, int,
1031*38fd1498Szrj const char *) ATTRIBUTE_NORETURN;
1032*38fd1498Szrj
1033*38fd1498Szrj
1034*38fd1498Szrj /* Return string representation of regexp mode MODE. */
1035*38fd1498Szrj static const char *
regexp_name(enum regexp_mode mode)1036*38fd1498Szrj regexp_name (enum regexp_mode mode)
1037*38fd1498Szrj {
1038*38fd1498Szrj switch (mode)
1039*38fd1498Szrj {
1040*38fd1498Szrj case rm_unit:
1041*38fd1498Szrj return "rm_unit";
1042*38fd1498Szrj case rm_reserv:
1043*38fd1498Szrj return "rm_reserv";
1044*38fd1498Szrj case rm_nothing:
1045*38fd1498Szrj return "rm_nothing";
1046*38fd1498Szrj case rm_sequence:
1047*38fd1498Szrj return "rm_sequence";
1048*38fd1498Szrj case rm_repeat:
1049*38fd1498Szrj return "rm_repeat";
1050*38fd1498Szrj case rm_allof:
1051*38fd1498Szrj return "rm_allof";
1052*38fd1498Szrj case rm_oneof:
1053*38fd1498Szrj return "rm_oneof";
1054*38fd1498Szrj default:
1055*38fd1498Szrj gcc_unreachable ();
1056*38fd1498Szrj }
1057*38fd1498Szrj }
1058*38fd1498Szrj
1059*38fd1498Szrj /* The function prints message about unexpected regexp and finish the
1060*38fd1498Szrj program. */
1061*38fd1498Szrj static void
regexp_mode_check_failed(enum regexp_mode mode,const char * expected_mode_str,const char * file,int line,const char * func)1062*38fd1498Szrj regexp_mode_check_failed (enum regexp_mode mode,
1063*38fd1498Szrj const char *expected_mode_str,
1064*38fd1498Szrj const char *file, int line, const char *func)
1065*38fd1498Szrj {
1066*38fd1498Szrj fprintf
1067*38fd1498Szrj (stderr,
1068*38fd1498Szrj "\n%s: %d: error in %s: REGEXP check: expected decl %s, have %s\n",
1069*38fd1498Szrj file, line, func, expected_mode_str, regexp_name (mode));
1070*38fd1498Szrj exit (1);
1071*38fd1498Szrj }
1072*38fd1498Szrj
1073*38fd1498Szrj #else /* #if CHECKING_P && (GCC_VERSION >= 2007) */
1074*38fd1498Szrj
1075*38fd1498Szrj #define DECL_UNIT(d) (&(d)->decl.unit)
1076*38fd1498Szrj #define DECL_BYPASS(d) (&(d)->decl.bypass)
1077*38fd1498Szrj #define DECL_AUTOMATON(d) (&(d)->decl.automaton)
1078*38fd1498Szrj #define DECL_EXCL(d) (&(d)->decl.excl)
1079*38fd1498Szrj #define DECL_PRESENCE(d) (&(d)->decl.presence)
1080*38fd1498Szrj #define DECL_ABSENCE(d) (&(d)->decl.absence)
1081*38fd1498Szrj #define DECL_RESERV(d) (&(d)->decl.reserv)
1082*38fd1498Szrj #define DECL_INSN_RESERV(d) (&(d)->decl.insn_reserv)
1083*38fd1498Szrj
1084*38fd1498Szrj #define REGEXP_UNIT(r) (&(r)->regexp.unit)
1085*38fd1498Szrj #define REGEXP_RESERV(r) (&(r)->regexp.reserv)
1086*38fd1498Szrj #define REGEXP_SEQUENCE(r) (&(r)->regexp.sequence)
1087*38fd1498Szrj #define REGEXP_REPEAT(r) (&(r)->regexp.repeat)
1088*38fd1498Szrj #define REGEXP_ALLOF(r) (&(r)->regexp.allof)
1089*38fd1498Szrj #define REGEXP_ONEOF(r) (&(r)->regexp.oneof)
1090*38fd1498Szrj
1091*38fd1498Szrj #endif /* #if CHECKING_P && (GCC_VERSION >= 2007) */
1092*38fd1498Szrj
1093*38fd1498Szrj #define XCREATENODE(T) ((T *) create_node (sizeof (T)))
1094*38fd1498Szrj #define XCREATENODEVEC(T, N) ((T *) create_node (sizeof (T) * (N)))
1095*38fd1498Szrj #define XCREATENODEVAR(T, S) ((T *) create_node ((S)))
1096*38fd1498Szrj
1097*38fd1498Szrj #define XCOPYNODE(T, P) ((T *) copy_node ((P), sizeof (T)))
1098*38fd1498Szrj #define XCOPYNODEVEC(T, P, N) ((T *) copy_node ((P), sizeof (T) * (N)))
1099*38fd1498Szrj #define XCOPYNODEVAR(T, P, S) ((T *) copy_node ((P), (S)))
1100*38fd1498Szrj
1101*38fd1498Szrj /* Create IR structure (node). */
1102*38fd1498Szrj static void *
create_node(size_t size)1103*38fd1498Szrj create_node (size_t size)
1104*38fd1498Szrj {
1105*38fd1498Szrj void *result;
1106*38fd1498Szrj
1107*38fd1498Szrj obstack_blank (&irp, size);
1108*38fd1498Szrj result = obstack_base (&irp);
1109*38fd1498Szrj obstack_finish (&irp);
1110*38fd1498Szrj /* Default values of members are NULL and zero. */
1111*38fd1498Szrj memset (result, 0, size);
1112*38fd1498Szrj return result;
1113*38fd1498Szrj }
1114*38fd1498Szrj
1115*38fd1498Szrj /* Copy IR structure (node). */
1116*38fd1498Szrj static void *
copy_node(const void * from,size_t size)1117*38fd1498Szrj copy_node (const void *from, size_t size)
1118*38fd1498Szrj {
1119*38fd1498Szrj void *const result = create_node (size);
1120*38fd1498Szrj memcpy (result, from, size);
1121*38fd1498Szrj return result;
1122*38fd1498Szrj }
1123*38fd1498Szrj
1124*38fd1498Szrj /* The function checks that NAME does not contain quotes (`"'). */
1125*38fd1498Szrj static const char *
check_name(const char * name,pos_t pos ATTRIBUTE_UNUSED)1126*38fd1498Szrj check_name (const char * name, pos_t pos ATTRIBUTE_UNUSED)
1127*38fd1498Szrj {
1128*38fd1498Szrj const char *str;
1129*38fd1498Szrj
1130*38fd1498Szrj for (str = name; *str != '\0'; str++)
1131*38fd1498Szrj if (*str == '\"')
1132*38fd1498Szrj error ("Name `%s' contains quotes", name);
1133*38fd1498Szrj return name;
1134*38fd1498Szrj }
1135*38fd1498Szrj
1136*38fd1498Szrj /* Pointers to all declarations during IR generation are stored in the
1137*38fd1498Szrj following. */
1138*38fd1498Szrj static vec<decl_t> decls;
1139*38fd1498Szrj
1140*38fd1498Szrj /* Given a pointer to a (char *) and a separator, return an alloc'ed
1141*38fd1498Szrj string containing the next separated element, taking parentheses
1142*38fd1498Szrj into account if PAR_FLAG has nonzero value. Advance the pointer to
1143*38fd1498Szrj after the string scanned, or the end-of-string. Return NULL if at
1144*38fd1498Szrj end of string. */
1145*38fd1498Szrj static char *
next_sep_el(const char ** pstr,int sep,int par_flag)1146*38fd1498Szrj next_sep_el (const char **pstr, int sep, int par_flag)
1147*38fd1498Szrj {
1148*38fd1498Szrj char *out_str;
1149*38fd1498Szrj const char *p;
1150*38fd1498Szrj int pars_num;
1151*38fd1498Szrj int n_spaces;
1152*38fd1498Szrj
1153*38fd1498Szrj /* Remove leading whitespaces. */
1154*38fd1498Szrj while (ISSPACE ((int) **pstr))
1155*38fd1498Szrj (*pstr)++;
1156*38fd1498Szrj
1157*38fd1498Szrj if (**pstr == '\0')
1158*38fd1498Szrj return NULL;
1159*38fd1498Szrj
1160*38fd1498Szrj n_spaces = 0;
1161*38fd1498Szrj for (pars_num = 0, p = *pstr; *p != '\0'; p++)
1162*38fd1498Szrj {
1163*38fd1498Szrj if (par_flag && *p == '(')
1164*38fd1498Szrj pars_num++;
1165*38fd1498Szrj else if (par_flag && *p == ')')
1166*38fd1498Szrj pars_num--;
1167*38fd1498Szrj else if (pars_num == 0 && *p == sep)
1168*38fd1498Szrj break;
1169*38fd1498Szrj if (pars_num == 0 && ISSPACE ((int) *p))
1170*38fd1498Szrj n_spaces++;
1171*38fd1498Szrj else
1172*38fd1498Szrj {
1173*38fd1498Szrj for (; n_spaces != 0; n_spaces--)
1174*38fd1498Szrj obstack_1grow (&irp, p [-n_spaces]);
1175*38fd1498Szrj obstack_1grow (&irp, *p);
1176*38fd1498Szrj }
1177*38fd1498Szrj }
1178*38fd1498Szrj obstack_1grow (&irp, '\0');
1179*38fd1498Szrj out_str = (char *) obstack_base (&irp);
1180*38fd1498Szrj obstack_finish (&irp);
1181*38fd1498Szrj
1182*38fd1498Szrj *pstr = p;
1183*38fd1498Szrj if (**pstr == sep)
1184*38fd1498Szrj (*pstr)++;
1185*38fd1498Szrj
1186*38fd1498Szrj return out_str;
1187*38fd1498Szrj }
1188*38fd1498Szrj
1189*38fd1498Szrj /* Given a string and a separator, return the number of separated
1190*38fd1498Szrj elements in it, taking parentheses into account if PAR_FLAG has
1191*38fd1498Szrj nonzero value. Return 0 for the null string, -1 if parentheses is
1192*38fd1498Szrj not balanced. */
1193*38fd1498Szrj static int
n_sep_els(const char * s,int sep,int par_flag)1194*38fd1498Szrj n_sep_els (const char *s, int sep, int par_flag)
1195*38fd1498Szrj {
1196*38fd1498Szrj int n;
1197*38fd1498Szrj int pars_num;
1198*38fd1498Szrj
1199*38fd1498Szrj if (*s == '\0')
1200*38fd1498Szrj return 0;
1201*38fd1498Szrj
1202*38fd1498Szrj for (pars_num = 0, n = 1; *s; s++)
1203*38fd1498Szrj if (par_flag && *s == '(')
1204*38fd1498Szrj pars_num++;
1205*38fd1498Szrj else if (par_flag && *s == ')')
1206*38fd1498Szrj pars_num--;
1207*38fd1498Szrj else if (pars_num == 0 && *s == sep)
1208*38fd1498Szrj n++;
1209*38fd1498Szrj
1210*38fd1498Szrj return (pars_num != 0 ? -1 : n);
1211*38fd1498Szrj }
1212*38fd1498Szrj
1213*38fd1498Szrj /* Given a string and a separator, return vector of strings which are
1214*38fd1498Szrj elements in the string and number of elements through els_num.
1215*38fd1498Szrj Take parentheses into account if PAREN_P has nonzero value. The
1216*38fd1498Szrj function also inserts the end marker NULL at the end of vector.
1217*38fd1498Szrj Return 0 for the null string, -1 if parentheses are not balanced. */
1218*38fd1498Szrj static char **
get_str_vect(const char * str,int * els_num,int sep,int paren_p)1219*38fd1498Szrj get_str_vect (const char *str, int *els_num, int sep, int paren_p)
1220*38fd1498Szrj {
1221*38fd1498Szrj int i;
1222*38fd1498Szrj char **vect;
1223*38fd1498Szrj const char **pstr;
1224*38fd1498Szrj char *trail;
1225*38fd1498Szrj
1226*38fd1498Szrj *els_num = n_sep_els (str, sep, paren_p);
1227*38fd1498Szrj if (*els_num <= 0)
1228*38fd1498Szrj return NULL;
1229*38fd1498Szrj obstack_blank (&irp, sizeof (char *) * (*els_num + 1));
1230*38fd1498Szrj vect = (char **) obstack_base (&irp);
1231*38fd1498Szrj obstack_finish (&irp);
1232*38fd1498Szrj pstr = &str;
1233*38fd1498Szrj for (i = 0; i < *els_num; i++)
1234*38fd1498Szrj vect [i] = next_sep_el (pstr, sep, paren_p);
1235*38fd1498Szrj trail = next_sep_el (pstr, sep, paren_p);
1236*38fd1498Szrj gcc_assert (!trail);
1237*38fd1498Szrj vect [i] = NULL;
1238*38fd1498Szrj return vect;
1239*38fd1498Szrj }
1240*38fd1498Szrj
1241*38fd1498Szrj /* Process a DEFINE_CPU_UNIT.
1242*38fd1498Szrj
1243*38fd1498Szrj This gives information about a unit contained in CPU. We fill a
1244*38fd1498Szrj struct unit_decl with information used later by `expand_automata'. */
1245*38fd1498Szrj static void
gen_cpu_unit(md_rtx_info * info)1246*38fd1498Szrj gen_cpu_unit (md_rtx_info *info)
1247*38fd1498Szrj {
1248*38fd1498Szrj decl_t decl;
1249*38fd1498Szrj char **str_cpu_units;
1250*38fd1498Szrj int vect_length;
1251*38fd1498Szrj int i;
1252*38fd1498Szrj
1253*38fd1498Szrj rtx def = info->def;
1254*38fd1498Szrj str_cpu_units = get_str_vect (XSTR (def, 0), &vect_length, ',', FALSE);
1255*38fd1498Szrj if (str_cpu_units == NULL)
1256*38fd1498Szrj fatal_at (info->loc, "invalid string `%s' in %s",
1257*38fd1498Szrj XSTR (def, 0), GET_RTX_NAME (GET_CODE (def)));
1258*38fd1498Szrj for (i = 0; i < vect_length; i++)
1259*38fd1498Szrj {
1260*38fd1498Szrj decl = XCREATENODE (struct decl);
1261*38fd1498Szrj decl->mode = dm_unit;
1262*38fd1498Szrj decl->pos = 0;
1263*38fd1498Szrj DECL_UNIT (decl)->name = check_name (str_cpu_units [i], decl->pos);
1264*38fd1498Szrj DECL_UNIT (decl)->automaton_name = XSTR (def, 1);
1265*38fd1498Szrj DECL_UNIT (decl)->query_p = 0;
1266*38fd1498Szrj DECL_UNIT (decl)->min_occ_cycle_num = -1;
1267*38fd1498Szrj DECL_UNIT (decl)->in_set_p = 0;
1268*38fd1498Szrj decls.safe_push (decl);
1269*38fd1498Szrj }
1270*38fd1498Szrj }
1271*38fd1498Szrj
1272*38fd1498Szrj /* Process a DEFINE_QUERY_CPU_UNIT.
1273*38fd1498Szrj
1274*38fd1498Szrj This gives information about a unit contained in CPU. We fill a
1275*38fd1498Szrj struct unit_decl with information used later by `expand_automata'. */
1276*38fd1498Szrj static void
gen_query_cpu_unit(md_rtx_info * info)1277*38fd1498Szrj gen_query_cpu_unit (md_rtx_info *info)
1278*38fd1498Szrj {
1279*38fd1498Szrj decl_t decl;
1280*38fd1498Szrj char **str_cpu_units;
1281*38fd1498Szrj int vect_length;
1282*38fd1498Szrj int i;
1283*38fd1498Szrj
1284*38fd1498Szrj rtx def = info->def;
1285*38fd1498Szrj str_cpu_units = get_str_vect (XSTR (def, 0), &vect_length, ',',
1286*38fd1498Szrj FALSE);
1287*38fd1498Szrj if (str_cpu_units == NULL)
1288*38fd1498Szrj fatal_at (info->loc, "invalid string `%s' in %s",
1289*38fd1498Szrj XSTR (def, 0), GET_RTX_NAME (GET_CODE (def)));
1290*38fd1498Szrj for (i = 0; i < vect_length; i++)
1291*38fd1498Szrj {
1292*38fd1498Szrj decl = XCREATENODE (struct decl);
1293*38fd1498Szrj decl->mode = dm_unit;
1294*38fd1498Szrj decl->pos = 0;
1295*38fd1498Szrj DECL_UNIT (decl)->name = check_name (str_cpu_units [i], decl->pos);
1296*38fd1498Szrj DECL_UNIT (decl)->automaton_name = XSTR (def, 1);
1297*38fd1498Szrj DECL_UNIT (decl)->query_p = 1;
1298*38fd1498Szrj decls.safe_push (decl);
1299*38fd1498Szrj }
1300*38fd1498Szrj }
1301*38fd1498Szrj
1302*38fd1498Szrj /* Process a DEFINE_BYPASS.
1303*38fd1498Szrj
1304*38fd1498Szrj This gives information about a unit contained in the CPU. We fill
1305*38fd1498Szrj in a struct bypass_decl with information used later by
1306*38fd1498Szrj `expand_automata'. */
1307*38fd1498Szrj static void
gen_bypass(md_rtx_info * info)1308*38fd1498Szrj gen_bypass (md_rtx_info *info)
1309*38fd1498Szrj {
1310*38fd1498Szrj decl_t decl;
1311*38fd1498Szrj char **out_patterns;
1312*38fd1498Szrj int out_length;
1313*38fd1498Szrj char **in_patterns;
1314*38fd1498Szrj int in_length;
1315*38fd1498Szrj int i, j;
1316*38fd1498Szrj
1317*38fd1498Szrj rtx def = info->def;
1318*38fd1498Szrj out_patterns = get_str_vect (XSTR (def, 1), &out_length, ',', FALSE);
1319*38fd1498Szrj if (out_patterns == NULL)
1320*38fd1498Szrj fatal_at (info->loc, "invalid string `%s' in %s",
1321*38fd1498Szrj XSTR (def, 1), GET_RTX_NAME (GET_CODE (def)));
1322*38fd1498Szrj in_patterns = get_str_vect (XSTR (def, 2), &in_length, ',', FALSE);
1323*38fd1498Szrj if (in_patterns == NULL)
1324*38fd1498Szrj fatal_at (info->loc, "invalid string `%s' in %s",
1325*38fd1498Szrj XSTR (def, 2), GET_RTX_NAME (GET_CODE (def)));
1326*38fd1498Szrj for (i = 0; i < out_length; i++)
1327*38fd1498Szrj for (j = 0; j < in_length; j++)
1328*38fd1498Szrj {
1329*38fd1498Szrj decl = XCREATENODE (struct decl);
1330*38fd1498Szrj decl->mode = dm_bypass;
1331*38fd1498Szrj decl->pos = 0;
1332*38fd1498Szrj DECL_BYPASS (decl)->latency = XINT (def, 0);
1333*38fd1498Szrj DECL_BYPASS (decl)->out_pattern = out_patterns[i];
1334*38fd1498Szrj DECL_BYPASS (decl)->in_pattern = in_patterns[j];
1335*38fd1498Szrj DECL_BYPASS (decl)->bypass_guard_name = XSTR (def, 3);
1336*38fd1498Szrj decls.safe_push (decl);
1337*38fd1498Szrj }
1338*38fd1498Szrj }
1339*38fd1498Szrj
1340*38fd1498Szrj /* Process an EXCLUSION_SET.
1341*38fd1498Szrj
1342*38fd1498Szrj This gives information about a cpu unit conflicts. We fill a
1343*38fd1498Szrj struct excl_rel_decl (excl) with information used later by
1344*38fd1498Szrj `expand_automata'. */
1345*38fd1498Szrj static void
gen_excl_set(md_rtx_info * info)1346*38fd1498Szrj gen_excl_set (md_rtx_info *info)
1347*38fd1498Szrj {
1348*38fd1498Szrj decl_t decl;
1349*38fd1498Szrj char **first_str_cpu_units;
1350*38fd1498Szrj char **second_str_cpu_units;
1351*38fd1498Szrj int first_vect_length;
1352*38fd1498Szrj int length;
1353*38fd1498Szrj int i;
1354*38fd1498Szrj
1355*38fd1498Szrj rtx def = info->def;
1356*38fd1498Szrj first_str_cpu_units
1357*38fd1498Szrj = get_str_vect (XSTR (def, 0), &first_vect_length, ',', FALSE);
1358*38fd1498Szrj if (first_str_cpu_units == NULL)
1359*38fd1498Szrj fatal_at (info->loc, "invalid string `%s' in %s",
1360*38fd1498Szrj XSTR (def, 0), GET_RTX_NAME (GET_CODE (def)));
1361*38fd1498Szrj second_str_cpu_units = get_str_vect (XSTR (def, 1), &length, ',',
1362*38fd1498Szrj FALSE);
1363*38fd1498Szrj if (second_str_cpu_units == NULL)
1364*38fd1498Szrj fatal_at (info->loc, "invalid string `%s' in %s",
1365*38fd1498Szrj XSTR (def, 1), GET_RTX_NAME (GET_CODE (def)));
1366*38fd1498Szrj length += first_vect_length;
1367*38fd1498Szrj decl = XCREATENODEVAR (struct decl, (sizeof (struct decl)
1368*38fd1498Szrj + (length - 1) * sizeof (char *)));
1369*38fd1498Szrj decl->mode = dm_excl;
1370*38fd1498Szrj decl->pos = 0;
1371*38fd1498Szrj DECL_EXCL (decl)->all_names_num = length;
1372*38fd1498Szrj DECL_EXCL (decl)->first_list_length = first_vect_length;
1373*38fd1498Szrj for (i = 0; i < length; i++)
1374*38fd1498Szrj if (i < first_vect_length)
1375*38fd1498Szrj DECL_EXCL (decl)->names [i] = first_str_cpu_units [i];
1376*38fd1498Szrj else
1377*38fd1498Szrj DECL_EXCL (decl)->names [i]
1378*38fd1498Szrj = second_str_cpu_units [i - first_vect_length];
1379*38fd1498Szrj decls.safe_push (decl);
1380*38fd1498Szrj }
1381*38fd1498Szrj
1382*38fd1498Szrj /* Process a PRESENCE_SET, a FINAL_PRESENCE_SET, an ABSENCE_SET,
1383*38fd1498Szrj FINAL_ABSENCE_SET (it is depended on PRESENCE_P and FINAL_P).
1384*38fd1498Szrj
1385*38fd1498Szrj This gives information about a cpu unit reservation requirements.
1386*38fd1498Szrj We fill a struct unit_pattern_rel_decl with information used later
1387*38fd1498Szrj by `expand_automata'. */
1388*38fd1498Szrj static void
gen_presence_absence_set(md_rtx_info * info,int presence_p,int final_p)1389*38fd1498Szrj gen_presence_absence_set (md_rtx_info *info, int presence_p, int final_p)
1390*38fd1498Szrj {
1391*38fd1498Szrj decl_t decl;
1392*38fd1498Szrj char **str_cpu_units;
1393*38fd1498Szrj char **str_pattern_lists;
1394*38fd1498Szrj char ***str_patterns;
1395*38fd1498Szrj int cpu_units_length;
1396*38fd1498Szrj int length;
1397*38fd1498Szrj int patterns_length;
1398*38fd1498Szrj int i;
1399*38fd1498Szrj
1400*38fd1498Szrj rtx def = info->def;
1401*38fd1498Szrj str_cpu_units = get_str_vect (XSTR (def, 0), &cpu_units_length, ',',
1402*38fd1498Szrj FALSE);
1403*38fd1498Szrj if (str_cpu_units == NULL)
1404*38fd1498Szrj fatal_at (info->loc, "invalid string `%s' in %s",
1405*38fd1498Szrj XSTR (def, 0), GET_RTX_NAME (GET_CODE (def)));
1406*38fd1498Szrj str_pattern_lists = get_str_vect (XSTR (def, 1),
1407*38fd1498Szrj &patterns_length, ',', FALSE);
1408*38fd1498Szrj if (str_pattern_lists == NULL)
1409*38fd1498Szrj fatal_at (info->loc, "invalid string `%s' in %s",
1410*38fd1498Szrj XSTR (def, 1), GET_RTX_NAME (GET_CODE (def)));
1411*38fd1498Szrj str_patterns = XOBNEWVEC (&irp, char **, patterns_length);
1412*38fd1498Szrj for (i = 0; i < patterns_length; i++)
1413*38fd1498Szrj {
1414*38fd1498Szrj str_patterns [i] = get_str_vect (str_pattern_lists [i],
1415*38fd1498Szrj &length, ' ', FALSE);
1416*38fd1498Szrj gcc_assert (str_patterns [i]);
1417*38fd1498Szrj }
1418*38fd1498Szrj decl = XCREATENODE (struct decl);
1419*38fd1498Szrj decl->pos = 0;
1420*38fd1498Szrj if (presence_p)
1421*38fd1498Szrj {
1422*38fd1498Szrj decl->mode = dm_presence;
1423*38fd1498Szrj DECL_PRESENCE (decl)->names_num = cpu_units_length;
1424*38fd1498Szrj DECL_PRESENCE (decl)->names = str_cpu_units;
1425*38fd1498Szrj DECL_PRESENCE (decl)->patterns = str_patterns;
1426*38fd1498Szrj DECL_PRESENCE (decl)->patterns_num = patterns_length;
1427*38fd1498Szrj DECL_PRESENCE (decl)->final_p = final_p;
1428*38fd1498Szrj }
1429*38fd1498Szrj else
1430*38fd1498Szrj {
1431*38fd1498Szrj decl->mode = dm_absence;
1432*38fd1498Szrj DECL_ABSENCE (decl)->names_num = cpu_units_length;
1433*38fd1498Szrj DECL_ABSENCE (decl)->names = str_cpu_units;
1434*38fd1498Szrj DECL_ABSENCE (decl)->patterns = str_patterns;
1435*38fd1498Szrj DECL_ABSENCE (decl)->patterns_num = patterns_length;
1436*38fd1498Szrj DECL_ABSENCE (decl)->final_p = final_p;
1437*38fd1498Szrj }
1438*38fd1498Szrj decls.safe_push (decl);
1439*38fd1498Szrj }
1440*38fd1498Szrj
1441*38fd1498Szrj /* Process a PRESENCE_SET.
1442*38fd1498Szrj
1443*38fd1498Szrj This gives information about a cpu unit reservation requirements.
1444*38fd1498Szrj We fill a struct unit_pattern_rel_decl (presence) with information
1445*38fd1498Szrj used later by `expand_automata'. */
1446*38fd1498Szrj static void
gen_presence_set(md_rtx_info * info)1447*38fd1498Szrj gen_presence_set (md_rtx_info *info)
1448*38fd1498Szrj {
1449*38fd1498Szrj gen_presence_absence_set (info, TRUE, FALSE);
1450*38fd1498Szrj }
1451*38fd1498Szrj
1452*38fd1498Szrj /* Process a FINAL_PRESENCE_SET.
1453*38fd1498Szrj
1454*38fd1498Szrj This gives information about a cpu unit reservation requirements.
1455*38fd1498Szrj We fill a struct unit_pattern_rel_decl (presence) with information
1456*38fd1498Szrj used later by `expand_automata'. */
1457*38fd1498Szrj static void
gen_final_presence_set(md_rtx_info * info)1458*38fd1498Szrj gen_final_presence_set (md_rtx_info *info)
1459*38fd1498Szrj {
1460*38fd1498Szrj gen_presence_absence_set (info, TRUE, TRUE);
1461*38fd1498Szrj }
1462*38fd1498Szrj
1463*38fd1498Szrj /* Process an ABSENCE_SET.
1464*38fd1498Szrj
1465*38fd1498Szrj This gives information about a cpu unit reservation requirements.
1466*38fd1498Szrj We fill a struct unit_pattern_rel_decl (absence) with information
1467*38fd1498Szrj used later by `expand_automata'. */
1468*38fd1498Szrj static void
gen_absence_set(md_rtx_info * info)1469*38fd1498Szrj gen_absence_set (md_rtx_info *info)
1470*38fd1498Szrj {
1471*38fd1498Szrj gen_presence_absence_set (info, FALSE, FALSE);
1472*38fd1498Szrj }
1473*38fd1498Szrj
1474*38fd1498Szrj /* Process a FINAL_ABSENCE_SET.
1475*38fd1498Szrj
1476*38fd1498Szrj This gives information about a cpu unit reservation requirements.
1477*38fd1498Szrj We fill a struct unit_pattern_rel_decl (absence) with information
1478*38fd1498Szrj used later by `expand_automata'. */
1479*38fd1498Szrj static void
gen_final_absence_set(md_rtx_info * info)1480*38fd1498Szrj gen_final_absence_set (md_rtx_info *info)
1481*38fd1498Szrj {
1482*38fd1498Szrj gen_presence_absence_set (info, FALSE, TRUE);
1483*38fd1498Szrj }
1484*38fd1498Szrj
1485*38fd1498Szrj /* Process a DEFINE_AUTOMATON.
1486*38fd1498Szrj
1487*38fd1498Szrj This gives information about a finite state automaton used for
1488*38fd1498Szrj recognizing pipeline hazards. We fill a struct automaton_decl
1489*38fd1498Szrj with information used later by `expand_automata'. */
1490*38fd1498Szrj static void
gen_automaton(md_rtx_info * info)1491*38fd1498Szrj gen_automaton (md_rtx_info *info)
1492*38fd1498Szrj {
1493*38fd1498Szrj decl_t decl;
1494*38fd1498Szrj char **str_automata;
1495*38fd1498Szrj int vect_length;
1496*38fd1498Szrj int i;
1497*38fd1498Szrj
1498*38fd1498Szrj rtx def = info->def;
1499*38fd1498Szrj str_automata = get_str_vect (XSTR (def, 0), &vect_length, ',', FALSE);
1500*38fd1498Szrj if (str_automata == NULL)
1501*38fd1498Szrj fatal_at (info->loc, "invalid string `%s' in %s",
1502*38fd1498Szrj XSTR (def, 0), GET_RTX_NAME (GET_CODE (def)));
1503*38fd1498Szrj for (i = 0; i < vect_length; i++)
1504*38fd1498Szrj {
1505*38fd1498Szrj decl = XCREATENODE (struct decl);
1506*38fd1498Szrj decl->mode = dm_automaton;
1507*38fd1498Szrj decl->pos = 0;
1508*38fd1498Szrj DECL_AUTOMATON (decl)->name = check_name (str_automata [i], decl->pos);
1509*38fd1498Szrj decls.safe_push (decl);
1510*38fd1498Szrj }
1511*38fd1498Szrj }
1512*38fd1498Szrj
1513*38fd1498Szrj /* Process an AUTOMATA_OPTION.
1514*38fd1498Szrj
1515*38fd1498Szrj This gives information how to generate finite state automaton used
1516*38fd1498Szrj for recognizing pipeline hazards. */
1517*38fd1498Szrj static void
gen_automata_option(md_rtx_info * info)1518*38fd1498Szrj gen_automata_option (md_rtx_info *info)
1519*38fd1498Szrj {
1520*38fd1498Szrj const char *option = XSTR (info->def, 0);
1521*38fd1498Szrj if (strcmp (option, NO_MINIMIZATION_OPTION + 1) == 0)
1522*38fd1498Szrj no_minimization_flag = 1;
1523*38fd1498Szrj else if (strcmp (option, TIME_OPTION + 1) == 0)
1524*38fd1498Szrj time_flag = 1;
1525*38fd1498Szrj else if (strcmp (option, STATS_OPTION + 1) == 0)
1526*38fd1498Szrj stats_flag = 1;
1527*38fd1498Szrj else if (strcmp (option, V_OPTION + 1) == 0)
1528*38fd1498Szrj v_flag = 1;
1529*38fd1498Szrj else if (strcmp (option, W_OPTION + 1) == 0)
1530*38fd1498Szrj w_flag = 1;
1531*38fd1498Szrj else if (strcmp (option, NDFA_OPTION + 1) == 0)
1532*38fd1498Szrj ndfa_flag = 1;
1533*38fd1498Szrj else if (strcmp (option, COLLAPSE_OPTION + 1) == 0)
1534*38fd1498Szrj collapse_flag = 1;
1535*38fd1498Szrj else if (strcmp (option, NO_COMB_OPTION + 1) == 0)
1536*38fd1498Szrj no_comb_flag = 1;
1537*38fd1498Szrj else if (strcmp (option, PROGRESS_OPTION + 1) == 0)
1538*38fd1498Szrj progress_flag = 1;
1539*38fd1498Szrj else
1540*38fd1498Szrj fatal_at (info->loc, "invalid option `%s' in %s",
1541*38fd1498Szrj option, GET_RTX_NAME (GET_CODE (info->def)));
1542*38fd1498Szrj }
1543*38fd1498Szrj
1544*38fd1498Szrj /* Name in reservation to denote absence reservation. */
1545*38fd1498Szrj #define NOTHING_NAME "nothing"
1546*38fd1498Szrj
1547*38fd1498Szrj /* The following string contains original reservation string being
1548*38fd1498Szrj parsed. */
1549*38fd1498Szrj static const char *reserv_str;
1550*38fd1498Szrj
1551*38fd1498Szrj /* Parse an element in STR. */
1552*38fd1498Szrj static regexp_t
gen_regexp_el(const char * str)1553*38fd1498Szrj gen_regexp_el (const char *str)
1554*38fd1498Szrj {
1555*38fd1498Szrj regexp_t regexp;
1556*38fd1498Szrj char *dstr;
1557*38fd1498Szrj int len;
1558*38fd1498Szrj
1559*38fd1498Szrj if (*str == '(')
1560*38fd1498Szrj {
1561*38fd1498Szrj len = strlen (str);
1562*38fd1498Szrj if (str [len - 1] != ')')
1563*38fd1498Szrj fatal ("garbage after ) in reservation `%s'", reserv_str);
1564*38fd1498Szrj dstr = XALLOCAVAR (char, len - 1);
1565*38fd1498Szrj memcpy (dstr, str + 1, len - 2);
1566*38fd1498Szrj dstr [len-2] = '\0';
1567*38fd1498Szrj regexp = gen_regexp_sequence (dstr);
1568*38fd1498Szrj }
1569*38fd1498Szrj else if (strcmp (str, NOTHING_NAME) == 0)
1570*38fd1498Szrj {
1571*38fd1498Szrj regexp = XCREATENODE (struct regexp);
1572*38fd1498Szrj regexp->mode = rm_nothing;
1573*38fd1498Szrj }
1574*38fd1498Szrj else
1575*38fd1498Szrj {
1576*38fd1498Szrj regexp = XCREATENODE (struct regexp);
1577*38fd1498Szrj regexp->mode = rm_unit;
1578*38fd1498Szrj REGEXP_UNIT (regexp)->name = str;
1579*38fd1498Szrj }
1580*38fd1498Szrj return regexp;
1581*38fd1498Szrj }
1582*38fd1498Szrj
1583*38fd1498Szrj /* Parse construction `repeat' in STR. */
1584*38fd1498Szrj static regexp_t
gen_regexp_repeat(const char * str)1585*38fd1498Szrj gen_regexp_repeat (const char *str)
1586*38fd1498Szrj {
1587*38fd1498Szrj regexp_t regexp;
1588*38fd1498Szrj regexp_t repeat;
1589*38fd1498Szrj char **repeat_vect;
1590*38fd1498Szrj int els_num;
1591*38fd1498Szrj int i;
1592*38fd1498Szrj
1593*38fd1498Szrj repeat_vect = get_str_vect (str, &els_num, '*', TRUE);
1594*38fd1498Szrj if (repeat_vect == NULL)
1595*38fd1498Szrj fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1596*38fd1498Szrj if (els_num > 1)
1597*38fd1498Szrj {
1598*38fd1498Szrj regexp = gen_regexp_el (repeat_vect [0]);
1599*38fd1498Szrj for (i = 1; i < els_num; i++)
1600*38fd1498Szrj {
1601*38fd1498Szrj repeat = XCREATENODE (struct regexp);
1602*38fd1498Szrj repeat->mode = rm_repeat;
1603*38fd1498Szrj REGEXP_REPEAT (repeat)->regexp = regexp;
1604*38fd1498Szrj REGEXP_REPEAT (repeat)->repeat_num = atoi (repeat_vect [i]);
1605*38fd1498Szrj if (REGEXP_REPEAT (repeat)->repeat_num <= 1)
1606*38fd1498Szrj fatal ("repetition `%s' <= 1 in reservation `%s'",
1607*38fd1498Szrj str, reserv_str);
1608*38fd1498Szrj regexp = repeat;
1609*38fd1498Szrj }
1610*38fd1498Szrj return regexp;
1611*38fd1498Szrj }
1612*38fd1498Szrj else
1613*38fd1498Szrj return gen_regexp_el (repeat_vect[0]);
1614*38fd1498Szrj }
1615*38fd1498Szrj
1616*38fd1498Szrj /* Parse reservation STR which possibly contains separator '+'. */
1617*38fd1498Szrj static regexp_t
gen_regexp_allof(const char * str)1618*38fd1498Szrj gen_regexp_allof (const char *str)
1619*38fd1498Szrj {
1620*38fd1498Szrj regexp_t allof;
1621*38fd1498Szrj char **allof_vect;
1622*38fd1498Szrj int els_num;
1623*38fd1498Szrj int i;
1624*38fd1498Szrj
1625*38fd1498Szrj allof_vect = get_str_vect (str, &els_num, '+', TRUE);
1626*38fd1498Szrj if (allof_vect == NULL)
1627*38fd1498Szrj fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1628*38fd1498Szrj if (els_num > 1)
1629*38fd1498Szrj {
1630*38fd1498Szrj allof = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
1631*38fd1498Szrj + sizeof (regexp_t) * (els_num - 1));
1632*38fd1498Szrj allof->mode = rm_allof;
1633*38fd1498Szrj REGEXP_ALLOF (allof)->regexps_num = els_num;
1634*38fd1498Szrj for (i = 0; i < els_num; i++)
1635*38fd1498Szrj REGEXP_ALLOF (allof)->regexps [i] = gen_regexp_repeat (allof_vect [i]);
1636*38fd1498Szrj return allof;
1637*38fd1498Szrj }
1638*38fd1498Szrj else
1639*38fd1498Szrj return gen_regexp_repeat (allof_vect[0]);
1640*38fd1498Szrj }
1641*38fd1498Szrj
1642*38fd1498Szrj /* Parse reservation STR which possibly contains separator '|'. */
1643*38fd1498Szrj static regexp_t
gen_regexp_oneof(const char * str)1644*38fd1498Szrj gen_regexp_oneof (const char *str)
1645*38fd1498Szrj {
1646*38fd1498Szrj regexp_t oneof;
1647*38fd1498Szrj char **oneof_vect;
1648*38fd1498Szrj int els_num;
1649*38fd1498Szrj int i;
1650*38fd1498Szrj
1651*38fd1498Szrj oneof_vect = get_str_vect (str, &els_num, '|', TRUE);
1652*38fd1498Szrj if (oneof_vect == NULL)
1653*38fd1498Szrj fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1654*38fd1498Szrj if (els_num > 1)
1655*38fd1498Szrj {
1656*38fd1498Szrj oneof = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
1657*38fd1498Szrj + sizeof (regexp_t) * (els_num - 1));
1658*38fd1498Szrj oneof->mode = rm_oneof;
1659*38fd1498Szrj REGEXP_ONEOF (oneof)->regexps_num = els_num;
1660*38fd1498Szrj for (i = 0; i < els_num; i++)
1661*38fd1498Szrj REGEXP_ONEOF (oneof)->regexps [i] = gen_regexp_allof (oneof_vect [i]);
1662*38fd1498Szrj return oneof;
1663*38fd1498Szrj }
1664*38fd1498Szrj else
1665*38fd1498Szrj return gen_regexp_allof (oneof_vect[0]);
1666*38fd1498Szrj }
1667*38fd1498Szrj
1668*38fd1498Szrj /* Parse reservation STR which possibly contains separator ','. */
1669*38fd1498Szrj static regexp_t
gen_regexp_sequence(const char * str)1670*38fd1498Szrj gen_regexp_sequence (const char *str)
1671*38fd1498Szrj {
1672*38fd1498Szrj regexp_t sequence;
1673*38fd1498Szrj char **sequence_vect;
1674*38fd1498Szrj int els_num;
1675*38fd1498Szrj int i;
1676*38fd1498Szrj
1677*38fd1498Szrj sequence_vect = get_str_vect (str, &els_num, ',', TRUE);
1678*38fd1498Szrj if (els_num == -1)
1679*38fd1498Szrj fatal ("unbalanced parentheses in reservation `%s'", str);
1680*38fd1498Szrj if (sequence_vect == NULL)
1681*38fd1498Szrj fatal ("invalid reservation `%s'", str);
1682*38fd1498Szrj if (els_num > 1)
1683*38fd1498Szrj {
1684*38fd1498Szrj sequence = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
1685*38fd1498Szrj + sizeof (regexp_t) * (els_num - 1));
1686*38fd1498Szrj sequence->mode = rm_sequence;
1687*38fd1498Szrj REGEXP_SEQUENCE (sequence)->regexps_num = els_num;
1688*38fd1498Szrj for (i = 0; i < els_num; i++)
1689*38fd1498Szrj REGEXP_SEQUENCE (sequence)->regexps [i]
1690*38fd1498Szrj = gen_regexp_oneof (sequence_vect [i]);
1691*38fd1498Szrj return sequence;
1692*38fd1498Szrj }
1693*38fd1498Szrj else
1694*38fd1498Szrj return gen_regexp_oneof (sequence_vect[0]);
1695*38fd1498Szrj }
1696*38fd1498Szrj
1697*38fd1498Szrj /* Parse construction reservation STR. */
1698*38fd1498Szrj static regexp_t
gen_regexp(const char * str)1699*38fd1498Szrj gen_regexp (const char *str)
1700*38fd1498Szrj {
1701*38fd1498Szrj reserv_str = str;
1702*38fd1498Szrj return gen_regexp_sequence (str);
1703*38fd1498Szrj }
1704*38fd1498Szrj
1705*38fd1498Szrj /* Process a DEFINE_RESERVATION.
1706*38fd1498Szrj
1707*38fd1498Szrj This gives information about a reservation of cpu units. We fill
1708*38fd1498Szrj in a struct reserv_decl with information used later by
1709*38fd1498Szrj `expand_automata'. */
1710*38fd1498Szrj static void
gen_reserv(md_rtx_info * info)1711*38fd1498Szrj gen_reserv (md_rtx_info *info)
1712*38fd1498Szrj {
1713*38fd1498Szrj decl_t decl;
1714*38fd1498Szrj
1715*38fd1498Szrj rtx def = info->def;
1716*38fd1498Szrj decl = XCREATENODE (struct decl);
1717*38fd1498Szrj decl->mode = dm_reserv;
1718*38fd1498Szrj decl->pos = 0;
1719*38fd1498Szrj DECL_RESERV (decl)->name = check_name (XSTR (def, 0), decl->pos);
1720*38fd1498Szrj DECL_RESERV (decl)->regexp = gen_regexp (XSTR (def, 1));
1721*38fd1498Szrj decls.safe_push (decl);
1722*38fd1498Szrj }
1723*38fd1498Szrj
1724*38fd1498Szrj /* Process a DEFINE_INSN_RESERVATION.
1725*38fd1498Szrj
1726*38fd1498Szrj This gives information about the reservation of cpu units by an
1727*38fd1498Szrj insn. We fill a struct insn_reserv_decl with information used
1728*38fd1498Szrj later by `expand_automata'. */
1729*38fd1498Szrj static void
gen_insn_reserv(md_rtx_info * info)1730*38fd1498Szrj gen_insn_reserv (md_rtx_info *info)
1731*38fd1498Szrj {
1732*38fd1498Szrj decl_t decl;
1733*38fd1498Szrj
1734*38fd1498Szrj rtx def = info->def;
1735*38fd1498Szrj decl = XCREATENODE (struct decl);
1736*38fd1498Szrj decl->mode = dm_insn_reserv;
1737*38fd1498Szrj decl->pos = 0;
1738*38fd1498Szrj DECL_INSN_RESERV (decl)->name
1739*38fd1498Szrj = check_name (XSTR (def, 0), decl->pos);
1740*38fd1498Szrj DECL_INSN_RESERV (decl)->default_latency = XINT (def, 1);
1741*38fd1498Szrj DECL_INSN_RESERV (decl)->condexp = XEXP (def, 2);
1742*38fd1498Szrj DECL_INSN_RESERV (decl)->regexp = gen_regexp (XSTR (def, 3));
1743*38fd1498Szrj decls.safe_push (decl);
1744*38fd1498Szrj }
1745*38fd1498Szrj
1746*38fd1498Szrj
1747*38fd1498Szrj
1748*38fd1498Szrj /* The function evaluates hash value (0..UINT_MAX) of string. */
1749*38fd1498Szrj static unsigned
string_hash(const char * string)1750*38fd1498Szrj string_hash (const char *string)
1751*38fd1498Szrj {
1752*38fd1498Szrj unsigned result, i;
1753*38fd1498Szrj
1754*38fd1498Szrj for (result = i = 0;*string++ != '\0'; i++)
1755*38fd1498Szrj result += ((unsigned char) *string << (i % CHAR_BIT));
1756*38fd1498Szrj return result;
1757*38fd1498Szrj }
1758*38fd1498Szrj
1759*38fd1498Szrj
1760*38fd1498Szrj
1761*38fd1498Szrj /* This page contains abstract data `table of automaton declarations'.
1762*38fd1498Szrj Elements of the table is nodes representing automaton declarations.
1763*38fd1498Szrj Key of the table elements is name of given automaton. Remember
1764*38fd1498Szrj that automaton names have own space. */
1765*38fd1498Szrj
1766*38fd1498Szrj /* The function evaluates hash value of an automaton declaration. The
1767*38fd1498Szrj function is used by abstract data `hashtab'. The function returns
1768*38fd1498Szrj hash value (0..UINT_MAX) of given automaton declaration. */
1769*38fd1498Szrj static hashval_t
automaton_decl_hash(const void * automaton_decl)1770*38fd1498Szrj automaton_decl_hash (const void *automaton_decl)
1771*38fd1498Szrj {
1772*38fd1498Szrj const_decl_t const decl = (const_decl_t) automaton_decl;
1773*38fd1498Szrj
1774*38fd1498Szrj gcc_assert (decl->mode != dm_automaton
1775*38fd1498Szrj || DECL_AUTOMATON (decl)->name);
1776*38fd1498Szrj return string_hash (DECL_AUTOMATON (decl)->name);
1777*38fd1498Szrj }
1778*38fd1498Szrj
1779*38fd1498Szrj /* The function tests automaton declarations on equality of their
1780*38fd1498Szrj keys. The function is used by abstract data `hashtab'. The
1781*38fd1498Szrj function returns 1 if the declarations have the same key, 0
1782*38fd1498Szrj otherwise. */
1783*38fd1498Szrj static int
automaton_decl_eq_p(const void * automaton_decl_1,const void * automaton_decl_2)1784*38fd1498Szrj automaton_decl_eq_p (const void* automaton_decl_1,
1785*38fd1498Szrj const void* automaton_decl_2)
1786*38fd1498Szrj {
1787*38fd1498Szrj const_decl_t const decl1 = (const_decl_t) automaton_decl_1;
1788*38fd1498Szrj const_decl_t const decl2 = (const_decl_t) automaton_decl_2;
1789*38fd1498Szrj
1790*38fd1498Szrj gcc_assert (decl1->mode == dm_automaton
1791*38fd1498Szrj && DECL_AUTOMATON (decl1)->name
1792*38fd1498Szrj && decl2->mode == dm_automaton
1793*38fd1498Szrj && DECL_AUTOMATON (decl2)->name);
1794*38fd1498Szrj return strcmp (DECL_AUTOMATON (decl1)->name,
1795*38fd1498Szrj DECL_AUTOMATON (decl2)->name) == 0;
1796*38fd1498Szrj }
1797*38fd1498Szrj
1798*38fd1498Szrj /* The automaton declaration table itself is represented by the
1799*38fd1498Szrj following variable. */
1800*38fd1498Szrj static htab_t automaton_decl_table;
1801*38fd1498Szrj
1802*38fd1498Szrj /* The function inserts automaton declaration into the table. The
1803*38fd1498Szrj function does nothing if an automaton declaration with the same key
1804*38fd1498Szrj exists already in the table. The function returns automaton
1805*38fd1498Szrj declaration node in the table with the same key as given automaton
1806*38fd1498Szrj declaration node. */
1807*38fd1498Szrj static decl_t
insert_automaton_decl(decl_t automaton_decl)1808*38fd1498Szrj insert_automaton_decl (decl_t automaton_decl)
1809*38fd1498Szrj {
1810*38fd1498Szrj void **entry_ptr;
1811*38fd1498Szrj
1812*38fd1498Szrj entry_ptr = htab_find_slot (automaton_decl_table, automaton_decl, INSERT);
1813*38fd1498Szrj if (*entry_ptr == NULL)
1814*38fd1498Szrj *entry_ptr = (void *) automaton_decl;
1815*38fd1498Szrj return (decl_t) *entry_ptr;
1816*38fd1498Szrj }
1817*38fd1498Szrj
1818*38fd1498Szrj /* The following variable value is node representing automaton
1819*38fd1498Szrj declaration. The node used for searching automaton declaration
1820*38fd1498Szrj with given name. */
1821*38fd1498Szrj static struct decl work_automaton_decl;
1822*38fd1498Szrj
1823*38fd1498Szrj /* The function searches for automaton declaration in the table with
1824*38fd1498Szrj the same key as node representing name of the automaton
1825*38fd1498Szrj declaration. The function returns node found in the table, NULL if
1826*38fd1498Szrj such node does not exist in the table. */
1827*38fd1498Szrj static decl_t
find_automaton_decl(const char * name)1828*38fd1498Szrj find_automaton_decl (const char *name)
1829*38fd1498Szrj {
1830*38fd1498Szrj void *entry;
1831*38fd1498Szrj
1832*38fd1498Szrj work_automaton_decl.mode = dm_automaton;
1833*38fd1498Szrj DECL_AUTOMATON (&work_automaton_decl)->name = name;
1834*38fd1498Szrj entry = htab_find (automaton_decl_table, &work_automaton_decl);
1835*38fd1498Szrj return (decl_t) entry;
1836*38fd1498Szrj }
1837*38fd1498Szrj
1838*38fd1498Szrj /* The function creates empty automaton declaration table and node
1839*38fd1498Szrj representing automaton declaration and used for searching automaton
1840*38fd1498Szrj declaration with given name. The function must be called only once
1841*38fd1498Szrj before any work with the automaton declaration table. */
1842*38fd1498Szrj static void
initiate_automaton_decl_table(void)1843*38fd1498Szrj initiate_automaton_decl_table (void)
1844*38fd1498Szrj {
1845*38fd1498Szrj work_automaton_decl.mode = dm_automaton;
1846*38fd1498Szrj automaton_decl_table = htab_create (10, automaton_decl_hash,
1847*38fd1498Szrj automaton_decl_eq_p, (htab_del) 0);
1848*38fd1498Szrj }
1849*38fd1498Szrj
1850*38fd1498Szrj /* The function deletes the automaton declaration table. Only call of
1851*38fd1498Szrj function `initiate_automaton_decl_table' is possible immediately
1852*38fd1498Szrj after this function call. */
1853*38fd1498Szrj static void
finish_automaton_decl_table(void)1854*38fd1498Szrj finish_automaton_decl_table (void)
1855*38fd1498Szrj {
1856*38fd1498Szrj htab_delete (automaton_decl_table);
1857*38fd1498Szrj }
1858*38fd1498Szrj
1859*38fd1498Szrj
1860*38fd1498Szrj
1861*38fd1498Szrj /* This page contains abstract data `table of insn declarations'.
1862*38fd1498Szrj Elements of the table is nodes representing insn declarations. Key
1863*38fd1498Szrj of the table elements is name of given insn (in corresponding
1864*38fd1498Szrj define_insn_reservation). Remember that insn names have own
1865*38fd1498Szrj space. */
1866*38fd1498Szrj
1867*38fd1498Szrj /* The function evaluates hash value of an insn declaration. The
1868*38fd1498Szrj function is used by abstract data `hashtab'. The function returns
1869*38fd1498Szrj hash value (0..UINT_MAX) of given insn declaration. */
1870*38fd1498Szrj static hashval_t
insn_decl_hash(const void * insn_decl)1871*38fd1498Szrj insn_decl_hash (const void *insn_decl)
1872*38fd1498Szrj {
1873*38fd1498Szrj const_decl_t const decl = (const_decl_t) insn_decl;
1874*38fd1498Szrj
1875*38fd1498Szrj gcc_assert (decl->mode == dm_insn_reserv
1876*38fd1498Szrj && DECL_INSN_RESERV (decl)->name);
1877*38fd1498Szrj return string_hash (DECL_INSN_RESERV (decl)->name);
1878*38fd1498Szrj }
1879*38fd1498Szrj
1880*38fd1498Szrj /* The function tests insn declarations on equality of their keys.
1881*38fd1498Szrj The function is used by abstract data `hashtab'. The function
1882*38fd1498Szrj returns 1 if declarations have the same key, 0 otherwise. */
1883*38fd1498Szrj static int
insn_decl_eq_p(const void * insn_decl_1,const void * insn_decl_2)1884*38fd1498Szrj insn_decl_eq_p (const void *insn_decl_1, const void *insn_decl_2)
1885*38fd1498Szrj {
1886*38fd1498Szrj const_decl_t const decl1 = (const_decl_t) insn_decl_1;
1887*38fd1498Szrj const_decl_t const decl2 = (const_decl_t) insn_decl_2;
1888*38fd1498Szrj
1889*38fd1498Szrj gcc_assert (decl1->mode == dm_insn_reserv
1890*38fd1498Szrj && DECL_INSN_RESERV (decl1)->name
1891*38fd1498Szrj && decl2->mode == dm_insn_reserv
1892*38fd1498Szrj && DECL_INSN_RESERV (decl2)->name);
1893*38fd1498Szrj return strcmp (DECL_INSN_RESERV (decl1)->name,
1894*38fd1498Szrj DECL_INSN_RESERV (decl2)->name) == 0;
1895*38fd1498Szrj }
1896*38fd1498Szrj
1897*38fd1498Szrj /* The insn declaration table itself is represented by the following
1898*38fd1498Szrj variable. The table does not contain insn reservation
1899*38fd1498Szrj declarations. */
1900*38fd1498Szrj static htab_t insn_decl_table;
1901*38fd1498Szrj
1902*38fd1498Szrj /* The function inserts insn declaration into the table. The function
1903*38fd1498Szrj does nothing if an insn declaration with the same key exists
1904*38fd1498Szrj already in the table. The function returns insn declaration node
1905*38fd1498Szrj in the table with the same key as given insn declaration node. */
1906*38fd1498Szrj static decl_t
insert_insn_decl(decl_t insn_decl)1907*38fd1498Szrj insert_insn_decl (decl_t insn_decl)
1908*38fd1498Szrj {
1909*38fd1498Szrj void **entry_ptr;
1910*38fd1498Szrj
1911*38fd1498Szrj entry_ptr = htab_find_slot (insn_decl_table, insn_decl, INSERT);
1912*38fd1498Szrj if (*entry_ptr == NULL)
1913*38fd1498Szrj *entry_ptr = (void *) insn_decl;
1914*38fd1498Szrj return (decl_t) *entry_ptr;
1915*38fd1498Szrj }
1916*38fd1498Szrj
1917*38fd1498Szrj /* The following variable value is node representing insn reservation
1918*38fd1498Szrj declaration. The node used for searching insn reservation
1919*38fd1498Szrj declaration with given name. */
1920*38fd1498Szrj static struct decl work_insn_decl;
1921*38fd1498Szrj
1922*38fd1498Szrj /* The function searches for insn reservation declaration in the table
1923*38fd1498Szrj with the same key as node representing name of the insn reservation
1924*38fd1498Szrj declaration. The function returns node found in the table, NULL if
1925*38fd1498Szrj such node does not exist in the table. */
1926*38fd1498Szrj static decl_t
find_insn_decl(const char * name)1927*38fd1498Szrj find_insn_decl (const char *name)
1928*38fd1498Szrj {
1929*38fd1498Szrj void *entry;
1930*38fd1498Szrj
1931*38fd1498Szrj work_insn_decl.mode = dm_insn_reserv;
1932*38fd1498Szrj DECL_INSN_RESERV (&work_insn_decl)->name = name;
1933*38fd1498Szrj entry = htab_find (insn_decl_table, &work_insn_decl);
1934*38fd1498Szrj return (decl_t) entry;
1935*38fd1498Szrj }
1936*38fd1498Szrj
1937*38fd1498Szrj /* The function creates empty insn declaration table and node
1938*38fd1498Szrj representing insn declaration and used for searching insn
1939*38fd1498Szrj declaration with given name. The function must be called only once
1940*38fd1498Szrj before any work with the insn declaration table. */
1941*38fd1498Szrj static void
initiate_insn_decl_table(void)1942*38fd1498Szrj initiate_insn_decl_table (void)
1943*38fd1498Szrj {
1944*38fd1498Szrj work_insn_decl.mode = dm_insn_reserv;
1945*38fd1498Szrj insn_decl_table = htab_create (10, insn_decl_hash, insn_decl_eq_p,
1946*38fd1498Szrj (htab_del) 0);
1947*38fd1498Szrj }
1948*38fd1498Szrj
1949*38fd1498Szrj /* The function deletes the insn declaration table. Only call of
1950*38fd1498Szrj function `initiate_insn_decl_table' is possible immediately after
1951*38fd1498Szrj this function call. */
1952*38fd1498Szrj static void
finish_insn_decl_table(void)1953*38fd1498Szrj finish_insn_decl_table (void)
1954*38fd1498Szrj {
1955*38fd1498Szrj htab_delete (insn_decl_table);
1956*38fd1498Szrj }
1957*38fd1498Szrj
1958*38fd1498Szrj
1959*38fd1498Szrj
1960*38fd1498Szrj /* This page contains abstract data `table of declarations'. Elements
1961*38fd1498Szrj of the table is nodes representing declarations (of units and
1962*38fd1498Szrj reservations). Key of the table elements is names of given
1963*38fd1498Szrj declarations. */
1964*38fd1498Szrj
1965*38fd1498Szrj /* The function evaluates hash value of a declaration. The function
1966*38fd1498Szrj is used by abstract data `hashtab'. The function returns hash
1967*38fd1498Szrj value (0..UINT_MAX) of given declaration. */
1968*38fd1498Szrj static hashval_t
decl_hash(const void * decl)1969*38fd1498Szrj decl_hash (const void *decl)
1970*38fd1498Szrj {
1971*38fd1498Szrj const_decl_t const d = (const_decl_t) decl;
1972*38fd1498Szrj
1973*38fd1498Szrj gcc_assert ((d->mode == dm_unit && DECL_UNIT (d)->name)
1974*38fd1498Szrj || (d->mode == dm_reserv && DECL_RESERV (d)->name));
1975*38fd1498Szrj return string_hash (d->mode == dm_unit
1976*38fd1498Szrj ? DECL_UNIT (d)->name : DECL_RESERV (d)->name);
1977*38fd1498Szrj }
1978*38fd1498Szrj
1979*38fd1498Szrj /* The function tests declarations on equality of their keys. The
1980*38fd1498Szrj function is used by abstract data 'hashtab'. The function
1981*38fd1498Szrj returns 1 if the declarations have the same key, 0 otherwise. */
1982*38fd1498Szrj static int
decl_eq_p(const void * decl_1,const void * decl_2)1983*38fd1498Szrj decl_eq_p (const void *decl_1, const void *decl_2)
1984*38fd1498Szrj {
1985*38fd1498Szrj const_decl_t const d1 = (const_decl_t) decl_1;
1986*38fd1498Szrj const_decl_t const d2 = (const_decl_t) decl_2;
1987*38fd1498Szrj
1988*38fd1498Szrj gcc_assert ((d1->mode == dm_unit && DECL_UNIT (d1)->name)
1989*38fd1498Szrj || (d1->mode == dm_reserv && DECL_RESERV (d1)->name));
1990*38fd1498Szrj gcc_assert ((d2->mode == dm_unit && DECL_UNIT (d2)->name)
1991*38fd1498Szrj || (d2->mode == dm_reserv && DECL_RESERV (d2)->name));
1992*38fd1498Szrj return strcmp ((d1->mode == dm_unit
1993*38fd1498Szrj ? DECL_UNIT (d1)->name : DECL_RESERV (d1)->name),
1994*38fd1498Szrj (d2->mode == dm_unit
1995*38fd1498Szrj ? DECL_UNIT (d2)->name : DECL_RESERV (d2)->name)) == 0;
1996*38fd1498Szrj }
1997*38fd1498Szrj
1998*38fd1498Szrj /* The declaration table itself is represented by the following
1999*38fd1498Szrj variable. */
2000*38fd1498Szrj static htab_t decl_table;
2001*38fd1498Szrj
2002*38fd1498Szrj /* The function inserts declaration into the table. The function does
2003*38fd1498Szrj nothing if a declaration with the same key exists already in the
2004*38fd1498Szrj table. The function returns declaration node in the table with the
2005*38fd1498Szrj same key as given declaration node. */
2006*38fd1498Szrj
2007*38fd1498Szrj static decl_t
insert_decl(decl_t decl)2008*38fd1498Szrj insert_decl (decl_t decl)
2009*38fd1498Szrj {
2010*38fd1498Szrj void **entry_ptr;
2011*38fd1498Szrj
2012*38fd1498Szrj entry_ptr = htab_find_slot (decl_table, decl, INSERT);
2013*38fd1498Szrj if (*entry_ptr == NULL)
2014*38fd1498Szrj *entry_ptr = (void *) decl;
2015*38fd1498Szrj return (decl_t) *entry_ptr;
2016*38fd1498Szrj }
2017*38fd1498Szrj
2018*38fd1498Szrj /* The following variable value is node representing declaration. The
2019*38fd1498Szrj node used for searching declaration with given name. */
2020*38fd1498Szrj static struct decl work_decl;
2021*38fd1498Szrj
2022*38fd1498Szrj /* The function searches for declaration in the table with the same
2023*38fd1498Szrj key as node representing name of the declaration. The function
2024*38fd1498Szrj returns node found in the table, NULL if such node does not exist
2025*38fd1498Szrj in the table. */
2026*38fd1498Szrj static decl_t
find_decl(const char * name)2027*38fd1498Szrj find_decl (const char *name)
2028*38fd1498Szrj {
2029*38fd1498Szrj void *entry;
2030*38fd1498Szrj
2031*38fd1498Szrj work_decl.mode = dm_unit;
2032*38fd1498Szrj DECL_UNIT (&work_decl)->name = name;
2033*38fd1498Szrj entry = htab_find (decl_table, &work_decl);
2034*38fd1498Szrj return (decl_t) entry;
2035*38fd1498Szrj }
2036*38fd1498Szrj
2037*38fd1498Szrj /* The function creates empty declaration table and node representing
2038*38fd1498Szrj declaration and used for searching declaration with given name.
2039*38fd1498Szrj The function must be called only once before any work with the
2040*38fd1498Szrj declaration table. */
2041*38fd1498Szrj static void
initiate_decl_table(void)2042*38fd1498Szrj initiate_decl_table (void)
2043*38fd1498Szrj {
2044*38fd1498Szrj work_decl.mode = dm_unit;
2045*38fd1498Szrj decl_table = htab_create (10, decl_hash, decl_eq_p, (htab_del) 0);
2046*38fd1498Szrj }
2047*38fd1498Szrj
2048*38fd1498Szrj /* The function deletes the declaration table. Only call of function
2049*38fd1498Szrj `initiate_declaration_table' is possible immediately after this
2050*38fd1498Szrj function call. */
2051*38fd1498Szrj static void
finish_decl_table(void)2052*38fd1498Szrj finish_decl_table (void)
2053*38fd1498Szrj {
2054*38fd1498Szrj htab_delete (decl_table);
2055*38fd1498Szrj }
2056*38fd1498Szrj
2057*38fd1498Szrj
2058*38fd1498Szrj
2059*38fd1498Szrj /* This page contains checker of pipeline hazard description. */
2060*38fd1498Szrj
2061*38fd1498Szrj /* Checking NAMES in an exclusion clause vector and returning formed
2062*38fd1498Szrj unit_set_el_list. */
2063*38fd1498Szrj static unit_set_el_t
process_excls(char ** names,int num,pos_t excl_pos ATTRIBUTE_UNUSED)2064*38fd1498Szrj process_excls (char **names, int num, pos_t excl_pos ATTRIBUTE_UNUSED)
2065*38fd1498Szrj {
2066*38fd1498Szrj unit_set_el_t el_list;
2067*38fd1498Szrj unit_set_el_t last_el;
2068*38fd1498Szrj unit_set_el_t new_el;
2069*38fd1498Szrj decl_t decl_in_table;
2070*38fd1498Szrj int i;
2071*38fd1498Szrj
2072*38fd1498Szrj el_list = NULL;
2073*38fd1498Szrj last_el = NULL;
2074*38fd1498Szrj for (i = 0; i < num; i++)
2075*38fd1498Szrj {
2076*38fd1498Szrj decl_in_table = find_decl (names [i]);
2077*38fd1498Szrj if (decl_in_table == NULL)
2078*38fd1498Szrj error ("unit `%s' in exclusion is not declared", names [i]);
2079*38fd1498Szrj else if (decl_in_table->mode != dm_unit)
2080*38fd1498Szrj error ("`%s' in exclusion is not unit", names [i]);
2081*38fd1498Szrj else
2082*38fd1498Szrj {
2083*38fd1498Szrj new_el = XCREATENODE (struct unit_set_el);
2084*38fd1498Szrj new_el->unit_decl = DECL_UNIT (decl_in_table);
2085*38fd1498Szrj new_el->next_unit_set_el = NULL;
2086*38fd1498Szrj if (last_el == NULL)
2087*38fd1498Szrj el_list = last_el = new_el;
2088*38fd1498Szrj else
2089*38fd1498Szrj {
2090*38fd1498Szrj last_el->next_unit_set_el = new_el;
2091*38fd1498Szrj last_el = last_el->next_unit_set_el;
2092*38fd1498Szrj }
2093*38fd1498Szrj }
2094*38fd1498Szrj }
2095*38fd1498Szrj return el_list;
2096*38fd1498Szrj }
2097*38fd1498Szrj
2098*38fd1498Szrj /* The function adds each element from SOURCE_LIST to the exclusion
2099*38fd1498Szrj list of the each element from DEST_LIST. Checking situation "unit
2100*38fd1498Szrj excludes itself". */
2101*38fd1498Szrj static void
add_excls(unit_set_el_t dest_list,unit_set_el_t source_list,pos_t excl_pos ATTRIBUTE_UNUSED)2102*38fd1498Szrj add_excls (unit_set_el_t dest_list, unit_set_el_t source_list,
2103*38fd1498Szrj pos_t excl_pos ATTRIBUTE_UNUSED)
2104*38fd1498Szrj {
2105*38fd1498Szrj unit_set_el_t dst;
2106*38fd1498Szrj unit_set_el_t src;
2107*38fd1498Szrj unit_set_el_t curr_el;
2108*38fd1498Szrj unit_set_el_t prev_el;
2109*38fd1498Szrj unit_set_el_t copy;
2110*38fd1498Szrj
2111*38fd1498Szrj for (dst = dest_list; dst != NULL; dst = dst->next_unit_set_el)
2112*38fd1498Szrj for (src = source_list; src != NULL; src = src->next_unit_set_el)
2113*38fd1498Szrj {
2114*38fd1498Szrj if (dst->unit_decl == src->unit_decl)
2115*38fd1498Szrj {
2116*38fd1498Szrj error ("unit `%s' excludes itself", src->unit_decl->name);
2117*38fd1498Szrj continue;
2118*38fd1498Szrj }
2119*38fd1498Szrj if (dst->unit_decl->automaton_name != NULL
2120*38fd1498Szrj && src->unit_decl->automaton_name != NULL
2121*38fd1498Szrj && strcmp (dst->unit_decl->automaton_name,
2122*38fd1498Szrj src->unit_decl->automaton_name) != 0)
2123*38fd1498Szrj {
2124*38fd1498Szrj error ("units `%s' and `%s' in exclusion set belong to different automata",
2125*38fd1498Szrj src->unit_decl->name, dst->unit_decl->name);
2126*38fd1498Szrj continue;
2127*38fd1498Szrj }
2128*38fd1498Szrj for (curr_el = dst->unit_decl->excl_list, prev_el = NULL;
2129*38fd1498Szrj curr_el != NULL;
2130*38fd1498Szrj prev_el = curr_el, curr_el = curr_el->next_unit_set_el)
2131*38fd1498Szrj if (curr_el->unit_decl == src->unit_decl)
2132*38fd1498Szrj break;
2133*38fd1498Szrj if (curr_el == NULL)
2134*38fd1498Szrj {
2135*38fd1498Szrj /* Element not found - insert. */
2136*38fd1498Szrj copy = XCOPYNODE (struct unit_set_el, src);
2137*38fd1498Szrj copy->next_unit_set_el = NULL;
2138*38fd1498Szrj if (prev_el == NULL)
2139*38fd1498Szrj dst->unit_decl->excl_list = copy;
2140*38fd1498Szrj else
2141*38fd1498Szrj prev_el->next_unit_set_el = copy;
2142*38fd1498Szrj }
2143*38fd1498Szrj }
2144*38fd1498Szrj }
2145*38fd1498Szrj
2146*38fd1498Szrj /* Checking NAMES in presence/absence clause and returning the
2147*38fd1498Szrj formed unit_set_el_list. The function is called only after
2148*38fd1498Szrj processing all exclusion sets. */
2149*38fd1498Szrj static unit_set_el_t
process_presence_absence_names(char ** names,int num,pos_t req_pos ATTRIBUTE_UNUSED,int presence_p,int final_p)2150*38fd1498Szrj process_presence_absence_names (char **names, int num,
2151*38fd1498Szrj pos_t req_pos ATTRIBUTE_UNUSED,
2152*38fd1498Szrj int presence_p, int final_p)
2153*38fd1498Szrj {
2154*38fd1498Szrj unit_set_el_t el_list;
2155*38fd1498Szrj unit_set_el_t last_el;
2156*38fd1498Szrj unit_set_el_t new_el;
2157*38fd1498Szrj decl_t decl_in_table;
2158*38fd1498Szrj int i;
2159*38fd1498Szrj
2160*38fd1498Szrj el_list = NULL;
2161*38fd1498Szrj last_el = NULL;
2162*38fd1498Szrj for (i = 0; i < num; i++)
2163*38fd1498Szrj {
2164*38fd1498Szrj decl_in_table = find_decl (names [i]);
2165*38fd1498Szrj if (decl_in_table == NULL)
2166*38fd1498Szrj error ((presence_p
2167*38fd1498Szrj ? (final_p
2168*38fd1498Szrj ? "unit `%s' in final presence set is not declared"
2169*38fd1498Szrj : "unit `%s' in presence set is not declared")
2170*38fd1498Szrj : (final_p
2171*38fd1498Szrj ? "unit `%s' in final absence set is not declared"
2172*38fd1498Szrj : "unit `%s' in absence set is not declared")), names [i]);
2173*38fd1498Szrj else if (decl_in_table->mode != dm_unit)
2174*38fd1498Szrj error ((presence_p
2175*38fd1498Szrj ? (final_p
2176*38fd1498Szrj ? "`%s' in final presence set is not unit"
2177*38fd1498Szrj : "`%s' in presence set is not unit")
2178*38fd1498Szrj : (final_p
2179*38fd1498Szrj ? "`%s' in final absence set is not unit"
2180*38fd1498Szrj : "`%s' in absence set is not unit")), names [i]);
2181*38fd1498Szrj else
2182*38fd1498Szrj {
2183*38fd1498Szrj new_el = XCREATENODE (struct unit_set_el);
2184*38fd1498Szrj new_el->unit_decl = DECL_UNIT (decl_in_table);
2185*38fd1498Szrj new_el->next_unit_set_el = NULL;
2186*38fd1498Szrj if (last_el == NULL)
2187*38fd1498Szrj el_list = last_el = new_el;
2188*38fd1498Szrj else
2189*38fd1498Szrj {
2190*38fd1498Szrj last_el->next_unit_set_el = new_el;
2191*38fd1498Szrj last_el = last_el->next_unit_set_el;
2192*38fd1498Szrj }
2193*38fd1498Szrj }
2194*38fd1498Szrj }
2195*38fd1498Szrj return el_list;
2196*38fd1498Szrj }
2197*38fd1498Szrj
2198*38fd1498Szrj /* Checking NAMES in patterns of a presence/absence clause and
2199*38fd1498Szrj returning the formed pattern_set_el_list. The function is called
2200*38fd1498Szrj only after processing all exclusion sets. */
2201*38fd1498Szrj static pattern_set_el_t
process_presence_absence_patterns(char *** patterns,int num,pos_t req_pos ATTRIBUTE_UNUSED,int presence_p,int final_p)2202*38fd1498Szrj process_presence_absence_patterns (char ***patterns, int num,
2203*38fd1498Szrj pos_t req_pos ATTRIBUTE_UNUSED,
2204*38fd1498Szrj int presence_p, int final_p)
2205*38fd1498Szrj {
2206*38fd1498Szrj pattern_set_el_t el_list;
2207*38fd1498Szrj pattern_set_el_t last_el;
2208*38fd1498Szrj pattern_set_el_t new_el;
2209*38fd1498Szrj decl_t decl_in_table;
2210*38fd1498Szrj int i, j;
2211*38fd1498Szrj
2212*38fd1498Szrj el_list = NULL;
2213*38fd1498Szrj last_el = NULL;
2214*38fd1498Szrj for (i = 0; i < num; i++)
2215*38fd1498Szrj {
2216*38fd1498Szrj for (j = 0; patterns [i] [j] != NULL; j++)
2217*38fd1498Szrj ;
2218*38fd1498Szrj new_el = XCREATENODEVAR (struct pattern_set_el,
2219*38fd1498Szrj sizeof (struct pattern_set_el)
2220*38fd1498Szrj + sizeof (struct unit_decl *) * j);
2221*38fd1498Szrj new_el->unit_decls
2222*38fd1498Szrj = (struct unit_decl **) ((char *) new_el
2223*38fd1498Szrj + sizeof (struct pattern_set_el));
2224*38fd1498Szrj new_el->next_pattern_set_el = NULL;
2225*38fd1498Szrj if (last_el == NULL)
2226*38fd1498Szrj el_list = last_el = new_el;
2227*38fd1498Szrj else
2228*38fd1498Szrj {
2229*38fd1498Szrj last_el->next_pattern_set_el = new_el;
2230*38fd1498Szrj last_el = last_el->next_pattern_set_el;
2231*38fd1498Szrj }
2232*38fd1498Szrj new_el->units_num = 0;
2233*38fd1498Szrj for (j = 0; patterns [i] [j] != NULL; j++)
2234*38fd1498Szrj {
2235*38fd1498Szrj decl_in_table = find_decl (patterns [i] [j]);
2236*38fd1498Szrj if (decl_in_table == NULL)
2237*38fd1498Szrj error ((presence_p
2238*38fd1498Szrj ? (final_p
2239*38fd1498Szrj ? "unit `%s' in final presence set is not declared"
2240*38fd1498Szrj : "unit `%s' in presence set is not declared")
2241*38fd1498Szrj : (final_p
2242*38fd1498Szrj ? "unit `%s' in final absence set is not declared"
2243*38fd1498Szrj : "unit `%s' in absence set is not declared")),
2244*38fd1498Szrj patterns [i] [j]);
2245*38fd1498Szrj else if (decl_in_table->mode != dm_unit)
2246*38fd1498Szrj error ((presence_p
2247*38fd1498Szrj ? (final_p
2248*38fd1498Szrj ? "`%s' in final presence set is not unit"
2249*38fd1498Szrj : "`%s' in presence set is not unit")
2250*38fd1498Szrj : (final_p
2251*38fd1498Szrj ? "`%s' in final absence set is not unit"
2252*38fd1498Szrj : "`%s' in absence set is not unit")),
2253*38fd1498Szrj patterns [i] [j]);
2254*38fd1498Szrj else
2255*38fd1498Szrj {
2256*38fd1498Szrj new_el->unit_decls [new_el->units_num]
2257*38fd1498Szrj = DECL_UNIT (decl_in_table);
2258*38fd1498Szrj new_el->units_num++;
2259*38fd1498Szrj }
2260*38fd1498Szrj }
2261*38fd1498Szrj }
2262*38fd1498Szrj return el_list;
2263*38fd1498Szrj }
2264*38fd1498Szrj
2265*38fd1498Szrj /* The function adds each element from PATTERN_LIST to presence (if
2266*38fd1498Szrj PRESENCE_P) or absence list of the each element from DEST_LIST.
2267*38fd1498Szrj Checking situations "unit requires own absence", and "unit excludes
2268*38fd1498Szrj and requires presence of ...", "unit requires absence and presence
2269*38fd1498Szrj of ...", "units in (final) presence set belong to different
2270*38fd1498Szrj automata", and "units in (final) absence set belong to different
2271*38fd1498Szrj automata". Remember that we process absence sets only after all
2272*38fd1498Szrj presence sets. */
2273*38fd1498Szrj static void
add_presence_absence(unit_set_el_t dest_list,pattern_set_el_t pattern_list,pos_t req_pos ATTRIBUTE_UNUSED,int presence_p,int final_p)2274*38fd1498Szrj add_presence_absence (unit_set_el_t dest_list,
2275*38fd1498Szrj pattern_set_el_t pattern_list,
2276*38fd1498Szrj pos_t req_pos ATTRIBUTE_UNUSED,
2277*38fd1498Szrj int presence_p, int final_p)
2278*38fd1498Szrj {
2279*38fd1498Szrj unit_set_el_t dst;
2280*38fd1498Szrj pattern_set_el_t pat;
2281*38fd1498Szrj struct unit_decl *unit;
2282*38fd1498Szrj unit_set_el_t curr_excl_el;
2283*38fd1498Szrj pattern_set_el_t curr_pat_el;
2284*38fd1498Szrj pattern_set_el_t prev_el;
2285*38fd1498Szrj pattern_set_el_t copy;
2286*38fd1498Szrj int i;
2287*38fd1498Szrj int no_error_flag;
2288*38fd1498Szrj
2289*38fd1498Szrj for (dst = dest_list; dst != NULL; dst = dst->next_unit_set_el)
2290*38fd1498Szrj for (pat = pattern_list; pat != NULL; pat = pat->next_pattern_set_el)
2291*38fd1498Szrj {
2292*38fd1498Szrj for (i = 0; i < pat->units_num; i++)
2293*38fd1498Szrj {
2294*38fd1498Szrj unit = pat->unit_decls [i];
2295*38fd1498Szrj if (dst->unit_decl == unit && pat->units_num == 1 && !presence_p)
2296*38fd1498Szrj {
2297*38fd1498Szrj error ("unit `%s' requires own absence", unit->name);
2298*38fd1498Szrj continue;
2299*38fd1498Szrj }
2300*38fd1498Szrj if (dst->unit_decl->automaton_name != NULL
2301*38fd1498Szrj && unit->automaton_name != NULL
2302*38fd1498Szrj && strcmp (dst->unit_decl->automaton_name,
2303*38fd1498Szrj unit->automaton_name) != 0)
2304*38fd1498Szrj {
2305*38fd1498Szrj error ((presence_p
2306*38fd1498Szrj ? (final_p
2307*38fd1498Szrj ? "units `%s' and `%s' in final presence set belong to different automata"
2308*38fd1498Szrj : "units `%s' and `%s' in presence set belong to different automata")
2309*38fd1498Szrj : (final_p
2310*38fd1498Szrj ? "units `%s' and `%s' in final absence set belong to different automata"
2311*38fd1498Szrj : "units `%s' and `%s' in absence set belong to different automata")),
2312*38fd1498Szrj unit->name, dst->unit_decl->name);
2313*38fd1498Szrj continue;
2314*38fd1498Szrj }
2315*38fd1498Szrj no_error_flag = 1;
2316*38fd1498Szrj if (presence_p)
2317*38fd1498Szrj for (curr_excl_el = dst->unit_decl->excl_list;
2318*38fd1498Szrj curr_excl_el != NULL;
2319*38fd1498Szrj curr_excl_el = curr_excl_el->next_unit_set_el)
2320*38fd1498Szrj {
2321*38fd1498Szrj if (unit == curr_excl_el->unit_decl && pat->units_num == 1)
2322*38fd1498Szrj {
2323*38fd1498Szrj if (!w_flag)
2324*38fd1498Szrj {
2325*38fd1498Szrj error ("unit `%s' excludes and requires presence of `%s'",
2326*38fd1498Szrj dst->unit_decl->name, unit->name);
2327*38fd1498Szrj no_error_flag = 0;
2328*38fd1498Szrj }
2329*38fd1498Szrj else
2330*38fd1498Szrj warning ("unit `%s' excludes and requires presence of `%s'",
2331*38fd1498Szrj dst->unit_decl->name, unit->name);
2332*38fd1498Szrj }
2333*38fd1498Szrj }
2334*38fd1498Szrj else if (pat->units_num == 1)
2335*38fd1498Szrj for (curr_pat_el = dst->unit_decl->presence_list;
2336*38fd1498Szrj curr_pat_el != NULL;
2337*38fd1498Szrj curr_pat_el = curr_pat_el->next_pattern_set_el)
2338*38fd1498Szrj if (curr_pat_el->units_num == 1
2339*38fd1498Szrj && unit == curr_pat_el->unit_decls [0])
2340*38fd1498Szrj {
2341*38fd1498Szrj if (!w_flag)
2342*38fd1498Szrj {
2343*38fd1498Szrj error ("unit `%s' requires absence and presence of `%s'",
2344*38fd1498Szrj dst->unit_decl->name, unit->name);
2345*38fd1498Szrj no_error_flag = 0;
2346*38fd1498Szrj }
2347*38fd1498Szrj else
2348*38fd1498Szrj warning ("unit `%s' requires absence and presence of `%s'",
2349*38fd1498Szrj dst->unit_decl->name, unit->name);
2350*38fd1498Szrj }
2351*38fd1498Szrj if (no_error_flag)
2352*38fd1498Szrj {
2353*38fd1498Szrj for (prev_el = (presence_p
2354*38fd1498Szrj ? (final_p
2355*38fd1498Szrj ? dst->unit_decl->final_presence_list
2356*38fd1498Szrj : dst->unit_decl->presence_list)
2357*38fd1498Szrj : (final_p
2358*38fd1498Szrj ? dst->unit_decl->final_absence_list
2359*38fd1498Szrj : dst->unit_decl->absence_list));
2360*38fd1498Szrj prev_el != NULL && prev_el->next_pattern_set_el != NULL;
2361*38fd1498Szrj prev_el = prev_el->next_pattern_set_el)
2362*38fd1498Szrj ;
2363*38fd1498Szrj copy = XCOPYNODE (struct pattern_set_el, pat);
2364*38fd1498Szrj copy->next_pattern_set_el = NULL;
2365*38fd1498Szrj if (prev_el == NULL)
2366*38fd1498Szrj {
2367*38fd1498Szrj if (presence_p)
2368*38fd1498Szrj {
2369*38fd1498Szrj if (final_p)
2370*38fd1498Szrj dst->unit_decl->final_presence_list = copy;
2371*38fd1498Szrj else
2372*38fd1498Szrj dst->unit_decl->presence_list = copy;
2373*38fd1498Szrj }
2374*38fd1498Szrj else if (final_p)
2375*38fd1498Szrj dst->unit_decl->final_absence_list = copy;
2376*38fd1498Szrj else
2377*38fd1498Szrj dst->unit_decl->absence_list = copy;
2378*38fd1498Szrj }
2379*38fd1498Szrj else
2380*38fd1498Szrj prev_el->next_pattern_set_el = copy;
2381*38fd1498Szrj }
2382*38fd1498Szrj }
2383*38fd1498Szrj }
2384*38fd1498Szrj }
2385*38fd1498Szrj
2386*38fd1498Szrj
2387*38fd1498Szrj /* The function inserts BYPASS in the list of bypasses of the
2388*38fd1498Szrj corresponding output insn. The order of bypasses in the list is
2389*38fd1498Szrj described in a comment for member `bypass_list' (see above). If
2390*38fd1498Szrj there is already the same bypass in the list the function reports
2391*38fd1498Szrj this and does nothing. */
2392*38fd1498Szrj static void
insert_bypass(struct bypass_decl * bypass)2393*38fd1498Szrj insert_bypass (struct bypass_decl *bypass)
2394*38fd1498Szrj {
2395*38fd1498Szrj struct bypass_decl *curr, *last;
2396*38fd1498Szrj struct insn_reserv_decl *out_insn_reserv = bypass->out_insn_reserv;
2397*38fd1498Szrj struct insn_reserv_decl *in_insn_reserv = bypass->in_insn_reserv;
2398*38fd1498Szrj
2399*38fd1498Szrj for (curr = out_insn_reserv->bypass_list, last = NULL;
2400*38fd1498Szrj curr != NULL;
2401*38fd1498Szrj last = curr, curr = curr->next)
2402*38fd1498Szrj if (curr->in_insn_reserv == in_insn_reserv)
2403*38fd1498Szrj {
2404*38fd1498Szrj if ((bypass->bypass_guard_name != NULL
2405*38fd1498Szrj && curr->bypass_guard_name != NULL
2406*38fd1498Szrj && ! strcmp (bypass->bypass_guard_name, curr->bypass_guard_name))
2407*38fd1498Szrj || bypass->bypass_guard_name == curr->bypass_guard_name)
2408*38fd1498Szrj {
2409*38fd1498Szrj if (bypass->bypass_guard_name == NULL)
2410*38fd1498Szrj {
2411*38fd1498Szrj if (!w_flag)
2412*38fd1498Szrj error ("the same bypass `%s - %s' is already defined",
2413*38fd1498Szrj bypass->out_pattern, bypass->in_pattern);
2414*38fd1498Szrj else
2415*38fd1498Szrj warning ("the same bypass `%s - %s' is already defined",
2416*38fd1498Szrj bypass->out_pattern, bypass->in_pattern);
2417*38fd1498Szrj }
2418*38fd1498Szrj else if (!w_flag)
2419*38fd1498Szrj error ("the same bypass `%s - %s' (guard %s) is already defined",
2420*38fd1498Szrj bypass->out_pattern, bypass->in_pattern,
2421*38fd1498Szrj bypass->bypass_guard_name);
2422*38fd1498Szrj else
2423*38fd1498Szrj warning
2424*38fd1498Szrj ("the same bypass `%s - %s' (guard %s) is already defined",
2425*38fd1498Szrj bypass->out_pattern, bypass->in_pattern,
2426*38fd1498Szrj bypass->bypass_guard_name);
2427*38fd1498Szrj return;
2428*38fd1498Szrj }
2429*38fd1498Szrj if (curr->bypass_guard_name == NULL)
2430*38fd1498Szrj break;
2431*38fd1498Szrj if (curr->next == NULL || curr->next->in_insn_reserv != in_insn_reserv)
2432*38fd1498Szrj {
2433*38fd1498Szrj last = curr;
2434*38fd1498Szrj break;
2435*38fd1498Szrj }
2436*38fd1498Szrj
2437*38fd1498Szrj }
2438*38fd1498Szrj if (last == NULL)
2439*38fd1498Szrj {
2440*38fd1498Szrj bypass->next = out_insn_reserv->bypass_list;
2441*38fd1498Szrj out_insn_reserv->bypass_list = bypass;
2442*38fd1498Szrj }
2443*38fd1498Szrj else
2444*38fd1498Szrj {
2445*38fd1498Szrj bypass->next = last->next;
2446*38fd1498Szrj last->next = bypass;
2447*38fd1498Szrj }
2448*38fd1498Szrj }
2449*38fd1498Szrj
2450*38fd1498Szrj /* BYPASS is a define_bypass decl that includes glob pattern PATTERN.
2451*38fd1498Szrj Call FN (BYPASS, INSN, DATA) for each matching instruction INSN. */
2452*38fd1498Szrj
2453*38fd1498Szrj static void
for_each_matching_insn(decl_t bypass,const char * pattern,void (* fn)(decl_t,decl_t,void *),void * data)2454*38fd1498Szrj for_each_matching_insn (decl_t bypass, const char *pattern,
2455*38fd1498Szrj void (*fn) (decl_t, decl_t, void *), void *data)
2456*38fd1498Szrj {
2457*38fd1498Szrj decl_t insn_reserv;
2458*38fd1498Szrj bool matched_p;
2459*38fd1498Szrj int i;
2460*38fd1498Szrj
2461*38fd1498Szrj matched_p = false;
2462*38fd1498Szrj if (strpbrk (pattern, "*?["))
2463*38fd1498Szrj for (i = 0; i < description->decls_num; i++)
2464*38fd1498Szrj {
2465*38fd1498Szrj insn_reserv = description->decls[i];
2466*38fd1498Szrj if (insn_reserv->mode == dm_insn_reserv
2467*38fd1498Szrj && fnmatch (pattern, DECL_INSN_RESERV (insn_reserv)->name, 0) == 0)
2468*38fd1498Szrj {
2469*38fd1498Szrj fn (bypass, insn_reserv, data);
2470*38fd1498Szrj matched_p = true;
2471*38fd1498Szrj }
2472*38fd1498Szrj }
2473*38fd1498Szrj else
2474*38fd1498Szrj {
2475*38fd1498Szrj insn_reserv = find_insn_decl (pattern);
2476*38fd1498Szrj if (insn_reserv)
2477*38fd1498Szrj {
2478*38fd1498Szrj fn (bypass, insn_reserv, data);
2479*38fd1498Szrj matched_p = true;
2480*38fd1498Szrj }
2481*38fd1498Szrj }
2482*38fd1498Szrj if (!matched_p)
2483*38fd1498Szrj error ("there is no insn reservation that matches `%s'", pattern);
2484*38fd1498Szrj }
2485*38fd1498Szrj
2486*38fd1498Szrj /* A subroutine of process_bypass that is called for each pair
2487*38fd1498Szrj of matching instructions. OUT_INSN_RESERV is the output
2488*38fd1498Szrj instruction and DATA is the input instruction. */
2489*38fd1498Szrj
2490*38fd1498Szrj static void
process_bypass_2(decl_t model,decl_t out_insn_reserv,void * data)2491*38fd1498Szrj process_bypass_2 (decl_t model, decl_t out_insn_reserv, void *data)
2492*38fd1498Szrj {
2493*38fd1498Szrj struct bypass_decl *bypass;
2494*38fd1498Szrj decl_t in_insn_reserv;
2495*38fd1498Szrj
2496*38fd1498Szrj in_insn_reserv = (decl_t) data;
2497*38fd1498Szrj if (strcmp (DECL_INSN_RESERV (in_insn_reserv)->name,
2498*38fd1498Szrj DECL_BYPASS (model)->in_pattern) == 0
2499*38fd1498Szrj && strcmp (DECL_INSN_RESERV (out_insn_reserv)->name,
2500*38fd1498Szrj DECL_BYPASS (model)->out_pattern) == 0)
2501*38fd1498Szrj bypass = DECL_BYPASS (model);
2502*38fd1498Szrj else
2503*38fd1498Szrj {
2504*38fd1498Szrj bypass = XCNEW (struct bypass_decl);
2505*38fd1498Szrj bypass->latency = DECL_BYPASS (model)->latency;
2506*38fd1498Szrj bypass->out_pattern = DECL_INSN_RESERV (out_insn_reserv)->name;
2507*38fd1498Szrj bypass->in_pattern = DECL_INSN_RESERV (in_insn_reserv)->name;
2508*38fd1498Szrj bypass->bypass_guard_name = DECL_BYPASS (model)->bypass_guard_name;
2509*38fd1498Szrj }
2510*38fd1498Szrj bypass->out_insn_reserv = DECL_INSN_RESERV (out_insn_reserv);
2511*38fd1498Szrj bypass->in_insn_reserv = DECL_INSN_RESERV (in_insn_reserv);
2512*38fd1498Szrj insert_bypass (bypass);
2513*38fd1498Szrj }
2514*38fd1498Szrj
2515*38fd1498Szrj /* A subroutine of process_bypass that is called for each input
2516*38fd1498Szrj instruction IN_INSN_RESERV. */
2517*38fd1498Szrj
2518*38fd1498Szrj static void
process_bypass_1(decl_t bypass,decl_t in_insn_reserv,void * data ATTRIBUTE_UNUSED)2519*38fd1498Szrj process_bypass_1 (decl_t bypass, decl_t in_insn_reserv,
2520*38fd1498Szrj void *data ATTRIBUTE_UNUSED)
2521*38fd1498Szrj {
2522*38fd1498Szrj for_each_matching_insn (bypass, DECL_BYPASS (bypass)->out_pattern,
2523*38fd1498Szrj process_bypass_2, in_insn_reserv);
2524*38fd1498Szrj }
2525*38fd1498Szrj
2526*38fd1498Szrj /* Process define_bypass decl BYPASS, inserting a bypass for each specific
2527*38fd1498Szrj pair of insn reservations. */
2528*38fd1498Szrj
2529*38fd1498Szrj static void
process_bypass(decl_t bypass)2530*38fd1498Szrj process_bypass (decl_t bypass)
2531*38fd1498Szrj {
2532*38fd1498Szrj for_each_matching_insn (bypass, DECL_BYPASS (bypass)->in_pattern,
2533*38fd1498Szrj process_bypass_1, NULL);
2534*38fd1498Szrj }
2535*38fd1498Szrj
2536*38fd1498Szrj /* The function processes pipeline description declarations, checks
2537*38fd1498Szrj their correctness, and forms exclusion/presence/absence sets. */
2538*38fd1498Szrj static void
process_decls(void)2539*38fd1498Szrj process_decls (void)
2540*38fd1498Szrj {
2541*38fd1498Szrj decl_t decl;
2542*38fd1498Szrj decl_t automaton_decl;
2543*38fd1498Szrj decl_t decl_in_table;
2544*38fd1498Szrj int automaton_presence;
2545*38fd1498Szrj int i;
2546*38fd1498Szrj
2547*38fd1498Szrj /* Checking repeated automata declarations. */
2548*38fd1498Szrj automaton_presence = 0;
2549*38fd1498Szrj for (i = 0; i < description->decls_num; i++)
2550*38fd1498Szrj {
2551*38fd1498Szrj decl = description->decls [i];
2552*38fd1498Szrj if (decl->mode == dm_automaton)
2553*38fd1498Szrj {
2554*38fd1498Szrj automaton_presence = 1;
2555*38fd1498Szrj decl_in_table = insert_automaton_decl (decl);
2556*38fd1498Szrj if (decl_in_table != decl)
2557*38fd1498Szrj {
2558*38fd1498Szrj if (!w_flag)
2559*38fd1498Szrj error ("repeated declaration of automaton `%s'",
2560*38fd1498Szrj DECL_AUTOMATON (decl)->name);
2561*38fd1498Szrj else
2562*38fd1498Szrj warning ("repeated declaration of automaton `%s'",
2563*38fd1498Szrj DECL_AUTOMATON (decl)->name);
2564*38fd1498Szrj }
2565*38fd1498Szrj }
2566*38fd1498Szrj }
2567*38fd1498Szrj /* Checking undeclared automata, repeated declarations (except for
2568*38fd1498Szrj automata) and correctness of their attributes (insn latency times
2569*38fd1498Szrj etc.). */
2570*38fd1498Szrj for (i = 0; i < description->decls_num; i++)
2571*38fd1498Szrj {
2572*38fd1498Szrj decl = description->decls [i];
2573*38fd1498Szrj if (decl->mode == dm_insn_reserv)
2574*38fd1498Szrj {
2575*38fd1498Szrj if (DECL_INSN_RESERV (decl)->default_latency < 0)
2576*38fd1498Szrj error ("define_insn_reservation `%s' has negative latency time",
2577*38fd1498Szrj DECL_INSN_RESERV (decl)->name);
2578*38fd1498Szrj DECL_INSN_RESERV (decl)->insn_num = description->insns_num;
2579*38fd1498Szrj description->insns_num++;
2580*38fd1498Szrj decl_in_table = insert_insn_decl (decl);
2581*38fd1498Szrj if (decl_in_table != decl)
2582*38fd1498Szrj error ("`%s' is already used as insn reservation name",
2583*38fd1498Szrj DECL_INSN_RESERV (decl)->name);
2584*38fd1498Szrj }
2585*38fd1498Szrj else if (decl->mode == dm_bypass)
2586*38fd1498Szrj {
2587*38fd1498Szrj if (DECL_BYPASS (decl)->latency < 0)
2588*38fd1498Szrj error ("define_bypass `%s - %s' has negative latency time",
2589*38fd1498Szrj DECL_BYPASS (decl)->out_pattern,
2590*38fd1498Szrj DECL_BYPASS (decl)->in_pattern);
2591*38fd1498Szrj }
2592*38fd1498Szrj else if (decl->mode == dm_unit || decl->mode == dm_reserv)
2593*38fd1498Szrj {
2594*38fd1498Szrj if (decl->mode == dm_unit)
2595*38fd1498Szrj {
2596*38fd1498Szrj DECL_UNIT (decl)->automaton_decl = NULL;
2597*38fd1498Szrj if (DECL_UNIT (decl)->automaton_name != NULL)
2598*38fd1498Szrj {
2599*38fd1498Szrj automaton_decl
2600*38fd1498Szrj = find_automaton_decl (DECL_UNIT (decl)->automaton_name);
2601*38fd1498Szrj if (automaton_decl == NULL)
2602*38fd1498Szrj error ("automaton `%s' is not declared",
2603*38fd1498Szrj DECL_UNIT (decl)->automaton_name);
2604*38fd1498Szrj else
2605*38fd1498Szrj {
2606*38fd1498Szrj DECL_AUTOMATON (automaton_decl)->automaton_is_used = 1;
2607*38fd1498Szrj DECL_UNIT (decl)->automaton_decl
2608*38fd1498Szrj = DECL_AUTOMATON (automaton_decl);
2609*38fd1498Szrj }
2610*38fd1498Szrj }
2611*38fd1498Szrj else if (automaton_presence)
2612*38fd1498Szrj error ("define_unit `%s' without automaton when one defined",
2613*38fd1498Szrj DECL_UNIT (decl)->name);
2614*38fd1498Szrj DECL_UNIT (decl)->unit_num = description->units_num;
2615*38fd1498Szrj description->units_num++;
2616*38fd1498Szrj if (strcmp (DECL_UNIT (decl)->name, NOTHING_NAME) == 0)
2617*38fd1498Szrj {
2618*38fd1498Szrj error ("`%s' is declared as cpu unit", NOTHING_NAME);
2619*38fd1498Szrj continue;
2620*38fd1498Szrj }
2621*38fd1498Szrj decl_in_table = find_decl (DECL_UNIT (decl)->name);
2622*38fd1498Szrj }
2623*38fd1498Szrj else
2624*38fd1498Szrj {
2625*38fd1498Szrj if (strcmp (DECL_RESERV (decl)->name, NOTHING_NAME) == 0)
2626*38fd1498Szrj {
2627*38fd1498Szrj error ("`%s' is declared as cpu reservation", NOTHING_NAME);
2628*38fd1498Szrj continue;
2629*38fd1498Szrj }
2630*38fd1498Szrj decl_in_table = find_decl (DECL_RESERV (decl)->name);
2631*38fd1498Szrj }
2632*38fd1498Szrj if (decl_in_table == NULL)
2633*38fd1498Szrj decl_in_table = insert_decl (decl);
2634*38fd1498Szrj else
2635*38fd1498Szrj {
2636*38fd1498Szrj if (decl->mode == dm_unit)
2637*38fd1498Szrj error ("repeated declaration of unit `%s'",
2638*38fd1498Szrj DECL_UNIT (decl)->name);
2639*38fd1498Szrj else
2640*38fd1498Szrj error ("repeated declaration of reservation `%s'",
2641*38fd1498Szrj DECL_RESERV (decl)->name);
2642*38fd1498Szrj }
2643*38fd1498Szrj }
2644*38fd1498Szrj }
2645*38fd1498Szrj /* Check bypasses and form list of bypasses for each (output)
2646*38fd1498Szrj insn. */
2647*38fd1498Szrj for (i = 0; i < description->decls_num; i++)
2648*38fd1498Szrj {
2649*38fd1498Szrj decl = description->decls [i];
2650*38fd1498Szrj if (decl->mode == dm_bypass)
2651*38fd1498Szrj process_bypass (decl);
2652*38fd1498Szrj }
2653*38fd1498Szrj
2654*38fd1498Szrj /* Check exclusion set declarations and form exclusion sets. */
2655*38fd1498Szrj for (i = 0; i < description->decls_num; i++)
2656*38fd1498Szrj {
2657*38fd1498Szrj decl = description->decls [i];
2658*38fd1498Szrj if (decl->mode == dm_excl)
2659*38fd1498Szrj {
2660*38fd1498Szrj unit_set_el_t unit_set_el_list;
2661*38fd1498Szrj unit_set_el_t unit_set_el_list_2;
2662*38fd1498Szrj
2663*38fd1498Szrj unit_set_el_list
2664*38fd1498Szrj = process_excls (DECL_EXCL (decl)->names,
2665*38fd1498Szrj DECL_EXCL (decl)->first_list_length, decl->pos);
2666*38fd1498Szrj unit_set_el_list_2
2667*38fd1498Szrj = process_excls (&DECL_EXCL (decl)->names
2668*38fd1498Szrj [DECL_EXCL (decl)->first_list_length],
2669*38fd1498Szrj DECL_EXCL (decl)->all_names_num
2670*38fd1498Szrj - DECL_EXCL (decl)->first_list_length,
2671*38fd1498Szrj decl->pos);
2672*38fd1498Szrj add_excls (unit_set_el_list, unit_set_el_list_2, decl->pos);
2673*38fd1498Szrj add_excls (unit_set_el_list_2, unit_set_el_list, decl->pos);
2674*38fd1498Szrj }
2675*38fd1498Szrj }
2676*38fd1498Szrj
2677*38fd1498Szrj /* Check presence set declarations and form presence sets. */
2678*38fd1498Szrj for (i = 0; i < description->decls_num; i++)
2679*38fd1498Szrj {
2680*38fd1498Szrj decl = description->decls [i];
2681*38fd1498Szrj if (decl->mode == dm_presence)
2682*38fd1498Szrj {
2683*38fd1498Szrj unit_set_el_t unit_set_el_list;
2684*38fd1498Szrj pattern_set_el_t pattern_set_el_list;
2685*38fd1498Szrj
2686*38fd1498Szrj unit_set_el_list
2687*38fd1498Szrj = process_presence_absence_names
2688*38fd1498Szrj (DECL_PRESENCE (decl)->names, DECL_PRESENCE (decl)->names_num,
2689*38fd1498Szrj decl->pos, TRUE, DECL_PRESENCE (decl)->final_p);
2690*38fd1498Szrj pattern_set_el_list
2691*38fd1498Szrj = process_presence_absence_patterns
2692*38fd1498Szrj (DECL_PRESENCE (decl)->patterns,
2693*38fd1498Szrj DECL_PRESENCE (decl)->patterns_num,
2694*38fd1498Szrj decl->pos, TRUE, DECL_PRESENCE (decl)->final_p);
2695*38fd1498Szrj add_presence_absence (unit_set_el_list, pattern_set_el_list,
2696*38fd1498Szrj decl->pos, TRUE,
2697*38fd1498Szrj DECL_PRESENCE (decl)->final_p);
2698*38fd1498Szrj }
2699*38fd1498Szrj }
2700*38fd1498Szrj
2701*38fd1498Szrj /* Check absence set declarations and form absence sets. */
2702*38fd1498Szrj for (i = 0; i < description->decls_num; i++)
2703*38fd1498Szrj {
2704*38fd1498Szrj decl = description->decls [i];
2705*38fd1498Szrj if (decl->mode == dm_absence)
2706*38fd1498Szrj {
2707*38fd1498Szrj unit_set_el_t unit_set_el_list;
2708*38fd1498Szrj pattern_set_el_t pattern_set_el_list;
2709*38fd1498Szrj
2710*38fd1498Szrj unit_set_el_list
2711*38fd1498Szrj = process_presence_absence_names
2712*38fd1498Szrj (DECL_ABSENCE (decl)->names, DECL_ABSENCE (decl)->names_num,
2713*38fd1498Szrj decl->pos, FALSE, DECL_ABSENCE (decl)->final_p);
2714*38fd1498Szrj pattern_set_el_list
2715*38fd1498Szrj = process_presence_absence_patterns
2716*38fd1498Szrj (DECL_ABSENCE (decl)->patterns,
2717*38fd1498Szrj DECL_ABSENCE (decl)->patterns_num,
2718*38fd1498Szrj decl->pos, FALSE, DECL_ABSENCE (decl)->final_p);
2719*38fd1498Szrj add_presence_absence (unit_set_el_list, pattern_set_el_list,
2720*38fd1498Szrj decl->pos, FALSE,
2721*38fd1498Szrj DECL_ABSENCE (decl)->final_p);
2722*38fd1498Szrj }
2723*38fd1498Szrj }
2724*38fd1498Szrj }
2725*38fd1498Szrj
2726*38fd1498Szrj /* The following function checks that declared automaton is used. If
2727*38fd1498Szrj the automaton is not used, the function fixes error/warning. The
2728*38fd1498Szrj following function must be called only after `process_decls'. */
2729*38fd1498Szrj static void
check_automaton_usage(void)2730*38fd1498Szrj check_automaton_usage (void)
2731*38fd1498Szrj {
2732*38fd1498Szrj decl_t decl;
2733*38fd1498Szrj int i;
2734*38fd1498Szrj
2735*38fd1498Szrj for (i = 0; i < description->decls_num; i++)
2736*38fd1498Szrj {
2737*38fd1498Szrj decl = description->decls [i];
2738*38fd1498Szrj if (decl->mode == dm_automaton
2739*38fd1498Szrj && !DECL_AUTOMATON (decl)->automaton_is_used)
2740*38fd1498Szrj {
2741*38fd1498Szrj if (!w_flag)
2742*38fd1498Szrj error ("automaton `%s' is not used", DECL_AUTOMATON (decl)->name);
2743*38fd1498Szrj else
2744*38fd1498Szrj warning ("automaton `%s' is not used",
2745*38fd1498Szrj DECL_AUTOMATON (decl)->name);
2746*38fd1498Szrj }
2747*38fd1498Szrj }
2748*38fd1498Szrj }
2749*38fd1498Szrj
2750*38fd1498Szrj /* The following recursive function processes all regexp in order to
2751*38fd1498Szrj fix usage of units or reservations and to fix errors of undeclared
2752*38fd1498Szrj name. The function may change unit_regexp onto reserv_regexp.
2753*38fd1498Szrj Remember that reserv_regexp does not exist before the function
2754*38fd1498Szrj call. */
2755*38fd1498Szrj static regexp_t
process_regexp(regexp_t regexp)2756*38fd1498Szrj process_regexp (regexp_t regexp)
2757*38fd1498Szrj {
2758*38fd1498Szrj decl_t decl_in_table;
2759*38fd1498Szrj regexp_t new_regexp;
2760*38fd1498Szrj int i;
2761*38fd1498Szrj
2762*38fd1498Szrj switch (regexp->mode)
2763*38fd1498Szrj {
2764*38fd1498Szrj case rm_unit:
2765*38fd1498Szrj decl_in_table = find_decl (REGEXP_UNIT (regexp)->name);
2766*38fd1498Szrj if (decl_in_table == NULL)
2767*38fd1498Szrj error ("undeclared unit or reservation `%s'",
2768*38fd1498Szrj REGEXP_UNIT (regexp)->name);
2769*38fd1498Szrj else
2770*38fd1498Szrj switch (decl_in_table->mode)
2771*38fd1498Szrj {
2772*38fd1498Szrj case dm_unit:
2773*38fd1498Szrj DECL_UNIT (decl_in_table)->unit_is_used = 1;
2774*38fd1498Szrj REGEXP_UNIT (regexp)->unit_decl = DECL_UNIT (decl_in_table);
2775*38fd1498Szrj break;
2776*38fd1498Szrj
2777*38fd1498Szrj case dm_reserv:
2778*38fd1498Szrj DECL_RESERV (decl_in_table)->reserv_is_used = 1;
2779*38fd1498Szrj new_regexp = XCREATENODE (struct regexp);
2780*38fd1498Szrj new_regexp->mode = rm_reserv;
2781*38fd1498Szrj new_regexp->pos = regexp->pos;
2782*38fd1498Szrj REGEXP_RESERV (new_regexp)->name = REGEXP_UNIT (regexp)->name;
2783*38fd1498Szrj REGEXP_RESERV (new_regexp)->reserv_decl
2784*38fd1498Szrj = DECL_RESERV (decl_in_table);
2785*38fd1498Szrj regexp = new_regexp;
2786*38fd1498Szrj break;
2787*38fd1498Szrj
2788*38fd1498Szrj default:
2789*38fd1498Szrj gcc_unreachable ();
2790*38fd1498Szrj }
2791*38fd1498Szrj break;
2792*38fd1498Szrj case rm_sequence:
2793*38fd1498Szrj for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
2794*38fd1498Szrj REGEXP_SEQUENCE (regexp)->regexps [i]
2795*38fd1498Szrj = process_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
2796*38fd1498Szrj break;
2797*38fd1498Szrj case rm_allof:
2798*38fd1498Szrj for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
2799*38fd1498Szrj REGEXP_ALLOF (regexp)->regexps [i]
2800*38fd1498Szrj = process_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
2801*38fd1498Szrj break;
2802*38fd1498Szrj case rm_oneof:
2803*38fd1498Szrj for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
2804*38fd1498Szrj REGEXP_ONEOF (regexp)->regexps [i]
2805*38fd1498Szrj = process_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
2806*38fd1498Szrj break;
2807*38fd1498Szrj case rm_repeat:
2808*38fd1498Szrj REGEXP_REPEAT (regexp)->regexp
2809*38fd1498Szrj = process_regexp (REGEXP_REPEAT (regexp)->regexp);
2810*38fd1498Szrj break;
2811*38fd1498Szrj case rm_nothing:
2812*38fd1498Szrj break;
2813*38fd1498Szrj default:
2814*38fd1498Szrj gcc_unreachable ();
2815*38fd1498Szrj }
2816*38fd1498Szrj return regexp;
2817*38fd1498Szrj }
2818*38fd1498Szrj
2819*38fd1498Szrj /* The following function processes regexp of define_reservation and
2820*38fd1498Szrj define_insn_reservation with the aid of function
2821*38fd1498Szrj `process_regexp'. */
2822*38fd1498Szrj static void
process_regexp_decls(void)2823*38fd1498Szrj process_regexp_decls (void)
2824*38fd1498Szrj {
2825*38fd1498Szrj decl_t decl;
2826*38fd1498Szrj int i;
2827*38fd1498Szrj
2828*38fd1498Szrj for (i = 0; i < description->decls_num; i++)
2829*38fd1498Szrj {
2830*38fd1498Szrj decl = description->decls [i];
2831*38fd1498Szrj if (decl->mode == dm_reserv)
2832*38fd1498Szrj DECL_RESERV (decl)->regexp
2833*38fd1498Szrj = process_regexp (DECL_RESERV (decl)->regexp);
2834*38fd1498Szrj else if (decl->mode == dm_insn_reserv)
2835*38fd1498Szrj DECL_INSN_RESERV (decl)->regexp
2836*38fd1498Szrj = process_regexp (DECL_INSN_RESERV (decl)->regexp);
2837*38fd1498Szrj }
2838*38fd1498Szrj }
2839*38fd1498Szrj
2840*38fd1498Szrj /* The following function checks that declared unit is used. If the
2841*38fd1498Szrj unit is not used, the function fixes errors/warnings. The
2842*38fd1498Szrj following function must be called only after `process_decls',
2843*38fd1498Szrj `process_regexp_decls'. */
2844*38fd1498Szrj static void
check_usage(void)2845*38fd1498Szrj check_usage (void)
2846*38fd1498Szrj {
2847*38fd1498Szrj decl_t decl;
2848*38fd1498Szrj int i;
2849*38fd1498Szrj
2850*38fd1498Szrj for (i = 0; i < description->decls_num; i++)
2851*38fd1498Szrj {
2852*38fd1498Szrj decl = description->decls [i];
2853*38fd1498Szrj if (decl->mode == dm_unit && !DECL_UNIT (decl)->unit_is_used)
2854*38fd1498Szrj {
2855*38fd1498Szrj if (!w_flag)
2856*38fd1498Szrj error ("unit `%s' is not used", DECL_UNIT (decl)->name);
2857*38fd1498Szrj else
2858*38fd1498Szrj warning ("unit `%s' is not used", DECL_UNIT (decl)->name);
2859*38fd1498Szrj }
2860*38fd1498Szrj else if (decl->mode == dm_reserv && !DECL_RESERV (decl)->reserv_is_used)
2861*38fd1498Szrj {
2862*38fd1498Szrj if (!w_flag)
2863*38fd1498Szrj error ("reservation `%s' is not used", DECL_RESERV (decl)->name);
2864*38fd1498Szrj else
2865*38fd1498Szrj warning ("reservation `%s' is not used", DECL_RESERV (decl)->name);
2866*38fd1498Szrj }
2867*38fd1498Szrj }
2868*38fd1498Szrj }
2869*38fd1498Szrj
2870*38fd1498Szrj /* The following variable value is number of reservation being
2871*38fd1498Szrj processed on loop recognition. */
2872*38fd1498Szrj static int curr_loop_pass_num;
2873*38fd1498Szrj
2874*38fd1498Szrj /* The following recursive function returns nonzero value if REGEXP
2875*38fd1498Szrj contains given decl or reservations in given regexp refers for
2876*38fd1498Szrj given decl. */
2877*38fd1498Szrj static int
loop_in_regexp(regexp_t regexp,decl_t start_decl)2878*38fd1498Szrj loop_in_regexp (regexp_t regexp, decl_t start_decl)
2879*38fd1498Szrj {
2880*38fd1498Szrj int i;
2881*38fd1498Szrj
2882*38fd1498Szrj if (regexp == NULL)
2883*38fd1498Szrj return 0;
2884*38fd1498Szrj switch (regexp->mode)
2885*38fd1498Szrj {
2886*38fd1498Szrj case rm_unit:
2887*38fd1498Szrj return 0;
2888*38fd1498Szrj
2889*38fd1498Szrj case rm_reserv:
2890*38fd1498Szrj if (start_decl->mode == dm_reserv
2891*38fd1498Szrj && REGEXP_RESERV (regexp)->reserv_decl == DECL_RESERV (start_decl))
2892*38fd1498Szrj return 1;
2893*38fd1498Szrj else if (REGEXP_RESERV (regexp)->reserv_decl->loop_pass_num
2894*38fd1498Szrj == curr_loop_pass_num)
2895*38fd1498Szrj /* declaration has been processed. */
2896*38fd1498Szrj return 0;
2897*38fd1498Szrj else
2898*38fd1498Szrj {
2899*38fd1498Szrj REGEXP_RESERV (regexp)->reserv_decl->loop_pass_num
2900*38fd1498Szrj = curr_loop_pass_num;
2901*38fd1498Szrj return loop_in_regexp (REGEXP_RESERV (regexp)->reserv_decl->regexp,
2902*38fd1498Szrj start_decl);
2903*38fd1498Szrj }
2904*38fd1498Szrj
2905*38fd1498Szrj case rm_sequence:
2906*38fd1498Szrj for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
2907*38fd1498Szrj if (loop_in_regexp (REGEXP_SEQUENCE (regexp)->regexps [i], start_decl))
2908*38fd1498Szrj return 1;
2909*38fd1498Szrj return 0;
2910*38fd1498Szrj
2911*38fd1498Szrj case rm_allof:
2912*38fd1498Szrj for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
2913*38fd1498Szrj if (loop_in_regexp (REGEXP_ALLOF (regexp)->regexps [i], start_decl))
2914*38fd1498Szrj return 1;
2915*38fd1498Szrj return 0;
2916*38fd1498Szrj
2917*38fd1498Szrj case rm_oneof:
2918*38fd1498Szrj for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
2919*38fd1498Szrj if (loop_in_regexp (REGEXP_ONEOF (regexp)->regexps [i], start_decl))
2920*38fd1498Szrj return 1;
2921*38fd1498Szrj return 0;
2922*38fd1498Szrj
2923*38fd1498Szrj case rm_repeat:
2924*38fd1498Szrj return loop_in_regexp (REGEXP_REPEAT (regexp)->regexp, start_decl);
2925*38fd1498Szrj
2926*38fd1498Szrj case rm_nothing:
2927*38fd1498Szrj return 0;
2928*38fd1498Szrj
2929*38fd1498Szrj default:
2930*38fd1498Szrj gcc_unreachable ();
2931*38fd1498Szrj }
2932*38fd1498Szrj }
2933*38fd1498Szrj
2934*38fd1498Szrj /* The following function fixes errors "cycle in definition ...". The
2935*38fd1498Szrj function uses function `loop_in_regexp' for that. */
2936*38fd1498Szrj static void
check_loops_in_regexps(void)2937*38fd1498Szrj check_loops_in_regexps (void)
2938*38fd1498Szrj {
2939*38fd1498Szrj decl_t decl;
2940*38fd1498Szrj int i;
2941*38fd1498Szrj
2942*38fd1498Szrj for (i = 0; i < description->decls_num; i++)
2943*38fd1498Szrj {
2944*38fd1498Szrj decl = description->decls [i];
2945*38fd1498Szrj if (decl->mode == dm_reserv)
2946*38fd1498Szrj DECL_RESERV (decl)->loop_pass_num = 0;
2947*38fd1498Szrj }
2948*38fd1498Szrj for (i = 0; i < description->decls_num; i++)
2949*38fd1498Szrj {
2950*38fd1498Szrj decl = description->decls [i];
2951*38fd1498Szrj curr_loop_pass_num = i;
2952*38fd1498Szrj
2953*38fd1498Szrj if (decl->mode == dm_reserv)
2954*38fd1498Szrj {
2955*38fd1498Szrj DECL_RESERV (decl)->loop_pass_num = curr_loop_pass_num;
2956*38fd1498Szrj if (loop_in_regexp (DECL_RESERV (decl)->regexp, decl))
2957*38fd1498Szrj {
2958*38fd1498Szrj gcc_assert (DECL_RESERV (decl)->regexp);
2959*38fd1498Szrj error ("cycle in definition of reservation `%s'",
2960*38fd1498Szrj DECL_RESERV (decl)->name);
2961*38fd1498Szrj }
2962*38fd1498Szrj }
2963*38fd1498Szrj }
2964*38fd1498Szrj }
2965*38fd1498Szrj
2966*38fd1498Szrj /* The function recursively processes IR of reservation and defines
2967*38fd1498Szrj max and min cycle for reservation of unit. */
2968*38fd1498Szrj static void
process_regexp_cycles(regexp_t regexp,int max_start_cycle,int min_start_cycle,int * max_finish_cycle,int * min_finish_cycle)2969*38fd1498Szrj process_regexp_cycles (regexp_t regexp, int max_start_cycle,
2970*38fd1498Szrj int min_start_cycle, int *max_finish_cycle,
2971*38fd1498Szrj int *min_finish_cycle)
2972*38fd1498Szrj {
2973*38fd1498Szrj int i;
2974*38fd1498Szrj
2975*38fd1498Szrj switch (regexp->mode)
2976*38fd1498Szrj {
2977*38fd1498Szrj case rm_unit:
2978*38fd1498Szrj if (REGEXP_UNIT (regexp)->unit_decl->max_occ_cycle_num < max_start_cycle)
2979*38fd1498Szrj REGEXP_UNIT (regexp)->unit_decl->max_occ_cycle_num = max_start_cycle;
2980*38fd1498Szrj if (REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num > min_start_cycle
2981*38fd1498Szrj || REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num == -1)
2982*38fd1498Szrj REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num = min_start_cycle;
2983*38fd1498Szrj *max_finish_cycle = max_start_cycle;
2984*38fd1498Szrj *min_finish_cycle = min_start_cycle;
2985*38fd1498Szrj break;
2986*38fd1498Szrj
2987*38fd1498Szrj case rm_reserv:
2988*38fd1498Szrj process_regexp_cycles (REGEXP_RESERV (regexp)->reserv_decl->regexp,
2989*38fd1498Szrj max_start_cycle, min_start_cycle,
2990*38fd1498Szrj max_finish_cycle, min_finish_cycle);
2991*38fd1498Szrj break;
2992*38fd1498Szrj
2993*38fd1498Szrj case rm_repeat:
2994*38fd1498Szrj for (i = 0; i < REGEXP_REPEAT (regexp)->repeat_num; i++)
2995*38fd1498Szrj {
2996*38fd1498Szrj process_regexp_cycles (REGEXP_REPEAT (regexp)->regexp,
2997*38fd1498Szrj max_start_cycle, min_start_cycle,
2998*38fd1498Szrj max_finish_cycle, min_finish_cycle);
2999*38fd1498Szrj max_start_cycle = *max_finish_cycle + 1;
3000*38fd1498Szrj min_start_cycle = *min_finish_cycle + 1;
3001*38fd1498Szrj }
3002*38fd1498Szrj break;
3003*38fd1498Szrj
3004*38fd1498Szrj case rm_sequence:
3005*38fd1498Szrj for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
3006*38fd1498Szrj {
3007*38fd1498Szrj process_regexp_cycles (REGEXP_SEQUENCE (regexp)->regexps [i],
3008*38fd1498Szrj max_start_cycle, min_start_cycle,
3009*38fd1498Szrj max_finish_cycle, min_finish_cycle);
3010*38fd1498Szrj max_start_cycle = *max_finish_cycle + 1;
3011*38fd1498Szrj min_start_cycle = *min_finish_cycle + 1;
3012*38fd1498Szrj }
3013*38fd1498Szrj break;
3014*38fd1498Szrj
3015*38fd1498Szrj case rm_allof:
3016*38fd1498Szrj {
3017*38fd1498Szrj int max_cycle = 0;
3018*38fd1498Szrj int min_cycle = 0;
3019*38fd1498Szrj
3020*38fd1498Szrj for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
3021*38fd1498Szrj {
3022*38fd1498Szrj process_regexp_cycles (REGEXP_ALLOF (regexp)->regexps [i],
3023*38fd1498Szrj max_start_cycle, min_start_cycle,
3024*38fd1498Szrj max_finish_cycle, min_finish_cycle);
3025*38fd1498Szrj if (max_cycle < *max_finish_cycle)
3026*38fd1498Szrj max_cycle = *max_finish_cycle;
3027*38fd1498Szrj if (i == 0 || min_cycle > *min_finish_cycle)
3028*38fd1498Szrj min_cycle = *min_finish_cycle;
3029*38fd1498Szrj }
3030*38fd1498Szrj *max_finish_cycle = max_cycle;
3031*38fd1498Szrj *min_finish_cycle = min_cycle;
3032*38fd1498Szrj }
3033*38fd1498Szrj break;
3034*38fd1498Szrj
3035*38fd1498Szrj case rm_oneof:
3036*38fd1498Szrj {
3037*38fd1498Szrj int max_cycle = 0;
3038*38fd1498Szrj int min_cycle = 0;
3039*38fd1498Szrj
3040*38fd1498Szrj for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
3041*38fd1498Szrj {
3042*38fd1498Szrj process_regexp_cycles (REGEXP_ONEOF (regexp)->regexps [i],
3043*38fd1498Szrj max_start_cycle, min_start_cycle,
3044*38fd1498Szrj max_finish_cycle, min_finish_cycle);
3045*38fd1498Szrj if (max_cycle < *max_finish_cycle)
3046*38fd1498Szrj max_cycle = *max_finish_cycle;
3047*38fd1498Szrj if (i == 0 || min_cycle > *min_finish_cycle)
3048*38fd1498Szrj min_cycle = *min_finish_cycle;
3049*38fd1498Szrj }
3050*38fd1498Szrj *max_finish_cycle = max_cycle;
3051*38fd1498Szrj *min_finish_cycle = min_cycle;
3052*38fd1498Szrj }
3053*38fd1498Szrj break;
3054*38fd1498Szrj
3055*38fd1498Szrj case rm_nothing:
3056*38fd1498Szrj *max_finish_cycle = max_start_cycle;
3057*38fd1498Szrj *min_finish_cycle = min_start_cycle;
3058*38fd1498Szrj break;
3059*38fd1498Szrj
3060*38fd1498Szrj default:
3061*38fd1498Szrj gcc_unreachable ();
3062*38fd1498Szrj }
3063*38fd1498Szrj }
3064*38fd1498Szrj
3065*38fd1498Szrj /* The following function is called only for correct program. The
3066*38fd1498Szrj function defines max reservation of insns in cycles. */
3067*38fd1498Szrj static void
evaluate_max_reserv_cycles(void)3068*38fd1498Szrj evaluate_max_reserv_cycles (void)
3069*38fd1498Szrj {
3070*38fd1498Szrj int max_insn_cycles_num;
3071*38fd1498Szrj int min_insn_cycles_num;
3072*38fd1498Szrj decl_t decl;
3073*38fd1498Szrj int i;
3074*38fd1498Szrj
3075*38fd1498Szrj description->max_insn_reserv_cycles = 0;
3076*38fd1498Szrj for (i = 0; i < description->decls_num; i++)
3077*38fd1498Szrj {
3078*38fd1498Szrj decl = description->decls [i];
3079*38fd1498Szrj if (decl->mode == dm_insn_reserv)
3080*38fd1498Szrj {
3081*38fd1498Szrj process_regexp_cycles (DECL_INSN_RESERV (decl)->regexp, 0, 0,
3082*38fd1498Szrj &max_insn_cycles_num, &min_insn_cycles_num);
3083*38fd1498Szrj if (description->max_insn_reserv_cycles < max_insn_cycles_num)
3084*38fd1498Szrj description->max_insn_reserv_cycles = max_insn_cycles_num;
3085*38fd1498Szrj }
3086*38fd1498Szrj }
3087*38fd1498Szrj description->max_insn_reserv_cycles++;
3088*38fd1498Szrj }
3089*38fd1498Szrj
3090*38fd1498Szrj /* The following function calls functions for checking all
3091*38fd1498Szrj description. */
3092*38fd1498Szrj static void
check_all_description(void)3093*38fd1498Szrj check_all_description (void)
3094*38fd1498Szrj {
3095*38fd1498Szrj process_decls ();
3096*38fd1498Szrj check_automaton_usage ();
3097*38fd1498Szrj process_regexp_decls ();
3098*38fd1498Szrj check_usage ();
3099*38fd1498Szrj check_loops_in_regexps ();
3100*38fd1498Szrj if (!have_error)
3101*38fd1498Szrj evaluate_max_reserv_cycles ();
3102*38fd1498Szrj }
3103*38fd1498Szrj
3104*38fd1498Szrj
3105*38fd1498Szrj
3106*38fd1498Szrj /* The page contains abstract data `ticker'. This data is used to
3107*38fd1498Szrj report time of different phases of building automata. It is
3108*38fd1498Szrj possibly to write a description for which automata will be built
3109*38fd1498Szrj during several minutes even on fast machine. */
3110*38fd1498Szrj
3111*38fd1498Szrj /* The following function creates ticker and makes it active. */
3112*38fd1498Szrj static ticker_t
create_ticker(void)3113*38fd1498Szrj create_ticker (void)
3114*38fd1498Szrj {
3115*38fd1498Szrj ticker_t ticker;
3116*38fd1498Szrj
3117*38fd1498Szrj ticker.modified_creation_time = get_run_time ();
3118*38fd1498Szrj ticker.incremented_off_time = 0;
3119*38fd1498Szrj return ticker;
3120*38fd1498Szrj }
3121*38fd1498Szrj
3122*38fd1498Szrj /* The following function switches off given ticker. */
3123*38fd1498Szrj static void
ticker_off(ticker_t * ticker)3124*38fd1498Szrj ticker_off (ticker_t *ticker)
3125*38fd1498Szrj {
3126*38fd1498Szrj if (ticker->incremented_off_time == 0)
3127*38fd1498Szrj ticker->incremented_off_time = get_run_time () + 1;
3128*38fd1498Szrj }
3129*38fd1498Szrj
3130*38fd1498Szrj /* The following function switches on given ticker. */
3131*38fd1498Szrj static void
ticker_on(ticker_t * ticker)3132*38fd1498Szrj ticker_on (ticker_t *ticker)
3133*38fd1498Szrj {
3134*38fd1498Szrj if (ticker->incremented_off_time != 0)
3135*38fd1498Szrj {
3136*38fd1498Szrj ticker->modified_creation_time
3137*38fd1498Szrj += get_run_time () - ticker->incremented_off_time + 1;
3138*38fd1498Szrj ticker->incremented_off_time = 0;
3139*38fd1498Szrj }
3140*38fd1498Szrj }
3141*38fd1498Szrj
3142*38fd1498Szrj /* The following function returns current time in milliseconds since
3143*38fd1498Szrj the moment when given ticker was created. */
3144*38fd1498Szrj static int
active_time(ticker_t ticker)3145*38fd1498Szrj active_time (ticker_t ticker)
3146*38fd1498Szrj {
3147*38fd1498Szrj if (ticker.incremented_off_time != 0)
3148*38fd1498Szrj return ticker.incremented_off_time - 1 - ticker.modified_creation_time;
3149*38fd1498Szrj else
3150*38fd1498Szrj return get_run_time () - ticker.modified_creation_time;
3151*38fd1498Szrj }
3152*38fd1498Szrj
3153*38fd1498Szrj /* The following function returns string representation of active time
3154*38fd1498Szrj of given ticker. The result is string representation of seconds
3155*38fd1498Szrj with accuracy of 1/100 second. Only result of the last call of the
3156*38fd1498Szrj function exists. Therefore the following code is not correct
3157*38fd1498Szrj
3158*38fd1498Szrj printf ("parser time: %s\ngeneration time: %s\n",
3159*38fd1498Szrj active_time_string (parser_ticker),
3160*38fd1498Szrj active_time_string (generation_ticker));
3161*38fd1498Szrj
3162*38fd1498Szrj Correct code has to be the following
3163*38fd1498Szrj
3164*38fd1498Szrj printf ("parser time: %s\n", active_time_string (parser_ticker));
3165*38fd1498Szrj printf ("generation time: %s\n",
3166*38fd1498Szrj active_time_string (generation_ticker));
3167*38fd1498Szrj
3168*38fd1498Szrj */
3169*38fd1498Szrj static void
print_active_time(FILE * f,ticker_t ticker)3170*38fd1498Szrj print_active_time (FILE *f, ticker_t ticker)
3171*38fd1498Szrj {
3172*38fd1498Szrj int msecs;
3173*38fd1498Szrj
3174*38fd1498Szrj msecs = active_time (ticker);
3175*38fd1498Szrj fprintf (f, "%d.%06d", msecs / 1000000, msecs % 1000000);
3176*38fd1498Szrj }
3177*38fd1498Szrj
3178*38fd1498Szrj
3179*38fd1498Szrj
3180*38fd1498Szrj /* The following variable value is number of automaton which are
3181*38fd1498Szrj really being created. This value is defined on the base of
3182*38fd1498Szrj argument of option `-split'. If the variable has zero value the
3183*38fd1498Szrj number of automata is defined by the constructions `%automaton'.
3184*38fd1498Szrj This case occurs when option `-split' is absent or has zero
3185*38fd1498Szrj argument. If constructions `define_automaton' is absent only one
3186*38fd1498Szrj automaton is created. */
3187*38fd1498Szrj static int automata_num;
3188*38fd1498Szrj
3189*38fd1498Szrj /* The following variable values are times of
3190*38fd1498Szrj o transformation of regular expressions
3191*38fd1498Szrj o building NDFA (DFA if !ndfa_flag)
3192*38fd1498Szrj o NDFA -> DFA (simply the same automaton if !ndfa_flag)
3193*38fd1498Szrj o DFA minimization
3194*38fd1498Szrj o building insn equivalence classes
3195*38fd1498Szrj o all previous ones
3196*38fd1498Szrj o code output */
3197*38fd1498Szrj static ticker_t transform_time;
3198*38fd1498Szrj static ticker_t NDFA_time;
3199*38fd1498Szrj static ticker_t NDFA_to_DFA_time;
3200*38fd1498Szrj static ticker_t minimize_time;
3201*38fd1498Szrj static ticker_t equiv_time;
3202*38fd1498Szrj static ticker_t automaton_generation_time;
3203*38fd1498Szrj static ticker_t output_time;
3204*38fd1498Szrj
3205*38fd1498Szrj /* The following variable values are times of
3206*38fd1498Szrj all checking
3207*38fd1498Szrj all generation
3208*38fd1498Szrj all pipeline hazard translator work */
3209*38fd1498Szrj static ticker_t check_time;
3210*38fd1498Szrj static ticker_t generation_time;
3211*38fd1498Szrj static ticker_t all_time;
3212*38fd1498Szrj
3213*38fd1498Szrj
3214*38fd1498Szrj
3215*38fd1498Szrj /* Pseudo insn decl which denotes advancing cycle. */
3216*38fd1498Szrj static decl_t advance_cycle_insn_decl;
3217*38fd1498Szrj /* Pseudo insn decl which denotes collapsing the NDFA state. */
3218*38fd1498Szrj static decl_t collapse_ndfa_insn_decl;
3219*38fd1498Szrj
3220*38fd1498Szrj /* Create and record a decl for the special advance-cycle transition. */
3221*38fd1498Szrj static void
add_advance_cycle_insn_decl(void)3222*38fd1498Szrj add_advance_cycle_insn_decl (void)
3223*38fd1498Szrj {
3224*38fd1498Szrj advance_cycle_insn_decl = XCREATENODE (struct decl);
3225*38fd1498Szrj advance_cycle_insn_decl->mode = dm_insn_reserv;
3226*38fd1498Szrj advance_cycle_insn_decl->pos = no_pos;
3227*38fd1498Szrj DECL_INSN_RESERV (advance_cycle_insn_decl)->regexp = NULL;
3228*38fd1498Szrj DECL_INSN_RESERV (advance_cycle_insn_decl)->name = "$advance_cycle";
3229*38fd1498Szrj DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num
3230*38fd1498Szrj = description->insns_num;
3231*38fd1498Szrj description->decls [description->decls_num] = advance_cycle_insn_decl;
3232*38fd1498Szrj description->decls_num++;
3233*38fd1498Szrj description->insns_num++;
3234*38fd1498Szrj }
3235*38fd1498Szrj
3236*38fd1498Szrj /* Create and record a decl for the special collapse-NDFA transition. */
3237*38fd1498Szrj static void
add_collapse_ndfa_insn_decl(void)3238*38fd1498Szrj add_collapse_ndfa_insn_decl (void)
3239*38fd1498Szrj {
3240*38fd1498Szrj collapse_ndfa_insn_decl = XCREATENODE (struct decl);
3241*38fd1498Szrj collapse_ndfa_insn_decl->mode = dm_insn_reserv;
3242*38fd1498Szrj collapse_ndfa_insn_decl->pos = no_pos;
3243*38fd1498Szrj DECL_INSN_RESERV (collapse_ndfa_insn_decl)->regexp = NULL;
3244*38fd1498Szrj DECL_INSN_RESERV (collapse_ndfa_insn_decl)->name = "$collapse_ndfa";
3245*38fd1498Szrj DECL_INSN_RESERV (collapse_ndfa_insn_decl)->insn_num
3246*38fd1498Szrj = description->insns_num;
3247*38fd1498Szrj description->decls [description->decls_num] = collapse_ndfa_insn_decl;
3248*38fd1498Szrj description->decls_num++;
3249*38fd1498Szrj description->insns_num++;
3250*38fd1498Szrj }
3251*38fd1498Szrj
3252*38fd1498Szrj /* True if DECL is either of the two special decls we created. */
3253*38fd1498Szrj static bool
special_decl_p(struct insn_reserv_decl * decl)3254*38fd1498Szrj special_decl_p (struct insn_reserv_decl *decl)
3255*38fd1498Szrj {
3256*38fd1498Szrj return (decl == DECL_INSN_RESERV (advance_cycle_insn_decl)
3257*38fd1498Szrj || (collapse_flag
3258*38fd1498Szrj && decl == DECL_INSN_RESERV (collapse_ndfa_insn_decl)));
3259*38fd1498Szrj }
3260*38fd1498Szrj
3261*38fd1498Szrj
3262*38fd1498Szrj /* Abstract data `alternative states' which represents
3263*38fd1498Szrj nondeterministic nature of the description (see comments for
3264*38fd1498Szrj structures alt_state and state). */
3265*38fd1498Szrj
3266*38fd1498Szrj /* List of free states. */
3267*38fd1498Szrj static alt_state_t first_free_alt_state;
3268*38fd1498Szrj
3269*38fd1498Szrj #ifndef NDEBUG
3270*38fd1498Szrj /* The following variables is maximal number of allocated nodes
3271*38fd1498Szrj alt_state. */
3272*38fd1498Szrj static int allocated_alt_states_num = 0;
3273*38fd1498Szrj #endif
3274*38fd1498Szrj
3275*38fd1498Szrj /* The following function returns free node alt_state. It may be new
3276*38fd1498Szrj allocated node or node freed earlier. */
3277*38fd1498Szrj static alt_state_t
get_free_alt_state(void)3278*38fd1498Szrj get_free_alt_state (void)
3279*38fd1498Szrj {
3280*38fd1498Szrj alt_state_t result;
3281*38fd1498Szrj
3282*38fd1498Szrj if (first_free_alt_state != NULL)
3283*38fd1498Szrj {
3284*38fd1498Szrj result = first_free_alt_state;
3285*38fd1498Szrj first_free_alt_state = first_free_alt_state->next_alt_state;
3286*38fd1498Szrj }
3287*38fd1498Szrj else
3288*38fd1498Szrj {
3289*38fd1498Szrj #ifndef NDEBUG
3290*38fd1498Szrj allocated_alt_states_num++;
3291*38fd1498Szrj #endif
3292*38fd1498Szrj result = XCREATENODE (struct alt_state);
3293*38fd1498Szrj }
3294*38fd1498Szrj result->state = NULL;
3295*38fd1498Szrj result->next_alt_state = NULL;
3296*38fd1498Szrj result->next_sorted_alt_state = NULL;
3297*38fd1498Szrj return result;
3298*38fd1498Szrj }
3299*38fd1498Szrj
3300*38fd1498Szrj /* The function frees node ALT_STATE. */
3301*38fd1498Szrj static void
free_alt_state(alt_state_t alt_state)3302*38fd1498Szrj free_alt_state (alt_state_t alt_state)
3303*38fd1498Szrj {
3304*38fd1498Szrj if (alt_state == NULL)
3305*38fd1498Szrj return;
3306*38fd1498Szrj alt_state->next_alt_state = first_free_alt_state;
3307*38fd1498Szrj first_free_alt_state = alt_state;
3308*38fd1498Szrj }
3309*38fd1498Szrj
3310*38fd1498Szrj /* The function frees list started with node ALT_STATE_LIST. */
3311*38fd1498Szrj static void
free_alt_states(alt_state_t alt_states_list)3312*38fd1498Szrj free_alt_states (alt_state_t alt_states_list)
3313*38fd1498Szrj {
3314*38fd1498Szrj alt_state_t curr_alt_state;
3315*38fd1498Szrj alt_state_t next_alt_state;
3316*38fd1498Szrj
3317*38fd1498Szrj for (curr_alt_state = alt_states_list;
3318*38fd1498Szrj curr_alt_state != NULL;
3319*38fd1498Szrj curr_alt_state = next_alt_state)
3320*38fd1498Szrj {
3321*38fd1498Szrj next_alt_state = curr_alt_state->next_alt_state;
3322*38fd1498Szrj free_alt_state (curr_alt_state);
3323*38fd1498Szrj }
3324*38fd1498Szrj }
3325*38fd1498Szrj
3326*38fd1498Szrj /* The function compares unique numbers of alt states. */
3327*38fd1498Szrj static int
alt_state_cmp(const void * alt_state_ptr_1,const void * alt_state_ptr_2)3328*38fd1498Szrj alt_state_cmp (const void *alt_state_ptr_1, const void *alt_state_ptr_2)
3329*38fd1498Szrj {
3330*38fd1498Szrj if ((*(const alt_state_t *) alt_state_ptr_1)->state->unique_num
3331*38fd1498Szrj == (*(const alt_state_t *) alt_state_ptr_2)->state->unique_num)
3332*38fd1498Szrj return 0;
3333*38fd1498Szrj else if ((*(const alt_state_t *) alt_state_ptr_1)->state->unique_num
3334*38fd1498Szrj < (*(const alt_state_t *) alt_state_ptr_2)->state->unique_num)
3335*38fd1498Szrj return -1;
3336*38fd1498Szrj else
3337*38fd1498Szrj return 1;
3338*38fd1498Szrj }
3339*38fd1498Szrj
3340*38fd1498Szrj /* The function sorts ALT_STATES_LIST and removes duplicated alt
3341*38fd1498Szrj states from the list. The comparison key is alt state unique
3342*38fd1498Szrj number. */
3343*38fd1498Szrj
3344*38fd1498Szrj static alt_state_t
uniq_sort_alt_states(alt_state_t alt_states_list)3345*38fd1498Szrj uniq_sort_alt_states (alt_state_t alt_states_list)
3346*38fd1498Szrj {
3347*38fd1498Szrj alt_state_t curr_alt_state;
3348*38fd1498Szrj size_t i;
3349*38fd1498Szrj size_t prev_unique_state_ind;
3350*38fd1498Szrj alt_state_t result;
3351*38fd1498Szrj
3352*38fd1498Szrj if (alt_states_list == 0)
3353*38fd1498Szrj return 0;
3354*38fd1498Szrj if (alt_states_list->next_alt_state == 0)
3355*38fd1498Szrj return alt_states_list;
3356*38fd1498Szrj
3357*38fd1498Szrj auto_vec<alt_state_t, 150> alt_states;
3358*38fd1498Szrj for (curr_alt_state = alt_states_list;
3359*38fd1498Szrj curr_alt_state != NULL;
3360*38fd1498Szrj curr_alt_state = curr_alt_state->next_alt_state)
3361*38fd1498Szrj alt_states.safe_push (curr_alt_state);
3362*38fd1498Szrj
3363*38fd1498Szrj alt_states.qsort (alt_state_cmp);
3364*38fd1498Szrj
3365*38fd1498Szrj prev_unique_state_ind = 0;
3366*38fd1498Szrj for (i = 1; i < alt_states.length (); i++)
3367*38fd1498Szrj if (alt_states[prev_unique_state_ind]->state != alt_states[i]->state)
3368*38fd1498Szrj {
3369*38fd1498Szrj prev_unique_state_ind++;
3370*38fd1498Szrj alt_states[prev_unique_state_ind] = alt_states[i];
3371*38fd1498Szrj }
3372*38fd1498Szrj alt_states.truncate (prev_unique_state_ind + 1);
3373*38fd1498Szrj
3374*38fd1498Szrj for (i = 1; i < alt_states.length (); i++)
3375*38fd1498Szrj alt_states[i-1]->next_sorted_alt_state
3376*38fd1498Szrj = alt_states[i];
3377*38fd1498Szrj alt_states.last ()->next_sorted_alt_state = 0;
3378*38fd1498Szrj
3379*38fd1498Szrj result = alt_states[0];
3380*38fd1498Szrj
3381*38fd1498Szrj return result;
3382*38fd1498Szrj }
3383*38fd1498Szrj
3384*38fd1498Szrj /* The function checks equality of alt state lists. Remember that the
3385*38fd1498Szrj lists must be already sorted by the previous function. */
3386*38fd1498Szrj static int
alt_states_eq(alt_state_t alt_states_1,alt_state_t alt_states_2)3387*38fd1498Szrj alt_states_eq (alt_state_t alt_states_1, alt_state_t alt_states_2)
3388*38fd1498Szrj {
3389*38fd1498Szrj while (alt_states_1 != NULL && alt_states_2 != NULL
3390*38fd1498Szrj && alt_state_cmp (&alt_states_1, &alt_states_2) == 0)
3391*38fd1498Szrj {
3392*38fd1498Szrj alt_states_1 = alt_states_1->next_sorted_alt_state;
3393*38fd1498Szrj alt_states_2 = alt_states_2->next_sorted_alt_state;
3394*38fd1498Szrj }
3395*38fd1498Szrj return alt_states_1 == alt_states_2;
3396*38fd1498Szrj }
3397*38fd1498Szrj
3398*38fd1498Szrj /* Initialization of the abstract data. */
3399*38fd1498Szrj static void
initiate_alt_states(void)3400*38fd1498Szrj initiate_alt_states (void)
3401*38fd1498Szrj {
3402*38fd1498Szrj first_free_alt_state = NULL;
3403*38fd1498Szrj }
3404*38fd1498Szrj
3405*38fd1498Szrj /* Finishing work with the abstract data. */
3406*38fd1498Szrj static void
finish_alt_states(void)3407*38fd1498Szrj finish_alt_states (void)
3408*38fd1498Szrj {
3409*38fd1498Szrj }
3410*38fd1498Szrj
3411*38fd1498Szrj
3412*38fd1498Szrj
3413*38fd1498Szrj /* The page contains macros for work with bits strings. We could use
3414*38fd1498Szrj standard gcc bitmap or sbitmap but it would result in difficulties
3415*38fd1498Szrj of building canadian cross. */
3416*38fd1498Szrj
3417*38fd1498Szrj /* Set bit number bitno in the bit string. The macro is not side
3418*38fd1498Szrj effect proof. */
3419*38fd1498Szrj #define bitmap_set_bit(bitstring, bitno) \
3420*38fd1498Szrj ((bitstring)[(bitno) / (sizeof (*(bitstring)) * CHAR_BIT)] |= \
3421*38fd1498Szrj (HOST_WIDE_INT)1 << (bitno) % (sizeof (*(bitstring)) * CHAR_BIT))
3422*38fd1498Szrj
3423*38fd1498Szrj #define CLEAR_BIT(bitstring, bitno) \
3424*38fd1498Szrj ((bitstring)[(bitno) / (sizeof (*(bitstring)) * CHAR_BIT)] &= \
3425*38fd1498Szrj ~((HOST_WIDE_INT)1 << (bitno) % (sizeof (*(bitstring)) * CHAR_BIT)))
3426*38fd1498Szrj
3427*38fd1498Szrj /* Test if bit number bitno in the bitstring is set. The macro is not
3428*38fd1498Szrj side effect proof. */
3429*38fd1498Szrj #define bitmap_bit_p(bitstring, bitno) \
3430*38fd1498Szrj ((bitstring)[(bitno) / (sizeof (*(bitstring)) * CHAR_BIT)] >> \
3431*38fd1498Szrj (bitno) % (sizeof (*(bitstring)) * CHAR_BIT) & 1)
3432*38fd1498Szrj
3433*38fd1498Szrj
3434*38fd1498Szrj
3435*38fd1498Szrj /* This page contains abstract data `state'. */
3436*38fd1498Szrj
3437*38fd1498Szrj /* Maximal length of reservations in cycles (>= 1). */
3438*38fd1498Szrj static int max_cycles_num;
3439*38fd1498Szrj
3440*38fd1498Szrj /* Number of set elements (see type set_el_t) needed for
3441*38fd1498Szrj representation of one cycle reservation. It is depended on units
3442*38fd1498Szrj number. */
3443*38fd1498Szrj static int els_in_cycle_reserv;
3444*38fd1498Szrj
3445*38fd1498Szrj /* Number of set elements (see type set_el_t) needed for
3446*38fd1498Szrj representation of maximal length reservation. Deterministic
3447*38fd1498Szrj reservation is stored as set (bit string) of length equal to the
3448*38fd1498Szrj variable value * number of bits in set_el_t. */
3449*38fd1498Szrj static int els_in_reservs;
3450*38fd1498Szrj
3451*38fd1498Szrj /* Array of pointers to unit declarations. */
3452*38fd1498Szrj static unit_decl_t *units_array;
3453*38fd1498Szrj
3454*38fd1498Szrj /* Temporary reservation of maximal length. */
3455*38fd1498Szrj static reserv_sets_t temp_reserv;
3456*38fd1498Szrj
3457*38fd1498Szrj /* The state table itself is represented by the following variable. */
3458*38fd1498Szrj static htab_t state_table;
3459*38fd1498Szrj
3460*38fd1498Szrj /* Linked list of free 'state' structures to be recycled. The
3461*38fd1498Szrj next_equiv_class_state pointer is borrowed for a free list. */
3462*38fd1498Szrj static state_t first_free_state;
3463*38fd1498Szrj
3464*38fd1498Szrj static int curr_unique_state_num;
3465*38fd1498Szrj
3466*38fd1498Szrj #ifndef NDEBUG
3467*38fd1498Szrj /* The following variables is maximal number of allocated nodes
3468*38fd1498Szrj `state'. */
3469*38fd1498Szrj static int allocated_states_num = 0;
3470*38fd1498Szrj #endif
3471*38fd1498Szrj
3472*38fd1498Szrj /* Allocate new reservation set. */
3473*38fd1498Szrj static reserv_sets_t
alloc_empty_reserv_sets(void)3474*38fd1498Szrj alloc_empty_reserv_sets (void)
3475*38fd1498Szrj {
3476*38fd1498Szrj reserv_sets_t result;
3477*38fd1498Szrj
3478*38fd1498Szrj obstack_blank (&irp, els_in_reservs * sizeof (set_el_t));
3479*38fd1498Szrj result = (reserv_sets_t) obstack_base (&irp);
3480*38fd1498Szrj obstack_finish (&irp);
3481*38fd1498Szrj memset (result, 0, els_in_reservs * sizeof (set_el_t));
3482*38fd1498Szrj return result;
3483*38fd1498Szrj }
3484*38fd1498Szrj
3485*38fd1498Szrj /* Hash value of reservation set. */
3486*38fd1498Szrj static unsigned
reserv_sets_hash_value(reserv_sets_t reservs)3487*38fd1498Szrj reserv_sets_hash_value (reserv_sets_t reservs)
3488*38fd1498Szrj {
3489*38fd1498Szrj set_el_t hash_value;
3490*38fd1498Szrj unsigned result;
3491*38fd1498Szrj int reservs_num, i;
3492*38fd1498Szrj set_el_t *reserv_ptr;
3493*38fd1498Szrj
3494*38fd1498Szrj hash_value = 0;
3495*38fd1498Szrj reservs_num = els_in_reservs;
3496*38fd1498Szrj reserv_ptr = reservs;
3497*38fd1498Szrj i = 0;
3498*38fd1498Szrj while (reservs_num != 0)
3499*38fd1498Szrj {
3500*38fd1498Szrj reservs_num--;
3501*38fd1498Szrj hash_value += ((*reserv_ptr >> i)
3502*38fd1498Szrj | (*reserv_ptr << (((sizeof (set_el_t) * CHAR_BIT) - 1) & -i)));
3503*38fd1498Szrj i++;
3504*38fd1498Szrj if (i == sizeof (set_el_t) * CHAR_BIT)
3505*38fd1498Szrj i = 0;
3506*38fd1498Szrj reserv_ptr++;
3507*38fd1498Szrj }
3508*38fd1498Szrj if (sizeof (set_el_t) <= sizeof (unsigned))
3509*38fd1498Szrj return hash_value;
3510*38fd1498Szrj result = 0;
3511*38fd1498Szrj for (i = sizeof (set_el_t); i > 0; i -= sizeof (unsigned) - 1)
3512*38fd1498Szrj {
3513*38fd1498Szrj result += (unsigned) hash_value;
3514*38fd1498Szrj hash_value >>= (sizeof (unsigned) - 1) * CHAR_BIT;
3515*38fd1498Szrj }
3516*38fd1498Szrj return result;
3517*38fd1498Szrj }
3518*38fd1498Szrj
3519*38fd1498Szrj /* Comparison of given reservation sets. */
3520*38fd1498Szrj static int
reserv_sets_cmp(const_reserv_sets_t reservs_1,const_reserv_sets_t reservs_2)3521*38fd1498Szrj reserv_sets_cmp (const_reserv_sets_t reservs_1, const_reserv_sets_t reservs_2)
3522*38fd1498Szrj {
3523*38fd1498Szrj int reservs_num;
3524*38fd1498Szrj const set_el_t *reserv_ptr_1;
3525*38fd1498Szrj const set_el_t *reserv_ptr_2;
3526*38fd1498Szrj
3527*38fd1498Szrj gcc_assert (reservs_1 && reservs_2);
3528*38fd1498Szrj reservs_num = els_in_reservs;
3529*38fd1498Szrj reserv_ptr_1 = reservs_1;
3530*38fd1498Szrj reserv_ptr_2 = reservs_2;
3531*38fd1498Szrj while (reservs_num != 0 && *reserv_ptr_1 == *reserv_ptr_2)
3532*38fd1498Szrj {
3533*38fd1498Szrj reservs_num--;
3534*38fd1498Szrj reserv_ptr_1++;
3535*38fd1498Szrj reserv_ptr_2++;
3536*38fd1498Szrj }
3537*38fd1498Szrj if (reservs_num == 0)
3538*38fd1498Szrj return 0;
3539*38fd1498Szrj else if (*reserv_ptr_1 < *reserv_ptr_2)
3540*38fd1498Szrj return -1;
3541*38fd1498Szrj else
3542*38fd1498Szrj return 1;
3543*38fd1498Szrj }
3544*38fd1498Szrj
3545*38fd1498Szrj /* The function checks equality of the reservation sets. */
3546*38fd1498Szrj static int
reserv_sets_eq(const_reserv_sets_t reservs_1,const_reserv_sets_t reservs_2)3547*38fd1498Szrj reserv_sets_eq (const_reserv_sets_t reservs_1, const_reserv_sets_t reservs_2)
3548*38fd1498Szrj {
3549*38fd1498Szrj return reserv_sets_cmp (reservs_1, reservs_2) == 0;
3550*38fd1498Szrj }
3551*38fd1498Szrj
3552*38fd1498Szrj /* Set up in the reservation set that unit with UNIT_NUM is used on
3553*38fd1498Szrj CYCLE_NUM. */
3554*38fd1498Szrj static void
set_unit_reserv(reserv_sets_t reservs,int cycle_num,int unit_num)3555*38fd1498Szrj set_unit_reserv (reserv_sets_t reservs, int cycle_num, int unit_num)
3556*38fd1498Szrj {
3557*38fd1498Szrj gcc_assert (cycle_num < max_cycles_num);
3558*38fd1498Szrj bitmap_set_bit (reservs, cycle_num * els_in_cycle_reserv
3559*38fd1498Szrj * sizeof (set_el_t) * CHAR_BIT + unit_num);
3560*38fd1498Szrj }
3561*38fd1498Szrj
3562*38fd1498Szrj /* Set up in the reservation set RESERVS that unit with UNIT_NUM is
3563*38fd1498Szrj used on CYCLE_NUM. */
3564*38fd1498Szrj static int
test_unit_reserv(reserv_sets_t reservs,int cycle_num,int unit_num)3565*38fd1498Szrj test_unit_reserv (reserv_sets_t reservs, int cycle_num, int unit_num)
3566*38fd1498Szrj {
3567*38fd1498Szrj gcc_assert (cycle_num < max_cycles_num);
3568*38fd1498Szrj return bitmap_bit_p (reservs, cycle_num * els_in_cycle_reserv
3569*38fd1498Szrj * sizeof (set_el_t) * CHAR_BIT + unit_num);
3570*38fd1498Szrj }
3571*38fd1498Szrj
3572*38fd1498Szrj /* The function checks that the reservation sets are intersected,
3573*38fd1498Szrj i.e. there is a unit reservation on a cycle in both reservation
3574*38fd1498Szrj sets. */
3575*38fd1498Szrj static int
reserv_sets_are_intersected(reserv_sets_t operand_1,reserv_sets_t operand_2)3576*38fd1498Szrj reserv_sets_are_intersected (reserv_sets_t operand_1,
3577*38fd1498Szrj reserv_sets_t operand_2)
3578*38fd1498Szrj {
3579*38fd1498Szrj set_el_t *el_ptr_1;
3580*38fd1498Szrj set_el_t *el_ptr_2;
3581*38fd1498Szrj set_el_t *cycle_ptr_1;
3582*38fd1498Szrj set_el_t *cycle_ptr_2;
3583*38fd1498Szrj
3584*38fd1498Szrj gcc_assert (operand_1 && operand_2);
3585*38fd1498Szrj for (el_ptr_1 = operand_1, el_ptr_2 = operand_2;
3586*38fd1498Szrj el_ptr_1 < operand_1 + els_in_reservs;
3587*38fd1498Szrj el_ptr_1++, el_ptr_2++)
3588*38fd1498Szrj if (*el_ptr_1 & *el_ptr_2)
3589*38fd1498Szrj return 1;
3590*38fd1498Szrj reserv_sets_or (temp_reserv, operand_1, operand_2);
3591*38fd1498Szrj for (cycle_ptr_1 = operand_1, cycle_ptr_2 = operand_2;
3592*38fd1498Szrj cycle_ptr_1 < operand_1 + els_in_reservs;
3593*38fd1498Szrj cycle_ptr_1 += els_in_cycle_reserv, cycle_ptr_2 += els_in_cycle_reserv)
3594*38fd1498Szrj {
3595*38fd1498Szrj for (el_ptr_1 = cycle_ptr_1, el_ptr_2 = get_excl_set (cycle_ptr_2);
3596*38fd1498Szrj el_ptr_1 < cycle_ptr_1 + els_in_cycle_reserv;
3597*38fd1498Szrj el_ptr_1++, el_ptr_2++)
3598*38fd1498Szrj if (*el_ptr_1 & *el_ptr_2)
3599*38fd1498Szrj return 1;
3600*38fd1498Szrj if (!check_presence_pattern_sets (cycle_ptr_1, cycle_ptr_2, FALSE))
3601*38fd1498Szrj return 1;
3602*38fd1498Szrj if (!check_presence_pattern_sets (temp_reserv + (cycle_ptr_2
3603*38fd1498Szrj - operand_2),
3604*38fd1498Szrj cycle_ptr_2, TRUE))
3605*38fd1498Szrj return 1;
3606*38fd1498Szrj if (!check_absence_pattern_sets (cycle_ptr_1, cycle_ptr_2, FALSE))
3607*38fd1498Szrj return 1;
3608*38fd1498Szrj if (!check_absence_pattern_sets (temp_reserv + (cycle_ptr_2 - operand_2),
3609*38fd1498Szrj cycle_ptr_2, TRUE))
3610*38fd1498Szrj return 1;
3611*38fd1498Szrj }
3612*38fd1498Szrj return 0;
3613*38fd1498Szrj }
3614*38fd1498Szrj
3615*38fd1498Szrj /* The function sets up RESULT bits by bits of OPERAND shifted on one
3616*38fd1498Szrj cpu cycle. The remaining bits of OPERAND (representing the last
3617*38fd1498Szrj cycle unit reservations) are not changed. */
3618*38fd1498Szrj static void
reserv_sets_shift(reserv_sets_t result,reserv_sets_t operand)3619*38fd1498Szrj reserv_sets_shift (reserv_sets_t result, reserv_sets_t operand)
3620*38fd1498Szrj {
3621*38fd1498Szrj int i;
3622*38fd1498Szrj
3623*38fd1498Szrj gcc_assert (result && operand && result != operand);
3624*38fd1498Szrj for (i = els_in_cycle_reserv; i < els_in_reservs; i++)
3625*38fd1498Szrj result [i - els_in_cycle_reserv] = operand [i];
3626*38fd1498Szrj }
3627*38fd1498Szrj
3628*38fd1498Szrj /* OR of the reservation sets. */
3629*38fd1498Szrj static void
reserv_sets_or(reserv_sets_t result,reserv_sets_t operand_1,reserv_sets_t operand_2)3630*38fd1498Szrj reserv_sets_or (reserv_sets_t result, reserv_sets_t operand_1,
3631*38fd1498Szrj reserv_sets_t operand_2)
3632*38fd1498Szrj {
3633*38fd1498Szrj set_el_t *el_ptr_1;
3634*38fd1498Szrj set_el_t *el_ptr_2;
3635*38fd1498Szrj set_el_t *result_set_el_ptr;
3636*38fd1498Szrj
3637*38fd1498Szrj gcc_assert (result && operand_1 && operand_2);
3638*38fd1498Szrj for (el_ptr_1 = operand_1, el_ptr_2 = operand_2, result_set_el_ptr = result;
3639*38fd1498Szrj el_ptr_1 < operand_1 + els_in_reservs;
3640*38fd1498Szrj el_ptr_1++, el_ptr_2++, result_set_el_ptr++)
3641*38fd1498Szrj *result_set_el_ptr = *el_ptr_1 | *el_ptr_2;
3642*38fd1498Szrj }
3643*38fd1498Szrj
3644*38fd1498Szrj /* AND of the reservation sets. */
3645*38fd1498Szrj static void
reserv_sets_and(reserv_sets_t result,reserv_sets_t operand_1,reserv_sets_t operand_2)3646*38fd1498Szrj reserv_sets_and (reserv_sets_t result, reserv_sets_t operand_1,
3647*38fd1498Szrj reserv_sets_t operand_2)
3648*38fd1498Szrj {
3649*38fd1498Szrj set_el_t *el_ptr_1;
3650*38fd1498Szrj set_el_t *el_ptr_2;
3651*38fd1498Szrj set_el_t *result_set_el_ptr;
3652*38fd1498Szrj
3653*38fd1498Szrj gcc_assert (result && operand_1 && operand_2);
3654*38fd1498Szrj for (el_ptr_1 = operand_1, el_ptr_2 = operand_2, result_set_el_ptr = result;
3655*38fd1498Szrj el_ptr_1 < operand_1 + els_in_reservs;
3656*38fd1498Szrj el_ptr_1++, el_ptr_2++, result_set_el_ptr++)
3657*38fd1498Szrj *result_set_el_ptr = *el_ptr_1 & *el_ptr_2;
3658*38fd1498Szrj }
3659*38fd1498Szrj
3660*38fd1498Szrj /* The function outputs string representation of units reservation on
3661*38fd1498Szrj cycle START_CYCLE in the reservation set. The function uses repeat
3662*38fd1498Szrj construction if REPETITION_NUM > 1. */
3663*38fd1498Szrj static void
output_cycle_reservs(FILE * f,reserv_sets_t reservs,int start_cycle,int repetition_num)3664*38fd1498Szrj output_cycle_reservs (FILE *f, reserv_sets_t reservs, int start_cycle,
3665*38fd1498Szrj int repetition_num)
3666*38fd1498Szrj {
3667*38fd1498Szrj int unit_num;
3668*38fd1498Szrj int reserved_units_num;
3669*38fd1498Szrj
3670*38fd1498Szrj reserved_units_num = 0;
3671*38fd1498Szrj for (unit_num = 0; unit_num < description->units_num; unit_num++)
3672*38fd1498Szrj if (bitmap_bit_p (reservs, start_cycle * els_in_cycle_reserv
3673*38fd1498Szrj * sizeof (set_el_t) * CHAR_BIT + unit_num))
3674*38fd1498Szrj reserved_units_num++;
3675*38fd1498Szrj gcc_assert (repetition_num > 0);
3676*38fd1498Szrj if (repetition_num != 1 && reserved_units_num > 1)
3677*38fd1498Szrj fprintf (f, "(");
3678*38fd1498Szrj reserved_units_num = 0;
3679*38fd1498Szrj for (unit_num = 0;
3680*38fd1498Szrj unit_num < description->units_num;
3681*38fd1498Szrj unit_num++)
3682*38fd1498Szrj if (bitmap_bit_p (reservs, start_cycle * els_in_cycle_reserv
3683*38fd1498Szrj * sizeof (set_el_t) * CHAR_BIT + unit_num))
3684*38fd1498Szrj {
3685*38fd1498Szrj if (reserved_units_num != 0)
3686*38fd1498Szrj fprintf (f, "+");
3687*38fd1498Szrj reserved_units_num++;
3688*38fd1498Szrj fprintf (f, "%s", units_array [unit_num]->name);
3689*38fd1498Szrj }
3690*38fd1498Szrj if (reserved_units_num == 0)
3691*38fd1498Szrj fprintf (f, NOTHING_NAME);
3692*38fd1498Szrj gcc_assert (repetition_num > 0);
3693*38fd1498Szrj if (repetition_num != 1 && reserved_units_num > 1)
3694*38fd1498Szrj fprintf (f, ")");
3695*38fd1498Szrj if (repetition_num != 1)
3696*38fd1498Szrj fprintf (f, "*%d", repetition_num);
3697*38fd1498Szrj }
3698*38fd1498Szrj
3699*38fd1498Szrj /* The function outputs string representation of units reservation in
3700*38fd1498Szrj the reservation set. */
3701*38fd1498Szrj static void
output_reserv_sets(FILE * f,reserv_sets_t reservs)3702*38fd1498Szrj output_reserv_sets (FILE *f, reserv_sets_t reservs)
3703*38fd1498Szrj {
3704*38fd1498Szrj int start_cycle = 0;
3705*38fd1498Szrj int cycle;
3706*38fd1498Szrj int repetition_num;
3707*38fd1498Szrj
3708*38fd1498Szrj repetition_num = 0;
3709*38fd1498Szrj for (cycle = 0; cycle < max_cycles_num; cycle++)
3710*38fd1498Szrj if (repetition_num == 0)
3711*38fd1498Szrj {
3712*38fd1498Szrj repetition_num++;
3713*38fd1498Szrj start_cycle = cycle;
3714*38fd1498Szrj }
3715*38fd1498Szrj else if (memcmp
3716*38fd1498Szrj ((char *) reservs + start_cycle * els_in_cycle_reserv
3717*38fd1498Szrj * sizeof (set_el_t),
3718*38fd1498Szrj (char *) reservs + cycle * els_in_cycle_reserv
3719*38fd1498Szrj * sizeof (set_el_t),
3720*38fd1498Szrj els_in_cycle_reserv * sizeof (set_el_t)) == 0)
3721*38fd1498Szrj repetition_num++;
3722*38fd1498Szrj else
3723*38fd1498Szrj {
3724*38fd1498Szrj if (start_cycle != 0)
3725*38fd1498Szrj fprintf (f, ", ");
3726*38fd1498Szrj output_cycle_reservs (f, reservs, start_cycle, repetition_num);
3727*38fd1498Szrj repetition_num = 1;
3728*38fd1498Szrj start_cycle = cycle;
3729*38fd1498Szrj }
3730*38fd1498Szrj if (start_cycle < max_cycles_num)
3731*38fd1498Szrj {
3732*38fd1498Szrj if (start_cycle != 0)
3733*38fd1498Szrj fprintf (f, ", ");
3734*38fd1498Szrj output_cycle_reservs (f, reservs, start_cycle, repetition_num);
3735*38fd1498Szrj }
3736*38fd1498Szrj }
3737*38fd1498Szrj
3738*38fd1498Szrj /* The following function returns free node state for AUTOMATON. It
3739*38fd1498Szrj may be new allocated node or node freed earlier. The function also
3740*38fd1498Szrj allocates reservation set if WITH_RESERVS has nonzero value. */
3741*38fd1498Szrj static state_t
get_free_state(int with_reservs,automaton_t automaton)3742*38fd1498Szrj get_free_state (int with_reservs, automaton_t automaton)
3743*38fd1498Szrj {
3744*38fd1498Szrj state_t result;
3745*38fd1498Szrj
3746*38fd1498Szrj gcc_assert (max_cycles_num > 0 && automaton);
3747*38fd1498Szrj if (first_free_state)
3748*38fd1498Szrj {
3749*38fd1498Szrj result = first_free_state;
3750*38fd1498Szrj first_free_state = result->next_equiv_class_state;
3751*38fd1498Szrj
3752*38fd1498Szrj result->next_equiv_class_state = NULL;
3753*38fd1498Szrj result->automaton = automaton;
3754*38fd1498Szrj result->first_out_arc = NULL;
3755*38fd1498Szrj result->it_was_placed_in_stack_for_NDFA_forming = 0;
3756*38fd1498Szrj result->it_was_placed_in_stack_for_DFA_forming = 0;
3757*38fd1498Szrj result->component_states = NULL;
3758*38fd1498Szrj }
3759*38fd1498Szrj else
3760*38fd1498Szrj {
3761*38fd1498Szrj #ifndef NDEBUG
3762*38fd1498Szrj allocated_states_num++;
3763*38fd1498Szrj #endif
3764*38fd1498Szrj result = XCREATENODE (struct state);
3765*38fd1498Szrj result->automaton = automaton;
3766*38fd1498Szrj result->first_out_arc = NULL;
3767*38fd1498Szrj result->unique_num = curr_unique_state_num;
3768*38fd1498Szrj curr_unique_state_num++;
3769*38fd1498Szrj }
3770*38fd1498Szrj if (with_reservs)
3771*38fd1498Szrj {
3772*38fd1498Szrj if (result->reservs == NULL)
3773*38fd1498Szrj result->reservs = alloc_empty_reserv_sets ();
3774*38fd1498Szrj else
3775*38fd1498Szrj memset (result->reservs, 0, els_in_reservs * sizeof (set_el_t));
3776*38fd1498Szrj }
3777*38fd1498Szrj return result;
3778*38fd1498Szrj }
3779*38fd1498Szrj
3780*38fd1498Szrj /* The function frees node STATE. */
3781*38fd1498Szrj static void
free_state(state_t state)3782*38fd1498Szrj free_state (state_t state)
3783*38fd1498Szrj {
3784*38fd1498Szrj free_alt_states (state->component_states);
3785*38fd1498Szrj state->next_equiv_class_state = first_free_state;
3786*38fd1498Szrj first_free_state = state;
3787*38fd1498Szrj }
3788*38fd1498Szrj
3789*38fd1498Szrj /* Hash value of STATE. If STATE represents deterministic state it is
3790*38fd1498Szrj simply hash value of the corresponding reservation set. Otherwise
3791*38fd1498Szrj it is formed from hash values of the component deterministic
3792*38fd1498Szrj states. One more key is order number of state automaton. */
3793*38fd1498Szrj static hashval_t
state_hash(const void * state)3794*38fd1498Szrj state_hash (const void *state)
3795*38fd1498Szrj {
3796*38fd1498Szrj unsigned int hash_value;
3797*38fd1498Szrj alt_state_t alt_state;
3798*38fd1498Szrj
3799*38fd1498Szrj if (((const_state_t) state)->component_states == NULL)
3800*38fd1498Szrj hash_value = reserv_sets_hash_value (((const_state_t) state)->reservs);
3801*38fd1498Szrj else
3802*38fd1498Szrj {
3803*38fd1498Szrj hash_value = 0;
3804*38fd1498Szrj for (alt_state = ((const_state_t) state)->component_states;
3805*38fd1498Szrj alt_state != NULL;
3806*38fd1498Szrj alt_state = alt_state->next_sorted_alt_state)
3807*38fd1498Szrj hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
3808*38fd1498Szrj | (hash_value << CHAR_BIT))
3809*38fd1498Szrj + alt_state->state->unique_num);
3810*38fd1498Szrj }
3811*38fd1498Szrj hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
3812*38fd1498Szrj | (hash_value << CHAR_BIT))
3813*38fd1498Szrj + ((const_state_t) state)->automaton->automaton_order_num);
3814*38fd1498Szrj return hash_value;
3815*38fd1498Szrj }
3816*38fd1498Szrj
3817*38fd1498Szrj /* Return nonzero value if the states are the same. */
3818*38fd1498Szrj static int
state_eq_p(const void * state_1,const void * state_2)3819*38fd1498Szrj state_eq_p (const void *state_1, const void *state_2)
3820*38fd1498Szrj {
3821*38fd1498Szrj alt_state_t alt_state_1;
3822*38fd1498Szrj alt_state_t alt_state_2;
3823*38fd1498Szrj
3824*38fd1498Szrj if (((const_state_t) state_1)->automaton != ((const_state_t) state_2)->automaton)
3825*38fd1498Szrj return 0;
3826*38fd1498Szrj else if (((const_state_t) state_1)->component_states == NULL
3827*38fd1498Szrj && ((const_state_t) state_2)->component_states == NULL)
3828*38fd1498Szrj return reserv_sets_eq (((const_state_t) state_1)->reservs,
3829*38fd1498Szrj ((const_state_t) state_2)->reservs);
3830*38fd1498Szrj else if (((const_state_t) state_1)->component_states != NULL
3831*38fd1498Szrj && ((const_state_t) state_2)->component_states != NULL)
3832*38fd1498Szrj {
3833*38fd1498Szrj for (alt_state_1 = ((const_state_t) state_1)->component_states,
3834*38fd1498Szrj alt_state_2 = ((const_state_t) state_2)->component_states;
3835*38fd1498Szrj alt_state_1 != NULL && alt_state_2 != NULL;
3836*38fd1498Szrj alt_state_1 = alt_state_1->next_sorted_alt_state,
3837*38fd1498Szrj alt_state_2 = alt_state_2->next_sorted_alt_state)
3838*38fd1498Szrj /* All state in the list must be already in the hash table.
3839*38fd1498Szrj Also the lists must be sorted. */
3840*38fd1498Szrj if (alt_state_1->state != alt_state_2->state)
3841*38fd1498Szrj return 0;
3842*38fd1498Szrj return alt_state_1 == alt_state_2;
3843*38fd1498Szrj }
3844*38fd1498Szrj else
3845*38fd1498Szrj return 0;
3846*38fd1498Szrj }
3847*38fd1498Szrj
3848*38fd1498Szrj /* Insert STATE into the state table. */
3849*38fd1498Szrj static state_t
insert_state(state_t state)3850*38fd1498Szrj insert_state (state_t state)
3851*38fd1498Szrj {
3852*38fd1498Szrj void **entry_ptr;
3853*38fd1498Szrj
3854*38fd1498Szrj entry_ptr = htab_find_slot (state_table, (void *) state, INSERT);
3855*38fd1498Szrj if (*entry_ptr == NULL)
3856*38fd1498Szrj *entry_ptr = (void *) state;
3857*38fd1498Szrj return (state_t) *entry_ptr;
3858*38fd1498Szrj }
3859*38fd1498Szrj
3860*38fd1498Szrj /* Add reservation of unit with UNIT_NUM on cycle CYCLE_NUM to
3861*38fd1498Szrj deterministic STATE. */
3862*38fd1498Szrj static void
set_state_reserv(state_t state,int cycle_num,int unit_num)3863*38fd1498Szrj set_state_reserv (state_t state, int cycle_num, int unit_num)
3864*38fd1498Szrj {
3865*38fd1498Szrj set_unit_reserv (state->reservs, cycle_num, unit_num);
3866*38fd1498Szrj }
3867*38fd1498Szrj
3868*38fd1498Szrj /* Return nonzero value if the deterministic states contains a
3869*38fd1498Szrj reservation of the same cpu unit on the same cpu cycle. */
3870*38fd1498Szrj static int
intersected_state_reservs_p(state_t state1,state_t state2)3871*38fd1498Szrj intersected_state_reservs_p (state_t state1, state_t state2)
3872*38fd1498Szrj {
3873*38fd1498Szrj gcc_assert (state1->automaton == state2->automaton);
3874*38fd1498Szrj return reserv_sets_are_intersected (state1->reservs, state2->reservs);
3875*38fd1498Szrj }
3876*38fd1498Szrj
3877*38fd1498Szrj /* Return deterministic state (inserted into the table) which
3878*38fd1498Szrj representing the automaton state which is union of reservations of
3879*38fd1498Szrj the deterministic states masked by RESERVS. */
3880*38fd1498Szrj static state_t
states_union(state_t state1,state_t state2,reserv_sets_t reservs)3881*38fd1498Szrj states_union (state_t state1, state_t state2, reserv_sets_t reservs)
3882*38fd1498Szrj {
3883*38fd1498Szrj state_t result;
3884*38fd1498Szrj state_t state_in_table;
3885*38fd1498Szrj
3886*38fd1498Szrj gcc_assert (state1->automaton == state2->automaton);
3887*38fd1498Szrj result = get_free_state (1, state1->automaton);
3888*38fd1498Szrj reserv_sets_or (result->reservs, state1->reservs, state2->reservs);
3889*38fd1498Szrj reserv_sets_and (result->reservs, result->reservs, reservs);
3890*38fd1498Szrj state_in_table = insert_state (result);
3891*38fd1498Szrj if (result != state_in_table)
3892*38fd1498Szrj {
3893*38fd1498Szrj free_state (result);
3894*38fd1498Szrj result = state_in_table;
3895*38fd1498Szrj }
3896*38fd1498Szrj return result;
3897*38fd1498Szrj }
3898*38fd1498Szrj
3899*38fd1498Szrj /* Return deterministic state (inserted into the table) which
3900*38fd1498Szrj represent the automaton state is obtained from deterministic STATE
3901*38fd1498Szrj by advancing cpu cycle and masking by RESERVS. */
3902*38fd1498Szrj static state_t
state_shift(state_t state,reserv_sets_t reservs)3903*38fd1498Szrj state_shift (state_t state, reserv_sets_t reservs)
3904*38fd1498Szrj {
3905*38fd1498Szrj state_t result;
3906*38fd1498Szrj state_t state_in_table;
3907*38fd1498Szrj
3908*38fd1498Szrj result = get_free_state (1, state->automaton);
3909*38fd1498Szrj reserv_sets_shift (result->reservs, state->reservs);
3910*38fd1498Szrj reserv_sets_and (result->reservs, result->reservs, reservs);
3911*38fd1498Szrj state_in_table = insert_state (result);
3912*38fd1498Szrj if (result != state_in_table)
3913*38fd1498Szrj {
3914*38fd1498Szrj free_state (result);
3915*38fd1498Szrj result = state_in_table;
3916*38fd1498Szrj }
3917*38fd1498Szrj return result;
3918*38fd1498Szrj }
3919*38fd1498Szrj
3920*38fd1498Szrj /* Initialization of the abstract data. */
3921*38fd1498Szrj static void
initiate_states(void)3922*38fd1498Szrj initiate_states (void)
3923*38fd1498Szrj {
3924*38fd1498Szrj decl_t decl;
3925*38fd1498Szrj int i;
3926*38fd1498Szrj
3927*38fd1498Szrj if (description->units_num)
3928*38fd1498Szrj units_array = XNEWVEC (unit_decl_t, description->units_num);
3929*38fd1498Szrj else
3930*38fd1498Szrj units_array = 0;
3931*38fd1498Szrj
3932*38fd1498Szrj for (i = 0; i < description->decls_num; i++)
3933*38fd1498Szrj {
3934*38fd1498Szrj decl = description->decls [i];
3935*38fd1498Szrj if (decl->mode == dm_unit)
3936*38fd1498Szrj units_array [DECL_UNIT (decl)->unit_num] = DECL_UNIT (decl);
3937*38fd1498Szrj }
3938*38fd1498Szrj max_cycles_num = description->max_insn_reserv_cycles;
3939*38fd1498Szrj els_in_cycle_reserv
3940*38fd1498Szrj = ((description->units_num + sizeof (set_el_t) * CHAR_BIT - 1)
3941*38fd1498Szrj / (sizeof (set_el_t) * CHAR_BIT));
3942*38fd1498Szrj els_in_reservs = els_in_cycle_reserv * max_cycles_num;
3943*38fd1498Szrj curr_unique_state_num = 0;
3944*38fd1498Szrj initiate_alt_states ();
3945*38fd1498Szrj state_table = htab_create (1500, state_hash, state_eq_p, (htab_del) 0);
3946*38fd1498Szrj temp_reserv = alloc_empty_reserv_sets ();
3947*38fd1498Szrj }
3948*38fd1498Szrj
3949*38fd1498Szrj /* Finishing work with the abstract data. */
3950*38fd1498Szrj static void
finish_states(void)3951*38fd1498Szrj finish_states (void)
3952*38fd1498Szrj {
3953*38fd1498Szrj free (units_array);
3954*38fd1498Szrj units_array = 0;
3955*38fd1498Szrj htab_delete (state_table);
3956*38fd1498Szrj first_free_state = NULL;
3957*38fd1498Szrj finish_alt_states ();
3958*38fd1498Szrj }
3959*38fd1498Szrj
3960*38fd1498Szrj
3961*38fd1498Szrj
3962*38fd1498Szrj /* Abstract data `arcs'. */
3963*38fd1498Szrj
3964*38fd1498Szrj /* List of free arcs. */
3965*38fd1498Szrj static arc_t first_free_arc;
3966*38fd1498Szrj
3967*38fd1498Szrj #ifndef NDEBUG
3968*38fd1498Szrj /* The following variables is maximal number of allocated nodes
3969*38fd1498Szrj `arc'. */
3970*38fd1498Szrj static int allocated_arcs_num = 0;
3971*38fd1498Szrj #endif
3972*38fd1498Szrj
3973*38fd1498Szrj /* The function frees node ARC. */
3974*38fd1498Szrj static void
free_arc(arc_t arc)3975*38fd1498Szrj free_arc (arc_t arc)
3976*38fd1498Szrj {
3977*38fd1498Szrj arc->next_out_arc = first_free_arc;
3978*38fd1498Szrj first_free_arc = arc;
3979*38fd1498Szrj }
3980*38fd1498Szrj
3981*38fd1498Szrj /* The function removes and frees ARC staring from FROM_STATE. */
3982*38fd1498Szrj static void
remove_arc(state_t from_state,arc_t arc)3983*38fd1498Szrj remove_arc (state_t from_state, arc_t arc)
3984*38fd1498Szrj {
3985*38fd1498Szrj arc_t prev_arc;
3986*38fd1498Szrj arc_t curr_arc;
3987*38fd1498Szrj
3988*38fd1498Szrj gcc_assert (arc);
3989*38fd1498Szrj for (prev_arc = NULL, curr_arc = from_state->first_out_arc;
3990*38fd1498Szrj curr_arc != NULL;
3991*38fd1498Szrj prev_arc = curr_arc, curr_arc = curr_arc->next_out_arc)
3992*38fd1498Szrj if (curr_arc == arc)
3993*38fd1498Szrj break;
3994*38fd1498Szrj gcc_assert (curr_arc);
3995*38fd1498Szrj if (prev_arc == NULL)
3996*38fd1498Szrj from_state->first_out_arc = arc->next_out_arc;
3997*38fd1498Szrj else
3998*38fd1498Szrj prev_arc->next_out_arc = arc->next_out_arc;
3999*38fd1498Szrj from_state->num_out_arcs--;
4000*38fd1498Szrj free_arc (arc);
4001*38fd1498Szrj }
4002*38fd1498Szrj
4003*38fd1498Szrj /* The functions returns arc with given characteristics (or NULL if
4004*38fd1498Szrj the arc does not exist). */
4005*38fd1498Szrj static arc_t
find_arc(state_t from_state,state_t to_state,ainsn_t insn)4006*38fd1498Szrj find_arc (state_t from_state, state_t to_state, ainsn_t insn)
4007*38fd1498Szrj {
4008*38fd1498Szrj arc_t arc;
4009*38fd1498Szrj
4010*38fd1498Szrj for (arc = first_out_arc (from_state); arc != NULL; arc = next_out_arc (arc))
4011*38fd1498Szrj if (arc->insn == insn
4012*38fd1498Szrj && (arc->to_state == to_state
4013*38fd1498Szrj || (collapse_flag
4014*38fd1498Szrj /* Any arc is good enough for a collapse-ndfa transition. */
4015*38fd1498Szrj && (insn->insn_reserv_decl
4016*38fd1498Szrj == DECL_INSN_RESERV (collapse_ndfa_insn_decl)))))
4017*38fd1498Szrj return arc;
4018*38fd1498Szrj return NULL;
4019*38fd1498Szrj }
4020*38fd1498Szrj
4021*38fd1498Szrj /* The function adds arc from FROM_STATE to TO_STATE marked by AINSN,
4022*38fd1498Szrj unless such an arc already exists. */
4023*38fd1498Szrj static void
add_arc(state_t from_state,state_t to_state,ainsn_t ainsn)4024*38fd1498Szrj add_arc (state_t from_state, state_t to_state, ainsn_t ainsn)
4025*38fd1498Szrj {
4026*38fd1498Szrj arc_t new_arc;
4027*38fd1498Szrj
4028*38fd1498Szrj new_arc = find_arc (from_state, to_state, ainsn);
4029*38fd1498Szrj if (new_arc != NULL)
4030*38fd1498Szrj return;
4031*38fd1498Szrj if (first_free_arc == NULL)
4032*38fd1498Szrj {
4033*38fd1498Szrj #ifndef NDEBUG
4034*38fd1498Szrj allocated_arcs_num++;
4035*38fd1498Szrj #endif
4036*38fd1498Szrj new_arc = XCREATENODE (struct arc);
4037*38fd1498Szrj new_arc->to_state = NULL;
4038*38fd1498Szrj new_arc->insn = NULL;
4039*38fd1498Szrj new_arc->next_out_arc = NULL;
4040*38fd1498Szrj }
4041*38fd1498Szrj else
4042*38fd1498Szrj {
4043*38fd1498Szrj new_arc = first_free_arc;
4044*38fd1498Szrj first_free_arc = first_free_arc->next_out_arc;
4045*38fd1498Szrj }
4046*38fd1498Szrj new_arc->to_state = to_state;
4047*38fd1498Szrj new_arc->insn = ainsn;
4048*38fd1498Szrj ainsn->arc_exists_p = 1;
4049*38fd1498Szrj new_arc->next_out_arc = from_state->first_out_arc;
4050*38fd1498Szrj from_state->first_out_arc = new_arc;
4051*38fd1498Szrj from_state->num_out_arcs++;
4052*38fd1498Szrj new_arc->next_arc_marked_by_insn = NULL;
4053*38fd1498Szrj }
4054*38fd1498Szrj
4055*38fd1498Szrj /* The function returns the first arc starting from STATE. */
4056*38fd1498Szrj static arc_t
first_out_arc(const_state_t state)4057*38fd1498Szrj first_out_arc (const_state_t state)
4058*38fd1498Szrj {
4059*38fd1498Szrj return state->first_out_arc;
4060*38fd1498Szrj }
4061*38fd1498Szrj
4062*38fd1498Szrj /* The function returns next out arc after ARC. */
4063*38fd1498Szrj static arc_t
next_out_arc(arc_t arc)4064*38fd1498Szrj next_out_arc (arc_t arc)
4065*38fd1498Szrj {
4066*38fd1498Szrj return arc->next_out_arc;
4067*38fd1498Szrj }
4068*38fd1498Szrj
4069*38fd1498Szrj /* Initialization of the abstract data. */
4070*38fd1498Szrj static void
initiate_arcs(void)4071*38fd1498Szrj initiate_arcs (void)
4072*38fd1498Szrj {
4073*38fd1498Szrj first_free_arc = NULL;
4074*38fd1498Szrj }
4075*38fd1498Szrj
4076*38fd1498Szrj /* Finishing work with the abstract data. */
4077*38fd1498Szrj static void
finish_arcs(void)4078*38fd1498Szrj finish_arcs (void)
4079*38fd1498Szrj {
4080*38fd1498Szrj }
4081*38fd1498Szrj
4082*38fd1498Szrj
4083*38fd1498Szrj
4084*38fd1498Szrj /* Abstract data `automata lists'. */
4085*38fd1498Szrj
4086*38fd1498Szrj /* List of free states. */
4087*38fd1498Szrj static automata_list_el_t first_free_automata_list_el;
4088*38fd1498Szrj
4089*38fd1498Szrj /* The list being formed. */
4090*38fd1498Szrj static automata_list_el_t current_automata_list;
4091*38fd1498Szrj
4092*38fd1498Szrj /* Hash table of automata lists. */
4093*38fd1498Szrj static htab_t automata_list_table;
4094*38fd1498Szrj
4095*38fd1498Szrj /* The following function returns free automata list el. It may be
4096*38fd1498Szrj new allocated node or node freed earlier. */
4097*38fd1498Szrj static automata_list_el_t
get_free_automata_list_el(void)4098*38fd1498Szrj get_free_automata_list_el (void)
4099*38fd1498Szrj {
4100*38fd1498Szrj automata_list_el_t result;
4101*38fd1498Szrj
4102*38fd1498Szrj if (first_free_automata_list_el != NULL)
4103*38fd1498Szrj {
4104*38fd1498Szrj result = first_free_automata_list_el;
4105*38fd1498Szrj first_free_automata_list_el
4106*38fd1498Szrj = first_free_automata_list_el->next_automata_list_el;
4107*38fd1498Szrj }
4108*38fd1498Szrj else
4109*38fd1498Szrj result = XCREATENODE (struct automata_list_el);
4110*38fd1498Szrj result->automaton = NULL;
4111*38fd1498Szrj result->next_automata_list_el = NULL;
4112*38fd1498Szrj return result;
4113*38fd1498Szrj }
4114*38fd1498Szrj
4115*38fd1498Szrj /* The function frees node AUTOMATA_LIST_EL. */
4116*38fd1498Szrj static void
free_automata_list_el(automata_list_el_t automata_list_el)4117*38fd1498Szrj free_automata_list_el (automata_list_el_t automata_list_el)
4118*38fd1498Szrj {
4119*38fd1498Szrj if (automata_list_el == NULL)
4120*38fd1498Szrj return;
4121*38fd1498Szrj automata_list_el->next_automata_list_el = first_free_automata_list_el;
4122*38fd1498Szrj first_free_automata_list_el = automata_list_el;
4123*38fd1498Szrj }
4124*38fd1498Szrj
4125*38fd1498Szrj /* The function frees list AUTOMATA_LIST. */
4126*38fd1498Szrj static void
free_automata_list(automata_list_el_t automata_list)4127*38fd1498Szrj free_automata_list (automata_list_el_t automata_list)
4128*38fd1498Szrj {
4129*38fd1498Szrj automata_list_el_t curr_automata_list_el;
4130*38fd1498Szrj automata_list_el_t next_automata_list_el;
4131*38fd1498Szrj
4132*38fd1498Szrj for (curr_automata_list_el = automata_list;
4133*38fd1498Szrj curr_automata_list_el != NULL;
4134*38fd1498Szrj curr_automata_list_el = next_automata_list_el)
4135*38fd1498Szrj {
4136*38fd1498Szrj next_automata_list_el = curr_automata_list_el->next_automata_list_el;
4137*38fd1498Szrj free_automata_list_el (curr_automata_list_el);
4138*38fd1498Szrj }
4139*38fd1498Szrj }
4140*38fd1498Szrj
4141*38fd1498Szrj /* Hash value of AUTOMATA_LIST. */
4142*38fd1498Szrj static hashval_t
automata_list_hash(const void * automata_list)4143*38fd1498Szrj automata_list_hash (const void *automata_list)
4144*38fd1498Szrj {
4145*38fd1498Szrj unsigned int hash_value;
4146*38fd1498Szrj const_automata_list_el_t curr_automata_list_el;
4147*38fd1498Szrj
4148*38fd1498Szrj hash_value = 0;
4149*38fd1498Szrj for (curr_automata_list_el = (const_automata_list_el_t) automata_list;
4150*38fd1498Szrj curr_automata_list_el != NULL;
4151*38fd1498Szrj curr_automata_list_el = curr_automata_list_el->next_automata_list_el)
4152*38fd1498Szrj hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
4153*38fd1498Szrj | (hash_value << CHAR_BIT))
4154*38fd1498Szrj + curr_automata_list_el->automaton->automaton_order_num);
4155*38fd1498Szrj return hash_value;
4156*38fd1498Szrj }
4157*38fd1498Szrj
4158*38fd1498Szrj /* Return nonzero value if the automata_lists are the same. */
4159*38fd1498Szrj static int
automata_list_eq_p(const void * automata_list_1,const void * automata_list_2)4160*38fd1498Szrj automata_list_eq_p (const void *automata_list_1, const void *automata_list_2)
4161*38fd1498Szrj {
4162*38fd1498Szrj const_automata_list_el_t automata_list_el_1;
4163*38fd1498Szrj const_automata_list_el_t automata_list_el_2;
4164*38fd1498Szrj
4165*38fd1498Szrj for (automata_list_el_1 = (const_automata_list_el_t) automata_list_1,
4166*38fd1498Szrj automata_list_el_2 = (const_automata_list_el_t) automata_list_2;
4167*38fd1498Szrj automata_list_el_1 != NULL && automata_list_el_2 != NULL;
4168*38fd1498Szrj automata_list_el_1 = automata_list_el_1->next_automata_list_el,
4169*38fd1498Szrj automata_list_el_2 = automata_list_el_2->next_automata_list_el)
4170*38fd1498Szrj if (automata_list_el_1->automaton != automata_list_el_2->automaton)
4171*38fd1498Szrj return 0;
4172*38fd1498Szrj return automata_list_el_1 == automata_list_el_2;
4173*38fd1498Szrj }
4174*38fd1498Szrj
4175*38fd1498Szrj /* Initialization of the abstract data. */
4176*38fd1498Szrj static void
initiate_automata_lists(void)4177*38fd1498Szrj initiate_automata_lists (void)
4178*38fd1498Szrj {
4179*38fd1498Szrj first_free_automata_list_el = NULL;
4180*38fd1498Szrj automata_list_table = htab_create (1500, automata_list_hash,
4181*38fd1498Szrj automata_list_eq_p, (htab_del) 0);
4182*38fd1498Szrj }
4183*38fd1498Szrj
4184*38fd1498Szrj /* The following function starts new automata list and makes it the
4185*38fd1498Szrj current one. */
4186*38fd1498Szrj static void
automata_list_start(void)4187*38fd1498Szrj automata_list_start (void)
4188*38fd1498Szrj {
4189*38fd1498Szrj current_automata_list = NULL;
4190*38fd1498Szrj }
4191*38fd1498Szrj
4192*38fd1498Szrj /* The following function adds AUTOMATON to the current list. */
4193*38fd1498Szrj static void
automata_list_add(automaton_t automaton)4194*38fd1498Szrj automata_list_add (automaton_t automaton)
4195*38fd1498Szrj {
4196*38fd1498Szrj automata_list_el_t el;
4197*38fd1498Szrj
4198*38fd1498Szrj el = get_free_automata_list_el ();
4199*38fd1498Szrj el->automaton = automaton;
4200*38fd1498Szrj el->next_automata_list_el = current_automata_list;
4201*38fd1498Szrj current_automata_list = el;
4202*38fd1498Szrj }
4203*38fd1498Szrj
4204*38fd1498Szrj /* The following function finishes forming the current list, inserts
4205*38fd1498Szrj it into the table and returns it. */
4206*38fd1498Szrj static automata_list_el_t
automata_list_finish(void)4207*38fd1498Szrj automata_list_finish (void)
4208*38fd1498Szrj {
4209*38fd1498Szrj void **entry_ptr;
4210*38fd1498Szrj
4211*38fd1498Szrj if (current_automata_list == NULL)
4212*38fd1498Szrj return NULL;
4213*38fd1498Szrj entry_ptr = htab_find_slot (automata_list_table,
4214*38fd1498Szrj (void *) current_automata_list, INSERT);
4215*38fd1498Szrj if (*entry_ptr == NULL)
4216*38fd1498Szrj *entry_ptr = (void *) current_automata_list;
4217*38fd1498Szrj else
4218*38fd1498Szrj free_automata_list (current_automata_list);
4219*38fd1498Szrj current_automata_list = NULL;
4220*38fd1498Szrj return (automata_list_el_t) *entry_ptr;
4221*38fd1498Szrj }
4222*38fd1498Szrj
4223*38fd1498Szrj /* Finishing work with the abstract data. */
4224*38fd1498Szrj static void
finish_automata_lists(void)4225*38fd1498Szrj finish_automata_lists (void)
4226*38fd1498Szrj {
4227*38fd1498Szrj htab_delete (automata_list_table);
4228*38fd1498Szrj }
4229*38fd1498Szrj
4230*38fd1498Szrj
4231*38fd1498Szrj
4232*38fd1498Szrj /* The page contains abstract data for work with exclusion sets (see
4233*38fd1498Szrj exclusion_set in file rtl.def). */
4234*38fd1498Szrj
4235*38fd1498Szrj /* The following variable refers to an exclusion set returned by
4236*38fd1498Szrj get_excl_set. This is bit string of length equal to cpu units
4237*38fd1498Szrj number. If exclusion set for given unit contains 1 for a unit,
4238*38fd1498Szrj then simultaneous reservation of the units is prohibited. */
4239*38fd1498Szrj static reserv_sets_t excl_set;
4240*38fd1498Szrj
4241*38fd1498Szrj /* The array contains exclusion sets for each unit. */
4242*38fd1498Szrj static reserv_sets_t *unit_excl_set_table;
4243*38fd1498Szrj
4244*38fd1498Szrj /* The following function forms the array containing exclusion sets
4245*38fd1498Szrj for each unit. */
4246*38fd1498Szrj static void
initiate_excl_sets(void)4247*38fd1498Szrj initiate_excl_sets (void)
4248*38fd1498Szrj {
4249*38fd1498Szrj decl_t decl;
4250*38fd1498Szrj reserv_sets_t unit_excl_set;
4251*38fd1498Szrj unit_set_el_t el;
4252*38fd1498Szrj int i;
4253*38fd1498Szrj
4254*38fd1498Szrj obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4255*38fd1498Szrj excl_set = (reserv_sets_t) obstack_base (&irp);
4256*38fd1498Szrj obstack_finish (&irp);
4257*38fd1498Szrj obstack_blank (&irp, description->units_num * sizeof (reserv_sets_t));
4258*38fd1498Szrj unit_excl_set_table = (reserv_sets_t *) obstack_base (&irp);
4259*38fd1498Szrj obstack_finish (&irp);
4260*38fd1498Szrj /* Evaluate unit exclusion sets. */
4261*38fd1498Szrj for (i = 0; i < description->decls_num; i++)
4262*38fd1498Szrj {
4263*38fd1498Szrj decl = description->decls [i];
4264*38fd1498Szrj if (decl->mode == dm_unit)
4265*38fd1498Szrj {
4266*38fd1498Szrj obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4267*38fd1498Szrj unit_excl_set = (reserv_sets_t) obstack_base (&irp);
4268*38fd1498Szrj obstack_finish (&irp);
4269*38fd1498Szrj memset (unit_excl_set, 0, els_in_cycle_reserv * sizeof (set_el_t));
4270*38fd1498Szrj for (el = DECL_UNIT (decl)->excl_list;
4271*38fd1498Szrj el != NULL;
4272*38fd1498Szrj el = el->next_unit_set_el)
4273*38fd1498Szrj {
4274*38fd1498Szrj bitmap_set_bit (unit_excl_set, el->unit_decl->unit_num);
4275*38fd1498Szrj el->unit_decl->in_set_p = TRUE;
4276*38fd1498Szrj }
4277*38fd1498Szrj unit_excl_set_table [DECL_UNIT (decl)->unit_num] = unit_excl_set;
4278*38fd1498Szrj }
4279*38fd1498Szrj }
4280*38fd1498Szrj }
4281*38fd1498Szrj
4282*38fd1498Szrj /* The function sets up and return EXCL_SET which is union of
4283*38fd1498Szrj exclusion sets for each unit in IN_SET. */
4284*38fd1498Szrj static reserv_sets_t
get_excl_set(reserv_sets_t in_set)4285*38fd1498Szrj get_excl_set (reserv_sets_t in_set)
4286*38fd1498Szrj {
4287*38fd1498Szrj int el;
4288*38fd1498Szrj unsigned int i;
4289*38fd1498Szrj int start_unit_num;
4290*38fd1498Szrj int unit_num;
4291*38fd1498Szrj
4292*38fd1498Szrj memset (excl_set, 0, els_in_cycle_reserv * sizeof (set_el_t));
4293*38fd1498Szrj for (el = 0; el < els_in_cycle_reserv; el++)
4294*38fd1498Szrj if (in_set[el])
4295*38fd1498Szrj for (i = 0; i < CHAR_BIT * sizeof (set_el_t); i++)
4296*38fd1498Szrj if ((in_set[el] >> i) & 1)
4297*38fd1498Szrj {
4298*38fd1498Szrj start_unit_num = el * CHAR_BIT * sizeof (set_el_t) + i;
4299*38fd1498Szrj if (start_unit_num >= description->units_num)
4300*38fd1498Szrj return excl_set;
4301*38fd1498Szrj for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4302*38fd1498Szrj {
4303*38fd1498Szrj excl_set [unit_num]
4304*38fd1498Szrj |= unit_excl_set_table [start_unit_num] [unit_num];
4305*38fd1498Szrj }
4306*38fd1498Szrj }
4307*38fd1498Szrj return excl_set;
4308*38fd1498Szrj }
4309*38fd1498Szrj
4310*38fd1498Szrj
4311*38fd1498Szrj
4312*38fd1498Szrj /* The page contains abstract data for work with presence/absence
4313*38fd1498Szrj pattern sets (see presence_set/absence_set in file rtl.def). */
4314*38fd1498Szrj
4315*38fd1498Szrj /* The following arrays contain correspondingly presence, final
4316*38fd1498Szrj presence, absence, and final absence patterns for each unit. */
4317*38fd1498Szrj static pattern_reserv_t *unit_presence_set_table;
4318*38fd1498Szrj static pattern_reserv_t *unit_final_presence_set_table;
4319*38fd1498Szrj static pattern_reserv_t *unit_absence_set_table;
4320*38fd1498Szrj static pattern_reserv_t *unit_final_absence_set_table;
4321*38fd1498Szrj
4322*38fd1498Szrj /* The following function forms list of reservation sets for given
4323*38fd1498Szrj PATTERN_LIST. */
4324*38fd1498Szrj static pattern_reserv_t
form_reserv_sets_list(pattern_set_el_t pattern_list)4325*38fd1498Szrj form_reserv_sets_list (pattern_set_el_t pattern_list)
4326*38fd1498Szrj {
4327*38fd1498Szrj pattern_set_el_t el;
4328*38fd1498Szrj pattern_reserv_t first, curr, prev;
4329*38fd1498Szrj int i;
4330*38fd1498Szrj
4331*38fd1498Szrj prev = first = NULL;
4332*38fd1498Szrj for (el = pattern_list; el != NULL; el = el->next_pattern_set_el)
4333*38fd1498Szrj {
4334*38fd1498Szrj curr = XCREATENODE (struct pattern_reserv);
4335*38fd1498Szrj curr->reserv = alloc_empty_reserv_sets ();
4336*38fd1498Szrj curr->next_pattern_reserv = NULL;
4337*38fd1498Szrj for (i = 0; i < el->units_num; i++)
4338*38fd1498Szrj {
4339*38fd1498Szrj bitmap_set_bit (curr->reserv, el->unit_decls [i]->unit_num);
4340*38fd1498Szrj el->unit_decls [i]->in_set_p = TRUE;
4341*38fd1498Szrj }
4342*38fd1498Szrj if (prev != NULL)
4343*38fd1498Szrj prev->next_pattern_reserv = curr;
4344*38fd1498Szrj else
4345*38fd1498Szrj first = curr;
4346*38fd1498Szrj prev = curr;
4347*38fd1498Szrj }
4348*38fd1498Szrj return first;
4349*38fd1498Szrj }
4350*38fd1498Szrj
4351*38fd1498Szrj /* The following function forms the array containing presence and
4352*38fd1498Szrj absence pattern sets for each unit. */
4353*38fd1498Szrj static void
initiate_presence_absence_pattern_sets(void)4354*38fd1498Szrj initiate_presence_absence_pattern_sets (void)
4355*38fd1498Szrj {
4356*38fd1498Szrj decl_t decl;
4357*38fd1498Szrj int i;
4358*38fd1498Szrj
4359*38fd1498Szrj obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4360*38fd1498Szrj unit_presence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4361*38fd1498Szrj obstack_finish (&irp);
4362*38fd1498Szrj obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4363*38fd1498Szrj unit_final_presence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4364*38fd1498Szrj obstack_finish (&irp);
4365*38fd1498Szrj obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4366*38fd1498Szrj unit_absence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4367*38fd1498Szrj obstack_finish (&irp);
4368*38fd1498Szrj obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4369*38fd1498Szrj unit_final_absence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4370*38fd1498Szrj obstack_finish (&irp);
4371*38fd1498Szrj /* Evaluate unit presence/absence sets. */
4372*38fd1498Szrj for (i = 0; i < description->decls_num; i++)
4373*38fd1498Szrj {
4374*38fd1498Szrj decl = description->decls [i];
4375*38fd1498Szrj if (decl->mode == dm_unit)
4376*38fd1498Szrj {
4377*38fd1498Szrj unit_presence_set_table [DECL_UNIT (decl)->unit_num]
4378*38fd1498Szrj = form_reserv_sets_list (DECL_UNIT (decl)->presence_list);
4379*38fd1498Szrj unit_final_presence_set_table [DECL_UNIT (decl)->unit_num]
4380*38fd1498Szrj = form_reserv_sets_list (DECL_UNIT (decl)->final_presence_list);
4381*38fd1498Szrj unit_absence_set_table [DECL_UNIT (decl)->unit_num]
4382*38fd1498Szrj = form_reserv_sets_list (DECL_UNIT (decl)->absence_list);
4383*38fd1498Szrj unit_final_absence_set_table [DECL_UNIT (decl)->unit_num]
4384*38fd1498Szrj = form_reserv_sets_list (DECL_UNIT (decl)->final_absence_list);
4385*38fd1498Szrj }
4386*38fd1498Szrj }
4387*38fd1498Szrj }
4388*38fd1498Szrj
4389*38fd1498Szrj /* The function checks that CHECKED_SET satisfies all presence pattern
4390*38fd1498Szrj sets for units in ORIGINAL_SET. The function returns TRUE if it
4391*38fd1498Szrj is ok. */
4392*38fd1498Szrj static int
check_presence_pattern_sets(reserv_sets_t checked_set,reserv_sets_t original_set,int final_p)4393*38fd1498Szrj check_presence_pattern_sets (reserv_sets_t checked_set,
4394*38fd1498Szrj reserv_sets_t original_set,
4395*38fd1498Szrj int final_p)
4396*38fd1498Szrj {
4397*38fd1498Szrj int el;
4398*38fd1498Szrj unsigned int i;
4399*38fd1498Szrj int start_unit_num;
4400*38fd1498Szrj int unit_num;
4401*38fd1498Szrj int presence_p;
4402*38fd1498Szrj pattern_reserv_t pat_reserv;
4403*38fd1498Szrj
4404*38fd1498Szrj for (el = 0; el < els_in_cycle_reserv; el++)
4405*38fd1498Szrj if (original_set[el])
4406*38fd1498Szrj for (i = 0; i < CHAR_BIT * sizeof (set_el_t); i++)
4407*38fd1498Szrj if ((original_set[el] >> i) & 1)
4408*38fd1498Szrj {
4409*38fd1498Szrj start_unit_num = el * CHAR_BIT * sizeof (set_el_t) + i;
4410*38fd1498Szrj if (start_unit_num >= description->units_num)
4411*38fd1498Szrj break;
4412*38fd1498Szrj if ((final_p
4413*38fd1498Szrj && unit_final_presence_set_table [start_unit_num] == NULL)
4414*38fd1498Szrj || (!final_p
4415*38fd1498Szrj && unit_presence_set_table [start_unit_num] == NULL))
4416*38fd1498Szrj continue;
4417*38fd1498Szrj presence_p = FALSE;
4418*38fd1498Szrj for (pat_reserv = (final_p
4419*38fd1498Szrj ? unit_final_presence_set_table [start_unit_num]
4420*38fd1498Szrj : unit_presence_set_table [start_unit_num]);
4421*38fd1498Szrj pat_reserv != NULL;
4422*38fd1498Szrj pat_reserv = pat_reserv->next_pattern_reserv)
4423*38fd1498Szrj {
4424*38fd1498Szrj for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4425*38fd1498Szrj if ((checked_set [unit_num] & pat_reserv->reserv [unit_num])
4426*38fd1498Szrj != pat_reserv->reserv [unit_num])
4427*38fd1498Szrj break;
4428*38fd1498Szrj presence_p = presence_p || unit_num >= els_in_cycle_reserv;
4429*38fd1498Szrj }
4430*38fd1498Szrj if (!presence_p)
4431*38fd1498Szrj return FALSE;
4432*38fd1498Szrj }
4433*38fd1498Szrj return TRUE;
4434*38fd1498Szrj }
4435*38fd1498Szrj
4436*38fd1498Szrj /* The function checks that CHECKED_SET satisfies all absence pattern
4437*38fd1498Szrj sets for units in ORIGINAL_SET. The function returns TRUE if it
4438*38fd1498Szrj is ok. */
4439*38fd1498Szrj static int
check_absence_pattern_sets(reserv_sets_t checked_set,reserv_sets_t original_set,int final_p)4440*38fd1498Szrj check_absence_pattern_sets (reserv_sets_t checked_set,
4441*38fd1498Szrj reserv_sets_t original_set,
4442*38fd1498Szrj int final_p)
4443*38fd1498Szrj {
4444*38fd1498Szrj int el;
4445*38fd1498Szrj unsigned int i;
4446*38fd1498Szrj int start_unit_num;
4447*38fd1498Szrj int unit_num;
4448*38fd1498Szrj pattern_reserv_t pat_reserv;
4449*38fd1498Szrj
4450*38fd1498Szrj for (el = 0; el < els_in_cycle_reserv; el++)
4451*38fd1498Szrj if (original_set[el])
4452*38fd1498Szrj for (i = 0; i < CHAR_BIT * sizeof (set_el_t); i++)
4453*38fd1498Szrj if ((original_set[el] >> i) & 1)
4454*38fd1498Szrj {
4455*38fd1498Szrj start_unit_num = el * CHAR_BIT * sizeof (set_el_t) + i;
4456*38fd1498Szrj if (start_unit_num >= description->units_num)
4457*38fd1498Szrj break;
4458*38fd1498Szrj for (pat_reserv = (final_p
4459*38fd1498Szrj ? unit_final_absence_set_table [start_unit_num]
4460*38fd1498Szrj : unit_absence_set_table [start_unit_num]);
4461*38fd1498Szrj pat_reserv != NULL;
4462*38fd1498Szrj pat_reserv = pat_reserv->next_pattern_reserv)
4463*38fd1498Szrj {
4464*38fd1498Szrj for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4465*38fd1498Szrj if ((checked_set [unit_num] & pat_reserv->reserv [unit_num])
4466*38fd1498Szrj != pat_reserv->reserv [unit_num]
4467*38fd1498Szrj && pat_reserv->reserv [unit_num])
4468*38fd1498Szrj break;
4469*38fd1498Szrj if (unit_num >= els_in_cycle_reserv)
4470*38fd1498Szrj return FALSE;
4471*38fd1498Szrj }
4472*38fd1498Szrj }
4473*38fd1498Szrj return TRUE;
4474*38fd1498Szrj }
4475*38fd1498Szrj
4476*38fd1498Szrj
4477*38fd1498Szrj
4478*38fd1498Szrj /* This page contains code for transformation of original reservations
4479*38fd1498Szrj described in .md file. The main goal of transformations is
4480*38fd1498Szrj simplifying reservation and lifting up all `|' on the top of IR
4481*38fd1498Szrj reservation representation. */
4482*38fd1498Szrj
4483*38fd1498Szrj
4484*38fd1498Szrj /* The following function makes copy of IR representation of
4485*38fd1498Szrj reservation. The function also substitutes all reservations
4486*38fd1498Szrj defined by define_reservation by corresponding value during making
4487*38fd1498Szrj the copy. */
4488*38fd1498Szrj static regexp_t
copy_insn_regexp(regexp_t regexp)4489*38fd1498Szrj copy_insn_regexp (regexp_t regexp)
4490*38fd1498Szrj {
4491*38fd1498Szrj regexp_t result;
4492*38fd1498Szrj int i;
4493*38fd1498Szrj
4494*38fd1498Szrj switch (regexp->mode)
4495*38fd1498Szrj {
4496*38fd1498Szrj case rm_reserv:
4497*38fd1498Szrj result = copy_insn_regexp (REGEXP_RESERV (regexp)->reserv_decl->regexp);
4498*38fd1498Szrj break;
4499*38fd1498Szrj
4500*38fd1498Szrj case rm_unit:
4501*38fd1498Szrj result = XCOPYNODE (struct regexp, regexp);
4502*38fd1498Szrj break;
4503*38fd1498Szrj
4504*38fd1498Szrj case rm_repeat:
4505*38fd1498Szrj result = XCOPYNODE (struct regexp, regexp);
4506*38fd1498Szrj REGEXP_REPEAT (result)->regexp
4507*38fd1498Szrj = copy_insn_regexp (REGEXP_REPEAT (regexp)->regexp);
4508*38fd1498Szrj break;
4509*38fd1498Szrj
4510*38fd1498Szrj case rm_sequence:
4511*38fd1498Szrj result = XCOPYNODEVAR (struct regexp, regexp,
4512*38fd1498Szrj sizeof (struct regexp) + sizeof (regexp_t)
4513*38fd1498Szrj * (REGEXP_SEQUENCE (regexp)->regexps_num - 1));
4514*38fd1498Szrj for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4515*38fd1498Szrj REGEXP_SEQUENCE (result)->regexps [i]
4516*38fd1498Szrj = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4517*38fd1498Szrj break;
4518*38fd1498Szrj
4519*38fd1498Szrj case rm_allof:
4520*38fd1498Szrj result = XCOPYNODEVAR (struct regexp, regexp,
4521*38fd1498Szrj sizeof (struct regexp) + sizeof (regexp_t)
4522*38fd1498Szrj * (REGEXP_ALLOF (regexp)->regexps_num - 1));
4523*38fd1498Szrj for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4524*38fd1498Szrj REGEXP_ALLOF (result)->regexps [i]
4525*38fd1498Szrj = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4526*38fd1498Szrj break;
4527*38fd1498Szrj
4528*38fd1498Szrj case rm_oneof:
4529*38fd1498Szrj result = XCOPYNODEVAR (struct regexp, regexp,
4530*38fd1498Szrj sizeof (struct regexp) + sizeof (regexp_t)
4531*38fd1498Szrj * (REGEXP_ONEOF (regexp)->regexps_num - 1));
4532*38fd1498Szrj for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4533*38fd1498Szrj REGEXP_ONEOF (result)->regexps [i]
4534*38fd1498Szrj = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4535*38fd1498Szrj break;
4536*38fd1498Szrj
4537*38fd1498Szrj case rm_nothing:
4538*38fd1498Szrj result = XCOPYNODE (struct regexp, regexp);
4539*38fd1498Szrj break;
4540*38fd1498Szrj
4541*38fd1498Szrj default:
4542*38fd1498Szrj gcc_unreachable ();
4543*38fd1498Szrj }
4544*38fd1498Szrj return result;
4545*38fd1498Szrj }
4546*38fd1498Szrj
4547*38fd1498Szrj /* The following variable is set up 1 if a transformation has been
4548*38fd1498Szrj applied. */
4549*38fd1498Szrj static int regexp_transformed_p;
4550*38fd1498Szrj
4551*38fd1498Szrj /* The function makes transformation
4552*38fd1498Szrj A*N -> A, A, ... */
4553*38fd1498Szrj static regexp_t
transform_1(regexp_t regexp)4554*38fd1498Szrj transform_1 (regexp_t regexp)
4555*38fd1498Szrj {
4556*38fd1498Szrj int i;
4557*38fd1498Szrj int repeat_num;
4558*38fd1498Szrj regexp_t operand;
4559*38fd1498Szrj pos_t pos;
4560*38fd1498Szrj
4561*38fd1498Szrj if (regexp->mode == rm_repeat)
4562*38fd1498Szrj {
4563*38fd1498Szrj repeat_num = REGEXP_REPEAT (regexp)->repeat_num;
4564*38fd1498Szrj gcc_assert (repeat_num > 1);
4565*38fd1498Szrj operand = REGEXP_REPEAT (regexp)->regexp;
4566*38fd1498Szrj pos = regexp->mode;
4567*38fd1498Szrj regexp = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4568*38fd1498Szrj + sizeof (regexp_t) * (repeat_num - 1));
4569*38fd1498Szrj regexp->mode = rm_sequence;
4570*38fd1498Szrj regexp->pos = pos;
4571*38fd1498Szrj REGEXP_SEQUENCE (regexp)->regexps_num = repeat_num;
4572*38fd1498Szrj for (i = 0; i < repeat_num; i++)
4573*38fd1498Szrj REGEXP_SEQUENCE (regexp)->regexps [i] = copy_insn_regexp (operand);
4574*38fd1498Szrj regexp_transformed_p = 1;
4575*38fd1498Szrj }
4576*38fd1498Szrj return regexp;
4577*38fd1498Szrj }
4578*38fd1498Szrj
4579*38fd1498Szrj /* The function makes transformations
4580*38fd1498Szrj ...,(A,B,...),C,... -> ...,A,B,...,C,...
4581*38fd1498Szrj ...+(A+B+...)+C+... -> ...+A+B+...+C+...
4582*38fd1498Szrj ...|(A|B|...)|C|... -> ...|A|B|...|C|... */
4583*38fd1498Szrj static regexp_t
transform_2(regexp_t regexp)4584*38fd1498Szrj transform_2 (regexp_t regexp)
4585*38fd1498Szrj {
4586*38fd1498Szrj if (regexp->mode == rm_sequence)
4587*38fd1498Szrj {
4588*38fd1498Szrj regexp_t sequence = NULL;
4589*38fd1498Szrj regexp_t result;
4590*38fd1498Szrj int sequence_index = 0;
4591*38fd1498Szrj int i, j;
4592*38fd1498Szrj
4593*38fd1498Szrj for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4594*38fd1498Szrj if (REGEXP_SEQUENCE (regexp)->regexps [i]->mode == rm_sequence)
4595*38fd1498Szrj {
4596*38fd1498Szrj sequence_index = i;
4597*38fd1498Szrj sequence = REGEXP_SEQUENCE (regexp)->regexps [i];
4598*38fd1498Szrj break;
4599*38fd1498Szrj }
4600*38fd1498Szrj if (i < REGEXP_SEQUENCE (regexp)->regexps_num)
4601*38fd1498Szrj {
4602*38fd1498Szrj gcc_assert (REGEXP_SEQUENCE (sequence)->regexps_num > 1
4603*38fd1498Szrj && REGEXP_SEQUENCE (regexp)->regexps_num > 1);
4604*38fd1498Szrj result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4605*38fd1498Szrj + sizeof (regexp_t)
4606*38fd1498Szrj * (REGEXP_SEQUENCE (regexp)->regexps_num
4607*38fd1498Szrj + REGEXP_SEQUENCE (sequence)->regexps_num
4608*38fd1498Szrj - 2));
4609*38fd1498Szrj result->mode = rm_sequence;
4610*38fd1498Szrj result->pos = regexp->pos;
4611*38fd1498Szrj REGEXP_SEQUENCE (result)->regexps_num
4612*38fd1498Szrj = (REGEXP_SEQUENCE (regexp)->regexps_num
4613*38fd1498Szrj + REGEXP_SEQUENCE (sequence)->regexps_num - 1);
4614*38fd1498Szrj for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4615*38fd1498Szrj if (i < sequence_index)
4616*38fd1498Szrj REGEXP_SEQUENCE (result)->regexps [i]
4617*38fd1498Szrj = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4618*38fd1498Szrj else if (i > sequence_index)
4619*38fd1498Szrj REGEXP_SEQUENCE (result)->regexps
4620*38fd1498Szrj [i + REGEXP_SEQUENCE (sequence)->regexps_num - 1]
4621*38fd1498Szrj = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4622*38fd1498Szrj else
4623*38fd1498Szrj for (j = 0; j < REGEXP_SEQUENCE (sequence)->regexps_num; j++)
4624*38fd1498Szrj REGEXP_SEQUENCE (result)->regexps [i + j]
4625*38fd1498Szrj = copy_insn_regexp (REGEXP_SEQUENCE (sequence)->regexps [j]);
4626*38fd1498Szrj regexp_transformed_p = 1;
4627*38fd1498Szrj regexp = result;
4628*38fd1498Szrj }
4629*38fd1498Szrj }
4630*38fd1498Szrj else if (regexp->mode == rm_allof)
4631*38fd1498Szrj {
4632*38fd1498Szrj regexp_t allof = NULL;
4633*38fd1498Szrj regexp_t result;
4634*38fd1498Szrj int allof_index = 0;
4635*38fd1498Szrj int i, j;
4636*38fd1498Szrj
4637*38fd1498Szrj for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4638*38fd1498Szrj if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_allof)
4639*38fd1498Szrj {
4640*38fd1498Szrj allof_index = i;
4641*38fd1498Szrj allof = REGEXP_ALLOF (regexp)->regexps [i];
4642*38fd1498Szrj break;
4643*38fd1498Szrj }
4644*38fd1498Szrj if (i < REGEXP_ALLOF (regexp)->regexps_num)
4645*38fd1498Szrj {
4646*38fd1498Szrj gcc_assert (REGEXP_ALLOF (allof)->regexps_num > 1
4647*38fd1498Szrj && REGEXP_ALLOF (regexp)->regexps_num > 1);
4648*38fd1498Szrj result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4649*38fd1498Szrj + sizeof (regexp_t)
4650*38fd1498Szrj * (REGEXP_ALLOF (regexp)->regexps_num
4651*38fd1498Szrj + REGEXP_ALLOF (allof)->regexps_num - 2));
4652*38fd1498Szrj result->mode = rm_allof;
4653*38fd1498Szrj result->pos = regexp->pos;
4654*38fd1498Szrj REGEXP_ALLOF (result)->regexps_num
4655*38fd1498Szrj = (REGEXP_ALLOF (regexp)->regexps_num
4656*38fd1498Szrj + REGEXP_ALLOF (allof)->regexps_num - 1);
4657*38fd1498Szrj for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4658*38fd1498Szrj if (i < allof_index)
4659*38fd1498Szrj REGEXP_ALLOF (result)->regexps [i]
4660*38fd1498Szrj = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4661*38fd1498Szrj else if (i > allof_index)
4662*38fd1498Szrj REGEXP_ALLOF (result)->regexps
4663*38fd1498Szrj [i + REGEXP_ALLOF (allof)->regexps_num - 1]
4664*38fd1498Szrj = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4665*38fd1498Szrj else
4666*38fd1498Szrj for (j = 0; j < REGEXP_ALLOF (allof)->regexps_num; j++)
4667*38fd1498Szrj REGEXP_ALLOF (result)->regexps [i + j]
4668*38fd1498Szrj = copy_insn_regexp (REGEXP_ALLOF (allof)->regexps [j]);
4669*38fd1498Szrj regexp_transformed_p = 1;
4670*38fd1498Szrj regexp = result;
4671*38fd1498Szrj }
4672*38fd1498Szrj }
4673*38fd1498Szrj else if (regexp->mode == rm_oneof)
4674*38fd1498Szrj {
4675*38fd1498Szrj regexp_t oneof = NULL;
4676*38fd1498Szrj regexp_t result;
4677*38fd1498Szrj int oneof_index = 0;
4678*38fd1498Szrj int i, j;
4679*38fd1498Szrj
4680*38fd1498Szrj for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4681*38fd1498Szrj if (REGEXP_ONEOF (regexp)->regexps [i]->mode == rm_oneof)
4682*38fd1498Szrj {
4683*38fd1498Szrj oneof_index = i;
4684*38fd1498Szrj oneof = REGEXP_ONEOF (regexp)->regexps [i];
4685*38fd1498Szrj break;
4686*38fd1498Szrj }
4687*38fd1498Szrj if (i < REGEXP_ONEOF (regexp)->regexps_num)
4688*38fd1498Szrj {
4689*38fd1498Szrj gcc_assert (REGEXP_ONEOF (oneof)->regexps_num > 1
4690*38fd1498Szrj && REGEXP_ONEOF (regexp)->regexps_num > 1);
4691*38fd1498Szrj result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4692*38fd1498Szrj + sizeof (regexp_t)
4693*38fd1498Szrj * (REGEXP_ONEOF (regexp)->regexps_num
4694*38fd1498Szrj + REGEXP_ONEOF (oneof)->regexps_num - 2));
4695*38fd1498Szrj result->mode = rm_oneof;
4696*38fd1498Szrj result->pos = regexp->pos;
4697*38fd1498Szrj REGEXP_ONEOF (result)->regexps_num
4698*38fd1498Szrj = (REGEXP_ONEOF (regexp)->regexps_num
4699*38fd1498Szrj + REGEXP_ONEOF (oneof)->regexps_num - 1);
4700*38fd1498Szrj for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4701*38fd1498Szrj if (i < oneof_index)
4702*38fd1498Szrj REGEXP_ONEOF (result)->regexps [i]
4703*38fd1498Szrj = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4704*38fd1498Szrj else if (i > oneof_index)
4705*38fd1498Szrj REGEXP_ONEOF (result)->regexps
4706*38fd1498Szrj [i + REGEXP_ONEOF (oneof)->regexps_num - 1]
4707*38fd1498Szrj = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4708*38fd1498Szrj else
4709*38fd1498Szrj for (j = 0; j < REGEXP_ONEOF (oneof)->regexps_num; j++)
4710*38fd1498Szrj REGEXP_ONEOF (result)->regexps [i + j]
4711*38fd1498Szrj = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [j]);
4712*38fd1498Szrj regexp_transformed_p = 1;
4713*38fd1498Szrj regexp = result;
4714*38fd1498Szrj }
4715*38fd1498Szrj }
4716*38fd1498Szrj return regexp;
4717*38fd1498Szrj }
4718*38fd1498Szrj
4719*38fd1498Szrj /* The function makes transformations
4720*38fd1498Szrj ...,A|B|...,C,... -> (...,A,C,...)|(...,B,C,...)|...
4721*38fd1498Szrj ...+(A|B|...)+C+... -> (...+A+C+...)|(...+B+C+...)|...
4722*38fd1498Szrj ...+(A,B,...)+C+... -> (...+A+C+...),B,...
4723*38fd1498Szrj ...+(A,B,...)+(C,D,...) -> (A+C),(B+D),... */
4724*38fd1498Szrj static regexp_t
transform_3(regexp_t regexp)4725*38fd1498Szrj transform_3 (regexp_t regexp)
4726*38fd1498Szrj {
4727*38fd1498Szrj if (regexp->mode == rm_sequence)
4728*38fd1498Szrj {
4729*38fd1498Szrj regexp_t oneof = NULL;
4730*38fd1498Szrj int oneof_index = 0;
4731*38fd1498Szrj regexp_t result;
4732*38fd1498Szrj regexp_t sequence;
4733*38fd1498Szrj int i, j;
4734*38fd1498Szrj
4735*38fd1498Szrj for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4736*38fd1498Szrj if (REGEXP_SEQUENCE (regexp)->regexps [i]->mode == rm_oneof)
4737*38fd1498Szrj {
4738*38fd1498Szrj oneof_index = i;
4739*38fd1498Szrj oneof = REGEXP_SEQUENCE (regexp)->regexps [i];
4740*38fd1498Szrj break;
4741*38fd1498Szrj }
4742*38fd1498Szrj if (i < REGEXP_SEQUENCE (regexp)->regexps_num)
4743*38fd1498Szrj {
4744*38fd1498Szrj gcc_assert (REGEXP_ONEOF (oneof)->regexps_num > 1
4745*38fd1498Szrj && REGEXP_SEQUENCE (regexp)->regexps_num > 1);
4746*38fd1498Szrj result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4747*38fd1498Szrj + sizeof (regexp_t)
4748*38fd1498Szrj * (REGEXP_ONEOF (oneof)->regexps_num - 1));
4749*38fd1498Szrj result->mode = rm_oneof;
4750*38fd1498Szrj result->pos = regexp->pos;
4751*38fd1498Szrj REGEXP_ONEOF (result)->regexps_num
4752*38fd1498Szrj = REGEXP_ONEOF (oneof)->regexps_num;
4753*38fd1498Szrj for (i = 0; i < REGEXP_ONEOF (result)->regexps_num; i++)
4754*38fd1498Szrj {
4755*38fd1498Szrj sequence
4756*38fd1498Szrj = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4757*38fd1498Szrj + sizeof (regexp_t)
4758*38fd1498Szrj * (REGEXP_SEQUENCE (regexp)->regexps_num - 1));
4759*38fd1498Szrj sequence->mode = rm_sequence;
4760*38fd1498Szrj sequence->pos = regexp->pos;
4761*38fd1498Szrj REGEXP_SEQUENCE (sequence)->regexps_num
4762*38fd1498Szrj = REGEXP_SEQUENCE (regexp)->regexps_num;
4763*38fd1498Szrj REGEXP_ONEOF (result)->regexps [i] = sequence;
4764*38fd1498Szrj for (j = 0; j < REGEXP_SEQUENCE (sequence)->regexps_num; j++)
4765*38fd1498Szrj if (j != oneof_index)
4766*38fd1498Szrj REGEXP_SEQUENCE (sequence)->regexps [j]
4767*38fd1498Szrj = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [j]);
4768*38fd1498Szrj else
4769*38fd1498Szrj REGEXP_SEQUENCE (sequence)->regexps [j]
4770*38fd1498Szrj = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [i]);
4771*38fd1498Szrj }
4772*38fd1498Szrj regexp_transformed_p = 1;
4773*38fd1498Szrj regexp = result;
4774*38fd1498Szrj }
4775*38fd1498Szrj }
4776*38fd1498Szrj else if (regexp->mode == rm_allof)
4777*38fd1498Szrj {
4778*38fd1498Szrj regexp_t oneof = NULL;
4779*38fd1498Szrj regexp_t seq;
4780*38fd1498Szrj int oneof_index = 0;
4781*38fd1498Szrj int max_seq_length, allof_length;
4782*38fd1498Szrj regexp_t result;
4783*38fd1498Szrj regexp_t allof = NULL;
4784*38fd1498Szrj regexp_t allof_op = NULL;
4785*38fd1498Szrj int i, j;
4786*38fd1498Szrj
4787*38fd1498Szrj for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4788*38fd1498Szrj if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_oneof)
4789*38fd1498Szrj {
4790*38fd1498Szrj oneof_index = i;
4791*38fd1498Szrj oneof = REGEXP_ALLOF (regexp)->regexps [i];
4792*38fd1498Szrj break;
4793*38fd1498Szrj }
4794*38fd1498Szrj if (i < REGEXP_ALLOF (regexp)->regexps_num)
4795*38fd1498Szrj {
4796*38fd1498Szrj gcc_assert (REGEXP_ONEOF (oneof)->regexps_num > 1
4797*38fd1498Szrj && REGEXP_ALLOF (regexp)->regexps_num > 1);
4798*38fd1498Szrj result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4799*38fd1498Szrj + sizeof (regexp_t)
4800*38fd1498Szrj * (REGEXP_ONEOF (oneof)->regexps_num - 1));
4801*38fd1498Szrj result->mode = rm_oneof;
4802*38fd1498Szrj result->pos = regexp->pos;
4803*38fd1498Szrj REGEXP_ONEOF (result)->regexps_num
4804*38fd1498Szrj = REGEXP_ONEOF (oneof)->regexps_num;
4805*38fd1498Szrj for (i = 0; i < REGEXP_ONEOF (result)->regexps_num; i++)
4806*38fd1498Szrj {
4807*38fd1498Szrj allof
4808*38fd1498Szrj = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4809*38fd1498Szrj + sizeof (regexp_t)
4810*38fd1498Szrj * (REGEXP_ALLOF (regexp)->regexps_num - 1));
4811*38fd1498Szrj allof->mode = rm_allof;
4812*38fd1498Szrj allof->pos = regexp->pos;
4813*38fd1498Szrj REGEXP_ALLOF (allof)->regexps_num
4814*38fd1498Szrj = REGEXP_ALLOF (regexp)->regexps_num;
4815*38fd1498Szrj REGEXP_ONEOF (result)->regexps [i] = allof;
4816*38fd1498Szrj for (j = 0; j < REGEXP_ALLOF (allof)->regexps_num; j++)
4817*38fd1498Szrj if (j != oneof_index)
4818*38fd1498Szrj REGEXP_ALLOF (allof)->regexps [j]
4819*38fd1498Szrj = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [j]);
4820*38fd1498Szrj else
4821*38fd1498Szrj REGEXP_ALLOF (allof)->regexps [j]
4822*38fd1498Szrj = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [i]);
4823*38fd1498Szrj }
4824*38fd1498Szrj regexp_transformed_p = 1;
4825*38fd1498Szrj regexp = result;
4826*38fd1498Szrj }
4827*38fd1498Szrj max_seq_length = 0;
4828*38fd1498Szrj if (regexp->mode == rm_allof)
4829*38fd1498Szrj for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4830*38fd1498Szrj {
4831*38fd1498Szrj switch (REGEXP_ALLOF (regexp)->regexps [i]->mode)
4832*38fd1498Szrj {
4833*38fd1498Szrj case rm_sequence:
4834*38fd1498Szrj seq = REGEXP_ALLOF (regexp)->regexps [i];
4835*38fd1498Szrj if (max_seq_length < REGEXP_SEQUENCE (seq)->regexps_num)
4836*38fd1498Szrj max_seq_length = REGEXP_SEQUENCE (seq)->regexps_num;
4837*38fd1498Szrj break;
4838*38fd1498Szrj
4839*38fd1498Szrj case rm_unit:
4840*38fd1498Szrj case rm_nothing:
4841*38fd1498Szrj break;
4842*38fd1498Szrj
4843*38fd1498Szrj default:
4844*38fd1498Szrj max_seq_length = 0;
4845*38fd1498Szrj goto break_for;
4846*38fd1498Szrj }
4847*38fd1498Szrj }
4848*38fd1498Szrj break_for:
4849*38fd1498Szrj if (max_seq_length != 0)
4850*38fd1498Szrj {
4851*38fd1498Szrj gcc_assert (max_seq_length != 1
4852*38fd1498Szrj && REGEXP_ALLOF (regexp)->regexps_num > 1);
4853*38fd1498Szrj result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4854*38fd1498Szrj + sizeof (regexp_t) * (max_seq_length - 1));
4855*38fd1498Szrj result->mode = rm_sequence;
4856*38fd1498Szrj result->pos = regexp->pos;
4857*38fd1498Szrj REGEXP_SEQUENCE (result)->regexps_num = max_seq_length;
4858*38fd1498Szrj for (i = 0; i < max_seq_length; i++)
4859*38fd1498Szrj {
4860*38fd1498Szrj allof_length = 0;
4861*38fd1498Szrj for (j = 0; j < REGEXP_ALLOF (regexp)->regexps_num; j++)
4862*38fd1498Szrj switch (REGEXP_ALLOF (regexp)->regexps [j]->mode)
4863*38fd1498Szrj {
4864*38fd1498Szrj case rm_sequence:
4865*38fd1498Szrj if (i < (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4866*38fd1498Szrj ->regexps [j])->regexps_num))
4867*38fd1498Szrj {
4868*38fd1498Szrj allof_op
4869*38fd1498Szrj = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4870*38fd1498Szrj ->regexps [j])
4871*38fd1498Szrj ->regexps [i]);
4872*38fd1498Szrj allof_length++;
4873*38fd1498Szrj }
4874*38fd1498Szrj break;
4875*38fd1498Szrj case rm_unit:
4876*38fd1498Szrj case rm_nothing:
4877*38fd1498Szrj if (i == 0)
4878*38fd1498Szrj {
4879*38fd1498Szrj allof_op = REGEXP_ALLOF (regexp)->regexps [j];
4880*38fd1498Szrj allof_length++;
4881*38fd1498Szrj }
4882*38fd1498Szrj break;
4883*38fd1498Szrj default:
4884*38fd1498Szrj break;
4885*38fd1498Szrj }
4886*38fd1498Szrj
4887*38fd1498Szrj if (allof_length == 1)
4888*38fd1498Szrj REGEXP_SEQUENCE (result)->regexps [i] = allof_op;
4889*38fd1498Szrj else
4890*38fd1498Szrj {
4891*38fd1498Szrj allof = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4892*38fd1498Szrj + sizeof (regexp_t)
4893*38fd1498Szrj * (allof_length - 1));
4894*38fd1498Szrj allof->mode = rm_allof;
4895*38fd1498Szrj allof->pos = regexp->pos;
4896*38fd1498Szrj REGEXP_ALLOF (allof)->regexps_num = allof_length;
4897*38fd1498Szrj REGEXP_SEQUENCE (result)->regexps [i] = allof;
4898*38fd1498Szrj allof_length = 0;
4899*38fd1498Szrj for (j = 0; j < REGEXP_ALLOF (regexp)->regexps_num; j++)
4900*38fd1498Szrj if (REGEXP_ALLOF (regexp)->regexps [j]->mode == rm_sequence
4901*38fd1498Szrj && (i <
4902*38fd1498Szrj (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4903*38fd1498Szrj ->regexps [j])->regexps_num)))
4904*38fd1498Szrj {
4905*38fd1498Szrj allof_op = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4906*38fd1498Szrj ->regexps [j])
4907*38fd1498Szrj ->regexps [i]);
4908*38fd1498Szrj REGEXP_ALLOF (allof)->regexps [allof_length]
4909*38fd1498Szrj = allof_op;
4910*38fd1498Szrj allof_length++;
4911*38fd1498Szrj }
4912*38fd1498Szrj else if (i == 0
4913*38fd1498Szrj && (REGEXP_ALLOF (regexp)->regexps [j]->mode
4914*38fd1498Szrj == rm_unit
4915*38fd1498Szrj || (REGEXP_ALLOF (regexp)->regexps [j]->mode
4916*38fd1498Szrj == rm_nothing)))
4917*38fd1498Szrj {
4918*38fd1498Szrj allof_op = REGEXP_ALLOF (regexp)->regexps [j];
4919*38fd1498Szrj REGEXP_ALLOF (allof)->regexps [allof_length]
4920*38fd1498Szrj = allof_op;
4921*38fd1498Szrj allof_length++;
4922*38fd1498Szrj }
4923*38fd1498Szrj }
4924*38fd1498Szrj }
4925*38fd1498Szrj regexp_transformed_p = 1;
4926*38fd1498Szrj regexp = result;
4927*38fd1498Szrj }
4928*38fd1498Szrj }
4929*38fd1498Szrj return regexp;
4930*38fd1498Szrj }
4931*38fd1498Szrj
4932*38fd1498Szrj /* The function traverses IR of reservation and applies transformations
4933*38fd1498Szrj implemented by FUNC. */
4934*38fd1498Szrj static regexp_t
regexp_transform_func(regexp_t regexp,regexp_t (* func)(regexp_t regexp))4935*38fd1498Szrj regexp_transform_func (regexp_t regexp, regexp_t (*func) (regexp_t regexp))
4936*38fd1498Szrj {
4937*38fd1498Szrj int i;
4938*38fd1498Szrj
4939*38fd1498Szrj switch (regexp->mode)
4940*38fd1498Szrj {
4941*38fd1498Szrj case rm_sequence:
4942*38fd1498Szrj for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4943*38fd1498Szrj REGEXP_SEQUENCE (regexp)->regexps [i]
4944*38fd1498Szrj = regexp_transform_func (REGEXP_SEQUENCE (regexp)->regexps [i],
4945*38fd1498Szrj func);
4946*38fd1498Szrj break;
4947*38fd1498Szrj
4948*38fd1498Szrj case rm_allof:
4949*38fd1498Szrj for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4950*38fd1498Szrj REGEXP_ALLOF (regexp)->regexps [i]
4951*38fd1498Szrj = regexp_transform_func (REGEXP_ALLOF (regexp)->regexps [i], func);
4952*38fd1498Szrj break;
4953*38fd1498Szrj
4954*38fd1498Szrj case rm_oneof:
4955*38fd1498Szrj for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4956*38fd1498Szrj REGEXP_ONEOF (regexp)->regexps [i]
4957*38fd1498Szrj = regexp_transform_func (REGEXP_ONEOF (regexp)->regexps [i], func);
4958*38fd1498Szrj break;
4959*38fd1498Szrj
4960*38fd1498Szrj case rm_repeat:
4961*38fd1498Szrj REGEXP_REPEAT (regexp)->regexp
4962*38fd1498Szrj = regexp_transform_func (REGEXP_REPEAT (regexp)->regexp, func);
4963*38fd1498Szrj break;
4964*38fd1498Szrj
4965*38fd1498Szrj case rm_nothing:
4966*38fd1498Szrj case rm_unit:
4967*38fd1498Szrj break;
4968*38fd1498Szrj
4969*38fd1498Szrj default:
4970*38fd1498Szrj gcc_unreachable ();
4971*38fd1498Szrj }
4972*38fd1498Szrj return (*func) (regexp);
4973*38fd1498Szrj }
4974*38fd1498Szrj
4975*38fd1498Szrj /* The function applies all transformations for IR representation of
4976*38fd1498Szrj reservation REGEXP. */
4977*38fd1498Szrj static regexp_t
transform_regexp(regexp_t regexp)4978*38fd1498Szrj transform_regexp (regexp_t regexp)
4979*38fd1498Szrj {
4980*38fd1498Szrj regexp = regexp_transform_func (regexp, transform_1);
4981*38fd1498Szrj do
4982*38fd1498Szrj {
4983*38fd1498Szrj regexp_transformed_p = 0;
4984*38fd1498Szrj regexp = regexp_transform_func (regexp, transform_2);
4985*38fd1498Szrj regexp = regexp_transform_func (regexp, transform_3);
4986*38fd1498Szrj }
4987*38fd1498Szrj while (regexp_transformed_p);
4988*38fd1498Szrj return regexp;
4989*38fd1498Szrj }
4990*38fd1498Szrj
4991*38fd1498Szrj /* The function applies all transformations for reservations of all
4992*38fd1498Szrj insn declarations. */
4993*38fd1498Szrj static void
transform_insn_regexps(void)4994*38fd1498Szrj transform_insn_regexps (void)
4995*38fd1498Szrj {
4996*38fd1498Szrj decl_t decl;
4997*38fd1498Szrj int i;
4998*38fd1498Szrj
4999*38fd1498Szrj transform_time = create_ticker ();
5000*38fd1498Szrj add_advance_cycle_insn_decl ();
5001*38fd1498Szrj if (collapse_flag)
5002*38fd1498Szrj add_collapse_ndfa_insn_decl ();
5003*38fd1498Szrj if (progress_flag)
5004*38fd1498Szrj fprintf (stderr, "Reservation transformation...");
5005*38fd1498Szrj for (i = 0; i < description->normal_decls_num; i++)
5006*38fd1498Szrj {
5007*38fd1498Szrj decl = description->decls [i];
5008*38fd1498Szrj if (decl->mode == dm_insn_reserv)
5009*38fd1498Szrj DECL_INSN_RESERV (decl)->transformed_regexp
5010*38fd1498Szrj = transform_regexp (copy_insn_regexp
5011*38fd1498Szrj (DECL_INSN_RESERV (decl)->regexp));
5012*38fd1498Szrj }
5013*38fd1498Szrj if (progress_flag)
5014*38fd1498Szrj fprintf (stderr, "done\n");
5015*38fd1498Szrj ticker_off (&transform_time);
5016*38fd1498Szrj }
5017*38fd1498Szrj
5018*38fd1498Szrj
5019*38fd1498Szrj
5020*38fd1498Szrj /* The following variable value is TRUE if the first annotated message
5021*38fd1498Szrj about units to automata distribution has been output. */
5022*38fd1498Szrj static int annotation_message_reported_p;
5023*38fd1498Szrj
5024*38fd1498Szrj /* The vector contains all decls which are automata. */
5025*38fd1498Szrj static vec<decl_t> automaton_decls;
5026*38fd1498Szrj
5027*38fd1498Szrj /* The following structure describes usage of a unit in a reservation. */
5028*38fd1498Szrj struct unit_usage
5029*38fd1498Szrj {
5030*38fd1498Szrj unit_decl_t unit_decl;
5031*38fd1498Szrj /* The following forms a list of units used on the same cycle in the
5032*38fd1498Szrj same alternative. The list is ordered by the correspdoning unit
5033*38fd1498Szrj declarations and there is no unit declaration duplication in the
5034*38fd1498Szrj list. */
5035*38fd1498Szrj struct unit_usage *next;
5036*38fd1498Szrj };
5037*38fd1498Szrj typedef struct unit_usage *unit_usage_t;
5038*38fd1498Szrj
5039*38fd1498Szrj
5040*38fd1498Szrj /* Obstack for unit_usage structures. */
5041*38fd1498Szrj static struct obstack unit_usages;
5042*38fd1498Szrj
5043*38fd1498Szrj /* VLA for representation of array of pointers to unit usage
5044*38fd1498Szrj structures. There is an element for each combination of
5045*38fd1498Szrj (alternative number, cycle). Unit usages on given cycle in
5046*38fd1498Szrj alternative with given number are referred through element with
5047*38fd1498Szrj index equals to the cycle * number of all alternatives in the
5048*38fd1498Szrj regexp + the alternative number. */
5049*38fd1498Szrj static vec<unit_usage_t> cycle_alt_unit_usages;
5050*38fd1498Szrj
5051*38fd1498Szrj /* The following function creates the structure unit_usage for UNIT on
5052*38fd1498Szrj CYCLE in REGEXP alternative with ALT_NUM. The structure is made
5053*38fd1498Szrj accessed through cycle_alt_unit_usages. */
5054*38fd1498Szrj static void
store_alt_unit_usage(regexp_t regexp,regexp_t unit,int cycle,int alt_num)5055*38fd1498Szrj store_alt_unit_usage (regexp_t regexp, regexp_t unit, int cycle,
5056*38fd1498Szrj int alt_num)
5057*38fd1498Szrj {
5058*38fd1498Szrj size_t length;
5059*38fd1498Szrj unit_decl_t unit_decl;
5060*38fd1498Szrj unit_usage_t unit_usage_ptr, curr, prev;
5061*38fd1498Szrj int index;
5062*38fd1498Szrj
5063*38fd1498Szrj gcc_assert (regexp && regexp->mode == rm_oneof
5064*38fd1498Szrj && alt_num < REGEXP_ONEOF (regexp)->regexps_num);
5065*38fd1498Szrj unit_decl = REGEXP_UNIT (unit)->unit_decl;
5066*38fd1498Szrj
5067*38fd1498Szrj length = (cycle + 1) * REGEXP_ONEOF (regexp)->regexps_num;
5068*38fd1498Szrj while (cycle_alt_unit_usages.length () < length)
5069*38fd1498Szrj cycle_alt_unit_usages.safe_push (NULL);
5070*38fd1498Szrj
5071*38fd1498Szrj index = cycle * REGEXP_ONEOF (regexp)->regexps_num + alt_num;
5072*38fd1498Szrj prev = NULL;
5073*38fd1498Szrj for (curr = cycle_alt_unit_usages[index];
5074*38fd1498Szrj curr != NULL;
5075*38fd1498Szrj prev = curr, curr = curr->next)
5076*38fd1498Szrj if (curr->unit_decl >= unit_decl)
5077*38fd1498Szrj break;
5078*38fd1498Szrj if (curr != NULL && curr->unit_decl == unit_decl)
5079*38fd1498Szrj return;
5080*38fd1498Szrj obstack_blank (&unit_usages, sizeof (struct unit_usage));
5081*38fd1498Szrj unit_usage_ptr = (struct unit_usage *) obstack_base (&unit_usages);
5082*38fd1498Szrj obstack_finish (&unit_usages);
5083*38fd1498Szrj unit_usage_ptr->unit_decl = unit_decl;
5084*38fd1498Szrj unit_decl->last_distribution_check_cycle = -1; /* undefined */
5085*38fd1498Szrj unit_usage_ptr->next = curr;
5086*38fd1498Szrj if (prev == NULL)
5087*38fd1498Szrj cycle_alt_unit_usages[index] = unit_usage_ptr;
5088*38fd1498Szrj else
5089*38fd1498Szrj prev->next = unit_usage_ptr;
5090*38fd1498Szrj }
5091*38fd1498Szrj
5092*38fd1498Szrj /* Return true if unit UNIT_DECL is present on the LIST. */
5093*38fd1498Szrj static bool
unit_present_on_list_p(unit_usage_t list,unit_decl_t unit_decl)5094*38fd1498Szrj unit_present_on_list_p (unit_usage_t list, unit_decl_t unit_decl)
5095*38fd1498Szrj {
5096*38fd1498Szrj while (list != NULL)
5097*38fd1498Szrj {
5098*38fd1498Szrj if (list->unit_decl == unit_decl)
5099*38fd1498Szrj return true;
5100*38fd1498Szrj list = list->next;
5101*38fd1498Szrj }
5102*38fd1498Szrj return false;
5103*38fd1498Szrj }
5104*38fd1498Szrj
5105*38fd1498Szrj /* The function returns true if reservations of alternatives ALT1 and
5106*38fd1498Szrj ALT2 are equal after excluding reservations of units of
5107*38fd1498Szrj EXCLUDED_AUTOMATON_DECL. */
5108*38fd1498Szrj static bool
equal_alternatives_p(int alt1,int alt2,int n_alts,struct automaton_decl * excluded_automaton_decl)5109*38fd1498Szrj equal_alternatives_p (int alt1, int alt2, int n_alts,
5110*38fd1498Szrj struct automaton_decl *excluded_automaton_decl)
5111*38fd1498Szrj {
5112*38fd1498Szrj int i;
5113*38fd1498Szrj unit_usage_t list1, list2;
5114*38fd1498Szrj
5115*38fd1498Szrj for (i = 0;
5116*38fd1498Szrj i < (int) cycle_alt_unit_usages.length ();
5117*38fd1498Szrj i += n_alts)
5118*38fd1498Szrj {
5119*38fd1498Szrj for (list1 = cycle_alt_unit_usages[i + alt1],
5120*38fd1498Szrj list2 = cycle_alt_unit_usages[i + alt2];;
5121*38fd1498Szrj list1 = list1->next, list2 = list2->next)
5122*38fd1498Szrj {
5123*38fd1498Szrj while (list1 != NULL
5124*38fd1498Szrj && list1->unit_decl->automaton_decl == excluded_automaton_decl)
5125*38fd1498Szrj list1 = list1->next;
5126*38fd1498Szrj while (list2 != NULL
5127*38fd1498Szrj && list2->unit_decl->automaton_decl == excluded_automaton_decl)
5128*38fd1498Szrj list2 = list2->next;
5129*38fd1498Szrj if (list1 == NULL || list2 == NULL)
5130*38fd1498Szrj {
5131*38fd1498Szrj if (list1 != list2)
5132*38fd1498Szrj return false;
5133*38fd1498Szrj else
5134*38fd1498Szrj break;
5135*38fd1498Szrj }
5136*38fd1498Szrj if (list1->unit_decl != list2->unit_decl)
5137*38fd1498Szrj return false;
5138*38fd1498Szrj }
5139*38fd1498Szrj }
5140*38fd1498Szrj return true;
5141*38fd1498Szrj }
5142*38fd1498Szrj
5143*38fd1498Szrj
5144*38fd1498Szrj /* The function processes given REGEXP to find units with the wrong
5145*38fd1498Szrj distribution. */
5146*38fd1498Szrj static void
check_regexp_units_distribution(const char * insn_reserv_name,regexp_t regexp)5147*38fd1498Szrj check_regexp_units_distribution (const char *insn_reserv_name,
5148*38fd1498Szrj regexp_t regexp)
5149*38fd1498Szrj {
5150*38fd1498Szrj int i, j, k, cycle, start, n_alts, alt, alt2;
5151*38fd1498Szrj bool annotation_reservation_message_reported_p;
5152*38fd1498Szrj regexp_t seq, allof, unit;
5153*38fd1498Szrj struct unit_usage *unit_usage_ptr;
5154*38fd1498Szrj
5155*38fd1498Szrj if (regexp == NULL || regexp->mode != rm_oneof)
5156*38fd1498Szrj return;
5157*38fd1498Szrj /* Store all unit usages in the regexp: */
5158*38fd1498Szrj obstack_init (&unit_usages);
5159*38fd1498Szrj cycle_alt_unit_usages.create (10);
5160*38fd1498Szrj
5161*38fd1498Szrj for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
5162*38fd1498Szrj {
5163*38fd1498Szrj seq = REGEXP_ONEOF (regexp)->regexps [i];
5164*38fd1498Szrj switch (seq->mode)
5165*38fd1498Szrj {
5166*38fd1498Szrj case rm_sequence:
5167*38fd1498Szrj for (j = 0; j < REGEXP_SEQUENCE (seq)->regexps_num; j++)
5168*38fd1498Szrj {
5169*38fd1498Szrj allof = REGEXP_SEQUENCE (seq)->regexps [j];
5170*38fd1498Szrj switch (allof->mode)
5171*38fd1498Szrj {
5172*38fd1498Szrj case rm_allof:
5173*38fd1498Szrj for (k = 0; k < REGEXP_ALLOF (allof)->regexps_num; k++)
5174*38fd1498Szrj {
5175*38fd1498Szrj unit = REGEXP_ALLOF (allof)->regexps [k];
5176*38fd1498Szrj if (unit->mode == rm_unit)
5177*38fd1498Szrj store_alt_unit_usage (regexp, unit, j, i);
5178*38fd1498Szrj else
5179*38fd1498Szrj gcc_assert (unit->mode == rm_nothing);
5180*38fd1498Szrj }
5181*38fd1498Szrj break;
5182*38fd1498Szrj
5183*38fd1498Szrj case rm_unit:
5184*38fd1498Szrj store_alt_unit_usage (regexp, allof, j, i);
5185*38fd1498Szrj break;
5186*38fd1498Szrj
5187*38fd1498Szrj case rm_nothing:
5188*38fd1498Szrj break;
5189*38fd1498Szrj
5190*38fd1498Szrj default:
5191*38fd1498Szrj gcc_unreachable ();
5192*38fd1498Szrj }
5193*38fd1498Szrj }
5194*38fd1498Szrj break;
5195*38fd1498Szrj
5196*38fd1498Szrj case rm_allof:
5197*38fd1498Szrj for (k = 0; k < REGEXP_ALLOF (seq)->regexps_num; k++)
5198*38fd1498Szrj {
5199*38fd1498Szrj unit = REGEXP_ALLOF (seq)->regexps [k];
5200*38fd1498Szrj switch (unit->mode)
5201*38fd1498Szrj {
5202*38fd1498Szrj case rm_unit:
5203*38fd1498Szrj store_alt_unit_usage (regexp, unit, 0, i);
5204*38fd1498Szrj break;
5205*38fd1498Szrj
5206*38fd1498Szrj case rm_nothing:
5207*38fd1498Szrj break;
5208*38fd1498Szrj
5209*38fd1498Szrj default:
5210*38fd1498Szrj gcc_unreachable ();
5211*38fd1498Szrj }
5212*38fd1498Szrj }
5213*38fd1498Szrj break;
5214*38fd1498Szrj
5215*38fd1498Szrj case rm_unit:
5216*38fd1498Szrj store_alt_unit_usage (regexp, seq, 0, i);
5217*38fd1498Szrj break;
5218*38fd1498Szrj
5219*38fd1498Szrj case rm_nothing:
5220*38fd1498Szrj break;
5221*38fd1498Szrj
5222*38fd1498Szrj default:
5223*38fd1498Szrj gcc_unreachable ();
5224*38fd1498Szrj }
5225*38fd1498Szrj }
5226*38fd1498Szrj /* Check distribution: */
5227*38fd1498Szrj for (i = 0; i < (int) cycle_alt_unit_usages.length (); i++)
5228*38fd1498Szrj for (unit_usage_ptr = cycle_alt_unit_usages[i];
5229*38fd1498Szrj unit_usage_ptr != NULL;
5230*38fd1498Szrj unit_usage_ptr = unit_usage_ptr->next)
5231*38fd1498Szrj unit_usage_ptr->unit_decl->last_distribution_check_cycle = -1;
5232*38fd1498Szrj n_alts = REGEXP_ONEOF (regexp)->regexps_num;
5233*38fd1498Szrj auto_vec<int> marked (n_alts);
5234*38fd1498Szrj for (i = 0; i < n_alts; i++)
5235*38fd1498Szrj marked.safe_push (0);
5236*38fd1498Szrj annotation_reservation_message_reported_p = false;
5237*38fd1498Szrj for (i = 0; i < (int) cycle_alt_unit_usages.length (); i++)
5238*38fd1498Szrj {
5239*38fd1498Szrj cycle = i / n_alts;
5240*38fd1498Szrj start = cycle * n_alts;
5241*38fd1498Szrj for (unit_usage_ptr = cycle_alt_unit_usages[i];
5242*38fd1498Szrj unit_usage_ptr != NULL;
5243*38fd1498Szrj unit_usage_ptr = unit_usage_ptr->next)
5244*38fd1498Szrj {
5245*38fd1498Szrj if (unit_usage_ptr->unit_decl->last_distribution_check_cycle == cycle)
5246*38fd1498Szrj continue;
5247*38fd1498Szrj unit_usage_ptr->unit_decl->last_distribution_check_cycle = cycle;
5248*38fd1498Szrj for (alt = 0; alt < n_alts; alt++)
5249*38fd1498Szrj if (! unit_present_on_list_p (cycle_alt_unit_usages[start + alt],
5250*38fd1498Szrj unit_usage_ptr->unit_decl))
5251*38fd1498Szrj break;
5252*38fd1498Szrj if (alt >= n_alts)
5253*38fd1498Szrj continue;
5254*38fd1498Szrj memset (marked.address (), 0, n_alts * sizeof (int));
5255*38fd1498Szrj for (alt = 0; alt < n_alts; alt++)
5256*38fd1498Szrj {
5257*38fd1498Szrj if (! unit_present_on_list_p (cycle_alt_unit_usages[start + alt],
5258*38fd1498Szrj unit_usage_ptr->unit_decl))
5259*38fd1498Szrj continue;
5260*38fd1498Szrj for (j = 0;
5261*38fd1498Szrj j < (int) cycle_alt_unit_usages.length ();
5262*38fd1498Szrj j++)
5263*38fd1498Szrj {
5264*38fd1498Szrj alt2 = j % n_alts;
5265*38fd1498Szrj if (! unit_present_on_list_p
5266*38fd1498Szrj (cycle_alt_unit_usages[start + alt2],
5267*38fd1498Szrj unit_usage_ptr->unit_decl)
5268*38fd1498Szrj && equal_alternatives_p (alt, alt2, n_alts,
5269*38fd1498Szrj unit_usage_ptr
5270*38fd1498Szrj ->unit_decl->automaton_decl))
5271*38fd1498Szrj {
5272*38fd1498Szrj marked[alt] = 1;
5273*38fd1498Szrj marked[alt2] = 1;
5274*38fd1498Szrj }
5275*38fd1498Szrj }
5276*38fd1498Szrj }
5277*38fd1498Szrj for (alt = 0; alt < n_alts && marked[alt]; alt++)
5278*38fd1498Szrj ;
5279*38fd1498Szrj if (alt < n_alts && 0)
5280*38fd1498Szrj {
5281*38fd1498Szrj if (! annotation_message_reported_p)
5282*38fd1498Szrj {
5283*38fd1498Szrj fprintf (stderr, "\n");
5284*38fd1498Szrj error ("The following units do not satisfy units-automata distribution rule");
5285*38fd1498Szrj error ("(Unit presence on one alt and its absence on other alt\n");
5286*38fd1498Szrj error (" result in different other automata reservations)");
5287*38fd1498Szrj annotation_message_reported_p = TRUE;
5288*38fd1498Szrj }
5289*38fd1498Szrj if (! annotation_reservation_message_reported_p)
5290*38fd1498Szrj {
5291*38fd1498Szrj error ("Reserv %s:", insn_reserv_name);
5292*38fd1498Szrj annotation_reservation_message_reported_p = true;
5293*38fd1498Szrj }
5294*38fd1498Szrj error (" Unit %s, cycle %d, alt %d, another alt %d",
5295*38fd1498Szrj unit_usage_ptr->unit_decl->name, cycle, i % n_alts, alt);
5296*38fd1498Szrj }
5297*38fd1498Szrj }
5298*38fd1498Szrj }
5299*38fd1498Szrj cycle_alt_unit_usages.release ();
5300*38fd1498Szrj obstack_free (&unit_usages, NULL);
5301*38fd1498Szrj }
5302*38fd1498Szrj
5303*38fd1498Szrj /* The function finds units which violates units to automata
5304*38fd1498Szrj distribution rule. If the units exist, report about them. */
5305*38fd1498Szrj static void
check_unit_distributions_to_automata(void)5306*38fd1498Szrj check_unit_distributions_to_automata (void)
5307*38fd1498Szrj {
5308*38fd1498Szrj decl_t decl;
5309*38fd1498Szrj int i;
5310*38fd1498Szrj
5311*38fd1498Szrj if (progress_flag)
5312*38fd1498Szrj fprintf (stderr, "Check unit distributions to automata...");
5313*38fd1498Szrj automaton_decls.create (0);
5314*38fd1498Szrj for (i = 0; i < description->decls_num; i++)
5315*38fd1498Szrj {
5316*38fd1498Szrj decl = description->decls [i];
5317*38fd1498Szrj if (decl->mode == dm_automaton)
5318*38fd1498Szrj automaton_decls.safe_push (decl);
5319*38fd1498Szrj }
5320*38fd1498Szrj if (automaton_decls.length () > 1)
5321*38fd1498Szrj {
5322*38fd1498Szrj annotation_message_reported_p = FALSE;
5323*38fd1498Szrj for (i = 0; i < description->decls_num; i++)
5324*38fd1498Szrj {
5325*38fd1498Szrj decl = description->decls [i];
5326*38fd1498Szrj if (decl->mode == dm_insn_reserv)
5327*38fd1498Szrj check_regexp_units_distribution
5328*38fd1498Szrj (DECL_INSN_RESERV (decl)->name,
5329*38fd1498Szrj DECL_INSN_RESERV (decl)->transformed_regexp);
5330*38fd1498Szrj }
5331*38fd1498Szrj }
5332*38fd1498Szrj automaton_decls.release ();
5333*38fd1498Szrj if (progress_flag)
5334*38fd1498Szrj fprintf (stderr, "done\n");
5335*38fd1498Szrj }
5336*38fd1498Szrj
5337*38fd1498Szrj
5338*38fd1498Szrj
5339*38fd1498Szrj /* The page contains code for building alt_states (see comments for
5340*38fd1498Szrj IR) describing all possible insns reservations of an automaton. */
5341*38fd1498Szrj
5342*38fd1498Szrj /* Current state being formed for which the current alt_state
5343*38fd1498Szrj refers. */
5344*38fd1498Szrj static state_t state_being_formed;
5345*38fd1498Szrj
5346*38fd1498Szrj /* Current alt_state being formed. */
5347*38fd1498Szrj static alt_state_t alt_state_being_formed;
5348*38fd1498Szrj
5349*38fd1498Szrj /* This recursive function processes `,' and units in reservation
5350*38fd1498Szrj REGEXP for forming alt_states of AUTOMATON. It is believed that
5351*38fd1498Szrj CURR_CYCLE is start cycle of all reservation REGEXP. */
5352*38fd1498Szrj static int
process_seq_for_forming_states(regexp_t regexp,automaton_t automaton,int curr_cycle)5353*38fd1498Szrj process_seq_for_forming_states (regexp_t regexp, automaton_t automaton,
5354*38fd1498Szrj int curr_cycle)
5355*38fd1498Szrj {
5356*38fd1498Szrj int i;
5357*38fd1498Szrj
5358*38fd1498Szrj if (regexp == NULL)
5359*38fd1498Szrj return curr_cycle;
5360*38fd1498Szrj
5361*38fd1498Szrj switch (regexp->mode)
5362*38fd1498Szrj {
5363*38fd1498Szrj case rm_unit:
5364*38fd1498Szrj if (REGEXP_UNIT (regexp)->unit_decl->corresponding_automaton_num
5365*38fd1498Szrj == automaton->automaton_order_num)
5366*38fd1498Szrj set_state_reserv (state_being_formed, curr_cycle,
5367*38fd1498Szrj REGEXP_UNIT (regexp)->unit_decl->unit_num);
5368*38fd1498Szrj return curr_cycle;
5369*38fd1498Szrj
5370*38fd1498Szrj case rm_sequence:
5371*38fd1498Szrj for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
5372*38fd1498Szrj curr_cycle
5373*38fd1498Szrj = process_seq_for_forming_states
5374*38fd1498Szrj (REGEXP_SEQUENCE (regexp)->regexps [i], automaton, curr_cycle) + 1;
5375*38fd1498Szrj return curr_cycle;
5376*38fd1498Szrj
5377*38fd1498Szrj case rm_allof:
5378*38fd1498Szrj {
5379*38fd1498Szrj int finish_cycle = 0;
5380*38fd1498Szrj int cycle;
5381*38fd1498Szrj
5382*38fd1498Szrj for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
5383*38fd1498Szrj {
5384*38fd1498Szrj cycle = process_seq_for_forming_states (REGEXP_ALLOF (regexp)
5385*38fd1498Szrj ->regexps [i],
5386*38fd1498Szrj automaton, curr_cycle);
5387*38fd1498Szrj if (finish_cycle < cycle)
5388*38fd1498Szrj finish_cycle = cycle;
5389*38fd1498Szrj }
5390*38fd1498Szrj return finish_cycle;
5391*38fd1498Szrj }
5392*38fd1498Szrj
5393*38fd1498Szrj case rm_nothing:
5394*38fd1498Szrj return curr_cycle;
5395*38fd1498Szrj
5396*38fd1498Szrj default:
5397*38fd1498Szrj gcc_unreachable ();
5398*38fd1498Szrj }
5399*38fd1498Szrj }
5400*38fd1498Szrj
5401*38fd1498Szrj /* This recursive function finishes forming ALT_STATE of AUTOMATON and
5402*38fd1498Szrj inserts alt_state into the table. */
5403*38fd1498Szrj static void
finish_forming_alt_state(alt_state_t alt_state,automaton_t automaton ATTRIBUTE_UNUSED)5404*38fd1498Szrj finish_forming_alt_state (alt_state_t alt_state,
5405*38fd1498Szrj automaton_t automaton ATTRIBUTE_UNUSED)
5406*38fd1498Szrj {
5407*38fd1498Szrj state_t state_in_table;
5408*38fd1498Szrj state_t corresponding_state;
5409*38fd1498Szrj
5410*38fd1498Szrj corresponding_state = alt_state->state;
5411*38fd1498Szrj state_in_table = insert_state (corresponding_state);
5412*38fd1498Szrj if (state_in_table != corresponding_state)
5413*38fd1498Szrj {
5414*38fd1498Szrj free_state (corresponding_state);
5415*38fd1498Szrj alt_state->state = state_in_table;
5416*38fd1498Szrj }
5417*38fd1498Szrj }
5418*38fd1498Szrj
5419*38fd1498Szrj /* The following variable value is current automaton insn for whose
5420*38fd1498Szrj reservation the alt states are created. */
5421*38fd1498Szrj static ainsn_t curr_ainsn;
5422*38fd1498Szrj
5423*38fd1498Szrj /* This recursive function processes `|' in reservation REGEXP for
5424*38fd1498Szrj forming alt_states of AUTOMATON. List of the alt states should
5425*38fd1498Szrj have the same order as in the description. */
5426*38fd1498Szrj static void
process_alts_for_forming_states(regexp_t regexp,automaton_t automaton,int inside_oneof_p)5427*38fd1498Szrj process_alts_for_forming_states (regexp_t regexp, automaton_t automaton,
5428*38fd1498Szrj int inside_oneof_p)
5429*38fd1498Szrj {
5430*38fd1498Szrj int i;
5431*38fd1498Szrj
5432*38fd1498Szrj if (regexp->mode != rm_oneof)
5433*38fd1498Szrj {
5434*38fd1498Szrj alt_state_being_formed = get_free_alt_state ();
5435*38fd1498Szrj state_being_formed = get_free_state (1, automaton);
5436*38fd1498Szrj alt_state_being_formed->state = state_being_formed;
5437*38fd1498Szrj /* We inserts in reverse order but we process alternatives also
5438*38fd1498Szrj in reverse order. So we have the same order of alternative
5439*38fd1498Szrj as in the description. */
5440*38fd1498Szrj alt_state_being_formed->next_alt_state = curr_ainsn->alt_states;
5441*38fd1498Szrj curr_ainsn->alt_states = alt_state_being_formed;
5442*38fd1498Szrj (void) process_seq_for_forming_states (regexp, automaton, 0);
5443*38fd1498Szrj finish_forming_alt_state (alt_state_being_formed, automaton);
5444*38fd1498Szrj }
5445*38fd1498Szrj else
5446*38fd1498Szrj {
5447*38fd1498Szrj gcc_assert (!inside_oneof_p);
5448*38fd1498Szrj /* We processes it in reverse order to get list with the same
5449*38fd1498Szrj order as in the description. See also the previous
5450*38fd1498Szrj commentary. */
5451*38fd1498Szrj for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
5452*38fd1498Szrj process_alts_for_forming_states (REGEXP_ONEOF (regexp)->regexps [i],
5453*38fd1498Szrj automaton, 1);
5454*38fd1498Szrj }
5455*38fd1498Szrj }
5456*38fd1498Szrj
5457*38fd1498Szrj /* Create nodes alt_state for all AUTOMATON insns. */
5458*38fd1498Szrj static void
create_alt_states(automaton_t automaton)5459*38fd1498Szrj create_alt_states (automaton_t automaton)
5460*38fd1498Szrj {
5461*38fd1498Szrj struct insn_reserv_decl *reserv_decl;
5462*38fd1498Szrj
5463*38fd1498Szrj for (curr_ainsn = automaton->ainsn_list;
5464*38fd1498Szrj curr_ainsn != NULL;
5465*38fd1498Szrj curr_ainsn = curr_ainsn->next_ainsn)
5466*38fd1498Szrj {
5467*38fd1498Szrj reserv_decl = curr_ainsn->insn_reserv_decl;
5468*38fd1498Szrj if (!special_decl_p (reserv_decl))
5469*38fd1498Szrj {
5470*38fd1498Szrj curr_ainsn->alt_states = NULL;
5471*38fd1498Szrj process_alts_for_forming_states (reserv_decl->transformed_regexp,
5472*38fd1498Szrj automaton, 0);
5473*38fd1498Szrj curr_ainsn->sorted_alt_states
5474*38fd1498Szrj = uniq_sort_alt_states (curr_ainsn->alt_states);
5475*38fd1498Szrj }
5476*38fd1498Szrj }
5477*38fd1498Szrj }
5478*38fd1498Szrj
5479*38fd1498Szrj
5480*38fd1498Szrj
5481*38fd1498Szrj /* The page contains major code for building DFA(s) for fast pipeline
5482*38fd1498Szrj hazards recognition. */
5483*38fd1498Szrj
5484*38fd1498Szrj /* The function forms list of ainsns of AUTOMATON with the same
5485*38fd1498Szrj reservation. */
5486*38fd1498Szrj
5487*38fd1498Szrj static void
form_ainsn_with_same_reservs(automaton_t automaton)5488*38fd1498Szrj form_ainsn_with_same_reservs (automaton_t automaton)
5489*38fd1498Szrj {
5490*38fd1498Szrj ainsn_t curr_ainsn;
5491*38fd1498Szrj size_t i;
5492*38fd1498Szrj auto_vec<ainsn_t, 150> last_insns;
5493*38fd1498Szrj
5494*38fd1498Szrj for (curr_ainsn = automaton->ainsn_list;
5495*38fd1498Szrj curr_ainsn != NULL;
5496*38fd1498Szrj curr_ainsn = curr_ainsn->next_ainsn)
5497*38fd1498Szrj if (special_decl_p (curr_ainsn->insn_reserv_decl))
5498*38fd1498Szrj {
5499*38fd1498Szrj curr_ainsn->next_same_reservs_insn = NULL;
5500*38fd1498Szrj curr_ainsn->first_insn_with_same_reservs = 1;
5501*38fd1498Szrj }
5502*38fd1498Szrj else
5503*38fd1498Szrj {
5504*38fd1498Szrj for (i = 0; i < last_insns.length (); i++)
5505*38fd1498Szrj if (alt_states_eq
5506*38fd1498Szrj (curr_ainsn->sorted_alt_states,
5507*38fd1498Szrj last_insns[i]->sorted_alt_states))
5508*38fd1498Szrj break;
5509*38fd1498Szrj curr_ainsn->next_same_reservs_insn = NULL;
5510*38fd1498Szrj if (i < last_insns.length ())
5511*38fd1498Szrj {
5512*38fd1498Szrj curr_ainsn->first_insn_with_same_reservs = 0;
5513*38fd1498Szrj last_insns[i]->next_same_reservs_insn = curr_ainsn;
5514*38fd1498Szrj last_insns[i] = curr_ainsn;
5515*38fd1498Szrj }
5516*38fd1498Szrj else
5517*38fd1498Szrj {
5518*38fd1498Szrj last_insns.safe_push (curr_ainsn);
5519*38fd1498Szrj curr_ainsn->first_insn_with_same_reservs = 1;
5520*38fd1498Szrj }
5521*38fd1498Szrj }
5522*38fd1498Szrj }
5523*38fd1498Szrj
5524*38fd1498Szrj /* Forming unit reservations which can affect creating the automaton
5525*38fd1498Szrj states achieved from a given state. It permits to build smaller
5526*38fd1498Szrj automata in many cases. We would have the same automata after
5527*38fd1498Szrj the minimization without such optimization, but the automaton
5528*38fd1498Szrj right after the building could be huge. So in other words, usage
5529*38fd1498Szrj of reservs_matter means some minimization during building the
5530*38fd1498Szrj automaton. */
5531*38fd1498Szrj static reserv_sets_t
form_reservs_matter(automaton_t automaton)5532*38fd1498Szrj form_reservs_matter (automaton_t automaton)
5533*38fd1498Szrj {
5534*38fd1498Szrj int cycle, unit;
5535*38fd1498Szrj reserv_sets_t reservs_matter = alloc_empty_reserv_sets ();
5536*38fd1498Szrj
5537*38fd1498Szrj for (cycle = 0; cycle < max_cycles_num; cycle++)
5538*38fd1498Szrj for (unit = 0; unit < description->units_num; unit++)
5539*38fd1498Szrj if (units_array [unit]->automaton_decl
5540*38fd1498Szrj == automaton->corresponding_automaton_decl
5541*38fd1498Szrj && (cycle >= units_array [unit]->min_occ_cycle_num
5542*38fd1498Szrj /* We can not remove queried unit from reservations. */
5543*38fd1498Szrj || units_array [unit]->query_p
5544*38fd1498Szrj /* We can not remove units which are used
5545*38fd1498Szrj `exclusion_set', `presence_set',
5546*38fd1498Szrj `final_presence_set', `absence_set', and
5547*38fd1498Szrj `final_absence_set'. */
5548*38fd1498Szrj || units_array [unit]->in_set_p))
5549*38fd1498Szrj set_unit_reserv (reservs_matter, cycle, unit);
5550*38fd1498Szrj return reservs_matter;
5551*38fd1498Szrj }
5552*38fd1498Szrj
5553*38fd1498Szrj /* The following function creates all states of nondeterministic AUTOMATON. */
5554*38fd1498Szrj static void
make_automaton(automaton_t automaton)5555*38fd1498Szrj make_automaton (automaton_t automaton)
5556*38fd1498Szrj {
5557*38fd1498Szrj ainsn_t ainsn;
5558*38fd1498Szrj struct insn_reserv_decl *insn_reserv_decl;
5559*38fd1498Szrj alt_state_t alt_state;
5560*38fd1498Szrj state_t state;
5561*38fd1498Szrj state_t start_state;
5562*38fd1498Szrj state_t state2;
5563*38fd1498Szrj auto_vec<state_t, 150> state_stack;
5564*38fd1498Szrj int states_n;
5565*38fd1498Szrj reserv_sets_t reservs_matter = form_reservs_matter (automaton);
5566*38fd1498Szrj
5567*38fd1498Szrj /* Create the start state (empty state). */
5568*38fd1498Szrj start_state = insert_state (get_free_state (1, automaton));
5569*38fd1498Szrj automaton->start_state = start_state;
5570*38fd1498Szrj start_state->it_was_placed_in_stack_for_NDFA_forming = 1;
5571*38fd1498Szrj state_stack.safe_push (start_state);
5572*38fd1498Szrj states_n = 1;
5573*38fd1498Szrj while (state_stack.length () != 0)
5574*38fd1498Szrj {
5575*38fd1498Szrj state = state_stack.pop ();
5576*38fd1498Szrj for (ainsn = automaton->ainsn_list;
5577*38fd1498Szrj ainsn != NULL;
5578*38fd1498Szrj ainsn = ainsn->next_ainsn)
5579*38fd1498Szrj if (ainsn->first_insn_with_same_reservs)
5580*38fd1498Szrj {
5581*38fd1498Szrj insn_reserv_decl = ainsn->insn_reserv_decl;
5582*38fd1498Szrj if (!special_decl_p (insn_reserv_decl))
5583*38fd1498Szrj {
5584*38fd1498Szrj /* We process alt_states in the same order as they are
5585*38fd1498Szrj present in the description. */
5586*38fd1498Szrj for (alt_state = ainsn->alt_states;
5587*38fd1498Szrj alt_state != NULL;
5588*38fd1498Szrj alt_state = alt_state->next_alt_state)
5589*38fd1498Szrj {
5590*38fd1498Szrj state2 = alt_state->state;
5591*38fd1498Szrj if (!intersected_state_reservs_p (state, state2))
5592*38fd1498Szrj {
5593*38fd1498Szrj state2 = states_union (state, state2, reservs_matter);
5594*38fd1498Szrj if (!state2->it_was_placed_in_stack_for_NDFA_forming)
5595*38fd1498Szrj {
5596*38fd1498Szrj state2->it_was_placed_in_stack_for_NDFA_forming
5597*38fd1498Szrj = 1;
5598*38fd1498Szrj state_stack.safe_push (state2);
5599*38fd1498Szrj states_n++;
5600*38fd1498Szrj if (progress_flag && states_n % 100 == 0)
5601*38fd1498Szrj fprintf (stderr, ".");
5602*38fd1498Szrj }
5603*38fd1498Szrj add_arc (state, state2, ainsn);
5604*38fd1498Szrj if (!ndfa_flag)
5605*38fd1498Szrj break;
5606*38fd1498Szrj }
5607*38fd1498Szrj }
5608*38fd1498Szrj }
5609*38fd1498Szrj }
5610*38fd1498Szrj /* Add transition to advance cycle. */
5611*38fd1498Szrj state2 = state_shift (state, reservs_matter);
5612*38fd1498Szrj if (!state2->it_was_placed_in_stack_for_NDFA_forming)
5613*38fd1498Szrj {
5614*38fd1498Szrj state2->it_was_placed_in_stack_for_NDFA_forming = 1;
5615*38fd1498Szrj state_stack.safe_push (state2);
5616*38fd1498Szrj states_n++;
5617*38fd1498Szrj if (progress_flag && states_n % 100 == 0)
5618*38fd1498Szrj fprintf (stderr, ".");
5619*38fd1498Szrj }
5620*38fd1498Szrj add_arc (state, state2, automaton->advance_ainsn);
5621*38fd1498Szrj }
5622*38fd1498Szrj }
5623*38fd1498Szrj
5624*38fd1498Szrj /* Form lists of all arcs of STATE marked by the same ainsn. */
5625*38fd1498Szrj static void
form_arcs_marked_by_insn(state_t state)5626*38fd1498Szrj form_arcs_marked_by_insn (state_t state)
5627*38fd1498Szrj {
5628*38fd1498Szrj decl_t decl;
5629*38fd1498Szrj arc_t arc;
5630*38fd1498Szrj int i;
5631*38fd1498Szrj
5632*38fd1498Szrj for (i = 0; i < description->decls_num; i++)
5633*38fd1498Szrj {
5634*38fd1498Szrj decl = description->decls [i];
5635*38fd1498Szrj if (decl->mode == dm_insn_reserv)
5636*38fd1498Szrj DECL_INSN_RESERV (decl)->arcs_marked_by_insn = NULL;
5637*38fd1498Szrj }
5638*38fd1498Szrj for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5639*38fd1498Szrj {
5640*38fd1498Szrj gcc_assert (arc->insn);
5641*38fd1498Szrj arc->next_arc_marked_by_insn
5642*38fd1498Szrj = arc->insn->insn_reserv_decl->arcs_marked_by_insn;
5643*38fd1498Szrj arc->insn->insn_reserv_decl->arcs_marked_by_insn = arc;
5644*38fd1498Szrj }
5645*38fd1498Szrj }
5646*38fd1498Szrj
5647*38fd1498Szrj /* The function creates composed state (see comments for IR) from
5648*38fd1498Szrj ORIGINAL_STATE and list of arcs ARCS_MARKED_BY_INSN marked by the
5649*38fd1498Szrj same insn. If the composed state is not in STATE_STACK yet, it is
5650*38fd1498Szrj pushed into STATE_STACK. */
5651*38fd1498Szrj
5652*38fd1498Szrj static int
create_composed_state(state_t original_state,arc_t arcs_marked_by_insn,vec<state_t> * state_stack)5653*38fd1498Szrj create_composed_state (state_t original_state, arc_t arcs_marked_by_insn,
5654*38fd1498Szrj vec<state_t> *state_stack)
5655*38fd1498Szrj {
5656*38fd1498Szrj state_t state;
5657*38fd1498Szrj alt_state_t alt_state, curr_alt_state;
5658*38fd1498Szrj alt_state_t new_alt_state;
5659*38fd1498Szrj arc_t curr_arc;
5660*38fd1498Szrj arc_t next_arc;
5661*38fd1498Szrj state_t state_in_table;
5662*38fd1498Szrj state_t temp_state;
5663*38fd1498Szrj alt_state_t canonical_alt_states_list;
5664*38fd1498Szrj int alts_number;
5665*38fd1498Szrj int new_state_p = 0;
5666*38fd1498Szrj
5667*38fd1498Szrj if (arcs_marked_by_insn == NULL)
5668*38fd1498Szrj return new_state_p;
5669*38fd1498Szrj if (arcs_marked_by_insn->next_arc_marked_by_insn == NULL)
5670*38fd1498Szrj state = arcs_marked_by_insn->to_state;
5671*38fd1498Szrj else
5672*38fd1498Szrj {
5673*38fd1498Szrj gcc_assert (ndfa_flag);
5674*38fd1498Szrj /* Create composed state. */
5675*38fd1498Szrj state = get_free_state (0, arcs_marked_by_insn->to_state->automaton);
5676*38fd1498Szrj curr_alt_state = NULL;
5677*38fd1498Szrj for (curr_arc = arcs_marked_by_insn;
5678*38fd1498Szrj curr_arc != NULL;
5679*38fd1498Szrj curr_arc = curr_arc->next_arc_marked_by_insn)
5680*38fd1498Szrj if (curr_arc->to_state->component_states == NULL)
5681*38fd1498Szrj {
5682*38fd1498Szrj new_alt_state = get_free_alt_state ();
5683*38fd1498Szrj new_alt_state->next_alt_state = curr_alt_state;
5684*38fd1498Szrj new_alt_state->state = curr_arc->to_state;
5685*38fd1498Szrj curr_alt_state = new_alt_state;
5686*38fd1498Szrj }
5687*38fd1498Szrj else
5688*38fd1498Szrj for (alt_state = curr_arc->to_state->component_states;
5689*38fd1498Szrj alt_state != NULL;
5690*38fd1498Szrj alt_state = alt_state->next_sorted_alt_state)
5691*38fd1498Szrj {
5692*38fd1498Szrj new_alt_state = get_free_alt_state ();
5693*38fd1498Szrj new_alt_state->next_alt_state = curr_alt_state;
5694*38fd1498Szrj new_alt_state->state = alt_state->state;
5695*38fd1498Szrj gcc_assert (!alt_state->state->component_states);
5696*38fd1498Szrj curr_alt_state = new_alt_state;
5697*38fd1498Szrj }
5698*38fd1498Szrj /* There are not identical sets in the alt state list. */
5699*38fd1498Szrj canonical_alt_states_list = uniq_sort_alt_states (curr_alt_state);
5700*38fd1498Szrj if (canonical_alt_states_list->next_sorted_alt_state == NULL)
5701*38fd1498Szrj {
5702*38fd1498Szrj temp_state = state;
5703*38fd1498Szrj state = canonical_alt_states_list->state;
5704*38fd1498Szrj free_state (temp_state);
5705*38fd1498Szrj }
5706*38fd1498Szrj else
5707*38fd1498Szrj {
5708*38fd1498Szrj state->component_states = canonical_alt_states_list;
5709*38fd1498Szrj state_in_table = insert_state (state);
5710*38fd1498Szrj if (state_in_table != state)
5711*38fd1498Szrj {
5712*38fd1498Szrj gcc_assert
5713*38fd1498Szrj (state_in_table->it_was_placed_in_stack_for_DFA_forming);
5714*38fd1498Szrj free_state (state);
5715*38fd1498Szrj state = state_in_table;
5716*38fd1498Szrj }
5717*38fd1498Szrj else
5718*38fd1498Szrj {
5719*38fd1498Szrj gcc_assert (!state->it_was_placed_in_stack_for_DFA_forming);
5720*38fd1498Szrj new_state_p = 1;
5721*38fd1498Szrj for (curr_alt_state = state->component_states;
5722*38fd1498Szrj curr_alt_state != NULL;
5723*38fd1498Szrj curr_alt_state = curr_alt_state->next_sorted_alt_state)
5724*38fd1498Szrj for (curr_arc = first_out_arc (curr_alt_state->state);
5725*38fd1498Szrj curr_arc != NULL;
5726*38fd1498Szrj curr_arc = next_out_arc (curr_arc))
5727*38fd1498Szrj if (!collapse_flag
5728*38fd1498Szrj /* When producing collapse-NDFA transitions, we
5729*38fd1498Szrj only add advance-cycle transitions to the
5730*38fd1498Szrj collapsed states. */
5731*38fd1498Szrj || (curr_arc->insn->insn_reserv_decl
5732*38fd1498Szrj != DECL_INSN_RESERV (advance_cycle_insn_decl)))
5733*38fd1498Szrj add_arc (state, curr_arc->to_state, curr_arc->insn);
5734*38fd1498Szrj }
5735*38fd1498Szrj arcs_marked_by_insn->to_state = state;
5736*38fd1498Szrj for (alts_number = 0,
5737*38fd1498Szrj curr_arc = arcs_marked_by_insn->next_arc_marked_by_insn;
5738*38fd1498Szrj curr_arc != NULL;
5739*38fd1498Szrj curr_arc = next_arc)
5740*38fd1498Szrj {
5741*38fd1498Szrj next_arc = curr_arc->next_arc_marked_by_insn;
5742*38fd1498Szrj remove_arc (original_state, curr_arc);
5743*38fd1498Szrj alts_number++;
5744*38fd1498Szrj }
5745*38fd1498Szrj }
5746*38fd1498Szrj }
5747*38fd1498Szrj if (!state->it_was_placed_in_stack_for_DFA_forming)
5748*38fd1498Szrj {
5749*38fd1498Szrj state->it_was_placed_in_stack_for_DFA_forming = 1;
5750*38fd1498Szrj state_stack->safe_push (state);
5751*38fd1498Szrj }
5752*38fd1498Szrj return new_state_p;
5753*38fd1498Szrj }
5754*38fd1498Szrj
5755*38fd1498Szrj /* The function transforms nondeterministic AUTOMATON into
5756*38fd1498Szrj deterministic. */
5757*38fd1498Szrj
5758*38fd1498Szrj static void
NDFA_to_DFA(automaton_t automaton)5759*38fd1498Szrj NDFA_to_DFA (automaton_t automaton)
5760*38fd1498Szrj {
5761*38fd1498Szrj state_t start_state;
5762*38fd1498Szrj state_t state;
5763*38fd1498Szrj decl_t decl;
5764*38fd1498Szrj auto_vec<state_t> state_stack;
5765*38fd1498Szrj int i;
5766*38fd1498Szrj int states_n;
5767*38fd1498Szrj
5768*38fd1498Szrj /* Create the start state (empty state). */
5769*38fd1498Szrj start_state = automaton->start_state;
5770*38fd1498Szrj start_state->it_was_placed_in_stack_for_DFA_forming = 1;
5771*38fd1498Szrj state_stack.safe_push (start_state);
5772*38fd1498Szrj states_n = 1;
5773*38fd1498Szrj while (state_stack.length () != 0)
5774*38fd1498Szrj {
5775*38fd1498Szrj state = state_stack.pop ();
5776*38fd1498Szrj form_arcs_marked_by_insn (state);
5777*38fd1498Szrj for (i = 0; i < description->decls_num; i++)
5778*38fd1498Szrj {
5779*38fd1498Szrj decl = description->decls [i];
5780*38fd1498Szrj if (decl->mode == dm_insn_reserv
5781*38fd1498Szrj && decl != collapse_ndfa_insn_decl
5782*38fd1498Szrj && create_composed_state
5783*38fd1498Szrj (state, DECL_INSN_RESERV (decl)->arcs_marked_by_insn,
5784*38fd1498Szrj &state_stack))
5785*38fd1498Szrj {
5786*38fd1498Szrj states_n++;
5787*38fd1498Szrj if (progress_flag && states_n % 100 == 0)
5788*38fd1498Szrj fprintf (stderr, ".");
5789*38fd1498Szrj }
5790*38fd1498Szrj }
5791*38fd1498Szrj /* Add a transition to collapse the NDFA. */
5792*38fd1498Szrj if (collapse_flag)
5793*38fd1498Szrj {
5794*38fd1498Szrj if (state->component_states != NULL)
5795*38fd1498Szrj {
5796*38fd1498Szrj state_t state2 = state->component_states->state;
5797*38fd1498Szrj if (!state2->it_was_placed_in_stack_for_DFA_forming)
5798*38fd1498Szrj {
5799*38fd1498Szrj state2->it_was_placed_in_stack_for_DFA_forming = 1;
5800*38fd1498Szrj state_stack.safe_push (state2);
5801*38fd1498Szrj }
5802*38fd1498Szrj add_arc (state, state2, automaton->collapse_ainsn);
5803*38fd1498Szrj }
5804*38fd1498Szrj else
5805*38fd1498Szrj add_arc (state, state, automaton->collapse_ainsn);
5806*38fd1498Szrj }
5807*38fd1498Szrj }
5808*38fd1498Szrj }
5809*38fd1498Szrj
5810*38fd1498Szrj /* The following variable value is current number (1, 2, ...) of passing
5811*38fd1498Szrj graph of states. */
5812*38fd1498Szrj static int curr_state_graph_pass_num;
5813*38fd1498Szrj
5814*38fd1498Szrj /* This recursive function passes all states achieved from START_STATE
5815*38fd1498Szrj and applies APPLIED_FUNC to them. */
5816*38fd1498Szrj static void
pass_state_graph(state_t start_state,void (* applied_func)(state_t state))5817*38fd1498Szrj pass_state_graph (state_t start_state, void (*applied_func) (state_t state))
5818*38fd1498Szrj {
5819*38fd1498Szrj arc_t arc;
5820*38fd1498Szrj
5821*38fd1498Szrj if (start_state->pass_num == curr_state_graph_pass_num)
5822*38fd1498Szrj return;
5823*38fd1498Szrj start_state->pass_num = curr_state_graph_pass_num;
5824*38fd1498Szrj (*applied_func) (start_state);
5825*38fd1498Szrj for (arc = first_out_arc (start_state);
5826*38fd1498Szrj arc != NULL;
5827*38fd1498Szrj arc = next_out_arc (arc))
5828*38fd1498Szrj pass_state_graph (arc->to_state, applied_func);
5829*38fd1498Szrj }
5830*38fd1498Szrj
5831*38fd1498Szrj /* This recursive function passes all states of AUTOMATON and applies
5832*38fd1498Szrj APPLIED_FUNC to them. */
5833*38fd1498Szrj static void
pass_states(automaton_t automaton,void (* applied_func)(state_t state))5834*38fd1498Szrj pass_states (automaton_t automaton, void (*applied_func) (state_t state))
5835*38fd1498Szrj {
5836*38fd1498Szrj curr_state_graph_pass_num++;
5837*38fd1498Szrj pass_state_graph (automaton->start_state, applied_func);
5838*38fd1498Szrj }
5839*38fd1498Szrj
5840*38fd1498Szrj /* The function initializes code for passing of all states. */
5841*38fd1498Szrj static void
initiate_pass_states(void)5842*38fd1498Szrj initiate_pass_states (void)
5843*38fd1498Szrj {
5844*38fd1498Szrj curr_state_graph_pass_num = 0;
5845*38fd1498Szrj }
5846*38fd1498Szrj
5847*38fd1498Szrj /* The following vla is used for storing pointers to all achieved
5848*38fd1498Szrj states. */
5849*38fd1498Szrj static vec<state_t> all_achieved_states;
5850*38fd1498Szrj
5851*38fd1498Szrj /* This function is called by function pass_states to add an achieved
5852*38fd1498Szrj STATE. */
5853*38fd1498Szrj static void
add_achieved_state(state_t state)5854*38fd1498Szrj add_achieved_state (state_t state)
5855*38fd1498Szrj {
5856*38fd1498Szrj all_achieved_states.safe_push (state);
5857*38fd1498Szrj }
5858*38fd1498Szrj
5859*38fd1498Szrj /* The function sets up equivalence numbers of insns which mark all
5860*38fd1498Szrj out arcs of STATE by equiv_class_num_1 (if ODD_ITERATION_FLAG has
5861*38fd1498Szrj nonzero value) or by equiv_class_num_2 of the destination state. */
5862*38fd1498Szrj static void
set_out_arc_insns_equiv_num(state_t state,int odd_iteration_flag)5863*38fd1498Szrj set_out_arc_insns_equiv_num (state_t state, int odd_iteration_flag)
5864*38fd1498Szrj {
5865*38fd1498Szrj arc_t arc;
5866*38fd1498Szrj
5867*38fd1498Szrj for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5868*38fd1498Szrj {
5869*38fd1498Szrj gcc_assert (!arc->insn->insn_reserv_decl->equiv_class_num);
5870*38fd1498Szrj arc->insn->insn_reserv_decl->equiv_class_num
5871*38fd1498Szrj = (odd_iteration_flag
5872*38fd1498Szrj ? arc->to_state->equiv_class_num_1
5873*38fd1498Szrj : arc->to_state->equiv_class_num_2);
5874*38fd1498Szrj gcc_assert (arc->insn->insn_reserv_decl->equiv_class_num);
5875*38fd1498Szrj }
5876*38fd1498Szrj }
5877*38fd1498Szrj
5878*38fd1498Szrj /* The function clears equivalence numbers and alt_states in all insns
5879*38fd1498Szrj which mark all out arcs of STATE. */
5880*38fd1498Szrj static void
clear_arc_insns_equiv_num(state_t state)5881*38fd1498Szrj clear_arc_insns_equiv_num (state_t state)
5882*38fd1498Szrj {
5883*38fd1498Szrj arc_t arc;
5884*38fd1498Szrj
5885*38fd1498Szrj for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5886*38fd1498Szrj arc->insn->insn_reserv_decl->equiv_class_num = 0;
5887*38fd1498Szrj }
5888*38fd1498Szrj
5889*38fd1498Szrj
5890*38fd1498Szrj /* The following function returns TRUE if STATE reserves the unit with
5891*38fd1498Szrj UNIT_NUM on the first cycle. */
5892*38fd1498Szrj static int
first_cycle_unit_presence(state_t state,int unit_num)5893*38fd1498Szrj first_cycle_unit_presence (state_t state, int unit_num)
5894*38fd1498Szrj {
5895*38fd1498Szrj alt_state_t alt_state;
5896*38fd1498Szrj
5897*38fd1498Szrj if (state->component_states == NULL)
5898*38fd1498Szrj return test_unit_reserv (state->reservs, 0, unit_num);
5899*38fd1498Szrj else
5900*38fd1498Szrj {
5901*38fd1498Szrj for (alt_state = state->component_states;
5902*38fd1498Szrj alt_state != NULL;
5903*38fd1498Szrj alt_state = alt_state->next_sorted_alt_state)
5904*38fd1498Szrj if (test_unit_reserv (alt_state->state->reservs, 0, unit_num))
5905*38fd1498Szrj return true;
5906*38fd1498Szrj }
5907*38fd1498Szrj return false;
5908*38fd1498Szrj }
5909*38fd1498Szrj
5910*38fd1498Szrj /* This fills in the presence_signature[] member of STATE. */
5911*38fd1498Szrj static void
cache_presence(state_t state)5912*38fd1498Szrj cache_presence (state_t state)
5913*38fd1498Szrj {
5914*38fd1498Szrj int i, num = 0;
5915*38fd1498Szrj unsigned int sz;
5916*38fd1498Szrj sz = (description->query_units_num + sizeof (int) * CHAR_BIT - 1)
5917*38fd1498Szrj / (sizeof (int) * CHAR_BIT);
5918*38fd1498Szrj
5919*38fd1498Szrj state->presence_signature = XCREATENODEVEC (unsigned int, sz);
5920*38fd1498Szrj for (i = 0; i < description->units_num; i++)
5921*38fd1498Szrj if (units_array [i]->query_p)
5922*38fd1498Szrj {
5923*38fd1498Szrj int presence1_p = first_cycle_unit_presence (state, i);
5924*38fd1498Szrj state->presence_signature[num / (sizeof (int) * CHAR_BIT)]
5925*38fd1498Szrj |= (!!presence1_p) << (num % (sizeof (int) * CHAR_BIT));
5926*38fd1498Szrj num++;
5927*38fd1498Szrj }
5928*38fd1498Szrj }
5929*38fd1498Szrj
5930*38fd1498Szrj /* The function returns nonzero value if STATE is not equivalent to
5931*38fd1498Szrj ANOTHER_STATE from the same current partition on equivalence
5932*38fd1498Szrj classes. Another state has ANOTHER_STATE_OUT_ARCS_NUM number of
5933*38fd1498Szrj output arcs. Iteration of making equivalence partition is defined
5934*38fd1498Szrj by ODD_ITERATION_FLAG. */
5935*38fd1498Szrj static int
state_is_differed(state_t state,state_t another_state,int odd_iteration_flag)5936*38fd1498Szrj state_is_differed (state_t state, state_t another_state,
5937*38fd1498Szrj int odd_iteration_flag)
5938*38fd1498Szrj {
5939*38fd1498Szrj arc_t arc;
5940*38fd1498Szrj unsigned int sz, si;
5941*38fd1498Szrj
5942*38fd1498Szrj gcc_assert (state->num_out_arcs == another_state->num_out_arcs);
5943*38fd1498Szrj
5944*38fd1498Szrj sz = (description->query_units_num + sizeof (int) * CHAR_BIT - 1)
5945*38fd1498Szrj / (sizeof (int) * CHAR_BIT);
5946*38fd1498Szrj
5947*38fd1498Szrj for (si = 0; si < sz; si++)
5948*38fd1498Szrj gcc_assert (state->presence_signature[si]
5949*38fd1498Szrj == another_state->presence_signature[si]);
5950*38fd1498Szrj
5951*38fd1498Szrj for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5952*38fd1498Szrj {
5953*38fd1498Szrj if ((odd_iteration_flag
5954*38fd1498Szrj ? arc->to_state->equiv_class_num_1
5955*38fd1498Szrj : arc->to_state->equiv_class_num_2)
5956*38fd1498Szrj != arc->insn->insn_reserv_decl->equiv_class_num)
5957*38fd1498Szrj return 1;
5958*38fd1498Szrj }
5959*38fd1498Szrj
5960*38fd1498Szrj return 0;
5961*38fd1498Szrj }
5962*38fd1498Szrj
5963*38fd1498Szrj /* Compares two states pointed to by STATE_PTR_1 and STATE_PTR_2
5964*38fd1498Szrj and return -1, 0 or 1. This function can be used as predicate for
5965*38fd1498Szrj qsort(). It requires the member presence_signature[] of both
5966*38fd1498Szrj states be filled. */
5967*38fd1498Szrj static int
compare_states_for_equiv(const void * state_ptr_1,const void * state_ptr_2)5968*38fd1498Szrj compare_states_for_equiv (const void *state_ptr_1,
5969*38fd1498Szrj const void *state_ptr_2)
5970*38fd1498Szrj {
5971*38fd1498Szrj const_state_t const s1 = *(const_state_t const*)state_ptr_1;
5972*38fd1498Szrj const_state_t const s2 = *(const_state_t const*)state_ptr_2;
5973*38fd1498Szrj unsigned int sz, si;
5974*38fd1498Szrj if (s1->num_out_arcs < s2->num_out_arcs)
5975*38fd1498Szrj return -1;
5976*38fd1498Szrj else if (s1->num_out_arcs > s2->num_out_arcs)
5977*38fd1498Szrj return 1;
5978*38fd1498Szrj
5979*38fd1498Szrj sz = (description->query_units_num + sizeof (int) * CHAR_BIT - 1)
5980*38fd1498Szrj / (sizeof (int) * CHAR_BIT);
5981*38fd1498Szrj
5982*38fd1498Szrj for (si = 0; si < sz; si++)
5983*38fd1498Szrj if (s1->presence_signature[si] < s2->presence_signature[si])
5984*38fd1498Szrj return -1;
5985*38fd1498Szrj else if (s1->presence_signature[si] > s2->presence_signature[si])
5986*38fd1498Szrj return 1;
5987*38fd1498Szrj return 0;
5988*38fd1498Szrj }
5989*38fd1498Szrj
5990*38fd1498Szrj /* The function makes initial partition of STATES on equivalent
5991*38fd1498Szrj classes and saves it into CLASSES. This function requires the input
5992*38fd1498Szrj to be sorted via compare_states_for_equiv(). */
5993*38fd1498Szrj static int
init_equiv_class(vec<state_t> states,vec<state_t> * classes)5994*38fd1498Szrj init_equiv_class (vec<state_t> states, vec<state_t> *classes)
5995*38fd1498Szrj {
5996*38fd1498Szrj size_t i;
5997*38fd1498Szrj state_t prev = 0;
5998*38fd1498Szrj int class_num = 1;
5999*38fd1498Szrj
6000*38fd1498Szrj classes->create (150);
6001*38fd1498Szrj for (i = 0; i < states.length (); i++)
6002*38fd1498Szrj {
6003*38fd1498Szrj state_t state = states[i];
6004*38fd1498Szrj if (prev)
6005*38fd1498Szrj {
6006*38fd1498Szrj if (compare_states_for_equiv (&prev, &state) != 0)
6007*38fd1498Szrj {
6008*38fd1498Szrj classes->safe_push (prev);
6009*38fd1498Szrj class_num++;
6010*38fd1498Szrj prev = NULL;
6011*38fd1498Szrj }
6012*38fd1498Szrj }
6013*38fd1498Szrj state->equiv_class_num_1 = class_num;
6014*38fd1498Szrj state->next_equiv_class_state = prev;
6015*38fd1498Szrj prev = state;
6016*38fd1498Szrj }
6017*38fd1498Szrj if (prev)
6018*38fd1498Szrj classes->safe_push (prev);
6019*38fd1498Szrj return class_num;
6020*38fd1498Szrj }
6021*38fd1498Szrj
6022*38fd1498Szrj /* The function copies pointers to equivalent states from vla FROM
6023*38fd1498Szrj into vla TO. */
6024*38fd1498Szrj static void
copy_equiv_class(vec<state_t> * to,vec<state_t> from)6025*38fd1498Szrj copy_equiv_class (vec<state_t> *to, vec<state_t> from)
6026*38fd1498Szrj {
6027*38fd1498Szrj to->release ();
6028*38fd1498Szrj *to = from.copy ();
6029*38fd1498Szrj }
6030*38fd1498Szrj
6031*38fd1498Szrj /* The function processes equivalence class given by its first state,
6032*38fd1498Szrj FIRST_STATE, on odd iteration if ODD_ITERATION_FLAG. If there
6033*38fd1498Szrj are not equivalent states, the function partitions the class
6034*38fd1498Szrj removing nonequivalent states and placing them in
6035*38fd1498Szrj *NEXT_ITERATION_CLASSES, increments *NEW_EQUIV_CLASS_NUM_PTR ans
6036*38fd1498Szrj assigns it to the state equivalence number. If the class has been
6037*38fd1498Szrj partitioned, the function returns nonzero value. */
6038*38fd1498Szrj static int
partition_equiv_class(state_t first_state,int odd_iteration_flag,vec<state_t> * next_iteration_classes,int * new_equiv_class_num_ptr)6039*38fd1498Szrj partition_equiv_class (state_t first_state, int odd_iteration_flag,
6040*38fd1498Szrj vec<state_t> *next_iteration_classes,
6041*38fd1498Szrj int *new_equiv_class_num_ptr)
6042*38fd1498Szrj {
6043*38fd1498Szrj state_t new_equiv_class;
6044*38fd1498Szrj int partition_p;
6045*38fd1498Szrj state_t curr_state;
6046*38fd1498Szrj state_t prev_state;
6047*38fd1498Szrj state_t next_state;
6048*38fd1498Szrj
6049*38fd1498Szrj partition_p = 0;
6050*38fd1498Szrj
6051*38fd1498Szrj while (first_state != NULL)
6052*38fd1498Szrj {
6053*38fd1498Szrj new_equiv_class = NULL;
6054*38fd1498Szrj if (first_state->next_equiv_class_state != NULL)
6055*38fd1498Szrj {
6056*38fd1498Szrj /* There are more one states in the class equivalence. */
6057*38fd1498Szrj set_out_arc_insns_equiv_num (first_state, odd_iteration_flag);
6058*38fd1498Szrj for (prev_state = first_state,
6059*38fd1498Szrj curr_state = first_state->next_equiv_class_state;
6060*38fd1498Szrj curr_state != NULL;
6061*38fd1498Szrj curr_state = next_state)
6062*38fd1498Szrj {
6063*38fd1498Szrj next_state = curr_state->next_equiv_class_state;
6064*38fd1498Szrj if (state_is_differed (curr_state, first_state,
6065*38fd1498Szrj odd_iteration_flag))
6066*38fd1498Szrj {
6067*38fd1498Szrj /* Remove curr state from the class equivalence. */
6068*38fd1498Szrj prev_state->next_equiv_class_state = next_state;
6069*38fd1498Szrj /* Add curr state to the new class equivalence. */
6070*38fd1498Szrj curr_state->next_equiv_class_state = new_equiv_class;
6071*38fd1498Szrj if (new_equiv_class == NULL)
6072*38fd1498Szrj (*new_equiv_class_num_ptr)++;
6073*38fd1498Szrj if (odd_iteration_flag)
6074*38fd1498Szrj curr_state->equiv_class_num_2 = *new_equiv_class_num_ptr;
6075*38fd1498Szrj else
6076*38fd1498Szrj curr_state->equiv_class_num_1 = *new_equiv_class_num_ptr;
6077*38fd1498Szrj new_equiv_class = curr_state;
6078*38fd1498Szrj partition_p = 1;
6079*38fd1498Szrj }
6080*38fd1498Szrj else
6081*38fd1498Szrj prev_state = curr_state;
6082*38fd1498Szrj }
6083*38fd1498Szrj clear_arc_insns_equiv_num (first_state);
6084*38fd1498Szrj }
6085*38fd1498Szrj if (new_equiv_class != NULL)
6086*38fd1498Szrj next_iteration_classes->safe_push (new_equiv_class);
6087*38fd1498Szrj first_state = new_equiv_class;
6088*38fd1498Szrj }
6089*38fd1498Szrj return partition_p;
6090*38fd1498Szrj }
6091*38fd1498Szrj
6092*38fd1498Szrj /* The function finds equivalent states of AUTOMATON. */
6093*38fd1498Szrj static void
evaluate_equiv_classes(automaton_t automaton,vec<state_t> * equiv_classes)6094*38fd1498Szrj evaluate_equiv_classes (automaton_t automaton, vec<state_t> *equiv_classes)
6095*38fd1498Szrj {
6096*38fd1498Szrj int new_equiv_class_num;
6097*38fd1498Szrj int odd_iteration_flag;
6098*38fd1498Szrj int finish_flag;
6099*38fd1498Szrj vec<state_t> next_iteration_classes;
6100*38fd1498Szrj size_t i;
6101*38fd1498Szrj
6102*38fd1498Szrj all_achieved_states.create (1500);
6103*38fd1498Szrj pass_states (automaton, add_achieved_state);
6104*38fd1498Szrj pass_states (automaton, cache_presence);
6105*38fd1498Szrj all_achieved_states.qsort (compare_states_for_equiv);
6106*38fd1498Szrj
6107*38fd1498Szrj odd_iteration_flag = 0;
6108*38fd1498Szrj new_equiv_class_num = init_equiv_class (all_achieved_states,
6109*38fd1498Szrj &next_iteration_classes);
6110*38fd1498Szrj
6111*38fd1498Szrj do
6112*38fd1498Szrj {
6113*38fd1498Szrj odd_iteration_flag = !odd_iteration_flag;
6114*38fd1498Szrj finish_flag = 1;
6115*38fd1498Szrj copy_equiv_class (equiv_classes, next_iteration_classes);
6116*38fd1498Szrj
6117*38fd1498Szrj /* Transfer equiv numbers for the next iteration. */
6118*38fd1498Szrj for (i = 0; i < all_achieved_states.length (); i++)
6119*38fd1498Szrj if (odd_iteration_flag)
6120*38fd1498Szrj all_achieved_states[i]->equiv_class_num_2
6121*38fd1498Szrj = all_achieved_states[i]->equiv_class_num_1;
6122*38fd1498Szrj else
6123*38fd1498Szrj all_achieved_states[i]->equiv_class_num_1
6124*38fd1498Szrj = all_achieved_states[i]->equiv_class_num_2;
6125*38fd1498Szrj
6126*38fd1498Szrj for (i = 0; i < equiv_classes->length (); i++)
6127*38fd1498Szrj if (partition_equiv_class ((*equiv_classes)[i],
6128*38fd1498Szrj odd_iteration_flag,
6129*38fd1498Szrj &next_iteration_classes,
6130*38fd1498Szrj &new_equiv_class_num))
6131*38fd1498Szrj finish_flag = 0;
6132*38fd1498Szrj }
6133*38fd1498Szrj while (!finish_flag);
6134*38fd1498Szrj next_iteration_classes.release ();
6135*38fd1498Szrj all_achieved_states.release ();
6136*38fd1498Szrj }
6137*38fd1498Szrj
6138*38fd1498Szrj /* The function merges equivalent states of AUTOMATON. */
6139*38fd1498Szrj static void
merge_states(automaton_t automaton,vec<state_t> equiv_classes)6140*38fd1498Szrj merge_states (automaton_t automaton, vec<state_t> equiv_classes)
6141*38fd1498Szrj {
6142*38fd1498Szrj state_t curr_state;
6143*38fd1498Szrj state_t new_state;
6144*38fd1498Szrj state_t first_class_state;
6145*38fd1498Szrj alt_state_t alt_states;
6146*38fd1498Szrj alt_state_t alt_state, new_alt_state;
6147*38fd1498Szrj arc_t curr_arc;
6148*38fd1498Szrj arc_t next_arc;
6149*38fd1498Szrj size_t i;
6150*38fd1498Szrj
6151*38fd1498Szrj /* Create states corresponding to equivalence classes containing two
6152*38fd1498Szrj or more states. */
6153*38fd1498Szrj for (i = 0; i < equiv_classes.length (); i++)
6154*38fd1498Szrj {
6155*38fd1498Szrj curr_state = equiv_classes[i];
6156*38fd1498Szrj if (curr_state->next_equiv_class_state != NULL)
6157*38fd1498Szrj {
6158*38fd1498Szrj /* There are more one states in the class equivalence. */
6159*38fd1498Szrj /* Create new compound state. */
6160*38fd1498Szrj new_state = get_free_state (0, automaton);
6161*38fd1498Szrj alt_states = NULL;
6162*38fd1498Szrj first_class_state = curr_state;
6163*38fd1498Szrj for (curr_state = first_class_state;
6164*38fd1498Szrj curr_state != NULL;
6165*38fd1498Szrj curr_state = curr_state->next_equiv_class_state)
6166*38fd1498Szrj {
6167*38fd1498Szrj curr_state->equiv_class_state = new_state;
6168*38fd1498Szrj if (curr_state->component_states == NULL)
6169*38fd1498Szrj {
6170*38fd1498Szrj new_alt_state = get_free_alt_state ();
6171*38fd1498Szrj new_alt_state->state = curr_state;
6172*38fd1498Szrj new_alt_state->next_alt_state = alt_states;
6173*38fd1498Szrj alt_states = new_alt_state;
6174*38fd1498Szrj }
6175*38fd1498Szrj else
6176*38fd1498Szrj for (alt_state = curr_state->component_states;
6177*38fd1498Szrj alt_state != NULL;
6178*38fd1498Szrj alt_state = alt_state->next_sorted_alt_state)
6179*38fd1498Szrj {
6180*38fd1498Szrj new_alt_state = get_free_alt_state ();
6181*38fd1498Szrj new_alt_state->state = alt_state->state;
6182*38fd1498Szrj new_alt_state->next_alt_state = alt_states;
6183*38fd1498Szrj alt_states = new_alt_state;
6184*38fd1498Szrj }
6185*38fd1498Szrj }
6186*38fd1498Szrj /* It is important that alt states were sorted before and
6187*38fd1498Szrj after merging to have the same querying results. */
6188*38fd1498Szrj new_state->component_states = uniq_sort_alt_states (alt_states);
6189*38fd1498Szrj }
6190*38fd1498Szrj else
6191*38fd1498Szrj curr_state->equiv_class_state = curr_state;
6192*38fd1498Szrj }
6193*38fd1498Szrj
6194*38fd1498Szrj for (i = 0; i < equiv_classes.length (); i++)
6195*38fd1498Szrj {
6196*38fd1498Szrj curr_state = equiv_classes[i];
6197*38fd1498Szrj if (curr_state->next_equiv_class_state != NULL)
6198*38fd1498Szrj {
6199*38fd1498Szrj first_class_state = curr_state;
6200*38fd1498Szrj /* Create new arcs output from the state corresponding to
6201*38fd1498Szrj equiv class. */
6202*38fd1498Szrj for (curr_arc = first_out_arc (first_class_state);
6203*38fd1498Szrj curr_arc != NULL;
6204*38fd1498Szrj curr_arc = next_out_arc (curr_arc))
6205*38fd1498Szrj add_arc (first_class_state->equiv_class_state,
6206*38fd1498Szrj curr_arc->to_state->equiv_class_state,
6207*38fd1498Szrj curr_arc->insn);
6208*38fd1498Szrj /* Delete output arcs from states of given class equivalence. */
6209*38fd1498Szrj for (curr_state = first_class_state;
6210*38fd1498Szrj curr_state != NULL;
6211*38fd1498Szrj curr_state = curr_state->next_equiv_class_state)
6212*38fd1498Szrj {
6213*38fd1498Szrj if (automaton->start_state == curr_state)
6214*38fd1498Szrj automaton->start_state = curr_state->equiv_class_state;
6215*38fd1498Szrj /* Delete the state and its output arcs. */
6216*38fd1498Szrj for (curr_arc = first_out_arc (curr_state);
6217*38fd1498Szrj curr_arc != NULL;
6218*38fd1498Szrj curr_arc = next_arc)
6219*38fd1498Szrj {
6220*38fd1498Szrj next_arc = next_out_arc (curr_arc);
6221*38fd1498Szrj free_arc (curr_arc);
6222*38fd1498Szrj }
6223*38fd1498Szrj }
6224*38fd1498Szrj }
6225*38fd1498Szrj else
6226*38fd1498Szrj {
6227*38fd1498Szrj /* Change `to_state' of arcs output from the state of given
6228*38fd1498Szrj equivalence class. */
6229*38fd1498Szrj for (curr_arc = first_out_arc (curr_state);
6230*38fd1498Szrj curr_arc != NULL;
6231*38fd1498Szrj curr_arc = next_out_arc (curr_arc))
6232*38fd1498Szrj curr_arc->to_state = curr_arc->to_state->equiv_class_state;
6233*38fd1498Szrj }
6234*38fd1498Szrj }
6235*38fd1498Szrj }
6236*38fd1498Szrj
6237*38fd1498Szrj /* The function sets up new_cycle_p for states if there is arc to the
6238*38fd1498Szrj state marked by advance_cycle_insn_decl. */
6239*38fd1498Szrj static void
set_new_cycle_flags(state_t state)6240*38fd1498Szrj set_new_cycle_flags (state_t state)
6241*38fd1498Szrj {
6242*38fd1498Szrj arc_t arc;
6243*38fd1498Szrj
6244*38fd1498Szrj for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6245*38fd1498Szrj if (arc->insn->insn_reserv_decl
6246*38fd1498Szrj == DECL_INSN_RESERV (advance_cycle_insn_decl))
6247*38fd1498Szrj arc->to_state->new_cycle_p = 1;
6248*38fd1498Szrj }
6249*38fd1498Szrj
6250*38fd1498Szrj /* The top level function for minimization of deterministic
6251*38fd1498Szrj AUTOMATON. */
6252*38fd1498Szrj static void
minimize_DFA(automaton_t automaton)6253*38fd1498Szrj minimize_DFA (automaton_t automaton)
6254*38fd1498Szrj {
6255*38fd1498Szrj auto_vec<state_t> equiv_classes;
6256*38fd1498Szrj
6257*38fd1498Szrj evaluate_equiv_classes (automaton, &equiv_classes);
6258*38fd1498Szrj merge_states (automaton, equiv_classes);
6259*38fd1498Szrj pass_states (automaton, set_new_cycle_flags);
6260*38fd1498Szrj }
6261*38fd1498Szrj
6262*38fd1498Szrj /* Values of two variables are counted number of states and arcs in an
6263*38fd1498Szrj automaton. */
6264*38fd1498Szrj static int curr_counted_states_num;
6265*38fd1498Szrj static int curr_counted_arcs_num;
6266*38fd1498Szrj
6267*38fd1498Szrj /* The function is called by function `pass_states' to count states
6268*38fd1498Szrj and arcs of an automaton. */
6269*38fd1498Szrj static void
incr_states_and_arcs_nums(state_t state)6270*38fd1498Szrj incr_states_and_arcs_nums (state_t state)
6271*38fd1498Szrj {
6272*38fd1498Szrj arc_t arc;
6273*38fd1498Szrj
6274*38fd1498Szrj curr_counted_states_num++;
6275*38fd1498Szrj for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6276*38fd1498Szrj curr_counted_arcs_num++;
6277*38fd1498Szrj }
6278*38fd1498Szrj
6279*38fd1498Szrj /* The function counts states and arcs of AUTOMATON. */
6280*38fd1498Szrj static void
count_states_and_arcs(automaton_t automaton,int * states_num,int * arcs_num)6281*38fd1498Szrj count_states_and_arcs (automaton_t automaton, int *states_num,
6282*38fd1498Szrj int *arcs_num)
6283*38fd1498Szrj {
6284*38fd1498Szrj curr_counted_states_num = 0;
6285*38fd1498Szrj curr_counted_arcs_num = 0;
6286*38fd1498Szrj pass_states (automaton, incr_states_and_arcs_nums);
6287*38fd1498Szrj *states_num = curr_counted_states_num;
6288*38fd1498Szrj *arcs_num = curr_counted_arcs_num;
6289*38fd1498Szrj }
6290*38fd1498Szrj
6291*38fd1498Szrj /* The function builds one DFA AUTOMATON for fast pipeline hazards
6292*38fd1498Szrj recognition after checking and simplifying IR of the
6293*38fd1498Szrj description. */
6294*38fd1498Szrj static void
build_automaton(automaton_t automaton)6295*38fd1498Szrj build_automaton (automaton_t automaton)
6296*38fd1498Szrj {
6297*38fd1498Szrj int states_num;
6298*38fd1498Szrj int arcs_num;
6299*38fd1498Szrj
6300*38fd1498Szrj ticker_on (&NDFA_time);
6301*38fd1498Szrj if (progress_flag)
6302*38fd1498Szrj {
6303*38fd1498Szrj if (automaton->corresponding_automaton_decl == NULL)
6304*38fd1498Szrj fprintf (stderr, "Create anonymous automaton");
6305*38fd1498Szrj else
6306*38fd1498Szrj fprintf (stderr, "Create automaton `%s'",
6307*38fd1498Szrj automaton->corresponding_automaton_decl->name);
6308*38fd1498Szrj fprintf (stderr, " (1 dot is 100 new states):");
6309*38fd1498Szrj }
6310*38fd1498Szrj make_automaton (automaton);
6311*38fd1498Szrj if (progress_flag)
6312*38fd1498Szrj fprintf (stderr, " done\n");
6313*38fd1498Szrj ticker_off (&NDFA_time);
6314*38fd1498Szrj count_states_and_arcs (automaton, &states_num, &arcs_num);
6315*38fd1498Szrj automaton->NDFA_states_num = states_num;
6316*38fd1498Szrj automaton->NDFA_arcs_num = arcs_num;
6317*38fd1498Szrj ticker_on (&NDFA_to_DFA_time);
6318*38fd1498Szrj if (progress_flag)
6319*38fd1498Szrj {
6320*38fd1498Szrj if (automaton->corresponding_automaton_decl == NULL)
6321*38fd1498Szrj fprintf (stderr, "Make anonymous DFA");
6322*38fd1498Szrj else
6323*38fd1498Szrj fprintf (stderr, "Make DFA `%s'",
6324*38fd1498Szrj automaton->corresponding_automaton_decl->name);
6325*38fd1498Szrj fprintf (stderr, " (1 dot is 100 new states):");
6326*38fd1498Szrj }
6327*38fd1498Szrj NDFA_to_DFA (automaton);
6328*38fd1498Szrj if (progress_flag)
6329*38fd1498Szrj fprintf (stderr, " done\n");
6330*38fd1498Szrj ticker_off (&NDFA_to_DFA_time);
6331*38fd1498Szrj count_states_and_arcs (automaton, &states_num, &arcs_num);
6332*38fd1498Szrj automaton->DFA_states_num = states_num;
6333*38fd1498Szrj automaton->DFA_arcs_num = arcs_num;
6334*38fd1498Szrj if (!no_minimization_flag)
6335*38fd1498Szrj {
6336*38fd1498Szrj ticker_on (&minimize_time);
6337*38fd1498Szrj if (progress_flag)
6338*38fd1498Szrj {
6339*38fd1498Szrj if (automaton->corresponding_automaton_decl == NULL)
6340*38fd1498Szrj fprintf (stderr, "Minimize anonymous DFA...");
6341*38fd1498Szrj else
6342*38fd1498Szrj fprintf (stderr, "Minimize DFA `%s'...",
6343*38fd1498Szrj automaton->corresponding_automaton_decl->name);
6344*38fd1498Szrj }
6345*38fd1498Szrj minimize_DFA (automaton);
6346*38fd1498Szrj if (progress_flag)
6347*38fd1498Szrj fprintf (stderr, "done\n");
6348*38fd1498Szrj ticker_off (&minimize_time);
6349*38fd1498Szrj count_states_and_arcs (automaton, &states_num, &arcs_num);
6350*38fd1498Szrj automaton->minimal_DFA_states_num = states_num;
6351*38fd1498Szrj automaton->minimal_DFA_arcs_num = arcs_num;
6352*38fd1498Szrj }
6353*38fd1498Szrj }
6354*38fd1498Szrj
6355*38fd1498Szrj
6356*38fd1498Szrj
6357*38fd1498Szrj /* The page contains code for enumeration of all states of an automaton. */
6358*38fd1498Szrj
6359*38fd1498Szrj /* Variable used for enumeration of all states of an automaton. Its
6360*38fd1498Szrj value is current number of automaton states. */
6361*38fd1498Szrj static int curr_state_order_num;
6362*38fd1498Szrj
6363*38fd1498Szrj /* The function is called by function `pass_states' for enumerating
6364*38fd1498Szrj states. */
6365*38fd1498Szrj static void
set_order_state_num(state_t state)6366*38fd1498Szrj set_order_state_num (state_t state)
6367*38fd1498Szrj {
6368*38fd1498Szrj state->order_state_num = curr_state_order_num;
6369*38fd1498Szrj curr_state_order_num++;
6370*38fd1498Szrj }
6371*38fd1498Szrj
6372*38fd1498Szrj /* The function enumerates all states of AUTOMATON. */
6373*38fd1498Szrj static void
enumerate_states(automaton_t automaton)6374*38fd1498Szrj enumerate_states (automaton_t automaton)
6375*38fd1498Szrj {
6376*38fd1498Szrj curr_state_order_num = 0;
6377*38fd1498Szrj pass_states (automaton, set_order_state_num);
6378*38fd1498Szrj automaton->achieved_states_num = curr_state_order_num;
6379*38fd1498Szrj }
6380*38fd1498Szrj
6381*38fd1498Szrj
6382*38fd1498Szrj
6383*38fd1498Szrj /* The page contains code for finding equivalent automaton insns
6384*38fd1498Szrj (ainsns). */
6385*38fd1498Szrj
6386*38fd1498Szrj /* The function inserts AINSN into cyclic list
6387*38fd1498Szrj CYCLIC_EQUIV_CLASS_INSN_LIST of ainsns. */
6388*38fd1498Szrj static ainsn_t
insert_ainsn_into_equiv_class(ainsn_t ainsn,ainsn_t cyclic_equiv_class_insn_list)6389*38fd1498Szrj insert_ainsn_into_equiv_class (ainsn_t ainsn,
6390*38fd1498Szrj ainsn_t cyclic_equiv_class_insn_list)
6391*38fd1498Szrj {
6392*38fd1498Szrj if (cyclic_equiv_class_insn_list == NULL)
6393*38fd1498Szrj ainsn->next_equiv_class_insn = ainsn;
6394*38fd1498Szrj else
6395*38fd1498Szrj {
6396*38fd1498Szrj ainsn->next_equiv_class_insn
6397*38fd1498Szrj = cyclic_equiv_class_insn_list->next_equiv_class_insn;
6398*38fd1498Szrj cyclic_equiv_class_insn_list->next_equiv_class_insn = ainsn;
6399*38fd1498Szrj }
6400*38fd1498Szrj return ainsn;
6401*38fd1498Szrj }
6402*38fd1498Szrj
6403*38fd1498Szrj /* The function deletes equiv_class_insn into cyclic list of
6404*38fd1498Szrj equivalent ainsns. */
6405*38fd1498Szrj static void
delete_ainsn_from_equiv_class(ainsn_t equiv_class_insn)6406*38fd1498Szrj delete_ainsn_from_equiv_class (ainsn_t equiv_class_insn)
6407*38fd1498Szrj {
6408*38fd1498Szrj ainsn_t curr_equiv_class_insn;
6409*38fd1498Szrj ainsn_t prev_equiv_class_insn;
6410*38fd1498Szrj
6411*38fd1498Szrj prev_equiv_class_insn = equiv_class_insn;
6412*38fd1498Szrj for (curr_equiv_class_insn = equiv_class_insn->next_equiv_class_insn;
6413*38fd1498Szrj curr_equiv_class_insn != equiv_class_insn;
6414*38fd1498Szrj curr_equiv_class_insn = curr_equiv_class_insn->next_equiv_class_insn)
6415*38fd1498Szrj prev_equiv_class_insn = curr_equiv_class_insn;
6416*38fd1498Szrj if (prev_equiv_class_insn != equiv_class_insn)
6417*38fd1498Szrj prev_equiv_class_insn->next_equiv_class_insn
6418*38fd1498Szrj = equiv_class_insn->next_equiv_class_insn;
6419*38fd1498Szrj }
6420*38fd1498Szrj
6421*38fd1498Szrj /* The function processes AINSN of a state in order to find equivalent
6422*38fd1498Szrj ainsns. INSN_ARCS_ARRAY is table: code of insn -> out arc of the
6423*38fd1498Szrj state. */
6424*38fd1498Szrj static void
process_insn_equiv_class(ainsn_t ainsn,arc_t * insn_arcs_array)6425*38fd1498Szrj process_insn_equiv_class (ainsn_t ainsn, arc_t *insn_arcs_array)
6426*38fd1498Szrj {
6427*38fd1498Szrj ainsn_t next_insn;
6428*38fd1498Szrj ainsn_t curr_insn;
6429*38fd1498Szrj ainsn_t cyclic_insn_list;
6430*38fd1498Szrj arc_t arc;
6431*38fd1498Szrj
6432*38fd1498Szrj gcc_assert (insn_arcs_array [ainsn->insn_reserv_decl->insn_num]);
6433*38fd1498Szrj curr_insn = ainsn;
6434*38fd1498Szrj /* New class of ainsns which are not equivalent to given ainsn. */
6435*38fd1498Szrj cyclic_insn_list = NULL;
6436*38fd1498Szrj do
6437*38fd1498Szrj {
6438*38fd1498Szrj next_insn = curr_insn->next_equiv_class_insn;
6439*38fd1498Szrj arc = insn_arcs_array [curr_insn->insn_reserv_decl->insn_num];
6440*38fd1498Szrj if (arc == NULL
6441*38fd1498Szrj || (insn_arcs_array [ainsn->insn_reserv_decl->insn_num]->to_state
6442*38fd1498Szrj != arc->to_state))
6443*38fd1498Szrj {
6444*38fd1498Szrj delete_ainsn_from_equiv_class (curr_insn);
6445*38fd1498Szrj cyclic_insn_list = insert_ainsn_into_equiv_class (curr_insn,
6446*38fd1498Szrj cyclic_insn_list);
6447*38fd1498Szrj }
6448*38fd1498Szrj curr_insn = next_insn;
6449*38fd1498Szrj }
6450*38fd1498Szrj while (curr_insn != ainsn);
6451*38fd1498Szrj }
6452*38fd1498Szrj
6453*38fd1498Szrj /* The function processes STATE in order to find equivalent ainsns. */
6454*38fd1498Szrj static void
process_state_for_insn_equiv_partition(state_t state)6455*38fd1498Szrj process_state_for_insn_equiv_partition (state_t state)
6456*38fd1498Szrj {
6457*38fd1498Szrj arc_t arc;
6458*38fd1498Szrj arc_t *insn_arcs_array = XCNEWVEC (arc_t, description->insns_num);
6459*38fd1498Szrj
6460*38fd1498Szrj /* Process insns of the arcs. */
6461*38fd1498Szrj for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6462*38fd1498Szrj insn_arcs_array [arc->insn->insn_reserv_decl->insn_num] = arc;
6463*38fd1498Szrj for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6464*38fd1498Szrj process_insn_equiv_class (arc->insn, insn_arcs_array);
6465*38fd1498Szrj
6466*38fd1498Szrj free (insn_arcs_array);
6467*38fd1498Szrj }
6468*38fd1498Szrj
6469*38fd1498Szrj /* The function searches for equivalent ainsns of AUTOMATON. */
6470*38fd1498Szrj static void
set_insn_equiv_classes(automaton_t automaton)6471*38fd1498Szrj set_insn_equiv_classes (automaton_t automaton)
6472*38fd1498Szrj {
6473*38fd1498Szrj ainsn_t ainsn;
6474*38fd1498Szrj ainsn_t first_insn;
6475*38fd1498Szrj ainsn_t curr_insn;
6476*38fd1498Szrj ainsn_t cyclic_insn_list;
6477*38fd1498Szrj ainsn_t insn_with_same_reservs;
6478*38fd1498Szrj int equiv_classes_num;
6479*38fd1498Szrj
6480*38fd1498Szrj /* All insns are included in one equivalence class. */
6481*38fd1498Szrj cyclic_insn_list = NULL;
6482*38fd1498Szrj for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6483*38fd1498Szrj if (ainsn->first_insn_with_same_reservs)
6484*38fd1498Szrj cyclic_insn_list = insert_ainsn_into_equiv_class (ainsn,
6485*38fd1498Szrj cyclic_insn_list);
6486*38fd1498Szrj /* Process insns in order to make equivalence partition. */
6487*38fd1498Szrj pass_states (automaton, process_state_for_insn_equiv_partition);
6488*38fd1498Szrj /* Enumerate equiv classes. */
6489*38fd1498Szrj for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6490*38fd1498Szrj /* Set undefined value. */
6491*38fd1498Szrj ainsn->insn_equiv_class_num = -1;
6492*38fd1498Szrj equiv_classes_num = 0;
6493*38fd1498Szrj for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6494*38fd1498Szrj if (ainsn->insn_equiv_class_num < 0)
6495*38fd1498Szrj {
6496*38fd1498Szrj first_insn = ainsn;
6497*38fd1498Szrj gcc_assert (first_insn->first_insn_with_same_reservs);
6498*38fd1498Szrj first_insn->first_ainsn_with_given_equivalence_num = 1;
6499*38fd1498Szrj curr_insn = first_insn;
6500*38fd1498Szrj do
6501*38fd1498Szrj {
6502*38fd1498Szrj for (insn_with_same_reservs = curr_insn;
6503*38fd1498Szrj insn_with_same_reservs != NULL;
6504*38fd1498Szrj insn_with_same_reservs
6505*38fd1498Szrj = insn_with_same_reservs->next_same_reservs_insn)
6506*38fd1498Szrj insn_with_same_reservs->insn_equiv_class_num = equiv_classes_num;
6507*38fd1498Szrj curr_insn = curr_insn->next_equiv_class_insn;
6508*38fd1498Szrj }
6509*38fd1498Szrj while (curr_insn != first_insn);
6510*38fd1498Szrj equiv_classes_num++;
6511*38fd1498Szrj }
6512*38fd1498Szrj automaton->insn_equiv_classes_num = equiv_classes_num;
6513*38fd1498Szrj }
6514*38fd1498Szrj
6515*38fd1498Szrj
6516*38fd1498Szrj
6517*38fd1498Szrj /* This page contains code for creating DFA(s) and calls functions
6518*38fd1498Szrj building them. */
6519*38fd1498Szrj
6520*38fd1498Szrj
6521*38fd1498Szrj /* The following value is used to prevent floating point overflow for
6522*38fd1498Szrj estimating an automaton bound. The value should be less DBL_MAX on
6523*38fd1498Szrj the host machine. We use here approximate minimum of maximal
6524*38fd1498Szrj double floating point value required by ANSI C standard. It
6525*38fd1498Szrj will work for non ANSI sun compiler too. */
6526*38fd1498Szrj
6527*38fd1498Szrj #define MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND 1.0E37
6528*38fd1498Szrj
6529*38fd1498Szrj /* The function estimate size of the single DFA used by PHR (pipeline
6530*38fd1498Szrj hazards recognizer). */
6531*38fd1498Szrj static double
estimate_one_automaton_bound(void)6532*38fd1498Szrj estimate_one_automaton_bound (void)
6533*38fd1498Szrj {
6534*38fd1498Szrj decl_t decl;
6535*38fd1498Szrj double one_automaton_estimation_bound;
6536*38fd1498Szrj double root_value;
6537*38fd1498Szrj int i;
6538*38fd1498Szrj
6539*38fd1498Szrj one_automaton_estimation_bound = 1.0;
6540*38fd1498Szrj for (i = 0; i < description->decls_num; i++)
6541*38fd1498Szrj {
6542*38fd1498Szrj decl = description->decls [i];
6543*38fd1498Szrj if (decl->mode == dm_unit)
6544*38fd1498Szrj {
6545*38fd1498Szrj root_value = exp (log (DECL_UNIT (decl)->max_occ_cycle_num
6546*38fd1498Szrj - DECL_UNIT (decl)->min_occ_cycle_num + 1.0)
6547*38fd1498Szrj / automata_num);
6548*38fd1498Szrj if (MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND / root_value
6549*38fd1498Szrj > one_automaton_estimation_bound)
6550*38fd1498Szrj one_automaton_estimation_bound *= root_value;
6551*38fd1498Szrj }
6552*38fd1498Szrj }
6553*38fd1498Szrj return one_automaton_estimation_bound;
6554*38fd1498Szrj }
6555*38fd1498Szrj
6556*38fd1498Szrj /* The function compares unit declarations according to their maximal
6557*38fd1498Szrj cycle in reservations. */
6558*38fd1498Szrj static int
compare_max_occ_cycle_nums(const void * unit_decl_1,const void * unit_decl_2)6559*38fd1498Szrj compare_max_occ_cycle_nums (const void *unit_decl_1,
6560*38fd1498Szrj const void *unit_decl_2)
6561*38fd1498Szrj {
6562*38fd1498Szrj if ((DECL_UNIT (*(const_decl_t const*) unit_decl_1)->max_occ_cycle_num)
6563*38fd1498Szrj < (DECL_UNIT (*(const_decl_t const*) unit_decl_2)->max_occ_cycle_num))
6564*38fd1498Szrj return 1;
6565*38fd1498Szrj else if ((DECL_UNIT (*(const_decl_t const*) unit_decl_1)->max_occ_cycle_num)
6566*38fd1498Szrj == (DECL_UNIT (*(const_decl_t const*) unit_decl_2)->max_occ_cycle_num))
6567*38fd1498Szrj return 0;
6568*38fd1498Szrj else
6569*38fd1498Szrj return -1;
6570*38fd1498Szrj }
6571*38fd1498Szrj
6572*38fd1498Szrj /* The function makes heuristic assigning automata to units. Actually
6573*38fd1498Szrj efficacy of the algorithm has been checked yet??? */
6574*38fd1498Szrj
6575*38fd1498Szrj static void
units_to_automata_heuristic_distr(void)6576*38fd1498Szrj units_to_automata_heuristic_distr (void)
6577*38fd1498Szrj {
6578*38fd1498Szrj double estimation_bound;
6579*38fd1498Szrj int automaton_num;
6580*38fd1498Szrj int rest_units_num;
6581*38fd1498Szrj double bound_value;
6582*38fd1498Szrj unit_decl_t *unit_decls;
6583*38fd1498Szrj int i, j;
6584*38fd1498Szrj
6585*38fd1498Szrj if (description->units_num == 0)
6586*38fd1498Szrj return;
6587*38fd1498Szrj estimation_bound = estimate_one_automaton_bound ();
6588*38fd1498Szrj unit_decls = XNEWVEC (unit_decl_t, description->units_num);
6589*38fd1498Szrj
6590*38fd1498Szrj for (i = 0, j = 0; i < description->decls_num; i++)
6591*38fd1498Szrj if (description->decls[i]->mode == dm_unit)
6592*38fd1498Szrj unit_decls[j++] = DECL_UNIT (description->decls[i]);
6593*38fd1498Szrj gcc_assert (j == description->units_num);
6594*38fd1498Szrj
6595*38fd1498Szrj qsort (unit_decls, description->units_num,
6596*38fd1498Szrj sizeof (unit_decl_t), compare_max_occ_cycle_nums);
6597*38fd1498Szrj
6598*38fd1498Szrj automaton_num = 0;
6599*38fd1498Szrj bound_value = unit_decls[0]->max_occ_cycle_num;
6600*38fd1498Szrj unit_decls[0]->corresponding_automaton_num = automaton_num;
6601*38fd1498Szrj
6602*38fd1498Szrj for (i = 1; i < description->units_num; i++)
6603*38fd1498Szrj {
6604*38fd1498Szrj rest_units_num = description->units_num - i + 1;
6605*38fd1498Szrj gcc_assert (automata_num - automaton_num - 1 <= rest_units_num);
6606*38fd1498Szrj if (automaton_num < automata_num - 1
6607*38fd1498Szrj && ((automata_num - automaton_num - 1 == rest_units_num)
6608*38fd1498Szrj || (bound_value
6609*38fd1498Szrj > (estimation_bound
6610*38fd1498Szrj / unit_decls[i]->max_occ_cycle_num))))
6611*38fd1498Szrj {
6612*38fd1498Szrj bound_value = unit_decls[i]->max_occ_cycle_num;
6613*38fd1498Szrj automaton_num++;
6614*38fd1498Szrj }
6615*38fd1498Szrj else
6616*38fd1498Szrj bound_value *= unit_decls[i]->max_occ_cycle_num;
6617*38fd1498Szrj unit_decls[i]->corresponding_automaton_num = automaton_num;
6618*38fd1498Szrj }
6619*38fd1498Szrj gcc_assert (automaton_num == automata_num - 1);
6620*38fd1498Szrj free (unit_decls);
6621*38fd1498Szrj }
6622*38fd1498Szrj
6623*38fd1498Szrj /* The functions creates automaton insns for each automata. Automaton
6624*38fd1498Szrj insn is simply insn for given automaton which makes reservation
6625*38fd1498Szrj only of units of the automaton. */
6626*38fd1498Szrj static void
create_ainsns(automaton_t automaton)6627*38fd1498Szrj create_ainsns (automaton_t automaton)
6628*38fd1498Szrj {
6629*38fd1498Szrj decl_t decl;
6630*38fd1498Szrj ainsn_t first_ainsn;
6631*38fd1498Szrj ainsn_t curr_ainsn;
6632*38fd1498Szrj ainsn_t prev_ainsn;
6633*38fd1498Szrj int i;
6634*38fd1498Szrj
6635*38fd1498Szrj first_ainsn = NULL;
6636*38fd1498Szrj prev_ainsn = NULL;
6637*38fd1498Szrj for (i = 0; i < description->decls_num; i++)
6638*38fd1498Szrj {
6639*38fd1498Szrj decl = description->decls [i];
6640*38fd1498Szrj if (decl->mode == dm_insn_reserv)
6641*38fd1498Szrj {
6642*38fd1498Szrj curr_ainsn = XCREATENODE (struct ainsn);
6643*38fd1498Szrj curr_ainsn->insn_reserv_decl = DECL_INSN_RESERV (decl);
6644*38fd1498Szrj curr_ainsn->important_p = FALSE;
6645*38fd1498Szrj curr_ainsn->next_ainsn = NULL;
6646*38fd1498Szrj if (prev_ainsn == NULL)
6647*38fd1498Szrj first_ainsn = curr_ainsn;
6648*38fd1498Szrj else
6649*38fd1498Szrj prev_ainsn->next_ainsn = curr_ainsn;
6650*38fd1498Szrj if (decl == advance_cycle_insn_decl)
6651*38fd1498Szrj automaton->advance_ainsn = curr_ainsn;
6652*38fd1498Szrj else if (decl == collapse_ndfa_insn_decl)
6653*38fd1498Szrj automaton->collapse_ainsn = curr_ainsn;
6654*38fd1498Szrj prev_ainsn = curr_ainsn;
6655*38fd1498Szrj }
6656*38fd1498Szrj }
6657*38fd1498Szrj automaton->ainsn_list = first_ainsn;
6658*38fd1498Szrj }
6659*38fd1498Szrj
6660*38fd1498Szrj /* The function assigns automata to units according to constructions
6661*38fd1498Szrj `define_automaton' in the description. */
6662*38fd1498Szrj static void
units_to_automata_distr(void)6663*38fd1498Szrj units_to_automata_distr (void)
6664*38fd1498Szrj {
6665*38fd1498Szrj decl_t decl;
6666*38fd1498Szrj int i;
6667*38fd1498Szrj
6668*38fd1498Szrj for (i = 0; i < description->decls_num; i++)
6669*38fd1498Szrj {
6670*38fd1498Szrj decl = description->decls [i];
6671*38fd1498Szrj if (decl->mode == dm_unit)
6672*38fd1498Szrj {
6673*38fd1498Szrj if (DECL_UNIT (decl)->automaton_decl == NULL
6674*38fd1498Szrj || (DECL_UNIT (decl)->automaton_decl->corresponding_automaton
6675*38fd1498Szrj == NULL))
6676*38fd1498Szrj /* Distribute to the first automaton. */
6677*38fd1498Szrj DECL_UNIT (decl)->corresponding_automaton_num = 0;
6678*38fd1498Szrj else
6679*38fd1498Szrj DECL_UNIT (decl)->corresponding_automaton_num
6680*38fd1498Szrj = (DECL_UNIT (decl)->automaton_decl
6681*38fd1498Szrj ->corresponding_automaton->automaton_order_num);
6682*38fd1498Szrj }
6683*38fd1498Szrj }
6684*38fd1498Szrj }
6685*38fd1498Szrj
6686*38fd1498Szrj /* The function creates DFA(s) for fast pipeline hazards recognition
6687*38fd1498Szrj after checking and simplifying IR of the description. */
6688*38fd1498Szrj static void
create_automata(void)6689*38fd1498Szrj create_automata (void)
6690*38fd1498Szrj {
6691*38fd1498Szrj automaton_t curr_automaton;
6692*38fd1498Szrj automaton_t prev_automaton;
6693*38fd1498Szrj decl_t decl;
6694*38fd1498Szrj int curr_automaton_num;
6695*38fd1498Szrj int i;
6696*38fd1498Szrj
6697*38fd1498Szrj if (automata_num != 0)
6698*38fd1498Szrj {
6699*38fd1498Szrj units_to_automata_heuristic_distr ();
6700*38fd1498Szrj for (prev_automaton = NULL, curr_automaton_num = 0;
6701*38fd1498Szrj curr_automaton_num < automata_num;
6702*38fd1498Szrj curr_automaton_num++, prev_automaton = curr_automaton)
6703*38fd1498Szrj {
6704*38fd1498Szrj curr_automaton = XCREATENODE (struct automaton);
6705*38fd1498Szrj create_ainsns (curr_automaton);
6706*38fd1498Szrj curr_automaton->corresponding_automaton_decl = NULL;
6707*38fd1498Szrj curr_automaton->next_automaton = NULL;
6708*38fd1498Szrj curr_automaton->automaton_order_num = curr_automaton_num;
6709*38fd1498Szrj if (prev_automaton == NULL)
6710*38fd1498Szrj description->first_automaton = curr_automaton;
6711*38fd1498Szrj else
6712*38fd1498Szrj prev_automaton->next_automaton = curr_automaton;
6713*38fd1498Szrj }
6714*38fd1498Szrj }
6715*38fd1498Szrj else
6716*38fd1498Szrj {
6717*38fd1498Szrj curr_automaton_num = 0;
6718*38fd1498Szrj prev_automaton = NULL;
6719*38fd1498Szrj for (i = 0; i < description->decls_num; i++)
6720*38fd1498Szrj {
6721*38fd1498Szrj decl = description->decls [i];
6722*38fd1498Szrj if (decl->mode == dm_automaton
6723*38fd1498Szrj && DECL_AUTOMATON (decl)->automaton_is_used)
6724*38fd1498Szrj {
6725*38fd1498Szrj curr_automaton = XCREATENODE (struct automaton);
6726*38fd1498Szrj create_ainsns (curr_automaton);
6727*38fd1498Szrj curr_automaton->corresponding_automaton_decl
6728*38fd1498Szrj = DECL_AUTOMATON (decl);
6729*38fd1498Szrj curr_automaton->next_automaton = NULL;
6730*38fd1498Szrj DECL_AUTOMATON (decl)->corresponding_automaton = curr_automaton;
6731*38fd1498Szrj curr_automaton->automaton_order_num = curr_automaton_num;
6732*38fd1498Szrj if (prev_automaton == NULL)
6733*38fd1498Szrj description->first_automaton = curr_automaton;
6734*38fd1498Szrj else
6735*38fd1498Szrj prev_automaton->next_automaton = curr_automaton;
6736*38fd1498Szrj curr_automaton_num++;
6737*38fd1498Szrj prev_automaton = curr_automaton;
6738*38fd1498Szrj }
6739*38fd1498Szrj }
6740*38fd1498Szrj if (curr_automaton_num == 0)
6741*38fd1498Szrj {
6742*38fd1498Szrj curr_automaton = XCREATENODE (struct automaton);
6743*38fd1498Szrj create_ainsns (curr_automaton);
6744*38fd1498Szrj curr_automaton->corresponding_automaton_decl = NULL;
6745*38fd1498Szrj curr_automaton->next_automaton = NULL;
6746*38fd1498Szrj description->first_automaton = curr_automaton;
6747*38fd1498Szrj }
6748*38fd1498Szrj units_to_automata_distr ();
6749*38fd1498Szrj }
6750*38fd1498Szrj NDFA_time = create_ticker ();
6751*38fd1498Szrj ticker_off (&NDFA_time);
6752*38fd1498Szrj NDFA_to_DFA_time = create_ticker ();
6753*38fd1498Szrj ticker_off (&NDFA_to_DFA_time);
6754*38fd1498Szrj minimize_time = create_ticker ();
6755*38fd1498Szrj ticker_off (&minimize_time);
6756*38fd1498Szrj equiv_time = create_ticker ();
6757*38fd1498Szrj ticker_off (&equiv_time);
6758*38fd1498Szrj for (curr_automaton = description->first_automaton;
6759*38fd1498Szrj curr_automaton != NULL;
6760*38fd1498Szrj curr_automaton = curr_automaton->next_automaton)
6761*38fd1498Szrj {
6762*38fd1498Szrj if (progress_flag)
6763*38fd1498Szrj {
6764*38fd1498Szrj if (curr_automaton->corresponding_automaton_decl == NULL)
6765*38fd1498Szrj fprintf (stderr, "Prepare anonymous automaton creation ... ");
6766*38fd1498Szrj else
6767*38fd1498Szrj fprintf (stderr, "Prepare automaton `%s' creation...",
6768*38fd1498Szrj curr_automaton->corresponding_automaton_decl->name);
6769*38fd1498Szrj }
6770*38fd1498Szrj create_alt_states (curr_automaton);
6771*38fd1498Szrj form_ainsn_with_same_reservs (curr_automaton);
6772*38fd1498Szrj if (progress_flag)
6773*38fd1498Szrj fprintf (stderr, "done\n");
6774*38fd1498Szrj build_automaton (curr_automaton);
6775*38fd1498Szrj enumerate_states (curr_automaton);
6776*38fd1498Szrj ticker_on (&equiv_time);
6777*38fd1498Szrj set_insn_equiv_classes (curr_automaton);
6778*38fd1498Szrj ticker_off (&equiv_time);
6779*38fd1498Szrj }
6780*38fd1498Szrj }
6781*38fd1498Szrj
6782*38fd1498Szrj
6783*38fd1498Szrj
6784*38fd1498Szrj /* This page contains code for forming string representation of
6785*38fd1498Szrj regexp. The representation is formed on IR obstack. So you should
6786*38fd1498Szrj not work with IR obstack between regexp_representation and
6787*38fd1498Szrj finish_regexp_representation calls. */
6788*38fd1498Szrj
6789*38fd1498Szrj /* This recursive function forms string representation of regexp
6790*38fd1498Szrj (without tailing '\0'). */
6791*38fd1498Szrj static void
form_regexp(regexp_t regexp)6792*38fd1498Szrj form_regexp (regexp_t regexp)
6793*38fd1498Szrj {
6794*38fd1498Szrj int i;
6795*38fd1498Szrj
6796*38fd1498Szrj switch (regexp->mode)
6797*38fd1498Szrj {
6798*38fd1498Szrj case rm_unit: case rm_reserv:
6799*38fd1498Szrj {
6800*38fd1498Szrj const char *name = (regexp->mode == rm_unit
6801*38fd1498Szrj ? REGEXP_UNIT (regexp)->name
6802*38fd1498Szrj : REGEXP_RESERV (regexp)->name);
6803*38fd1498Szrj
6804*38fd1498Szrj obstack_grow (&irp, name, strlen (name));
6805*38fd1498Szrj break;
6806*38fd1498Szrj }
6807*38fd1498Szrj
6808*38fd1498Szrj case rm_sequence:
6809*38fd1498Szrj for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
6810*38fd1498Szrj {
6811*38fd1498Szrj if (i != 0)
6812*38fd1498Szrj obstack_1grow (&irp, ',');
6813*38fd1498Szrj form_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
6814*38fd1498Szrj }
6815*38fd1498Szrj break;
6816*38fd1498Szrj
6817*38fd1498Szrj case rm_allof:
6818*38fd1498Szrj obstack_1grow (&irp, '(');
6819*38fd1498Szrj for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
6820*38fd1498Szrj {
6821*38fd1498Szrj if (i != 0)
6822*38fd1498Szrj obstack_1grow (&irp, '+');
6823*38fd1498Szrj if (REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_sequence
6824*38fd1498Szrj || REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_oneof)
6825*38fd1498Szrj obstack_1grow (&irp, '(');
6826*38fd1498Szrj form_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
6827*38fd1498Szrj if (REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_sequence
6828*38fd1498Szrj || REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_oneof)
6829*38fd1498Szrj obstack_1grow (&irp, ')');
6830*38fd1498Szrj }
6831*38fd1498Szrj obstack_1grow (&irp, ')');
6832*38fd1498Szrj break;
6833*38fd1498Szrj
6834*38fd1498Szrj case rm_oneof:
6835*38fd1498Szrj for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
6836*38fd1498Szrj {
6837*38fd1498Szrj if (i != 0)
6838*38fd1498Szrj obstack_1grow (&irp, '|');
6839*38fd1498Szrj if (REGEXP_ONEOF (regexp)->regexps[i]->mode == rm_sequence)
6840*38fd1498Szrj obstack_1grow (&irp, '(');
6841*38fd1498Szrj form_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
6842*38fd1498Szrj if (REGEXP_ONEOF (regexp)->regexps[i]->mode == rm_sequence)
6843*38fd1498Szrj obstack_1grow (&irp, ')');
6844*38fd1498Szrj }
6845*38fd1498Szrj break;
6846*38fd1498Szrj
6847*38fd1498Szrj case rm_repeat:
6848*38fd1498Szrj {
6849*38fd1498Szrj char digits [30];
6850*38fd1498Szrj
6851*38fd1498Szrj if (REGEXP_REPEAT (regexp)->regexp->mode == rm_sequence
6852*38fd1498Szrj || REGEXP_REPEAT (regexp)->regexp->mode == rm_allof
6853*38fd1498Szrj || REGEXP_REPEAT (regexp)->regexp->mode == rm_oneof)
6854*38fd1498Szrj obstack_1grow (&irp, '(');
6855*38fd1498Szrj form_regexp (REGEXP_REPEAT (regexp)->regexp);
6856*38fd1498Szrj if (REGEXP_REPEAT (regexp)->regexp->mode == rm_sequence
6857*38fd1498Szrj || REGEXP_REPEAT (regexp)->regexp->mode == rm_allof
6858*38fd1498Szrj || REGEXP_REPEAT (regexp)->regexp->mode == rm_oneof)
6859*38fd1498Szrj obstack_1grow (&irp, ')');
6860*38fd1498Szrj sprintf (digits, "*%d", REGEXP_REPEAT (regexp)->repeat_num);
6861*38fd1498Szrj obstack_grow (&irp, digits, strlen (digits));
6862*38fd1498Szrj break;
6863*38fd1498Szrj }
6864*38fd1498Szrj
6865*38fd1498Szrj case rm_nothing:
6866*38fd1498Szrj obstack_grow (&irp, NOTHING_NAME, strlen (NOTHING_NAME));
6867*38fd1498Szrj break;
6868*38fd1498Szrj
6869*38fd1498Szrj default:
6870*38fd1498Szrj gcc_unreachable ();
6871*38fd1498Szrj }
6872*38fd1498Szrj }
6873*38fd1498Szrj
6874*38fd1498Szrj /* The function returns string representation of REGEXP on IR
6875*38fd1498Szrj obstack. */
6876*38fd1498Szrj static const char *
regexp_representation(regexp_t regexp)6877*38fd1498Szrj regexp_representation (regexp_t regexp)
6878*38fd1498Szrj {
6879*38fd1498Szrj form_regexp (regexp);
6880*38fd1498Szrj obstack_1grow (&irp, '\0');
6881*38fd1498Szrj return (char *) obstack_base (&irp);
6882*38fd1498Szrj }
6883*38fd1498Szrj
6884*38fd1498Szrj /* The function frees memory allocated for last formed string
6885*38fd1498Szrj representation of regexp. */
6886*38fd1498Szrj static void
finish_regexp_representation(void)6887*38fd1498Szrj finish_regexp_representation (void)
6888*38fd1498Szrj {
6889*38fd1498Szrj int length = obstack_object_size (&irp);
6890*38fd1498Szrj
6891*38fd1498Szrj obstack_blank_fast (&irp, -length);
6892*38fd1498Szrj }
6893*38fd1498Szrj
6894*38fd1498Szrj
6895*38fd1498Szrj
6896*38fd1498Szrj /* This page contains code for output PHR (pipeline hazards recognizer). */
6897*38fd1498Szrj
6898*38fd1498Szrj /* The function outputs minimal C type which is sufficient for
6899*38fd1498Szrj representation numbers in range min_range_value and
6900*38fd1498Szrj max_range_value. Because host machine and build machine may be
6901*38fd1498Szrj different, we use here minimal values required by ANSI C standard
6902*38fd1498Szrj instead of UCHAR_MAX, SHRT_MAX, SHRT_MIN, etc. This is a good
6903*38fd1498Szrj approximation. */
6904*38fd1498Szrj
6905*38fd1498Szrj static void
output_range_type(FILE * f,long int min_range_value,long int max_range_value)6906*38fd1498Szrj output_range_type (FILE *f, long int min_range_value,
6907*38fd1498Szrj long int max_range_value)
6908*38fd1498Szrj {
6909*38fd1498Szrj if (min_range_value >= 0 && max_range_value <= 255)
6910*38fd1498Szrj fprintf (f, "unsigned char");
6911*38fd1498Szrj else if (min_range_value >= -127 && max_range_value <= 127)
6912*38fd1498Szrj fprintf (f, "signed char");
6913*38fd1498Szrj else if (min_range_value >= 0 && max_range_value <= 65535)
6914*38fd1498Szrj fprintf (f, "unsigned short");
6915*38fd1498Szrj else if (min_range_value >= -32767 && max_range_value <= 32767)
6916*38fd1498Szrj fprintf (f, "short");
6917*38fd1498Szrj else
6918*38fd1498Szrj fprintf (f, "int");
6919*38fd1498Szrj }
6920*38fd1498Szrj
6921*38fd1498Szrj /* The function outputs all initialization values of VECT. */
6922*38fd1498Szrj static void
output_vect(vla_hwint_t vect)6923*38fd1498Szrj output_vect (vla_hwint_t vect)
6924*38fd1498Szrj {
6925*38fd1498Szrj int els_on_line;
6926*38fd1498Szrj size_t vect_length = vect.length ();
6927*38fd1498Szrj size_t i;
6928*38fd1498Szrj
6929*38fd1498Szrj els_on_line = 1;
6930*38fd1498Szrj if (vect_length == 0)
6931*38fd1498Szrj fputs ("0 /* This is dummy el because the vect is empty */", output_file);
6932*38fd1498Szrj else
6933*38fd1498Szrj for (i = 0; i < vect_length; i++)
6934*38fd1498Szrj {
6935*38fd1498Szrj fprintf (output_file, "%5ld", (long) vect[i]);
6936*38fd1498Szrj if (els_on_line == 10)
6937*38fd1498Szrj {
6938*38fd1498Szrj els_on_line = 0;
6939*38fd1498Szrj fputs (",\n", output_file);
6940*38fd1498Szrj }
6941*38fd1498Szrj else if (i < vect_length-1)
6942*38fd1498Szrj fputs (", ", output_file);
6943*38fd1498Szrj els_on_line++;
6944*38fd1498Szrj }
6945*38fd1498Szrj }
6946*38fd1498Szrj
6947*38fd1498Szrj /* The following is name of the structure which represents DFA(s) for
6948*38fd1498Szrj PHR. */
6949*38fd1498Szrj #define CHIP_NAME "DFA_chip"
6950*38fd1498Szrj
6951*38fd1498Szrj /* The following is name of member which represents state of a DFA for
6952*38fd1498Szrj PHR. */
6953*38fd1498Szrj static void
output_chip_member_name(FILE * f,automaton_t automaton)6954*38fd1498Szrj output_chip_member_name (FILE *f, automaton_t automaton)
6955*38fd1498Szrj {
6956*38fd1498Szrj if (automaton->corresponding_automaton_decl == NULL)
6957*38fd1498Szrj fprintf (f, "automaton_state_%d", automaton->automaton_order_num);
6958*38fd1498Szrj else
6959*38fd1498Szrj fprintf (f, "%s_automaton_state",
6960*38fd1498Szrj automaton->corresponding_automaton_decl->name);
6961*38fd1498Szrj }
6962*38fd1498Szrj
6963*38fd1498Szrj /* The following is name of temporary variable which stores state of a
6964*38fd1498Szrj DFA for PHR. */
6965*38fd1498Szrj static void
output_temp_chip_member_name(FILE * f,automaton_t automaton)6966*38fd1498Szrj output_temp_chip_member_name (FILE *f, automaton_t automaton)
6967*38fd1498Szrj {
6968*38fd1498Szrj fprintf (f, "_");
6969*38fd1498Szrj output_chip_member_name (f, automaton);
6970*38fd1498Szrj }
6971*38fd1498Szrj
6972*38fd1498Szrj /* This is name of macro value which is code of pseudo_insns
6973*38fd1498Szrj representing advancing cpu cycle and collapsing the NDFA.
6974*38fd1498Szrj Its value is used as internal code unknown insn. */
6975*38fd1498Szrj #define ADVANCE_CYCLE_VALUE_NAME "DFA__ADVANCE_CYCLE"
6976*38fd1498Szrj #define COLLAPSE_NDFA_VALUE_NAME "NDFA__COLLAPSE"
6977*38fd1498Szrj
6978*38fd1498Szrj /* Output name of translate vector for given automaton. */
6979*38fd1498Szrj static void
output_translate_vect_name(FILE * f,automaton_t automaton)6980*38fd1498Szrj output_translate_vect_name (FILE *f, automaton_t automaton)
6981*38fd1498Szrj {
6982*38fd1498Szrj if (automaton->corresponding_automaton_decl == NULL)
6983*38fd1498Szrj fprintf (f, "translate_%d", automaton->automaton_order_num);
6984*38fd1498Szrj else
6985*38fd1498Szrj fprintf (f, "%s_translate", automaton->corresponding_automaton_decl->name);
6986*38fd1498Szrj }
6987*38fd1498Szrj
6988*38fd1498Szrj /* Output name for simple transition table representation. */
6989*38fd1498Szrj static void
output_trans_full_vect_name(FILE * f,automaton_t automaton)6990*38fd1498Szrj output_trans_full_vect_name (FILE *f, automaton_t automaton)
6991*38fd1498Szrj {
6992*38fd1498Szrj if (automaton->corresponding_automaton_decl == NULL)
6993*38fd1498Szrj fprintf (f, "transitions_%d", automaton->automaton_order_num);
6994*38fd1498Szrj else
6995*38fd1498Szrj fprintf (f, "%s_transitions",
6996*38fd1498Szrj automaton->corresponding_automaton_decl->name);
6997*38fd1498Szrj }
6998*38fd1498Szrj
6999*38fd1498Szrj /* Output name of comb vector of the transition table for given
7000*38fd1498Szrj automaton. */
7001*38fd1498Szrj static void
output_trans_comb_vect_name(FILE * f,automaton_t automaton)7002*38fd1498Szrj output_trans_comb_vect_name (FILE *f, automaton_t automaton)
7003*38fd1498Szrj {
7004*38fd1498Szrj if (automaton->corresponding_automaton_decl == NULL)
7005*38fd1498Szrj fprintf (f, "transitions_%d", automaton->automaton_order_num);
7006*38fd1498Szrj else
7007*38fd1498Szrj fprintf (f, "%s_transitions",
7008*38fd1498Szrj automaton->corresponding_automaton_decl->name);
7009*38fd1498Szrj }
7010*38fd1498Szrj
7011*38fd1498Szrj /* Output name of check vector of the transition table for given
7012*38fd1498Szrj automaton. */
7013*38fd1498Szrj static void
output_trans_check_vect_name(FILE * f,automaton_t automaton)7014*38fd1498Szrj output_trans_check_vect_name (FILE *f, automaton_t automaton)
7015*38fd1498Szrj {
7016*38fd1498Szrj if (automaton->corresponding_automaton_decl == NULL)
7017*38fd1498Szrj fprintf (f, "check_%d", automaton->automaton_order_num);
7018*38fd1498Szrj else
7019*38fd1498Szrj fprintf (f, "%s_check", automaton->corresponding_automaton_decl->name);
7020*38fd1498Szrj }
7021*38fd1498Szrj
7022*38fd1498Szrj /* Output name of base vector of the transition table for given
7023*38fd1498Szrj automaton. */
7024*38fd1498Szrj static void
output_trans_base_vect_name(FILE * f,automaton_t automaton)7025*38fd1498Szrj output_trans_base_vect_name (FILE *f, automaton_t automaton)
7026*38fd1498Szrj {
7027*38fd1498Szrj if (automaton->corresponding_automaton_decl == NULL)
7028*38fd1498Szrj fprintf (f, "base_%d", automaton->automaton_order_num);
7029*38fd1498Szrj else
7030*38fd1498Szrj fprintf (f, "%s_base", automaton->corresponding_automaton_decl->name);
7031*38fd1498Szrj }
7032*38fd1498Szrj
7033*38fd1498Szrj /* Output name of simple min issue delay table representation. */
7034*38fd1498Szrj static void
output_min_issue_delay_vect_name(FILE * f,automaton_t automaton)7035*38fd1498Szrj output_min_issue_delay_vect_name (FILE *f, automaton_t automaton)
7036*38fd1498Szrj {
7037*38fd1498Szrj if (automaton->corresponding_automaton_decl == NULL)
7038*38fd1498Szrj fprintf (f, "min_issue_delay_%d", automaton->automaton_order_num);
7039*38fd1498Szrj else
7040*38fd1498Szrj fprintf (f, "%s_min_issue_delay",
7041*38fd1498Szrj automaton->corresponding_automaton_decl->name);
7042*38fd1498Szrj }
7043*38fd1498Szrj
7044*38fd1498Szrj /* Output name of deadlock vector for given automaton. */
7045*38fd1498Szrj static void
output_dead_lock_vect_name(FILE * f,automaton_t automaton)7046*38fd1498Szrj output_dead_lock_vect_name (FILE *f, automaton_t automaton)
7047*38fd1498Szrj {
7048*38fd1498Szrj if (automaton->corresponding_automaton_decl == NULL)
7049*38fd1498Szrj fprintf (f, "dead_lock_%d", automaton->automaton_order_num);
7050*38fd1498Szrj else
7051*38fd1498Szrj fprintf (f, "%s_dead_lock", automaton->corresponding_automaton_decl->name);
7052*38fd1498Szrj }
7053*38fd1498Szrj
7054*38fd1498Szrj /* Output name of reserved units table for AUTOMATON into file F. */
7055*38fd1498Szrj static void
output_reserved_units_table_name(FILE * f,automaton_t automaton)7056*38fd1498Szrj output_reserved_units_table_name (FILE *f, automaton_t automaton)
7057*38fd1498Szrj {
7058*38fd1498Szrj if (automaton->corresponding_automaton_decl == NULL)
7059*38fd1498Szrj fprintf (f, "reserved_units_%d", automaton->automaton_order_num);
7060*38fd1498Szrj else
7061*38fd1498Szrj fprintf (f, "%s_reserved_units",
7062*38fd1498Szrj automaton->corresponding_automaton_decl->name);
7063*38fd1498Szrj }
7064*38fd1498Szrj
7065*38fd1498Szrj /* Name of the PHR interface macro. */
7066*38fd1498Szrj #define CPU_UNITS_QUERY_MACRO_NAME "CPU_UNITS_QUERY"
7067*38fd1498Szrj
7068*38fd1498Szrj /* Names of an internal functions: */
7069*38fd1498Szrj #define INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME "internal_min_issue_delay"
7070*38fd1498Szrj
7071*38fd1498Szrj /* This is external type of DFA(s) state. */
7072*38fd1498Szrj #define STATE_TYPE_NAME "state_t"
7073*38fd1498Szrj
7074*38fd1498Szrj #define INTERNAL_TRANSITION_FUNC_NAME "internal_state_transition"
7075*38fd1498Szrj
7076*38fd1498Szrj #define INTERNAL_RESET_FUNC_NAME "internal_reset"
7077*38fd1498Szrj
7078*38fd1498Szrj #define INTERNAL_DEAD_LOCK_FUNC_NAME "internal_state_dead_lock_p"
7079*38fd1498Szrj
7080*38fd1498Szrj #define INTERNAL_INSN_LATENCY_FUNC_NAME "internal_insn_latency"
7081*38fd1498Szrj
7082*38fd1498Szrj /* Name of cache of insn dfa codes. */
7083*38fd1498Szrj #define DFA_INSN_CODES_VARIABLE_NAME "dfa_insn_codes"
7084*38fd1498Szrj
7085*38fd1498Szrj /* Name of length of cache of insn dfa codes. */
7086*38fd1498Szrj #define DFA_INSN_CODES_LENGTH_VARIABLE_NAME "dfa_insn_codes_length"
7087*38fd1498Szrj
7088*38fd1498Szrj /* Names of the PHR interface functions: */
7089*38fd1498Szrj #define SIZE_FUNC_NAME "state_size"
7090*38fd1498Szrj
7091*38fd1498Szrj #define TRANSITION_FUNC_NAME "state_transition"
7092*38fd1498Szrj
7093*38fd1498Szrj #define MIN_ISSUE_DELAY_FUNC_NAME "min_issue_delay"
7094*38fd1498Szrj
7095*38fd1498Szrj #define MIN_INSN_CONFLICT_DELAY_FUNC_NAME "min_insn_conflict_delay"
7096*38fd1498Szrj
7097*38fd1498Szrj #define DEAD_LOCK_FUNC_NAME "state_dead_lock_p"
7098*38fd1498Szrj
7099*38fd1498Szrj #define RESET_FUNC_NAME "state_reset"
7100*38fd1498Szrj
7101*38fd1498Szrj #define INSN_LATENCY_FUNC_NAME "insn_latency"
7102*38fd1498Szrj
7103*38fd1498Szrj #define PRINT_RESERVATION_FUNC_NAME "print_reservation"
7104*38fd1498Szrj
7105*38fd1498Szrj #define GET_CPU_UNIT_CODE_FUNC_NAME "get_cpu_unit_code"
7106*38fd1498Szrj
7107*38fd1498Szrj #define CPU_UNIT_RESERVATION_P_FUNC_NAME "cpu_unit_reservation_p"
7108*38fd1498Szrj
7109*38fd1498Szrj #define INSN_HAS_DFA_RESERVATION_P_FUNC_NAME "insn_has_dfa_reservation_p"
7110*38fd1498Szrj
7111*38fd1498Szrj #define DFA_CLEAN_INSN_CACHE_FUNC_NAME "dfa_clean_insn_cache"
7112*38fd1498Szrj
7113*38fd1498Szrj #define DFA_CLEAR_SINGLE_INSN_CACHE_FUNC_NAME "dfa_clear_single_insn_cache"
7114*38fd1498Szrj
7115*38fd1498Szrj #define DFA_START_FUNC_NAME "dfa_start"
7116*38fd1498Szrj
7117*38fd1498Szrj #define DFA_FINISH_FUNC_NAME "dfa_finish"
7118*38fd1498Szrj
7119*38fd1498Szrj /* Names of parameters of the PHR interface functions. */
7120*38fd1498Szrj #define STATE_NAME "state"
7121*38fd1498Szrj
7122*38fd1498Szrj #define INSN_PARAMETER_NAME "insn"
7123*38fd1498Szrj
7124*38fd1498Szrj #define INSN2_PARAMETER_NAME "insn2"
7125*38fd1498Szrj
7126*38fd1498Szrj #define CHIP_PARAMETER_NAME "chip"
7127*38fd1498Szrj
7128*38fd1498Szrj #define FILE_PARAMETER_NAME "f"
7129*38fd1498Szrj
7130*38fd1498Szrj #define CPU_UNIT_NAME_PARAMETER_NAME "cpu_unit_name"
7131*38fd1498Szrj
7132*38fd1498Szrj #define CPU_CODE_PARAMETER_NAME "cpu_unit_code"
7133*38fd1498Szrj
7134*38fd1498Szrj /* Names of the variables whose values are internal insn code of rtx
7135*38fd1498Szrj insn. */
7136*38fd1498Szrj #define INTERNAL_INSN_CODE_NAME "insn_code"
7137*38fd1498Szrj
7138*38fd1498Szrj #define INTERNAL_INSN2_CODE_NAME "insn2_code"
7139*38fd1498Szrj
7140*38fd1498Szrj /* Names of temporary variables in some functions. */
7141*38fd1498Szrj #define TEMPORARY_VARIABLE_NAME "temp"
7142*38fd1498Szrj
7143*38fd1498Szrj #define I_VARIABLE_NAME "i"
7144*38fd1498Szrj
7145*38fd1498Szrj /* Name of result variable in some functions. */
7146*38fd1498Szrj #define RESULT_VARIABLE_NAME "res"
7147*38fd1498Szrj
7148*38fd1498Szrj /* Name of function (attribute) to translate insn into internal insn
7149*38fd1498Szrj code. */
7150*38fd1498Szrj #define INTERNAL_DFA_INSN_CODE_FUNC_NAME "internal_dfa_insn_code"
7151*38fd1498Szrj
7152*38fd1498Szrj /* Name of function (attribute) to translate insn into internal insn
7153*38fd1498Szrj code with caching. */
7154*38fd1498Szrj #define DFA_INSN_CODE_FUNC_NAME "dfa_insn_code"
7155*38fd1498Szrj
7156*38fd1498Szrj /* Output C type which is used for representation of codes of states
7157*38fd1498Szrj of AUTOMATON. */
7158*38fd1498Szrj static void
output_state_member_type(FILE * f,automaton_t automaton)7159*38fd1498Szrj output_state_member_type (FILE *f, automaton_t automaton)
7160*38fd1498Szrj {
7161*38fd1498Szrj output_range_type (f, 0, automaton->achieved_states_num);
7162*38fd1498Szrj }
7163*38fd1498Szrj
7164*38fd1498Szrj /* Output definition of the structure representing current DFA(s)
7165*38fd1498Szrj state(s). */
7166*38fd1498Szrj static void
output_chip_definitions(void)7167*38fd1498Szrj output_chip_definitions (void)
7168*38fd1498Szrj {
7169*38fd1498Szrj automaton_t automaton;
7170*38fd1498Szrj
7171*38fd1498Szrj fprintf (output_file, "struct %s\n{\n", CHIP_NAME);
7172*38fd1498Szrj for (automaton = description->first_automaton;
7173*38fd1498Szrj automaton != NULL;
7174*38fd1498Szrj automaton = automaton->next_automaton)
7175*38fd1498Szrj {
7176*38fd1498Szrj fprintf (output_file, " ");
7177*38fd1498Szrj output_state_member_type (output_file, automaton);
7178*38fd1498Szrj fprintf (output_file, " ");
7179*38fd1498Szrj output_chip_member_name (output_file, automaton);
7180*38fd1498Szrj fprintf (output_file, ";\n");
7181*38fd1498Szrj }
7182*38fd1498Szrj fprintf (output_file, "};\n\n");
7183*38fd1498Szrj #if 0
7184*38fd1498Szrj fprintf (output_file, "static struct %s %s;\n\n", CHIP_NAME, CHIP_NAME);
7185*38fd1498Szrj #endif
7186*38fd1498Szrj }
7187*38fd1498Szrj
7188*38fd1498Szrj
7189*38fd1498Szrj /* The function outputs translate vector of internal insn code into
7190*38fd1498Szrj insn equivalence class number. The equivalence class number is
7191*38fd1498Szrj used to access to table and vectors representing DFA(s). */
7192*38fd1498Szrj static void
output_translate_vect(automaton_t automaton)7193*38fd1498Szrj output_translate_vect (automaton_t automaton)
7194*38fd1498Szrj {
7195*38fd1498Szrj ainsn_t ainsn;
7196*38fd1498Szrj int insn_value;
7197*38fd1498Szrj vla_hwint_t translate_vect;
7198*38fd1498Szrj
7199*38fd1498Szrj translate_vect.create (description->insns_num);
7200*38fd1498Szrj
7201*38fd1498Szrj for (insn_value = 0; insn_value < description->insns_num; insn_value++)
7202*38fd1498Szrj /* Undefined value */
7203*38fd1498Szrj translate_vect.quick_push (automaton->insn_equiv_classes_num);
7204*38fd1498Szrj
7205*38fd1498Szrj for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
7206*38fd1498Szrj translate_vect[ainsn->insn_reserv_decl->insn_num] =
7207*38fd1498Szrj ainsn->insn_equiv_class_num;
7208*38fd1498Szrj
7209*38fd1498Szrj fprintf (output_file,
7210*38fd1498Szrj "/* Vector translating external insn codes to internal ones.*/\n");
7211*38fd1498Szrj fprintf (output_file, "static const ");
7212*38fd1498Szrj output_range_type (output_file, 0, automaton->insn_equiv_classes_num);
7213*38fd1498Szrj fprintf (output_file, " ");
7214*38fd1498Szrj output_translate_vect_name (output_file, automaton);
7215*38fd1498Szrj fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7216*38fd1498Szrj output_vect (translate_vect);
7217*38fd1498Szrj fprintf (output_file, "};\n\n");
7218*38fd1498Szrj translate_vect.release ();
7219*38fd1498Szrj }
7220*38fd1498Szrj
7221*38fd1498Szrj /* The value in a table state x ainsn -> something which represents
7222*38fd1498Szrj undefined value. */
7223*38fd1498Szrj static int undefined_vect_el_value;
7224*38fd1498Szrj
7225*38fd1498Szrj /* The following function returns nonzero value if the best
7226*38fd1498Szrj representation of the table is comb vector. */
7227*38fd1498Szrj static int
comb_vect_p(state_ainsn_table_t tab)7228*38fd1498Szrj comb_vect_p (state_ainsn_table_t tab)
7229*38fd1498Szrj {
7230*38fd1498Szrj if (no_comb_flag)
7231*38fd1498Szrj return false;
7232*38fd1498Szrj return (2 * tab->full_vect.length () > 5 * tab->comb_vect.length ());
7233*38fd1498Szrj }
7234*38fd1498Szrj
7235*38fd1498Szrj /* The following function creates new table for AUTOMATON. */
7236*38fd1498Szrj static state_ainsn_table_t
create_state_ainsn_table(automaton_t automaton)7237*38fd1498Szrj create_state_ainsn_table (automaton_t automaton)
7238*38fd1498Szrj {
7239*38fd1498Szrj state_ainsn_table_t tab;
7240*38fd1498Szrj int full_vect_length;
7241*38fd1498Szrj int i;
7242*38fd1498Szrj
7243*38fd1498Szrj tab = XCREATENODE (struct state_ainsn_table);
7244*38fd1498Szrj tab->automaton = automaton;
7245*38fd1498Szrj
7246*38fd1498Szrj tab->comb_vect.create (10000);
7247*38fd1498Szrj tab->check_vect.create (10000);
7248*38fd1498Szrj
7249*38fd1498Szrj tab->base_vect.create (0);
7250*38fd1498Szrj tab->base_vect.safe_grow (automaton->achieved_states_num);
7251*38fd1498Szrj
7252*38fd1498Szrj full_vect_length = (automaton->insn_equiv_classes_num
7253*38fd1498Szrj * automaton->achieved_states_num);
7254*38fd1498Szrj tab->full_vect.create (full_vect_length);
7255*38fd1498Szrj for (i = 0; i < full_vect_length; i++)
7256*38fd1498Szrj tab->full_vect.quick_push (undefined_vect_el_value);
7257*38fd1498Szrj
7258*38fd1498Szrj tab->min_base_vect_el_value = 0;
7259*38fd1498Szrj tab->max_base_vect_el_value = 0;
7260*38fd1498Szrj tab->min_comb_vect_el_value = 0;
7261*38fd1498Szrj tab->max_comb_vect_el_value = 0;
7262*38fd1498Szrj return tab;
7263*38fd1498Szrj }
7264*38fd1498Szrj
7265*38fd1498Szrj /* The following function outputs the best C representation of the
7266*38fd1498Szrj table TAB of given TABLE_NAME. */
7267*38fd1498Szrj static void
output_state_ainsn_table(state_ainsn_table_t tab,const char * table_name,void (* output_full_vect_name_func)(FILE *,automaton_t),void (* output_comb_vect_name_func)(FILE *,automaton_t),void (* output_check_vect_name_func)(FILE *,automaton_t),void (* output_base_vect_name_func)(FILE *,automaton_t))7268*38fd1498Szrj output_state_ainsn_table (state_ainsn_table_t tab, const char *table_name,
7269*38fd1498Szrj void (*output_full_vect_name_func) (FILE *, automaton_t),
7270*38fd1498Szrj void (*output_comb_vect_name_func) (FILE *, automaton_t),
7271*38fd1498Szrj void (*output_check_vect_name_func) (FILE *, automaton_t),
7272*38fd1498Szrj void (*output_base_vect_name_func) (FILE *, automaton_t))
7273*38fd1498Szrj {
7274*38fd1498Szrj if (!comb_vect_p (tab))
7275*38fd1498Szrj {
7276*38fd1498Szrj fprintf (output_file, "/* Vector for %s. */\n", table_name);
7277*38fd1498Szrj fprintf (output_file, "static const ");
7278*38fd1498Szrj output_range_type (output_file, tab->min_comb_vect_el_value,
7279*38fd1498Szrj tab->max_comb_vect_el_value);
7280*38fd1498Szrj fprintf (output_file, " ");
7281*38fd1498Szrj (*output_full_vect_name_func) (output_file, tab->automaton);
7282*38fd1498Szrj fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7283*38fd1498Szrj output_vect (tab->full_vect);
7284*38fd1498Szrj fprintf (output_file, "};\n\n");
7285*38fd1498Szrj }
7286*38fd1498Szrj else
7287*38fd1498Szrj {
7288*38fd1498Szrj fprintf (output_file, "/* Comb vector for %s. */\n", table_name);
7289*38fd1498Szrj fprintf (output_file, "static const ");
7290*38fd1498Szrj output_range_type (output_file, tab->min_comb_vect_el_value,
7291*38fd1498Szrj tab->max_comb_vect_el_value);
7292*38fd1498Szrj fprintf (output_file, " ");
7293*38fd1498Szrj (*output_comb_vect_name_func) (output_file, tab->automaton);
7294*38fd1498Szrj fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7295*38fd1498Szrj output_vect (tab->comb_vect);
7296*38fd1498Szrj fprintf (output_file, "};\n\n");
7297*38fd1498Szrj fprintf (output_file, "/* Check vector for %s. */\n", table_name);
7298*38fd1498Szrj fprintf (output_file, "static const ");
7299*38fd1498Szrj output_range_type (output_file, 0, tab->automaton->achieved_states_num);
7300*38fd1498Szrj fprintf (output_file, " ");
7301*38fd1498Szrj (*output_check_vect_name_func) (output_file, tab->automaton);
7302*38fd1498Szrj fprintf (output_file, "[] = {\n");
7303*38fd1498Szrj output_vect (tab->check_vect);
7304*38fd1498Szrj fprintf (output_file, "};\n\n");
7305*38fd1498Szrj fprintf (output_file, "/* Base vector for %s. */\n", table_name);
7306*38fd1498Szrj fprintf (output_file, "static const ");
7307*38fd1498Szrj output_range_type (output_file, tab->min_base_vect_el_value,
7308*38fd1498Szrj tab->max_base_vect_el_value);
7309*38fd1498Szrj fprintf (output_file, " ");
7310*38fd1498Szrj (*output_base_vect_name_func) (output_file, tab->automaton);
7311*38fd1498Szrj fprintf (output_file, "[] = {\n");
7312*38fd1498Szrj output_vect (tab->base_vect);
7313*38fd1498Szrj fprintf (output_file, "};\n\n");
7314*38fd1498Szrj }
7315*38fd1498Szrj }
7316*38fd1498Szrj
7317*38fd1498Szrj /* The following function adds vector VECT to table TAB as its line
7318*38fd1498Szrj with number VECT_NUM. */
7319*38fd1498Szrj static void
add_vect(state_ainsn_table_t tab,int vect_num,vla_hwint_t vect)7320*38fd1498Szrj add_vect (state_ainsn_table_t tab, int vect_num, vla_hwint_t vect)
7321*38fd1498Szrj {
7322*38fd1498Szrj int vect_length;
7323*38fd1498Szrj size_t real_vect_length;
7324*38fd1498Szrj int comb_vect_index;
7325*38fd1498Szrj int comb_vect_els_num;
7326*38fd1498Szrj int vect_index;
7327*38fd1498Szrj int first_unempty_vect_index;
7328*38fd1498Szrj int additional_els_num;
7329*38fd1498Szrj int no_state_value;
7330*38fd1498Szrj vect_el_t vect_el;
7331*38fd1498Szrj int i;
7332*38fd1498Szrj unsigned long vect_mask, comb_vect_mask;
7333*38fd1498Szrj
7334*38fd1498Szrj vect_length = vect.length ();
7335*38fd1498Szrj gcc_assert (vect_length);
7336*38fd1498Szrj gcc_assert (vect.last () != undefined_vect_el_value);
7337*38fd1498Szrj real_vect_length = tab->automaton->insn_equiv_classes_num;
7338*38fd1498Szrj /* Form full vector in the table: */
7339*38fd1498Szrj {
7340*38fd1498Szrj size_t full_base = tab->automaton->insn_equiv_classes_num * vect_num;
7341*38fd1498Szrj if (tab->full_vect.length () < full_base + vect_length)
7342*38fd1498Szrj tab->full_vect.safe_grow (full_base + vect_length);
7343*38fd1498Szrj for (i = 0; i < vect_length; i++)
7344*38fd1498Szrj tab->full_vect[full_base + i] = vect[i];
7345*38fd1498Szrj }
7346*38fd1498Szrj
7347*38fd1498Szrj /* The comb_vect min/max values are also used for the full vector, so
7348*38fd1498Szrj compute them now. */
7349*38fd1498Szrj for (vect_index = 0; vect_index < vect_length; vect_index++)
7350*38fd1498Szrj if (vect[vect_index] != undefined_vect_el_value)
7351*38fd1498Szrj {
7352*38fd1498Szrj vect_el_t x = vect[vect_index];
7353*38fd1498Szrj gcc_assert (x >= 0);
7354*38fd1498Szrj if (tab->max_comb_vect_el_value < x)
7355*38fd1498Szrj tab->max_comb_vect_el_value = x;
7356*38fd1498Szrj if (tab->min_comb_vect_el_value > x)
7357*38fd1498Szrj tab->min_comb_vect_el_value = x;
7358*38fd1498Szrj }
7359*38fd1498Szrj if (no_comb_flag)
7360*38fd1498Szrj return;
7361*38fd1498Szrj
7362*38fd1498Szrj /* Form comb vector in the table: */
7363*38fd1498Szrj gcc_assert (tab->comb_vect.length () == tab->check_vect.length ());
7364*38fd1498Szrj
7365*38fd1498Szrj comb_vect_els_num = tab->comb_vect.length ();
7366*38fd1498Szrj for (first_unempty_vect_index = 0;
7367*38fd1498Szrj first_unempty_vect_index < vect_length;
7368*38fd1498Szrj first_unempty_vect_index++)
7369*38fd1498Szrj if (vect[first_unempty_vect_index]
7370*38fd1498Szrj != undefined_vect_el_value)
7371*38fd1498Szrj break;
7372*38fd1498Szrj
7373*38fd1498Szrj /* Search for the place in comb vect for the inserted vect. */
7374*38fd1498Szrj
7375*38fd1498Szrj /* Slow case. */
7376*38fd1498Szrj if (vect_length - first_unempty_vect_index >= SIZEOF_LONG * CHAR_BIT)
7377*38fd1498Szrj {
7378*38fd1498Szrj for (comb_vect_index = 0;
7379*38fd1498Szrj comb_vect_index < comb_vect_els_num;
7380*38fd1498Szrj comb_vect_index++)
7381*38fd1498Szrj {
7382*38fd1498Szrj for (vect_index = first_unempty_vect_index;
7383*38fd1498Szrj vect_index < vect_length
7384*38fd1498Szrj && vect_index + comb_vect_index < comb_vect_els_num;
7385*38fd1498Szrj vect_index++)
7386*38fd1498Szrj if (vect[vect_index]
7387*38fd1498Szrj != undefined_vect_el_value
7388*38fd1498Szrj && (tab->comb_vect[vect_index + comb_vect_index]
7389*38fd1498Szrj != undefined_vect_el_value))
7390*38fd1498Szrj break;
7391*38fd1498Szrj if (vect_index >= vect_length
7392*38fd1498Szrj || vect_index + comb_vect_index >= comb_vect_els_num)
7393*38fd1498Szrj break;
7394*38fd1498Szrj }
7395*38fd1498Szrj goto found;
7396*38fd1498Szrj }
7397*38fd1498Szrj
7398*38fd1498Szrj /* Fast case. */
7399*38fd1498Szrj vect_mask = 0;
7400*38fd1498Szrj for (vect_index = first_unempty_vect_index;
7401*38fd1498Szrj vect_index < vect_length;
7402*38fd1498Szrj vect_index++)
7403*38fd1498Szrj {
7404*38fd1498Szrj vect_mask = vect_mask << 1;
7405*38fd1498Szrj if (vect[vect_index] != undefined_vect_el_value)
7406*38fd1498Szrj vect_mask |= 1;
7407*38fd1498Szrj }
7408*38fd1498Szrj
7409*38fd1498Szrj /* Search for the place in comb vect for the inserted vect. */
7410*38fd1498Szrj comb_vect_index = 0;
7411*38fd1498Szrj if (comb_vect_els_num == 0)
7412*38fd1498Szrj goto found;
7413*38fd1498Szrj
7414*38fd1498Szrj comb_vect_mask = 0;
7415*38fd1498Szrj for (vect_index = first_unempty_vect_index;
7416*38fd1498Szrj vect_index < vect_length && vect_index < comb_vect_els_num;
7417*38fd1498Szrj vect_index++)
7418*38fd1498Szrj {
7419*38fd1498Szrj comb_vect_mask <<= 1;
7420*38fd1498Szrj if (vect_index + comb_vect_index < comb_vect_els_num
7421*38fd1498Szrj && tab->comb_vect[vect_index + comb_vect_index]
7422*38fd1498Szrj != undefined_vect_el_value)
7423*38fd1498Szrj comb_vect_mask |= 1;
7424*38fd1498Szrj }
7425*38fd1498Szrj if ((vect_mask & comb_vect_mask) == 0)
7426*38fd1498Szrj goto found;
7427*38fd1498Szrj
7428*38fd1498Szrj for (comb_vect_index = 1, i = vect_length; i < comb_vect_els_num;
7429*38fd1498Szrj comb_vect_index++, i++)
7430*38fd1498Szrj {
7431*38fd1498Szrj comb_vect_mask = (comb_vect_mask << 1) | 1;
7432*38fd1498Szrj comb_vect_mask ^= (tab->comb_vect[i]
7433*38fd1498Szrj == undefined_vect_el_value);
7434*38fd1498Szrj if ((vect_mask & comb_vect_mask) == 0)
7435*38fd1498Szrj goto found;
7436*38fd1498Szrj }
7437*38fd1498Szrj for ( ; comb_vect_index < comb_vect_els_num; comb_vect_index++)
7438*38fd1498Szrj {
7439*38fd1498Szrj comb_vect_mask <<= 1;
7440*38fd1498Szrj if ((vect_mask & comb_vect_mask) == 0)
7441*38fd1498Szrj goto found;
7442*38fd1498Szrj }
7443*38fd1498Szrj
7444*38fd1498Szrj found:
7445*38fd1498Szrj /* Slot was found. */
7446*38fd1498Szrj additional_els_num = comb_vect_index + real_vect_length - comb_vect_els_num;
7447*38fd1498Szrj if (additional_els_num < 0)
7448*38fd1498Szrj additional_els_num = 0;
7449*38fd1498Szrj /* Expand comb and check vectors. */
7450*38fd1498Szrj vect_el = undefined_vect_el_value;
7451*38fd1498Szrj no_state_value = tab->automaton->achieved_states_num;
7452*38fd1498Szrj while (additional_els_num > 0)
7453*38fd1498Szrj {
7454*38fd1498Szrj tab->comb_vect.safe_push (vect_el);
7455*38fd1498Szrj tab->check_vect.safe_push (no_state_value);
7456*38fd1498Szrj additional_els_num--;
7457*38fd1498Szrj }
7458*38fd1498Szrj gcc_assert (tab->comb_vect.length ()
7459*38fd1498Szrj >= comb_vect_index + real_vect_length);
7460*38fd1498Szrj /* Fill comb and check vectors. */
7461*38fd1498Szrj for (vect_index = 0; vect_index < vect_length; vect_index++)
7462*38fd1498Szrj if (vect[vect_index] != undefined_vect_el_value)
7463*38fd1498Szrj {
7464*38fd1498Szrj vect_el_t x = vect[vect_index];
7465*38fd1498Szrj gcc_assert (tab->comb_vect[comb_vect_index + vect_index]
7466*38fd1498Szrj == undefined_vect_el_value);
7467*38fd1498Szrj gcc_assert (x >= 0);
7468*38fd1498Szrj tab->comb_vect[comb_vect_index + vect_index] = x;
7469*38fd1498Szrj tab->check_vect[comb_vect_index + vect_index] = vect_num;
7470*38fd1498Szrj }
7471*38fd1498Szrj if (tab->max_comb_vect_el_value < undefined_vect_el_value)
7472*38fd1498Szrj tab->max_comb_vect_el_value = undefined_vect_el_value;
7473*38fd1498Szrj if (tab->min_comb_vect_el_value > undefined_vect_el_value)
7474*38fd1498Szrj tab->min_comb_vect_el_value = undefined_vect_el_value;
7475*38fd1498Szrj if (tab->max_base_vect_el_value < comb_vect_index)
7476*38fd1498Szrj tab->max_base_vect_el_value = comb_vect_index;
7477*38fd1498Szrj if (tab->min_base_vect_el_value > comb_vect_index)
7478*38fd1498Szrj tab->min_base_vect_el_value = comb_vect_index;
7479*38fd1498Szrj
7480*38fd1498Szrj tab->base_vect[vect_num] = comb_vect_index;
7481*38fd1498Szrj }
7482*38fd1498Szrj
7483*38fd1498Szrj /* Return number of out arcs of STATE. */
7484*38fd1498Szrj static int
out_state_arcs_num(const_state_t state)7485*38fd1498Szrj out_state_arcs_num (const_state_t state)
7486*38fd1498Szrj {
7487*38fd1498Szrj int result;
7488*38fd1498Szrj arc_t arc;
7489*38fd1498Szrj
7490*38fd1498Szrj result = 0;
7491*38fd1498Szrj for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
7492*38fd1498Szrj {
7493*38fd1498Szrj gcc_assert (arc->insn);
7494*38fd1498Szrj if (arc->insn->first_ainsn_with_given_equivalence_num)
7495*38fd1498Szrj result++;
7496*38fd1498Szrj }
7497*38fd1498Szrj return result;
7498*38fd1498Szrj }
7499*38fd1498Szrj
7500*38fd1498Szrj /* Compare number of possible transitions from the states. */
7501*38fd1498Szrj static int
compare_transition_els_num(const void * state_ptr_1,const void * state_ptr_2)7502*38fd1498Szrj compare_transition_els_num (const void *state_ptr_1,
7503*38fd1498Szrj const void *state_ptr_2)
7504*38fd1498Szrj {
7505*38fd1498Szrj const int transition_els_num_1
7506*38fd1498Szrj = out_state_arcs_num (*(const_state_t const*) state_ptr_1);
7507*38fd1498Szrj const int transition_els_num_2
7508*38fd1498Szrj = out_state_arcs_num (*(const_state_t const*) state_ptr_2);
7509*38fd1498Szrj
7510*38fd1498Szrj if (transition_els_num_1 < transition_els_num_2)
7511*38fd1498Szrj return 1;
7512*38fd1498Szrj else if (transition_els_num_1 == transition_els_num_2)
7513*38fd1498Szrj return 0;
7514*38fd1498Szrj else
7515*38fd1498Szrj return -1;
7516*38fd1498Szrj }
7517*38fd1498Szrj
7518*38fd1498Szrj /* The function adds element EL_VALUE to vector VECT for a table state
7519*38fd1498Szrj x AINSN. */
7520*38fd1498Szrj static void
add_vect_el(vla_hwint_t & vect,ainsn_t ainsn,int el_value)7521*38fd1498Szrj add_vect_el (vla_hwint_t &vect, ainsn_t ainsn, int el_value)
7522*38fd1498Szrj {
7523*38fd1498Szrj int equiv_class_num;
7524*38fd1498Szrj int vect_index;
7525*38fd1498Szrj
7526*38fd1498Szrj gcc_assert (ainsn);
7527*38fd1498Szrj equiv_class_num = ainsn->insn_equiv_class_num;
7528*38fd1498Szrj for (vect_index = vect.length ();
7529*38fd1498Szrj vect_index <= equiv_class_num;
7530*38fd1498Szrj vect_index++)
7531*38fd1498Szrj vect.safe_push (undefined_vect_el_value);
7532*38fd1498Szrj vect[equiv_class_num] = el_value;
7533*38fd1498Szrj }
7534*38fd1498Szrj
7535*38fd1498Szrj /* This is for forming vector of states of an automaton. */
7536*38fd1498Szrj static vec<state_t> output_states_vect;
7537*38fd1498Szrj
7538*38fd1498Szrj /* The function is called by function pass_states. The function adds
7539*38fd1498Szrj STATE to `output_states_vect'. */
7540*38fd1498Szrj static void
add_states_vect_el(state_t state)7541*38fd1498Szrj add_states_vect_el (state_t state)
7542*38fd1498Szrj {
7543*38fd1498Szrj output_states_vect.safe_push (state);
7544*38fd1498Szrj }
7545*38fd1498Szrj
7546*38fd1498Szrj /* Form and output vectors (comb, check, base or full vector)
7547*38fd1498Szrj representing transition table of AUTOMATON. */
7548*38fd1498Szrj static void
output_trans_table(automaton_t automaton)7549*38fd1498Szrj output_trans_table (automaton_t automaton)
7550*38fd1498Szrj {
7551*38fd1498Szrj size_t i;
7552*38fd1498Szrj arc_t arc;
7553*38fd1498Szrj vla_hwint_t transition_vect = vla_hwint_t ();
7554*38fd1498Szrj
7555*38fd1498Szrj undefined_vect_el_value = automaton->achieved_states_num;
7556*38fd1498Szrj automaton->trans_table = create_state_ainsn_table (automaton);
7557*38fd1498Szrj /* Create vect of pointers to states ordered by num of transitions
7558*38fd1498Szrj from the state (state with the maximum num is the first). */
7559*38fd1498Szrj output_states_vect.create (0);
7560*38fd1498Szrj pass_states (automaton, add_states_vect_el);
7561*38fd1498Szrj output_states_vect.qsort (compare_transition_els_num);
7562*38fd1498Szrj
7563*38fd1498Szrj for (i = 0; i < output_states_vect.length (); i++)
7564*38fd1498Szrj {
7565*38fd1498Szrj transition_vect.truncate (0);
7566*38fd1498Szrj for (arc = first_out_arc (output_states_vect[i]);
7567*38fd1498Szrj arc != NULL;
7568*38fd1498Szrj arc = next_out_arc (arc))
7569*38fd1498Szrj {
7570*38fd1498Szrj gcc_assert (arc->insn);
7571*38fd1498Szrj if (arc->insn->first_ainsn_with_given_equivalence_num)
7572*38fd1498Szrj add_vect_el (transition_vect, arc->insn,
7573*38fd1498Szrj arc->to_state->order_state_num);
7574*38fd1498Szrj }
7575*38fd1498Szrj add_vect (automaton->trans_table,
7576*38fd1498Szrj output_states_vect[i]->order_state_num,
7577*38fd1498Szrj transition_vect);
7578*38fd1498Szrj }
7579*38fd1498Szrj output_state_ainsn_table
7580*38fd1498Szrj (automaton->trans_table, "state transitions",
7581*38fd1498Szrj output_trans_full_vect_name, output_trans_comb_vect_name,
7582*38fd1498Szrj output_trans_check_vect_name, output_trans_base_vect_name);
7583*38fd1498Szrj
7584*38fd1498Szrj output_states_vect.release ();
7585*38fd1498Szrj transition_vect.release ();
7586*38fd1498Szrj }
7587*38fd1498Szrj
7588*38fd1498Szrj /* Form and output vectors representing minimal issue delay table of
7589*38fd1498Szrj AUTOMATON. The table is state x ainsn -> minimal issue delay of
7590*38fd1498Szrj the ainsn. */
7591*38fd1498Szrj static void
output_min_issue_delay_table(automaton_t automaton)7592*38fd1498Szrj output_min_issue_delay_table (automaton_t automaton)
7593*38fd1498Szrj {
7594*38fd1498Szrj vla_hwint_t min_issue_delay_vect;
7595*38fd1498Szrj vla_hwint_t compressed_min_issue_delay_vect;
7596*38fd1498Szrj ainsn_t ainsn;
7597*38fd1498Szrj size_t i;
7598*38fd1498Szrj size_t min_issue_delay_len, compressed_min_issue_delay_len;
7599*38fd1498Szrj size_t cfactor;
7600*38fd1498Szrj int changed;
7601*38fd1498Szrj
7602*38fd1498Szrj /* Create vect of pointers to states ordered by num of transitions
7603*38fd1498Szrj from the state (state with the maximum num is the first). */
7604*38fd1498Szrj output_states_vect.create (0);
7605*38fd1498Szrj pass_states (automaton, add_states_vect_el);
7606*38fd1498Szrj
7607*38fd1498Szrj min_issue_delay_len = (output_states_vect.length ()
7608*38fd1498Szrj * automaton->insn_equiv_classes_num);
7609*38fd1498Szrj min_issue_delay_vect.create (min_issue_delay_len);
7610*38fd1498Szrj for (i = 0; i < min_issue_delay_len; i++)
7611*38fd1498Szrj min_issue_delay_vect.quick_push (-1);
7612*38fd1498Szrj
7613*38fd1498Szrj automaton->max_min_delay = 0;
7614*38fd1498Szrj
7615*38fd1498Szrj do
7616*38fd1498Szrj {
7617*38fd1498Szrj size_t state_no;
7618*38fd1498Szrj
7619*38fd1498Szrj changed = 0;
7620*38fd1498Szrj
7621*38fd1498Szrj for (state_no = 0; state_no < output_states_vect.length ();
7622*38fd1498Szrj state_no++)
7623*38fd1498Szrj {
7624*38fd1498Szrj state_t s = output_states_vect[state_no];
7625*38fd1498Szrj arc_t arc;
7626*38fd1498Szrj
7627*38fd1498Szrj for (arc = first_out_arc (s); arc; arc = next_out_arc (arc))
7628*38fd1498Szrj {
7629*38fd1498Szrj int k;
7630*38fd1498Szrj
7631*38fd1498Szrj size_t asn = s->order_state_num
7632*38fd1498Szrj * automaton->insn_equiv_classes_num
7633*38fd1498Szrj + arc->insn->insn_equiv_class_num;
7634*38fd1498Szrj
7635*38fd1498Szrj if (min_issue_delay_vect[asn])
7636*38fd1498Szrj {
7637*38fd1498Szrj min_issue_delay_vect[asn] = (vect_el_t) 0;
7638*38fd1498Szrj changed = 1;
7639*38fd1498Szrj }
7640*38fd1498Szrj
7641*38fd1498Szrj for (k = 0; k < automaton->insn_equiv_classes_num; k++)
7642*38fd1498Szrj {
7643*38fd1498Szrj size_t n0, n1;
7644*38fd1498Szrj vect_el_t delay0, delay1;
7645*38fd1498Szrj
7646*38fd1498Szrj n0 = s->order_state_num
7647*38fd1498Szrj * automaton->insn_equiv_classes_num
7648*38fd1498Szrj + k;
7649*38fd1498Szrj n1 = arc->to_state->order_state_num
7650*38fd1498Szrj * automaton->insn_equiv_classes_num
7651*38fd1498Szrj + k;
7652*38fd1498Szrj delay0 = min_issue_delay_vect[n0];
7653*38fd1498Szrj delay1 = min_issue_delay_vect[n1];
7654*38fd1498Szrj if (delay1 != -1)
7655*38fd1498Szrj {
7656*38fd1498Szrj if (arc->insn->insn_reserv_decl
7657*38fd1498Szrj == DECL_INSN_RESERV (advance_cycle_insn_decl))
7658*38fd1498Szrj delay1++;
7659*38fd1498Szrj if (delay1 < delay0 || delay0 == -1)
7660*38fd1498Szrj {
7661*38fd1498Szrj min_issue_delay_vect[n0] = delay1;
7662*38fd1498Szrj changed = 1;
7663*38fd1498Szrj }
7664*38fd1498Szrj }
7665*38fd1498Szrj }
7666*38fd1498Szrj }
7667*38fd1498Szrj }
7668*38fd1498Szrj }
7669*38fd1498Szrj while (changed);
7670*38fd1498Szrj
7671*38fd1498Szrj automaton->max_min_delay = 0;
7672*38fd1498Szrj
7673*38fd1498Szrj for (ainsn = automaton->ainsn_list; ainsn; ainsn = ainsn->next_ainsn)
7674*38fd1498Szrj if (ainsn->first_ainsn_with_given_equivalence_num)
7675*38fd1498Szrj {
7676*38fd1498Szrj for (i = 0; i < output_states_vect.length (); i++)
7677*38fd1498Szrj {
7678*38fd1498Szrj state_t s = output_states_vect[i];
7679*38fd1498Szrj size_t np = s->order_state_num
7680*38fd1498Szrj * automaton->insn_equiv_classes_num
7681*38fd1498Szrj + ainsn->insn_equiv_class_num;
7682*38fd1498Szrj vect_el_t x = min_issue_delay_vect[np];
7683*38fd1498Szrj
7684*38fd1498Szrj if (automaton->max_min_delay < x)
7685*38fd1498Szrj automaton->max_min_delay = x;
7686*38fd1498Szrj if (x == -1)
7687*38fd1498Szrj min_issue_delay_vect[np] = (vect_el_t) 0;
7688*38fd1498Szrj }
7689*38fd1498Szrj }
7690*38fd1498Szrj
7691*38fd1498Szrj fprintf (output_file, "/* Vector of min issue delay of insns. */\n");
7692*38fd1498Szrj fprintf (output_file, "static const ");
7693*38fd1498Szrj output_range_type (output_file, 0, automaton->max_min_delay);
7694*38fd1498Szrj fprintf (output_file, " ");
7695*38fd1498Szrj output_min_issue_delay_vect_name (output_file, automaton);
7696*38fd1498Szrj fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7697*38fd1498Szrj /* Compress the vector. */
7698*38fd1498Szrj if (automaton->max_min_delay < 2)
7699*38fd1498Szrj cfactor = 8;
7700*38fd1498Szrj else if (automaton->max_min_delay < 4)
7701*38fd1498Szrj cfactor = 4;
7702*38fd1498Szrj else if (automaton->max_min_delay < 16)
7703*38fd1498Szrj cfactor = 2;
7704*38fd1498Szrj else
7705*38fd1498Szrj cfactor = 1;
7706*38fd1498Szrj automaton->min_issue_delay_table_compression_factor = cfactor;
7707*38fd1498Szrj
7708*38fd1498Szrj compressed_min_issue_delay_len = (min_issue_delay_len+cfactor-1) / cfactor;
7709*38fd1498Szrj compressed_min_issue_delay_vect.create (compressed_min_issue_delay_len);
7710*38fd1498Szrj
7711*38fd1498Szrj for (i = 0; i < compressed_min_issue_delay_len; i++)
7712*38fd1498Szrj compressed_min_issue_delay_vect.quick_push (0);
7713*38fd1498Szrj
7714*38fd1498Szrj for (i = 0; i < min_issue_delay_len; i++)
7715*38fd1498Szrj {
7716*38fd1498Szrj size_t ci = i / cfactor;
7717*38fd1498Szrj vect_el_t x = min_issue_delay_vect[i];
7718*38fd1498Szrj vect_el_t cx = compressed_min_issue_delay_vect[ci];
7719*38fd1498Szrj
7720*38fd1498Szrj cx |= x << (8 - (i % cfactor + 1) * (8 / cfactor));
7721*38fd1498Szrj compressed_min_issue_delay_vect[ci] = cx;
7722*38fd1498Szrj }
7723*38fd1498Szrj output_vect (compressed_min_issue_delay_vect);
7724*38fd1498Szrj fprintf (output_file, "};\n\n");
7725*38fd1498Szrj output_states_vect.release ();
7726*38fd1498Szrj min_issue_delay_vect.release ();
7727*38fd1498Szrj compressed_min_issue_delay_vect.release ();
7728*38fd1498Szrj }
7729*38fd1498Szrj
7730*38fd1498Szrj /* Form and output vector representing the locked states of
7731*38fd1498Szrj AUTOMATON. */
7732*38fd1498Szrj static void
output_dead_lock_vect(automaton_t automaton)7733*38fd1498Szrj output_dead_lock_vect (automaton_t automaton)
7734*38fd1498Szrj {
7735*38fd1498Szrj size_t i;
7736*38fd1498Szrj arc_t arc;
7737*38fd1498Szrj vla_hwint_t dead_lock_vect = vla_hwint_t ();
7738*38fd1498Szrj
7739*38fd1498Szrj /* Create vect of pointers to states ordered by num of
7740*38fd1498Szrj transitions from the state (state with the maximum num is the
7741*38fd1498Szrj first). */
7742*38fd1498Szrj automaton->locked_states = 0;
7743*38fd1498Szrj output_states_vect.create (0);
7744*38fd1498Szrj pass_states (automaton, add_states_vect_el);
7745*38fd1498Szrj
7746*38fd1498Szrj dead_lock_vect.safe_grow (output_states_vect.length ());
7747*38fd1498Szrj for (i = 0; i < output_states_vect.length (); i++)
7748*38fd1498Szrj {
7749*38fd1498Szrj state_t s = output_states_vect[i];
7750*38fd1498Szrj arc = first_out_arc (s);
7751*38fd1498Szrj gcc_assert (arc);
7752*38fd1498Szrj if (next_out_arc (arc) == NULL
7753*38fd1498Szrj && (arc->insn->insn_reserv_decl
7754*38fd1498Szrj == DECL_INSN_RESERV (advance_cycle_insn_decl)))
7755*38fd1498Szrj {
7756*38fd1498Szrj dead_lock_vect[s->order_state_num] = 1;
7757*38fd1498Szrj automaton->locked_states++;
7758*38fd1498Szrj }
7759*38fd1498Szrj else
7760*38fd1498Szrj dead_lock_vect[s->order_state_num] = (vect_el_t) 0;
7761*38fd1498Szrj }
7762*38fd1498Szrj if (automaton->locked_states == 0)
7763*38fd1498Szrj return;
7764*38fd1498Szrj
7765*38fd1498Szrj fprintf (output_file, "/* Vector for locked state flags. */\n");
7766*38fd1498Szrj fprintf (output_file, "static const ");
7767*38fd1498Szrj output_range_type (output_file, 0, 1);
7768*38fd1498Szrj fprintf (output_file, " ");
7769*38fd1498Szrj output_dead_lock_vect_name (output_file, automaton);
7770*38fd1498Szrj fprintf (output_file, "[] = {\n");
7771*38fd1498Szrj output_vect (dead_lock_vect);
7772*38fd1498Szrj fprintf (output_file, "};\n\n");
7773*38fd1498Szrj output_states_vect.release ();
7774*38fd1498Szrj dead_lock_vect.release ();
7775*38fd1498Szrj }
7776*38fd1498Szrj
7777*38fd1498Szrj /* Form and output vector representing reserved units of the states of
7778*38fd1498Szrj AUTOMATON. */
7779*38fd1498Szrj static void
output_reserved_units_table(automaton_t automaton)7780*38fd1498Szrj output_reserved_units_table (automaton_t automaton)
7781*38fd1498Szrj {
7782*38fd1498Szrj vla_hwint_t reserved_units_table = vla_hwint_t ();
7783*38fd1498Szrj int state_byte_size;
7784*38fd1498Szrj int reserved_units_size;
7785*38fd1498Szrj size_t n;
7786*38fd1498Szrj int i;
7787*38fd1498Szrj
7788*38fd1498Szrj if (description->query_units_num == 0)
7789*38fd1498Szrj return;
7790*38fd1498Szrj
7791*38fd1498Szrj /* Create vect of pointers to states. */
7792*38fd1498Szrj output_states_vect.create (0);
7793*38fd1498Szrj pass_states (automaton, add_states_vect_el);
7794*38fd1498Szrj /* Create vector. */
7795*38fd1498Szrj state_byte_size = (description->query_units_num + 7) / 8;
7796*38fd1498Szrj reserved_units_size = (output_states_vect.length ()
7797*38fd1498Szrj * state_byte_size);
7798*38fd1498Szrj
7799*38fd1498Szrj reserved_units_table.create (reserved_units_size);
7800*38fd1498Szrj
7801*38fd1498Szrj for (i = 0; i < reserved_units_size; i++)
7802*38fd1498Szrj reserved_units_table.quick_push (0);
7803*38fd1498Szrj for (n = 0; n < output_states_vect.length (); n++)
7804*38fd1498Szrj {
7805*38fd1498Szrj state_t s = output_states_vect[n];
7806*38fd1498Szrj for (i = 0; i < description->units_num; i++)
7807*38fd1498Szrj if (units_array [i]->query_p
7808*38fd1498Szrj && first_cycle_unit_presence (s, i))
7809*38fd1498Szrj {
7810*38fd1498Szrj int ri = (s->order_state_num * state_byte_size
7811*38fd1498Szrj + units_array [i]->query_num / 8);
7812*38fd1498Szrj vect_el_t x = reserved_units_table[ri];
7813*38fd1498Szrj
7814*38fd1498Szrj x += 1 << (units_array [i]->query_num % 8);
7815*38fd1498Szrj reserved_units_table[ri] = x;
7816*38fd1498Szrj }
7817*38fd1498Szrj }
7818*38fd1498Szrj fprintf (output_file, "\n#if %s\n", CPU_UNITS_QUERY_MACRO_NAME);
7819*38fd1498Szrj fprintf (output_file, "/* Vector for reserved units of states. */\n");
7820*38fd1498Szrj fprintf (output_file, "static const ");
7821*38fd1498Szrj output_range_type (output_file, 0, 255);
7822*38fd1498Szrj fprintf (output_file, " ");
7823*38fd1498Szrj output_reserved_units_table_name (output_file, automaton);
7824*38fd1498Szrj fprintf (output_file, "[] = {\n");
7825*38fd1498Szrj output_vect (reserved_units_table);
7826*38fd1498Szrj fprintf (output_file, "};\n#endif /* #if %s */\n\n",
7827*38fd1498Szrj CPU_UNITS_QUERY_MACRO_NAME);
7828*38fd1498Szrj
7829*38fd1498Szrj output_states_vect.release ();
7830*38fd1498Szrj reserved_units_table.release ();
7831*38fd1498Szrj }
7832*38fd1498Szrj
7833*38fd1498Szrj /* The function outputs all tables representing DFA(s) used for fast
7834*38fd1498Szrj pipeline hazards recognition. */
7835*38fd1498Szrj static void
output_tables(void)7836*38fd1498Szrj output_tables (void)
7837*38fd1498Szrj {
7838*38fd1498Szrj automaton_t automaton;
7839*38fd1498Szrj
7840*38fd1498Szrj for (automaton = description->first_automaton;
7841*38fd1498Szrj automaton != NULL;
7842*38fd1498Szrj automaton = automaton->next_automaton)
7843*38fd1498Szrj {
7844*38fd1498Szrj output_translate_vect (automaton);
7845*38fd1498Szrj output_trans_table (automaton);
7846*38fd1498Szrj output_min_issue_delay_table (automaton);
7847*38fd1498Szrj output_dead_lock_vect (automaton);
7848*38fd1498Szrj output_reserved_units_table (automaton);
7849*38fd1498Szrj }
7850*38fd1498Szrj fprintf (output_file, "\n#define %s %d\n\n", ADVANCE_CYCLE_VALUE_NAME,
7851*38fd1498Szrj DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
7852*38fd1498Szrj if (collapse_flag)
7853*38fd1498Szrj fprintf (output_file, "\n#define %s %d\n\n", COLLAPSE_NDFA_VALUE_NAME,
7854*38fd1498Szrj DECL_INSN_RESERV (collapse_ndfa_insn_decl)->insn_num);
7855*38fd1498Szrj }
7856*38fd1498Szrj
7857*38fd1498Szrj /* The function outputs definition and value of PHR interface variable
7858*38fd1498Szrj `max_insn_queue_index'. Its value is not less than maximal queue
7859*38fd1498Szrj length needed for the insn scheduler. */
7860*38fd1498Szrj static void
output_max_insn_queue_index_def(void)7861*38fd1498Szrj output_max_insn_queue_index_def (void)
7862*38fd1498Szrj {
7863*38fd1498Szrj int i, max, latency;
7864*38fd1498Szrj decl_t decl;
7865*38fd1498Szrj
7866*38fd1498Szrj max = description->max_insn_reserv_cycles;
7867*38fd1498Szrj for (i = 0; i < description->decls_num; i++)
7868*38fd1498Szrj {
7869*38fd1498Szrj decl = description->decls [i];
7870*38fd1498Szrj if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
7871*38fd1498Szrj {
7872*38fd1498Szrj latency = DECL_INSN_RESERV (decl)->default_latency;
7873*38fd1498Szrj if (latency > max)
7874*38fd1498Szrj max = latency;
7875*38fd1498Szrj }
7876*38fd1498Szrj else if (decl->mode == dm_bypass)
7877*38fd1498Szrj {
7878*38fd1498Szrj latency = DECL_BYPASS (decl)->latency;
7879*38fd1498Szrj if (latency > max)
7880*38fd1498Szrj max = latency;
7881*38fd1498Szrj }
7882*38fd1498Szrj }
7883*38fd1498Szrj for (i = 0; (1 << i) <= max; i++)
7884*38fd1498Szrj ;
7885*38fd1498Szrj gcc_assert (i >= 0);
7886*38fd1498Szrj fprintf (output_file, "\nconst int max_insn_queue_index = %d;\n\n",
7887*38fd1498Szrj (1 << i) - 1);
7888*38fd1498Szrj }
7889*38fd1498Szrj
7890*38fd1498Szrj /* The function outputs switch cases for insn reservations using
7891*38fd1498Szrj function *output_automata_list_code. */
7892*38fd1498Szrj static void
output_insn_code_cases(void (* output_automata_list_code)(automata_list_el_t))7893*38fd1498Szrj output_insn_code_cases (void (*output_automata_list_code)
7894*38fd1498Szrj (automata_list_el_t))
7895*38fd1498Szrj {
7896*38fd1498Szrj decl_t decl, decl2;
7897*38fd1498Szrj int i, j;
7898*38fd1498Szrj
7899*38fd1498Szrj for (i = 0; i < description->decls_num; i++)
7900*38fd1498Szrj {
7901*38fd1498Szrj decl = description->decls [i];
7902*38fd1498Szrj if (decl->mode == dm_insn_reserv)
7903*38fd1498Szrj DECL_INSN_RESERV (decl)->processed_p = FALSE;
7904*38fd1498Szrj }
7905*38fd1498Szrj for (i = 0; i < description->decls_num; i++)
7906*38fd1498Szrj {
7907*38fd1498Szrj decl = description->decls [i];
7908*38fd1498Szrj if (decl->mode == dm_insn_reserv
7909*38fd1498Szrj && !DECL_INSN_RESERV (decl)->processed_p)
7910*38fd1498Szrj {
7911*38fd1498Szrj for (j = i; j < description->decls_num; j++)
7912*38fd1498Szrj {
7913*38fd1498Szrj decl2 = description->decls [j];
7914*38fd1498Szrj if (decl2->mode == dm_insn_reserv
7915*38fd1498Szrj && (DECL_INSN_RESERV (decl2)->important_automata_list
7916*38fd1498Szrj == DECL_INSN_RESERV (decl)->important_automata_list))
7917*38fd1498Szrj {
7918*38fd1498Szrj DECL_INSN_RESERV (decl2)->processed_p = TRUE;
7919*38fd1498Szrj fprintf (output_file, " case %d: /* %s */\n",
7920*38fd1498Szrj DECL_INSN_RESERV (decl2)->insn_num,
7921*38fd1498Szrj DECL_INSN_RESERV (decl2)->name);
7922*38fd1498Szrj }
7923*38fd1498Szrj }
7924*38fd1498Szrj (*output_automata_list_code)
7925*38fd1498Szrj (DECL_INSN_RESERV (decl)->important_automata_list);
7926*38fd1498Szrj }
7927*38fd1498Szrj }
7928*38fd1498Szrj }
7929*38fd1498Szrj
7930*38fd1498Szrj
7931*38fd1498Szrj /* The function outputs a code for evaluation of a minimal delay of
7932*38fd1498Szrj issue of insns which have reservations in given AUTOMATA_LIST. */
7933*38fd1498Szrj static void
output_automata_list_min_issue_delay_code(automata_list_el_t automata_list)7934*38fd1498Szrj output_automata_list_min_issue_delay_code (automata_list_el_t automata_list)
7935*38fd1498Szrj {
7936*38fd1498Szrj automata_list_el_t el;
7937*38fd1498Szrj automaton_t automaton;
7938*38fd1498Szrj
7939*38fd1498Szrj for (el = automata_list; el != NULL; el = el->next_automata_list_el)
7940*38fd1498Szrj {
7941*38fd1498Szrj automaton = el->automaton;
7942*38fd1498Szrj fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
7943*38fd1498Szrj output_min_issue_delay_vect_name (output_file, automaton);
7944*38fd1498Szrj fprintf (output_file,
7945*38fd1498Szrj (automaton->min_issue_delay_table_compression_factor != 1
7946*38fd1498Szrj ? " [(" : " ["));
7947*38fd1498Szrj output_translate_vect_name (output_file, automaton);
7948*38fd1498Szrj fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
7949*38fd1498Szrj fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7950*38fd1498Szrj output_chip_member_name (output_file, automaton);
7951*38fd1498Szrj fprintf (output_file, " * %d", automaton->insn_equiv_classes_num);
7952*38fd1498Szrj if (automaton->min_issue_delay_table_compression_factor == 1)
7953*38fd1498Szrj fprintf (output_file, "];\n");
7954*38fd1498Szrj else
7955*38fd1498Szrj {
7956*38fd1498Szrj fprintf (output_file, ") / %d];\n",
7957*38fd1498Szrj automaton->min_issue_delay_table_compression_factor);
7958*38fd1498Szrj fprintf (output_file, " %s = (%s >> (8 - ((",
7959*38fd1498Szrj TEMPORARY_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
7960*38fd1498Szrj output_translate_vect_name (output_file, automaton);
7961*38fd1498Szrj fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
7962*38fd1498Szrj fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7963*38fd1498Szrj output_chip_member_name (output_file, automaton);
7964*38fd1498Szrj fprintf (output_file, " * %d)", automaton->insn_equiv_classes_num);
7965*38fd1498Szrj fprintf
7966*38fd1498Szrj (output_file, " %% %d + 1) * %d)) & %d;\n",
7967*38fd1498Szrj automaton->min_issue_delay_table_compression_factor,
7968*38fd1498Szrj 8 / automaton->min_issue_delay_table_compression_factor,
7969*38fd1498Szrj (1 << (8 / automaton->min_issue_delay_table_compression_factor))
7970*38fd1498Szrj - 1);
7971*38fd1498Szrj }
7972*38fd1498Szrj if (el == automata_list)
7973*38fd1498Szrj fprintf (output_file, " %s = %s;\n",
7974*38fd1498Szrj RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
7975*38fd1498Szrj else
7976*38fd1498Szrj {
7977*38fd1498Szrj fprintf (output_file, " if (%s > %s)\n",
7978*38fd1498Szrj TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
7979*38fd1498Szrj fprintf (output_file, " %s = %s;\n",
7980*38fd1498Szrj RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
7981*38fd1498Szrj }
7982*38fd1498Szrj }
7983*38fd1498Szrj fprintf (output_file, " break;\n\n");
7984*38fd1498Szrj }
7985*38fd1498Szrj
7986*38fd1498Szrj /* Output function `internal_min_issue_delay'. */
7987*38fd1498Szrj static void
output_internal_min_issue_delay_func(void)7988*38fd1498Szrj output_internal_min_issue_delay_func (void)
7989*38fd1498Szrj {
7990*38fd1498Szrj fprintf (output_file,
7991*38fd1498Szrj "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
7992*38fd1498Szrj INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7993*38fd1498Szrj CHIP_NAME, CHIP_PARAMETER_NAME);
7994*38fd1498Szrj fprintf (output_file, "{\n int %s ATTRIBUTE_UNUSED;\n int %s = -1;\n",
7995*38fd1498Szrj TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
7996*38fd1498Szrj fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
7997*38fd1498Szrj output_insn_code_cases (output_automata_list_min_issue_delay_code);
7998*38fd1498Szrj fprintf (output_file,
7999*38fd1498Szrj "\n default:\n %s = -1;\n break;\n }\n",
8000*38fd1498Szrj RESULT_VARIABLE_NAME);
8001*38fd1498Szrj fprintf (output_file, " return %s;\n", RESULT_VARIABLE_NAME);
8002*38fd1498Szrj fprintf (output_file, "}\n\n");
8003*38fd1498Szrj }
8004*38fd1498Szrj
8005*38fd1498Szrj /* The function outputs a code changing state after issue of insns
8006*38fd1498Szrj which have reservations in given AUTOMATA_LIST. */
8007*38fd1498Szrj static void
output_automata_list_transition_code(automata_list_el_t automata_list)8008*38fd1498Szrj output_automata_list_transition_code (automata_list_el_t automata_list)
8009*38fd1498Szrj {
8010*38fd1498Szrj automata_list_el_t el, next_el;
8011*38fd1498Szrj
8012*38fd1498Szrj fprintf (output_file, " {\n");
8013*38fd1498Szrj if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
8014*38fd1498Szrj for (el = automata_list;; el = next_el)
8015*38fd1498Szrj {
8016*38fd1498Szrj next_el = el->next_automata_list_el;
8017*38fd1498Szrj if (next_el == NULL)
8018*38fd1498Szrj break;
8019*38fd1498Szrj fprintf (output_file, " ");
8020*38fd1498Szrj output_state_member_type (output_file, el->automaton);
8021*38fd1498Szrj fprintf (output_file, " ");
8022*38fd1498Szrj output_temp_chip_member_name (output_file, el->automaton);
8023*38fd1498Szrj fprintf (output_file, ";\n");
8024*38fd1498Szrj }
8025*38fd1498Szrj for (el = automata_list; el != NULL; el = el->next_automata_list_el)
8026*38fd1498Szrj if (comb_vect_p (el->automaton->trans_table))
8027*38fd1498Szrj {
8028*38fd1498Szrj fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
8029*38fd1498Szrj output_trans_base_vect_name (output_file, el->automaton);
8030*38fd1498Szrj fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
8031*38fd1498Szrj output_chip_member_name (output_file, el->automaton);
8032*38fd1498Szrj fprintf (output_file, "] + ");
8033*38fd1498Szrj output_translate_vect_name (output_file, el->automaton);
8034*38fd1498Szrj fprintf (output_file, " [%s];\n", INTERNAL_INSN_CODE_NAME);
8035*38fd1498Szrj fprintf (output_file, " if (");
8036*38fd1498Szrj output_trans_check_vect_name (output_file, el->automaton);
8037*38fd1498Szrj fprintf (output_file, " [%s] != %s->",
8038*38fd1498Szrj TEMPORARY_VARIABLE_NAME, CHIP_PARAMETER_NAME);
8039*38fd1498Szrj output_chip_member_name (output_file, el->automaton);
8040*38fd1498Szrj fprintf (output_file, ")\n");
8041*38fd1498Szrj fprintf (output_file, " return %s (%s, %s);\n",
8042*38fd1498Szrj INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8043*38fd1498Szrj CHIP_PARAMETER_NAME);
8044*38fd1498Szrj fprintf (output_file, " else\n");
8045*38fd1498Szrj fprintf (output_file, " ");
8046*38fd1498Szrj if (el->next_automata_list_el != NULL)
8047*38fd1498Szrj output_temp_chip_member_name (output_file, el->automaton);
8048*38fd1498Szrj else
8049*38fd1498Szrj {
8050*38fd1498Szrj fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
8051*38fd1498Szrj output_chip_member_name (output_file, el->automaton);
8052*38fd1498Szrj }
8053*38fd1498Szrj fprintf (output_file, " = ");
8054*38fd1498Szrj output_trans_comb_vect_name (output_file, el->automaton);
8055*38fd1498Szrj fprintf (output_file, " [%s];\n", TEMPORARY_VARIABLE_NAME);
8056*38fd1498Szrj }
8057*38fd1498Szrj else
8058*38fd1498Szrj {
8059*38fd1498Szrj fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
8060*38fd1498Szrj output_trans_full_vect_name (output_file, el->automaton);
8061*38fd1498Szrj fprintf (output_file, " [");
8062*38fd1498Szrj output_translate_vect_name (output_file, el->automaton);
8063*38fd1498Szrj fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
8064*38fd1498Szrj fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
8065*38fd1498Szrj output_chip_member_name (output_file, el->automaton);
8066*38fd1498Szrj fprintf (output_file, " * %d];\n",
8067*38fd1498Szrj el->automaton->insn_equiv_classes_num);
8068*38fd1498Szrj fprintf (output_file, " if (%s >= %d)\n",
8069*38fd1498Szrj TEMPORARY_VARIABLE_NAME, el->automaton->achieved_states_num);
8070*38fd1498Szrj fprintf (output_file, " return %s (%s, %s);\n",
8071*38fd1498Szrj INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8072*38fd1498Szrj CHIP_PARAMETER_NAME);
8073*38fd1498Szrj fprintf (output_file, " else\n ");
8074*38fd1498Szrj if (el->next_automata_list_el != NULL)
8075*38fd1498Szrj output_temp_chip_member_name (output_file, el->automaton);
8076*38fd1498Szrj else
8077*38fd1498Szrj {
8078*38fd1498Szrj fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
8079*38fd1498Szrj output_chip_member_name (output_file, el->automaton);
8080*38fd1498Szrj }
8081*38fd1498Szrj fprintf (output_file, " = %s;\n", TEMPORARY_VARIABLE_NAME);
8082*38fd1498Szrj }
8083*38fd1498Szrj if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
8084*38fd1498Szrj for (el = automata_list;; el = next_el)
8085*38fd1498Szrj {
8086*38fd1498Szrj next_el = el->next_automata_list_el;
8087*38fd1498Szrj if (next_el == NULL)
8088*38fd1498Szrj break;
8089*38fd1498Szrj fprintf (output_file, " %s->", CHIP_PARAMETER_NAME);
8090*38fd1498Szrj output_chip_member_name (output_file, el->automaton);
8091*38fd1498Szrj fprintf (output_file, " = ");
8092*38fd1498Szrj output_temp_chip_member_name (output_file, el->automaton);
8093*38fd1498Szrj fprintf (output_file, ";\n");
8094*38fd1498Szrj }
8095*38fd1498Szrj fprintf (output_file, " return -1;\n");
8096*38fd1498Szrj fprintf (output_file, " }\n");
8097*38fd1498Szrj }
8098*38fd1498Szrj
8099*38fd1498Szrj /* Output function `internal_state_transition'. */
8100*38fd1498Szrj static void
output_internal_trans_func(void)8101*38fd1498Szrj output_internal_trans_func (void)
8102*38fd1498Szrj {
8103*38fd1498Szrj fprintf (output_file,
8104*38fd1498Szrj "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
8105*38fd1498Szrj INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8106*38fd1498Szrj CHIP_NAME, CHIP_PARAMETER_NAME);
8107*38fd1498Szrj fprintf (output_file, "{\n int %s ATTRIBUTE_UNUSED;\n", TEMPORARY_VARIABLE_NAME);
8108*38fd1498Szrj fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8109*38fd1498Szrj output_insn_code_cases (output_automata_list_transition_code);
8110*38fd1498Szrj fprintf (output_file, "\n default:\n return -1;\n }\n");
8111*38fd1498Szrj fprintf (output_file, "}\n\n");
8112*38fd1498Szrj }
8113*38fd1498Szrj
8114*38fd1498Szrj /* Output code
8115*38fd1498Szrj
8116*38fd1498Szrj gcc_checking_assert (insn != 0);
8117*38fd1498Szrj insn_code = dfa_insn_code (insn);
8118*38fd1498Szrj if (insn_code >= DFA__ADVANCE_CYCLE)
8119*38fd1498Szrj return code;
8120*38fd1498Szrj
8121*38fd1498Szrj where insn denotes INSN_NAME, insn_code denotes INSN_CODE_NAME, and
8122*38fd1498Szrj code denotes CODE. */
8123*38fd1498Szrj static void
output_internal_insn_code_evaluation(const char * insn_name,const char * insn_code_name,int code)8124*38fd1498Szrj output_internal_insn_code_evaluation (const char *insn_name,
8125*38fd1498Szrj const char *insn_code_name,
8126*38fd1498Szrj int code)
8127*38fd1498Szrj {
8128*38fd1498Szrj fprintf (output_file, " gcc_checking_assert (%s != 0);\n"
8129*38fd1498Szrj " %s = %s (%s);\n"
8130*38fd1498Szrj " if (%s >= %s)\n return %d;\n",
8131*38fd1498Szrj insn_name,
8132*38fd1498Szrj insn_code_name, DFA_INSN_CODE_FUNC_NAME, insn_name,
8133*38fd1498Szrj insn_code_name, ADVANCE_CYCLE_VALUE_NAME, code);
8134*38fd1498Szrj }
8135*38fd1498Szrj
8136*38fd1498Szrj
8137*38fd1498Szrj /* This function outputs `dfa_insn_code' and its helper function
8138*38fd1498Szrj `dfa_insn_code_enlarge'. */
8139*38fd1498Szrj static void
output_dfa_insn_code_func(void)8140*38fd1498Szrj output_dfa_insn_code_func (void)
8141*38fd1498Szrj {
8142*38fd1498Szrj /* Emacs c-mode gets really confused if there's a { or } in column 0
8143*38fd1498Szrj inside a string, so don't do that. */
8144*38fd1498Szrj fprintf (output_file, "\
8145*38fd1498Szrj static void\n\
8146*38fd1498Szrj dfa_insn_code_enlarge (int uid)\n\
8147*38fd1498Szrj {\n\
8148*38fd1498Szrj int i = %s;\n\
8149*38fd1498Szrj %s = 2 * uid;\n\
8150*38fd1498Szrj %s = XRESIZEVEC (int, %s,\n\
8151*38fd1498Szrj %s);\n\
8152*38fd1498Szrj for (; i < %s; i++)\n\
8153*38fd1498Szrj %s[i] = -1;\n}\n\n",
8154*38fd1498Szrj DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8155*38fd1498Szrj DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8156*38fd1498Szrj DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
8157*38fd1498Szrj DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8158*38fd1498Szrj DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8159*38fd1498Szrj DFA_INSN_CODES_VARIABLE_NAME);
8160*38fd1498Szrj fprintf (output_file, "\
8161*38fd1498Szrj static inline int\n%s (rtx_insn *%s)\n\
8162*38fd1498Szrj {\n\
8163*38fd1498Szrj int uid = INSN_UID (%s);\n\
8164*38fd1498Szrj int %s;\n\n",
8165*38fd1498Szrj DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME,
8166*38fd1498Szrj INSN_PARAMETER_NAME, INTERNAL_INSN_CODE_NAME);
8167*38fd1498Szrj
8168*38fd1498Szrj fprintf (output_file,
8169*38fd1498Szrj " if (uid >= %s)\n dfa_insn_code_enlarge (uid);\n\n",
8170*38fd1498Szrj DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8171*38fd1498Szrj fprintf (output_file, " %s = %s[uid];\n",
8172*38fd1498Szrj INTERNAL_INSN_CODE_NAME, DFA_INSN_CODES_VARIABLE_NAME);
8173*38fd1498Szrj fprintf (output_file, "\
8174*38fd1498Szrj if (%s < 0)\n\
8175*38fd1498Szrj {\n\
8176*38fd1498Szrj %s = %s (%s);\n\
8177*38fd1498Szrj %s[uid] = %s;\n\
8178*38fd1498Szrj }\n",
8179*38fd1498Szrj INTERNAL_INSN_CODE_NAME,
8180*38fd1498Szrj INTERNAL_INSN_CODE_NAME,
8181*38fd1498Szrj INTERNAL_DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME,
8182*38fd1498Szrj DFA_INSN_CODES_VARIABLE_NAME, INTERNAL_INSN_CODE_NAME);
8183*38fd1498Szrj fprintf (output_file, " return %s;\n}\n\n", INTERNAL_INSN_CODE_NAME);
8184*38fd1498Szrj }
8185*38fd1498Szrj
8186*38fd1498Szrj /* The function outputs PHR interface function `state_transition'. */
8187*38fd1498Szrj static void
output_trans_func(void)8188*38fd1498Szrj output_trans_func (void)
8189*38fd1498Szrj {
8190*38fd1498Szrj fprintf (output_file, "int\n%s (%s %s, rtx %s)\n",
8191*38fd1498Szrj TRANSITION_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME,
8192*38fd1498Szrj INSN_PARAMETER_NAME);
8193*38fd1498Szrj fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
8194*38fd1498Szrj fprintf (output_file, "\n if (%s == 0)\n", INSN_PARAMETER_NAME);
8195*38fd1498Szrj fprintf (output_file, " %s = %s;\n",
8196*38fd1498Szrj INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8197*38fd1498Szrj if (collapse_flag)
8198*38fd1498Szrj {
8199*38fd1498Szrj fprintf (output_file, " else if (%s == const0_rtx)\n",
8200*38fd1498Szrj INSN_PARAMETER_NAME);
8201*38fd1498Szrj fprintf (output_file, " %s = %s;\n",
8202*38fd1498Szrj INTERNAL_INSN_CODE_NAME, COLLAPSE_NDFA_VALUE_NAME);
8203*38fd1498Szrj }
8204*38fd1498Szrj fprintf (output_file, " else\n {\n");
8205*38fd1498Szrj fprintf (output_file, " %s = %s (as_a <rtx_insn *> (%s));\n",
8206*38fd1498Szrj INTERNAL_INSN_CODE_NAME, DFA_INSN_CODE_FUNC_NAME,
8207*38fd1498Szrj INSN_PARAMETER_NAME);
8208*38fd1498Szrj fprintf (output_file, " if (%s > %s)\n return -1;\n }\n",
8209*38fd1498Szrj INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8210*38fd1498Szrj fprintf (output_file, " return %s (%s, (struct %s *) %s);\n}\n\n",
8211*38fd1498Szrj INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME, STATE_NAME);
8212*38fd1498Szrj }
8213*38fd1498Szrj
8214*38fd1498Szrj /* Output function `min_issue_delay'. */
8215*38fd1498Szrj static void
output_min_issue_delay_func(void)8216*38fd1498Szrj output_min_issue_delay_func (void)
8217*38fd1498Szrj {
8218*38fd1498Szrj fprintf (output_file, "int\n%s (%s %s, rtx_insn *%s)\n",
8219*38fd1498Szrj MIN_ISSUE_DELAY_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME,
8220*38fd1498Szrj INSN_PARAMETER_NAME);
8221*38fd1498Szrj fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
8222*38fd1498Szrj fprintf (output_file, "\n if (%s != 0)\n {\n", INSN_PARAMETER_NAME);
8223*38fd1498Szrj fprintf (output_file, " %s = %s (%s);\n", INTERNAL_INSN_CODE_NAME,
8224*38fd1498Szrj DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME);
8225*38fd1498Szrj fprintf (output_file, " if (%s > %s)\n return 0;\n",
8226*38fd1498Szrj INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8227*38fd1498Szrj fprintf (output_file, " }\n else\n %s = %s;\n",
8228*38fd1498Szrj INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8229*38fd1498Szrj fprintf (output_file, "\n return %s (%s, (struct %s *) %s);\n",
8230*38fd1498Szrj INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8231*38fd1498Szrj CHIP_NAME, STATE_NAME);
8232*38fd1498Szrj fprintf (output_file, "}\n\n");
8233*38fd1498Szrj }
8234*38fd1498Szrj
8235*38fd1498Szrj /* Output function `internal_dead_lock'. */
8236*38fd1498Szrj static void
output_internal_dead_lock_func(void)8237*38fd1498Szrj output_internal_dead_lock_func (void)
8238*38fd1498Szrj {
8239*38fd1498Szrj automaton_t automaton;
8240*38fd1498Szrj
8241*38fd1498Szrj fprintf (output_file, "static int\n%s (struct %s *ARG_UNUSED (%s))\n",
8242*38fd1498Szrj INTERNAL_DEAD_LOCK_FUNC_NAME, CHIP_NAME, CHIP_PARAMETER_NAME);
8243*38fd1498Szrj fprintf (output_file, "{\n");
8244*38fd1498Szrj for (automaton = description->first_automaton;
8245*38fd1498Szrj automaton != NULL;
8246*38fd1498Szrj automaton = automaton->next_automaton)
8247*38fd1498Szrj if (automaton->locked_states)
8248*38fd1498Szrj {
8249*38fd1498Szrj fprintf (output_file, " if (");
8250*38fd1498Szrj output_dead_lock_vect_name (output_file, automaton);
8251*38fd1498Szrj fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
8252*38fd1498Szrj output_chip_member_name (output_file, automaton);
8253*38fd1498Szrj fprintf (output_file, "])\n return 1/* TRUE */;\n");
8254*38fd1498Szrj }
8255*38fd1498Szrj fprintf (output_file, " return 0/* FALSE */;\n}\n\n");
8256*38fd1498Szrj }
8257*38fd1498Szrj
8258*38fd1498Szrj /* The function outputs PHR interface function `state_dead_lock_p'. */
8259*38fd1498Szrj static void
output_dead_lock_func(void)8260*38fd1498Szrj output_dead_lock_func (void)
8261*38fd1498Szrj {
8262*38fd1498Szrj fprintf (output_file, "int\n%s (%s %s)\n",
8263*38fd1498Szrj DEAD_LOCK_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME);
8264*38fd1498Szrj fprintf (output_file, "{\n return %s ((struct %s *) %s);\n}\n\n",
8265*38fd1498Szrj INTERNAL_DEAD_LOCK_FUNC_NAME, CHIP_NAME, STATE_NAME);
8266*38fd1498Szrj }
8267*38fd1498Szrj
8268*38fd1498Szrj /* Output function `internal_reset'. */
8269*38fd1498Szrj static void
output_internal_reset_func(void)8270*38fd1498Szrj output_internal_reset_func (void)
8271*38fd1498Szrj {
8272*38fd1498Szrj fprintf (output_file, "static inline void\n%s (struct %s *%s)\n",
8273*38fd1498Szrj INTERNAL_RESET_FUNC_NAME, CHIP_NAME, CHIP_PARAMETER_NAME);
8274*38fd1498Szrj fprintf (output_file, "{\n memset (%s, 0, sizeof (struct %s));\n}\n\n",
8275*38fd1498Szrj CHIP_PARAMETER_NAME, CHIP_NAME);
8276*38fd1498Szrj }
8277*38fd1498Szrj
8278*38fd1498Szrj /* The function outputs PHR interface function `state_size'. */
8279*38fd1498Szrj static void
output_size_func(void)8280*38fd1498Szrj output_size_func (void)
8281*38fd1498Szrj {
8282*38fd1498Szrj fprintf (output_file, "int\n%s (void)\n", SIZE_FUNC_NAME);
8283*38fd1498Szrj fprintf (output_file, "{\n return sizeof (struct %s);\n}\n\n", CHIP_NAME);
8284*38fd1498Szrj }
8285*38fd1498Szrj
8286*38fd1498Szrj /* The function outputs PHR interface function `state_reset'. */
8287*38fd1498Szrj static void
output_reset_func(void)8288*38fd1498Szrj output_reset_func (void)
8289*38fd1498Szrj {
8290*38fd1498Szrj fprintf (output_file, "void\n%s (%s %s)\n",
8291*38fd1498Szrj RESET_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME);
8292*38fd1498Szrj fprintf (output_file, "{\n %s ((struct %s *) %s);\n}\n\n", INTERNAL_RESET_FUNC_NAME,
8293*38fd1498Szrj CHIP_NAME, STATE_NAME);
8294*38fd1498Szrj }
8295*38fd1498Szrj
8296*38fd1498Szrj /* Output function `min_insn_conflict_delay'. */
8297*38fd1498Szrj static void
output_min_insn_conflict_delay_func(void)8298*38fd1498Szrj output_min_insn_conflict_delay_func (void)
8299*38fd1498Szrj {
8300*38fd1498Szrj fprintf (output_file,
8301*38fd1498Szrj "int\n%s (%s %s, rtx_insn *%s, rtx_insn *%s)\n",
8302*38fd1498Szrj MIN_INSN_CONFLICT_DELAY_FUNC_NAME, STATE_TYPE_NAME,
8303*38fd1498Szrj STATE_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8304*38fd1498Szrj fprintf (output_file, "{\n struct %s %s;\n int %s, %s, transition;\n",
8305*38fd1498Szrj CHIP_NAME, CHIP_NAME, INTERNAL_INSN_CODE_NAME,
8306*38fd1498Szrj INTERNAL_INSN2_CODE_NAME);
8307*38fd1498Szrj output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8308*38fd1498Szrj INTERNAL_INSN_CODE_NAME, 0);
8309*38fd1498Szrj output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
8310*38fd1498Szrj INTERNAL_INSN2_CODE_NAME, 0);
8311*38fd1498Szrj fprintf (output_file, " memcpy (&%s, %s, sizeof (%s));\n",
8312*38fd1498Szrj CHIP_NAME, STATE_NAME, CHIP_NAME);
8313*38fd1498Szrj fprintf (output_file, " %s (&%s);\n", INTERNAL_RESET_FUNC_NAME, CHIP_NAME);
8314*38fd1498Szrj fprintf (output_file, " transition = %s (%s, &%s);\n",
8315*38fd1498Szrj INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME);
8316*38fd1498Szrj fprintf (output_file, " gcc_assert (transition <= 0);\n");
8317*38fd1498Szrj fprintf (output_file, " return %s (%s, &%s);\n",
8318*38fd1498Szrj INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN2_CODE_NAME,
8319*38fd1498Szrj CHIP_NAME);
8320*38fd1498Szrj fprintf (output_file, "}\n\n");
8321*38fd1498Szrj }
8322*38fd1498Szrj
8323*38fd1498Szrj /* Output the array holding default latency values. These are used in
8324*38fd1498Szrj insn_latency and maximal_insn_latency function implementations. */
8325*38fd1498Szrj static void
output_default_latencies(void)8326*38fd1498Szrj output_default_latencies (void)
8327*38fd1498Szrj {
8328*38fd1498Szrj int i, j, col;
8329*38fd1498Szrj decl_t decl;
8330*38fd1498Szrj const char *tabletype = "unsigned char";
8331*38fd1498Szrj
8332*38fd1498Szrj /* Find the smallest integer type that can hold all the default
8333*38fd1498Szrj latency values. */
8334*38fd1498Szrj for (i = 0; i < description->decls_num; i++)
8335*38fd1498Szrj if (description->decls[i]->mode == dm_insn_reserv)
8336*38fd1498Szrj {
8337*38fd1498Szrj decl = description->decls[i];
8338*38fd1498Szrj if (DECL_INSN_RESERV (decl)->default_latency > UCHAR_MAX
8339*38fd1498Szrj && tabletype[0] != 'i') /* Don't shrink it. */
8340*38fd1498Szrj tabletype = "unsigned short";
8341*38fd1498Szrj if (DECL_INSN_RESERV (decl)->default_latency > USHRT_MAX)
8342*38fd1498Szrj tabletype = "int";
8343*38fd1498Szrj }
8344*38fd1498Szrj
8345*38fd1498Szrj fprintf (output_file, " static const %s default_latencies[] =\n {",
8346*38fd1498Szrj tabletype);
8347*38fd1498Szrj
8348*38fd1498Szrj for (i = 0, j = 0, col = 7; i < description->normal_decls_num; i++)
8349*38fd1498Szrj if (description->decls[i]->mode == dm_insn_reserv)
8350*38fd1498Szrj {
8351*38fd1498Szrj if ((col = (col+1) % 8) == 0)
8352*38fd1498Szrj fputs ("\n ", output_file);
8353*38fd1498Szrj decl = description->decls[i];
8354*38fd1498Szrj gcc_assert (j++ == DECL_INSN_RESERV (decl)->insn_num);
8355*38fd1498Szrj fprintf (output_file, "% 4d,",
8356*38fd1498Szrj DECL_INSN_RESERV (decl)->default_latency);
8357*38fd1498Szrj }
8358*38fd1498Szrj gcc_assert (j == description->insns_num - (collapse_flag ? 2 : 1));
8359*38fd1498Szrj fputs ("\n };\n", output_file);
8360*38fd1498Szrj }
8361*38fd1498Szrj
8362*38fd1498Szrj /* Output function `internal_insn_latency'. */
8363*38fd1498Szrj static void
output_internal_insn_latency_func(void)8364*38fd1498Szrj output_internal_insn_latency_func (void)
8365*38fd1498Szrj {
8366*38fd1498Szrj int i;
8367*38fd1498Szrj decl_t decl;
8368*38fd1498Szrj struct bypass_decl *bypass;
8369*38fd1498Szrj
8370*38fd1498Szrj fprintf (output_file, "static int\n"
8371*38fd1498Szrj "%s (int %s ATTRIBUTE_UNUSED, int %s ATTRIBUTE_UNUSED,\n"
8372*38fd1498Szrj "\trtx_insn *%s ATTRIBUTE_UNUSED, rtx_insn *%s ATTRIBUTE_UNUSED)\n",
8373*38fd1498Szrj INTERNAL_INSN_LATENCY_FUNC_NAME,
8374*38fd1498Szrj INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME,
8375*38fd1498Szrj INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8376*38fd1498Szrj fprintf (output_file, "{\n");
8377*38fd1498Szrj
8378*38fd1498Szrj if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8379*38fd1498Szrj {
8380*38fd1498Szrj fputs (" return 0;\n}\n\n", output_file);
8381*38fd1498Szrj return;
8382*38fd1498Szrj }
8383*38fd1498Szrj
8384*38fd1498Szrj fprintf (output_file, " switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8385*38fd1498Szrj for (i = 0; i < description->decls_num; i++)
8386*38fd1498Szrj if (description->decls[i]->mode == dm_insn_reserv
8387*38fd1498Szrj && DECL_INSN_RESERV (description->decls[i])->bypass_list)
8388*38fd1498Szrj {
8389*38fd1498Szrj decl = description->decls [i];
8390*38fd1498Szrj fprintf (output_file,
8391*38fd1498Szrj " case %d:\n switch (%s)\n {\n",
8392*38fd1498Szrj DECL_INSN_RESERV (decl)->insn_num,
8393*38fd1498Szrj INTERNAL_INSN2_CODE_NAME);
8394*38fd1498Szrj for (bypass = DECL_INSN_RESERV (decl)->bypass_list;
8395*38fd1498Szrj bypass != NULL;
8396*38fd1498Szrj bypass = bypass->next)
8397*38fd1498Szrj {
8398*38fd1498Szrj gcc_assert (bypass->in_insn_reserv->insn_num
8399*38fd1498Szrj != (DECL_INSN_RESERV
8400*38fd1498Szrj (advance_cycle_insn_decl)->insn_num));
8401*38fd1498Szrj fprintf (output_file, " case %d:\n",
8402*38fd1498Szrj bypass->in_insn_reserv->insn_num);
8403*38fd1498Szrj for (;;)
8404*38fd1498Szrj {
8405*38fd1498Szrj if (bypass->bypass_guard_name == NULL)
8406*38fd1498Szrj {
8407*38fd1498Szrj gcc_assert (bypass->next == NULL
8408*38fd1498Szrj || (bypass->in_insn_reserv
8409*38fd1498Szrj != bypass->next->in_insn_reserv));
8410*38fd1498Szrj fprintf (output_file, " return %d;\n",
8411*38fd1498Szrj bypass->latency);
8412*38fd1498Szrj }
8413*38fd1498Szrj else
8414*38fd1498Szrj {
8415*38fd1498Szrj fprintf (output_file,
8416*38fd1498Szrj " if (%s (%s, %s))\n",
8417*38fd1498Szrj bypass->bypass_guard_name, INSN_PARAMETER_NAME,
8418*38fd1498Szrj INSN2_PARAMETER_NAME);
8419*38fd1498Szrj fprintf (output_file, " return %d;\n",
8420*38fd1498Szrj bypass->latency);
8421*38fd1498Szrj }
8422*38fd1498Szrj if (bypass->next == NULL
8423*38fd1498Szrj || bypass->in_insn_reserv != bypass->next->in_insn_reserv)
8424*38fd1498Szrj break;
8425*38fd1498Szrj bypass = bypass->next;
8426*38fd1498Szrj }
8427*38fd1498Szrj if (bypass->bypass_guard_name != NULL)
8428*38fd1498Szrj fprintf (output_file, " break;\n");
8429*38fd1498Szrj }
8430*38fd1498Szrj fputs (" }\n break;\n", output_file);
8431*38fd1498Szrj }
8432*38fd1498Szrj
8433*38fd1498Szrj fprintf (output_file, " }\n return default_latencies[%s];\n}\n\n",
8434*38fd1498Szrj INTERNAL_INSN_CODE_NAME);
8435*38fd1498Szrj }
8436*38fd1498Szrj
8437*38fd1498Szrj /* Output function `internal_maximum_insn_latency'. */
8438*38fd1498Szrj static void
output_internal_maximal_insn_latency_func(void)8439*38fd1498Szrj output_internal_maximal_insn_latency_func (void)
8440*38fd1498Szrj {
8441*38fd1498Szrj decl_t decl;
8442*38fd1498Szrj struct bypass_decl *bypass;
8443*38fd1498Szrj int i;
8444*38fd1498Szrj int max;
8445*38fd1498Szrj
8446*38fd1498Szrj fprintf (output_file, "static int\n%s (int %s ATTRIBUTE_UNUSED)\n",
8447*38fd1498Szrj "internal_maximal_insn_latency", INTERNAL_INSN_CODE_NAME);
8448*38fd1498Szrj fprintf (output_file, "{\n");
8449*38fd1498Szrj
8450*38fd1498Szrj if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8451*38fd1498Szrj {
8452*38fd1498Szrj fputs (" return 0;\n}\n\n", output_file);
8453*38fd1498Szrj return;
8454*38fd1498Szrj }
8455*38fd1498Szrj
8456*38fd1498Szrj fprintf (output_file, " switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8457*38fd1498Szrj for (i = 0; i < description->decls_num; i++)
8458*38fd1498Szrj if (description->decls[i]->mode == dm_insn_reserv
8459*38fd1498Szrj && DECL_INSN_RESERV (description->decls[i])->bypass_list)
8460*38fd1498Szrj {
8461*38fd1498Szrj decl = description->decls [i];
8462*38fd1498Szrj max = DECL_INSN_RESERV (decl)->default_latency;
8463*38fd1498Szrj fprintf (output_file,
8464*38fd1498Szrj " case %d: {",
8465*38fd1498Szrj DECL_INSN_RESERV (decl)->insn_num);
8466*38fd1498Szrj for (bypass = DECL_INSN_RESERV (decl)->bypass_list;
8467*38fd1498Szrj bypass != NULL;
8468*38fd1498Szrj bypass = bypass->next)
8469*38fd1498Szrj {
8470*38fd1498Szrj if (bypass->latency > max)
8471*38fd1498Szrj max = bypass->latency;
8472*38fd1498Szrj }
8473*38fd1498Szrj fprintf (output_file, " return %d; }\n break;\n", max);
8474*38fd1498Szrj }
8475*38fd1498Szrj
8476*38fd1498Szrj fprintf (output_file, " }\n return default_latencies[%s];\n}\n\n",
8477*38fd1498Szrj INTERNAL_INSN_CODE_NAME);
8478*38fd1498Szrj }
8479*38fd1498Szrj
8480*38fd1498Szrj /* The function outputs PHR interface function `insn_latency'. */
8481*38fd1498Szrj static void
output_insn_latency_func(void)8482*38fd1498Szrj output_insn_latency_func (void)
8483*38fd1498Szrj {
8484*38fd1498Szrj fprintf (output_file, "int\n%s (rtx_insn *%s, rtx_insn *%s)\n",
8485*38fd1498Szrj INSN_LATENCY_FUNC_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8486*38fd1498Szrj fprintf (output_file, "{\n int %s, %s;\n",
8487*38fd1498Szrj INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME);
8488*38fd1498Szrj output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8489*38fd1498Szrj INTERNAL_INSN_CODE_NAME, 0);
8490*38fd1498Szrj output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
8491*38fd1498Szrj INTERNAL_INSN2_CODE_NAME, 0);
8492*38fd1498Szrj fprintf (output_file, " return %s (%s, %s, %s, %s);\n}\n\n",
8493*38fd1498Szrj INTERNAL_INSN_LATENCY_FUNC_NAME,
8494*38fd1498Szrj INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME,
8495*38fd1498Szrj INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8496*38fd1498Szrj }
8497*38fd1498Szrj
8498*38fd1498Szrj /* The function outputs PHR interface function `maximal_insn_latency'. */
8499*38fd1498Szrj static void
output_maximal_insn_latency_func(void)8500*38fd1498Szrj output_maximal_insn_latency_func (void)
8501*38fd1498Szrj {
8502*38fd1498Szrj fprintf (output_file, "int\n%s (rtx_insn *%s)\n",
8503*38fd1498Szrj "maximal_insn_latency", INSN_PARAMETER_NAME);
8504*38fd1498Szrj fprintf (output_file, "{\n int %s;\n",
8505*38fd1498Szrj INTERNAL_INSN_CODE_NAME);
8506*38fd1498Szrj output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8507*38fd1498Szrj INTERNAL_INSN_CODE_NAME, 0);
8508*38fd1498Szrj fprintf (output_file, " return %s (%s);\n}\n\n",
8509*38fd1498Szrj "internal_maximal_insn_latency", INTERNAL_INSN_CODE_NAME);
8510*38fd1498Szrj }
8511*38fd1498Szrj
8512*38fd1498Szrj /* The function outputs PHR interface function `print_reservation'. */
8513*38fd1498Szrj static void
output_print_reservation_func(void)8514*38fd1498Szrj output_print_reservation_func (void)
8515*38fd1498Szrj {
8516*38fd1498Szrj decl_t decl;
8517*38fd1498Szrj int i, j;
8518*38fd1498Szrj
8519*38fd1498Szrj fprintf (output_file,
8520*38fd1498Szrj "void\n%s (FILE *%s, rtx_insn *%s ATTRIBUTE_UNUSED)\n{\n",
8521*38fd1498Szrj PRINT_RESERVATION_FUNC_NAME, FILE_PARAMETER_NAME,
8522*38fd1498Szrj INSN_PARAMETER_NAME);
8523*38fd1498Szrj
8524*38fd1498Szrj if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8525*38fd1498Szrj {
8526*38fd1498Szrj fprintf (output_file, " fputs (\"%s\", %s);\n}\n\n",
8527*38fd1498Szrj NOTHING_NAME, FILE_PARAMETER_NAME);
8528*38fd1498Szrj return;
8529*38fd1498Szrj }
8530*38fd1498Szrj
8531*38fd1498Szrj
8532*38fd1498Szrj fputs (" static const char *const reservation_names[] =\n {",
8533*38fd1498Szrj output_file);
8534*38fd1498Szrj
8535*38fd1498Szrj for (i = 0, j = 0; i < description->normal_decls_num; i++)
8536*38fd1498Szrj {
8537*38fd1498Szrj decl = description->decls [i];
8538*38fd1498Szrj if (decl->mode == dm_insn_reserv)
8539*38fd1498Szrj {
8540*38fd1498Szrj gcc_assert (j == DECL_INSN_RESERV (decl)->insn_num);
8541*38fd1498Szrj j++;
8542*38fd1498Szrj
8543*38fd1498Szrj fprintf (output_file, "\n \"%s\",",
8544*38fd1498Szrj regexp_representation (DECL_INSN_RESERV (decl)->regexp));
8545*38fd1498Szrj finish_regexp_representation ();
8546*38fd1498Szrj }
8547*38fd1498Szrj }
8548*38fd1498Szrj gcc_assert (j == description->insns_num - (collapse_flag ? 2 : 1));
8549*38fd1498Szrj
8550*38fd1498Szrj fprintf (output_file, "\n \"%s\"\n };\n int %s;\n\n",
8551*38fd1498Szrj NOTHING_NAME, INTERNAL_INSN_CODE_NAME);
8552*38fd1498Szrj
8553*38fd1498Szrj fprintf (output_file, " if (%s == 0)\n %s = %s;\n",
8554*38fd1498Szrj INSN_PARAMETER_NAME,
8555*38fd1498Szrj INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8556*38fd1498Szrj fprintf (output_file, " else\n\
8557*38fd1498Szrj {\n\
8558*38fd1498Szrj %s = %s (%s);\n\
8559*38fd1498Szrj if (%s > %s)\n\
8560*38fd1498Szrj %s = %s;\n\
8561*38fd1498Szrj }\n",
8562*38fd1498Szrj INTERNAL_INSN_CODE_NAME, DFA_INSN_CODE_FUNC_NAME,
8563*38fd1498Szrj INSN_PARAMETER_NAME,
8564*38fd1498Szrj INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8565*38fd1498Szrj INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8566*38fd1498Szrj
8567*38fd1498Szrj fprintf (output_file, " fputs (reservation_names[%s], %s);\n}\n\n",
8568*38fd1498Szrj INTERNAL_INSN_CODE_NAME, FILE_PARAMETER_NAME);
8569*38fd1498Szrj }
8570*38fd1498Szrj
8571*38fd1498Szrj /* The following function is used to sort unit declaration by their
8572*38fd1498Szrj names. */
8573*38fd1498Szrj static int
units_cmp(const void * unit1,const void * unit2)8574*38fd1498Szrj units_cmp (const void *unit1, const void *unit2)
8575*38fd1498Szrj {
8576*38fd1498Szrj const_unit_decl_t const u1 = *(const_unit_decl_t const*) unit1;
8577*38fd1498Szrj const_unit_decl_t const u2 = *(const_unit_decl_t const*) unit2;
8578*38fd1498Szrj
8579*38fd1498Szrj return strcmp (u1->name, u2->name);
8580*38fd1498Szrj }
8581*38fd1498Szrj
8582*38fd1498Szrj /* The following macro value is name of struct containing unit name
8583*38fd1498Szrj and unit code. */
8584*38fd1498Szrj #define NAME_CODE_STRUCT_NAME "name_code"
8585*38fd1498Szrj
8586*38fd1498Szrj /* The following macro value is name of table of struct name_code. */
8587*38fd1498Szrj #define NAME_CODE_TABLE_NAME "name_code_table"
8588*38fd1498Szrj
8589*38fd1498Szrj /* The following macro values are member names for struct name_code. */
8590*38fd1498Szrj #define NAME_MEMBER_NAME "name"
8591*38fd1498Szrj #define CODE_MEMBER_NAME "code"
8592*38fd1498Szrj
8593*38fd1498Szrj /* The following macro values are local variable names for function
8594*38fd1498Szrj `get_cpu_unit_code'. */
8595*38fd1498Szrj #define CMP_VARIABLE_NAME "cmp"
8596*38fd1498Szrj #define LOW_VARIABLE_NAME "l"
8597*38fd1498Szrj #define MIDDLE_VARIABLE_NAME "m"
8598*38fd1498Szrj #define HIGH_VARIABLE_NAME "h"
8599*38fd1498Szrj
8600*38fd1498Szrj /* The following function outputs function to obtain internal cpu unit
8601*38fd1498Szrj code by the cpu unit name. */
8602*38fd1498Szrj static void
output_get_cpu_unit_code_func(void)8603*38fd1498Szrj output_get_cpu_unit_code_func (void)
8604*38fd1498Szrj {
8605*38fd1498Szrj int i;
8606*38fd1498Szrj unit_decl_t *units;
8607*38fd1498Szrj
8608*38fd1498Szrj fprintf (output_file, "int\n%s (const char *%s)\n",
8609*38fd1498Szrj GET_CPU_UNIT_CODE_FUNC_NAME, CPU_UNIT_NAME_PARAMETER_NAME);
8610*38fd1498Szrj fprintf (output_file, "{\n struct %s {const char *%s; int %s;};\n",
8611*38fd1498Szrj NAME_CODE_STRUCT_NAME, NAME_MEMBER_NAME, CODE_MEMBER_NAME);
8612*38fd1498Szrj fprintf (output_file, " int %s, %s, %s, %s;\n", CMP_VARIABLE_NAME,
8613*38fd1498Szrj LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8614*38fd1498Szrj fprintf (output_file, " static struct %s %s [] =\n {\n",
8615*38fd1498Szrj NAME_CODE_STRUCT_NAME, NAME_CODE_TABLE_NAME);
8616*38fd1498Szrj units = XNEWVEC (unit_decl_t, description->units_num);
8617*38fd1498Szrj memcpy (units, units_array, sizeof (unit_decl_t) * description->units_num);
8618*38fd1498Szrj qsort (units, description->units_num, sizeof (unit_decl_t), units_cmp);
8619*38fd1498Szrj for (i = 0; i < description->units_num; i++)
8620*38fd1498Szrj if (units [i]->query_p)
8621*38fd1498Szrj fprintf (output_file, " {\"%s\", %d},\n",
8622*38fd1498Szrj units[i]->name, units[i]->query_num);
8623*38fd1498Szrj fprintf (output_file, " };\n\n");
8624*38fd1498Szrj fprintf (output_file, " /* The following is binary search: */\n");
8625*38fd1498Szrj fprintf (output_file, " %s = 0;\n", LOW_VARIABLE_NAME);
8626*38fd1498Szrj fprintf (output_file, " %s = sizeof (%s) / sizeof (struct %s) - 1;\n",
8627*38fd1498Szrj HIGH_VARIABLE_NAME, NAME_CODE_TABLE_NAME, NAME_CODE_STRUCT_NAME);
8628*38fd1498Szrj fprintf (output_file, " while (%s <= %s)\n {\n",
8629*38fd1498Szrj LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8630*38fd1498Szrj fprintf (output_file, " %s = (%s + %s) / 2;\n",
8631*38fd1498Szrj MIDDLE_VARIABLE_NAME, LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8632*38fd1498Szrj fprintf (output_file, " %s = strcmp (%s, %s [%s].%s);\n",
8633*38fd1498Szrj CMP_VARIABLE_NAME, CPU_UNIT_NAME_PARAMETER_NAME,
8634*38fd1498Szrj NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, NAME_MEMBER_NAME);
8635*38fd1498Szrj fprintf (output_file, " if (%s < 0)\n", CMP_VARIABLE_NAME);
8636*38fd1498Szrj fprintf (output_file, " %s = %s - 1;\n",
8637*38fd1498Szrj HIGH_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
8638*38fd1498Szrj fprintf (output_file, " else if (%s > 0)\n", CMP_VARIABLE_NAME);
8639*38fd1498Szrj fprintf (output_file, " %s = %s + 1;\n",
8640*38fd1498Szrj LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
8641*38fd1498Szrj fprintf (output_file, " else\n");
8642*38fd1498Szrj fprintf (output_file, " return %s [%s].%s;\n }\n",
8643*38fd1498Szrj NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, CODE_MEMBER_NAME);
8644*38fd1498Szrj fprintf (output_file, " return -1;\n}\n\n");
8645*38fd1498Szrj free (units);
8646*38fd1498Szrj }
8647*38fd1498Szrj
8648*38fd1498Szrj /* The following function outputs function to check reservation of cpu
8649*38fd1498Szrj unit (its internal code will be passed as the function argument) in
8650*38fd1498Szrj given cpu state. */
8651*38fd1498Szrj static void
output_cpu_unit_reservation_p(void)8652*38fd1498Szrj output_cpu_unit_reservation_p (void)
8653*38fd1498Szrj {
8654*38fd1498Szrj automaton_t automaton;
8655*38fd1498Szrj
8656*38fd1498Szrj fprintf (output_file, "int\n%s (%s %s, int %s)\n",
8657*38fd1498Szrj CPU_UNIT_RESERVATION_P_FUNC_NAME,
8658*38fd1498Szrj STATE_TYPE_NAME, STATE_NAME,
8659*38fd1498Szrj CPU_CODE_PARAMETER_NAME);
8660*38fd1498Szrj fprintf (output_file, "{\n gcc_assert (%s >= 0 && %s < %d);\n",
8661*38fd1498Szrj CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME,
8662*38fd1498Szrj description->query_units_num);
8663*38fd1498Szrj if (description->query_units_num > 0)
8664*38fd1498Szrj for (automaton = description->first_automaton;
8665*38fd1498Szrj automaton != NULL;
8666*38fd1498Szrj automaton = automaton->next_automaton)
8667*38fd1498Szrj {
8668*38fd1498Szrj fprintf (output_file, " if ((");
8669*38fd1498Szrj output_reserved_units_table_name (output_file, automaton);
8670*38fd1498Szrj fprintf (output_file, " [((struct %s *) %s)->", CHIP_NAME, STATE_NAME);
8671*38fd1498Szrj output_chip_member_name (output_file, automaton);
8672*38fd1498Szrj fprintf (output_file, " * %d + %s / 8] >> (%s %% 8)) & 1)\n",
8673*38fd1498Szrj (description->query_units_num + 7) / 8,
8674*38fd1498Szrj CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME);
8675*38fd1498Szrj fprintf (output_file, " return 1;\n");
8676*38fd1498Szrj }
8677*38fd1498Szrj fprintf (output_file, " return 0;\n}\n\n");
8678*38fd1498Szrj }
8679*38fd1498Szrj
8680*38fd1498Szrj /* The following function outputs a function to check if insn
8681*38fd1498Szrj has a dfa reservation. */
8682*38fd1498Szrj static void
output_insn_has_dfa_reservation_p(void)8683*38fd1498Szrj output_insn_has_dfa_reservation_p (void)
8684*38fd1498Szrj {
8685*38fd1498Szrj fprintf (output_file,
8686*38fd1498Szrj "bool\n%s (rtx_insn *%s ATTRIBUTE_UNUSED)\n{\n",
8687*38fd1498Szrj INSN_HAS_DFA_RESERVATION_P_FUNC_NAME,
8688*38fd1498Szrj INSN_PARAMETER_NAME);
8689*38fd1498Szrj
8690*38fd1498Szrj if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8691*38fd1498Szrj {
8692*38fd1498Szrj fprintf (output_file, " return false;\n}\n\n");
8693*38fd1498Szrj return;
8694*38fd1498Szrj }
8695*38fd1498Szrj
8696*38fd1498Szrj fprintf (output_file, " int %s;\n\n", INTERNAL_INSN_CODE_NAME);
8697*38fd1498Szrj
8698*38fd1498Szrj fprintf (output_file, " if (%s == 0)\n %s = %s;\n",
8699*38fd1498Szrj INSN_PARAMETER_NAME,
8700*38fd1498Szrj INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8701*38fd1498Szrj fprintf (output_file, " else\n\
8702*38fd1498Szrj {\n\
8703*38fd1498Szrj %s = %s (%s);\n\
8704*38fd1498Szrj if (%s > %s)\n\
8705*38fd1498Szrj %s = %s;\n\
8706*38fd1498Szrj }\n\n",
8707*38fd1498Szrj INTERNAL_INSN_CODE_NAME, DFA_INSN_CODE_FUNC_NAME,
8708*38fd1498Szrj INSN_PARAMETER_NAME,
8709*38fd1498Szrj INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8710*38fd1498Szrj INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8711*38fd1498Szrj
8712*38fd1498Szrj fprintf (output_file, " return %s != %s;\n}\n\n",
8713*38fd1498Szrj INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8714*38fd1498Szrj }
8715*38fd1498Szrj
8716*38fd1498Szrj /* The function outputs PHR interface functions `dfa_clean_insn_cache'
8717*38fd1498Szrj and 'dfa_clear_single_insn_cache'. */
8718*38fd1498Szrj static void
output_dfa_clean_insn_cache_func(void)8719*38fd1498Szrj output_dfa_clean_insn_cache_func (void)
8720*38fd1498Szrj {
8721*38fd1498Szrj fprintf (output_file,
8722*38fd1498Szrj "void\n%s (void)\n{\n int %s;\n\n",
8723*38fd1498Szrj DFA_CLEAN_INSN_CACHE_FUNC_NAME, I_VARIABLE_NAME);
8724*38fd1498Szrj fprintf (output_file,
8725*38fd1498Szrj " for (%s = 0; %s < %s; %s++)\n %s [%s] = -1;\n}\n\n",
8726*38fd1498Szrj I_VARIABLE_NAME, I_VARIABLE_NAME,
8727*38fd1498Szrj DFA_INSN_CODES_LENGTH_VARIABLE_NAME, I_VARIABLE_NAME,
8728*38fd1498Szrj DFA_INSN_CODES_VARIABLE_NAME, I_VARIABLE_NAME);
8729*38fd1498Szrj
8730*38fd1498Szrj fprintf (output_file,
8731*38fd1498Szrj "void\n%s (rtx_insn *%s)\n{\n int %s;\n\n",
8732*38fd1498Szrj DFA_CLEAR_SINGLE_INSN_CACHE_FUNC_NAME, INSN_PARAMETER_NAME,
8733*38fd1498Szrj I_VARIABLE_NAME);
8734*38fd1498Szrj fprintf (output_file,
8735*38fd1498Szrj " %s = INSN_UID (%s);\n if (%s < %s)\n %s [%s] = -1;\n}\n\n",
8736*38fd1498Szrj I_VARIABLE_NAME, INSN_PARAMETER_NAME, I_VARIABLE_NAME,
8737*38fd1498Szrj DFA_INSN_CODES_LENGTH_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
8738*38fd1498Szrj I_VARIABLE_NAME);
8739*38fd1498Szrj }
8740*38fd1498Szrj
8741*38fd1498Szrj /* The function outputs PHR interface function `dfa_start'. */
8742*38fd1498Szrj static void
output_dfa_start_func(void)8743*38fd1498Szrj output_dfa_start_func (void)
8744*38fd1498Szrj {
8745*38fd1498Szrj fprintf (output_file,
8746*38fd1498Szrj "void\n%s (void)\n{\n %s = get_max_uid ();\n",
8747*38fd1498Szrj DFA_START_FUNC_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8748*38fd1498Szrj fprintf (output_file, " %s = XNEWVEC (int, %s);\n",
8749*38fd1498Szrj DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8750*38fd1498Szrj fprintf (output_file, " %s ();\n}\n\n", DFA_CLEAN_INSN_CACHE_FUNC_NAME);
8751*38fd1498Szrj }
8752*38fd1498Szrj
8753*38fd1498Szrj /* The function outputs PHR interface function `dfa_finish'. */
8754*38fd1498Szrj static void
output_dfa_finish_func(void)8755*38fd1498Szrj output_dfa_finish_func (void)
8756*38fd1498Szrj {
8757*38fd1498Szrj fprintf (output_file, "void\n%s (void)\n{\n free (%s);\n}\n\n",
8758*38fd1498Szrj DFA_FINISH_FUNC_NAME, DFA_INSN_CODES_VARIABLE_NAME);
8759*38fd1498Szrj }
8760*38fd1498Szrj
8761*38fd1498Szrj
8762*38fd1498Szrj
8763*38fd1498Szrj /* The page contains code for output description file (readable
8764*38fd1498Szrj representation of original description and generated DFA(s). */
8765*38fd1498Szrj
8766*38fd1498Szrj /* The function outputs string representation of IR reservation. */
8767*38fd1498Szrj static void
output_regexp(regexp_t regexp)8768*38fd1498Szrj output_regexp (regexp_t regexp)
8769*38fd1498Szrj {
8770*38fd1498Szrj fprintf (output_description_file, "%s", regexp_representation (regexp));
8771*38fd1498Szrj finish_regexp_representation ();
8772*38fd1498Szrj }
8773*38fd1498Szrj
8774*38fd1498Szrj /* Output names of units in LIST separated by comma. */
8775*38fd1498Szrj static void
output_unit_set_el_list(unit_set_el_t list)8776*38fd1498Szrj output_unit_set_el_list (unit_set_el_t list)
8777*38fd1498Szrj {
8778*38fd1498Szrj unit_set_el_t el;
8779*38fd1498Szrj
8780*38fd1498Szrj for (el = list; el != NULL; el = el->next_unit_set_el)
8781*38fd1498Szrj {
8782*38fd1498Szrj if (el != list)
8783*38fd1498Szrj fprintf (output_description_file, ", ");
8784*38fd1498Szrj fprintf (output_description_file, "%s", el->unit_decl->name);
8785*38fd1498Szrj }
8786*38fd1498Szrj }
8787*38fd1498Szrj
8788*38fd1498Szrj /* Output patterns in LIST separated by comma. */
8789*38fd1498Szrj static void
output_pattern_set_el_list(pattern_set_el_t list)8790*38fd1498Szrj output_pattern_set_el_list (pattern_set_el_t list)
8791*38fd1498Szrj {
8792*38fd1498Szrj pattern_set_el_t el;
8793*38fd1498Szrj int i;
8794*38fd1498Szrj
8795*38fd1498Szrj for (el = list; el != NULL; el = el->next_pattern_set_el)
8796*38fd1498Szrj {
8797*38fd1498Szrj if (el != list)
8798*38fd1498Szrj fprintf (output_description_file, ", ");
8799*38fd1498Szrj for (i = 0; i < el->units_num; i++)
8800*38fd1498Szrj fprintf (output_description_file, (i == 0 ? "%s" : " %s"),
8801*38fd1498Szrj el->unit_decls [i]->name);
8802*38fd1498Szrj }
8803*38fd1498Szrj }
8804*38fd1498Szrj
8805*38fd1498Szrj /* The function outputs string representation of IR define_reservation
8806*38fd1498Szrj and define_insn_reservation. */
8807*38fd1498Szrj static void
output_description(void)8808*38fd1498Szrj output_description (void)
8809*38fd1498Szrj {
8810*38fd1498Szrj decl_t decl;
8811*38fd1498Szrj int i;
8812*38fd1498Szrj
8813*38fd1498Szrj for (i = 0; i < description->decls_num; i++)
8814*38fd1498Szrj {
8815*38fd1498Szrj decl = description->decls [i];
8816*38fd1498Szrj if (decl->mode == dm_unit)
8817*38fd1498Szrj {
8818*38fd1498Szrj if (DECL_UNIT (decl)->excl_list != NULL)
8819*38fd1498Szrj {
8820*38fd1498Szrj fprintf (output_description_file, "unit %s exclusion_set: ",
8821*38fd1498Szrj DECL_UNIT (decl)->name);
8822*38fd1498Szrj output_unit_set_el_list (DECL_UNIT (decl)->excl_list);
8823*38fd1498Szrj fprintf (output_description_file, "\n");
8824*38fd1498Szrj }
8825*38fd1498Szrj if (DECL_UNIT (decl)->presence_list != NULL)
8826*38fd1498Szrj {
8827*38fd1498Szrj fprintf (output_description_file, "unit %s presence_set: ",
8828*38fd1498Szrj DECL_UNIT (decl)->name);
8829*38fd1498Szrj output_pattern_set_el_list (DECL_UNIT (decl)->presence_list);
8830*38fd1498Szrj fprintf (output_description_file, "\n");
8831*38fd1498Szrj }
8832*38fd1498Szrj if (DECL_UNIT (decl)->final_presence_list != NULL)
8833*38fd1498Szrj {
8834*38fd1498Szrj fprintf (output_description_file, "unit %s final_presence_set: ",
8835*38fd1498Szrj DECL_UNIT (decl)->name);
8836*38fd1498Szrj output_pattern_set_el_list
8837*38fd1498Szrj (DECL_UNIT (decl)->final_presence_list);
8838*38fd1498Szrj fprintf (output_description_file, "\n");
8839*38fd1498Szrj }
8840*38fd1498Szrj if (DECL_UNIT (decl)->absence_list != NULL)
8841*38fd1498Szrj {
8842*38fd1498Szrj fprintf (output_description_file, "unit %s absence_set: ",
8843*38fd1498Szrj DECL_UNIT (decl)->name);
8844*38fd1498Szrj output_pattern_set_el_list (DECL_UNIT (decl)->absence_list);
8845*38fd1498Szrj fprintf (output_description_file, "\n");
8846*38fd1498Szrj }
8847*38fd1498Szrj if (DECL_UNIT (decl)->final_absence_list != NULL)
8848*38fd1498Szrj {
8849*38fd1498Szrj fprintf (output_description_file, "unit %s final_absence_set: ",
8850*38fd1498Szrj DECL_UNIT (decl)->name);
8851*38fd1498Szrj output_pattern_set_el_list
8852*38fd1498Szrj (DECL_UNIT (decl)->final_absence_list);
8853*38fd1498Szrj fprintf (output_description_file, "\n");
8854*38fd1498Szrj }
8855*38fd1498Szrj }
8856*38fd1498Szrj }
8857*38fd1498Szrj fprintf (output_description_file, "\n");
8858*38fd1498Szrj for (i = 0; i < description->normal_decls_num; i++)
8859*38fd1498Szrj {
8860*38fd1498Szrj decl = description->decls [i];
8861*38fd1498Szrj if (decl->mode == dm_reserv)
8862*38fd1498Szrj {
8863*38fd1498Szrj fprintf (output_description_file, "reservation %s: ",
8864*38fd1498Szrj DECL_RESERV (decl)->name);
8865*38fd1498Szrj output_regexp (DECL_RESERV (decl)->regexp);
8866*38fd1498Szrj fprintf (output_description_file, "\n");
8867*38fd1498Szrj }
8868*38fd1498Szrj else if (decl->mode == dm_insn_reserv)
8869*38fd1498Szrj {
8870*38fd1498Szrj fprintf (output_description_file, "insn reservation %s ",
8871*38fd1498Szrj DECL_INSN_RESERV (decl)->name);
8872*38fd1498Szrj print_rtl (output_description_file,
8873*38fd1498Szrj DECL_INSN_RESERV (decl)->condexp);
8874*38fd1498Szrj fprintf (output_description_file, ": ");
8875*38fd1498Szrj output_regexp (DECL_INSN_RESERV (decl)->regexp);
8876*38fd1498Szrj fprintf (output_description_file, "\n");
8877*38fd1498Szrj }
8878*38fd1498Szrj else if (decl->mode == dm_bypass)
8879*38fd1498Szrj fprintf (output_description_file, "bypass %d %s %s\n",
8880*38fd1498Szrj DECL_BYPASS (decl)->latency,
8881*38fd1498Szrj DECL_BYPASS (decl)->out_pattern,
8882*38fd1498Szrj DECL_BYPASS (decl)->in_pattern);
8883*38fd1498Szrj }
8884*38fd1498Szrj fprintf (output_description_file, "\n\f\n");
8885*38fd1498Szrj }
8886*38fd1498Szrj
8887*38fd1498Szrj /* The function outputs name of AUTOMATON. */
8888*38fd1498Szrj static void
output_automaton_name(FILE * f,automaton_t automaton)8889*38fd1498Szrj output_automaton_name (FILE *f, automaton_t automaton)
8890*38fd1498Szrj {
8891*38fd1498Szrj if (automaton->corresponding_automaton_decl == NULL)
8892*38fd1498Szrj fprintf (f, "#%d", automaton->automaton_order_num);
8893*38fd1498Szrj else
8894*38fd1498Szrj fprintf (f, "`%s'", automaton->corresponding_automaton_decl->name);
8895*38fd1498Szrj }
8896*38fd1498Szrj
8897*38fd1498Szrj /* Maximal length of line for pretty printing into description
8898*38fd1498Szrj file. */
8899*38fd1498Szrj #define MAX_LINE_LENGTH 70
8900*38fd1498Szrj
8901*38fd1498Szrj /* The function outputs units name belonging to AUTOMATON. */
8902*38fd1498Szrj static void
output_automaton_units(automaton_t automaton)8903*38fd1498Szrj output_automaton_units (automaton_t automaton)
8904*38fd1498Szrj {
8905*38fd1498Szrj decl_t decl;
8906*38fd1498Szrj const char *name;
8907*38fd1498Szrj int curr_line_length;
8908*38fd1498Szrj int there_is_an_automaton_unit;
8909*38fd1498Szrj int i;
8910*38fd1498Szrj
8911*38fd1498Szrj fprintf (output_description_file, "\n Corresponding units:\n");
8912*38fd1498Szrj fprintf (output_description_file, " ");
8913*38fd1498Szrj curr_line_length = 4;
8914*38fd1498Szrj there_is_an_automaton_unit = 0;
8915*38fd1498Szrj for (i = 0; i < description->decls_num; i++)
8916*38fd1498Szrj {
8917*38fd1498Szrj decl = description->decls [i];
8918*38fd1498Szrj if (decl->mode == dm_unit
8919*38fd1498Szrj && (DECL_UNIT (decl)->corresponding_automaton_num
8920*38fd1498Szrj == automaton->automaton_order_num))
8921*38fd1498Szrj {
8922*38fd1498Szrj there_is_an_automaton_unit = 1;
8923*38fd1498Szrj name = DECL_UNIT (decl)->name;
8924*38fd1498Szrj if (curr_line_length + strlen (name) + 1 > MAX_LINE_LENGTH )
8925*38fd1498Szrj {
8926*38fd1498Szrj curr_line_length = strlen (name) + 4;
8927*38fd1498Szrj fprintf (output_description_file, "\n ");
8928*38fd1498Szrj }
8929*38fd1498Szrj else
8930*38fd1498Szrj {
8931*38fd1498Szrj curr_line_length += strlen (name) + 1;
8932*38fd1498Szrj fprintf (output_description_file, " ");
8933*38fd1498Szrj }
8934*38fd1498Szrj fprintf (output_description_file, "%s", name);
8935*38fd1498Szrj }
8936*38fd1498Szrj }
8937*38fd1498Szrj if (!there_is_an_automaton_unit)
8938*38fd1498Szrj fprintf (output_description_file, "<None>");
8939*38fd1498Szrj fprintf (output_description_file, "\n\n");
8940*38fd1498Szrj }
8941*38fd1498Szrj
8942*38fd1498Szrj /* The following variable is used for forming array of all possible cpu unit
8943*38fd1498Szrj reservations described by the current DFA state. */
8944*38fd1498Szrj static vec<reserv_sets_t> state_reservs;
8945*38fd1498Szrj
8946*38fd1498Szrj /* The function forms `state_reservs' for STATE. */
8947*38fd1498Szrj static void
add_state_reservs(state_t state)8948*38fd1498Szrj add_state_reservs (state_t state)
8949*38fd1498Szrj {
8950*38fd1498Szrj alt_state_t curr_alt_state;
8951*38fd1498Szrj
8952*38fd1498Szrj if (state->component_states != NULL)
8953*38fd1498Szrj for (curr_alt_state = state->component_states;
8954*38fd1498Szrj curr_alt_state != NULL;
8955*38fd1498Szrj curr_alt_state = curr_alt_state->next_sorted_alt_state)
8956*38fd1498Szrj add_state_reservs (curr_alt_state->state);
8957*38fd1498Szrj else
8958*38fd1498Szrj state_reservs.safe_push (state->reservs);
8959*38fd1498Szrj }
8960*38fd1498Szrj
8961*38fd1498Szrj /* The function outputs readable representation of all out arcs of
8962*38fd1498Szrj STATE. */
8963*38fd1498Szrj static void
output_state_arcs(state_t state)8964*38fd1498Szrj output_state_arcs (state_t state)
8965*38fd1498Szrj {
8966*38fd1498Szrj arc_t arc;
8967*38fd1498Szrj ainsn_t ainsn;
8968*38fd1498Szrj const char *insn_name;
8969*38fd1498Szrj int curr_line_length;
8970*38fd1498Szrj
8971*38fd1498Szrj for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
8972*38fd1498Szrj {
8973*38fd1498Szrj ainsn = arc->insn;
8974*38fd1498Szrj gcc_assert (ainsn->first_insn_with_same_reservs);
8975*38fd1498Szrj fprintf (output_description_file, " ");
8976*38fd1498Szrj curr_line_length = 7;
8977*38fd1498Szrj fprintf (output_description_file, "%2d: ", ainsn->insn_equiv_class_num);
8978*38fd1498Szrj do
8979*38fd1498Szrj {
8980*38fd1498Szrj insn_name = ainsn->insn_reserv_decl->name;
8981*38fd1498Szrj if (curr_line_length + strlen (insn_name) > MAX_LINE_LENGTH)
8982*38fd1498Szrj {
8983*38fd1498Szrj if (ainsn != arc->insn)
8984*38fd1498Szrj {
8985*38fd1498Szrj fprintf (output_description_file, ",\n ");
8986*38fd1498Szrj curr_line_length = strlen (insn_name) + 6;
8987*38fd1498Szrj }
8988*38fd1498Szrj else
8989*38fd1498Szrj curr_line_length += strlen (insn_name);
8990*38fd1498Szrj }
8991*38fd1498Szrj else
8992*38fd1498Szrj {
8993*38fd1498Szrj curr_line_length += strlen (insn_name);
8994*38fd1498Szrj if (ainsn != arc->insn)
8995*38fd1498Szrj {
8996*38fd1498Szrj curr_line_length += 2;
8997*38fd1498Szrj fprintf (output_description_file, ", ");
8998*38fd1498Szrj }
8999*38fd1498Szrj }
9000*38fd1498Szrj fprintf (output_description_file, "%s", insn_name);
9001*38fd1498Szrj ainsn = ainsn->next_same_reservs_insn;
9002*38fd1498Szrj }
9003*38fd1498Szrj while (ainsn != NULL);
9004*38fd1498Szrj fprintf (output_description_file, " %d \n",
9005*38fd1498Szrj arc->to_state->order_state_num);
9006*38fd1498Szrj }
9007*38fd1498Szrj fprintf (output_description_file, "\n");
9008*38fd1498Szrj }
9009*38fd1498Szrj
9010*38fd1498Szrj /* The following function is used for sorting possible cpu unit
9011*38fd1498Szrj reservation of a DFA state. */
9012*38fd1498Szrj static int
state_reservs_cmp(const void * reservs_ptr_1,const void * reservs_ptr_2)9013*38fd1498Szrj state_reservs_cmp (const void *reservs_ptr_1, const void *reservs_ptr_2)
9014*38fd1498Szrj {
9015*38fd1498Szrj return reserv_sets_cmp (*(const_reserv_sets_t const*) reservs_ptr_1,
9016*38fd1498Szrj *(const_reserv_sets_t const*) reservs_ptr_2);
9017*38fd1498Szrj }
9018*38fd1498Szrj
9019*38fd1498Szrj /* The following function is used for sorting possible cpu unit
9020*38fd1498Szrj reservation of a DFA state. */
9021*38fd1498Szrj static void
remove_state_duplicate_reservs(void)9022*38fd1498Szrj remove_state_duplicate_reservs (void)
9023*38fd1498Szrj {
9024*38fd1498Szrj size_t i, j;
9025*38fd1498Szrj
9026*38fd1498Szrj for (i = 1, j = 0; i < state_reservs.length (); i++)
9027*38fd1498Szrj if (reserv_sets_cmp (state_reservs[j], state_reservs[i]))
9028*38fd1498Szrj {
9029*38fd1498Szrj j++;
9030*38fd1498Szrj state_reservs[j] = state_reservs[i];
9031*38fd1498Szrj }
9032*38fd1498Szrj state_reservs.truncate (j + 1);
9033*38fd1498Szrj }
9034*38fd1498Szrj
9035*38fd1498Szrj /* The following function output readable representation of DFA(s)
9036*38fd1498Szrj state used for fast recognition of pipeline hazards. State is
9037*38fd1498Szrj described by possible (current and scheduled) cpu unit
9038*38fd1498Szrj reservations. */
9039*38fd1498Szrj static void
output_state(state_t state)9040*38fd1498Szrj output_state (state_t state)
9041*38fd1498Szrj {
9042*38fd1498Szrj size_t i;
9043*38fd1498Szrj
9044*38fd1498Szrj state_reservs.create (0);
9045*38fd1498Szrj
9046*38fd1498Szrj fprintf (output_description_file, " State #%d", state->order_state_num);
9047*38fd1498Szrj fprintf (output_description_file,
9048*38fd1498Szrj state->new_cycle_p ? " (new cycle)\n" : "\n");
9049*38fd1498Szrj add_state_reservs (state);
9050*38fd1498Szrj state_reservs.qsort (state_reservs_cmp);
9051*38fd1498Szrj remove_state_duplicate_reservs ();
9052*38fd1498Szrj for (i = 0; i < state_reservs.length (); i++)
9053*38fd1498Szrj {
9054*38fd1498Szrj fprintf (output_description_file, " ");
9055*38fd1498Szrj output_reserv_sets (output_description_file, state_reservs[i]);
9056*38fd1498Szrj fprintf (output_description_file, "\n");
9057*38fd1498Szrj }
9058*38fd1498Szrj fprintf (output_description_file, "\n");
9059*38fd1498Szrj output_state_arcs (state);
9060*38fd1498Szrj state_reservs.release ();
9061*38fd1498Szrj }
9062*38fd1498Szrj
9063*38fd1498Szrj /* The following function output readable representation of
9064*38fd1498Szrj DFAs used for fast recognition of pipeline hazards. */
9065*38fd1498Szrj static void
output_automaton_descriptions(void)9066*38fd1498Szrj output_automaton_descriptions (void)
9067*38fd1498Szrj {
9068*38fd1498Szrj automaton_t automaton;
9069*38fd1498Szrj
9070*38fd1498Szrj for (automaton = description->first_automaton;
9071*38fd1498Szrj automaton != NULL;
9072*38fd1498Szrj automaton = automaton->next_automaton)
9073*38fd1498Szrj {
9074*38fd1498Szrj fprintf (output_description_file, "\nAutomaton ");
9075*38fd1498Szrj output_automaton_name (output_description_file, automaton);
9076*38fd1498Szrj fprintf (output_description_file, "\n");
9077*38fd1498Szrj output_automaton_units (automaton);
9078*38fd1498Szrj pass_states (automaton, output_state);
9079*38fd1498Szrj }
9080*38fd1498Szrj }
9081*38fd1498Szrj
9082*38fd1498Szrj
9083*38fd1498Szrj
9084*38fd1498Szrj /* The page contains top level function for generation DFA(s) used for
9085*38fd1498Szrj PHR. */
9086*38fd1498Szrj
9087*38fd1498Szrj /* The function outputs statistics about work of different phases of
9088*38fd1498Szrj DFA generator. */
9089*38fd1498Szrj static void
output_statistics(FILE * f)9090*38fd1498Szrj output_statistics (FILE *f)
9091*38fd1498Szrj {
9092*38fd1498Szrj automaton_t automaton;
9093*38fd1498Szrj int states_num;
9094*38fd1498Szrj #ifndef NDEBUG
9095*38fd1498Szrj int transition_comb_vect_els = 0;
9096*38fd1498Szrj int transition_full_vect_els = 0;
9097*38fd1498Szrj int min_issue_delay_vect_els = 0;
9098*38fd1498Szrj int locked_states = 0;
9099*38fd1498Szrj #endif
9100*38fd1498Szrj
9101*38fd1498Szrj for (automaton = description->first_automaton;
9102*38fd1498Szrj automaton != NULL;
9103*38fd1498Szrj automaton = automaton->next_automaton)
9104*38fd1498Szrj {
9105*38fd1498Szrj fprintf (f, "\nAutomaton ");
9106*38fd1498Szrj output_automaton_name (f, automaton);
9107*38fd1498Szrj fprintf (f, "\n %5d NDFA states, %5d NDFA arcs\n",
9108*38fd1498Szrj automaton->NDFA_states_num, automaton->NDFA_arcs_num);
9109*38fd1498Szrj fprintf (f, " %5d DFA states, %5d DFA arcs\n",
9110*38fd1498Szrj automaton->DFA_states_num, automaton->DFA_arcs_num);
9111*38fd1498Szrj states_num = automaton->DFA_states_num;
9112*38fd1498Szrj if (!no_minimization_flag)
9113*38fd1498Szrj {
9114*38fd1498Szrj fprintf (f, " %5d minimal DFA states, %5d minimal DFA arcs\n",
9115*38fd1498Szrj automaton->minimal_DFA_states_num,
9116*38fd1498Szrj automaton->minimal_DFA_arcs_num);
9117*38fd1498Szrj states_num = automaton->minimal_DFA_states_num;
9118*38fd1498Szrj }
9119*38fd1498Szrj fprintf (f, " %5d all insns %5d insn equivalence classes\n",
9120*38fd1498Szrj description->insns_num, automaton->insn_equiv_classes_num);
9121*38fd1498Szrj fprintf (f, " %d locked states\n", automaton->locked_states);
9122*38fd1498Szrj #ifndef NDEBUG
9123*38fd1498Szrj fprintf
9124*38fd1498Szrj (f, "%5ld transition comb vector els, %5ld trans table els: %s\n",
9125*38fd1498Szrj (long) automaton->trans_table->comb_vect.length (),
9126*38fd1498Szrj (long) automaton->trans_table->full_vect.length (),
9127*38fd1498Szrj (comb_vect_p (automaton->trans_table)
9128*38fd1498Szrj ? "use comb vect" : "use simple vect"));
9129*38fd1498Szrj fprintf
9130*38fd1498Szrj (f, "%5ld min delay table els, compression factor %d\n",
9131*38fd1498Szrj (long) states_num * automaton->insn_equiv_classes_num,
9132*38fd1498Szrj automaton->min_issue_delay_table_compression_factor);
9133*38fd1498Szrj transition_comb_vect_els
9134*38fd1498Szrj += automaton->trans_table->comb_vect.length ();
9135*38fd1498Szrj transition_full_vect_els
9136*38fd1498Szrj += automaton->trans_table->full_vect.length ();
9137*38fd1498Szrj min_issue_delay_vect_els
9138*38fd1498Szrj += states_num * automaton->insn_equiv_classes_num;
9139*38fd1498Szrj locked_states
9140*38fd1498Szrj += automaton->locked_states;
9141*38fd1498Szrj #endif
9142*38fd1498Szrj }
9143*38fd1498Szrj #ifndef NDEBUG
9144*38fd1498Szrj fprintf (f, "\n%5d all allocated states, %5d all allocated arcs\n",
9145*38fd1498Szrj allocated_states_num, allocated_arcs_num);
9146*38fd1498Szrj fprintf (f, "%5d all allocated alternative states\n",
9147*38fd1498Szrj allocated_alt_states_num);
9148*38fd1498Szrj fprintf (f, "%5d all transition comb vector els, %5d all trans table els\n",
9149*38fd1498Szrj transition_comb_vect_els, transition_full_vect_els);
9150*38fd1498Szrj fprintf (f, "%5d all min delay table els\n", min_issue_delay_vect_els);
9151*38fd1498Szrj fprintf (f, "%5d all locked states\n", locked_states);
9152*38fd1498Szrj #endif
9153*38fd1498Szrj }
9154*38fd1498Szrj
9155*38fd1498Szrj /* The function output times of work of different phases of DFA
9156*38fd1498Szrj generator. */
9157*38fd1498Szrj static void
output_time_statistics(FILE * f)9158*38fd1498Szrj output_time_statistics (FILE *f)
9159*38fd1498Szrj {
9160*38fd1498Szrj fprintf (f, "\n transformation: ");
9161*38fd1498Szrj print_active_time (f, transform_time);
9162*38fd1498Szrj fprintf (f, (!ndfa_flag ? ", building DFA: " : ", building NDFA: "));
9163*38fd1498Szrj print_active_time (f, NDFA_time);
9164*38fd1498Szrj if (ndfa_flag)
9165*38fd1498Szrj {
9166*38fd1498Szrj fprintf (f, ", NDFA -> DFA: ");
9167*38fd1498Szrj print_active_time (f, NDFA_to_DFA_time);
9168*38fd1498Szrj }
9169*38fd1498Szrj fprintf (f, "\n DFA minimization: ");
9170*38fd1498Szrj print_active_time (f, minimize_time);
9171*38fd1498Szrj fprintf (f, ", making insn equivalence: ");
9172*38fd1498Szrj print_active_time (f, equiv_time);
9173*38fd1498Szrj fprintf (f, "\n all automaton generation: ");
9174*38fd1498Szrj print_active_time (f, automaton_generation_time);
9175*38fd1498Szrj fprintf (f, ", output: ");
9176*38fd1498Szrj print_active_time (f, output_time);
9177*38fd1498Szrj fprintf (f, "\n");
9178*38fd1498Szrj }
9179*38fd1498Szrj
9180*38fd1498Szrj /* The function generates DFA (deterministic finite state automaton)
9181*38fd1498Szrj for fast recognition of pipeline hazards. No errors during
9182*38fd1498Szrj checking must be fixed before this function call. */
9183*38fd1498Szrj static void
generate(void)9184*38fd1498Szrj generate (void)
9185*38fd1498Szrj {
9186*38fd1498Szrj automata_num = split_argument;
9187*38fd1498Szrj if (description->units_num < automata_num)
9188*38fd1498Szrj automata_num = description->units_num;
9189*38fd1498Szrj initiate_states ();
9190*38fd1498Szrj initiate_arcs ();
9191*38fd1498Szrj initiate_automata_lists ();
9192*38fd1498Szrj initiate_pass_states ();
9193*38fd1498Szrj initiate_excl_sets ();
9194*38fd1498Szrj initiate_presence_absence_pattern_sets ();
9195*38fd1498Szrj automaton_generation_time = create_ticker ();
9196*38fd1498Szrj create_automata ();
9197*38fd1498Szrj ticker_off (&automaton_generation_time);
9198*38fd1498Szrj }
9199*38fd1498Szrj
9200*38fd1498Szrj
9201*38fd1498Szrj
9202*38fd1498Szrj /* This page mainly contains top level functions of pipeline hazards
9203*38fd1498Szrj description translator. */
9204*38fd1498Szrj
9205*38fd1498Szrj /* The following macro value is suffix of name of description file of
9206*38fd1498Szrj pipeline hazards description translator. */
9207*38fd1498Szrj #define STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX ".dfa"
9208*38fd1498Szrj
9209*38fd1498Szrj /* The function returns suffix of given file name. The returned
9210*38fd1498Szrj string can not be changed. */
9211*38fd1498Szrj static const char *
file_name_suffix(const char * file_name)9212*38fd1498Szrj file_name_suffix (const char *file_name)
9213*38fd1498Szrj {
9214*38fd1498Szrj const char *last_period;
9215*38fd1498Szrj
9216*38fd1498Szrj for (last_period = NULL; *file_name != '\0'; file_name++)
9217*38fd1498Szrj if (*file_name == '.')
9218*38fd1498Szrj last_period = file_name;
9219*38fd1498Szrj return (last_period == NULL ? file_name : last_period);
9220*38fd1498Szrj }
9221*38fd1498Szrj
9222*38fd1498Szrj /* The function returns base name of given file name, i.e. pointer to
9223*38fd1498Szrj first char after last `/' (or `\' for WIN32) in given file name,
9224*38fd1498Szrj given file name itself if the directory name is absent. The
9225*38fd1498Szrj returned string can not be changed. */
9226*38fd1498Szrj static const char *
base_file_name(const char * file_name)9227*38fd1498Szrj base_file_name (const char *file_name)
9228*38fd1498Szrj {
9229*38fd1498Szrj int directory_name_length;
9230*38fd1498Szrj
9231*38fd1498Szrj directory_name_length = strlen (file_name);
9232*38fd1498Szrj #ifdef WIN32
9233*38fd1498Szrj while (directory_name_length >= 0 && file_name[directory_name_length] != '/'
9234*38fd1498Szrj && file_name[directory_name_length] != '\\')
9235*38fd1498Szrj #else
9236*38fd1498Szrj while (directory_name_length >= 0 && file_name[directory_name_length] != '/')
9237*38fd1498Szrj #endif
9238*38fd1498Szrj directory_name_length--;
9239*38fd1498Szrj return file_name + directory_name_length + 1;
9240*38fd1498Szrj }
9241*38fd1498Szrj
9242*38fd1498Szrj /* A function passed as argument to init_rtx_reader_args_cb. It parses the
9243*38fd1498Szrj options available for genautomata. Returns true if the option was
9244*38fd1498Szrj recognized. */
9245*38fd1498Szrj static bool
parse_automata_opt(const char * str)9246*38fd1498Szrj parse_automata_opt (const char *str)
9247*38fd1498Szrj {
9248*38fd1498Szrj if (strcmp (str, NO_MINIMIZATION_OPTION) == 0)
9249*38fd1498Szrj no_minimization_flag = 1;
9250*38fd1498Szrj else if (strcmp (str, TIME_OPTION) == 0)
9251*38fd1498Szrj time_flag = 1;
9252*38fd1498Szrj else if (strcmp (str, STATS_OPTION) == 0)
9253*38fd1498Szrj stats_flag = 1;
9254*38fd1498Szrj else if (strcmp (str, V_OPTION) == 0)
9255*38fd1498Szrj v_flag = 1;
9256*38fd1498Szrj else if (strcmp (str, W_OPTION) == 0)
9257*38fd1498Szrj w_flag = 1;
9258*38fd1498Szrj else if (strcmp (str, NDFA_OPTION) == 0)
9259*38fd1498Szrj ndfa_flag = 1;
9260*38fd1498Szrj else if (strcmp (str, COLLAPSE_OPTION) == 0)
9261*38fd1498Szrj collapse_flag = 1;
9262*38fd1498Szrj else if (strcmp (str, PROGRESS_OPTION) == 0)
9263*38fd1498Szrj progress_flag = 1;
9264*38fd1498Szrj else if (strcmp (str, "-split") == 0)
9265*38fd1498Szrj {
9266*38fd1498Szrj fatal ("option `-split' has not been implemented yet\n");
9267*38fd1498Szrj /* split_argument = atoi (argument_vect [i + 1]); */
9268*38fd1498Szrj }
9269*38fd1498Szrj else
9270*38fd1498Szrj return false;
9271*38fd1498Szrj
9272*38fd1498Szrj return true;
9273*38fd1498Szrj }
9274*38fd1498Szrj
9275*38fd1498Szrj /* The following is top level function to initialize the work of
9276*38fd1498Szrj pipeline hazards description translator. */
9277*38fd1498Szrj static void
initiate_automaton_gen(const char ** argv)9278*38fd1498Szrj initiate_automaton_gen (const char **argv)
9279*38fd1498Szrj {
9280*38fd1498Szrj const char *base_name;
9281*38fd1498Szrj
9282*38fd1498Szrj /* Initialize IR storage. */
9283*38fd1498Szrj obstack_init (&irp);
9284*38fd1498Szrj initiate_automaton_decl_table ();
9285*38fd1498Szrj initiate_insn_decl_table ();
9286*38fd1498Szrj initiate_decl_table ();
9287*38fd1498Szrj output_file = stdout;
9288*38fd1498Szrj output_description_file = NULL;
9289*38fd1498Szrj base_name = base_file_name (argv[1]);
9290*38fd1498Szrj obstack_grow (&irp, base_name,
9291*38fd1498Szrj strlen (base_name) - strlen (file_name_suffix (base_name)));
9292*38fd1498Szrj obstack_grow (&irp, STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX,
9293*38fd1498Szrj strlen (STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX) + 1);
9294*38fd1498Szrj obstack_1grow (&irp, '\0');
9295*38fd1498Szrj output_description_file_name = (char *) obstack_base (&irp);
9296*38fd1498Szrj obstack_finish (&irp);
9297*38fd1498Szrj }
9298*38fd1498Szrj
9299*38fd1498Szrj /* The following function checks existence at least one arc marked by
9300*38fd1498Szrj each insn. */
9301*38fd1498Szrj static void
check_automata_insn_issues(void)9302*38fd1498Szrj check_automata_insn_issues (void)
9303*38fd1498Szrj {
9304*38fd1498Szrj automaton_t automaton;
9305*38fd1498Szrj ainsn_t ainsn, reserv_ainsn;
9306*38fd1498Szrj
9307*38fd1498Szrj for (automaton = description->first_automaton;
9308*38fd1498Szrj automaton != NULL;
9309*38fd1498Szrj automaton = automaton->next_automaton)
9310*38fd1498Szrj {
9311*38fd1498Szrj for (ainsn = automaton->ainsn_list;
9312*38fd1498Szrj ainsn != NULL;
9313*38fd1498Szrj ainsn = ainsn->next_ainsn)
9314*38fd1498Szrj if (ainsn->first_insn_with_same_reservs && !ainsn->arc_exists_p
9315*38fd1498Szrj && ainsn != automaton->collapse_ainsn)
9316*38fd1498Szrj {
9317*38fd1498Szrj for (reserv_ainsn = ainsn;
9318*38fd1498Szrj reserv_ainsn != NULL;
9319*38fd1498Szrj reserv_ainsn = reserv_ainsn->next_same_reservs_insn)
9320*38fd1498Szrj if (automaton->corresponding_automaton_decl != NULL)
9321*38fd1498Szrj {
9322*38fd1498Szrj if (!w_flag)
9323*38fd1498Szrj error ("Automaton `%s': Insn `%s' will never be issued",
9324*38fd1498Szrj automaton->corresponding_automaton_decl->name,
9325*38fd1498Szrj reserv_ainsn->insn_reserv_decl->name);
9326*38fd1498Szrj else
9327*38fd1498Szrj warning ("Automaton `%s': Insn `%s' will never be issued",
9328*38fd1498Szrj automaton->corresponding_automaton_decl->name,
9329*38fd1498Szrj reserv_ainsn->insn_reserv_decl->name);
9330*38fd1498Szrj }
9331*38fd1498Szrj else
9332*38fd1498Szrj {
9333*38fd1498Szrj if (!w_flag)
9334*38fd1498Szrj error ("Insn `%s' will never be issued",
9335*38fd1498Szrj reserv_ainsn->insn_reserv_decl->name);
9336*38fd1498Szrj else
9337*38fd1498Szrj warning ("Insn `%s' will never be issued",
9338*38fd1498Szrj reserv_ainsn->insn_reserv_decl->name);
9339*38fd1498Szrj }
9340*38fd1498Szrj }
9341*38fd1498Szrj }
9342*38fd1498Szrj }
9343*38fd1498Szrj
9344*38fd1498Szrj /* The following vla is used for storing pointers to all achieved
9345*38fd1498Szrj states. */
9346*38fd1498Szrj static vec<state_t> automaton_states;
9347*38fd1498Szrj
9348*38fd1498Szrj /* This function is called by function pass_states to add an achieved
9349*38fd1498Szrj STATE. */
9350*38fd1498Szrj static void
add_automaton_state(state_t state)9351*38fd1498Szrj add_automaton_state (state_t state)
9352*38fd1498Szrj {
9353*38fd1498Szrj automaton_states.safe_push (state);
9354*38fd1498Szrj }
9355*38fd1498Szrj
9356*38fd1498Szrj /* The following function forms list of important automata (whose
9357*38fd1498Szrj states may be changed after the insn issue) for each insn. */
9358*38fd1498Szrj static void
form_important_insn_automata_lists(void)9359*38fd1498Szrj form_important_insn_automata_lists (void)
9360*38fd1498Szrj {
9361*38fd1498Szrj automaton_t automaton;
9362*38fd1498Szrj decl_t decl;
9363*38fd1498Szrj ainsn_t ainsn;
9364*38fd1498Szrj arc_t arc;
9365*38fd1498Szrj int i;
9366*38fd1498Szrj size_t n;
9367*38fd1498Szrj
9368*38fd1498Szrj automaton_states.create (0);
9369*38fd1498Szrj /* Mark important ainsns. */
9370*38fd1498Szrj for (automaton = description->first_automaton;
9371*38fd1498Szrj automaton != NULL;
9372*38fd1498Szrj automaton = automaton->next_automaton)
9373*38fd1498Szrj {
9374*38fd1498Szrj automaton_states.truncate (0);
9375*38fd1498Szrj pass_states (automaton, add_automaton_state);
9376*38fd1498Szrj for (n = 0; n < automaton_states.length (); n++)
9377*38fd1498Szrj {
9378*38fd1498Szrj state_t s = automaton_states[n];
9379*38fd1498Szrj for (arc = first_out_arc (s);
9380*38fd1498Szrj arc != NULL;
9381*38fd1498Szrj arc = next_out_arc (arc))
9382*38fd1498Szrj if (arc->to_state != s)
9383*38fd1498Szrj {
9384*38fd1498Szrj gcc_assert (arc->insn->first_insn_with_same_reservs);
9385*38fd1498Szrj for (ainsn = arc->insn;
9386*38fd1498Szrj ainsn != NULL;
9387*38fd1498Szrj ainsn = ainsn->next_same_reservs_insn)
9388*38fd1498Szrj ainsn->important_p = TRUE;
9389*38fd1498Szrj }
9390*38fd1498Szrj }
9391*38fd1498Szrj }
9392*38fd1498Szrj automaton_states.release ();
9393*38fd1498Szrj
9394*38fd1498Szrj /* Create automata sets for the insns. */
9395*38fd1498Szrj for (i = 0; i < description->decls_num; i++)
9396*38fd1498Szrj {
9397*38fd1498Szrj decl = description->decls [i];
9398*38fd1498Szrj if (decl->mode == dm_insn_reserv)
9399*38fd1498Szrj {
9400*38fd1498Szrj automata_list_start ();
9401*38fd1498Szrj for (automaton = description->first_automaton;
9402*38fd1498Szrj automaton != NULL;
9403*38fd1498Szrj automaton = automaton->next_automaton)
9404*38fd1498Szrj for (ainsn = automaton->ainsn_list;
9405*38fd1498Szrj ainsn != NULL;
9406*38fd1498Szrj ainsn = ainsn->next_ainsn)
9407*38fd1498Szrj if (ainsn->important_p
9408*38fd1498Szrj && ainsn->insn_reserv_decl == DECL_INSN_RESERV (decl))
9409*38fd1498Szrj {
9410*38fd1498Szrj automata_list_add (automaton);
9411*38fd1498Szrj break;
9412*38fd1498Szrj }
9413*38fd1498Szrj DECL_INSN_RESERV (decl)->important_automata_list
9414*38fd1498Szrj = automata_list_finish ();
9415*38fd1498Szrj }
9416*38fd1498Szrj }
9417*38fd1498Szrj }
9418*38fd1498Szrj
9419*38fd1498Szrj
9420*38fd1498Szrj /* The following is top level function to generate automat(a,on) for
9421*38fd1498Szrj fast recognition of pipeline hazards. */
9422*38fd1498Szrj static void
expand_automata(void)9423*38fd1498Szrj expand_automata (void)
9424*38fd1498Szrj {
9425*38fd1498Szrj int i;
9426*38fd1498Szrj
9427*38fd1498Szrj description = XCREATENODEVAR (struct description,
9428*38fd1498Szrj sizeof (struct description)
9429*38fd1498Szrj /* Two entries for special insns. */
9430*38fd1498Szrj + sizeof (decl_t) * (decls.length () + 1));
9431*38fd1498Szrj description->decls_num = decls.length ();
9432*38fd1498Szrj description->normal_decls_num = description->decls_num;
9433*38fd1498Szrj description->query_units_num = 0;
9434*38fd1498Szrj for (i = 0; i < description->decls_num; i++)
9435*38fd1498Szrj {
9436*38fd1498Szrj description->decls [i] = decls[i];
9437*38fd1498Szrj if (description->decls [i]->mode == dm_unit
9438*38fd1498Szrj && DECL_UNIT (description->decls [i])->query_p)
9439*38fd1498Szrj DECL_UNIT (description->decls [i])->query_num
9440*38fd1498Szrj = description->query_units_num++;
9441*38fd1498Szrj }
9442*38fd1498Szrj all_time = create_ticker ();
9443*38fd1498Szrj check_time = create_ticker ();
9444*38fd1498Szrj if (progress_flag)
9445*38fd1498Szrj fprintf (stderr, "Check description...");
9446*38fd1498Szrj check_all_description ();
9447*38fd1498Szrj if (progress_flag)
9448*38fd1498Szrj fprintf (stderr, "done\n");
9449*38fd1498Szrj ticker_off (&check_time);
9450*38fd1498Szrj generation_time = create_ticker ();
9451*38fd1498Szrj if (!have_error)
9452*38fd1498Szrj {
9453*38fd1498Szrj transform_insn_regexps ();
9454*38fd1498Szrj check_unit_distributions_to_automata ();
9455*38fd1498Szrj }
9456*38fd1498Szrj if (!have_error)
9457*38fd1498Szrj {
9458*38fd1498Szrj generate ();
9459*38fd1498Szrj check_automata_insn_issues ();
9460*38fd1498Szrj }
9461*38fd1498Szrj if (!have_error)
9462*38fd1498Szrj {
9463*38fd1498Szrj form_important_insn_automata_lists ();
9464*38fd1498Szrj }
9465*38fd1498Szrj ticker_off (&generation_time);
9466*38fd1498Szrj }
9467*38fd1498Szrj
9468*38fd1498Szrj /* The following is top level function to output PHR and to finish
9469*38fd1498Szrj work with pipeline description translator. */
9470*38fd1498Szrj static void
write_automata(void)9471*38fd1498Szrj write_automata (void)
9472*38fd1498Szrj {
9473*38fd1498Szrj output_time = create_ticker ();
9474*38fd1498Szrj if (progress_flag)
9475*38fd1498Szrj fprintf (stderr, "Forming and outputting automata tables...");
9476*38fd1498Szrj output_tables ();
9477*38fd1498Szrj if (progress_flag)
9478*38fd1498Szrj {
9479*38fd1498Szrj fprintf (stderr, "done\n");
9480*38fd1498Szrj fprintf (stderr, "Output functions to work with automata...");
9481*38fd1498Szrj }
9482*38fd1498Szrj output_chip_definitions ();
9483*38fd1498Szrj output_max_insn_queue_index_def ();
9484*38fd1498Szrj output_internal_min_issue_delay_func ();
9485*38fd1498Szrj output_internal_trans_func ();
9486*38fd1498Szrj /* Cache of insn dfa codes: */
9487*38fd1498Szrj fprintf (output_file, "\nstatic int *%s;\n", DFA_INSN_CODES_VARIABLE_NAME);
9488*38fd1498Szrj fprintf (output_file, "\nstatic int %s;\n\n",
9489*38fd1498Szrj DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
9490*38fd1498Szrj output_dfa_insn_code_func ();
9491*38fd1498Szrj output_trans_func ();
9492*38fd1498Szrj output_min_issue_delay_func ();
9493*38fd1498Szrj output_internal_dead_lock_func ();
9494*38fd1498Szrj output_dead_lock_func ();
9495*38fd1498Szrj output_size_func ();
9496*38fd1498Szrj output_internal_reset_func ();
9497*38fd1498Szrj output_reset_func ();
9498*38fd1498Szrj output_min_insn_conflict_delay_func ();
9499*38fd1498Szrj output_default_latencies ();
9500*38fd1498Szrj output_internal_insn_latency_func ();
9501*38fd1498Szrj output_insn_latency_func ();
9502*38fd1498Szrj output_internal_maximal_insn_latency_func ();
9503*38fd1498Szrj output_maximal_insn_latency_func ();
9504*38fd1498Szrj output_print_reservation_func ();
9505*38fd1498Szrj /* Output function get_cpu_unit_code. */
9506*38fd1498Szrj fprintf (output_file, "\n#if %s\n\n", CPU_UNITS_QUERY_MACRO_NAME);
9507*38fd1498Szrj output_get_cpu_unit_code_func ();
9508*38fd1498Szrj output_cpu_unit_reservation_p ();
9509*38fd1498Szrj output_insn_has_dfa_reservation_p ();
9510*38fd1498Szrj fprintf (output_file, "\n#endif /* #if %s */\n\n",
9511*38fd1498Szrj CPU_UNITS_QUERY_MACRO_NAME);
9512*38fd1498Szrj output_dfa_clean_insn_cache_func ();
9513*38fd1498Szrj output_dfa_start_func ();
9514*38fd1498Szrj output_dfa_finish_func ();
9515*38fd1498Szrj if (progress_flag)
9516*38fd1498Szrj fprintf (stderr, "done\n");
9517*38fd1498Szrj if (v_flag)
9518*38fd1498Szrj {
9519*38fd1498Szrj output_description_file = fopen (output_description_file_name, "w");
9520*38fd1498Szrj if (output_description_file == NULL)
9521*38fd1498Szrj {
9522*38fd1498Szrj perror (output_description_file_name);
9523*38fd1498Szrj exit (FATAL_EXIT_CODE);
9524*38fd1498Szrj }
9525*38fd1498Szrj if (progress_flag)
9526*38fd1498Szrj fprintf (stderr, "Output automata description...");
9527*38fd1498Szrj output_description ();
9528*38fd1498Szrj output_automaton_descriptions ();
9529*38fd1498Szrj if (progress_flag)
9530*38fd1498Szrj fprintf (stderr, "done\n");
9531*38fd1498Szrj output_statistics (output_description_file);
9532*38fd1498Szrj }
9533*38fd1498Szrj if (stats_flag)
9534*38fd1498Szrj output_statistics (stderr);
9535*38fd1498Szrj ticker_off (&output_time);
9536*38fd1498Szrj if (time_flag)
9537*38fd1498Szrj output_time_statistics (stderr);
9538*38fd1498Szrj finish_states ();
9539*38fd1498Szrj finish_arcs ();
9540*38fd1498Szrj finish_automata_lists ();
9541*38fd1498Szrj if (time_flag)
9542*38fd1498Szrj {
9543*38fd1498Szrj fprintf (stderr, "Summary:\n");
9544*38fd1498Szrj fprintf (stderr, " check time ");
9545*38fd1498Szrj print_active_time (stderr, check_time);
9546*38fd1498Szrj fprintf (stderr, ", generation time ");
9547*38fd1498Szrj print_active_time (stderr, generation_time);
9548*38fd1498Szrj fprintf (stderr, ", all time ");
9549*38fd1498Szrj print_active_time (stderr, all_time);
9550*38fd1498Szrj fprintf (stderr, "\n");
9551*38fd1498Szrj }
9552*38fd1498Szrj /* Finish all work. */
9553*38fd1498Szrj if (output_description_file != NULL)
9554*38fd1498Szrj {
9555*38fd1498Szrj fflush (output_description_file);
9556*38fd1498Szrj if (ferror (stdout) != 0)
9557*38fd1498Szrj fatal ("Error in writing DFA description file %s: %s",
9558*38fd1498Szrj output_description_file_name, xstrerror (errno));
9559*38fd1498Szrj fclose (output_description_file);
9560*38fd1498Szrj }
9561*38fd1498Szrj finish_automaton_decl_table ();
9562*38fd1498Szrj finish_insn_decl_table ();
9563*38fd1498Szrj finish_decl_table ();
9564*38fd1498Szrj obstack_free (&irp, NULL);
9565*38fd1498Szrj if (have_error && output_description_file != NULL)
9566*38fd1498Szrj remove (output_description_file_name);
9567*38fd1498Szrj }
9568*38fd1498Szrj
9569*38fd1498Szrj int
main(int argc,const char ** argv)9570*38fd1498Szrj main (int argc, const char **argv)
9571*38fd1498Szrj {
9572*38fd1498Szrj progname = "genautomata";
9573*38fd1498Szrj
9574*38fd1498Szrj if (!init_rtx_reader_args_cb (argc, argv, parse_automata_opt))
9575*38fd1498Szrj return (FATAL_EXIT_CODE);
9576*38fd1498Szrj
9577*38fd1498Szrj initiate_automaton_gen (argv);
9578*38fd1498Szrj md_rtx_info info;
9579*38fd1498Szrj while (read_md_rtx (&info))
9580*38fd1498Szrj switch (GET_CODE (info.def))
9581*38fd1498Szrj {
9582*38fd1498Szrj case DEFINE_CPU_UNIT:
9583*38fd1498Szrj gen_cpu_unit (&info);
9584*38fd1498Szrj break;
9585*38fd1498Szrj
9586*38fd1498Szrj case DEFINE_QUERY_CPU_UNIT:
9587*38fd1498Szrj gen_query_cpu_unit (&info);
9588*38fd1498Szrj break;
9589*38fd1498Szrj
9590*38fd1498Szrj case DEFINE_BYPASS:
9591*38fd1498Szrj gen_bypass (&info);
9592*38fd1498Szrj break;
9593*38fd1498Szrj
9594*38fd1498Szrj case EXCLUSION_SET:
9595*38fd1498Szrj gen_excl_set (&info);
9596*38fd1498Szrj break;
9597*38fd1498Szrj
9598*38fd1498Szrj case PRESENCE_SET:
9599*38fd1498Szrj gen_presence_set (&info);
9600*38fd1498Szrj break;
9601*38fd1498Szrj
9602*38fd1498Szrj case FINAL_PRESENCE_SET:
9603*38fd1498Szrj gen_final_presence_set (&info);
9604*38fd1498Szrj break;
9605*38fd1498Szrj
9606*38fd1498Szrj case ABSENCE_SET:
9607*38fd1498Szrj gen_absence_set (&info);
9608*38fd1498Szrj break;
9609*38fd1498Szrj
9610*38fd1498Szrj case FINAL_ABSENCE_SET:
9611*38fd1498Szrj gen_final_absence_set (&info);
9612*38fd1498Szrj break;
9613*38fd1498Szrj
9614*38fd1498Szrj case DEFINE_AUTOMATON:
9615*38fd1498Szrj gen_automaton (&info);
9616*38fd1498Szrj break;
9617*38fd1498Szrj
9618*38fd1498Szrj case AUTOMATA_OPTION:
9619*38fd1498Szrj gen_automata_option (&info);
9620*38fd1498Szrj break;
9621*38fd1498Szrj
9622*38fd1498Szrj case DEFINE_RESERVATION:
9623*38fd1498Szrj gen_reserv (&info);
9624*38fd1498Szrj break;
9625*38fd1498Szrj
9626*38fd1498Szrj case DEFINE_INSN_RESERVATION:
9627*38fd1498Szrj gen_insn_reserv (&info);
9628*38fd1498Szrj break;
9629*38fd1498Szrj
9630*38fd1498Szrj default:
9631*38fd1498Szrj break;
9632*38fd1498Szrj }
9633*38fd1498Szrj
9634*38fd1498Szrj if (have_error)
9635*38fd1498Szrj return FATAL_EXIT_CODE;
9636*38fd1498Szrj
9637*38fd1498Szrj if (decls.length () > 0)
9638*38fd1498Szrj {
9639*38fd1498Szrj expand_automata ();
9640*38fd1498Szrj if (!have_error)
9641*38fd1498Szrj {
9642*38fd1498Szrj puts ("/* Generated automatically by the program `genautomata'\n"
9643*38fd1498Szrj " from the machine description file `md'. */\n\n"
9644*38fd1498Szrj "#define IN_TARGET_CODE 1\n"
9645*38fd1498Szrj "#include \"config.h\"\n"
9646*38fd1498Szrj "#include \"system.h\"\n"
9647*38fd1498Szrj "#include \"coretypes.h\"\n"
9648*38fd1498Szrj "#include \"tm.h\"\n"
9649*38fd1498Szrj "#include \"alias.h\"\n"
9650*38fd1498Szrj "#include \"tree.h\"\n"
9651*38fd1498Szrj "#include \"varasm.h\"\n"
9652*38fd1498Szrj "#include \"stor-layout.h\"\n"
9653*38fd1498Szrj "#include \"calls.h\"\n"
9654*38fd1498Szrj "#include \"rtl.h\"\n"
9655*38fd1498Szrj "#include \"memmodel.h\"\n"
9656*38fd1498Szrj "#include \"tm_p.h\"\n"
9657*38fd1498Szrj "#include \"insn-config.h\"\n"
9658*38fd1498Szrj "#include \"recog.h\"\n"
9659*38fd1498Szrj "#include \"regs.h\"\n"
9660*38fd1498Szrj "#include \"output.h\"\n"
9661*38fd1498Szrj "#include \"insn-attr.h\"\n"
9662*38fd1498Szrj "#include \"diagnostic-core.h\"\n"
9663*38fd1498Szrj "#include \"flags.h\"\n"
9664*38fd1498Szrj "#include \"function.h\"\n"
9665*38fd1498Szrj "#include \"emit-rtl.h\"\n");
9666*38fd1498Szrj /* FIXME: emit-rtl.h can go away once crtl is in rtl.h. */
9667*38fd1498Szrj
9668*38fd1498Szrj write_automata ();
9669*38fd1498Szrj }
9670*38fd1498Szrj }
9671*38fd1498Szrj else
9672*38fd1498Szrj {
9673*38fd1498Szrj puts ("/* Generated automatically by the program `genautomata'\n"
9674*38fd1498Szrj " from the machine description file `md'. */\n\n"
9675*38fd1498Szrj "/* There is no automaton, but ISO C forbids empty\n"
9676*38fd1498Szrj " translation units, so include a header file with some\n"
9677*38fd1498Szrj " declarations, and its pre-requisite header file. */\n"
9678*38fd1498Szrj "#include \"config.h\"\n"
9679*38fd1498Szrj "#include \"system.h\"\n");
9680*38fd1498Szrj }
9681*38fd1498Szrj
9682*38fd1498Szrj fflush (stdout);
9683*38fd1498Szrj return (ferror (stdout) != 0 || have_error
9684*38fd1498Szrj ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
9685*38fd1498Szrj }
9686