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