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