1 /* Pipeline hazard description translator.
2 Copyright (C) 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
4 Written by Vladimir Makarov <vmakarov@redhat.com>
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
13 GCC is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING. If not, write to the Free
20 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
25 1. Detecting pipeline structural hazards quickly. T. Proebsting,
26 C. Fraser. Proceedings of ACM SIGPLAN-SIGACT Symposium on
27 Principles of Programming Languages, pages 280--286, 1994.
29 This article is a good start point to understand usage of finite
30 state automata for pipeline hazard recognizers. But I'd
31 recommend the 2nd article for more deep understanding.
33 2. Efficient Instruction Scheduling Using Finite State Automata:
34 V. Bala and N. Rubin, Proceedings of MICRO-28. This is the best
35 article about usage of finite state automata for pipeline hazard
38 The current implementation is different from the 2nd article in the
41 1. New operator `|' (alternative) is permitted in functional unit
42 reservation which can be treated deterministically and
43 non-deterministically.
45 2. Possibility of usage of nondeterministic automata too.
47 3. Possibility to query functional unit reservations for given
50 4. Several constructions to describe impossible reservations
51 (`exclusion_set', `presence_set', `final_presence_set',
52 `absence_set', and `final_absence_set').
54 5. No reverse automata are generated. Trace instruction scheduling
55 requires this. It can be easily added in the future if we
58 6. Union of automaton states are not generated yet. It is planned
59 to be implemented. Such feature is needed to make more accurate
60 interlock insn scheduling to get state describing functional
61 unit reservation in a joint CFG point. */
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
68 The translator functions `gen_cpu_unit', `gen_query_cpu_unit',
69 `gen_bypass', `gen_excl_set', `gen_presence_set',
70 `gen_final_presence_set', `gen_absence_set',
71 `gen_final_absence_set', `gen_automaton', `gen_automata_option',
72 `gen_reserv', `gen_insn_reserv' are called from file
73 `genattrtab.c'. They transform RTL constructions describing
74 automata in .md file into internal representation convenient for
77 The translator major function `expand_automata' processes the
78 description internal representation into finite state automaton.
81 o checking correctness of the automaton pipeline description
82 (major function is `check_all_description').
84 o generating automaton (automata) from the description (major
85 function is `make_automaton').
87 o optional transformation of nondeterministic finite state
88 automata into deterministic ones if the alternative operator
89 `|' is treated nondeterministically in the description (major
90 function is NDFA_to_DFA).
92 o optional minimization of the finite state automata by merging
93 equivalent automaton states (major function is `minimize_DFA').
95 o forming tables (some as comb vectors) and attributes
96 representing the automata (functions output_..._table).
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
106 #include "coretypes.h"
120 #include "genattrtab.h"
122 /* Positions in machine description file. Now they are not used. But
123 they could be used in the future for better diagnostic messages. */
126 /* The following is element of vector of current (and planned in the
127 future) functional unit reservations. */
128 typedef unsigned HOST_WIDE_INT set_el_t
;
130 /* Reservations of function units are represented by value of the following
132 typedef set_el_t
*reserv_sets_t
;
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. */
139 size_t length
; /* current size of vla. */
140 varray_type varray
; /* container for vla. */
143 typedef vla_ptr_t vla_hwint_t
;
145 /* The following structure describes a ticker. */
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
;
157 /* The ticker is represented by the following type. */
158 typedef struct ticker ticker_t
;
160 /* The following type describes elements of output vectors. */
161 typedef HOST_WIDE_INT vect_el_t
;
163 /* Forward declaration of structures of internal representation of
164 pipeline description based on NDFA. */
169 struct automaton_decl
;
170 struct unit_pattern_rel_decl
;
172 struct insn_reserv_decl
;
175 struct result_regexp
;
176 struct reserv_regexp
;
177 struct nothing_regexp
;
178 struct sequence_regexp
;
179 struct repeat_regexp
;
185 struct pattern_set_el
;
186 struct pattern_reserv
;
192 struct state_ainsn_table
;
194 /* The following typedefs are for brevity. */
195 typedef struct unit_decl
*unit_decl_t
;
196 typedef struct decl
*decl_t
;
197 typedef struct regexp
*regexp_t
;
198 typedef struct unit_set_el
*unit_set_el_t
;
199 typedef struct pattern_set_el
*pattern_set_el_t
;
200 typedef struct pattern_reserv
*pattern_reserv_t
;
201 typedef struct alt_state
*alt_state_t
;
202 typedef struct state
*state_t
;
203 typedef struct arc
*arc_t
;
204 typedef struct ainsn
*ainsn_t
;
205 typedef struct automaton
*automaton_t
;
206 typedef struct automata_list_el
*automata_list_el_t
;
207 typedef struct state_ainsn_table
*state_ainsn_table_t
;
210 /* Prototypes of functions gen_cpu_unit, gen_query_cpu_unit,
211 gen_bypass, gen_excl_set, gen_presence_set, gen_final_presence_set,
212 gen_absence_set, gen_final_absence_set, gen_automaton,
213 gen_automata_option, gen_reserv, gen_insn_reserv,
214 initiate_automaton_gen, expand_automata, write_automata are
215 described on the file top because the functions are called from
218 static void *create_node (size_t);
219 static void *copy_node (const void *, size_t);
220 static char *check_name (char *, pos_t
);
221 static char *next_sep_el (char **, int, int);
222 static int n_sep_els (char *, int, int);
223 static char **get_str_vect (char *, int *, int, int);
224 static void gen_presence_absence_set (rtx
, int, int);
225 static regexp_t
gen_regexp_el (char *);
226 static regexp_t
gen_regexp_repeat (char *);
227 static regexp_t
gen_regexp_allof (char *);
228 static regexp_t
gen_regexp_oneof (char *);
229 static regexp_t
gen_regexp_sequence (char *);
230 static regexp_t
gen_regexp (char *);
232 static unsigned string_hash (const char *);
233 static unsigned automaton_decl_hash (const void *);
234 static int automaton_decl_eq_p (const void *,
236 static decl_t
insert_automaton_decl (decl_t
);
237 static decl_t
find_automaton_decl (char *);
238 static void initiate_automaton_decl_table (void);
239 static void finish_automaton_decl_table (void);
241 static hashval_t
insn_decl_hash (const void *);
242 static int insn_decl_eq_p (const void *,
244 static decl_t
insert_insn_decl (decl_t
);
245 static decl_t
find_insn_decl (char *);
246 static void initiate_insn_decl_table (void);
247 static void finish_insn_decl_table (void);
249 static hashval_t
decl_hash (const void *);
250 static int decl_eq_p (const void *,
252 static decl_t
insert_decl (decl_t
);
253 static decl_t
find_decl (char *);
254 static void initiate_decl_table (void);
255 static void finish_decl_table (void);
257 static unit_set_el_t
process_excls (char **, int, pos_t
);
258 static void add_excls (unit_set_el_t
, unit_set_el_t
,
260 static unit_set_el_t process_presence_absence_names
261 (char **, int, pos_t
,
263 static pattern_set_el_t process_presence_absence_patterns
264 (char ***, int, pos_t
,
266 static void add_presence_absence (unit_set_el_t
,
269 static void process_decls (void);
270 static struct bypass_decl
*find_bypass (struct bypass_decl
*,
271 struct insn_reserv_decl
*);
272 static void check_automaton_usage (void);
273 static regexp_t
process_regexp (regexp_t
);
274 static void process_regexp_decls (void);
275 static void check_usage (void);
276 static int loop_in_regexp (regexp_t
, decl_t
);
277 static void check_loops_in_regexps (void);
278 static void process_regexp_cycles (regexp_t
, int, int,
280 static void evaluate_max_reserv_cycles (void);
281 static void check_all_description (void);
283 static ticker_t
create_ticker (void);
284 static void ticker_off (ticker_t
*);
285 static void ticker_on (ticker_t
*);
286 static int active_time (ticker_t
);
287 static void print_active_time (FILE *, ticker_t
);
289 static void add_advance_cycle_insn_decl (void);
291 static alt_state_t
get_free_alt_state (void);
292 static void free_alt_state (alt_state_t
);
293 static void free_alt_states (alt_state_t
);
294 static int alt_state_cmp (const void *alt_state_ptr_1
,
295 const void *alt_state_ptr_2
);
296 static alt_state_t
uniq_sort_alt_states (alt_state_t
);
297 static int alt_states_eq (alt_state_t
, alt_state_t
);
298 static void initiate_alt_states (void);
299 static void finish_alt_states (void);
301 static reserv_sets_t
alloc_empty_reserv_sets (void);
302 static unsigned reserv_sets_hash_value (reserv_sets_t
);
303 static int reserv_sets_cmp (reserv_sets_t
, reserv_sets_t
);
304 static int reserv_sets_eq (reserv_sets_t
, reserv_sets_t
);
305 static void set_unit_reserv (reserv_sets_t
, int, int);
306 static int test_unit_reserv (reserv_sets_t
, int, int);
307 static int it_is_empty_reserv_sets (reserv_sets_t
)
309 static int reserv_sets_are_intersected (reserv_sets_t
, reserv_sets_t
);
310 static void reserv_sets_shift (reserv_sets_t
, reserv_sets_t
);
311 static void reserv_sets_or (reserv_sets_t
, reserv_sets_t
,
313 static void reserv_sets_and (reserv_sets_t
, reserv_sets_t
,
316 static void output_cycle_reservs (FILE *, reserv_sets_t
,
318 static void output_reserv_sets (FILE *, reserv_sets_t
);
319 static state_t
get_free_state (int, automaton_t
);
320 static void free_state (state_t
);
321 static hashval_t
state_hash (const void *);
322 static int state_eq_p (const void *, const void *);
323 static state_t
insert_state (state_t
);
324 static void set_state_reserv (state_t
, int, int);
325 static int intersected_state_reservs_p (state_t
, state_t
);
326 static state_t
states_union (state_t
, state_t
, reserv_sets_t
);
327 static state_t
state_shift (state_t
, reserv_sets_t
);
328 static void initiate_states (void);
329 static void finish_states (void);
331 static void free_arc (arc_t
);
332 static void remove_arc (state_t
, arc_t
);
333 static arc_t
find_arc (state_t
, state_t
, ainsn_t
);
334 static arc_t
add_arc (state_t
, state_t
, ainsn_t
, int);
335 static arc_t
first_out_arc (state_t
);
336 static arc_t
next_out_arc (arc_t
);
337 static void initiate_arcs (void);
338 static void finish_arcs (void);
340 static automata_list_el_t
get_free_automata_list_el (void);
341 static void free_automata_list_el (automata_list_el_t
);
342 static void free_automata_list (automata_list_el_t
);
343 static hashval_t
automata_list_hash (const void *);
344 static int automata_list_eq_p (const void *, const void *);
345 static void initiate_automata_lists (void);
346 static void automata_list_start (void);
347 static void automata_list_add (automaton_t
);
348 static automata_list_el_t
automata_list_finish (void);
349 static void finish_automata_lists (void);
351 static void initiate_excl_sets (void);
352 static reserv_sets_t
get_excl_set (reserv_sets_t
);
354 static pattern_reserv_t
form_reserv_sets_list (pattern_set_el_t
);
355 static void initiate_presence_absence_pattern_sets (void);
356 static int check_presence_pattern_sets (reserv_sets_t
,
358 static int check_absence_pattern_sets (reserv_sets_t
, reserv_sets_t
,
361 static regexp_t
copy_insn_regexp (regexp_t
);
362 static regexp_t
transform_1 (regexp_t
);
363 static regexp_t
transform_2 (regexp_t
);
364 static regexp_t
transform_3 (regexp_t
);
365 static regexp_t regexp_transform_func
366 (regexp_t
, regexp_t (*) (regexp_t
));
367 static regexp_t
transform_regexp (regexp_t
);
368 static void transform_insn_regexps (void);
370 static void store_alt_unit_usage (regexp_t
, regexp_t
, int, int);
371 static void check_regexp_units_distribution (const char *, regexp_t
);
372 static void check_unit_distributions_to_automata (void);
374 static int process_seq_for_forming_states (regexp_t
, automaton_t
,
376 static void finish_forming_alt_state (alt_state_t
,
378 static void process_alts_for_forming_states (regexp_t
,
380 static void create_alt_states (automaton_t
);
382 static void form_ainsn_with_same_reservs (automaton_t
);
384 static reserv_sets_t
form_reservs_matter (automaton_t
);
385 static void make_automaton (automaton_t
);
386 static void form_arcs_marked_by_insn (state_t
);
387 static int create_composed_state (state_t
, arc_t
, vla_ptr_t
*);
388 static void NDFA_to_DFA (automaton_t
);
389 static void pass_state_graph (state_t
, void (*) (state_t
));
390 static void pass_states (automaton_t
,
392 static void initiate_pass_states (void);
393 static void add_achieved_state (state_t
);
394 static int set_out_arc_insns_equiv_num (state_t
, int);
395 static void clear_arc_insns_equiv_num (state_t
);
396 static void copy_equiv_class (vla_ptr_t
*to
,
397 const vla_ptr_t
*from
);
398 static int first_cycle_unit_presence (state_t
, int);
399 static int state_is_differed (state_t
, state_t
, int, int);
400 static state_t
init_equiv_class (state_t
*states
, int);
401 static int partition_equiv_class (state_t
*, int,
403 static void evaluate_equiv_classes (automaton_t
, vla_ptr_t
*);
404 static void merge_states (automaton_t
, vla_ptr_t
*);
405 static void set_new_cycle_flags (state_t
);
406 static void minimize_DFA (automaton_t
);
407 static void incr_states_and_arcs_nums (state_t
);
408 static void count_states_and_arcs (automaton_t
, int *, int *);
409 static void build_automaton (automaton_t
);
411 static void set_order_state_num (state_t
);
412 static void enumerate_states (automaton_t
);
414 static ainsn_t
insert_ainsn_into_equiv_class (ainsn_t
, ainsn_t
);
415 static void delete_ainsn_from_equiv_class (ainsn_t
);
416 static void process_insn_equiv_class (ainsn_t
, arc_t
*);
417 static void process_state_for_insn_equiv_partition (state_t
);
418 static void set_insn_equiv_classes (automaton_t
);
420 static double estimate_one_automaton_bound (void);
421 static int compare_max_occ_cycle_nums (const void *,
423 static void units_to_automata_heuristic_distr (void);
424 static ainsn_t
create_ainsns (void);
425 static void units_to_automata_distr (void);
426 static void create_automata (void);
428 static void form_regexp (regexp_t
);
429 static const char *regexp_representation (regexp_t
);
430 static void finish_regexp_representation (void);
432 static void output_range_type (FILE *, long int, long int);
433 static int longest_path_length (state_t
);
434 static void process_state_longest_path_length (state_t
);
435 static void output_dfa_max_issue_rate (void);
436 static void output_vect (vect_el_t
*, int);
437 static void output_chip_member_name (FILE *, automaton_t
);
438 static void output_temp_chip_member_name (FILE *, automaton_t
);
439 static void output_translate_vect_name (FILE *, automaton_t
);
440 static void output_trans_full_vect_name (FILE *, automaton_t
);
441 static void output_trans_comb_vect_name (FILE *, automaton_t
);
442 static void output_trans_check_vect_name (FILE *, automaton_t
);
443 static void output_trans_base_vect_name (FILE *, automaton_t
);
444 static void output_state_alts_full_vect_name (FILE *, automaton_t
);
445 static void output_state_alts_comb_vect_name (FILE *, automaton_t
);
446 static void output_state_alts_check_vect_name (FILE *, automaton_t
);
447 static void output_state_alts_base_vect_name (FILE *, automaton_t
);
448 static void output_min_issue_delay_vect_name (FILE *, automaton_t
);
449 static void output_dead_lock_vect_name (FILE *, automaton_t
);
450 static void output_reserved_units_table_name (FILE *, automaton_t
);
451 static void output_state_member_type (FILE *, automaton_t
);
452 static void output_chip_definitions (void);
453 static void output_translate_vect (automaton_t
);
454 static int comb_vect_p (state_ainsn_table_t
);
455 static state_ainsn_table_t
create_state_ainsn_table (automaton_t
);
456 static void output_state_ainsn_table
457 (state_ainsn_table_t
, char *, void (*) (FILE *, automaton_t
),
458 void (*) (FILE *, automaton_t
), void (*) (FILE *, automaton_t
),
459 void (*) (FILE *, automaton_t
));
460 static void add_vect (state_ainsn_table_t
,
461 int, vect_el_t
*, int);
462 static int out_state_arcs_num (state_t
);
463 static int compare_transition_els_num (const void *, const void *);
464 static void add_vect_el (vla_hwint_t
*,
466 static void add_states_vect_el (state_t
);
467 static void output_trans_table (automaton_t
);
468 static void output_state_alts_table (automaton_t
);
469 static int min_issue_delay_pass_states (state_t
, ainsn_t
);
470 static int min_issue_delay (state_t
, ainsn_t
);
471 static void initiate_min_issue_delay_pass_states (void);
472 static void output_min_issue_delay_table (automaton_t
);
473 static void output_dead_lock_vect (automaton_t
);
474 static void output_reserved_units_table (automaton_t
);
475 static void output_tables (void);
476 static void output_max_insn_queue_index_def (void);
477 static void output_insn_code_cases (void (*) (automata_list_el_t
));
478 static void output_automata_list_min_issue_delay_code (automata_list_el_t
);
479 static void output_internal_min_issue_delay_func (void);
480 static void output_automata_list_transition_code (automata_list_el_t
);
481 static void output_internal_trans_func (void);
482 static void output_internal_insn_code_evaluation (const char *,
484 static void output_dfa_insn_code_func (void);
485 static void output_trans_func (void);
486 static void output_automata_list_state_alts_code (automata_list_el_t
);
487 static void output_internal_state_alts_func (void);
488 static void output_state_alts_func (void);
489 static void output_min_issue_delay_func (void);
490 static void output_internal_dead_lock_func (void);
491 static void output_dead_lock_func (void);
492 static void output_internal_reset_func (void);
493 static void output_size_func (void);
494 static void output_reset_func (void);
495 static void output_min_insn_conflict_delay_func (void);
496 static void output_internal_insn_latency_func (void);
497 static void output_insn_latency_func (void);
498 static void output_print_reservation_func (void);
499 static int units_cmp (const void *,
501 static void output_get_cpu_unit_code_func (void);
502 static void output_cpu_unit_reservation_p (void);
503 static void output_dfa_clean_insn_cache_func (void);
504 static void output_dfa_start_func (void);
505 static void output_dfa_finish_func (void);
507 static void output_regexp (regexp_t
);
508 static void output_unit_set_el_list (unit_set_el_t
);
509 static void output_pattern_set_el_list (pattern_set_el_t
);
510 static void output_description (void);
511 static void output_automaton_name (FILE *, automaton_t
);
512 static void output_automaton_units (automaton_t
);
513 static void add_state_reservs (state_t
);
514 static void output_state_arcs (state_t
);
515 static int state_reservs_cmp (const void *,
517 static void remove_state_duplicate_reservs (void);
518 static void output_state (state_t
);
519 static void output_automaton_descriptions (void);
520 static void output_statistics (FILE *);
521 static void output_time_statistics (FILE *);
522 static void generate (void);
524 static void make_insn_alts_attr (void);
525 static void make_internal_dfa_insn_code_attr (void);
526 static void make_default_insn_latency_attr (void);
527 static void make_bypass_attr (void);
528 static const char *file_name_suffix (const char *);
529 static const char *base_file_name (const char *);
530 static void check_automata_insn_issues (void);
531 static void add_automaton_state (state_t
);
532 static void form_important_insn_automata_lists (void);
534 /* Undefined position. */
535 static pos_t no_pos
= 0;
537 /* All IR is stored in the following obstack. */
538 static struct obstack irp
;
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. */
547 /* Start work with vla. */
548 #define VLA_PTR_CREATE(vla, allocated_length, name) \
551 vla_ptr_t *const _vla_ptr = &(vla); \
553 VARRAY_GENERIC_PTR_INIT (_vla_ptr->varray, allocated_length, name);\
554 _vla_ptr->length = 0; \
558 /* Finish work with the vla. */
559 #define VLA_PTR_DELETE(vla) VARRAY_FREE ((vla).varray)
561 /* Return start address of the vla. */
562 #define VLA_PTR_BEGIN(vla) ((void *) &VARRAY_GENERIC_PTR ((vla).varray, 0))
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, \
568 /* Nullify the vla. */
569 #define VLA_PTR_NULLIFY(vla) ((vla).length = 0)
571 /* Shorten the vla on given number bytes. */
572 #define VLA_PTR_SHORTEN(vla, n) ((vla).length -= (n))
574 /* Expand the vla on N elements. The values of new elements are
576 #define VLA_PTR_EXPAND(vla, n) \
578 vla_ptr_t *const _expand_vla_ptr = &(vla); \
579 const size_t _new_length = (n) + _expand_vla_ptr->length; \
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; \
588 /* Add element to the end of the vla. */
589 #define VLA_PTR_ADD(vla, ptr) \
591 vla_ptr_t *const _vla_ptr = &(vla); \
593 VLA_PTR_EXPAND (*_vla_ptr, 1); \
594 VARRAY_GENERIC_PTR (_vla_ptr->varray, _vla_ptr->length - 1) = (ptr);\
597 /* Length of the vla in elements. */
598 #define VLA_PTR_LENGTH(vla) ((vla).length)
600 /* N-th element of the vla. */
601 #define VLA_PTR(vla, n) VARRAY_GENERIC_PTR ((vla).varray, n)
604 /* The following macros are analogous to the previous ones but for
605 VLAs of HOST WIDE INTs. */
607 #define VLA_HWINT_CREATE(vla, allocated_length, name) \
609 vla_hwint_t *const _vla_ptr = &(vla); \
611 VARRAY_WIDE_INT_INIT (_vla_ptr->varray, allocated_length, name); \
612 _vla_ptr->length = 0; \
615 #define VLA_HWINT_DELETE(vla) VARRAY_FREE ((vla).varray)
617 #define VLA_HWINT_BEGIN(vla) (&VARRAY_WIDE_INT ((vla).varray, 0))
619 #define VLA_HWINT_NULLIFY(vla) ((vla).length = 0)
621 #define VLA_HWINT_EXPAND(vla, n) \
623 vla_hwint_t *const _expand_vla_ptr = &(vla); \
624 const size_t _new_length = (n) + _expand_vla_ptr->length; \
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; \
633 #define VLA_HWINT_ADD(vla, ptr) \
635 vla_hwint_t *const _vla_ptr = &(vla); \
637 VLA_HWINT_EXPAND (*_vla_ptr, 1); \
638 VARRAY_WIDE_INT (_vla_ptr->varray, _vla_ptr->length - 1) = (ptr); \
641 #define VLA_HWINT_LENGTH(vla) ((vla).length)
643 #define VLA_HWINT(vla, n) VARRAY_WIDE_INT ((vla).varray, n)
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
651 #define NO_MINIMIZATION_OPTION "-no-minimization"
653 #define TIME_OPTION "-time"
655 #define V_OPTION "-v"
657 #define W_OPTION "-w"
659 #define NDFA_OPTION "-ndfa"
661 #define PROGRESS_OPTION "-progress"
663 /* The following flags are set up by function `initiate_automaton_gen'. */
665 /* Make automata with nondeterministic reservation by insns (`-ndfa'). */
666 static int ndfa_flag
;
668 /* Do not make minimization of DFA (`-no-minimization'). */
669 static int no_minimization_flag
;
671 /* Value of this variable is number of automata being generated. The
672 actual number of automata may be less this value if there is not
673 sufficient number of units. This value is defined by argument of
674 option `-split' or by constructions automaton if the value is zero
675 (it is default value of the argument). */
676 static int split_argument
;
678 /* Flag of output time statistics (`-time'). */
679 static int time_flag
;
681 /* Flag of creation of description file which contains description of
682 result automaton and statistics information (`-v'). */
685 /* Flag of output of a progress bar showing how many states were
686 generated so far for automaton being processed (`-progress'). */
687 static int progress_flag
;
689 /* Flag of generating warning instead of error for non-critical errors
694 /* Output file for pipeline hazard recognizer (PHR) being generated.
695 The value is NULL if the file is not defined. */
696 static FILE *output_file
;
698 /* Description file of PHR. The value is NULL if the file is not
700 static FILE *output_description_file
;
702 /* PHR description file name. */
703 static char *output_description_file_name
;
705 /* Value of the following variable is node representing description
706 being processed. This is start point of IR. */
707 static struct description
*description
;
711 /* This page contains description of IR structure (nodes). */
725 /* This describes define_cpu_unit and define_query_cpu_unit (see file
730 /* NULL if the automaton name is absent. */
731 char *automaton_name
;
732 /* If the following value is not zero, the cpu unit reservation is
733 described in define_query_cpu_unit. */
736 /* The following fields are defined by checker. */
738 /* The following field value is nonzero if the unit is used in an
742 /* The following field value is order number (0, 1, ...) of given
745 /* The following field value is corresponding declaration of
746 automaton which was given in description. If the field value is
747 NULL then automaton in the unit declaration was absent. */
748 struct automaton_decl
*automaton_decl
;
749 /* The following field value is maximal cycle number (1, ...) on
750 which given unit occurs in insns. Zero value means that given
751 unit is not used in insns. */
752 int max_occ_cycle_num
;
753 /* The following field value is minimal cycle number (0, ...) on
754 which given unit occurs in insns. -1 value means that given
755 unit is not used in insns. */
756 int min_occ_cycle_num
;
757 /* The following list contains units which conflict with given
759 unit_set_el_t excl_list
;
760 /* The following list contains patterns which are required to
761 reservation of given unit. */
762 pattern_set_el_t presence_list
;
763 pattern_set_el_t final_presence_list
;
764 /* The following list contains patterns which should be not present
765 in reservation for given unit. */
766 pattern_set_el_t absence_list
;
767 pattern_set_el_t final_absence_list
;
768 /* The following is used only when `query_p' has nonzero value.
769 This is query number for the unit. */
771 /* The following is the last cycle on which the unit was checked for
772 correct distributions of units to automata in a regexp. */
773 int last_distribution_check_cycle
;
775 /* The following fields are defined by automaton generator. */
777 /* The following field value is number of the automaton to which
778 given unit belongs. */
779 int corresponding_automaton_num
;
780 /* If the following value is not zero, the cpu unit is present in a
781 `exclusion_set' or in right part of a `presence_set',
782 `final_presence_set', `absence_set', and
783 `final_absence_set'define_query_cpu_unit. */
787 /* This describes define_bypass (see file rtl.def). */
793 char *bypass_guard_name
;
795 /* The following fields are defined by checker. */
797 /* output and input insns of given bypass. */
798 struct insn_reserv_decl
*out_insn_reserv
;
799 struct insn_reserv_decl
*in_insn_reserv
;
800 /* The next bypass for given output insn. */
801 struct bypass_decl
*next
;
804 /* This describes define_automaton (see file rtl.def). */
805 struct automaton_decl
809 /* The following fields are defined by automaton generator. */
811 /* The following field value is nonzero if the automaton is used in
812 an regexp definition. */
813 char automaton_is_used
;
815 /* The following fields are defined by checker. */
817 /* The following field value is the corresponding automaton. This
818 field is not NULL only if the automaton is present in unit
819 declarations and the automatic partition on automata is not
821 automaton_t corresponding_automaton
;
824 /* This describes exclusion relations: exclusion_set (see file
829 int first_list_length
;
833 /* This describes unit relations: [final_]presence_set or
834 [final_]absence_set (see file rtl.def). */
835 struct unit_pattern_rel_decl
844 /* This describes define_reservation (see file rtl.def). */
850 /* The following fields are defined by checker. */
852 /* The following field value is nonzero if the unit is used in an
855 /* The following field is used to check up cycle in expression
860 /* This describes define_insn_reservation (see file rtl.def). */
861 struct insn_reserv_decl
868 /* The following fields are defined by checker. */
870 /* The following field value is order number (0, 1, ...) of given
873 /* The following field value is list of bypasses in which given insn
875 struct bypass_decl
*bypass_list
;
877 /* The following fields are defined by automaton generator. */
879 /* The following field is the insn regexp transformed that
880 the regexp has not optional regexp, repetition regexp, and an
881 reservation name (i.e. reservation identifiers are changed by the
882 corresponding regexp) and all alternations are the topest level
883 of the regexp. The value can be NULL only if it is special
884 insn `cycle advancing'. */
885 regexp_t transformed_regexp
;
886 /* The following field value is list of arcs marked given
887 insn. The field is used in transformation NDFA -> DFA. */
888 arc_t arcs_marked_by_insn
;
889 /* The two following fields are used during minimization of a finite state
891 /* The field value is number of equivalence class of state into
892 which arc marked by given insn enters from a state (fixed during
893 an automaton minimization). */
895 /* The field value is state_alts of arc leaving a state (fixed
896 during an automaton minimization) and marked by given insn
899 /* The following member value is the list to automata which can be
900 changed by the insn issue. */
901 automata_list_el_t important_automata_list
;
902 /* The following member is used to process insn once for output. */
906 /* This contains a declaration mentioned above. */
909 /* What node in the union? */
914 struct unit_decl unit
;
915 struct bypass_decl bypass
;
916 struct automaton_decl automaton
;
917 struct excl_rel_decl excl
;
918 struct unit_pattern_rel_decl presence
;
919 struct unit_pattern_rel_decl absence
;
920 struct reserv_decl reserv
;
921 struct insn_reserv_decl insn_reserv
;
925 /* The following structures represent parsed reservation strings. */
937 /* Cpu unit in reservation. */
941 unit_decl_t unit_decl
;
944 /* Define_reservation in a reservation. */
948 struct reserv_decl
*reserv_decl
;
951 /* Absence of reservation (represented by string `nothing'). */
952 struct nothing_regexp
954 /* This used to be empty but ISO C doesn't allow that. */
958 /* Representation of reservations separated by ',' (see file
960 struct sequence_regexp
963 regexp_t regexps
[1];
966 /* Representation of construction `repeat' (see file rtl.def). */
973 /* Representation of reservations separated by '+' (see file
978 regexp_t regexps
[1];
981 /* Representation of reservations separated by '|' (see file
986 regexp_t regexps
[1];
989 /* Representation of a reservation string. */
992 /* What node in the union? */
993 enum regexp_mode mode
;
997 struct unit_regexp unit
;
998 struct reserv_regexp reserv
;
999 struct nothing_regexp nothing
;
1000 struct sequence_regexp sequence
;
1001 struct repeat_regexp repeat
;
1002 struct allof_regexp allof
;
1003 struct oneof_regexp oneof
;
1007 /* Represents description of pipeline hazard description based on
1013 /* The following fields are defined by checker. */
1015 /* The following fields values are correspondingly number of all
1016 units, query units, and insns in the description. */
1018 int query_units_num
;
1020 /* The following field value is max length (in cycles) of
1021 reservations of insns. The field value is defined only for
1022 correct programs. */
1023 int max_insn_reserv_cycles
;
1025 /* The following fields are defined by automaton generator. */
1027 /* The following field value is the first automaton. */
1028 automaton_t first_automaton
;
1030 /* The following field is created by pipeline hazard parser and
1031 contains all declarations. We allocate additional entry for
1032 special insn "cycle advancing" which is added by the automaton
1038 /* The following nodes are created in automaton checker. */
1040 /* The following nodes represent exclusion set for cpu units. Each
1041 element is accessed through only one excl_list. */
1044 unit_decl_t unit_decl
;
1045 unit_set_el_t next_unit_set_el
;
1048 /* The following nodes represent presence or absence pattern for cpu
1049 units. Each element is accessed through only one presence_list or
1051 struct pattern_set_el
1053 /* The number of units in unit_decls. */
1055 /* The units forming the pattern. */
1056 struct unit_decl
**unit_decls
;
1057 pattern_set_el_t next_pattern_set_el
;
1061 /* The following nodes are created in automaton generator. */
1064 /* The following nodes represent presence or absence pattern for cpu
1065 units. Each element is accessed through only one element of
1066 unit_presence_set_table or unit_absence_set_table. */
1067 struct pattern_reserv
1069 reserv_sets_t reserv
;
1070 pattern_reserv_t next_pattern_reserv
;
1073 /* The following node type describes state automaton. The state may
1074 be deterministic or non-deterministic. Non-deterministic state has
1075 several component states which represent alternative cpu units
1076 reservations. The state also is used for describing a
1077 deterministic reservation of automaton insn. */
1080 /* The following member value is nonzero if there is a transition by
1083 /* The following field is list of processor unit reservations on
1085 reserv_sets_t reservs
;
1086 /* The following field is unique number of given state between other
1089 /* The following field value is automaton to which given state
1091 automaton_t automaton
;
1092 /* The following field value is the first arc output from given
1094 arc_t first_out_arc
;
1095 /* The following field is used to form NDFA. */
1096 char it_was_placed_in_stack_for_NDFA_forming
;
1097 /* The following field is used to form DFA. */
1098 char it_was_placed_in_stack_for_DFA_forming
;
1099 /* The following field is used to transform NDFA to DFA and DFA
1100 minimization. The field value is not NULL if the state is a
1101 compound state. In this case the value of field `unit_sets_list'
1102 is NULL. All states in the list are in the hash table. The list
1103 is formed through field `next_sorted_alt_state'. We should
1104 support only one level of nesting state. */
1105 alt_state_t component_states
;
1106 /* The following field is used for passing graph of states. */
1108 /* The list of states belonging to one equivalence class is formed
1109 with the aid of the following field. */
1110 state_t next_equiv_class_state
;
1111 /* The two following fields are used during minimization of a finite
1113 int equiv_class_num_1
, equiv_class_num_2
;
1114 /* The following field is used during minimization of a finite state
1115 automaton. The field value is state corresponding to equivalence
1116 class to which given state belongs. */
1117 state_t equiv_class_state
;
1118 /* The following field value is the order number of given state.
1119 The states in final DFA is enumerated with the aid of the
1121 int order_state_num
;
1122 /* This member is used for passing states for searching minimal
1125 /* The following member is used to evaluate min issue delay of insn
1127 int min_insn_issue_delay
;
1128 /* The following member is used to evaluate max issue rate of the
1129 processor. The value of the member is maximal length of the path
1130 from given state no containing arcs marked by special insn `cycle
1132 int longest_path_length
;
1135 /* The following macro is an initial value of member
1136 `longest_path_length' of a state. */
1137 #define UNDEFINED_LONGEST_PATH_LENGTH -1
1139 /* Automaton arc. */
1142 /* The following field refers for the state into which given arc
1145 /* The following field describes that the insn issue (with cycle
1146 advancing for special insn `cycle advancing' and without cycle
1147 advancing for others) makes transition from given state to
1148 another given state. */
1150 /* The following field value is the next arc output from the same
1153 /* List of arcs marked given insn is formed with the following
1154 field. The field is used in transformation NDFA -> DFA. */
1155 arc_t next_arc_marked_by_insn
;
1156 /* The following field is defined if NDFA_FLAG is zero. The member
1157 value is number of alternative reservations which can be used for
1158 transition for given state by given insn. */
1162 /* The following node type describes a deterministic alternative in
1163 non-deterministic state which characterizes cpu unit reservations
1164 of automaton insn or which is part of NDFA. */
1167 /* The following field is a deterministic state which characterizes
1168 unit reservations of the instruction. */
1170 /* The following field refers to the next state which characterizes
1171 unit reservations of the instruction. */
1172 alt_state_t next_alt_state
;
1173 /* The following field refers to the next state in sorted list. */
1174 alt_state_t next_sorted_alt_state
;
1177 /* The following node type describes insn of automaton. They are
1178 labels of FA arcs. */
1181 /* The following field value is the corresponding insn declaration
1183 struct insn_reserv_decl
*insn_reserv_decl
;
1184 /* The following field value is the next insn declaration for an
1187 /* The following field is states which characterize automaton unit
1188 reservations of the instruction. The value can be NULL only if it
1189 is special insn `cycle advancing'. */
1190 alt_state_t alt_states
;
1191 /* The following field is sorted list of states which characterize
1192 automaton unit reservations of the instruction. The value can be
1193 NULL only if it is special insn `cycle advancing'. */
1194 alt_state_t sorted_alt_states
;
1195 /* The following field refers the next automaton insn with
1196 the same reservations. */
1197 ainsn_t next_same_reservs_insn
;
1198 /* The following field is flag of the first automaton insn with the
1199 same reservations in the declaration list. Only arcs marked such
1200 insn is present in the automaton. This significantly decreases
1201 memory requirements especially when several automata are
1203 char first_insn_with_same_reservs
;
1204 /* The following member has nonzero value if there is arc from state of
1205 the automaton marked by the ainsn. */
1207 /* Cyclic list of insns of an equivalence class is formed with the
1208 aid of the following field. */
1209 ainsn_t next_equiv_class_insn
;
1210 /* The following field value is nonzero if the insn declaration is
1211 the first insn declaration with given equivalence number. */
1212 char first_ainsn_with_given_equivalence_num
;
1213 /* The following field is number of class of equivalence of insns.
1214 It is necessary because many insns may be equivalent with the
1215 point of view of pipeline hazards. */
1216 int insn_equiv_class_num
;
1217 /* The following member value is TRUE if there is an arc in the
1218 automaton marked by the insn into another state. In other
1219 words, the insn can change the state of the automaton. */
1223 /* The following describes an automaton for PHR. */
1226 /* The following field value is the list of insn declarations for
1229 /* The following field value is the corresponding automaton
1230 declaration. This field is not NULL only if the automatic
1231 partition on automata is not used. */
1232 struct automaton_decl
*corresponding_automaton_decl
;
1233 /* The following field value is the next automaton. */
1234 automaton_t next_automaton
;
1235 /* The following field is start state of FA. There are not unit
1236 reservations in the state. */
1237 state_t start_state
;
1238 /* The following field value is number of equivalence classes of
1239 insns (see field `insn_equiv_class_num' in
1240 `insn_reserv_decl'). */
1241 int insn_equiv_classes_num
;
1242 /* The following field value is number of states of final DFA. */
1243 int achieved_states_num
;
1244 /* The following field value is the order number (0, 1, ...) of
1246 int automaton_order_num
;
1247 /* The following fields contain statistics information about
1248 building automaton. */
1249 int NDFA_states_num
, DFA_states_num
;
1250 /* The following field value is defined only if minimization of DFA
1252 int minimal_DFA_states_num
;
1253 int NDFA_arcs_num
, DFA_arcs_num
;
1254 /* The following field value is defined only if minimization of DFA
1256 int minimal_DFA_arcs_num
;
1257 /* The following two members refer for two table state x ainsn ->
1259 state_ainsn_table_t trans_table
;
1260 state_ainsn_table_t state_alts_table
;
1261 /* The following member value is maximal value of min issue delay
1262 for insns of the automaton. */
1264 /* Usually min issue delay is small and we can place several (2, 4,
1265 8) elements in one vector element. So the compression factor can
1266 be 1 (no compression), 2, 4, 8. */
1267 int min_issue_delay_table_compression_factor
;
1270 /* The following is the element of the list of automata. */
1271 struct automata_list_el
1273 /* The automaton itself. */
1274 automaton_t automaton
;
1275 /* The next automata set element. */
1276 automata_list_el_t next_automata_list_el
;
1279 /* The following structure describes a table state X ainsn -> int(>= 0). */
1280 struct state_ainsn_table
1282 /* Automaton to which given table belongs. */
1283 automaton_t automaton
;
1284 /* The following tree vectors for comb vector implementation of the
1286 vla_hwint_t comb_vect
;
1287 vla_hwint_t check_vect
;
1288 vla_hwint_t base_vect
;
1289 /* This is simple implementation of the table. */
1290 vla_hwint_t full_vect
;
1291 /* Minimal and maximal values of the previous vectors. */
1292 int min_comb_vect_el_value
, max_comb_vect_el_value
;
1293 int min_base_vect_el_value
, max_base_vect_el_value
;
1296 /* Macros to access members of unions. Use only them for access to
1297 union members of declarations and regexps. */
1299 #if defined ENABLE_CHECKING && (GCC_VERSION >= 2007)
1301 #define DECL_UNIT(d) __extension__ \
1302 (({ struct decl *const _decl = (d); \
1303 if (_decl->mode != dm_unit) \
1304 decl_mode_check_failed (_decl->mode, "dm_unit", \
1305 __FILE__, __LINE__, __FUNCTION__); \
1306 &(_decl)->decl.unit; }))
1308 #define DECL_BYPASS(d) __extension__ \
1309 (({ struct decl *const _decl = (d); \
1310 if (_decl->mode != dm_bypass) \
1311 decl_mode_check_failed (_decl->mode, "dm_bypass", \
1312 __FILE__, __LINE__, __FUNCTION__); \
1313 &(_decl)->decl.bypass; }))
1315 #define DECL_AUTOMATON(d) __extension__ \
1316 (({ struct decl *const _decl = (d); \
1317 if (_decl->mode != dm_automaton) \
1318 decl_mode_check_failed (_decl->mode, "dm_automaton", \
1319 __FILE__, __LINE__, __FUNCTION__); \
1320 &(_decl)->decl.automaton; }))
1322 #define DECL_EXCL(d) __extension__ \
1323 (({ struct decl *const _decl = (d); \
1324 if (_decl->mode != dm_excl) \
1325 decl_mode_check_failed (_decl->mode, "dm_excl", \
1326 __FILE__, __LINE__, __FUNCTION__); \
1327 &(_decl)->decl.excl; }))
1329 #define DECL_PRESENCE(d) __extension__ \
1330 (({ struct decl *const _decl = (d); \
1331 if (_decl->mode != dm_presence) \
1332 decl_mode_check_failed (_decl->mode, "dm_presence", \
1333 __FILE__, __LINE__, __FUNCTION__); \
1334 &(_decl)->decl.presence; }))
1336 #define DECL_ABSENCE(d) __extension__ \
1337 (({ struct decl *const _decl = (d); \
1338 if (_decl->mode != dm_absence) \
1339 decl_mode_check_failed (_decl->mode, "dm_absence", \
1340 __FILE__, __LINE__, __FUNCTION__); \
1341 &(_decl)->decl.absence; }))
1343 #define DECL_RESERV(d) __extension__ \
1344 (({ struct decl *const _decl = (d); \
1345 if (_decl->mode != dm_reserv) \
1346 decl_mode_check_failed (_decl->mode, "dm_reserv", \
1347 __FILE__, __LINE__, __FUNCTION__); \
1348 &(_decl)->decl.reserv; }))
1350 #define DECL_INSN_RESERV(d) __extension__ \
1351 (({ struct decl *const _decl = (d); \
1352 if (_decl->mode != dm_insn_reserv) \
1353 decl_mode_check_failed (_decl->mode, "dm_insn_reserv", \
1354 __FILE__, __LINE__, __FUNCTION__); \
1355 &(_decl)->decl.insn_reserv; }))
1357 static const char *decl_name (enum decl_mode
);
1358 static void decl_mode_check_failed (enum decl_mode
, const char *,
1359 const char *, int, const char *);
1361 /* Return string representation of declaration mode MODE. */
1363 decl_name (enum decl_mode mode
)
1365 static char str
[100];
1367 if (mode
== dm_unit
)
1369 else if (mode
== dm_bypass
)
1371 else if (mode
== dm_automaton
)
1372 return "dm_automaton";
1373 else if (mode
== dm_excl
)
1375 else if (mode
== dm_presence
)
1376 return "dm_presence";
1377 else if (mode
== dm_absence
)
1378 return "dm_absence";
1379 else if (mode
== dm_reserv
)
1381 else if (mode
== dm_insn_reserv
)
1382 return "dm_insn_reserv";
1384 sprintf (str
, "unknown (%d)", (int) mode
);
1388 /* The function prints message about unexpected declaration and finish
1391 decl_mode_check_failed (enum decl_mode mode
, const char *expected_mode_str
,
1392 const char *file
, int line
, const char *func
)
1396 "\n%s: %d: error in %s: DECL check: expected decl %s, have %s\n",
1397 file
, line
, func
, expected_mode_str
, decl_name (mode
));
1402 #define REGEXP_UNIT(r) __extension__ \
1403 (({ struct regexp *const _regexp = (r); \
1404 if (_regexp->mode != rm_unit) \
1405 regexp_mode_check_failed (_regexp->mode, "rm_unit", \
1406 __FILE__, __LINE__, __FUNCTION__); \
1407 &(_regexp)->regexp.unit; }))
1409 #define REGEXP_RESERV(r) __extension__ \
1410 (({ struct regexp *const _regexp = (r); \
1411 if (_regexp->mode != rm_reserv) \
1412 regexp_mode_check_failed (_regexp->mode, "rm_reserv", \
1413 __FILE__, __LINE__, __FUNCTION__); \
1414 &(_regexp)->regexp.reserv; }))
1416 #define REGEXP_SEQUENCE(r) __extension__ \
1417 (({ struct regexp *const _regexp = (r); \
1418 if (_regexp->mode != rm_sequence) \
1419 regexp_mode_check_failed (_regexp->mode, "rm_sequence", \
1420 __FILE__, __LINE__, __FUNCTION__); \
1421 &(_regexp)->regexp.sequence; }))
1423 #define REGEXP_REPEAT(r) __extension__ \
1424 (({ struct regexp *const _regexp = (r); \
1425 if (_regexp->mode != rm_repeat) \
1426 regexp_mode_check_failed (_regexp->mode, "rm_repeat", \
1427 __FILE__, __LINE__, __FUNCTION__); \
1428 &(_regexp)->regexp.repeat; }))
1430 #define REGEXP_ALLOF(r) __extension__ \
1431 (({ struct regexp *const _regexp = (r); \
1432 if (_regexp->mode != rm_allof) \
1433 regexp_mode_check_failed (_regexp->mode, "rm_allof", \
1434 __FILE__, __LINE__, __FUNCTION__); \
1435 &(_regexp)->regexp.allof; }))
1437 #define REGEXP_ONEOF(r) __extension__ \
1438 (({ struct regexp *const _regexp = (r); \
1439 if (_regexp->mode != rm_oneof) \
1440 regexp_mode_check_failed (_regexp->mode, "rm_oneof", \
1441 __FILE__, __LINE__, __FUNCTION__); \
1442 &(_regexp)->regexp.oneof; }))
1444 static const char *regexp_name (enum regexp_mode
);
1445 static void regexp_mode_check_failed (enum regexp_mode
, const char *,
1450 /* Return string representation of regexp mode MODE. */
1452 regexp_name (enum regexp_mode mode
)
1454 static char str
[100];
1456 if (mode
== rm_unit
)
1458 else if (mode
== 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
)
1466 else if (mode
== rm_allof
)
1468 else if (mode
== rm_oneof
)
1471 sprintf (str
, "unknown (%d)", (int) mode
);
1475 /* The function prints message about unexpected regexp and finish the
1478 regexp_mode_check_failed (enum regexp_mode mode
,
1479 const char *expected_mode_str
,
1480 const char *file
, int line
, const char *func
)
1484 "\n%s: %d: error in %s: REGEXP check: expected decl %s, have %s\n",
1485 file
, line
, func
, expected_mode_str
, regexp_name (mode
));
1489 #else /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */
1491 #define DECL_UNIT(d) (&(d)->decl.unit)
1492 #define DECL_BYPASS(d) (&(d)->decl.bypass)
1493 #define DECL_AUTOMATON(d) (&(d)->decl.automaton)
1494 #define DECL_EXCL(d) (&(d)->decl.excl)
1495 #define DECL_PRESENCE(d) (&(d)->decl.presence)
1496 #define DECL_ABSENCE(d) (&(d)->decl.absence)
1497 #define DECL_RESERV(d) (&(d)->decl.reserv)
1498 #define DECL_INSN_RESERV(d) (&(d)->decl.insn_reserv)
1500 #define REGEXP_UNIT(r) (&(r)->regexp.unit)
1501 #define REGEXP_RESERV(r) (&(r)->regexp.reserv)
1502 #define REGEXP_SEQUENCE(r) (&(r)->regexp.sequence)
1503 #define REGEXP_REPEAT(r) (&(r)->regexp.repeat)
1504 #define REGEXP_ALLOF(r) (&(r)->regexp.allof)
1505 #define REGEXP_ONEOF(r) (&(r)->regexp.oneof)
1507 #endif /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */
1509 /* Create IR structure (node). */
1511 create_node (size_t size
)
1515 obstack_blank (&irp
, size
);
1516 result
= obstack_base (&irp
);
1517 obstack_finish (&irp
);
1518 /* Default values of members are NULL and zero. */
1519 memset (result
, 0, size
);
1523 /* Copy IR structure (node). */
1525 copy_node (const void *from
, size_t size
)
1527 void *const result
= create_node (size
);
1528 memcpy (result
, from
, size
);
1532 /* The function checks that NAME does not contain quotes (`"'). */
1534 check_name (char * name
, pos_t pos ATTRIBUTE_UNUSED
)
1538 for (str
= name
; *str
!= '\0'; str
++)
1540 error ("Name `%s' contains quotes", name
);
1544 /* Pointers to all declarations during IR generation are stored in the
1546 static vla_ptr_t decls
;
1548 /* Given a pointer to a (char *) and a separator, return an alloc'ed
1549 string containing the next separated element, taking parentheses
1550 into account if PAR_FLAG has nonzero value. Advance the pointer to
1551 after the string scanned, or the end-of-string. Return NULL if at
1554 next_sep_el (char **pstr
, int sep
, int par_flag
)
1561 /* Remove leading whitespaces. */
1562 while (ISSPACE ((int) **pstr
))
1569 for (pars_num
= 0, p
= *pstr
; *p
!= '\0'; p
++)
1571 if (par_flag
&& *p
== '(')
1573 else if (par_flag
&& *p
== ')')
1575 else if (pars_num
== 0 && *p
== sep
)
1577 if (pars_num
== 0 && ISSPACE ((int) *p
))
1581 for (; n_spaces
!= 0; n_spaces
--)
1582 obstack_1grow (&irp
, p
[-n_spaces
]);
1583 obstack_1grow (&irp
, *p
);
1586 obstack_1grow (&irp
, '\0');
1587 out_str
= obstack_base (&irp
);
1588 obstack_finish (&irp
);
1597 /* Given a string and a separator, return the number of separated
1598 elements in it, taking parentheses into account if PAR_FLAG has
1599 nonzero value. Return 0 for the null string, -1 if parentheses is
1602 n_sep_els (char *s
, int sep
, int par_flag
)
1610 for (pars_num
= 0, n
= 1; *s
; s
++)
1611 if (par_flag
&& *s
== '(')
1613 else if (par_flag
&& *s
== ')')
1615 else if (pars_num
== 0 && *s
== sep
)
1618 return (pars_num
!= 0 ? -1 : n
);
1621 /* Given a string and a separator, return vector of strings which are
1622 elements in the string and number of elements through els_num.
1623 Take parentheses into account if PAREN_P has nonzero value. The
1624 function also inserts the end marker NULL at the end of vector.
1625 Return 0 for the null string, -1 if parentheses are not balanced. */
1627 get_str_vect (char *str
, int *els_num
, int sep
, int paren_p
)
1633 *els_num
= n_sep_els (str
, sep
, paren_p
);
1636 obstack_blank (&irp
, sizeof (char *) * (*els_num
+ 1));
1637 vect
= (char **) obstack_base (&irp
);
1638 obstack_finish (&irp
);
1640 for (i
= 0; i
< *els_num
; i
++)
1641 vect
[i
] = next_sep_el (pstr
, sep
, paren_p
);
1642 if (next_sep_el (pstr
, sep
, paren_p
) != NULL
)
1648 /* Process a DEFINE_CPU_UNIT.
1650 This gives information about a unit contained in CPU. We fill a
1651 struct unit_decl with information used later by `expand_automata'. */
1653 gen_cpu_unit (rtx def
)
1656 char **str_cpu_units
;
1660 str_cpu_units
= get_str_vect ((char *) XSTR (def
, 0), &vect_length
, ',',
1662 if (str_cpu_units
== NULL
)
1663 fatal ("invalid string `%s' in define_cpu_unit", XSTR (def
, 0));
1664 for (i
= 0; i
< vect_length
; i
++)
1666 decl
= create_node (sizeof (struct decl
));
1667 decl
->mode
= dm_unit
;
1669 DECL_UNIT (decl
)->name
= check_name (str_cpu_units
[i
], decl
->pos
);
1670 DECL_UNIT (decl
)->automaton_name
= (char *) XSTR (def
, 1);
1671 DECL_UNIT (decl
)->query_p
= 0;
1672 DECL_UNIT (decl
)->min_occ_cycle_num
= -1;
1673 DECL_UNIT (decl
)->in_set_p
= 0;
1674 VLA_PTR_ADD (decls
, decl
);
1679 /* Process a DEFINE_QUERY_CPU_UNIT.
1681 This gives information about a unit contained in CPU. We fill a
1682 struct unit_decl with information used later by `expand_automata'. */
1684 gen_query_cpu_unit (rtx def
)
1687 char **str_cpu_units
;
1691 str_cpu_units
= get_str_vect ((char *) XSTR (def
, 0), &vect_length
, ',',
1693 if (str_cpu_units
== NULL
)
1694 fatal ("invalid string `%s' in define_query_cpu_unit", XSTR (def
, 0));
1695 for (i
= 0; i
< vect_length
; i
++)
1697 decl
= create_node (sizeof (struct decl
));
1698 decl
->mode
= dm_unit
;
1700 DECL_UNIT (decl
)->name
= check_name (str_cpu_units
[i
], decl
->pos
);
1701 DECL_UNIT (decl
)->automaton_name
= (char *) XSTR (def
, 1);
1702 DECL_UNIT (decl
)->query_p
= 1;
1703 VLA_PTR_ADD (decls
, decl
);
1708 /* Process a DEFINE_BYPASS.
1710 This gives information about a unit contained in the CPU. We fill
1711 in a struct bypass_decl with information used later by
1712 `expand_automata'. */
1714 gen_bypass (rtx def
)
1723 out_insns
= get_str_vect ((char *) XSTR (def
, 1), &out_length
, ',', FALSE
);
1724 if (out_insns
== NULL
)
1725 fatal ("invalid string `%s' in define_bypass", XSTR (def
, 1));
1726 in_insns
= get_str_vect ((char *) XSTR (def
, 2), &in_length
, ',', FALSE
);
1727 if (in_insns
== NULL
)
1728 fatal ("invalid string `%s' in define_bypass", XSTR (def
, 2));
1729 for (i
= 0; i
< out_length
; i
++)
1730 for (j
= 0; j
< in_length
; j
++)
1732 decl
= create_node (sizeof (struct decl
));
1733 decl
->mode
= dm_bypass
;
1735 DECL_BYPASS (decl
)->latency
= XINT (def
, 0);
1736 DECL_BYPASS (decl
)->out_insn_name
= out_insns
[i
];
1737 DECL_BYPASS (decl
)->in_insn_name
= in_insns
[j
];
1738 DECL_BYPASS (decl
)->bypass_guard_name
= (char *) XSTR (def
, 3);
1739 VLA_PTR_ADD (decls
, decl
);
1744 /* Process an EXCLUSION_SET.
1746 This gives information about a cpu unit conflicts. We fill a
1747 struct excl_rel_decl (excl) with information used later by
1748 `expand_automata'. */
1750 gen_excl_set (rtx def
)
1753 char **first_str_cpu_units
;
1754 char **second_str_cpu_units
;
1755 int first_vect_length
;
1760 = get_str_vect ((char *) XSTR (def
, 0), &first_vect_length
, ',', FALSE
);
1761 if (first_str_cpu_units
== NULL
)
1762 fatal ("invalid first string `%s' in exclusion_set", XSTR (def
, 0));
1763 second_str_cpu_units
= get_str_vect ((char *) XSTR (def
, 1), &length
, ',',
1765 if (second_str_cpu_units
== NULL
)
1766 fatal ("invalid second string `%s' in exclusion_set", XSTR (def
, 1));
1767 length
+= first_vect_length
;
1768 decl
= create_node (sizeof (struct decl
) + (length
- 1) * sizeof (char *));
1769 decl
->mode
= dm_excl
;
1771 DECL_EXCL (decl
)->all_names_num
= length
;
1772 DECL_EXCL (decl
)->first_list_length
= first_vect_length
;
1773 for (i
= 0; i
< length
; i
++)
1774 if (i
< first_vect_length
)
1775 DECL_EXCL (decl
)->names
[i
] = first_str_cpu_units
[i
];
1777 DECL_EXCL (decl
)->names
[i
]
1778 = second_str_cpu_units
[i
- first_vect_length
];
1779 VLA_PTR_ADD (decls
, decl
);
1783 /* Process a PRESENCE_SET, a FINAL_PRESENCE_SET, an ABSENCE_SET,
1784 FINAL_ABSENCE_SET (it is depended on PRESENCE_P and FINAL_P).
1786 This gives information about a cpu unit reservation requirements.
1787 We fill a struct unit_pattern_rel_decl with information used later
1788 by `expand_automata'. */
1790 gen_presence_absence_set (rtx def
, int presence_p
, int final_p
)
1793 char **str_cpu_units
;
1794 char ***str_patterns
;
1795 int cpu_units_length
;
1797 int patterns_length
;
1800 str_cpu_units
= get_str_vect ((char *) XSTR (def
, 0), &cpu_units_length
, ',',
1802 if (str_cpu_units
== NULL
)
1805 ? "invalid first string `%s' in final_presence_set"
1806 : "invalid first string `%s' in presence_set")
1808 ? "invalid first string `%s' in final_absence_set"
1809 : "invalid first string `%s' in absence_set")),
1811 str_patterns
= (char ***) get_str_vect ((char *) XSTR (def
, 1),
1812 &patterns_length
, ',', FALSE
);
1813 if (str_patterns
== NULL
)
1816 ? "invalid second string `%s' in final_presence_set"
1817 : "invalid second string `%s' in presence_set")
1819 ? "invalid second string `%s' in final_absence_set"
1820 : "invalid second string `%s' in absence_set")), XSTR (def
, 1));
1821 for (i
= 0; i
< patterns_length
; i
++)
1823 str_patterns
[i
] = get_str_vect ((char *) str_patterns
[i
], &length
, ' ',
1825 if (str_patterns
[i
] == NULL
)
1828 decl
= create_node (sizeof (struct decl
));
1832 decl
->mode
= dm_presence
;
1833 DECL_PRESENCE (decl
)->names_num
= cpu_units_length
;
1834 DECL_PRESENCE (decl
)->names
= str_cpu_units
;
1835 DECL_PRESENCE (decl
)->patterns
= str_patterns
;
1836 DECL_PRESENCE (decl
)->patterns_num
= patterns_length
;
1837 DECL_PRESENCE (decl
)->final_p
= final_p
;
1841 decl
->mode
= dm_absence
;
1842 DECL_ABSENCE (decl
)->names_num
= cpu_units_length
;
1843 DECL_ABSENCE (decl
)->names
= str_cpu_units
;
1844 DECL_ABSENCE (decl
)->patterns
= str_patterns
;
1845 DECL_ABSENCE (decl
)->patterns_num
= patterns_length
;
1846 DECL_ABSENCE (decl
)->final_p
= final_p
;
1848 VLA_PTR_ADD (decls
, decl
);
1852 /* Process a PRESENCE_SET.
1854 This gives information about a cpu unit reservation requirements.
1855 We fill a struct unit_pattern_rel_decl (presence) with information
1856 used later by `expand_automata'. */
1858 gen_presence_set (rtx def
)
1860 gen_presence_absence_set (def
, TRUE
, FALSE
);
1863 /* Process a FINAL_PRESENCE_SET.
1865 This gives information about a cpu unit reservation requirements.
1866 We fill a struct unit_pattern_rel_decl (presence) with information
1867 used later by `expand_automata'. */
1869 gen_final_presence_set (rtx def
)
1871 gen_presence_absence_set (def
, TRUE
, TRUE
);
1874 /* Process an ABSENCE_SET.
1876 This gives information about a cpu unit reservation requirements.
1877 We fill a struct unit_pattern_rel_decl (absence) with information
1878 used later by `expand_automata'. */
1880 gen_absence_set (rtx def
)
1882 gen_presence_absence_set (def
, FALSE
, FALSE
);
1885 /* Process a FINAL_ABSENCE_SET.
1887 This gives information about a cpu unit reservation requirements.
1888 We fill a struct unit_pattern_rel_decl (absence) with information
1889 used later by `expand_automata'. */
1891 gen_final_absence_set (rtx def
)
1893 gen_presence_absence_set (def
, FALSE
, TRUE
);
1896 /* Process a DEFINE_AUTOMATON.
1898 This gives information about a finite state automaton used for
1899 recognizing pipeline hazards. We fill a struct automaton_decl
1900 with information used later by `expand_automata'. */
1902 gen_automaton (rtx def
)
1905 char **str_automata
;
1909 str_automata
= get_str_vect ((char *) XSTR (def
, 0), &vect_length
, ',',
1911 if (str_automata
== NULL
)
1912 fatal ("invalid string `%s' in define_automaton", XSTR (def
, 0));
1913 for (i
= 0; i
< vect_length
; i
++)
1915 decl
= create_node (sizeof (struct decl
));
1916 decl
->mode
= dm_automaton
;
1918 DECL_AUTOMATON (decl
)->name
= check_name (str_automata
[i
], decl
->pos
);
1919 VLA_PTR_ADD (decls
, decl
);
1924 /* Process an AUTOMATA_OPTION.
1926 This gives information how to generate finite state automaton used
1927 for recognizing pipeline hazards. */
1929 gen_automata_option (rtx def
)
1931 if (strcmp (XSTR (def
, 0), NO_MINIMIZATION_OPTION
+ 1) == 0)
1932 no_minimization_flag
= 1;
1933 else if (strcmp (XSTR (def
, 0), TIME_OPTION
+ 1) == 0)
1935 else if (strcmp (XSTR (def
, 0), V_OPTION
+ 1) == 0)
1937 else if (strcmp (XSTR (def
, 0), W_OPTION
+ 1) == 0)
1939 else if (strcmp (XSTR (def
, 0), NDFA_OPTION
+ 1) == 0)
1941 else if (strcmp (XSTR (def
, 0), PROGRESS_OPTION
+ 1) == 0)
1944 fatal ("invalid option `%s' in automata_option", XSTR (def
, 0));
1947 /* Name in reservation to denote absence reservation. */
1948 #define NOTHING_NAME "nothing"
1950 /* The following string contains original reservation string being
1952 static char *reserv_str
;
1954 /* Parse an element in STR. */
1956 gen_regexp_el (char *str
)
1964 if (str
[len
- 1] != ')')
1965 fatal ("garbage after ) in reservation `%s'", reserv_str
);
1966 str
[len
- 1] = '\0';
1967 regexp
= gen_regexp_sequence (str
+ 1);
1969 else if (strcmp (str
, NOTHING_NAME
) == 0)
1971 regexp
= create_node (sizeof (struct decl
));
1972 regexp
->mode
= rm_nothing
;
1976 regexp
= create_node (sizeof (struct decl
));
1977 regexp
->mode
= rm_unit
;
1978 REGEXP_UNIT (regexp
)->name
= str
;
1983 /* Parse construction `repeat' in STR. */
1985 gen_regexp_repeat (char *str
)
1993 repeat_vect
= get_str_vect (str
, &els_num
, '*', TRUE
);
1994 if (repeat_vect
== NULL
)
1995 fatal ("invalid `%s' in reservation `%s'", str
, reserv_str
);
1998 regexp
= gen_regexp_el (repeat_vect
[0]);
1999 for (i
= 1; i
< els_num
; i
++)
2001 repeat
= create_node (sizeof (struct regexp
));
2002 repeat
->mode
= rm_repeat
;
2003 REGEXP_REPEAT (repeat
)->regexp
= regexp
;
2004 REGEXP_REPEAT (repeat
)->repeat_num
= atoi (repeat_vect
[i
]);
2005 if (REGEXP_REPEAT (repeat
)->repeat_num
<= 1)
2006 fatal ("repetition `%s' <= 1 in reservation `%s'",
2013 return gen_regexp_el (str
);
2016 /* Parse reservation STR which possibly contains separator '+'. */
2018 gen_regexp_allof (char *str
)
2025 allof_vect
= get_str_vect (str
, &els_num
, '+', TRUE
);
2026 if (allof_vect
== NULL
)
2027 fatal ("invalid `%s' in reservation `%s'", str
, reserv_str
);
2030 allof
= create_node (sizeof (struct regexp
)
2031 + sizeof (regexp_t
) * (els_num
- 1));
2032 allof
->mode
= rm_allof
;
2033 REGEXP_ALLOF (allof
)->regexps_num
= els_num
;
2034 for (i
= 0; i
< els_num
; i
++)
2035 REGEXP_ALLOF (allof
)->regexps
[i
] = gen_regexp_repeat (allof_vect
[i
]);
2039 return gen_regexp_repeat (str
);
2042 /* Parse reservation STR which possibly contains separator '|'. */
2044 gen_regexp_oneof (char *str
)
2051 oneof_vect
= get_str_vect (str
, &els_num
, '|', TRUE
);
2052 if (oneof_vect
== NULL
)
2053 fatal ("invalid `%s' in reservation `%s'", str
, reserv_str
);
2056 oneof
= create_node (sizeof (struct regexp
)
2057 + sizeof (regexp_t
) * (els_num
- 1));
2058 oneof
->mode
= rm_oneof
;
2059 REGEXP_ONEOF (oneof
)->regexps_num
= els_num
;
2060 for (i
= 0; i
< els_num
; i
++)
2061 REGEXP_ONEOF (oneof
)->regexps
[i
] = gen_regexp_allof (oneof_vect
[i
]);
2065 return gen_regexp_allof (str
);
2068 /* Parse reservation STR which possibly contains separator ','. */
2070 gen_regexp_sequence (char *str
)
2073 char **sequence_vect
;
2077 sequence_vect
= get_str_vect (str
, &els_num
, ',', TRUE
);
2080 sequence
= create_node (sizeof (struct regexp
)
2081 + sizeof (regexp_t
) * (els_num
- 1));
2082 sequence
->mode
= rm_sequence
;
2083 REGEXP_SEQUENCE (sequence
)->regexps_num
= els_num
;
2084 for (i
= 0; i
< els_num
; i
++)
2085 REGEXP_SEQUENCE (sequence
)->regexps
[i
]
2086 = gen_regexp_oneof (sequence_vect
[i
]);
2090 return gen_regexp_oneof (str
);
2093 /* Parse construction reservation STR. */
2095 gen_regexp (char *str
)
2098 return gen_regexp_sequence (str
);;
2101 /* Process a DEFINE_RESERVATION.
2103 This gives information about a reservation of cpu units. We fill
2104 in a struct reserv_decl with information used later by
2105 `expand_automata'. */
2107 gen_reserv (rtx def
)
2111 decl
= create_node (sizeof (struct decl
));
2112 decl
->mode
= dm_reserv
;
2114 DECL_RESERV (decl
)->name
= check_name ((char *) XSTR (def
, 0), decl
->pos
);
2115 DECL_RESERV (decl
)->regexp
= gen_regexp ((char *) XSTR (def
, 1));
2116 VLA_PTR_ADD (decls
, decl
);
2120 /* Process a DEFINE_INSN_RESERVATION.
2122 This gives information about the reservation of cpu units by an
2123 insn. We fill a struct insn_reserv_decl with information used
2124 later by `expand_automata'. */
2126 gen_insn_reserv (rtx def
)
2130 decl
= create_node (sizeof (struct decl
));
2131 decl
->mode
= dm_insn_reserv
;
2133 DECL_INSN_RESERV (decl
)->name
2134 = check_name ((char *) XSTR (def
, 0), decl
->pos
);
2135 DECL_INSN_RESERV (decl
)->default_latency
= XINT (def
, 1);
2136 DECL_INSN_RESERV (decl
)->condexp
= XEXP (def
, 2);
2137 DECL_INSN_RESERV (decl
)->regexp
= gen_regexp ((char *) XSTR (def
, 3));
2138 VLA_PTR_ADD (decls
, decl
);
2144 /* The function evaluates hash value (0..UINT_MAX) of string. */
2146 string_hash (const char *string
)
2150 for (result
= i
= 0;*string
++ != '\0'; i
++)
2151 result
+= ((unsigned char) *string
<< (i
% CHAR_BIT
));
2157 /* This page contains abstract data `table of automaton declarations'.
2158 Elements of the table is nodes representing automaton declarations.
2159 Key of the table elements is name of given automaton. Remember
2160 that automaton names have own space. */
2162 /* The function evaluates hash value of an automaton declaration. The
2163 function is used by abstract data `hashtab'. The function returns
2164 hash value (0..UINT_MAX) of given automaton declaration. */
2166 automaton_decl_hash (const void *automaton_decl
)
2168 const decl_t decl
= (decl_t
) automaton_decl
;
2170 if (decl
->mode
== dm_automaton
&& DECL_AUTOMATON (decl
)->name
== NULL
)
2172 return string_hash (DECL_AUTOMATON (decl
)->name
);
2175 /* The function tests automaton declarations on equality of their
2176 keys. The function is used by abstract data `hashtab'. The
2177 function returns 1 if the declarations have the same key, 0
2180 automaton_decl_eq_p (const void* automaton_decl_1
,
2181 const void* automaton_decl_2
)
2183 const decl_t decl1
= (decl_t
) automaton_decl_1
;
2184 const decl_t decl2
= (decl_t
) automaton_decl_2
;
2186 if (decl1
->mode
!= dm_automaton
|| DECL_AUTOMATON (decl1
)->name
== NULL
2187 || decl2
->mode
!= dm_automaton
|| DECL_AUTOMATON (decl2
)->name
== NULL
)
2189 return strcmp (DECL_AUTOMATON (decl1
)->name
,
2190 DECL_AUTOMATON (decl2
)->name
) == 0;
2193 /* The automaton declaration table itself is represented by the
2194 following variable. */
2195 static htab_t automaton_decl_table
;
2197 /* The function inserts automaton declaration into the table. The
2198 function does nothing if an automaton declaration with the same key
2199 exists already in the table. The function returns automaton
2200 declaration node in the table with the same key as given automaton
2201 declaration node. */
2203 insert_automaton_decl (decl_t automaton_decl
)
2207 entry_ptr
= htab_find_slot (automaton_decl_table
, automaton_decl
, 1);
2208 if (*entry_ptr
== NULL
)
2209 *entry_ptr
= (void *) automaton_decl
;
2210 return (decl_t
) *entry_ptr
;
2213 /* The following variable value is node representing automaton
2214 declaration. The node used for searching automaton declaration
2216 static struct decl work_automaton_decl
;
2218 /* The function searches for automaton declaration in the table with
2219 the same key as node representing name of the automaton
2220 declaration. The function returns node found in the table, NULL if
2221 such node does not exist in the table. */
2223 find_automaton_decl (char *name
)
2227 work_automaton_decl
.mode
= dm_automaton
;
2228 DECL_AUTOMATON (&work_automaton_decl
)->name
= name
;
2229 entry
= htab_find (automaton_decl_table
, &work_automaton_decl
);
2230 return (decl_t
) entry
;
2233 /* The function creates empty automaton declaration table and node
2234 representing automaton declaration and used for searching automaton
2235 declaration with given name. The function must be called only once
2236 before any work with the automaton declaration table. */
2238 initiate_automaton_decl_table (void)
2240 work_automaton_decl
.mode
= dm_automaton
;
2241 automaton_decl_table
= htab_create (10, automaton_decl_hash
,
2242 automaton_decl_eq_p
, (htab_del
) 0);
2245 /* The function deletes the automaton declaration table. Only call of
2246 function `initiate_automaton_decl_table' is possible immediately
2247 after this function call. */
2249 finish_automaton_decl_table (void)
2251 htab_delete (automaton_decl_table
);
2256 /* This page contains abstract data `table of insn declarations'.
2257 Elements of the table is nodes representing insn declarations. Key
2258 of the table elements is name of given insn (in corresponding
2259 define_insn_reservation). Remember that insn names have own
2262 /* The function evaluates hash value of an insn declaration. The
2263 function is used by abstract data `hashtab'. The function returns
2264 hash value (0..UINT_MAX) of given insn declaration. */
2266 insn_decl_hash (const void *insn_decl
)
2268 const decl_t decl
= (decl_t
) insn_decl
;
2270 if (decl
->mode
!= dm_insn_reserv
|| DECL_INSN_RESERV (decl
)->name
== NULL
)
2272 return string_hash (DECL_INSN_RESERV (decl
)->name
);
2275 /* The function tests insn declarations on equality of their keys.
2276 The function is used by abstract data `hashtab'. The function
2277 returns 1 if declarations have the same key, 0 otherwise. */
2279 insn_decl_eq_p (const void *insn_decl_1
, const void *insn_decl_2
)
2281 const decl_t decl1
= (decl_t
) insn_decl_1
;
2282 const decl_t decl2
= (decl_t
) insn_decl_2
;
2284 if (decl1
->mode
!= dm_insn_reserv
|| DECL_INSN_RESERV (decl1
)->name
== NULL
2285 || decl2
->mode
!= dm_insn_reserv
2286 || DECL_INSN_RESERV (decl2
)->name
== NULL
)
2288 return strcmp (DECL_INSN_RESERV (decl1
)->name
,
2289 DECL_INSN_RESERV (decl2
)->name
) == 0;
2292 /* The insn declaration table itself is represented by the following
2293 variable. The table does not contain insn reservation
2295 static htab_t insn_decl_table
;
2297 /* The function inserts insn declaration into the table. The function
2298 does nothing if an insn declaration with the same key exists
2299 already in the table. The function returns insn declaration node
2300 in the table with the same key as given insn declaration node. */
2302 insert_insn_decl (decl_t insn_decl
)
2306 entry_ptr
= htab_find_slot (insn_decl_table
, insn_decl
, 1);
2307 if (*entry_ptr
== NULL
)
2308 *entry_ptr
= (void *) insn_decl
;
2309 return (decl_t
) *entry_ptr
;
2312 /* The following variable value is node representing insn reservation
2313 declaration. The node used for searching insn reservation
2314 declaration with given name. */
2315 static struct decl work_insn_decl
;
2317 /* The function searches for insn reservation declaration in the table
2318 with the same key as node representing name of the insn reservation
2319 declaration. The function returns node found in the table, NULL if
2320 such node does not exist in the table. */
2322 find_insn_decl (char *name
)
2326 work_insn_decl
.mode
= dm_insn_reserv
;
2327 DECL_INSN_RESERV (&work_insn_decl
)->name
= name
;
2328 entry
= htab_find (insn_decl_table
, &work_insn_decl
);
2329 return (decl_t
) entry
;
2332 /* The function creates empty insn declaration table and node
2333 representing insn declaration and used for searching insn
2334 declaration with given name. The function must be called only once
2335 before any work with the insn declaration table. */
2337 initiate_insn_decl_table (void)
2339 work_insn_decl
.mode
= dm_insn_reserv
;
2340 insn_decl_table
= htab_create (10, insn_decl_hash
, insn_decl_eq_p
,
2344 /* The function deletes the insn declaration table. Only call of
2345 function `initiate_insn_decl_table' is possible immediately after
2346 this function call. */
2348 finish_insn_decl_table (void)
2350 htab_delete (insn_decl_table
);
2355 /* This page contains abstract data `table of declarations'. Elements
2356 of the table is nodes representing declarations (of units and
2357 reservations). Key of the table elements is names of given
2360 /* The function evaluates hash value of a declaration. The function
2361 is used by abstract data `hashtab'. The function returns hash
2362 value (0..UINT_MAX) of given declaration. */
2364 decl_hash (const void *decl
)
2366 const decl_t d
= (const decl_t
) decl
;
2368 if ((d
->mode
!= dm_unit
|| DECL_UNIT (d
)->name
== NULL
)
2369 && (d
->mode
!= dm_reserv
|| DECL_RESERV (d
)->name
== NULL
))
2371 return string_hash (d
->mode
== dm_unit
2372 ? DECL_UNIT (d
)->name
: DECL_RESERV (d
)->name
);
2375 /* The function tests declarations on equality of their keys. The
2376 function is used by abstract data `hashtab'. The function
2377 returns 1 if the declarations have the same key, 0 otherwise. */
2379 decl_eq_p (const void *decl_1
, const void *decl_2
)
2381 const decl_t d1
= (const decl_t
) decl_1
;
2382 const decl_t d2
= (const decl_t
) decl_2
;
2384 if (((d1
->mode
!= dm_unit
|| DECL_UNIT (d1
)->name
== NULL
)
2385 && (d1
->mode
!= dm_reserv
|| DECL_RESERV (d1
)->name
== NULL
))
2386 || ((d2
->mode
!= dm_unit
|| DECL_UNIT (d2
)->name
== NULL
)
2387 && (d2
->mode
!= dm_reserv
|| DECL_RESERV (d2
)->name
== NULL
)))
2389 return strcmp ((d1
->mode
== dm_unit
2390 ? DECL_UNIT (d1
)->name
: DECL_RESERV (d1
)->name
),
2391 (d2
->mode
== dm_unit
2392 ? DECL_UNIT (d2
)->name
: DECL_RESERV (d2
)->name
)) == 0;
2395 /* The declaration table itself is represented by the following
2397 static htab_t decl_table
;
2399 /* The function inserts declaration into the table. The function does
2400 nothing if a declaration with the same key exists already in the
2401 table. The function returns declaration node in the table with the
2402 same key as given declaration node. */
2405 insert_decl (decl_t decl
)
2409 entry_ptr
= htab_find_slot (decl_table
, decl
, 1);
2410 if (*entry_ptr
== NULL
)
2411 *entry_ptr
= (void *) decl
;
2412 return (decl_t
) *entry_ptr
;
2415 /* The following variable value is node representing declaration. The
2416 node used for searching declaration with given name. */
2417 static struct decl work_decl
;
2419 /* The function searches for declaration in the table with the same
2420 key as node representing name of the declaration. The function
2421 returns node found in the table, NULL if such node does not exist
2424 find_decl (char *name
)
2428 work_decl
.mode
= dm_unit
;
2429 DECL_UNIT (&work_decl
)->name
= name
;
2430 entry
= htab_find (decl_table
, &work_decl
);
2431 return (decl_t
) entry
;
2434 /* The function creates empty declaration table and node representing
2435 declaration and used for searching declaration with given name.
2436 The function must be called only once before any work with the
2437 declaration table. */
2439 initiate_decl_table (void)
2441 work_decl
.mode
= dm_unit
;
2442 decl_table
= htab_create (10, decl_hash
, decl_eq_p
, (htab_del
) 0);
2445 /* The function deletes the declaration table. Only call of function
2446 `initiate_declaration_table' is possible immediately after this
2449 finish_decl_table (void)
2451 htab_delete (decl_table
);
2456 /* This page contains checker of pipeline hazard description. */
2458 /* Checking NAMES in an exclusion clause vector and returning formed
2459 unit_set_el_list. */
2460 static unit_set_el_t
2461 process_excls (char **names
, int num
, pos_t excl_pos ATTRIBUTE_UNUSED
)
2463 unit_set_el_t el_list
;
2464 unit_set_el_t last_el
;
2465 unit_set_el_t new_el
;
2466 decl_t decl_in_table
;
2471 for (i
= 0; i
< num
; i
++)
2473 decl_in_table
= find_decl (names
[i
]);
2474 if (decl_in_table
== NULL
)
2475 error ("unit `%s' in exclusion is not declared", names
[i
]);
2476 else if (decl_in_table
->mode
!= dm_unit
)
2477 error ("`%s' in exclusion is not unit", names
[i
]);
2480 new_el
= create_node (sizeof (struct unit_set_el
));
2481 new_el
->unit_decl
= DECL_UNIT (decl_in_table
);
2482 new_el
->next_unit_set_el
= NULL
;
2483 if (last_el
== NULL
)
2484 el_list
= last_el
= new_el
;
2487 last_el
->next_unit_set_el
= new_el
;
2488 last_el
= last_el
->next_unit_set_el
;
2495 /* The function adds each element from SOURCE_LIST to the exclusion
2496 list of the each element from DEST_LIST. Checking situation "unit
2497 excludes itself". */
2499 add_excls (unit_set_el_t dest_list
, unit_set_el_t source_list
,
2500 pos_t excl_pos ATTRIBUTE_UNUSED
)
2504 unit_set_el_t curr_el
;
2505 unit_set_el_t prev_el
;
2508 for (dst
= dest_list
; dst
!= NULL
; dst
= dst
->next_unit_set_el
)
2509 for (src
= source_list
; src
!= NULL
; src
= src
->next_unit_set_el
)
2511 if (dst
->unit_decl
== src
->unit_decl
)
2513 error ("unit `%s' excludes itself", src
->unit_decl
->name
);
2516 if (dst
->unit_decl
->automaton_name
!= NULL
2517 && src
->unit_decl
->automaton_name
!= NULL
2518 && strcmp (dst
->unit_decl
->automaton_name
,
2519 src
->unit_decl
->automaton_name
) != 0)
2521 error ("units `%s' and `%s' in exclusion set belong to different automata",
2522 src
->unit_decl
->name
, dst
->unit_decl
->name
);
2525 for (curr_el
= dst
->unit_decl
->excl_list
, prev_el
= NULL
;
2527 prev_el
= curr_el
, curr_el
= curr_el
->next_unit_set_el
)
2528 if (curr_el
->unit_decl
== src
->unit_decl
)
2530 if (curr_el
== NULL
)
2532 /* Element not found - insert. */
2533 copy
= copy_node (src
, sizeof (*src
));
2534 copy
->next_unit_set_el
= NULL
;
2535 if (prev_el
== NULL
)
2536 dst
->unit_decl
->excl_list
= copy
;
2538 prev_el
->next_unit_set_el
= copy
;
2543 /* Checking NAMES in presence/absence clause and returning the
2544 formed unit_set_el_list. The function is called only after
2545 processing all exclusion sets. */
2546 static unit_set_el_t
2547 process_presence_absence_names (char **names
, int num
,
2548 pos_t req_pos ATTRIBUTE_UNUSED
,
2549 int presence_p
, int final_p
)
2551 unit_set_el_t el_list
;
2552 unit_set_el_t last_el
;
2553 unit_set_el_t new_el
;
2554 decl_t decl_in_table
;
2559 for (i
= 0; i
< num
; i
++)
2561 decl_in_table
= find_decl (names
[i
]);
2562 if (decl_in_table
== NULL
)
2565 ? "unit `%s' in final presence set is not declared"
2566 : "unit `%s' in presence set is not declared")
2568 ? "unit `%s' in final absence set is not declared"
2569 : "unit `%s' in absence set is not declared")), names
[i
]);
2570 else if (decl_in_table
->mode
!= dm_unit
)
2573 ? "`%s' in final presence set is not unit"
2574 : "`%s' in presence set is not unit")
2576 ? "`%s' in final absence set is not unit"
2577 : "`%s' in absence set is not unit")), names
[i
]);
2580 new_el
= create_node (sizeof (struct unit_set_el
));
2581 new_el
->unit_decl
= DECL_UNIT (decl_in_table
);
2582 new_el
->next_unit_set_el
= NULL
;
2583 if (last_el
== NULL
)
2584 el_list
= last_el
= new_el
;
2587 last_el
->next_unit_set_el
= new_el
;
2588 last_el
= last_el
->next_unit_set_el
;
2595 /* Checking NAMES in patterns of a presence/absence clause and
2596 returning the formed pattern_set_el_list. The function is called
2597 only after processing all exclusion sets. */
2598 static pattern_set_el_t
2599 process_presence_absence_patterns (char ***patterns
, int num
,
2600 pos_t req_pos ATTRIBUTE_UNUSED
,
2601 int presence_p
, int final_p
)
2603 pattern_set_el_t el_list
;
2604 pattern_set_el_t last_el
;
2605 pattern_set_el_t new_el
;
2606 decl_t decl_in_table
;
2611 for (i
= 0; i
< num
; i
++)
2613 for (j
= 0; patterns
[i
] [j
] != NULL
; j
++)
2615 new_el
= create_node (sizeof (struct pattern_set_el
)
2616 + sizeof (struct unit_decl
*) * j
);
2618 = (struct unit_decl
**) ((char *) new_el
2619 + sizeof (struct pattern_set_el
));
2620 new_el
->next_pattern_set_el
= NULL
;
2621 if (last_el
== NULL
)
2622 el_list
= last_el
= new_el
;
2625 last_el
->next_pattern_set_el
= new_el
;
2626 last_el
= last_el
->next_pattern_set_el
;
2628 new_el
->units_num
= 0;
2629 for (j
= 0; patterns
[i
] [j
] != NULL
; j
++)
2631 decl_in_table
= find_decl (patterns
[i
] [j
]);
2632 if (decl_in_table
== NULL
)
2635 ? "unit `%s' in final presence set is not declared"
2636 : "unit `%s' in presence set is not declared")
2638 ? "unit `%s' in final absence set is not declared"
2639 : "unit `%s' in absence set is not declared")),
2641 else if (decl_in_table
->mode
!= dm_unit
)
2644 ? "`%s' in final presence set is not unit"
2645 : "`%s' in presence set is not unit")
2647 ? "`%s' in final absence set is not unit"
2648 : "`%s' in absence set is not unit")),
2652 new_el
->unit_decls
[new_el
->units_num
]
2653 = DECL_UNIT (decl_in_table
);
2654 new_el
->units_num
++;
2661 /* The function adds each element from PATTERN_LIST to presence (if
2662 PRESENCE_P) or absence list of the each element from DEST_LIST.
2663 Checking situations "unit requires own absence", and "unit excludes
2664 and requires presence of ...", "unit requires absence and presence
2665 of ...", "units in (final) presence set belong to different
2666 automata", and "units in (final) absence set belong to different
2667 automata". Remember that we process absence sets only after all
2670 add_presence_absence (unit_set_el_t dest_list
,
2671 pattern_set_el_t pattern_list
,
2672 pos_t req_pos ATTRIBUTE_UNUSED
,
2673 int presence_p
, int final_p
)
2676 pattern_set_el_t pat
;
2677 struct unit_decl
*unit
;
2678 unit_set_el_t curr_excl_el
;
2679 pattern_set_el_t curr_pat_el
;
2680 pattern_set_el_t prev_el
;
2681 pattern_set_el_t copy
;
2685 for (dst
= dest_list
; dst
!= NULL
; dst
= dst
->next_unit_set_el
)
2686 for (pat
= pattern_list
; pat
!= NULL
; pat
= pat
->next_pattern_set_el
)
2688 for (i
= 0; i
< pat
->units_num
; i
++)
2690 unit
= pat
->unit_decls
[i
];
2691 if (dst
->unit_decl
== unit
&& pat
->units_num
== 1 && !presence_p
)
2693 error ("unit `%s' requires own absence", unit
->name
);
2696 if (dst
->unit_decl
->automaton_name
!= NULL
2697 && unit
->automaton_name
!= NULL
2698 && strcmp (dst
->unit_decl
->automaton_name
,
2699 unit
->automaton_name
) != 0)
2703 ? "units `%s' and `%s' in final presence set belong to different automata"
2704 : "units `%s' and `%s' in presence set belong to different automata")
2706 ? "units `%s' and `%s' in final absence set belong to different automata"
2707 : "units `%s' and `%s' in absence set belong to different automata")),
2708 unit
->name
, dst
->unit_decl
->name
);
2713 for (curr_excl_el
= dst
->unit_decl
->excl_list
;
2714 curr_excl_el
!= NULL
;
2715 curr_excl_el
= curr_excl_el
->next_unit_set_el
)
2717 if (unit
== curr_excl_el
->unit_decl
&& pat
->units_num
== 1)
2721 error ("unit `%s' excludes and requires presence of `%s'",
2722 dst
->unit_decl
->name
, unit
->name
);
2727 ("unit `%s' excludes and requires presence of `%s'",
2728 dst
->unit_decl
->name
, unit
->name
);
2731 else if (pat
->units_num
== 1)
2732 for (curr_pat_el
= dst
->unit_decl
->presence_list
;
2733 curr_pat_el
!= NULL
;
2734 curr_pat_el
= curr_pat_el
->next_pattern_set_el
)
2735 if (curr_pat_el
->units_num
== 1
2736 && unit
== curr_pat_el
->unit_decls
[0])
2741 ("unit `%s' requires absence and presence of `%s'",
2742 dst
->unit_decl
->name
, unit
->name
);
2747 ("unit `%s' requires absence and presence of `%s'",
2748 dst
->unit_decl
->name
, unit
->name
);
2752 for (prev_el
= (presence_p
2754 ? dst
->unit_decl
->final_presence_list
2755 : dst
->unit_decl
->final_presence_list
)
2757 ? dst
->unit_decl
->final_absence_list
2758 : dst
->unit_decl
->absence_list
));
2759 prev_el
!= NULL
&& prev_el
->next_pattern_set_el
!= NULL
;
2760 prev_el
= prev_el
->next_pattern_set_el
)
2762 copy
= copy_node (pat
, sizeof (*pat
));
2763 copy
->next_pattern_set_el
= NULL
;
2764 if (prev_el
== NULL
)
2769 dst
->unit_decl
->final_presence_list
= copy
;
2771 dst
->unit_decl
->presence_list
= copy
;
2774 dst
->unit_decl
->final_absence_list
= copy
;
2776 dst
->unit_decl
->absence_list
= copy
;
2779 prev_el
->next_pattern_set_el
= copy
;
2786 /* The function searches for bypass with given IN_INSN_RESERV in given
2788 static struct bypass_decl
*
2789 find_bypass (struct bypass_decl
*bypass_list
,
2790 struct insn_reserv_decl
*in_insn_reserv
)
2792 struct bypass_decl
*bypass
;
2794 for (bypass
= bypass_list
; bypass
!= NULL
; bypass
= bypass
->next
)
2795 if (bypass
->in_insn_reserv
== in_insn_reserv
)
2800 /* The function processes pipeline description declarations, checks
2801 their correctness, and forms exclusion/presence/absence sets. */
2803 process_decls (void)
2806 decl_t automaton_decl
;
2807 decl_t decl_in_table
;
2808 decl_t out_insn_reserv
;
2809 decl_t in_insn_reserv
;
2810 struct bypass_decl
*bypass
;
2811 int automaton_presence
;
2814 /* Checking repeated automata declarations. */
2815 automaton_presence
= 0;
2816 for (i
= 0; i
< description
->decls_num
; i
++)
2818 decl
= description
->decls
[i
];
2819 if (decl
->mode
== dm_automaton
)
2821 automaton_presence
= 1;
2822 decl_in_table
= insert_automaton_decl (decl
);
2823 if (decl_in_table
!= decl
)
2826 error ("repeated declaration of automaton `%s'",
2827 DECL_AUTOMATON (decl
)->name
);
2829 warning ("repeated declaration of automaton `%s'",
2830 DECL_AUTOMATON (decl
)->name
);
2834 /* Checking undeclared automata, repeated declarations (except for
2835 automata) and correctness of their attributes (insn latency times
2837 for (i
= 0; i
< description
->decls_num
; i
++)
2839 decl
= description
->decls
[i
];
2840 if (decl
->mode
== dm_insn_reserv
)
2842 DECL_INSN_RESERV (decl
)->condexp
2843 = check_attr_test (DECL_INSN_RESERV (decl
)->condexp
, 0, 0);
2844 if (DECL_INSN_RESERV (decl
)->default_latency
< 0)
2845 error ("define_insn_reservation `%s' has negative latency time",
2846 DECL_INSN_RESERV (decl
)->name
);
2847 DECL_INSN_RESERV (decl
)->insn_num
= description
->insns_num
;
2848 description
->insns_num
++;
2849 decl_in_table
= insert_insn_decl (decl
);
2850 if (decl_in_table
!= decl
)
2851 error ("`%s' is already used as insn reservation name",
2852 DECL_INSN_RESERV (decl
)->name
);
2854 else if (decl
->mode
== dm_bypass
)
2856 if (DECL_BYPASS (decl
)->latency
< 0)
2857 error ("define_bypass `%s - %s' has negative latency time",
2858 DECL_BYPASS (decl
)->out_insn_name
,
2859 DECL_BYPASS (decl
)->in_insn_name
);
2861 else if (decl
->mode
== dm_unit
|| decl
->mode
== dm_reserv
)
2863 if (decl
->mode
== dm_unit
)
2865 DECL_UNIT (decl
)->automaton_decl
= NULL
;
2866 if (DECL_UNIT (decl
)->automaton_name
!= NULL
)
2869 = find_automaton_decl (DECL_UNIT (decl
)->automaton_name
);
2870 if (automaton_decl
== NULL
)
2871 error ("automaton `%s' is not declared",
2872 DECL_UNIT (decl
)->automaton_name
);
2875 DECL_AUTOMATON (automaton_decl
)->automaton_is_used
= 1;
2876 DECL_UNIT (decl
)->automaton_decl
2877 = DECL_AUTOMATON (automaton_decl
);
2880 else if (automaton_presence
)
2881 error ("define_unit `%s' without automaton when one defined",
2882 DECL_UNIT (decl
)->name
);
2883 DECL_UNIT (decl
)->unit_num
= description
->units_num
;
2884 description
->units_num
++;
2885 if (strcmp (DECL_UNIT (decl
)->name
, NOTHING_NAME
) == 0)
2887 error ("`%s' is declared as cpu unit", NOTHING_NAME
);
2890 decl_in_table
= find_decl (DECL_UNIT (decl
)->name
);
2894 if (strcmp (DECL_RESERV (decl
)->name
, NOTHING_NAME
) == 0)
2896 error ("`%s' is declared as cpu reservation", NOTHING_NAME
);
2899 decl_in_table
= find_decl (DECL_RESERV (decl
)->name
);
2901 if (decl_in_table
== NULL
)
2902 decl_in_table
= insert_decl (decl
);
2905 if (decl
->mode
== dm_unit
)
2906 error ("repeated declaration of unit `%s'",
2907 DECL_UNIT (decl
)->name
);
2909 error ("repeated declaration of reservation `%s'",
2910 DECL_RESERV (decl
)->name
);
2914 /* Check bypasses and form list of bypasses for each (output)
2916 for (i
= 0; i
< description
->decls_num
; i
++)
2918 decl
= description
->decls
[i
];
2919 if (decl
->mode
== dm_bypass
)
2921 out_insn_reserv
= find_insn_decl (DECL_BYPASS (decl
)->out_insn_name
);
2922 in_insn_reserv
= find_insn_decl (DECL_BYPASS (decl
)->in_insn_name
);
2923 if (out_insn_reserv
== NULL
)
2924 error ("there is no insn reservation `%s'",
2925 DECL_BYPASS (decl
)->out_insn_name
);
2926 else if (in_insn_reserv
== NULL
)
2927 error ("there is no insn reservation `%s'",
2928 DECL_BYPASS (decl
)->in_insn_name
);
2931 DECL_BYPASS (decl
)->out_insn_reserv
2932 = DECL_INSN_RESERV (out_insn_reserv
);
2933 DECL_BYPASS (decl
)->in_insn_reserv
2934 = DECL_INSN_RESERV (in_insn_reserv
);
2936 = find_bypass (DECL_INSN_RESERV (out_insn_reserv
)->bypass_list
,
2937 DECL_BYPASS (decl
)->in_insn_reserv
);
2940 if (DECL_BYPASS (decl
)->latency
== bypass
->latency
)
2944 ("the same bypass `%s - %s' is already defined",
2945 DECL_BYPASS (decl
)->out_insn_name
,
2946 DECL_BYPASS (decl
)->in_insn_name
);
2949 ("the same bypass `%s - %s' is already defined",
2950 DECL_BYPASS (decl
)->out_insn_name
,
2951 DECL_BYPASS (decl
)->in_insn_name
);
2954 error ("bypass `%s - %s' is already defined",
2955 DECL_BYPASS (decl
)->out_insn_name
,
2956 DECL_BYPASS (decl
)->in_insn_name
);
2960 DECL_BYPASS (decl
)->next
2961 = DECL_INSN_RESERV (out_insn_reserv
)->bypass_list
;
2962 DECL_INSN_RESERV (out_insn_reserv
)->bypass_list
2963 = DECL_BYPASS (decl
);
2969 /* Check exclusion set declarations and form exclusion sets. */
2970 for (i
= 0; i
< description
->decls_num
; i
++)
2972 decl
= description
->decls
[i
];
2973 if (decl
->mode
== dm_excl
)
2975 unit_set_el_t unit_set_el_list
;
2976 unit_set_el_t unit_set_el_list_2
;
2979 = process_excls (DECL_EXCL (decl
)->names
,
2980 DECL_EXCL (decl
)->first_list_length
, decl
->pos
);
2982 = process_excls (&DECL_EXCL (decl
)->names
2983 [DECL_EXCL (decl
)->first_list_length
],
2984 DECL_EXCL (decl
)->all_names_num
2985 - DECL_EXCL (decl
)->first_list_length
,
2987 add_excls (unit_set_el_list
, unit_set_el_list_2
, decl
->pos
);
2988 add_excls (unit_set_el_list_2
, unit_set_el_list
, decl
->pos
);
2992 /* Check presence set declarations and form presence sets. */
2993 for (i
= 0; i
< description
->decls_num
; i
++)
2995 decl
= description
->decls
[i
];
2996 if (decl
->mode
== dm_presence
)
2998 unit_set_el_t unit_set_el_list
;
2999 pattern_set_el_t pattern_set_el_list
;
3002 = process_presence_absence_names
3003 (DECL_PRESENCE (decl
)->names
, DECL_PRESENCE (decl
)->names_num
,
3004 decl
->pos
, TRUE
, DECL_PRESENCE (decl
)->final_p
);
3006 = process_presence_absence_patterns
3007 (DECL_PRESENCE (decl
)->patterns
,
3008 DECL_PRESENCE (decl
)->patterns_num
,
3009 decl
->pos
, TRUE
, DECL_PRESENCE (decl
)->final_p
);
3010 add_presence_absence (unit_set_el_list
, pattern_set_el_list
,
3012 DECL_PRESENCE (decl
)->final_p
);
3016 /* Check absence set declarations and form absence sets. */
3017 for (i
= 0; i
< description
->decls_num
; i
++)
3019 decl
= description
->decls
[i
];
3020 if (decl
->mode
== dm_absence
)
3022 unit_set_el_t unit_set_el_list
;
3023 pattern_set_el_t pattern_set_el_list
;
3026 = process_presence_absence_names
3027 (DECL_ABSENCE (decl
)->names
, DECL_ABSENCE (decl
)->names_num
,
3028 decl
->pos
, FALSE
, DECL_ABSENCE (decl
)->final_p
);
3030 = process_presence_absence_patterns
3031 (DECL_ABSENCE (decl
)->patterns
,
3032 DECL_ABSENCE (decl
)->patterns_num
,
3033 decl
->pos
, FALSE
, DECL_ABSENCE (decl
)->final_p
);
3034 add_presence_absence (unit_set_el_list
, pattern_set_el_list
,
3036 DECL_ABSENCE (decl
)->final_p
);
3041 /* The following function checks that declared automaton is used. If
3042 the automaton is not used, the function fixes error/warning. The
3043 following function must be called only after `process_decls'. */
3045 check_automaton_usage (void)
3050 for (i
= 0; i
< description
->decls_num
; i
++)
3052 decl
= description
->decls
[i
];
3053 if (decl
->mode
== dm_automaton
3054 && !DECL_AUTOMATON (decl
)->automaton_is_used
)
3057 error ("automaton `%s' is not used", DECL_AUTOMATON (decl
)->name
);
3059 warning ("automaton `%s' is not used",
3060 DECL_AUTOMATON (decl
)->name
);
3065 /* The following recursive function processes all regexp in order to
3066 fix usage of units or reservations and to fix errors of undeclared
3067 name. The function may change unit_regexp onto reserv_regexp.
3068 Remember that reserv_regexp does not exist before the function
3071 process_regexp (regexp_t regexp
)
3073 decl_t decl_in_table
;
3074 regexp_t new_regexp
;
3077 if (regexp
->mode
== rm_unit
)
3079 decl_in_table
= find_decl (REGEXP_UNIT (regexp
)->name
);
3080 if (decl_in_table
== NULL
)
3081 error ("undeclared unit or reservation `%s'",
3082 REGEXP_UNIT (regexp
)->name
);
3083 else if (decl_in_table
->mode
== dm_unit
)
3085 DECL_UNIT (decl_in_table
)->unit_is_used
= 1;
3086 REGEXP_UNIT (regexp
)->unit_decl
= DECL_UNIT (decl_in_table
);
3088 else if (decl_in_table
->mode
== dm_reserv
)
3090 DECL_RESERV (decl_in_table
)->reserv_is_used
= 1;
3091 new_regexp
= create_node (sizeof (struct regexp
));
3092 new_regexp
->mode
= rm_reserv
;
3093 new_regexp
->pos
= regexp
->pos
;
3094 REGEXP_RESERV (new_regexp
)->name
= REGEXP_UNIT (regexp
)->name
;
3095 REGEXP_RESERV (new_regexp
)->reserv_decl
3096 = DECL_RESERV (decl_in_table
);
3097 regexp
= new_regexp
;
3102 else if (regexp
->mode
== rm_sequence
)
3103 for (i
= 0; i
<REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
3104 REGEXP_SEQUENCE (regexp
)->regexps
[i
]
3105 = process_regexp (REGEXP_SEQUENCE (regexp
)->regexps
[i
]);
3106 else if (regexp
->mode
== rm_allof
)
3107 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
3108 REGEXP_ALLOF (regexp
)->regexps
[i
]
3109 = process_regexp (REGEXP_ALLOF (regexp
)->regexps
[i
]);
3110 else if (regexp
->mode
== rm_oneof
)
3111 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
3112 REGEXP_ONEOF (regexp
)->regexps
[i
]
3113 = process_regexp (REGEXP_ONEOF (regexp
)->regexps
[i
]);
3114 else if (regexp
->mode
== rm_repeat
)
3115 REGEXP_REPEAT (regexp
)->regexp
3116 = process_regexp (REGEXP_REPEAT (regexp
)->regexp
);
3117 else if (regexp
->mode
!= rm_nothing
)
3122 /* The following function processes regexp of define_reservation and
3123 define_insn_reservation with the aid of function
3124 `process_regexp'. */
3126 process_regexp_decls (void)
3131 for (i
= 0; i
< description
->decls_num
; i
++)
3133 decl
= description
->decls
[i
];
3134 if (decl
->mode
== dm_reserv
)
3135 DECL_RESERV (decl
)->regexp
3136 = process_regexp (DECL_RESERV (decl
)->regexp
);
3137 else if (decl
->mode
== dm_insn_reserv
)
3138 DECL_INSN_RESERV (decl
)->regexp
3139 = process_regexp (DECL_INSN_RESERV (decl
)->regexp
);
3143 /* The following function checks that declared unit is used. If the
3144 unit is not used, the function fixes errors/warnings. The
3145 following function must be called only after `process_decls',
3146 `process_regexp_decls'. */
3153 for (i
= 0; i
< description
->decls_num
; i
++)
3155 decl
= description
->decls
[i
];
3156 if (decl
->mode
== dm_unit
&& !DECL_UNIT (decl
)->unit_is_used
)
3159 error ("unit `%s' is not used", DECL_UNIT (decl
)->name
);
3161 warning ("unit `%s' is not used", DECL_UNIT (decl
)->name
);
3163 else if (decl
->mode
== dm_reserv
&& !DECL_RESERV (decl
)->reserv_is_used
)
3166 error ("reservation `%s' is not used", DECL_RESERV (decl
)->name
);
3168 warning ("reservation `%s' is not used", DECL_RESERV (decl
)->name
);
3173 /* The following variable value is number of reservation being
3174 processed on loop recognition. */
3175 static int curr_loop_pass_num
;
3177 /* The following recursive function returns nonzero value if REGEXP
3178 contains given decl or reservations in given regexp refers for
3181 loop_in_regexp (regexp_t regexp
, decl_t start_decl
)
3187 if (regexp
->mode
== rm_unit
)
3189 else if (regexp
->mode
== rm_reserv
)
3191 if (start_decl
->mode
== dm_reserv
3192 && REGEXP_RESERV (regexp
)->reserv_decl
== DECL_RESERV (start_decl
))
3194 else if (REGEXP_RESERV (regexp
)->reserv_decl
->loop_pass_num
3195 == curr_loop_pass_num
)
3196 /* declaration has been processed. */
3200 REGEXP_RESERV (regexp
)->reserv_decl
->loop_pass_num
3201 = curr_loop_pass_num
;
3202 return loop_in_regexp (REGEXP_RESERV (regexp
)->reserv_decl
->regexp
,
3206 else if (regexp
->mode
== rm_sequence
)
3208 for (i
= 0; i
<REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
3209 if (loop_in_regexp (REGEXP_SEQUENCE (regexp
)->regexps
[i
], start_decl
))
3213 else if (regexp
->mode
== rm_allof
)
3215 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
3216 if (loop_in_regexp (REGEXP_ALLOF (regexp
)->regexps
[i
], start_decl
))
3220 else if (regexp
->mode
== rm_oneof
)
3222 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
3223 if (loop_in_regexp (REGEXP_ONEOF (regexp
)->regexps
[i
], start_decl
))
3227 else if (regexp
->mode
== rm_repeat
)
3228 return loop_in_regexp (REGEXP_REPEAT (regexp
)->regexp
, start_decl
);
3231 if (regexp
->mode
!= rm_nothing
)
3237 /* The following function fixes errors "cycle in definition ...". The
3238 function uses function `loop_in_regexp' for that. */
3240 check_loops_in_regexps (void)
3245 for (i
= 0; i
< description
->decls_num
; i
++)
3247 decl
= description
->decls
[i
];
3248 if (decl
->mode
== dm_reserv
)
3249 DECL_RESERV (decl
)->loop_pass_num
= 0;
3251 for (i
= 0; i
< description
->decls_num
; i
++)
3253 decl
= description
->decls
[i
];
3254 curr_loop_pass_num
= i
;
3256 if (decl
->mode
== dm_reserv
)
3258 DECL_RESERV (decl
)->loop_pass_num
= curr_loop_pass_num
;
3259 if (loop_in_regexp (DECL_RESERV (decl
)->regexp
, decl
))
3261 if (DECL_RESERV (decl
)->regexp
== NULL
)
3263 error ("cycle in definition of reservation `%s'",
3264 DECL_RESERV (decl
)->name
);
3270 /* The function recursively processes IR of reservation and defines
3271 max and min cycle for reservation of unit. */
3273 process_regexp_cycles (regexp_t regexp
, int max_start_cycle
,
3274 int min_start_cycle
, int *max_finish_cycle
,
3275 int *min_finish_cycle
)
3279 if (regexp
->mode
== rm_unit
)
3281 if (REGEXP_UNIT (regexp
)->unit_decl
->max_occ_cycle_num
< max_start_cycle
)
3282 REGEXP_UNIT (regexp
)->unit_decl
->max_occ_cycle_num
= max_start_cycle
;
3283 if (REGEXP_UNIT (regexp
)->unit_decl
->min_occ_cycle_num
> min_start_cycle
3284 || REGEXP_UNIT (regexp
)->unit_decl
->min_occ_cycle_num
== -1)
3285 REGEXP_UNIT (regexp
)->unit_decl
->min_occ_cycle_num
= min_start_cycle
;
3286 *max_finish_cycle
= max_start_cycle
;
3287 *min_finish_cycle
= min_start_cycle
;
3289 else if (regexp
->mode
== rm_reserv
)
3290 process_regexp_cycles (REGEXP_RESERV (regexp
)->reserv_decl
->regexp
,
3291 max_start_cycle
, min_start_cycle
,
3292 max_finish_cycle
, min_finish_cycle
);
3293 else if (regexp
->mode
== rm_repeat
)
3295 for (i
= 0; i
< REGEXP_REPEAT (regexp
)->repeat_num
; i
++)
3297 process_regexp_cycles (REGEXP_REPEAT (regexp
)->regexp
,
3298 max_start_cycle
, min_start_cycle
,
3299 max_finish_cycle
, min_finish_cycle
);
3300 max_start_cycle
= *max_finish_cycle
+ 1;
3301 min_start_cycle
= *min_finish_cycle
+ 1;
3304 else if (regexp
->mode
== rm_sequence
)
3306 for (i
= 0; i
<REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
3308 process_regexp_cycles (REGEXP_SEQUENCE (regexp
)->regexps
[i
],
3309 max_start_cycle
, min_start_cycle
,
3310 max_finish_cycle
, min_finish_cycle
);
3311 max_start_cycle
= *max_finish_cycle
+ 1;
3312 min_start_cycle
= *min_finish_cycle
+ 1;
3315 else if (regexp
->mode
== rm_allof
)
3320 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
3322 process_regexp_cycles (REGEXP_ALLOF (regexp
)->regexps
[i
],
3323 max_start_cycle
, min_start_cycle
,
3324 max_finish_cycle
, min_finish_cycle
);
3325 if (max_cycle
< *max_finish_cycle
)
3326 max_cycle
= *max_finish_cycle
;
3327 if (i
== 0 || min_cycle
> *min_finish_cycle
)
3328 min_cycle
= *min_finish_cycle
;
3330 *max_finish_cycle
= max_cycle
;
3331 *min_finish_cycle
= min_cycle
;
3333 else if (regexp
->mode
== rm_oneof
)
3338 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
3340 process_regexp_cycles (REGEXP_ONEOF (regexp
)->regexps
[i
],
3341 max_start_cycle
, min_start_cycle
,
3342 max_finish_cycle
, min_finish_cycle
);
3343 if (max_cycle
< *max_finish_cycle
)
3344 max_cycle
= *max_finish_cycle
;
3345 if (i
== 0 || min_cycle
> *min_finish_cycle
)
3346 min_cycle
= *min_finish_cycle
;
3348 *max_finish_cycle
= max_cycle
;
3349 *min_finish_cycle
= min_cycle
;
3353 if (regexp
->mode
!= rm_nothing
)
3355 *max_finish_cycle
= max_start_cycle
;
3356 *min_finish_cycle
= min_start_cycle
;
3360 /* The following function is called only for correct program. The
3361 function defines max reservation of insns in cycles. */
3363 evaluate_max_reserv_cycles (void)
3365 int max_insn_cycles_num
;
3366 int min_insn_cycles_num
;
3370 description
->max_insn_reserv_cycles
= 0;
3371 for (i
= 0; i
< description
->decls_num
; i
++)
3373 decl
= description
->decls
[i
];
3374 if (decl
->mode
== dm_insn_reserv
)
3376 process_regexp_cycles (DECL_INSN_RESERV (decl
)->regexp
, 0, 0,
3377 &max_insn_cycles_num
, &min_insn_cycles_num
);
3378 if (description
->max_insn_reserv_cycles
< max_insn_cycles_num
)
3379 description
->max_insn_reserv_cycles
= max_insn_cycles_num
;
3382 description
->max_insn_reserv_cycles
++;
3385 /* The following function calls functions for checking all
3388 check_all_description (void)
3391 check_automaton_usage ();
3392 process_regexp_decls ();
3394 check_loops_in_regexps ();
3396 evaluate_max_reserv_cycles ();
3401 /* The page contains abstract data `ticker'. This data is used to
3402 report time of different phases of building automata. It is
3403 possibly to write a description for which automata will be built
3404 during several minutes even on fast machine. */
3406 /* The following function creates ticker and makes it active. */
3408 create_ticker (void)
3412 ticker
.modified_creation_time
= get_run_time ();
3413 ticker
.incremented_off_time
= 0;
3417 /* The following function switches off given ticker. */
3419 ticker_off (ticker_t
*ticker
)
3421 if (ticker
->incremented_off_time
== 0)
3422 ticker
->incremented_off_time
= get_run_time () + 1;
3425 /* The following function switches on given ticker. */
3427 ticker_on (ticker_t
*ticker
)
3429 if (ticker
->incremented_off_time
!= 0)
3431 ticker
->modified_creation_time
3432 += get_run_time () - ticker
->incremented_off_time
+ 1;
3433 ticker
->incremented_off_time
= 0;
3437 /* The following function returns current time in milliseconds since
3438 the moment when given ticker was created. */
3440 active_time (ticker_t ticker
)
3442 if (ticker
.incremented_off_time
!= 0)
3443 return ticker
.incremented_off_time
- 1 - ticker
.modified_creation_time
;
3445 return get_run_time () - ticker
.modified_creation_time
;
3448 /* The following function returns string representation of active time
3449 of given ticker. The result is string representation of seconds
3450 with accuracy of 1/100 second. Only result of the last call of the
3451 function exists. Therefore the following code is not correct
3453 printf ("parser time: %s\ngeneration time: %s\n",
3454 active_time_string (parser_ticker),
3455 active_time_string (generation_ticker));
3457 Correct code has to be the following
3459 printf ("parser time: %s\n", active_time_string (parser_ticker));
3460 printf ("generation time: %s\n",
3461 active_time_string (generation_ticker));
3465 print_active_time (FILE *f
, ticker_t ticker
)
3469 msecs
= active_time (ticker
);
3470 fprintf (f
, "%d.%06d", msecs
/ 1000000, msecs
% 1000000);
3475 /* The following variable value is number of automaton which are
3476 really being created. This value is defined on the base of
3477 argument of option `-split'. If the variable has zero value the
3478 number of automata is defined by the constructions `%automaton'.
3479 This case occurs when option `-split' is absent or has zero
3480 argument. If constructions `define_automaton' is absent only one
3481 automaton is created. */
3482 static int automata_num
;
3484 /* The following variable values are times of
3485 o transformation of regular expressions
3486 o building NDFA (DFA if !ndfa_flag)
3487 o NDFA -> DFA (simply the same automaton if !ndfa_flag)
3489 o building insn equivalence classes
3492 static ticker_t transform_time
;
3493 static ticker_t NDFA_time
;
3494 static ticker_t NDFA_to_DFA_time
;
3495 static ticker_t minimize_time
;
3496 static ticker_t equiv_time
;
3497 static ticker_t automaton_generation_time
;
3498 static ticker_t output_time
;
3500 /* The following variable values are times of
3503 all pipeline hazard translator work */
3504 static ticker_t check_time
;
3505 static ticker_t generation_time
;
3506 static ticker_t all_time
;
3510 /* Pseudo insn decl which denotes advancing cycle. */
3511 static decl_t advance_cycle_insn_decl
;
3513 add_advance_cycle_insn_decl (void)
3515 advance_cycle_insn_decl
= create_node (sizeof (struct decl
));
3516 advance_cycle_insn_decl
->mode
= dm_insn_reserv
;
3517 advance_cycle_insn_decl
->pos
= no_pos
;
3518 DECL_INSN_RESERV (advance_cycle_insn_decl
)->regexp
= NULL
;
3519 DECL_INSN_RESERV (advance_cycle_insn_decl
)->name
= (char *) "$advance_cycle";
3520 DECL_INSN_RESERV (advance_cycle_insn_decl
)->insn_num
3521 = description
->insns_num
;
3522 description
->decls
[description
->decls_num
] = advance_cycle_insn_decl
;
3523 description
->decls_num
++;
3524 description
->insns_num
++;
3529 /* Abstract data `alternative states' which represents
3530 nondeterministic nature of the description (see comments for
3531 structures alt_state and state). */
3533 /* List of free states. */
3534 static alt_state_t first_free_alt_state
;
3537 /* The following variables is maximal number of allocated nodes
3539 static int allocated_alt_states_num
= 0;
3542 /* The following function returns free node alt_state. It may be new
3543 allocated node or node freed earlier. */
3545 get_free_alt_state (void)
3549 if (first_free_alt_state
!= NULL
)
3551 result
= first_free_alt_state
;
3552 first_free_alt_state
= first_free_alt_state
->next_alt_state
;
3557 allocated_alt_states_num
++;
3559 result
= create_node (sizeof (struct alt_state
));
3561 result
->state
= NULL
;
3562 result
->next_alt_state
= NULL
;
3563 result
->next_sorted_alt_state
= NULL
;
3567 /* The function frees node ALT_STATE. */
3569 free_alt_state (alt_state_t alt_state
)
3571 if (alt_state
== NULL
)
3573 alt_state
->next_alt_state
= first_free_alt_state
;
3574 first_free_alt_state
= alt_state
;
3577 /* The function frees list started with node ALT_STATE_LIST. */
3579 free_alt_states (alt_state_t alt_states_list
)
3581 alt_state_t curr_alt_state
;
3582 alt_state_t next_alt_state
;
3584 for (curr_alt_state
= alt_states_list
;
3585 curr_alt_state
!= NULL
;
3586 curr_alt_state
= next_alt_state
)
3588 next_alt_state
= curr_alt_state
->next_alt_state
;
3589 free_alt_state (curr_alt_state
);
3593 /* The function compares unique numbers of alt states. */
3595 alt_state_cmp (const void *alt_state_ptr_1
, const void *alt_state_ptr_2
)
3597 if ((*(alt_state_t
*) alt_state_ptr_1
)->state
->unique_num
3598 == (*(alt_state_t
*) alt_state_ptr_2
)->state
->unique_num
)
3600 else if ((*(alt_state_t
*) alt_state_ptr_1
)->state
->unique_num
3601 < (*(alt_state_t
*) alt_state_ptr_2
)->state
->unique_num
)
3607 /* The function sorts ALT_STATES_LIST and removes duplicated alt
3608 states from the list. The comparison key is alt state unique
3611 uniq_sort_alt_states (alt_state_t alt_states_list
)
3613 alt_state_t curr_alt_state
;
3614 vla_ptr_t alt_states
;
3616 size_t prev_unique_state_ind
;
3618 alt_state_t
*result_ptr
;
3620 VLA_PTR_CREATE (alt_states
, 150, "alt_states");
3621 for (curr_alt_state
= alt_states_list
;
3622 curr_alt_state
!= NULL
;
3623 curr_alt_state
= curr_alt_state
->next_alt_state
)
3624 VLA_PTR_ADD (alt_states
, curr_alt_state
);
3625 qsort (VLA_PTR_BEGIN (alt_states
), VLA_PTR_LENGTH (alt_states
),
3626 sizeof (alt_state_t
), alt_state_cmp
);
3627 if (VLA_PTR_LENGTH (alt_states
) == 0)
3631 result_ptr
= VLA_PTR_BEGIN (alt_states
);
3632 prev_unique_state_ind
= 0;
3633 for (i
= 1; i
< VLA_PTR_LENGTH (alt_states
); i
++)
3634 if (result_ptr
[prev_unique_state_ind
]->state
!= result_ptr
[i
]->state
)
3636 prev_unique_state_ind
++;
3637 result_ptr
[prev_unique_state_ind
] = result_ptr
[i
];
3640 for (i
= prev_unique_state_ind
+ 1; i
< VLA_PTR_LENGTH (alt_states
); i
++)
3641 free_alt_state (result_ptr
[i
]);
3643 VLA_PTR_SHORTEN (alt_states
, i
- prev_unique_state_ind
- 1);
3644 result_ptr
= VLA_PTR_BEGIN (alt_states
);
3645 for (i
= 1; i
< VLA_PTR_LENGTH (alt_states
); i
++)
3646 result_ptr
[i
- 1]->next_sorted_alt_state
= result_ptr
[i
];
3647 result_ptr
[i
- 1]->next_sorted_alt_state
= NULL
;
3648 result
= *result_ptr
;
3650 VLA_PTR_DELETE (alt_states
);
3654 /* The function checks equality of alt state lists. Remember that the
3655 lists must be already sorted by the previous function. */
3657 alt_states_eq (alt_state_t alt_states_1
, alt_state_t alt_states_2
)
3659 while (alt_states_1
!= NULL
&& alt_states_2
!= NULL
3660 && alt_state_cmp (&alt_states_1
, &alt_states_2
) == 0)
3662 alt_states_1
= alt_states_1
->next_sorted_alt_state
;
3663 alt_states_2
= alt_states_2
->next_sorted_alt_state
;
3665 return alt_states_1
== alt_states_2
;
3668 /* Initialization of the abstract data. */
3670 initiate_alt_states (void)
3672 first_free_alt_state
= NULL
;
3675 /* Finishing work with the abstract data. */
3677 finish_alt_states (void)
3683 /* The page contains macros for work with bits strings. We could use
3684 standard gcc bitmap or sbitmap but it would result in difficulties
3685 of building canadian cross. */
3687 /* Set bit number bitno in the bit string. The macro is not side
3689 #define SET_BIT(bitstring, bitno) \
3690 (((char *) (bitstring)) [(bitno) / CHAR_BIT] |= 1 << (bitno) % CHAR_BIT)
3692 #define CLEAR_BIT(bitstring, bitno) \
3693 (((char *) (bitstring)) [(bitno) / CHAR_BIT] &= ~(1 << (bitno) % CHAR_BIT))
3695 /* Test if bit number bitno in the bitstring is set. The macro is not
3696 side effect proof. */
3697 #define TEST_BIT(bitstring, bitno) \
3698 (((char *) (bitstring)) [(bitno) / CHAR_BIT] >> (bitno) % CHAR_BIT & 1)
3702 /* This page contains abstract data `state'. */
3704 /* Maximal length of reservations in cycles (>= 1). */
3705 static int max_cycles_num
;
3707 /* Number of set elements (see type set_el_t) needed for
3708 representation of one cycle reservation. It is depended on units
3710 static int els_in_cycle_reserv
;
3712 /* Number of set elements (see type set_el_t) needed for
3713 representation of maximal length reservation. Deterministic
3714 reservation is stored as set (bit string) of length equal to the
3715 variable value * number of bits in set_el_t. */
3716 static int els_in_reservs
;
3718 /* VLA for representation of array of pointers to unit
3720 static vla_ptr_t units_container
;
3722 /* The start address of the array. */
3723 static unit_decl_t
*units_array
;
3725 /* Temporary reservation of maximal length. */
3726 static reserv_sets_t temp_reserv
;
3728 /* The state table itself is represented by the following variable. */
3729 static htab_t state_table
;
3731 /* VLA for representation of array of pointers to free nodes
3733 static vla_ptr_t free_states
;
3735 static int curr_unique_state_num
;
3738 /* The following variables is maximal number of allocated nodes
3740 static int allocated_states_num
= 0;
3743 /* Allocate new reservation set. */
3744 static reserv_sets_t
3745 alloc_empty_reserv_sets (void)
3747 reserv_sets_t result
;
3749 obstack_blank (&irp
, els_in_reservs
* sizeof (set_el_t
));
3750 result
= (reserv_sets_t
) obstack_base (&irp
);
3751 obstack_finish (&irp
);
3752 memset (result
, 0, els_in_reservs
* sizeof (set_el_t
));
3756 /* Hash value of reservation set. */
3758 reserv_sets_hash_value (reserv_sets_t reservs
)
3760 set_el_t hash_value
;
3763 set_el_t
*reserv_ptr
;
3766 reservs_num
= els_in_reservs
;
3767 reserv_ptr
= reservs
;
3769 while (reservs_num
!= 0)
3772 hash_value
+= ((*reserv_ptr
>> i
)
3773 | (*reserv_ptr
<< (sizeof (set_el_t
) * CHAR_BIT
- i
)));
3775 if (i
== sizeof (set_el_t
) * CHAR_BIT
)
3779 if (sizeof (set_el_t
) <= sizeof (unsigned))
3782 for (i
= sizeof (set_el_t
); i
> 0; i
-= sizeof (unsigned) - 1)
3784 result
+= (unsigned) hash_value
;
3785 hash_value
>>= (sizeof (unsigned) - 1) * CHAR_BIT
;
3790 /* Comparison of given reservation sets. */
3792 reserv_sets_cmp (reserv_sets_t reservs_1
, reserv_sets_t reservs_2
)
3795 set_el_t
*reserv_ptr_1
;
3796 set_el_t
*reserv_ptr_2
;
3798 if (reservs_1
== NULL
|| reservs_2
== NULL
)
3800 reservs_num
= els_in_reservs
;
3801 reserv_ptr_1
= reservs_1
;
3802 reserv_ptr_2
= reservs_2
;
3803 while (reservs_num
!= 0 && *reserv_ptr_1
== *reserv_ptr_2
)
3809 if (reservs_num
== 0)
3811 else if (*reserv_ptr_1
< *reserv_ptr_2
)
3817 /* The function checks equality of the reservation sets. */
3819 reserv_sets_eq (reserv_sets_t reservs_1
, reserv_sets_t reservs_2
)
3821 return reserv_sets_cmp (reservs_1
, reservs_2
) == 0;
3824 /* Set up in the reservation set that unit with UNIT_NUM is used on
3827 set_unit_reserv (reserv_sets_t reservs
, int cycle_num
, int unit_num
)
3829 if (cycle_num
>= max_cycles_num
)
3831 SET_BIT (reservs
, cycle_num
* els_in_cycle_reserv
3832 * sizeof (set_el_t
) * CHAR_BIT
+ unit_num
);
3835 /* Set up in the reservation set RESERVS that unit with UNIT_NUM is
3836 used on CYCLE_NUM. */
3838 test_unit_reserv (reserv_sets_t reservs
, int cycle_num
, int unit_num
)
3840 if (cycle_num
>= max_cycles_num
)
3842 return TEST_BIT (reservs
, cycle_num
* els_in_cycle_reserv
3843 * sizeof (set_el_t
) * CHAR_BIT
+ unit_num
);
3846 /* The function checks that the reservation set represents no one unit
3849 it_is_empty_reserv_sets (reserv_sets_t operand
)
3851 set_el_t
*reserv_ptr
;
3854 if (operand
== NULL
)
3856 for (reservs_num
= els_in_reservs
, reserv_ptr
= operand
;
3858 reserv_ptr
++, reservs_num
--)
3859 if (*reserv_ptr
!= 0)
3864 /* The function checks that the reservation sets are intersected,
3865 i.e. there is a unit reservation on a cycle in both reservation
3868 reserv_sets_are_intersected (reserv_sets_t operand_1
,
3869 reserv_sets_t operand_2
)
3873 set_el_t
*cycle_ptr_1
;
3874 set_el_t
*cycle_ptr_2
;
3876 if (operand_1
== NULL
|| operand_2
== NULL
)
3878 for (el_ptr_1
= operand_1
, el_ptr_2
= operand_2
;
3879 el_ptr_1
< operand_1
+ els_in_reservs
;
3880 el_ptr_1
++, el_ptr_2
++)
3881 if (*el_ptr_1
& *el_ptr_2
)
3883 reserv_sets_or (temp_reserv
, operand_1
, operand_2
);
3884 for (cycle_ptr_1
= operand_1
, cycle_ptr_2
= operand_2
;
3885 cycle_ptr_1
< operand_1
+ els_in_reservs
;
3886 cycle_ptr_1
+= els_in_cycle_reserv
, cycle_ptr_2
+= els_in_cycle_reserv
)
3888 for (el_ptr_1
= cycle_ptr_1
, el_ptr_2
= get_excl_set (cycle_ptr_2
);
3889 el_ptr_1
< cycle_ptr_1
+ els_in_cycle_reserv
;
3890 el_ptr_1
++, el_ptr_2
++)
3891 if (*el_ptr_1
& *el_ptr_2
)
3893 if (!check_presence_pattern_sets (cycle_ptr_1
, cycle_ptr_2
, FALSE
))
3895 if (!check_presence_pattern_sets (temp_reserv
+ (cycle_ptr_2
3899 if (!check_absence_pattern_sets (cycle_ptr_1
, cycle_ptr_2
, FALSE
))
3901 if (!check_absence_pattern_sets (temp_reserv
+ (cycle_ptr_2
- operand_2
),
3908 /* The function sets up RESULT bits by bits of OPERAND shifted on one
3909 cpu cycle. The remaining bits of OPERAND (representing the last
3910 cycle unit reservations) are not changed. */
3912 reserv_sets_shift (reserv_sets_t result
, reserv_sets_t operand
)
3916 if (result
== NULL
|| operand
== NULL
|| result
== operand
)
3918 for (i
= els_in_cycle_reserv
; i
< els_in_reservs
; i
++)
3919 result
[i
- els_in_cycle_reserv
] = operand
[i
];
3922 /* OR of the reservation sets. */
3924 reserv_sets_or (reserv_sets_t result
, reserv_sets_t operand_1
,
3925 reserv_sets_t operand_2
)
3929 set_el_t
*result_set_el_ptr
;
3931 if (result
== NULL
|| operand_1
== NULL
|| operand_2
== NULL
)
3933 for (el_ptr_1
= operand_1
, el_ptr_2
= operand_2
, result_set_el_ptr
= result
;
3934 el_ptr_1
< operand_1
+ els_in_reservs
;
3935 el_ptr_1
++, el_ptr_2
++, result_set_el_ptr
++)
3936 *result_set_el_ptr
= *el_ptr_1
| *el_ptr_2
;
3939 /* AND of the reservation sets. */
3941 reserv_sets_and (reserv_sets_t result
, reserv_sets_t operand_1
,
3942 reserv_sets_t operand_2
)
3946 set_el_t
*result_set_el_ptr
;
3948 if (result
== NULL
|| operand_1
== NULL
|| operand_2
== NULL
)
3950 for (el_ptr_1
= operand_1
, el_ptr_2
= operand_2
, result_set_el_ptr
= result
;
3951 el_ptr_1
< operand_1
+ els_in_reservs
;
3952 el_ptr_1
++, el_ptr_2
++, result_set_el_ptr
++)
3953 *result_set_el_ptr
= *el_ptr_1
& *el_ptr_2
;
3956 /* The function outputs string representation of units reservation on
3957 cycle START_CYCLE in the reservation set. The function uses repeat
3958 construction if REPETITION_NUM > 1. */
3960 output_cycle_reservs (FILE *f
, reserv_sets_t reservs
, int start_cycle
,
3964 int reserved_units_num
;
3966 reserved_units_num
= 0;
3967 for (unit_num
= 0; unit_num
< description
->units_num
; unit_num
++)
3968 if (TEST_BIT (reservs
, start_cycle
* els_in_cycle_reserv
3969 * sizeof (set_el_t
) * CHAR_BIT
+ unit_num
))
3970 reserved_units_num
++;
3971 if (repetition_num
<= 0)
3973 if (repetition_num
!= 1 && reserved_units_num
> 1)
3975 reserved_units_num
= 0;
3977 unit_num
< description
->units_num
;
3979 if (TEST_BIT (reservs
, start_cycle
* els_in_cycle_reserv
3980 * sizeof (set_el_t
) * CHAR_BIT
+ unit_num
))
3982 if (reserved_units_num
!= 0)
3984 reserved_units_num
++;
3985 fprintf (f
, "%s", units_array
[unit_num
]->name
);
3987 if (reserved_units_num
== 0)
3988 fprintf (f
, NOTHING_NAME
);
3989 if (repetition_num
<= 0)
3991 if (repetition_num
!= 1 && reserved_units_num
> 1)
3993 if (repetition_num
!= 1)
3994 fprintf (f
, "*%d", repetition_num
);
3997 /* The function outputs string representation of units reservation in
3998 the reservation set. */
4000 output_reserv_sets (FILE *f
, reserv_sets_t reservs
)
4002 int start_cycle
= 0;
4007 for (cycle
= 0; cycle
< max_cycles_num
; cycle
++)
4008 if (repetition_num
== 0)
4011 start_cycle
= cycle
;
4014 ((char *) reservs
+ start_cycle
* els_in_cycle_reserv
4015 * sizeof (set_el_t
),
4016 (char *) reservs
+ cycle
* els_in_cycle_reserv
4017 * sizeof (set_el_t
),
4018 els_in_cycle_reserv
* sizeof (set_el_t
)) == 0)
4022 if (start_cycle
!= 0)
4024 output_cycle_reservs (f
, reservs
, start_cycle
, repetition_num
);
4026 start_cycle
= cycle
;
4028 if (start_cycle
< max_cycles_num
)
4030 if (start_cycle
!= 0)
4032 output_cycle_reservs (f
, reservs
, start_cycle
, repetition_num
);
4036 /* The following function returns free node state for AUTOMATON. It
4037 may be new allocated node or node freed earlier. The function also
4038 allocates reservation set if WITH_RESERVS has nonzero value. */
4040 get_free_state (int with_reservs
, automaton_t automaton
)
4044 if (max_cycles_num
<= 0 || automaton
== NULL
)
4046 if (VLA_PTR_LENGTH (free_states
) != 0)
4048 result
= VLA_PTR (free_states
, VLA_PTR_LENGTH (free_states
) - 1);
4049 VLA_PTR_SHORTEN (free_states
, 1);
4050 result
->automaton
= automaton
;
4051 result
->first_out_arc
= NULL
;
4052 result
->it_was_placed_in_stack_for_NDFA_forming
= 0;
4053 result
->it_was_placed_in_stack_for_DFA_forming
= 0;
4054 result
->component_states
= NULL
;
4055 result
->longest_path_length
= UNDEFINED_LONGEST_PATH_LENGTH
;
4060 allocated_states_num
++;
4062 result
= create_node (sizeof (struct state
));
4063 result
->automaton
= automaton
;
4064 result
->first_out_arc
= NULL
;
4065 result
->unique_num
= curr_unique_state_num
;
4066 result
->longest_path_length
= UNDEFINED_LONGEST_PATH_LENGTH
;
4067 curr_unique_state_num
++;
4071 if (result
->reservs
== NULL
)
4072 result
->reservs
= alloc_empty_reserv_sets ();
4074 memset (result
->reservs
, 0, els_in_reservs
* sizeof (set_el_t
));
4079 /* The function frees node STATE. */
4081 free_state (state_t state
)
4083 free_alt_states (state
->component_states
);
4084 VLA_PTR_ADD (free_states
, state
);
4087 /* Hash value of STATE. If STATE represents deterministic state it is
4088 simply hash value of the corresponding reservation set. Otherwise
4089 it is formed from hash values of the component deterministic
4090 states. One more key is order number of state automaton. */
4092 state_hash (const void *state
)
4094 unsigned int hash_value
;
4095 alt_state_t alt_state
;
4097 if (((state_t
) state
)->component_states
== NULL
)
4098 hash_value
= reserv_sets_hash_value (((state_t
) state
)->reservs
);
4102 for (alt_state
= ((state_t
) state
)->component_states
;
4104 alt_state
= alt_state
->next_sorted_alt_state
)
4105 hash_value
= (((hash_value
>> (sizeof (unsigned) - 1) * CHAR_BIT
)
4106 | (hash_value
<< CHAR_BIT
))
4107 + alt_state
->state
->unique_num
);
4109 hash_value
= (((hash_value
>> (sizeof (unsigned) - 1) * CHAR_BIT
)
4110 | (hash_value
<< CHAR_BIT
))
4111 + ((state_t
) state
)->automaton
->automaton_order_num
);
4115 /* Return nonzero value if the states are the same. */
4117 state_eq_p (const void *state_1
, const void *state_2
)
4119 alt_state_t alt_state_1
;
4120 alt_state_t alt_state_2
;
4122 if (((state_t
) state_1
)->automaton
!= ((state_t
) state_2
)->automaton
)
4124 else if (((state_t
) state_1
)->component_states
== NULL
4125 && ((state_t
) state_2
)->component_states
== NULL
)
4126 return reserv_sets_eq (((state_t
) state_1
)->reservs
,
4127 ((state_t
) state_2
)->reservs
);
4128 else if (((state_t
) state_1
)->component_states
!= NULL
4129 && ((state_t
) state_2
)->component_states
!= NULL
)
4131 for (alt_state_1
= ((state_t
) state_1
)->component_states
,
4132 alt_state_2
= ((state_t
) state_2
)->component_states
;
4133 alt_state_1
!= NULL
&& alt_state_2
!= NULL
;
4134 alt_state_1
= alt_state_1
->next_sorted_alt_state
,
4135 alt_state_2
= alt_state_2
->next_sorted_alt_state
)
4136 /* All state in the list must be already in the hash table.
4137 Also the lists must be sorted. */
4138 if (alt_state_1
->state
!= alt_state_2
->state
)
4140 return alt_state_1
== alt_state_2
;
4146 /* Insert STATE into the state table. */
4148 insert_state (state_t state
)
4152 entry_ptr
= htab_find_slot (state_table
, (void *) state
, 1);
4153 if (*entry_ptr
== NULL
)
4154 *entry_ptr
= (void *) state
;
4155 return (state_t
) *entry_ptr
;
4158 /* Add reservation of unit with UNIT_NUM on cycle CYCLE_NUM to
4159 deterministic STATE. */
4161 set_state_reserv (state_t state
, int cycle_num
, int unit_num
)
4163 set_unit_reserv (state
->reservs
, cycle_num
, unit_num
);
4166 /* Return nonzero value if the deterministic states contains a
4167 reservation of the same cpu unit on the same cpu cycle. */
4169 intersected_state_reservs_p (state_t state1
, state_t state2
)
4171 if (state1
->automaton
!= state2
->automaton
)
4173 return reserv_sets_are_intersected (state1
->reservs
, state2
->reservs
);
4176 /* Return deterministic state (inserted into the table) which
4177 representing the automaton state which is union of reservations of
4178 the deterministic states masked by RESERVS. */
4180 states_union (state_t state1
, state_t state2
, reserv_sets_t reservs
)
4183 state_t state_in_table
;
4185 if (state1
->automaton
!= state2
->automaton
)
4187 result
= get_free_state (1, state1
->automaton
);
4188 reserv_sets_or (result
->reservs
, state1
->reservs
, state2
->reservs
);
4189 reserv_sets_and (result
->reservs
, result
->reservs
, reservs
);
4190 state_in_table
= insert_state (result
);
4191 if (result
!= state_in_table
)
4193 free_state (result
);
4194 result
= state_in_table
;
4199 /* Return deterministic state (inserted into the table) which
4200 represent the automaton state is obtained from deterministic STATE
4201 by advancing cpu cycle and masking by RESERVS. */
4203 state_shift (state_t state
, reserv_sets_t reservs
)
4206 state_t state_in_table
;
4208 result
= get_free_state (1, state
->automaton
);
4209 reserv_sets_shift (result
->reservs
, state
->reservs
);
4210 reserv_sets_and (result
->reservs
, result
->reservs
, reservs
);
4211 state_in_table
= insert_state (result
);
4212 if (result
!= state_in_table
)
4214 free_state (result
);
4215 result
= state_in_table
;
4220 /* Initialization of the abstract data. */
4222 initiate_states (void)
4227 VLA_PTR_CREATE (units_container
, description
->units_num
, "units_container");
4229 = (description
->decls_num
&& description
->units_num
4230 ? VLA_PTR_BEGIN (units_container
) : NULL
);
4231 for (i
= 0; i
< description
->decls_num
; i
++)
4233 decl
= description
->decls
[i
];
4234 if (decl
->mode
== dm_unit
)
4235 units_array
[DECL_UNIT (decl
)->unit_num
] = DECL_UNIT (decl
);
4237 max_cycles_num
= description
->max_insn_reserv_cycles
;
4239 = ((description
->units_num
+ sizeof (set_el_t
) * CHAR_BIT
- 1)
4240 / (sizeof (set_el_t
) * CHAR_BIT
));
4241 els_in_reservs
= els_in_cycle_reserv
* max_cycles_num
;
4242 curr_unique_state_num
= 0;
4243 initiate_alt_states ();
4244 VLA_PTR_CREATE (free_states
, 1500, "free states");
4245 state_table
= htab_create (1500, state_hash
, state_eq_p
, (htab_del
) 0);
4246 temp_reserv
= alloc_empty_reserv_sets ();
4249 /* Finishing work with the abstract data. */
4251 finish_states (void)
4253 VLA_PTR_DELETE (units_container
);
4254 htab_delete (state_table
);
4255 VLA_PTR_DELETE (free_states
);
4256 finish_alt_states ();
4261 /* Abstract data `arcs'. */
4263 /* List of free arcs. */
4264 static arc_t first_free_arc
;
4267 /* The following variables is maximal number of allocated nodes
4269 static int allocated_arcs_num
= 0;
4272 /* The function frees node ARC. */
4274 free_arc (arc_t arc
)
4276 arc
->next_out_arc
= first_free_arc
;
4277 first_free_arc
= arc
;
4280 /* The function removes and frees ARC staring from FROM_STATE. */
4282 remove_arc (state_t from_state
, arc_t arc
)
4289 for (prev_arc
= NULL
, curr_arc
= from_state
->first_out_arc
;
4291 prev_arc
= curr_arc
, curr_arc
= curr_arc
->next_out_arc
)
4292 if (curr_arc
== arc
)
4294 if (curr_arc
== NULL
)
4296 if (prev_arc
== NULL
)
4297 from_state
->first_out_arc
= arc
->next_out_arc
;
4299 prev_arc
->next_out_arc
= arc
->next_out_arc
;
4303 /* The functions returns arc with given characteristics (or NULL if
4304 the arc does not exist). */
4306 find_arc (state_t from_state
, state_t to_state
, ainsn_t insn
)
4310 for (arc
= first_out_arc (from_state
); arc
!= NULL
; arc
= next_out_arc (arc
))
4311 if (arc
->to_state
== to_state
&& arc
->insn
== insn
)
4316 /* The function adds arc from FROM_STATE to TO_STATE marked by AINSN
4317 and with given STATE_ALTS. The function returns added arc (or
4318 already existing arc). */
4320 add_arc (state_t from_state
, state_t to_state
, ainsn_t ainsn
,
4325 new_arc
= find_arc (from_state
, to_state
, ainsn
);
4326 if (new_arc
!= NULL
)
4328 if (first_free_arc
== NULL
)
4331 allocated_arcs_num
++;
4333 new_arc
= create_node (sizeof (struct arc
));
4334 new_arc
->to_state
= NULL
;
4335 new_arc
->insn
= NULL
;
4336 new_arc
->next_out_arc
= NULL
;
4340 new_arc
= first_free_arc
;
4341 first_free_arc
= first_free_arc
->next_out_arc
;
4343 new_arc
->to_state
= to_state
;
4344 new_arc
->insn
= ainsn
;
4345 ainsn
->arc_exists_p
= 1;
4346 new_arc
->next_out_arc
= from_state
->first_out_arc
;
4347 from_state
->first_out_arc
= new_arc
;
4348 new_arc
->next_arc_marked_by_insn
= NULL
;
4349 new_arc
->state_alts
= state_alts
;
4353 /* The function returns the first arc starting from STATE. */
4355 first_out_arc (state_t state
)
4357 return state
->first_out_arc
;
4360 /* The function returns next out arc after ARC. */
4362 next_out_arc (arc_t arc
)
4364 return arc
->next_out_arc
;
4367 /* Initialization of the abstract data. */
4369 initiate_arcs (void)
4371 first_free_arc
= NULL
;
4374 /* Finishing work with the abstract data. */
4382 /* Abstract data `automata lists'. */
4384 /* List of free states. */
4385 static automata_list_el_t first_free_automata_list_el
;
4387 /* The list being formed. */
4388 static automata_list_el_t current_automata_list
;
4390 /* Hash table of automata lists. */
4391 static htab_t automata_list_table
;
4393 /* The following function returns free automata list el. It may be
4394 new allocated node or node freed earlier. */
4395 static automata_list_el_t
4396 get_free_automata_list_el (void)
4398 automata_list_el_t result
;
4400 if (first_free_automata_list_el
!= NULL
)
4402 result
= first_free_automata_list_el
;
4403 first_free_automata_list_el
4404 = first_free_automata_list_el
->next_automata_list_el
;
4407 result
= create_node (sizeof (struct automata_list_el
));
4408 result
->automaton
= NULL
;
4409 result
->next_automata_list_el
= NULL
;
4413 /* The function frees node AUTOMATA_LIST_EL. */
4415 free_automata_list_el (automata_list_el_t automata_list_el
)
4417 if (automata_list_el
== NULL
)
4419 automata_list_el
->next_automata_list_el
= first_free_automata_list_el
;
4420 first_free_automata_list_el
= automata_list_el
;
4423 /* The function frees list AUTOMATA_LIST. */
4425 free_automata_list (automata_list_el_t automata_list
)
4427 automata_list_el_t curr_automata_list_el
;
4428 automata_list_el_t next_automata_list_el
;
4430 for (curr_automata_list_el
= automata_list
;
4431 curr_automata_list_el
!= NULL
;
4432 curr_automata_list_el
= next_automata_list_el
)
4434 next_automata_list_el
= curr_automata_list_el
->next_automata_list_el
;
4435 free_automata_list_el (curr_automata_list_el
);
4439 /* Hash value of AUTOMATA_LIST. */
4441 automata_list_hash (const void *automata_list
)
4443 unsigned int hash_value
;
4444 automata_list_el_t curr_automata_list_el
;
4447 for (curr_automata_list_el
= (automata_list_el_t
) automata_list
;
4448 curr_automata_list_el
!= NULL
;
4449 curr_automata_list_el
= curr_automata_list_el
->next_automata_list_el
)
4450 hash_value
= (((hash_value
>> (sizeof (unsigned) - 1) * CHAR_BIT
)
4451 | (hash_value
<< CHAR_BIT
))
4452 + curr_automata_list_el
->automaton
->automaton_order_num
);
4456 /* Return nonzero value if the automata_lists are the same. */
4458 automata_list_eq_p (const void *automata_list_1
, const void *automata_list_2
)
4460 automata_list_el_t automata_list_el_1
;
4461 automata_list_el_t automata_list_el_2
;
4463 for (automata_list_el_1
= (automata_list_el_t
) automata_list_1
,
4464 automata_list_el_2
= (automata_list_el_t
) automata_list_2
;
4465 automata_list_el_1
!= NULL
&& automata_list_el_2
!= NULL
;
4466 automata_list_el_1
= automata_list_el_1
->next_automata_list_el
,
4467 automata_list_el_2
= automata_list_el_2
->next_automata_list_el
)
4468 if (automata_list_el_1
->automaton
!= automata_list_el_2
->automaton
)
4470 return automata_list_el_1
== automata_list_el_2
;
4473 /* Initialization of the abstract data. */
4475 initiate_automata_lists (void)
4477 first_free_automata_list_el
= NULL
;
4478 automata_list_table
= htab_create (1500, automata_list_hash
,
4479 automata_list_eq_p
, (htab_del
) 0);
4482 /* The following function starts new automata list and makes it the
4485 automata_list_start (void)
4487 current_automata_list
= NULL
;
4490 /* The following function adds AUTOMATON to the current list. */
4492 automata_list_add (automaton_t automaton
)
4494 automata_list_el_t el
;
4496 el
= get_free_automata_list_el ();
4497 el
->automaton
= automaton
;
4498 el
->next_automata_list_el
= current_automata_list
;
4499 current_automata_list
= el
;
4502 /* The following function finishes forming the current list, inserts
4503 it into the table and returns it. */
4504 static automata_list_el_t
4505 automata_list_finish (void)
4509 if (current_automata_list
== NULL
)
4511 entry_ptr
= htab_find_slot (automata_list_table
,
4512 (void *) current_automata_list
, 1);
4513 if (*entry_ptr
== NULL
)
4514 *entry_ptr
= (void *) current_automata_list
;
4516 free_automata_list (current_automata_list
);
4517 current_automata_list
= NULL
;
4518 return (automata_list_el_t
) *entry_ptr
;
4521 /* Finishing work with the abstract data. */
4523 finish_automata_lists (void)
4525 htab_delete (automata_list_table
);
4530 /* The page contains abstract data for work with exclusion sets (see
4531 exclusion_set in file rtl.def). */
4533 /* The following variable refers to an exclusion set returned by
4534 get_excl_set. This is bit string of length equal to cpu units
4535 number. If exclusion set for given unit contains 1 for a unit,
4536 then simultaneous reservation of the units is prohibited. */
4537 static reserv_sets_t excl_set
;
4539 /* The array contains exclusion sets for each unit. */
4540 static reserv_sets_t
*unit_excl_set_table
;
4542 /* The following function forms the array containing exclusion sets
4545 initiate_excl_sets (void)
4548 reserv_sets_t unit_excl_set
;
4552 obstack_blank (&irp
, els_in_cycle_reserv
* sizeof (set_el_t
));
4553 excl_set
= (reserv_sets_t
) obstack_base (&irp
);
4554 obstack_finish (&irp
);
4555 obstack_blank (&irp
, description
->units_num
* sizeof (reserv_sets_t
));
4556 unit_excl_set_table
= (reserv_sets_t
*) obstack_base (&irp
);
4557 obstack_finish (&irp
);
4558 /* Evaluate unit exclusion sets. */
4559 for (i
= 0; i
< description
->decls_num
; i
++)
4561 decl
= description
->decls
[i
];
4562 if (decl
->mode
== dm_unit
)
4564 obstack_blank (&irp
, els_in_cycle_reserv
* sizeof (set_el_t
));
4565 unit_excl_set
= (reserv_sets_t
) obstack_base (&irp
);
4566 obstack_finish (&irp
);
4567 memset (unit_excl_set
, 0, els_in_cycle_reserv
* sizeof (set_el_t
));
4568 for (el
= DECL_UNIT (decl
)->excl_list
;
4570 el
= el
->next_unit_set_el
)
4572 SET_BIT (unit_excl_set
, el
->unit_decl
->unit_num
);
4573 el
->unit_decl
->in_set_p
= TRUE
;
4575 unit_excl_set_table
[DECL_UNIT (decl
)->unit_num
] = unit_excl_set
;
4580 /* The function sets up and return EXCL_SET which is union of
4581 exclusion sets for each unit in IN_SET. */
4582 static reserv_sets_t
4583 get_excl_set (reserv_sets_t in_set
)
4591 chars_num
= els_in_cycle_reserv
* sizeof (set_el_t
);
4592 memset (excl_set
, 0, chars_num
);
4593 for (excl_char_num
= 0; excl_char_num
< chars_num
; excl_char_num
++)
4594 if (((unsigned char *) in_set
) [excl_char_num
])
4595 for (i
= CHAR_BIT
- 1; i
>= 0; i
--)
4596 if ((((unsigned char *) in_set
) [excl_char_num
] >> i
) & 1)
4598 start_unit_num
= excl_char_num
* CHAR_BIT
+ i
;
4599 if (start_unit_num
>= description
->units_num
)
4601 for (unit_num
= 0; unit_num
< els_in_cycle_reserv
; unit_num
++)
4604 |= unit_excl_set_table
[start_unit_num
] [unit_num
];
4612 /* The page contains abstract data for work with presence/absence
4613 pattern sets (see presence_set/absence_set in file rtl.def). */
4615 /* The following arrays contain correspondingly presence, final
4616 presence, absence, and final absence patterns for each unit. */
4617 static pattern_reserv_t
*unit_presence_set_table
;
4618 static pattern_reserv_t
*unit_final_presence_set_table
;
4619 static pattern_reserv_t
*unit_absence_set_table
;
4620 static pattern_reserv_t
*unit_final_absence_set_table
;
4622 /* The following function forms list of reservation sets for given
4624 static pattern_reserv_t
4625 form_reserv_sets_list (pattern_set_el_t pattern_list
)
4627 pattern_set_el_t el
;
4628 pattern_reserv_t first
, curr
, prev
;
4631 prev
= first
= NULL
;
4632 for (el
= pattern_list
; el
!= NULL
; el
= el
->next_pattern_set_el
)
4634 curr
= create_node (sizeof (struct pattern_reserv
));
4635 curr
->reserv
= alloc_empty_reserv_sets ();
4636 curr
->next_pattern_reserv
= NULL
;
4637 for (i
= 0; i
< el
->units_num
; i
++)
4639 SET_BIT (curr
->reserv
, el
->unit_decls
[i
]->unit_num
);
4640 el
->unit_decls
[i
]->in_set_p
= TRUE
;
4643 prev
->next_pattern_reserv
= curr
;
4651 /* The following function forms the array containing presence and
4652 absence pattern sets for each unit. */
4654 initiate_presence_absence_pattern_sets (void)
4659 obstack_blank (&irp
, description
->units_num
* sizeof (pattern_reserv_t
));
4660 unit_presence_set_table
= (pattern_reserv_t
*) obstack_base (&irp
);
4661 obstack_finish (&irp
);
4662 obstack_blank (&irp
, description
->units_num
* sizeof (pattern_reserv_t
));
4663 unit_final_presence_set_table
= (pattern_reserv_t
*) obstack_base (&irp
);
4664 obstack_finish (&irp
);
4665 obstack_blank (&irp
, description
->units_num
* sizeof (pattern_reserv_t
));
4666 unit_absence_set_table
= (pattern_reserv_t
*) obstack_base (&irp
);
4667 obstack_finish (&irp
);
4668 obstack_blank (&irp
, description
->units_num
* sizeof (pattern_reserv_t
));
4669 unit_final_absence_set_table
= (pattern_reserv_t
*) obstack_base (&irp
);
4670 obstack_finish (&irp
);
4671 /* Evaluate unit presence/absence sets. */
4672 for (i
= 0; i
< description
->decls_num
; i
++)
4674 decl
= description
->decls
[i
];
4675 if (decl
->mode
== dm_unit
)
4677 unit_presence_set_table
[DECL_UNIT (decl
)->unit_num
]
4678 = form_reserv_sets_list (DECL_UNIT (decl
)->presence_list
);
4679 unit_final_presence_set_table
[DECL_UNIT (decl
)->unit_num
]
4680 = form_reserv_sets_list (DECL_UNIT (decl
)->final_presence_list
);
4681 unit_absence_set_table
[DECL_UNIT (decl
)->unit_num
]
4682 = form_reserv_sets_list (DECL_UNIT (decl
)->absence_list
);
4683 unit_final_absence_set_table
[DECL_UNIT (decl
)->unit_num
]
4684 = form_reserv_sets_list (DECL_UNIT (decl
)->final_absence_list
);
4689 /* The function checks that CHECKED_SET satisfies all presence pattern
4690 sets for units in ORIGIONAL_SET. The function returns TRUE if it
4693 check_presence_pattern_sets (reserv_sets_t checked_set
,
4694 reserv_sets_t origional_set
,
4703 pattern_reserv_t pat_reserv
;
4705 chars_num
= els_in_cycle_reserv
* sizeof (set_el_t
);
4706 for (char_num
= 0; char_num
< chars_num
; char_num
++)
4707 if (((unsigned char *) origional_set
) [char_num
])
4708 for (i
= CHAR_BIT
- 1; i
>= 0; i
--)
4709 if ((((unsigned char *) origional_set
) [char_num
] >> i
) & 1)
4711 start_unit_num
= char_num
* CHAR_BIT
+ i
;
4712 if (start_unit_num
>= description
->units_num
)
4715 && unit_final_presence_set_table
[start_unit_num
] == NULL
)
4717 && unit_presence_set_table
[start_unit_num
] == NULL
))
4720 for (pat_reserv
= (final_p
4721 ? unit_final_presence_set_table
[start_unit_num
]
4722 : unit_presence_set_table
[start_unit_num
]);
4724 pat_reserv
= pat_reserv
->next_pattern_reserv
)
4726 for (unit_num
= 0; unit_num
< els_in_cycle_reserv
; unit_num
++)
4727 if ((checked_set
[unit_num
] & pat_reserv
->reserv
[unit_num
])
4728 != pat_reserv
->reserv
[unit_num
])
4730 presence_p
= presence_p
|| unit_num
>= els_in_cycle_reserv
;
4738 /* The function checks that CHECKED_SET satisfies all absence pattern
4739 sets for units in ORIGIONAL_SET. The function returns TRUE if it
4742 check_absence_pattern_sets (reserv_sets_t checked_set
,
4743 reserv_sets_t origional_set
,
4751 pattern_reserv_t pat_reserv
;
4753 chars_num
= els_in_cycle_reserv
* sizeof (set_el_t
);
4754 for (char_num
= 0; char_num
< chars_num
; char_num
++)
4755 if (((unsigned char *) origional_set
) [char_num
])
4756 for (i
= CHAR_BIT
- 1; i
>= 0; i
--)
4757 if ((((unsigned char *) origional_set
) [char_num
] >> i
) & 1)
4759 start_unit_num
= char_num
* CHAR_BIT
+ i
;
4760 if (start_unit_num
>= description
->units_num
)
4762 for (pat_reserv
= (final_p
4763 ? unit_final_absence_set_table
[start_unit_num
]
4764 : unit_absence_set_table
[start_unit_num
]);
4766 pat_reserv
= pat_reserv
->next_pattern_reserv
)
4768 for (unit_num
= 0; unit_num
< els_in_cycle_reserv
; unit_num
++)
4769 if ((checked_set
[unit_num
] & pat_reserv
->reserv
[unit_num
])
4770 != pat_reserv
->reserv
[unit_num
]
4771 && pat_reserv
->reserv
[unit_num
])
4773 if (unit_num
>= els_in_cycle_reserv
)
4782 /* This page contains code for transformation of original reservations
4783 described in .md file. The main goal of transformations is
4784 simplifying reservation and lifting up all `|' on the top of IR
4785 reservation representation. */
4788 /* The following function makes copy of IR representation of
4789 reservation. The function also substitutes all reservations
4790 defined by define_reservation by corresponding value during making
4793 copy_insn_regexp (regexp_t regexp
)
4798 if (regexp
->mode
== rm_reserv
)
4799 result
= copy_insn_regexp (REGEXP_RESERV (regexp
)->reserv_decl
->regexp
);
4800 else if (regexp
->mode
== rm_unit
)
4801 result
= copy_node (regexp
, sizeof (struct regexp
));
4802 else if (regexp
->mode
== rm_repeat
)
4804 result
= copy_node (regexp
, sizeof (struct regexp
));
4805 REGEXP_REPEAT (result
)->regexp
4806 = copy_insn_regexp (REGEXP_REPEAT (regexp
)->regexp
);
4808 else if (regexp
->mode
== rm_sequence
)
4810 result
= copy_node (regexp
,
4811 sizeof (struct regexp
) + sizeof (regexp_t
)
4812 * (REGEXP_SEQUENCE (regexp
)->regexps_num
- 1));
4813 for (i
= 0; i
<REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
4814 REGEXP_SEQUENCE (result
)->regexps
[i
]
4815 = copy_insn_regexp (REGEXP_SEQUENCE (regexp
)->regexps
[i
]);
4817 else if (regexp
->mode
== rm_allof
)
4819 result
= copy_node (regexp
,
4820 sizeof (struct regexp
) + sizeof (regexp_t
)
4821 * (REGEXP_ALLOF (regexp
)->regexps_num
- 1));
4822 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
4823 REGEXP_ALLOF (result
)->regexps
[i
]
4824 = copy_insn_regexp (REGEXP_ALLOF (regexp
)->regexps
[i
]);
4826 else if (regexp
->mode
== rm_oneof
)
4828 result
= copy_node (regexp
,
4829 sizeof (struct regexp
) + sizeof (regexp_t
)
4830 * (REGEXP_ONEOF (regexp
)->regexps_num
- 1));
4831 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
4832 REGEXP_ONEOF (result
)->regexps
[i
]
4833 = copy_insn_regexp (REGEXP_ONEOF (regexp
)->regexps
[i
]);
4837 if (regexp
->mode
!= rm_nothing
)
4839 result
= copy_node (regexp
, sizeof (struct regexp
));
4844 /* The following variable is set up 1 if a transformation has been
4846 static int regexp_transformed_p
;
4848 /* The function makes transformation
4851 transform_1 (regexp_t regexp
)
4858 if (regexp
->mode
== rm_repeat
)
4860 repeat_num
= REGEXP_REPEAT (regexp
)->repeat_num
;
4861 if (repeat_num
<= 1)
4863 operand
= REGEXP_REPEAT (regexp
)->regexp
;
4865 regexp
= create_node (sizeof (struct regexp
) + sizeof (regexp_t
)
4866 * (repeat_num
- 1));
4867 regexp
->mode
= rm_sequence
;
4869 REGEXP_SEQUENCE (regexp
)->regexps_num
= repeat_num
;
4870 for (i
= 0; i
< repeat_num
; i
++)
4871 REGEXP_SEQUENCE (regexp
)->regexps
[i
] = copy_insn_regexp (operand
);
4872 regexp_transformed_p
= 1;
4877 /* The function makes transformations
4878 ...,(A,B,...),C,... -> ...,A,B,...,C,...
4879 ...+(A+B+...)+C+... -> ...+A+B+...+C+...
4880 ...|(A|B|...)|C|... -> ...|A|B|...|C|... */
4882 transform_2 (regexp_t regexp
)
4884 if (regexp
->mode
== rm_sequence
)
4886 regexp_t sequence
= NULL
;
4888 int sequence_index
= 0;
4891 for (i
= 0; i
< REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
4892 if (REGEXP_SEQUENCE (regexp
)->regexps
[i
]->mode
== rm_sequence
)
4895 sequence
= REGEXP_SEQUENCE (regexp
)->regexps
[i
];
4898 if (i
< REGEXP_SEQUENCE (regexp
)->regexps_num
)
4900 if ( REGEXP_SEQUENCE (sequence
)->regexps_num
<= 1
4901 || REGEXP_SEQUENCE (regexp
)->regexps_num
<= 1)
4903 result
= create_node (sizeof (struct regexp
)
4905 * (REGEXP_SEQUENCE (regexp
)->regexps_num
4906 + REGEXP_SEQUENCE (sequence
)->regexps_num
4908 result
->mode
= rm_sequence
;
4909 result
->pos
= regexp
->pos
;
4910 REGEXP_SEQUENCE (result
)->regexps_num
4911 = (REGEXP_SEQUENCE (regexp
)->regexps_num
4912 + REGEXP_SEQUENCE (sequence
)->regexps_num
- 1);
4913 for (i
= 0; i
< REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
4914 if (i
< sequence_index
)
4915 REGEXP_SEQUENCE (result
)->regexps
[i
]
4916 = copy_insn_regexp (REGEXP_SEQUENCE (regexp
)->regexps
[i
]);
4917 else if (i
> sequence_index
)
4918 REGEXP_SEQUENCE (result
)->regexps
4919 [i
+ REGEXP_SEQUENCE (sequence
)->regexps_num
- 1]
4920 = copy_insn_regexp (REGEXP_SEQUENCE (regexp
)->regexps
[i
]);
4922 for (j
= 0; j
< REGEXP_SEQUENCE (sequence
)->regexps_num
; j
++)
4923 REGEXP_SEQUENCE (result
)->regexps
[i
+ j
]
4924 = copy_insn_regexp (REGEXP_SEQUENCE (sequence
)->regexps
[j
]);
4925 regexp_transformed_p
= 1;
4929 else if (regexp
->mode
== rm_allof
)
4931 regexp_t allof
= NULL
;
4933 int allof_index
= 0;
4936 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
4937 if (REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
== rm_allof
)
4940 allof
= REGEXP_ALLOF (regexp
)->regexps
[i
];
4943 if (i
< REGEXP_ALLOF (regexp
)->regexps_num
)
4945 if (REGEXP_ALLOF (allof
)->regexps_num
<= 1
4946 || REGEXP_ALLOF (regexp
)->regexps_num
<= 1)
4948 result
= create_node (sizeof (struct regexp
)
4950 * (REGEXP_ALLOF (regexp
)->regexps_num
4951 + REGEXP_ALLOF (allof
)->regexps_num
- 2));
4952 result
->mode
= rm_allof
;
4953 result
->pos
= regexp
->pos
;
4954 REGEXP_ALLOF (result
)->regexps_num
4955 = (REGEXP_ALLOF (regexp
)->regexps_num
4956 + REGEXP_ALLOF (allof
)->regexps_num
- 1);
4957 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
4958 if (i
< allof_index
)
4959 REGEXP_ALLOF (result
)->regexps
[i
]
4960 = copy_insn_regexp (REGEXP_ALLOF (regexp
)->regexps
[i
]);
4961 else if (i
> allof_index
)
4962 REGEXP_ALLOF (result
)->regexps
4963 [i
+ REGEXP_ALLOF (allof
)->regexps_num
- 1]
4964 = copy_insn_regexp (REGEXP_ALLOF (regexp
)->regexps
[i
]);
4966 for (j
= 0; j
< REGEXP_ALLOF (allof
)->regexps_num
; j
++)
4967 REGEXP_ALLOF (result
)->regexps
[i
+ j
]
4968 = copy_insn_regexp (REGEXP_ALLOF (allof
)->regexps
[j
]);
4969 regexp_transformed_p
= 1;
4973 else if (regexp
->mode
== rm_oneof
)
4975 regexp_t oneof
= NULL
;
4977 int oneof_index
= 0;
4980 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
4981 if (REGEXP_ONEOF (regexp
)->regexps
[i
]->mode
== rm_oneof
)
4984 oneof
= REGEXP_ONEOF (regexp
)->regexps
[i
];
4987 if (i
< REGEXP_ONEOF (regexp
)->regexps_num
)
4989 if (REGEXP_ONEOF (oneof
)->regexps_num
<= 1
4990 || REGEXP_ONEOF (regexp
)->regexps_num
<= 1)
4992 result
= create_node (sizeof (struct regexp
)
4994 * (REGEXP_ONEOF (regexp
)->regexps_num
4995 + REGEXP_ONEOF (oneof
)->regexps_num
- 2));
4996 result
->mode
= rm_oneof
;
4997 result
->pos
= regexp
->pos
;
4998 REGEXP_ONEOF (result
)->regexps_num
4999 = (REGEXP_ONEOF (regexp
)->regexps_num
5000 + REGEXP_ONEOF (oneof
)->regexps_num
- 1);
5001 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
5002 if (i
< oneof_index
)
5003 REGEXP_ONEOF (result
)->regexps
[i
]
5004 = copy_insn_regexp (REGEXP_ONEOF (regexp
)->regexps
[i
]);
5005 else if (i
> oneof_index
)
5006 REGEXP_ONEOF (result
)->regexps
5007 [i
+ REGEXP_ONEOF (oneof
)->regexps_num
- 1]
5008 = copy_insn_regexp (REGEXP_ONEOF (regexp
)->regexps
[i
]);
5010 for (j
= 0; j
< REGEXP_ONEOF (oneof
)->regexps_num
; j
++)
5011 REGEXP_ONEOF (result
)->regexps
[i
+ j
]
5012 = copy_insn_regexp (REGEXP_ONEOF (oneof
)->regexps
[j
]);
5013 regexp_transformed_p
= 1;
5020 /* The function makes transformations
5021 ...,A|B|...,C,... -> (...,A,C,...)|(...,B,C,...)|...
5022 ...+(A|B|...)+C+... -> (...+A+C+...)|(...+B+C+...)|...
5023 ...+(A,B,...)+C+... -> (...+A+C+...),B,...
5024 ...+(A,B,...)+(C,D,...) -> (A+C),(B+D),... */
5026 transform_3 (regexp_t regexp
)
5028 if (regexp
->mode
== rm_sequence
)
5030 regexp_t oneof
= NULL
;
5031 int oneof_index
= 0;
5036 for (i
= 0; i
<REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
5037 if (REGEXP_SEQUENCE (regexp
)->regexps
[i
]->mode
== rm_oneof
)
5040 oneof
= REGEXP_SEQUENCE (regexp
)->regexps
[i
];
5043 if (i
< REGEXP_SEQUENCE (regexp
)->regexps_num
)
5045 if (REGEXP_ONEOF (oneof
)->regexps_num
<= 1
5046 || REGEXP_SEQUENCE (regexp
)->regexps_num
<= 1)
5048 result
= create_node (sizeof (struct regexp
)
5050 * (REGEXP_ONEOF (oneof
)->regexps_num
- 1));
5051 result
->mode
= rm_oneof
;
5052 result
->pos
= regexp
->pos
;
5053 REGEXP_ONEOF (result
)->regexps_num
5054 = REGEXP_ONEOF (oneof
)->regexps_num
;
5055 for (i
= 0; i
< REGEXP_ONEOF (result
)->regexps_num
; i
++)
5058 = create_node (sizeof (struct regexp
)
5060 * (REGEXP_SEQUENCE (regexp
)->regexps_num
- 1));
5061 sequence
->mode
= rm_sequence
;
5062 sequence
->pos
= regexp
->pos
;
5063 REGEXP_SEQUENCE (sequence
)->regexps_num
5064 = REGEXP_SEQUENCE (regexp
)->regexps_num
;
5065 REGEXP_ONEOF (result
)->regexps
[i
] = sequence
;
5066 for (j
= 0; j
< REGEXP_SEQUENCE (sequence
)->regexps_num
; j
++)
5067 if (j
!= oneof_index
)
5068 REGEXP_SEQUENCE (sequence
)->regexps
[j
]
5069 = copy_insn_regexp (REGEXP_SEQUENCE (regexp
)->regexps
[j
]);
5071 REGEXP_SEQUENCE (sequence
)->regexps
[j
]
5072 = copy_insn_regexp (REGEXP_ONEOF (oneof
)->regexps
[i
]);
5074 regexp_transformed_p
= 1;
5078 else if (regexp
->mode
== rm_allof
)
5080 regexp_t oneof
= NULL
;
5082 int oneof_index
= 0;
5083 int max_seq_length
, allof_length
;
5085 regexp_t allof
= NULL
;
5086 regexp_t allof_op
= NULL
;
5089 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
5090 if (REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
== rm_oneof
)
5093 oneof
= REGEXP_ALLOF (regexp
)->regexps
[i
];
5096 if (i
< REGEXP_ALLOF (regexp
)->regexps_num
)
5098 if (REGEXP_ONEOF (oneof
)->regexps_num
<= 1
5099 || REGEXP_ALLOF (regexp
)->regexps_num
<= 1)
5101 result
= create_node (sizeof (struct regexp
)
5103 * (REGEXP_ONEOF (oneof
)->regexps_num
- 1));
5104 result
->mode
= rm_oneof
;
5105 result
->pos
= regexp
->pos
;
5106 REGEXP_ONEOF (result
)->regexps_num
5107 = REGEXP_ONEOF (oneof
)->regexps_num
;
5108 for (i
= 0; i
< REGEXP_ONEOF (result
)->regexps_num
; i
++)
5111 = create_node (sizeof (struct regexp
)
5113 * (REGEXP_ALLOF (regexp
)->regexps_num
- 1));
5114 allof
->mode
= rm_allof
;
5115 allof
->pos
= regexp
->pos
;
5116 REGEXP_ALLOF (allof
)->regexps_num
5117 = REGEXP_ALLOF (regexp
)->regexps_num
;
5118 REGEXP_ONEOF (result
)->regexps
[i
] = allof
;
5119 for (j
= 0; j
< REGEXP_ALLOF (allof
)->regexps_num
; j
++)
5120 if (j
!= oneof_index
)
5121 REGEXP_ALLOF (allof
)->regexps
[j
]
5122 = copy_insn_regexp (REGEXP_ALLOF (regexp
)->regexps
[j
]);
5124 REGEXP_ALLOF (allof
)->regexps
[j
]
5125 = copy_insn_regexp (REGEXP_ONEOF (oneof
)->regexps
[i
]);
5127 regexp_transformed_p
= 1;
5131 if (regexp
->mode
== rm_allof
)
5132 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
5134 if (REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
== rm_sequence
)
5136 seq
= REGEXP_ALLOF (regexp
)->regexps
[i
];
5137 if (max_seq_length
< REGEXP_SEQUENCE (seq
)->regexps_num
)
5138 max_seq_length
= REGEXP_SEQUENCE (seq
)->regexps_num
;
5140 else if (REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
!= rm_unit
5141 && REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
!= rm_nothing
)
5147 if (max_seq_length
!= 0)
5149 if (max_seq_length
== 1 || REGEXP_ALLOF (regexp
)->regexps_num
<= 1)
5151 result
= create_node (sizeof (struct regexp
)
5152 + sizeof (regexp_t
) * (max_seq_length
- 1));
5153 result
->mode
= rm_sequence
;
5154 result
->pos
= regexp
->pos
;
5155 REGEXP_SEQUENCE (result
)->regexps_num
= max_seq_length
;
5156 for (i
= 0; i
< max_seq_length
; i
++)
5159 for (j
= 0; j
< REGEXP_ALLOF (regexp
)->regexps_num
; j
++)
5160 if (REGEXP_ALLOF (regexp
)->regexps
[j
]->mode
== rm_sequence
5161 && (i
< (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp
)
5162 ->regexps
[j
])->regexps_num
)))
5165 = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp
)->regexps
[j
])
5170 && (REGEXP_ALLOF (regexp
)->regexps
[j
]->mode
5172 || (REGEXP_ALLOF (regexp
)->regexps
[j
]->mode
5175 allof_op
= REGEXP_ALLOF (regexp
)->regexps
[j
];
5178 if (allof_length
== 1)
5179 REGEXP_SEQUENCE (result
)->regexps
[i
] = allof_op
;
5182 allof
= create_node (sizeof (struct regexp
)
5184 * (allof_length
- 1));
5185 allof
->mode
= rm_allof
;
5186 allof
->pos
= regexp
->pos
;
5187 REGEXP_ALLOF (allof
)->regexps_num
= allof_length
;
5188 REGEXP_SEQUENCE (result
)->regexps
[i
] = allof
;
5190 for (j
= 0; j
< REGEXP_ALLOF (regexp
)->regexps_num
; j
++)
5191 if (REGEXP_ALLOF (regexp
)->regexps
[j
]->mode
== rm_sequence
5193 (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp
)
5194 ->regexps
[j
])->regexps_num
)))
5196 allof_op
= (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp
)
5199 REGEXP_ALLOF (allof
)->regexps
[allof_length
]
5204 && (REGEXP_ALLOF (regexp
)->regexps
[j
]->mode
5206 || (REGEXP_ALLOF (regexp
)->regexps
[j
]->mode
5209 allof_op
= REGEXP_ALLOF (regexp
)->regexps
[j
];
5210 REGEXP_ALLOF (allof
)->regexps
[allof_length
]
5216 regexp_transformed_p
= 1;
5223 /* The function traverses IR of reservation and applies transformations
5224 implemented by FUNC. */
5226 regexp_transform_func (regexp_t regexp
, regexp_t (*func
) (regexp_t regexp
))
5230 if (regexp
->mode
== rm_sequence
)
5231 for (i
= 0; i
< REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
5232 REGEXP_SEQUENCE (regexp
)->regexps
[i
]
5233 = regexp_transform_func (REGEXP_SEQUENCE (regexp
)->regexps
[i
], func
);
5234 else if (regexp
->mode
== rm_allof
)
5235 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
5236 REGEXP_ALLOF (regexp
)->regexps
[i
]
5237 = regexp_transform_func (REGEXP_ALLOF (regexp
)->regexps
[i
], func
);
5238 else if (regexp
->mode
== rm_oneof
)
5239 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
5240 REGEXP_ONEOF (regexp
)->regexps
[i
]
5241 = regexp_transform_func (REGEXP_ONEOF (regexp
)->regexps
[i
], func
);
5242 else if (regexp
->mode
== rm_repeat
)
5243 REGEXP_REPEAT (regexp
)->regexp
5244 = regexp_transform_func (REGEXP_REPEAT (regexp
)->regexp
, func
);
5245 else if (regexp
->mode
!= rm_nothing
&& regexp
->mode
!= rm_unit
)
5247 return (*func
) (regexp
);
5250 /* The function applies all transformations for IR representation of
5251 reservation REGEXP. */
5253 transform_regexp (regexp_t regexp
)
5255 regexp
= regexp_transform_func (regexp
, transform_1
);
5258 regexp_transformed_p
= 0;
5259 regexp
= regexp_transform_func (regexp
, transform_2
);
5260 regexp
= regexp_transform_func (regexp
, transform_3
);
5262 while (regexp_transformed_p
);
5266 /* The function applies all transformations for reservations of all
5267 insn declarations. */
5269 transform_insn_regexps (void)
5274 transform_time
= create_ticker ();
5275 add_advance_cycle_insn_decl ();
5277 fprintf (stderr
, "Reservation transformation...");
5278 for (i
= 0; i
< description
->decls_num
; i
++)
5280 decl
= description
->decls
[i
];
5281 if (decl
->mode
== dm_insn_reserv
&& decl
!= advance_cycle_insn_decl
)
5282 DECL_INSN_RESERV (decl
)->transformed_regexp
5283 = transform_regexp (copy_insn_regexp
5284 (DECL_INSN_RESERV (decl
)->regexp
));
5287 fprintf (stderr
, "done\n");
5288 ticker_off (&transform_time
);
5293 /* The following variable value is TRUE if the first annotated message
5294 about units to automata distribution has been output. */
5295 static int annotation_message_reported_p
;
5297 /* The following structure describes usage of a unit in a reservation. */
5300 unit_decl_t unit_decl
;
5301 /* The following forms a list of units used on the same cycle in the
5302 same alternative. */
5303 struct unit_usage
*next
;
5306 /* Obstack for unit_usage structures. */
5307 static struct obstack unit_usages
;
5309 /* VLA for representation of array of pointers to unit usage
5310 structures. There is an element for each combination of
5311 (alternative number, cycle). Unit usages on given cycle in
5312 alternative with given number are referred through element with
5313 index equals to the cycle * number of all alternatives in the regexp
5314 + the alternative number. */
5315 static vla_ptr_t cycle_alt_unit_usages
;
5317 /* The following function creates the structure unit_usage for UNIT on
5318 CYCLE in REGEXP alternative with ALT_NUM. The structure is made
5319 accessed through cycle_alt_unit_usages. */
5321 store_alt_unit_usage (regexp_t regexp
, regexp_t unit
, int cycle
,
5324 size_t i
, length
, old_length
;
5325 unit_decl_t unit_decl
;
5326 struct unit_usage
*unit_usage_ptr
;
5329 if (regexp
== NULL
|| regexp
->mode
!= rm_oneof
5330 || alt_num
>= REGEXP_ONEOF (regexp
)->regexps_num
)
5332 unit_decl
= REGEXP_UNIT (unit
)->unit_decl
;
5333 old_length
= VLA_PTR_LENGTH (cycle_alt_unit_usages
);
5334 length
= (cycle
+ 1) * REGEXP_ONEOF (regexp
)->regexps_num
;
5335 if (old_length
< length
)
5337 VLA_PTR_EXPAND (cycle_alt_unit_usages
, length
- old_length
);
5338 for (i
= old_length
; i
< length
; i
++)
5339 VLA_PTR (cycle_alt_unit_usages
, i
) = NULL
;
5341 obstack_blank (&unit_usages
, sizeof (struct unit_usage
));
5342 unit_usage_ptr
= (struct unit_usage
*) obstack_base (&unit_usages
);
5343 obstack_finish (&unit_usages
);
5344 unit_usage_ptr
->unit_decl
= unit_decl
;
5345 index
= cycle
* REGEXP_ONEOF (regexp
)->regexps_num
+ alt_num
;
5346 unit_usage_ptr
->next
= VLA_PTR (cycle_alt_unit_usages
, index
);
5347 VLA_PTR (cycle_alt_unit_usages
, index
) = unit_usage_ptr
;
5348 unit_decl
->last_distribution_check_cycle
= -1; /* undefined */
5351 /* The function processes given REGEXP to find units with the wrong
5354 check_regexp_units_distribution (const char *insn_reserv_name
,
5358 regexp_t seq
, allof
, unit
;
5359 struct unit_usage
*unit_usage_ptr
, *other_unit_usage_ptr
;
5361 if (regexp
== NULL
|| regexp
->mode
!= rm_oneof
)
5363 /* Store all unit usages in the regexp: */
5364 obstack_init (&unit_usages
);
5365 VLA_PTR_CREATE (cycle_alt_unit_usages
, 100, "unit usages on cycles");
5366 for (i
= REGEXP_ONEOF (regexp
)->regexps_num
- 1; i
>= 0; i
--)
5368 seq
= REGEXP_ONEOF (regexp
)->regexps
[i
];
5369 if (seq
->mode
== rm_sequence
)
5370 for (j
= 0; j
< REGEXP_SEQUENCE (seq
)->regexps_num
; j
++)
5372 allof
= REGEXP_SEQUENCE (seq
)->regexps
[j
];
5373 if (allof
->mode
== rm_allof
)
5374 for (k
= 0; k
< REGEXP_ALLOF (allof
)->regexps_num
; k
++)
5376 unit
= REGEXP_ALLOF (allof
)->regexps
[k
];
5377 if (unit
->mode
== rm_unit
)
5378 store_alt_unit_usage (regexp
, unit
, j
, i
);
5379 else if (unit
->mode
!= rm_nothing
)
5382 else if (allof
->mode
== rm_unit
)
5383 store_alt_unit_usage (regexp
, allof
, j
, i
);
5384 else if (allof
->mode
!= rm_nothing
)
5387 else if (seq
->mode
== rm_allof
)
5388 for (k
= 0; k
< REGEXP_ALLOF (seq
)->regexps_num
; k
++)
5390 unit
= REGEXP_ALLOF (seq
)->regexps
[k
];
5391 if (unit
->mode
== rm_unit
)
5392 store_alt_unit_usage (regexp
, unit
, 0, i
);
5393 else if (unit
->mode
!= rm_nothing
)
5396 else if (seq
->mode
== rm_unit
)
5397 store_alt_unit_usage (regexp
, seq
, 0, i
);
5398 else if (seq
->mode
!= rm_nothing
)
5401 /* Check distribution: */
5402 for (i
= 0; i
< (int) VLA_PTR_LENGTH (cycle_alt_unit_usages
); i
++)
5404 cycle
= i
/ REGEXP_ONEOF (regexp
)->regexps_num
;
5405 for (unit_usage_ptr
= VLA_PTR (cycle_alt_unit_usages
, i
);
5406 unit_usage_ptr
!= NULL
;
5407 unit_usage_ptr
= unit_usage_ptr
->next
)
5408 if (cycle
!= unit_usage_ptr
->unit_decl
->last_distribution_check_cycle
)
5410 unit_usage_ptr
->unit_decl
->last_distribution_check_cycle
= cycle
;
5411 for (k
= cycle
* REGEXP_ONEOF (regexp
)->regexps_num
;
5412 k
< (int) VLA_PTR_LENGTH (cycle_alt_unit_usages
)
5413 && k
== cycle
* REGEXP_ONEOF (regexp
)->regexps_num
;
5416 for (other_unit_usage_ptr
= VLA_PTR (cycle_alt_unit_usages
, k
);
5417 other_unit_usage_ptr
!= NULL
;
5418 other_unit_usage_ptr
= other_unit_usage_ptr
->next
)
5419 if (unit_usage_ptr
->unit_decl
->automaton_decl
5420 == other_unit_usage_ptr
->unit_decl
->automaton_decl
)
5422 if (other_unit_usage_ptr
== NULL
5423 && VLA_PTR (cycle_alt_unit_usages
, k
) != NULL
)
5426 if (k
< (int) VLA_PTR_LENGTH (cycle_alt_unit_usages
)
5427 && k
== cycle
* REGEXP_ONEOF (regexp
)->regexps_num
)
5429 if (!annotation_message_reported_p
)
5431 fprintf (stderr
, "\n");
5432 error ("The following units do not satisfy units-automata distribution rule");
5433 error (" (A unit of given unit automaton should be on each reserv. altern.)");
5434 annotation_message_reported_p
= TRUE
;
5436 error ("Unit %s, reserv. %s, cycle %d",
5437 unit_usage_ptr
->unit_decl
->name
, insn_reserv_name
,
5442 VLA_PTR_DELETE (cycle_alt_unit_usages
);
5443 obstack_free (&unit_usages
, NULL
);
5446 /* The function finds units which violates units to automata
5447 distribution rule. If the units exist, report about them. */
5449 check_unit_distributions_to_automata (void)
5455 fprintf (stderr
, "Check unit distributions to automata...");
5456 annotation_message_reported_p
= FALSE
;
5457 for (i
= 0; i
< description
->decls_num
; i
++)
5459 decl
= description
->decls
[i
];
5460 if (decl
->mode
== dm_insn_reserv
)
5461 check_regexp_units_distribution
5462 (DECL_INSN_RESERV (decl
)->name
,
5463 DECL_INSN_RESERV (decl
)->transformed_regexp
);
5466 fprintf (stderr
, "done\n");
5471 /* The page contains code for building alt_states (see comments for
5472 IR) describing all possible insns reservations of an automaton. */
5474 /* Current state being formed for which the current alt_state
5476 static state_t state_being_formed
;
5478 /* Current alt_state being formed. */
5479 static alt_state_t alt_state_being_formed
;
5481 /* This recursive function processes `,' and units in reservation
5482 REGEXP for forming alt_states of AUTOMATON. It is believed that
5483 CURR_CYCLE is start cycle of all reservation REGEXP. */
5485 process_seq_for_forming_states (regexp_t regexp
, automaton_t automaton
,
5492 else if (regexp
->mode
== rm_unit
)
5494 if (REGEXP_UNIT (regexp
)->unit_decl
->corresponding_automaton_num
5495 == automaton
->automaton_order_num
)
5496 set_state_reserv (state_being_formed
, curr_cycle
,
5497 REGEXP_UNIT (regexp
)->unit_decl
->unit_num
);
5500 else if (regexp
->mode
== rm_sequence
)
5502 for (i
= 0; i
< REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
5504 = process_seq_for_forming_states
5505 (REGEXP_SEQUENCE (regexp
)->regexps
[i
], automaton
, curr_cycle
) + 1;
5508 else if (regexp
->mode
== rm_allof
)
5510 int finish_cycle
= 0;
5513 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
5515 cycle
= process_seq_for_forming_states (REGEXP_ALLOF (regexp
)
5517 automaton
, curr_cycle
);
5518 if (finish_cycle
< cycle
)
5519 finish_cycle
= cycle
;
5521 return finish_cycle
;
5525 if (regexp
->mode
!= rm_nothing
)
5531 /* This recursive function finishes forming ALT_STATE of AUTOMATON and
5532 inserts alt_state into the table. */
5534 finish_forming_alt_state (alt_state_t alt_state
,
5535 automaton_t automaton ATTRIBUTE_UNUSED
)
5537 state_t state_in_table
;
5538 state_t corresponding_state
;
5540 corresponding_state
= alt_state
->state
;
5541 state_in_table
= insert_state (corresponding_state
);
5542 if (state_in_table
!= corresponding_state
)
5544 free_state (corresponding_state
);
5545 alt_state
->state
= state_in_table
;
5549 /* The following variable value is current automaton insn for whose
5550 reservation the alt states are created. */
5551 static ainsn_t curr_ainsn
;
5553 /* This recursive function processes `|' in reservation REGEXP for
5554 forming alt_states of AUTOMATON. List of the alt states should
5555 have the same order as in the description. */
5557 process_alts_for_forming_states (regexp_t regexp
, automaton_t automaton
,
5562 if (regexp
->mode
!= rm_oneof
)
5564 alt_state_being_formed
= get_free_alt_state ();
5565 state_being_formed
= get_free_state (1, automaton
);
5566 alt_state_being_formed
->state
= state_being_formed
;
5567 /* We inserts in reverse order but we process alternatives also
5568 in reverse order. So we have the same order of alternative
5569 as in the description. */
5570 alt_state_being_formed
->next_alt_state
= curr_ainsn
->alt_states
;
5571 curr_ainsn
->alt_states
= alt_state_being_formed
;
5572 (void) process_seq_for_forming_states (regexp
, automaton
, 0);
5573 finish_forming_alt_state (alt_state_being_formed
, automaton
);
5579 /* We processes it in reverse order to get list with the same
5580 order as in the description. See also the previous
5582 for (i
= REGEXP_ONEOF (regexp
)->regexps_num
- 1; i
>= 0; i
--)
5583 process_alts_for_forming_states (REGEXP_ONEOF (regexp
)->regexps
[i
],
5588 /* Create nodes alt_state for all AUTOMATON insns. */
5590 create_alt_states (automaton_t automaton
)
5592 struct insn_reserv_decl
*reserv_decl
;
5594 for (curr_ainsn
= automaton
->ainsn_list
;
5596 curr_ainsn
= curr_ainsn
->next_ainsn
)
5598 reserv_decl
= curr_ainsn
->insn_reserv_decl
;
5599 if (reserv_decl
!= DECL_INSN_RESERV (advance_cycle_insn_decl
))
5601 curr_ainsn
->alt_states
= NULL
;
5602 process_alts_for_forming_states (reserv_decl
->transformed_regexp
,
5604 curr_ainsn
->sorted_alt_states
5605 = uniq_sort_alt_states (curr_ainsn
->alt_states
);
5612 /* The page contains major code for building DFA(s) for fast pipeline
5613 hazards recognition. */
5615 /* The function forms list of ainsns of AUTOMATON with the same
5618 form_ainsn_with_same_reservs (automaton_t automaton
)
5622 vla_ptr_t first_insns
;
5623 vla_ptr_t last_insns
;
5625 VLA_PTR_CREATE (first_insns
, 150, "first insns with the same reservs");
5626 VLA_PTR_CREATE (last_insns
, 150, "last insns with the same reservs");
5627 for (curr_ainsn
= automaton
->ainsn_list
;
5629 curr_ainsn
= curr_ainsn
->next_ainsn
)
5630 if (curr_ainsn
->insn_reserv_decl
5631 == DECL_INSN_RESERV (advance_cycle_insn_decl
))
5633 curr_ainsn
->next_same_reservs_insn
= NULL
;
5634 curr_ainsn
->first_insn_with_same_reservs
= 1;
5638 for (i
= 0; i
< VLA_PTR_LENGTH (first_insns
); i
++)
5640 (curr_ainsn
->sorted_alt_states
,
5641 ((ainsn_t
) VLA_PTR (first_insns
, i
))->sorted_alt_states
))
5643 curr_ainsn
->next_same_reservs_insn
= NULL
;
5644 if (i
< VLA_PTR_LENGTH (first_insns
))
5646 curr_ainsn
->first_insn_with_same_reservs
= 0;
5647 ((ainsn_t
) VLA_PTR (last_insns
, i
))->next_same_reservs_insn
5649 VLA_PTR (last_insns
, i
) = curr_ainsn
;
5653 VLA_PTR_ADD (first_insns
, curr_ainsn
);
5654 VLA_PTR_ADD (last_insns
, curr_ainsn
);
5655 curr_ainsn
->first_insn_with_same_reservs
= 1;
5658 VLA_PTR_DELETE (first_insns
);
5659 VLA_PTR_DELETE (last_insns
);
5662 /* Forming unit reservations which can affect creating the automaton
5663 states achieved from a given state. It permits to build smaller
5664 automata in many cases. We would have the same automata after
5665 the minimization without such optimization, but the automaton
5666 right after the building could be huge. So in other words, usage
5667 of reservs_matter means some minimization during building the
5669 static reserv_sets_t
5670 form_reservs_matter (automaton_t automaton
)
5673 reserv_sets_t reservs_matter
= alloc_empty_reserv_sets();
5675 for (cycle
= 0; cycle
< max_cycles_num
; cycle
++)
5676 for (unit
= 0; unit
< description
->units_num
; unit
++)
5677 if (units_array
[unit
]->automaton_decl
5678 == automaton
->corresponding_automaton_decl
5679 && (cycle
>= units_array
[unit
]->min_occ_cycle_num
5680 /* We can not remove queried unit from reservations. */
5681 || units_array
[unit
]->query_p
5682 /* We can not remove units which are used
5683 `exclusion_set', `presence_set',
5684 `final_presence_set', `absence_set', and
5685 `final_absence_set'. */
5686 || units_array
[unit
]->in_set_p
))
5687 set_unit_reserv (reservs_matter
, cycle
, unit
);
5688 return reservs_matter
;
5691 /* The following function creates all states of nondeterministic (if
5692 NDFA_FLAG has nonzero value) or deterministic AUTOMATON. */
5694 make_automaton (automaton_t automaton
)
5697 struct insn_reserv_decl
*insn_reserv_decl
;
5698 alt_state_t alt_state
;
5700 state_t start_state
;
5702 ainsn_t advance_cycle_ainsn
;
5704 vla_ptr_t state_stack
;
5706 reserv_sets_t reservs_matter
= form_reservs_matter (automaton
);
5708 VLA_PTR_CREATE (state_stack
, 150, "state stack");
5709 /* Create the start state (empty state). */
5710 start_state
= insert_state (get_free_state (1, automaton
));
5711 automaton
->start_state
= start_state
;
5712 start_state
->it_was_placed_in_stack_for_NDFA_forming
= 1;
5713 VLA_PTR_ADD (state_stack
, start_state
);
5715 while (VLA_PTR_LENGTH (state_stack
) != 0)
5717 state
= VLA_PTR (state_stack
, VLA_PTR_LENGTH (state_stack
) - 1);
5718 VLA_PTR_SHORTEN (state_stack
, 1);
5719 advance_cycle_ainsn
= NULL
;
5720 for (ainsn
= automaton
->ainsn_list
;
5722 ainsn
= ainsn
->next_ainsn
)
5723 if (ainsn
->first_insn_with_same_reservs
)
5725 insn_reserv_decl
= ainsn
->insn_reserv_decl
;
5726 if (insn_reserv_decl
!= DECL_INSN_RESERV (advance_cycle_insn_decl
))
5728 /* We process alt_states in the same order as they are
5729 present in the description. */
5731 for (alt_state
= ainsn
->alt_states
;
5733 alt_state
= alt_state
->next_alt_state
)
5735 state2
= alt_state
->state
;
5736 if (!intersected_state_reservs_p (state
, state2
))
5738 state2
= states_union (state
, state2
, reservs_matter
);
5739 if (!state2
->it_was_placed_in_stack_for_NDFA_forming
)
5741 state2
->it_was_placed_in_stack_for_NDFA_forming
5743 VLA_PTR_ADD (state_stack
, state2
);
5745 if (progress_flag
&& states_n
% 100 == 0)
5746 fprintf (stderr
, ".");
5748 added_arc
= add_arc (state
, state2
, ainsn
, 1);
5753 if (!ndfa_flag
&& added_arc
!= NULL
)
5755 added_arc
->state_alts
= 0;
5756 for (alt_state
= ainsn
->alt_states
;
5758 alt_state
= alt_state
->next_alt_state
)
5760 state2
= alt_state
->state
;
5761 if (!intersected_state_reservs_p (state
, state2
))
5762 added_arc
->state_alts
++;
5767 advance_cycle_ainsn
= ainsn
;
5769 /* Add transition to advance cycle. */
5770 state2
= state_shift (state
, reservs_matter
);
5771 if (!state2
->it_was_placed_in_stack_for_NDFA_forming
)
5773 state2
->it_was_placed_in_stack_for_NDFA_forming
= 1;
5774 VLA_PTR_ADD (state_stack
, state2
);
5776 if (progress_flag
&& states_n
% 100 == 0)
5777 fprintf (stderr
, ".");
5779 if (advance_cycle_ainsn
== NULL
)
5781 add_arc (state
, state2
, advance_cycle_ainsn
, 1);
5783 VLA_PTR_DELETE (state_stack
);
5786 /* Foms lists of all arcs of STATE marked by the same ainsn. */
5788 form_arcs_marked_by_insn (state_t state
)
5794 for (i
= 0; i
< description
->decls_num
; i
++)
5796 decl
= description
->decls
[i
];
5797 if (decl
->mode
== dm_insn_reserv
)
5798 DECL_INSN_RESERV (decl
)->arcs_marked_by_insn
= NULL
;
5800 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
5802 if (arc
->insn
== NULL
)
5804 arc
->next_arc_marked_by_insn
5805 = arc
->insn
->insn_reserv_decl
->arcs_marked_by_insn
;
5806 arc
->insn
->insn_reserv_decl
->arcs_marked_by_insn
= arc
;
5810 /* The function creates composed state (see comments for IR) from
5811 ORIGINAL_STATE and list of arcs ARCS_MARKED_BY_INSN marked by the
5812 same insn. If the composed state is not in STATE_STACK yet, it is
5813 pushed into STATE_STACK. */
5815 create_composed_state (state_t original_state
, arc_t arcs_marked_by_insn
,
5816 vla_ptr_t
*state_stack
)
5819 alt_state_t alt_state
, curr_alt_state
;
5820 alt_state_t new_alt_state
;
5823 state_t state_in_table
;
5825 alt_state_t canonical_alt_states_list
;
5827 int new_state_p
= 0;
5829 if (arcs_marked_by_insn
== NULL
)
5831 if (arcs_marked_by_insn
->next_arc_marked_by_insn
== NULL
)
5832 state
= arcs_marked_by_insn
->to_state
;
5837 /* Create composed state. */
5838 state
= get_free_state (0, arcs_marked_by_insn
->to_state
->automaton
);
5839 curr_alt_state
= NULL
;
5840 for (curr_arc
= arcs_marked_by_insn
;
5842 curr_arc
= curr_arc
->next_arc_marked_by_insn
)
5843 if (curr_arc
->to_state
->component_states
== NULL
)
5845 new_alt_state
= get_free_alt_state ();
5846 new_alt_state
->next_alt_state
= curr_alt_state
;
5847 new_alt_state
->state
= curr_arc
->to_state
;
5848 curr_alt_state
= new_alt_state
;
5851 for (alt_state
= curr_arc
->to_state
->component_states
;
5853 alt_state
= alt_state
->next_sorted_alt_state
)
5855 new_alt_state
= get_free_alt_state ();
5856 new_alt_state
->next_alt_state
= curr_alt_state
;
5857 new_alt_state
->state
= alt_state
->state
;
5858 if (alt_state
->state
->component_states
!= NULL
)
5860 curr_alt_state
= new_alt_state
;
5862 /* There are not identical sets in the alt state list. */
5863 canonical_alt_states_list
= uniq_sort_alt_states (curr_alt_state
);
5864 if (canonical_alt_states_list
->next_sorted_alt_state
== NULL
)
5867 state
= canonical_alt_states_list
->state
;
5868 free_state (temp_state
);
5872 state
->component_states
= canonical_alt_states_list
;
5873 state_in_table
= insert_state (state
);
5874 if (state_in_table
!= state
)
5876 if (!state_in_table
->it_was_placed_in_stack_for_DFA_forming
)
5879 state
= state_in_table
;
5883 if (state
->it_was_placed_in_stack_for_DFA_forming
)
5886 for (curr_alt_state
= state
->component_states
;
5887 curr_alt_state
!= NULL
;
5888 curr_alt_state
= curr_alt_state
->next_sorted_alt_state
)
5889 for (curr_arc
= first_out_arc (curr_alt_state
->state
);
5891 curr_arc
= next_out_arc (curr_arc
))
5892 add_arc (state
, curr_arc
->to_state
, curr_arc
->insn
, 1);
5894 arcs_marked_by_insn
->to_state
= state
;
5895 for (alts_number
= 0,
5896 curr_arc
= arcs_marked_by_insn
->next_arc_marked_by_insn
;
5898 curr_arc
= next_arc
)
5900 next_arc
= curr_arc
->next_arc_marked_by_insn
;
5901 remove_arc (original_state
, curr_arc
);
5904 arcs_marked_by_insn
->state_alts
= alts_number
;
5907 if (!state
->it_was_placed_in_stack_for_DFA_forming
)
5909 state
->it_was_placed_in_stack_for_DFA_forming
= 1;
5910 VLA_PTR_ADD (*state_stack
, state
);
5915 /* The function transforms nondeterministic AUTOMATON into
5918 NDFA_to_DFA (automaton_t automaton
)
5920 state_t start_state
;
5923 vla_ptr_t state_stack
;
5927 VLA_PTR_CREATE (state_stack
, 150, "state stack");
5928 /* Create the start state (empty state). */
5929 start_state
= automaton
->start_state
;
5930 start_state
->it_was_placed_in_stack_for_DFA_forming
= 1;
5931 VLA_PTR_ADD (state_stack
, start_state
);
5933 while (VLA_PTR_LENGTH (state_stack
) != 0)
5935 state
= VLA_PTR (state_stack
, VLA_PTR_LENGTH (state_stack
) - 1);
5936 VLA_PTR_SHORTEN (state_stack
, 1);
5937 form_arcs_marked_by_insn (state
);
5938 for (i
= 0; i
< description
->decls_num
; i
++)
5940 decl
= description
->decls
[i
];
5941 if (decl
->mode
== dm_insn_reserv
5942 && create_composed_state
5943 (state
, DECL_INSN_RESERV (decl
)->arcs_marked_by_insn
,
5947 if (progress_flag
&& states_n
% 100 == 0)
5948 fprintf (stderr
, ".");
5952 VLA_PTR_DELETE (state_stack
);
5955 /* The following variable value is current number (1, 2, ...) of passing
5957 static int curr_state_graph_pass_num
;
5959 /* This recursive function passes all states achieved from START_STATE
5960 and applies APPLIED_FUNC to them. */
5962 pass_state_graph (state_t start_state
, void (*applied_func
) (state_t state
))
5966 if (start_state
->pass_num
== curr_state_graph_pass_num
)
5968 start_state
->pass_num
= curr_state_graph_pass_num
;
5969 (*applied_func
) (start_state
);
5970 for (arc
= first_out_arc (start_state
);
5972 arc
= next_out_arc (arc
))
5973 pass_state_graph (arc
->to_state
, applied_func
);
5976 /* This recursive function passes all states of AUTOMATON and applies
5977 APPLIED_FUNC to them. */
5979 pass_states (automaton_t automaton
, void (*applied_func
) (state_t state
))
5981 curr_state_graph_pass_num
++;
5982 pass_state_graph (automaton
->start_state
, applied_func
);
5985 /* The function initializes code for passing of all states. */
5987 initiate_pass_states (void)
5989 curr_state_graph_pass_num
= 0;
5992 /* The following vla is used for storing pointers to all achieved
5994 static vla_ptr_t all_achieved_states
;
5996 /* This function is called by function pass_states to add an achieved
5999 add_achieved_state (state_t state
)
6001 VLA_PTR_ADD (all_achieved_states
, state
);
6004 /* The function sets up equivalence numbers of insns which mark all
6005 out arcs of STATE by equiv_class_num_1 (if ODD_ITERATION_FLAG has
6006 nonzero value) or by equiv_class_num_2 of the destination state.
6007 The function returns number of out arcs of STATE. */
6009 set_out_arc_insns_equiv_num (state_t state
, int odd_iteration_flag
)
6011 int state_out_arcs_num
;
6014 state_out_arcs_num
= 0;
6015 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
6017 if (arc
->insn
->insn_reserv_decl
->equiv_class_num
!= 0
6018 || arc
->insn
->insn_reserv_decl
->state_alts
!= 0)
6020 state_out_arcs_num
++;
6021 arc
->insn
->insn_reserv_decl
->equiv_class_num
6022 = (odd_iteration_flag
6023 ? arc
->to_state
->equiv_class_num_1
6024 : arc
->to_state
->equiv_class_num_2
);
6025 arc
->insn
->insn_reserv_decl
->state_alts
= arc
->state_alts
;
6026 if (arc
->insn
->insn_reserv_decl
->equiv_class_num
== 0
6027 || arc
->insn
->insn_reserv_decl
->state_alts
<= 0)
6030 return state_out_arcs_num
;
6033 /* The function clears equivalence numbers and alt_states in all insns
6034 which mark all out arcs of STATE. */
6036 clear_arc_insns_equiv_num (state_t state
)
6040 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
6042 arc
->insn
->insn_reserv_decl
->equiv_class_num
= 0;
6043 arc
->insn
->insn_reserv_decl
->state_alts
= 0;
6047 /* The function copies pointers to equivalent states from vla FROM
6050 copy_equiv_class (vla_ptr_t
*to
, const vla_ptr_t
*from
)
6054 VLA_PTR_NULLIFY (*to
);
6055 for (class_ptr
= VLA_PTR_BEGIN (*from
);
6056 class_ptr
<= (state_t
*) VLA_PTR_LAST (*from
);
6058 VLA_PTR_ADD (*to
, *class_ptr
);
6061 /* The following function returns TRUE if STATE reserves the unit with
6062 UNIT_NUM on the first cycle. */
6064 first_cycle_unit_presence (state_t state
, int unit_num
)
6068 if (state
->component_states
== NULL
)
6069 presence_p
= test_unit_reserv (state
->reservs
, 0, unit_num
);
6072 = test_unit_reserv (state
->component_states
->state
->reservs
,
6077 /* The function returns nonzero value if STATE is not equivalent to
6078 ANOTHER_STATE from the same current partition on equivalence
6079 classes. Another state has ANOTHER_STATE_OUT_ARCS_NUM number of
6080 output arcs. Iteration of making equivalence partition is defined
6081 by ODD_ITERATION_FLAG. */
6083 state_is_differed (state_t state
, state_t another_state
,
6084 int another_state_out_arcs_num
, int odd_iteration_flag
)
6087 int state_out_arcs_num
;
6088 int i
, presence1_p
, presence2_p
;
6090 state_out_arcs_num
= 0;
6091 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
6093 state_out_arcs_num
++;
6094 if ((odd_iteration_flag
6095 ? arc
->to_state
->equiv_class_num_1
6096 : arc
->to_state
->equiv_class_num_2
)
6097 != arc
->insn
->insn_reserv_decl
->equiv_class_num
6098 || (arc
->insn
->insn_reserv_decl
->state_alts
!= arc
->state_alts
))
6101 if (state_out_arcs_num
!= another_state_out_arcs_num
)
6103 /* Now we are looking at the states with the point of view of query
6105 for (i
= 0; i
< description
->units_num
; i
++)
6106 if (units_array
[i
]->query_p
)
6108 presence1_p
= first_cycle_unit_presence (state
, i
);
6109 presence2_p
= first_cycle_unit_presence (another_state
, i
);
6110 if ((presence1_p
&& !presence2_p
) || (!presence1_p
&& presence2_p
))
6116 /* The function makes initial partition of STATES on equivalent
6119 init_equiv_class (state_t
*states
, int states_num
)
6122 state_t result_equiv_class
;
6124 result_equiv_class
= NULL
;
6125 for (state_ptr
= states
; state_ptr
< states
+ states_num
; state_ptr
++)
6127 (*state_ptr
)->equiv_class_num_1
= 1;
6128 (*state_ptr
)->next_equiv_class_state
= result_equiv_class
;
6129 result_equiv_class
= *state_ptr
;
6131 return result_equiv_class
;
6134 /* The function processes equivalence class given by its pointer
6135 EQUIV_CLASS_PTR on odd iteration if ODD_ITERATION_FLAG. If there
6136 are not equivalent states, the function partitions the class
6137 removing nonequivalent states and placing them in
6138 *NEXT_ITERATION_CLASSES, increments *NEW_EQUIV_CLASS_NUM_PTR ans
6139 assigns it to the state equivalence number. If the class has been
6140 partitioned, the function returns nonzero value. */
6142 partition_equiv_class (state_t
*equiv_class_ptr
, int odd_iteration_flag
,
6143 vla_ptr_t
*next_iteration_classes
,
6144 int *new_equiv_class_num_ptr
)
6146 state_t new_equiv_class
;
6148 state_t first_state
;
6155 if (*equiv_class_ptr
== NULL
)
6157 for (first_state
= *equiv_class_ptr
;
6158 first_state
!= NULL
;
6159 first_state
= new_equiv_class
)
6161 new_equiv_class
= NULL
;
6162 if (first_state
->next_equiv_class_state
!= NULL
)
6164 /* There are more one states in the class equivalence. */
6165 out_arcs_num
= set_out_arc_insns_equiv_num (first_state
,
6166 odd_iteration_flag
);
6167 for (prev_state
= first_state
,
6168 curr_state
= first_state
->next_equiv_class_state
;
6170 curr_state
= next_state
)
6172 next_state
= curr_state
->next_equiv_class_state
;
6173 if (state_is_differed (curr_state
, first_state
, out_arcs_num
,
6174 odd_iteration_flag
))
6176 /* Remove curr state from the class equivalence. */
6177 prev_state
->next_equiv_class_state
= next_state
;
6178 /* Add curr state to the new class equivalence. */
6179 curr_state
->next_equiv_class_state
= new_equiv_class
;
6180 if (new_equiv_class
== NULL
)
6181 (*new_equiv_class_num_ptr
)++;
6182 if (odd_iteration_flag
)
6183 curr_state
->equiv_class_num_2
= *new_equiv_class_num_ptr
;
6185 curr_state
->equiv_class_num_1
= *new_equiv_class_num_ptr
;
6186 new_equiv_class
= curr_state
;
6190 prev_state
= curr_state
;
6192 clear_arc_insns_equiv_num (first_state
);
6194 if (new_equiv_class
!= NULL
)
6195 VLA_PTR_ADD (*next_iteration_classes
, new_equiv_class
);
6200 /* The function finds equivalent states of AUTOMATON. */
6202 evaluate_equiv_classes (automaton_t automaton
, vla_ptr_t
*equiv_classes
)
6204 state_t new_equiv_class
;
6205 int new_equiv_class_num
;
6206 int odd_iteration_flag
;
6208 vla_ptr_t next_iteration_classes
;
6209 state_t
*equiv_class_ptr
;
6212 VLA_PTR_CREATE (all_achieved_states
, 1500, "all achieved states");
6213 pass_states (automaton
, add_achieved_state
);
6214 new_equiv_class
= init_equiv_class (VLA_PTR_BEGIN (all_achieved_states
),
6215 VLA_PTR_LENGTH (all_achieved_states
));
6216 odd_iteration_flag
= 0;
6217 new_equiv_class_num
= 1;
6218 VLA_PTR_CREATE (next_iteration_classes
, 150, "next iteration classes");
6219 VLA_PTR_ADD (next_iteration_classes
, new_equiv_class
);
6222 odd_iteration_flag
= !odd_iteration_flag
;
6224 copy_equiv_class (equiv_classes
, &next_iteration_classes
);
6225 /* Transfer equiv numbers for the next iteration. */
6226 for (state_ptr
= VLA_PTR_BEGIN (all_achieved_states
);
6227 state_ptr
<= (state_t
*) VLA_PTR_LAST (all_achieved_states
);
6229 if (odd_iteration_flag
)
6230 (*state_ptr
)->equiv_class_num_2
= (*state_ptr
)->equiv_class_num_1
;
6232 (*state_ptr
)->equiv_class_num_1
= (*state_ptr
)->equiv_class_num_2
;
6233 for (equiv_class_ptr
= VLA_PTR_BEGIN (*equiv_classes
);
6234 equiv_class_ptr
<= (state_t
*) VLA_PTR_LAST (*equiv_classes
);
6236 if (partition_equiv_class (equiv_class_ptr
, odd_iteration_flag
,
6237 &next_iteration_classes
,
6238 &new_equiv_class_num
))
6241 while (!finish_flag
);
6242 VLA_PTR_DELETE (next_iteration_classes
);
6243 VLA_PTR_DELETE (all_achieved_states
);
6246 /* The function merges equivalent states of AUTOMATON. */
6248 merge_states (automaton_t automaton
, vla_ptr_t
*equiv_classes
)
6250 state_t
*equiv_class_ptr
;
6253 state_t first_class_state
;
6254 alt_state_t alt_states
;
6255 alt_state_t alt_state
, new_alt_state
;
6259 /* Create states corresponding to equivalence classes containing two
6261 for (equiv_class_ptr
= VLA_PTR_BEGIN (*equiv_classes
);
6262 equiv_class_ptr
<= (state_t
*) VLA_PTR_LAST (*equiv_classes
);
6264 if ((*equiv_class_ptr
)->next_equiv_class_state
!= NULL
)
6266 /* There are more one states in the class equivalence. */
6267 /* Create new compound state. */
6268 new_state
= get_free_state (0, automaton
);
6270 first_class_state
= *equiv_class_ptr
;
6271 for (curr_state
= first_class_state
;
6273 curr_state
= curr_state
->next_equiv_class_state
)
6275 curr_state
->equiv_class_state
= new_state
;
6276 if (curr_state
->component_states
== NULL
)
6278 new_alt_state
= get_free_alt_state ();
6279 new_alt_state
->state
= curr_state
;
6280 new_alt_state
->next_alt_state
= alt_states
;
6281 alt_states
= new_alt_state
;
6284 for (alt_state
= curr_state
->component_states
;
6286 alt_state
= alt_state
->next_sorted_alt_state
)
6288 new_alt_state
= get_free_alt_state ();
6289 new_alt_state
->state
= alt_state
->state
;
6290 new_alt_state
->next_alt_state
= alt_states
;
6291 alt_states
= new_alt_state
;
6294 /* Its is important that alt states were sorted before and
6295 after merging to have the same querying results. */
6296 new_state
->component_states
= uniq_sort_alt_states (alt_states
);
6299 (*equiv_class_ptr
)->equiv_class_state
= *equiv_class_ptr
;
6300 for (equiv_class_ptr
= VLA_PTR_BEGIN (*equiv_classes
);
6301 equiv_class_ptr
<= (state_t
*) VLA_PTR_LAST (*equiv_classes
);
6303 if ((*equiv_class_ptr
)->next_equiv_class_state
!= NULL
)
6305 first_class_state
= *equiv_class_ptr
;
6306 /* Create new arcs output from the state corresponding to
6308 for (curr_arc
= first_out_arc (first_class_state
);
6310 curr_arc
= next_out_arc (curr_arc
))
6311 add_arc (first_class_state
->equiv_class_state
,
6312 curr_arc
->to_state
->equiv_class_state
,
6313 curr_arc
->insn
, curr_arc
->state_alts
);
6314 /* Delete output arcs from states of given class equivalence. */
6315 for (curr_state
= first_class_state
;
6317 curr_state
= curr_state
->next_equiv_class_state
)
6319 if (automaton
->start_state
== curr_state
)
6320 automaton
->start_state
= curr_state
->equiv_class_state
;
6321 /* Delete the state and its output arcs. */
6322 for (curr_arc
= first_out_arc (curr_state
);
6324 curr_arc
= next_arc
)
6326 next_arc
= next_out_arc (curr_arc
);
6327 free_arc (curr_arc
);
6333 /* Change `to_state' of arcs output from the state of given
6334 equivalence class. */
6335 for (curr_arc
= first_out_arc (*equiv_class_ptr
);
6337 curr_arc
= next_out_arc (curr_arc
))
6338 curr_arc
->to_state
= curr_arc
->to_state
->equiv_class_state
;
6342 /* The function sets up new_cycle_p for states if there is arc to the
6343 state marked by advance_cycle_insn_decl. */
6345 set_new_cycle_flags (state_t state
)
6349 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
6350 if (arc
->insn
->insn_reserv_decl
6351 == DECL_INSN_RESERV (advance_cycle_insn_decl
))
6352 arc
->to_state
->new_cycle_p
= 1;
6355 /* The top level function for minimization of deterministic
6358 minimize_DFA (automaton_t automaton
)
6360 vla_ptr_t equiv_classes
;
6362 VLA_PTR_CREATE (equiv_classes
, 1500, "equivalence classes");
6363 evaluate_equiv_classes (automaton
, &equiv_classes
);
6364 merge_states (automaton
, &equiv_classes
);
6365 pass_states (automaton
, set_new_cycle_flags
);
6366 VLA_PTR_DELETE (equiv_classes
);
6369 /* Values of two variables are counted number of states and arcs in an
6371 static int curr_counted_states_num
;
6372 static int curr_counted_arcs_num
;
6374 /* The function is called by function `pass_states' to count states
6375 and arcs of an automaton. */
6377 incr_states_and_arcs_nums (state_t state
)
6381 curr_counted_states_num
++;
6382 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
6383 curr_counted_arcs_num
++;
6386 /* The function counts states and arcs of AUTOMATON. */
6388 count_states_and_arcs (automaton_t automaton
, int *states_num
,
6391 curr_counted_states_num
= 0;
6392 curr_counted_arcs_num
= 0;
6393 pass_states (automaton
, incr_states_and_arcs_nums
);
6394 *states_num
= curr_counted_states_num
;
6395 *arcs_num
= curr_counted_arcs_num
;
6398 /* The function builds one DFA AUTOMATON for fast pipeline hazards
6399 recognition after checking and simplifying IR of the
6402 build_automaton (automaton_t automaton
)
6407 ticker_on (&NDFA_time
);
6410 if (automaton
->corresponding_automaton_decl
== NULL
)
6411 fprintf (stderr
, "Create anonymous automaton");
6413 fprintf (stderr
, "Create automaton `%s'",
6414 automaton
->corresponding_automaton_decl
->name
);
6415 fprintf (stderr
, " (1 dot is 100 new states):");
6417 make_automaton (automaton
);
6419 fprintf (stderr
, " done\n");
6420 ticker_off (&NDFA_time
);
6421 count_states_and_arcs (automaton
, &states_num
, &arcs_num
);
6422 automaton
->NDFA_states_num
= states_num
;
6423 automaton
->NDFA_arcs_num
= arcs_num
;
6424 ticker_on (&NDFA_to_DFA_time
);
6427 if (automaton
->corresponding_automaton_decl
== NULL
)
6428 fprintf (stderr
, "Make anonymous DFA");
6430 fprintf (stderr
, "Make DFA `%s'",
6431 automaton
->corresponding_automaton_decl
->name
);
6432 fprintf (stderr
, " (1 dot is 100 new states):");
6434 NDFA_to_DFA (automaton
);
6436 fprintf (stderr
, " done\n");
6437 ticker_off (&NDFA_to_DFA_time
);
6438 count_states_and_arcs (automaton
, &states_num
, &arcs_num
);
6439 automaton
->DFA_states_num
= states_num
;
6440 automaton
->DFA_arcs_num
= arcs_num
;
6441 if (!no_minimization_flag
)
6443 ticker_on (&minimize_time
);
6446 if (automaton
->corresponding_automaton_decl
== NULL
)
6447 fprintf (stderr
, "Minimize anonymous DFA...");
6449 fprintf (stderr
, "Minimize DFA `%s'...",
6450 automaton
->corresponding_automaton_decl
->name
);
6452 minimize_DFA (automaton
);
6454 fprintf (stderr
, "done\n");
6455 ticker_off (&minimize_time
);
6456 count_states_and_arcs (automaton
, &states_num
, &arcs_num
);
6457 automaton
->minimal_DFA_states_num
= states_num
;
6458 automaton
->minimal_DFA_arcs_num
= arcs_num
;
6464 /* The page contains code for enumeration of all states of an automaton. */
6466 /* Variable used for enumeration of all states of an automaton. Its
6467 value is current number of automaton states. */
6468 static int curr_state_order_num
;
6470 /* The function is called by function `pass_states' for enumerating
6473 set_order_state_num (state_t state
)
6475 state
->order_state_num
= curr_state_order_num
;
6476 curr_state_order_num
++;
6479 /* The function enumerates all states of AUTOMATON. */
6481 enumerate_states (automaton_t automaton
)
6483 curr_state_order_num
= 0;
6484 pass_states (automaton
, set_order_state_num
);
6485 automaton
->achieved_states_num
= curr_state_order_num
;
6490 /* The page contains code for finding equivalent automaton insns
6493 /* The function inserts AINSN into cyclic list
6494 CYCLIC_EQUIV_CLASS_INSN_LIST of ainsns. */
6496 insert_ainsn_into_equiv_class (ainsn_t ainsn
,
6497 ainsn_t cyclic_equiv_class_insn_list
)
6499 if (cyclic_equiv_class_insn_list
== NULL
)
6500 ainsn
->next_equiv_class_insn
= ainsn
;
6503 ainsn
->next_equiv_class_insn
6504 = cyclic_equiv_class_insn_list
->next_equiv_class_insn
;
6505 cyclic_equiv_class_insn_list
->next_equiv_class_insn
= ainsn
;
6510 /* The function deletes equiv_class_insn into cyclic list of
6511 equivalent ainsns. */
6513 delete_ainsn_from_equiv_class (ainsn_t equiv_class_insn
)
6515 ainsn_t curr_equiv_class_insn
;
6516 ainsn_t prev_equiv_class_insn
;
6518 prev_equiv_class_insn
= equiv_class_insn
;
6519 for (curr_equiv_class_insn
= equiv_class_insn
->next_equiv_class_insn
;
6520 curr_equiv_class_insn
!= equiv_class_insn
;
6521 curr_equiv_class_insn
= curr_equiv_class_insn
->next_equiv_class_insn
)
6522 prev_equiv_class_insn
= curr_equiv_class_insn
;
6523 if (prev_equiv_class_insn
!= equiv_class_insn
)
6524 prev_equiv_class_insn
->next_equiv_class_insn
6525 = equiv_class_insn
->next_equiv_class_insn
;
6528 /* The function processes AINSN of a state in order to find equivalent
6529 ainsns. INSN_ARCS_ARRAY is table: code of insn -> out arc of the
6532 process_insn_equiv_class (ainsn_t ainsn
, arc_t
*insn_arcs_array
)
6536 ainsn_t cyclic_insn_list
;
6539 if (insn_arcs_array
[ainsn
->insn_reserv_decl
->insn_num
] == NULL
)
6542 /* New class of ainsns which are not equivalent to given ainsn. */
6543 cyclic_insn_list
= NULL
;
6546 next_insn
= curr_insn
->next_equiv_class_insn
;
6547 arc
= insn_arcs_array
[curr_insn
->insn_reserv_decl
->insn_num
];
6549 || (insn_arcs_array
[ainsn
->insn_reserv_decl
->insn_num
]->to_state
6552 delete_ainsn_from_equiv_class (curr_insn
);
6553 cyclic_insn_list
= insert_ainsn_into_equiv_class (curr_insn
,
6556 curr_insn
= next_insn
;
6558 while (curr_insn
!= ainsn
);
6561 /* The function processes STATE in order to find equivalent ainsns. */
6563 process_state_for_insn_equiv_partition (state_t state
)
6566 arc_t
*insn_arcs_array
;
6568 vla_ptr_t insn_arcs_vect
;
6570 VLA_PTR_CREATE (insn_arcs_vect
, 500, "insn arcs vector");
6571 VLA_PTR_EXPAND (insn_arcs_vect
, description
->insns_num
);
6572 insn_arcs_array
= VLA_PTR_BEGIN (insn_arcs_vect
);
6573 /* Process insns of the arcs. */
6574 for (i
= 0; i
< description
->insns_num
; i
++)
6575 insn_arcs_array
[i
] = NULL
;
6576 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
6577 insn_arcs_array
[arc
->insn
->insn_reserv_decl
->insn_num
] = arc
;
6578 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
6579 process_insn_equiv_class (arc
->insn
, insn_arcs_array
);
6580 VLA_PTR_DELETE (insn_arcs_vect
);
6583 /* The function searches for equivalent ainsns of AUTOMATON. */
6585 set_insn_equiv_classes (automaton_t automaton
)
6590 ainsn_t cyclic_insn_list
;
6591 ainsn_t insn_with_same_reservs
;
6592 int equiv_classes_num
;
6594 /* All insns are included in one equivalence class. */
6595 cyclic_insn_list
= NULL
;
6596 for (ainsn
= automaton
->ainsn_list
; ainsn
!= NULL
; ainsn
= ainsn
->next_ainsn
)
6597 if (ainsn
->first_insn_with_same_reservs
)
6598 cyclic_insn_list
= insert_ainsn_into_equiv_class (ainsn
,
6600 /* Process insns in order to make equivalence partition. */
6601 pass_states (automaton
, process_state_for_insn_equiv_partition
);
6602 /* Enumerate equiv classes. */
6603 for (ainsn
= automaton
->ainsn_list
; ainsn
!= NULL
; ainsn
= ainsn
->next_ainsn
)
6604 /* Set undefined value. */
6605 ainsn
->insn_equiv_class_num
= -1;
6606 equiv_classes_num
= 0;
6607 for (ainsn
= automaton
->ainsn_list
; ainsn
!= NULL
; ainsn
= ainsn
->next_ainsn
)
6608 if (ainsn
->insn_equiv_class_num
< 0)
6611 if (!first_insn
->first_insn_with_same_reservs
)
6613 first_insn
->first_ainsn_with_given_equivalence_num
= 1;
6614 curr_insn
= first_insn
;
6617 for (insn_with_same_reservs
= curr_insn
;
6618 insn_with_same_reservs
!= NULL
;
6619 insn_with_same_reservs
6620 = insn_with_same_reservs
->next_same_reservs_insn
)
6621 insn_with_same_reservs
->insn_equiv_class_num
= equiv_classes_num
;
6622 curr_insn
= curr_insn
->next_equiv_class_insn
;
6624 while (curr_insn
!= first_insn
);
6625 equiv_classes_num
++;
6627 automaton
->insn_equiv_classes_num
= equiv_classes_num
;
6632 /* This page contains code for creating DFA(s) and calls functions
6636 /* The following value is used to prevent floating point overflow for
6637 estimating an automaton bound. The value should be less DBL_MAX on
6638 the host machine. We use here approximate minimum of maximal
6639 double floating point value required by ANSI C standard. It
6640 will work for non ANSI sun compiler too. */
6642 #define MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND 1.0E37
6644 /* The function estimate size of the single DFA used by PHR (pipeline
6645 hazards recognizer). */
6647 estimate_one_automaton_bound (void)
6650 double one_automaton_estimation_bound
;
6654 one_automaton_estimation_bound
= 1.0;
6655 for (i
= 0; i
< description
->decls_num
; i
++)
6657 decl
= description
->decls
[i
];
6658 if (decl
->mode
== dm_unit
)
6660 root_value
= exp (log (DECL_UNIT (decl
)->max_occ_cycle_num
6661 - DECL_UNIT (decl
)->min_occ_cycle_num
+ 1.0)
6663 if (MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND
/ root_value
6664 > one_automaton_estimation_bound
)
6665 one_automaton_estimation_bound
*= root_value
;
6668 return one_automaton_estimation_bound
;
6671 /* The function compares unit declarations according to their maximal
6672 cycle in reservations. */
6674 compare_max_occ_cycle_nums (const void *unit_decl_1
,
6675 const void *unit_decl_2
)
6677 if ((DECL_UNIT (*(decl_t
*) unit_decl_1
)->max_occ_cycle_num
)
6678 < (DECL_UNIT (*(decl_t
*) unit_decl_2
)->max_occ_cycle_num
))
6680 else if ((DECL_UNIT (*(decl_t
*) unit_decl_1
)->max_occ_cycle_num
)
6681 == (DECL_UNIT (*(decl_t
*) unit_decl_2
)->max_occ_cycle_num
))
6687 /* The function makes heuristic assigning automata to units. Actually
6688 efficacy of the algorithm has been checked yet??? */
6690 units_to_automata_heuristic_distr (void)
6692 double estimation_bound
;
6694 decl_t
*unit_decl_ptr
;
6698 vla_ptr_t unit_decls
;
6701 if (description
->units_num
== 0)
6703 estimation_bound
= estimate_one_automaton_bound ();
6704 VLA_PTR_CREATE (unit_decls
, 150, "unit decls");
6705 for (i
= 0; i
< description
->decls_num
; i
++)
6707 decl
= description
->decls
[i
];
6708 if (decl
->mode
== dm_unit
)
6709 VLA_PTR_ADD (unit_decls
, decl
);
6711 qsort (VLA_PTR_BEGIN (unit_decls
), VLA_PTR_LENGTH (unit_decls
),
6712 sizeof (decl_t
), compare_max_occ_cycle_nums
);
6714 unit_decl_ptr
= VLA_PTR_BEGIN (unit_decls
);
6715 bound_value
= DECL_UNIT (*unit_decl_ptr
)->max_occ_cycle_num
;
6716 DECL_UNIT (*unit_decl_ptr
)->corresponding_automaton_num
= automaton_num
;
6717 for (unit_decl_ptr
++;
6718 unit_decl_ptr
<= (decl_t
*) VLA_PTR_LAST (unit_decls
);
6722 = ((decl_t
*) VLA_PTR_LAST (unit_decls
) - unit_decl_ptr
+ 1);
6723 if (automata_num
- automaton_num
- 1 > rest_units_num
)
6725 if (automaton_num
< automata_num
- 1
6726 && ((automata_num
- automaton_num
- 1 == rest_units_num
)
6729 / (DECL_UNIT (*unit_decl_ptr
)->max_occ_cycle_num
)))))
6731 bound_value
= DECL_UNIT (*unit_decl_ptr
)->max_occ_cycle_num
;
6735 bound_value
*= DECL_UNIT (*unit_decl_ptr
)->max_occ_cycle_num
;
6736 DECL_UNIT (*unit_decl_ptr
)->corresponding_automaton_num
= automaton_num
;
6738 if (automaton_num
!= automata_num
- 1)
6740 VLA_PTR_DELETE (unit_decls
);
6743 /* The functions creates automaton insns for each automata. Automaton
6744 insn is simply insn for given automaton which makes reservation
6745 only of units of the automaton. */
6747 create_ainsns (void)
6750 ainsn_t first_ainsn
;
6757 for (i
= 0; i
< description
->decls_num
; i
++)
6759 decl
= description
->decls
[i
];
6760 if (decl
->mode
== dm_insn_reserv
)
6762 curr_ainsn
= create_node (sizeof (struct ainsn
));
6763 curr_ainsn
->insn_reserv_decl
= DECL_INSN_RESERV (decl
);
6764 curr_ainsn
->important_p
= FALSE
;
6765 curr_ainsn
->next_ainsn
= NULL
;
6766 if (prev_ainsn
== NULL
)
6767 first_ainsn
= curr_ainsn
;
6769 prev_ainsn
->next_ainsn
= curr_ainsn
;
6770 prev_ainsn
= curr_ainsn
;
6776 /* The function assigns automata to units according to constructions
6777 `define_automaton' in the description. */
6779 units_to_automata_distr (void)
6784 for (i
= 0; i
< description
->decls_num
; i
++)
6786 decl
= description
->decls
[i
];
6787 if (decl
->mode
== dm_unit
)
6789 if (DECL_UNIT (decl
)->automaton_decl
== NULL
6790 || (DECL_UNIT (decl
)->automaton_decl
->corresponding_automaton
6792 /* Distribute to the first automaton. */
6793 DECL_UNIT (decl
)->corresponding_automaton_num
= 0;
6795 DECL_UNIT (decl
)->corresponding_automaton_num
6796 = (DECL_UNIT (decl
)->automaton_decl
6797 ->corresponding_automaton
->automaton_order_num
);
6802 /* The function creates DFA(s) for fast pipeline hazards recognition
6803 after checking and simplifying IR of the description. */
6805 create_automata (void)
6807 automaton_t curr_automaton
;
6808 automaton_t prev_automaton
;
6810 int curr_automaton_num
;
6813 if (automata_num
!= 0)
6815 units_to_automata_heuristic_distr ();
6816 for (prev_automaton
= NULL
, curr_automaton_num
= 0;
6817 curr_automaton_num
< automata_num
;
6818 curr_automaton_num
++, prev_automaton
= curr_automaton
)
6820 curr_automaton
= create_node (sizeof (struct automaton
));
6821 curr_automaton
->ainsn_list
= create_ainsns ();
6822 curr_automaton
->corresponding_automaton_decl
= NULL
;
6823 curr_automaton
->next_automaton
= NULL
;
6824 curr_automaton
->automaton_order_num
= curr_automaton_num
;
6825 if (prev_automaton
== NULL
)
6826 description
->first_automaton
= curr_automaton
;
6828 prev_automaton
->next_automaton
= curr_automaton
;
6833 curr_automaton_num
= 0;
6834 prev_automaton
= NULL
;
6835 for (i
= 0; i
< description
->decls_num
; i
++)
6837 decl
= description
->decls
[i
];
6838 if (decl
->mode
== dm_automaton
6839 && DECL_AUTOMATON (decl
)->automaton_is_used
)
6841 curr_automaton
= create_node (sizeof (struct automaton
));
6842 curr_automaton
->ainsn_list
= create_ainsns ();
6843 curr_automaton
->corresponding_automaton_decl
6844 = DECL_AUTOMATON (decl
);
6845 curr_automaton
->next_automaton
= NULL
;
6846 DECL_AUTOMATON (decl
)->corresponding_automaton
= curr_automaton
;
6847 curr_automaton
->automaton_order_num
= curr_automaton_num
;
6848 if (prev_automaton
== NULL
)
6849 description
->first_automaton
= curr_automaton
;
6851 prev_automaton
->next_automaton
= curr_automaton
;
6852 curr_automaton_num
++;
6853 prev_automaton
= curr_automaton
;
6856 if (curr_automaton_num
== 0)
6858 curr_automaton
= create_node (sizeof (struct automaton
));
6859 curr_automaton
->ainsn_list
= create_ainsns ();
6860 curr_automaton
->corresponding_automaton_decl
= NULL
;
6861 curr_automaton
->next_automaton
= NULL
;
6862 description
->first_automaton
= curr_automaton
;
6864 units_to_automata_distr ();
6866 NDFA_time
= create_ticker ();
6867 ticker_off (&NDFA_time
);
6868 NDFA_to_DFA_time
= create_ticker ();
6869 ticker_off (&NDFA_to_DFA_time
);
6870 minimize_time
= create_ticker ();
6871 ticker_off (&minimize_time
);
6872 equiv_time
= create_ticker ();
6873 ticker_off (&equiv_time
);
6874 for (curr_automaton
= description
->first_automaton
;
6875 curr_automaton
!= NULL
;
6876 curr_automaton
= curr_automaton
->next_automaton
)
6880 if (curr_automaton
->corresponding_automaton_decl
== NULL
)
6881 fprintf (stderr
, "Prepare anonymous automaton creation ... ");
6883 fprintf (stderr
, "Prepare automaton `%s' creation...",
6884 curr_automaton
->corresponding_automaton_decl
->name
);
6886 create_alt_states (curr_automaton
);
6887 form_ainsn_with_same_reservs (curr_automaton
);
6889 fprintf (stderr
, "done\n");
6890 build_automaton (curr_automaton
);
6891 enumerate_states (curr_automaton
);
6892 ticker_on (&equiv_time
);
6893 set_insn_equiv_classes (curr_automaton
);
6894 ticker_off (&equiv_time
);
6900 /* This page contains code for forming string representation of
6901 regexp. The representation is formed on IR obstack. So you should
6902 not work with IR obstack between regexp_representation and
6903 finish_regexp_representation calls. */
6905 /* This recursive function forms string representation of regexp
6906 (without tailing '\0'). */
6908 form_regexp (regexp_t regexp
)
6912 if (regexp
->mode
== rm_unit
|| regexp
->mode
== rm_reserv
)
6914 const char *name
= (regexp
->mode
== rm_unit
6915 ? REGEXP_UNIT (regexp
)->name
6916 : REGEXP_RESERV (regexp
)->name
);
6918 obstack_grow (&irp
, name
, strlen (name
));
6920 else if (regexp
->mode
== rm_sequence
)
6921 for (i
= 0; i
< REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
6924 obstack_1grow (&irp
, ',');
6925 form_regexp (REGEXP_SEQUENCE (regexp
)->regexps
[i
]);
6927 else if (regexp
->mode
== rm_allof
)
6929 obstack_1grow (&irp
, '(');
6930 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
6933 obstack_1grow (&irp
, '+');
6934 if (REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
== rm_sequence
6935 || REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
== rm_oneof
)
6936 obstack_1grow (&irp
, '(');
6937 form_regexp (REGEXP_ALLOF (regexp
)->regexps
[i
]);
6938 if (REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
== rm_sequence
6939 || REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
== rm_oneof
)
6940 obstack_1grow (&irp
, ')');
6942 obstack_1grow (&irp
, ')');
6944 else if (regexp
->mode
== rm_oneof
)
6945 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
6948 obstack_1grow (&irp
, '|');
6949 if (REGEXP_ONEOF (regexp
)->regexps
[i
]->mode
== rm_sequence
)
6950 obstack_1grow (&irp
, '(');
6951 form_regexp (REGEXP_ONEOF (regexp
)->regexps
[i
]);
6952 if (REGEXP_ONEOF (regexp
)->regexps
[i
]->mode
== rm_sequence
)
6953 obstack_1grow (&irp
, ')');
6955 else if (regexp
->mode
== rm_repeat
)
6959 if (REGEXP_REPEAT (regexp
)->regexp
->mode
== rm_sequence
6960 || REGEXP_REPEAT (regexp
)->regexp
->mode
== rm_allof
6961 || REGEXP_REPEAT (regexp
)->regexp
->mode
== rm_oneof
)
6962 obstack_1grow (&irp
, '(');
6963 form_regexp (REGEXP_REPEAT (regexp
)->regexp
);
6964 if (REGEXP_REPEAT (regexp
)->regexp
->mode
== rm_sequence
6965 || REGEXP_REPEAT (regexp
)->regexp
->mode
== rm_allof
6966 || REGEXP_REPEAT (regexp
)->regexp
->mode
== rm_oneof
)
6967 obstack_1grow (&irp
, ')');
6968 sprintf (digits
, "*%d", REGEXP_REPEAT (regexp
)->repeat_num
);
6969 obstack_grow (&irp
, digits
, strlen (digits
));
6971 else if (regexp
->mode
== rm_nothing
)
6972 obstack_grow (&irp
, NOTHING_NAME
, strlen (NOTHING_NAME
));
6977 /* The function returns string representation of REGEXP on IR
6980 regexp_representation (regexp_t regexp
)
6982 form_regexp (regexp
);
6983 obstack_1grow (&irp
, '\0');
6984 return obstack_base (&irp
);
6987 /* The function frees memory allocated for last formed string
6988 representation of regexp. */
6990 finish_regexp_representation (void)
6992 int length
= obstack_object_size (&irp
);
6994 obstack_blank_fast (&irp
, -length
);
6999 /* This page contains code for output PHR (pipeline hazards recognizer). */
7001 /* The function outputs minimal C type which is sufficient for
7002 representation numbers in range min_range_value and
7003 max_range_value. Because host machine and build machine may be
7004 different, we use here minimal values required by ANSI C standard
7005 instead of UCHAR_MAX, SHRT_MAX, SHRT_MIN, etc. This is a good
7009 output_range_type (FILE *f
, long int min_range_value
,
7010 long int max_range_value
)
7012 if (min_range_value
>= 0 && max_range_value
<= 255)
7013 fprintf (f
, "unsigned char");
7014 else if (min_range_value
>= -127 && max_range_value
<= 127)
7015 fprintf (f
, "signed char");
7016 else if (min_range_value
>= 0 && max_range_value
<= 65535)
7017 fprintf (f
, "unsigned short");
7018 else if (min_range_value
>= -32767 && max_range_value
<= 32767)
7019 fprintf (f
, "short");
7024 /* The following macro value is used as value of member
7025 `longest_path_length' of state when we are processing path and the
7026 state on the path. */
7028 #define ON_THE_PATH -2
7030 /* The following recursive function searches for the length of the
7031 longest path starting from STATE which does not contain cycles and
7032 `cycle advance' arcs. */
7035 longest_path_length (state_t state
)
7040 if (state
->longest_path_length
== ON_THE_PATH
)
7041 /* We don't expect the path cycle here. Our graph may contain
7042 only cycles with one state on the path not containing `cycle
7043 advance' arcs -- see comment below. */
7045 else if (state
->longest_path_length
!= UNDEFINED_LONGEST_PATH_LENGTH
)
7046 /* We already visited the state. */
7047 return state
->longest_path_length
;
7050 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
7051 /* Ignore cycles containing one state and `cycle advance' arcs. */
7052 if (arc
->to_state
!= state
7053 && (arc
->insn
->insn_reserv_decl
7054 != DECL_INSN_RESERV (advance_cycle_insn_decl
)))
7056 length
= longest_path_length (arc
->to_state
);
7057 if (length
> result
)
7060 state
->longest_path_length
= result
+ 1;
7064 /* The following variable value is value of the corresponding global
7065 variable in the automaton based pipeline interface. */
7067 static int max_dfa_issue_rate
;
7069 /* The following function processes the longest path length staring
7070 from STATE to find MAX_DFA_ISSUE_RATE. */
7073 process_state_longest_path_length (state_t state
)
7077 value
= longest_path_length (state
);
7078 if (value
> max_dfa_issue_rate
)
7079 max_dfa_issue_rate
= value
;
7082 /* The following macro value is name of the corresponding global
7083 variable in the automaton based pipeline interface. */
7085 #define MAX_DFA_ISSUE_RATE_VAR_NAME "max_dfa_issue_rate"
7087 /* The following function calculates value of the corresponding
7088 global variable and outputs its declaration. */
7091 output_dfa_max_issue_rate (void)
7093 automaton_t automaton
;
7095 if (UNDEFINED_LONGEST_PATH_LENGTH
== ON_THE_PATH
|| ON_THE_PATH
>= 0)
7097 max_dfa_issue_rate
= 0;
7098 for (automaton
= description
->first_automaton
;
7100 automaton
= automaton
->next_automaton
)
7101 pass_states (automaton
, process_state_longest_path_length
);
7102 fprintf (output_file
, "\nint %s = %d;\n",
7103 MAX_DFA_ISSUE_RATE_VAR_NAME
, max_dfa_issue_rate
);
7106 /* The function outputs all initialization values of VECT with length
7109 output_vect (vect_el_t
*vect
, int vect_length
)
7114 if (vect_length
== 0)
7115 fprintf (output_file
,
7116 "0 /* This is dummy el because the vect is empty */");
7121 fprintf (output_file
, "%5ld", (long) *vect
);
7123 if (els_on_line
== 10)
7126 fprintf (output_file
, ",\n");
7128 else if (vect_length
!= 0)
7129 fprintf (output_file
, ", ");
7133 while (vect_length
!= 0);
7137 /* The following is name of the structure which represents DFA(s) for
7139 #define CHIP_NAME "DFA_chip"
7141 /* The following is name of member which represents state of a DFA for
7144 output_chip_member_name (FILE *f
, automaton_t automaton
)
7146 if (automaton
->corresponding_automaton_decl
== NULL
)
7147 fprintf (f
, "automaton_state_%d", automaton
->automaton_order_num
);
7149 fprintf (f
, "%s_automaton_state",
7150 automaton
->corresponding_automaton_decl
->name
);
7153 /* The following is name of temporary variable which stores state of a
7156 output_temp_chip_member_name (FILE *f
, automaton_t automaton
)
7159 output_chip_member_name (f
, automaton
);
7162 /* This is name of macro value which is code of pseudo_insn
7163 representing advancing cpu cycle. Its value is used as internal
7164 code unknown insn. */
7165 #define ADVANCE_CYCLE_VALUE_NAME "DFA__ADVANCE_CYCLE"
7167 /* Output name of translate vector for given automaton. */
7169 output_translate_vect_name (FILE *f
, automaton_t automaton
)
7171 if (automaton
->corresponding_automaton_decl
== NULL
)
7172 fprintf (f
, "translate_%d", automaton
->automaton_order_num
);
7174 fprintf (f
, "%s_translate", automaton
->corresponding_automaton_decl
->name
);
7177 /* Output name for simple transition table representation. */
7179 output_trans_full_vect_name (FILE *f
, automaton_t automaton
)
7181 if (automaton
->corresponding_automaton_decl
== NULL
)
7182 fprintf (f
, "transitions_%d", automaton
->automaton_order_num
);
7184 fprintf (f
, "%s_transitions",
7185 automaton
->corresponding_automaton_decl
->name
);
7188 /* Output name of comb vector of the transition table for given
7191 output_trans_comb_vect_name (FILE *f
, automaton_t automaton
)
7193 if (automaton
->corresponding_automaton_decl
== NULL
)
7194 fprintf (f
, "transitions_%d", automaton
->automaton_order_num
);
7196 fprintf (f
, "%s_transitions",
7197 automaton
->corresponding_automaton_decl
->name
);
7200 /* Output name of check vector of the transition table for given
7203 output_trans_check_vect_name (FILE *f
, automaton_t automaton
)
7205 if (automaton
->corresponding_automaton_decl
== NULL
)
7206 fprintf (f
, "check_%d", automaton
->automaton_order_num
);
7208 fprintf (f
, "%s_check", automaton
->corresponding_automaton_decl
->name
);
7211 /* Output name of base vector of the transition table for given
7214 output_trans_base_vect_name (FILE *f
, automaton_t automaton
)
7216 if (automaton
->corresponding_automaton_decl
== NULL
)
7217 fprintf (f
, "base_%d", automaton
->automaton_order_num
);
7219 fprintf (f
, "%s_base", automaton
->corresponding_automaton_decl
->name
);
7222 /* Output name for simple alternatives number representation. */
7224 output_state_alts_full_vect_name (FILE *f
, automaton_t automaton
)
7226 if (automaton
->corresponding_automaton_decl
== NULL
)
7227 fprintf (f
, "state_alts_%d", automaton
->automaton_order_num
);
7229 fprintf (f
, "%s_state_alts",
7230 automaton
->corresponding_automaton_decl
->name
);
7233 /* Output name of comb vector of the alternatives number table for given
7236 output_state_alts_comb_vect_name (FILE *f
, automaton_t automaton
)
7238 if (automaton
->corresponding_automaton_decl
== NULL
)
7239 fprintf (f
, "state_alts_%d", automaton
->automaton_order_num
);
7241 fprintf (f
, "%s_state_alts",
7242 automaton
->corresponding_automaton_decl
->name
);
7245 /* Output name of check vector of the alternatives number table for given
7248 output_state_alts_check_vect_name (FILE *f
, automaton_t automaton
)
7250 if (automaton
->corresponding_automaton_decl
== NULL
)
7251 fprintf (f
, "check_state_alts_%d", automaton
->automaton_order_num
);
7253 fprintf (f
, "%s_check_state_alts",
7254 automaton
->corresponding_automaton_decl
->name
);
7257 /* Output name of base vector of the alternatives number table for given
7260 output_state_alts_base_vect_name (FILE *f
, automaton_t automaton
)
7262 if (automaton
->corresponding_automaton_decl
== NULL
)
7263 fprintf (f
, "base_state_alts_%d", automaton
->automaton_order_num
);
7265 fprintf (f
, "%s_base_state_alts",
7266 automaton
->corresponding_automaton_decl
->name
);
7269 /* Output name of simple min issue delay table representation. */
7271 output_min_issue_delay_vect_name (FILE *f
, automaton_t automaton
)
7273 if (automaton
->corresponding_automaton_decl
== NULL
)
7274 fprintf (f
, "min_issue_delay_%d", automaton
->automaton_order_num
);
7276 fprintf (f
, "%s_min_issue_delay",
7277 automaton
->corresponding_automaton_decl
->name
);
7280 /* Output name of deadlock vector for given automaton. */
7282 output_dead_lock_vect_name (FILE *f
, automaton_t automaton
)
7284 if (automaton
->corresponding_automaton_decl
== NULL
)
7285 fprintf (f
, "dead_lock_%d", automaton
->automaton_order_num
);
7287 fprintf (f
, "%s_dead_lock", automaton
->corresponding_automaton_decl
->name
);
7290 /* Output name of reserved units table for AUTOMATON into file F. */
7292 output_reserved_units_table_name (FILE *f
, automaton_t automaton
)
7294 if (automaton
->corresponding_automaton_decl
== NULL
)
7295 fprintf (f
, "reserved_units_%d", automaton
->automaton_order_num
);
7297 fprintf (f
, "%s_reserved_units",
7298 automaton
->corresponding_automaton_decl
->name
);
7301 /* Name of the PHR interface macro. */
7302 #define AUTOMATON_STATE_ALTS_MACRO_NAME "AUTOMATON_STATE_ALTS"
7304 /* Name of the PHR interface macro. */
7305 #define CPU_UNITS_QUERY_MACRO_NAME "CPU_UNITS_QUERY"
7307 /* Names of an internal functions: */
7308 #define INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME "internal_min_issue_delay"
7310 /* This is external type of DFA(s) state. */
7311 #define STATE_TYPE_NAME "state_t"
7313 #define INTERNAL_TRANSITION_FUNC_NAME "internal_state_transition"
7315 #define INTERNAL_STATE_ALTS_FUNC_NAME "internal_state_alts"
7317 #define INTERNAL_RESET_FUNC_NAME "internal_reset"
7319 #define INTERNAL_DEAD_LOCK_FUNC_NAME "internal_state_dead_lock_p"
7321 #define INTERNAL_INSN_LATENCY_FUNC_NAME "internal_insn_latency"
7323 /* Name of cache of insn dfa codes. */
7324 #define DFA_INSN_CODES_VARIABLE_NAME "dfa_insn_codes"
7326 /* Name of length of cache of insn dfa codes. */
7327 #define DFA_INSN_CODES_LENGTH_VARIABLE_NAME "dfa_insn_codes_length"
7329 /* Names of the PHR interface functions: */
7330 #define SIZE_FUNC_NAME "state_size"
7332 #define TRANSITION_FUNC_NAME "state_transition"
7334 #define STATE_ALTS_FUNC_NAME "state_alts"
7336 #define MIN_ISSUE_DELAY_FUNC_NAME "min_issue_delay"
7338 #define MIN_INSN_CONFLICT_DELAY_FUNC_NAME "min_insn_conflict_delay"
7340 #define DEAD_LOCK_FUNC_NAME "state_dead_lock_p"
7342 #define RESET_FUNC_NAME "state_reset"
7344 #define INSN_LATENCY_FUNC_NAME "insn_latency"
7346 #define PRINT_RESERVATION_FUNC_NAME "print_reservation"
7348 #define GET_CPU_UNIT_CODE_FUNC_NAME "get_cpu_unit_code"
7350 #define CPU_UNIT_RESERVATION_P_FUNC_NAME "cpu_unit_reservation_p"
7352 #define DFA_CLEAN_INSN_CACHE_FUNC_NAME "dfa_clean_insn_cache"
7354 #define DFA_START_FUNC_NAME "dfa_start"
7356 #define DFA_FINISH_FUNC_NAME "dfa_finish"
7358 /* Names of parameters of the PHR interface functions. */
7359 #define STATE_NAME "state"
7361 #define INSN_PARAMETER_NAME "insn"
7363 #define INSN2_PARAMETER_NAME "insn2"
7365 #define CHIP_PARAMETER_NAME "chip"
7367 #define FILE_PARAMETER_NAME "f"
7369 #define CPU_UNIT_NAME_PARAMETER_NAME "cpu_unit_name"
7371 #define CPU_CODE_PARAMETER_NAME "cpu_unit_code"
7373 /* Names of the variables whose values are internal insn code of rtx
7375 #define INTERNAL_INSN_CODE_NAME "insn_code"
7377 #define INTERNAL_INSN2_CODE_NAME "insn2_code"
7379 /* Names of temporary variables in some functions. */
7380 #define TEMPORARY_VARIABLE_NAME "temp"
7382 #define I_VARIABLE_NAME "i"
7384 /* Name of result variable in some functions. */
7385 #define RESULT_VARIABLE_NAME "res"
7387 /* Name of function (attribute) to translate insn into internal insn
7389 #define INTERNAL_DFA_INSN_CODE_FUNC_NAME "internal_dfa_insn_code"
7391 /* Name of function (attribute) to translate insn into internal insn
7392 code with caching. */
7393 #define DFA_INSN_CODE_FUNC_NAME "dfa_insn_code"
7395 /* Name of function (attribute) to translate insn into internal insn
7397 #define INSN_DEFAULT_LATENCY_FUNC_NAME "insn_default_latency"
7399 /* Name of function (attribute) to translate insn into internal insn
7401 #define BYPASS_P_FUNC_NAME "bypass_p"
7403 /* Output C type which is used for representation of codes of states
7406 output_state_member_type (FILE *f
, automaton_t automaton
)
7408 output_range_type (f
, 0, automaton
->achieved_states_num
);
7411 /* Output definition of the structure representing current DFA(s)
7414 output_chip_definitions (void)
7416 automaton_t automaton
;
7418 fprintf (output_file
, "struct %s\n{\n", CHIP_NAME
);
7419 for (automaton
= description
->first_automaton
;
7421 automaton
= automaton
->next_automaton
)
7423 fprintf (output_file
, " ");
7424 output_state_member_type (output_file
, automaton
);
7425 fprintf (output_file
, " ");
7426 output_chip_member_name (output_file
, automaton
);
7427 fprintf (output_file
, ";\n");
7429 fprintf (output_file
, "};\n\n");
7431 fprintf (output_file
, "static struct %s %s;\n\n", CHIP_NAME
, CHIP_NAME
);
7436 /* The function outputs translate vector of internal insn code into
7437 insn equivalence class number. The equivalence class number is
7438 used to access to table and vectors representing DFA(s). */
7440 output_translate_vect (automaton_t automaton
)
7444 vla_hwint_t translate_vect
;
7446 VLA_HWINT_CREATE (translate_vect
, 250, "translate vector");
7447 VLA_HWINT_EXPAND (translate_vect
, description
->insns_num
);
7448 for (insn_value
= 0; insn_value
< description
->insns_num
; insn_value
++)
7449 /* Undefined value */
7450 VLA_HWINT (translate_vect
, insn_value
) = automaton
->insn_equiv_classes_num
;
7451 for (ainsn
= automaton
->ainsn_list
; ainsn
!= NULL
; ainsn
= ainsn
->next_ainsn
)
7452 VLA_HWINT (translate_vect
, ainsn
->insn_reserv_decl
->insn_num
)
7453 = ainsn
->insn_equiv_class_num
;
7454 fprintf (output_file
,
7455 "/* Vector translating external insn codes to internal ones.*/\n");
7456 fprintf (output_file
, "static const ");
7457 output_range_type (output_file
, 0, automaton
->insn_equiv_classes_num
);
7458 fprintf (output_file
, " ");
7459 output_translate_vect_name (output_file
, automaton
);
7460 fprintf (output_file
, "[] ATTRIBUTE_UNUSED = {\n");
7461 output_vect (VLA_HWINT_BEGIN (translate_vect
),
7462 VLA_HWINT_LENGTH (translate_vect
));
7463 fprintf (output_file
, "};\n\n");
7464 VLA_HWINT_DELETE (translate_vect
);
7467 /* The value in a table state x ainsn -> something which represents
7469 static int undefined_vect_el_value
;
7471 /* The following function returns nonzero value if the best
7472 representation of the table is comb vector. */
7474 comb_vect_p (state_ainsn_table_t tab
)
7476 return (2 * VLA_HWINT_LENGTH (tab
->full_vect
)
7477 > 5 * VLA_HWINT_LENGTH (tab
->comb_vect
));
7480 /* The following function creates new table for AUTOMATON. */
7481 static state_ainsn_table_t
7482 create_state_ainsn_table (automaton_t automaton
)
7484 state_ainsn_table_t tab
;
7485 int full_vect_length
;
7488 tab
= create_node (sizeof (struct state_ainsn_table
));
7489 tab
->automaton
= automaton
;
7490 VLA_HWINT_CREATE (tab
->comb_vect
, 10000, "comb vector");
7491 VLA_HWINT_CREATE (tab
->check_vect
, 10000, "check vector");
7492 VLA_HWINT_CREATE (tab
->base_vect
, 1000, "base vector");
7493 VLA_HWINT_EXPAND (tab
->base_vect
, automaton
->achieved_states_num
);
7494 VLA_HWINT_CREATE (tab
->full_vect
, 10000, "full vector");
7495 full_vect_length
= (automaton
->insn_equiv_classes_num
7496 * automaton
->achieved_states_num
);
7497 VLA_HWINT_EXPAND (tab
->full_vect
, full_vect_length
);
7498 for (i
= 0; i
< full_vect_length
; i
++)
7499 VLA_HWINT (tab
->full_vect
, i
) = undefined_vect_el_value
;
7500 tab
->min_base_vect_el_value
= 0;
7501 tab
->max_base_vect_el_value
= 0;
7502 tab
->min_comb_vect_el_value
= 0;
7503 tab
->max_comb_vect_el_value
= 0;
7507 /* The following function outputs the best C representation of the
7508 table TAB of given TABLE_NAME. */
7510 output_state_ainsn_table (state_ainsn_table_t tab
, char *table_name
,
7511 void (*output_full_vect_name_func
) (FILE *, automaton_t
),
7512 void (*output_comb_vect_name_func
) (FILE *, automaton_t
),
7513 void (*output_check_vect_name_func
) (FILE *, automaton_t
),
7514 void (*output_base_vect_name_func
) (FILE *, automaton_t
))
7516 if (!comb_vect_p (tab
))
7518 fprintf (output_file
, "/* Vector for %s. */\n", table_name
);
7519 fprintf (output_file
, "static const ");
7520 output_range_type (output_file
, tab
->min_comb_vect_el_value
,
7521 tab
->max_comb_vect_el_value
);
7522 fprintf (output_file
, " ");
7523 (*output_full_vect_name_func
) (output_file
, tab
->automaton
);
7524 fprintf (output_file
, "[] ATTRIBUTE_UNUSED = {\n");
7525 output_vect (VLA_HWINT_BEGIN (tab
->full_vect
),
7526 VLA_HWINT_LENGTH (tab
->full_vect
));
7527 fprintf (output_file
, "};\n\n");
7531 fprintf (output_file
, "/* Comb vector for %s. */\n", table_name
);
7532 fprintf (output_file
, "static const ");
7533 output_range_type (output_file
, tab
->min_comb_vect_el_value
,
7534 tab
->max_comb_vect_el_value
);
7535 fprintf (output_file
, " ");
7536 (*output_comb_vect_name_func
) (output_file
, tab
->automaton
);
7537 fprintf (output_file
, "[] ATTRIBUTE_UNUSED = {\n");
7538 output_vect (VLA_HWINT_BEGIN (tab
->comb_vect
),
7539 VLA_HWINT_LENGTH (tab
->comb_vect
));
7540 fprintf (output_file
, "};\n\n");
7541 fprintf (output_file
, "/* Check vector for %s. */\n", table_name
);
7542 fprintf (output_file
, "static const ");
7543 output_range_type (output_file
, 0, tab
->automaton
->achieved_states_num
);
7544 fprintf (output_file
, " ");
7545 (*output_check_vect_name_func
) (output_file
, tab
->automaton
);
7546 fprintf (output_file
, "[] = {\n");
7547 output_vect (VLA_HWINT_BEGIN (tab
->check_vect
),
7548 VLA_HWINT_LENGTH (tab
->check_vect
));
7549 fprintf (output_file
, "};\n\n");
7550 fprintf (output_file
, "/* Base vector for %s. */\n", table_name
);
7551 fprintf (output_file
, "static const ");
7552 output_range_type (output_file
, tab
->min_base_vect_el_value
,
7553 tab
->max_base_vect_el_value
);
7554 fprintf (output_file
, " ");
7555 (*output_base_vect_name_func
) (output_file
, tab
->automaton
);
7556 fprintf (output_file
, "[] = {\n");
7557 output_vect (VLA_HWINT_BEGIN (tab
->base_vect
),
7558 VLA_HWINT_LENGTH (tab
->base_vect
));
7559 fprintf (output_file
, "};\n\n");
7563 /* The following function adds vector with length VECT_LENGTH and
7564 elements pointed by VECT to table TAB as its line with number
7567 add_vect (state_ainsn_table_t tab
, int vect_num
, vect_el_t
*vect
,
7570 int real_vect_length
;
7571 vect_el_t
*comb_vect_start
;
7572 vect_el_t
*check_vect_start
;
7573 int comb_vect_index
;
7574 int comb_vect_els_num
;
7576 int first_unempty_vect_index
;
7577 int additional_els_num
;
7582 if (vect_length
== 0)
7584 real_vect_length
= tab
->automaton
->insn_equiv_classes_num
;
7585 if (vect
[vect_length
- 1] == undefined_vect_el_value
)
7587 /* Form full vector in the table: */
7588 for (i
= 0; i
< vect_length
; i
++)
7589 VLA_HWINT (tab
->full_vect
,
7590 i
+ tab
->automaton
->insn_equiv_classes_num
* vect_num
)
7592 /* Form comb vector in the table: */
7593 if (VLA_HWINT_LENGTH (tab
->comb_vect
) != VLA_HWINT_LENGTH (tab
->check_vect
))
7595 comb_vect_start
= VLA_HWINT_BEGIN (tab
->comb_vect
);
7596 comb_vect_els_num
= VLA_HWINT_LENGTH (tab
->comb_vect
);
7597 for (first_unempty_vect_index
= 0;
7598 first_unempty_vect_index
< vect_length
;
7599 first_unempty_vect_index
++)
7600 if (vect
[first_unempty_vect_index
] != undefined_vect_el_value
)
7602 /* Search for the place in comb vect for the inserted vect. */
7603 for (comb_vect_index
= 0;
7604 comb_vect_index
< comb_vect_els_num
;
7607 for (vect_index
= first_unempty_vect_index
;
7608 vect_index
< vect_length
7609 && vect_index
+ comb_vect_index
< comb_vect_els_num
;
7611 if (vect
[vect_index
] != undefined_vect_el_value
7612 && (comb_vect_start
[vect_index
+ comb_vect_index
]
7613 != undefined_vect_el_value
))
7615 if (vect_index
>= vect_length
7616 || vect_index
+ comb_vect_index
>= comb_vect_els_num
)
7619 /* Slot was found. */
7620 additional_els_num
= comb_vect_index
+ real_vect_length
- comb_vect_els_num
;
7621 if (additional_els_num
< 0)
7622 additional_els_num
= 0;
7623 /* Expand comb and check vectors. */
7624 vect_el
= undefined_vect_el_value
;
7625 no_state_value
= tab
->automaton
->achieved_states_num
;
7626 while (additional_els_num
> 0)
7628 VLA_HWINT_ADD (tab
->comb_vect
, vect_el
);
7629 VLA_HWINT_ADD (tab
->check_vect
, no_state_value
);
7630 additional_els_num
--;
7632 comb_vect_start
= VLA_HWINT_BEGIN (tab
->comb_vect
);
7633 check_vect_start
= VLA_HWINT_BEGIN (tab
->check_vect
);
7634 if (VLA_HWINT_LENGTH (tab
->comb_vect
)
7635 < (size_t) (comb_vect_index
+ real_vect_length
))
7637 /* Fill comb and check vectors. */
7638 for (vect_index
= 0; vect_index
< vect_length
; vect_index
++)
7639 if (vect
[vect_index
] != undefined_vect_el_value
)
7641 if (comb_vect_start
[comb_vect_index
+ vect_index
]
7642 != undefined_vect_el_value
)
7644 comb_vect_start
[comb_vect_index
+ vect_index
] = vect
[vect_index
];
7645 if (vect
[vect_index
] < 0)
7647 if (tab
->max_comb_vect_el_value
< vect
[vect_index
])
7648 tab
->max_comb_vect_el_value
= vect
[vect_index
];
7649 if (tab
->min_comb_vect_el_value
> vect
[vect_index
])
7650 tab
->min_comb_vect_el_value
= vect
[vect_index
];
7651 check_vect_start
[comb_vect_index
+ vect_index
] = vect_num
;
7653 if (tab
->max_comb_vect_el_value
< undefined_vect_el_value
)
7654 tab
->max_comb_vect_el_value
= undefined_vect_el_value
;
7655 if (tab
->min_comb_vect_el_value
> undefined_vect_el_value
)
7656 tab
->min_comb_vect_el_value
= undefined_vect_el_value
;
7657 if (tab
->max_base_vect_el_value
< comb_vect_index
)
7658 tab
->max_base_vect_el_value
= comb_vect_index
;
7659 if (tab
->min_base_vect_el_value
> comb_vect_index
)
7660 tab
->min_base_vect_el_value
= comb_vect_index
;
7661 VLA_HWINT (tab
->base_vect
, vect_num
) = comb_vect_index
;
7664 /* Return number of out arcs of STATE. */
7666 out_state_arcs_num (state_t state
)
7672 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
7674 if (arc
->insn
== NULL
)
7676 if (arc
->insn
->first_ainsn_with_given_equivalence_num
)
7682 /* Compare number of possible transitions from the states. */
7684 compare_transition_els_num (const void *state_ptr_1
,
7685 const void *state_ptr_2
)
7687 int transition_els_num_1
;
7688 int transition_els_num_2
;
7690 transition_els_num_1
= out_state_arcs_num (*(state_t
*) state_ptr_1
);
7691 transition_els_num_2
= out_state_arcs_num (*(state_t
*) state_ptr_2
);
7692 if (transition_els_num_1
< transition_els_num_2
)
7694 else if (transition_els_num_1
== transition_els_num_2
)
7700 /* The function adds element EL_VALUE to vector VECT for a table state
7703 add_vect_el (vla_hwint_t
*vect
, ainsn_t ainsn
, int el_value
)
7705 int equiv_class_num
;
7710 equiv_class_num
= ainsn
->insn_equiv_class_num
;
7711 for (vect_index
= VLA_HWINT_LENGTH (*vect
);
7712 vect_index
<= equiv_class_num
;
7714 VLA_HWINT_ADD (*vect
, undefined_vect_el_value
);
7715 VLA_HWINT (*vect
, equiv_class_num
) = el_value
;
7718 /* This is for forming vector of states of an automaton. */
7719 static vla_ptr_t output_states_vect
;
7721 /* The function is called by function pass_states. The function adds
7722 STATE to `output_states_vect'. */
7724 add_states_vect_el (state_t state
)
7726 VLA_PTR_ADD (output_states_vect
, state
);
7729 /* Form and output vectors (comb, check, base or full vector)
7730 representing transition table of AUTOMATON. */
7732 output_trans_table (automaton_t automaton
)
7736 vla_hwint_t transition_vect
;
7738 undefined_vect_el_value
= automaton
->achieved_states_num
;
7739 automaton
->trans_table
= create_state_ainsn_table (automaton
);
7740 /* Create vect of pointers to states ordered by num of transitions
7741 from the state (state with the maximum num is the first). */
7742 VLA_PTR_CREATE (output_states_vect
, 1500, "output states vector");
7743 pass_states (automaton
, add_states_vect_el
);
7744 qsort (VLA_PTR_BEGIN (output_states_vect
),
7745 VLA_PTR_LENGTH (output_states_vect
),
7746 sizeof (state_t
), compare_transition_els_num
);
7747 VLA_HWINT_CREATE (transition_vect
, 500, "transition vector");
7748 for (state_ptr
= VLA_PTR_BEGIN (output_states_vect
);
7749 state_ptr
<= (state_t
*) VLA_PTR_LAST (output_states_vect
);
7752 VLA_HWINT_NULLIFY (transition_vect
);
7753 for (arc
= first_out_arc (*state_ptr
);
7755 arc
= next_out_arc (arc
))
7757 if (arc
->insn
== NULL
)
7759 if (arc
->insn
->first_ainsn_with_given_equivalence_num
)
7760 add_vect_el (&transition_vect
, arc
->insn
,
7761 arc
->to_state
->order_state_num
);
7763 add_vect (automaton
->trans_table
, (*state_ptr
)->order_state_num
,
7764 VLA_HWINT_BEGIN (transition_vect
),
7765 VLA_HWINT_LENGTH (transition_vect
));
7767 output_state_ainsn_table
7768 (automaton
->trans_table
, (char *) "state transitions",
7769 output_trans_full_vect_name
, output_trans_comb_vect_name
,
7770 output_trans_check_vect_name
, output_trans_base_vect_name
);
7771 VLA_PTR_DELETE (output_states_vect
);
7772 VLA_HWINT_DELETE (transition_vect
);
7775 /* Form and output vectors (comb, check, base or simple vect)
7776 representing alts number table of AUTOMATON. The table is state x
7777 ainsn -> number of possible alternative reservations by the
7780 output_state_alts_table (automaton_t automaton
)
7784 vla_hwint_t state_alts_vect
;
7786 undefined_vect_el_value
= 0; /* no alts when transition is not possible */
7787 automaton
->state_alts_table
= create_state_ainsn_table (automaton
);
7788 /* Create vect of pointers to states ordered by num of transitions
7789 from the state (state with the maximum num is the first). */
7790 VLA_PTR_CREATE (output_states_vect
, 1500, "output states vector");
7791 pass_states (automaton
, add_states_vect_el
);
7792 qsort (VLA_PTR_BEGIN (output_states_vect
),
7793 VLA_PTR_LENGTH (output_states_vect
),
7794 sizeof (state_t
), compare_transition_els_num
);
7795 /* Create base, comb, and check vectors. */
7796 VLA_HWINT_CREATE (state_alts_vect
, 500, "state alts vector");
7797 for (state_ptr
= VLA_PTR_BEGIN (output_states_vect
);
7798 state_ptr
<= (state_t
*) VLA_PTR_LAST (output_states_vect
);
7801 VLA_HWINT_NULLIFY (state_alts_vect
);
7802 for (arc
= first_out_arc (*state_ptr
);
7804 arc
= next_out_arc (arc
))
7806 if (arc
->insn
== NULL
)
7808 if (arc
->insn
->first_ainsn_with_given_equivalence_num
)
7809 add_vect_el (&state_alts_vect
, arc
->insn
, arc
->state_alts
);
7811 add_vect (automaton
->state_alts_table
, (*state_ptr
)->order_state_num
,
7812 VLA_HWINT_BEGIN (state_alts_vect
),
7813 VLA_HWINT_LENGTH (state_alts_vect
));
7815 output_state_ainsn_table
7816 (automaton
->state_alts_table
, (char *) "state insn alternatives",
7817 output_state_alts_full_vect_name
, output_state_alts_comb_vect_name
,
7818 output_state_alts_check_vect_name
, output_state_alts_base_vect_name
);
7819 VLA_PTR_DELETE (output_states_vect
);
7820 VLA_HWINT_DELETE (state_alts_vect
);
7823 /* The current number of passing states to find minimal issue delay
7824 value for an ainsn and state. */
7825 static int curr_state_pass_num
;
7827 /* This recursive function passes states to find minimal issue delay
7828 value for AINSN. The state being visited is STATE. The function
7829 returns minimal issue delay value for AINSN in STATE or -1 if we
7830 enter into a loop. */
7832 min_issue_delay_pass_states (state_t state
, ainsn_t ainsn
)
7835 int min_insn_issue_delay
, insn_issue_delay
;
7837 if (state
->state_pass_num
== curr_state_pass_num
7838 || state
->min_insn_issue_delay
!= -1)
7839 /* We've entered into a loop or already have the correct value for
7840 given state and ainsn. */
7841 return state
->min_insn_issue_delay
;
7842 state
->state_pass_num
= curr_state_pass_num
;
7843 min_insn_issue_delay
= -1;
7844 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
7845 if (arc
->insn
== ainsn
)
7847 min_insn_issue_delay
= 0;
7852 insn_issue_delay
= min_issue_delay_pass_states (arc
->to_state
, ainsn
);
7853 if (insn_issue_delay
!= -1)
7855 if (arc
->insn
->insn_reserv_decl
7856 == DECL_INSN_RESERV (advance_cycle_insn_decl
))
7858 if (min_insn_issue_delay
== -1
7859 || min_insn_issue_delay
> insn_issue_delay
)
7861 min_insn_issue_delay
= insn_issue_delay
;
7862 if (insn_issue_delay
== 0)
7867 return min_insn_issue_delay
;
7870 /* The function searches minimal issue delay value for AINSN in STATE.
7871 The function can return negative value if we can not issue AINSN. We
7872 will report about it later. */
7874 min_issue_delay (state_t state
, ainsn_t ainsn
)
7876 curr_state_pass_num
++;
7877 state
->min_insn_issue_delay
= min_issue_delay_pass_states (state
, ainsn
);
7878 return state
->min_insn_issue_delay
;
7881 /* The function initiates code for finding minimal issue delay values.
7882 It should be called only once. */
7884 initiate_min_issue_delay_pass_states (void)
7886 curr_state_pass_num
= 0;
7889 /* Form and output vectors representing minimal issue delay table of
7890 AUTOMATON. The table is state x ainsn -> minimal issue delay of
7893 output_min_issue_delay_table (automaton_t automaton
)
7895 vla_hwint_t min_issue_delay_vect
;
7896 vla_hwint_t compressed_min_issue_delay_vect
;
7897 vect_el_t min_delay
;
7902 /* Create vect of pointers to states ordered by num of transitions
7903 from the state (state with the maximum num is the first). */
7904 VLA_PTR_CREATE (output_states_vect
, 1500, "output states vector");
7905 pass_states (automaton
, add_states_vect_el
);
7906 VLA_HWINT_CREATE (min_issue_delay_vect
, 1500, "min issue delay vector");
7907 VLA_HWINT_EXPAND (min_issue_delay_vect
,
7908 VLA_HWINT_LENGTH (output_states_vect
)
7909 * automaton
->insn_equiv_classes_num
);
7911 i
< ((int) VLA_HWINT_LENGTH (output_states_vect
)
7912 * automaton
->insn_equiv_classes_num
);
7914 VLA_HWINT (min_issue_delay_vect
, i
) = 0;
7915 automaton
->max_min_delay
= 0;
7916 for (ainsn
= automaton
->ainsn_list
; ainsn
!= NULL
; ainsn
= ainsn
->next_ainsn
)
7917 if (ainsn
->first_ainsn_with_given_equivalence_num
)
7919 for (state_ptr
= VLA_PTR_BEGIN (output_states_vect
);
7920 state_ptr
<= (state_t
*) VLA_PTR_LAST (output_states_vect
);
7922 (*state_ptr
)->min_insn_issue_delay
= -1;
7923 for (state_ptr
= VLA_PTR_BEGIN (output_states_vect
);
7924 state_ptr
<= (state_t
*) VLA_PTR_LAST (output_states_vect
);
7927 min_delay
= min_issue_delay (*state_ptr
, ainsn
);
7928 if (automaton
->max_min_delay
< min_delay
)
7929 automaton
->max_min_delay
= min_delay
;
7930 VLA_HWINT (min_issue_delay_vect
,
7931 (*state_ptr
)->order_state_num
7932 * automaton
->insn_equiv_classes_num
7933 + ainsn
->insn_equiv_class_num
) = min_delay
;
7936 fprintf (output_file
, "/* Vector of min issue delay of insns. */\n");
7937 fprintf (output_file
, "static const ");
7938 output_range_type (output_file
, 0, automaton
->max_min_delay
);
7939 fprintf (output_file
, " ");
7940 output_min_issue_delay_vect_name (output_file
, automaton
);
7941 fprintf (output_file
, "[] ATTRIBUTE_UNUSED = {\n");
7942 /* Compress the vector. */
7943 if (automaton
->max_min_delay
< 2)
7944 automaton
->min_issue_delay_table_compression_factor
= 8;
7945 else if (automaton
->max_min_delay
< 4)
7946 automaton
->min_issue_delay_table_compression_factor
= 4;
7947 else if (automaton
->max_min_delay
< 16)
7948 automaton
->min_issue_delay_table_compression_factor
= 2;
7950 automaton
->min_issue_delay_table_compression_factor
= 1;
7951 VLA_HWINT_CREATE (compressed_min_issue_delay_vect
, 1500,
7952 "compressed min issue delay vector");
7953 VLA_HWINT_EXPAND (compressed_min_issue_delay_vect
,
7954 (VLA_HWINT_LENGTH (min_issue_delay_vect
)
7955 + automaton
->min_issue_delay_table_compression_factor
7957 / automaton
->min_issue_delay_table_compression_factor
);
7959 i
< (int) VLA_HWINT_LENGTH (compressed_min_issue_delay_vect
);
7961 VLA_HWINT (compressed_min_issue_delay_vect
, i
) = 0;
7962 for (i
= 0; i
< (int) VLA_HWINT_LENGTH (min_issue_delay_vect
); i
++)
7963 VLA_HWINT (compressed_min_issue_delay_vect
,
7964 i
/ automaton
->min_issue_delay_table_compression_factor
)
7965 |= (VLA_HWINT (min_issue_delay_vect
, i
)
7966 << (8 - (i
% automaton
->min_issue_delay_table_compression_factor
7968 * (8 / automaton
->min_issue_delay_table_compression_factor
)));
7969 output_vect (VLA_HWINT_BEGIN (compressed_min_issue_delay_vect
),
7970 VLA_HWINT_LENGTH (compressed_min_issue_delay_vect
));
7971 fprintf (output_file
, "};\n\n");
7972 VLA_PTR_DELETE (output_states_vect
);
7973 VLA_HWINT_DELETE (min_issue_delay_vect
);
7974 VLA_HWINT_DELETE (compressed_min_issue_delay_vect
);
7978 /* Number of states which contains transition only by advancing cpu
7980 static int locked_states_num
;
7983 /* Form and output vector representing the locked states of
7986 output_dead_lock_vect (automaton_t automaton
)
7990 vla_hwint_t dead_lock_vect
;
7992 /* Create vect of pointers to states ordered by num of
7993 transitions from the state (state with the maximum num is the
7995 VLA_PTR_CREATE (output_states_vect
, 1500, "output states vector");
7996 pass_states (automaton
, add_states_vect_el
);
7997 VLA_HWINT_CREATE (dead_lock_vect
, 1500, "is dead locked vector");
7998 VLA_HWINT_EXPAND (dead_lock_vect
, VLA_HWINT_LENGTH (output_states_vect
));
7999 for (state_ptr
= VLA_PTR_BEGIN (output_states_vect
);
8000 state_ptr
<= (state_t
*) VLA_PTR_LAST (output_states_vect
);
8003 arc
= first_out_arc (*state_ptr
);
8006 VLA_HWINT (dead_lock_vect
, (*state_ptr
)->order_state_num
)
8007 = (next_out_arc (arc
) == NULL
8008 && (arc
->insn
->insn_reserv_decl
8009 == DECL_INSN_RESERV (advance_cycle_insn_decl
)) ? 1 : 0);
8011 if (VLA_HWINT (dead_lock_vect
, (*state_ptr
)->order_state_num
))
8012 locked_states_num
++;
8015 fprintf (output_file
, "/* Vector for locked state flags. */\n");
8016 fprintf (output_file
, "static const ");
8017 output_range_type (output_file
, 0, 1);
8018 fprintf (output_file
, " ");
8019 output_dead_lock_vect_name (output_file
, automaton
);
8020 fprintf (output_file
, "[] = {\n");
8021 output_vect (VLA_HWINT_BEGIN (dead_lock_vect
),
8022 VLA_HWINT_LENGTH (dead_lock_vect
));
8023 fprintf (output_file
, "};\n\n");
8024 VLA_HWINT_DELETE (dead_lock_vect
);
8025 VLA_PTR_DELETE (output_states_vect
);
8028 /* Form and output vector representing reserved units of the states of
8031 output_reserved_units_table (automaton_t automaton
)
8033 state_t
*curr_state_ptr
;
8034 vla_hwint_t reserved_units_table
;
8035 size_t state_byte_size
;
8038 /* Create vect of pointers to states. */
8039 VLA_PTR_CREATE (output_states_vect
, 1500, "output states vector");
8040 pass_states (automaton
, add_states_vect_el
);
8041 /* Create vector. */
8042 VLA_HWINT_CREATE (reserved_units_table
, 1500, "reserved units vector");
8043 state_byte_size
= (description
->query_units_num
+ 7) / 8;
8044 VLA_HWINT_EXPAND (reserved_units_table
,
8045 VLA_HWINT_LENGTH (output_states_vect
) * state_byte_size
);
8047 i
< (int) (VLA_HWINT_LENGTH (output_states_vect
) * state_byte_size
);
8049 VLA_HWINT (reserved_units_table
, i
) = 0;
8050 for (curr_state_ptr
= VLA_PTR_BEGIN (output_states_vect
);
8051 curr_state_ptr
<= (state_t
*) VLA_PTR_LAST (output_states_vect
);
8054 for (i
= 0; i
< description
->units_num
; i
++)
8055 if (units_array
[i
]->query_p
8056 && first_cycle_unit_presence (*curr_state_ptr
, i
))
8057 VLA_HWINT (reserved_units_table
,
8058 (*curr_state_ptr
)->order_state_num
* state_byte_size
8059 + units_array
[i
]->query_num
/ 8)
8060 += (1 << (units_array
[i
]->query_num
% 8));
8062 fprintf (output_file
, "/* Vector for reserved units of states. */\n");
8063 fprintf (output_file
, "static const ");
8064 output_range_type (output_file
, 0, 255);
8065 fprintf (output_file
, " ");
8066 output_reserved_units_table_name (output_file
, automaton
);
8067 fprintf (output_file
, "[] = {\n");
8068 output_vect (VLA_HWINT_BEGIN (reserved_units_table
),
8069 VLA_HWINT_LENGTH (reserved_units_table
));
8070 fprintf (output_file
, "};\n\n");
8071 VLA_HWINT_DELETE (reserved_units_table
);
8072 VLA_PTR_DELETE (output_states_vect
);
8075 /* The function outputs all tables representing DFA(s) used for fast
8076 pipeline hazards recognition. */
8078 output_tables (void)
8080 automaton_t automaton
;
8083 locked_states_num
= 0;
8085 initiate_min_issue_delay_pass_states ();
8086 for (automaton
= description
->first_automaton
;
8088 automaton
= automaton
->next_automaton
)
8090 output_translate_vect (automaton
);
8091 output_trans_table (automaton
);
8092 fprintf (output_file
, "\n#if %s\n", AUTOMATON_STATE_ALTS_MACRO_NAME
);
8093 output_state_alts_table (automaton
);
8094 fprintf (output_file
, "\n#endif /* #if %s */\n\n",
8095 AUTOMATON_STATE_ALTS_MACRO_NAME
);
8096 output_min_issue_delay_table (automaton
);
8097 output_dead_lock_vect (automaton
);
8098 fprintf (output_file
, "\n#if %s\n\n", CPU_UNITS_QUERY_MACRO_NAME
);
8099 output_reserved_units_table (automaton
);
8100 fprintf (output_file
, "\n#endif /* #if %s */\n\n",
8101 CPU_UNITS_QUERY_MACRO_NAME
);
8103 fprintf (output_file
, "\n#define %s %d\n\n", ADVANCE_CYCLE_VALUE_NAME
,
8104 DECL_INSN_RESERV (advance_cycle_insn_decl
)->insn_num
);
8107 /* The function outputs definition and value of PHR interface variable
8108 `max_insn_queue_index'. Its value is not less than maximal queue
8109 length needed for the insn scheduler. */
8111 output_max_insn_queue_index_def (void)
8113 int i
, max
, latency
;
8116 max
= description
->max_insn_reserv_cycles
;
8117 for (i
= 0; i
< description
->decls_num
; i
++)
8119 decl
= description
->decls
[i
];
8120 if (decl
->mode
== dm_insn_reserv
&& decl
!= advance_cycle_insn_decl
)
8122 latency
= DECL_INSN_RESERV (decl
)->default_latency
;
8126 else if (decl
->mode
== dm_bypass
)
8128 latency
= DECL_BYPASS (decl
)->latency
;
8133 for (i
= 0; (1 << i
) <= max
; i
++)
8137 fprintf (output_file
, "\nint max_insn_queue_index = %d;\n\n", (1 << i
) - 1);
8141 /* The function outputs switch cases for insn reservations using
8142 function *output_automata_list_code. */
8144 output_insn_code_cases (void (*output_automata_list_code
)
8145 (automata_list_el_t
))
8150 for (i
= 0; i
< description
->decls_num
; i
++)
8152 decl
= description
->decls
[i
];
8153 if (decl
->mode
== dm_insn_reserv
)
8154 DECL_INSN_RESERV (decl
)->processed_p
= FALSE
;
8156 for (i
= 0; i
< description
->decls_num
; i
++)
8158 decl
= description
->decls
[i
];
8159 if (decl
->mode
== dm_insn_reserv
8160 && !DECL_INSN_RESERV (decl
)->processed_p
)
8162 for (j
= i
; j
< description
->decls_num
; j
++)
8164 decl2
= description
->decls
[j
];
8165 if (decl2
->mode
== dm_insn_reserv
8166 && (DECL_INSN_RESERV (decl2
)->important_automata_list
8167 == DECL_INSN_RESERV (decl
)->important_automata_list
))
8169 DECL_INSN_RESERV (decl2
)->processed_p
= TRUE
;
8170 fprintf (output_file
, " case %d: /* %s */\n",
8171 DECL_INSN_RESERV (decl2
)->insn_num
,
8172 DECL_INSN_RESERV (decl2
)->name
);
8175 (*output_automata_list_code
)
8176 (DECL_INSN_RESERV (decl
)->important_automata_list
);
8182 /* The function outputs a code for evaluation of a minimal delay of
8183 issue of insns which have reservations in given AUTOMATA_LIST. */
8185 output_automata_list_min_issue_delay_code (automata_list_el_t automata_list
)
8187 automata_list_el_t el
;
8188 automaton_t automaton
;
8190 for (el
= automata_list
; el
!= NULL
; el
= el
->next_automata_list_el
)
8192 automaton
= el
->automaton
;
8193 fprintf (output_file
, "\n %s = ", TEMPORARY_VARIABLE_NAME
);
8194 output_min_issue_delay_vect_name (output_file
, automaton
);
8195 fprintf (output_file
,
8196 (automaton
->min_issue_delay_table_compression_factor
!= 1
8198 output_translate_vect_name (output_file
, automaton
);
8199 fprintf (output_file
, " [%s] + ", INTERNAL_INSN_CODE_NAME
);
8200 fprintf (output_file
, "%s->", CHIP_PARAMETER_NAME
);
8201 output_chip_member_name (output_file
, automaton
);
8202 fprintf (output_file
, " * %d", automaton
->insn_equiv_classes_num
);
8203 if (automaton
->min_issue_delay_table_compression_factor
== 1)
8204 fprintf (output_file
, "];\n");
8207 fprintf (output_file
, ") / %d];\n",
8208 automaton
->min_issue_delay_table_compression_factor
);
8209 fprintf (output_file
, " %s = (%s >> (8 - (",
8210 TEMPORARY_VARIABLE_NAME
, TEMPORARY_VARIABLE_NAME
);
8211 output_translate_vect_name (output_file
, automaton
);
8213 (output_file
, " [%s] %% %d + 1) * %d)) & %d;\n",
8214 INTERNAL_INSN_CODE_NAME
,
8215 automaton
->min_issue_delay_table_compression_factor
,
8216 8 / automaton
->min_issue_delay_table_compression_factor
,
8217 (1 << (8 / automaton
->min_issue_delay_table_compression_factor
))
8220 if (el
== automata_list
)
8221 fprintf (output_file
, " %s = %s;\n",
8222 RESULT_VARIABLE_NAME
, TEMPORARY_VARIABLE_NAME
);
8225 fprintf (output_file
, " if (%s > %s)\n",
8226 TEMPORARY_VARIABLE_NAME
, RESULT_VARIABLE_NAME
);
8227 fprintf (output_file
, " %s = %s;\n",
8228 RESULT_VARIABLE_NAME
, TEMPORARY_VARIABLE_NAME
);
8231 fprintf (output_file
, " break;\n\n");
8234 /* Output function `internal_min_issue_delay'. */
8236 output_internal_min_issue_delay_func (void)
8238 fprintf (output_file
,
8239 "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
8240 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
8241 CHIP_NAME
, CHIP_PARAMETER_NAME
);
8242 fprintf (output_file
, "{\n int %s ATTRIBUTE_UNUSED;\n int %s = -1;\n",
8243 TEMPORARY_VARIABLE_NAME
, RESULT_VARIABLE_NAME
);
8244 fprintf (output_file
, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME
);
8245 output_insn_code_cases (output_automata_list_min_issue_delay_code
);
8246 fprintf (output_file
,
8247 "\n default:\n %s = -1;\n break;\n }\n",
8248 RESULT_VARIABLE_NAME
);
8249 fprintf (output_file
, " return %s;\n", RESULT_VARIABLE_NAME
);
8250 fprintf (output_file
, "}\n\n");
8253 /* The function outputs a code changing state after issue of insns
8254 which have reservations in given AUTOMATA_LIST. */
8256 output_automata_list_transition_code (automata_list_el_t automata_list
)
8258 automata_list_el_t el
, next_el
;
8260 fprintf (output_file
, " {\n");
8261 if (automata_list
!= NULL
&& automata_list
->next_automata_list_el
!= NULL
)
8262 for (el
= automata_list
;; el
= next_el
)
8264 next_el
= el
->next_automata_list_el
;
8265 if (next_el
== NULL
)
8267 fprintf (output_file
, " ");
8268 output_state_member_type (output_file
, el
->automaton
);
8269 fprintf (output_file
, " ");
8270 output_temp_chip_member_name (output_file
, el
->automaton
);
8271 fprintf (output_file
, ";\n");
8273 for (el
= automata_list
; el
!= NULL
; el
= el
->next_automata_list_el
)
8274 if (comb_vect_p (el
->automaton
->trans_table
))
8276 fprintf (output_file
, "\n %s = ", TEMPORARY_VARIABLE_NAME
);
8277 output_trans_base_vect_name (output_file
, el
->automaton
);
8278 fprintf (output_file
, " [%s->", CHIP_PARAMETER_NAME
);
8279 output_chip_member_name (output_file
, el
->automaton
);
8280 fprintf (output_file
, "] + ");
8281 output_translate_vect_name (output_file
, el
->automaton
);
8282 fprintf (output_file
, " [%s];\n", INTERNAL_INSN_CODE_NAME
);
8283 fprintf (output_file
, " if (");
8284 output_trans_check_vect_name (output_file
, el
->automaton
);
8285 fprintf (output_file
, " [%s] != %s->",
8286 TEMPORARY_VARIABLE_NAME
, CHIP_PARAMETER_NAME
);
8287 output_chip_member_name (output_file
, el
->automaton
);
8288 fprintf (output_file
, ")\n");
8289 fprintf (output_file
, " return %s (%s, %s);\n",
8290 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
8291 CHIP_PARAMETER_NAME
);
8292 fprintf (output_file
, " else\n");
8293 fprintf (output_file
, " ");
8294 if (el
->next_automata_list_el
!= NULL
)
8295 output_temp_chip_member_name (output_file
, el
->automaton
);
8298 fprintf (output_file
, "%s->", CHIP_PARAMETER_NAME
);
8299 output_chip_member_name (output_file
, el
->automaton
);
8301 fprintf (output_file
, " = ");
8302 output_trans_comb_vect_name (output_file
, el
->automaton
);
8303 fprintf (output_file
, " [%s];\n", TEMPORARY_VARIABLE_NAME
);
8307 fprintf (output_file
, "\n %s = ", TEMPORARY_VARIABLE_NAME
);
8308 output_trans_full_vect_name (output_file
, el
->automaton
);
8309 fprintf (output_file
, " [");
8310 output_translate_vect_name (output_file
, el
->automaton
);
8311 fprintf (output_file
, " [%s] + ", INTERNAL_INSN_CODE_NAME
);
8312 fprintf (output_file
, "%s->", CHIP_PARAMETER_NAME
);
8313 output_chip_member_name (output_file
, el
->automaton
);
8314 fprintf (output_file
, " * %d];\n",
8315 el
->automaton
->insn_equiv_classes_num
);
8316 fprintf (output_file
, " if (%s >= %d)\n",
8317 TEMPORARY_VARIABLE_NAME
, el
->automaton
->achieved_states_num
);
8318 fprintf (output_file
, " return %s (%s, %s);\n",
8319 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
8320 CHIP_PARAMETER_NAME
);
8321 fprintf (output_file
, " else\n ");
8322 if (el
->next_automata_list_el
!= NULL
)
8323 output_temp_chip_member_name (output_file
, el
->automaton
);
8326 fprintf (output_file
, "%s->", CHIP_PARAMETER_NAME
);
8327 output_chip_member_name (output_file
, el
->automaton
);
8329 fprintf (output_file
, " = %s;\n", TEMPORARY_VARIABLE_NAME
);
8331 if (automata_list
!= NULL
&& automata_list
->next_automata_list_el
!= NULL
)
8332 for (el
= automata_list
;; el
= next_el
)
8334 next_el
= el
->next_automata_list_el
;
8335 if (next_el
== NULL
)
8337 fprintf (output_file
, " %s->", CHIP_PARAMETER_NAME
);
8338 output_chip_member_name (output_file
, el
->automaton
);
8339 fprintf (output_file
, " = ");
8340 output_temp_chip_member_name (output_file
, el
->automaton
);
8341 fprintf (output_file
, ";\n");
8343 fprintf (output_file
, " return -1;\n");
8344 fprintf (output_file
, " }\n");
8347 /* Output function `internal_state_transition'. */
8349 output_internal_trans_func (void)
8351 fprintf (output_file
,
8352 "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
8353 INTERNAL_TRANSITION_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
8354 CHIP_NAME
, CHIP_PARAMETER_NAME
);
8355 fprintf (output_file
, "{\n int %s ATTRIBUTE_UNUSED;\n", TEMPORARY_VARIABLE_NAME
);
8356 fprintf (output_file
, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME
);
8357 output_insn_code_cases (output_automata_list_transition_code
);
8358 fprintf (output_file
, "\n default:\n return -1;\n }\n");
8359 fprintf (output_file
, "}\n\n");
8366 insn_code = dfa_insn_code (insn);
8367 if (insn_code > DFA__ADVANCE_CYCLE)
8371 insn_code = DFA__ADVANCE_CYCLE;
8373 where insn denotes INSN_NAME, insn_code denotes INSN_CODE_NAME, and
8374 code denotes CODE. */
8376 output_internal_insn_code_evaluation (const char *insn_name
,
8377 const char *insn_code_name
,
8380 fprintf (output_file
, "\n if (%s != 0)\n {\n", insn_name
);
8381 fprintf (output_file
, " %s = %s (%s);\n", insn_code_name
,
8382 DFA_INSN_CODE_FUNC_NAME
, insn_name
);
8383 fprintf (output_file
, " if (%s > %s)\n return %d;\n",
8384 insn_code_name
, ADVANCE_CYCLE_VALUE_NAME
, code
);
8385 fprintf (output_file
, " }\n else\n %s = %s;\n\n",
8386 insn_code_name
, ADVANCE_CYCLE_VALUE_NAME
);
8390 /* This function outputs `dfa_insn_code' and its helper function
8391 `dfa_insn_code_enlarge'. */
8393 output_dfa_insn_code_func (void)
8395 /* Emacs c-mode gets really confused if there's a { or } in column 0
8396 inside a string, so don't do that. */
8397 fprintf (output_file
, "\
8399 dfa_insn_code_enlarge (int uid)\n\
8403 %s = xrealloc (%s,\n\
8404 %s * sizeof(int));\n\
8405 for (; i < %s; i++)\n\
8406 %s[i] = -1;\n}\n\n",
8407 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
,
8408 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
,
8409 DFA_INSN_CODES_VARIABLE_NAME
, DFA_INSN_CODES_VARIABLE_NAME
,
8410 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
,
8411 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
,
8412 DFA_INSN_CODES_VARIABLE_NAME
);
8413 fprintf (output_file
, "\
8414 static inline int\n%s (rtx %s)\n\
8416 int uid = INSN_UID (%s);\n\
8418 DFA_INSN_CODE_FUNC_NAME
, INSN_PARAMETER_NAME
,
8419 INSN_PARAMETER_NAME
, INTERNAL_INSN_CODE_NAME
);
8421 fprintf (output_file
,
8422 " if (uid >= %s)\n dfa_insn_code_enlarge (uid);\n\n",
8423 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
);
8424 fprintf (output_file
, " %s = %s[uid];\n",
8425 INTERNAL_INSN_CODE_NAME
, DFA_INSN_CODES_VARIABLE_NAME
);
8426 fprintf (output_file
, "\
8432 INTERNAL_INSN_CODE_NAME
,
8433 INTERNAL_INSN_CODE_NAME
,
8434 INTERNAL_DFA_INSN_CODE_FUNC_NAME
, INSN_PARAMETER_NAME
,
8435 DFA_INSN_CODES_VARIABLE_NAME
, INTERNAL_INSN_CODE_NAME
);
8436 fprintf (output_file
, " return %s;\n}\n\n", INTERNAL_INSN_CODE_NAME
);
8439 /* The function outputs PHR interface function `state_transition'. */
8441 output_trans_func (void)
8443 fprintf (output_file
, "int\n%s (%s %s, rtx %s)\n",
8444 TRANSITION_FUNC_NAME
, STATE_TYPE_NAME
, STATE_NAME
,
8445 INSN_PARAMETER_NAME
);
8446 fprintf (output_file
, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME
);
8447 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME
,
8448 INTERNAL_INSN_CODE_NAME
, -1);
8449 fprintf (output_file
, " return %s (%s, %s);\n}\n\n",
8450 INTERNAL_TRANSITION_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
, STATE_NAME
);
8453 /* The function outputs a code for evaluation of alternative states
8454 number for insns which have reservations in given AUTOMATA_LIST. */
8456 output_automata_list_state_alts_code (automata_list_el_t automata_list
)
8458 automata_list_el_t el
;
8459 automaton_t automaton
;
8461 fprintf (output_file
, " {\n");
8462 for (el
= automata_list
; el
!= NULL
; el
= el
->next_automata_list_el
)
8463 if (comb_vect_p (el
->automaton
->state_alts_table
))
8465 fprintf (output_file
, " int %s;\n", TEMPORARY_VARIABLE_NAME
);
8468 for (el
= automata_list
; el
!= NULL
; el
= el
->next_automata_list_el
)
8470 automaton
= el
->automaton
;
8471 if (comb_vect_p (automaton
->state_alts_table
))
8473 fprintf (output_file
, "\n %s = ", TEMPORARY_VARIABLE_NAME
);
8474 output_state_alts_base_vect_name (output_file
, automaton
);
8475 fprintf (output_file
, " [%s->", CHIP_PARAMETER_NAME
);
8476 output_chip_member_name (output_file
, automaton
);
8477 fprintf (output_file
, "] + ");
8478 output_translate_vect_name (output_file
, automaton
);
8479 fprintf (output_file
, " [%s];\n", INTERNAL_INSN_CODE_NAME
);
8480 fprintf (output_file
, " if (");
8481 output_state_alts_check_vect_name (output_file
, automaton
);
8482 fprintf (output_file
, " [%s] != %s->",
8483 TEMPORARY_VARIABLE_NAME
, CHIP_PARAMETER_NAME
);
8484 output_chip_member_name (output_file
, automaton
);
8485 fprintf (output_file
, ")\n");
8486 fprintf (output_file
, " return 0;\n");
8487 fprintf (output_file
, " else\n");
8488 fprintf (output_file
,
8489 (el
== automata_list
8490 ? " %s = " : " %s += "),
8491 RESULT_VARIABLE_NAME
);
8492 output_state_alts_comb_vect_name (output_file
, automaton
);
8493 fprintf (output_file
, " [%s];\n", TEMPORARY_VARIABLE_NAME
);
8497 fprintf (output_file
,
8498 (el
== automata_list
8499 ? "\n %s = " : " %s += "),
8500 RESULT_VARIABLE_NAME
);
8501 output_state_alts_full_vect_name (output_file
, automaton
);
8502 fprintf (output_file
, " [");
8503 output_translate_vect_name (output_file
, automaton
);
8504 fprintf (output_file
, " [%s] + ", INTERNAL_INSN_CODE_NAME
);
8505 fprintf (output_file
, "%s->", CHIP_PARAMETER_NAME
);
8506 output_chip_member_name (output_file
, automaton
);
8507 fprintf (output_file
, " * %d];\n",
8508 automaton
->insn_equiv_classes_num
);
8511 fprintf (output_file
, " break;\n }\n\n");
8514 /* Output function `internal_state_alts'. */
8516 output_internal_state_alts_func (void)
8518 fprintf (output_file
,
8519 "static int\n%s (int %s, struct %s *%s)\n",
8520 INTERNAL_STATE_ALTS_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
8521 CHIP_NAME
, CHIP_PARAMETER_NAME
);
8522 fprintf (output_file
, "{\n int %s;\n", RESULT_VARIABLE_NAME
);
8523 fprintf (output_file
, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME
);
8524 output_insn_code_cases (output_automata_list_state_alts_code
);
8525 fprintf (output_file
,
8526 "\n default:\n %s = 0;\n break;\n }\n",
8527 RESULT_VARIABLE_NAME
);
8528 fprintf (output_file
, " return %s;\n", RESULT_VARIABLE_NAME
);
8529 fprintf (output_file
, "}\n\n");
8532 /* The function outputs PHR interface function `state_alts'. */
8534 output_state_alts_func (void)
8536 fprintf (output_file
, "int\n%s (%s, %s)\n\t%s %s;\n\trtx %s;\n",
8537 STATE_ALTS_FUNC_NAME
, STATE_NAME
, INSN_PARAMETER_NAME
,
8538 STATE_TYPE_NAME
, STATE_NAME
, INSN_PARAMETER_NAME
);
8539 fprintf (output_file
, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME
);
8540 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME
,
8541 INTERNAL_INSN_CODE_NAME
, 0);
8542 fprintf (output_file
, " return %s (%s, %s);\n}\n\n",
8543 INTERNAL_STATE_ALTS_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
, STATE_NAME
);
8546 /* Output function `min_issue_delay'. */
8548 output_min_issue_delay_func (void)
8550 fprintf (output_file
, "int\n%s (%s %s, rtx %s)\n",
8551 MIN_ISSUE_DELAY_FUNC_NAME
, STATE_TYPE_NAME
, STATE_NAME
,
8552 INSN_PARAMETER_NAME
);
8553 fprintf (output_file
, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME
);
8554 fprintf (output_file
, "\n if (%s != 0)\n {\n", INSN_PARAMETER_NAME
);
8555 fprintf (output_file
, " %s = %s (%s);\n", INTERNAL_INSN_CODE_NAME
,
8556 DFA_INSN_CODE_FUNC_NAME
, INSN_PARAMETER_NAME
);
8557 fprintf (output_file
, " if (%s > %s)\n return 0;\n",
8558 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
8559 fprintf (output_file
, " }\n else\n %s = %s;\n",
8560 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
8561 fprintf (output_file
, "\n return %s (%s, %s);\n",
8562 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
8564 fprintf (output_file
, "}\n\n");
8567 /* Output function `internal_dead_lock'. */
8569 output_internal_dead_lock_func (void)
8571 automaton_t automaton
;
8573 fprintf (output_file
, "static int\n%s (struct %s *%s)\n",
8574 INTERNAL_DEAD_LOCK_FUNC_NAME
, CHIP_NAME
, CHIP_PARAMETER_NAME
);
8575 fprintf (output_file
, "{\n");
8576 for (automaton
= description
->first_automaton
;
8578 automaton
= automaton
->next_automaton
)
8580 fprintf (output_file
, " if (");
8581 output_dead_lock_vect_name (output_file
, automaton
);
8582 fprintf (output_file
, " [%s->", CHIP_PARAMETER_NAME
);
8583 output_chip_member_name (output_file
, automaton
);
8584 fprintf (output_file
, "])\n return 1/* TRUE */;\n");
8586 fprintf (output_file
, " return 0/* FALSE */;\n}\n\n");
8589 /* The function outputs PHR interface function `state_dead_lock_p'. */
8591 output_dead_lock_func (void)
8593 fprintf (output_file
, "int\n%s (%s %s)\n",
8594 DEAD_LOCK_FUNC_NAME
, STATE_TYPE_NAME
, STATE_NAME
);
8595 fprintf (output_file
, "{\n return %s (%s);\n}\n\n",
8596 INTERNAL_DEAD_LOCK_FUNC_NAME
, STATE_NAME
);
8599 /* Output function `internal_reset'. */
8601 output_internal_reset_func (void)
8603 fprintf (output_file
, "static inline void\n%s (struct %s *%s)\n",
8604 INTERNAL_RESET_FUNC_NAME
, CHIP_NAME
, CHIP_PARAMETER_NAME
);
8605 fprintf (output_file
, "{\n memset (%s, 0, sizeof (struct %s));\n}\n\n",
8606 CHIP_PARAMETER_NAME
, CHIP_NAME
);
8609 /* The function outputs PHR interface function `state_size'. */
8611 output_size_func (void)
8613 fprintf (output_file
, "int\n%s (void)\n", SIZE_FUNC_NAME
);
8614 fprintf (output_file
, "{\n return sizeof (struct %s);\n}\n\n", CHIP_NAME
);
8617 /* The function outputs PHR interface function `state_reset'. */
8619 output_reset_func (void)
8621 fprintf (output_file
, "void\n%s (%s %s)\n",
8622 RESET_FUNC_NAME
, STATE_TYPE_NAME
, STATE_NAME
);
8623 fprintf (output_file
, "{\n %s (%s);\n}\n\n", INTERNAL_RESET_FUNC_NAME
,
8627 /* Output function `min_insn_conflict_delay'. */
8629 output_min_insn_conflict_delay_func (void)
8631 fprintf (output_file
,
8632 "int\n%s (%s %s, rtx %s, rtx %s)\n",
8633 MIN_INSN_CONFLICT_DELAY_FUNC_NAME
, STATE_TYPE_NAME
,
8634 STATE_NAME
, INSN_PARAMETER_NAME
, INSN2_PARAMETER_NAME
);
8635 fprintf (output_file
, "{\n struct %s %s;\n int %s, %s;\n",
8636 CHIP_NAME
, CHIP_NAME
, INTERNAL_INSN_CODE_NAME
,
8637 INTERNAL_INSN2_CODE_NAME
);
8638 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME
,
8639 INTERNAL_INSN_CODE_NAME
, 0);
8640 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME
,
8641 INTERNAL_INSN2_CODE_NAME
, 0);
8642 fprintf (output_file
, " memcpy (&%s, %s, sizeof (%s));\n",
8643 CHIP_NAME
, STATE_NAME
, CHIP_NAME
);
8644 fprintf (output_file
, " %s (&%s);\n", INTERNAL_RESET_FUNC_NAME
, CHIP_NAME
);
8645 fprintf (output_file
, " if (%s (%s, &%s) > 0)\n abort ();\n",
8646 INTERNAL_TRANSITION_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
, CHIP_NAME
);
8647 fprintf (output_file
, " return %s (%s, &%s);\n",
8648 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME
, INTERNAL_INSN2_CODE_NAME
,
8650 fprintf (output_file
, "}\n\n");
8653 /* Output function `internal_insn_latency'. */
8655 output_internal_insn_latency_func (void)
8658 struct bypass_decl
*bypass
;
8660 const char *tabletype
= "unsigned char";
8662 /* Find the smallest integer type that can hold all the default
8664 for (i
= 0; i
< description
->decls_num
; i
++)
8665 if (description
->decls
[i
]->mode
== dm_insn_reserv
)
8667 decl
= description
->decls
[i
];
8668 if (DECL_INSN_RESERV (decl
)->default_latency
> UCHAR_MAX
8669 && tabletype
[0] != 'i') /* Don't shrink it. */
8670 tabletype
= "unsigned short";
8671 if (DECL_INSN_RESERV (decl
)->default_latency
> USHRT_MAX
)
8675 fprintf (output_file
, "static int\n%s (int %s ATTRIBUTE_UNUSED,\n\tint %s ATTRIBUTE_UNUSED,\n\trtx %s ATTRIBUTE_UNUSED,\n\trtx %s ATTRIBUTE_UNUSED)\n",
8676 INTERNAL_INSN_LATENCY_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
8677 INTERNAL_INSN2_CODE_NAME
, INSN_PARAMETER_NAME
,
8678 INSN2_PARAMETER_NAME
);
8679 fprintf (output_file
, "{\n");
8681 if (DECL_INSN_RESERV (advance_cycle_insn_decl
)->insn_num
== 0)
8683 fputs (" return 0;\n}\n\n", output_file
);
8687 fprintf (output_file
, " static const %s default_latencies[] =\n {",
8690 for (i
= 0, j
= 0, col
= 7; i
< description
->decls_num
; i
++)
8691 if (description
->decls
[i
]->mode
== dm_insn_reserv
8692 && description
->decls
[i
] != advance_cycle_insn_decl
)
8694 if ((col
= (col
+1) % 8) == 0)
8695 fputs ("\n ", output_file
);
8696 decl
= description
->decls
[i
];
8697 if (j
++ != DECL_INSN_RESERV (decl
)->insn_num
)
8699 fprintf (output_file
, "% 4d,",
8700 DECL_INSN_RESERV (decl
)->default_latency
);
8702 if (j
!= DECL_INSN_RESERV (advance_cycle_insn_decl
)->insn_num
)
8704 fputs ("\n };\n", output_file
);
8706 fprintf (output_file
, " if (%s >= %s || %s >= %s)\n return 0;\n",
8707 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
,
8708 INTERNAL_INSN2_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
8710 fprintf (output_file
, " switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME
);
8711 for (i
= 0; i
< description
->decls_num
; i
++)
8712 if (description
->decls
[i
]->mode
== dm_insn_reserv
8713 && DECL_INSN_RESERV (description
->decls
[i
])->bypass_list
)
8715 decl
= description
->decls
[i
];
8716 fprintf (output_file
,
8717 " case %d:\n switch (%s)\n {\n",
8718 DECL_INSN_RESERV (decl
)->insn_num
,
8719 INTERNAL_INSN2_CODE_NAME
);
8720 for (bypass
= DECL_INSN_RESERV (decl
)->bypass_list
;
8722 bypass
= bypass
->next
)
8724 if (bypass
->in_insn_reserv
->insn_num
8725 == DECL_INSN_RESERV (advance_cycle_insn_decl
)->insn_num
)
8727 fprintf (output_file
, " case %d:\n",
8728 bypass
->in_insn_reserv
->insn_num
);
8729 if (bypass
->bypass_guard_name
== NULL
)
8730 fprintf (output_file
, " return %d;\n",
8734 fprintf (output_file
,
8735 " if (%s (%s, %s))\n",
8736 bypass
->bypass_guard_name
, INSN_PARAMETER_NAME
,
8737 INSN2_PARAMETER_NAME
);
8738 fprintf (output_file
,
8739 " return %d;\n break;\n",
8743 fputs (" }\n break;\n", output_file
);
8746 fprintf (output_file
, " }\n return default_latencies[%s];\n}\n\n",
8747 INTERNAL_INSN_CODE_NAME
);
8750 /* The function outputs PHR interface function `insn_latency'. */
8752 output_insn_latency_func (void)
8754 fprintf (output_file
, "int\n%s (rtx %s, rtx %s)\n",
8755 INSN_LATENCY_FUNC_NAME
, INSN_PARAMETER_NAME
, INSN2_PARAMETER_NAME
);
8756 fprintf (output_file
, "{\n int %s, %s;\n",
8757 INTERNAL_INSN_CODE_NAME
, INTERNAL_INSN2_CODE_NAME
);
8758 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME
,
8759 INTERNAL_INSN_CODE_NAME
, 0);
8760 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME
,
8761 INTERNAL_INSN2_CODE_NAME
, 0);
8762 fprintf (output_file
, " return %s (%s, %s, %s, %s);\n}\n\n",
8763 INTERNAL_INSN_LATENCY_FUNC_NAME
,
8764 INTERNAL_INSN_CODE_NAME
, INTERNAL_INSN2_CODE_NAME
,
8765 INSN_PARAMETER_NAME
, INSN2_PARAMETER_NAME
);
8768 /* The function outputs PHR interface function `print_reservation'. */
8770 output_print_reservation_func (void)
8775 fprintf (output_file
,
8776 "void\n%s (FILE *%s, rtx %s ATTRIBUTE_UNUSED)\n{\n",
8777 PRINT_RESERVATION_FUNC_NAME
, FILE_PARAMETER_NAME
,
8778 INSN_PARAMETER_NAME
);
8780 if (DECL_INSN_RESERV (advance_cycle_insn_decl
)->insn_num
== 0)
8782 fprintf (output_file
, " fputs (\"%s\", %s);\n}\n\n",
8783 NOTHING_NAME
, FILE_PARAMETER_NAME
);
8788 fputs (" static const char *const reservation_names[] =\n {",
8791 for (i
= 0, j
= 0; i
< description
->decls_num
; i
++)
8793 decl
= description
->decls
[i
];
8794 if (decl
->mode
== dm_insn_reserv
&& decl
!= advance_cycle_insn_decl
)
8796 if (j
++ != DECL_INSN_RESERV (decl
)->insn_num
)
8798 fprintf (output_file
, "\n \"%s\",",
8799 regexp_representation (DECL_INSN_RESERV (decl
)->regexp
));
8800 finish_regexp_representation ();
8803 if (j
!= DECL_INSN_RESERV (advance_cycle_insn_decl
)->insn_num
)
8806 fprintf (output_file
, "\n \"%s\"\n };\n int %s;\n\n",
8807 NOTHING_NAME
, INTERNAL_INSN_CODE_NAME
);
8809 fprintf (output_file
, " if (%s == 0)\n %s = %s;\n",
8810 INSN_PARAMETER_NAME
,
8811 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
8812 fprintf (output_file
, " else\n\
8818 INTERNAL_INSN_CODE_NAME
, DFA_INSN_CODE_FUNC_NAME
,
8819 INSN_PARAMETER_NAME
,
8820 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
,
8821 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
8823 fprintf (output_file
, " fputs (reservation_names[%s], %s);\n}\n\n",
8824 INTERNAL_INSN_CODE_NAME
, FILE_PARAMETER_NAME
);
8827 /* The following function is used to sort unit declaration by their
8830 units_cmp (const void *unit1
, const void *unit2
)
8832 const unit_decl_t u1
= *(unit_decl_t
*) unit1
;
8833 const unit_decl_t u2
= *(unit_decl_t
*) unit2
;
8835 return strcmp (u1
->name
, u2
->name
);
8838 /* The following macro value is name of struct containing unit name
8840 #define NAME_CODE_STRUCT_NAME "name_code"
8842 /* The following macro value is name of table of struct name_code. */
8843 #define NAME_CODE_TABLE_NAME "name_code_table"
8845 /* The following macro values are member names for struct name_code. */
8846 #define NAME_MEMBER_NAME "name"
8847 #define CODE_MEMBER_NAME "code"
8849 /* The following macro values are local variable names for function
8850 `get_cpu_unit_code'. */
8851 #define CMP_VARIABLE_NAME "cmp"
8852 #define LOW_VARIABLE_NAME "l"
8853 #define MIDDLE_VARIABLE_NAME "m"
8854 #define HIGH_VARIABLE_NAME "h"
8856 /* The following function outputs function to obtain internal cpu unit
8857 code by the cpu unit name. */
8859 output_get_cpu_unit_code_func (void)
8864 fprintf (output_file
, "int\n%s (%s)\n\tconst char *%s;\n",
8865 GET_CPU_UNIT_CODE_FUNC_NAME
, CPU_UNIT_NAME_PARAMETER_NAME
,
8866 CPU_UNIT_NAME_PARAMETER_NAME
);
8867 fprintf (output_file
, "{\n struct %s {const char *%s; int %s;};\n",
8868 NAME_CODE_STRUCT_NAME
, NAME_MEMBER_NAME
, CODE_MEMBER_NAME
);
8869 fprintf (output_file
, " int %s, %s, %s, %s;\n", CMP_VARIABLE_NAME
,
8870 LOW_VARIABLE_NAME
, MIDDLE_VARIABLE_NAME
, HIGH_VARIABLE_NAME
);
8871 fprintf (output_file
, " static struct %s %s [] =\n {\n",
8872 NAME_CODE_STRUCT_NAME
, NAME_CODE_TABLE_NAME
);
8873 units
= xmalloc (sizeof (unit_decl_t
) * description
->units_num
);
8874 memcpy (units
, units_array
, sizeof (unit_decl_t
) * description
->units_num
);
8875 qsort (units
, description
->units_num
, sizeof (unit_decl_t
), units_cmp
);
8876 for (i
= 0; i
< description
->units_num
; i
++)
8877 if (units
[i
]->query_p
)
8878 fprintf (output_file
, " {\"%s\", %d},\n",
8879 units
[i
]->name
, units
[i
]->query_num
);
8880 fprintf (output_file
, " };\n\n");
8881 fprintf (output_file
, " /* The following is binary search: */\n");
8882 fprintf (output_file
, " %s = 0;\n", LOW_VARIABLE_NAME
);
8883 fprintf (output_file
, " %s = sizeof (%s) / sizeof (struct %s) - 1;\n",
8884 HIGH_VARIABLE_NAME
, NAME_CODE_TABLE_NAME
, NAME_CODE_STRUCT_NAME
);
8885 fprintf (output_file
, " while (%s <= %s)\n {\n",
8886 LOW_VARIABLE_NAME
, HIGH_VARIABLE_NAME
);
8887 fprintf (output_file
, " %s = (%s + %s) / 2;\n",
8888 MIDDLE_VARIABLE_NAME
, LOW_VARIABLE_NAME
, HIGH_VARIABLE_NAME
);
8889 fprintf (output_file
, " %s = strcmp (%s, %s [%s].%s);\n",
8890 CMP_VARIABLE_NAME
, CPU_UNIT_NAME_PARAMETER_NAME
,
8891 NAME_CODE_TABLE_NAME
, MIDDLE_VARIABLE_NAME
, NAME_MEMBER_NAME
);
8892 fprintf (output_file
, " if (%s < 0)\n", CMP_VARIABLE_NAME
);
8893 fprintf (output_file
, " %s = %s - 1;\n",
8894 HIGH_VARIABLE_NAME
, MIDDLE_VARIABLE_NAME
);
8895 fprintf (output_file
, " else if (%s > 0)\n", CMP_VARIABLE_NAME
);
8896 fprintf (output_file
, " %s = %s + 1;\n",
8897 LOW_VARIABLE_NAME
, MIDDLE_VARIABLE_NAME
);
8898 fprintf (output_file
, " else\n");
8899 fprintf (output_file
, " return %s [%s].%s;\n }\n",
8900 NAME_CODE_TABLE_NAME
, MIDDLE_VARIABLE_NAME
, CODE_MEMBER_NAME
);
8901 fprintf (output_file
, " return -1;\n}\n\n");
8905 /* The following function outputs function to check reservation of cpu
8906 unit (its internal code will be passed as the function argument) in
8909 output_cpu_unit_reservation_p (void)
8911 automaton_t automaton
;
8913 fprintf (output_file
, "int\n%s (%s, %s)\n\t%s %s;\n\tint %s;\n",
8914 CPU_UNIT_RESERVATION_P_FUNC_NAME
, STATE_NAME
,
8915 CPU_CODE_PARAMETER_NAME
, STATE_TYPE_NAME
, STATE_NAME
,
8916 CPU_CODE_PARAMETER_NAME
);
8917 fprintf (output_file
, "{\n if (%s < 0 || %s >= %d)\n abort ();\n",
8918 CPU_CODE_PARAMETER_NAME
, CPU_CODE_PARAMETER_NAME
,
8919 description
->query_units_num
);
8920 for (automaton
= description
->first_automaton
;
8922 automaton
= automaton
->next_automaton
)
8924 fprintf (output_file
, " if ((");
8925 output_reserved_units_table_name (output_file
, automaton
);
8926 fprintf (output_file
, " [((struct %s *) %s)->", CHIP_NAME
, STATE_NAME
);
8927 output_chip_member_name (output_file
, automaton
);
8928 fprintf (output_file
, " * %d + %s / 8] >> (%s %% 8)) & 1)\n",
8929 (description
->query_units_num
+ 7) / 8,
8930 CPU_CODE_PARAMETER_NAME
, CPU_CODE_PARAMETER_NAME
);
8931 fprintf (output_file
, " return 1;\n");
8933 fprintf (output_file
, " return 0;\n}\n\n");
8936 /* The function outputs PHR interface function `dfa_clean_insn_cache'. */
8938 output_dfa_clean_insn_cache_func (void)
8940 fprintf (output_file
,
8941 "void\n%s (void)\n{\n int %s;\n\n",
8942 DFA_CLEAN_INSN_CACHE_FUNC_NAME
, I_VARIABLE_NAME
);
8943 fprintf (output_file
,
8944 " for (%s = 0; %s < %s; %s++)\n %s [%s] = -1;\n}\n\n",
8945 I_VARIABLE_NAME
, I_VARIABLE_NAME
,
8946 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
, I_VARIABLE_NAME
,
8947 DFA_INSN_CODES_VARIABLE_NAME
, I_VARIABLE_NAME
);
8950 /* The function outputs PHR interface function `dfa_start'. */
8952 output_dfa_start_func (void)
8954 fprintf (output_file
,
8955 "void\n%s (void)\n{\n %s = get_max_uid ();\n",
8956 DFA_START_FUNC_NAME
, DFA_INSN_CODES_LENGTH_VARIABLE_NAME
);
8957 fprintf (output_file
, " %s = xmalloc (%s * sizeof (int));\n",
8958 DFA_INSN_CODES_VARIABLE_NAME
, DFA_INSN_CODES_LENGTH_VARIABLE_NAME
);
8959 fprintf (output_file
, " %s ();\n}\n\n", DFA_CLEAN_INSN_CACHE_FUNC_NAME
);
8962 /* The function outputs PHR interface function `dfa_finish'. */
8964 output_dfa_finish_func (void)
8966 fprintf (output_file
, "void\n%s (void)\n{\n free (%s);\n}\n\n",
8967 DFA_FINISH_FUNC_NAME
, DFA_INSN_CODES_VARIABLE_NAME
);
8972 /* The page contains code for output description file (readable
8973 representation of original description and generated DFA(s). */
8975 /* The function outputs string representation of IR reservation. */
8977 output_regexp (regexp_t regexp
)
8979 fprintf (output_description_file
, "%s", regexp_representation (regexp
));
8980 finish_regexp_representation ();
8983 /* Output names of units in LIST separated by comma. */
8985 output_unit_set_el_list (unit_set_el_t list
)
8989 for (el
= list
; el
!= NULL
; el
= el
->next_unit_set_el
)
8992 fprintf (output_description_file
, ", ");
8993 fprintf (output_description_file
, "%s", el
->unit_decl
->name
);
8997 /* Output patterns in LIST separated by comma. */
8999 output_pattern_set_el_list (pattern_set_el_t list
)
9001 pattern_set_el_t el
;
9004 for (el
= list
; el
!= NULL
; el
= el
->next_pattern_set_el
)
9007 fprintf (output_description_file
, ", ");
9008 for (i
= 0; i
< el
->units_num
; i
++)
9009 fprintf (output_description_file
, (i
== 0 ? "%s" : " %s"),
9010 el
->unit_decls
[i
]->name
);
9014 /* The function outputs string representation of IR define_reservation
9015 and define_insn_reservation. */
9017 output_description (void)
9022 for (i
= 0; i
< description
->decls_num
; i
++)
9024 decl
= description
->decls
[i
];
9025 if (decl
->mode
== dm_unit
)
9027 if (DECL_UNIT (decl
)->excl_list
!= NULL
)
9029 fprintf (output_description_file
, "unit %s exlusion_set: ",
9030 DECL_UNIT (decl
)->name
);
9031 output_unit_set_el_list (DECL_UNIT (decl
)->excl_list
);
9032 fprintf (output_description_file
, "\n");
9034 if (DECL_UNIT (decl
)->presence_list
!= NULL
)
9036 fprintf (output_description_file
, "unit %s presence_set: ",
9037 DECL_UNIT (decl
)->name
);
9038 output_pattern_set_el_list (DECL_UNIT (decl
)->presence_list
);
9039 fprintf (output_description_file
, "\n");
9041 if (DECL_UNIT (decl
)->final_presence_list
!= NULL
)
9043 fprintf (output_description_file
, "unit %s final_presence_set: ",
9044 DECL_UNIT (decl
)->name
);
9045 output_pattern_set_el_list
9046 (DECL_UNIT (decl
)->final_presence_list
);
9047 fprintf (output_description_file
, "\n");
9049 if (DECL_UNIT (decl
)->absence_list
!= NULL
)
9051 fprintf (output_description_file
, "unit %s absence_set: ",
9052 DECL_UNIT (decl
)->name
);
9053 output_pattern_set_el_list (DECL_UNIT (decl
)->absence_list
);
9054 fprintf (output_description_file
, "\n");
9056 if (DECL_UNIT (decl
)->final_absence_list
!= NULL
)
9058 fprintf (output_description_file
, "unit %s final_absence_set: ",
9059 DECL_UNIT (decl
)->name
);
9060 output_pattern_set_el_list
9061 (DECL_UNIT (decl
)->final_absence_list
);
9062 fprintf (output_description_file
, "\n");
9066 fprintf (output_description_file
, "\n");
9067 for (i
= 0; i
< description
->decls_num
; i
++)
9069 decl
= description
->decls
[i
];
9070 if (decl
->mode
== dm_reserv
)
9072 fprintf (output_description_file
, "reservation %s: ",
9073 DECL_RESERV (decl
)->name
);
9074 output_regexp (DECL_RESERV (decl
)->regexp
);
9075 fprintf (output_description_file
, "\n");
9077 else if (decl
->mode
== dm_insn_reserv
&& decl
!= advance_cycle_insn_decl
)
9079 fprintf (output_description_file
, "insn reservation %s ",
9080 DECL_INSN_RESERV (decl
)->name
);
9081 print_rtl (output_description_file
,
9082 DECL_INSN_RESERV (decl
)->condexp
);
9083 fprintf (output_description_file
, ": ");
9084 output_regexp (DECL_INSN_RESERV (decl
)->regexp
);
9085 fprintf (output_description_file
, "\n");
9087 else if (decl
->mode
== dm_bypass
)
9088 fprintf (output_description_file
, "bypass %d %s %s\n",
9089 DECL_BYPASS (decl
)->latency
,
9090 DECL_BYPASS (decl
)->out_insn_name
,
9091 DECL_BYPASS (decl
)->in_insn_name
);
9093 fprintf (output_description_file
, "\n\f\n");
9096 /* The function outputs name of AUTOMATON. */
9098 output_automaton_name (FILE *f
, automaton_t automaton
)
9100 if (automaton
->corresponding_automaton_decl
== NULL
)
9101 fprintf (f
, "#%d", automaton
->automaton_order_num
);
9103 fprintf (f
, "`%s'", automaton
->corresponding_automaton_decl
->name
);
9106 /* Maximal length of line for pretty printing into description
9108 #define MAX_LINE_LENGTH 70
9110 /* The function outputs units name belonging to AUTOMATON. */
9112 output_automaton_units (automaton_t automaton
)
9116 int curr_line_length
;
9117 int there_is_an_automaton_unit
;
9120 fprintf (output_description_file
, "\n Corresponding units:\n");
9121 fprintf (output_description_file
, " ");
9122 curr_line_length
= 4;
9123 there_is_an_automaton_unit
= 0;
9124 for (i
= 0; i
< description
->decls_num
; i
++)
9126 decl
= description
->decls
[i
];
9127 if (decl
->mode
== dm_unit
9128 && (DECL_UNIT (decl
)->corresponding_automaton_num
9129 == automaton
->automaton_order_num
))
9131 there_is_an_automaton_unit
= 1;
9132 name
= DECL_UNIT (decl
)->name
;
9133 if (curr_line_length
+ strlen (name
) + 1 > MAX_LINE_LENGTH
)
9135 curr_line_length
= strlen (name
) + 4;
9136 fprintf (output_description_file
, "\n ");
9140 curr_line_length
+= strlen (name
) + 1;
9141 fprintf (output_description_file
, " ");
9143 fprintf (output_description_file
, "%s", name
);
9146 if (!there_is_an_automaton_unit
)
9147 fprintf (output_description_file
, "<None>");
9148 fprintf (output_description_file
, "\n\n");
9151 /* The following variable is used for forming array of all possible cpu unit
9152 reservations described by the current DFA state. */
9153 static vla_ptr_t state_reservs
;
9155 /* The function forms `state_reservs' for STATE. */
9157 add_state_reservs (state_t state
)
9159 alt_state_t curr_alt_state
;
9160 reserv_sets_t reservs
;
9162 if (state
->component_states
!= NULL
)
9163 for (curr_alt_state
= state
->component_states
;
9164 curr_alt_state
!= NULL
;
9165 curr_alt_state
= curr_alt_state
->next_sorted_alt_state
)
9166 add_state_reservs (curr_alt_state
->state
);
9169 reservs
= state
->reservs
;
9170 VLA_PTR_ADD (state_reservs
, reservs
);
9174 /* The function outputs readable representation of all out arcs of
9177 output_state_arcs (state_t state
)
9182 int curr_line_length
;
9184 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
9187 if (!ainsn
->first_insn_with_same_reservs
)
9189 fprintf (output_description_file
, " ");
9190 curr_line_length
= 7;
9191 fprintf (output_description_file
, "%2d: ", ainsn
->insn_equiv_class_num
);
9194 insn_name
= ainsn
->insn_reserv_decl
->name
;
9195 if (curr_line_length
+ strlen (insn_name
) > MAX_LINE_LENGTH
)
9197 if (ainsn
!= arc
->insn
)
9199 fprintf (output_description_file
, ",\n ");
9200 curr_line_length
= strlen (insn_name
) + 6;
9203 curr_line_length
+= strlen (insn_name
);
9207 curr_line_length
+= strlen (insn_name
);
9208 if (ainsn
!= arc
->insn
)
9210 curr_line_length
+= 2;
9211 fprintf (output_description_file
, ", ");
9214 fprintf (output_description_file
, "%s", insn_name
);
9215 ainsn
= ainsn
->next_same_reservs_insn
;
9217 while (ainsn
!= NULL
);
9218 fprintf (output_description_file
, " %d (%d)\n",
9219 arc
->to_state
->order_state_num
, arc
->state_alts
);
9221 fprintf (output_description_file
, "\n");
9224 /* The following function is used for sorting possible cpu unit
9225 reservation of a DFA state. */
9227 state_reservs_cmp (const void *reservs_ptr_1
, const void *reservs_ptr_2
)
9229 return reserv_sets_cmp (*(reserv_sets_t
*) reservs_ptr_1
,
9230 *(reserv_sets_t
*) reservs_ptr_2
);
9233 /* The following function is used for sorting possible cpu unit
9234 reservation of a DFA state. */
9236 remove_state_duplicate_reservs (void)
9238 reserv_sets_t
*reservs_ptr
;
9239 reserv_sets_t
*last_formed_reservs_ptr
;
9241 last_formed_reservs_ptr
= NULL
;
9242 for (reservs_ptr
= VLA_PTR_BEGIN (state_reservs
);
9243 reservs_ptr
<= (reserv_sets_t
*) VLA_PTR_LAST (state_reservs
);
9245 if (last_formed_reservs_ptr
== NULL
)
9246 last_formed_reservs_ptr
= reservs_ptr
;
9247 else if (reserv_sets_cmp (*last_formed_reservs_ptr
, *reservs_ptr
) != 0)
9249 ++last_formed_reservs_ptr
;
9250 *last_formed_reservs_ptr
= *reservs_ptr
;
9252 VLA_PTR_SHORTEN (state_reservs
, reservs_ptr
- last_formed_reservs_ptr
- 1);
9255 /* The following function output readable representation of DFA(s)
9256 state used for fast recognition of pipeline hazards. State is
9257 described by possible (current and scheduled) cpu unit
9260 output_state (state_t state
)
9262 reserv_sets_t
*reservs_ptr
;
9264 VLA_PTR_CREATE (state_reservs
, 150, "state reservations");
9265 fprintf (output_description_file
, " State #%d", state
->order_state_num
);
9266 fprintf (output_description_file
,
9267 state
->new_cycle_p
? " (new cycle)\n" : "\n");
9268 add_state_reservs (state
);
9269 qsort (VLA_PTR_BEGIN (state_reservs
), VLA_PTR_LENGTH (state_reservs
),
9270 sizeof (reserv_sets_t
), state_reservs_cmp
);
9271 remove_state_duplicate_reservs ();
9272 for (reservs_ptr
= VLA_PTR_BEGIN (state_reservs
);
9273 reservs_ptr
<= (reserv_sets_t
*) VLA_PTR_LAST (state_reservs
);
9276 fprintf (output_description_file
, " ");
9277 output_reserv_sets (output_description_file
, *reservs_ptr
);
9278 fprintf (output_description_file
, "\n");
9280 fprintf (output_description_file
, "\n");
9281 output_state_arcs (state
);
9282 VLA_PTR_DELETE (state_reservs
);
9285 /* The following function output readable representation of
9286 DFAs used for fast recognition of pipeline hazards. */
9288 output_automaton_descriptions (void)
9290 automaton_t automaton
;
9292 for (automaton
= description
->first_automaton
;
9294 automaton
= automaton
->next_automaton
)
9296 fprintf (output_description_file
, "\nAutomaton ");
9297 output_automaton_name (output_description_file
, automaton
);
9298 fprintf (output_description_file
, "\n");
9299 output_automaton_units (automaton
);
9300 pass_states (automaton
, output_state
);
9306 /* The page contains top level function for generation DFA(s) used for
9309 /* The function outputs statistics about work of different phases of
9312 output_statistics (FILE *f
)
9314 automaton_t automaton
;
9317 int transition_comb_vect_els
= 0;
9318 int transition_full_vect_els
= 0;
9319 int state_alts_comb_vect_els
= 0;
9320 int state_alts_full_vect_els
= 0;
9321 int min_issue_delay_vect_els
= 0;
9324 for (automaton
= description
->first_automaton
;
9326 automaton
= automaton
->next_automaton
)
9328 fprintf (f
, "\nAutomaton ");
9329 output_automaton_name (f
, automaton
);
9330 fprintf (f
, "\n %5d NDFA states, %5d NDFA arcs\n",
9331 automaton
->NDFA_states_num
, automaton
->NDFA_arcs_num
);
9332 fprintf (f
, " %5d DFA states, %5d DFA arcs\n",
9333 automaton
->DFA_states_num
, automaton
->DFA_arcs_num
);
9334 states_num
= automaton
->DFA_states_num
;
9335 if (!no_minimization_flag
)
9337 fprintf (f
, " %5d minimal DFA states, %5d minimal DFA arcs\n",
9338 automaton
->minimal_DFA_states_num
,
9339 automaton
->minimal_DFA_arcs_num
);
9340 states_num
= automaton
->minimal_DFA_states_num
;
9342 fprintf (f
, " %5d all insns %5d insn equivalence classes\n",
9343 description
->insns_num
, automaton
->insn_equiv_classes_num
);
9346 (f
, "%5ld transition comb vector els, %5ld trans table els: %s\n",
9347 (long) VLA_HWINT_LENGTH (automaton
->trans_table
->comb_vect
),
9348 (long) VLA_HWINT_LENGTH (automaton
->trans_table
->full_vect
),
9349 (comb_vect_p (automaton
->trans_table
)
9350 ? "use comb vect" : "use simple vect"));
9352 (f
, "%5ld state alts comb vector els, %5ld state alts table els: %s\n",
9353 (long) VLA_HWINT_LENGTH (automaton
->state_alts_table
->comb_vect
),
9354 (long) VLA_HWINT_LENGTH (automaton
->state_alts_table
->full_vect
),
9355 (comb_vect_p (automaton
->state_alts_table
)
9356 ? "use comb vect" : "use simple vect"));
9358 (f
, "%5ld min delay table els, compression factor %d\n",
9359 (long) states_num
* automaton
->insn_equiv_classes_num
,
9360 automaton
->min_issue_delay_table_compression_factor
);
9361 transition_comb_vect_els
9362 += VLA_HWINT_LENGTH (automaton
->trans_table
->comb_vect
);
9363 transition_full_vect_els
9364 += VLA_HWINT_LENGTH (automaton
->trans_table
->full_vect
);
9365 state_alts_comb_vect_els
9366 += VLA_HWINT_LENGTH (automaton
->state_alts_table
->comb_vect
);
9367 state_alts_full_vect_els
9368 += VLA_HWINT_LENGTH (automaton
->state_alts_table
->full_vect
);
9369 min_issue_delay_vect_els
9370 += states_num
* automaton
->insn_equiv_classes_num
;
9374 fprintf (f
, "\n%5d all allocated states, %5d all allocated arcs\n",
9375 allocated_states_num
, allocated_arcs_num
);
9376 fprintf (f
, "%5d all allocated alternative states\n",
9377 allocated_alt_states_num
);
9378 fprintf (f
, "%5d all transition comb vector els, %5d all trans table els\n",
9379 transition_comb_vect_els
, transition_full_vect_els
);
9381 (f
, "%5d all state alts comb vector els, %5d all state alts table els\n",
9382 state_alts_comb_vect_els
, state_alts_full_vect_els
);
9383 fprintf (f
, "%5d all min delay table els\n", min_issue_delay_vect_els
);
9384 fprintf (f
, "%5d locked states num\n", locked_states_num
);
9388 /* The function output times of work of different phases of DFA
9391 output_time_statistics (FILE *f
)
9393 fprintf (f
, "\n transformation: ");
9394 print_active_time (f
, transform_time
);
9395 fprintf (f
, (!ndfa_flag
? ", building DFA: " : ", building NDFA: "));
9396 print_active_time (f
, NDFA_time
);
9399 fprintf (f
, ", NDFA -> DFA: ");
9400 print_active_time (f
, NDFA_to_DFA_time
);
9402 fprintf (f
, "\n DFA minimization: ");
9403 print_active_time (f
, minimize_time
);
9404 fprintf (f
, ", making insn equivalence: ");
9405 print_active_time (f
, equiv_time
);
9406 fprintf (f
, "\n all automaton generation: ");
9407 print_active_time (f
, automaton_generation_time
);
9408 fprintf (f
, ", output: ");
9409 print_active_time (f
, output_time
);
9413 /* The function generates DFA (deterministic finite state automaton)
9414 for fast recognition of pipeline hazards. No errors during
9415 checking must be fixed before this function call. */
9419 automata_num
= split_argument
;
9420 if (description
->units_num
< automata_num
)
9421 automata_num
= description
->units_num
;
9424 initiate_automata_lists ();
9425 initiate_pass_states ();
9426 initiate_excl_sets ();
9427 initiate_presence_absence_pattern_sets ();
9428 automaton_generation_time
= create_ticker ();
9430 ticker_off (&automaton_generation_time
);
9435 /* The following function creates insn attribute whose values are
9436 number alternatives in insn reservations. */
9438 make_insn_alts_attr (void)
9444 condexp
= rtx_alloc (COND
);
9445 XVEC (condexp
, 0) = rtvec_alloc ((description
->insns_num
- 1) * 2);
9446 XEXP (condexp
, 1) = make_numeric_value (0);
9447 for (i
= insn_num
= 0; i
< description
->decls_num
; i
++)
9449 decl
= description
->decls
[i
];
9450 if (decl
->mode
== dm_insn_reserv
&& decl
!= advance_cycle_insn_decl
)
9452 XVECEXP (condexp
, 0, 2 * insn_num
)
9453 = DECL_INSN_RESERV (decl
)->condexp
;
9454 XVECEXP (condexp
, 0, 2 * insn_num
+ 1)
9455 = make_numeric_value
9456 (DECL_INSN_RESERV (decl
)->transformed_regexp
->mode
!= rm_oneof
9457 ? 1 : REGEXP_ONEOF (DECL_INSN_RESERV (decl
)
9458 ->transformed_regexp
)->regexps_num
);
9462 if (description
->insns_num
!= insn_num
+ 1)
9464 make_internal_attr (attr_printf (sizeof ("*")
9465 + strlen (INSN_ALTS_FUNC_NAME
) + 1,
9466 "*%s", INSN_ALTS_FUNC_NAME
),
9467 condexp
, ATTR_NONE
);
9472 /* The following function creates attribute which is order number of
9473 insn in pipeline hazard description translator. */
9475 make_internal_dfa_insn_code_attr (void)
9481 condexp
= rtx_alloc (COND
);
9482 XVEC (condexp
, 0) = rtvec_alloc ((description
->insns_num
- 1) * 2);
9484 = make_numeric_value (DECL_INSN_RESERV (advance_cycle_insn_decl
)
9486 for (i
= insn_num
= 0; i
< description
->decls_num
; i
++)
9488 decl
= description
->decls
[i
];
9489 if (decl
->mode
== dm_insn_reserv
&& decl
!= advance_cycle_insn_decl
)
9491 XVECEXP (condexp
, 0, 2 * insn_num
)
9492 = DECL_INSN_RESERV (decl
)->condexp
;
9493 XVECEXP (condexp
, 0, 2 * insn_num
+ 1)
9494 = make_numeric_value (DECL_INSN_RESERV (decl
)->insn_num
);
9498 if (description
->insns_num
!= insn_num
+ 1)
9501 (attr_printf (sizeof ("*")
9502 + strlen (INTERNAL_DFA_INSN_CODE_FUNC_NAME
) + 1,
9503 "*%s", INTERNAL_DFA_INSN_CODE_FUNC_NAME
),
9504 condexp
, ATTR_STATIC
);
9509 /* The following function creates attribute which order number of insn
9510 in pipeline hazard description translator. */
9512 make_default_insn_latency_attr (void)
9518 condexp
= rtx_alloc (COND
);
9519 XVEC (condexp
, 0) = rtvec_alloc ((description
->insns_num
- 1) * 2);
9520 XEXP (condexp
, 1) = make_numeric_value (0);
9521 for (i
= insn_num
= 0; i
< description
->decls_num
; i
++)
9523 decl
= description
->decls
[i
];
9524 if (decl
->mode
== dm_insn_reserv
&& decl
!= advance_cycle_insn_decl
)
9526 XVECEXP (condexp
, 0, 2 * insn_num
)
9527 = DECL_INSN_RESERV (decl
)->condexp
;
9528 XVECEXP (condexp
, 0, 2 * insn_num
+ 1)
9529 = make_numeric_value (DECL_INSN_RESERV (decl
)->default_latency
);
9533 if (description
->insns_num
!= insn_num
+ 1)
9535 make_internal_attr (attr_printf (sizeof ("*")
9536 + strlen (INSN_DEFAULT_LATENCY_FUNC_NAME
)
9537 + 1, "*%s", INSN_DEFAULT_LATENCY_FUNC_NAME
),
9538 condexp
, ATTR_NONE
);
9543 /* The following function creates attribute which returns 1 if given
9544 output insn has bypassing and 0 otherwise. */
9546 make_bypass_attr (void)
9549 int bypass_insns_num
= 0;
9553 for (i
= 0; i
< description
->decls_num
; i
++)
9555 decl
= description
->decls
[i
];
9556 if (decl
->mode
== dm_insn_reserv
9557 && DECL_INSN_RESERV (decl
)->condexp
!= NULL
9558 && DECL_INSN_RESERV (decl
)->bypass_list
!= NULL
)
9561 if (bypass_insns_num
== 0)
9562 result_rtx
= make_numeric_value (0);
9565 result_rtx
= rtx_alloc (COND
);
9566 XVEC (result_rtx
, 0) = rtvec_alloc (bypass_insns_num
* 2);
9567 XEXP (result_rtx
, 1) = make_numeric_value (0);
9569 for (i
= bypass_insn
= 0; i
< description
->decls_num
; i
++)
9571 decl
= description
->decls
[i
];
9572 if (decl
->mode
== dm_insn_reserv
9573 && DECL_INSN_RESERV (decl
)->condexp
!= NULL
9574 && DECL_INSN_RESERV (decl
)->bypass_list
!= NULL
)
9576 XVECEXP (result_rtx
, 0, 2 * bypass_insn
)
9577 = DECL_INSN_RESERV (decl
)->condexp
;
9578 XVECEXP (result_rtx
, 0, 2 * bypass_insn
+ 1)
9579 = make_numeric_value (1);
9584 make_internal_attr (attr_printf (sizeof ("*")
9585 + strlen (BYPASS_P_FUNC_NAME
) + 1,
9586 "*%s", BYPASS_P_FUNC_NAME
),
9587 result_rtx
, ATTR_NONE
);
9592 /* This page mainly contains top level functions of pipeline hazards
9593 description translator. */
9595 /* The following macro value is suffix of name of description file of
9596 pipeline hazards description translator. */
9597 #define STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX ".dfa"
9599 /* The function returns suffix of given file name. The returned
9600 string can not be changed. */
9602 file_name_suffix (const char *file_name
)
9604 const char *last_period
;
9606 for (last_period
= NULL
; *file_name
!= '\0'; file_name
++)
9607 if (*file_name
== '.')
9608 last_period
= file_name
;
9609 return (last_period
== NULL
? file_name
: last_period
);
9612 /* The function returns base name of given file name, i.e. pointer to
9613 first char after last `/' (or `\' for WIN32) in given file name,
9614 given file name itself if the directory name is absent. The
9615 returned string can not be changed. */
9617 base_file_name (const char *file_name
)
9619 int directory_name_length
;
9621 directory_name_length
= strlen (file_name
);
9623 while (directory_name_length
>= 0 && file_name
[directory_name_length
] != '/'
9624 && file_name
[directory_name_length
] != '\\')
9626 while (directory_name_length
>= 0 && file_name
[directory_name_length
] != '/')
9628 directory_name_length
--;
9629 return file_name
+ directory_name_length
+ 1;
9632 /* The following is top level function to initialize the work of
9633 pipeline hazards description translator. */
9635 initiate_automaton_gen (int argc
, char **argv
)
9637 const char *base_name
;
9641 split_argument
= 0; /* default value */
9642 no_minimization_flag
= 0;
9647 for (i
= 2; i
< argc
; i
++)
9648 if (strcmp (argv
[i
], NO_MINIMIZATION_OPTION
) == 0)
9649 no_minimization_flag
= 1;
9650 else if (strcmp (argv
[i
], TIME_OPTION
) == 0)
9652 else if (strcmp (argv
[i
], V_OPTION
) == 0)
9654 else if (strcmp (argv
[i
], W_OPTION
) == 0)
9656 else if (strcmp (argv
[i
], NDFA_OPTION
) == 0)
9658 else if (strcmp (argv
[i
], PROGRESS_OPTION
) == 0)
9660 else if (strcmp (argv
[i
], "-split") == 0)
9663 fatal ("-split has no argument.");
9664 fatal ("option `-split' has not been implemented yet\n");
9665 /* split_argument = atoi (argument_vect [i + 1]); */
9667 VLA_PTR_CREATE (decls
, 150, "decls");
9668 /* Initialize IR storage. */
9669 obstack_init (&irp
);
9670 initiate_automaton_decl_table ();
9671 initiate_insn_decl_table ();
9672 initiate_decl_table ();
9673 output_file
= stdout
;
9674 output_description_file
= NULL
;
9675 base_name
= base_file_name (argv
[1]);
9676 obstack_grow (&irp
, base_name
,
9677 strlen (base_name
) - strlen (file_name_suffix (base_name
)));
9678 obstack_grow (&irp
, STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX
,
9679 strlen (STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX
) + 1);
9680 obstack_1grow (&irp
, '\0');
9681 output_description_file_name
= obstack_base (&irp
);
9682 obstack_finish (&irp
);
9685 /* The following function checks existence at least one arc marked by
9688 check_automata_insn_issues (void)
9690 automaton_t automaton
;
9691 ainsn_t ainsn
, reserv_ainsn
;
9693 for (automaton
= description
->first_automaton
;
9695 automaton
= automaton
->next_automaton
)
9697 for (ainsn
= automaton
->ainsn_list
;
9699 ainsn
= ainsn
->next_ainsn
)
9700 if (ainsn
->first_insn_with_same_reservs
&& !ainsn
->arc_exists_p
)
9702 for (reserv_ainsn
= ainsn
;
9703 reserv_ainsn
!= NULL
;
9704 reserv_ainsn
= reserv_ainsn
->next_same_reservs_insn
)
9705 if (automaton
->corresponding_automaton_decl
!= NULL
)
9708 error ("Automaton `%s': Insn `%s' will never be issued",
9709 automaton
->corresponding_automaton_decl
->name
,
9710 reserv_ainsn
->insn_reserv_decl
->name
);
9713 ("Automaton `%s': Insn `%s' will never be issued",
9714 automaton
->corresponding_automaton_decl
->name
,
9715 reserv_ainsn
->insn_reserv_decl
->name
);
9720 error ("Insn `%s' will never be issued",
9721 reserv_ainsn
->insn_reserv_decl
->name
);
9723 warning ("Insn `%s' will never be issued",
9724 reserv_ainsn
->insn_reserv_decl
->name
);
9730 /* The following vla is used for storing pointers to all achieved
9732 static vla_ptr_t automaton_states
;
9734 /* This function is called by function pass_states to add an achieved
9737 add_automaton_state (state_t state
)
9739 VLA_PTR_ADD (automaton_states
, state
);
9742 /* The following function forms list of important automata (whose
9743 states may be changed after the insn issue) for each insn. */
9745 form_important_insn_automata_lists (void)
9747 automaton_t automaton
;
9754 VLA_PTR_CREATE (automaton_states
, 1500,
9755 "automaton states for forming important insn automata sets");
9756 /* Mark important ainsns. */
9757 for (automaton
= description
->first_automaton
;
9759 automaton
= automaton
->next_automaton
)
9761 VLA_PTR_NULLIFY (automaton_states
);
9762 pass_states (automaton
, add_automaton_state
);
9763 for (state_ptr
= VLA_PTR_BEGIN (automaton_states
);
9764 state_ptr
<= (state_t
*) VLA_PTR_LAST (automaton_states
);
9767 for (arc
= first_out_arc (*state_ptr
);
9769 arc
= next_out_arc (arc
))
9770 if (arc
->to_state
!= *state_ptr
)
9772 if (!arc
->insn
->first_insn_with_same_reservs
)
9774 for (ainsn
= arc
->insn
;
9776 ainsn
= ainsn
->next_same_reservs_insn
)
9777 ainsn
->important_p
= TRUE
;
9781 VLA_PTR_DELETE (automaton_states
);
9782 /* Create automata sets for the insns. */
9783 for (i
= 0; i
< description
->decls_num
; i
++)
9785 decl
= description
->decls
[i
];
9786 if (decl
->mode
== dm_insn_reserv
)
9788 automata_list_start ();
9789 for (automaton
= description
->first_automaton
;
9791 automaton
= automaton
->next_automaton
)
9792 for (ainsn
= automaton
->ainsn_list
;
9794 ainsn
= ainsn
->next_ainsn
)
9795 if (ainsn
->important_p
9796 && ainsn
->insn_reserv_decl
== DECL_INSN_RESERV (decl
))
9798 automata_list_add (automaton
);
9801 DECL_INSN_RESERV (decl
)->important_automata_list
9802 = automata_list_finish ();
9808 /* The following is top level function to generate automat(a,on) for
9809 fast recognition of pipeline hazards. */
9811 expand_automata (void)
9815 description
= create_node (sizeof (struct description
)
9816 /* One entry for cycle advancing insn. */
9817 + sizeof (decl_t
) * VLA_PTR_LENGTH (decls
));
9818 description
->decls_num
= VLA_PTR_LENGTH (decls
);
9819 description
->query_units_num
= 0;
9820 for (i
= 0; i
< description
->decls_num
; i
++)
9822 description
->decls
[i
] = VLA_PTR (decls
, i
);
9823 if (description
->decls
[i
]->mode
== dm_unit
9824 && DECL_UNIT (description
->decls
[i
])->query_p
)
9825 DECL_UNIT (description
->decls
[i
])->query_num
9826 = description
->query_units_num
++;
9828 all_time
= create_ticker ();
9829 check_time
= create_ticker ();
9831 fprintf (stderr
, "Check description...");
9832 check_all_description ();
9834 fprintf (stderr
, "done\n");
9835 ticker_off (&check_time
);
9836 generation_time
= create_ticker ();
9839 transform_insn_regexps ();
9840 check_unit_distributions_to_automata ();
9845 check_automata_insn_issues ();
9849 form_important_insn_automata_lists ();
9851 fprintf (stderr
, "Generation of attributes...");
9852 make_internal_dfa_insn_code_attr ();
9853 make_insn_alts_attr ();
9854 make_default_insn_latency_attr ();
9855 make_bypass_attr ();
9857 fprintf (stderr
, "done\n");
9859 ticker_off (&generation_time
);
9860 ticker_off (&all_time
);
9862 fprintf (stderr
, "All other genattrtab stuff...");
9865 /* The following is top level function to output PHR and to finish
9866 work with pipeline description translator. */
9868 write_automata (void)
9871 fprintf (stderr
, "done\n");
9873 fatal ("Errors in DFA description");
9874 ticker_on (&all_time
);
9875 output_time
= create_ticker ();
9877 fprintf (stderr
, "Forming and outputting automata tables...");
9878 output_dfa_max_issue_rate ();
9882 fprintf (stderr
, "done\n");
9883 fprintf (stderr
, "Output functions to work with automata...");
9885 output_chip_definitions ();
9886 output_max_insn_queue_index_def ();
9887 output_internal_min_issue_delay_func ();
9888 output_internal_trans_func ();
9889 /* Cache of insn dfa codes: */
9890 fprintf (output_file
, "\nstatic int *%s;\n", DFA_INSN_CODES_VARIABLE_NAME
);
9891 fprintf (output_file
, "\nstatic int %s;\n\n",
9892 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
);
9893 output_dfa_insn_code_func ();
9894 output_trans_func ();
9895 fprintf (output_file
, "\n#if %s\n\n", AUTOMATON_STATE_ALTS_MACRO_NAME
);
9896 output_internal_state_alts_func ();
9897 output_state_alts_func ();
9898 fprintf (output_file
, "\n#endif /* #if %s */\n\n",
9899 AUTOMATON_STATE_ALTS_MACRO_NAME
);
9900 output_min_issue_delay_func ();
9901 output_internal_dead_lock_func ();
9902 output_dead_lock_func ();
9903 output_size_func ();
9904 output_internal_reset_func ();
9905 output_reset_func ();
9906 output_min_insn_conflict_delay_func ();
9907 output_internal_insn_latency_func ();
9908 output_insn_latency_func ();
9909 output_print_reservation_func ();
9910 /* Output function get_cpu_unit_code. */
9911 fprintf (output_file
, "\n#if %s\n\n", CPU_UNITS_QUERY_MACRO_NAME
);
9912 output_get_cpu_unit_code_func ();
9913 output_cpu_unit_reservation_p ();
9914 fprintf (output_file
, "\n#endif /* #if %s */\n\n",
9915 CPU_UNITS_QUERY_MACRO_NAME
);
9916 output_dfa_clean_insn_cache_func ();
9917 output_dfa_start_func ();
9918 output_dfa_finish_func ();
9920 fprintf (stderr
, "done\n");
9923 output_description_file
= fopen (output_description_file_name
, "w");
9924 if (output_description_file
== NULL
)
9926 perror (output_description_file_name
);
9927 exit (FATAL_EXIT_CODE
);
9930 fprintf (stderr
, "Output automata description...");
9931 output_description ();
9932 output_automaton_descriptions ();
9934 fprintf (stderr
, "done\n");
9935 output_statistics (output_description_file
);
9937 output_statistics (stderr
);
9938 ticker_off (&output_time
);
9939 output_time_statistics (stderr
);
9942 finish_automata_lists ();
9945 fprintf (stderr
, "Summary:\n");
9946 fprintf (stderr
, " check time ");
9947 print_active_time (stderr
, check_time
);
9948 fprintf (stderr
, ", generation time ");
9949 print_active_time (stderr
, generation_time
);
9950 fprintf (stderr
, ", all time ");
9951 print_active_time (stderr
, all_time
);
9952 fprintf (stderr
, "\n");
9954 /* Finish all work. */
9955 if (output_description_file
!= NULL
)
9957 fflush (output_description_file
);
9958 if (ferror (stdout
) != 0)
9959 fatal ("Error in writing DFA description file %s",
9960 output_description_file_name
);
9961 fclose (output_description_file
);
9963 finish_automaton_decl_table ();
9964 finish_insn_decl_table ();
9965 finish_decl_table ();
9966 obstack_free (&irp
, NULL
);
9967 if (have_error
&& output_description_file
!= NULL
)
9968 remove (output_description_file_name
);