genautomata.c (add_vect): Speedup by using integers as bit-vectors for walking throug...
[gcc.git] / gcc / genautomata.c
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 \f
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 \f
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 \f
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_equivalence_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 *
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
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 *
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
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 *
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 *
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 *
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 *
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
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 **
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 \f
2143
2144 /* The function evaluates hash value (0..UINT_MAX) of string. */
2145 static unsigned
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 \f
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
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
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
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
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
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
2249 finish_automaton_decl_table (void)
2250 {
2251 htab_delete (automaton_decl_table);
2252 }
2253
2254 \f
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
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
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
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
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
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
2348 finish_insn_decl_table (void)
2349 {
2350 htab_delete (insn_decl_table);
2351 }
2352
2353 \f
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
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
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
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
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
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
2449 finish_decl_table (void)
2450 {
2451 htab_delete (decl_table);
2452 }
2453
2454 \f
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
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
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
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
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
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 *
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
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
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
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
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
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
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
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
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
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
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 \f
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
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
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
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
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
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 \f
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 \f
3509
3510 /* Pseudo insn decl which denotes advancing cycle. */
3511 static decl_t advance_cycle_insn_decl;
3512 static 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 \f
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
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
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
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
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
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
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
3670 initiate_alt_states (void)
3671 {
3672 first_free_alt_state = NULL;
3673 }
3674
3675 /* Finishing work with the abstract data. */
3676 static void
3677 finish_alt_states (void)
3678 {
3679 }
3680
3681 \f
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 \f
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 \f
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
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
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
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
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
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
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
4369 initiate_arcs (void)
4370 {
4371 first_free_arc = NULL;
4372 }
4373
4374 /* Finishing work with the abstract data. */
4375 static void
4376 finish_arcs (void)
4377 {
4378 }
4379
4380 \f
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
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
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
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
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
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
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
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
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
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
4523 finish_automata_lists (void)
4524 {
4525 htab_delete (automata_list_table);
4526 }
4527
4528 \f
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
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
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 \f
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
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
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
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
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 \f
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
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
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
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
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
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
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
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 \f
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
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
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
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 \f
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
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
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
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
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 \f
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 \f
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
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
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 \f
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
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
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
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
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
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_equivalence_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 \f
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
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
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
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
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
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
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 \f
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
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 *
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
6990 finish_regexp_representation (void)
6991 {
6992 int length = obstack_object_size (&irp);
6993
6994 obstack_blank_fast (&irp, -length);
6995 }
6996
6997 \f
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 unsigned long vect_mask, comb_vect_mask;
7582
7583 if (vect_length == 0)
7584 abort ();
7585 real_vect_length = tab->automaton->insn_equiv_classes_num;
7586 if (vect [vect_length - 1] == undefined_vect_el_value)
7587 abort ();
7588 /* Form full vector in the table: */
7589 for (i = 0; i < vect_length; i++)
7590 VLA_HWINT (tab->full_vect,
7591 i + tab->automaton->insn_equiv_classes_num * vect_num)
7592 = vect [i];
7593 /* Form comb vector in the table: */
7594 if (VLA_HWINT_LENGTH (tab->comb_vect) != VLA_HWINT_LENGTH (tab->check_vect))
7595 abort ();
7596 comb_vect_start = VLA_HWINT_BEGIN (tab->comb_vect);
7597 comb_vect_els_num = VLA_HWINT_LENGTH (tab->comb_vect);
7598 for (first_unempty_vect_index = 0;
7599 first_unempty_vect_index < vect_length;
7600 first_unempty_vect_index++)
7601 if (vect [first_unempty_vect_index] != undefined_vect_el_value)
7602 break;
7603
7604 /* Search for the place in comb vect for the inserted vect. */
7605
7606 /* Slow case. */
7607 if (vect_length - first_unempty_vect_index >= SIZEOF_LONG * CHAR_BIT)
7608 {
7609 for (comb_vect_index = 0;
7610 comb_vect_index < comb_vect_els_num;
7611 comb_vect_index++)
7612 {
7613 for (vect_index = first_unempty_vect_index;
7614 vect_index < vect_length
7615 && vect_index + comb_vect_index < comb_vect_els_num;
7616 vect_index++)
7617 if (vect [vect_index] != undefined_vect_el_value
7618 && (comb_vect_start [vect_index + comb_vect_index]
7619 != undefined_vect_el_value))
7620 break;
7621 if (vect_index >= vect_length
7622 || vect_index + comb_vect_index >= comb_vect_els_num)
7623 break;
7624 }
7625 goto found;
7626 }
7627
7628 /* Fast case. */
7629 vect_mask = 0;
7630 for (vect_index = first_unempty_vect_index;
7631 vect_index < vect_length;
7632 vect_index++)
7633 {
7634 vect_mask = vect_mask << 1;
7635 if (vect [vect_index] != undefined_vect_el_value)
7636 vect_mask |= 1;
7637 }
7638
7639 /* Search for the place in comb vect for the inserted vect. */
7640 comb_vect_index = 0;
7641 if (comb_vect_els_num == 0)
7642 goto found;
7643
7644 comb_vect_mask = 0;
7645 for (vect_index = first_unempty_vect_index;
7646 vect_index < vect_length && vect_index < comb_vect_els_num;
7647 vect_index++)
7648 {
7649 comb_vect_mask <<= 1;
7650 if (vect_index + comb_vect_index < comb_vect_els_num
7651 && comb_vect_start [vect_index + comb_vect_index]
7652 != undefined_vect_el_value)
7653 comb_vect_mask |= 1;
7654 }
7655 if ((vect_mask & comb_vect_mask) == 0)
7656 goto found;
7657
7658 for (comb_vect_index = 1, i = vect_length; i < comb_vect_els_num;
7659 comb_vect_index++, i++)
7660 {
7661 comb_vect_mask = (comb_vect_mask << 1) | 1;
7662 comb_vect_mask ^= comb_vect_start [i] == undefined_vect_el_value;
7663 if ((vect_mask & comb_vect_mask) == 0)
7664 goto found;
7665 }
7666 for ( ; comb_vect_index < comb_vect_els_num; comb_vect_index++)
7667 {
7668 comb_vect_mask <<= 1;
7669 if ((vect_mask & comb_vect_mask) == 0)
7670 goto found;
7671 }
7672
7673 found:
7674 /* Slot was found. */
7675 additional_els_num = comb_vect_index + real_vect_length - comb_vect_els_num;
7676 if (additional_els_num < 0)
7677 additional_els_num = 0;
7678 /* Expand comb and check vectors. */
7679 vect_el = undefined_vect_el_value;
7680 no_state_value = tab->automaton->achieved_states_num;
7681 while (additional_els_num > 0)
7682 {
7683 VLA_HWINT_ADD (tab->comb_vect, vect_el);
7684 VLA_HWINT_ADD (tab->check_vect, no_state_value);
7685 additional_els_num--;
7686 }
7687 comb_vect_start = VLA_HWINT_BEGIN (tab->comb_vect);
7688 check_vect_start = VLA_HWINT_BEGIN (tab->check_vect);
7689 if (VLA_HWINT_LENGTH (tab->comb_vect)
7690 < (size_t) (comb_vect_index + real_vect_length))
7691 abort ();
7692 /* Fill comb and check vectors. */
7693 for (vect_index = 0; vect_index < vect_length; vect_index++)
7694 if (vect [vect_index] != undefined_vect_el_value)
7695 {
7696 if (comb_vect_start [comb_vect_index + vect_index]
7697 != undefined_vect_el_value)
7698 abort ();
7699 comb_vect_start [comb_vect_index + vect_index] = vect [vect_index];
7700 if (vect [vect_index] < 0)
7701 abort ();
7702 if (tab->max_comb_vect_el_value < vect [vect_index])
7703 tab->max_comb_vect_el_value = vect [vect_index];
7704 if (tab->min_comb_vect_el_value > vect [vect_index])
7705 tab->min_comb_vect_el_value = vect [vect_index];
7706 check_vect_start [comb_vect_index + vect_index] = vect_num;
7707 }
7708 if (tab->max_comb_vect_el_value < undefined_vect_el_value)
7709 tab->max_comb_vect_el_value = undefined_vect_el_value;
7710 if (tab->min_comb_vect_el_value > undefined_vect_el_value)
7711 tab->min_comb_vect_el_value = undefined_vect_el_value;
7712 if (tab->max_base_vect_el_value < comb_vect_index)
7713 tab->max_base_vect_el_value = comb_vect_index;
7714 if (tab->min_base_vect_el_value > comb_vect_index)
7715 tab->min_base_vect_el_value = comb_vect_index;
7716 VLA_HWINT (tab->base_vect, vect_num) = comb_vect_index;
7717 }
7718
7719 /* Return number of out arcs of STATE. */
7720 static int
7721 out_state_arcs_num (state_t state)
7722 {
7723 int result;
7724 arc_t arc;
7725
7726 result = 0;
7727 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
7728 {
7729 if (arc->insn == NULL)
7730 abort ();
7731 if (arc->insn->first_ainsn_with_given_equivalence_num)
7732 result++;
7733 }
7734 return result;
7735 }
7736
7737 /* Compare number of possible transitions from the states. */
7738 static int
7739 compare_transition_els_num (const void *state_ptr_1,
7740 const void *state_ptr_2)
7741 {
7742 int transition_els_num_1;
7743 int transition_els_num_2;
7744
7745 transition_els_num_1 = out_state_arcs_num (*(state_t *) state_ptr_1);
7746 transition_els_num_2 = out_state_arcs_num (*(state_t *) state_ptr_2);
7747 if (transition_els_num_1 < transition_els_num_2)
7748 return 1;
7749 else if (transition_els_num_1 == transition_els_num_2)
7750 return 0;
7751 else
7752 return -1;
7753 }
7754
7755 /* The function adds element EL_VALUE to vector VECT for a table state
7756 x AINSN. */
7757 static void
7758 add_vect_el (vla_hwint_t *vect, ainsn_t ainsn, int el_value)
7759 {
7760 int equiv_class_num;
7761 int vect_index;
7762
7763 if (ainsn == NULL)
7764 abort ();
7765 equiv_class_num = ainsn->insn_equiv_class_num;
7766 for (vect_index = VLA_HWINT_LENGTH (*vect);
7767 vect_index <= equiv_class_num;
7768 vect_index++)
7769 VLA_HWINT_ADD (*vect, undefined_vect_el_value);
7770 VLA_HWINT (*vect, equiv_class_num) = el_value;
7771 }
7772
7773 /* This is for forming vector of states of an automaton. */
7774 static vla_ptr_t output_states_vect;
7775
7776 /* The function is called by function pass_states. The function adds
7777 STATE to `output_states_vect'. */
7778 static void
7779 add_states_vect_el (state_t state)
7780 {
7781 VLA_PTR_ADD (output_states_vect, state);
7782 }
7783
7784 /* Form and output vectors (comb, check, base or full vector)
7785 representing transition table of AUTOMATON. */
7786 static void
7787 output_trans_table (automaton_t automaton)
7788 {
7789 state_t *state_ptr;
7790 arc_t arc;
7791 vla_hwint_t transition_vect;
7792
7793 undefined_vect_el_value = automaton->achieved_states_num;
7794 automaton->trans_table = create_state_ainsn_table (automaton);
7795 /* Create vect of pointers to states ordered by num of transitions
7796 from the state (state with the maximum num is the first). */
7797 VLA_PTR_CREATE (output_states_vect, 1500, "output states vector");
7798 pass_states (automaton, add_states_vect_el);
7799 qsort (VLA_PTR_BEGIN (output_states_vect),
7800 VLA_PTR_LENGTH (output_states_vect),
7801 sizeof (state_t), compare_transition_els_num);
7802 VLA_HWINT_CREATE (transition_vect, 500, "transition vector");
7803 for (state_ptr = VLA_PTR_BEGIN (output_states_vect);
7804 state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
7805 state_ptr++)
7806 {
7807 VLA_HWINT_NULLIFY (transition_vect);
7808 for (arc = first_out_arc (*state_ptr);
7809 arc != NULL;
7810 arc = next_out_arc (arc))
7811 {
7812 if (arc->insn == NULL)
7813 abort ();
7814 if (arc->insn->first_ainsn_with_given_equivalence_num)
7815 add_vect_el (&transition_vect, arc->insn,
7816 arc->to_state->order_state_num);
7817 }
7818 add_vect (automaton->trans_table, (*state_ptr)->order_state_num,
7819 VLA_HWINT_BEGIN (transition_vect),
7820 VLA_HWINT_LENGTH (transition_vect));
7821 }
7822 output_state_ainsn_table
7823 (automaton->trans_table, (char *) "state transitions",
7824 output_trans_full_vect_name, output_trans_comb_vect_name,
7825 output_trans_check_vect_name, output_trans_base_vect_name);
7826 VLA_PTR_DELETE (output_states_vect);
7827 VLA_HWINT_DELETE (transition_vect);
7828 }
7829
7830 /* Form and output vectors (comb, check, base or simple vect)
7831 representing alts number table of AUTOMATON. The table is state x
7832 ainsn -> number of possible alternative reservations by the
7833 ainsn. */
7834 static void
7835 output_state_alts_table (automaton_t automaton)
7836 {
7837 state_t *state_ptr;
7838 arc_t arc;
7839 vla_hwint_t state_alts_vect;
7840
7841 undefined_vect_el_value = 0; /* no alts when transition is not possible */
7842 automaton->state_alts_table = create_state_ainsn_table (automaton);
7843 /* Create vect of pointers to states ordered by num of transitions
7844 from the state (state with the maximum num is the first). */
7845 VLA_PTR_CREATE (output_states_vect, 1500, "output states vector");
7846 pass_states (automaton, add_states_vect_el);
7847 qsort (VLA_PTR_BEGIN (output_states_vect),
7848 VLA_PTR_LENGTH (output_states_vect),
7849 sizeof (state_t), compare_transition_els_num);
7850 /* Create base, comb, and check vectors. */
7851 VLA_HWINT_CREATE (state_alts_vect, 500, "state alts vector");
7852 for (state_ptr = VLA_PTR_BEGIN (output_states_vect);
7853 state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
7854 state_ptr++)
7855 {
7856 VLA_HWINT_NULLIFY (state_alts_vect);
7857 for (arc = first_out_arc (*state_ptr);
7858 arc != NULL;
7859 arc = next_out_arc (arc))
7860 {
7861 if (arc->insn == NULL)
7862 abort ();
7863 if (arc->insn->first_ainsn_with_given_equivalence_num)
7864 add_vect_el (&state_alts_vect, arc->insn, arc->state_alts);
7865 }
7866 add_vect (automaton->state_alts_table, (*state_ptr)->order_state_num,
7867 VLA_HWINT_BEGIN (state_alts_vect),
7868 VLA_HWINT_LENGTH (state_alts_vect));
7869 }
7870 output_state_ainsn_table
7871 (automaton->state_alts_table, (char *) "state insn alternatives",
7872 output_state_alts_full_vect_name, output_state_alts_comb_vect_name,
7873 output_state_alts_check_vect_name, output_state_alts_base_vect_name);
7874 VLA_PTR_DELETE (output_states_vect);
7875 VLA_HWINT_DELETE (state_alts_vect);
7876 }
7877
7878 /* The current number of passing states to find minimal issue delay
7879 value for an ainsn and state. */
7880 static int curr_state_pass_num;
7881
7882 /* This recursive function passes states to find minimal issue delay
7883 value for AINSN. The state being visited is STATE. The function
7884 returns minimal issue delay value for AINSN in STATE or -1 if we
7885 enter into a loop. */
7886 static int
7887 min_issue_delay_pass_states (state_t state, ainsn_t ainsn)
7888 {
7889 arc_t arc;
7890 int min_insn_issue_delay, insn_issue_delay;
7891
7892 if (state->state_pass_num == curr_state_pass_num
7893 || state->min_insn_issue_delay != -1)
7894 /* We've entered into a loop or already have the correct value for
7895 given state and ainsn. */
7896 return state->min_insn_issue_delay;
7897 state->state_pass_num = curr_state_pass_num;
7898 min_insn_issue_delay = -1;
7899 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
7900 if (arc->insn == ainsn)
7901 {
7902 min_insn_issue_delay = 0;
7903 break;
7904 }
7905 else
7906 {
7907 insn_issue_delay = min_issue_delay_pass_states (arc->to_state, ainsn);
7908 if (insn_issue_delay != -1)
7909 {
7910 if (arc->insn->insn_reserv_decl
7911 == DECL_INSN_RESERV (advance_cycle_insn_decl))
7912 insn_issue_delay++;
7913 if (min_insn_issue_delay == -1
7914 || min_insn_issue_delay > insn_issue_delay)
7915 {
7916 min_insn_issue_delay = insn_issue_delay;
7917 if (insn_issue_delay == 0)
7918 break;
7919 }
7920 }
7921 }
7922 return min_insn_issue_delay;
7923 }
7924
7925 /* The function searches minimal issue delay value for AINSN in STATE.
7926 The function can return negative value if we can not issue AINSN. We
7927 will report about it later. */
7928 static int
7929 min_issue_delay (state_t state, ainsn_t ainsn)
7930 {
7931 curr_state_pass_num++;
7932 state->min_insn_issue_delay = min_issue_delay_pass_states (state, ainsn);
7933 return state->min_insn_issue_delay;
7934 }
7935
7936 /* The function initiates code for finding minimal issue delay values.
7937 It should be called only once. */
7938 static void
7939 initiate_min_issue_delay_pass_states (void)
7940 {
7941 curr_state_pass_num = 0;
7942 }
7943
7944 /* Form and output vectors representing minimal issue delay table of
7945 AUTOMATON. The table is state x ainsn -> minimal issue delay of
7946 the ainsn. */
7947 static void
7948 output_min_issue_delay_table (automaton_t automaton)
7949 {
7950 vla_hwint_t min_issue_delay_vect;
7951 vla_hwint_t compressed_min_issue_delay_vect;
7952 vect_el_t min_delay;
7953 ainsn_t ainsn;
7954 state_t *state_ptr;
7955 int i;
7956
7957 /* Create vect of pointers to states ordered by num of transitions
7958 from the state (state with the maximum num is the first). */
7959 VLA_PTR_CREATE (output_states_vect, 1500, "output states vector");
7960 pass_states (automaton, add_states_vect_el);
7961 VLA_HWINT_CREATE (min_issue_delay_vect, 1500, "min issue delay vector");
7962 VLA_HWINT_EXPAND (min_issue_delay_vect,
7963 VLA_HWINT_LENGTH (output_states_vect)
7964 * automaton->insn_equiv_classes_num);
7965 for (i = 0;
7966 i < ((int) VLA_HWINT_LENGTH (output_states_vect)
7967 * automaton->insn_equiv_classes_num);
7968 i++)
7969 VLA_HWINT (min_issue_delay_vect, i) = 0;
7970 automaton->max_min_delay = 0;
7971 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
7972 if (ainsn->first_ainsn_with_given_equivalence_num)
7973 {
7974 for (state_ptr = VLA_PTR_BEGIN (output_states_vect);
7975 state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
7976 state_ptr++)
7977 (*state_ptr)->min_insn_issue_delay = -1;
7978 for (state_ptr = VLA_PTR_BEGIN (output_states_vect);
7979 state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
7980 state_ptr++)
7981 {
7982 min_delay = min_issue_delay (*state_ptr, ainsn);
7983 if (automaton->max_min_delay < min_delay)
7984 automaton->max_min_delay = min_delay;
7985 VLA_HWINT (min_issue_delay_vect,
7986 (*state_ptr)->order_state_num
7987 * automaton->insn_equiv_classes_num
7988 + ainsn->insn_equiv_class_num) = min_delay;
7989 }
7990 }
7991 fprintf (output_file, "/* Vector of min issue delay of insns. */\n");
7992 fprintf (output_file, "static const ");
7993 output_range_type (output_file, 0, automaton->max_min_delay);
7994 fprintf (output_file, " ");
7995 output_min_issue_delay_vect_name (output_file, automaton);
7996 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7997 /* Compress the vector. */
7998 if (automaton->max_min_delay < 2)
7999 automaton->min_issue_delay_table_compression_factor = 8;
8000 else if (automaton->max_min_delay < 4)
8001 automaton->min_issue_delay_table_compression_factor = 4;
8002 else if (automaton->max_min_delay < 16)
8003 automaton->min_issue_delay_table_compression_factor = 2;
8004 else
8005 automaton->min_issue_delay_table_compression_factor = 1;
8006 VLA_HWINT_CREATE (compressed_min_issue_delay_vect, 1500,
8007 "compressed min issue delay vector");
8008 VLA_HWINT_EXPAND (compressed_min_issue_delay_vect,
8009 (VLA_HWINT_LENGTH (min_issue_delay_vect)
8010 + automaton->min_issue_delay_table_compression_factor
8011 - 1)
8012 / automaton->min_issue_delay_table_compression_factor);
8013 for (i = 0;
8014 i < (int) VLA_HWINT_LENGTH (compressed_min_issue_delay_vect);
8015 i++)
8016 VLA_HWINT (compressed_min_issue_delay_vect, i) = 0;
8017 for (i = 0; i < (int) VLA_HWINT_LENGTH (min_issue_delay_vect); i++)
8018 VLA_HWINT (compressed_min_issue_delay_vect,
8019 i / automaton->min_issue_delay_table_compression_factor)
8020 |= (VLA_HWINT (min_issue_delay_vect, i)
8021 << (8 - (i % automaton->min_issue_delay_table_compression_factor
8022 + 1)
8023 * (8 / automaton->min_issue_delay_table_compression_factor)));
8024 output_vect (VLA_HWINT_BEGIN (compressed_min_issue_delay_vect),
8025 VLA_HWINT_LENGTH (compressed_min_issue_delay_vect));
8026 fprintf (output_file, "};\n\n");
8027 VLA_PTR_DELETE (output_states_vect);
8028 VLA_HWINT_DELETE (min_issue_delay_vect);
8029 VLA_HWINT_DELETE (compressed_min_issue_delay_vect);
8030 }
8031
8032 #ifndef NDEBUG
8033 /* Number of states which contains transition only by advancing cpu
8034 cycle. */
8035 static int locked_states_num;
8036 #endif
8037
8038 /* Form and output vector representing the locked states of
8039 AUTOMATON. */
8040 static void
8041 output_dead_lock_vect (automaton_t automaton)
8042 {
8043 state_t *state_ptr;
8044 arc_t arc;
8045 vla_hwint_t dead_lock_vect;
8046
8047 /* Create vect of pointers to states ordered by num of
8048 transitions from the state (state with the maximum num is the
8049 first). */
8050 VLA_PTR_CREATE (output_states_vect, 1500, "output states vector");
8051 pass_states (automaton, add_states_vect_el);
8052 VLA_HWINT_CREATE (dead_lock_vect, 1500, "is dead locked vector");
8053 VLA_HWINT_EXPAND (dead_lock_vect, VLA_HWINT_LENGTH (output_states_vect));
8054 for (state_ptr = VLA_PTR_BEGIN (output_states_vect);
8055 state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
8056 state_ptr++)
8057 {
8058 arc = first_out_arc (*state_ptr);
8059 if (arc == NULL)
8060 abort ();
8061 VLA_HWINT (dead_lock_vect, (*state_ptr)->order_state_num)
8062 = (next_out_arc (arc) == NULL
8063 && (arc->insn->insn_reserv_decl
8064 == DECL_INSN_RESERV (advance_cycle_insn_decl)) ? 1 : 0);
8065 #ifndef NDEBUG
8066 if (VLA_HWINT (dead_lock_vect, (*state_ptr)->order_state_num))
8067 locked_states_num++;
8068 #endif
8069 }
8070 fprintf (output_file, "/* Vector for locked state flags. */\n");
8071 fprintf (output_file, "static const ");
8072 output_range_type (output_file, 0, 1);
8073 fprintf (output_file, " ");
8074 output_dead_lock_vect_name (output_file, automaton);
8075 fprintf (output_file, "[] = {\n");
8076 output_vect (VLA_HWINT_BEGIN (dead_lock_vect),
8077 VLA_HWINT_LENGTH (dead_lock_vect));
8078 fprintf (output_file, "};\n\n");
8079 VLA_HWINT_DELETE (dead_lock_vect);
8080 VLA_PTR_DELETE (output_states_vect);
8081 }
8082
8083 /* Form and output vector representing reserved units of the states of
8084 AUTOMATON. */
8085 static void
8086 output_reserved_units_table (automaton_t automaton)
8087 {
8088 state_t *curr_state_ptr;
8089 vla_hwint_t reserved_units_table;
8090 size_t state_byte_size;
8091 int i;
8092
8093 /* Create vect of pointers to states. */
8094 VLA_PTR_CREATE (output_states_vect, 1500, "output states vector");
8095 pass_states (automaton, add_states_vect_el);
8096 /* Create vector. */
8097 VLA_HWINT_CREATE (reserved_units_table, 1500, "reserved units vector");
8098 state_byte_size = (description->query_units_num + 7) / 8;
8099 VLA_HWINT_EXPAND (reserved_units_table,
8100 VLA_HWINT_LENGTH (output_states_vect) * state_byte_size);
8101 for (i = 0;
8102 i < (int) (VLA_HWINT_LENGTH (output_states_vect) * state_byte_size);
8103 i++)
8104 VLA_HWINT (reserved_units_table, i) = 0;
8105 for (curr_state_ptr = VLA_PTR_BEGIN (output_states_vect);
8106 curr_state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
8107 curr_state_ptr++)
8108 {
8109 for (i = 0; i < description->units_num; i++)
8110 if (units_array [i]->query_p
8111 && first_cycle_unit_presence (*curr_state_ptr, i))
8112 VLA_HWINT (reserved_units_table,
8113 (*curr_state_ptr)->order_state_num * state_byte_size
8114 + units_array [i]->query_num / 8)
8115 += (1 << (units_array [i]->query_num % 8));
8116 }
8117 fprintf (output_file, "/* Vector for reserved units of states. */\n");
8118 fprintf (output_file, "static const ");
8119 output_range_type (output_file, 0, 255);
8120 fprintf (output_file, " ");
8121 output_reserved_units_table_name (output_file, automaton);
8122 fprintf (output_file, "[] = {\n");
8123 output_vect (VLA_HWINT_BEGIN (reserved_units_table),
8124 VLA_HWINT_LENGTH (reserved_units_table));
8125 fprintf (output_file, "};\n\n");
8126 VLA_HWINT_DELETE (reserved_units_table);
8127 VLA_PTR_DELETE (output_states_vect);
8128 }
8129
8130 /* The function outputs all tables representing DFA(s) used for fast
8131 pipeline hazards recognition. */
8132 static void
8133 output_tables (void)
8134 {
8135 automaton_t automaton;
8136
8137 #ifndef NDEBUG
8138 locked_states_num = 0;
8139 #endif
8140 initiate_min_issue_delay_pass_states ();
8141 for (automaton = description->first_automaton;
8142 automaton != NULL;
8143 automaton = automaton->next_automaton)
8144 {
8145 output_translate_vect (automaton);
8146 output_trans_table (automaton);
8147 fprintf (output_file, "\n#if %s\n", AUTOMATON_STATE_ALTS_MACRO_NAME);
8148 output_state_alts_table (automaton);
8149 fprintf (output_file, "\n#endif /* #if %s */\n\n",
8150 AUTOMATON_STATE_ALTS_MACRO_NAME);
8151 output_min_issue_delay_table (automaton);
8152 output_dead_lock_vect (automaton);
8153 fprintf (output_file, "\n#if %s\n\n", CPU_UNITS_QUERY_MACRO_NAME);
8154 output_reserved_units_table (automaton);
8155 fprintf (output_file, "\n#endif /* #if %s */\n\n",
8156 CPU_UNITS_QUERY_MACRO_NAME);
8157 }
8158 fprintf (output_file, "\n#define %s %d\n\n", ADVANCE_CYCLE_VALUE_NAME,
8159 DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
8160 }
8161
8162 /* The function outputs definition and value of PHR interface variable
8163 `max_insn_queue_index'. Its value is not less than maximal queue
8164 length needed for the insn scheduler. */
8165 static void
8166 output_max_insn_queue_index_def (void)
8167 {
8168 int i, max, latency;
8169 decl_t decl;
8170
8171 max = description->max_insn_reserv_cycles;
8172 for (i = 0; i < description->decls_num; i++)
8173 {
8174 decl = description->decls [i];
8175 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
8176 {
8177 latency = DECL_INSN_RESERV (decl)->default_latency;
8178 if (latency > max)
8179 max = latency;
8180 }
8181 else if (decl->mode == dm_bypass)
8182 {
8183 latency = DECL_BYPASS (decl)->latency;
8184 if (latency > max)
8185 max = latency;
8186 }
8187 }
8188 for (i = 0; (1 << i) <= max; i++)
8189 ;
8190 if (i < 0)
8191 abort ();
8192 fprintf (output_file, "\nint max_insn_queue_index = %d;\n\n", (1 << i) - 1);
8193 }
8194
8195
8196 /* The function outputs switch cases for insn reservations using
8197 function *output_automata_list_code. */
8198 static void
8199 output_insn_code_cases (void (*output_automata_list_code)
8200 (automata_list_el_t))
8201 {
8202 decl_t decl, decl2;
8203 int i, j;
8204
8205 for (i = 0; i < description->decls_num; i++)
8206 {
8207 decl = description->decls [i];
8208 if (decl->mode == dm_insn_reserv)
8209 DECL_INSN_RESERV (decl)->processed_p = FALSE;
8210 }
8211 for (i = 0; i < description->decls_num; i++)
8212 {
8213 decl = description->decls [i];
8214 if (decl->mode == dm_insn_reserv
8215 && !DECL_INSN_RESERV (decl)->processed_p)
8216 {
8217 for (j = i; j < description->decls_num; j++)
8218 {
8219 decl2 = description->decls [j];
8220 if (decl2->mode == dm_insn_reserv
8221 && (DECL_INSN_RESERV (decl2)->important_automata_list
8222 == DECL_INSN_RESERV (decl)->important_automata_list))
8223 {
8224 DECL_INSN_RESERV (decl2)->processed_p = TRUE;
8225 fprintf (output_file, " case %d: /* %s */\n",
8226 DECL_INSN_RESERV (decl2)->insn_num,
8227 DECL_INSN_RESERV (decl2)->name);
8228 }
8229 }
8230 (*output_automata_list_code)
8231 (DECL_INSN_RESERV (decl)->important_automata_list);
8232 }
8233 }
8234 }
8235
8236
8237 /* The function outputs a code for evaluation of a minimal delay of
8238 issue of insns which have reservations in given AUTOMATA_LIST. */
8239 static void
8240 output_automata_list_min_issue_delay_code (automata_list_el_t automata_list)
8241 {
8242 automata_list_el_t el;
8243 automaton_t automaton;
8244
8245 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
8246 {
8247 automaton = el->automaton;
8248 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
8249 output_min_issue_delay_vect_name (output_file, automaton);
8250 fprintf (output_file,
8251 (automaton->min_issue_delay_table_compression_factor != 1
8252 ? " [(" : " ["));
8253 output_translate_vect_name (output_file, automaton);
8254 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
8255 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
8256 output_chip_member_name (output_file, automaton);
8257 fprintf (output_file, " * %d", automaton->insn_equiv_classes_num);
8258 if (automaton->min_issue_delay_table_compression_factor == 1)
8259 fprintf (output_file, "];\n");
8260 else
8261 {
8262 fprintf (output_file, ") / %d];\n",
8263 automaton->min_issue_delay_table_compression_factor);
8264 fprintf (output_file, " %s = (%s >> (8 - (",
8265 TEMPORARY_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
8266 output_translate_vect_name (output_file, automaton);
8267 fprintf
8268 (output_file, " [%s] %% %d + 1) * %d)) & %d;\n",
8269 INTERNAL_INSN_CODE_NAME,
8270 automaton->min_issue_delay_table_compression_factor,
8271 8 / automaton->min_issue_delay_table_compression_factor,
8272 (1 << (8 / automaton->min_issue_delay_table_compression_factor))
8273 - 1);
8274 }
8275 if (el == automata_list)
8276 fprintf (output_file, " %s = %s;\n",
8277 RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
8278 else
8279 {
8280 fprintf (output_file, " if (%s > %s)\n",
8281 TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
8282 fprintf (output_file, " %s = %s;\n",
8283 RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
8284 }
8285 }
8286 fprintf (output_file, " break;\n\n");
8287 }
8288
8289 /* Output function `internal_min_issue_delay'. */
8290 static void
8291 output_internal_min_issue_delay_func (void)
8292 {
8293 fprintf (output_file,
8294 "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
8295 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8296 CHIP_NAME, CHIP_PARAMETER_NAME);
8297 fprintf (output_file, "{\n int %s ATTRIBUTE_UNUSED;\n int %s = -1;\n",
8298 TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
8299 fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8300 output_insn_code_cases (output_automata_list_min_issue_delay_code);
8301 fprintf (output_file,
8302 "\n default:\n %s = -1;\n break;\n }\n",
8303 RESULT_VARIABLE_NAME);
8304 fprintf (output_file, " return %s;\n", RESULT_VARIABLE_NAME);
8305 fprintf (output_file, "}\n\n");
8306 }
8307
8308 /* The function outputs a code changing state after issue of insns
8309 which have reservations in given AUTOMATA_LIST. */
8310 static void
8311 output_automata_list_transition_code (automata_list_el_t automata_list)
8312 {
8313 automata_list_el_t el, next_el;
8314
8315 fprintf (output_file, " {\n");
8316 if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
8317 for (el = automata_list;; el = next_el)
8318 {
8319 next_el = el->next_automata_list_el;
8320 if (next_el == NULL)
8321 break;
8322 fprintf (output_file, " ");
8323 output_state_member_type (output_file, el->automaton);
8324 fprintf (output_file, " ");
8325 output_temp_chip_member_name (output_file, el->automaton);
8326 fprintf (output_file, ";\n");
8327 }
8328 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
8329 if (comb_vect_p (el->automaton->trans_table))
8330 {
8331 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
8332 output_trans_base_vect_name (output_file, el->automaton);
8333 fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
8334 output_chip_member_name (output_file, el->automaton);
8335 fprintf (output_file, "] + ");
8336 output_translate_vect_name (output_file, el->automaton);
8337 fprintf (output_file, " [%s];\n", INTERNAL_INSN_CODE_NAME);
8338 fprintf (output_file, " if (");
8339 output_trans_check_vect_name (output_file, el->automaton);
8340 fprintf (output_file, " [%s] != %s->",
8341 TEMPORARY_VARIABLE_NAME, CHIP_PARAMETER_NAME);
8342 output_chip_member_name (output_file, el->automaton);
8343 fprintf (output_file, ")\n");
8344 fprintf (output_file, " return %s (%s, %s);\n",
8345 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8346 CHIP_PARAMETER_NAME);
8347 fprintf (output_file, " else\n");
8348 fprintf (output_file, " ");
8349 if (el->next_automata_list_el != NULL)
8350 output_temp_chip_member_name (output_file, el->automaton);
8351 else
8352 {
8353 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
8354 output_chip_member_name (output_file, el->automaton);
8355 }
8356 fprintf (output_file, " = ");
8357 output_trans_comb_vect_name (output_file, el->automaton);
8358 fprintf (output_file, " [%s];\n", TEMPORARY_VARIABLE_NAME);
8359 }
8360 else
8361 {
8362 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
8363 output_trans_full_vect_name (output_file, el->automaton);
8364 fprintf (output_file, " [");
8365 output_translate_vect_name (output_file, el->automaton);
8366 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
8367 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
8368 output_chip_member_name (output_file, el->automaton);
8369 fprintf (output_file, " * %d];\n",
8370 el->automaton->insn_equiv_classes_num);
8371 fprintf (output_file, " if (%s >= %d)\n",
8372 TEMPORARY_VARIABLE_NAME, el->automaton->achieved_states_num);
8373 fprintf (output_file, " return %s (%s, %s);\n",
8374 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8375 CHIP_PARAMETER_NAME);
8376 fprintf (output_file, " else\n ");
8377 if (el->next_automata_list_el != NULL)
8378 output_temp_chip_member_name (output_file, el->automaton);
8379 else
8380 {
8381 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
8382 output_chip_member_name (output_file, el->automaton);
8383 }
8384 fprintf (output_file, " = %s;\n", TEMPORARY_VARIABLE_NAME);
8385 }
8386 if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
8387 for (el = automata_list;; el = next_el)
8388 {
8389 next_el = el->next_automata_list_el;
8390 if (next_el == NULL)
8391 break;
8392 fprintf (output_file, " %s->", CHIP_PARAMETER_NAME);
8393 output_chip_member_name (output_file, el->automaton);
8394 fprintf (output_file, " = ");
8395 output_temp_chip_member_name (output_file, el->automaton);
8396 fprintf (output_file, ";\n");
8397 }
8398 fprintf (output_file, " return -1;\n");
8399 fprintf (output_file, " }\n");
8400 }
8401
8402 /* Output function `internal_state_transition'. */
8403 static void
8404 output_internal_trans_func (void)
8405 {
8406 fprintf (output_file,
8407 "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
8408 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8409 CHIP_NAME, CHIP_PARAMETER_NAME);
8410 fprintf (output_file, "{\n int %s ATTRIBUTE_UNUSED;\n", TEMPORARY_VARIABLE_NAME);
8411 fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8412 output_insn_code_cases (output_automata_list_transition_code);
8413 fprintf (output_file, "\n default:\n return -1;\n }\n");
8414 fprintf (output_file, "}\n\n");
8415 }
8416
8417 /* Output code
8418
8419 if (insn != 0)
8420 {
8421 insn_code = dfa_insn_code (insn);
8422 if (insn_code > DFA__ADVANCE_CYCLE)
8423 return code;
8424 }
8425 else
8426 insn_code = DFA__ADVANCE_CYCLE;
8427
8428 where insn denotes INSN_NAME, insn_code denotes INSN_CODE_NAME, and
8429 code denotes CODE. */
8430 static void
8431 output_internal_insn_code_evaluation (const char *insn_name,
8432 const char *insn_code_name,
8433 int code)
8434 {
8435 fprintf (output_file, "\n if (%s != 0)\n {\n", insn_name);
8436 fprintf (output_file, " %s = %s (%s);\n", insn_code_name,
8437 DFA_INSN_CODE_FUNC_NAME, insn_name);
8438 fprintf (output_file, " if (%s > %s)\n return %d;\n",
8439 insn_code_name, ADVANCE_CYCLE_VALUE_NAME, code);
8440 fprintf (output_file, " }\n else\n %s = %s;\n\n",
8441 insn_code_name, ADVANCE_CYCLE_VALUE_NAME);
8442 }
8443
8444
8445 /* This function outputs `dfa_insn_code' and its helper function
8446 `dfa_insn_code_enlarge'. */
8447 static void
8448 output_dfa_insn_code_func (void)
8449 {
8450 /* Emacs c-mode gets really confused if there's a { or } in column 0
8451 inside a string, so don't do that. */
8452 fprintf (output_file, "\
8453 static void\n\
8454 dfa_insn_code_enlarge (int uid)\n\
8455 {\n\
8456 int i = %s;\n\
8457 %s = 2 * uid;\n\
8458 %s = xrealloc (%s,\n\
8459 %s * sizeof(int));\n\
8460 for (; i < %s; i++)\n\
8461 %s[i] = -1;\n}\n\n",
8462 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8463 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8464 DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
8465 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8466 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8467 DFA_INSN_CODES_VARIABLE_NAME);
8468 fprintf (output_file, "\
8469 static inline int\n%s (rtx %s)\n\
8470 {\n\
8471 int uid = INSN_UID (%s);\n\
8472 int %s;\n\n",
8473 DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME,
8474 INSN_PARAMETER_NAME, INTERNAL_INSN_CODE_NAME);
8475
8476 fprintf (output_file,
8477 " if (uid >= %s)\n dfa_insn_code_enlarge (uid);\n\n",
8478 DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8479 fprintf (output_file, " %s = %s[uid];\n",
8480 INTERNAL_INSN_CODE_NAME, DFA_INSN_CODES_VARIABLE_NAME);
8481 fprintf (output_file, "\
8482 if (%s < 0)\n\
8483 {\n\
8484 %s = %s (%s);\n\
8485 %s[uid] = %s;\n\
8486 }\n",
8487 INTERNAL_INSN_CODE_NAME,
8488 INTERNAL_INSN_CODE_NAME,
8489 INTERNAL_DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME,
8490 DFA_INSN_CODES_VARIABLE_NAME, INTERNAL_INSN_CODE_NAME);
8491 fprintf (output_file, " return %s;\n}\n\n", INTERNAL_INSN_CODE_NAME);
8492 }
8493
8494 /* The function outputs PHR interface function `state_transition'. */
8495 static void
8496 output_trans_func (void)
8497 {
8498 fprintf (output_file, "int\n%s (%s %s, rtx %s)\n",
8499 TRANSITION_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME,
8500 INSN_PARAMETER_NAME);
8501 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
8502 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8503 INTERNAL_INSN_CODE_NAME, -1);
8504 fprintf (output_file, " return %s (%s, %s);\n}\n\n",
8505 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, STATE_NAME);
8506 }
8507
8508 /* The function outputs a code for evaluation of alternative states
8509 number for insns which have reservations in given AUTOMATA_LIST. */
8510 static void
8511 output_automata_list_state_alts_code (automata_list_el_t automata_list)
8512 {
8513 automata_list_el_t el;
8514 automaton_t automaton;
8515
8516 fprintf (output_file, " {\n");
8517 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
8518 if (comb_vect_p (el->automaton->state_alts_table))
8519 {
8520 fprintf (output_file, " int %s;\n", TEMPORARY_VARIABLE_NAME);
8521 break;
8522 }
8523 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
8524 {
8525 automaton = el->automaton;
8526 if (comb_vect_p (automaton->state_alts_table))
8527 {
8528 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
8529 output_state_alts_base_vect_name (output_file, automaton);
8530 fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
8531 output_chip_member_name (output_file, automaton);
8532 fprintf (output_file, "] + ");
8533 output_translate_vect_name (output_file, automaton);
8534 fprintf (output_file, " [%s];\n", INTERNAL_INSN_CODE_NAME);
8535 fprintf (output_file, " if (");
8536 output_state_alts_check_vect_name (output_file, automaton);
8537 fprintf (output_file, " [%s] != %s->",
8538 TEMPORARY_VARIABLE_NAME, CHIP_PARAMETER_NAME);
8539 output_chip_member_name (output_file, automaton);
8540 fprintf (output_file, ")\n");
8541 fprintf (output_file, " return 0;\n");
8542 fprintf (output_file, " else\n");
8543 fprintf (output_file,
8544 (el == automata_list
8545 ? " %s = " : " %s += "),
8546 RESULT_VARIABLE_NAME);
8547 output_state_alts_comb_vect_name (output_file, automaton);
8548 fprintf (output_file, " [%s];\n", TEMPORARY_VARIABLE_NAME);
8549 }
8550 else
8551 {
8552 fprintf (output_file,
8553 (el == automata_list
8554 ? "\n %s = " : " %s += "),
8555 RESULT_VARIABLE_NAME);
8556 output_state_alts_full_vect_name (output_file, automaton);
8557 fprintf (output_file, " [");
8558 output_translate_vect_name (output_file, automaton);
8559 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
8560 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
8561 output_chip_member_name (output_file, automaton);
8562 fprintf (output_file, " * %d];\n",
8563 automaton->insn_equiv_classes_num);
8564 }
8565 }
8566 fprintf (output_file, " break;\n }\n\n");
8567 }
8568
8569 /* Output function `internal_state_alts'. */
8570 static void
8571 output_internal_state_alts_func (void)
8572 {
8573 fprintf (output_file,
8574 "static int\n%s (int %s, struct %s *%s)\n",
8575 INTERNAL_STATE_ALTS_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8576 CHIP_NAME, CHIP_PARAMETER_NAME);
8577 fprintf (output_file, "{\n int %s;\n", RESULT_VARIABLE_NAME);
8578 fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8579 output_insn_code_cases (output_automata_list_state_alts_code);
8580 fprintf (output_file,
8581 "\n default:\n %s = 0;\n break;\n }\n",
8582 RESULT_VARIABLE_NAME);
8583 fprintf (output_file, " return %s;\n", RESULT_VARIABLE_NAME);
8584 fprintf (output_file, "}\n\n");
8585 }
8586
8587 /* The function outputs PHR interface function `state_alts'. */
8588 static void
8589 output_state_alts_func (void)
8590 {
8591 fprintf (output_file, "int\n%s (%s, %s)\n\t%s %s;\n\trtx %s;\n",
8592 STATE_ALTS_FUNC_NAME, STATE_NAME, INSN_PARAMETER_NAME,
8593 STATE_TYPE_NAME, STATE_NAME, INSN_PARAMETER_NAME);
8594 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
8595 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8596 INTERNAL_INSN_CODE_NAME, 0);
8597 fprintf (output_file, " return %s (%s, %s);\n}\n\n",
8598 INTERNAL_STATE_ALTS_FUNC_NAME, INTERNAL_INSN_CODE_NAME, STATE_NAME);
8599 }
8600
8601 /* Output function `min_issue_delay'. */
8602 static void
8603 output_min_issue_delay_func (void)
8604 {
8605 fprintf (output_file, "int\n%s (%s %s, rtx %s)\n",
8606 MIN_ISSUE_DELAY_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME,
8607 INSN_PARAMETER_NAME);
8608 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
8609 fprintf (output_file, "\n if (%s != 0)\n {\n", INSN_PARAMETER_NAME);
8610 fprintf (output_file, " %s = %s (%s);\n", INTERNAL_INSN_CODE_NAME,
8611 DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME);
8612 fprintf (output_file, " if (%s > %s)\n return 0;\n",
8613 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8614 fprintf (output_file, " }\n else\n %s = %s;\n",
8615 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8616 fprintf (output_file, "\n return %s (%s, %s);\n",
8617 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8618 STATE_NAME);
8619 fprintf (output_file, "}\n\n");
8620 }
8621
8622 /* Output function `internal_dead_lock'. */
8623 static void
8624 output_internal_dead_lock_func (void)
8625 {
8626 automaton_t automaton;
8627
8628 fprintf (output_file, "static int\n%s (struct %s *%s)\n",
8629 INTERNAL_DEAD_LOCK_FUNC_NAME, CHIP_NAME, CHIP_PARAMETER_NAME);
8630 fprintf (output_file, "{\n");
8631 for (automaton = description->first_automaton;
8632 automaton != NULL;
8633 automaton = automaton->next_automaton)
8634 {
8635 fprintf (output_file, " if (");
8636 output_dead_lock_vect_name (output_file, automaton);
8637 fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
8638 output_chip_member_name (output_file, automaton);
8639 fprintf (output_file, "])\n return 1/* TRUE */;\n");
8640 }
8641 fprintf (output_file, " return 0/* FALSE */;\n}\n\n");
8642 }
8643
8644 /* The function outputs PHR interface function `state_dead_lock_p'. */
8645 static void
8646 output_dead_lock_func (void)
8647 {
8648 fprintf (output_file, "int\n%s (%s %s)\n",
8649 DEAD_LOCK_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME);
8650 fprintf (output_file, "{\n return %s (%s);\n}\n\n",
8651 INTERNAL_DEAD_LOCK_FUNC_NAME, STATE_NAME);
8652 }
8653
8654 /* Output function `internal_reset'. */
8655 static void
8656 output_internal_reset_func (void)
8657 {
8658 fprintf (output_file, "static inline void\n%s (struct %s *%s)\n",
8659 INTERNAL_RESET_FUNC_NAME, CHIP_NAME, CHIP_PARAMETER_NAME);
8660 fprintf (output_file, "{\n memset (%s, 0, sizeof (struct %s));\n}\n\n",
8661 CHIP_PARAMETER_NAME, CHIP_NAME);
8662 }
8663
8664 /* The function outputs PHR interface function `state_size'. */
8665 static void
8666 output_size_func (void)
8667 {
8668 fprintf (output_file, "int\n%s (void)\n", SIZE_FUNC_NAME);
8669 fprintf (output_file, "{\n return sizeof (struct %s);\n}\n\n", CHIP_NAME);
8670 }
8671
8672 /* The function outputs PHR interface function `state_reset'. */
8673 static void
8674 output_reset_func (void)
8675 {
8676 fprintf (output_file, "void\n%s (%s %s)\n",
8677 RESET_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME);
8678 fprintf (output_file, "{\n %s (%s);\n}\n\n", INTERNAL_RESET_FUNC_NAME,
8679 STATE_NAME);
8680 }
8681
8682 /* Output function `min_insn_conflict_delay'. */
8683 static void
8684 output_min_insn_conflict_delay_func (void)
8685 {
8686 fprintf (output_file,
8687 "int\n%s (%s %s, rtx %s, rtx %s)\n",
8688 MIN_INSN_CONFLICT_DELAY_FUNC_NAME, STATE_TYPE_NAME,
8689 STATE_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8690 fprintf (output_file, "{\n struct %s %s;\n int %s, %s;\n",
8691 CHIP_NAME, CHIP_NAME, INTERNAL_INSN_CODE_NAME,
8692 INTERNAL_INSN2_CODE_NAME);
8693 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8694 INTERNAL_INSN_CODE_NAME, 0);
8695 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
8696 INTERNAL_INSN2_CODE_NAME, 0);
8697 fprintf (output_file, " memcpy (&%s, %s, sizeof (%s));\n",
8698 CHIP_NAME, STATE_NAME, CHIP_NAME);
8699 fprintf (output_file, " %s (&%s);\n", INTERNAL_RESET_FUNC_NAME, CHIP_NAME);
8700 fprintf (output_file, " if (%s (%s, &%s) > 0)\n abort ();\n",
8701 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME);
8702 fprintf (output_file, " return %s (%s, &%s);\n",
8703 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN2_CODE_NAME,
8704 CHIP_NAME);
8705 fprintf (output_file, "}\n\n");
8706 }
8707
8708 /* Output function `internal_insn_latency'. */
8709 static void
8710 output_internal_insn_latency_func (void)
8711 {
8712 decl_t decl;
8713 struct bypass_decl *bypass;
8714 int i, j, col;
8715 const char *tabletype = "unsigned char";
8716
8717 /* Find the smallest integer type that can hold all the default
8718 latency values. */
8719 for (i = 0; i < description->decls_num; i++)
8720 if (description->decls[i]->mode == dm_insn_reserv)
8721 {
8722 decl = description->decls[i];
8723 if (DECL_INSN_RESERV (decl)->default_latency > UCHAR_MAX
8724 && tabletype[0] != 'i') /* Don't shrink it. */
8725 tabletype = "unsigned short";
8726 if (DECL_INSN_RESERV (decl)->default_latency > USHRT_MAX)
8727 tabletype = "int";
8728 }
8729
8730 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",
8731 INTERNAL_INSN_LATENCY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8732 INTERNAL_INSN2_CODE_NAME, INSN_PARAMETER_NAME,
8733 INSN2_PARAMETER_NAME);
8734 fprintf (output_file, "{\n");
8735
8736 if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8737 {
8738 fputs (" return 0;\n}\n\n", output_file);
8739 return;
8740 }
8741
8742 fprintf (output_file, " static const %s default_latencies[] =\n {",
8743 tabletype);
8744
8745 for (i = 0, j = 0, col = 7; i < description->decls_num; i++)
8746 if (description->decls[i]->mode == dm_insn_reserv
8747 && description->decls[i] != advance_cycle_insn_decl)
8748 {
8749 if ((col = (col+1) % 8) == 0)
8750 fputs ("\n ", output_file);
8751 decl = description->decls[i];
8752 if (j++ != DECL_INSN_RESERV (decl)->insn_num)
8753 abort ();
8754 fprintf (output_file, "% 4d,",
8755 DECL_INSN_RESERV (decl)->default_latency);
8756 }
8757 if (j != DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num)
8758 abort ();
8759 fputs ("\n };\n", output_file);
8760
8761 fprintf (output_file, " if (%s >= %s || %s >= %s)\n return 0;\n",
8762 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8763 INTERNAL_INSN2_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8764
8765 fprintf (output_file, " switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8766 for (i = 0; i < description->decls_num; i++)
8767 if (description->decls[i]->mode == dm_insn_reserv
8768 && DECL_INSN_RESERV (description->decls[i])->bypass_list)
8769 {
8770 decl = description->decls [i];
8771 fprintf (output_file,
8772 " case %d:\n switch (%s)\n {\n",
8773 DECL_INSN_RESERV (decl)->insn_num,
8774 INTERNAL_INSN2_CODE_NAME);
8775 for (bypass = DECL_INSN_RESERV (decl)->bypass_list;
8776 bypass != NULL;
8777 bypass = bypass->next)
8778 {
8779 if (bypass->in_insn_reserv->insn_num
8780 == DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num)
8781 abort ();
8782 fprintf (output_file, " case %d:\n",
8783 bypass->in_insn_reserv->insn_num);
8784 if (bypass->bypass_guard_name == NULL)
8785 fprintf (output_file, " return %d;\n",
8786 bypass->latency);
8787 else
8788 {
8789 fprintf (output_file,
8790 " if (%s (%s, %s))\n",
8791 bypass->bypass_guard_name, INSN_PARAMETER_NAME,
8792 INSN2_PARAMETER_NAME);
8793 fprintf (output_file,
8794 " return %d;\n break;\n",
8795 bypass->latency);
8796 }
8797 }
8798 fputs (" }\n break;\n", output_file);
8799 }
8800
8801 fprintf (output_file, " }\n return default_latencies[%s];\n}\n\n",
8802 INTERNAL_INSN_CODE_NAME);
8803 }
8804
8805 /* The function outputs PHR interface function `insn_latency'. */
8806 static void
8807 output_insn_latency_func (void)
8808 {
8809 fprintf (output_file, "int\n%s (rtx %s, rtx %s)\n",
8810 INSN_LATENCY_FUNC_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8811 fprintf (output_file, "{\n int %s, %s;\n",
8812 INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME);
8813 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8814 INTERNAL_INSN_CODE_NAME, 0);
8815 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
8816 INTERNAL_INSN2_CODE_NAME, 0);
8817 fprintf (output_file, " return %s (%s, %s, %s, %s);\n}\n\n",
8818 INTERNAL_INSN_LATENCY_FUNC_NAME,
8819 INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME,
8820 INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8821 }
8822
8823 /* The function outputs PHR interface function `print_reservation'. */
8824 static void
8825 output_print_reservation_func (void)
8826 {
8827 decl_t decl;
8828 int i, j;
8829
8830 fprintf (output_file,
8831 "void\n%s (FILE *%s, rtx %s ATTRIBUTE_UNUSED)\n{\n",
8832 PRINT_RESERVATION_FUNC_NAME, FILE_PARAMETER_NAME,
8833 INSN_PARAMETER_NAME);
8834
8835 if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8836 {
8837 fprintf (output_file, " fputs (\"%s\", %s);\n}\n\n",
8838 NOTHING_NAME, FILE_PARAMETER_NAME);
8839 return;
8840 }
8841
8842
8843 fputs (" static const char *const reservation_names[] =\n {",
8844 output_file);
8845
8846 for (i = 0, j = 0; i < description->decls_num; i++)
8847 {
8848 decl = description->decls [i];
8849 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
8850 {
8851 if (j++ != DECL_INSN_RESERV (decl)->insn_num)
8852 abort ();
8853 fprintf (output_file, "\n \"%s\",",
8854 regexp_representation (DECL_INSN_RESERV (decl)->regexp));
8855 finish_regexp_representation ();
8856 }
8857 }
8858 if (j != DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num)
8859 abort ();
8860
8861 fprintf (output_file, "\n \"%s\"\n };\n int %s;\n\n",
8862 NOTHING_NAME, INTERNAL_INSN_CODE_NAME);
8863
8864 fprintf (output_file, " if (%s == 0)\n %s = %s;\n",
8865 INSN_PARAMETER_NAME,
8866 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8867 fprintf (output_file, " else\n\
8868 {\n\
8869 %s = %s (%s);\n\
8870 if (%s > %s)\n\
8871 %s = %s;\n\
8872 }\n",
8873 INTERNAL_INSN_CODE_NAME, DFA_INSN_CODE_FUNC_NAME,
8874 INSN_PARAMETER_NAME,
8875 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8876 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8877
8878 fprintf (output_file, " fputs (reservation_names[%s], %s);\n}\n\n",
8879 INTERNAL_INSN_CODE_NAME, FILE_PARAMETER_NAME);
8880 }
8881
8882 /* The following function is used to sort unit declaration by their
8883 names. */
8884 static int
8885 units_cmp (const void *unit1, const void *unit2)
8886 {
8887 const unit_decl_t u1 = *(unit_decl_t *) unit1;
8888 const unit_decl_t u2 = *(unit_decl_t *) unit2;
8889
8890 return strcmp (u1->name, u2->name);
8891 }
8892
8893 /* The following macro value is name of struct containing unit name
8894 and unit code. */
8895 #define NAME_CODE_STRUCT_NAME "name_code"
8896
8897 /* The following macro value is name of table of struct name_code. */
8898 #define NAME_CODE_TABLE_NAME "name_code_table"
8899
8900 /* The following macro values are member names for struct name_code. */
8901 #define NAME_MEMBER_NAME "name"
8902 #define CODE_MEMBER_NAME "code"
8903
8904 /* The following macro values are local variable names for function
8905 `get_cpu_unit_code'. */
8906 #define CMP_VARIABLE_NAME "cmp"
8907 #define LOW_VARIABLE_NAME "l"
8908 #define MIDDLE_VARIABLE_NAME "m"
8909 #define HIGH_VARIABLE_NAME "h"
8910
8911 /* The following function outputs function to obtain internal cpu unit
8912 code by the cpu unit name. */
8913 static void
8914 output_get_cpu_unit_code_func (void)
8915 {
8916 int i;
8917 unit_decl_t *units;
8918
8919 fprintf (output_file, "int\n%s (%s)\n\tconst char *%s;\n",
8920 GET_CPU_UNIT_CODE_FUNC_NAME, CPU_UNIT_NAME_PARAMETER_NAME,
8921 CPU_UNIT_NAME_PARAMETER_NAME);
8922 fprintf (output_file, "{\n struct %s {const char *%s; int %s;};\n",
8923 NAME_CODE_STRUCT_NAME, NAME_MEMBER_NAME, CODE_MEMBER_NAME);
8924 fprintf (output_file, " int %s, %s, %s, %s;\n", CMP_VARIABLE_NAME,
8925 LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8926 fprintf (output_file, " static struct %s %s [] =\n {\n",
8927 NAME_CODE_STRUCT_NAME, NAME_CODE_TABLE_NAME);
8928 units = xmalloc (sizeof (unit_decl_t) * description->units_num);
8929 memcpy (units, units_array, sizeof (unit_decl_t) * description->units_num);
8930 qsort (units, description->units_num, sizeof (unit_decl_t), units_cmp);
8931 for (i = 0; i < description->units_num; i++)
8932 if (units [i]->query_p)
8933 fprintf (output_file, " {\"%s\", %d},\n",
8934 units[i]->name, units[i]->query_num);
8935 fprintf (output_file, " };\n\n");
8936 fprintf (output_file, " /* The following is binary search: */\n");
8937 fprintf (output_file, " %s = 0;\n", LOW_VARIABLE_NAME);
8938 fprintf (output_file, " %s = sizeof (%s) / sizeof (struct %s) - 1;\n",
8939 HIGH_VARIABLE_NAME, NAME_CODE_TABLE_NAME, NAME_CODE_STRUCT_NAME);
8940 fprintf (output_file, " while (%s <= %s)\n {\n",
8941 LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8942 fprintf (output_file, " %s = (%s + %s) / 2;\n",
8943 MIDDLE_VARIABLE_NAME, LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8944 fprintf (output_file, " %s = strcmp (%s, %s [%s].%s);\n",
8945 CMP_VARIABLE_NAME, CPU_UNIT_NAME_PARAMETER_NAME,
8946 NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, NAME_MEMBER_NAME);
8947 fprintf (output_file, " if (%s < 0)\n", CMP_VARIABLE_NAME);
8948 fprintf (output_file, " %s = %s - 1;\n",
8949 HIGH_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
8950 fprintf (output_file, " else if (%s > 0)\n", CMP_VARIABLE_NAME);
8951 fprintf (output_file, " %s = %s + 1;\n",
8952 LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
8953 fprintf (output_file, " else\n");
8954 fprintf (output_file, " return %s [%s].%s;\n }\n",
8955 NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, CODE_MEMBER_NAME);
8956 fprintf (output_file, " return -1;\n}\n\n");
8957 free (units);
8958 }
8959
8960 /* The following function outputs function to check reservation of cpu
8961 unit (its internal code will be passed as the function argument) in
8962 given cpu state. */
8963 static void
8964 output_cpu_unit_reservation_p (void)
8965 {
8966 automaton_t automaton;
8967
8968 fprintf (output_file, "int\n%s (%s, %s)\n\t%s %s;\n\tint %s;\n",
8969 CPU_UNIT_RESERVATION_P_FUNC_NAME, STATE_NAME,
8970 CPU_CODE_PARAMETER_NAME, STATE_TYPE_NAME, STATE_NAME,
8971 CPU_CODE_PARAMETER_NAME);
8972 fprintf (output_file, "{\n if (%s < 0 || %s >= %d)\n abort ();\n",
8973 CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME,
8974 description->query_units_num);
8975 for (automaton = description->first_automaton;
8976 automaton != NULL;
8977 automaton = automaton->next_automaton)
8978 {
8979 fprintf (output_file, " if ((");
8980 output_reserved_units_table_name (output_file, automaton);
8981 fprintf (output_file, " [((struct %s *) %s)->", CHIP_NAME, STATE_NAME);
8982 output_chip_member_name (output_file, automaton);
8983 fprintf (output_file, " * %d + %s / 8] >> (%s %% 8)) & 1)\n",
8984 (description->query_units_num + 7) / 8,
8985 CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME);
8986 fprintf (output_file, " return 1;\n");
8987 }
8988 fprintf (output_file, " return 0;\n}\n\n");
8989 }
8990
8991 /* The function outputs PHR interface function `dfa_clean_insn_cache'. */
8992 static void
8993 output_dfa_clean_insn_cache_func (void)
8994 {
8995 fprintf (output_file,
8996 "void\n%s (void)\n{\n int %s;\n\n",
8997 DFA_CLEAN_INSN_CACHE_FUNC_NAME, I_VARIABLE_NAME);
8998 fprintf (output_file,
8999 " for (%s = 0; %s < %s; %s++)\n %s [%s] = -1;\n}\n\n",
9000 I_VARIABLE_NAME, I_VARIABLE_NAME,
9001 DFA_INSN_CODES_LENGTH_VARIABLE_NAME, I_VARIABLE_NAME,
9002 DFA_INSN_CODES_VARIABLE_NAME, I_VARIABLE_NAME);
9003 }
9004
9005 /* The function outputs PHR interface function `dfa_start'. */
9006 static void
9007 output_dfa_start_func (void)
9008 {
9009 fprintf (output_file,
9010 "void\n%s (void)\n{\n %s = get_max_uid ();\n",
9011 DFA_START_FUNC_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
9012 fprintf (output_file, " %s = xmalloc (%s * sizeof (int));\n",
9013 DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
9014 fprintf (output_file, " %s ();\n}\n\n", DFA_CLEAN_INSN_CACHE_FUNC_NAME);
9015 }
9016
9017 /* The function outputs PHR interface function `dfa_finish'. */
9018 static void
9019 output_dfa_finish_func (void)
9020 {
9021 fprintf (output_file, "void\n%s (void)\n{\n free (%s);\n}\n\n",
9022 DFA_FINISH_FUNC_NAME, DFA_INSN_CODES_VARIABLE_NAME);
9023 }
9024
9025 \f
9026
9027 /* The page contains code for output description file (readable
9028 representation of original description and generated DFA(s). */
9029
9030 /* The function outputs string representation of IR reservation. */
9031 static void
9032 output_regexp (regexp_t regexp)
9033 {
9034 fprintf (output_description_file, "%s", regexp_representation (regexp));
9035 finish_regexp_representation ();
9036 }
9037
9038 /* Output names of units in LIST separated by comma. */
9039 static void
9040 output_unit_set_el_list (unit_set_el_t list)
9041 {
9042 unit_set_el_t el;
9043
9044 for (el = list; el != NULL; el = el->next_unit_set_el)
9045 {
9046 if (el != list)
9047 fprintf (output_description_file, ", ");
9048 fprintf (output_description_file, "%s", el->unit_decl->name);
9049 }
9050 }
9051
9052 /* Output patterns in LIST separated by comma. */
9053 static void
9054 output_pattern_set_el_list (pattern_set_el_t list)
9055 {
9056 pattern_set_el_t el;
9057 int i;
9058
9059 for (el = list; el != NULL; el = el->next_pattern_set_el)
9060 {
9061 if (el != list)
9062 fprintf (output_description_file, ", ");
9063 for (i = 0; i < el->units_num; i++)
9064 fprintf (output_description_file, (i == 0 ? "%s" : " %s"),
9065 el->unit_decls [i]->name);
9066 }
9067 }
9068
9069 /* The function outputs string representation of IR define_reservation
9070 and define_insn_reservation. */
9071 static void
9072 output_description (void)
9073 {
9074 decl_t decl;
9075 int i;
9076
9077 for (i = 0; i < description->decls_num; i++)
9078 {
9079 decl = description->decls [i];
9080 if (decl->mode == dm_unit)
9081 {
9082 if (DECL_UNIT (decl)->excl_list != NULL)
9083 {
9084 fprintf (output_description_file, "unit %s exlusion_set: ",
9085 DECL_UNIT (decl)->name);
9086 output_unit_set_el_list (DECL_UNIT (decl)->excl_list);
9087 fprintf (output_description_file, "\n");
9088 }
9089 if (DECL_UNIT (decl)->presence_list != NULL)
9090 {
9091 fprintf (output_description_file, "unit %s presence_set: ",
9092 DECL_UNIT (decl)->name);
9093 output_pattern_set_el_list (DECL_UNIT (decl)->presence_list);
9094 fprintf (output_description_file, "\n");
9095 }
9096 if (DECL_UNIT (decl)->final_presence_list != NULL)
9097 {
9098 fprintf (output_description_file, "unit %s final_presence_set: ",
9099 DECL_UNIT (decl)->name);
9100 output_pattern_set_el_list
9101 (DECL_UNIT (decl)->final_presence_list);
9102 fprintf (output_description_file, "\n");
9103 }
9104 if (DECL_UNIT (decl)->absence_list != NULL)
9105 {
9106 fprintf (output_description_file, "unit %s absence_set: ",
9107 DECL_UNIT (decl)->name);
9108 output_pattern_set_el_list (DECL_UNIT (decl)->absence_list);
9109 fprintf (output_description_file, "\n");
9110 }
9111 if (DECL_UNIT (decl)->final_absence_list != NULL)
9112 {
9113 fprintf (output_description_file, "unit %s final_absence_set: ",
9114 DECL_UNIT (decl)->name);
9115 output_pattern_set_el_list
9116 (DECL_UNIT (decl)->final_absence_list);
9117 fprintf (output_description_file, "\n");
9118 }
9119 }
9120 }
9121 fprintf (output_description_file, "\n");
9122 for (i = 0; i < description->decls_num; i++)
9123 {
9124 decl = description->decls [i];
9125 if (decl->mode == dm_reserv)
9126 {
9127 fprintf (output_description_file, "reservation %s: ",
9128 DECL_RESERV (decl)->name);
9129 output_regexp (DECL_RESERV (decl)->regexp);
9130 fprintf (output_description_file, "\n");
9131 }
9132 else if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
9133 {
9134 fprintf (output_description_file, "insn reservation %s ",
9135 DECL_INSN_RESERV (decl)->name);
9136 print_rtl (output_description_file,
9137 DECL_INSN_RESERV (decl)->condexp);
9138 fprintf (output_description_file, ": ");
9139 output_regexp (DECL_INSN_RESERV (decl)->regexp);
9140 fprintf (output_description_file, "\n");
9141 }
9142 else if (decl->mode == dm_bypass)
9143 fprintf (output_description_file, "bypass %d %s %s\n",
9144 DECL_BYPASS (decl)->latency,
9145 DECL_BYPASS (decl)->out_insn_name,
9146 DECL_BYPASS (decl)->in_insn_name);
9147 }
9148 fprintf (output_description_file, "\n\f\n");
9149 }
9150
9151 /* The function outputs name of AUTOMATON. */
9152 static void
9153 output_automaton_name (FILE *f, automaton_t automaton)
9154 {
9155 if (automaton->corresponding_automaton_decl == NULL)
9156 fprintf (f, "#%d", automaton->automaton_order_num);
9157 else
9158 fprintf (f, "`%s'", automaton->corresponding_automaton_decl->name);
9159 }
9160
9161 /* Maximal length of line for pretty printing into description
9162 file. */
9163 #define MAX_LINE_LENGTH 70
9164
9165 /* The function outputs units name belonging to AUTOMATON. */
9166 static void
9167 output_automaton_units (automaton_t automaton)
9168 {
9169 decl_t decl;
9170 char *name;
9171 int curr_line_length;
9172 int there_is_an_automaton_unit;
9173 int i;
9174
9175 fprintf (output_description_file, "\n Corresponding units:\n");
9176 fprintf (output_description_file, " ");
9177 curr_line_length = 4;
9178 there_is_an_automaton_unit = 0;
9179 for (i = 0; i < description->decls_num; i++)
9180 {
9181 decl = description->decls [i];
9182 if (decl->mode == dm_unit
9183 && (DECL_UNIT (decl)->corresponding_automaton_num
9184 == automaton->automaton_order_num))
9185 {
9186 there_is_an_automaton_unit = 1;
9187 name = DECL_UNIT (decl)->name;
9188 if (curr_line_length + strlen (name) + 1 > MAX_LINE_LENGTH )
9189 {
9190 curr_line_length = strlen (name) + 4;
9191 fprintf (output_description_file, "\n ");
9192 }
9193 else
9194 {
9195 curr_line_length += strlen (name) + 1;
9196 fprintf (output_description_file, " ");
9197 }
9198 fprintf (output_description_file, "%s", name);
9199 }
9200 }
9201 if (!there_is_an_automaton_unit)
9202 fprintf (output_description_file, "<None>");
9203 fprintf (output_description_file, "\n\n");
9204 }
9205
9206 /* The following variable is used for forming array of all possible cpu unit
9207 reservations described by the current DFA state. */
9208 static vla_ptr_t state_reservs;
9209
9210 /* The function forms `state_reservs' for STATE. */
9211 static void
9212 add_state_reservs (state_t state)
9213 {
9214 alt_state_t curr_alt_state;
9215 reserv_sets_t reservs;
9216
9217 if (state->component_states != NULL)
9218 for (curr_alt_state = state->component_states;
9219 curr_alt_state != NULL;
9220 curr_alt_state = curr_alt_state->next_sorted_alt_state)
9221 add_state_reservs (curr_alt_state->state);
9222 else
9223 {
9224 reservs = state->reservs;
9225 VLA_PTR_ADD (state_reservs, reservs);
9226 }
9227 }
9228
9229 /* The function outputs readable representation of all out arcs of
9230 STATE. */
9231 static void
9232 output_state_arcs (state_t state)
9233 {
9234 arc_t arc;
9235 ainsn_t ainsn;
9236 char *insn_name;
9237 int curr_line_length;
9238
9239 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
9240 {
9241 ainsn = arc->insn;
9242 if (!ainsn->first_insn_with_same_reservs)
9243 abort ();
9244 fprintf (output_description_file, " ");
9245 curr_line_length = 7;
9246 fprintf (output_description_file, "%2d: ", ainsn->insn_equiv_class_num);
9247 do
9248 {
9249 insn_name = ainsn->insn_reserv_decl->name;
9250 if (curr_line_length + strlen (insn_name) > MAX_LINE_LENGTH)
9251 {
9252 if (ainsn != arc->insn)
9253 {
9254 fprintf (output_description_file, ",\n ");
9255 curr_line_length = strlen (insn_name) + 6;
9256 }
9257 else
9258 curr_line_length += strlen (insn_name);
9259 }
9260 else
9261 {
9262 curr_line_length += strlen (insn_name);
9263 if (ainsn != arc->insn)
9264 {
9265 curr_line_length += 2;
9266 fprintf (output_description_file, ", ");
9267 }
9268 }
9269 fprintf (output_description_file, "%s", insn_name);
9270 ainsn = ainsn->next_same_reservs_insn;
9271 }
9272 while (ainsn != NULL);
9273 fprintf (output_description_file, " %d (%d)\n",
9274 arc->to_state->order_state_num, arc->state_alts);
9275 }
9276 fprintf (output_description_file, "\n");
9277 }
9278
9279 /* The following function is used for sorting possible cpu unit
9280 reservation of a DFA state. */
9281 static int
9282 state_reservs_cmp (const void *reservs_ptr_1, const void *reservs_ptr_2)
9283 {
9284 return reserv_sets_cmp (*(reserv_sets_t *) reservs_ptr_1,
9285 *(reserv_sets_t *) reservs_ptr_2);
9286 }
9287
9288 /* The following function is used for sorting possible cpu unit
9289 reservation of a DFA state. */
9290 static void
9291 remove_state_duplicate_reservs (void)
9292 {
9293 reserv_sets_t *reservs_ptr;
9294 reserv_sets_t *last_formed_reservs_ptr;
9295
9296 last_formed_reservs_ptr = NULL;
9297 for (reservs_ptr = VLA_PTR_BEGIN (state_reservs);
9298 reservs_ptr <= (reserv_sets_t *) VLA_PTR_LAST (state_reservs);
9299 reservs_ptr++)
9300 if (last_formed_reservs_ptr == NULL)
9301 last_formed_reservs_ptr = reservs_ptr;
9302 else if (reserv_sets_cmp (*last_formed_reservs_ptr, *reservs_ptr) != 0)
9303 {
9304 ++last_formed_reservs_ptr;
9305 *last_formed_reservs_ptr = *reservs_ptr;
9306 }
9307 VLA_PTR_SHORTEN (state_reservs, reservs_ptr - last_formed_reservs_ptr - 1);
9308 }
9309
9310 /* The following function output readable representation of DFA(s)
9311 state used for fast recognition of pipeline hazards. State is
9312 described by possible (current and scheduled) cpu unit
9313 reservations. */
9314 static void
9315 output_state (state_t state)
9316 {
9317 reserv_sets_t *reservs_ptr;
9318
9319 VLA_PTR_CREATE (state_reservs, 150, "state reservations");
9320 fprintf (output_description_file, " State #%d", state->order_state_num);
9321 fprintf (output_description_file,
9322 state->new_cycle_p ? " (new cycle)\n" : "\n");
9323 add_state_reservs (state);
9324 qsort (VLA_PTR_BEGIN (state_reservs), VLA_PTR_LENGTH (state_reservs),
9325 sizeof (reserv_sets_t), state_reservs_cmp);
9326 remove_state_duplicate_reservs ();
9327 for (reservs_ptr = VLA_PTR_BEGIN (state_reservs);
9328 reservs_ptr <= (reserv_sets_t *) VLA_PTR_LAST (state_reservs);
9329 reservs_ptr++)
9330 {
9331 fprintf (output_description_file, " ");
9332 output_reserv_sets (output_description_file, *reservs_ptr);
9333 fprintf (output_description_file, "\n");
9334 }
9335 fprintf (output_description_file, "\n");
9336 output_state_arcs (state);
9337 VLA_PTR_DELETE (state_reservs);
9338 }
9339
9340 /* The following function output readable representation of
9341 DFAs used for fast recognition of pipeline hazards. */
9342 static void
9343 output_automaton_descriptions (void)
9344 {
9345 automaton_t automaton;
9346
9347 for (automaton = description->first_automaton;
9348 automaton != NULL;
9349 automaton = automaton->next_automaton)
9350 {
9351 fprintf (output_description_file, "\nAutomaton ");
9352 output_automaton_name (output_description_file, automaton);
9353 fprintf (output_description_file, "\n");
9354 output_automaton_units (automaton);
9355 pass_states (automaton, output_state);
9356 }
9357 }
9358
9359 \f
9360
9361 /* The page contains top level function for generation DFA(s) used for
9362 PHR. */
9363
9364 /* The function outputs statistics about work of different phases of
9365 DFA generator. */
9366 static void
9367 output_statistics (FILE *f)
9368 {
9369 automaton_t automaton;
9370 int states_num;
9371 #ifndef NDEBUG
9372 int transition_comb_vect_els = 0;
9373 int transition_full_vect_els = 0;
9374 int state_alts_comb_vect_els = 0;
9375 int state_alts_full_vect_els = 0;
9376 int min_issue_delay_vect_els = 0;
9377 #endif
9378
9379 for (automaton = description->first_automaton;
9380 automaton != NULL;
9381 automaton = automaton->next_automaton)
9382 {
9383 fprintf (f, "\nAutomaton ");
9384 output_automaton_name (f, automaton);
9385 fprintf (f, "\n %5d NDFA states, %5d NDFA arcs\n",
9386 automaton->NDFA_states_num, automaton->NDFA_arcs_num);
9387 fprintf (f, " %5d DFA states, %5d DFA arcs\n",
9388 automaton->DFA_states_num, automaton->DFA_arcs_num);
9389 states_num = automaton->DFA_states_num;
9390 if (!no_minimization_flag)
9391 {
9392 fprintf (f, " %5d minimal DFA states, %5d minimal DFA arcs\n",
9393 automaton->minimal_DFA_states_num,
9394 automaton->minimal_DFA_arcs_num);
9395 states_num = automaton->minimal_DFA_states_num;
9396 }
9397 fprintf (f, " %5d all insns %5d insn equivalence classes\n",
9398 description->insns_num, automaton->insn_equiv_classes_num);
9399 #ifndef NDEBUG
9400 fprintf
9401 (f, "%5ld transition comb vector els, %5ld trans table els: %s\n",
9402 (long) VLA_HWINT_LENGTH (automaton->trans_table->comb_vect),
9403 (long) VLA_HWINT_LENGTH (automaton->trans_table->full_vect),
9404 (comb_vect_p (automaton->trans_table)
9405 ? "use comb vect" : "use simple vect"));
9406 fprintf
9407 (f, "%5ld state alts comb vector els, %5ld state alts table els: %s\n",
9408 (long) VLA_HWINT_LENGTH (automaton->state_alts_table->comb_vect),
9409 (long) VLA_HWINT_LENGTH (automaton->state_alts_table->full_vect),
9410 (comb_vect_p (automaton->state_alts_table)
9411 ? "use comb vect" : "use simple vect"));
9412 fprintf
9413 (f, "%5ld min delay table els, compression factor %d\n",
9414 (long) states_num * automaton->insn_equiv_classes_num,
9415 automaton->min_issue_delay_table_compression_factor);
9416 transition_comb_vect_els
9417 += VLA_HWINT_LENGTH (automaton->trans_table->comb_vect);
9418 transition_full_vect_els
9419 += VLA_HWINT_LENGTH (automaton->trans_table->full_vect);
9420 state_alts_comb_vect_els
9421 += VLA_HWINT_LENGTH (automaton->state_alts_table->comb_vect);
9422 state_alts_full_vect_els
9423 += VLA_HWINT_LENGTH (automaton->state_alts_table->full_vect);
9424 min_issue_delay_vect_els
9425 += states_num * automaton->insn_equiv_classes_num;
9426 #endif
9427 }
9428 #ifndef NDEBUG
9429 fprintf (f, "\n%5d all allocated states, %5d all allocated arcs\n",
9430 allocated_states_num, allocated_arcs_num);
9431 fprintf (f, "%5d all allocated alternative states\n",
9432 allocated_alt_states_num);
9433 fprintf (f, "%5d all transition comb vector els, %5d all trans table els\n",
9434 transition_comb_vect_els, transition_full_vect_els);
9435 fprintf
9436 (f, "%5d all state alts comb vector els, %5d all state alts table els\n",
9437 state_alts_comb_vect_els, state_alts_full_vect_els);
9438 fprintf (f, "%5d all min delay table els\n", min_issue_delay_vect_els);
9439 fprintf (f, "%5d locked states num\n", locked_states_num);
9440 #endif
9441 }
9442
9443 /* The function output times of work of different phases of DFA
9444 generator. */
9445 static void
9446 output_time_statistics (FILE *f)
9447 {
9448 fprintf (f, "\n transformation: ");
9449 print_active_time (f, transform_time);
9450 fprintf (f, (!ndfa_flag ? ", building DFA: " : ", building NDFA: "));
9451 print_active_time (f, NDFA_time);
9452 if (ndfa_flag)
9453 {
9454 fprintf (f, ", NDFA -> DFA: ");
9455 print_active_time (f, NDFA_to_DFA_time);
9456 }
9457 fprintf (f, "\n DFA minimization: ");
9458 print_active_time (f, minimize_time);
9459 fprintf (f, ", making insn equivalence: ");
9460 print_active_time (f, equiv_time);
9461 fprintf (f, "\n all automaton generation: ");
9462 print_active_time (f, automaton_generation_time);
9463 fprintf (f, ", output: ");
9464 print_active_time (f, output_time);
9465 fprintf (f, "\n");
9466 }
9467
9468 /* The function generates DFA (deterministic finite state automaton)
9469 for fast recognition of pipeline hazards. No errors during
9470 checking must be fixed before this function call. */
9471 static void
9472 generate (void)
9473 {
9474 automata_num = split_argument;
9475 if (description->units_num < automata_num)
9476 automata_num = description->units_num;
9477 initiate_states ();
9478 initiate_arcs ();
9479 initiate_automata_lists ();
9480 initiate_pass_states ();
9481 initiate_excl_sets ();
9482 initiate_presence_absence_pattern_sets ();
9483 automaton_generation_time = create_ticker ();
9484 create_automata ();
9485 ticker_off (&automaton_generation_time);
9486 }
9487
9488 \f
9489
9490 /* The following function creates insn attribute whose values are
9491 number alternatives in insn reservations. */
9492 static void
9493 make_insn_alts_attr (void)
9494 {
9495 int i, insn_num;
9496 decl_t decl;
9497 rtx condexp;
9498
9499 condexp = rtx_alloc (COND);
9500 XVEC (condexp, 0) = rtvec_alloc ((description->insns_num - 1) * 2);
9501 XEXP (condexp, 1) = make_numeric_value (0);
9502 for (i = insn_num = 0; i < description->decls_num; i++)
9503 {
9504 decl = description->decls [i];
9505 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
9506 {
9507 XVECEXP (condexp, 0, 2 * insn_num)
9508 = DECL_INSN_RESERV (decl)->condexp;
9509 XVECEXP (condexp, 0, 2 * insn_num + 1)
9510 = make_numeric_value
9511 (DECL_INSN_RESERV (decl)->transformed_regexp->mode != rm_oneof
9512 ? 1 : REGEXP_ONEOF (DECL_INSN_RESERV (decl)
9513 ->transformed_regexp)->regexps_num);
9514 insn_num++;
9515 }
9516 }
9517 if (description->insns_num != insn_num + 1)
9518 abort ();
9519 make_internal_attr (attr_printf (sizeof ("*")
9520 + strlen (INSN_ALTS_FUNC_NAME) + 1,
9521 "*%s", INSN_ALTS_FUNC_NAME),
9522 condexp, ATTR_NONE);
9523 }
9524
9525 \f
9526
9527 /* The following function creates attribute which is order number of
9528 insn in pipeline hazard description translator. */
9529 static void
9530 make_internal_dfa_insn_code_attr (void)
9531 {
9532 int i, insn_num;
9533 decl_t decl;
9534 rtx condexp;
9535
9536 condexp = rtx_alloc (COND);
9537 XVEC (condexp, 0) = rtvec_alloc ((description->insns_num - 1) * 2);
9538 XEXP (condexp, 1)
9539 = make_numeric_value (DECL_INSN_RESERV (advance_cycle_insn_decl)
9540 ->insn_num + 1);
9541 for (i = insn_num = 0; i < description->decls_num; i++)
9542 {
9543 decl = description->decls [i];
9544 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
9545 {
9546 XVECEXP (condexp, 0, 2 * insn_num)
9547 = DECL_INSN_RESERV (decl)->condexp;
9548 XVECEXP (condexp, 0, 2 * insn_num + 1)
9549 = make_numeric_value (DECL_INSN_RESERV (decl)->insn_num);
9550 insn_num++;
9551 }
9552 }
9553 if (description->insns_num != insn_num + 1)
9554 abort ();
9555 make_internal_attr
9556 (attr_printf (sizeof ("*")
9557 + strlen (INTERNAL_DFA_INSN_CODE_FUNC_NAME) + 1,
9558 "*%s", INTERNAL_DFA_INSN_CODE_FUNC_NAME),
9559 condexp, ATTR_STATIC);
9560 }
9561
9562 \f
9563
9564 /* The following function creates attribute which order number of insn
9565 in pipeline hazard description translator. */
9566 static void
9567 make_default_insn_latency_attr (void)
9568 {
9569 int i, insn_num;
9570 decl_t decl;
9571 rtx condexp;
9572
9573 condexp = rtx_alloc (COND);
9574 XVEC (condexp, 0) = rtvec_alloc ((description->insns_num - 1) * 2);
9575 XEXP (condexp, 1) = make_numeric_value (0);
9576 for (i = insn_num = 0; i < description->decls_num; i++)
9577 {
9578 decl = description->decls [i];
9579 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
9580 {
9581 XVECEXP (condexp, 0, 2 * insn_num)
9582 = DECL_INSN_RESERV (decl)->condexp;
9583 XVECEXP (condexp, 0, 2 * insn_num + 1)
9584 = make_numeric_value (DECL_INSN_RESERV (decl)->default_latency);
9585 insn_num++;
9586 }
9587 }
9588 if (description->insns_num != insn_num + 1)
9589 abort ();
9590 make_internal_attr (attr_printf (sizeof ("*")
9591 + strlen (INSN_DEFAULT_LATENCY_FUNC_NAME)
9592 + 1, "*%s", INSN_DEFAULT_LATENCY_FUNC_NAME),
9593 condexp, ATTR_NONE);
9594 }
9595
9596 \f
9597
9598 /* The following function creates attribute which returns 1 if given
9599 output insn has bypassing and 0 otherwise. */
9600 static void
9601 make_bypass_attr (void)
9602 {
9603 int i, bypass_insn;
9604 int bypass_insns_num = 0;
9605 decl_t decl;
9606 rtx result_rtx;
9607
9608 for (i = 0; i < description->decls_num; i++)
9609 {
9610 decl = description->decls [i];
9611 if (decl->mode == dm_insn_reserv
9612 && DECL_INSN_RESERV (decl)->condexp != NULL
9613 && DECL_INSN_RESERV (decl)->bypass_list != NULL)
9614 bypass_insns_num++;
9615 }
9616 if (bypass_insns_num == 0)
9617 result_rtx = make_numeric_value (0);
9618 else
9619 {
9620 result_rtx = rtx_alloc (COND);
9621 XVEC (result_rtx, 0) = rtvec_alloc (bypass_insns_num * 2);
9622 XEXP (result_rtx, 1) = make_numeric_value (0);
9623
9624 for (i = bypass_insn = 0; i < description->decls_num; i++)
9625 {
9626 decl = description->decls [i];
9627 if (decl->mode == dm_insn_reserv
9628 && DECL_INSN_RESERV (decl)->condexp != NULL
9629 && DECL_INSN_RESERV (decl)->bypass_list != NULL)
9630 {
9631 XVECEXP (result_rtx, 0, 2 * bypass_insn)
9632 = DECL_INSN_RESERV (decl)->condexp;
9633 XVECEXP (result_rtx, 0, 2 * bypass_insn + 1)
9634 = make_numeric_value (1);
9635 bypass_insn++;
9636 }
9637 }
9638 }
9639 make_internal_attr (attr_printf (sizeof ("*")
9640 + strlen (BYPASS_P_FUNC_NAME) + 1,
9641 "*%s", BYPASS_P_FUNC_NAME),
9642 result_rtx, ATTR_NONE);
9643 }
9644
9645 \f
9646
9647 /* This page mainly contains top level functions of pipeline hazards
9648 description translator. */
9649
9650 /* The following macro value is suffix of name of description file of
9651 pipeline hazards description translator. */
9652 #define STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX ".dfa"
9653
9654 /* The function returns suffix of given file name. The returned
9655 string can not be changed. */
9656 static const char *
9657 file_name_suffix (const char *file_name)
9658 {
9659 const char *last_period;
9660
9661 for (last_period = NULL; *file_name != '\0'; file_name++)
9662 if (*file_name == '.')
9663 last_period = file_name;
9664 return (last_period == NULL ? file_name : last_period);
9665 }
9666
9667 /* The function returns base name of given file name, i.e. pointer to
9668 first char after last `/' (or `\' for WIN32) in given file name,
9669 given file name itself if the directory name is absent. The
9670 returned string can not be changed. */
9671 static const char *
9672 base_file_name (const char *file_name)
9673 {
9674 int directory_name_length;
9675
9676 directory_name_length = strlen (file_name);
9677 #ifdef WIN32
9678 while (directory_name_length >= 0 && file_name[directory_name_length] != '/'
9679 && file_name[directory_name_length] != '\\')
9680 #else
9681 while (directory_name_length >= 0 && file_name[directory_name_length] != '/')
9682 #endif
9683 directory_name_length--;
9684 return file_name + directory_name_length + 1;
9685 }
9686
9687 /* The following is top level function to initialize the work of
9688 pipeline hazards description translator. */
9689 void
9690 initiate_automaton_gen (int argc, char **argv)
9691 {
9692 const char *base_name;
9693 int i;
9694
9695 ndfa_flag = 0;
9696 split_argument = 0; /* default value */
9697 no_minimization_flag = 0;
9698 time_flag = 0;
9699 v_flag = 0;
9700 w_flag = 0;
9701 progress_flag = 0;
9702 for (i = 2; i < argc; i++)
9703 if (strcmp (argv [i], NO_MINIMIZATION_OPTION) == 0)
9704 no_minimization_flag = 1;
9705 else if (strcmp (argv [i], TIME_OPTION) == 0)
9706 time_flag = 1;
9707 else if (strcmp (argv [i], V_OPTION) == 0)
9708 v_flag = 1;
9709 else if (strcmp (argv [i], W_OPTION) == 0)
9710 w_flag = 1;
9711 else if (strcmp (argv [i], NDFA_OPTION) == 0)
9712 ndfa_flag = 1;
9713 else if (strcmp (argv [i], PROGRESS_OPTION) == 0)
9714 progress_flag = 1;
9715 else if (strcmp (argv [i], "-split") == 0)
9716 {
9717 if (i + 1 >= argc)
9718 fatal ("-split has no argument.");
9719 fatal ("option `-split' has not been implemented yet\n");
9720 /* split_argument = atoi (argument_vect [i + 1]); */
9721 }
9722 VLA_PTR_CREATE (decls, 150, "decls");
9723 /* Initialize IR storage. */
9724 obstack_init (&irp);
9725 initiate_automaton_decl_table ();
9726 initiate_insn_decl_table ();
9727 initiate_decl_table ();
9728 output_file = stdout;
9729 output_description_file = NULL;
9730 base_name = base_file_name (argv[1]);
9731 obstack_grow (&irp, base_name,
9732 strlen (base_name) - strlen (file_name_suffix (base_name)));
9733 obstack_grow (&irp, STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX,
9734 strlen (STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX) + 1);
9735 obstack_1grow (&irp, '\0');
9736 output_description_file_name = obstack_base (&irp);
9737 obstack_finish (&irp);
9738 }
9739
9740 /* The following function checks existence at least one arc marked by
9741 each insn. */
9742 static void
9743 check_automata_insn_issues (void)
9744 {
9745 automaton_t automaton;
9746 ainsn_t ainsn, reserv_ainsn;
9747
9748 for (automaton = description->first_automaton;
9749 automaton != NULL;
9750 automaton = automaton->next_automaton)
9751 {
9752 for (ainsn = automaton->ainsn_list;
9753 ainsn != NULL;
9754 ainsn = ainsn->next_ainsn)
9755 if (ainsn->first_insn_with_same_reservs && !ainsn->arc_exists_p)
9756 {
9757 for (reserv_ainsn = ainsn;
9758 reserv_ainsn != NULL;
9759 reserv_ainsn = reserv_ainsn->next_same_reservs_insn)
9760 if (automaton->corresponding_automaton_decl != NULL)
9761 {
9762 if (!w_flag)
9763 error ("Automaton `%s': Insn `%s' will never be issued",
9764 automaton->corresponding_automaton_decl->name,
9765 reserv_ainsn->insn_reserv_decl->name);
9766 else
9767 warning
9768 ("Automaton `%s': Insn `%s' will never be issued",
9769 automaton->corresponding_automaton_decl->name,
9770 reserv_ainsn->insn_reserv_decl->name);
9771 }
9772 else
9773 {
9774 if (!w_flag)
9775 error ("Insn `%s' will never be issued",
9776 reserv_ainsn->insn_reserv_decl->name);
9777 else
9778 warning ("Insn `%s' will never be issued",
9779 reserv_ainsn->insn_reserv_decl->name);
9780 }
9781 }
9782 }
9783 }
9784
9785 /* The following vla is used for storing pointers to all achieved
9786 states. */
9787 static vla_ptr_t automaton_states;
9788
9789 /* This function is called by function pass_states to add an achieved
9790 STATE. */
9791 static void
9792 add_automaton_state (state_t state)
9793 {
9794 VLA_PTR_ADD (automaton_states, state);
9795 }
9796
9797 /* The following function forms list of important automata (whose
9798 states may be changed after the insn issue) for each insn. */
9799 static void
9800 form_important_insn_automata_lists (void)
9801 {
9802 automaton_t automaton;
9803 state_t *state_ptr;
9804 decl_t decl;
9805 ainsn_t ainsn;
9806 arc_t arc;
9807 int i;
9808
9809 VLA_PTR_CREATE (automaton_states, 1500,
9810 "automaton states for forming important insn automata sets");
9811 /* Mark important ainsns. */
9812 for (automaton = description->first_automaton;
9813 automaton != NULL;
9814 automaton = automaton->next_automaton)
9815 {
9816 VLA_PTR_NULLIFY (automaton_states);
9817 pass_states (automaton, add_automaton_state);
9818 for (state_ptr = VLA_PTR_BEGIN (automaton_states);
9819 state_ptr <= (state_t *) VLA_PTR_LAST (automaton_states);
9820 state_ptr++)
9821 {
9822 for (arc = first_out_arc (*state_ptr);
9823 arc != NULL;
9824 arc = next_out_arc (arc))
9825 if (arc->to_state != *state_ptr)
9826 {
9827 if (!arc->insn->first_insn_with_same_reservs)
9828 abort ();
9829 for (ainsn = arc->insn;
9830 ainsn != NULL;
9831 ainsn = ainsn->next_same_reservs_insn)
9832 ainsn->important_p = TRUE;
9833 }
9834 }
9835 }
9836 VLA_PTR_DELETE (automaton_states);
9837 /* Create automata sets for the insns. */
9838 for (i = 0; i < description->decls_num; i++)
9839 {
9840 decl = description->decls [i];
9841 if (decl->mode == dm_insn_reserv)
9842 {
9843 automata_list_start ();
9844 for (automaton = description->first_automaton;
9845 automaton != NULL;
9846 automaton = automaton->next_automaton)
9847 for (ainsn = automaton->ainsn_list;
9848 ainsn != NULL;
9849 ainsn = ainsn->next_ainsn)
9850 if (ainsn->important_p
9851 && ainsn->insn_reserv_decl == DECL_INSN_RESERV (decl))
9852 {
9853 automata_list_add (automaton);
9854 break;
9855 }
9856 DECL_INSN_RESERV (decl)->important_automata_list
9857 = automata_list_finish ();
9858 }
9859 }
9860 }
9861
9862
9863 /* The following is top level function to generate automat(a,on) for
9864 fast recognition of pipeline hazards. */
9865 void
9866 expand_automata (void)
9867 {
9868 int i;
9869
9870 description = create_node (sizeof (struct description)
9871 /* One entry for cycle advancing insn. */
9872 + sizeof (decl_t) * VLA_PTR_LENGTH (decls));
9873 description->decls_num = VLA_PTR_LENGTH (decls);
9874 description->query_units_num = 0;
9875 for (i = 0; i < description->decls_num; i++)
9876 {
9877 description->decls [i] = VLA_PTR (decls, i);
9878 if (description->decls [i]->mode == dm_unit
9879 && DECL_UNIT (description->decls [i])->query_p)
9880 DECL_UNIT (description->decls [i])->query_num
9881 = description->query_units_num++;
9882 }
9883 all_time = create_ticker ();
9884 check_time = create_ticker ();
9885 if (progress_flag)
9886 fprintf (stderr, "Check description...");
9887 check_all_description ();
9888 if (progress_flag)
9889 fprintf (stderr, "done\n");
9890 ticker_off (&check_time);
9891 generation_time = create_ticker ();
9892 if (!have_error)
9893 {
9894 transform_insn_regexps ();
9895 check_unit_distributions_to_automata ();
9896 }
9897 if (!have_error)
9898 {
9899 generate ();
9900 check_automata_insn_issues ();
9901 }
9902 if (!have_error)
9903 {
9904 form_important_insn_automata_lists ();
9905 if (progress_flag)
9906 fprintf (stderr, "Generation of attributes...");
9907 make_internal_dfa_insn_code_attr ();
9908 make_insn_alts_attr ();
9909 make_default_insn_latency_attr ();
9910 make_bypass_attr ();
9911 if (progress_flag)
9912 fprintf (stderr, "done\n");
9913 }
9914 ticker_off (&generation_time);
9915 ticker_off (&all_time);
9916 if (progress_flag)
9917 fprintf (stderr, "All other genattrtab stuff...");
9918 }
9919
9920 /* The following is top level function to output PHR and to finish
9921 work with pipeline description translator. */
9922 void
9923 write_automata (void)
9924 {
9925 if (progress_flag)
9926 fprintf (stderr, "done\n");
9927 if (have_error)
9928 fatal ("Errors in DFA description");
9929 ticker_on (&all_time);
9930 output_time = create_ticker ();
9931 if (progress_flag)
9932 fprintf (stderr, "Forming and outputting automata tables...");
9933 output_dfa_max_issue_rate ();
9934 output_tables ();
9935 if (progress_flag)
9936 {
9937 fprintf (stderr, "done\n");
9938 fprintf (stderr, "Output functions to work with automata...");
9939 }
9940 output_chip_definitions ();
9941 output_max_insn_queue_index_def ();
9942 output_internal_min_issue_delay_func ();
9943 output_internal_trans_func ();
9944 /* Cache of insn dfa codes: */
9945 fprintf (output_file, "\nstatic int *%s;\n", DFA_INSN_CODES_VARIABLE_NAME);
9946 fprintf (output_file, "\nstatic int %s;\n\n",
9947 DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
9948 output_dfa_insn_code_func ();
9949 output_trans_func ();
9950 fprintf (output_file, "\n#if %s\n\n", AUTOMATON_STATE_ALTS_MACRO_NAME);
9951 output_internal_state_alts_func ();
9952 output_state_alts_func ();
9953 fprintf (output_file, "\n#endif /* #if %s */\n\n",
9954 AUTOMATON_STATE_ALTS_MACRO_NAME);
9955 output_min_issue_delay_func ();
9956 output_internal_dead_lock_func ();
9957 output_dead_lock_func ();
9958 output_size_func ();
9959 output_internal_reset_func ();
9960 output_reset_func ();
9961 output_min_insn_conflict_delay_func ();
9962 output_internal_insn_latency_func ();
9963 output_insn_latency_func ();
9964 output_print_reservation_func ();
9965 /* Output function get_cpu_unit_code. */
9966 fprintf (output_file, "\n#if %s\n\n", CPU_UNITS_QUERY_MACRO_NAME);
9967 output_get_cpu_unit_code_func ();
9968 output_cpu_unit_reservation_p ();
9969 fprintf (output_file, "\n#endif /* #if %s */\n\n",
9970 CPU_UNITS_QUERY_MACRO_NAME);
9971 output_dfa_clean_insn_cache_func ();
9972 output_dfa_start_func ();
9973 output_dfa_finish_func ();
9974 if (progress_flag)
9975 fprintf (stderr, "done\n");
9976 if (v_flag)
9977 {
9978 output_description_file = fopen (output_description_file_name, "w");
9979 if (output_description_file == NULL)
9980 {
9981 perror (output_description_file_name);
9982 exit (FATAL_EXIT_CODE);
9983 }
9984 if (progress_flag)
9985 fprintf (stderr, "Output automata description...");
9986 output_description ();
9987 output_automaton_descriptions ();
9988 if (progress_flag)
9989 fprintf (stderr, "done\n");
9990 output_statistics (output_description_file);
9991 }
9992 output_statistics (stderr);
9993 ticker_off (&output_time);
9994 output_time_statistics (stderr);
9995 finish_states ();
9996 finish_arcs ();
9997 finish_automata_lists ();
9998 if (time_flag)
9999 {
10000 fprintf (stderr, "Summary:\n");
10001 fprintf (stderr, " check time ");
10002 print_active_time (stderr, check_time);
10003 fprintf (stderr, ", generation time ");
10004 print_active_time (stderr, generation_time);
10005 fprintf (stderr, ", all time ");
10006 print_active_time (stderr, all_time);
10007 fprintf (stderr, "\n");
10008 }
10009 /* Finish all work. */
10010 if (output_description_file != NULL)
10011 {
10012 fflush (output_description_file);
10013 if (ferror (stdout) != 0)
10014 fatal ("Error in writing DFA description file %s",
10015 output_description_file_name);
10016 fclose (output_description_file);
10017 }
10018 finish_automaton_decl_table ();
10019 finish_insn_decl_table ();
10020 finish_decl_table ();
10021 obstack_free (&irp, NULL);
10022 if (have_error && output_description_file != NULL)
10023 remove (output_description_file_name);
10024 }