2002-06-05 Eric Christopher <echristo@redhat.com>
[official-gcc.git] / gcc / genautomata.c
blob900cfb610c314c4e4ec10ce911eb12202e9c19e7
1 /* Pipeline hazard description translator.
2 Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
4 Written by Vladimir Makarov <vmakarov@redhat.com>
6 This file is part of GNU CC.
8 GNU CC 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.
13 GNU CC 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.
18 You should have received a copy of the GNU General Public License
19 along with GNU CC; see the file COPYING. If not, write to the Free
20 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
21 02111-1307, USA. */
23 /* References:
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.
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.
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.
38 The current implementation is different from the 2nd article in the
39 following:
41 1. New operator `|' (alternative) is permitted in functional unit
42 reservation which can be treated deterministicly and
43 non-deterministicly.
45 2. Possibility of usage of nondeterministic automata too.
47 3. Possibility to query functional unit reservations for given
48 automaton state.
50 4. Several constructions to describe impossible reservations
51 (`exclusion_set', `presence_set', and `absence_set').
53 5. No reverse automata are generated. Trace instruction scheduling
54 requires this. It can be easily added in the future if we
55 really need this.
57 6. Union of automaton states are not generated yet. It is planned
58 to be implemented. Such feature is needed to make more accurate
59 interlock insn scheduling to get state describing functional
60 unit reservation in a joint CFG point.
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.
68 The translator functions `gen_cpu_unit', `gen_query_cpu_unit',
69 `gen_bypass', `gen_excl_set', `gen_presence_set',
70 `gen_absence_set', `gen_automaton', `gen_automata_option',
71 `gen_reserv', `gen_insn_reserv' are called from file
72 `genattrtab.c'. They transform RTL constructions describing
73 automata in .md file into internal representation convenient for
74 further processing.
76 The translator major function `expand_automata' processes the
77 description internal representation into finite state automaton.
78 It can be divided on:
80 o checking correctness of the automaton pipeline description
81 (major function is `check_all_description').
83 o generating automaton (automata) from the description (major
84 function is `make_automaton').
86 o optional transformation of nondeterministic finite state
87 automata into deterministic ones if the alternative operator
88 `|' is treated nondeterministicly in the description (major
89 function is NDFA_to_DFA).
91 o optional minimization of the finite state automata by merging
92 equivalent automaton states (major function is `minimize_DFA').
94 o forming tables (some as comb vectors) and attributes
95 representing the automata (functions output_..._table).
97 Function `write_automata' outputs the created finite state
98 automaton as different tables and functions which works with the
99 automata to inquire automaton state and to change its state. These
100 function are used by gcc instruction scheduler and may be some
101 other gcc code. */
103 #include "hconfig.h"
104 #include "system.h"
105 #include "rtl.h"
106 #include "obstack.h"
107 #include "errors.h"
109 #include <ctype.h>
110 #include <math.h>
111 #include "hashtab.h"
112 #include "varray.h"
114 #ifdef HAVE_LIMITS_H
115 #include <limits.h>
116 #else
117 #ifndef CHAR_BIT
118 #define CHAR_BIT 8
119 #endif
120 #endif
122 #include "genattrtab.h"
124 #define obstack_chunk_alloc xmalloc
125 #define obstack_chunk_free free
127 /* Positions in machine description file. Now they are not used. But
128 they could be used in the future for better diagnostic messages. */
129 typedef int pos_t;
131 /* The following is element of vector of current (and planned in the
132 future) functional unit reservations. */
133 typedef unsigned HOST_WIDE_INT set_el_t;
135 /* Reservations of function units are represented by value of the following
136 type. */
137 typedef set_el_t *reserv_sets_t;
139 /* The following structure represents variable length array (vla) of
140 pointers and HOST WIDE INTs. We could be use only varray. But we
141 add new lay because we add elements very frequently and this could
142 stress OS allocator when varray is used only. */
143 typedef struct {
144 size_t length; /* current size of vla. */
145 varray_type varray; /* container for vla. */
146 } vla_ptr_t;
148 typedef vla_ptr_t vla_hwint_t;
150 /* The following structure describes a ticker. */
151 struct ticker
153 /* The following member value is time of the ticker creation with
154 taking into account time when the ticker is off. Active time of
155 the ticker is current time minus the value. */
156 int modified_creation_time;
157 /* The following member value is time (incremented by one) when the
158 ticker was off. Zero value means that now the ticker is on. */
159 int incremented_off_time;
162 /* The ticker is represented by the following type. */
163 typedef struct ticker ticker_t;
165 /* The following type describes elements of output vectors. */
166 typedef HOST_WIDE_INT vect_el_t;
168 /* Forward declaration of structures of internal representation of
169 pipeline description based on NDFA. */
171 struct unit_decl;
172 struct bypass_decl;
173 struct result_decl;
174 struct automaton_decl;
175 struct unit_rel_decl;
176 struct reserv_decl;
177 struct insn_reserv_decl;
178 struct decl;
179 struct unit_regexp;
180 struct result_regexp;
181 struct reserv_regexp;
182 struct nothing_regexp;
183 struct sequence_regexp;
184 struct repeat_regexp;
185 struct allof_regexp;
186 struct oneof_regexp;
187 struct regexp;
188 struct description;
189 struct unit_set_el;
190 struct state;
191 struct alt_state;
192 struct arc;
193 struct ainsn;
194 struct automaton;
195 struct state_ainsn_table;
197 /* The following typedefs are for brevity. */
198 typedef struct unit_decl *unit_decl_t;
199 typedef struct decl *decl_t;
200 typedef struct regexp *regexp_t;
201 typedef struct unit_set_el *unit_set_el_t;
202 typedef struct alt_state *alt_state_t;
203 typedef struct state *state_t;
204 typedef struct arc *arc_t;
205 typedef struct ainsn *ainsn_t;
206 typedef struct automaton *automaton_t;
207 typedef struct automata_list_el *automata_list_el_t;
208 typedef struct state_ainsn_table *state_ainsn_table_t;
211 /* Prototypes of functions gen_cpu_unit, gen_query_cpu_unit,
212 gen_bypass, gen_excl_set, gen_presence_set, gen_absence_set,
213 gen_automaton, 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'. */
218 static void *create_node PARAMS ((size_t));
219 static void *copy_node PARAMS ((void *, size_t));
220 static char *check_name PARAMS ((char *, pos_t));
221 static char *next_sep_el PARAMS ((char **, int, int));
222 static int n_sep_els PARAMS ((char *, int, int));
223 static char **get_str_vect PARAMS ((char *, int *, int, int));
224 static regexp_t gen_regexp_el PARAMS ((char *));
225 static regexp_t gen_regexp_repeat PARAMS ((char *));
226 static regexp_t gen_regexp_allof PARAMS ((char *));
227 static regexp_t gen_regexp_oneof PARAMS ((char *));
228 static regexp_t gen_regexp_sequence PARAMS ((char *));
229 static regexp_t gen_regexp PARAMS ((char *));
231 static unsigned string_hash PARAMS ((const char *));
232 static unsigned automaton_decl_hash PARAMS ((const void *));
233 static int automaton_decl_eq_p PARAMS ((const void *,
234 const void *));
235 static decl_t insert_automaton_decl PARAMS ((decl_t));
236 static decl_t find_automaton_decl PARAMS ((char *));
237 static void initiate_automaton_decl_table PARAMS ((void));
238 static void finish_automaton_decl_table PARAMS ((void));
240 static unsigned insn_decl_hash PARAMS ((const void *));
241 static int insn_decl_eq_p PARAMS ((const void *,
242 const void *));
243 static decl_t insert_insn_decl PARAMS ((decl_t));
244 static decl_t find_insn_decl PARAMS ((char *));
245 static void initiate_insn_decl_table PARAMS ((void));
246 static void finish_insn_decl_table PARAMS ((void));
248 static unsigned decl_hash PARAMS ((const void *));
249 static int decl_eq_p PARAMS ((const void *,
250 const void *));
251 static decl_t insert_decl PARAMS ((decl_t));
252 static decl_t find_decl PARAMS ((char *));
253 static void initiate_decl_table PARAMS ((void));
254 static void finish_decl_table PARAMS ((void));
256 static unit_set_el_t process_excls PARAMS ((char **, int, pos_t));
257 static void add_excls PARAMS ((unit_set_el_t, unit_set_el_t,
258 pos_t));
259 static unit_set_el_t process_presence_absence
260 PARAMS ((char **, int, pos_t, int));
261 static void add_presence_absence PARAMS ((unit_set_el_t, unit_set_el_t,
262 pos_t, int));
263 static void process_decls PARAMS ((void));
264 static struct bypass_decl *find_bypass PARAMS ((struct bypass_decl *,
265 struct insn_reserv_decl *));
266 static void check_automaton_usage PARAMS ((void));
267 static regexp_t process_regexp PARAMS ((regexp_t));
268 static void process_regexp_decls PARAMS ((void));
269 static void check_usage PARAMS ((void));
270 static int loop_in_regexp PARAMS ((regexp_t, decl_t));
271 static void check_loops_in_regexps PARAMS ((void));
272 static int process_regexp_cycles PARAMS ((regexp_t, int));
273 static void evaluate_max_reserv_cycles PARAMS ((void));
274 static void check_all_description PARAMS ((void));
276 static ticker_t create_ticker PARAMS ((void));
277 static void ticker_off PARAMS ((ticker_t *));
278 static void ticker_on PARAMS ((ticker_t *));
279 static int active_time PARAMS ((ticker_t));
280 static void print_active_time PARAMS ((FILE *, ticker_t));
282 static void add_advance_cycle_insn_decl PARAMS ((void));
284 static alt_state_t get_free_alt_state PARAMS ((void));
285 static void free_alt_state PARAMS ((alt_state_t));
286 static void free_alt_states PARAMS ((alt_state_t));
287 static int alt_state_cmp PARAMS ((const void *alt_state_ptr_1,
288 const void *alt_state_ptr_2));
289 static alt_state_t uniq_sort_alt_states PARAMS ((alt_state_t));
290 static int alt_states_eq PARAMS ((alt_state_t, alt_state_t));
291 static void initiate_alt_states PARAMS ((void));
292 static void finish_alt_states PARAMS ((void));
294 static reserv_sets_t alloc_empty_reserv_sets PARAMS ((void));
295 static unsigned reserv_sets_hash_value PARAMS ((reserv_sets_t));
296 static int reserv_sets_cmp PARAMS ((reserv_sets_t, reserv_sets_t));
297 static int reserv_sets_eq PARAMS ((reserv_sets_t, reserv_sets_t));
298 static void set_unit_reserv PARAMS ((reserv_sets_t, int, int));
299 static int test_unit_reserv PARAMS ((reserv_sets_t, int, int));
300 static int it_is_empty_reserv_sets PARAMS ((reserv_sets_t))
301 ATTRIBUTE_UNUSED;
302 static int reserv_sets_are_intersected PARAMS ((reserv_sets_t, reserv_sets_t));
303 static void reserv_sets_shift PARAMS ((reserv_sets_t, reserv_sets_t));
304 static void reserv_sets_or PARAMS ((reserv_sets_t, reserv_sets_t,
305 reserv_sets_t));
306 static void reserv_sets_and PARAMS ((reserv_sets_t, reserv_sets_t,
307 reserv_sets_t))
308 ATTRIBUTE_UNUSED;
309 static void output_cycle_reservs PARAMS ((FILE *, reserv_sets_t,
310 int, int));
311 static void output_reserv_sets PARAMS ((FILE *, reserv_sets_t));
312 static state_t get_free_state PARAMS ((int, automaton_t));
313 static void free_state PARAMS ((state_t));
314 static unsigned state_hash PARAMS ((const void *));
315 static int state_eq_p PARAMS ((const void *, const void *));
316 static state_t insert_state PARAMS ((state_t));
317 static void set_state_reserv PARAMS ((state_t, int, int));
318 static int intersected_state_reservs_p PARAMS ((state_t, state_t));
319 static state_t states_union PARAMS ((state_t, state_t));
320 static state_t state_shift PARAMS ((state_t));
321 static void initiate_states PARAMS ((void));
322 static void finish_states PARAMS ((void));
324 static void free_arc PARAMS ((arc_t));
325 static void remove_arc PARAMS ((state_t, arc_t));
326 static arc_t find_arc PARAMS ((state_t, state_t, ainsn_t));
327 static arc_t add_arc PARAMS ((state_t, state_t, ainsn_t, int));
328 static arc_t first_out_arc PARAMS ((state_t));
329 static arc_t next_out_arc PARAMS ((arc_t));
330 static void initiate_arcs PARAMS ((void));
331 static void finish_arcs PARAMS ((void));
333 static automata_list_el_t get_free_automata_list_el PARAMS ((void));
334 static void free_automata_list_el PARAMS ((automata_list_el_t));
335 static void free_automata_list PARAMS ((automata_list_el_t));
336 static unsigned automata_list_hash PARAMS ((const void *));
337 static int automata_list_eq_p PARAMS ((const void *, const void *));
338 static void initiate_automata_lists PARAMS ((void));
339 static void automata_list_start PARAMS ((void));
340 static void automata_list_add PARAMS ((automaton_t));
341 static automata_list_el_t automata_list_finish PARAMS ((void));
342 static void finish_automata_lists PARAMS ((void));
344 static void initiate_excl_sets PARAMS ((void));
345 static reserv_sets_t get_excl_set PARAMS ((reserv_sets_t));
347 static void initiate_presence_absence_sets PARAMS ((void));
348 static reserv_sets_t get_presence_absence_set PARAMS ((reserv_sets_t, int));
350 static regexp_t copy_insn_regexp PARAMS ((regexp_t));
351 static regexp_t transform_1 PARAMS ((regexp_t));
352 static regexp_t transform_2 PARAMS ((regexp_t));
353 static regexp_t transform_3 PARAMS ((regexp_t));
354 static regexp_t regexp_transform_func
355 PARAMS ((regexp_t, regexp_t (*) (regexp_t)));
356 static regexp_t transform_regexp PARAMS ((regexp_t));
357 static void transform_insn_regexps PARAMS ((void));
359 static void process_unit_to_form_the_same_automaton_unit_lists
360 PARAMS ((regexp_t, regexp_t, int));
361 static void form_the_same_automaton_unit_lists_from_regexp PARAMS ((regexp_t));
362 static void form_the_same_automaton_unit_lists PARAMS ((void));
363 static void check_unit_distributions_to_automata PARAMS ((void));
365 static int process_seq_for_forming_states PARAMS ((regexp_t, automaton_t,
366 int));
367 static void finish_forming_alt_state PARAMS ((alt_state_t,
368 automaton_t));
369 static void process_alts_for_forming_states PARAMS ((regexp_t,
370 automaton_t, int));
371 static void create_alt_states PARAMS ((automaton_t));
373 static void form_ainsn_with_same_reservs PARAMS ((automaton_t));
375 static void make_automaton PARAMS ((automaton_t));
376 static void form_arcs_marked_by_insn PARAMS ((state_t));
377 static void create_composed_state PARAMS ((state_t, arc_t, vla_ptr_t *));
378 static void NDFA_to_DFA PARAMS ((automaton_t));
379 static void pass_state_graph PARAMS ((state_t, void (*) (state_t)));
380 static void pass_states PARAMS ((automaton_t,
381 void (*) (state_t)));
382 static void initiate_pass_states PARAMS ((void));
383 static void add_achieved_state PARAMS ((state_t));
384 static int set_out_arc_insns_equiv_num PARAMS ((state_t, int));
385 static void clear_arc_insns_equiv_num PARAMS ((state_t));
386 static void copy_equiv_class PARAMS ((vla_ptr_t *to,
387 const vla_ptr_t *from));
388 static int state_is_differed PARAMS ((state_t, int, int));
389 static state_t init_equiv_class PARAMS ((state_t *states, int));
390 static int partition_equiv_class PARAMS ((state_t *, int,
391 vla_ptr_t *, int *));
392 static void evaluate_equiv_classes PARAMS ((automaton_t, vla_ptr_t *));
393 static void merge_states PARAMS ((automaton_t, vla_ptr_t *));
394 static void set_new_cycle_flags PARAMS ((state_t));
395 static void minimize_DFA PARAMS ((automaton_t));
396 static void incr_states_and_arcs_nums PARAMS ((state_t));
397 static void count_states_and_arcs PARAMS ((automaton_t, int *, int *));
398 static void build_automaton PARAMS ((automaton_t));
400 static void set_order_state_num PARAMS ((state_t));
401 static void enumerate_states PARAMS ((automaton_t));
403 static ainsn_t insert_ainsn_into_equiv_class PARAMS ((ainsn_t, ainsn_t));
404 static void delete_ainsn_from_equiv_class PARAMS ((ainsn_t));
405 static void process_insn_equiv_class PARAMS ((ainsn_t, arc_t *));
406 static void process_state_for_insn_equiv_partition PARAMS ((state_t));
407 static void set_insn_equiv_classes PARAMS ((automaton_t));
409 static double estimate_one_automaton_bound PARAMS ((void));
410 static int compare_max_occ_cycle_nums PARAMS ((const void *,
411 const void *));
412 static void units_to_automata_heuristic_distr PARAMS ((void));
413 static ainsn_t create_ainsns PARAMS ((void));
414 static void units_to_automata_distr PARAMS ((void));
415 static void create_automata PARAMS ((void));
417 static void form_regexp PARAMS ((regexp_t));
418 static const char *regexp_representation PARAMS ((regexp_t));
419 static void finish_regexp_representation PARAMS ((void));
421 static void output_range_type PARAMS ((FILE *, long int, long int));
422 static int longest_path_length PARAMS ((state_t));
423 static void process_state_longest_path_length PARAMS ((state_t));
424 static void output_dfa_max_issue_rate PARAMS ((void));
425 static void output_vect PARAMS ((vect_el_t *, int));
426 static void output_chip_member_name PARAMS ((FILE *, automaton_t));
427 static void output_temp_chip_member_name PARAMS ((FILE *, automaton_t));
428 static void output_translate_vect_name PARAMS ((FILE *, automaton_t));
429 static void output_trans_full_vect_name PARAMS ((FILE *, automaton_t));
430 static void output_trans_comb_vect_name PARAMS ((FILE *, automaton_t));
431 static void output_trans_check_vect_name PARAMS ((FILE *, automaton_t));
432 static void output_trans_base_vect_name PARAMS ((FILE *, automaton_t));
433 static void output_state_alts_full_vect_name PARAMS ((FILE *, automaton_t));
434 static void output_state_alts_comb_vect_name PARAMS ((FILE *, automaton_t));
435 static void output_state_alts_check_vect_name PARAMS ((FILE *, automaton_t));
436 static void output_state_alts_base_vect_name PARAMS ((FILE *, automaton_t));
437 static void output_min_issue_delay_vect_name PARAMS ((FILE *, automaton_t));
438 static void output_dead_lock_vect_name PARAMS ((FILE *, automaton_t));
439 static void output_reserved_units_table_name PARAMS ((FILE *, automaton_t));
440 static void output_state_member_type PARAMS ((FILE *, automaton_t));
441 static void output_chip_definitions PARAMS ((void));
442 static void output_translate_vect PARAMS ((automaton_t));
443 static int comb_vect_p PARAMS ((state_ainsn_table_t));
444 static state_ainsn_table_t create_state_ainsn_table PARAMS ((automaton_t));
445 static void output_state_ainsn_table
446 PARAMS ((state_ainsn_table_t, char *, void (*) (FILE *, automaton_t),
447 void (*) (FILE *, automaton_t), void (*) (FILE *, automaton_t),
448 void (*) (FILE *, automaton_t)));
449 static void add_vect PARAMS ((state_ainsn_table_t,
450 int, vect_el_t *, int));
451 static int out_state_arcs_num PARAMS ((state_t));
452 static int compare_transition_els_num PARAMS ((const void *, const void *));
453 static void add_vect_el PARAMS ((vla_hwint_t *,
454 ainsn_t, int));
455 static void add_states_vect_el PARAMS ((state_t));
456 static void output_trans_table PARAMS ((automaton_t));
457 static void output_state_alts_table PARAMS ((automaton_t));
458 static int min_issue_delay_pass_states PARAMS ((state_t, ainsn_t));
459 static int min_issue_delay PARAMS ((state_t, ainsn_t));
460 static void initiate_min_issue_delay_pass_states PARAMS ((void));
461 static void output_min_issue_delay_table PARAMS ((automaton_t));
462 static void output_dead_lock_vect PARAMS ((automaton_t));
463 static void output_reserved_units_table PARAMS ((automaton_t));
464 static void output_tables PARAMS ((void));
465 static void output_max_insn_queue_index_def PARAMS ((void));
466 static void output_insn_code_cases PARAMS ((void (*) (automata_list_el_t)));
467 static void output_automata_list_min_issue_delay_code PARAMS ((automata_list_el_t));
468 static void output_internal_min_issue_delay_func PARAMS ((void));
469 static void output_automata_list_transition_code PARAMS ((automata_list_el_t));
470 static void output_internal_trans_func PARAMS ((void));
471 static void output_internal_insn_code_evaluation PARAMS ((const char *,
472 const char *, int));
473 static void output_dfa_insn_code_func PARAMS ((void));
474 static void output_trans_func PARAMS ((void));
475 static void output_automata_list_state_alts_code PARAMS ((automata_list_el_t));
476 static void output_internal_state_alts_func PARAMS ((void));
477 static void output_state_alts_func PARAMS ((void));
478 static void output_min_issue_delay_func PARAMS ((void));
479 static void output_internal_dead_lock_func PARAMS ((void));
480 static void output_dead_lock_func PARAMS ((void));
481 static void output_internal_reset_func PARAMS ((void));
482 static void output_size_func PARAMS ((void));
483 static void output_reset_func PARAMS ((void));
484 static void output_min_insn_conflict_delay_func PARAMS ((void));
485 static void output_internal_insn_latency_func PARAMS ((void));
486 static void output_insn_latency_func PARAMS ((void));
487 static void output_print_reservation_func PARAMS ((void));
488 static int units_cmp PARAMS ((const void *,
489 const void *));
490 static void output_get_cpu_unit_code_func PARAMS ((void));
491 static void output_cpu_unit_reservation_p PARAMS ((void));
492 static void output_dfa_start_func PARAMS ((void));
493 static void output_dfa_finish_func PARAMS ((void));
495 static void output_regexp PARAMS ((regexp_t ));
496 static void output_unit_set_el_list PARAMS ((unit_set_el_t));
497 static void output_description PARAMS ((void));
498 static void output_automaton_name PARAMS ((FILE *, automaton_t));
499 static void output_automaton_units PARAMS ((automaton_t));
500 static void add_state_reservs PARAMS ((state_t));
501 static void output_state_arcs PARAMS ((state_t));
502 static int state_reservs_cmp PARAMS ((const void *,
503 const void *));
504 static void remove_state_duplicate_reservs PARAMS ((void));
505 static void output_state PARAMS ((state_t));
506 static void output_automaton_descriptions PARAMS ((void));
507 static void output_statistics PARAMS ((FILE *));
508 static void output_time_statistics PARAMS ((FILE *));
509 static void generate PARAMS ((void));
511 static void make_insn_alts_attr PARAMS ((void));
512 static void make_internal_dfa_insn_code_attr PARAMS ((void));
513 static void make_default_insn_latency_attr PARAMS ((void));
514 static void make_bypass_attr PARAMS ((void));
515 static const char *file_name_suffix PARAMS ((const char *));
516 static const char *base_file_name PARAMS ((const char *));
517 static void check_automata_insn_issues PARAMS ((void));
518 static void add_automaton_state PARAMS ((state_t));
519 static void form_important_insn_automata_lists PARAMS ((void));
521 /* Undefined position. */
522 static pos_t no_pos = 0;
524 /* All IR is stored in the following obstack. */
525 static struct obstack irp;
529 /* This page contains code for work with variable length array (vla)
530 of pointers. We could be use only varray. But we add new lay
531 because we add elements very frequently and this could stress OS
532 allocator when varray is used only. */
534 /* Start work with vla. */
535 #define VLA_PTR_CREATE(vla, allocated_length, name) \
536 do \
538 vla_ptr_t *vla_ptr = &(vla); \
540 VARRAY_GENERIC_PTR_INIT (vla_ptr->varray, allocated_length, name);\
541 vla_ptr->length = 0; \
543 while (0)
545 /* Finish work with the vla. */
546 #define VLA_PTR_DELETE(vla) VARRAY_FREE ((vla).varray)
548 /* Return start address of the vla. */
549 #define VLA_PTR_BEGIN(vla) ((void *) &VARRAY_GENERIC_PTR ((vla).varray, 0))
551 /* Address of the last element of the vla. Do not use side effects in
552 the macro argument. */
553 #define VLA_PTR_LAST(vla) (&VARRAY_GENERIC_PTR ((vla).varray, \
554 (vla).length - 1))
555 /* Nullify the vla. */
556 #define VLA_PTR_NULLIFY(vla) ((vla).length = 0)
558 /* Shorten the vla on given number bytes. */
559 #define VLA_PTR_SHORTEN(vla, n) ((vla).length -= (n))
561 /* Expand the vla on N elements. The values of new elements are
562 undefined. */
563 #define VLA_PTR_EXPAND(vla, n) \
564 do { \
565 vla_ptr_t *expand_vla_ptr = &(vla); \
566 size_t new_length = (n) + expand_vla_ptr->length; \
568 if (VARRAY_SIZE (expand_vla_ptr->varray) < new_length) \
569 VARRAY_GROW (expand_vla_ptr->varray, \
570 (new_length - expand_vla_ptr->length < 128 \
571 ? expand_vla_ptr->length + 128 : new_length)); \
572 expand_vla_ptr->length = new_length; \
573 } while (0)
575 /* Add element to the end of the vla. */
576 #define VLA_PTR_ADD(vla, ptr) \
577 do { \
578 vla_ptr_t *vla_ptr = &(vla); \
580 VLA_PTR_EXPAND (*vla_ptr, 1); \
581 VARRAY_GENERIC_PTR (vla_ptr->varray, vla_ptr->length - 1) = (ptr);\
582 } while (0)
584 /* Length of the vla in elements. */
585 #define VLA_PTR_LENGTH(vla) ((vla).length)
587 /* N-th element of the vla. */
588 #define VLA_PTR(vla, n) VARRAY_GENERIC_PTR ((vla).varray, n)
591 /* The following macros are analogous to the previous ones but for
592 VLAs of HOST WIDE INTs. */
594 #define VLA_HWINT_CREATE(vla, allocated_length, name) \
595 do { \
596 vla_hwint_t *vla_ptr = &(vla); \
598 VARRAY_WIDE_INT_INIT (vla_ptr->varray, allocated_length, name); \
599 vla_ptr->length = 0; \
600 } while (0)
602 #define VLA_HWINT_DELETE(vla) VARRAY_FREE ((vla).varray)
604 #define VLA_HWINT_BEGIN(vla) (&VARRAY_WIDE_INT ((vla).varray, 0))
606 /* Do not use side effects in the macro argument. */
607 #define VLA_HWINT_LAST(vla) (&VARRAY_WIDE_INT ((vla).varray, \
608 (vla).length - 1))
610 #define VLA_HWINT_NULLIFY(vla) ((vla).length = 0)
612 #define VLA_HWINT_SHORTEN(vla, n) ((vla).length -= (n))
614 #define VLA_HWINT_EXPAND(vla, n) \
615 do { \
616 vla_hwint_t *expand_vla_ptr = &(vla); \
617 size_t new_length = (n) + expand_vla_ptr->length; \
619 if (VARRAY_SIZE (expand_vla_ptr->varray) < new_length) \
620 VARRAY_GROW (expand_vla_ptr->varray, \
621 (new_length - expand_vla_ptr->length < 128 \
622 ? expand_vla_ptr->length + 128 : new_length)); \
623 expand_vla_ptr->length = new_length; \
624 } while (0)
626 #define VLA_HWINT_ADD(vla, ptr) \
627 do { \
628 vla_hwint_t *vla_ptr = &(vla); \
630 VLA_HWINT_EXPAND (*vla_ptr, 1); \
631 VARRAY_WIDE_INT (vla_ptr->varray, vla_ptr->length - 1) = (ptr); \
632 } while (0)
634 #define VLA_HWINT_LENGTH(vla) ((vla).length)
636 #define VLA_HWINT(vla, n) VARRAY_WIDE_INT ((vla).varray, n)
640 /* Options with the following names can be set up in automata_option
641 construction. Because the strings occur more one time we use the
642 macros. */
644 #define NO_MINIMIZATION_OPTION "-no-minimization"
646 #define W_OPTION "-w"
648 #define NDFA_OPTION "-ndfa"
650 /* The following flags are set up by function `initiate_automaton_gen'. */
652 /* Make automata with nondeterministic reservation by insns (`-ndfa'). */
653 static int ndfa_flag;
655 /* Do not make minimization of DFA (`-no-minimization'). */
656 static int no_minimization_flag;
658 /* Value of this variable is number of automata being generated. The
659 actual number of automata may be less this value if there is not
660 sufficient number of units. This value is defined by argument of
661 option `-split' or by constructions automaton if the value is zero
662 (it is default value of the argument). */
663 static int split_argument;
665 /* Flag of output time statistics (`-time'). */
666 static int time_flag;
668 /* Flag of creation of description file which contains description of
669 result automaton and statistics information (`-v'). */
670 static int v_flag;
672 /* Flag of generating warning instead of error for non-critical errors
673 (`-w'). */
674 static int w_flag;
677 /* Output file for pipeline hazard recognizer (PHR) being generated.
678 The value is NULL if the file is not defined. */
679 static FILE *output_file;
681 /* Description file of PHR. The value is NULL if the file is not
682 created. */
683 static FILE *output_description_file;
685 /* PHR description file name. */
686 static char *output_description_file_name;
688 /* Value of the following variable is node representing description
689 being processed. This is start point of IR. */
690 static struct description *description;
694 /* This page contains description of IR structure (nodes). */
696 enum decl_mode
698 dm_unit,
699 dm_bypass,
700 dm_automaton,
701 dm_excl,
702 dm_presence,
703 dm_absence,
704 dm_reserv,
705 dm_insn_reserv
708 /* This describes define_cpu_unit and define_query_cpu_unit (see file
709 rtl.def). */
710 struct unit_decl
712 char *name;
713 /* NULL if the automaton name is absent. */
714 char *automaton_name;
715 /* If the following value is not zero, the cpu unit reservation is
716 described in define_query_cpu_unit. */
717 char query_p;
719 /* The following fields are defined by checker. */
721 /* The following field value is nonzero if the unit is used in an
722 regexp. */
723 char unit_is_used;
725 /* The following field value is used to form cyclic lists of units
726 which should be in the same automaton because the unit is
727 reserved not on all alternatives of a regexp on a cycle. */
728 unit_decl_t the_same_automaton_unit;
729 /* The following field is TRUE if we already reported that the unit
730 is not in the same automaton. */
731 int the_same_automaton_message_reported_p;
733 /* The following field value is order number (0, 1, ...) of given
734 unit. */
735 int unit_num;
736 /* The following field value is corresponding declaration of
737 automaton which was given in description. If the field value is
738 NULL then automaton in the unit declaration was absent. */
739 struct automaton_decl *automaton_decl;
740 /* The following field value is maximal cycle number (1, ...) on
741 which given unit occurs in insns. Zero value means that given
742 unit is not used in insns. */
743 int max_occ_cycle_num;
744 /* The following list contains units which conflict with given
745 unit. */
746 unit_set_el_t excl_list;
747 /* The following list contains units which are required to
748 reservation of given unit. */
749 unit_set_el_t presence_list;
750 /* The following list contains units which should be not present in
751 reservation for given unit. */
752 unit_set_el_t absence_list;
753 /* The following is used only when `query_p' has nonzero value.
754 This is query number for the unit. */
755 int query_num;
757 /* The following fields are defined by automaton generator. */
759 /* The following field value is number of the automaton to which
760 given unit belongs. */
761 int corresponding_automaton_num;
764 /* This describes define_bypass (see file rtl.def). */
765 struct bypass_decl
767 int latency;
768 char *out_insn_name;
769 char *in_insn_name;
770 char *bypass_guard_name;
772 /* The following fields are defined by checker. */
774 /* output and input insns of given bypass. */
775 struct insn_reserv_decl *out_insn_reserv;
776 struct insn_reserv_decl *in_insn_reserv;
777 /* The next bypass for given output insn. */
778 struct bypass_decl *next;
781 /* This describes define_automaton (see file rtl.def). */
782 struct automaton_decl
784 char *name;
786 /* The following fields are defined by automaton generator. */
788 /* The following field value is nonzero if the automaton is used in
789 an regexp definition. */
790 char automaton_is_used;
792 /* The following fields are defined by checker. */
794 /* The following field value is the corresponding automaton. This
795 field is not NULL only if the automaton is present in unit
796 declarations and the automatic partition on automata is not
797 used. */
798 automaton_t corresponding_automaton;
801 /* This describes unit relations: exclusion_set, presence_set, or
802 absence_set (see file rtl.def). */
803 struct unit_rel_decl
805 int names_num;
806 int first_list_length;
807 char *names [1];
810 /* This describes define_reservation (see file rtl.def). */
811 struct reserv_decl
813 char *name;
814 regexp_t regexp;
816 /* The following fields are defined by checker. */
818 /* The following field value is nonzero if the unit is used in an
819 regexp. */
820 char reserv_is_used;
821 /* The following field is used to check up cycle in expression
822 definition. */
823 int loop_pass_num;
826 /* This describes define_insn_reservartion (see file rtl.def). */
827 struct insn_reserv_decl
829 rtx condexp;
830 int default_latency;
831 regexp_t regexp;
832 char *name;
834 /* The following fields are defined by checker. */
836 /* The following field value is order number (0, 1, ...) of given
837 insn. */
838 int insn_num;
839 /* The following field value is list of bypasses in which given insn
840 is output insn. */
841 struct bypass_decl *bypass_list;
843 /* The following fields are defined by automaton generator. */
845 /* The following field is the insn regexp transformed that
846 the regexp has not optional regexp, repetition regexp, and an
847 reservation name (i.e. reservation identifiers are changed by the
848 corresponding regexp) and all alternations are the topest level
849 of the regexp. The value can be NULL only if it is special
850 insn `cycle advancing'. */
851 regexp_t transformed_regexp;
852 /* The following field value is list of arcs marked given
853 insn. The field is used in transfromation NDFA -> DFA. */
854 arc_t arcs_marked_by_insn;
855 /* The two following fields are used during minimization of a finite state
856 automaton. */
857 /* The field value is number of equivalence class of state into
858 which arc marked by given insn enters from a state (fixed during
859 an automaton minimization). */
860 int equiv_class_num;
861 /* The field value is state_alts of arc leaving a state (fixed
862 during an automaton minimization) and marked by given insn
863 enters. */
864 int state_alts;
865 /* The following member value is the list to automata which can be
866 changed by the insn issue. */
867 automata_list_el_t important_automata_list;
868 /* The following member is used to process insn once for output. */
869 int processed_p;
872 /* This contains a declaration mentioned above. */
873 struct decl
875 /* What node in the union? */
876 enum decl_mode mode;
877 pos_t pos;
878 union
880 struct unit_decl unit;
881 struct bypass_decl bypass;
882 struct automaton_decl automaton;
883 struct unit_rel_decl excl;
884 struct unit_rel_decl presence;
885 struct unit_rel_decl absence;
886 struct reserv_decl reserv;
887 struct insn_reserv_decl insn_reserv;
888 } decl;
891 /* The following structures represent parsed reservation strings. */
892 enum regexp_mode
894 rm_unit,
895 rm_reserv,
896 rm_nothing,
897 rm_sequence,
898 rm_repeat,
899 rm_allof,
900 rm_oneof
903 /* Cpu unit in reservation. */
904 struct unit_regexp
906 char *name;
907 unit_decl_t unit_decl;
910 /* Define_reservation in a reservation. */
911 struct reserv_regexp
913 char *name;
914 struct reserv_decl *reserv_decl;
917 /* Absence of reservation (represented by string `nothing'). */
918 struct nothing_regexp
920 /* This used to be empty but ISO C doesn't allow that. */
921 char unused;
924 /* Representation of reservations separated by ',' (see file
925 rtl.def). */
926 struct sequence_regexp
928 int regexps_num;
929 regexp_t regexps [1];
932 /* Representation of construction `repeat' (see file rtl.def). */
933 struct repeat_regexp
935 int repeat_num;
936 regexp_t regexp;
939 /* Representation of reservations separated by '+' (see file
940 rtl.def). */
941 struct allof_regexp
943 int regexps_num;
944 regexp_t regexps [1];
947 /* Representation of reservations separated by '|' (see file
948 rtl.def). */
949 struct oneof_regexp
951 int regexps_num;
952 regexp_t regexps [1];
955 /* Representation of a reservation string. */
956 struct regexp
958 /* What node in the union? */
959 enum regexp_mode mode;
960 pos_t pos;
961 union
963 struct unit_regexp unit;
964 struct reserv_regexp reserv;
965 struct nothing_regexp nothing;
966 struct sequence_regexp sequence;
967 struct repeat_regexp repeat;
968 struct allof_regexp allof;
969 struct oneof_regexp oneof;
970 } regexp;
973 /* Reperesents description of pipeline hazard description based on
974 NDFA. */
975 struct description
977 int decls_num;
979 /* The following fields are defined by checker. */
981 /* The following fields values are correspondingly number of all
982 units, query units, and insns in the description. */
983 int units_num;
984 int query_units_num;
985 int insns_num;
986 /* The following field value is max length (in cycles) of
987 reservations of insns. The field value is defined only for
988 correct programs. */
989 int max_insn_reserv_cycles;
991 /* The following fields are defined by automaton generator. */
993 /* The following field value is the first automaton. */
994 automaton_t first_automaton;
996 /* The following field is created by pipeline hazard parser and
997 contains all declarations. We allocate additional entry for
998 special insn "cycle advancing" which is added by the automaton
999 generator. */
1000 decl_t decls [1];
1005 /* The following nodes are created in automaton checker. */
1007 /* The following nodes represent exclusion, presence, absence set for
1008 cpu units. Each element are accessed through only one excl_list,
1009 presence_list, absence_list. */
1010 struct unit_set_el
1012 unit_decl_t unit_decl;
1013 unit_set_el_t next_unit_set_el;
1018 /* The following nodes are created in automaton generator. */
1020 /* The following node type describes state automaton. The state may
1021 be deterministic or non-deterministic. Non-deterministic state has
1022 several component states which represent alternative cpu units
1023 reservations. The state also is used for describing a
1024 deterministic reservation of automaton insn. */
1025 struct state
1027 /* The following member value is nonzero if there is a transition by
1028 cycle advancing. */
1029 int new_cycle_p;
1030 /* The following field is list of processor unit reservations on
1031 each cycle. */
1032 reserv_sets_t reservs;
1033 /* The following field is unique number of given state between other
1034 states. */
1035 int unique_num;
1036 /* The following field value is automaton to which given state
1037 belongs. */
1038 automaton_t automaton;
1039 /* The following field value is the first arc output from given
1040 state. */
1041 arc_t first_out_arc;
1042 /* The following field is used to form NDFA. */
1043 char it_was_placed_in_stack_for_NDFA_forming;
1044 /* The following field is used to form DFA. */
1045 char it_was_placed_in_stack_for_DFA_forming;
1046 /* The following field is used to transform NDFA to DFA. The field
1047 value is not NULL if the state is a compound state. In this case
1048 the value of field `unit_sets_list' is NULL. All states in the
1049 list are in the hash table. The list is formed through field
1050 `next_sorted_alt_state'. */
1051 alt_state_t component_states;
1052 /* The following field is used for passing graph of states. */
1053 int pass_num;
1054 /* The list of states belonging to one equivalence class is formed
1055 with the aid of the following field. */
1056 state_t next_equiv_class_state;
1057 /* The two following fields are used during minimization of a finite
1058 state automaton. */
1059 int equiv_class_num_1, equiv_class_num_2;
1060 /* The following field is used during minimization of a finite state
1061 automaton. The field value is state corresponding to equivalence
1062 class to which given state belongs. */
1063 state_t equiv_class_state;
1064 /* The following field value is the order number of given state.
1065 The states in final DFA is enumerated with the aid of the
1066 following field. */
1067 int order_state_num;
1068 /* This member is used for passing states for searching minimal
1069 delay time. */
1070 int state_pass_num;
1071 /* The following member is used to evaluate min issue delay of insn
1072 for a state. */
1073 int min_insn_issue_delay;
1074 /* The following member is used to evaluate max issue rate of the
1075 processor. The value of the member is maximal length of the path
1076 from given state no containing arcs marked by special insn `cycle
1077 advancing'. */
1078 int longest_path_length;
1081 /* The following macro is an initial value of member
1082 `longest_path_length' of a state. */
1083 #define UNDEFINED_LONGEST_PATH_LENGTH -1
1085 /* Automaton arc. */
1086 struct arc
1088 /* The following field refers for the state into which given arc
1089 enters. */
1090 state_t to_state;
1091 /* The following field describes that the insn issue (with cycle
1092 advancing for special insn `cycle advancing' and without cycle
1093 advancing for others) makes transition from given state to
1094 another given state. */
1095 ainsn_t insn;
1096 /* The following field value is the next arc output from the same
1097 state. */
1098 arc_t next_out_arc;
1099 /* List of arcs marked given insn is formed with the following
1100 field. The field is used in transfromation NDFA -> DFA. */
1101 arc_t next_arc_marked_by_insn;
1102 /* The following field is defined if NDFA_FLAG is zero. The member
1103 value is number of alternative reservations which can be used for
1104 transition for given state by given insn. */
1105 int state_alts;
1108 /* The following node type describes a deterministic alternative in
1109 non-deterministic state which characterizes cpu unit reservations
1110 of automaton insn or which is part of NDFA. */
1111 struct alt_state
1113 /* The following field is a determinist state which characterizes
1114 unit reservations of the instruction. */
1115 state_t state;
1116 /* The following field refers to the next state which characterizes
1117 unit reservations of the instruction. */
1118 alt_state_t next_alt_state;
1119 /* The following field refers to the next state in sorted list. */
1120 alt_state_t next_sorted_alt_state;
1123 /* The following node type describes insn of automaton. They are
1124 labels of FA arcs. */
1125 struct ainsn
1127 /* The following field value is the corresponding insn declaration
1128 of description. */
1129 struct insn_reserv_decl *insn_reserv_decl;
1130 /* The following field value is the next insn declaration for an
1131 automaton. */
1132 ainsn_t next_ainsn;
1133 /* The following field is states which characterize automaton unit
1134 reservations of the instruction. The value can be NULL only if it
1135 is special insn `cycle advancing'. */
1136 alt_state_t alt_states;
1137 /* The following field is sorted list of states which characterize
1138 automaton unit reservations of the instruction. The value can be
1139 NULL only if it is special insn `cycle advancing'. */
1140 alt_state_t sorted_alt_states;
1141 /* The following field refers the next automaton insn with
1142 the same reservations. */
1143 ainsn_t next_same_reservs_insn;
1144 /* The following field is flag of the first automaton insn with the
1145 same reservations in the declaration list. Only arcs marked such
1146 insn is present in the automaton. This significantly decreases
1147 memory requirements especially when several automata are
1148 formed. */
1149 char first_insn_with_same_reservs;
1150 /* The following member has nonzero value if there is arc from state of
1151 the automaton marked by the ainsn. */
1152 char arc_exists_p;
1153 /* Cyclic list of insns of an equivalence class is formed with the
1154 aid of the following field. */
1155 ainsn_t next_equiv_class_insn;
1156 /* The following field value is nonzero if the insn declaration is
1157 the first insn declaration with given equivalence number. */
1158 char first_ainsn_with_given_equialence_num;
1159 /* The following field is number of class of equivalence of insns.
1160 It is necessary because many insns may be equivalent with the
1161 point of view of pipeline hazards. */
1162 int insn_equiv_class_num;
1163 /* The following member value is TRUE if there is an arc in the
1164 automaton marked by the insn into another state. In other
1165 words, the insn can change the state of the automaton. */
1166 int important_p;
1169 /* The folowing describes an automaton for PHR. */
1170 struct automaton
1172 /* The following field value is the list of insn declarations for
1173 given automaton. */
1174 ainsn_t ainsn_list;
1175 /* The following field value is the corresponding automaton
1176 declaration. This field is not NULL only if the automatic
1177 partition on automata is not used. */
1178 struct automaton_decl *corresponding_automaton_decl;
1179 /* The following field value is the next automaton. */
1180 automaton_t next_automaton;
1181 /* The following field is start state of FA. There are not unit
1182 reservations in the state. */
1183 state_t start_state;
1184 /* The following field value is number of equivalence classes of
1185 insns (see field `insn_equiv_class_num' in
1186 `insn_reserv_decl'). */
1187 int insn_equiv_classes_num;
1188 /* The following field value is number of states of final DFA. */
1189 int achieved_states_num;
1190 /* The following field value is the order number (0, 1, ...) of
1191 given automaton. */
1192 int automaton_order_num;
1193 /* The following fields contain statistics information about
1194 building automaton. */
1195 int NDFA_states_num, DFA_states_num;
1196 /* The following field value is defined only if minimization of DFA
1197 is used. */
1198 int minimal_DFA_states_num;
1199 int NDFA_arcs_num, DFA_arcs_num;
1200 /* The following field value is defined only if minimization of DFA
1201 is used. */
1202 int minimal_DFA_arcs_num;
1203 /* The following two members refer for two table state x ainsn ->
1204 int. */
1205 state_ainsn_table_t trans_table;
1206 state_ainsn_table_t state_alts_table;
1207 /* The following member value is maximal value of min issue delay
1208 for insns of the automaton. */
1209 int max_min_delay;
1210 /* Usually min issue delay is small and we can place several (2, 4,
1211 8) elements in one vector element. So the compression factor can
1212 be 1 (no compression), 2, 4, 8. */
1213 int min_issue_delay_table_compression_factor;
1216 /* The following is the element of the list of automata. */
1217 struct automata_list_el
1219 /* The automaton itself. */
1220 automaton_t automaton;
1221 /* The next automata set element. */
1222 automata_list_el_t next_automata_list_el;
1225 /* The following structure describes a table state X ainsn -> int(>= 0). */
1226 struct state_ainsn_table
1228 /* Automaton to which given table belongs. */
1229 automaton_t automaton;
1230 /* The following tree vectors for comb vector implementation of the
1231 table. */
1232 vla_hwint_t comb_vect;
1233 vla_hwint_t check_vect;
1234 vla_hwint_t base_vect;
1235 /* This is simple implementation of the table. */
1236 vla_hwint_t full_vect;
1237 /* Minimal and maximal values of the previous vectors. */
1238 int min_comb_vect_el_value, max_comb_vect_el_value;
1239 int min_base_vect_el_value, max_base_vect_el_value;
1242 /* Create IR structure (node). */
1243 static void *
1244 create_node (size)
1245 size_t size;
1247 void *result;
1249 obstack_blank (&irp, size);
1250 result = obstack_base (&irp);
1251 obstack_finish (&irp);
1252 /* Default values of members are NULL and zero. */
1253 memset (result, 0, size);
1254 return result;
1257 /* Copy IR structure (node). */
1258 static void *
1259 copy_node (from, size)
1260 void *from;
1261 size_t size;
1263 void *result;
1264 result = create_node (size);
1265 memcpy (result, from, size);
1266 return result;
1269 /* The function checks that NAME does not contain quotes (`"'). */
1270 static char *
1271 check_name (name, pos)
1272 char * name;
1273 pos_t pos ATTRIBUTE_UNUSED;
1275 char *str;
1277 for (str = name; *str != '\0'; str++)
1278 if (*str == '\"')
1279 error ("Name `%s' contains quotes", name);
1280 return name;
1283 /* Pointers top all declartions during IR generation are stored in the
1284 following. */
1285 static vla_ptr_t decls;
1287 /* Given a pointer to a (char *) and a separator, return an alloc'ed
1288 string containing the next separated element, taking parentheses
1289 into account if PAR_FLAG has nonzero value. Advance the pointer to
1290 after the string scanned, or the end-of-string. Return NULL if at
1291 end of string. */
1292 static char *
1293 next_sep_el (pstr, sep, par_flag)
1294 char **pstr;
1295 int sep;
1296 int par_flag;
1298 char *out_str;
1299 char *p;
1300 int pars_num;
1301 int n_spaces;
1303 /* Remove leading whitespaces. */
1304 while (isspace ((int) **pstr))
1305 (*pstr)++;
1307 if (**pstr == '\0')
1308 return NULL;
1310 n_spaces = 0;
1311 for (pars_num = 0, p = *pstr; *p != '\0'; p++)
1313 if (par_flag && *p == '(')
1314 pars_num++;
1315 else if (par_flag && *p == ')')
1316 pars_num--;
1317 else if (pars_num == 0 && *p == sep)
1318 break;
1319 if (pars_num == 0 && isspace ((int) *p))
1320 n_spaces++;
1321 else
1323 for (; n_spaces != 0; n_spaces--)
1324 obstack_1grow (&irp, p [-n_spaces]);
1325 obstack_1grow (&irp, *p);
1328 obstack_1grow (&irp, '\0');
1329 out_str = obstack_base (&irp);
1330 obstack_finish (&irp);
1332 *pstr = p;
1333 if (**pstr == sep)
1334 (*pstr)++;
1336 return out_str;
1339 /* Given a string and a separator, return the number of separated
1340 elements in it, taking parentheses into account if PAR_FLAG has
1341 nonzero value. Return 0 for the null string, -1 if parantheses is
1342 not balanced. */
1343 static int
1344 n_sep_els (s, sep, par_flag)
1345 char *s;
1346 int sep;
1347 int par_flag;
1349 int n;
1350 int pars_num;
1352 if (*s == '\0')
1353 return 0;
1355 for (pars_num = 0, n = 1; *s; s++)
1356 if (par_flag && *s == '(')
1357 pars_num++;
1358 else if (par_flag && *s == ')')
1359 pars_num--;
1360 else if (pars_num == 0 && *s == sep)
1361 n++;
1363 return (pars_num != 0 ? -1 : n);
1366 /* Given a string and a separator, return vector of strings which are
1367 elements in the string and number of elements through els_num.
1368 Take parentheses into account if PAR_FLAG has nonzero value.
1369 Return 0 for the null string, -1 if parantheses are not balanced. */
1370 static char **
1371 get_str_vect (str, els_num, sep, par_flag)
1372 char *str;
1373 int *els_num;
1374 int sep;
1375 int par_flag;
1377 int i;
1378 char **vect;
1379 char **pstr;
1381 *els_num = n_sep_els (str, sep, par_flag);
1382 if (*els_num <= 0)
1383 return NULL;
1384 obstack_blank (&irp, sizeof (char *) * (*els_num));
1385 vect = (char **) obstack_base (&irp);
1386 obstack_finish (&irp);
1387 pstr = &str;
1388 for (i = 0; i < *els_num; i++)
1389 vect [i] = next_sep_el (pstr, sep, par_flag);
1390 if (next_sep_el (pstr, sep, par_flag) != NULL)
1391 abort ();
1392 return vect;
1395 /* Process a DEFINE_CPU_UNIT.
1397 This gives information about a unit contained in CPU. We fill a
1398 struct unit_decl with information used later by `expand_automata'. */
1399 void
1400 gen_cpu_unit (def)
1401 rtx def;
1403 decl_t decl;
1404 char **str_cpu_units;
1405 int vect_length;
1406 int i;
1408 str_cpu_units = get_str_vect ((char *) XSTR (def, 0), &vect_length, ',', 0);
1409 if (str_cpu_units == NULL)
1410 fatal ("invalid string `%s' in define_cpu_unit", XSTR (def, 0));
1411 for (i = 0; i < vect_length; i++)
1413 decl = create_node (sizeof (struct decl));
1414 decl->mode = dm_unit;
1415 decl->pos = 0;
1416 decl->decl.unit.name = check_name (str_cpu_units [i], decl->pos);
1417 decl->decl.unit.automaton_name = (char *) XSTR (def, 1);
1418 decl->decl.unit.query_p = 0;
1419 VLA_PTR_ADD (decls, decl);
1420 num_dfa_decls++;
1424 /* Process a DEFINE_QUERY_CPU_UNIT.
1426 This gives information about a unit contained in CPU. We fill a
1427 struct unit_decl with information used later by `expand_automata'. */
1428 void
1429 gen_query_cpu_unit (def)
1430 rtx def;
1432 decl_t decl;
1433 char **str_cpu_units;
1434 int vect_length;
1435 int i;
1437 str_cpu_units = get_str_vect ((char *) XSTR (def, 0), &vect_length, ',', 0);
1438 if (str_cpu_units == NULL)
1439 fatal ("invalid string `%s' in define_query_cpu_unit", XSTR (def, 0));
1440 for (i = 0; i < vect_length; i++)
1442 decl = create_node (sizeof (struct decl));
1443 decl->mode = dm_unit;
1444 decl->pos = 0;
1445 decl->decl.unit.name = check_name (str_cpu_units [i], decl->pos);
1446 decl->decl.unit.automaton_name = (char *) XSTR (def, 1);
1447 decl->decl.unit.query_p = 1;
1448 VLA_PTR_ADD (decls, decl);
1449 num_dfa_decls++;
1453 /* Process a DEFINE_BYPASS.
1455 This gives information about a unit contained in the CPU. We fill
1456 in a struct bypass_decl with information used later by
1457 `expand_automata'. */
1458 void
1459 gen_bypass (def)
1460 rtx def;
1462 decl_t decl;
1463 char **out_insns;
1464 int out_length;
1465 char **in_insns;
1466 int in_length;
1467 int i, j;
1469 out_insns = get_str_vect ((char *) XSTR (def, 1), &out_length, ',', 0);
1470 if (out_insns == NULL)
1471 fatal ("invalid string `%s' in define_bypass", XSTR (def, 1));
1472 in_insns = get_str_vect ((char *) XSTR (def, 2), &in_length, ',', 0);
1473 if (in_insns == NULL)
1474 fatal ("invalid string `%s' in define_bypass", XSTR (def, 2));
1475 for (i = 0; i < out_length; i++)
1476 for (j = 0; j < in_length; j++)
1478 decl = create_node (sizeof (struct decl));
1479 decl->mode = dm_bypass;
1480 decl->pos = 0;
1481 decl->decl.bypass.latency = XINT (def, 0);
1482 decl->decl.bypass.out_insn_name = out_insns [i];
1483 decl->decl.bypass.in_insn_name = in_insns [j];
1484 decl->decl.bypass.bypass_guard_name = (char *) XSTR (def, 3);
1485 VLA_PTR_ADD (decls, decl);
1486 num_dfa_decls++;
1490 /* Process an EXCLUSION_SET.
1492 This gives information about a cpu unit conflicts. We fill a
1493 struct unit_rel_decl (excl) with information used later by
1494 `expand_automata'. */
1495 void
1496 gen_excl_set (def)
1497 rtx def;
1499 decl_t decl;
1500 char **first_str_cpu_units;
1501 char **second_str_cpu_units;
1502 int first_vect_length;
1503 int length;
1504 int i;
1506 first_str_cpu_units
1507 = get_str_vect ((char *) XSTR (def, 0), &first_vect_length, ',', 0);
1508 if (first_str_cpu_units == NULL)
1509 fatal ("invalid first string `%s' in exclusion_set", XSTR (def, 0));
1510 second_str_cpu_units = get_str_vect ((char *) XSTR (def, 1), &length, ',',
1512 if (second_str_cpu_units == NULL)
1513 fatal ("invalid second string `%s' in exclusion_set", XSTR (def, 1));
1514 length += first_vect_length;
1515 decl = create_node (sizeof (struct decl) + (length - 1) * sizeof (char *));
1516 decl->mode = dm_excl;
1517 decl->pos = 0;
1518 decl->decl.excl.names_num = length;
1519 decl->decl.excl.first_list_length = first_vect_length;
1520 for (i = 0; i < length; i++)
1521 if (i < first_vect_length)
1522 decl->decl.excl.names [i] = first_str_cpu_units [i];
1523 else
1524 decl->decl.excl.names [i] = second_str_cpu_units [i - first_vect_length];
1525 VLA_PTR_ADD (decls, decl);
1526 num_dfa_decls++;
1529 /* Process a PRESENCE_SET.
1531 This gives information about a cpu unit reservation requirements.
1532 We fill a struct unit_rel_decl (presence) with information used
1533 later by `expand_automata'. */
1534 void
1535 gen_presence_set (def)
1536 rtx def;
1538 decl_t decl;
1539 char **first_str_cpu_units;
1540 char **second_str_cpu_units;
1541 int first_vect_length;
1542 int length;
1543 int i;
1545 first_str_cpu_units
1546 = get_str_vect ((char *) XSTR (def, 0), &first_vect_length, ',', 0);
1547 if (first_str_cpu_units == NULL)
1548 fatal ("invalid first string `%s' in presence_set", XSTR (def, 0));
1549 second_str_cpu_units = get_str_vect ((char *) XSTR (def, 1), &length, ',',
1551 if (second_str_cpu_units == NULL)
1552 fatal ("invalid second string `%s' in presence_set", XSTR (def, 1));
1553 length += first_vect_length;
1554 decl = create_node (sizeof (struct decl) + (length - 1) * sizeof (char *));
1555 decl->mode = dm_presence;
1556 decl->pos = 0;
1557 decl->decl.presence.names_num = length;
1558 decl->decl.presence.first_list_length = first_vect_length;
1559 for (i = 0; i < length; i++)
1560 if (i < first_vect_length)
1561 decl->decl.presence.names [i] = first_str_cpu_units [i];
1562 else
1563 decl->decl.presence.names [i]
1564 = second_str_cpu_units [i - first_vect_length];
1565 VLA_PTR_ADD (decls, decl);
1566 num_dfa_decls++;
1569 /* Process an ABSENCE_SET.
1571 This gives information about a cpu unit reservation requirements.
1572 We fill a struct unit_rel_decl (absence) with information used
1573 later by `expand_automata'. */
1574 void
1575 gen_absence_set (def)
1576 rtx def;
1578 decl_t decl;
1579 char **first_str_cpu_units;
1580 char **second_str_cpu_units;
1581 int first_vect_length;
1582 int length;
1583 int i;
1585 first_str_cpu_units
1586 = get_str_vect ((char *) XSTR (def, 0), &first_vect_length, ',', 0);
1587 if (first_str_cpu_units == NULL)
1588 fatal ("invalid first string `%s' in absence_set", XSTR (def, 0));
1589 second_str_cpu_units = get_str_vect ((char *) XSTR (def, 1), &length, ',',
1591 if (second_str_cpu_units == NULL)
1592 fatal ("invalid second string `%s' in absence_set", XSTR (def, 1));
1593 length += first_vect_length;
1594 decl = create_node (sizeof (struct decl) + (length - 1) * sizeof (char *));
1595 decl->mode = dm_absence;
1596 decl->pos = 0;
1597 decl->decl.absence.names_num = length;
1598 decl->decl.absence.first_list_length = first_vect_length;
1599 for (i = 0; i < length; i++)
1600 if (i < first_vect_length)
1601 decl->decl.absence.names [i] = first_str_cpu_units [i];
1602 else
1603 decl->decl.absence.names [i]
1604 = second_str_cpu_units [i - first_vect_length];
1605 VLA_PTR_ADD (decls, decl);
1606 num_dfa_decls++;
1609 /* Process a DEFINE_AUTOMATON.
1611 This gives information about a finite state automaton used for
1612 recognizing pipeline hazards. We fill a struct automaton_decl
1613 with information used later by `expand_automata'. */
1614 void
1615 gen_automaton (def)
1616 rtx def;
1618 decl_t decl;
1619 char **str_automata;
1620 int vect_length;
1621 int i;
1623 str_automata = get_str_vect ((char *) XSTR (def, 0), &vect_length, ',', 0);
1624 if (str_automata == NULL)
1625 fatal ("invalid string `%s' in define_automaton", XSTR (def, 0));
1626 for (i = 0; i < vect_length; i++)
1628 decl = create_node (sizeof (struct decl));
1629 decl->mode = dm_automaton;
1630 decl->pos = 0;
1631 decl->decl.automaton.name = check_name (str_automata [i], decl->pos);
1632 VLA_PTR_ADD (decls, decl);
1633 num_dfa_decls++;
1637 /* Process an AUTOMATA_OPTION.
1639 This gives information how to generate finite state automaton used
1640 for recognizing pipeline hazards. */
1641 void
1642 gen_automata_option (def)
1643 rtx def;
1645 if (strcmp ((char *) XSTR (def, 0), NO_MINIMIZATION_OPTION + 1) == 0)
1646 no_minimization_flag = 1;
1647 else if (strcmp ((char *) XSTR (def, 0), W_OPTION + 1) == 0)
1648 w_flag = 1;
1649 else if (strcmp ((char *) XSTR (def, 0), NDFA_OPTION + 1) == 0)
1650 ndfa_flag = 1;
1651 else
1652 fatal ("invalid option `%s' in automata_option", XSTR (def, 0));
1655 /* Name in reservation to denote absence reservation. */
1656 #define NOTHING_NAME "nothing"
1658 /* The following string contains original reservation string being
1659 parsed. */
1660 static char *reserv_str;
1662 /* Parse an element in STR. */
1663 static regexp_t
1664 gen_regexp_el (str)
1665 char *str;
1667 regexp_t regexp;
1668 int len;
1670 if (*str == '(')
1672 len = strlen (str);
1673 if (str [len - 1] != ')')
1674 fatal ("garbage after ) in reservation `%s'", reserv_str);
1675 str [len - 1] = '\0';
1676 regexp = gen_regexp_sequence (str + 1);
1678 else if (strcmp (str, NOTHING_NAME) == 0)
1680 regexp = create_node (sizeof (struct decl));
1681 regexp->mode = rm_nothing;
1683 else
1685 regexp = create_node (sizeof (struct decl));
1686 regexp->mode = rm_unit;
1687 regexp->regexp.unit.name = str;
1689 return regexp;
1692 /* Parse construction `repeat' in STR. */
1693 static regexp_t
1694 gen_regexp_repeat (str)
1695 char *str;
1697 regexp_t regexp;
1698 regexp_t repeat;
1699 char **repeat_vect;
1700 int els_num;
1701 int i;
1703 repeat_vect = get_str_vect (str, &els_num, '*', 1);
1704 if (repeat_vect == NULL)
1705 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1706 if (els_num > 1)
1708 regexp = gen_regexp_el (repeat_vect [0]);
1709 for (i = 1; i < els_num; i++)
1711 repeat = create_node (sizeof (struct regexp));
1712 repeat->mode = rm_repeat;
1713 repeat->regexp.repeat.regexp = regexp;
1714 repeat->regexp.repeat.repeat_num = atoi (repeat_vect [i]);
1715 if (repeat->regexp.repeat.repeat_num <= 1)
1716 fatal ("repetition `%s' <= 1 in reservation `%s'",
1717 str, reserv_str);
1718 regexp = repeat;
1720 return regexp;
1722 else
1723 return gen_regexp_el (str);
1726 /* Parse reservation STR which possibly contains separator '+'. */
1727 static regexp_t
1728 gen_regexp_allof (str)
1729 char *str;
1731 regexp_t allof;
1732 char **allof_vect;
1733 int els_num;
1734 int i;
1736 allof_vect = get_str_vect (str, &els_num, '+', 1);
1737 if (allof_vect == NULL)
1738 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1739 if (els_num > 1)
1741 allof = create_node (sizeof (struct regexp)
1742 + sizeof (regexp_t) * (els_num - 1));
1743 allof->mode = rm_allof;
1744 allof->regexp.allof.regexps_num = els_num;
1745 for (i = 0; i < els_num; i++)
1746 allof->regexp.allof.regexps [i] = gen_regexp_repeat (allof_vect [i]);
1747 return allof;
1749 else
1750 return gen_regexp_repeat (str);
1753 /* Parse reservation STR which possibly contains separator '|'. */
1754 static regexp_t
1755 gen_regexp_oneof (str)
1756 char *str;
1758 regexp_t oneof;
1759 char **oneof_vect;
1760 int els_num;
1761 int i;
1763 oneof_vect = get_str_vect (str, &els_num, '|', 1);
1764 if (oneof_vect == NULL)
1765 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1766 if (els_num > 1)
1768 oneof = create_node (sizeof (struct regexp)
1769 + sizeof (regexp_t) * (els_num - 1));
1770 oneof->mode = rm_oneof;
1771 oneof->regexp.oneof.regexps_num = els_num;
1772 for (i = 0; i < els_num; i++)
1773 oneof->regexp.oneof.regexps [i] = gen_regexp_allof (oneof_vect [i]);
1774 return oneof;
1776 else
1777 return gen_regexp_allof (str);
1780 /* Parse reservation STR which possibly contains separator ','. */
1781 static regexp_t
1782 gen_regexp_sequence (str)
1783 char *str;
1785 regexp_t sequence;
1786 char **sequence_vect;
1787 int els_num;
1788 int i;
1790 sequence_vect = get_str_vect (str, &els_num, ',', 1);
1791 if (els_num > 1)
1793 sequence = create_node (sizeof (struct regexp)
1794 + sizeof (regexp_t) * (els_num - 1));
1795 sequence->mode = rm_sequence;
1796 sequence->regexp.sequence.regexps_num = els_num;
1797 for (i = 0; i < els_num; i++)
1798 sequence->regexp.sequence.regexps [i]
1799 = gen_regexp_oneof (sequence_vect [i]);
1800 return sequence;
1802 else
1803 return gen_regexp_oneof (str);
1806 /* Parse construction reservation STR. */
1807 static regexp_t
1808 gen_regexp (str)
1809 char *str;
1811 reserv_str = str;
1812 return gen_regexp_sequence (str);;
1815 /* Process a DEFINE_RESERVATION.
1817 This gives information about a reservation of cpu units. We fill
1818 in a struct reserv_decl with information used later by
1819 `expand_automata'. */
1820 void
1821 gen_reserv (def)
1822 rtx def;
1824 decl_t decl;
1826 decl = create_node (sizeof (struct decl));
1827 decl->mode = dm_reserv;
1828 decl->pos = 0;
1829 decl->decl.reserv.name = check_name ((char *) XSTR (def, 0), decl->pos);
1830 decl->decl.reserv.regexp = gen_regexp ((char *) XSTR (def, 1));
1831 VLA_PTR_ADD (decls, decl);
1832 num_dfa_decls++;
1835 /* Process a DEFINE_INSN_RESERVATION.
1837 This gives information about the reservation of cpu units by an
1838 insn. We fill a struct insn_reserv_decl with information used
1839 later by `expand_automata'. */
1840 void
1841 gen_insn_reserv (def)
1842 rtx def;
1844 decl_t decl;
1846 decl = create_node (sizeof (struct decl));
1847 decl->mode = dm_insn_reserv;
1848 decl->pos = 0;
1849 decl->decl.insn_reserv.name = check_name ((char *) XSTR (def, 0), decl->pos);
1850 decl->decl.insn_reserv.default_latency = XINT (def, 1);
1851 decl->decl.insn_reserv.condexp = XEXP (def, 2);
1852 decl->decl.insn_reserv.regexp = gen_regexp ((char *) XSTR (def, 3));
1853 VLA_PTR_ADD (decls, decl);
1854 num_dfa_decls++;
1859 /* The function evaluates hash value (0..UINT_MAX) of string. */
1860 static unsigned
1861 string_hash (string)
1862 const char *string;
1864 unsigned result, i;
1866 for (result = i = 0;*string++ != '\0'; i++)
1867 result += ((unsigned char) *string << (i % CHAR_BIT));
1868 return result;
1873 /* This page contains abstract data `table of automaton declarations'.
1874 Elements of the table is nodes representing automaton declarations.
1875 Key of the table elements is name of given automaton. Rememeber
1876 that automaton names have own space. */
1878 /* The function evaluates hash value of an automaton declaration. The
1879 function is used by abstract data `hashtab'. The function returns
1880 hash value (0..UINT_MAX) of given automaton declaration. */
1881 static unsigned
1882 automaton_decl_hash (automaton_decl)
1883 const void *automaton_decl;
1885 const decl_t decl = (decl_t) automaton_decl;
1887 if (decl->mode == dm_automaton && decl->decl.automaton.name == NULL)
1888 abort ();
1889 return string_hash (decl->decl.automaton.name);
1892 /* The function tests automaton declarations on equality of their
1893 keys. The function is used by abstract data `hashtab'. The
1894 function returns 1 if the declarations have the same key, 0
1895 otherwise. */
1896 static int
1897 automaton_decl_eq_p (automaton_decl_1, automaton_decl_2)
1898 const void* automaton_decl_1;
1899 const void* automaton_decl_2;
1901 const decl_t decl1 = (decl_t) automaton_decl_1;
1902 const decl_t decl2 = (decl_t) automaton_decl_2;
1904 if (decl1->mode != dm_automaton || decl1->decl.automaton.name == NULL
1905 || decl2->mode != dm_automaton || decl2->decl.automaton.name == NULL)
1906 abort ();
1907 return strcmp (decl1->decl.automaton.name, decl2->decl.automaton.name) == 0;
1910 /* The automaton declaration table itself is represented by the
1911 following variable. */
1912 static htab_t automaton_decl_table;
1914 /* The function inserts automaton declaration into the table. The
1915 function does nothing if an automaton declaration with the same key
1916 exists already in the table. The function returns automaton
1917 declaration node in the table with the same key as given automaton
1918 declaration node. */
1919 static decl_t
1920 insert_automaton_decl (automaton_decl)
1921 decl_t automaton_decl;
1923 void **entry_ptr;
1925 entry_ptr = htab_find_slot (automaton_decl_table, automaton_decl, 1);
1926 if (*entry_ptr == NULL)
1927 *entry_ptr = (void *) automaton_decl;
1928 return (decl_t) *entry_ptr;
1931 /* The following variable value is node representing automaton
1932 declaration. The node used for searching automaton declaration
1933 with given name. */
1934 static struct decl work_automaton_decl;
1936 /* The function searches for automaton declaration in the table with
1937 the same key as node representing name of the automaton
1938 declaration. The function returns node found in the table, NULL if
1939 such node does not exist in the table. */
1940 static decl_t
1941 find_automaton_decl (name)
1942 char *name;
1944 void *entry;
1946 work_automaton_decl.decl.automaton.name = name;
1947 entry = htab_find (automaton_decl_table, &work_automaton_decl);
1948 return (decl_t) entry;
1951 /* The function creates empty automaton declaration table and node
1952 representing automaton declaration and used for searching automaton
1953 declaration with given name. The function must be called only once
1954 before any work with the automaton declaration table. */
1955 static void
1956 initiate_automaton_decl_table ()
1958 work_automaton_decl.mode = dm_automaton;
1959 automaton_decl_table = htab_create (10, automaton_decl_hash,
1960 automaton_decl_eq_p, (htab_del) 0);
1963 /* The function deletes the automaton declaration table. Only call of
1964 function `initiate_automaton_decl_table' is possible immediately
1965 after this function call. */
1966 static void
1967 finish_automaton_decl_table ()
1969 htab_delete (automaton_decl_table);
1974 /* This page contains abstract data `table of insn declarations'.
1975 Elements of the table is nodes representing insn declarations. Key
1976 of the table elements is name of given insn (in corresponding
1977 define_insn_reservation). Rememeber that insn names have own
1978 space. */
1980 /* The function evaluates hash value of an insn declaration. The
1981 function is used by abstract data `hashtab'. The function returns
1982 hash value (0..UINT_MAX) of given insn declaration. */
1983 static unsigned
1984 insn_decl_hash (insn_decl)
1985 const void *insn_decl;
1987 const decl_t decl = (decl_t) insn_decl;
1989 if (decl->mode != dm_insn_reserv || decl->decl.insn_reserv.name == NULL)
1990 abort ();
1991 return string_hash (decl->decl.insn_reserv.name);
1994 /* The function tests insn declarations on equality of their keys.
1995 The function is used by abstract data `hashtab'. The function
1996 returns 1 if declarations have the same key, 0 otherwise. */
1997 static int
1998 insn_decl_eq_p (insn_decl_1, insn_decl_2)
1999 const void *insn_decl_1;
2000 const void *insn_decl_2;
2002 const decl_t decl1 = (decl_t) insn_decl_1;
2003 const decl_t decl2 = (decl_t) insn_decl_2;
2005 if (decl1->mode != dm_insn_reserv || decl1->decl.insn_reserv.name == NULL
2006 || decl2->mode != dm_insn_reserv || decl2->decl.insn_reserv.name == NULL)
2007 abort ();
2008 return strcmp (decl1->decl.insn_reserv.name,
2009 decl2->decl.insn_reserv.name) == 0;
2012 /* The insn declaration table itself is represented by the following
2013 variable. The table does not contain insn reservation
2014 declarations. */
2015 static htab_t insn_decl_table;
2017 /* The function inserts insn declaration into the table. The function
2018 does nothing if an insn declaration with the same key exists
2019 already in the table. The function returns insn declaration node
2020 in the table with the same key as given insn declaration node. */
2021 static decl_t
2022 insert_insn_decl (insn_decl)
2023 decl_t insn_decl;
2025 void **entry_ptr;
2027 entry_ptr = htab_find_slot (insn_decl_table, insn_decl, 1);
2028 if (*entry_ptr == NULL)
2029 *entry_ptr = (void *) insn_decl;
2030 return (decl_t) *entry_ptr;
2033 /* The following variable value is node representing insn reservation
2034 declaration. The node used for searching insn reservation
2035 declaration with given name. */
2036 static struct decl work_insn_decl;
2038 /* The function searches for insn reservation declaration in the table
2039 with the same key as node representing name of the insn reservation
2040 declaration. The function returns node found in the table, NULL if
2041 such node does not exist in the table. */
2042 static decl_t
2043 find_insn_decl (name)
2044 char *name;
2046 void *entry;
2048 work_insn_decl.decl.insn_reserv.name = name;
2049 entry = htab_find (insn_decl_table, &work_insn_decl);
2050 return (decl_t) entry;
2053 /* The function creates empty insn declaration table and node
2054 representing insn declaration and used for searching insn
2055 declaration with given name. The function must be called only once
2056 before any work with the insn declaration table. */
2057 static void
2058 initiate_insn_decl_table ()
2060 work_insn_decl.mode = dm_insn_reserv;
2061 insn_decl_table = htab_create (10, insn_decl_hash, insn_decl_eq_p,
2062 (htab_del) 0);
2065 /* The function deletes the insn declaration table. Only call of
2066 function `initiate_insn_decl_table' is possible immediately after
2067 this function call. */
2068 static void
2069 finish_insn_decl_table ()
2071 htab_delete (insn_decl_table);
2076 /* This page contains abstract data `table of declarations'. Elements
2077 of the table is nodes representing declarations (of units and
2078 reservations). Key of the table elements is names of given
2079 declarations. */
2081 /* The function evaluates hash value of a declaration. The function
2082 is used by abstract data `hashtab'. The function returns hash
2083 value (0..UINT_MAX) of given declaration. */
2084 static unsigned
2085 decl_hash (decl)
2086 const void *decl;
2088 const decl_t d = (const decl_t) decl;
2090 if ((d->mode != dm_unit || d->decl.unit.name == NULL)
2091 && (d->mode != dm_reserv || d->decl.reserv.name == NULL))
2092 abort ();
2093 return string_hash (d->mode == dm_unit
2094 ? d->decl.unit.name : d->decl.reserv.name);
2097 /* The function tests declarations on equality of their keys. The
2098 function is used by abstract data `hashtab'. The function
2099 returns 1 if the declarations have the same key, 0 otherwise. */
2100 static int
2101 decl_eq_p (decl_1, decl_2)
2102 const void *decl_1;
2103 const void *decl_2;
2105 const decl_t d1 = (const decl_t) decl_1;
2106 const decl_t d2 = (const decl_t) decl_2;
2108 if (((d1->mode != dm_unit || d1->decl.unit.name == NULL)
2109 && (d1->mode != dm_reserv || d1->decl.reserv.name == NULL))
2110 || ((d2->mode != dm_unit || d2->decl.unit.name == NULL)
2111 && (d2->mode != dm_reserv || d2->decl.reserv.name == NULL)))
2112 abort ();
2113 return strcmp ((d1->mode == dm_unit
2114 ? d1->decl.unit.name : d1->decl.reserv.name),
2115 (d2->mode == dm_unit
2116 ? d2->decl.unit.name : d2->decl.reserv.name)) == 0;
2119 /* The declaration table itself is represented by the following
2120 variable. */
2121 static htab_t decl_table;
2123 /* The function inserts declaration into the table. The function does
2124 nothing if a declaration with the same key exists already in the
2125 table. The function returns declaration node in the table with the
2126 same key as given declaration node. */
2128 static decl_t
2129 insert_decl (decl)
2130 decl_t decl;
2132 void **entry_ptr;
2134 entry_ptr = htab_find_slot (decl_table, decl, 1);
2135 if (*entry_ptr == NULL)
2136 *entry_ptr = (void *) decl;
2137 return (decl_t) *entry_ptr;
2140 /* The following variable value is node representing declaration. The
2141 node used for searching declaration with given name. */
2142 static struct decl work_decl;
2144 /* The function searches for declaration in the table with the same
2145 key as node representing name of the declaration. The function
2146 returns node found in the table, NULL if such node does not exist
2147 in the table. */
2148 static decl_t
2149 find_decl (name)
2150 char *name;
2152 void *entry;
2154 work_decl.decl.unit.name = name;
2155 entry = htab_find (decl_table, &work_decl);
2156 return (decl_t) entry;
2159 /* The function creates empty declaration table and node representing
2160 declaration and used for searching declaration with given name.
2161 The function must be called only once before any work with the
2162 declaration table. */
2163 static void
2164 initiate_decl_table ()
2166 work_decl.mode = dm_unit;
2167 decl_table = htab_create (10, decl_hash, decl_eq_p, (htab_del) 0);
2170 /* The function deletes the declaration table. Only call of function
2171 `initiate_declaration_table' is possible immediately after this
2172 function call. */
2173 static void
2174 finish_decl_table ()
2176 htab_delete (decl_table);
2181 /* This page contains checker of pipeline hazard description. */
2183 /* Checking NAMES in an exclusion clause vector and returning formed
2184 unit_set_el_list. */
2185 static unit_set_el_t
2186 process_excls (names, num, excl_pos)
2187 char **names;
2188 int num;
2189 pos_t excl_pos ATTRIBUTE_UNUSED;
2191 unit_set_el_t el_list;
2192 unit_set_el_t last_el;
2193 unit_set_el_t new_el;
2194 decl_t decl_in_table;
2195 int i;
2197 el_list = NULL;
2198 last_el = NULL;
2199 for (i = 0; i < num; i++)
2201 decl_in_table = find_decl (names [i]);
2202 if (decl_in_table == NULL)
2203 error ("unit `%s' in exclusion is not declared", names [i]);
2204 else if (decl_in_table->mode != dm_unit)
2205 error ("`%s' in exclusion is not unit", names [i]);
2206 else
2208 new_el = create_node (sizeof (struct unit_set_el));
2209 new_el->unit_decl = &decl_in_table->decl.unit;
2210 new_el->next_unit_set_el = NULL;
2211 if (last_el == NULL)
2212 el_list = last_el = new_el;
2213 else
2215 last_el->next_unit_set_el = new_el;
2216 last_el = last_el->next_unit_set_el;
2220 return el_list;
2223 /* The function adds each element from SOURCE_LIST to the exclusion
2224 list of the each element from DEST_LIST. Checking situation "unit
2225 excludes itself". */
2226 static void
2227 add_excls (dest_list, source_list, excl_pos)
2228 unit_set_el_t dest_list;
2229 unit_set_el_t source_list;
2230 pos_t excl_pos ATTRIBUTE_UNUSED;
2232 unit_set_el_t dst;
2233 unit_set_el_t src;
2234 unit_set_el_t curr_el;
2235 unit_set_el_t prev_el;
2236 unit_set_el_t copy;
2238 for (dst = dest_list; dst != NULL; dst = dst->next_unit_set_el)
2239 for (src = source_list; src != NULL; src = src->next_unit_set_el)
2241 if (dst->unit_decl == src->unit_decl)
2243 error ("unit `%s' excludes itself", src->unit_decl->name);
2244 continue;
2246 if (dst->unit_decl->automaton_name != NULL
2247 && src->unit_decl->automaton_name != NULL
2248 && strcmp (dst->unit_decl->automaton_name,
2249 src->unit_decl->automaton_name) != 0)
2251 error ("units `%s' and `%s' in exclusion set belong to different automata",
2252 src->unit_decl->name, dst->unit_decl->name);
2253 continue;
2255 for (curr_el = dst->unit_decl->excl_list, prev_el = NULL;
2256 curr_el != NULL;
2257 prev_el = curr_el, curr_el = curr_el->next_unit_set_el)
2258 if (curr_el->unit_decl == src->unit_decl)
2259 break;
2260 if (curr_el == NULL)
2262 /* Element not found - insert. */
2263 copy = copy_node (src, sizeof (*src));
2264 copy->next_unit_set_el = NULL;
2265 if (prev_el == NULL)
2266 dst->unit_decl->excl_list = copy;
2267 else
2268 prev_el->next_unit_set_el = copy;
2273 /* Checking NAMES in an presence clause vector and returning formed
2274 unit_set_el_list. The function is called only after processing all
2275 exclusion sets. */
2276 static unit_set_el_t
2277 process_presence_absence (names, num, req_pos, presence_p)
2278 char **names;
2279 int num;
2280 pos_t req_pos ATTRIBUTE_UNUSED;
2281 int presence_p;
2283 unit_set_el_t el_list;
2284 unit_set_el_t last_el;
2285 unit_set_el_t new_el;
2286 decl_t decl_in_table;
2287 int i;
2289 el_list = NULL;
2290 last_el = NULL;
2291 for (i = 0; i < num; i++)
2293 decl_in_table = find_decl (names [i]);
2294 if (decl_in_table == NULL)
2295 error ((presence_p
2296 ? "unit `%s' in presence set is not declared"
2297 : "unit `%s' in absence set is not declared"), names [i]);
2298 else if (decl_in_table->mode != dm_unit)
2299 error ((presence_p
2300 ? "`%s' in presence set is not unit"
2301 : "`%s' in absence set is not unit"), names [i]);
2302 else
2304 new_el = create_node (sizeof (struct unit_set_el));
2305 new_el->unit_decl = &decl_in_table->decl.unit;
2306 new_el->next_unit_set_el = NULL;
2307 if (last_el == NULL)
2308 el_list = last_el = new_el;
2309 else
2311 last_el->next_unit_set_el = new_el;
2312 last_el = last_el->next_unit_set_el;
2316 return el_list;
2319 /* The function adds each element from SOURCE_LIST to presence (if
2320 PRESENCE_P) or absence list of the each element from DEST_LIST.
2321 Checking situations "unit requires own presence", "unit requires
2322 own absence", and "unit excludes and requires presence of ...".
2323 Remember that we process absence sets only after all presence
2324 sets. */
2325 static void
2326 add_presence_absence (dest_list, source_list, req_pos, presence_p)
2327 unit_set_el_t dest_list;
2328 unit_set_el_t source_list;
2329 pos_t req_pos ATTRIBUTE_UNUSED;
2330 int presence_p;
2332 unit_set_el_t dst;
2333 unit_set_el_t src;
2334 unit_set_el_t curr_el;
2335 unit_set_el_t prev_el;
2336 unit_set_el_t copy;
2338 for (dst = dest_list; dst != NULL; dst = dst->next_unit_set_el)
2339 for (src = source_list; src != NULL; src = src->next_unit_set_el)
2341 if (dst->unit_decl == src->unit_decl)
2343 error ((presence_p
2344 ? "unit `%s' requires own presence"
2345 : "unit `%s' requires own absence"), src->unit_decl->name);
2346 continue;
2348 if (dst->unit_decl->automaton_name != NULL
2349 && src->unit_decl->automaton_name != NULL
2350 && strcmp (dst->unit_decl->automaton_name,
2351 src->unit_decl->automaton_name) != 0)
2353 error ((presence_p
2354 ? "units `%s' and `%s' in presence set belong to different automata"
2355 : "units `%s' and `%s' in absence set belong to different automata"),
2356 src->unit_decl->name, dst->unit_decl->name);
2357 continue;
2359 for (curr_el = (presence_p
2360 ? dst->unit_decl->presence_list
2361 : dst->unit_decl->absence_list), prev_el = NULL;
2362 curr_el != NULL;
2363 prev_el = curr_el, curr_el = curr_el->next_unit_set_el)
2364 if (curr_el->unit_decl == src->unit_decl)
2365 break;
2366 if (curr_el == NULL)
2368 /* Element not found - insert if there is no error. */
2369 int no_error_flag = 1;
2371 if (presence_p)
2372 for (curr_el = dst->unit_decl->excl_list;
2373 curr_el != NULL;
2374 curr_el = curr_el->next_unit_set_el)
2376 if (src->unit_decl == curr_el->unit_decl)
2378 if (!w_flag)
2380 error
2381 ("unit `%s' excludes and requires presence of `%s'",
2382 dst->unit_decl->name, src->unit_decl->name);
2383 no_error_flag = 0;
2385 else
2386 warning
2387 ("unit `%s' excludes and requires presence of `%s'",
2388 dst->unit_decl->name, src->unit_decl->name);
2391 else
2392 for (curr_el = dst->unit_decl->presence_list;
2393 curr_el != NULL;
2394 curr_el = curr_el->next_unit_set_el)
2396 if (src->unit_decl == curr_el->unit_decl)
2398 if (!w_flag)
2400 error
2401 ("unit `%s' requires absence and presence of `%s'",
2402 dst->unit_decl->name, src->unit_decl->name);
2403 no_error_flag = 0;
2405 else
2406 warning
2407 ("unit `%s' requires absence and presence of `%s'",
2408 dst->unit_decl->name, src->unit_decl->name);
2411 if (no_error_flag)
2413 copy = copy_node (src, sizeof (*src));
2414 copy->next_unit_set_el = NULL;
2415 if (prev_el == NULL)
2417 if (presence_p)
2418 dst->unit_decl->presence_list = copy;
2419 else
2420 dst->unit_decl->absence_list = copy;
2422 else
2423 prev_el->next_unit_set_el = copy;
2429 /* The function searches for bypass with given IN_INSN_RESERV in given
2430 BYPASS_LIST. */
2431 static struct bypass_decl *
2432 find_bypass (bypass_list, in_insn_reserv)
2433 struct bypass_decl *bypass_list;
2434 struct insn_reserv_decl *in_insn_reserv;
2436 struct bypass_decl *bypass;
2438 for (bypass = bypass_list; bypass != NULL; bypass = bypass->next)
2439 if (bypass->in_insn_reserv == in_insn_reserv)
2440 break;
2441 return bypass;
2444 /* The function processes pipeline description declarations, checks
2445 their correctness, and forms exclusion/presence/absence sets. */
2446 static void
2447 process_decls ()
2449 decl_t decl;
2450 decl_t automaton_decl;
2451 decl_t decl_in_table;
2452 decl_t out_insn_reserv;
2453 decl_t in_insn_reserv;
2454 struct bypass_decl *bypass;
2455 int automaton_presence;
2456 int i;
2458 /* Checking repeated automata declarations. */
2459 automaton_presence = 0;
2460 for (i = 0; i < description->decls_num; i++)
2462 decl = description->decls [i];
2463 if (decl->mode == dm_automaton)
2465 automaton_presence = 1;
2466 decl_in_table = insert_automaton_decl (decl);
2467 if (decl_in_table != decl)
2469 if (!w_flag)
2470 error ("repeated declaration of automaton `%s'",
2471 decl->decl.automaton.name);
2472 else
2473 warning ("repeated declaration of automaton `%s'",
2474 decl->decl.automaton.name);
2478 /* Checking undeclared automata, repeated declarations (except for
2479 automata) and correctness of their attributes (insn latency times
2480 etc.). */
2481 for (i = 0; i < description->decls_num; i++)
2483 decl = description->decls [i];
2484 if (decl->mode == dm_insn_reserv)
2486 decl->decl.insn_reserv.condexp
2487 = check_attr_test (decl->decl.insn_reserv.condexp, 0, 0);
2488 if (decl->decl.insn_reserv.default_latency < 0)
2489 error ("define_insn_reservation `%s' has negative latency time",
2490 decl->decl.insn_reserv.name);
2491 decl->decl.insn_reserv.insn_num = description->insns_num;
2492 description->insns_num++;
2493 decl_in_table = insert_insn_decl (decl);
2494 if (decl_in_table != decl)
2495 error ("`%s' is already used as insn reservation name",
2496 decl->decl.insn_reserv.name);
2498 else if (decl->mode == dm_bypass)
2500 if (decl->decl.bypass.latency < 0)
2501 error ("define_bypass `%s - %s' has negative latency time",
2502 decl->decl.bypass.out_insn_name,
2503 decl->decl.bypass.in_insn_name);
2505 else if (decl->mode == dm_unit || decl->mode == dm_reserv)
2507 if (decl->mode == dm_unit)
2509 decl->decl.unit.automaton_decl = NULL;
2510 if (decl->decl.unit.automaton_name != NULL)
2512 automaton_decl
2513 = find_automaton_decl (decl->decl.unit.automaton_name);
2514 if (automaton_decl == NULL)
2515 error ("automaton `%s' is not declared",
2516 decl->decl.unit.automaton_name);
2517 else
2519 automaton_decl->decl.automaton.automaton_is_used = 1;
2520 decl->decl.unit.automaton_decl
2521 = &automaton_decl->decl.automaton;
2524 else if (automaton_presence)
2525 error ("define_unit `%s' without automaton when one defined",
2526 decl->decl.unit.name);
2527 decl->decl.unit.unit_num = description->units_num;
2528 description->units_num++;
2529 if (strcmp (decl->decl.unit.name, NOTHING_NAME) == 0)
2531 error ("`%s' is declared as cpu unit", NOTHING_NAME);
2532 continue;
2534 decl_in_table = find_decl (decl->decl.unit.name);
2536 else
2538 if (strcmp (decl->decl.reserv.name, NOTHING_NAME) == 0)
2540 error ("`%s' is declared as cpu reservation", NOTHING_NAME);
2541 continue;
2543 decl_in_table = find_decl (decl->decl.reserv.name);
2545 if (decl_in_table == NULL)
2546 decl_in_table = insert_decl (decl);
2547 else
2549 if (decl->mode == dm_unit)
2550 error ("repeated declaration of unit `%s'",
2551 decl->decl.unit.name);
2552 else
2553 error ("repeated declaration of reservation `%s'",
2554 decl->decl.reserv.name);
2558 /* Check bypasses and form list of bypasses for each (output)
2559 insn. */
2560 for (i = 0; i < description->decls_num; i++)
2562 decl = description->decls [i];
2563 if (decl->mode == dm_bypass)
2565 out_insn_reserv = find_insn_decl (decl->decl.bypass.out_insn_name);
2566 in_insn_reserv = find_insn_decl (decl->decl.bypass.in_insn_name);
2567 if (out_insn_reserv == NULL)
2568 error ("there is no insn reservation `%s'",
2569 decl->decl.bypass.out_insn_name);
2570 else if (in_insn_reserv == NULL)
2571 error ("there is no insn reservation `%s'",
2572 decl->decl.bypass.in_insn_name);
2573 else
2575 decl->decl.bypass.out_insn_reserv
2576 = &out_insn_reserv->decl.insn_reserv;
2577 decl->decl.bypass.in_insn_reserv
2578 = &in_insn_reserv->decl.insn_reserv;
2579 bypass
2580 = find_bypass (out_insn_reserv->decl.insn_reserv.bypass_list,
2581 decl->decl.bypass.in_insn_reserv);
2582 if (bypass != NULL)
2584 if (decl->decl.bypass.latency == bypass->latency)
2586 if (!w_flag)
2587 error
2588 ("the same bypass `%s - %s' is already defined",
2589 decl->decl.bypass.out_insn_name,
2590 decl->decl.bypass.in_insn_name);
2591 else
2592 warning
2593 ("the same bypass `%s - %s' is already defined",
2594 decl->decl.bypass.out_insn_name,
2595 decl->decl.bypass.in_insn_name);
2597 else
2598 error ("bypass `%s - %s' is already defined",
2599 decl->decl.bypass.out_insn_name,
2600 decl->decl.bypass.in_insn_name);
2602 else
2604 decl->decl.bypass.next
2605 = out_insn_reserv->decl.insn_reserv.bypass_list;
2606 out_insn_reserv->decl.insn_reserv.bypass_list
2607 = &decl->decl.bypass;
2613 /* Check exclusion set declarations and form exclussion sets. */
2614 for (i = 0; i < description->decls_num; i++)
2616 decl = description->decls [i];
2617 if (decl->mode == dm_excl)
2619 unit_set_el_t unit_set_el_list;
2620 unit_set_el_t unit_set_el_list_2;
2622 unit_set_el_list
2623 = process_excls (decl->decl.excl.names,
2624 decl->decl.excl.first_list_length, decl->pos);
2625 unit_set_el_list_2
2626 = process_excls (&decl->decl.excl.names
2627 [decl->decl.excl.first_list_length],
2628 decl->decl.excl.names_num
2629 - decl->decl.excl.first_list_length,
2630 decl->pos);
2631 add_excls (unit_set_el_list, unit_set_el_list_2, decl->pos);
2632 add_excls (unit_set_el_list_2, unit_set_el_list, decl->pos);
2636 /* Check presence set declarations and form presence sets. */
2637 for (i = 0; i < description->decls_num; i++)
2639 decl = description->decls [i];
2640 if (decl->mode == dm_presence)
2642 unit_set_el_t unit_set_el_list;
2643 unit_set_el_t unit_set_el_list_2;
2645 unit_set_el_list
2646 = process_presence_absence
2647 (decl->decl.presence.names,
2648 decl->decl.presence.first_list_length, decl->pos, 1);
2649 unit_set_el_list_2
2650 = process_presence_absence
2651 (&decl->decl.presence.names
2652 [decl->decl.presence.first_list_length],
2653 decl->decl.presence.names_num
2654 - decl->decl.presence.first_list_length,
2655 decl->pos, 1);
2656 add_presence_absence (unit_set_el_list, unit_set_el_list_2,
2657 decl->pos, 1);
2661 /* Check absence set declarations and form absence sets. */
2662 for (i = 0; i < description->decls_num; i++)
2664 decl = description->decls [i];
2665 if (decl->mode == dm_absence)
2667 unit_set_el_t unit_set_el_list;
2668 unit_set_el_t unit_set_el_list_2;
2670 unit_set_el_list
2671 = process_presence_absence
2672 (decl->decl.presence.names,
2673 decl->decl.presence.first_list_length, decl->pos, 0);
2674 unit_set_el_list_2
2675 = process_presence_absence
2676 (&decl->decl.presence.names
2677 [decl->decl.presence.first_list_length],
2678 decl->decl.presence.names_num
2679 - decl->decl.presence.first_list_length,
2680 decl->pos, 0);
2681 add_presence_absence (unit_set_el_list, unit_set_el_list_2,
2682 decl->pos, 0);
2687 /* The following function checks that declared automaton is used. If
2688 the automaton is not used, the function fixes error/warning. The
2689 following function must be called only after `process_decls'. */
2690 static void
2691 check_automaton_usage ()
2693 decl_t decl;
2694 int i;
2696 for (i = 0; i < description->decls_num; i++)
2698 decl = description->decls [i];
2699 if (decl->mode == dm_automaton
2700 && !decl->decl.automaton.automaton_is_used)
2702 if (!w_flag)
2703 error ("automaton `%s' is not used", decl->decl.automaton.name);
2704 else
2705 warning ("automaton `%s' is not used", decl->decl.automaton.name);
2710 /* The following recursive function processes all regexp in order to
2711 fix usage of units or reservations and to fix errors of undeclared
2712 name. The function may change unit_regexp onto reserv_regexp.
2713 Remember that reserv_regexp does not exist before the function
2714 call. */
2715 static regexp_t
2716 process_regexp (regexp)
2717 regexp_t regexp;
2719 decl_t decl_in_table;
2720 regexp_t new_regexp;
2721 int i;
2723 if (regexp->mode == rm_unit)
2725 decl_in_table = find_decl (regexp->regexp.unit.name);
2726 if (decl_in_table == NULL)
2727 error ("undeclared unit or reservation `%s'",
2728 regexp->regexp.unit.name);
2729 else if (decl_in_table->mode == dm_unit)
2731 decl_in_table->decl.unit.unit_is_used = 1;
2732 regexp->regexp.unit.unit_decl = &decl_in_table->decl.unit;
2734 else if (decl_in_table->mode == dm_reserv)
2736 decl_in_table->decl.reserv.reserv_is_used = 1;
2737 new_regexp = create_node (sizeof (struct regexp));
2738 new_regexp->mode = rm_reserv;
2739 new_regexp->pos = regexp->pos;
2740 new_regexp->regexp.reserv.name = regexp->regexp.unit.name;
2741 new_regexp->regexp.reserv.reserv_decl = &decl_in_table->decl.reserv;
2742 regexp = new_regexp;
2744 else
2745 abort ();
2747 else if (regexp->mode == rm_sequence)
2748 for (i = 0; i < regexp->regexp.sequence.regexps_num; i++)
2749 regexp->regexp.sequence.regexps [i]
2750 = process_regexp (regexp->regexp.sequence.regexps [i]);
2751 else if (regexp->mode == rm_allof)
2752 for (i = 0; i < regexp->regexp.allof.regexps_num; i++)
2753 regexp->regexp.allof.regexps [i]
2754 = process_regexp (regexp->regexp.allof.regexps [i]);
2755 else if (regexp->mode == rm_oneof)
2756 for (i = 0; i < regexp->regexp.oneof.regexps_num; i++)
2757 regexp->regexp.oneof.regexps [i]
2758 = process_regexp (regexp->regexp.oneof.regexps [i]);
2759 else if (regexp->mode == rm_repeat)
2760 regexp->regexp.repeat.regexp
2761 = process_regexp (regexp->regexp.repeat.regexp);
2762 else if (regexp->mode != rm_nothing)
2763 abort ();
2764 return regexp;
2767 /* The following function processes regexp of define_reservation and
2768 define_insn_reservation with the aid of function
2769 `process_regexp'. */
2770 static void
2771 process_regexp_decls ()
2773 decl_t decl;
2774 int i;
2776 for (i = 0; i < description->decls_num; i++)
2778 decl = description->decls [i];
2779 if (decl->mode == dm_reserv)
2780 decl->decl.reserv.regexp = process_regexp (decl->decl.reserv.regexp);
2781 else if (decl->mode == dm_insn_reserv)
2782 decl->decl.insn_reserv.regexp
2783 = process_regexp (decl->decl.insn_reserv.regexp);
2787 /* The following function checks that declared unit is used. If the
2788 unit is not used, the function fixes errors/warnings. The
2789 following function must be called only after `process_decls',
2790 `process_regexp_decls'. */
2791 static void
2792 check_usage ()
2794 decl_t decl;
2795 int i;
2797 for (i = 0; i < description->decls_num; i++)
2799 decl = description->decls [i];
2800 if (decl->mode == dm_unit && !decl->decl.unit.unit_is_used)
2802 if (!w_flag)
2803 error ("unit `%s' is not used", decl->decl.unit.name);
2804 else
2805 warning ("unit `%s' is not used", decl->decl.unit.name);
2807 else if (decl->mode == dm_reserv && !decl->decl.reserv.reserv_is_used)
2809 if (!w_flag)
2810 error ("reservation `%s' is not used", decl->decl.reserv.name);
2811 else
2812 warning ("reservation `%s' is not used", decl->decl.reserv.name);
2817 /* The following variable value is number of reservation being
2818 processed on loop recognition. */
2819 static int curr_loop_pass_num;
2821 /* The following recursive function returns nonzero value if REGEXP
2822 contains given decl or reservations in given regexp refers for
2823 given decl. */
2824 static int
2825 loop_in_regexp (regexp, start_decl)
2826 regexp_t regexp;
2827 decl_t start_decl;
2829 int i;
2831 if (regexp == NULL)
2832 return 0;
2833 if (regexp->mode == rm_unit)
2834 return 0;
2835 else if (regexp->mode == rm_reserv)
2837 if (start_decl->mode == dm_reserv
2838 && regexp->regexp.reserv.reserv_decl == &start_decl->decl.reserv)
2839 return 1;
2840 else if (regexp->regexp.reserv.reserv_decl->loop_pass_num
2841 == curr_loop_pass_num)
2842 /* declaration has been processed. */
2843 return 0;
2844 else
2846 regexp->regexp.reserv.reserv_decl->loop_pass_num
2847 = curr_loop_pass_num;
2848 return loop_in_regexp (regexp->regexp.reserv.reserv_decl->regexp,
2849 start_decl);
2852 else if (regexp->mode == rm_sequence)
2854 for (i = 0; i < regexp->regexp.sequence.regexps_num; i++)
2855 if (loop_in_regexp (regexp->regexp.sequence.regexps [i], start_decl))
2856 return 1;
2857 return 0;
2859 else if (regexp->mode == rm_allof)
2861 for (i = 0; i < regexp->regexp.allof.regexps_num; i++)
2862 if (loop_in_regexp (regexp->regexp.allof.regexps [i], start_decl))
2863 return 1;
2864 return 0;
2866 else if (regexp->mode == rm_oneof)
2868 for (i = 0; i < regexp->regexp.oneof.regexps_num; i++)
2869 if (loop_in_regexp (regexp->regexp.oneof.regexps [i], start_decl))
2870 return 1;
2871 return 0;
2873 else if (regexp->mode == rm_repeat)
2874 return loop_in_regexp (regexp->regexp.repeat.regexp, start_decl);
2875 else
2877 if (regexp->mode != rm_nothing)
2878 abort ();
2879 return 0;
2883 /* The following function fixes errors "cycle in definition ...". The
2884 function uses function `loop_in_regexp' for that. */
2885 static void
2886 check_loops_in_regexps ()
2888 decl_t decl;
2889 int i;
2891 for (i = 0; i < description->decls_num; i++)
2893 decl = description->decls [i];
2894 if (decl->mode == dm_reserv)
2895 decl->decl.reserv.loop_pass_num = 0;
2897 for (i = 0; i < description->decls_num; i++)
2899 decl = description->decls [i];
2900 curr_loop_pass_num = i;
2902 if (decl->mode == dm_reserv)
2904 decl->decl.reserv.loop_pass_num = curr_loop_pass_num;
2905 if (loop_in_regexp (decl->decl.reserv.regexp, decl))
2907 if (decl->decl.reserv.regexp == NULL)
2908 abort ();
2909 error ("cycle in definition of reservation `%s'",
2910 decl->decl.reserv.name);
2916 /* The function recursively processes IR of reservation and defines
2917 max and min cycle for reservation of unit and for result in the
2918 reservation. */
2919 static int
2920 process_regexp_cycles (regexp, start_cycle)
2921 regexp_t regexp;
2922 int start_cycle;
2924 int i;
2926 if (regexp->mode == rm_unit)
2928 if (regexp->regexp.unit.unit_decl->max_occ_cycle_num < start_cycle)
2929 regexp->regexp.unit.unit_decl->max_occ_cycle_num = start_cycle;
2930 return start_cycle;
2932 else if (regexp->mode == rm_reserv)
2933 return process_regexp_cycles (regexp->regexp.reserv.reserv_decl->regexp,
2934 start_cycle);
2935 else if (regexp->mode == rm_repeat)
2937 for (i = 0; i < regexp->regexp.repeat.repeat_num; i++)
2938 start_cycle = process_regexp_cycles (regexp->regexp.repeat.regexp,
2939 start_cycle) + 1;
2940 return start_cycle;
2942 else if (regexp->mode == rm_sequence)
2944 for (i = 0; i < regexp->regexp.sequence.regexps_num; i++)
2945 start_cycle
2946 = process_regexp_cycles (regexp->regexp.sequence.regexps [i],
2947 start_cycle) + 1;
2948 return start_cycle;
2950 else if (regexp->mode == rm_allof)
2952 int finish_cycle = 0;
2953 int cycle;
2955 for (i = 0; i < regexp->regexp.allof.regexps_num; i++)
2957 cycle = process_regexp_cycles (regexp->regexp.allof.regexps [i],
2958 start_cycle);
2959 if (finish_cycle < cycle)
2960 finish_cycle = cycle;
2962 return finish_cycle;
2964 else if (regexp->mode == rm_oneof)
2966 int finish_cycle = 0;
2967 int cycle;
2969 for (i = 0; i < regexp->regexp.oneof.regexps_num; i++)
2971 cycle = process_regexp_cycles (regexp->regexp.oneof.regexps [i],
2972 start_cycle);
2973 if (finish_cycle < cycle)
2974 finish_cycle = cycle;
2976 return finish_cycle;
2978 else
2980 if (regexp->mode != rm_nothing)
2981 abort ();
2982 return start_cycle;
2986 /* The following function is called only for correct program. The
2987 function defines max reservation of insns in cycles. */
2988 static void
2989 evaluate_max_reserv_cycles ()
2991 int max_insn_cycles_num;
2992 decl_t decl;
2993 int i;
2995 description->max_insn_reserv_cycles = 0;
2996 for (i = 0; i < description->decls_num; i++)
2998 decl = description->decls [i];
2999 if (decl->mode == dm_insn_reserv)
3001 max_insn_cycles_num
3002 = process_regexp_cycles (decl->decl.insn_reserv.regexp, 0);
3003 if (description->max_insn_reserv_cycles < max_insn_cycles_num)
3004 description->max_insn_reserv_cycles = max_insn_cycles_num;
3007 description->max_insn_reserv_cycles++;
3010 /* The following function calls functions for checking all
3011 description. */
3012 static void
3013 check_all_description ()
3015 process_decls ();
3016 check_automaton_usage ();
3017 process_regexp_decls ();
3018 check_usage ();
3019 check_loops_in_regexps ();
3020 if (!have_error)
3021 evaluate_max_reserv_cycles ();
3026 /* The page contains abstract data `ticker'. This data is used to
3027 report time of different phases of building automata. It is
3028 possibly to write a description for which automata will be built
3029 during several minutes even on fast machine. */
3031 /* The following function creates ticker and makes it active. */
3032 static ticker_t
3033 create_ticker ()
3035 ticker_t ticker;
3037 ticker.modified_creation_time = get_run_time ();
3038 ticker.incremented_off_time = 0;
3039 return ticker;
3042 /* The following function switches off given ticker. */
3043 static void
3044 ticker_off (ticker)
3045 ticker_t *ticker;
3047 if (ticker->incremented_off_time == 0)
3048 ticker->incremented_off_time = get_run_time () + 1;
3051 /* The following function switches on given ticker. */
3052 static void
3053 ticker_on (ticker)
3054 ticker_t *ticker;
3056 if (ticker->incremented_off_time != 0)
3058 ticker->modified_creation_time
3059 += get_run_time () - ticker->incremented_off_time + 1;
3060 ticker->incremented_off_time = 0;
3064 /* The following function returns current time in milliseconds since
3065 the moment when given ticker was created. */
3066 static int
3067 active_time (ticker)
3068 ticker_t ticker;
3070 if (ticker.incremented_off_time != 0)
3071 return ticker.incremented_off_time - 1 - ticker.modified_creation_time;
3072 else
3073 return get_run_time () - ticker.modified_creation_time;
3076 /* The following function returns string representation of active time
3077 of given ticker. The result is string representation of seconds
3078 with accuracy of 1/100 second. Only result of the last call of the
3079 function exists. Therefore the following code is not correct
3081 printf ("parser time: %s\ngeneration time: %s\n",
3082 active_time_string (parser_ticker),
3083 active_time_string (generation_ticker));
3085 Correct code has to be the following
3087 printf ("parser time: %s\n", active_time_string (parser_ticker));
3088 printf ("generation time: %s\n",
3089 active_time_string (generation_ticker));
3092 static void
3093 print_active_time (f, ticker)
3094 FILE *f;
3095 ticker_t ticker;
3097 int msecs;
3099 msecs = active_time (ticker);
3100 fprintf (f, "%d.%06d", msecs / 1000000, msecs % 1000000);
3105 /* The following variable value is number of automaton which are
3106 really being created. This value is defined on the base of
3107 argument of option `-split'. If the variable has zero value the
3108 number of automata is defined by the constructions `%automaton'.
3109 This case occures when option `-split' is absent or has zero
3110 argument. If constructions `define_automaton' is absent only one
3111 automaton is created. */
3112 static int automata_num;
3114 /* The following variable values are times of
3115 o transformation of regular expressions
3116 o building NDFA (DFA if !ndfa_flag)
3117 o NDFA -> DFA (simply the same automaton if !ndfa_flag)
3118 o DFA minimization
3119 o building insn equivalence classes
3120 o all previous ones
3121 o code output */
3122 static ticker_t transform_time;
3123 static ticker_t NDFA_time;
3124 static ticker_t NDFA_to_DFA_time;
3125 static ticker_t minimize_time;
3126 static ticker_t equiv_time;
3127 static ticker_t automaton_generation_time;
3128 static ticker_t output_time;
3130 /* The following variable values are times of
3131 all checking
3132 all generation
3133 all pipeline hazard translator work */
3134 static ticker_t check_time;
3135 static ticker_t generation_time;
3136 static ticker_t all_time;
3140 /* Pseudo insn decl which denotes advancing cycle. */
3141 static decl_t advance_cycle_insn_decl;
3142 static void
3143 add_advance_cycle_insn_decl ()
3145 advance_cycle_insn_decl = create_node (sizeof (struct decl));
3146 advance_cycle_insn_decl->mode = dm_insn_reserv;
3147 advance_cycle_insn_decl->pos = no_pos;
3148 advance_cycle_insn_decl->decl.insn_reserv.regexp = NULL;
3149 advance_cycle_insn_decl->decl.insn_reserv.name = (char *) "$advance_cycle";
3150 advance_cycle_insn_decl->decl.insn_reserv.insn_num = description->insns_num;
3151 description->decls [description->decls_num] = advance_cycle_insn_decl;
3152 description->decls_num++;
3153 description->insns_num++;
3154 num_dfa_decls++;
3158 /* Abstract data `alternative states' which reperesents
3159 nondeterministic nature of the description (see comments for
3160 structures alt_state and state). */
3162 /* List of free states. */
3163 static alt_state_t first_free_alt_state;
3165 #ifndef NDEBUG
3166 /* The following variables is maximal number of allocated nodes
3167 alt_state. */
3168 static int allocated_alt_states_num = 0;
3169 #endif
3171 /* The following function returns free node alt_state. It may be new
3172 allocated node or node freed eralier. */
3173 static alt_state_t
3174 get_free_alt_state ()
3176 alt_state_t result;
3178 if (first_free_alt_state != NULL)
3180 result = first_free_alt_state;
3181 first_free_alt_state = first_free_alt_state->next_alt_state;
3183 else
3185 #ifndef NDEBUG
3186 allocated_alt_states_num++;
3187 #endif
3188 result = create_node (sizeof (struct alt_state));
3190 result->state = NULL;
3191 result->next_alt_state = NULL;
3192 result->next_sorted_alt_state = NULL;
3193 return result;
3196 /* The function frees node ALT_STATE. */
3197 static void
3198 free_alt_state (alt_state)
3199 alt_state_t alt_state;
3201 if (alt_state == NULL)
3202 return;
3203 alt_state->next_alt_state = first_free_alt_state;
3204 first_free_alt_state = alt_state;
3207 /* The function frees list started with node ALT_STATE_LIST. */
3208 static void
3209 free_alt_states (alt_states_list)
3210 alt_state_t alt_states_list;
3212 alt_state_t curr_alt_state;
3213 alt_state_t next_alt_state;
3215 for (curr_alt_state = alt_states_list;
3216 curr_alt_state != NULL;
3217 curr_alt_state = next_alt_state)
3219 next_alt_state = curr_alt_state->next_alt_state;
3220 free_alt_state (curr_alt_state);
3224 /* The function compares unique numbers of alt states. */
3225 static int
3226 alt_state_cmp (alt_state_ptr_1, alt_state_ptr_2)
3227 const void *alt_state_ptr_1;
3228 const void *alt_state_ptr_2;
3230 if ((*(alt_state_t *) alt_state_ptr_1)->state->unique_num
3231 == (*(alt_state_t *) alt_state_ptr_2)->state->unique_num)
3232 return 0;
3233 else if ((*(alt_state_t *) alt_state_ptr_1)->state->unique_num
3234 < (*(alt_state_t *) alt_state_ptr_2)->state->unique_num)
3235 return -1;
3236 else
3237 return 1;
3240 /* The function sorts ALT_STATES_LIST and removes duplicated alt
3241 states from the list. The comparison key is alt state unique
3242 number. */
3243 static alt_state_t
3244 uniq_sort_alt_states (alt_states_list)
3245 alt_state_t alt_states_list;
3247 alt_state_t curr_alt_state;
3248 vla_ptr_t alt_states;
3249 size_t i;
3250 size_t prev_unique_state_ind;
3251 alt_state_t result;
3252 alt_state_t *result_ptr;
3254 VLA_PTR_CREATE (alt_states, 150, "alt_states");
3255 for (curr_alt_state = alt_states_list;
3256 curr_alt_state != NULL;
3257 curr_alt_state = curr_alt_state->next_alt_state)
3258 VLA_PTR_ADD (alt_states, curr_alt_state);
3259 qsort (VLA_PTR_BEGIN (alt_states), VLA_PTR_LENGTH (alt_states),
3260 sizeof (alt_state_t), alt_state_cmp);
3261 if (VLA_PTR_LENGTH (alt_states) == 0)
3262 result = NULL;
3263 else
3265 result_ptr = VLA_PTR_BEGIN (alt_states);
3266 prev_unique_state_ind = 0;
3267 for (i = 1; i < VLA_PTR_LENGTH (alt_states); i++)
3268 if (result_ptr [prev_unique_state_ind]->state != result_ptr [i]->state)
3270 prev_unique_state_ind++;
3271 result_ptr [prev_unique_state_ind] = result_ptr [i];
3273 #if 0
3274 for (i = prev_unique_state_ind + 1; i < VLA_PTR_LENGTH (alt_states); i++)
3275 free_alt_state (result_ptr [i]);
3276 #endif
3277 VLA_PTR_SHORTEN (alt_states, i - prev_unique_state_ind - 1);
3278 result_ptr = VLA_PTR_BEGIN (alt_states);
3279 for (i = 1; i < VLA_PTR_LENGTH (alt_states); i++)
3280 result_ptr [i - 1]->next_sorted_alt_state = result_ptr [i];
3281 result_ptr [i - 1]->next_sorted_alt_state = NULL;
3282 result = *result_ptr;
3284 VLA_PTR_DELETE (alt_states);
3285 return result;
3288 /* The function checks equality of alt state lists. Remember that the
3289 lists must be already sorted by the previous function. */
3290 static int
3291 alt_states_eq (alt_states_1, alt_states_2)
3292 alt_state_t alt_states_1;
3293 alt_state_t alt_states_2;
3295 while (alt_states_1 != NULL && alt_states_2 != NULL
3296 && alt_state_cmp (&alt_states_1, &alt_states_2) == 0)
3298 alt_states_1 = alt_states_1->next_sorted_alt_state;
3299 alt_states_2 = alt_states_2->next_sorted_alt_state;
3301 return alt_states_1 == alt_states_2;
3304 /* Initialization of the abstract data. */
3305 static void
3306 initiate_alt_states ()
3308 first_free_alt_state = NULL;
3311 /* Finishing work with the abstract data. */
3312 static void
3313 finish_alt_states ()
3319 /* The page contains macros for work with bits strings. We could use
3320 standard gcc bitmap or sbitmap but it would result in difficulties
3321 of building canadian cross. */
3323 /* Set bit number bitno in the bit string. The macro is not side
3324 effect proof. */
3325 #define SET_BIT(bitstring, bitno) \
3326 (((char *) (bitstring)) [(bitno) / CHAR_BIT] |= 1 << (bitno) % CHAR_BIT)
3328 /* Test if bit number bitno in the bitstring is set. The macro is not
3329 side effect proof. */
3330 #define TEST_BIT(bitstring, bitno) \
3331 (((char *) (bitstring)) [(bitno) / CHAR_BIT] >> (bitno) % CHAR_BIT & 1)
3335 /* This page contains abstract data `state'. */
3337 /* Maximal length of reservations in cycles (>= 1). */
3338 static int max_cycles_num;
3340 /* Number of set elements (see type set_el_t) needed for
3341 representation of one cycle reservation. It is depended on units
3342 number. */
3343 static int els_in_cycle_reserv;
3345 /* Number of set elements (see type set_el_t) needed for
3346 representation of maximal length reservation. Deterministic
3347 reservation is stored as set (bit string) of length equal to the
3348 variable value * number of bits in set_el_t. */
3349 static int els_in_reservs;
3351 /* VLA for representation of array of pointers to unit
3352 declarations. */
3353 static vla_ptr_t units_container;
3355 /* The start address of the array. */
3356 static unit_decl_t *units_array;
3358 /* Empty reservation of maximal length. */
3359 static reserv_sets_t empty_reserv;
3361 /* The state table itself is represented by the following variable. */
3362 static htab_t state_table;
3364 /* VLA for representation of array of pointers to free nodes
3365 `state'. */
3366 static vla_ptr_t free_states;
3368 static int curr_unique_state_num;
3370 #ifndef NDEBUG
3371 /* The following variables is maximal number of allocated nodes
3372 `state'. */
3373 static int allocated_states_num = 0;
3374 #endif
3376 /* Allocate new reservation set. */
3377 static reserv_sets_t
3378 alloc_empty_reserv_sets ()
3380 reserv_sets_t result;
3382 obstack_blank (&irp, els_in_reservs * sizeof (set_el_t));
3383 result = (reserv_sets_t) obstack_base (&irp);
3384 obstack_finish (&irp);
3385 memset (result, 0, els_in_reservs * sizeof (set_el_t));
3386 return result;
3389 /* Hash value of reservation set. */
3390 static unsigned
3391 reserv_sets_hash_value (reservs)
3392 reserv_sets_t reservs;
3394 set_el_t hash_value;
3395 unsigned result;
3396 int reservs_num, i;
3397 set_el_t *reserv_ptr;
3399 hash_value = 0;
3400 reservs_num = els_in_reservs;
3401 reserv_ptr = reservs;
3402 i = 0;
3403 while (reservs_num != 0)
3405 reservs_num--;
3406 hash_value += ((*reserv_ptr >> i)
3407 | (*reserv_ptr << (sizeof (set_el_t) * CHAR_BIT - i)));
3408 i++;
3409 if (i == sizeof (set_el_t) * CHAR_BIT)
3410 i = 0;
3411 reserv_ptr++;
3413 if (sizeof (set_el_t) <= sizeof (unsigned))
3414 return hash_value;
3415 result = 0;
3416 for (i = sizeof (set_el_t); i > 0; i -= sizeof (unsigned) - 1)
3418 result += (unsigned) hash_value;
3419 hash_value >>= (sizeof (unsigned) - 1) * CHAR_BIT;
3421 return result;
3424 /* Comparison of given reservation sets. */
3425 static int
3426 reserv_sets_cmp (reservs_1, reservs_2)
3427 reserv_sets_t reservs_1;
3428 reserv_sets_t reservs_2;
3430 int reservs_num;
3431 set_el_t *reserv_ptr_1;
3432 set_el_t *reserv_ptr_2;
3434 if (reservs_1 == NULL || reservs_2 == NULL)
3435 abort ();
3436 reservs_num = els_in_reservs;
3437 reserv_ptr_1 = reservs_1;
3438 reserv_ptr_2 = reservs_2;
3439 while (reservs_num != 0 && *reserv_ptr_1 == *reserv_ptr_2)
3441 reservs_num--;
3442 reserv_ptr_1++;
3443 reserv_ptr_2++;
3445 if (reservs_num == 0)
3446 return 0;
3447 else if (*reserv_ptr_1 < *reserv_ptr_2)
3448 return -1;
3449 else
3450 return 1;
3453 /* The function checks equality of the reservation sets. */
3454 static int
3455 reserv_sets_eq (reservs_1, reservs_2)
3456 reserv_sets_t reservs_1;
3457 reserv_sets_t reservs_2;
3459 return reserv_sets_cmp (reservs_1, reservs_2) == 0;
3462 /* Set up in the reservation set that unit with UNIT_NUM is used on
3463 CYCLE_NUM. */
3464 static void
3465 set_unit_reserv (reservs, cycle_num, unit_num)
3466 reserv_sets_t reservs;
3467 int cycle_num;
3468 int unit_num;
3470 if (cycle_num >= max_cycles_num)
3471 abort ();
3472 SET_BIT (reservs, cycle_num * els_in_cycle_reserv
3473 * sizeof (set_el_t) * CHAR_BIT + unit_num);
3476 /* Set up in the reservation set RESERVS that unit with UNIT_NUM is
3477 used on CYCLE_NUM. */
3478 static int
3479 test_unit_reserv (reservs, cycle_num, unit_num)
3480 reserv_sets_t reservs;
3481 int cycle_num;
3482 int unit_num;
3484 if (cycle_num >= max_cycles_num)
3485 abort ();
3486 return TEST_BIT (reservs, cycle_num * els_in_cycle_reserv
3487 * sizeof (set_el_t) * CHAR_BIT + unit_num);
3490 /* The function checks that the reservation set represents no one unit
3491 reservation. */
3492 static int
3493 it_is_empty_reserv_sets (operand)
3494 reserv_sets_t operand;
3496 set_el_t *reserv_ptr;
3497 int reservs_num;
3499 if (operand == NULL)
3500 abort ();
3501 for (reservs_num = els_in_reservs, reserv_ptr = operand;
3502 reservs_num != 0;
3503 reserv_ptr++, reservs_num--)
3504 if (*reserv_ptr != 0)
3505 return 0;
3506 return 1;
3509 /* The function checks that the reservation sets are intersected,
3510 i.e. there is a unit reservation on a cycle in both reservation
3511 sets. */
3512 static int
3513 reserv_sets_are_intersected (operand_1, operand_2)
3514 reserv_sets_t operand_1;
3515 reserv_sets_t operand_2;
3517 set_el_t *el_ptr_1;
3518 set_el_t *el_ptr_2;
3519 set_el_t *cycle_ptr_1;
3520 set_el_t *cycle_ptr_2;
3521 int nonzero_p;
3523 if (operand_1 == NULL || operand_2 == NULL)
3524 abort ();
3525 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2;
3526 el_ptr_1 < operand_1 + els_in_reservs;
3527 el_ptr_1++, el_ptr_2++)
3528 if (*el_ptr_1 & *el_ptr_2)
3529 return 1;
3530 for (cycle_ptr_1 = operand_1, cycle_ptr_2 = operand_2;
3531 cycle_ptr_1 < operand_1 + els_in_reservs;
3532 cycle_ptr_1 += els_in_cycle_reserv, cycle_ptr_2 += els_in_cycle_reserv)
3534 for (el_ptr_1 = cycle_ptr_1, el_ptr_2 = get_excl_set (cycle_ptr_2);
3535 el_ptr_1 < cycle_ptr_1 + els_in_cycle_reserv;
3536 el_ptr_1++, el_ptr_2++)
3537 if (*el_ptr_1 & *el_ptr_2)
3538 return 1;
3539 nonzero_p = 0;
3540 for (el_ptr_1 = cycle_ptr_1,
3541 el_ptr_2 = get_presence_absence_set (cycle_ptr_2, 1);
3542 el_ptr_1 < cycle_ptr_1 + els_in_cycle_reserv;
3543 el_ptr_1++, el_ptr_2++)
3544 if (*el_ptr_1 & *el_ptr_2)
3545 break;
3546 else if (*el_ptr_2 != 0)
3547 nonzero_p = 1;
3548 if (nonzero_p && el_ptr_1 >= cycle_ptr_1 + els_in_cycle_reserv)
3549 return 1;
3550 for (el_ptr_1 = cycle_ptr_1,
3551 el_ptr_2 = get_presence_absence_set (cycle_ptr_2, 0);
3552 el_ptr_1 < cycle_ptr_1 + els_in_cycle_reserv;
3553 el_ptr_1++, el_ptr_2++)
3554 /* It looks like code for exclusion but exclusion set is
3555 made as symmetric relation preliminary. */
3556 if (*el_ptr_1 & *el_ptr_2)
3557 return 1;
3559 return 0;
3562 /* The function sets up RESULT bits by bits of OPERAND shifted on one
3563 cpu cycle. The remaining bits of OPERAND (representing the last
3564 cycle unit reservations) are not chenged. */
3565 static void
3566 reserv_sets_shift (result, operand)
3567 reserv_sets_t result;
3568 reserv_sets_t operand;
3570 int i;
3572 if (result == NULL || operand == NULL || result == operand)
3573 abort ();
3574 for (i = els_in_cycle_reserv; i < els_in_reservs; i++)
3575 result [i - els_in_cycle_reserv] = operand [i];
3578 /* OR of the reservation sets. */
3579 static void
3580 reserv_sets_or (result, operand_1, operand_2)
3581 reserv_sets_t result;
3582 reserv_sets_t operand_1;
3583 reserv_sets_t operand_2;
3585 set_el_t *el_ptr_1;
3586 set_el_t *el_ptr_2;
3587 set_el_t *result_set_el_ptr;
3589 if (result == NULL || operand_1 == NULL || operand_2 == NULL)
3590 abort ();
3591 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2, result_set_el_ptr = result;
3592 el_ptr_1 < operand_1 + els_in_reservs;
3593 el_ptr_1++, el_ptr_2++, result_set_el_ptr++)
3594 *result_set_el_ptr = *el_ptr_1 | *el_ptr_2;
3597 /* AND of the reservation sets. */
3598 static void
3599 reserv_sets_and (result, operand_1, operand_2)
3600 reserv_sets_t result;
3601 reserv_sets_t operand_1;
3602 reserv_sets_t operand_2;
3604 set_el_t *el_ptr_1;
3605 set_el_t *el_ptr_2;
3606 set_el_t *result_set_el_ptr;
3608 if (result == NULL || operand_1 == NULL || operand_2 == NULL)
3609 abort ();
3610 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2, result_set_el_ptr = result;
3611 el_ptr_1 < operand_1 + els_in_reservs;
3612 el_ptr_1++, el_ptr_2++, result_set_el_ptr++)
3613 *result_set_el_ptr = *el_ptr_1 & *el_ptr_2;
3616 /* The function outputs string representation of units reservation on
3617 cycle START_CYCLE in the reservation set. The function uses repeat
3618 construction if REPETITION_NUM > 1. */
3619 static void
3620 output_cycle_reservs (f, reservs, start_cycle, repetition_num)
3621 FILE *f;
3622 reserv_sets_t reservs;
3623 int start_cycle;
3624 int repetition_num;
3626 int unit_num;
3627 int reserved_units_num;
3629 reserved_units_num = 0;
3630 for (unit_num = 0; unit_num < description->units_num; unit_num++)
3631 if (TEST_BIT (reservs, start_cycle * els_in_cycle_reserv
3632 * sizeof (set_el_t) * CHAR_BIT + unit_num))
3633 reserved_units_num++;
3634 if (repetition_num <= 0)
3635 abort ();
3636 if (repetition_num != 1 && reserved_units_num > 1)
3637 fprintf (f, "(");
3638 reserved_units_num = 0;
3639 for (unit_num = 0;
3640 unit_num < description->units_num;
3641 unit_num++)
3642 if (TEST_BIT (reservs, start_cycle * els_in_cycle_reserv
3643 * sizeof (set_el_t) * CHAR_BIT + unit_num))
3645 if (reserved_units_num != 0)
3646 fprintf (f, "+");
3647 reserved_units_num++;
3648 fprintf (f, "%s", units_array [unit_num]->name);
3650 if (reserved_units_num == 0)
3651 fprintf (f, NOTHING_NAME);
3652 if (repetition_num <= 0)
3653 abort ();
3654 if (reserved_units_num > 1)
3655 fprintf (f, ")");
3656 if (repetition_num != 1)
3657 fprintf (f, "*%d", repetition_num);
3660 /* The function outputs string representation of units reservation in
3661 the reservation set. */
3662 static void
3663 output_reserv_sets (f, reservs)
3664 FILE *f;
3665 reserv_sets_t reservs;
3667 int start_cycle = 0;
3668 int cycle;
3669 int repetition_num;
3671 repetition_num = 0;
3672 for (cycle = 0; cycle < max_cycles_num; cycle++)
3673 if (repetition_num == 0)
3675 repetition_num++;
3676 start_cycle = cycle;
3678 else if (memcmp
3679 ((char *) reservs + start_cycle * els_in_cycle_reserv
3680 * sizeof (set_el_t),
3681 (char *) reservs + cycle * els_in_cycle_reserv
3682 * sizeof (set_el_t),
3683 els_in_cycle_reserv * sizeof (set_el_t)) == 0)
3684 repetition_num++;
3685 else
3687 if (start_cycle != 0)
3688 fprintf (f, ", ");
3689 output_cycle_reservs (f, reservs, start_cycle, repetition_num);
3690 repetition_num = 1;
3691 start_cycle = cycle;
3693 if (start_cycle < max_cycles_num)
3695 if (start_cycle != 0)
3696 fprintf (f, ", ");
3697 output_cycle_reservs (f, reservs, start_cycle, repetition_num);
3701 /* The following function returns free node state for AUTOMATON. It
3702 may be new allocated node or node freed eralier. The function also
3703 allocates reservation set if WITH_RESERVS has nonzero value. */
3704 static state_t
3705 get_free_state (with_reservs, automaton)
3706 int with_reservs;
3707 automaton_t automaton;
3709 state_t result;
3711 if (max_cycles_num <= 0 || automaton == NULL)
3712 abort ();
3713 if (VLA_PTR_LENGTH (free_states) != 0)
3715 result = VLA_PTR (free_states, VLA_PTR_LENGTH (free_states) - 1);
3716 VLA_PTR_SHORTEN (free_states, 1);
3717 result->automaton = automaton;
3718 result->first_out_arc = NULL;
3719 result->it_was_placed_in_stack_for_NDFA_forming = 0;
3720 result->it_was_placed_in_stack_for_DFA_forming = 0;
3721 result->component_states = NULL;
3722 result->longest_path_length = UNDEFINED_LONGEST_PATH_LENGTH;
3724 else
3726 #ifndef NDEBUG
3727 allocated_states_num++;
3728 #endif
3729 result = create_node (sizeof (struct state));
3730 result->automaton = automaton;
3731 result->first_out_arc = NULL;
3732 result->unique_num = curr_unique_state_num;
3733 result->longest_path_length = UNDEFINED_LONGEST_PATH_LENGTH;
3734 curr_unique_state_num++;
3736 if (with_reservs)
3738 if (result->reservs == NULL)
3739 result->reservs = alloc_empty_reserv_sets ();
3740 else
3741 memset (result->reservs, 0, els_in_reservs * sizeof (set_el_t));
3743 return result;
3746 /* The function frees node STATE. */
3747 static void
3748 free_state (state)
3749 state_t state;
3751 free_alt_states (state->component_states);
3752 VLA_PTR_ADD (free_states, state);
3755 /* Hash value of STATE. If STATE represents deterministic state it is
3756 simply hash value of the corresponding reservation set. Otherwise
3757 it is formed from hash values of the component deterministic
3758 states. One more key is order number of state automaton. */
3759 static unsigned
3760 state_hash (state)
3761 const void *state;
3763 unsigned int hash_value;
3764 alt_state_t alt_state;
3766 if (((state_t) state)->component_states == NULL)
3767 hash_value = reserv_sets_hash_value (((state_t) state)->reservs);
3768 else
3770 hash_value = 0;
3771 for (alt_state = ((state_t) state)->component_states;
3772 alt_state != NULL;
3773 alt_state = alt_state->next_sorted_alt_state)
3774 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
3775 | (hash_value << CHAR_BIT))
3776 + alt_state->state->unique_num);
3778 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
3779 | (hash_value << CHAR_BIT))
3780 + ((state_t) state)->automaton->automaton_order_num);
3781 return hash_value;
3784 /* Return nonzero value if the states are the same. */
3785 static int
3786 state_eq_p (state_1, state_2)
3787 const void *state_1;
3788 const void *state_2;
3790 alt_state_t alt_state_1;
3791 alt_state_t alt_state_2;
3793 if (((state_t) state_1)->automaton != ((state_t) state_2)->automaton)
3794 return 0;
3795 else if (((state_t) state_1)->component_states == NULL
3796 && ((state_t) state_2)->component_states == NULL)
3797 return reserv_sets_eq (((state_t) state_1)->reservs,
3798 ((state_t) state_2)->reservs);
3799 else if (((state_t) state_1)->component_states != NULL
3800 && ((state_t) state_2)->component_states != NULL)
3802 for (alt_state_1 = ((state_t) state_1)->component_states,
3803 alt_state_2 = ((state_t) state_2)->component_states;
3804 alt_state_1 != NULL && alt_state_2 != NULL;
3805 alt_state_1 = alt_state_1->next_sorted_alt_state,
3806 alt_state_2 = alt_state_2->next_sorted_alt_state)
3807 /* All state in the list must be already in the hash table.
3808 Also the lists must be sorted. */
3809 if (alt_state_1->state != alt_state_2->state)
3810 return 0;
3811 return alt_state_1 == alt_state_2;
3813 else
3814 return 0;
3817 /* Insert STATE into the state table. */
3818 static state_t
3819 insert_state (state)
3820 state_t state;
3822 void **entry_ptr;
3824 entry_ptr = htab_find_slot (state_table, (void *) state, 1);
3825 if (*entry_ptr == NULL)
3826 *entry_ptr = (void *) state;
3827 return (state_t) *entry_ptr;
3830 /* Add reservation of unit with UNIT_NUM on cycle CYCLE_NUM to
3831 deterministic STATE. */
3832 static void
3833 set_state_reserv (state, cycle_num, unit_num)
3834 state_t state;
3835 int cycle_num;
3836 int unit_num;
3838 set_unit_reserv (state->reservs, cycle_num, unit_num);
3841 /* Return nonzero value if the deterministic states contains a
3842 reservation of the same cpu unit on the same cpu cycle. */
3843 static int
3844 intersected_state_reservs_p (state1, state2)
3845 state_t state1;
3846 state_t state2;
3848 if (state1->automaton != state2->automaton)
3849 abort ();
3850 return reserv_sets_are_intersected (state1->reservs, state2->reservs);
3853 /* Return deterministic state (inserted into the table) which
3854 representing the automaton state whic is union of reservations of
3855 deterministic states. */
3856 static state_t
3857 states_union (state1, state2)
3858 state_t state1;
3859 state_t state2;
3861 state_t result;
3862 state_t state_in_table;
3864 if (state1->automaton != state2->automaton)
3865 abort ();
3866 result = get_free_state (1, state1->automaton);
3867 reserv_sets_or (result->reservs, state1->reservs, state2->reservs);
3868 state_in_table = insert_state (result);
3869 if (result != state_in_table)
3871 free_state (result);
3872 result = state_in_table;
3874 return result;
3877 /* Return deterministic state (inserted into the table) which
3878 represent the automaton state is obtained from deterministic STATE
3879 by advancing cpu cycle. */
3880 static state_t
3881 state_shift (state)
3882 state_t state;
3884 state_t result;
3885 state_t state_in_table;
3887 result = get_free_state (1, state->automaton);
3888 reserv_sets_shift (result->reservs, state->reservs);
3889 state_in_table = insert_state (result);
3890 if (result != state_in_table)
3892 free_state (result);
3893 result = state_in_table;
3895 return result;
3898 /* Initialization of the abstract data. */
3899 static void
3900 initiate_states ()
3902 decl_t decl;
3903 int i;
3905 VLA_PTR_CREATE (units_container, description->units_num, "units_container");
3906 units_array
3907 = (description->decls_num && description->units_num
3908 ? VLA_PTR_BEGIN (units_container) : NULL);
3909 for (i = 0; i < description->decls_num; i++)
3911 decl = description->decls [i];
3912 if (decl->mode == dm_unit)
3913 units_array [decl->decl.unit.unit_num] = &decl->decl.unit;
3915 max_cycles_num = description->max_insn_reserv_cycles;
3916 els_in_cycle_reserv
3917 = ((description->units_num + sizeof (set_el_t) * CHAR_BIT - 1)
3918 / (sizeof (set_el_t) * CHAR_BIT));
3919 els_in_reservs = els_in_cycle_reserv * max_cycles_num;
3920 curr_unique_state_num = 0;
3921 initiate_alt_states ();
3922 VLA_PTR_CREATE (free_states, 1500, "free states");
3923 state_table = htab_create (1500, state_hash, state_eq_p, (htab_del) 0);
3924 empty_reserv = alloc_empty_reserv_sets ();
3927 /* Finisging work with the abstract data. */
3928 static void
3929 finish_states ()
3931 VLA_PTR_DELETE (units_container);
3932 htab_delete (state_table);
3933 VLA_PTR_DELETE (free_states);
3934 finish_alt_states ();
3939 /* Abstract data `arcs'. */
3941 /* List of free arcs. */
3942 static arc_t first_free_arc;
3944 #ifndef NDEBUG
3945 /* The following variables is maximal number of allocated nodes
3946 `arc'. */
3947 static int allocated_arcs_num = 0;
3948 #endif
3950 /* The function frees node ARC. */
3951 static void
3952 free_arc (arc)
3953 arc_t arc;
3955 arc->next_out_arc = first_free_arc;
3956 first_free_arc = arc;
3959 /* The function removes and frees ARC staring from FROM_STATE. */
3960 static void
3961 remove_arc (from_state, arc)
3962 state_t from_state;
3963 arc_t arc;
3965 arc_t prev_arc;
3966 arc_t curr_arc;
3968 if (arc == NULL)
3969 abort ();
3970 for (prev_arc = NULL, curr_arc = from_state->first_out_arc;
3971 curr_arc != NULL;
3972 prev_arc = curr_arc, curr_arc = curr_arc->next_out_arc)
3973 if (curr_arc == arc)
3974 break;
3975 if (curr_arc == NULL)
3976 abort ();
3977 if (prev_arc == NULL)
3978 from_state->first_out_arc = arc->next_out_arc;
3979 else
3980 prev_arc->next_out_arc = arc->next_out_arc;
3981 free_arc (arc);
3984 /* The functions returns arc with given characteristics (or NULL if
3985 the arc does not exist). */
3986 static arc_t
3987 find_arc (from_state, to_state, insn)
3988 state_t from_state;
3989 state_t to_state;
3990 ainsn_t insn;
3992 arc_t arc;
3994 for (arc = first_out_arc (from_state); arc != NULL; arc = next_out_arc (arc))
3995 if (arc->to_state == to_state && arc->insn == insn)
3996 return arc;
3997 return NULL;
4000 /* The function adds arc from FROM_STATE to TO_STATE marked by AINSN
4001 and with given STATE_ALTS. The function returns added arc (or
4002 already existing arc). */
4003 static arc_t
4004 add_arc (from_state, to_state, ainsn, state_alts)
4005 state_t from_state;
4006 state_t to_state;
4007 ainsn_t ainsn;
4008 int state_alts;
4010 arc_t new_arc;
4012 new_arc = find_arc (from_state, to_state, ainsn);
4013 if (new_arc != NULL)
4014 return new_arc;
4015 if (first_free_arc == NULL)
4017 #ifndef NDEBUG
4018 allocated_arcs_num++;
4019 #endif
4020 new_arc = create_node (sizeof (struct arc));
4021 new_arc->to_state = NULL;
4022 new_arc->insn = NULL;
4023 new_arc->next_out_arc = NULL;
4025 else
4027 new_arc = first_free_arc;
4028 first_free_arc = first_free_arc->next_out_arc;
4030 new_arc->to_state = to_state;
4031 new_arc->insn = ainsn;
4032 ainsn->arc_exists_p = 1;
4033 new_arc->next_out_arc = from_state->first_out_arc;
4034 from_state->first_out_arc = new_arc;
4035 new_arc->next_arc_marked_by_insn = NULL;
4036 new_arc->state_alts = state_alts;
4037 return new_arc;
4040 /* The function returns the first arc starting from STATE. */
4041 static arc_t
4042 first_out_arc (state)
4043 state_t state;
4045 return state->first_out_arc;
4048 /* The function returns next out arc after ARC. */
4049 static arc_t
4050 next_out_arc (arc)
4051 arc_t arc;
4053 return arc->next_out_arc;
4056 /* Initialization of the abstract data. */
4057 static void
4058 initiate_arcs ()
4060 first_free_arc = NULL;
4063 /* Finishing work with the abstract data. */
4064 static void
4065 finish_arcs ()
4071 /* Abstract data `automata lists'. */
4073 /* List of free states. */
4074 static automata_list_el_t first_free_automata_list_el;
4076 /* The list being formed. */
4077 static automata_list_el_t current_automata_list;
4079 /* Hash table of automata lists. */
4080 static htab_t automata_list_table;
4082 /* The following function returns free automata list el. It may be
4083 new allocated node or node freed earlier. */
4084 static automata_list_el_t
4085 get_free_automata_list_el ()
4087 automata_list_el_t result;
4089 if (first_free_automata_list_el != NULL)
4091 result = first_free_automata_list_el;
4092 first_free_automata_list_el
4093 = first_free_automata_list_el->next_automata_list_el;
4095 else
4096 result = create_node (sizeof (struct automata_list_el));
4097 result->automaton = NULL;
4098 result->next_automata_list_el = NULL;
4099 return result;
4102 /* The function frees node AUTOMATA_LIST_EL. */
4103 static void
4104 free_automata_list_el (automata_list_el)
4105 automata_list_el_t automata_list_el;
4107 if (automata_list_el == NULL)
4108 return;
4109 automata_list_el->next_automata_list_el = first_free_automata_list_el;
4110 first_free_automata_list_el = automata_list_el;
4113 /* The function frees list AUTOMATA_LIST. */
4114 static void
4115 free_automata_list (automata_list)
4116 automata_list_el_t automata_list;
4118 automata_list_el_t curr_automata_list_el;
4119 automata_list_el_t next_automata_list_el;
4121 for (curr_automata_list_el = automata_list;
4122 curr_automata_list_el != NULL;
4123 curr_automata_list_el = next_automata_list_el)
4125 next_automata_list_el = curr_automata_list_el->next_automata_list_el;
4126 free_automata_list_el (curr_automata_list_el);
4130 /* Hash value of AUTOMATA_LIST. */
4131 static unsigned
4132 automata_list_hash (automata_list)
4133 const void *automata_list;
4135 unsigned int hash_value;
4136 automata_list_el_t curr_automata_list_el;
4138 hash_value = 0;
4139 for (curr_automata_list_el = (automata_list_el_t) automata_list;
4140 curr_automata_list_el != NULL;
4141 curr_automata_list_el = curr_automata_list_el->next_automata_list_el)
4142 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
4143 | (hash_value << CHAR_BIT))
4144 + curr_automata_list_el->automaton->automaton_order_num);
4145 return hash_value;
4148 /* Return nonzero value if the automata_lists are the same. */
4149 static int
4150 automata_list_eq_p (automata_list_1, automata_list_2)
4151 const void *automata_list_1;
4152 const void *automata_list_2;
4154 automata_list_el_t automata_list_el_1;
4155 automata_list_el_t automata_list_el_2;
4157 for (automata_list_el_1 = (automata_list_el_t) automata_list_1,
4158 automata_list_el_2 = (automata_list_el_t) automata_list_2;
4159 automata_list_el_1 != NULL && automata_list_el_2 != NULL;
4160 automata_list_el_1 = automata_list_el_1->next_automata_list_el,
4161 automata_list_el_2 = automata_list_el_2->next_automata_list_el)
4162 if (automata_list_el_1->automaton != automata_list_el_2->automaton)
4163 return 0;
4164 return automata_list_el_1 == automata_list_el_2;
4167 /* Initialization of the abstract data. */
4168 static void
4169 initiate_automata_lists ()
4171 first_free_automata_list_el = NULL;
4172 automata_list_table = htab_create (1500, automata_list_hash,
4173 automata_list_eq_p, (htab_del) 0);
4176 /* The following function starts new automata list and makes it the
4177 current one. */
4178 static void
4179 automata_list_start ()
4181 current_automata_list = NULL;
4184 /* The following function adds AUTOMATON to the current list. */
4185 static void
4186 automata_list_add (automaton)
4187 automaton_t automaton;
4189 automata_list_el_t el;
4191 el = get_free_automata_list_el ();
4192 el->automaton = automaton;
4193 el->next_automata_list_el = current_automata_list;
4194 current_automata_list = el;
4197 /* The following function finishes forming the current list, inserts
4198 it into the table and returns it. */
4199 static automata_list_el_t
4200 automata_list_finish ()
4202 void **entry_ptr;
4204 if (current_automata_list == NULL)
4205 return NULL;
4206 entry_ptr = htab_find_slot (automata_list_table,
4207 (void *) current_automata_list, 1);
4208 if (*entry_ptr == NULL)
4209 *entry_ptr = (void *) current_automata_list;
4210 else
4211 free_automata_list (current_automata_list);
4212 current_automata_list = NULL;
4213 return (automata_list_el_t) *entry_ptr;
4216 /* Finishing work with the abstract data. */
4217 static void
4218 finish_automata_lists ()
4220 htab_delete (automata_list_table);
4225 /* The page contains abstract data for work with exclusion sets (see
4226 exclusion_set in file rtl.def). */
4228 /* The following variable refers to an exclusion set returned by
4229 get_excl_set. This is bit string of length equal to cpu units
4230 number. If exclusion set for given unit contains 1 for a unit,
4231 then simultaneous reservation of the units is prohibited. */
4232 static reserv_sets_t excl_set;
4234 /* The array contains exclusion sets for each unit. */
4235 static reserv_sets_t *unit_excl_set_table;
4237 /* The following function forms the array containing exclusion sets
4238 for each unit. */
4239 static void
4240 initiate_excl_sets ()
4242 decl_t decl;
4243 reserv_sets_t unit_excl_set;
4244 unit_set_el_t el;
4245 int i;
4247 obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4248 excl_set = (reserv_sets_t) obstack_base (&irp);
4249 obstack_finish (&irp);
4250 obstack_blank (&irp, description->units_num * sizeof (reserv_sets_t));
4251 unit_excl_set_table = (reserv_sets_t *) obstack_base (&irp);
4252 obstack_finish (&irp);
4253 /* Evaluate unit exclusion sets. */
4254 for (i = 0; i < description->decls_num; i++)
4256 decl = description->decls [i];
4257 if (decl->mode == dm_unit)
4259 obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4260 unit_excl_set = (reserv_sets_t) obstack_base (&irp);
4261 obstack_finish (&irp);
4262 memset (unit_excl_set, 0, els_in_cycle_reserv * sizeof (set_el_t));
4263 for (el = decl->decl.unit.excl_list;
4264 el != NULL;
4265 el = el->next_unit_set_el)
4266 SET_BIT (unit_excl_set, el->unit_decl->unit_num);
4267 unit_excl_set_table [decl->decl.unit.unit_num] = unit_excl_set;
4272 /* The function sets up and return EXCL_SET which is union of
4273 exclusion sets for each unit in IN_SET. */
4274 static reserv_sets_t
4275 get_excl_set (in_set)
4276 reserv_sets_t in_set;
4278 int excl_char_num;
4279 int chars_num;
4280 int i;
4281 int start_unit_num;
4282 int unit_num;
4284 chars_num = els_in_cycle_reserv * sizeof (set_el_t);
4285 memset (excl_set, 0, chars_num);
4286 for (excl_char_num = 0; excl_char_num < chars_num; excl_char_num++)
4287 if (((unsigned char *) in_set) [excl_char_num])
4288 for (i = CHAR_BIT - 1; i >= 0; i--)
4289 if ((((unsigned char *) in_set) [excl_char_num] >> i) & 1)
4291 start_unit_num = excl_char_num * CHAR_BIT + i;
4292 if (start_unit_num >= description->units_num)
4293 return excl_set;
4294 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4296 excl_set [unit_num]
4297 |= unit_excl_set_table [start_unit_num] [unit_num];
4300 return excl_set;
4305 /* The page contains abstract data for work with presence/absence sets
4306 (see presence_set/absence_set in file rtl.def). */
4308 /* The following variables refer to correspondingly an presence and an
4309 absence set returned by get_presence_absence_set. This is bit
4310 string of length equal to cpu units number. */
4311 static reserv_sets_t presence_set, absence_set;
4313 /* The following arrays contain correspondingly presence and absence
4314 sets for each unit. */
4315 static reserv_sets_t *unit_presence_set_table, *unit_absence_set_table;
4317 /* The following function forms the array containing presence and
4318 absence sets for each unit */
4319 static void
4320 initiate_presence_absence_sets ()
4322 decl_t decl;
4323 reserv_sets_t unit_set;
4324 unit_set_el_t el;
4325 int i;
4327 obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4328 presence_set = (reserv_sets_t) obstack_base (&irp);
4329 obstack_finish (&irp);
4330 obstack_blank (&irp, description->units_num * sizeof (reserv_sets_t));
4331 unit_presence_set_table = (reserv_sets_t *) obstack_base (&irp);
4332 obstack_finish (&irp);
4333 obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4334 absence_set = (reserv_sets_t) obstack_base (&irp);
4335 obstack_finish (&irp);
4336 obstack_blank (&irp, description->units_num * sizeof (reserv_sets_t));
4337 unit_absence_set_table = (reserv_sets_t *) obstack_base (&irp);
4338 obstack_finish (&irp);
4339 /* Evaluate unit presence/absence sets. */
4340 for (i = 0; i < description->decls_num; i++)
4342 decl = description->decls [i];
4343 if (decl->mode == dm_unit)
4345 obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4346 unit_set = (reserv_sets_t) obstack_base (&irp);
4347 obstack_finish (&irp);
4348 memset (unit_set, 0, els_in_cycle_reserv * sizeof (set_el_t));
4349 for (el = decl->decl.unit.presence_list;
4350 el != NULL;
4351 el = el->next_unit_set_el)
4352 SET_BIT (unit_set, el->unit_decl->unit_num);
4353 unit_presence_set_table [decl->decl.unit.unit_num] = unit_set;
4355 obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4356 unit_set = (reserv_sets_t) obstack_base (&irp);
4357 obstack_finish (&irp);
4358 memset (unit_set, 0, els_in_cycle_reserv * sizeof (set_el_t));
4359 for (el = decl->decl.unit.absence_list;
4360 el != NULL;
4361 el = el->next_unit_set_el)
4362 SET_BIT (unit_set, el->unit_decl->unit_num);
4363 unit_absence_set_table [decl->decl.unit.unit_num] = unit_set;
4368 /* The function sets up and return PRESENCE_SET (if PRESENCE_P) or
4369 ABSENCE_SET which is union of corresponding sets for each unit in
4370 IN_SET. */
4371 static reserv_sets_t
4372 get_presence_absence_set (in_set, presence_p)
4373 reserv_sets_t in_set;
4374 int presence_p;
4376 int char_num;
4377 int chars_num;
4378 int i;
4379 int start_unit_num;
4380 int unit_num;
4382 chars_num = els_in_cycle_reserv * sizeof (set_el_t);
4383 if (presence_p)
4384 memset (presence_set, 0, chars_num);
4385 else
4386 memset (absence_set, 0, chars_num);
4387 for (char_num = 0; char_num < chars_num; char_num++)
4388 if (((unsigned char *) in_set) [char_num])
4389 for (i = CHAR_BIT - 1; i >= 0; i--)
4390 if ((((unsigned char *) in_set) [char_num] >> i) & 1)
4392 start_unit_num = char_num * CHAR_BIT + i;
4393 if (start_unit_num >= description->units_num)
4394 return (presence_p ? presence_set : absence_set);
4395 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4396 if (presence_p)
4397 presence_set [unit_num]
4398 |= unit_presence_set_table [start_unit_num] [unit_num];
4399 else
4400 absence_set [unit_num]
4401 |= unit_absence_set_table [start_unit_num] [unit_num];
4403 return (presence_p ? presence_set : absence_set);
4408 /* This page contains code for transformation of original reservations
4409 described in .md file. The main goal of transformations is
4410 simplifying reservation and lifting up all `|' on the top of IR
4411 reservation representation. */
4414 /* The following function makes copy of IR representation of
4415 reservation. The function also substitutes all reservations
4416 defined by define_reservation by corresponding value during making
4417 the copy. */
4418 static regexp_t
4419 copy_insn_regexp (regexp)
4420 regexp_t regexp;
4422 regexp_t result;
4423 int i;
4425 if (regexp->mode == rm_reserv)
4426 result = copy_insn_regexp (regexp->regexp.reserv.reserv_decl->regexp);
4427 else if (regexp->mode == rm_unit)
4428 result = copy_node (regexp, sizeof (struct regexp));
4429 else if (regexp->mode == rm_repeat)
4431 result = copy_node (regexp, sizeof (struct regexp));
4432 result->regexp.repeat.regexp
4433 = copy_insn_regexp (regexp->regexp.repeat.regexp);
4435 else if (regexp->mode == rm_sequence)
4437 result = copy_node (regexp,
4438 sizeof (struct regexp) + sizeof (regexp_t)
4439 * (regexp->regexp.sequence.regexps_num - 1));
4440 for (i = 0; i < regexp->regexp.sequence.regexps_num; i++)
4441 result->regexp.sequence.regexps [i]
4442 = copy_insn_regexp (regexp->regexp.sequence.regexps [i]);
4444 else if (regexp->mode == rm_allof)
4446 result = copy_node (regexp,
4447 sizeof (struct regexp) + sizeof (regexp_t)
4448 * (regexp->regexp.allof.regexps_num - 1));
4449 for (i = 0; i < regexp->regexp.allof.regexps_num; i++)
4450 result->regexp.allof.regexps [i]
4451 = copy_insn_regexp (regexp->regexp.allof.regexps [i]);
4453 else if (regexp->mode == rm_oneof)
4455 result = copy_node (regexp,
4456 sizeof (struct regexp) + sizeof (regexp_t)
4457 * (regexp->regexp.oneof.regexps_num - 1));
4458 for (i = 0; i < regexp->regexp.oneof.regexps_num; i++)
4459 result->regexp.oneof.regexps [i]
4460 = copy_insn_regexp (regexp->regexp.oneof.regexps [i]);
4462 else
4464 if (regexp->mode != rm_nothing)
4465 abort ();
4466 result = copy_node (regexp, sizeof (struct regexp));
4468 return result;
4471 /* The following variable is set up 1 if a transformation has been
4472 applied. */
4473 static int regexp_transformed_p;
4475 /* The function makes transformation
4476 A*N -> A, A, ... */
4477 static regexp_t
4478 transform_1 (regexp)
4479 regexp_t regexp;
4481 int i;
4482 int repeat_num;
4483 regexp_t operand;
4484 pos_t pos;
4486 if (regexp->mode == rm_repeat)
4488 repeat_num = regexp->regexp.repeat.repeat_num;
4489 if (repeat_num <= 1)
4490 abort ();
4491 operand = regexp->regexp.repeat.regexp;
4492 pos = regexp->mode;
4493 regexp = create_node (sizeof (struct regexp) + sizeof (regexp_t)
4494 * (repeat_num - 1));
4495 regexp->mode = rm_sequence;
4496 regexp->pos = pos;
4497 regexp->regexp.sequence.regexps_num = repeat_num;
4498 for (i = 0; i < repeat_num; i++)
4499 regexp->regexp.sequence.regexps [i] = copy_insn_regexp (operand);
4500 regexp_transformed_p = 1;
4502 return regexp;
4505 /* The function makes transformations
4506 ...,(A,B,...),C,... -> ...,A,B,...,C,...
4507 ...+(A+B+...)+C+... -> ...+A+B+...+C+...
4508 ...|(A|B|...)|C|... -> ...|A|B|...|C|... */
4509 static regexp_t
4510 transform_2 (regexp)
4511 regexp_t regexp;
4513 if (regexp->mode == rm_sequence)
4515 regexp_t sequence;
4516 regexp_t result;
4517 int sequence_index;
4518 int i, j;
4520 for (i = 0; i < regexp->regexp.sequence.regexps_num; i++)
4521 if (regexp->regexp.sequence.regexps [i]->mode == rm_sequence)
4523 sequence_index = i;
4524 sequence = regexp->regexp.sequence.regexps [i];
4525 break;
4527 if (i < regexp->regexp.sequence.regexps_num)
4529 if (sequence->regexp.sequence.regexps_num <= 1
4530 || regexp->regexp.sequence.regexps_num <= 1)
4531 abort ();
4532 result = create_node (sizeof (struct regexp)
4533 + sizeof (regexp_t)
4534 * (regexp->regexp.sequence.regexps_num
4535 + sequence->regexp.sequence.regexps_num
4536 - 2));
4537 result->mode = rm_sequence;
4538 result->pos = regexp->pos;
4539 result->regexp.sequence.regexps_num
4540 = (regexp->regexp.sequence.regexps_num
4541 + sequence->regexp.sequence.regexps_num - 1);
4542 for (i = 0; i < regexp->regexp.sequence.regexps_num; i++)
4543 if (i < sequence_index)
4544 result->regexp.sequence.regexps [i]
4545 = copy_insn_regexp (regexp->regexp.sequence.regexps [i]);
4546 else if (i > sequence_index)
4547 result->regexp.sequence.regexps
4548 [i + sequence->regexp.sequence.regexps_num - 1]
4549 = copy_insn_regexp (regexp->regexp.sequence.regexps [i]);
4550 else
4551 for (j = 0; j < sequence->regexp.sequence.regexps_num; j++)
4552 result->regexp.sequence.regexps [i + j]
4553 = copy_insn_regexp (sequence->regexp.sequence.regexps [j]);
4554 regexp_transformed_p = 1;
4555 regexp = result;
4558 else if (regexp->mode == rm_allof)
4560 regexp_t allof;
4561 regexp_t result;
4562 int allof_index;
4563 int i, j;
4565 for (i = 0; i < regexp->regexp.allof.regexps_num; i++)
4566 if (regexp->regexp.allof.regexps [i]->mode == rm_allof)
4568 allof_index = i;
4569 allof = regexp->regexp.allof.regexps [i];
4570 break;
4572 if (i < regexp->regexp.allof.regexps_num)
4574 if (allof->regexp.allof.regexps_num <= 1
4575 || regexp->regexp.allof.regexps_num <= 1)
4576 abort ();
4577 result = create_node (sizeof (struct regexp)
4578 + sizeof (regexp_t)
4579 * (regexp->regexp.allof.regexps_num
4580 + allof->regexp.allof.regexps_num - 2));
4581 result->mode = rm_allof;
4582 result->pos = regexp->pos;
4583 result->regexp.allof.regexps_num
4584 = (regexp->regexp.allof.regexps_num
4585 + allof->regexp.allof.regexps_num - 1);
4586 for (i = 0; i < regexp->regexp.allof.regexps_num; i++)
4587 if (i < allof_index)
4588 result->regexp.allof.regexps [i]
4589 = copy_insn_regexp (regexp->regexp.allof.regexps [i]);
4590 else if (i > allof_index)
4591 result->regexp.allof.regexps
4592 [i + allof->regexp.allof.regexps_num - 1]
4593 = copy_insn_regexp (regexp->regexp.allof.regexps [i]);
4594 else
4595 for (j = 0; j < allof->regexp.allof.regexps_num; j++)
4596 result->regexp.allof.regexps [i + j]
4597 = copy_insn_regexp (allof->regexp.allof.regexps [j]);
4598 regexp_transformed_p = 1;
4599 regexp = result;
4602 else if (regexp->mode == rm_oneof)
4604 regexp_t oneof;
4605 regexp_t result;
4606 int oneof_index;
4607 int i, j;
4609 for (i = 0; i < regexp->regexp.oneof.regexps_num; i++)
4610 if (regexp->regexp.oneof.regexps [i]->mode == rm_oneof)
4612 oneof_index = i;
4613 oneof = regexp->regexp.oneof.regexps [i];
4614 break;
4616 if (i < regexp->regexp.oneof.regexps_num)
4618 if (oneof->regexp.oneof.regexps_num <= 1
4619 || regexp->regexp.oneof.regexps_num <= 1)
4620 abort ();
4621 result = create_node (sizeof (struct regexp)
4622 + sizeof (regexp_t)
4623 * (regexp->regexp.oneof.regexps_num
4624 + oneof->regexp.oneof.regexps_num - 2));
4625 result->mode = rm_oneof;
4626 result->pos = regexp->pos;
4627 result->regexp.oneof.regexps_num
4628 = (regexp->regexp.oneof.regexps_num
4629 + oneof->regexp.oneof.regexps_num - 1);
4630 for (i = 0; i < regexp->regexp.oneof.regexps_num; i++)
4631 if (i < oneof_index)
4632 result->regexp.oneof.regexps [i]
4633 = copy_insn_regexp (regexp->regexp.oneof.regexps [i]);
4634 else if (i > oneof_index)
4635 result->regexp.oneof.regexps
4636 [i + oneof->regexp.oneof.regexps_num - 1]
4637 = copy_insn_regexp (regexp->regexp.oneof.regexps [i]);
4638 else
4639 for (j = 0; j < oneof->regexp.oneof.regexps_num; j++)
4640 result->regexp.oneof.regexps [i + j]
4641 = copy_insn_regexp (oneof->regexp.oneof.regexps [j]);
4642 regexp_transformed_p = 1;
4643 regexp = result;
4646 return regexp;
4649 /* The function makes transformations
4650 ...,A|B|...,C,... -> (...,A,C,...)|(...,B,C,...)|...
4651 ...+(A|B|...)+C+... -> (...+A+C+...)|(...+B+C+...)|...
4652 ...+(A,B,...)+C+... -> (...+A+C+...),B,...
4653 ...+(A,B,...)+(C,D,...) -> (A+C),(B+D),... */
4654 static regexp_t
4655 transform_3 (regexp)
4656 regexp_t regexp;
4658 if (regexp->mode == rm_sequence)
4660 regexp_t oneof;
4661 int oneof_index;
4662 regexp_t result;
4663 regexp_t sequence;
4664 int i, j;
4666 for (i = 0; i < regexp->regexp.sequence.regexps_num; i++)
4667 if (regexp->regexp.sequence.regexps [i]->mode == rm_oneof)
4669 oneof_index = i;
4670 oneof = regexp->regexp.sequence.regexps [i];
4671 break;
4673 if (i < regexp->regexp.sequence.regexps_num)
4675 if (oneof->regexp.oneof.regexps_num <= 1
4676 || regexp->regexp.sequence.regexps_num <= 1)
4677 abort ();
4678 result = create_node (sizeof (struct regexp)
4679 + sizeof (regexp_t)
4680 * (oneof->regexp.oneof.regexps_num - 1));
4681 result->mode = rm_oneof;
4682 result->pos = regexp->pos;
4683 result->regexp.oneof.regexps_num = oneof->regexp.oneof.regexps_num;
4684 for (i = 0; i < result->regexp.oneof.regexps_num; i++)
4686 sequence
4687 = create_node (sizeof (struct regexp)
4688 + sizeof (regexp_t)
4689 * (regexp->regexp.sequence.regexps_num - 1));
4690 sequence->mode = rm_sequence;
4691 sequence->pos = regexp->pos;
4692 sequence->regexp.sequence.regexps_num
4693 = regexp->regexp.sequence.regexps_num;
4694 result->regexp.oneof.regexps [i] = sequence;
4695 for (j = 0; j < sequence->regexp.sequence.regexps_num; j++)
4696 if (j != oneof_index)
4697 sequence->regexp.sequence.regexps [j]
4698 = copy_insn_regexp (regexp->regexp.sequence.regexps [j]);
4699 else
4700 sequence->regexp.sequence.regexps [j]
4701 = copy_insn_regexp (oneof->regexp.oneof.regexps [i]);
4703 regexp_transformed_p = 1;
4704 regexp = result;
4707 else if (regexp->mode == rm_allof)
4709 regexp_t oneof, seq;
4710 int oneof_index, max_seq_length, allof_length;
4711 regexp_t result;
4712 regexp_t allof, allof_op;
4713 int i, j;
4715 for (i = 0; i < regexp->regexp.allof.regexps_num; i++)
4716 if (regexp->regexp.allof.regexps [i]->mode == rm_oneof)
4718 oneof_index = i;
4719 oneof = regexp->regexp.allof.regexps [i];
4720 break;
4722 if (i < regexp->regexp.allof.regexps_num)
4724 if (oneof->regexp.oneof.regexps_num <= 1
4725 || regexp->regexp.allof.regexps_num <= 1)
4726 abort ();
4727 result = create_node (sizeof (struct regexp)
4728 + sizeof (regexp_t)
4729 * (oneof->regexp.oneof.regexps_num - 1));
4730 result->mode = rm_oneof;
4731 result->pos = regexp->pos;
4732 result->regexp.oneof.regexps_num = oneof->regexp.oneof.regexps_num;
4733 for (i = 0; i < result->regexp.oneof.regexps_num; i++)
4735 allof
4736 = create_node (sizeof (struct regexp)
4737 + sizeof (regexp_t)
4738 * (regexp->regexp.allof.regexps_num - 1));
4739 allof->mode = rm_allof;
4740 allof->pos = regexp->pos;
4741 allof->regexp.allof.regexps_num
4742 = regexp->regexp.allof.regexps_num;
4743 result->regexp.oneof.regexps [i] = allof;
4744 for (j = 0; j < allof->regexp.allof.regexps_num; j++)
4745 if (j != oneof_index)
4746 allof->regexp.allof.regexps [j]
4747 = copy_insn_regexp (regexp->regexp.allof.regexps [j]);
4748 else
4749 allof->regexp.allof.regexps [j]
4750 = copy_insn_regexp (oneof->regexp.oneof.regexps [i]);
4752 regexp_transformed_p = 1;
4753 regexp = result;
4755 max_seq_length = 0;
4756 for (i = 0; i < regexp->regexp.allof.regexps_num; i++)
4757 if (regexp->regexp.allof.regexps [i]->mode == rm_sequence)
4759 seq = regexp->regexp.allof.regexps [i];
4760 if (max_seq_length < seq->regexp.sequence.regexps_num)
4761 max_seq_length = seq->regexp.sequence.regexps_num;
4763 else if (regexp->regexp.allof.regexps [i]->mode != rm_unit)
4765 max_seq_length = 0;
4766 break;
4768 if (max_seq_length != 0)
4770 if (max_seq_length == 1 || regexp->regexp.allof.regexps_num <= 1)
4771 abort ();
4772 result = create_node (sizeof (struct regexp)
4773 + sizeof (regexp_t) * (max_seq_length - 1));
4774 result->mode = rm_sequence;
4775 result->pos = regexp->pos;
4776 result->regexp.sequence.regexps_num = max_seq_length;
4777 for (i = 0; i < max_seq_length; i++)
4779 allof_length = 0;
4780 for (j = 0; j < regexp->regexp.allof.regexps_num; j++)
4781 if (regexp->regexp.allof.regexps [j]->mode == rm_sequence
4782 && (i < (regexp->regexp.allof.regexps [j]
4783 ->regexp.sequence.regexps_num)))
4785 allof_op = (regexp->regexp.allof.regexps [j]
4786 ->regexp.sequence.regexps [i]);
4787 allof_length++;
4789 else if (i == 0
4790 && regexp->regexp.allof.regexps [j]->mode == rm_unit)
4792 allof_op = regexp->regexp.allof.regexps [j];
4793 allof_length++;
4795 if (allof_length == 1)
4796 result->regexp.sequence.regexps [i] = allof_op;
4797 else
4799 allof = create_node (sizeof (struct regexp)
4800 + sizeof (regexp_t)
4801 * (allof_length - 1));
4802 allof->mode = rm_allof;
4803 allof->pos = regexp->pos;
4804 allof->regexp.allof.regexps_num = allof_length;
4805 result->regexp.sequence.regexps [i] = allof;
4806 allof_length = 0;
4807 for (j = 0; j < regexp->regexp.allof.regexps_num; j++)
4808 if (regexp->regexp.allof.regexps [j]->mode == rm_sequence
4809 && (i < (regexp->regexp.allof.regexps [j]
4810 ->regexp.sequence.regexps_num)))
4812 allof_op = (regexp->regexp.allof.regexps [j]
4813 ->regexp.sequence.regexps [i]);
4814 allof->regexp.allof.regexps [allof_length] = allof_op;
4816 allof_length++;
4818 else if (i == 0
4819 && (regexp->regexp.allof.regexps [j]->mode
4820 == rm_unit))
4822 allof_op = regexp->regexp.allof.regexps [j];
4823 allof->regexp.allof.regexps [allof_length] = allof_op;
4824 allof_length++;
4828 regexp_transformed_p = 1;
4829 regexp = result;
4832 return regexp;
4835 /* The function traverses IR of reservation and applies transformations
4836 implemented by FUNC. */
4837 static regexp_t
4838 regexp_transform_func (regexp, func)
4839 regexp_t regexp;
4840 regexp_t (*func) PARAMS ((regexp_t regexp));
4842 int i;
4844 if (regexp->mode == rm_sequence)
4845 for (i = 0; i < regexp->regexp.sequence.regexps_num; i++)
4846 regexp->regexp.sequence.regexps [i]
4847 = regexp_transform_func (regexp->regexp.sequence.regexps [i], func);
4848 else if (regexp->mode == rm_allof)
4849 for (i = 0; i < regexp->regexp.allof.regexps_num; i++)
4850 regexp->regexp.allof.regexps [i]
4851 = regexp_transform_func (regexp->regexp.allof.regexps [i], func);
4852 else if (regexp->mode == rm_oneof)
4853 for (i = 0; i < regexp->regexp.oneof.regexps_num; i++)
4854 regexp->regexp.oneof.regexps [i]
4855 = regexp_transform_func (regexp->regexp.oneof.regexps [i], func);
4856 else if (regexp->mode == rm_repeat)
4857 regexp->regexp.repeat.regexp
4858 = regexp_transform_func (regexp->regexp.repeat.regexp, func);
4859 else if (regexp->mode != rm_nothing && regexp->mode != rm_unit)
4860 abort ();
4861 return (*func) (regexp);
4864 /* The function applies all transformations for IR representation of
4865 reservation REGEXP. */
4866 static regexp_t
4867 transform_regexp (regexp)
4868 regexp_t regexp;
4870 regexp = regexp_transform_func (regexp, transform_1);
4873 regexp_transformed_p = 0;
4874 regexp = regexp_transform_func (regexp, transform_2);
4875 regexp = regexp_transform_func (regexp, transform_3);
4877 while (regexp_transformed_p);
4878 return regexp;
4881 /* The function applys all transformations for reservations of all
4882 insn declarations. */
4883 static void
4884 transform_insn_regexps ()
4886 decl_t decl;
4887 int i;
4889 transform_time = create_ticker ();
4890 add_advance_cycle_insn_decl ();
4891 fprintf (stderr, "Reservation transformation...");
4892 fflush (stderr);
4893 for (i = 0; i < description->decls_num; i++)
4895 decl = description->decls [i];
4896 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
4897 decl->decl.insn_reserv.transformed_regexp
4898 = transform_regexp (copy_insn_regexp
4899 (decl->decl.insn_reserv.regexp));
4901 fprintf (stderr, "done\n");
4902 ticker_off (&transform_time);
4903 fflush (stderr);
4908 /* The following variable is an array indexed by cycle. Each element
4909 contains cyclic list of units which should be in the same cycle. */
4910 static unit_decl_t *the_same_automaton_lists;
4912 /* The function processes all alternative reservations on CYCLE in
4913 given REGEXP to check the UNIT is not reserved on the all
4914 alternatives. If it is true, the unit should be in the same
4915 automaton with other analogous units reserved on CYCLE in given
4916 REGEXP. */
4917 static void
4918 process_unit_to_form_the_same_automaton_unit_lists (unit, regexp, cycle)
4919 regexp_t unit;
4920 regexp_t regexp;
4921 int cycle;
4923 int i, k;
4924 regexp_t seq, allof;
4925 unit_decl_t unit_decl, last;
4927 if (regexp == NULL || regexp->mode != rm_oneof)
4928 abort ();
4929 unit_decl = unit->regexp.unit.unit_decl;
4930 for (i = regexp->regexp.oneof.regexps_num - 1; i >= 0; i--)
4932 seq = regexp->regexp.oneof.regexps [i];
4933 if (seq->mode == rm_sequence)
4935 if (cycle >= seq->regexp.sequence.regexps_num)
4936 break;
4937 allof = seq->regexp.sequence.regexps [cycle];
4938 if (allof->mode == rm_allof)
4940 for (k = 0; k < allof->regexp.allof.regexps_num; k++)
4941 if (allof->regexp.allof.regexps [k]->mode == rm_unit
4942 && (allof->regexp.allof.regexps [k]->regexp.unit.unit_decl
4943 == unit_decl))
4944 break;
4945 if (k >= allof->regexp.allof.regexps_num)
4946 break;
4948 else if (allof->mode == rm_unit
4949 && allof->regexp.unit.unit_decl != unit_decl)
4950 break;
4952 else if (cycle != 0)
4953 break;
4954 else if (seq->mode == rm_allof)
4956 for (k = 0; k < seq->regexp.allof.regexps_num; k++)
4957 if (seq->regexp.allof.regexps [k]->mode == rm_unit
4958 && (seq->regexp.allof.regexps [k]->regexp.unit.unit_decl
4959 == unit_decl))
4960 break;
4961 if (k >= seq->regexp.allof.regexps_num)
4962 break;
4964 else if (seq->mode == rm_unit && seq->regexp.unit.unit_decl != unit_decl)
4965 break;
4967 if (i >= 0)
4969 if (the_same_automaton_lists [cycle] == NULL)
4970 the_same_automaton_lists [cycle] = unit_decl;
4971 else
4973 for (last = the_same_automaton_lists [cycle];;)
4975 if (last == unit_decl)
4976 return;
4977 if (last->the_same_automaton_unit
4978 == the_same_automaton_lists [cycle])
4979 break;
4980 last = last->the_same_automaton_unit;
4982 last->the_same_automaton_unit = unit_decl->the_same_automaton_unit;
4983 unit_decl->the_same_automaton_unit
4984 = the_same_automaton_lists [cycle];
4989 /* The function processes given REGEXP to find units which should be
4990 in the same automaton. */
4991 static void
4992 form_the_same_automaton_unit_lists_from_regexp (regexp)
4993 regexp_t regexp;
4995 int i, j, k;
4996 regexp_t seq, allof, unit;
4998 if (regexp == NULL || regexp->mode != rm_oneof)
4999 return;
5000 for (i = 0; i < description->max_insn_reserv_cycles; i++)
5001 the_same_automaton_lists [i] = NULL;
5002 for (i = regexp->regexp.oneof.regexps_num - 1; i >= 0; i--)
5004 seq = regexp->regexp.oneof.regexps [i];
5005 if (seq->mode == rm_sequence)
5006 for (j = 0; j < seq->regexp.sequence.regexps_num; j++)
5008 allof = seq->regexp.sequence.regexps [j];
5009 if (allof->mode == rm_allof)
5010 for (k = 0; k < allof->regexp.allof.regexps_num; k++)
5012 unit = allof->regexp.allof.regexps [k];
5013 if (unit->mode == rm_unit)
5014 process_unit_to_form_the_same_automaton_unit_lists
5015 (unit, regexp, j);
5016 else if (unit->mode != rm_nothing)
5017 abort ();
5019 else if (allof->mode == rm_unit)
5020 process_unit_to_form_the_same_automaton_unit_lists
5021 (allof, regexp, j);
5022 else if (allof->mode != rm_nothing)
5023 abort ();
5025 else if (seq->mode == rm_allof)
5026 for (k = 0; k < seq->regexp.allof.regexps_num; k++)
5028 unit = seq->regexp.allof.regexps [k];
5029 if (unit->mode == rm_unit)
5030 process_unit_to_form_the_same_automaton_unit_lists
5031 (unit, regexp, 0);
5032 else if (unit->mode != rm_nothing)
5033 abort ();
5035 else if (seq->mode == rm_unit)
5036 process_unit_to_form_the_same_automaton_unit_lists (seq, regexp, 0);
5037 else if (seq->mode != rm_nothing)
5038 abort ();
5042 /* The function initializes data to search for units which should be
5043 in the same automaton and call function
5044 `form_the_same_automaton_unit_lists_from_regexp' for each insn
5045 reservation regexp. */
5046 static void
5047 form_the_same_automaton_unit_lists ()
5049 decl_t decl;
5050 int i;
5052 the_same_automaton_lists
5053 = (unit_decl_t *) xmalloc (description->max_insn_reserv_cycles
5054 * sizeof (unit_decl_t));
5055 for (i = 0; i < description->decls_num; i++)
5057 decl = description->decls [i];
5058 if (decl->mode == dm_unit)
5060 decl->decl.unit.the_same_automaton_message_reported_p = FALSE;
5061 decl->decl.unit.the_same_automaton_unit = &decl->decl.unit;
5064 for (i = 0; i < description->decls_num; i++)
5066 decl = description->decls [i];
5067 if (decl->mode == dm_insn_reserv)
5068 form_the_same_automaton_unit_lists_from_regexp
5069 (decl->decl.insn_reserv.transformed_regexp);
5071 free (the_same_automaton_lists);
5074 /* The function finds units which should be in the same automaton and,
5075 if they are not, reports about it. */
5076 static void
5077 check_unit_distributions_to_automata ()
5079 decl_t decl;
5080 unit_decl_t start_unit_decl, unit_decl;
5081 int i;
5083 form_the_same_automaton_unit_lists ();
5084 for (i = 0; i < description->decls_num; i++)
5086 decl = description->decls [i];
5087 if (decl->mode == dm_unit)
5089 start_unit_decl = &decl->decl.unit;
5090 if (!start_unit_decl->the_same_automaton_message_reported_p)
5091 for (unit_decl = start_unit_decl->the_same_automaton_unit;
5092 unit_decl != start_unit_decl;
5093 unit_decl = unit_decl->the_same_automaton_unit)
5094 if (start_unit_decl->automaton_decl != unit_decl->automaton_decl)
5096 error ("Units `%s' and `%s' should be in the same automaton",
5097 start_unit_decl->name, unit_decl->name);
5098 unit_decl->the_same_automaton_message_reported_p = TRUE;
5106 /* The page contains code for building alt_states (see comments for
5107 IR) describing all possible insns reservations of an automaton. */
5109 /* Current state being formed for which the current alt_state
5110 refers. */
5111 static state_t state_being_formed;
5113 /* Current alt_state being formed. */
5114 static alt_state_t alt_state_being_formed;
5116 /* This recursive function processes `,' and units in reservation
5117 REGEXP for forming alt_states of AUTOMATON. It is believed that
5118 CURR_CYCLE is start cycle of all reservation REGEXP. */
5119 static int
5120 process_seq_for_forming_states (regexp, automaton, curr_cycle)
5121 regexp_t regexp;
5122 automaton_t automaton;
5123 int curr_cycle;
5125 int i;
5127 if (regexp == NULL)
5128 return curr_cycle;
5129 else if (regexp->mode == rm_unit)
5131 if (regexp->regexp.unit.unit_decl->corresponding_automaton_num
5132 == automaton->automaton_order_num)
5133 set_state_reserv (state_being_formed, curr_cycle,
5134 regexp->regexp.unit.unit_decl->unit_num);
5135 return curr_cycle;
5137 else if (regexp->mode == rm_sequence)
5139 for (i = 0; i < regexp->regexp.sequence.regexps_num; i++)
5140 curr_cycle
5141 = process_seq_for_forming_states
5142 (regexp->regexp.sequence.regexps [i], automaton, curr_cycle) + 1;
5143 return curr_cycle;
5145 else if (regexp->mode == rm_allof)
5147 int finish_cycle = 0;
5148 int cycle;
5150 for (i = 0; i < regexp->regexp.allof.regexps_num; i++)
5152 cycle
5153 = process_seq_for_forming_states (regexp->regexp.allof.regexps [i],
5154 automaton, curr_cycle);
5155 if (finish_cycle < cycle)
5156 finish_cycle = cycle;
5158 return finish_cycle;
5160 else
5162 if (regexp->mode != rm_nothing)
5163 abort ();
5164 return curr_cycle;
5168 /* This recursive function finishes forming ALT_STATE of AUTOMATON and
5169 inserts alt_state into the table. */
5170 static void
5171 finish_forming_alt_state (alt_state, automaton)
5172 alt_state_t alt_state;
5173 automaton_t automaton ATTRIBUTE_UNUSED;
5175 state_t state_in_table;
5176 state_t corresponding_state;
5178 corresponding_state = alt_state->state;
5179 state_in_table = insert_state (corresponding_state);
5180 if (state_in_table != corresponding_state)
5182 free_state (corresponding_state);
5183 alt_state->state = state_in_table;
5187 /* The following variable value is current automaton insn for whose
5188 reservation the alt states are created. */
5189 static ainsn_t curr_ainsn;
5191 /* This recursive function processes `|' in reservation REGEXP for
5192 forming alt_states of AUTOMATON. List of the alt states should
5193 have the same order as in the description. */
5194 static void
5195 process_alts_for_forming_states (regexp, automaton, inside_oneof_p)
5196 regexp_t regexp;
5197 automaton_t automaton;
5198 int inside_oneof_p;
5200 int i;
5202 if (regexp->mode != rm_oneof)
5204 alt_state_being_formed = get_free_alt_state ();
5205 state_being_formed = get_free_state (1, automaton);
5206 alt_state_being_formed->state = state_being_formed;
5207 /* We inserts in reverse order but we process alternatives also
5208 in reverse order. So we have the same order of alternative
5209 as in the description. */
5210 alt_state_being_formed->next_alt_state = curr_ainsn->alt_states;
5211 curr_ainsn->alt_states = alt_state_being_formed;
5212 (void) process_seq_for_forming_states (regexp, automaton, 0);
5213 finish_forming_alt_state (alt_state_being_formed, automaton);
5215 else
5217 if (inside_oneof_p)
5218 abort ();
5219 /* We processes it in reverse order to get list with the same
5220 order as in the description. See also the previous
5221 commentary. */
5222 for (i = regexp->regexp.oneof.regexps_num - 1; i >= 0; i--)
5223 process_alts_for_forming_states (regexp->regexp.oneof.regexps [i],
5224 automaton, 1);
5228 /* Create nodes alt_state for all AUTOMATON insns. */
5229 static void
5230 create_alt_states (automaton)
5231 automaton_t automaton;
5233 struct insn_reserv_decl *reserv_decl;
5235 for (curr_ainsn = automaton->ainsn_list;
5236 curr_ainsn != NULL;
5237 curr_ainsn = curr_ainsn->next_ainsn)
5239 reserv_decl = curr_ainsn->insn_reserv_decl;
5240 if (reserv_decl != &advance_cycle_insn_decl->decl.insn_reserv)
5242 curr_ainsn->alt_states = NULL;
5243 process_alts_for_forming_states (reserv_decl->transformed_regexp,
5244 automaton, 0);
5245 curr_ainsn->sorted_alt_states
5246 = uniq_sort_alt_states (curr_ainsn->alt_states);
5253 /* The page contains major code for building DFA(s) for fast pipeline
5254 hazards recognition. */
5256 /* The function forms list of ainsns of AUTOMATON with the same
5257 reservation. */
5258 static void
5259 form_ainsn_with_same_reservs (automaton)
5260 automaton_t automaton;
5262 ainsn_t curr_ainsn;
5263 size_t i;
5264 vla_ptr_t first_insns;
5265 vla_ptr_t last_insns;
5267 VLA_PTR_CREATE (first_insns, 150, "first insns with the same reservs");
5268 VLA_PTR_CREATE (last_insns, 150, "last insns with the same reservs");
5269 for (curr_ainsn = automaton->ainsn_list;
5270 curr_ainsn != NULL;
5271 curr_ainsn = curr_ainsn->next_ainsn)
5272 if (curr_ainsn->insn_reserv_decl
5273 == &advance_cycle_insn_decl->decl.insn_reserv)
5275 curr_ainsn->next_same_reservs_insn = NULL;
5276 curr_ainsn->first_insn_with_same_reservs = 1;
5278 else
5280 for (i = 0; i < VLA_PTR_LENGTH (first_insns); i++)
5281 if (alt_states_eq
5282 (curr_ainsn->sorted_alt_states,
5283 ((ainsn_t) VLA_PTR (first_insns, i))->sorted_alt_states))
5284 break;
5285 curr_ainsn->next_same_reservs_insn = NULL;
5286 if (i < VLA_PTR_LENGTH (first_insns))
5288 curr_ainsn->first_insn_with_same_reservs = 0;
5289 ((ainsn_t) VLA_PTR (last_insns, i))->next_same_reservs_insn
5290 = curr_ainsn;
5291 VLA_PTR (last_insns, i) = curr_ainsn;
5293 else
5295 VLA_PTR_ADD (first_insns, curr_ainsn);
5296 VLA_PTR_ADD (last_insns, curr_ainsn);
5297 curr_ainsn->first_insn_with_same_reservs = 1;
5300 VLA_PTR_DELETE (first_insns);
5301 VLA_PTR_DELETE (last_insns);
5304 /* The following function creates all states of nondeterministic (if
5305 NDFA_FLAG has nonzero value) or deterministic AUTOMATON. */
5306 static void
5307 make_automaton (automaton)
5308 automaton_t automaton;
5310 ainsn_t ainsn;
5311 struct insn_reserv_decl *insn_reserv_decl;
5312 alt_state_t alt_state;
5313 state_t state;
5314 state_t start_state;
5315 state_t state2;
5316 ainsn_t advance_cycle_ainsn;
5317 arc_t added_arc;
5318 vla_ptr_t state_stack;
5320 VLA_PTR_CREATE (state_stack, 150, "state stack");
5321 /* Create the start state (empty state). */
5322 start_state = insert_state (get_free_state (1, automaton));
5323 automaton->start_state = start_state;
5324 start_state->it_was_placed_in_stack_for_NDFA_forming = 1;
5325 VLA_PTR_ADD (state_stack, start_state);
5326 while (VLA_PTR_LENGTH (state_stack) != 0)
5328 state = VLA_PTR (state_stack, VLA_PTR_LENGTH (state_stack) - 1);
5329 VLA_PTR_SHORTEN (state_stack, 1);
5330 advance_cycle_ainsn = NULL;
5331 for (ainsn = automaton->ainsn_list;
5332 ainsn != NULL;
5333 ainsn = ainsn->next_ainsn)
5334 if (ainsn->first_insn_with_same_reservs)
5336 insn_reserv_decl = ainsn->insn_reserv_decl;
5337 if (insn_reserv_decl != &advance_cycle_insn_decl->decl.insn_reserv)
5339 /* We process alt_states in the same order as they are
5340 present in the description. */
5341 added_arc = NULL;
5342 for (alt_state = ainsn->alt_states;
5343 alt_state != NULL;
5344 alt_state = alt_state->next_alt_state)
5346 state2 = alt_state->state;
5347 if (!intersected_state_reservs_p (state, state2))
5349 state2 = states_union (state, state2);
5350 if (!state2->it_was_placed_in_stack_for_NDFA_forming)
5352 state2->it_was_placed_in_stack_for_NDFA_forming
5353 = 1;
5354 VLA_PTR_ADD (state_stack, state2);
5356 added_arc = add_arc (state, state2, ainsn, 1);
5357 if (!ndfa_flag)
5358 break;
5361 if (!ndfa_flag && added_arc != NULL)
5363 added_arc->state_alts = 0;
5364 for (alt_state = ainsn->alt_states;
5365 alt_state != NULL;
5366 alt_state = alt_state->next_alt_state)
5368 state2 = alt_state->state;
5369 if (!intersected_state_reservs_p (state, state2))
5370 added_arc->state_alts++;
5374 else
5375 advance_cycle_ainsn = ainsn;
5377 /* Add transition to advance cycle. */
5378 state2 = state_shift (state);
5379 if (!state2->it_was_placed_in_stack_for_NDFA_forming)
5381 state2->it_was_placed_in_stack_for_NDFA_forming = 1;
5382 VLA_PTR_ADD (state_stack, state2);
5384 if (advance_cycle_ainsn == NULL)
5385 abort ();
5386 add_arc (state, state2, advance_cycle_ainsn, 1);
5388 VLA_PTR_DELETE (state_stack);
5391 /* Foms lists of all arcs of STATE marked by the same ainsn. */
5392 static void
5393 form_arcs_marked_by_insn (state)
5394 state_t state;
5396 decl_t decl;
5397 arc_t arc;
5398 int i;
5400 for (i = 0; i < description->decls_num; i++)
5402 decl = description->decls [i];
5403 if (decl->mode == dm_insn_reserv)
5404 decl->decl.insn_reserv.arcs_marked_by_insn = NULL;
5406 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5408 if (arc->insn == NULL)
5409 abort ();
5410 arc->next_arc_marked_by_insn
5411 = arc->insn->insn_reserv_decl->arcs_marked_by_insn;
5412 arc->insn->insn_reserv_decl->arcs_marked_by_insn = arc;
5416 /* The function creates composed state (see comments for IR) from
5417 ORIGINAL_STATE and list of arcs ARCS_MARKED_BY_INSN marked by the
5418 same insn. If the composed state is not in STATE_STACK yet, it is
5419 popped to STATE_STACK. */
5420 static void
5421 create_composed_state (original_state, arcs_marked_by_insn, state_stack)
5422 state_t original_state;
5423 arc_t arcs_marked_by_insn;
5424 vla_ptr_t *state_stack;
5426 state_t state;
5427 alt_state_t curr_alt_state;
5428 alt_state_t new_alt_state;
5429 arc_t curr_arc;
5430 arc_t next_arc;
5431 state_t state_in_table;
5432 state_t temp_state;
5433 alt_state_t canonical_alt_states_list;
5434 int alts_number;
5436 if (arcs_marked_by_insn == NULL)
5437 return;
5438 if (arcs_marked_by_insn->next_arc_marked_by_insn == NULL)
5439 state = arcs_marked_by_insn->to_state;
5440 else
5442 if (!ndfa_flag)
5443 abort ();
5444 /* Create composed state. */
5445 state = get_free_state (0, arcs_marked_by_insn->to_state->automaton);
5446 curr_alt_state = NULL;
5447 for (curr_arc = arcs_marked_by_insn;
5448 curr_arc != NULL;
5449 curr_arc = curr_arc->next_arc_marked_by_insn)
5451 new_alt_state = get_free_alt_state ();
5452 new_alt_state->next_alt_state = curr_alt_state;
5453 new_alt_state->state = curr_arc->to_state;
5454 if (curr_arc->to_state->component_states != NULL)
5455 abort ();
5456 curr_alt_state = new_alt_state;
5458 /* There are not identical sets in the alt state list. */
5459 canonical_alt_states_list = uniq_sort_alt_states (curr_alt_state);
5460 if (canonical_alt_states_list->next_sorted_alt_state == NULL)
5462 temp_state = state;
5463 state = canonical_alt_states_list->state;
5464 free_state (temp_state);
5466 else
5468 state->component_states = canonical_alt_states_list;
5469 state_in_table = insert_state (state);
5470 if (state_in_table != state)
5472 if (!state_in_table->it_was_placed_in_stack_for_DFA_forming)
5473 abort ();
5474 free_state (state);
5475 state = state_in_table;
5477 else
5479 if (state->it_was_placed_in_stack_for_DFA_forming)
5480 abort ();
5481 for (curr_alt_state = state->component_states;
5482 curr_alt_state != NULL;
5483 curr_alt_state = curr_alt_state->next_sorted_alt_state)
5484 for (curr_arc = first_out_arc (curr_alt_state->state);
5485 curr_arc != NULL;
5486 curr_arc = next_out_arc (curr_arc))
5487 add_arc (state, curr_arc->to_state, curr_arc->insn, 1);
5489 arcs_marked_by_insn->to_state = state;
5490 for (alts_number = 0,
5491 curr_arc = arcs_marked_by_insn->next_arc_marked_by_insn;
5492 curr_arc != NULL;
5493 curr_arc = next_arc)
5495 next_arc = curr_arc->next_arc_marked_by_insn;
5496 remove_arc (original_state, curr_arc);
5497 alts_number++;
5499 arcs_marked_by_insn->state_alts = alts_number;
5502 if (!state->it_was_placed_in_stack_for_DFA_forming)
5504 state->it_was_placed_in_stack_for_DFA_forming = 1;
5505 VLA_PTR_ADD (*state_stack, state);
5509 /* The function transformes nondeterminstic AUTOMATON into
5510 deterministic. */
5511 static void
5512 NDFA_to_DFA (automaton)
5513 automaton_t automaton;
5515 state_t start_state;
5516 state_t state;
5517 decl_t decl;
5518 vla_ptr_t state_stack;
5519 int i;
5521 VLA_PTR_CREATE (state_stack, 150, "state stack");
5522 /* Create the start state (empty state). */
5523 start_state = automaton->start_state;
5524 start_state->it_was_placed_in_stack_for_DFA_forming = 1;
5525 VLA_PTR_ADD (state_stack, start_state);
5526 while (VLA_PTR_LENGTH (state_stack) != 0)
5528 state = VLA_PTR (state_stack, VLA_PTR_LENGTH (state_stack) - 1);
5529 VLA_PTR_SHORTEN (state_stack, 1);
5530 form_arcs_marked_by_insn (state);
5531 for (i = 0; i < description->decls_num; i++)
5533 decl = description->decls [i];
5534 if (decl->mode == dm_insn_reserv)
5535 create_composed_state
5536 (state, decl->decl.insn_reserv.arcs_marked_by_insn,
5537 &state_stack);
5540 VLA_PTR_DELETE (state_stack);
5543 /* The following variable value is current number (1, 2, ...) of passing
5544 graph of states. */
5545 static int curr_state_graph_pass_num;
5547 /* This recursive function passes all states achieved from START_STATE
5548 and applies APPLIED_FUNC to them. */
5549 static void
5550 pass_state_graph (start_state, applied_func)
5551 state_t start_state;
5552 void (*applied_func) PARAMS ((state_t state));
5554 arc_t arc;
5556 if (start_state->pass_num == curr_state_graph_pass_num)
5557 return;
5558 start_state->pass_num = curr_state_graph_pass_num;
5559 (*applied_func) (start_state);
5560 for (arc = first_out_arc (start_state);
5561 arc != NULL;
5562 arc = next_out_arc (arc))
5563 pass_state_graph (arc->to_state, applied_func);
5566 /* This recursive function passes all states of AUTOMATON and applies
5567 APPLIED_FUNC to them. */
5568 static void
5569 pass_states (automaton, applied_func)
5570 automaton_t automaton;
5571 void (*applied_func) PARAMS ((state_t state));
5573 curr_state_graph_pass_num++;
5574 pass_state_graph (automaton->start_state, applied_func);
5577 /* The function initializes code for passing of all states. */
5578 static void
5579 initiate_pass_states ()
5581 curr_state_graph_pass_num = 0;
5584 /* The following vla is used for storing pointers to all achieved
5585 states. */
5586 static vla_ptr_t all_achieved_states;
5588 /* This function is called by function pass_states to add an achieved
5589 STATE. */
5590 static void
5591 add_achieved_state (state)
5592 state_t state;
5594 VLA_PTR_ADD (all_achieved_states, state);
5597 /* The function sets up equivalence numbers of insns which mark all
5598 out arcs of STATE by equiv_class_num_1 (if ODD_ITERATION_FLAG has
5599 nonzero value) or by equiv_class_num_2 of the destination state.
5600 The function returns number of out arcs of STATE. */
5601 static int
5602 set_out_arc_insns_equiv_num (state, odd_iteration_flag)
5603 state_t state;
5604 int odd_iteration_flag;
5606 int state_out_arcs_num;
5607 arc_t arc;
5609 state_out_arcs_num = 0;
5610 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5612 if (arc->insn->insn_reserv_decl->equiv_class_num != 0
5613 || arc->insn->insn_reserv_decl->state_alts != 0)
5614 abort ();
5615 state_out_arcs_num++;
5616 arc->insn->insn_reserv_decl->equiv_class_num
5617 = (odd_iteration_flag
5618 ? arc->to_state->equiv_class_num_1
5619 : arc->to_state->equiv_class_num_2);
5620 arc->insn->insn_reserv_decl->state_alts = arc->state_alts;
5621 if (arc->insn->insn_reserv_decl->equiv_class_num == 0
5622 || arc->insn->insn_reserv_decl->state_alts <= 0)
5623 abort ();
5625 return state_out_arcs_num;
5628 /* The function clears equivalence numbers and alt_states in all insns
5629 which mark all out arcs of STATE. */
5630 static void
5631 clear_arc_insns_equiv_num (state)
5632 state_t state;
5634 arc_t arc;
5636 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5638 arc->insn->insn_reserv_decl->equiv_class_num = 0;
5639 arc->insn->insn_reserv_decl->state_alts = 0;
5643 /* The function copies pointers to equivalent states from vla FROM
5644 into vla TO. */
5645 static void
5646 copy_equiv_class (to, from)
5647 vla_ptr_t *to;
5648 const vla_ptr_t *from;
5650 state_t *class_ptr;
5652 VLA_PTR_NULLIFY (*to);
5653 for (class_ptr = VLA_PTR_BEGIN (*from);
5654 class_ptr <= (state_t *) VLA_PTR_LAST (*from);
5655 class_ptr++)
5656 VLA_PTR_ADD (*to, *class_ptr);
5659 /* The function returns nonzero value if STATE is not equivalent to
5660 another state from the same current partition on equivalence
5661 classes Another state has ORIGINAL_STATE_OUT_ARCS_NUM number of
5662 output arcs. Iteration of making equivalence partition is defined
5663 by ODD_ITERATION_FLAG. */
5664 static int
5665 state_is_differed (state, original_state_out_arcs_num, odd_iteration_flag)
5666 state_t state;
5667 int original_state_out_arcs_num;
5668 int odd_iteration_flag;
5670 arc_t arc;
5671 int state_out_arcs_num;
5673 state_out_arcs_num = 0;
5674 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5676 state_out_arcs_num++;
5677 if ((odd_iteration_flag
5678 ? arc->to_state->equiv_class_num_1
5679 : arc->to_state->equiv_class_num_2)
5680 != arc->insn->insn_reserv_decl->equiv_class_num
5681 || (arc->insn->insn_reserv_decl->state_alts != arc->state_alts))
5682 return 1;
5684 return state_out_arcs_num != original_state_out_arcs_num;
5687 /* The function makes initial partition of STATES on equivalent
5688 classes. */
5689 static state_t
5690 init_equiv_class (states, states_num)
5691 state_t *states;
5692 int states_num;
5694 state_t *state_ptr;
5695 state_t result_equiv_class;
5697 result_equiv_class = NULL;
5698 for (state_ptr = states; state_ptr < states + states_num; state_ptr++)
5700 (*state_ptr)->equiv_class_num_1 = 1;
5701 (*state_ptr)->next_equiv_class_state = result_equiv_class;
5702 result_equiv_class = *state_ptr;
5704 return result_equiv_class;
5707 /* The function processes equivalence class given by its pointer
5708 EQUIV_CLASS_PTR on odd iteration if ODD_ITERATION_FLAG. If there
5709 are not equvalent states, the function partitions the class
5710 removing nonequivalent states and placing them in
5711 *NEXT_ITERATION_CLASSES, increments *NEW_EQUIV_CLASS_NUM_PTR ans
5712 assigns it to the state equivalence number. If the class has been
5713 partitioned, the function returns nonzero value. */
5714 static int
5715 partition_equiv_class (equiv_class_ptr, odd_iteration_flag,
5716 next_iteration_classes, new_equiv_class_num_ptr)
5717 state_t *equiv_class_ptr;
5718 int odd_iteration_flag;
5719 vla_ptr_t *next_iteration_classes;
5720 int *new_equiv_class_num_ptr;
5722 state_t new_equiv_class;
5723 int partition_p;
5724 state_t first_state;
5725 state_t curr_state;
5726 state_t prev_state;
5727 state_t next_state;
5728 int out_arcs_num;
5730 partition_p = 0;
5731 if (*equiv_class_ptr == NULL)
5732 abort ();
5733 for (first_state = *equiv_class_ptr;
5734 first_state != NULL;
5735 first_state = new_equiv_class)
5737 new_equiv_class = NULL;
5738 if (first_state->next_equiv_class_state != NULL)
5740 /* There are more one states in the class equivalence. */
5741 out_arcs_num = set_out_arc_insns_equiv_num (first_state,
5742 odd_iteration_flag);
5743 for (prev_state = first_state,
5744 curr_state = first_state->next_equiv_class_state;
5745 curr_state != NULL;
5746 curr_state = next_state)
5748 next_state = curr_state->next_equiv_class_state;
5749 if (state_is_differed (curr_state, out_arcs_num,
5750 odd_iteration_flag))
5752 /* Remove curr state from the class equivalence. */
5753 prev_state->next_equiv_class_state = next_state;
5754 /* Add curr state to the new class equivalence. */
5755 curr_state->next_equiv_class_state = new_equiv_class;
5756 if (new_equiv_class == NULL)
5757 (*new_equiv_class_num_ptr)++;
5758 if (odd_iteration_flag)
5759 curr_state->equiv_class_num_2 = *new_equiv_class_num_ptr;
5760 else
5761 curr_state->equiv_class_num_1 = *new_equiv_class_num_ptr;
5762 new_equiv_class = curr_state;
5763 partition_p = 1;
5765 else
5766 prev_state = curr_state;
5768 clear_arc_insns_equiv_num (first_state);
5770 if (new_equiv_class != NULL)
5771 VLA_PTR_ADD (*next_iteration_classes, new_equiv_class);
5773 return partition_p;
5776 /* The function finds equivalent states of AUTOMATON. */
5777 static void
5778 evaluate_equiv_classes (automaton, equiv_classes)
5779 automaton_t automaton;
5780 vla_ptr_t *equiv_classes;
5782 state_t new_equiv_class;
5783 int new_equiv_class_num;
5784 int odd_iteration_flag;
5785 int finish_flag;
5786 vla_ptr_t next_iteration_classes;
5787 state_t *equiv_class_ptr;
5788 state_t *state_ptr;
5790 VLA_PTR_CREATE (all_achieved_states, 1500, "all achieved states");
5791 pass_states (automaton, add_achieved_state);
5792 new_equiv_class = init_equiv_class (VLA_PTR_BEGIN (all_achieved_states),
5793 VLA_PTR_LENGTH (all_achieved_states));
5794 odd_iteration_flag = 0;
5795 new_equiv_class_num = 1;
5796 VLA_PTR_CREATE (next_iteration_classes, 150, "next iteration classes");
5797 VLA_PTR_ADD (next_iteration_classes, new_equiv_class);
5800 odd_iteration_flag = !odd_iteration_flag;
5801 finish_flag = 1;
5802 copy_equiv_class (equiv_classes, &next_iteration_classes);
5803 /* Transfer equiv numbers for the next iteration. */
5804 for (state_ptr = VLA_PTR_BEGIN (all_achieved_states);
5805 state_ptr <= (state_t *) VLA_PTR_LAST (all_achieved_states);
5806 state_ptr++)
5807 if (odd_iteration_flag)
5808 (*state_ptr)->equiv_class_num_2 = (*state_ptr)->equiv_class_num_1;
5809 else
5810 (*state_ptr)->equiv_class_num_1 = (*state_ptr)->equiv_class_num_2;
5811 for (equiv_class_ptr = VLA_PTR_BEGIN (*equiv_classes);
5812 equiv_class_ptr <= (state_t *) VLA_PTR_LAST (*equiv_classes);
5813 equiv_class_ptr++)
5814 if (partition_equiv_class (equiv_class_ptr, odd_iteration_flag,
5815 &next_iteration_classes,
5816 &new_equiv_class_num))
5817 finish_flag = 0;
5819 while (!finish_flag);
5820 VLA_PTR_DELETE (next_iteration_classes);
5821 VLA_PTR_DELETE (all_achieved_states);
5824 /* The function merges equivalent states of AUTOMATON. */
5825 static void
5826 merge_states (automaton, equiv_classes)
5827 automaton_t automaton;
5828 vla_ptr_t *equiv_classes;
5830 state_t *equiv_class_ptr;
5831 state_t curr_state;
5832 state_t new_state;
5833 state_t first_class_state;
5834 alt_state_t alt_states;
5835 alt_state_t new_alt_state;
5836 arc_t curr_arc;
5837 arc_t next_arc;
5839 /* Create states corresponding to equivalence classes containing two
5840 or more states. */
5841 for (equiv_class_ptr = VLA_PTR_BEGIN (*equiv_classes);
5842 equiv_class_ptr <= (state_t *) VLA_PTR_LAST (*equiv_classes);
5843 equiv_class_ptr++)
5844 if ((*equiv_class_ptr)->next_equiv_class_state != NULL)
5846 /* There are more one states in the class equivalence. */
5847 /* Create new compound state. */
5848 new_state = get_free_state (0, automaton);
5849 alt_states = NULL;
5850 first_class_state = *equiv_class_ptr;
5851 for (curr_state = first_class_state;
5852 curr_state != NULL;
5853 curr_state = curr_state->next_equiv_class_state)
5855 curr_state->equiv_class_state = new_state;
5856 new_alt_state = get_free_alt_state ();
5857 new_alt_state->state = curr_state;
5858 new_alt_state->next_sorted_alt_state = alt_states;
5859 alt_states = new_alt_state;
5861 new_state->component_states = alt_states;
5863 else
5864 (*equiv_class_ptr)->equiv_class_state = *equiv_class_ptr;
5865 for (equiv_class_ptr = VLA_PTR_BEGIN (*equiv_classes);
5866 equiv_class_ptr <= (state_t *) VLA_PTR_LAST (*equiv_classes);
5867 equiv_class_ptr++)
5868 if ((*equiv_class_ptr)->next_equiv_class_state != NULL)
5870 first_class_state = *equiv_class_ptr;
5871 /* Create new arcs output from the state corresponding to
5872 equiv class. */
5873 for (curr_arc = first_out_arc (first_class_state);
5874 curr_arc != NULL;
5875 curr_arc = next_out_arc (curr_arc))
5876 add_arc (first_class_state->equiv_class_state,
5877 curr_arc->to_state->equiv_class_state,
5878 curr_arc->insn, curr_arc->state_alts);
5879 /* Delete output arcs from states of given class equivalence. */
5880 for (curr_state = first_class_state;
5881 curr_state != NULL;
5882 curr_state = curr_state->next_equiv_class_state)
5884 if (automaton->start_state == curr_state)
5885 automaton->start_state = curr_state->equiv_class_state;
5886 /* Delete the state and its output arcs. */
5887 for (curr_arc = first_out_arc (curr_state);
5888 curr_arc != NULL;
5889 curr_arc = next_arc)
5891 next_arc = next_out_arc (curr_arc);
5892 free_arc (curr_arc);
5896 else
5898 /* Change `to_state' of arcs output from the state of given
5899 equivalence class. */
5900 for (curr_arc = first_out_arc (*equiv_class_ptr);
5901 curr_arc != NULL;
5902 curr_arc = next_out_arc (curr_arc))
5903 curr_arc->to_state = curr_arc->to_state->equiv_class_state;
5907 /* The function sets up new_cycle_p for states if there is arc to the
5908 state marked by advance_cycle_insn_decl. */
5909 static void
5910 set_new_cycle_flags (state)
5911 state_t state;
5913 arc_t arc;
5915 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5916 if (arc->insn->insn_reserv_decl
5917 == &advance_cycle_insn_decl->decl.insn_reserv)
5918 arc->to_state->new_cycle_p = 1;
5921 /* The top level function for minimization of deterministic
5922 AUTOMATON. */
5923 static void
5924 minimize_DFA (automaton)
5925 automaton_t automaton;
5927 vla_ptr_t equiv_classes;
5929 VLA_PTR_CREATE (equiv_classes, 1500, "equivalence classes");
5930 evaluate_equiv_classes (automaton, &equiv_classes);
5931 merge_states (automaton, &equiv_classes);
5932 pass_states (automaton, set_new_cycle_flags);
5933 VLA_PTR_DELETE (equiv_classes);
5936 /* Values of two variables are counted number of states and arcs in an
5937 automaton. */
5938 static int curr_counted_states_num;
5939 static int curr_counted_arcs_num;
5941 /* The function is called by function `pass_states' to count states
5942 and arcs of an automaton. */
5943 static void
5944 incr_states_and_arcs_nums (state)
5945 state_t state;
5947 arc_t arc;
5949 curr_counted_states_num++;
5950 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5951 curr_counted_arcs_num++;
5954 /* The function counts states and arcs of AUTOMATON. */
5955 static void
5956 count_states_and_arcs (automaton, states_num, arcs_num)
5957 automaton_t automaton;
5958 int *states_num;
5959 int *arcs_num;
5961 curr_counted_states_num = 0;
5962 curr_counted_arcs_num = 0;
5963 pass_states (automaton, incr_states_and_arcs_nums);
5964 *states_num = curr_counted_states_num;
5965 *arcs_num = curr_counted_arcs_num;
5968 /* The function builds one DFA AUTOMATON for fast pipeline hazards
5969 recognition after checking and simplifying IR of the
5970 description. */
5971 static void
5972 build_automaton (automaton)
5973 automaton_t automaton;
5975 int states_num;
5976 int arcs_num;
5978 ticker_on (&NDFA_time);
5979 make_automaton (automaton);
5980 ticker_off (&NDFA_time);
5981 count_states_and_arcs (automaton, &states_num, &arcs_num);
5982 automaton->NDFA_states_num = states_num;
5983 automaton->NDFA_arcs_num = arcs_num;
5984 ticker_on (&NDFA_to_DFA_time);
5985 NDFA_to_DFA (automaton);
5986 ticker_off (&NDFA_to_DFA_time);
5987 count_states_and_arcs (automaton, &states_num, &arcs_num);
5988 automaton->DFA_states_num = states_num;
5989 automaton->DFA_arcs_num = arcs_num;
5990 if (!no_minimization_flag)
5992 ticker_on (&minimize_time);
5993 minimize_DFA (automaton);
5994 ticker_off (&minimize_time);
5995 count_states_and_arcs (automaton, &states_num, &arcs_num);
5996 automaton->minimal_DFA_states_num = states_num;
5997 automaton->minimal_DFA_arcs_num = arcs_num;
6003 /* The page contains code for enumeration of all states of an automaton. */
6005 /* Variable used for enumeration of all states of an automaton. Its
6006 value is current number of automaton states. */
6007 static int curr_state_order_num;
6009 /* The function is called by function `pass_states' for enumerating
6010 states. */
6011 static void
6012 set_order_state_num (state)
6013 state_t state;
6015 state->order_state_num = curr_state_order_num;
6016 curr_state_order_num++;
6019 /* The function enumerates all states of AUTOMATON. */
6020 static void
6021 enumerate_states (automaton)
6022 automaton_t automaton;
6024 curr_state_order_num = 0;
6025 pass_states (automaton, set_order_state_num);
6026 automaton->achieved_states_num = curr_state_order_num;
6031 /* The page contains code for finding equivalent automaton insns
6032 (ainsns). */
6034 /* The function inserts AINSN into cyclic list
6035 CYCLIC_EQUIV_CLASS_INSN_LIST of ainsns. */
6036 static ainsn_t
6037 insert_ainsn_into_equiv_class (ainsn, cyclic_equiv_class_insn_list)
6038 ainsn_t ainsn;
6039 ainsn_t cyclic_equiv_class_insn_list;
6041 if (cyclic_equiv_class_insn_list == NULL)
6042 ainsn->next_equiv_class_insn = ainsn;
6043 else
6045 ainsn->next_equiv_class_insn
6046 = cyclic_equiv_class_insn_list->next_equiv_class_insn;
6047 cyclic_equiv_class_insn_list->next_equiv_class_insn = ainsn;
6049 return ainsn;
6052 /* The function deletes equiv_class_insn into cyclic list of
6053 equivalent ainsns. */
6054 static void
6055 delete_ainsn_from_equiv_class (equiv_class_insn)
6056 ainsn_t equiv_class_insn;
6058 ainsn_t curr_equiv_class_insn;
6059 ainsn_t prev_equiv_class_insn;
6061 prev_equiv_class_insn = equiv_class_insn;
6062 for (curr_equiv_class_insn = equiv_class_insn->next_equiv_class_insn;
6063 curr_equiv_class_insn != equiv_class_insn;
6064 curr_equiv_class_insn = curr_equiv_class_insn->next_equiv_class_insn)
6065 prev_equiv_class_insn = curr_equiv_class_insn;
6066 if (prev_equiv_class_insn != equiv_class_insn)
6067 prev_equiv_class_insn->next_equiv_class_insn
6068 = equiv_class_insn->next_equiv_class_insn;
6071 /* The function processes AINSN of a state in order to find equivalent
6072 ainsns. INSN_ARCS_ARRAY is table: code of insn -> out arc of the
6073 state. */
6074 static void
6075 process_insn_equiv_class (ainsn, insn_arcs_array)
6076 ainsn_t ainsn;
6077 arc_t *insn_arcs_array;
6079 ainsn_t next_insn;
6080 ainsn_t curr_insn;
6081 ainsn_t cyclic_insn_list;
6082 arc_t arc;
6084 if (insn_arcs_array [ainsn->insn_reserv_decl->insn_num] == NULL)
6085 abort ();
6086 curr_insn = ainsn;
6087 /* New class of ainsns which are not equivalent to given ainsn. */
6088 cyclic_insn_list = NULL;
6091 next_insn = curr_insn->next_equiv_class_insn;
6092 arc = insn_arcs_array [curr_insn->insn_reserv_decl->insn_num];
6093 if (arc == NULL
6094 || (insn_arcs_array [ainsn->insn_reserv_decl->insn_num]->to_state
6095 != arc->to_state))
6097 delete_ainsn_from_equiv_class (curr_insn);
6098 cyclic_insn_list = insert_ainsn_into_equiv_class (curr_insn,
6099 cyclic_insn_list);
6101 curr_insn = next_insn;
6103 while (curr_insn != ainsn);
6106 /* The function processes STATE in order to find equivalent ainsns. */
6107 static void
6108 process_state_for_insn_equiv_partition (state)
6109 state_t state;
6111 arc_t arc;
6112 arc_t *insn_arcs_array;
6113 int i;
6114 vla_ptr_t insn_arcs_vect;
6116 VLA_PTR_CREATE (insn_arcs_vect, 500, "insn arcs vector");
6117 VLA_PTR_EXPAND (insn_arcs_vect, description->insns_num);
6118 insn_arcs_array = VLA_PTR_BEGIN (insn_arcs_vect);
6119 /* Process insns of the arcs. */
6120 for (i = 0; i < description->insns_num; i++)
6121 insn_arcs_array [i] = NULL;
6122 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6123 insn_arcs_array [arc->insn->insn_reserv_decl->insn_num] = arc;
6124 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6125 process_insn_equiv_class (arc->insn, insn_arcs_array);
6126 VLA_PTR_DELETE (insn_arcs_vect);
6129 /* The function searches for equivalent ainsns of AUTOMATON. */
6130 static void
6131 set_insn_equiv_classes (automaton)
6132 automaton_t automaton;
6134 ainsn_t ainsn;
6135 ainsn_t first_insn;
6136 ainsn_t curr_insn;
6137 ainsn_t cyclic_insn_list;
6138 ainsn_t insn_with_same_reservs;
6139 int equiv_classes_num;
6141 /* All insns are included in one equivalence class. */
6142 cyclic_insn_list = NULL;
6143 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6144 if (ainsn->first_insn_with_same_reservs)
6145 cyclic_insn_list = insert_ainsn_into_equiv_class (ainsn,
6146 cyclic_insn_list);
6147 /* Process insns in order to make equivalence partition. */
6148 pass_states (automaton, process_state_for_insn_equiv_partition);
6149 /* Enumerate equiv classes. */
6150 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6151 /* Set undefined value. */
6152 ainsn->insn_equiv_class_num = -1;
6153 equiv_classes_num = 0;
6154 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6155 if (ainsn->insn_equiv_class_num < 0)
6157 first_insn = ainsn;
6158 if (!first_insn->first_insn_with_same_reservs)
6159 abort ();
6160 first_insn->first_ainsn_with_given_equialence_num = 1;
6161 curr_insn = first_insn;
6164 for (insn_with_same_reservs = curr_insn;
6165 insn_with_same_reservs != NULL;
6166 insn_with_same_reservs
6167 = insn_with_same_reservs->next_same_reservs_insn)
6168 insn_with_same_reservs->insn_equiv_class_num = equiv_classes_num;
6169 curr_insn = curr_insn->next_equiv_class_insn;
6171 while (curr_insn != first_insn);
6172 equiv_classes_num++;
6174 automaton->insn_equiv_classes_num = equiv_classes_num;
6179 /* This page contains code for creating DFA(s) and calls functions
6180 building them. */
6183 /* The following value is used to prevent floating point overflow for
6184 estimating an automaton bound. The value should be less DBL_MAX on
6185 the host machine. We use here approximate minimum of maximal
6186 double floating point value required by ANSI C standard. It
6187 will work for non ANSI sun compiler too. */
6189 #define MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND 1.0E37
6191 /* The function estimate size of the single DFA used by PHR (pipeline
6192 hazards recognizer). */
6193 static double
6194 estimate_one_automaton_bound ()
6196 decl_t decl;
6197 double one_automaton_estimation_bound;
6198 double root_value;
6199 int i;
6201 one_automaton_estimation_bound = 1.0;
6202 for (i = 0; i < description->decls_num; i++)
6204 decl = description->decls [i];
6205 if (decl->mode == dm_unit)
6207 root_value = exp (log (decl->decl.unit.max_occ_cycle_num + 1.0)
6208 / automata_num);
6209 if (MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND / root_value
6210 > one_automaton_estimation_bound)
6211 one_automaton_estimation_bound *= root_value;
6214 return one_automaton_estimation_bound;
6217 /* The function compares unit declarations acoording to their maximal
6218 cycle in reservations. */
6219 static int
6220 compare_max_occ_cycle_nums (unit_decl_1, unit_decl_2)
6221 const void *unit_decl_1;
6222 const void *unit_decl_2;
6224 if (((*(decl_t *) unit_decl_1)->decl.unit.max_occ_cycle_num)
6225 < ((*(decl_t *) unit_decl_2)->decl.unit.max_occ_cycle_num))
6226 return 1;
6227 else if (((*(decl_t *) unit_decl_1)->decl.unit.max_occ_cycle_num)
6228 == ((*(decl_t *) unit_decl_2)->decl.unit.max_occ_cycle_num))
6229 return 0;
6230 else
6231 return -1;
6234 /* The function makes heuristic assigning automata to units. Actually
6235 efficacy of the algorithm has been checked yet??? */
6236 static void
6237 units_to_automata_heuristic_distr ()
6239 double estimation_bound;
6240 decl_t decl;
6241 decl_t *unit_decl_ptr;
6242 int automaton_num;
6243 int rest_units_num;
6244 double bound_value;
6245 vla_ptr_t unit_decls;
6246 int i;
6248 if (description->units_num == 0)
6249 return;
6250 estimation_bound = estimate_one_automaton_bound ();
6251 VLA_PTR_CREATE (unit_decls, 150, "unit decls");
6252 for (i = 0; i < description->decls_num; i++)
6254 decl = description->decls [i];
6255 if (decl->mode == dm_unit)
6256 VLA_PTR_ADD (unit_decls, decl);
6258 qsort (VLA_PTR_BEGIN (unit_decls), VLA_PTR_LENGTH (unit_decls),
6259 sizeof (decl_t), compare_max_occ_cycle_nums);
6260 automaton_num = 0;
6261 unit_decl_ptr = VLA_PTR_BEGIN (unit_decls);
6262 bound_value = (*unit_decl_ptr)->decl.unit.max_occ_cycle_num;
6263 (*unit_decl_ptr)->decl.unit.corresponding_automaton_num = automaton_num;
6264 for (unit_decl_ptr++;
6265 unit_decl_ptr <= (decl_t *) VLA_PTR_LAST (unit_decls);
6266 unit_decl_ptr++)
6268 rest_units_num
6269 = ((decl_t *) VLA_PTR_LAST (unit_decls) - unit_decl_ptr + 1);
6270 if (automata_num - automaton_num - 1 > rest_units_num)
6271 abort ();
6272 if (automaton_num < automata_num - 1
6273 && ((automata_num - automaton_num - 1 == rest_units_num)
6274 || (bound_value
6275 > (estimation_bound
6276 / ((*unit_decl_ptr)->decl.unit.max_occ_cycle_num)))))
6278 bound_value = (*unit_decl_ptr)->decl.unit.max_occ_cycle_num;
6279 automaton_num++;
6281 else
6282 bound_value *= (*unit_decl_ptr)->decl.unit.max_occ_cycle_num;
6283 (*unit_decl_ptr)->decl.unit.corresponding_automaton_num = automaton_num;
6285 if (automaton_num != automata_num - 1)
6286 abort ();
6287 VLA_PTR_DELETE (unit_decls);
6290 /* The functions creates automaton insns for each automata. Automaton
6291 insn is simply insn for given automaton which makes reservation
6292 only of units of the automaton. */
6293 static ainsn_t
6294 create_ainsns ()
6296 decl_t decl;
6297 ainsn_t first_ainsn;
6298 ainsn_t curr_ainsn;
6299 ainsn_t prev_ainsn;
6300 int i;
6302 first_ainsn = NULL;
6303 prev_ainsn = NULL;
6304 for (i = 0; i < description->decls_num; i++)
6306 decl = description->decls [i];
6307 if (decl->mode == dm_insn_reserv)
6309 curr_ainsn = create_node (sizeof (struct ainsn));
6310 curr_ainsn->insn_reserv_decl = &decl->decl.insn_reserv;
6311 curr_ainsn->important_p = FALSE;
6312 curr_ainsn->next_ainsn = NULL;
6313 if (prev_ainsn == NULL)
6314 first_ainsn = curr_ainsn;
6315 else
6316 prev_ainsn->next_ainsn = curr_ainsn;
6317 prev_ainsn = curr_ainsn;
6320 return first_ainsn;
6323 /* The function assigns automata to units according to constructions
6324 `define_automaton' in the description. */
6325 static void
6326 units_to_automata_distr ()
6328 decl_t decl;
6329 int i;
6331 for (i = 0; i < description->decls_num; i++)
6333 decl = description->decls [i];
6334 if (decl->mode == dm_unit)
6336 if (decl->decl.unit.automaton_decl == NULL
6337 || (decl->decl.unit.automaton_decl->corresponding_automaton
6338 == NULL))
6339 /* Distribute to the first automaton. */
6340 decl->decl.unit.corresponding_automaton_num = 0;
6341 else
6342 decl->decl.unit.corresponding_automaton_num
6343 = (decl->decl.unit.automaton_decl
6344 ->corresponding_automaton->automaton_order_num);
6349 /* The function creates DFA(s) for fast pipeline hazards recognition
6350 after checking and simplifying IR of the description. */
6351 static void
6352 create_automata ()
6354 automaton_t curr_automaton;
6355 automaton_t prev_automaton;
6356 decl_t decl;
6357 int curr_automaton_num;
6358 int i;
6360 if (automata_num != 0)
6362 units_to_automata_heuristic_distr ();
6363 for (prev_automaton = NULL, curr_automaton_num = 0;
6364 curr_automaton_num < automata_num;
6365 curr_automaton_num++, prev_automaton = curr_automaton)
6367 curr_automaton = create_node (sizeof (struct automaton));
6368 curr_automaton->ainsn_list = create_ainsns ();
6369 curr_automaton->corresponding_automaton_decl = NULL;
6370 curr_automaton->next_automaton = NULL;
6371 curr_automaton->automaton_order_num = curr_automaton_num;
6372 if (prev_automaton == NULL)
6373 description->first_automaton = curr_automaton;
6374 else
6375 prev_automaton->next_automaton = curr_automaton;
6378 else
6380 curr_automaton_num = 0;
6381 prev_automaton = NULL;
6382 for (i = 0; i < description->decls_num; i++)
6384 decl = description->decls [i];
6385 if (decl->mode == dm_automaton
6386 && decl->decl.automaton.automaton_is_used)
6388 curr_automaton = create_node (sizeof (struct automaton));
6389 curr_automaton->ainsn_list = create_ainsns ();
6390 curr_automaton->corresponding_automaton_decl
6391 = &decl->decl.automaton;
6392 curr_automaton->next_automaton = NULL;
6393 decl->decl.automaton.corresponding_automaton = curr_automaton;
6394 curr_automaton->automaton_order_num = curr_automaton_num;
6395 if (prev_automaton == NULL)
6396 description->first_automaton = curr_automaton;
6397 else
6398 prev_automaton->next_automaton = curr_automaton;
6399 curr_automaton_num++;
6400 prev_automaton = curr_automaton;
6403 if (curr_automaton_num == 0)
6405 curr_automaton = create_node (sizeof (struct automaton));
6406 curr_automaton->ainsn_list = create_ainsns ();
6407 curr_automaton->corresponding_automaton_decl = NULL;
6408 curr_automaton->next_automaton = NULL;
6409 description->first_automaton = curr_automaton;
6411 units_to_automata_distr ();
6413 NDFA_time = create_ticker ();
6414 ticker_off (&NDFA_time);
6415 NDFA_to_DFA_time = create_ticker ();
6416 ticker_off (&NDFA_to_DFA_time);
6417 minimize_time = create_ticker ();
6418 ticker_off (&minimize_time);
6419 equiv_time = create_ticker ();
6420 ticker_off (&equiv_time);
6421 for (curr_automaton = description->first_automaton;
6422 curr_automaton != NULL;
6423 curr_automaton = curr_automaton->next_automaton)
6425 if (curr_automaton->corresponding_automaton_decl == NULL)
6426 fprintf (stderr, "Create anonymous automaton ...");
6427 else
6428 fprintf (stderr, "Create automaton `%s'...",
6429 curr_automaton->corresponding_automaton_decl->name);
6430 create_alt_states (curr_automaton);
6431 form_ainsn_with_same_reservs (curr_automaton);
6432 build_automaton (curr_automaton);
6433 enumerate_states (curr_automaton);
6434 ticker_on (&equiv_time);
6435 set_insn_equiv_classes (curr_automaton);
6436 ticker_off (&equiv_time);
6437 fprintf (stderr, "done\n");
6443 /* This page contains code for forming string representation of
6444 regexp. The representation is formed on IR obstack. So you should
6445 not work with IR obstack between regexp_representation and
6446 finish_regexp_representation calls. */
6448 /* This recursive function forms string representation of regexp
6449 (without tailing '\0'). */
6450 static void
6451 form_regexp (regexp)
6452 regexp_t regexp;
6454 int i;
6456 if (regexp->mode == rm_unit || regexp->mode == rm_reserv)
6458 const char *name = (regexp->mode == rm_unit
6459 ? regexp->regexp.unit.name
6460 : regexp->regexp.reserv.name);
6462 obstack_grow (&irp, name, strlen (name));
6464 else if (regexp->mode == rm_sequence)
6465 for (i = 0; i < regexp->regexp.sequence.regexps_num; i++)
6467 if (i != 0)
6468 obstack_1grow (&irp, ',');
6469 form_regexp (regexp->regexp.sequence.regexps [i]);
6471 else if (regexp->mode == rm_allof)
6473 obstack_1grow (&irp, '(');
6474 for (i = 0; i < regexp->regexp.allof.regexps_num; i++)
6476 if (i != 0)
6477 obstack_1grow (&irp, '+');
6478 if (regexp->regexp.allof.regexps[i]->mode == rm_sequence
6479 || regexp->regexp.oneof.regexps[i]->mode == rm_oneof)
6480 obstack_1grow (&irp, '(');
6481 form_regexp (regexp->regexp.allof.regexps [i]);
6482 if (regexp->regexp.allof.regexps[i]->mode == rm_sequence
6483 || regexp->regexp.oneof.regexps[i]->mode == rm_oneof)
6484 obstack_1grow (&irp, ')');
6486 obstack_1grow (&irp, ')');
6488 else if (regexp->mode == rm_oneof)
6489 for (i = 0; i < regexp->regexp.oneof.regexps_num; i++)
6491 if (i != 0)
6492 obstack_1grow (&irp, '|');
6493 if (regexp->regexp.oneof.regexps[i]->mode == rm_sequence)
6494 obstack_1grow (&irp, '(');
6495 form_regexp (regexp->regexp.oneof.regexps [i]);
6496 if (regexp->regexp.oneof.regexps[i]->mode == rm_sequence)
6497 obstack_1grow (&irp, ')');
6499 else if (regexp->mode == rm_repeat)
6501 char digits [30];
6503 if (regexp->regexp.repeat.regexp->mode == rm_sequence
6504 || regexp->regexp.repeat.regexp->mode == rm_allof
6505 || regexp->regexp.repeat.regexp->mode == rm_oneof)
6506 obstack_1grow (&irp, '(');
6507 form_regexp (regexp->regexp.repeat.regexp);
6508 if (regexp->regexp.repeat.regexp->mode == rm_sequence
6509 || regexp->regexp.repeat.regexp->mode == rm_allof
6510 || regexp->regexp.repeat.regexp->mode == rm_oneof)
6511 obstack_1grow (&irp, ')');
6512 sprintf (digits, "*%d", regexp->regexp.repeat.repeat_num);
6513 obstack_grow (&irp, digits, strlen (digits));
6515 else if (regexp->mode == rm_nothing)
6516 obstack_grow (&irp, NOTHING_NAME, strlen (NOTHING_NAME));
6517 else
6518 abort ();
6521 /* The function returns string representation of REGEXP on IR
6522 obstack. */
6523 static const char *
6524 regexp_representation (regexp)
6525 regexp_t regexp;
6527 form_regexp (regexp);
6528 obstack_1grow (&irp, '\0');
6529 return obstack_base (&irp);
6532 /* The function frees memory allocated for last formed string
6533 representation of regexp. */
6534 static void
6535 finish_regexp_representation ()
6537 int length = obstack_object_size (&irp);
6539 obstack_blank_fast (&irp, -length);
6544 /* This page contains code for output PHR (pipeline hazards recognizer). */
6546 /* The function outputs minimal C type which is sufficient for
6547 representation numbers in range min_range_value and
6548 max_range_value. Because host machine and build machine may be
6549 different, we use here minimal values required by ANSI C standard
6550 instead of UCHAR_MAX, SHRT_MAX, SHRT_MIN, etc. This is a good
6551 approximation. */
6553 static void
6554 output_range_type (f, min_range_value, max_range_value)
6555 FILE *f;
6556 long int min_range_value;
6557 long int max_range_value;
6559 if (min_range_value >= 0 && max_range_value <= 255)
6560 fprintf (f, "unsigned char");
6561 else if (min_range_value >= -127 && max_range_value <= 127)
6562 fprintf (f, "signed char");
6563 else if (min_range_value >= 0 && max_range_value <= 65535)
6564 fprintf (f, "unsigned short");
6565 else if (min_range_value >= -32767 && max_range_value <= 32767)
6566 fprintf (f, "short");
6567 else
6568 fprintf (f, "int");
6571 /* The following macro value is used as value of member
6572 `longest_path_length' of state when we are processing path and the
6573 state on the path. */
6575 #define ON_THE_PATH -2
6577 /* The following recursive function searches for the length of the
6578 longest path starting from STATE which does not contain cycles and
6579 `cycle advance' arcs. */
6581 static int
6582 longest_path_length (state)
6583 state_t state;
6585 arc_t arc;
6586 int length, result;
6588 if (state->longest_path_length == ON_THE_PATH)
6589 /* We don't expect the path cycle here. Our graph may contain
6590 only cycles with one state on the path not containing `cycle
6591 advance' arcs -- see comment below. */
6592 abort ();
6593 else if (state->longest_path_length != UNDEFINED_LONGEST_PATH_LENGTH)
6594 /* We alreday visited the state. */
6595 return state->longest_path_length;
6597 result = 0;
6598 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6599 /* Ignore cycles containing one state and `cycle advance' arcs. */
6600 if (arc->to_state != state
6601 && (arc->insn->insn_reserv_decl
6602 != &advance_cycle_insn_decl->decl.insn_reserv))
6604 length = longest_path_length (arc->to_state);
6605 if (length > result)
6606 result = length;
6608 state->longest_path_length = result + 1;
6609 return result;
6612 /* The following variable value is value of the corresponding global
6613 variable in the automaton based pipeline interface. */
6615 static int max_dfa_issue_rate;
6617 /* The following function processes the longest path length staring
6618 from STATE to find MAX_DFA_ISSUE_RATE. */
6620 static void
6621 process_state_longest_path_length (state)
6622 state_t state;
6624 int value;
6626 value = longest_path_length (state);
6627 if (value > max_dfa_issue_rate)
6628 max_dfa_issue_rate = value;
6631 /* The following nacro value is name of the corresponding global
6632 variable in the automaton based pipeline interface. */
6634 #define MAX_DFA_ISSUE_RATE_VAR_NAME "max_dfa_issue_rate"
6636 /* The following function calculates value of the the corresponding
6637 global variable and outputs its declaration. */
6639 static void
6640 output_dfa_max_issue_rate ()
6642 automaton_t automaton;
6644 if (UNDEFINED_LONGEST_PATH_LENGTH == ON_THE_PATH || ON_THE_PATH >= 0)
6645 abort ();
6646 max_dfa_issue_rate = 0;
6647 for (automaton = description->first_automaton;
6648 automaton != NULL;
6649 automaton = automaton->next_automaton)
6650 pass_states (automaton, process_state_longest_path_length);
6651 fprintf (output_file, "\nint %s = %d;\n",
6652 MAX_DFA_ISSUE_RATE_VAR_NAME, max_dfa_issue_rate);
6655 /* The function outputs all initialization values of VECT with length
6656 vect_length. */
6657 static void
6658 output_vect (vect, vect_length)
6659 vect_el_t *vect;
6660 int vect_length;
6662 int els_on_line;
6664 els_on_line = 1;
6665 if (vect_length == 0)
6666 fprintf (output_file,
6667 "0 /* This is dummy el because the vect is empty */");
6668 else
6672 fprintf (output_file, "%5ld", (long) *vect);
6673 vect_length--;
6674 if (els_on_line == 10)
6676 els_on_line = 0;
6677 fprintf (output_file, ",\n");
6679 else if (vect_length != 0)
6680 fprintf (output_file, ", ");
6681 els_on_line++;
6682 vect++;
6684 while (vect_length != 0);
6688 /* The following is name of the structure which represents DFA(s) for
6689 PHR. */
6690 #define CHIP_NAME "DFA_chip"
6692 /* The following is name of member which represents state of a DFA for
6693 PHR. */
6694 static void
6695 output_chip_member_name (f, automaton)
6696 FILE *f;
6697 automaton_t automaton;
6699 if (automaton->corresponding_automaton_decl == NULL)
6700 fprintf (f, "automaton_state_%d", automaton->automaton_order_num);
6701 else
6702 fprintf (f, "%s_automaton_state",
6703 automaton->corresponding_automaton_decl->name);
6706 /* The following is name of temporary variable which stores state of a
6707 DFA for PHR. */
6708 static void
6709 output_temp_chip_member_name (f, automaton)
6710 FILE *f;
6711 automaton_t automaton;
6713 fprintf (f, "_");
6714 output_chip_member_name (f, automaton);
6717 /* This is name of macro value which is code of pseudo_insn
6718 representing advancing cpu cycle. Its value is used as internal
6719 code unknown insn. */
6720 #define ADVANCE_CYCLE_VALUE_NAME "DFA__ADVANCE_CYCLE"
6722 /* Output name of translate vector for given automaton. */
6723 static void
6724 output_translate_vect_name (f, automaton)
6725 FILE *f;
6726 automaton_t automaton;
6728 if (automaton->corresponding_automaton_decl == NULL)
6729 fprintf (f, "translate_%d", automaton->automaton_order_num);
6730 else
6731 fprintf (f, "%s_translate", automaton->corresponding_automaton_decl->name);
6734 /* Output name for simple transition table representation. */
6735 static void
6736 output_trans_full_vect_name (f, automaton)
6737 FILE *f;
6738 automaton_t automaton;
6740 if (automaton->corresponding_automaton_decl == NULL)
6741 fprintf (f, "transitions_%d", automaton->automaton_order_num);
6742 else
6743 fprintf (f, "%s_transitions",
6744 automaton->corresponding_automaton_decl->name);
6747 /* Output name of comb vector of the transition table for given
6748 automaton. */
6749 static void
6750 output_trans_comb_vect_name (f, automaton)
6751 FILE *f;
6752 automaton_t automaton;
6754 if (automaton->corresponding_automaton_decl == NULL)
6755 fprintf (f, "transitions_%d", automaton->automaton_order_num);
6756 else
6757 fprintf (f, "%s_transitions",
6758 automaton->corresponding_automaton_decl->name);
6761 /* Output name of check vector of the transition table for given
6762 automaton. */
6763 static void
6764 output_trans_check_vect_name (f, automaton)
6765 FILE *f;
6766 automaton_t automaton;
6768 if (automaton->corresponding_automaton_decl == NULL)
6769 fprintf (f, "check_%d", automaton->automaton_order_num);
6770 else
6771 fprintf (f, "%s_check", automaton->corresponding_automaton_decl->name);
6774 /* Output name of base vector of the transition table for given
6775 automaton. */
6776 static void
6777 output_trans_base_vect_name (f, automaton)
6778 FILE *f;
6779 automaton_t automaton;
6781 if (automaton->corresponding_automaton_decl == NULL)
6782 fprintf (f, "base_%d", automaton->automaton_order_num);
6783 else
6784 fprintf (f, "%s_base", automaton->corresponding_automaton_decl->name);
6787 /* Output name for simple alternatives number representation. */
6788 static void
6789 output_state_alts_full_vect_name (f, automaton)
6790 FILE *f;
6791 automaton_t automaton;
6793 if (automaton->corresponding_automaton_decl == NULL)
6794 fprintf (f, "state_alts_%d", automaton->automaton_order_num);
6795 else
6796 fprintf (f, "%s_state_alts",
6797 automaton->corresponding_automaton_decl->name);
6800 /* Output name of comb vector of the alternatives number table for given
6801 automaton. */
6802 static void
6803 output_state_alts_comb_vect_name (f, automaton)
6804 FILE *f;
6805 automaton_t automaton;
6807 if (automaton->corresponding_automaton_decl == NULL)
6808 fprintf (f, "state_alts_%d", automaton->automaton_order_num);
6809 else
6810 fprintf (f, "%s_state_alts",
6811 automaton->corresponding_automaton_decl->name);
6814 /* Output name of check vector of the alternatives number table for given
6815 automaton. */
6816 static void
6817 output_state_alts_check_vect_name (f, automaton)
6818 FILE *f;
6819 automaton_t automaton;
6821 if (automaton->corresponding_automaton_decl == NULL)
6822 fprintf (f, "check_state_alts_%d", automaton->automaton_order_num);
6823 else
6824 fprintf (f, "%s_check_state_alts",
6825 automaton->corresponding_automaton_decl->name);
6828 /* Output name of base vector of the alternatives number table for given
6829 automaton. */
6830 static void
6831 output_state_alts_base_vect_name (f, automaton)
6832 FILE *f;
6833 automaton_t automaton;
6835 if (automaton->corresponding_automaton_decl == NULL)
6836 fprintf (f, "base_state_alts_%d", automaton->automaton_order_num);
6837 else
6838 fprintf (f, "%s_base_state_alts",
6839 automaton->corresponding_automaton_decl->name);
6842 /* Output name of simple min issue delay table representation. */
6843 static void
6844 output_min_issue_delay_vect_name (f, automaton)
6845 FILE *f;
6846 automaton_t automaton;
6848 if (automaton->corresponding_automaton_decl == NULL)
6849 fprintf (f, "min_issue_delay_%d", automaton->automaton_order_num);
6850 else
6851 fprintf (f, "%s_min_issue_delay",
6852 automaton->corresponding_automaton_decl->name);
6855 /* Output name of deadlock vector for given automaton. */
6856 static void
6857 output_dead_lock_vect_name (f, automaton)
6858 FILE *f;
6859 automaton_t automaton;
6861 if (automaton->corresponding_automaton_decl == NULL)
6862 fprintf (f, "dead_lock_%d", automaton->automaton_order_num);
6863 else
6864 fprintf (f, "%s_dead_lock", automaton->corresponding_automaton_decl->name);
6867 /* Output name of reserved units table for AUTOMATON into file F. */
6868 static void
6869 output_reserved_units_table_name (f, automaton)
6870 FILE *f;
6871 automaton_t automaton;
6873 if (automaton->corresponding_automaton_decl == NULL)
6874 fprintf (f, "reserved_units_%d", automaton->automaton_order_num);
6875 else
6876 fprintf (f, "%s_reserved_units",
6877 automaton->corresponding_automaton_decl->name);
6880 /* Name of the PHR interface macro. */
6881 #define AUTOMATON_STATE_ALTS_MACRO_NAME "AUTOMATON_STATE_ALTS"
6883 /* Name of the PHR interface macro. */
6884 #define CPU_UNITS_QUERY_MACRO_NAME "CPU_UNITS_QUERY"
6886 /* Names of an internal functions: */
6887 #define INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME "internal_min_issue_delay"
6889 /* This is external type of DFA(s) state. */
6890 #define STATE_TYPE_NAME "state_t"
6892 #define INTERNAL_TRANSITION_FUNC_NAME "internal_state_transition"
6894 #define INTERNAL_STATE_ALTS_FUNC_NAME "internal_state_alts"
6896 #define INTERNAL_RESET_FUNC_NAME "internal_reset"
6898 #define INTERNAL_DEAD_LOCK_FUNC_NAME "internal_state_dead_lock_p"
6900 #define INTERNAL_INSN_LATENCY_FUNC_NAME "internal_insn_latency"
6902 /* Name of cache of insn dfa codes. */
6903 #define DFA_INSN_CODES_VARIABLE_NAME "dfa_insn_codes"
6905 /* Name of length of cache of insn dfa codes. */
6906 #define DFA_INSN_CODES_LENGTH_VARIABLE_NAME "dfa_insn_codes_length"
6908 /* Names of the PHR interface functions: */
6909 #define SIZE_FUNC_NAME "state_size"
6911 #define TRANSITION_FUNC_NAME "state_transition"
6913 #define STATE_ALTS_FUNC_NAME "state_alts"
6915 #define MIN_ISSUE_DELAY_FUNC_NAME "min_issue_delay"
6917 #define MIN_INSN_CONFLICT_DELAY_FUNC_NAME "min_insn_conflict_delay"
6919 #define DEAD_LOCK_FUNC_NAME "state_dead_lock_p"
6921 #define RESET_FUNC_NAME "state_reset"
6923 #define INSN_LATENCY_FUNC_NAME "insn_latency"
6925 #define PRINT_RESERVATION_FUNC_NAME "print_reservation"
6927 #define GET_CPU_UNIT_CODE_FUNC_NAME "get_cpu_unit_code"
6929 #define CPU_UNIT_RESERVATION_P_FUNC_NAME "cpu_unit_reservation_p"
6931 #define DFA_START_FUNC_NAME "dfa_start"
6933 #define DFA_FINISH_FUNC_NAME "dfa_finish"
6935 /* Names of parameters of the PHR interface functions. */
6936 #define STATE_NAME "state"
6938 #define INSN_PARAMETER_NAME "insn"
6940 #define INSN2_PARAMETER_NAME "insn2"
6942 #define CHIP_PARAMETER_NAME "chip"
6944 #define FILE_PARAMETER_NAME "f"
6946 #define CPU_UNIT_NAME_PARAMETER_NAME "cpu_unit_name"
6948 #define CPU_CODE_PARAMETER_NAME "cpu_unit_code"
6950 /* Names of the variables whose values are internal insn code of rtx
6951 insn. */
6952 #define INTERNAL_INSN_CODE_NAME "insn_code"
6954 #define INTERNAL_INSN2_CODE_NAME "insn2_code"
6956 /* Names of temporary variables in some functions. */
6957 #define TEMPORARY_VARIABLE_NAME "temp"
6959 #define I_VARIABLE_NAME "i"
6961 /* Name of result variable in some functions. */
6962 #define RESULT_VARIABLE_NAME "res"
6964 /* Name of function (attribute) to translate insn into number of insn
6965 alternatives reservation. */
6966 #define INSN_ALTS_FUNC_NAME "insn_alts"
6968 /* Name of function (attribute) to translate insn into internal insn
6969 code. */
6970 #define INTERNAL_DFA_INSN_CODE_FUNC_NAME "internal_dfa_insn_code"
6972 /* Name of function (attribute) to translate insn into internal insn
6973 code with caching. */
6974 #define DFA_INSN_CODE_FUNC_NAME "dfa_insn_code"
6976 /* Name of function (attribute) to translate insn into internal insn
6977 code. */
6978 #define INSN_DEFAULT_LATENCY_FUNC_NAME "insn_default_latency"
6980 /* Name of function (attribute) to translate insn into internal insn
6981 code. */
6982 #define BYPASS_P_FUNC_NAME "bypass_p"
6984 /* Output C type which is used for representation of codes of states
6985 of AUTOMATON. */
6986 static void
6987 output_state_member_type (f, automaton)
6988 FILE *f;
6989 automaton_t automaton;
6991 output_range_type (f, 0, automaton->achieved_states_num);
6994 /* Output definition of the structure representing current DFA(s)
6995 state(s). */
6996 static void
6997 output_chip_definitions ()
6999 automaton_t automaton;
7001 fprintf (output_file, "struct %s\n{\n", CHIP_NAME);
7002 for (automaton = description->first_automaton;
7003 automaton != NULL;
7004 automaton = automaton->next_automaton)
7006 fprintf (output_file, " ");
7007 output_state_member_type (output_file, automaton);
7008 fprintf (output_file, " ");
7009 output_chip_member_name (output_file, automaton);
7010 fprintf (output_file, ";\n");
7012 fprintf (output_file, "};\n\n");
7013 #if 0
7014 fprintf (output_file, "static struct %s %s;\n\n", CHIP_NAME, CHIP_NAME);
7015 #endif
7019 /* The function outputs translate vector of internal insn code into
7020 insn equivalence class number. The equivalence class number is
7021 used to access to table and vectors reprewsenting DFA(s). */
7022 static void
7023 output_translate_vect (automaton)
7024 automaton_t automaton;
7026 ainsn_t ainsn;
7027 int insn_value;
7028 vla_hwint_t translate_vect;
7030 VLA_HWINT_CREATE (translate_vect, 250, "translate vector");
7031 VLA_HWINT_EXPAND (translate_vect, description->insns_num);
7032 for (insn_value = 0; insn_value <= description->insns_num; insn_value++)
7033 /* Undefined value */
7034 VLA_HWINT (translate_vect, insn_value) = automaton->insn_equiv_classes_num;
7035 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
7036 VLA_HWINT (translate_vect, ainsn->insn_reserv_decl->insn_num)
7037 = ainsn->insn_equiv_class_num;
7038 fprintf (output_file,
7039 "/* Vector translating external insn codes to internal ones.*/\n");
7040 fprintf (output_file, "static const ");
7041 output_range_type (output_file, 0, automaton->insn_equiv_classes_num);
7042 fprintf (output_file, " ");
7043 output_translate_vect_name (output_file, automaton);
7044 fprintf (output_file, "[] = {\n");
7045 output_vect (VLA_HWINT_BEGIN (translate_vect),
7046 VLA_HWINT_LENGTH (translate_vect));
7047 fprintf (output_file, "};\n\n");
7048 VLA_HWINT_DELETE (translate_vect);
7051 /* The value in a table state x ainsn -> something which represents
7052 undefined value. */
7053 static int undefined_vect_el_value;
7055 /* The following function returns nonzero value if the best
7056 representation of the table is comb vector. */
7057 static int
7058 comb_vect_p (tab)
7059 state_ainsn_table_t tab;
7061 return (2 * VLA_HWINT_LENGTH (tab->full_vect)
7062 > 5 * VLA_HWINT_LENGTH (tab->comb_vect));
7065 /* The following function creates new table for AUTOMATON. */
7066 static state_ainsn_table_t
7067 create_state_ainsn_table (automaton)
7068 automaton_t automaton;
7070 state_ainsn_table_t tab;
7071 int full_vect_length;
7072 int i;
7074 tab = create_node (sizeof (struct state_ainsn_table));
7075 tab->automaton = automaton;
7076 VLA_HWINT_CREATE (tab->comb_vect, 10000, "comb vector");
7077 VLA_HWINT_CREATE (tab->check_vect, 10000, "check vector");
7078 VLA_HWINT_CREATE (tab->base_vect, 1000, "base vector");
7079 VLA_HWINT_EXPAND (tab->base_vect, automaton->achieved_states_num);
7080 VLA_HWINT_CREATE (tab->full_vect, 10000, "full vector");
7081 full_vect_length = (automaton->insn_equiv_classes_num
7082 * automaton->achieved_states_num);
7083 VLA_HWINT_EXPAND (tab->full_vect, full_vect_length);
7084 for (i = 0; i < full_vect_length; i++)
7085 VLA_HWINT (tab->full_vect, i) = undefined_vect_el_value;
7086 tab->min_base_vect_el_value = 0;
7087 tab->max_base_vect_el_value = 0;
7088 tab->min_comb_vect_el_value = 0;
7089 tab->max_comb_vect_el_value = 0;
7090 return tab;
7093 /* The following function outputs the best C representation of the
7094 table TAB of given TABLE_NAME. */
7095 static void
7096 output_state_ainsn_table (tab, table_name, output_full_vect_name_func,
7097 output_comb_vect_name_func,
7098 output_check_vect_name_func,
7099 output_base_vect_name_func)
7100 state_ainsn_table_t tab;
7101 char *table_name;
7102 void (*output_full_vect_name_func) PARAMS ((FILE *, automaton_t));
7103 void (*output_comb_vect_name_func) PARAMS ((FILE *, automaton_t));
7104 void (*output_check_vect_name_func) PARAMS ((FILE *, automaton_t));
7105 void (*output_base_vect_name_func) PARAMS ((FILE *, automaton_t));
7107 if (!comb_vect_p (tab))
7109 fprintf (output_file, "/* Vector for %s. */\n", table_name);
7110 fprintf (output_file, "static const ");
7111 output_range_type (output_file, tab->min_comb_vect_el_value,
7112 tab->max_comb_vect_el_value);
7113 fprintf (output_file, " ");
7114 (*output_full_vect_name_func) (output_file, tab->automaton);
7115 fprintf (output_file, "[] = {\n");
7116 output_vect (VLA_HWINT_BEGIN (tab->full_vect),
7117 VLA_HWINT_LENGTH (tab->full_vect));
7118 fprintf (output_file, "};\n\n");
7120 else
7122 fprintf (output_file, "/* Comb vector for %s. */\n", table_name);
7123 fprintf (output_file, "static const ");
7124 output_range_type (output_file, tab->min_comb_vect_el_value,
7125 tab->max_comb_vect_el_value);
7126 fprintf (output_file, " ");
7127 (*output_comb_vect_name_func) (output_file, tab->automaton);
7128 fprintf (output_file, "[] = {\n");
7129 output_vect (VLA_HWINT_BEGIN (tab->comb_vect),
7130 VLA_HWINT_LENGTH (tab->comb_vect));
7131 fprintf (output_file, "};\n\n");
7132 fprintf (output_file, "/* Check vector for %s. */\n", table_name);
7133 fprintf (output_file, "static const ");
7134 output_range_type (output_file, 0, tab->automaton->achieved_states_num);
7135 fprintf (output_file, " ");
7136 (*output_check_vect_name_func) (output_file, tab->automaton);
7137 fprintf (output_file, "[] = {\n");
7138 output_vect (VLA_HWINT_BEGIN (tab->check_vect),
7139 VLA_HWINT_LENGTH (tab->check_vect));
7140 fprintf (output_file, "};\n\n");
7141 fprintf (output_file, "/* Base vector for %s. */\n", table_name);
7142 fprintf (output_file, "static const ");
7143 output_range_type (output_file, tab->min_base_vect_el_value,
7144 tab->max_base_vect_el_value);
7145 fprintf (output_file, " ");
7146 (*output_base_vect_name_func) (output_file, tab->automaton);
7147 fprintf (output_file, "[] = {\n");
7148 output_vect (VLA_HWINT_BEGIN (tab->base_vect),
7149 VLA_HWINT_LENGTH (tab->base_vect));
7150 fprintf (output_file, "};\n\n");
7154 /* The following function adds vector with length VECT_LENGTH and
7155 elements pointed by VECT to table TAB as its line with number
7156 VECT_NUM. */
7157 static void
7158 add_vect (tab, vect_num, vect, vect_length)
7159 state_ainsn_table_t tab;
7160 int vect_num;
7161 vect_el_t *vect;
7162 int vect_length;
7164 int real_vect_length;
7165 vect_el_t *comb_vect_start;
7166 vect_el_t *check_vect_start;
7167 int comb_vect_index;
7168 int comb_vect_els_num;
7169 int vect_index;
7170 int first_unempty_vect_index;
7171 int additional_els_num;
7172 int no_state_value;
7173 vect_el_t vect_el;
7174 int i;
7176 if (vect_length == 0)
7177 abort ();
7178 real_vect_length = tab->automaton->insn_equiv_classes_num;
7179 if (vect [vect_length - 1] == undefined_vect_el_value)
7180 abort ();
7181 /* Form full vector in the table: */
7182 for (i = 0; i < vect_length; i++)
7183 VLA_HWINT (tab->full_vect,
7184 i + tab->automaton->insn_equiv_classes_num * vect_num)
7185 = vect [i];
7186 /* Form comb vector in the table: */
7187 if (VLA_HWINT_LENGTH (tab->comb_vect) != VLA_HWINT_LENGTH (tab->check_vect))
7188 abort ();
7189 comb_vect_start = VLA_HWINT_BEGIN (tab->comb_vect);
7190 comb_vect_els_num = VLA_HWINT_LENGTH (tab->comb_vect);
7191 for (first_unempty_vect_index = 0;
7192 first_unempty_vect_index < vect_length;
7193 first_unempty_vect_index++)
7194 if (vect [first_unempty_vect_index] != undefined_vect_el_value)
7195 break;
7196 /* Search for the place in comb vect for the inserted vect. */
7197 for (comb_vect_index = 0;
7198 comb_vect_index < comb_vect_els_num;
7199 comb_vect_index++)
7201 for (vect_index = first_unempty_vect_index;
7202 vect_index < vect_length
7203 && vect_index + comb_vect_index < comb_vect_els_num;
7204 vect_index++)
7205 if (vect [vect_index] != undefined_vect_el_value
7206 && (comb_vect_start [vect_index + comb_vect_index]
7207 != undefined_vect_el_value))
7208 break;
7209 if (vect_index >= vect_length
7210 || vect_index + comb_vect_index >= comb_vect_els_num)
7211 break;
7213 /* Slot was found. */
7214 additional_els_num = comb_vect_index + real_vect_length - comb_vect_els_num;
7215 if (additional_els_num < 0)
7216 additional_els_num = 0;
7217 /* Expand comb and check vectors. */
7218 vect_el = undefined_vect_el_value;
7219 no_state_value = tab->automaton->achieved_states_num;
7220 while (additional_els_num > 0)
7222 VLA_HWINT_ADD (tab->comb_vect, vect_el);
7223 VLA_HWINT_ADD (tab->check_vect, no_state_value);
7224 additional_els_num--;
7226 comb_vect_start = VLA_HWINT_BEGIN (tab->comb_vect);
7227 check_vect_start = VLA_HWINT_BEGIN (tab->check_vect);
7228 if (VLA_HWINT_LENGTH (tab->comb_vect)
7229 < (size_t) (comb_vect_index + real_vect_length))
7230 abort ();
7231 /* Fill comb and check vectors. */
7232 for (vect_index = 0; vect_index < vect_length; vect_index++)
7233 if (vect [vect_index] != undefined_vect_el_value)
7235 if (comb_vect_start [comb_vect_index + vect_index]
7236 != undefined_vect_el_value)
7237 abort ();
7238 comb_vect_start [comb_vect_index + vect_index] = vect [vect_index];
7239 if (vect [vect_index] < 0)
7240 abort ();
7241 if (tab->max_comb_vect_el_value < vect [vect_index])
7242 tab->max_comb_vect_el_value = vect [vect_index];
7243 if (tab->min_comb_vect_el_value > vect [vect_index])
7244 tab->min_comb_vect_el_value = vect [vect_index];
7245 check_vect_start [comb_vect_index + vect_index] = vect_num;
7247 if (tab->max_base_vect_el_value < comb_vect_index)
7248 tab->max_base_vect_el_value = comb_vect_index;
7249 if (tab->min_base_vect_el_value > comb_vect_index)
7250 tab->min_base_vect_el_value = comb_vect_index;
7251 VLA_HWINT (tab->base_vect, vect_num) = comb_vect_index;
7254 /* Return number of out arcs of STATE. */
7255 static int
7256 out_state_arcs_num (state)
7257 state_t state;
7259 int result;
7260 arc_t arc;
7262 result = 0;
7263 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
7265 if (arc->insn == NULL)
7266 abort ();
7267 if (arc->insn->first_ainsn_with_given_equialence_num)
7268 result++;
7270 return result;
7273 /* Compare number of possible transitions from the states. */
7274 static int
7275 compare_transition_els_num (state_ptr_1, state_ptr_2)
7276 const void *state_ptr_1;
7277 const void *state_ptr_2;
7279 int transition_els_num_1;
7280 int transition_els_num_2;
7282 transition_els_num_1 = out_state_arcs_num (*(state_t *) state_ptr_1);
7283 transition_els_num_2 = out_state_arcs_num (*(state_t *) state_ptr_2);
7284 if (transition_els_num_1 < transition_els_num_2)
7285 return 1;
7286 else if (transition_els_num_1 == transition_els_num_2)
7287 return 0;
7288 else
7289 return -1;
7292 /* The function adds element EL_VALUE to vector VECT for a table state
7293 x AINSN. */
7294 static void
7295 add_vect_el (vect, ainsn, el_value)
7296 vla_hwint_t *vect;
7297 ainsn_t ainsn;
7298 int el_value;
7300 int equiv_class_num;
7301 int vect_index;
7303 if (ainsn == NULL)
7304 abort ();
7305 equiv_class_num = ainsn->insn_equiv_class_num;
7306 for (vect_index = VLA_HWINT_LENGTH (*vect);
7307 vect_index <= equiv_class_num;
7308 vect_index++)
7309 VLA_HWINT_ADD (*vect, undefined_vect_el_value);
7310 VLA_HWINT (*vect, equiv_class_num) = el_value;
7313 /* This is for forming vector of states of an automaton. */
7314 static vla_ptr_t output_states_vect;
7316 /* The function is called by function pass_states. The function adds
7317 STATE to `output_states_vect'. */
7318 static void
7319 add_states_vect_el (state)
7320 state_t state;
7322 VLA_PTR_ADD (output_states_vect, state);
7325 /* Form and output vectors (comb, check, base or full vector)
7326 representing transition table of AUTOMATON. */
7327 static void
7328 output_trans_table (automaton)
7329 automaton_t automaton;
7331 state_t *state_ptr;
7332 arc_t arc;
7333 vla_hwint_t transition_vect;
7335 undefined_vect_el_value = automaton->achieved_states_num;
7336 automaton->trans_table = create_state_ainsn_table (automaton);
7337 /* Create vect of pointers to states ordered by num of transitions
7338 from the state (state with the maximum num is the first). */
7339 VLA_PTR_CREATE (output_states_vect, 1500, "output states vector");
7340 pass_states (automaton, add_states_vect_el);
7341 qsort (VLA_PTR_BEGIN (output_states_vect),
7342 VLA_PTR_LENGTH (output_states_vect),
7343 sizeof (state_t), compare_transition_els_num);
7344 VLA_HWINT_CREATE (transition_vect, 500, "transition vector");
7345 for (state_ptr = VLA_PTR_BEGIN (output_states_vect);
7346 state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
7347 state_ptr++)
7349 VLA_HWINT_NULLIFY (transition_vect);
7350 for (arc = first_out_arc (*state_ptr);
7351 arc != NULL;
7352 arc = next_out_arc (arc))
7354 if (arc->insn == NULL)
7355 abort ();
7356 if (arc->insn->first_ainsn_with_given_equialence_num)
7357 add_vect_el (&transition_vect, arc->insn,
7358 arc->to_state->order_state_num);
7360 add_vect (automaton->trans_table, (*state_ptr)->order_state_num,
7361 VLA_HWINT_BEGIN (transition_vect),
7362 VLA_HWINT_LENGTH (transition_vect));
7364 output_state_ainsn_table
7365 (automaton->trans_table, (char *) "state transitions",
7366 output_trans_full_vect_name, output_trans_comb_vect_name,
7367 output_trans_check_vect_name, output_trans_base_vect_name);
7368 VLA_PTR_DELETE (output_states_vect);
7369 VLA_HWINT_DELETE (transition_vect);
7372 /* Form and output vectors (comb, check, base or simple vect)
7373 representing alts number table of AUTOMATON. The table is state x
7374 ainsn -> number of possible alternative reservations by the
7375 ainsn. */
7376 static void
7377 output_state_alts_table (automaton)
7378 automaton_t automaton;
7380 state_t *state_ptr;
7381 arc_t arc;
7382 vla_hwint_t state_alts_vect;
7384 undefined_vect_el_value = 0; /* no alts when transition is not possible */
7385 automaton->state_alts_table = create_state_ainsn_table (automaton);
7386 /* Create vect of pointers to states ordered by num of transitions
7387 from the state (state with the maximum num is the first). */
7388 VLA_PTR_CREATE (output_states_vect, 1500, "output states vector");
7389 pass_states (automaton, add_states_vect_el);
7390 qsort (VLA_PTR_BEGIN (output_states_vect),
7391 VLA_PTR_LENGTH (output_states_vect),
7392 sizeof (state_t), compare_transition_els_num);
7393 /* Create base, comb, and check vectors. */
7394 VLA_HWINT_CREATE (state_alts_vect, 500, "state alts vector");
7395 for (state_ptr = VLA_PTR_BEGIN (output_states_vect);
7396 state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
7397 state_ptr++)
7399 VLA_HWINT_NULLIFY (state_alts_vect);
7400 for (arc = first_out_arc (*state_ptr);
7401 arc != NULL;
7402 arc = next_out_arc (arc))
7404 if (arc->insn == NULL)
7405 abort ();
7406 if (arc->insn->first_ainsn_with_given_equialence_num)
7407 add_vect_el (&state_alts_vect, arc->insn, arc->state_alts);
7409 add_vect (automaton->state_alts_table, (*state_ptr)->order_state_num,
7410 VLA_HWINT_BEGIN (state_alts_vect),
7411 VLA_HWINT_LENGTH (state_alts_vect));
7413 output_state_ainsn_table
7414 (automaton->state_alts_table, (char *) "state insn alternatives",
7415 output_state_alts_full_vect_name, output_state_alts_comb_vect_name,
7416 output_state_alts_check_vect_name, output_state_alts_base_vect_name);
7417 VLA_PTR_DELETE (output_states_vect);
7418 VLA_HWINT_DELETE (state_alts_vect);
7421 /* The current number of passing states to find minimal issue delay
7422 value for an ainsn and state. */
7423 static int curr_state_pass_num;
7426 /* This recursive function passes states to find minimal issue delay
7427 value for AINSN. The state being visited is STATE. The function
7428 returns minimal issue delay value for AINSN in STATE or -1 if we
7429 enter into a loop. */
7430 static int
7431 min_issue_delay_pass_states (state, ainsn)
7432 state_t state;
7433 ainsn_t ainsn;
7435 arc_t arc;
7436 int min_insn_issue_delay, insn_issue_delay;
7438 if (state->state_pass_num == curr_state_pass_num
7439 || state->min_insn_issue_delay != -1)
7440 /* We've entered into a loop or already have the correct value for
7441 given state and ainsn. */
7442 return state->min_insn_issue_delay;
7443 state->state_pass_num = curr_state_pass_num;
7444 min_insn_issue_delay = -1;
7445 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
7446 if (arc->insn == ainsn)
7448 min_insn_issue_delay = 0;
7449 break;
7451 else
7453 insn_issue_delay = min_issue_delay_pass_states (arc->to_state, ainsn);
7454 if (insn_issue_delay != -1)
7456 if (arc->insn->insn_reserv_decl
7457 == &advance_cycle_insn_decl->decl.insn_reserv)
7458 insn_issue_delay++;
7459 if (min_insn_issue_delay == -1
7460 || min_insn_issue_delay > insn_issue_delay)
7462 min_insn_issue_delay = insn_issue_delay;
7463 if (insn_issue_delay == 0)
7464 break;
7468 return min_insn_issue_delay;
7471 /* The function searches minimal issue delay value for AINSN in STATE.
7472 The function can return negative value if we can not issue AINSN. We
7473 will report about it later. */
7474 static int
7475 min_issue_delay (state, ainsn)
7476 state_t state;
7477 ainsn_t ainsn;
7479 curr_state_pass_num++;
7480 state->min_insn_issue_delay = min_issue_delay_pass_states (state, ainsn);
7481 return state->min_insn_issue_delay;
7484 /* The function initiates code for finding minimal issue delay values.
7485 It should be called only once. */
7486 static void
7487 initiate_min_issue_delay_pass_states ()
7489 curr_state_pass_num = 0;
7492 /* Form and output vectors representing minimal issue delay table of
7493 AUTOMATON. The table is state x ainsn -> minimal issue delay of
7494 the ainsn. */
7495 static void
7496 output_min_issue_delay_table (automaton)
7497 automaton_t automaton;
7499 vla_hwint_t min_issue_delay_vect;
7500 vla_hwint_t compressed_min_issue_delay_vect;
7501 vect_el_t min_delay;
7502 ainsn_t ainsn;
7503 state_t *state_ptr;
7504 int i;
7506 /* Create vect of pointers to states ordered by num of transitions
7507 from the state (state with the maximum num is the first). */
7508 VLA_PTR_CREATE (output_states_vect, 1500, "output states vector");
7509 pass_states (automaton, add_states_vect_el);
7510 VLA_HWINT_CREATE (min_issue_delay_vect, 1500, "min issue delay vector");
7511 VLA_HWINT_EXPAND (min_issue_delay_vect,
7512 VLA_HWINT_LENGTH (output_states_vect)
7513 * automaton->insn_equiv_classes_num);
7514 for (i = 0;
7515 i < ((int) VLA_HWINT_LENGTH (output_states_vect)
7516 * automaton->insn_equiv_classes_num);
7517 i++)
7518 VLA_HWINT (min_issue_delay_vect, i) = 0;
7519 automaton->max_min_delay = 0;
7520 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
7521 if (ainsn->first_ainsn_with_given_equialence_num)
7523 for (state_ptr = VLA_PTR_BEGIN (output_states_vect);
7524 state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
7525 state_ptr++)
7526 (*state_ptr)->min_insn_issue_delay = -1;
7527 for (state_ptr = VLA_PTR_BEGIN (output_states_vect);
7528 state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
7529 state_ptr++)
7531 min_delay = min_issue_delay (*state_ptr, ainsn);
7532 if (automaton->max_min_delay < min_delay)
7533 automaton->max_min_delay = min_delay;
7534 VLA_HWINT (min_issue_delay_vect,
7535 (*state_ptr)->order_state_num
7536 * automaton->insn_equiv_classes_num
7537 + ainsn->insn_equiv_class_num) = min_delay;
7540 fprintf (output_file, "/* Vector of min issue delay of insns.*/\n");
7541 fprintf (output_file, "static const ");
7542 output_range_type (output_file, 0, automaton->max_min_delay);
7543 fprintf (output_file, " ");
7544 output_min_issue_delay_vect_name (output_file, automaton);
7545 fprintf (output_file, "[] = {\n");
7546 /* Compress the vector */
7547 if (automaton->max_min_delay < 2)
7548 automaton->min_issue_delay_table_compression_factor = 8;
7549 else if (automaton->max_min_delay < 4)
7550 automaton->min_issue_delay_table_compression_factor = 4;
7551 else if (automaton->max_min_delay < 16)
7552 automaton->min_issue_delay_table_compression_factor = 2;
7553 else
7554 automaton->min_issue_delay_table_compression_factor = 1;
7555 VLA_HWINT_CREATE (compressed_min_issue_delay_vect, 1500,
7556 "compressed min issue delay vector");
7557 VLA_HWINT_EXPAND (compressed_min_issue_delay_vect,
7558 (VLA_HWINT_LENGTH (min_issue_delay_vect)
7559 + automaton->min_issue_delay_table_compression_factor
7560 - 1)
7561 / automaton->min_issue_delay_table_compression_factor);
7562 for (i = 0;
7563 i < (int) VLA_HWINT_LENGTH (compressed_min_issue_delay_vect);
7564 i++)
7565 VLA_HWINT (compressed_min_issue_delay_vect, i) = 0;
7566 for (i = 0; i < (int) VLA_HWINT_LENGTH (min_issue_delay_vect); i++)
7567 VLA_HWINT (compressed_min_issue_delay_vect,
7568 i / automaton->min_issue_delay_table_compression_factor)
7569 |= (VLA_HWINT (min_issue_delay_vect, i)
7570 << (8 - (i % automaton->min_issue_delay_table_compression_factor
7571 + 1)
7572 * (8 / automaton->min_issue_delay_table_compression_factor)));
7573 output_vect (VLA_HWINT_BEGIN (compressed_min_issue_delay_vect),
7574 VLA_HWINT_LENGTH (compressed_min_issue_delay_vect));
7575 fprintf (output_file, "};\n\n");
7576 VLA_PTR_DELETE (output_states_vect);
7577 VLA_HWINT_DELETE (min_issue_delay_vect);
7578 VLA_HWINT_DELETE (compressed_min_issue_delay_vect);
7581 #ifndef NDEBUG
7582 /* Number of states which contains transition only by advancing cpu
7583 cycle. */
7584 static int locked_states_num;
7585 #endif
7587 /* Form and output vector representing the locked states of
7588 AUTOMATON. */
7589 static void
7590 output_dead_lock_vect (automaton)
7591 automaton_t automaton;
7593 state_t *state_ptr;
7594 arc_t arc;
7595 vla_hwint_t dead_lock_vect;
7597 /* Create vect of pointers to states ordered by num of
7598 transitions from the state (state with the maximum num is the
7599 first). */
7600 VLA_PTR_CREATE (output_states_vect, 1500, "output states vector");
7601 pass_states (automaton, add_states_vect_el);
7602 VLA_HWINT_CREATE (dead_lock_vect, 1500, "is dead locked vector");
7603 VLA_HWINT_EXPAND (dead_lock_vect, VLA_HWINT_LENGTH (output_states_vect));
7604 for (state_ptr = VLA_PTR_BEGIN (output_states_vect);
7605 state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
7606 state_ptr++)
7608 arc = first_out_arc (*state_ptr);
7609 if (arc == NULL)
7610 abort ();
7611 VLA_HWINT (dead_lock_vect, (*state_ptr)->order_state_num)
7612 = (next_out_arc (arc) == NULL
7613 && (arc->insn->insn_reserv_decl
7614 == &advance_cycle_insn_decl->decl.insn_reserv) ? 1 : 0);
7615 #ifndef NDEBUG
7616 if (VLA_HWINT (dead_lock_vect, (*state_ptr)->order_state_num))
7617 locked_states_num++;
7618 #endif
7620 fprintf (output_file, "/* Vector for locked state flags. */\n");
7621 fprintf (output_file, "static const ");
7622 output_range_type (output_file, 0, 1);
7623 fprintf (output_file, " ");
7624 output_dead_lock_vect_name (output_file, automaton);
7625 fprintf (output_file, "[] = {\n");
7626 output_vect (VLA_HWINT_BEGIN (dead_lock_vect),
7627 VLA_HWINT_LENGTH (dead_lock_vect));
7628 fprintf (output_file, "};\n\n");
7629 VLA_HWINT_DELETE (dead_lock_vect);
7630 VLA_PTR_DELETE (output_states_vect);
7633 /* Form and output vector representing reserved units of the states of
7634 AUTOMATON. */
7635 static void
7636 output_reserved_units_table (automaton)
7637 automaton_t automaton;
7639 state_t *curr_state_ptr;
7640 vla_hwint_t reserved_units_table;
7641 size_t state_byte_size;
7642 int i;
7644 /* Create vect of pointers to states. */
7645 VLA_PTR_CREATE (output_states_vect, 1500, "output states vector");
7646 pass_states (automaton, add_states_vect_el);
7647 /* Create vector. */
7648 VLA_HWINT_CREATE (reserved_units_table, 1500, "reserved units vector");
7649 state_byte_size = (description->query_units_num + 7) / 8;
7650 VLA_HWINT_EXPAND (reserved_units_table,
7651 VLA_HWINT_LENGTH (output_states_vect) * state_byte_size);
7652 for (i = 0;
7653 i < (int) (VLA_HWINT_LENGTH (output_states_vect) * state_byte_size);
7654 i++)
7655 VLA_HWINT (reserved_units_table, i) = 0;
7656 for (curr_state_ptr = VLA_PTR_BEGIN (output_states_vect);
7657 curr_state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
7658 curr_state_ptr++)
7660 for (i = 0; i < description->units_num; i++)
7661 if (units_array [i]->query_p)
7663 if (test_unit_reserv ((*curr_state_ptr)->reservs, 0, i))
7664 VLA_HWINT (reserved_units_table,
7665 (*curr_state_ptr)->order_state_num * state_byte_size
7666 + units_array [i]->query_num / 8)
7667 += (1 << (units_array [i]->query_num % 8));
7670 fprintf (output_file, "/* Vector for reserved units of states. */\n");
7671 fprintf (output_file, "static const ");
7672 output_range_type (output_file, 0, 255);
7673 fprintf (output_file, " ");
7674 output_reserved_units_table_name (output_file, automaton);
7675 fprintf (output_file, "[] = {\n");
7676 output_vect (VLA_HWINT_BEGIN (reserved_units_table),
7677 VLA_HWINT_LENGTH (reserved_units_table));
7678 fprintf (output_file, "};\n\n");
7679 VLA_HWINT_DELETE (reserved_units_table);
7680 VLA_PTR_DELETE (output_states_vect);
7683 /* The function outputs all tables representing DFA(s) used for fast
7684 pipeline hazards recognition. */
7685 static void
7686 output_tables ()
7688 automaton_t automaton;
7690 #ifndef NDEBUG
7691 locked_states_num = 0;
7692 #endif
7693 initiate_min_issue_delay_pass_states ();
7694 for (automaton = description->first_automaton;
7695 automaton != NULL;
7696 automaton = automaton->next_automaton)
7698 output_translate_vect (automaton);
7699 output_trans_table (automaton);
7700 fprintf (output_file, "\n#if %s\n", AUTOMATON_STATE_ALTS_MACRO_NAME);
7701 output_state_alts_table (automaton);
7702 fprintf (output_file, "\n#endif /* #if %s */\n\n",
7703 AUTOMATON_STATE_ALTS_MACRO_NAME);
7704 output_min_issue_delay_table (automaton);
7705 output_dead_lock_vect (automaton);
7706 if (no_minimization_flag)
7708 fprintf (output_file, "\n#if %s\n\n", CPU_UNITS_QUERY_MACRO_NAME);
7709 output_reserved_units_table (automaton);
7710 fprintf (output_file, "\n#endif /* #if %s */\n\n",
7711 CPU_UNITS_QUERY_MACRO_NAME);
7714 fprintf (output_file, "\n#define %s %d\n\n", ADVANCE_CYCLE_VALUE_NAME,
7715 advance_cycle_insn_decl->decl.insn_reserv.insn_num);
7718 /* The function outputs definition and value of PHR interface variable
7719 `max_insn_queue_index' */
7720 static void
7721 output_max_insn_queue_index_def ()
7723 int i;
7725 for (i = 0; (1 << i) <= description->max_insn_reserv_cycles; i++)
7727 if (i < 0)
7728 abort ();
7729 fprintf (output_file, "\nint max_insn_queue_index = %d;\n\n", (1 << i) - 1);
7733 /* The function outputs switch cases for insn reseravtions using
7734 function *output_automata_list_code. */
7735 static void
7736 output_insn_code_cases (output_automata_list_code)
7737 void (*output_automata_list_code) (automata_list_el_t);
7739 decl_t decl, decl_2;
7740 int i, j;
7742 for (i = 0; i < description->decls_num; i++)
7744 decl = description->decls [i];
7745 if (decl->mode == dm_insn_reserv)
7746 decl->decl.insn_reserv.processed_p = FALSE;
7748 for (i = 0; i < description->decls_num; i++)
7750 decl = description->decls [i];
7751 if (decl->mode == dm_insn_reserv && !decl->decl.insn_reserv.processed_p)
7753 for (j = i; j < description->decls_num; j++)
7755 decl_2 = description->decls [j];
7756 if (decl_2->mode == dm_insn_reserv
7757 && (decl_2->decl.insn_reserv.important_automata_list
7758 == decl->decl.insn_reserv.important_automata_list))
7760 decl_2->decl.insn_reserv.processed_p = TRUE;
7761 fprintf (output_file, " case %d: /* %s */\n",
7762 decl_2->decl.insn_reserv.insn_num,
7763 decl_2->decl.insn_reserv.name);
7766 (*output_automata_list_code)
7767 (decl->decl.insn_reserv.important_automata_list);
7773 /* The function outputs a code for evaluation of a minimal delay of
7774 issue of insns which have reservations in given AUTOMATA_LIST. */
7775 static void
7776 output_automata_list_min_issue_delay_code (automata_list)
7777 automata_list_el_t automata_list;
7779 automata_list_el_t el;
7780 automaton_t automaton;
7782 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
7784 automaton = el->automaton;
7785 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
7786 output_min_issue_delay_vect_name (output_file, automaton);
7787 fprintf (output_file,
7788 (automaton->min_issue_delay_table_compression_factor != 1
7789 ? " [(" : " ["));
7790 output_translate_vect_name (output_file, automaton);
7791 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
7792 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7793 output_chip_member_name (output_file, automaton);
7794 fprintf (output_file, " * %d", automaton->insn_equiv_classes_num);
7795 if (automaton->min_issue_delay_table_compression_factor == 1)
7796 fprintf (output_file, "];\n");
7797 else
7799 fprintf (output_file, ") / %d];\n",
7800 automaton->min_issue_delay_table_compression_factor);
7801 fprintf (output_file, " %s = (%s >> (8 - (",
7802 TEMPORARY_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
7803 output_translate_vect_name (output_file, automaton);
7804 fprintf
7805 (output_file, " [%s] %% %d + 1) * %d)) & %d;\n",
7806 INTERNAL_INSN_CODE_NAME,
7807 automaton->min_issue_delay_table_compression_factor,
7808 8 / automaton->min_issue_delay_table_compression_factor,
7809 (1 << (8 / automaton->min_issue_delay_table_compression_factor))
7810 - 1);
7812 if (el == automata_list)
7813 fprintf (output_file, " %s = %s;\n",
7814 RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
7815 else
7817 fprintf (output_file, " if (%s > %s)\n",
7818 TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
7819 fprintf (output_file, " %s = %s;\n",
7820 RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
7823 fprintf (output_file, " break;\n\n");
7826 /* Output function `internal_min_issue_delay'. */
7827 static void
7828 output_internal_min_issue_delay_func ()
7830 fprintf (output_file, "static int %s PARAMS ((int, struct %s *));\n",
7831 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, CHIP_NAME);
7832 fprintf (output_file,
7833 "static int\n%s (%s, %s)\n\tint %s;\n\tstruct %s *%s ATTRIBUTE_UNUSED;\n",
7834 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7835 CHIP_PARAMETER_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME,
7836 CHIP_PARAMETER_NAME);
7837 fprintf (output_file, "{\n int %s ATTRIBUTE_UNUSED;\n int %s;\n",
7838 TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
7839 fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
7840 output_insn_code_cases (output_automata_list_min_issue_delay_code);
7841 fprintf (output_file,
7842 "\n default:\n %s = -1;\n break;\n }\n",
7843 RESULT_VARIABLE_NAME);
7844 fprintf (output_file, " return %s;\n", RESULT_VARIABLE_NAME);
7845 fprintf (output_file, "}\n\n");
7848 /* The function outputs a code changing state after issue of insns
7849 which have reservations in given AUTOMATA_LIST. */
7850 static void
7851 output_automata_list_transition_code (automata_list)
7852 automata_list_el_t automata_list;
7854 automata_list_el_t el, next_el;
7856 fprintf (output_file, " {\n");
7857 if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
7858 for (el = automata_list;; el = next_el)
7860 next_el = el->next_automata_list_el;
7861 if (next_el == NULL)
7862 break;
7863 fprintf (output_file, " ");
7864 output_state_member_type (output_file, el->automaton);
7865 fprintf (output_file, " ");
7866 output_temp_chip_member_name (output_file, el->automaton);
7867 fprintf (output_file, ";\n");
7869 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
7870 if (comb_vect_p (el->automaton->trans_table))
7872 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
7873 output_trans_base_vect_name (output_file, el->automaton);
7874 fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
7875 output_chip_member_name (output_file, el->automaton);
7876 fprintf (output_file, "] + ");
7877 output_translate_vect_name (output_file, el->automaton);
7878 fprintf (output_file, " [%s];\n", INTERNAL_INSN_CODE_NAME);
7879 fprintf (output_file, " if (");
7880 output_trans_check_vect_name (output_file, el->automaton);
7881 fprintf (output_file, " [%s] != %s->",
7882 TEMPORARY_VARIABLE_NAME, CHIP_PARAMETER_NAME);
7883 output_chip_member_name (output_file, el->automaton);
7884 fprintf (output_file, ")\n");
7885 fprintf (output_file, " return %s (%s, %s);\n",
7886 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7887 CHIP_PARAMETER_NAME);
7888 fprintf (output_file, " else\n");
7889 fprintf (output_file, " ");
7890 if (el->next_automata_list_el != NULL)
7891 output_temp_chip_member_name (output_file, el->automaton);
7892 else
7894 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7895 output_chip_member_name (output_file, el->automaton);
7897 fprintf (output_file, " = ");
7898 output_trans_comb_vect_name (output_file, el->automaton);
7899 fprintf (output_file, " [%s];\n", TEMPORARY_VARIABLE_NAME);
7901 else
7903 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
7904 output_trans_full_vect_name (output_file, el->automaton);
7905 fprintf (output_file, " [");
7906 output_translate_vect_name (output_file, el->automaton);
7907 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
7908 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7909 output_chip_member_name (output_file, el->automaton);
7910 fprintf (output_file, " * %d];\n",
7911 el->automaton->insn_equiv_classes_num);
7912 fprintf (output_file, " if (%s >= %d)\n",
7913 TEMPORARY_VARIABLE_NAME, el->automaton->achieved_states_num);
7914 fprintf (output_file, " return %s (%s, %s);\n",
7915 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7916 CHIP_PARAMETER_NAME);
7917 fprintf (output_file, " else\n ");
7918 if (el->next_automata_list_el != NULL)
7919 output_temp_chip_member_name (output_file, el->automaton);
7920 else
7922 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7923 output_chip_member_name (output_file, el->automaton);
7925 fprintf (output_file, " = %s;\n", TEMPORARY_VARIABLE_NAME);
7927 if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
7928 for (el = automata_list;; el = next_el)
7930 next_el = el->next_automata_list_el;
7931 if (next_el == NULL)
7932 break;
7933 fprintf (output_file, " %s->", CHIP_PARAMETER_NAME);
7934 output_chip_member_name (output_file, el->automaton);
7935 fprintf (output_file, " = ");
7936 output_temp_chip_member_name (output_file, el->automaton);
7937 fprintf (output_file, ";\n");
7939 fprintf (output_file, " return -1;\n");
7940 fprintf (output_file, " }\n");
7943 /* Output function `internal_state_transition'. */
7944 static void
7945 output_internal_trans_func ()
7947 fprintf (output_file, "static int %s PARAMS ((int, struct %s *));\n",
7948 INTERNAL_TRANSITION_FUNC_NAME, CHIP_NAME);
7949 fprintf (output_file,
7950 "static int\n%s (%s, %s)\n\tint %s;\n\tstruct %s *%s ATTRIBUTE_UNUSED;\n",
7951 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7952 CHIP_PARAMETER_NAME, INTERNAL_INSN_CODE_NAME,
7953 CHIP_NAME, CHIP_PARAMETER_NAME);
7954 fprintf (output_file, "{\n int %s ATTRIBUTE_UNUSED;\n", TEMPORARY_VARIABLE_NAME);
7955 fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
7956 output_insn_code_cases (output_automata_list_transition_code);
7957 fprintf (output_file, "\n default:\n return -1;\n }\n");
7958 fprintf (output_file, "}\n\n");
7961 /* Output code
7963 if (insn != 0)
7965 insn_code = dfa_insn_code (insn);
7966 if (insn_code > DFA__ADVANCE_CYCLE)
7967 return code;
7969 else
7970 insn_code = DFA__ADVANCE_CYCLE;
7972 where insn denotes INSN_NAME, insn_code denotes INSN_CODE_NAME, and
7973 code denotes CODE. */
7974 static void
7975 output_internal_insn_code_evaluation (insn_name, insn_code_name, code)
7976 const char *insn_name;
7977 const char *insn_code_name;
7978 int code;
7980 fprintf (output_file, "\n if (%s != 0)\n {\n", insn_name);
7981 fprintf (output_file, " %s = %s (%s);\n", insn_code_name,
7982 DFA_INSN_CODE_FUNC_NAME, insn_name);
7983 fprintf (output_file, " if (%s > %s)\n return %d;\n",
7984 insn_code_name, ADVANCE_CYCLE_VALUE_NAME, code);
7985 fprintf (output_file, " }\n else\n %s = %s;\n\n",
7986 insn_code_name, ADVANCE_CYCLE_VALUE_NAME);
7990 /* The function outputs function `dfa_insn_code'. */
7991 static void
7992 output_dfa_insn_code_func ()
7994 fprintf (output_file, "#ifdef __GNUC__\n__inline__\n#endif\n");
7995 fprintf (output_file, "static int %s PARAMS ((rtx));\n",
7996 DFA_INSN_CODE_FUNC_NAME);
7997 fprintf (output_file, "static int\n%s (%s)\n\trtx %s;\n",
7998 DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME, INSN_PARAMETER_NAME);
7999 fprintf (output_file, "{\n int %s;\n int %s;\n\n",
8000 INTERNAL_INSN_CODE_NAME, TEMPORARY_VARIABLE_NAME);
8001 fprintf (output_file, " if (INSN_UID (%s) >= %s)\n {\n",
8002 INSN_PARAMETER_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8003 fprintf (output_file, " %s = %s;\n %s = 2 * INSN_UID (%s);\n",
8004 TEMPORARY_VARIABLE_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8005 DFA_INSN_CODES_LENGTH_VARIABLE_NAME, INSN_PARAMETER_NAME);
8006 fprintf (output_file, " %s = xrealloc (%s, %s * sizeof (int));\n",
8007 DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
8008 DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8009 fprintf (output_file,
8010 " for (; %s < %s; %s++)\n %s [%s] = -1;\n }\n",
8011 TEMPORARY_VARIABLE_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8012 TEMPORARY_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
8013 TEMPORARY_VARIABLE_NAME);
8014 fprintf (output_file, " if ((%s = %s [INSN_UID (%s)]) < 0)\n {\n",
8015 INTERNAL_INSN_CODE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
8016 INSN_PARAMETER_NAME);
8017 fprintf (output_file, " %s = %s (%s);\n", INTERNAL_INSN_CODE_NAME,
8018 INTERNAL_DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME);
8019 fprintf (output_file, " %s [INSN_UID (%s)] = %s;\n",
8020 DFA_INSN_CODES_VARIABLE_NAME, INSN_PARAMETER_NAME,
8021 INTERNAL_INSN_CODE_NAME);
8022 fprintf (output_file, " }\n return %s;\n}\n\n",
8023 INTERNAL_INSN_CODE_NAME);
8026 /* The function outputs PHR interface function `state_transition'. */
8027 static void
8028 output_trans_func ()
8030 fprintf (output_file, "int\n%s (%s, %s)\n\t%s %s;\n\trtx %s;\n",
8031 TRANSITION_FUNC_NAME, STATE_NAME, INSN_PARAMETER_NAME,
8032 STATE_TYPE_NAME, STATE_NAME, INSN_PARAMETER_NAME);
8033 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
8034 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8035 INTERNAL_INSN_CODE_NAME, -1);
8036 fprintf (output_file, " return %s (%s, %s);\n}\n\n",
8037 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, STATE_NAME);
8040 /* The function outputs a code for evaluation of alternative states
8041 number for insns which have reservations in given AUTOMATA_LIST. */
8042 static void
8043 output_automata_list_state_alts_code (automata_list)
8044 automata_list_el_t automata_list;
8046 automata_list_el_t el;
8047 automaton_t automaton;
8049 fprintf (output_file, " {\n");
8050 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
8051 if (comb_vect_p (el->automaton->state_alts_table))
8053 fprintf (output_file, " int %s;\n", TEMPORARY_VARIABLE_NAME);
8054 break;
8056 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
8058 automaton = el->automaton;
8059 if (comb_vect_p (automaton->state_alts_table))
8061 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
8062 output_state_alts_base_vect_name (output_file, automaton);
8063 fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
8064 output_chip_member_name (output_file, automaton);
8065 fprintf (output_file, "] + ");
8066 output_translate_vect_name (output_file, automaton);
8067 fprintf (output_file, " [%s];\n", INTERNAL_INSN_CODE_NAME);
8068 fprintf (output_file, " if (");
8069 output_state_alts_check_vect_name (output_file, automaton);
8070 fprintf (output_file, " [%s] != %s->",
8071 TEMPORARY_VARIABLE_NAME, CHIP_PARAMETER_NAME);
8072 output_chip_member_name (output_file, automaton);
8073 fprintf (output_file, ")\n");
8074 fprintf (output_file, " return 0;\n");
8075 fprintf (output_file, " else\n");
8076 fprintf (output_file,
8077 (el == automata_list
8078 ? " %s = " : " %s += "),
8079 RESULT_VARIABLE_NAME);
8080 output_state_alts_comb_vect_name (output_file, automaton);
8081 fprintf (output_file, " [%s];\n", TEMPORARY_VARIABLE_NAME);
8083 else
8085 fprintf (output_file,
8086 (el == automata_list
8087 ? "\n %s = " : " %s += "),
8088 RESULT_VARIABLE_NAME);
8089 output_state_alts_full_vect_name (output_file, automaton);
8090 fprintf (output_file, " [");
8091 output_translate_vect_name (output_file, automaton);
8092 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
8093 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
8094 output_chip_member_name (output_file, automaton);
8095 fprintf (output_file, " * %d];\n",
8096 automaton->insn_equiv_classes_num);
8099 fprintf (output_file, " break;\n }\n\n");
8102 /* Output function `internal_state_alts'. */
8103 static void
8104 output_internal_state_alts_func ()
8106 fprintf (output_file, "static int %s PARAMS ((int, struct %s *));\n",
8107 INTERNAL_STATE_ALTS_FUNC_NAME, CHIP_NAME);
8108 fprintf (output_file,
8109 "static int\n%s (%s, %s)\n\tint %s;\n\tstruct %s *%s;\n",
8110 INTERNAL_STATE_ALTS_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8111 CHIP_PARAMETER_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME,
8112 CHIP_PARAMETER_NAME);
8113 fprintf (output_file, "{\n int %s;\n", RESULT_VARIABLE_NAME);
8114 fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8115 output_insn_code_cases (output_automata_list_state_alts_code);
8116 fprintf (output_file,
8117 "\n default:\n %s = 0;\n break;\n }\n",
8118 RESULT_VARIABLE_NAME);
8119 fprintf (output_file, " return %s;\n", RESULT_VARIABLE_NAME);
8120 fprintf (output_file, "}\n\n");
8123 /* The function outputs PHR interface function `state_alts'. */
8124 static void
8125 output_state_alts_func ()
8127 fprintf (output_file, "int\n%s (%s, %s)\n\t%s %s;\n\trtx %s;\n",
8128 STATE_ALTS_FUNC_NAME, STATE_NAME, INSN_PARAMETER_NAME,
8129 STATE_TYPE_NAME, STATE_NAME, INSN_PARAMETER_NAME);
8130 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
8131 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8132 INTERNAL_INSN_CODE_NAME, 0);
8133 fprintf (output_file, " return %s (%s, %s);\n}\n\n",
8134 INTERNAL_STATE_ALTS_FUNC_NAME, INTERNAL_INSN_CODE_NAME, STATE_NAME);
8137 /* Output function `min_issue_delay'. */
8138 static void
8139 output_min_issue_delay_func ()
8141 fprintf (output_file, "int\n%s (%s, %s)\n\t%s %s;\n\trtx %s;\n",
8142 MIN_ISSUE_DELAY_FUNC_NAME, STATE_NAME, INSN_PARAMETER_NAME,
8143 STATE_TYPE_NAME, STATE_NAME, INSN_PARAMETER_NAME);
8144 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
8145 fprintf (output_file, "\n if (%s != 0)\n {\n", INSN_PARAMETER_NAME);
8146 fprintf (output_file, " %s = %s (%s);\n", INTERNAL_INSN_CODE_NAME,
8147 DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME);
8148 fprintf (output_file, " if (%s > %s)\n return 0;\n",
8149 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8150 fprintf (output_file, " }\n else\n %s = %s;\n",
8151 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8152 fprintf (output_file, "\n return %s (%s, %s);\n",
8153 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8154 STATE_NAME);
8155 fprintf (output_file, "}\n\n");
8158 /* Output function `internal_dead_lock'. */
8159 static void
8160 output_internal_dead_lock_func ()
8162 automaton_t automaton;
8164 fprintf (output_file, "static int %s PARAMS ((struct %s *));\n",
8165 INTERNAL_DEAD_LOCK_FUNC_NAME, CHIP_NAME);
8166 fprintf (output_file, "static int\n%s (%s)\n\tstruct %s *%s;\n",
8167 INTERNAL_DEAD_LOCK_FUNC_NAME, CHIP_PARAMETER_NAME, CHIP_NAME,
8168 CHIP_PARAMETER_NAME);
8169 fprintf (output_file, "{\n");
8170 for (automaton = description->first_automaton;
8171 automaton != NULL;
8172 automaton = automaton->next_automaton)
8174 fprintf (output_file, " if (");
8175 output_dead_lock_vect_name (output_file, automaton);
8176 fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
8177 output_chip_member_name (output_file, automaton);
8178 fprintf (output_file, "])\n return 1/* TRUE */;\n");
8180 fprintf (output_file, " return 0/* FALSE */;\n}\n\n");
8183 /* The function outputs PHR interface function `state_dead_lock_p'. */
8184 static void
8185 output_dead_lock_func ()
8187 fprintf (output_file, "int\n%s (%s)\n\t%s %s;\n",
8188 DEAD_LOCK_FUNC_NAME, STATE_NAME, STATE_TYPE_NAME, STATE_NAME);
8189 fprintf (output_file, "{\n return %s (%s);\n}\n\n",
8190 INTERNAL_DEAD_LOCK_FUNC_NAME, STATE_NAME);
8193 /* Output function `internal_reset'. */
8194 static void
8195 output_internal_reset_func ()
8197 fprintf (output_file, "static void %s PARAMS ((struct %s *));\n",
8198 INTERNAL_RESET_FUNC_NAME, CHIP_NAME);
8199 fprintf (output_file, "static void\n%s (%s)\n\tstruct %s *%s;\n",
8200 INTERNAL_RESET_FUNC_NAME, CHIP_PARAMETER_NAME,
8201 CHIP_NAME, CHIP_PARAMETER_NAME);
8202 fprintf (output_file, "{\n memset (%s, 0, sizeof (struct %s));\n}\n\n",
8203 CHIP_PARAMETER_NAME, CHIP_NAME);
8206 /* The function outputs PHR interface function `state_size'. */
8207 static void
8208 output_size_func ()
8210 fprintf (output_file, "int\n%s ()\n", SIZE_FUNC_NAME);
8211 fprintf (output_file, "{\n return sizeof (struct %s);\n}\n\n", CHIP_NAME);
8214 /* The function outputs PHR interface function `state_reset'. */
8215 static void
8216 output_reset_func ()
8218 fprintf (output_file, "void\n%s (%s)\n\t %s %s;\n",
8219 RESET_FUNC_NAME, STATE_NAME, STATE_TYPE_NAME, STATE_NAME);
8220 fprintf (output_file, "{\n %s (%s);\n}\n\n", INTERNAL_RESET_FUNC_NAME,
8221 STATE_NAME);
8224 /* Output function `min_insn_conflict_delay'. */
8225 static void
8226 output_min_insn_conflict_delay_func ()
8228 fprintf (output_file,
8229 "int\n%s (%s, %s, %s)\n\t%s %s;\n\trtx %s;\n\trtx %s;\n",
8230 MIN_INSN_CONFLICT_DELAY_FUNC_NAME,
8231 STATE_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME,
8232 STATE_TYPE_NAME, STATE_NAME,
8233 INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8234 fprintf (output_file, "{\n struct %s %s;\n int %s, %s;\n",
8235 CHIP_NAME, CHIP_NAME, INTERNAL_INSN_CODE_NAME,
8236 INTERNAL_INSN2_CODE_NAME);
8237 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8238 INTERNAL_INSN_CODE_NAME, 0);
8239 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
8240 INTERNAL_INSN2_CODE_NAME, 0);
8241 fprintf (output_file, " memcpy (&%s, %s, sizeof (%s));\n",
8242 CHIP_NAME, STATE_NAME, CHIP_NAME);
8243 fprintf (output_file, " %s (&%s);\n", INTERNAL_RESET_FUNC_NAME, CHIP_NAME);
8244 fprintf (output_file, " if (%s (%s, &%s) > 0)\n abort ();\n",
8245 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME);
8246 fprintf (output_file, " return %s (%s, &%s);\n",
8247 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN2_CODE_NAME,
8248 CHIP_NAME);
8249 fprintf (output_file, "}\n\n");
8252 /* Output function `internal_insn_latency'. */
8253 static void
8254 output_internal_insn_latency_func ()
8256 decl_t decl;
8257 struct bypass_decl *bypass;
8258 int i;
8260 fprintf (output_file, "static int %s PARAMS ((int, int, rtx, rtx));\n",
8261 INTERNAL_INSN_LATENCY_FUNC_NAME);
8262 fprintf (output_file, "static int\n%s (%s, %s, %s, %s)",
8263 INTERNAL_INSN_LATENCY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8264 INTERNAL_INSN2_CODE_NAME, INSN_PARAMETER_NAME,
8265 INSN2_PARAMETER_NAME);
8266 fprintf (output_file, "\n\tint %s;\n\tint %s;\n",
8267 INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME);
8268 fprintf (output_file,
8269 "\trtx %s ATTRIBUTE_UNUSED;\n\trtx %s ATTRIBUTE_UNUSED;\n",
8270 INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8271 fprintf (output_file, "{\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8272 for (i = 0; i < description->decls_num; i++)
8274 decl = description->decls [i];
8275 if (decl->mode == dm_insn_reserv)
8277 fprintf (output_file, " case %d:\n",
8278 decl->decl.insn_reserv.insn_num);
8279 if (decl->decl.insn_reserv.bypass_list == NULL)
8280 fprintf (output_file, " return (%s != %s ? %d : 0);\n",
8281 INTERNAL_INSN2_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8282 decl->decl.insn_reserv.default_latency);
8283 else
8285 fprintf (output_file, " switch (%s)\n {\n",
8286 INTERNAL_INSN2_CODE_NAME);
8287 for (bypass = decl->decl.insn_reserv.bypass_list;
8288 bypass != NULL;
8289 bypass = bypass->next)
8291 fprintf (output_file, " case %d:\n",
8292 bypass->in_insn_reserv->insn_num);
8293 if (bypass->bypass_guard_name == NULL)
8294 fprintf (output_file, " return %d;\n",
8295 bypass->latency);
8296 else
8297 fprintf (output_file,
8298 " return (%s (%s, %s) ? %d : %d);\n",
8299 bypass->bypass_guard_name, INSN_PARAMETER_NAME,
8300 INSN2_PARAMETER_NAME, bypass->latency,
8301 decl->decl.insn_reserv.default_latency);
8303 fprintf (output_file, " default:\n");
8304 fprintf (output_file,
8305 " return (%s != %s ? %d : 0);\n }\n",
8306 INTERNAL_INSN2_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8307 decl->decl.insn_reserv.default_latency);
8312 fprintf (output_file, " default:\n return 0;\n }\n}\n\n");
8315 /* The function outputs PHR interface function `insn_latency'. */
8316 static void
8317 output_insn_latency_func ()
8319 fprintf (output_file, "int\n%s (%s, %s)\n\trtx %s;\n\trtx %s;\n",
8320 INSN_LATENCY_FUNC_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME,
8321 INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8322 fprintf (output_file, "{\n int %s, %s;\n",
8323 INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME);
8324 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8325 INTERNAL_INSN_CODE_NAME, 0);
8326 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
8327 INTERNAL_INSN2_CODE_NAME, 0);
8328 fprintf (output_file, " return %s (%s, %s, %s, %s);\n}\n\n",
8329 INTERNAL_INSN_LATENCY_FUNC_NAME,
8330 INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME,
8331 INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8334 /* The function outputs PHR interface function `print_reservation'. */
8335 static void
8336 output_print_reservation_func ()
8338 decl_t decl;
8339 int i;
8341 fprintf (output_file, "void\n%s (%s, %s)\n\tFILE *%s;\n\trtx %s;\n",
8342 PRINT_RESERVATION_FUNC_NAME, FILE_PARAMETER_NAME,
8343 INSN_PARAMETER_NAME, FILE_PARAMETER_NAME,
8344 INSN_PARAMETER_NAME);
8345 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
8346 fprintf (output_file, "\n if (%s != 0)\n {\n", INSN_PARAMETER_NAME);
8347 fprintf (output_file, " %s = %s (%s);\n",
8348 INTERNAL_INSN_CODE_NAME, DFA_INSN_CODE_FUNC_NAME,
8349 INSN_PARAMETER_NAME);
8350 fprintf (output_file, " if (%s > %s)\n",
8351 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8352 fprintf (output_file, " {\n fprintf (%s, \"%s\");\n",
8353 FILE_PARAMETER_NAME, NOTHING_NAME);
8354 fprintf (output_file, " return;\n }\n");
8355 fprintf (output_file, " }\n else\n");
8356 fprintf (output_file,
8357 " {\n fprintf (%s, \"%s\");\n return;\n }\n",
8358 FILE_PARAMETER_NAME, NOTHING_NAME);
8359 fprintf (output_file, " switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8360 for (i = 0; i < description->decls_num; i++)
8362 decl = description->decls [i];
8363 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
8365 fprintf (output_file,
8366 " case %d:\n", decl->decl.insn_reserv.insn_num);
8367 fprintf (output_file,
8368 " fprintf (%s, \"%s\");\n break;\n",
8369 FILE_PARAMETER_NAME,
8370 regexp_representation (decl->decl.insn_reserv.regexp));
8371 finish_regexp_representation ();
8374 fprintf (output_file, " default:\n fprintf (%s, \"%s\");\n }\n",
8375 FILE_PARAMETER_NAME, NOTHING_NAME);
8376 fprintf (output_file, "}\n\n");
8379 /* The following function is used to sort unit declaration by their
8380 names. */
8381 static int
8382 units_cmp (unit1, unit2)
8383 const void *unit1, *unit2;
8385 const unit_decl_t u1 = *(unit_decl_t *) unit1;
8386 const unit_decl_t u2 = *(unit_decl_t *) unit2;
8388 return strcmp (u1->name, u2->name);
8391 /* The following macro value is name of struct containing unit name
8392 and unit code. */
8393 #define NAME_CODE_STRUCT_NAME "name_code"
8395 /* The following macro value is name of table of struct name_code. */
8396 #define NAME_CODE_TABLE_NAME "name_code_table"
8398 /* The following macro values are member names for struct name_code. */
8399 #define NAME_MEMBER_NAME "name"
8400 #define CODE_MEMBER_NAME "code"
8402 /* The following macro values are local variable names for function
8403 `get_cpu_unit_code'. */
8404 #define CMP_VARIABLE_NAME "cmp"
8405 #define LOW_VARIABLE_NAME "l"
8406 #define MIDDLE_VARIABLE_NAME "m"
8407 #define HIGH_VARIABLE_NAME "h"
8409 /* The following function outputs function to obtain internal cpu unit
8410 code by the cpu unit name. */
8411 static void
8412 output_get_cpu_unit_code_func ()
8414 int i;
8415 unit_decl_t *units;
8417 fprintf (output_file, "int\n%s (%s)\n\tconst char *%s;\n",
8418 GET_CPU_UNIT_CODE_FUNC_NAME, CPU_UNIT_NAME_PARAMETER_NAME,
8419 CPU_UNIT_NAME_PARAMETER_NAME);
8420 fprintf (output_file, "{\n struct %s {const char *%s; int %s;};\n",
8421 NAME_CODE_STRUCT_NAME, NAME_MEMBER_NAME, CODE_MEMBER_NAME);
8422 fprintf (output_file, " int %s, %s, %s, %s;\n", CMP_VARIABLE_NAME,
8423 LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8424 fprintf (output_file, " static struct %s %s [] =\n {\n",
8425 NAME_CODE_STRUCT_NAME, NAME_CODE_TABLE_NAME);
8426 units = (unit_decl_t *) xmalloc (sizeof (unit_decl_t)
8427 * description->units_num);
8428 memcpy (units, units_array, sizeof (unit_decl_t) * description->units_num);
8429 qsort (units, description->units_num, sizeof (unit_decl_t), units_cmp);
8430 for (i = 0; i < description->units_num; i++)
8431 if (units [i]->query_p)
8432 fprintf (output_file, " {\"%s\", %d},\n",
8433 units[i]->name, units[i]->query_num);
8434 fprintf (output_file, " };\n\n");
8435 fprintf (output_file, " /* The following is binary search: */\n");
8436 fprintf (output_file, " %s = 0;\n", LOW_VARIABLE_NAME);
8437 fprintf (output_file, " %s = sizeof (%s) / sizeof (struct %s) - 1;\n",
8438 HIGH_VARIABLE_NAME, NAME_CODE_TABLE_NAME, NAME_CODE_STRUCT_NAME);
8439 fprintf (output_file, " while (%s <= %s)\n {\n",
8440 LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8441 fprintf (output_file, " %s = (%s + %s) / 2;\n",
8442 MIDDLE_VARIABLE_NAME, LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8443 fprintf (output_file, " %s = strcmp (%s, %s [%s].%s);\n",
8444 CMP_VARIABLE_NAME, CPU_UNIT_NAME_PARAMETER_NAME,
8445 NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, NAME_MEMBER_NAME);
8446 fprintf (output_file, " if (%s < 0)\n", CMP_VARIABLE_NAME);
8447 fprintf (output_file, " %s = %s - 1;\n",
8448 HIGH_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
8449 fprintf (output_file, " else if (%s > 0)\n", CMP_VARIABLE_NAME);
8450 fprintf (output_file, " %s = %s + 1;\n",
8451 LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
8452 fprintf (output_file, " else\n");
8453 fprintf (output_file, " return %s [%s].%s;\n }\n",
8454 NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, CODE_MEMBER_NAME);
8455 fprintf (output_file, " return -1;\n}\n\n");
8456 free (units);
8459 /* The following function outputs function to check reservation of cpu
8460 unit (its internal code will be passed as the function argument) in
8461 given cpu state. */
8462 static void
8463 output_cpu_unit_reservation_p ()
8465 automaton_t automaton;
8467 fprintf (output_file, "int\n%s (%s, %s)\n\t%s %s;\n\tint %s;\n",
8468 CPU_UNIT_RESERVATION_P_FUNC_NAME, STATE_NAME,
8469 CPU_CODE_PARAMETER_NAME, STATE_TYPE_NAME, STATE_NAME,
8470 CPU_CODE_PARAMETER_NAME);
8471 fprintf (output_file, "{\n if (%s < 0 || %s >= %d)\n abort ();\n",
8472 CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME,
8473 description->query_units_num);
8474 for (automaton = description->first_automaton;
8475 automaton != NULL;
8476 automaton = automaton->next_automaton)
8478 fprintf (output_file, " if ((");
8479 output_reserved_units_table_name (output_file, automaton);
8480 fprintf (output_file, " [((struct %s *) %s)->", CHIP_NAME, STATE_NAME);
8481 output_chip_member_name (output_file, automaton);
8482 fprintf (output_file, " * %d + %s / 8] >> (%s %% 8)) & 1)\n",
8483 (description->query_units_num + 7) / 8,
8484 CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME);
8485 fprintf (output_file, " return 1;\n");
8487 fprintf (output_file, " return 0;\n}\n\n");
8490 /* The function outputs PHR interface function `dfa_start'. */
8491 static void
8492 output_dfa_start_func ()
8494 fprintf (output_file,
8495 "void\n%s ()\n{\n int %s;\n\n %s = get_max_uid ();\n",
8496 DFA_START_FUNC_NAME, I_VARIABLE_NAME,
8497 DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8498 fprintf (output_file, " %s = (int *) xmalloc (%s * sizeof (int));\n",
8499 DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8500 fprintf (output_file,
8501 " for (%s = 0; %s < %s; %s++)\n %s [%s] = -1;\n}\n\n",
8502 I_VARIABLE_NAME, I_VARIABLE_NAME,
8503 DFA_INSN_CODES_LENGTH_VARIABLE_NAME, I_VARIABLE_NAME,
8504 DFA_INSN_CODES_VARIABLE_NAME, I_VARIABLE_NAME);
8507 /* The function outputs PHR interface function `dfa_finish'. */
8508 static void
8509 output_dfa_finish_func ()
8511 fprintf (output_file, "void\n%s ()\n{\n free (%s);\n}\n\n",
8512 DFA_FINISH_FUNC_NAME, DFA_INSN_CODES_VARIABLE_NAME);
8517 /* The page contains code for output description file (readable
8518 representation of original description and generated DFA(s). */
8520 /* The function outputs string representation of IR reservation. */
8521 static void
8522 output_regexp (regexp)
8523 regexp_t regexp;
8525 fprintf (output_description_file, "%s", regexp_representation (regexp));
8526 finish_regexp_representation ();
8529 /* Output names of units in LIST separated by comma. */
8530 static void
8531 output_unit_set_el_list (list)
8532 unit_set_el_t list;
8534 unit_set_el_t el;
8536 for (el = list; el != NULL; el = el->next_unit_set_el)
8538 if (el != list)
8539 fprintf (output_description_file, ",");
8540 fprintf (output_description_file, "%s", el->unit_decl->name);
8544 /* The function outputs string representation of IR define_reservation
8545 and define_insn_reservation. */
8546 static void
8547 output_description ()
8549 decl_t decl;
8550 int i;
8552 for (i = 0; i < description->decls_num; i++)
8554 decl = description->decls [i];
8555 if (decl->mode == dm_unit)
8557 if (decl->decl.unit.excl_list != NULL)
8559 fprintf (output_description_file, "unit %s exlusion_set: ",
8560 decl->decl.unit.name);
8561 output_unit_set_el_list (decl->decl.unit.excl_list);
8562 fprintf (output_description_file, "\n");
8564 if (decl->decl.unit.presence_list != NULL)
8566 fprintf (output_description_file, "unit %s presence_set: ",
8567 decl->decl.unit.name);
8568 output_unit_set_el_list (decl->decl.unit.presence_list);
8569 fprintf (output_description_file, "\n");
8571 if (decl->decl.unit.absence_list != NULL)
8573 fprintf (output_description_file, "unit %s absence_set: ",
8574 decl->decl.unit.name);
8575 output_unit_set_el_list (decl->decl.unit.absence_list);
8576 fprintf (output_description_file, "\n");
8580 fprintf (output_description_file, "\n");
8581 for (i = 0; i < description->decls_num; i++)
8583 decl = description->decls [i];
8584 if (decl->mode == dm_reserv)
8586 fprintf (output_description_file, "reservation ");
8587 fprintf (output_description_file, decl->decl.reserv.name);
8588 fprintf (output_description_file, ": ");
8589 output_regexp (decl->decl.reserv.regexp);
8590 fprintf (output_description_file, "\n");
8592 else if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
8594 fprintf (output_description_file, "insn reservation %s ",
8595 decl->decl.insn_reserv.name);
8596 print_rtl (output_description_file, decl->decl.insn_reserv.condexp);
8597 fprintf (output_description_file, ": ");
8598 output_regexp (decl->decl.insn_reserv.regexp);
8599 fprintf (output_description_file, "\n");
8601 else if (decl->mode == dm_bypass)
8602 fprintf (output_description_file, "bypass %d %s %s\n",
8603 decl->decl.bypass.latency, decl->decl.bypass.out_insn_name,
8604 decl->decl.bypass.in_insn_name);
8606 fprintf (output_description_file, "\n\f\n");
8609 /* The function outputs name of AUTOMATON. */
8610 static void
8611 output_automaton_name (f, automaton)
8612 FILE *f;
8613 automaton_t automaton;
8615 if (automaton->corresponding_automaton_decl == NULL)
8616 fprintf (f, "#%d", automaton->automaton_order_num);
8617 else
8618 fprintf (f, "`%s'", automaton->corresponding_automaton_decl->name);
8621 /* Maximal length of line for pretty printing into description
8622 file. */
8623 #define MAX_LINE_LENGTH 70
8625 /* The function outputs units name belonging to AUTOMATON. */
8626 static void
8627 output_automaton_units (automaton)
8628 automaton_t automaton;
8630 decl_t decl;
8631 char *name;
8632 int curr_line_length;
8633 int there_is_an_automaton_unit;
8634 int i;
8636 fprintf (output_description_file, "\n Coresponding units:\n");
8637 fprintf (output_description_file, " ");
8638 curr_line_length = 4;
8639 there_is_an_automaton_unit = 0;
8640 for (i = 0; i < description->decls_num; i++)
8642 decl = description->decls [i];
8643 if (decl->mode == dm_unit
8644 && (decl->decl.unit.corresponding_automaton_num
8645 == automaton->automaton_order_num))
8647 there_is_an_automaton_unit = 1;
8648 name = decl->decl.unit.name;
8649 if (curr_line_length + strlen (name) + 1 > MAX_LINE_LENGTH )
8651 curr_line_length = strlen (name) + 4;
8652 fprintf (output_description_file, "\n ");
8654 else
8656 curr_line_length += strlen (name) + 1;
8657 fprintf (output_description_file, " ");
8659 fprintf (output_description_file, name);
8662 if (!there_is_an_automaton_unit)
8663 fprintf (output_description_file, "<None>");
8664 fprintf (output_description_file, "\n\n");
8667 /* The following variable is used for forming array of all possible cpu unit
8668 reservations described by the current DFA state. */
8669 static vla_ptr_t state_reservs;
8671 /* The function forms `state_reservs' for STATE. */
8672 static void
8673 add_state_reservs (state)
8674 state_t state;
8676 alt_state_t curr_alt_state;
8677 reserv_sets_t reservs;
8679 if (state->component_states != NULL)
8680 for (curr_alt_state = state->component_states;
8681 curr_alt_state != NULL;
8682 curr_alt_state = curr_alt_state->next_sorted_alt_state)
8683 add_state_reservs (curr_alt_state->state);
8684 else
8686 reservs = state->reservs;
8687 VLA_PTR_ADD (state_reservs, reservs);
8691 /* The function outputs readable represenatation of all out arcs of
8692 STATE. */
8693 static void
8694 output_state_arcs (state)
8695 state_t state;
8697 arc_t arc;
8698 ainsn_t ainsn;
8699 char *insn_name;
8700 int curr_line_length;
8702 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
8704 ainsn = arc->insn;
8705 if (!ainsn->first_insn_with_same_reservs)
8706 abort ();
8707 fprintf (output_description_file, " ");
8708 curr_line_length = 7;
8709 fprintf (output_description_file, "%2d: ", ainsn->insn_equiv_class_num);
8712 insn_name = ainsn->insn_reserv_decl->name;
8713 if (curr_line_length + strlen (insn_name) > MAX_LINE_LENGTH)
8715 if (ainsn != arc->insn)
8717 fprintf (output_description_file, ",\n ");
8718 curr_line_length = strlen (insn_name) + 6;
8720 else
8721 curr_line_length += strlen (insn_name);
8723 else
8725 curr_line_length += strlen (insn_name);
8726 if (ainsn != arc->insn)
8728 curr_line_length += 2;
8729 fprintf (output_description_file, ", ");
8732 fprintf (output_description_file, insn_name);
8733 ainsn = ainsn->next_same_reservs_insn;
8735 while (ainsn != NULL);
8736 fprintf (output_description_file, " %d (%d)\n",
8737 arc->to_state->order_state_num, arc->state_alts);
8739 fprintf (output_description_file, "\n");
8742 /* The following function is used for sorting possible cpu unit
8743 reservation of a DFA state. */
8744 static int
8745 state_reservs_cmp (reservs_ptr_1, reservs_ptr_2)
8746 const void *reservs_ptr_1;
8747 const void *reservs_ptr_2;
8749 return reserv_sets_cmp (*(reserv_sets_t *) reservs_ptr_1,
8750 *(reserv_sets_t *) reservs_ptr_2);
8753 /* The following function is used for sorting possible cpu unit
8754 reservation of a DFA state. */
8755 static void
8756 remove_state_duplicate_reservs ()
8758 reserv_sets_t *reservs_ptr;
8759 reserv_sets_t *last_formed_reservs_ptr;
8761 last_formed_reservs_ptr = NULL;
8762 for (reservs_ptr = VLA_PTR_BEGIN (state_reservs);
8763 reservs_ptr <= (reserv_sets_t *) VLA_PTR_LAST (state_reservs);
8764 reservs_ptr++)
8765 if (last_formed_reservs_ptr == NULL)
8766 last_formed_reservs_ptr = reservs_ptr;
8767 else if (reserv_sets_cmp (*last_formed_reservs_ptr, *reservs_ptr) != 0)
8769 ++last_formed_reservs_ptr;
8770 *last_formed_reservs_ptr = *reservs_ptr;
8772 VLA_PTR_SHORTEN (state_reservs, reservs_ptr - last_formed_reservs_ptr - 1);
8775 /* The following function output readable representation of DFA(s)
8776 state used for fast recognition of pipeline hazards. State is
8777 described by possible (current and scehduled) cpu unit
8778 reservations. */
8779 static void
8780 output_state (state)
8781 state_t state;
8783 reserv_sets_t *reservs_ptr;
8785 VLA_PTR_CREATE (state_reservs, 150, "state reservations");
8786 fprintf (output_description_file, " State #%d", state->order_state_num);
8787 fprintf (output_description_file,
8788 state->new_cycle_p ? " (new cycle)\n" : "\n");
8789 add_state_reservs (state);
8790 qsort (VLA_PTR_BEGIN (state_reservs), VLA_PTR_LENGTH (state_reservs),
8791 sizeof (reserv_sets_t), state_reservs_cmp);
8792 remove_state_duplicate_reservs ();
8793 for (reservs_ptr = VLA_PTR_BEGIN (state_reservs);
8794 reservs_ptr <= (reserv_sets_t *) VLA_PTR_LAST (state_reservs);
8795 reservs_ptr++)
8797 fprintf (output_description_file, " ");
8798 output_reserv_sets (output_description_file, *reservs_ptr);
8799 fprintf (output_description_file, "\n");
8801 fprintf (output_description_file, "\n");
8802 output_state_arcs (state);
8803 VLA_PTR_DELETE (state_reservs);
8806 /* The following function output readable representation of
8807 DFAs used for fast recognition of pipeline hazards. */
8808 static void
8809 output_automaton_descriptions ()
8811 automaton_t automaton;
8813 for (automaton = description->first_automaton;
8814 automaton != NULL;
8815 automaton = automaton->next_automaton)
8817 fprintf (output_description_file, "\nAutomaton ");
8818 output_automaton_name (output_description_file, automaton);
8819 fprintf (output_description_file, "\n");
8820 output_automaton_units (automaton);
8821 pass_states (automaton, output_state);
8827 /* The page contains top level function for generation DFA(s) used for
8828 PHR. */
8830 /* The function outputs statistics about work of different phases of
8831 DFA generator. */
8832 static void
8833 output_statistics (f)
8834 FILE *f;
8836 automaton_t automaton;
8837 #ifndef NDEBUG
8838 int transition_comb_vect_els = 0;
8839 int transition_full_vect_els = 0;
8840 int state_alts_comb_vect_els = 0;
8841 int state_alts_full_vect_els = 0;
8842 int min_issue_delay_vect_els = 0;
8843 #endif
8845 for (automaton = description->first_automaton;
8846 automaton != NULL;
8847 automaton = automaton->next_automaton)
8849 fprintf (f, "\nAutomaton ");
8850 output_automaton_name (f, automaton);
8851 fprintf (f, "\n %5d NDFA states, %5d NDFA arcs\n",
8852 automaton->NDFA_states_num, automaton->NDFA_arcs_num);
8853 fprintf (f, " %5d DFA states, %5d DFA arcs\n",
8854 automaton->DFA_states_num, automaton->DFA_arcs_num);
8855 if (!no_minimization_flag)
8856 fprintf (f, " %5d minimal DFA states, %5d minimal DFA arcs\n",
8857 automaton->minimal_DFA_states_num,
8858 automaton->minimal_DFA_arcs_num);
8859 fprintf (f, " %5d all insns %5d insn equivalence classes\n",
8860 description->insns_num, automaton->insn_equiv_classes_num);
8861 #ifndef NDEBUG
8862 fprintf
8863 (f, "%5ld transition comb vector els, %5ld trans table els: %s\n",
8864 (long) VLA_HWINT_LENGTH (automaton->trans_table->comb_vect),
8865 (long) VLA_HWINT_LENGTH (automaton->trans_table->full_vect),
8866 (comb_vect_p (automaton->trans_table)
8867 ? "use comb vect" : "use simple vect"));
8868 fprintf
8869 (f, "%5ld state alts comb vector els, %5ld state alts table els: %s\n",
8870 (long) VLA_HWINT_LENGTH (automaton->state_alts_table->comb_vect),
8871 (long) VLA_HWINT_LENGTH (automaton->state_alts_table->full_vect),
8872 (comb_vect_p (automaton->state_alts_table)
8873 ? "use comb vect" : "use simple vect"));
8874 fprintf
8875 (f, "%5ld min delay table els, compression factor %d\n",
8876 (long) automaton->DFA_states_num * automaton->insn_equiv_classes_num,
8877 automaton->min_issue_delay_table_compression_factor);
8878 transition_comb_vect_els
8879 += VLA_HWINT_LENGTH (automaton->trans_table->comb_vect);
8880 transition_full_vect_els
8881 += VLA_HWINT_LENGTH (automaton->trans_table->full_vect);
8882 state_alts_comb_vect_els
8883 += VLA_HWINT_LENGTH (automaton->state_alts_table->comb_vect);
8884 state_alts_full_vect_els
8885 += VLA_HWINT_LENGTH (automaton->state_alts_table->full_vect);
8886 min_issue_delay_vect_els
8887 += automaton->DFA_states_num * automaton->insn_equiv_classes_num;
8888 #endif
8890 #ifndef NDEBUG
8891 fprintf (f, "\n%5d all allocated states, %5d all allocated arcs\n",
8892 allocated_states_num, allocated_arcs_num);
8893 fprintf (f, "%5d all allocated alternative states\n",
8894 allocated_alt_states_num);
8895 fprintf (f, "%5d all transition comb vector els, %5d all trans table els\n",
8896 transition_comb_vect_els, transition_full_vect_els);
8897 fprintf
8898 (f, "%5d all state alts comb vector els, %5d all state alts table els\n",
8899 state_alts_comb_vect_els, state_alts_full_vect_els);
8900 fprintf (f, "%5d all min delay table els\n", min_issue_delay_vect_els);
8901 fprintf (f, "%5d locked states num\n", locked_states_num);
8902 #endif
8905 /* The function output times of work of different phases of DFA
8906 generator. */
8907 static void
8908 output_time_statistics (f)
8909 FILE *f;
8911 fprintf (f, "\n transformation: ");
8912 print_active_time (f, transform_time);
8913 fprintf (f, (!ndfa_flag ? ", building DFA: " : ", building NDFA: "));
8914 print_active_time (f, NDFA_time);
8915 if (ndfa_flag)
8917 fprintf (f, ", NDFA -> DFA: ");
8918 print_active_time (f, NDFA_to_DFA_time);
8920 fprintf (f, "\n DFA minimization: ");
8921 print_active_time (f, minimize_time);
8922 fprintf (f, ", making insn equivalence: ");
8923 print_active_time (f, equiv_time);
8924 fprintf (f, "\n all automaton generation: ");
8925 print_active_time (f, automaton_generation_time);
8926 fprintf (f, ", output: ");
8927 print_active_time (f, output_time);
8928 fprintf (f, "\n");
8931 /* The function generates DFA (deterministic finate state automaton)
8932 for fast recognition of pipeline hazards. No errors during
8933 checking must be fixed before this function call. */
8934 static void
8935 generate ()
8937 automata_num = split_argument;
8938 if (description->units_num < automata_num)
8939 automata_num = description->units_num;
8940 initiate_states ();
8941 initiate_arcs ();
8942 initiate_automata_lists ();
8943 initiate_pass_states ();
8944 initiate_excl_sets ();
8945 initiate_presence_absence_sets ();
8946 automaton_generation_time = create_ticker ();
8947 create_automata ();
8948 ticker_off (&automaton_generation_time);
8953 /* The following function creates attribute which order number of insn
8954 in pipeline hazard description translator. */
8955 static void
8956 make_insn_alts_attr ()
8958 int i, insn_num;
8959 decl_t decl;
8960 rtx condexp;
8962 condexp = rtx_alloc (COND);
8963 XVEC (condexp, 0) = rtvec_alloc ((description->insns_num - 1) * 2);
8964 XEXP (condexp, 1) = make_numeric_value (0);
8965 for (i = insn_num = 0; i < description->decls_num; i++)
8967 decl = description->decls [i];
8968 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
8970 XVECEXP (condexp, 0, 2 * insn_num) = decl->decl.insn_reserv.condexp;
8971 XVECEXP (condexp, 0, 2 * insn_num + 1)
8972 = make_numeric_value (decl->decl.insn_reserv.transformed_regexp
8973 ->regexp.oneof.regexps_num);
8974 insn_num++;
8977 if (description->insns_num != insn_num + 1)
8978 abort ();
8979 make_internal_attr (attr_printf (sizeof ("*")
8980 + strlen (INSN_ALTS_FUNC_NAME) + 1,
8981 "*%s", INSN_ALTS_FUNC_NAME),
8982 condexp, 0);
8987 /* The following function creates attribute which is order number of
8988 insn in pipeline hazard description translator. */
8989 static void
8990 make_internal_dfa_insn_code_attr ()
8992 int i, insn_num;
8993 decl_t decl;
8994 rtx condexp;
8996 condexp = rtx_alloc (COND);
8997 XVEC (condexp, 0) = rtvec_alloc ((description->insns_num - 1) * 2);
8998 XEXP (condexp, 1) = make_numeric_value (advance_cycle_insn_decl
8999 ->decl.insn_reserv.insn_num + 1);
9000 for (i = insn_num = 0; i < description->decls_num; i++)
9002 decl = description->decls [i];
9003 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
9005 XVECEXP (condexp, 0, 2 * insn_num) = decl->decl.insn_reserv.condexp;
9006 XVECEXP (condexp, 0, 2 * insn_num + 1)
9007 = make_numeric_value (decl->decl.insn_reserv.insn_num);
9008 insn_num++;
9011 if (description->insns_num != insn_num + 1)
9012 abort ();
9013 make_internal_attr
9014 (attr_printf (sizeof ("*")
9015 + strlen (INTERNAL_DFA_INSN_CODE_FUNC_NAME) + 1,
9016 "*%s", INTERNAL_DFA_INSN_CODE_FUNC_NAME),
9017 condexp, 0);
9022 /* The following function creates attribute which order number of insn
9023 in pipeline hazard description translator. */
9024 static void
9025 make_default_insn_latency_attr ()
9027 int i, insn_num;
9028 decl_t decl;
9029 rtx condexp;
9031 condexp = rtx_alloc (COND);
9032 XVEC (condexp, 0) = rtvec_alloc ((description->insns_num - 1) * 2);
9033 XEXP (condexp, 1) = make_numeric_value (0);
9034 for (i = insn_num = 0; i < description->decls_num; i++)
9036 decl = description->decls [i];
9037 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
9039 XVECEXP (condexp, 0, 2 * insn_num) = decl->decl.insn_reserv.condexp;
9040 XVECEXP (condexp, 0, 2 * insn_num + 1)
9041 = make_numeric_value (decl->decl.insn_reserv.default_latency);
9042 insn_num++;
9045 if (description->insns_num != insn_num + 1)
9046 abort ();
9047 make_internal_attr (attr_printf (sizeof ("*")
9048 + strlen (INSN_DEFAULT_LATENCY_FUNC_NAME)
9049 + 1, "*%s", INSN_DEFAULT_LATENCY_FUNC_NAME),
9050 condexp, 0);
9055 /* The following function creates attribute which returns 1 if given
9056 output insn has bypassing and 0 otherwise. */
9057 static void
9058 make_bypass_attr ()
9060 int i, bypass_insn;
9061 int bypass_insns_num = 0;
9062 decl_t decl;
9063 rtx result_rtx;
9065 for (i = 0; i < description->decls_num; i++)
9067 decl = description->decls [i];
9068 if (decl->mode == dm_insn_reserv
9069 && decl->decl.insn_reserv.condexp != NULL
9070 && decl->decl.insn_reserv.bypass_list != NULL)
9071 bypass_insns_num++;
9073 if (bypass_insns_num == 0)
9074 result_rtx = make_numeric_value (0);
9075 else
9077 result_rtx = rtx_alloc (COND);
9078 XVEC (result_rtx, 0) = rtvec_alloc (bypass_insns_num * 2);
9079 XEXP (result_rtx, 1) = make_numeric_value (0);
9081 for (i = bypass_insn = 0; i < description->decls_num; i++)
9083 decl = description->decls [i];
9084 if (decl->mode == dm_insn_reserv
9085 && decl->decl.insn_reserv.condexp != NULL
9086 && decl->decl.insn_reserv.bypass_list != NULL)
9088 XVECEXP (result_rtx, 0, 2 * bypass_insn)
9089 = decl->decl.insn_reserv.condexp;
9090 XVECEXP (result_rtx, 0, 2 * bypass_insn + 1)
9091 = make_numeric_value (1);
9092 bypass_insn++;
9096 make_internal_attr (attr_printf (sizeof ("*")
9097 + strlen (BYPASS_P_FUNC_NAME) + 1,
9098 "*%s", BYPASS_P_FUNC_NAME),
9099 result_rtx, 0);
9104 /* This page mainly contains top level functions of pipeline hazards
9105 description translator. */
9107 /* The following macro value is suffix of name of description file of
9108 pipeline hazards description translator. */
9109 #define STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX ".dfa"
9111 /* The function returns suffix of given file name. The returned
9112 string can not be changed. */
9113 static const char *
9114 file_name_suffix (file_name)
9115 const char *file_name;
9117 const char *last_period;
9119 for (last_period = NULL; *file_name != '\0'; file_name++)
9120 if (*file_name == '.')
9121 last_period = file_name;
9122 return (last_period == NULL ? file_name : last_period);
9125 /* The function returns base name of given file name, i.e. pointer to
9126 first char after last `/' (or `\' for WIN32) in given file name,
9127 given file name itself if the directory name is absent. The
9128 returned string can not be changed. */
9129 static const char *
9130 base_file_name (file_name)
9131 const char *file_name;
9133 int directory_name_length;
9135 directory_name_length = strlen (file_name);
9136 #ifdef WIN32
9137 while (directory_name_length >= 0 && file_name[directory_name_length] != '/'
9138 && file_name[directory_name_length] != '\\')
9139 #else
9140 while (directory_name_length >= 0 && file_name[directory_name_length] != '/')
9141 #endif
9142 directory_name_length--;
9143 return file_name + directory_name_length + 1;
9146 /* The following is top level function to initialize the work of
9147 pipeline hazards description translator. */
9148 void
9149 initiate_automaton_gen (argc, argv)
9150 int argc;
9151 char **argv;
9153 const char *base_name;
9154 int i;
9156 ndfa_flag = 0;
9157 split_argument = 0; /* default value */
9158 no_minimization_flag = 0;
9159 time_flag = 0;
9160 v_flag = 0;
9161 w_flag = 0;
9162 for (i = 2; i < argc; i++)
9163 if (strcmp (argv [i], NO_MINIMIZATION_OPTION) == 0)
9164 no_minimization_flag = 1;
9165 else if (strcmp (argv [i], "-time") == 0)
9166 time_flag = 1;
9167 else if (strcmp (argv [i], "-v") == 0)
9168 v_flag = 1;
9169 else if (strcmp (argv [i], W_OPTION) == 0)
9170 w_flag = 1;
9171 else if (strcmp (argv [i], NDFA_OPTION) == 0)
9172 ndfa_flag = 1;
9173 else if (strcmp (argv [i], "-split") == 0)
9175 if (i + 1 >= argc)
9176 fatal ("-split has no argument.");
9177 fatal ("option `-split' has not been implemented yet\n");
9178 /* split_argument = atoi (argument_vect [i + 1]); */
9180 VLA_PTR_CREATE (decls, 150, "decls");
9181 /* Initialize IR storage. */
9182 obstack_init (&irp);
9183 initiate_automaton_decl_table ();
9184 initiate_insn_decl_table ();
9185 initiate_decl_table ();
9186 output_file = stdout;
9187 output_description_file = NULL;
9188 base_name = base_file_name (argv[1]);
9189 obstack_grow (&irp, base_name,
9190 strlen (base_name) - strlen (file_name_suffix (base_name)));
9191 obstack_grow (&irp, STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX,
9192 strlen (STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX) + 1);
9193 obstack_1grow (&irp, '\0');
9194 output_description_file_name = obstack_base (&irp);
9195 obstack_finish (&irp);
9198 /* The following function checks existence at least one arc marked by
9199 each insn. */
9200 static void
9201 check_automata_insn_issues ()
9203 automaton_t automaton;
9204 ainsn_t ainsn, reserv_ainsn;
9206 for (automaton = description->first_automaton;
9207 automaton != NULL;
9208 automaton = automaton->next_automaton)
9210 for (ainsn = automaton->ainsn_list;
9211 ainsn != NULL;
9212 ainsn = ainsn->next_ainsn)
9213 if (ainsn->first_insn_with_same_reservs && !ainsn->arc_exists_p)
9215 for (reserv_ainsn = ainsn;
9216 reserv_ainsn != NULL;
9217 reserv_ainsn = reserv_ainsn->next_same_reservs_insn)
9218 if (automaton->corresponding_automaton_decl != NULL)
9220 if (!w_flag)
9221 error ("Automaton `%s': Insn `%s' will never be issued",
9222 automaton->corresponding_automaton_decl->name,
9223 reserv_ainsn->insn_reserv_decl->name);
9224 else
9225 warning
9226 ("Automaton `%s': Insn `%s' will never be issued",
9227 automaton->corresponding_automaton_decl->name,
9228 reserv_ainsn->insn_reserv_decl->name);
9230 else
9232 if (!w_flag)
9233 error ("Insn `%s' will never be issued",
9234 reserv_ainsn->insn_reserv_decl->name);
9235 else
9236 warning ("Insn `%s' will never be issued",
9237 reserv_ainsn->insn_reserv_decl->name);
9243 /* The following vla is used for storing pointers to all achieved
9244 states. */
9245 static vla_ptr_t automaton_states;
9247 /* This function is called by function pass_states to add an achieved
9248 STATE. */
9249 static void
9250 add_automaton_state (state)
9251 state_t state;
9253 VLA_PTR_ADD (automaton_states, state);
9256 /* The following function forms list of important automata (whose
9257 states may be changed after the insn issue) for each insn. */
9258 static void
9259 form_important_insn_automata_lists ()
9261 automaton_t automaton;
9262 state_t *state_ptr;
9263 decl_t decl;
9264 ainsn_t ainsn;
9265 arc_t arc;
9266 int i;
9268 VLA_PTR_CREATE (automaton_states, 1500,
9269 "automaton states for forming important insn automata sets");
9270 /* Mark important ainsns. */
9271 for (automaton = description->first_automaton;
9272 automaton != NULL;
9273 automaton = automaton->next_automaton)
9275 VLA_PTR_NULLIFY (automaton_states);
9276 pass_states (automaton, add_automaton_state);
9277 for (state_ptr = VLA_PTR_BEGIN (automaton_states);
9278 state_ptr <= (state_t *) VLA_PTR_LAST (automaton_states);
9279 state_ptr++)
9281 for (arc = first_out_arc (*state_ptr);
9282 arc != NULL;
9283 arc = next_out_arc (arc))
9284 if (arc->to_state != *state_ptr)
9286 if (!arc->insn->first_insn_with_same_reservs)
9287 abort ();
9288 for (ainsn = arc->insn;
9289 ainsn != NULL;
9290 ainsn = ainsn->next_same_reservs_insn)
9291 ainsn->important_p = TRUE;
9295 VLA_PTR_DELETE (automaton_states);
9296 /* Create automata sets for the insns. */
9297 for (i = 0; i < description->decls_num; i++)
9299 decl = description->decls [i];
9300 if (decl->mode == dm_insn_reserv)
9302 automata_list_start ();
9303 for (automaton = description->first_automaton;
9304 automaton != NULL;
9305 automaton = automaton->next_automaton)
9306 for (ainsn = automaton->ainsn_list;
9307 ainsn != NULL;
9308 ainsn = ainsn->next_ainsn)
9309 if (ainsn->important_p
9310 && ainsn->insn_reserv_decl == &decl->decl.insn_reserv)
9312 automata_list_add (automaton);
9313 break;
9315 decl->decl.insn_reserv.important_automata_list
9316 = automata_list_finish ();
9322 /* The following is top level function to generate automat(a,on) for
9323 fast recognition of pipeline hazards. */
9324 void
9325 expand_automata ()
9327 int i;
9329 description = create_node (sizeof (struct description)
9330 /* One entry for cycle advancing insn. */
9331 + sizeof (decl_t) * VLA_PTR_LENGTH (decls));
9332 description->decls_num = VLA_PTR_LENGTH (decls);
9333 description->query_units_num = 0;
9334 for (i = 0; i < description->decls_num; i++)
9336 description->decls [i] = VLA_PTR (decls, i);
9337 if (description->decls [i]->mode == dm_unit
9338 && description->decls [i]->decl.unit.query_p)
9339 description->decls [i]->decl.unit.query_num
9340 = description->query_units_num++;
9342 all_time = create_ticker ();
9343 check_time = create_ticker ();
9344 fprintf (stderr, "Check description...");
9345 fflush (stderr);
9346 check_all_description ();
9347 fprintf (stderr, "done\n");
9348 ticker_off (&check_time);
9349 generation_time = create_ticker ();
9350 if (!have_error)
9352 transform_insn_regexps ();
9353 check_unit_distributions_to_automata ();
9355 if (!have_error)
9357 generate ();
9358 check_automata_insn_issues ();
9360 if (!have_error)
9362 form_important_insn_automata_lists ();
9363 fprintf (stderr, "Generation of attributes...");
9364 fflush (stderr);
9365 make_internal_dfa_insn_code_attr ();
9366 make_insn_alts_attr ();
9367 make_default_insn_latency_attr ();
9368 make_bypass_attr ();
9369 fprintf (stderr, "done\n");
9371 ticker_off (&generation_time);
9372 ticker_off (&all_time);
9373 fprintf (stderr, "All other genattrtab stuff...");
9374 fflush (stderr);
9377 /* The following is top level function to output PHR and to finish
9378 work with pipeline description translator. */
9379 void
9380 write_automata ()
9382 fprintf (stderr, "done\n");
9383 if (have_error)
9384 fatal ("Errors in DFA description");
9385 ticker_on (&all_time);
9386 output_time = create_ticker ();
9387 fprintf (stderr, "Forming and outputing automata tables...");
9388 fflush (stderr);
9389 output_dfa_max_issue_rate ();
9390 output_tables ();
9391 fprintf (stderr, "done\n");
9392 fprintf (stderr, "Output functions to work with automata...");
9393 fflush (stderr);
9394 output_chip_definitions ();
9395 output_max_insn_queue_index_def ();
9396 output_internal_min_issue_delay_func ();
9397 output_internal_trans_func ();
9398 /* Cache of insn dfa codes: */
9399 fprintf (output_file, "\nstatic int *%s;\n", DFA_INSN_CODES_VARIABLE_NAME);
9400 fprintf (output_file, "\nstatic int %s;\n\n",
9401 DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
9402 output_dfa_insn_code_func ();
9403 output_trans_func ();
9404 fprintf (output_file, "\n#if %s\n\n", AUTOMATON_STATE_ALTS_MACRO_NAME);
9405 output_internal_state_alts_func ();
9406 output_state_alts_func ();
9407 fprintf (output_file, "\n#endif /* #if %s */\n\n",
9408 AUTOMATON_STATE_ALTS_MACRO_NAME);
9409 output_min_issue_delay_func ();
9410 output_internal_dead_lock_func ();
9411 output_dead_lock_func ();
9412 output_size_func ();
9413 output_internal_reset_func ();
9414 output_reset_func ();
9415 output_min_insn_conflict_delay_func ();
9416 output_internal_insn_latency_func ();
9417 output_insn_latency_func ();
9418 output_print_reservation_func ();
9419 if (no_minimization_flag)
9421 fprintf (output_file, "\n#if %s\n\n", CPU_UNITS_QUERY_MACRO_NAME);
9422 output_get_cpu_unit_code_func ();
9423 output_cpu_unit_reservation_p ();
9424 fprintf (output_file, "\n#endif /* #if %s */\n\n",
9425 CPU_UNITS_QUERY_MACRO_NAME);
9427 output_dfa_start_func ();
9428 output_dfa_finish_func ();
9429 fprintf (stderr, "done\n");
9430 if (v_flag)
9432 output_description_file = fopen (output_description_file_name, "w");
9433 if (output_description_file == NULL)
9435 perror (output_description_file_name);
9436 exit (FATAL_EXIT_CODE);
9438 fprintf (stderr, "Output automata description...");
9439 fflush (stderr);
9440 output_description ();
9441 output_automaton_descriptions ();
9442 fprintf (stderr, "done\n");
9443 output_statistics (output_description_file);
9445 output_statistics (stderr);
9446 ticker_off (&output_time);
9447 output_time_statistics (stderr);
9448 finish_states ();
9449 finish_arcs ();
9450 finish_automata_lists ();
9451 if (time_flag)
9453 fprintf (stderr, "Summary:\n");
9454 fprintf (stderr, " check time ");
9455 print_active_time (stderr, check_time);
9456 fprintf (stderr, ", generation time ");
9457 print_active_time (stderr, generation_time);
9458 fprintf (stderr, ", all time ");
9459 print_active_time (stderr, all_time);
9460 fprintf (stderr, "\n");
9462 /* Finish all work. */
9463 if (output_description_file != NULL)
9465 fflush (output_description_file);
9466 if (ferror (stdout) != 0)
9467 fatal ("Error in writing DFA description file %s",
9468 output_description_file_name);
9469 fclose (output_description_file);
9471 finish_automaton_decl_table ();
9472 finish_insn_decl_table ();
9473 finish_decl_table ();
9474 obstack_free (&irp, NULL);
9475 if (have_error && output_description_file != NULL)
9476 remove (output_description_file_name);