1 /* Pipeline hazard description translator.
2 Copyright (C) 2000, 2001, 2002, 2003 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 /* The following flags are set up by function `initiate_automaton_gen'. */
663 /* Make automata with nondeterministic reservation by insns (`-ndfa'). */
664 static int ndfa_flag
;
666 /* Do not make minimization of DFA (`-no-minimization'). */
667 static int no_minimization_flag
;
669 /* Value of this variable is number of automata being generated. The
670 actual number of automata may be less this value if there is not
671 sufficient number of units. This value is defined by argument of
672 option `-split' or by constructions automaton if the value is zero
673 (it is default value of the argument). */
674 static int split_argument
;
676 /* Flag of output time statistics (`-time'). */
677 static int time_flag
;
679 /* Flag of creation of description file which contains description of
680 result automaton and statistics information (`-v'). */
683 /* Flag of generating warning instead of error for non-critical errors
688 /* Output file for pipeline hazard recognizer (PHR) being generated.
689 The value is NULL if the file is not defined. */
690 static FILE *output_file
;
692 /* Description file of PHR. The value is NULL if the file is not
694 static FILE *output_description_file
;
696 /* PHR description file name. */
697 static char *output_description_file_name
;
699 /* Value of the following variable is node representing description
700 being processed. This is start point of IR. */
701 static struct description
*description
;
705 /* This page contains description of IR structure (nodes). */
719 /* This describes define_cpu_unit and define_query_cpu_unit (see file
724 /* NULL if the automaton name is absent. */
725 char *automaton_name
;
726 /* If the following value is not zero, the cpu unit reservation is
727 described in define_query_cpu_unit. */
730 /* The following fields are defined by checker. */
732 /* The following field value is nonzero if the unit is used in an
736 /* The following field value is order number (0, 1, ...) of given
739 /* The following field value is corresponding declaration of
740 automaton which was given in description. If the field value is
741 NULL then automaton in the unit declaration was absent. */
742 struct automaton_decl
*automaton_decl
;
743 /* The following field value is maximal cycle number (1, ...) on
744 which given unit occurs in insns. Zero value means that given
745 unit is not used in insns. */
746 int max_occ_cycle_num
;
747 /* The following field value is minimal cycle number (0, ...) on
748 which given unit occurs in insns. -1 value means that given
749 unit is not used in insns. */
750 int min_occ_cycle_num
;
751 /* The following list contains units which conflict with given
753 unit_set_el_t excl_list
;
754 /* The following list contains patterns which are required to
755 reservation of given unit. */
756 pattern_set_el_t presence_list
;
757 pattern_set_el_t final_presence_list
;
758 /* The following list contains patterns which should be not present
759 in reservation for given unit. */
760 pattern_set_el_t absence_list
;
761 pattern_set_el_t final_absence_list
;
762 /* The following is used only when `query_p' has nonzero value.
763 This is query number for the unit. */
765 /* The following is the last cycle on which the unit was checked for
766 correct distributions of units to automata in a regexp. */
767 int last_distribution_check_cycle
;
769 /* The following fields are defined by automaton generator. */
771 /* The following field value is number of the automaton to which
772 given unit belongs. */
773 int corresponding_automaton_num
;
774 /* If the following value is not zero, the cpu unit is present in a
775 `exclusion_set' or in right part of a `presence_set',
776 `final_presence_set', `absence_set', and
777 `final_absence_set'define_query_cpu_unit. */
781 /* This describes define_bypass (see file rtl.def). */
787 char *bypass_guard_name
;
789 /* The following fields are defined by checker. */
791 /* output and input insns of given bypass. */
792 struct insn_reserv_decl
*out_insn_reserv
;
793 struct insn_reserv_decl
*in_insn_reserv
;
794 /* The next bypass for given output insn. */
795 struct bypass_decl
*next
;
798 /* This describes define_automaton (see file rtl.def). */
799 struct automaton_decl
803 /* The following fields are defined by automaton generator. */
805 /* The following field value is nonzero if the automaton is used in
806 an regexp definition. */
807 char automaton_is_used
;
809 /* The following fields are defined by checker. */
811 /* The following field value is the corresponding automaton. This
812 field is not NULL only if the automaton is present in unit
813 declarations and the automatic partition on automata is not
815 automaton_t corresponding_automaton
;
818 /* This describes exclusion relations: exclusion_set (see file
823 int first_list_length
;
827 /* This describes unit relations: [final_]presence_set or
828 [final_]absence_set (see file rtl.def). */
829 struct unit_pattern_rel_decl
838 /* This describes define_reservation (see file rtl.def). */
844 /* The following fields are defined by checker. */
846 /* The following field value is nonzero if the unit is used in an
849 /* The following field is used to check up cycle in expression
854 /* This describes define_insn_reservation (see file rtl.def). */
855 struct insn_reserv_decl
862 /* The following fields are defined by checker. */
864 /* The following field value is order number (0, 1, ...) of given
867 /* The following field value is list of bypasses in which given insn
869 struct bypass_decl
*bypass_list
;
871 /* The following fields are defined by automaton generator. */
873 /* The following field is the insn regexp transformed that
874 the regexp has not optional regexp, repetition regexp, and an
875 reservation name (i.e. reservation identifiers are changed by the
876 corresponding regexp) and all alternations are the topest level
877 of the regexp. The value can be NULL only if it is special
878 insn `cycle advancing'. */
879 regexp_t transformed_regexp
;
880 /* The following field value is list of arcs marked given
881 insn. The field is used in transformation NDFA -> DFA. */
882 arc_t arcs_marked_by_insn
;
883 /* The two following fields are used during minimization of a finite state
885 /* The field value is number of equivalence class of state into
886 which arc marked by given insn enters from a state (fixed during
887 an automaton minimization). */
889 /* The field value is state_alts of arc leaving a state (fixed
890 during an automaton minimization) and marked by given insn
893 /* The following member value is the list to automata which can be
894 changed by the insn issue. */
895 automata_list_el_t important_automata_list
;
896 /* The following member is used to process insn once for output. */
900 /* This contains a declaration mentioned above. */
903 /* What node in the union? */
908 struct unit_decl unit
;
909 struct bypass_decl bypass
;
910 struct automaton_decl automaton
;
911 struct excl_rel_decl excl
;
912 struct unit_pattern_rel_decl presence
;
913 struct unit_pattern_rel_decl absence
;
914 struct reserv_decl reserv
;
915 struct insn_reserv_decl insn_reserv
;
919 /* The following structures represent parsed reservation strings. */
931 /* Cpu unit in reservation. */
935 unit_decl_t unit_decl
;
938 /* Define_reservation in a reservation. */
942 struct reserv_decl
*reserv_decl
;
945 /* Absence of reservation (represented by string `nothing'). */
946 struct nothing_regexp
948 /* This used to be empty but ISO C doesn't allow that. */
952 /* Representation of reservations separated by ',' (see file
954 struct sequence_regexp
957 regexp_t regexps
[1];
960 /* Representation of construction `repeat' (see file rtl.def). */
967 /* Representation of reservations separated by '+' (see file
972 regexp_t regexps
[1];
975 /* Representation of reservations separated by '|' (see file
980 regexp_t regexps
[1];
983 /* Representation of a reservation string. */
986 /* What node in the union? */
987 enum regexp_mode mode
;
991 struct unit_regexp unit
;
992 struct reserv_regexp reserv
;
993 struct nothing_regexp nothing
;
994 struct sequence_regexp sequence
;
995 struct repeat_regexp repeat
;
996 struct allof_regexp allof
;
997 struct oneof_regexp oneof
;
1001 /* Represents description of pipeline hazard description based on
1007 /* The following fields are defined by checker. */
1009 /* The following fields values are correspondingly number of all
1010 units, query units, and insns in the description. */
1012 int query_units_num
;
1014 /* The following field value is max length (in cycles) of
1015 reservations of insns. The field value is defined only for
1016 correct programs. */
1017 int max_insn_reserv_cycles
;
1019 /* The following fields are defined by automaton generator. */
1021 /* The following field value is the first automaton. */
1022 automaton_t first_automaton
;
1024 /* The following field is created by pipeline hazard parser and
1025 contains all declarations. We allocate additional entry for
1026 special insn "cycle advancing" which is added by the automaton
1032 /* The following nodes are created in automaton checker. */
1034 /* The following nodes represent exclusion set for cpu units. Each
1035 element is accessed through only one excl_list. */
1038 unit_decl_t unit_decl
;
1039 unit_set_el_t next_unit_set_el
;
1042 /* The following nodes represent presence or absence pattern for cpu
1043 units. Each element is accessed through only one presence_list or
1045 struct pattern_set_el
1047 /* The number of units in unit_decls. */
1049 /* The units forming the pattern. */
1050 struct unit_decl
**unit_decls
;
1051 pattern_set_el_t next_pattern_set_el
;
1055 /* The following nodes are created in automaton generator. */
1058 /* The following nodes represent presence or absence pattern for cpu
1059 units. Each element is accessed through only one element of
1060 unit_presence_set_table or unit_absence_set_table. */
1061 struct pattern_reserv
1063 reserv_sets_t reserv
;
1064 pattern_reserv_t next_pattern_reserv
;
1067 /* The following node type describes state automaton. The state may
1068 be deterministic or non-deterministic. Non-deterministic state has
1069 several component states which represent alternative cpu units
1070 reservations. The state also is used for describing a
1071 deterministic reservation of automaton insn. */
1074 /* The following member value is nonzero if there is a transition by
1077 /* The following field is list of processor unit reservations on
1079 reserv_sets_t reservs
;
1080 /* The following field is unique number of given state between other
1083 /* The following field value is automaton to which given state
1085 automaton_t automaton
;
1086 /* The following field value is the first arc output from given
1088 arc_t first_out_arc
;
1089 /* The following field is used to form NDFA. */
1090 char it_was_placed_in_stack_for_NDFA_forming
;
1091 /* The following field is used to form DFA. */
1092 char it_was_placed_in_stack_for_DFA_forming
;
1093 /* The following field is used to transform NDFA to DFA and DFA
1094 minimization. The field value is not NULL if the state is a
1095 compound state. In this case the value of field `unit_sets_list'
1096 is NULL. All states in the list are in the hash table. The list
1097 is formed through field `next_sorted_alt_state'. We should
1098 support only one level of nesting state. */
1099 alt_state_t component_states
;
1100 /* The following field is used for passing graph of states. */
1102 /* The list of states belonging to one equivalence class is formed
1103 with the aid of the following field. */
1104 state_t next_equiv_class_state
;
1105 /* The two following fields are used during minimization of a finite
1107 int equiv_class_num_1
, equiv_class_num_2
;
1108 /* The following field is used during minimization of a finite state
1109 automaton. The field value is state corresponding to equivalence
1110 class to which given state belongs. */
1111 state_t equiv_class_state
;
1112 /* The following field value is the order number of given state.
1113 The states in final DFA is enumerated with the aid of the
1115 int order_state_num
;
1116 /* This member is used for passing states for searching minimal
1119 /* The following member is used to evaluate min issue delay of insn
1121 int min_insn_issue_delay
;
1122 /* The following member is used to evaluate max issue rate of the
1123 processor. The value of the member is maximal length of the path
1124 from given state no containing arcs marked by special insn `cycle
1126 int longest_path_length
;
1129 /* The following macro is an initial value of member
1130 `longest_path_length' of a state. */
1131 #define UNDEFINED_LONGEST_PATH_LENGTH -1
1133 /* Automaton arc. */
1136 /* The following field refers for the state into which given arc
1139 /* The following field describes that the insn issue (with cycle
1140 advancing for special insn `cycle advancing' and without cycle
1141 advancing for others) makes transition from given state to
1142 another given state. */
1144 /* The following field value is the next arc output from the same
1147 /* List of arcs marked given insn is formed with the following
1148 field. The field is used in transformation NDFA -> DFA. */
1149 arc_t next_arc_marked_by_insn
;
1150 /* The following field is defined if NDFA_FLAG is zero. The member
1151 value is number of alternative reservations which can be used for
1152 transition for given state by given insn. */
1156 /* The following node type describes a deterministic alternative in
1157 non-deterministic state which characterizes cpu unit reservations
1158 of automaton insn or which is part of NDFA. */
1161 /* The following field is a deterministic state which characterizes
1162 unit reservations of the instruction. */
1164 /* The following field refers to the next state which characterizes
1165 unit reservations of the instruction. */
1166 alt_state_t next_alt_state
;
1167 /* The following field refers to the next state in sorted list. */
1168 alt_state_t next_sorted_alt_state
;
1171 /* The following node type describes insn of automaton. They are
1172 labels of FA arcs. */
1175 /* The following field value is the corresponding insn declaration
1177 struct insn_reserv_decl
*insn_reserv_decl
;
1178 /* The following field value is the next insn declaration for an
1181 /* The following field is states which characterize automaton unit
1182 reservations of the instruction. The value can be NULL only if it
1183 is special insn `cycle advancing'. */
1184 alt_state_t alt_states
;
1185 /* The following field is sorted list of states which characterize
1186 automaton unit reservations of the instruction. The value can be
1187 NULL only if it is special insn `cycle advancing'. */
1188 alt_state_t sorted_alt_states
;
1189 /* The following field refers the next automaton insn with
1190 the same reservations. */
1191 ainsn_t next_same_reservs_insn
;
1192 /* The following field is flag of the first automaton insn with the
1193 same reservations in the declaration list. Only arcs marked such
1194 insn is present in the automaton. This significantly decreases
1195 memory requirements especially when several automata are
1197 char first_insn_with_same_reservs
;
1198 /* The following member has nonzero value if there is arc from state of
1199 the automaton marked by the ainsn. */
1201 /* Cyclic list of insns of an equivalence class is formed with the
1202 aid of the following field. */
1203 ainsn_t next_equiv_class_insn
;
1204 /* The following field value is nonzero if the insn declaration is
1205 the first insn declaration with given equivalence number. */
1206 char first_ainsn_with_given_equialence_num
;
1207 /* The following field is number of class of equivalence of insns.
1208 It is necessary because many insns may be equivalent with the
1209 point of view of pipeline hazards. */
1210 int insn_equiv_class_num
;
1211 /* The following member value is TRUE if there is an arc in the
1212 automaton marked by the insn into another state. In other
1213 words, the insn can change the state of the automaton. */
1217 /* The following describes an automaton for PHR. */
1220 /* The following field value is the list of insn declarations for
1223 /* The following field value is the corresponding automaton
1224 declaration. This field is not NULL only if the automatic
1225 partition on automata is not used. */
1226 struct automaton_decl
*corresponding_automaton_decl
;
1227 /* The following field value is the next automaton. */
1228 automaton_t next_automaton
;
1229 /* The following field is start state of FA. There are not unit
1230 reservations in the state. */
1231 state_t start_state
;
1232 /* The following field value is number of equivalence classes of
1233 insns (see field `insn_equiv_class_num' in
1234 `insn_reserv_decl'). */
1235 int insn_equiv_classes_num
;
1236 /* The following field value is number of states of final DFA. */
1237 int achieved_states_num
;
1238 /* The following field value is the order number (0, 1, ...) of
1240 int automaton_order_num
;
1241 /* The following fields contain statistics information about
1242 building automaton. */
1243 int NDFA_states_num
, DFA_states_num
;
1244 /* The following field value is defined only if minimization of DFA
1246 int minimal_DFA_states_num
;
1247 int NDFA_arcs_num
, DFA_arcs_num
;
1248 /* The following field value is defined only if minimization of DFA
1250 int minimal_DFA_arcs_num
;
1251 /* The following two members refer for two table state x ainsn ->
1253 state_ainsn_table_t trans_table
;
1254 state_ainsn_table_t state_alts_table
;
1255 /* The following member value is maximal value of min issue delay
1256 for insns of the automaton. */
1258 /* Usually min issue delay is small and we can place several (2, 4,
1259 8) elements in one vector element. So the compression factor can
1260 be 1 (no compression), 2, 4, 8. */
1261 int min_issue_delay_table_compression_factor
;
1264 /* The following is the element of the list of automata. */
1265 struct automata_list_el
1267 /* The automaton itself. */
1268 automaton_t automaton
;
1269 /* The next automata set element. */
1270 automata_list_el_t next_automata_list_el
;
1273 /* The following structure describes a table state X ainsn -> int(>= 0). */
1274 struct state_ainsn_table
1276 /* Automaton to which given table belongs. */
1277 automaton_t automaton
;
1278 /* The following tree vectors for comb vector implementation of the
1280 vla_hwint_t comb_vect
;
1281 vla_hwint_t check_vect
;
1282 vla_hwint_t base_vect
;
1283 /* This is simple implementation of the table. */
1284 vla_hwint_t full_vect
;
1285 /* Minimal and maximal values of the previous vectors. */
1286 int min_comb_vect_el_value
, max_comb_vect_el_value
;
1287 int min_base_vect_el_value
, max_base_vect_el_value
;
1290 /* Macros to access members of unions. Use only them for access to
1291 union members of declarations and regexps. */
1293 #if defined ENABLE_CHECKING && (GCC_VERSION >= 2007)
1295 #define DECL_UNIT(d) __extension__ \
1296 (({ struct decl *const _decl = (d); \
1297 if (_decl->mode != dm_unit) \
1298 decl_mode_check_failed (_decl->mode, "dm_unit", \
1299 __FILE__, __LINE__, __FUNCTION__); \
1300 &(_decl)->decl.unit; }))
1302 #define DECL_BYPASS(d) __extension__ \
1303 (({ struct decl *const _decl = (d); \
1304 if (_decl->mode != dm_bypass) \
1305 decl_mode_check_failed (_decl->mode, "dm_bypass", \
1306 __FILE__, __LINE__, __FUNCTION__); \
1307 &(_decl)->decl.bypass; }))
1309 #define DECL_AUTOMATON(d) __extension__ \
1310 (({ struct decl *const _decl = (d); \
1311 if (_decl->mode != dm_automaton) \
1312 decl_mode_check_failed (_decl->mode, "dm_automaton", \
1313 __FILE__, __LINE__, __FUNCTION__); \
1314 &(_decl)->decl.automaton; }))
1316 #define DECL_EXCL(d) __extension__ \
1317 (({ struct decl *const _decl = (d); \
1318 if (_decl->mode != dm_excl) \
1319 decl_mode_check_failed (_decl->mode, "dm_excl", \
1320 __FILE__, __LINE__, __FUNCTION__); \
1321 &(_decl)->decl.excl; }))
1323 #define DECL_PRESENCE(d) __extension__ \
1324 (({ struct decl *const _decl = (d); \
1325 if (_decl->mode != dm_presence) \
1326 decl_mode_check_failed (_decl->mode, "dm_presence", \
1327 __FILE__, __LINE__, __FUNCTION__); \
1328 &(_decl)->decl.presence; }))
1330 #define DECL_ABSENCE(d) __extension__ \
1331 (({ struct decl *const _decl = (d); \
1332 if (_decl->mode != dm_absence) \
1333 decl_mode_check_failed (_decl->mode, "dm_absence", \
1334 __FILE__, __LINE__, __FUNCTION__); \
1335 &(_decl)->decl.absence; }))
1337 #define DECL_RESERV(d) __extension__ \
1338 (({ struct decl *const _decl = (d); \
1339 if (_decl->mode != dm_reserv) \
1340 decl_mode_check_failed (_decl->mode, "dm_reserv", \
1341 __FILE__, __LINE__, __FUNCTION__); \
1342 &(_decl)->decl.reserv; }))
1344 #define DECL_INSN_RESERV(d) __extension__ \
1345 (({ struct decl *const _decl = (d); \
1346 if (_decl->mode != dm_insn_reserv) \
1347 decl_mode_check_failed (_decl->mode, "dm_insn_reserv", \
1348 __FILE__, __LINE__, __FUNCTION__); \
1349 &(_decl)->decl.insn_reserv; }))
1351 static const char *decl_name (enum decl_mode
);
1352 static void decl_mode_check_failed (enum decl_mode
, const char *,
1353 const char *, int, const char *);
1355 /* Return string representation of declaration mode MODE. */
1357 decl_name (enum decl_mode mode
)
1359 static char str
[100];
1361 if (mode
== dm_unit
)
1363 else if (mode
== dm_bypass
)
1365 else if (mode
== dm_automaton
)
1366 return "dm_automaton";
1367 else if (mode
== dm_excl
)
1369 else if (mode
== dm_presence
)
1370 return "dm_presence";
1371 else if (mode
== dm_absence
)
1372 return "dm_absence";
1373 else if (mode
== dm_reserv
)
1375 else if (mode
== dm_insn_reserv
)
1376 return "dm_insn_reserv";
1378 sprintf (str
, "unknown (%d)", (int) mode
);
1382 /* The function prints message about unexpected declaration and finish
1385 decl_mode_check_failed (enum decl_mode mode
, const char *expected_mode_str
,
1386 const char *file
, int line
, const char *func
)
1390 "\n%s: %d: error in %s: DECL check: expected decl %s, have %s\n",
1391 file
, line
, func
, expected_mode_str
, decl_name (mode
));
1396 #define REGEXP_UNIT(r) __extension__ \
1397 (({ struct regexp *const _regexp = (r); \
1398 if (_regexp->mode != rm_unit) \
1399 regexp_mode_check_failed (_regexp->mode, "rm_unit", \
1400 __FILE__, __LINE__, __FUNCTION__); \
1401 &(_regexp)->regexp.unit; }))
1403 #define REGEXP_RESERV(r) __extension__ \
1404 (({ struct regexp *const _regexp = (r); \
1405 if (_regexp->mode != rm_reserv) \
1406 regexp_mode_check_failed (_regexp->mode, "rm_reserv", \
1407 __FILE__, __LINE__, __FUNCTION__); \
1408 &(_regexp)->regexp.reserv; }))
1410 #define REGEXP_SEQUENCE(r) __extension__ \
1411 (({ struct regexp *const _regexp = (r); \
1412 if (_regexp->mode != rm_sequence) \
1413 regexp_mode_check_failed (_regexp->mode, "rm_sequence", \
1414 __FILE__, __LINE__, __FUNCTION__); \
1415 &(_regexp)->regexp.sequence; }))
1417 #define REGEXP_REPEAT(r) __extension__ \
1418 (({ struct regexp *const _regexp = (r); \
1419 if (_regexp->mode != rm_repeat) \
1420 regexp_mode_check_failed (_regexp->mode, "rm_repeat", \
1421 __FILE__, __LINE__, __FUNCTION__); \
1422 &(_regexp)->regexp.repeat; }))
1424 #define REGEXP_ALLOF(r) __extension__ \
1425 (({ struct regexp *const _regexp = (r); \
1426 if (_regexp->mode != rm_allof) \
1427 regexp_mode_check_failed (_regexp->mode, "rm_allof", \
1428 __FILE__, __LINE__, __FUNCTION__); \
1429 &(_regexp)->regexp.allof; }))
1431 #define REGEXP_ONEOF(r) __extension__ \
1432 (({ struct regexp *const _regexp = (r); \
1433 if (_regexp->mode != rm_oneof) \
1434 regexp_mode_check_failed (_regexp->mode, "rm_oneof", \
1435 __FILE__, __LINE__, __FUNCTION__); \
1436 &(_regexp)->regexp.oneof; }))
1438 static const char *regexp_name (enum regexp_mode
);
1439 static void regexp_mode_check_failed (enum regexp_mode
, const char *,
1444 /* Return string representation of regexp mode MODE. */
1446 regexp_name (enum regexp_mode mode
)
1448 static char str
[100];
1450 if (mode
== rm_unit
)
1452 else if (mode
== rm_reserv
)
1454 else if (mode
== rm_nothing
)
1455 return "rm_nothing";
1456 else if (mode
== rm_sequence
)
1457 return "rm_sequence";
1458 else if (mode
== rm_repeat
)
1460 else if (mode
== rm_allof
)
1462 else if (mode
== rm_oneof
)
1465 sprintf (str
, "unknown (%d)", (int) mode
);
1469 /* The function prints message about unexpected regexp and finish the
1472 regexp_mode_check_failed (enum regexp_mode mode
,
1473 const char *expected_mode_str
,
1474 const char *file
, int line
, const char *func
)
1478 "\n%s: %d: error in %s: REGEXP check: expected decl %s, have %s\n",
1479 file
, line
, func
, expected_mode_str
, regexp_name (mode
));
1483 #else /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */
1485 #define DECL_UNIT(d) (&(d)->decl.unit)
1486 #define DECL_BYPASS(d) (&(d)->decl.bypass)
1487 #define DECL_AUTOMATON(d) (&(d)->decl.automaton)
1488 #define DECL_EXCL(d) (&(d)->decl.excl)
1489 #define DECL_PRESENCE(d) (&(d)->decl.presence)
1490 #define DECL_ABSENCE(d) (&(d)->decl.absence)
1491 #define DECL_RESERV(d) (&(d)->decl.reserv)
1492 #define DECL_INSN_RESERV(d) (&(d)->decl.insn_reserv)
1494 #define REGEXP_UNIT(r) (&(r)->regexp.unit)
1495 #define REGEXP_RESERV(r) (&(r)->regexp.reserv)
1496 #define REGEXP_SEQUENCE(r) (&(r)->regexp.sequence)
1497 #define REGEXP_REPEAT(r) (&(r)->regexp.repeat)
1498 #define REGEXP_ALLOF(r) (&(r)->regexp.allof)
1499 #define REGEXP_ONEOF(r) (&(r)->regexp.oneof)
1501 #endif /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */
1503 /* Create IR structure (node). */
1505 create_node (size_t size
)
1509 obstack_blank (&irp
, size
);
1510 result
= obstack_base (&irp
);
1511 obstack_finish (&irp
);
1512 /* Default values of members are NULL and zero. */
1513 memset (result
, 0, size
);
1517 /* Copy IR structure (node). */
1519 copy_node (const void *from
, size_t size
)
1521 void *const result
= create_node (size
);
1522 memcpy (result
, from
, size
);
1526 /* The function checks that NAME does not contain quotes (`"'). */
1528 check_name (char * name
, pos_t pos ATTRIBUTE_UNUSED
)
1532 for (str
= name
; *str
!= '\0'; str
++)
1534 error ("Name `%s' contains quotes", name
);
1538 /* Pointers to all declarations during IR generation are stored in the
1540 static vla_ptr_t decls
;
1542 /* Given a pointer to a (char *) and a separator, return an alloc'ed
1543 string containing the next separated element, taking parentheses
1544 into account if PAR_FLAG has nonzero value. Advance the pointer to
1545 after the string scanned, or the end-of-string. Return NULL if at
1548 next_sep_el (char **pstr
, int sep
, int par_flag
)
1555 /* Remove leading whitespaces. */
1556 while (ISSPACE ((int) **pstr
))
1563 for (pars_num
= 0, p
= *pstr
; *p
!= '\0'; p
++)
1565 if (par_flag
&& *p
== '(')
1567 else if (par_flag
&& *p
== ')')
1569 else if (pars_num
== 0 && *p
== sep
)
1571 if (pars_num
== 0 && ISSPACE ((int) *p
))
1575 for (; n_spaces
!= 0; n_spaces
--)
1576 obstack_1grow (&irp
, p
[-n_spaces
]);
1577 obstack_1grow (&irp
, *p
);
1580 obstack_1grow (&irp
, '\0');
1581 out_str
= obstack_base (&irp
);
1582 obstack_finish (&irp
);
1591 /* Given a string and a separator, return the number of separated
1592 elements in it, taking parentheses into account if PAR_FLAG has
1593 nonzero value. Return 0 for the null string, -1 if parentheses is
1596 n_sep_els (char *s
, int sep
, int par_flag
)
1604 for (pars_num
= 0, n
= 1; *s
; s
++)
1605 if (par_flag
&& *s
== '(')
1607 else if (par_flag
&& *s
== ')')
1609 else if (pars_num
== 0 && *s
== sep
)
1612 return (pars_num
!= 0 ? -1 : n
);
1615 /* Given a string and a separator, return vector of strings which are
1616 elements in the string and number of elements through els_num.
1617 Take parentheses into account if PAREN_P has nonzero value. The
1618 function also inserts the end marker NULL at the end of vector.
1619 Return 0 for the null string, -1 if parentheses are not balanced. */
1621 get_str_vect (char *str
, int *els_num
, int sep
, int paren_p
)
1627 *els_num
= n_sep_els (str
, sep
, paren_p
);
1630 obstack_blank (&irp
, sizeof (char *) * (*els_num
+ 1));
1631 vect
= (char **) obstack_base (&irp
);
1632 obstack_finish (&irp
);
1634 for (i
= 0; i
< *els_num
; i
++)
1635 vect
[i
] = next_sep_el (pstr
, sep
, paren_p
);
1636 if (next_sep_el (pstr
, sep
, paren_p
) != NULL
)
1642 /* Process a DEFINE_CPU_UNIT.
1644 This gives information about a unit contained in CPU. We fill a
1645 struct unit_decl with information used later by `expand_automata'. */
1647 gen_cpu_unit (rtx def
)
1650 char **str_cpu_units
;
1654 str_cpu_units
= get_str_vect ((char *) XSTR (def
, 0), &vect_length
, ',',
1656 if (str_cpu_units
== NULL
)
1657 fatal ("invalid string `%s' in define_cpu_unit", XSTR (def
, 0));
1658 for (i
= 0; i
< vect_length
; i
++)
1660 decl
= create_node (sizeof (struct decl
));
1661 decl
->mode
= dm_unit
;
1663 DECL_UNIT (decl
)->name
= check_name (str_cpu_units
[i
], decl
->pos
);
1664 DECL_UNIT (decl
)->automaton_name
= (char *) XSTR (def
, 1);
1665 DECL_UNIT (decl
)->query_p
= 0;
1666 DECL_UNIT (decl
)->min_occ_cycle_num
= -1;
1667 DECL_UNIT (decl
)->in_set_p
= 0;
1668 VLA_PTR_ADD (decls
, decl
);
1673 /* Process a DEFINE_QUERY_CPU_UNIT.
1675 This gives information about a unit contained in CPU. We fill a
1676 struct unit_decl with information used later by `expand_automata'. */
1678 gen_query_cpu_unit (rtx def
)
1681 char **str_cpu_units
;
1685 str_cpu_units
= get_str_vect ((char *) XSTR (def
, 0), &vect_length
, ',',
1687 if (str_cpu_units
== NULL
)
1688 fatal ("invalid string `%s' in define_query_cpu_unit", XSTR (def
, 0));
1689 for (i
= 0; i
< vect_length
; i
++)
1691 decl
= create_node (sizeof (struct decl
));
1692 decl
->mode
= dm_unit
;
1694 DECL_UNIT (decl
)->name
= check_name (str_cpu_units
[i
], decl
->pos
);
1695 DECL_UNIT (decl
)->automaton_name
= (char *) XSTR (def
, 1);
1696 DECL_UNIT (decl
)->query_p
= 1;
1697 VLA_PTR_ADD (decls
, decl
);
1702 /* Process a DEFINE_BYPASS.
1704 This gives information about a unit contained in the CPU. We fill
1705 in a struct bypass_decl with information used later by
1706 `expand_automata'. */
1708 gen_bypass (rtx def
)
1717 out_insns
= get_str_vect ((char *) XSTR (def
, 1), &out_length
, ',', FALSE
);
1718 if (out_insns
== NULL
)
1719 fatal ("invalid string `%s' in define_bypass", XSTR (def
, 1));
1720 in_insns
= get_str_vect ((char *) XSTR (def
, 2), &in_length
, ',', FALSE
);
1721 if (in_insns
== NULL
)
1722 fatal ("invalid string `%s' in define_bypass", XSTR (def
, 2));
1723 for (i
= 0; i
< out_length
; i
++)
1724 for (j
= 0; j
< in_length
; j
++)
1726 decl
= create_node (sizeof (struct decl
));
1727 decl
->mode
= dm_bypass
;
1729 DECL_BYPASS (decl
)->latency
= XINT (def
, 0);
1730 DECL_BYPASS (decl
)->out_insn_name
= out_insns
[i
];
1731 DECL_BYPASS (decl
)->in_insn_name
= in_insns
[j
];
1732 DECL_BYPASS (decl
)->bypass_guard_name
= (char *) XSTR (def
, 3);
1733 VLA_PTR_ADD (decls
, decl
);
1738 /* Process an EXCLUSION_SET.
1740 This gives information about a cpu unit conflicts. We fill a
1741 struct excl_rel_decl (excl) with information used later by
1742 `expand_automata'. */
1744 gen_excl_set (rtx def
)
1747 char **first_str_cpu_units
;
1748 char **second_str_cpu_units
;
1749 int first_vect_length
;
1754 = get_str_vect ((char *) XSTR (def
, 0), &first_vect_length
, ',', FALSE
);
1755 if (first_str_cpu_units
== NULL
)
1756 fatal ("invalid first string `%s' in exclusion_set", XSTR (def
, 0));
1757 second_str_cpu_units
= get_str_vect ((char *) XSTR (def
, 1), &length
, ',',
1759 if (second_str_cpu_units
== NULL
)
1760 fatal ("invalid second string `%s' in exclusion_set", XSTR (def
, 1));
1761 length
+= first_vect_length
;
1762 decl
= create_node (sizeof (struct decl
) + (length
- 1) * sizeof (char *));
1763 decl
->mode
= dm_excl
;
1765 DECL_EXCL (decl
)->all_names_num
= length
;
1766 DECL_EXCL (decl
)->first_list_length
= first_vect_length
;
1767 for (i
= 0; i
< length
; i
++)
1768 if (i
< first_vect_length
)
1769 DECL_EXCL (decl
)->names
[i
] = first_str_cpu_units
[i
];
1771 DECL_EXCL (decl
)->names
[i
]
1772 = second_str_cpu_units
[i
- first_vect_length
];
1773 VLA_PTR_ADD (decls
, decl
);
1777 /* Process a PRESENCE_SET, a FINAL_PRESENCE_SET, an ABSENCE_SET,
1778 FINAL_ABSENCE_SET (it is depended on PRESENCE_P and FINAL_P).
1780 This gives information about a cpu unit reservation requirements.
1781 We fill a struct unit_pattern_rel_decl with information used later
1782 by `expand_automata'. */
1784 gen_presence_absence_set (rtx def
, int presence_p
, int final_p
)
1787 char **str_cpu_units
;
1788 char ***str_patterns
;
1789 int cpu_units_length
;
1791 int patterns_length
;
1794 str_cpu_units
= get_str_vect ((char *) XSTR (def
, 0), &cpu_units_length
, ',',
1796 if (str_cpu_units
== NULL
)
1799 ? "invalid first string `%s' in final_presence_set"
1800 : "invalid first string `%s' in presence_set")
1802 ? "invalid first string `%s' in final_absence_set"
1803 : "invalid first string `%s' in absence_set")),
1805 str_patterns
= (char ***) get_str_vect ((char *) XSTR (def
, 1),
1806 &patterns_length
, ',', FALSE
);
1807 if (str_patterns
== NULL
)
1810 ? "invalid second string `%s' in final_presence_set"
1811 : "invalid second string `%s' in presence_set")
1813 ? "invalid second string `%s' in final_absence_set"
1814 : "invalid second string `%s' in absence_set")), XSTR (def
, 1));
1815 for (i
= 0; i
< patterns_length
; i
++)
1817 str_patterns
[i
] = get_str_vect ((char *) str_patterns
[i
], &length
, ' ',
1819 if (str_patterns
[i
] == NULL
)
1822 decl
= create_node (sizeof (struct decl
));
1826 decl
->mode
= dm_presence
;
1827 DECL_PRESENCE (decl
)->names_num
= cpu_units_length
;
1828 DECL_PRESENCE (decl
)->names
= str_cpu_units
;
1829 DECL_PRESENCE (decl
)->patterns
= str_patterns
;
1830 DECL_PRESENCE (decl
)->patterns_num
= patterns_length
;
1831 DECL_PRESENCE (decl
)->final_p
= final_p
;
1835 decl
->mode
= dm_absence
;
1836 DECL_ABSENCE (decl
)->names_num
= cpu_units_length
;
1837 DECL_ABSENCE (decl
)->names
= str_cpu_units
;
1838 DECL_ABSENCE (decl
)->patterns
= str_patterns
;
1839 DECL_ABSENCE (decl
)->patterns_num
= patterns_length
;
1840 DECL_ABSENCE (decl
)->final_p
= final_p
;
1842 VLA_PTR_ADD (decls
, decl
);
1846 /* Process a PRESENCE_SET.
1848 This gives information about a cpu unit reservation requirements.
1849 We fill a struct unit_pattern_rel_decl (presence) with information
1850 used later by `expand_automata'. */
1852 gen_presence_set (rtx def
)
1854 gen_presence_absence_set (def
, TRUE
, FALSE
);
1857 /* Process a FINAL_PRESENCE_SET.
1859 This gives information about a cpu unit reservation requirements.
1860 We fill a struct unit_pattern_rel_decl (presence) with information
1861 used later by `expand_automata'. */
1863 gen_final_presence_set (rtx def
)
1865 gen_presence_absence_set (def
, TRUE
, TRUE
);
1868 /* Process an ABSENCE_SET.
1870 This gives information about a cpu unit reservation requirements.
1871 We fill a struct unit_pattern_rel_decl (absence) with information
1872 used later by `expand_automata'. */
1874 gen_absence_set (rtx def
)
1876 gen_presence_absence_set (def
, FALSE
, FALSE
);
1879 /* Process a FINAL_ABSENCE_SET.
1881 This gives information about a cpu unit reservation requirements.
1882 We fill a struct unit_pattern_rel_decl (absence) with information
1883 used later by `expand_automata'. */
1885 gen_final_absence_set (rtx def
)
1887 gen_presence_absence_set (def
, FALSE
, TRUE
);
1890 /* Process a DEFINE_AUTOMATON.
1892 This gives information about a finite state automaton used for
1893 recognizing pipeline hazards. We fill a struct automaton_decl
1894 with information used later by `expand_automata'. */
1896 gen_automaton (rtx def
)
1899 char **str_automata
;
1903 str_automata
= get_str_vect ((char *) XSTR (def
, 0), &vect_length
, ',',
1905 if (str_automata
== NULL
)
1906 fatal ("invalid string `%s' in define_automaton", XSTR (def
, 0));
1907 for (i
= 0; i
< vect_length
; i
++)
1909 decl
= create_node (sizeof (struct decl
));
1910 decl
->mode
= dm_automaton
;
1912 DECL_AUTOMATON (decl
)->name
= check_name (str_automata
[i
], decl
->pos
);
1913 VLA_PTR_ADD (decls
, decl
);
1918 /* Process an AUTOMATA_OPTION.
1920 This gives information how to generate finite state automaton used
1921 for recognizing pipeline hazards. */
1923 gen_automata_option (rtx def
)
1925 if (strcmp (XSTR (def
, 0), NO_MINIMIZATION_OPTION
+ 1) == 0)
1926 no_minimization_flag
= 1;
1927 else if (strcmp (XSTR (def
, 0), TIME_OPTION
+ 1) == 0)
1929 else if (strcmp (XSTR (def
, 0), V_OPTION
+ 1) == 0)
1931 else if (strcmp (XSTR (def
, 0), W_OPTION
+ 1) == 0)
1933 else if (strcmp (XSTR (def
, 0), NDFA_OPTION
+ 1) == 0)
1936 fatal ("invalid option `%s' in automata_option", XSTR (def
, 0));
1939 /* Name in reservation to denote absence reservation. */
1940 #define NOTHING_NAME "nothing"
1942 /* The following string contains original reservation string being
1944 static char *reserv_str
;
1946 /* Parse an element in STR. */
1948 gen_regexp_el (char *str
)
1956 if (str
[len
- 1] != ')')
1957 fatal ("garbage after ) in reservation `%s'", reserv_str
);
1958 str
[len
- 1] = '\0';
1959 regexp
= gen_regexp_sequence (str
+ 1);
1961 else if (strcmp (str
, NOTHING_NAME
) == 0)
1963 regexp
= create_node (sizeof (struct decl
));
1964 regexp
->mode
= rm_nothing
;
1968 regexp
= create_node (sizeof (struct decl
));
1969 regexp
->mode
= rm_unit
;
1970 REGEXP_UNIT (regexp
)->name
= str
;
1975 /* Parse construction `repeat' in STR. */
1977 gen_regexp_repeat (char *str
)
1985 repeat_vect
= get_str_vect (str
, &els_num
, '*', TRUE
);
1986 if (repeat_vect
== NULL
)
1987 fatal ("invalid `%s' in reservation `%s'", str
, reserv_str
);
1990 regexp
= gen_regexp_el (repeat_vect
[0]);
1991 for (i
= 1; i
< els_num
; i
++)
1993 repeat
= create_node (sizeof (struct regexp
));
1994 repeat
->mode
= rm_repeat
;
1995 REGEXP_REPEAT (repeat
)->regexp
= regexp
;
1996 REGEXP_REPEAT (repeat
)->repeat_num
= atoi (repeat_vect
[i
]);
1997 if (REGEXP_REPEAT (repeat
)->repeat_num
<= 1)
1998 fatal ("repetition `%s' <= 1 in reservation `%s'",
2005 return gen_regexp_el (str
);
2008 /* Parse reservation STR which possibly contains separator '+'. */
2010 gen_regexp_allof (char *str
)
2017 allof_vect
= get_str_vect (str
, &els_num
, '+', TRUE
);
2018 if (allof_vect
== NULL
)
2019 fatal ("invalid `%s' in reservation `%s'", str
, reserv_str
);
2022 allof
= create_node (sizeof (struct regexp
)
2023 + sizeof (regexp_t
) * (els_num
- 1));
2024 allof
->mode
= rm_allof
;
2025 REGEXP_ALLOF (allof
)->regexps_num
= els_num
;
2026 for (i
= 0; i
< els_num
; i
++)
2027 REGEXP_ALLOF (allof
)->regexps
[i
] = gen_regexp_repeat (allof_vect
[i
]);
2031 return gen_regexp_repeat (str
);
2034 /* Parse reservation STR which possibly contains separator '|'. */
2036 gen_regexp_oneof (char *str
)
2043 oneof_vect
= get_str_vect (str
, &els_num
, '|', TRUE
);
2044 if (oneof_vect
== NULL
)
2045 fatal ("invalid `%s' in reservation `%s'", str
, reserv_str
);
2048 oneof
= create_node (sizeof (struct regexp
)
2049 + sizeof (regexp_t
) * (els_num
- 1));
2050 oneof
->mode
= rm_oneof
;
2051 REGEXP_ONEOF (oneof
)->regexps_num
= els_num
;
2052 for (i
= 0; i
< els_num
; i
++)
2053 REGEXP_ONEOF (oneof
)->regexps
[i
] = gen_regexp_allof (oneof_vect
[i
]);
2057 return gen_regexp_allof (str
);
2060 /* Parse reservation STR which possibly contains separator ','. */
2062 gen_regexp_sequence (char *str
)
2065 char **sequence_vect
;
2069 sequence_vect
= get_str_vect (str
, &els_num
, ',', TRUE
);
2072 sequence
= create_node (sizeof (struct regexp
)
2073 + sizeof (regexp_t
) * (els_num
- 1));
2074 sequence
->mode
= rm_sequence
;
2075 REGEXP_SEQUENCE (sequence
)->regexps_num
= els_num
;
2076 for (i
= 0; i
< els_num
; i
++)
2077 REGEXP_SEQUENCE (sequence
)->regexps
[i
]
2078 = gen_regexp_oneof (sequence_vect
[i
]);
2082 return gen_regexp_oneof (str
);
2085 /* Parse construction reservation STR. */
2087 gen_regexp (char *str
)
2090 return gen_regexp_sequence (str
);;
2093 /* Process a DEFINE_RESERVATION.
2095 This gives information about a reservation of cpu units. We fill
2096 in a struct reserv_decl with information used later by
2097 `expand_automata'. */
2099 gen_reserv (rtx def
)
2103 decl
= create_node (sizeof (struct decl
));
2104 decl
->mode
= dm_reserv
;
2106 DECL_RESERV (decl
)->name
= check_name ((char *) XSTR (def
, 0), decl
->pos
);
2107 DECL_RESERV (decl
)->regexp
= gen_regexp ((char *) XSTR (def
, 1));
2108 VLA_PTR_ADD (decls
, decl
);
2112 /* Process a DEFINE_INSN_RESERVATION.
2114 This gives information about the reservation of cpu units by an
2115 insn. We fill a struct insn_reserv_decl with information used
2116 later by `expand_automata'. */
2118 gen_insn_reserv (rtx def
)
2122 decl
= create_node (sizeof (struct decl
));
2123 decl
->mode
= dm_insn_reserv
;
2125 DECL_INSN_RESERV (decl
)->name
2126 = check_name ((char *) XSTR (def
, 0), decl
->pos
);
2127 DECL_INSN_RESERV (decl
)->default_latency
= XINT (def
, 1);
2128 DECL_INSN_RESERV (decl
)->condexp
= XEXP (def
, 2);
2129 DECL_INSN_RESERV (decl
)->regexp
= gen_regexp ((char *) XSTR (def
, 3));
2130 VLA_PTR_ADD (decls
, decl
);
2136 /* The function evaluates hash value (0..UINT_MAX) of string. */
2138 string_hash (const char *string
)
2142 for (result
= i
= 0;*string
++ != '\0'; i
++)
2143 result
+= ((unsigned char) *string
<< (i
% CHAR_BIT
));
2149 /* This page contains abstract data `table of automaton declarations'.
2150 Elements of the table is nodes representing automaton declarations.
2151 Key of the table elements is name of given automaton. Remember
2152 that automaton names have own space. */
2154 /* The function evaluates hash value of an automaton declaration. The
2155 function is used by abstract data `hashtab'. The function returns
2156 hash value (0..UINT_MAX) of given automaton declaration. */
2158 automaton_decl_hash (const void *automaton_decl
)
2160 const decl_t decl
= (decl_t
) automaton_decl
;
2162 if (decl
->mode
== dm_automaton
&& DECL_AUTOMATON (decl
)->name
== NULL
)
2164 return string_hash (DECL_AUTOMATON (decl
)->name
);
2167 /* The function tests automaton declarations on equality of their
2168 keys. The function is used by abstract data `hashtab'. The
2169 function returns 1 if the declarations have the same key, 0
2172 automaton_decl_eq_p (const void* automaton_decl_1
,
2173 const void* automaton_decl_2
)
2175 const decl_t decl1
= (decl_t
) automaton_decl_1
;
2176 const decl_t decl2
= (decl_t
) automaton_decl_2
;
2178 if (decl1
->mode
!= dm_automaton
|| DECL_AUTOMATON (decl1
)->name
== NULL
2179 || decl2
->mode
!= dm_automaton
|| DECL_AUTOMATON (decl2
)->name
== NULL
)
2181 return strcmp (DECL_AUTOMATON (decl1
)->name
,
2182 DECL_AUTOMATON (decl2
)->name
) == 0;
2185 /* The automaton declaration table itself is represented by the
2186 following variable. */
2187 static htab_t automaton_decl_table
;
2189 /* The function inserts automaton declaration into the table. The
2190 function does nothing if an automaton declaration with the same key
2191 exists already in the table. The function returns automaton
2192 declaration node in the table with the same key as given automaton
2193 declaration node. */
2195 insert_automaton_decl (decl_t automaton_decl
)
2199 entry_ptr
= htab_find_slot (automaton_decl_table
, automaton_decl
, 1);
2200 if (*entry_ptr
== NULL
)
2201 *entry_ptr
= (void *) automaton_decl
;
2202 return (decl_t
) *entry_ptr
;
2205 /* The following variable value is node representing automaton
2206 declaration. The node used for searching automaton declaration
2208 static struct decl work_automaton_decl
;
2210 /* The function searches for automaton declaration in the table with
2211 the same key as node representing name of the automaton
2212 declaration. The function returns node found in the table, NULL if
2213 such node does not exist in the table. */
2215 find_automaton_decl (char *name
)
2219 work_automaton_decl
.mode
= dm_automaton
;
2220 DECL_AUTOMATON (&work_automaton_decl
)->name
= name
;
2221 entry
= htab_find (automaton_decl_table
, &work_automaton_decl
);
2222 return (decl_t
) entry
;
2225 /* The function creates empty automaton declaration table and node
2226 representing automaton declaration and used for searching automaton
2227 declaration with given name. The function must be called only once
2228 before any work with the automaton declaration table. */
2230 initiate_automaton_decl_table (void)
2232 work_automaton_decl
.mode
= dm_automaton
;
2233 automaton_decl_table
= htab_create (10, automaton_decl_hash
,
2234 automaton_decl_eq_p
, (htab_del
) 0);
2237 /* The function deletes the automaton declaration table. Only call of
2238 function `initiate_automaton_decl_table' is possible immediately
2239 after this function call. */
2241 finish_automaton_decl_table (void)
2243 htab_delete (automaton_decl_table
);
2248 /* This page contains abstract data `table of insn declarations'.
2249 Elements of the table is nodes representing insn declarations. Key
2250 of the table elements is name of given insn (in corresponding
2251 define_insn_reservation). Remember that insn names have own
2254 /* The function evaluates hash value of an insn declaration. The
2255 function is used by abstract data `hashtab'. The function returns
2256 hash value (0..UINT_MAX) of given insn declaration. */
2258 insn_decl_hash (const void *insn_decl
)
2260 const decl_t decl
= (decl_t
) insn_decl
;
2262 if (decl
->mode
!= dm_insn_reserv
|| DECL_INSN_RESERV (decl
)->name
== NULL
)
2264 return string_hash (DECL_INSN_RESERV (decl
)->name
);
2267 /* The function tests insn declarations on equality of their keys.
2268 The function is used by abstract data `hashtab'. The function
2269 returns 1 if declarations have the same key, 0 otherwise. */
2271 insn_decl_eq_p (const void *insn_decl_1
, const void *insn_decl_2
)
2273 const decl_t decl1
= (decl_t
) insn_decl_1
;
2274 const decl_t decl2
= (decl_t
) insn_decl_2
;
2276 if (decl1
->mode
!= dm_insn_reserv
|| DECL_INSN_RESERV (decl1
)->name
== NULL
2277 || decl2
->mode
!= dm_insn_reserv
2278 || DECL_INSN_RESERV (decl2
)->name
== NULL
)
2280 return strcmp (DECL_INSN_RESERV (decl1
)->name
,
2281 DECL_INSN_RESERV (decl2
)->name
) == 0;
2284 /* The insn declaration table itself is represented by the following
2285 variable. The table does not contain insn reservation
2287 static htab_t insn_decl_table
;
2289 /* The function inserts insn declaration into the table. The function
2290 does nothing if an insn declaration with the same key exists
2291 already in the table. The function returns insn declaration node
2292 in the table with the same key as given insn declaration node. */
2294 insert_insn_decl (decl_t insn_decl
)
2298 entry_ptr
= htab_find_slot (insn_decl_table
, insn_decl
, 1);
2299 if (*entry_ptr
== NULL
)
2300 *entry_ptr
= (void *) insn_decl
;
2301 return (decl_t
) *entry_ptr
;
2304 /* The following variable value is node representing insn reservation
2305 declaration. The node used for searching insn reservation
2306 declaration with given name. */
2307 static struct decl work_insn_decl
;
2309 /* The function searches for insn reservation declaration in the table
2310 with the same key as node representing name of the insn reservation
2311 declaration. The function returns node found in the table, NULL if
2312 such node does not exist in the table. */
2314 find_insn_decl (char *name
)
2318 work_insn_decl
.mode
= dm_insn_reserv
;
2319 DECL_INSN_RESERV (&work_insn_decl
)->name
= name
;
2320 entry
= htab_find (insn_decl_table
, &work_insn_decl
);
2321 return (decl_t
) entry
;
2324 /* The function creates empty insn declaration table and node
2325 representing insn declaration and used for searching insn
2326 declaration with given name. The function must be called only once
2327 before any work with the insn declaration table. */
2329 initiate_insn_decl_table (void)
2331 work_insn_decl
.mode
= dm_insn_reserv
;
2332 insn_decl_table
= htab_create (10, insn_decl_hash
, insn_decl_eq_p
,
2336 /* The function deletes the insn declaration table. Only call of
2337 function `initiate_insn_decl_table' is possible immediately after
2338 this function call. */
2340 finish_insn_decl_table (void)
2342 htab_delete (insn_decl_table
);
2347 /* This page contains abstract data `table of declarations'. Elements
2348 of the table is nodes representing declarations (of units and
2349 reservations). Key of the table elements is names of given
2352 /* The function evaluates hash value of a declaration. The function
2353 is used by abstract data `hashtab'. The function returns hash
2354 value (0..UINT_MAX) of given declaration. */
2356 decl_hash (const void *decl
)
2358 const decl_t d
= (const decl_t
) decl
;
2360 if ((d
->mode
!= dm_unit
|| DECL_UNIT (d
)->name
== NULL
)
2361 && (d
->mode
!= dm_reserv
|| DECL_RESERV (d
)->name
== NULL
))
2363 return string_hash (d
->mode
== dm_unit
2364 ? DECL_UNIT (d
)->name
: DECL_RESERV (d
)->name
);
2367 /* The function tests declarations on equality of their keys. The
2368 function is used by abstract data `hashtab'. The function
2369 returns 1 if the declarations have the same key, 0 otherwise. */
2371 decl_eq_p (const void *decl_1
, const void *decl_2
)
2373 const decl_t d1
= (const decl_t
) decl_1
;
2374 const decl_t d2
= (const decl_t
) decl_2
;
2376 if (((d1
->mode
!= dm_unit
|| DECL_UNIT (d1
)->name
== NULL
)
2377 && (d1
->mode
!= dm_reserv
|| DECL_RESERV (d1
)->name
== NULL
))
2378 || ((d2
->mode
!= dm_unit
|| DECL_UNIT (d2
)->name
== NULL
)
2379 && (d2
->mode
!= dm_reserv
|| DECL_RESERV (d2
)->name
== NULL
)))
2381 return strcmp ((d1
->mode
== dm_unit
2382 ? DECL_UNIT (d1
)->name
: DECL_RESERV (d1
)->name
),
2383 (d2
->mode
== dm_unit
2384 ? DECL_UNIT (d2
)->name
: DECL_RESERV (d2
)->name
)) == 0;
2387 /* The declaration table itself is represented by the following
2389 static htab_t decl_table
;
2391 /* The function inserts declaration into the table. The function does
2392 nothing if a declaration with the same key exists already in the
2393 table. The function returns declaration node in the table with the
2394 same key as given declaration node. */
2397 insert_decl (decl_t decl
)
2401 entry_ptr
= htab_find_slot (decl_table
, decl
, 1);
2402 if (*entry_ptr
== NULL
)
2403 *entry_ptr
= (void *) decl
;
2404 return (decl_t
) *entry_ptr
;
2407 /* The following variable value is node representing declaration. The
2408 node used for searching declaration with given name. */
2409 static struct decl work_decl
;
2411 /* The function searches for declaration in the table with the same
2412 key as node representing name of the declaration. The function
2413 returns node found in the table, NULL if such node does not exist
2416 find_decl (char *name
)
2420 work_decl
.mode
= dm_unit
;
2421 DECL_UNIT (&work_decl
)->name
= name
;
2422 entry
= htab_find (decl_table
, &work_decl
);
2423 return (decl_t
) entry
;
2426 /* The function creates empty declaration table and node representing
2427 declaration and used for searching declaration with given name.
2428 The function must be called only once before any work with the
2429 declaration table. */
2431 initiate_decl_table (void)
2433 work_decl
.mode
= dm_unit
;
2434 decl_table
= htab_create (10, decl_hash
, decl_eq_p
, (htab_del
) 0);
2437 /* The function deletes the declaration table. Only call of function
2438 `initiate_declaration_table' is possible immediately after this
2441 finish_decl_table (void)
2443 htab_delete (decl_table
);
2448 /* This page contains checker of pipeline hazard description. */
2450 /* Checking NAMES in an exclusion clause vector and returning formed
2451 unit_set_el_list. */
2452 static unit_set_el_t
2453 process_excls (char **names
, int num
, pos_t excl_pos ATTRIBUTE_UNUSED
)
2455 unit_set_el_t el_list
;
2456 unit_set_el_t last_el
;
2457 unit_set_el_t new_el
;
2458 decl_t decl_in_table
;
2463 for (i
= 0; i
< num
; i
++)
2465 decl_in_table
= find_decl (names
[i
]);
2466 if (decl_in_table
== NULL
)
2467 error ("unit `%s' in exclusion is not declared", names
[i
]);
2468 else if (decl_in_table
->mode
!= dm_unit
)
2469 error ("`%s' in exclusion is not unit", names
[i
]);
2472 new_el
= create_node (sizeof (struct unit_set_el
));
2473 new_el
->unit_decl
= DECL_UNIT (decl_in_table
);
2474 new_el
->next_unit_set_el
= NULL
;
2475 if (last_el
== NULL
)
2476 el_list
= last_el
= new_el
;
2479 last_el
->next_unit_set_el
= new_el
;
2480 last_el
= last_el
->next_unit_set_el
;
2487 /* The function adds each element from SOURCE_LIST to the exclusion
2488 list of the each element from DEST_LIST. Checking situation "unit
2489 excludes itself". */
2491 add_excls (unit_set_el_t dest_list
, unit_set_el_t source_list
,
2492 pos_t excl_pos ATTRIBUTE_UNUSED
)
2496 unit_set_el_t curr_el
;
2497 unit_set_el_t prev_el
;
2500 for (dst
= dest_list
; dst
!= NULL
; dst
= dst
->next_unit_set_el
)
2501 for (src
= source_list
; src
!= NULL
; src
= src
->next_unit_set_el
)
2503 if (dst
->unit_decl
== src
->unit_decl
)
2505 error ("unit `%s' excludes itself", src
->unit_decl
->name
);
2508 if (dst
->unit_decl
->automaton_name
!= NULL
2509 && src
->unit_decl
->automaton_name
!= NULL
2510 && strcmp (dst
->unit_decl
->automaton_name
,
2511 src
->unit_decl
->automaton_name
) != 0)
2513 error ("units `%s' and `%s' in exclusion set belong to different automata",
2514 src
->unit_decl
->name
, dst
->unit_decl
->name
);
2517 for (curr_el
= dst
->unit_decl
->excl_list
, prev_el
= NULL
;
2519 prev_el
= curr_el
, curr_el
= curr_el
->next_unit_set_el
)
2520 if (curr_el
->unit_decl
== src
->unit_decl
)
2522 if (curr_el
== NULL
)
2524 /* Element not found - insert. */
2525 copy
= copy_node (src
, sizeof (*src
));
2526 copy
->next_unit_set_el
= NULL
;
2527 if (prev_el
== NULL
)
2528 dst
->unit_decl
->excl_list
= copy
;
2530 prev_el
->next_unit_set_el
= copy
;
2535 /* Checking NAMES in presence/absence clause and returning the
2536 formed unit_set_el_list. The function is called only after
2537 processing all exclusion sets. */
2538 static unit_set_el_t
2539 process_presence_absence_names (char **names
, int num
,
2540 pos_t req_pos ATTRIBUTE_UNUSED
,
2541 int presence_p
, int final_p
)
2543 unit_set_el_t el_list
;
2544 unit_set_el_t last_el
;
2545 unit_set_el_t new_el
;
2546 decl_t decl_in_table
;
2551 for (i
= 0; i
< num
; i
++)
2553 decl_in_table
= find_decl (names
[i
]);
2554 if (decl_in_table
== NULL
)
2557 ? "unit `%s' in final presence set is not declared"
2558 : "unit `%s' in presence set is not declared")
2560 ? "unit `%s' in final absence set is not declared"
2561 : "unit `%s' in absence set is not declared")), names
[i
]);
2562 else if (decl_in_table
->mode
!= dm_unit
)
2565 ? "`%s' in final presence set is not unit"
2566 : "`%s' in presence set is not unit")
2568 ? "`%s' in final absence set is not unit"
2569 : "`%s' in absence set is not unit")), names
[i
]);
2572 new_el
= create_node (sizeof (struct unit_set_el
));
2573 new_el
->unit_decl
= DECL_UNIT (decl_in_table
);
2574 new_el
->next_unit_set_el
= NULL
;
2575 if (last_el
== NULL
)
2576 el_list
= last_el
= new_el
;
2579 last_el
->next_unit_set_el
= new_el
;
2580 last_el
= last_el
->next_unit_set_el
;
2587 /* Checking NAMES in patterns of a presence/absence clause and
2588 returning the formed pattern_set_el_list. The function is called
2589 only after processing all exclusion sets. */
2590 static pattern_set_el_t
2591 process_presence_absence_patterns (char ***patterns
, int num
,
2592 pos_t req_pos ATTRIBUTE_UNUSED
,
2593 int presence_p
, int final_p
)
2595 pattern_set_el_t el_list
;
2596 pattern_set_el_t last_el
;
2597 pattern_set_el_t new_el
;
2598 decl_t decl_in_table
;
2603 for (i
= 0; i
< num
; i
++)
2605 for (j
= 0; patterns
[i
] [j
] != NULL
; j
++)
2607 new_el
= create_node (sizeof (struct pattern_set_el
)
2608 + sizeof (struct unit_decl
*) * j
);
2610 = (struct unit_decl
**) ((char *) new_el
2611 + sizeof (struct pattern_set_el
));
2612 new_el
->next_pattern_set_el
= NULL
;
2613 if (last_el
== NULL
)
2614 el_list
= last_el
= new_el
;
2617 last_el
->next_pattern_set_el
= new_el
;
2618 last_el
= last_el
->next_pattern_set_el
;
2620 new_el
->units_num
= 0;
2621 for (j
= 0; patterns
[i
] [j
] != NULL
; j
++)
2623 decl_in_table
= find_decl (patterns
[i
] [j
]);
2624 if (decl_in_table
== NULL
)
2627 ? "unit `%s' in final presence set is not declared"
2628 : "unit `%s' in presence set is not declared")
2630 ? "unit `%s' in final absence set is not declared"
2631 : "unit `%s' in absence set is not declared")),
2633 else if (decl_in_table
->mode
!= dm_unit
)
2636 ? "`%s' in final presence set is not unit"
2637 : "`%s' in presence set is not unit")
2639 ? "`%s' in final absence set is not unit"
2640 : "`%s' in absence set is not unit")),
2644 new_el
->unit_decls
[new_el
->units_num
]
2645 = DECL_UNIT (decl_in_table
);
2646 new_el
->units_num
++;
2653 /* The function adds each element from PATTERN_LIST to presence (if
2654 PRESENCE_P) or absence list of the each element from DEST_LIST.
2655 Checking situations "unit requires own absence", and "unit excludes
2656 and requires presence of ...", "unit requires absence and presence
2657 of ...", "units in (final) presence set belong to different
2658 automata", and "units in (final) absence set belong to different
2659 automata". Remember that we process absence sets only after all
2662 add_presence_absence (unit_set_el_t dest_list
,
2663 pattern_set_el_t pattern_list
,
2664 pos_t req_pos ATTRIBUTE_UNUSED
,
2665 int presence_p
, int final_p
)
2668 pattern_set_el_t pat
;
2669 struct unit_decl
*unit
;
2670 unit_set_el_t curr_excl_el
;
2671 pattern_set_el_t curr_pat_el
;
2672 pattern_set_el_t prev_el
;
2673 pattern_set_el_t copy
;
2677 for (dst
= dest_list
; dst
!= NULL
; dst
= dst
->next_unit_set_el
)
2678 for (pat
= pattern_list
; pat
!= NULL
; pat
= pat
->next_pattern_set_el
)
2680 for (i
= 0; i
< pat
->units_num
; i
++)
2682 unit
= pat
->unit_decls
[i
];
2683 if (dst
->unit_decl
== unit
&& pat
->units_num
== 1 && !presence_p
)
2685 error ("unit `%s' requires own absence", unit
->name
);
2688 if (dst
->unit_decl
->automaton_name
!= NULL
2689 && unit
->automaton_name
!= NULL
2690 && strcmp (dst
->unit_decl
->automaton_name
,
2691 unit
->automaton_name
) != 0)
2695 ? "units `%s' and `%s' in final presence set belong to different automata"
2696 : "units `%s' and `%s' in presence set belong to different automata")
2698 ? "units `%s' and `%s' in final absence set belong to different automata"
2699 : "units `%s' and `%s' in absence set belong to different automata")),
2700 unit
->name
, dst
->unit_decl
->name
);
2705 for (curr_excl_el
= dst
->unit_decl
->excl_list
;
2706 curr_excl_el
!= NULL
;
2707 curr_excl_el
= curr_excl_el
->next_unit_set_el
)
2709 if (unit
== curr_excl_el
->unit_decl
&& pat
->units_num
== 1)
2713 error ("unit `%s' excludes and requires presence of `%s'",
2714 dst
->unit_decl
->name
, unit
->name
);
2719 ("unit `%s' excludes and requires presence of `%s'",
2720 dst
->unit_decl
->name
, unit
->name
);
2723 else if (pat
->units_num
== 1)
2724 for (curr_pat_el
= dst
->unit_decl
->presence_list
;
2725 curr_pat_el
!= NULL
;
2726 curr_pat_el
= curr_pat_el
->next_pattern_set_el
)
2727 if (curr_pat_el
->units_num
== 1
2728 && unit
== curr_pat_el
->unit_decls
[0])
2733 ("unit `%s' requires absence and presence of `%s'",
2734 dst
->unit_decl
->name
, unit
->name
);
2739 ("unit `%s' requires absence and presence of `%s'",
2740 dst
->unit_decl
->name
, unit
->name
);
2744 for (prev_el
= (presence_p
2746 ? dst
->unit_decl
->final_presence_list
2747 : dst
->unit_decl
->final_presence_list
)
2749 ? dst
->unit_decl
->final_absence_list
2750 : dst
->unit_decl
->absence_list
));
2751 prev_el
!= NULL
&& prev_el
->next_pattern_set_el
!= NULL
;
2752 prev_el
= prev_el
->next_pattern_set_el
)
2754 copy
= copy_node (pat
, sizeof (*pat
));
2755 copy
->next_pattern_set_el
= NULL
;
2756 if (prev_el
== NULL
)
2761 dst
->unit_decl
->final_presence_list
= copy
;
2763 dst
->unit_decl
->presence_list
= copy
;
2766 dst
->unit_decl
->final_absence_list
= copy
;
2768 dst
->unit_decl
->absence_list
= copy
;
2771 prev_el
->next_pattern_set_el
= copy
;
2778 /* The function searches for bypass with given IN_INSN_RESERV in given
2780 static struct bypass_decl
*
2781 find_bypass (struct bypass_decl
*bypass_list
,
2782 struct insn_reserv_decl
*in_insn_reserv
)
2784 struct bypass_decl
*bypass
;
2786 for (bypass
= bypass_list
; bypass
!= NULL
; bypass
= bypass
->next
)
2787 if (bypass
->in_insn_reserv
== in_insn_reserv
)
2792 /* The function processes pipeline description declarations, checks
2793 their correctness, and forms exclusion/presence/absence sets. */
2795 process_decls (void)
2798 decl_t automaton_decl
;
2799 decl_t decl_in_table
;
2800 decl_t out_insn_reserv
;
2801 decl_t in_insn_reserv
;
2802 struct bypass_decl
*bypass
;
2803 int automaton_presence
;
2806 /* Checking repeated automata declarations. */
2807 automaton_presence
= 0;
2808 for (i
= 0; i
< description
->decls_num
; i
++)
2810 decl
= description
->decls
[i
];
2811 if (decl
->mode
== dm_automaton
)
2813 automaton_presence
= 1;
2814 decl_in_table
= insert_automaton_decl (decl
);
2815 if (decl_in_table
!= decl
)
2818 error ("repeated declaration of automaton `%s'",
2819 DECL_AUTOMATON (decl
)->name
);
2821 warning ("repeated declaration of automaton `%s'",
2822 DECL_AUTOMATON (decl
)->name
);
2826 /* Checking undeclared automata, repeated declarations (except for
2827 automata) and correctness of their attributes (insn latency times
2829 for (i
= 0; i
< description
->decls_num
; i
++)
2831 decl
= description
->decls
[i
];
2832 if (decl
->mode
== dm_insn_reserv
)
2834 DECL_INSN_RESERV (decl
)->condexp
2835 = check_attr_test (DECL_INSN_RESERV (decl
)->condexp
, 0, 0);
2836 if (DECL_INSN_RESERV (decl
)->default_latency
< 0)
2837 error ("define_insn_reservation `%s' has negative latency time",
2838 DECL_INSN_RESERV (decl
)->name
);
2839 DECL_INSN_RESERV (decl
)->insn_num
= description
->insns_num
;
2840 description
->insns_num
++;
2841 decl_in_table
= insert_insn_decl (decl
);
2842 if (decl_in_table
!= decl
)
2843 error ("`%s' is already used as insn reservation name",
2844 DECL_INSN_RESERV (decl
)->name
);
2846 else if (decl
->mode
== dm_bypass
)
2848 if (DECL_BYPASS (decl
)->latency
< 0)
2849 error ("define_bypass `%s - %s' has negative latency time",
2850 DECL_BYPASS (decl
)->out_insn_name
,
2851 DECL_BYPASS (decl
)->in_insn_name
);
2853 else if (decl
->mode
== dm_unit
|| decl
->mode
== dm_reserv
)
2855 if (decl
->mode
== dm_unit
)
2857 DECL_UNIT (decl
)->automaton_decl
= NULL
;
2858 if (DECL_UNIT (decl
)->automaton_name
!= NULL
)
2861 = find_automaton_decl (DECL_UNIT (decl
)->automaton_name
);
2862 if (automaton_decl
== NULL
)
2863 error ("automaton `%s' is not declared",
2864 DECL_UNIT (decl
)->automaton_name
);
2867 DECL_AUTOMATON (automaton_decl
)->automaton_is_used
= 1;
2868 DECL_UNIT (decl
)->automaton_decl
2869 = DECL_AUTOMATON (automaton_decl
);
2872 else if (automaton_presence
)
2873 error ("define_unit `%s' without automaton when one defined",
2874 DECL_UNIT (decl
)->name
);
2875 DECL_UNIT (decl
)->unit_num
= description
->units_num
;
2876 description
->units_num
++;
2877 if (strcmp (DECL_UNIT (decl
)->name
, NOTHING_NAME
) == 0)
2879 error ("`%s' is declared as cpu unit", NOTHING_NAME
);
2882 decl_in_table
= find_decl (DECL_UNIT (decl
)->name
);
2886 if (strcmp (DECL_RESERV (decl
)->name
, NOTHING_NAME
) == 0)
2888 error ("`%s' is declared as cpu reservation", NOTHING_NAME
);
2891 decl_in_table
= find_decl (DECL_RESERV (decl
)->name
);
2893 if (decl_in_table
== NULL
)
2894 decl_in_table
= insert_decl (decl
);
2897 if (decl
->mode
== dm_unit
)
2898 error ("repeated declaration of unit `%s'",
2899 DECL_UNIT (decl
)->name
);
2901 error ("repeated declaration of reservation `%s'",
2902 DECL_RESERV (decl
)->name
);
2906 /* Check bypasses and form list of bypasses for each (output)
2908 for (i
= 0; i
< description
->decls_num
; i
++)
2910 decl
= description
->decls
[i
];
2911 if (decl
->mode
== dm_bypass
)
2913 out_insn_reserv
= find_insn_decl (DECL_BYPASS (decl
)->out_insn_name
);
2914 in_insn_reserv
= find_insn_decl (DECL_BYPASS (decl
)->in_insn_name
);
2915 if (out_insn_reserv
== NULL
)
2916 error ("there is no insn reservation `%s'",
2917 DECL_BYPASS (decl
)->out_insn_name
);
2918 else if (in_insn_reserv
== NULL
)
2919 error ("there is no insn reservation `%s'",
2920 DECL_BYPASS (decl
)->in_insn_name
);
2923 DECL_BYPASS (decl
)->out_insn_reserv
2924 = DECL_INSN_RESERV (out_insn_reserv
);
2925 DECL_BYPASS (decl
)->in_insn_reserv
2926 = DECL_INSN_RESERV (in_insn_reserv
);
2928 = find_bypass (DECL_INSN_RESERV (out_insn_reserv
)->bypass_list
,
2929 DECL_BYPASS (decl
)->in_insn_reserv
);
2932 if (DECL_BYPASS (decl
)->latency
== bypass
->latency
)
2936 ("the same bypass `%s - %s' is already defined",
2937 DECL_BYPASS (decl
)->out_insn_name
,
2938 DECL_BYPASS (decl
)->in_insn_name
);
2941 ("the same bypass `%s - %s' is already defined",
2942 DECL_BYPASS (decl
)->out_insn_name
,
2943 DECL_BYPASS (decl
)->in_insn_name
);
2946 error ("bypass `%s - %s' is already defined",
2947 DECL_BYPASS (decl
)->out_insn_name
,
2948 DECL_BYPASS (decl
)->in_insn_name
);
2952 DECL_BYPASS (decl
)->next
2953 = DECL_INSN_RESERV (out_insn_reserv
)->bypass_list
;
2954 DECL_INSN_RESERV (out_insn_reserv
)->bypass_list
2955 = DECL_BYPASS (decl
);
2961 /* Check exclusion set declarations and form exclusion sets. */
2962 for (i
= 0; i
< description
->decls_num
; i
++)
2964 decl
= description
->decls
[i
];
2965 if (decl
->mode
== dm_excl
)
2967 unit_set_el_t unit_set_el_list
;
2968 unit_set_el_t unit_set_el_list_2
;
2971 = process_excls (DECL_EXCL (decl
)->names
,
2972 DECL_EXCL (decl
)->first_list_length
, decl
->pos
);
2974 = process_excls (&DECL_EXCL (decl
)->names
2975 [DECL_EXCL (decl
)->first_list_length
],
2976 DECL_EXCL (decl
)->all_names_num
2977 - DECL_EXCL (decl
)->first_list_length
,
2979 add_excls (unit_set_el_list
, unit_set_el_list_2
, decl
->pos
);
2980 add_excls (unit_set_el_list_2
, unit_set_el_list
, decl
->pos
);
2984 /* Check presence set declarations and form presence sets. */
2985 for (i
= 0; i
< description
->decls_num
; i
++)
2987 decl
= description
->decls
[i
];
2988 if (decl
->mode
== dm_presence
)
2990 unit_set_el_t unit_set_el_list
;
2991 pattern_set_el_t pattern_set_el_list
;
2994 = process_presence_absence_names
2995 (DECL_PRESENCE (decl
)->names
, DECL_PRESENCE (decl
)->names_num
,
2996 decl
->pos
, TRUE
, DECL_PRESENCE (decl
)->final_p
);
2998 = process_presence_absence_patterns
2999 (DECL_PRESENCE (decl
)->patterns
,
3000 DECL_PRESENCE (decl
)->patterns_num
,
3001 decl
->pos
, TRUE
, DECL_PRESENCE (decl
)->final_p
);
3002 add_presence_absence (unit_set_el_list
, pattern_set_el_list
,
3004 DECL_PRESENCE (decl
)->final_p
);
3008 /* Check absence set declarations and form absence sets. */
3009 for (i
= 0; i
< description
->decls_num
; i
++)
3011 decl
= description
->decls
[i
];
3012 if (decl
->mode
== dm_absence
)
3014 unit_set_el_t unit_set_el_list
;
3015 pattern_set_el_t pattern_set_el_list
;
3018 = process_presence_absence_names
3019 (DECL_ABSENCE (decl
)->names
, DECL_ABSENCE (decl
)->names_num
,
3020 decl
->pos
, FALSE
, DECL_ABSENCE (decl
)->final_p
);
3022 = process_presence_absence_patterns
3023 (DECL_ABSENCE (decl
)->patterns
,
3024 DECL_ABSENCE (decl
)->patterns_num
,
3025 decl
->pos
, FALSE
, DECL_ABSENCE (decl
)->final_p
);
3026 add_presence_absence (unit_set_el_list
, pattern_set_el_list
,
3028 DECL_ABSENCE (decl
)->final_p
);
3033 /* The following function checks that declared automaton is used. If
3034 the automaton is not used, the function fixes error/warning. The
3035 following function must be called only after `process_decls'. */
3037 check_automaton_usage (void)
3042 for (i
= 0; i
< description
->decls_num
; i
++)
3044 decl
= description
->decls
[i
];
3045 if (decl
->mode
== dm_automaton
3046 && !DECL_AUTOMATON (decl
)->automaton_is_used
)
3049 error ("automaton `%s' is not used", DECL_AUTOMATON (decl
)->name
);
3051 warning ("automaton `%s' is not used",
3052 DECL_AUTOMATON (decl
)->name
);
3057 /* The following recursive function processes all regexp in order to
3058 fix usage of units or reservations and to fix errors of undeclared
3059 name. The function may change unit_regexp onto reserv_regexp.
3060 Remember that reserv_regexp does not exist before the function
3063 process_regexp (regexp_t regexp
)
3065 decl_t decl_in_table
;
3066 regexp_t new_regexp
;
3069 if (regexp
->mode
== rm_unit
)
3071 decl_in_table
= find_decl (REGEXP_UNIT (regexp
)->name
);
3072 if (decl_in_table
== NULL
)
3073 error ("undeclared unit or reservation `%s'",
3074 REGEXP_UNIT (regexp
)->name
);
3075 else if (decl_in_table
->mode
== dm_unit
)
3077 DECL_UNIT (decl_in_table
)->unit_is_used
= 1;
3078 REGEXP_UNIT (regexp
)->unit_decl
= DECL_UNIT (decl_in_table
);
3080 else if (decl_in_table
->mode
== dm_reserv
)
3082 DECL_RESERV (decl_in_table
)->reserv_is_used
= 1;
3083 new_regexp
= create_node (sizeof (struct regexp
));
3084 new_regexp
->mode
= rm_reserv
;
3085 new_regexp
->pos
= regexp
->pos
;
3086 REGEXP_RESERV (new_regexp
)->name
= REGEXP_UNIT (regexp
)->name
;
3087 REGEXP_RESERV (new_regexp
)->reserv_decl
3088 = DECL_RESERV (decl_in_table
);
3089 regexp
= new_regexp
;
3094 else if (regexp
->mode
== rm_sequence
)
3095 for (i
= 0; i
<REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
3096 REGEXP_SEQUENCE (regexp
)->regexps
[i
]
3097 = process_regexp (REGEXP_SEQUENCE (regexp
)->regexps
[i
]);
3098 else if (regexp
->mode
== rm_allof
)
3099 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
3100 REGEXP_ALLOF (regexp
)->regexps
[i
]
3101 = process_regexp (REGEXP_ALLOF (regexp
)->regexps
[i
]);
3102 else if (regexp
->mode
== rm_oneof
)
3103 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
3104 REGEXP_ONEOF (regexp
)->regexps
[i
]
3105 = process_regexp (REGEXP_ONEOF (regexp
)->regexps
[i
]);
3106 else if (regexp
->mode
== rm_repeat
)
3107 REGEXP_REPEAT (regexp
)->regexp
3108 = process_regexp (REGEXP_REPEAT (regexp
)->regexp
);
3109 else if (regexp
->mode
!= rm_nothing
)
3114 /* The following function processes regexp of define_reservation and
3115 define_insn_reservation with the aid of function
3116 `process_regexp'. */
3118 process_regexp_decls (void)
3123 for (i
= 0; i
< description
->decls_num
; i
++)
3125 decl
= description
->decls
[i
];
3126 if (decl
->mode
== dm_reserv
)
3127 DECL_RESERV (decl
)->regexp
3128 = process_regexp (DECL_RESERV (decl
)->regexp
);
3129 else if (decl
->mode
== dm_insn_reserv
)
3130 DECL_INSN_RESERV (decl
)->regexp
3131 = process_regexp (DECL_INSN_RESERV (decl
)->regexp
);
3135 /* The following function checks that declared unit is used. If the
3136 unit is not used, the function fixes errors/warnings. The
3137 following function must be called only after `process_decls',
3138 `process_regexp_decls'. */
3145 for (i
= 0; i
< description
->decls_num
; i
++)
3147 decl
= description
->decls
[i
];
3148 if (decl
->mode
== dm_unit
&& !DECL_UNIT (decl
)->unit_is_used
)
3151 error ("unit `%s' is not used", DECL_UNIT (decl
)->name
);
3153 warning ("unit `%s' is not used", DECL_UNIT (decl
)->name
);
3155 else if (decl
->mode
== dm_reserv
&& !DECL_RESERV (decl
)->reserv_is_used
)
3158 error ("reservation `%s' is not used", DECL_RESERV (decl
)->name
);
3160 warning ("reservation `%s' is not used", DECL_RESERV (decl
)->name
);
3165 /* The following variable value is number of reservation being
3166 processed on loop recognition. */
3167 static int curr_loop_pass_num
;
3169 /* The following recursive function returns nonzero value if REGEXP
3170 contains given decl or reservations in given regexp refers for
3173 loop_in_regexp (regexp_t regexp
, decl_t start_decl
)
3179 if (regexp
->mode
== rm_unit
)
3181 else if (regexp
->mode
== rm_reserv
)
3183 if (start_decl
->mode
== dm_reserv
3184 && REGEXP_RESERV (regexp
)->reserv_decl
== DECL_RESERV (start_decl
))
3186 else if (REGEXP_RESERV (regexp
)->reserv_decl
->loop_pass_num
3187 == curr_loop_pass_num
)
3188 /* declaration has been processed. */
3192 REGEXP_RESERV (regexp
)->reserv_decl
->loop_pass_num
3193 = curr_loop_pass_num
;
3194 return loop_in_regexp (REGEXP_RESERV (regexp
)->reserv_decl
->regexp
,
3198 else if (regexp
->mode
== rm_sequence
)
3200 for (i
= 0; i
<REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
3201 if (loop_in_regexp (REGEXP_SEQUENCE (regexp
)->regexps
[i
], start_decl
))
3205 else if (regexp
->mode
== rm_allof
)
3207 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
3208 if (loop_in_regexp (REGEXP_ALLOF (regexp
)->regexps
[i
], start_decl
))
3212 else if (regexp
->mode
== rm_oneof
)
3214 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
3215 if (loop_in_regexp (REGEXP_ONEOF (regexp
)->regexps
[i
], start_decl
))
3219 else if (regexp
->mode
== rm_repeat
)
3220 return loop_in_regexp (REGEXP_REPEAT (regexp
)->regexp
, start_decl
);
3223 if (regexp
->mode
!= rm_nothing
)
3229 /* The following function fixes errors "cycle in definition ...". The
3230 function uses function `loop_in_regexp' for that. */
3232 check_loops_in_regexps (void)
3237 for (i
= 0; i
< description
->decls_num
; i
++)
3239 decl
= description
->decls
[i
];
3240 if (decl
->mode
== dm_reserv
)
3241 DECL_RESERV (decl
)->loop_pass_num
= 0;
3243 for (i
= 0; i
< description
->decls_num
; i
++)
3245 decl
= description
->decls
[i
];
3246 curr_loop_pass_num
= i
;
3248 if (decl
->mode
== dm_reserv
)
3250 DECL_RESERV (decl
)->loop_pass_num
= curr_loop_pass_num
;
3251 if (loop_in_regexp (DECL_RESERV (decl
)->regexp
, decl
))
3253 if (DECL_RESERV (decl
)->regexp
== NULL
)
3255 error ("cycle in definition of reservation `%s'",
3256 DECL_RESERV (decl
)->name
);
3262 /* The function recursively processes IR of reservation and defines
3263 max and min cycle for reservation of unit. */
3265 process_regexp_cycles (regexp_t regexp
, int max_start_cycle
,
3266 int min_start_cycle
, int *max_finish_cycle
,
3267 int *min_finish_cycle
)
3271 if (regexp
->mode
== rm_unit
)
3273 if (REGEXP_UNIT (regexp
)->unit_decl
->max_occ_cycle_num
< max_start_cycle
)
3274 REGEXP_UNIT (regexp
)->unit_decl
->max_occ_cycle_num
= max_start_cycle
;
3275 if (REGEXP_UNIT (regexp
)->unit_decl
->min_occ_cycle_num
> min_start_cycle
3276 || REGEXP_UNIT (regexp
)->unit_decl
->min_occ_cycle_num
== -1)
3277 REGEXP_UNIT (regexp
)->unit_decl
->min_occ_cycle_num
= min_start_cycle
;
3278 *max_finish_cycle
= max_start_cycle
;
3279 *min_finish_cycle
= min_start_cycle
;
3281 else if (regexp
->mode
== rm_reserv
)
3282 process_regexp_cycles (REGEXP_RESERV (regexp
)->reserv_decl
->regexp
,
3283 max_start_cycle
, min_start_cycle
,
3284 max_finish_cycle
, min_finish_cycle
);
3285 else if (regexp
->mode
== rm_repeat
)
3287 for (i
= 0; i
< REGEXP_REPEAT (regexp
)->repeat_num
; i
++)
3289 process_regexp_cycles (REGEXP_REPEAT (regexp
)->regexp
,
3290 max_start_cycle
, min_start_cycle
,
3291 max_finish_cycle
, min_finish_cycle
);
3292 max_start_cycle
= *max_finish_cycle
+ 1;
3293 min_start_cycle
= *min_finish_cycle
+ 1;
3296 else if (regexp
->mode
== rm_sequence
)
3298 for (i
= 0; i
<REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
3300 process_regexp_cycles (REGEXP_SEQUENCE (regexp
)->regexps
[i
],
3301 max_start_cycle
, min_start_cycle
,
3302 max_finish_cycle
, min_finish_cycle
);
3303 max_start_cycle
= *max_finish_cycle
+ 1;
3304 min_start_cycle
= *min_finish_cycle
+ 1;
3307 else if (regexp
->mode
== rm_allof
)
3312 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
3314 process_regexp_cycles (REGEXP_ALLOF (regexp
)->regexps
[i
],
3315 max_start_cycle
, min_start_cycle
,
3316 max_finish_cycle
, min_finish_cycle
);
3317 if (max_cycle
< *max_finish_cycle
)
3318 max_cycle
= *max_finish_cycle
;
3319 if (i
== 0 || min_cycle
> *min_finish_cycle
)
3320 min_cycle
= *min_finish_cycle
;
3322 *max_finish_cycle
= max_cycle
;
3323 *min_finish_cycle
= min_cycle
;
3325 else if (regexp
->mode
== rm_oneof
)
3330 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
3332 process_regexp_cycles (REGEXP_ONEOF (regexp
)->regexps
[i
],
3333 max_start_cycle
, min_start_cycle
,
3334 max_finish_cycle
, min_finish_cycle
);
3335 if (max_cycle
< *max_finish_cycle
)
3336 max_cycle
= *max_finish_cycle
;
3337 if (i
== 0 || min_cycle
> *min_finish_cycle
)
3338 min_cycle
= *min_finish_cycle
;
3340 *max_finish_cycle
= max_cycle
;
3341 *min_finish_cycle
= min_cycle
;
3345 if (regexp
->mode
!= rm_nothing
)
3347 *max_finish_cycle
= max_start_cycle
;
3348 *min_finish_cycle
= min_start_cycle
;
3352 /* The following function is called only for correct program. The
3353 function defines max reservation of insns in cycles. */
3355 evaluate_max_reserv_cycles (void)
3357 int max_insn_cycles_num
;
3358 int min_insn_cycles_num
;
3362 description
->max_insn_reserv_cycles
= 0;
3363 for (i
= 0; i
< description
->decls_num
; i
++)
3365 decl
= description
->decls
[i
];
3366 if (decl
->mode
== dm_insn_reserv
)
3368 process_regexp_cycles (DECL_INSN_RESERV (decl
)->regexp
, 0, 0,
3369 &max_insn_cycles_num
, &min_insn_cycles_num
);
3370 if (description
->max_insn_reserv_cycles
< max_insn_cycles_num
)
3371 description
->max_insn_reserv_cycles
= max_insn_cycles_num
;
3374 description
->max_insn_reserv_cycles
++;
3377 /* The following function calls functions for checking all
3380 check_all_description (void)
3383 check_automaton_usage ();
3384 process_regexp_decls ();
3386 check_loops_in_regexps ();
3388 evaluate_max_reserv_cycles ();
3393 /* The page contains abstract data `ticker'. This data is used to
3394 report time of different phases of building automata. It is
3395 possibly to write a description for which automata will be built
3396 during several minutes even on fast machine. */
3398 /* The following function creates ticker and makes it active. */
3400 create_ticker (void)
3404 ticker
.modified_creation_time
= get_run_time ();
3405 ticker
.incremented_off_time
= 0;
3409 /* The following function switches off given ticker. */
3411 ticker_off (ticker_t
*ticker
)
3413 if (ticker
->incremented_off_time
== 0)
3414 ticker
->incremented_off_time
= get_run_time () + 1;
3417 /* The following function switches on given ticker. */
3419 ticker_on (ticker_t
*ticker
)
3421 if (ticker
->incremented_off_time
!= 0)
3423 ticker
->modified_creation_time
3424 += get_run_time () - ticker
->incremented_off_time
+ 1;
3425 ticker
->incremented_off_time
= 0;
3429 /* The following function returns current time in milliseconds since
3430 the moment when given ticker was created. */
3432 active_time (ticker_t ticker
)
3434 if (ticker
.incremented_off_time
!= 0)
3435 return ticker
.incremented_off_time
- 1 - ticker
.modified_creation_time
;
3437 return get_run_time () - ticker
.modified_creation_time
;
3440 /* The following function returns string representation of active time
3441 of given ticker. The result is string representation of seconds
3442 with accuracy of 1/100 second. Only result of the last call of the
3443 function exists. Therefore the following code is not correct
3445 printf ("parser time: %s\ngeneration time: %s\n",
3446 active_time_string (parser_ticker),
3447 active_time_string (generation_ticker));
3449 Correct code has to be the following
3451 printf ("parser time: %s\n", active_time_string (parser_ticker));
3452 printf ("generation time: %s\n",
3453 active_time_string (generation_ticker));
3457 print_active_time (FILE *f
, ticker_t ticker
)
3461 msecs
= active_time (ticker
);
3462 fprintf (f
, "%d.%06d", msecs
/ 1000000, msecs
% 1000000);
3467 /* The following variable value is number of automaton which are
3468 really being created. This value is defined on the base of
3469 argument of option `-split'. If the variable has zero value the
3470 number of automata is defined by the constructions `%automaton'.
3471 This case occurs when option `-split' is absent or has zero
3472 argument. If constructions `define_automaton' is absent only one
3473 automaton is created. */
3474 static int automata_num
;
3476 /* The following variable values are times of
3477 o transformation of regular expressions
3478 o building NDFA (DFA if !ndfa_flag)
3479 o NDFA -> DFA (simply the same automaton if !ndfa_flag)
3481 o building insn equivalence classes
3484 static ticker_t transform_time
;
3485 static ticker_t NDFA_time
;
3486 static ticker_t NDFA_to_DFA_time
;
3487 static ticker_t minimize_time
;
3488 static ticker_t equiv_time
;
3489 static ticker_t automaton_generation_time
;
3490 static ticker_t output_time
;
3492 /* The following variable values are times of
3495 all pipeline hazard translator work */
3496 static ticker_t check_time
;
3497 static ticker_t generation_time
;
3498 static ticker_t all_time
;
3502 /* Pseudo insn decl which denotes advancing cycle. */
3503 static decl_t advance_cycle_insn_decl
;
3505 add_advance_cycle_insn_decl (void)
3507 advance_cycle_insn_decl
= create_node (sizeof (struct decl
));
3508 advance_cycle_insn_decl
->mode
= dm_insn_reserv
;
3509 advance_cycle_insn_decl
->pos
= no_pos
;
3510 DECL_INSN_RESERV (advance_cycle_insn_decl
)->regexp
= NULL
;
3511 DECL_INSN_RESERV (advance_cycle_insn_decl
)->name
= (char *) "$advance_cycle";
3512 DECL_INSN_RESERV (advance_cycle_insn_decl
)->insn_num
3513 = description
->insns_num
;
3514 description
->decls
[description
->decls_num
] = advance_cycle_insn_decl
;
3515 description
->decls_num
++;
3516 description
->insns_num
++;
3521 /* Abstract data `alternative states' which represents
3522 nondeterministic nature of the description (see comments for
3523 structures alt_state and state). */
3525 /* List of free states. */
3526 static alt_state_t first_free_alt_state
;
3529 /* The following variables is maximal number of allocated nodes
3531 static int allocated_alt_states_num
= 0;
3534 /* The following function returns free node alt_state. It may be new
3535 allocated node or node freed earlier. */
3537 get_free_alt_state (void)
3541 if (first_free_alt_state
!= NULL
)
3543 result
= first_free_alt_state
;
3544 first_free_alt_state
= first_free_alt_state
->next_alt_state
;
3549 allocated_alt_states_num
++;
3551 result
= create_node (sizeof (struct alt_state
));
3553 result
->state
= NULL
;
3554 result
->next_alt_state
= NULL
;
3555 result
->next_sorted_alt_state
= NULL
;
3559 /* The function frees node ALT_STATE. */
3561 free_alt_state (alt_state_t alt_state
)
3563 if (alt_state
== NULL
)
3565 alt_state
->next_alt_state
= first_free_alt_state
;
3566 first_free_alt_state
= alt_state
;
3569 /* The function frees list started with node ALT_STATE_LIST. */
3571 free_alt_states (alt_state_t alt_states_list
)
3573 alt_state_t curr_alt_state
;
3574 alt_state_t next_alt_state
;
3576 for (curr_alt_state
= alt_states_list
;
3577 curr_alt_state
!= NULL
;
3578 curr_alt_state
= next_alt_state
)
3580 next_alt_state
= curr_alt_state
->next_alt_state
;
3581 free_alt_state (curr_alt_state
);
3585 /* The function compares unique numbers of alt states. */
3587 alt_state_cmp (const void *alt_state_ptr_1
, const void *alt_state_ptr_2
)
3589 if ((*(alt_state_t
*) alt_state_ptr_1
)->state
->unique_num
3590 == (*(alt_state_t
*) alt_state_ptr_2
)->state
->unique_num
)
3592 else if ((*(alt_state_t
*) alt_state_ptr_1
)->state
->unique_num
3593 < (*(alt_state_t
*) alt_state_ptr_2
)->state
->unique_num
)
3599 /* The function sorts ALT_STATES_LIST and removes duplicated alt
3600 states from the list. The comparison key is alt state unique
3603 uniq_sort_alt_states (alt_state_t alt_states_list
)
3605 alt_state_t curr_alt_state
;
3606 vla_ptr_t alt_states
;
3608 size_t prev_unique_state_ind
;
3610 alt_state_t
*result_ptr
;
3612 VLA_PTR_CREATE (alt_states
, 150, "alt_states");
3613 for (curr_alt_state
= alt_states_list
;
3614 curr_alt_state
!= NULL
;
3615 curr_alt_state
= curr_alt_state
->next_alt_state
)
3616 VLA_PTR_ADD (alt_states
, curr_alt_state
);
3617 qsort (VLA_PTR_BEGIN (alt_states
), VLA_PTR_LENGTH (alt_states
),
3618 sizeof (alt_state_t
), alt_state_cmp
);
3619 if (VLA_PTR_LENGTH (alt_states
) == 0)
3623 result_ptr
= VLA_PTR_BEGIN (alt_states
);
3624 prev_unique_state_ind
= 0;
3625 for (i
= 1; i
< VLA_PTR_LENGTH (alt_states
); i
++)
3626 if (result_ptr
[prev_unique_state_ind
]->state
!= result_ptr
[i
]->state
)
3628 prev_unique_state_ind
++;
3629 result_ptr
[prev_unique_state_ind
] = result_ptr
[i
];
3632 for (i
= prev_unique_state_ind
+ 1; i
< VLA_PTR_LENGTH (alt_states
); i
++)
3633 free_alt_state (result_ptr
[i
]);
3635 VLA_PTR_SHORTEN (alt_states
, i
- prev_unique_state_ind
- 1);
3636 result_ptr
= VLA_PTR_BEGIN (alt_states
);
3637 for (i
= 1; i
< VLA_PTR_LENGTH (alt_states
); i
++)
3638 result_ptr
[i
- 1]->next_sorted_alt_state
= result_ptr
[i
];
3639 result_ptr
[i
- 1]->next_sorted_alt_state
= NULL
;
3640 result
= *result_ptr
;
3642 VLA_PTR_DELETE (alt_states
);
3646 /* The function checks equality of alt state lists. Remember that the
3647 lists must be already sorted by the previous function. */
3649 alt_states_eq (alt_state_t alt_states_1
, alt_state_t alt_states_2
)
3651 while (alt_states_1
!= NULL
&& alt_states_2
!= NULL
3652 && alt_state_cmp (&alt_states_1
, &alt_states_2
) == 0)
3654 alt_states_1
= alt_states_1
->next_sorted_alt_state
;
3655 alt_states_2
= alt_states_2
->next_sorted_alt_state
;
3657 return alt_states_1
== alt_states_2
;
3660 /* Initialization of the abstract data. */
3662 initiate_alt_states (void)
3664 first_free_alt_state
= NULL
;
3667 /* Finishing work with the abstract data. */
3669 finish_alt_states (void)
3675 /* The page contains macros for work with bits strings. We could use
3676 standard gcc bitmap or sbitmap but it would result in difficulties
3677 of building canadian cross. */
3679 /* Set bit number bitno in the bit string. The macro is not side
3681 #define SET_BIT(bitstring, bitno) \
3682 (((char *) (bitstring)) [(bitno) / CHAR_BIT] |= 1 << (bitno) % CHAR_BIT)
3684 #define CLEAR_BIT(bitstring, bitno) \
3685 (((char *) (bitstring)) [(bitno) / CHAR_BIT] &= ~(1 << (bitno) % CHAR_BIT))
3687 /* Test if bit number bitno in the bitstring is set. The macro is not
3688 side effect proof. */
3689 #define TEST_BIT(bitstring, bitno) \
3690 (((char *) (bitstring)) [(bitno) / CHAR_BIT] >> (bitno) % CHAR_BIT & 1)
3694 /* This page contains abstract data `state'. */
3696 /* Maximal length of reservations in cycles (>= 1). */
3697 static int max_cycles_num
;
3699 /* Number of set elements (see type set_el_t) needed for
3700 representation of one cycle reservation. It is depended on units
3702 static int els_in_cycle_reserv
;
3704 /* Number of set elements (see type set_el_t) needed for
3705 representation of maximal length reservation. Deterministic
3706 reservation is stored as set (bit string) of length equal to the
3707 variable value * number of bits in set_el_t. */
3708 static int els_in_reservs
;
3710 /* VLA for representation of array of pointers to unit
3712 static vla_ptr_t units_container
;
3714 /* The start address of the array. */
3715 static unit_decl_t
*units_array
;
3717 /* Temporary reservation of maximal length. */
3718 static reserv_sets_t temp_reserv
;
3720 /* The state table itself is represented by the following variable. */
3721 static htab_t state_table
;
3723 /* VLA for representation of array of pointers to free nodes
3725 static vla_ptr_t free_states
;
3727 static int curr_unique_state_num
;
3730 /* The following variables is maximal number of allocated nodes
3732 static int allocated_states_num
= 0;
3735 /* Allocate new reservation set. */
3736 static reserv_sets_t
3737 alloc_empty_reserv_sets (void)
3739 reserv_sets_t result
;
3741 obstack_blank (&irp
, els_in_reservs
* sizeof (set_el_t
));
3742 result
= (reserv_sets_t
) obstack_base (&irp
);
3743 obstack_finish (&irp
);
3744 memset (result
, 0, els_in_reservs
* sizeof (set_el_t
));
3748 /* Hash value of reservation set. */
3750 reserv_sets_hash_value (reserv_sets_t reservs
)
3752 set_el_t hash_value
;
3755 set_el_t
*reserv_ptr
;
3758 reservs_num
= els_in_reservs
;
3759 reserv_ptr
= reservs
;
3761 while (reservs_num
!= 0)
3764 hash_value
+= ((*reserv_ptr
>> i
)
3765 | (*reserv_ptr
<< (sizeof (set_el_t
) * CHAR_BIT
- i
)));
3767 if (i
== sizeof (set_el_t
) * CHAR_BIT
)
3771 if (sizeof (set_el_t
) <= sizeof (unsigned))
3774 for (i
= sizeof (set_el_t
); i
> 0; i
-= sizeof (unsigned) - 1)
3776 result
+= (unsigned) hash_value
;
3777 hash_value
>>= (sizeof (unsigned) - 1) * CHAR_BIT
;
3782 /* Comparison of given reservation sets. */
3784 reserv_sets_cmp (reserv_sets_t reservs_1
, reserv_sets_t reservs_2
)
3787 set_el_t
*reserv_ptr_1
;
3788 set_el_t
*reserv_ptr_2
;
3790 if (reservs_1
== NULL
|| reservs_2
== NULL
)
3792 reservs_num
= els_in_reservs
;
3793 reserv_ptr_1
= reservs_1
;
3794 reserv_ptr_2
= reservs_2
;
3795 while (reservs_num
!= 0 && *reserv_ptr_1
== *reserv_ptr_2
)
3801 if (reservs_num
== 0)
3803 else if (*reserv_ptr_1
< *reserv_ptr_2
)
3809 /* The function checks equality of the reservation sets. */
3811 reserv_sets_eq (reserv_sets_t reservs_1
, reserv_sets_t reservs_2
)
3813 return reserv_sets_cmp (reservs_1
, reservs_2
) == 0;
3816 /* Set up in the reservation set that unit with UNIT_NUM is used on
3819 set_unit_reserv (reserv_sets_t reservs
, int cycle_num
, int unit_num
)
3821 if (cycle_num
>= max_cycles_num
)
3823 SET_BIT (reservs
, cycle_num
* els_in_cycle_reserv
3824 * sizeof (set_el_t
) * CHAR_BIT
+ unit_num
);
3827 /* Set up in the reservation set RESERVS that unit with UNIT_NUM is
3828 used on CYCLE_NUM. */
3830 test_unit_reserv (reserv_sets_t reservs
, int cycle_num
, int unit_num
)
3832 if (cycle_num
>= max_cycles_num
)
3834 return TEST_BIT (reservs
, cycle_num
* els_in_cycle_reserv
3835 * sizeof (set_el_t
) * CHAR_BIT
+ unit_num
);
3838 /* The function checks that the reservation set represents no one unit
3841 it_is_empty_reserv_sets (reserv_sets_t operand
)
3843 set_el_t
*reserv_ptr
;
3846 if (operand
== NULL
)
3848 for (reservs_num
= els_in_reservs
, reserv_ptr
= operand
;
3850 reserv_ptr
++, reservs_num
--)
3851 if (*reserv_ptr
!= 0)
3856 /* The function checks that the reservation sets are intersected,
3857 i.e. there is a unit reservation on a cycle in both reservation
3860 reserv_sets_are_intersected (reserv_sets_t operand_1
,
3861 reserv_sets_t operand_2
)
3865 set_el_t
*cycle_ptr_1
;
3866 set_el_t
*cycle_ptr_2
;
3868 if (operand_1
== NULL
|| operand_2
== NULL
)
3870 for (el_ptr_1
= operand_1
, el_ptr_2
= operand_2
;
3871 el_ptr_1
< operand_1
+ els_in_reservs
;
3872 el_ptr_1
++, el_ptr_2
++)
3873 if (*el_ptr_1
& *el_ptr_2
)
3875 reserv_sets_or (temp_reserv
, operand_1
, operand_2
);
3876 for (cycle_ptr_1
= operand_1
, cycle_ptr_2
= operand_2
;
3877 cycle_ptr_1
< operand_1
+ els_in_reservs
;
3878 cycle_ptr_1
+= els_in_cycle_reserv
, cycle_ptr_2
+= els_in_cycle_reserv
)
3880 for (el_ptr_1
= cycle_ptr_1
, el_ptr_2
= get_excl_set (cycle_ptr_2
);
3881 el_ptr_1
< cycle_ptr_1
+ els_in_cycle_reserv
;
3882 el_ptr_1
++, el_ptr_2
++)
3883 if (*el_ptr_1
& *el_ptr_2
)
3885 if (!check_presence_pattern_sets (cycle_ptr_1
, cycle_ptr_2
, FALSE
))
3887 if (!check_presence_pattern_sets (temp_reserv
+ (cycle_ptr_2
3891 if (!check_absence_pattern_sets (cycle_ptr_1
, cycle_ptr_2
, FALSE
))
3893 if (!check_absence_pattern_sets (temp_reserv
+ (cycle_ptr_2
- operand_2
),
3900 /* The function sets up RESULT bits by bits of OPERAND shifted on one
3901 cpu cycle. The remaining bits of OPERAND (representing the last
3902 cycle unit reservations) are not changed. */
3904 reserv_sets_shift (reserv_sets_t result
, reserv_sets_t operand
)
3908 if (result
== NULL
|| operand
== NULL
|| result
== operand
)
3910 for (i
= els_in_cycle_reserv
; i
< els_in_reservs
; i
++)
3911 result
[i
- els_in_cycle_reserv
] = operand
[i
];
3914 /* OR of the reservation sets. */
3916 reserv_sets_or (reserv_sets_t result
, reserv_sets_t operand_1
,
3917 reserv_sets_t operand_2
)
3921 set_el_t
*result_set_el_ptr
;
3923 if (result
== NULL
|| operand_1
== NULL
|| operand_2
== NULL
)
3925 for (el_ptr_1
= operand_1
, el_ptr_2
= operand_2
, result_set_el_ptr
= result
;
3926 el_ptr_1
< operand_1
+ els_in_reservs
;
3927 el_ptr_1
++, el_ptr_2
++, result_set_el_ptr
++)
3928 *result_set_el_ptr
= *el_ptr_1
| *el_ptr_2
;
3931 /* AND of the reservation sets. */
3933 reserv_sets_and (reserv_sets_t result
, reserv_sets_t operand_1
,
3934 reserv_sets_t operand_2
)
3938 set_el_t
*result_set_el_ptr
;
3940 if (result
== NULL
|| operand_1
== NULL
|| operand_2
== NULL
)
3942 for (el_ptr_1
= operand_1
, el_ptr_2
= operand_2
, result_set_el_ptr
= result
;
3943 el_ptr_1
< operand_1
+ els_in_reservs
;
3944 el_ptr_1
++, el_ptr_2
++, result_set_el_ptr
++)
3945 *result_set_el_ptr
= *el_ptr_1
& *el_ptr_2
;
3948 /* The function outputs string representation of units reservation on
3949 cycle START_CYCLE in the reservation set. The function uses repeat
3950 construction if REPETITION_NUM > 1. */
3952 output_cycle_reservs (FILE *f
, reserv_sets_t reservs
, int start_cycle
,
3956 int reserved_units_num
;
3958 reserved_units_num
= 0;
3959 for (unit_num
= 0; unit_num
< description
->units_num
; unit_num
++)
3960 if (TEST_BIT (reservs
, start_cycle
* els_in_cycle_reserv
3961 * sizeof (set_el_t
) * CHAR_BIT
+ unit_num
))
3962 reserved_units_num
++;
3963 if (repetition_num
<= 0)
3965 if (repetition_num
!= 1 && reserved_units_num
> 1)
3967 reserved_units_num
= 0;
3969 unit_num
< description
->units_num
;
3971 if (TEST_BIT (reservs
, start_cycle
* els_in_cycle_reserv
3972 * sizeof (set_el_t
) * CHAR_BIT
+ unit_num
))
3974 if (reserved_units_num
!= 0)
3976 reserved_units_num
++;
3977 fprintf (f
, "%s", units_array
[unit_num
]->name
);
3979 if (reserved_units_num
== 0)
3980 fprintf (f
, NOTHING_NAME
);
3981 if (repetition_num
<= 0)
3983 if (repetition_num
!= 1 && reserved_units_num
> 1)
3985 if (repetition_num
!= 1)
3986 fprintf (f
, "*%d", repetition_num
);
3989 /* The function outputs string representation of units reservation in
3990 the reservation set. */
3992 output_reserv_sets (FILE *f
, reserv_sets_t reservs
)
3994 int start_cycle
= 0;
3999 for (cycle
= 0; cycle
< max_cycles_num
; cycle
++)
4000 if (repetition_num
== 0)
4003 start_cycle
= cycle
;
4006 ((char *) reservs
+ start_cycle
* els_in_cycle_reserv
4007 * sizeof (set_el_t
),
4008 (char *) reservs
+ cycle
* els_in_cycle_reserv
4009 * sizeof (set_el_t
),
4010 els_in_cycle_reserv
* sizeof (set_el_t
)) == 0)
4014 if (start_cycle
!= 0)
4016 output_cycle_reservs (f
, reservs
, start_cycle
, repetition_num
);
4018 start_cycle
= cycle
;
4020 if (start_cycle
< max_cycles_num
)
4022 if (start_cycle
!= 0)
4024 output_cycle_reservs (f
, reservs
, start_cycle
, repetition_num
);
4028 /* The following function returns free node state for AUTOMATON. It
4029 may be new allocated node or node freed earlier. The function also
4030 allocates reservation set if WITH_RESERVS has nonzero value. */
4032 get_free_state (int with_reservs
, automaton_t automaton
)
4036 if (max_cycles_num
<= 0 || automaton
== NULL
)
4038 if (VLA_PTR_LENGTH (free_states
) != 0)
4040 result
= VLA_PTR (free_states
, VLA_PTR_LENGTH (free_states
) - 1);
4041 VLA_PTR_SHORTEN (free_states
, 1);
4042 result
->automaton
= automaton
;
4043 result
->first_out_arc
= NULL
;
4044 result
->it_was_placed_in_stack_for_NDFA_forming
= 0;
4045 result
->it_was_placed_in_stack_for_DFA_forming
= 0;
4046 result
->component_states
= NULL
;
4047 result
->longest_path_length
= UNDEFINED_LONGEST_PATH_LENGTH
;
4052 allocated_states_num
++;
4054 result
= create_node (sizeof (struct state
));
4055 result
->automaton
= automaton
;
4056 result
->first_out_arc
= NULL
;
4057 result
->unique_num
= curr_unique_state_num
;
4058 result
->longest_path_length
= UNDEFINED_LONGEST_PATH_LENGTH
;
4059 curr_unique_state_num
++;
4063 if (result
->reservs
== NULL
)
4064 result
->reservs
= alloc_empty_reserv_sets ();
4066 memset (result
->reservs
, 0, els_in_reservs
* sizeof (set_el_t
));
4071 /* The function frees node STATE. */
4073 free_state (state_t state
)
4075 free_alt_states (state
->component_states
);
4076 VLA_PTR_ADD (free_states
, state
);
4079 /* Hash value of STATE. If STATE represents deterministic state it is
4080 simply hash value of the corresponding reservation set. Otherwise
4081 it is formed from hash values of the component deterministic
4082 states. One more key is order number of state automaton. */
4084 state_hash (const void *state
)
4086 unsigned int hash_value
;
4087 alt_state_t alt_state
;
4089 if (((state_t
) state
)->component_states
== NULL
)
4090 hash_value
= reserv_sets_hash_value (((state_t
) state
)->reservs
);
4094 for (alt_state
= ((state_t
) state
)->component_states
;
4096 alt_state
= alt_state
->next_sorted_alt_state
)
4097 hash_value
= (((hash_value
>> (sizeof (unsigned) - 1) * CHAR_BIT
)
4098 | (hash_value
<< CHAR_BIT
))
4099 + alt_state
->state
->unique_num
);
4101 hash_value
= (((hash_value
>> (sizeof (unsigned) - 1) * CHAR_BIT
)
4102 | (hash_value
<< CHAR_BIT
))
4103 + ((state_t
) state
)->automaton
->automaton_order_num
);
4107 /* Return nonzero value if the states are the same. */
4109 state_eq_p (const void *state_1
, const void *state_2
)
4111 alt_state_t alt_state_1
;
4112 alt_state_t alt_state_2
;
4114 if (((state_t
) state_1
)->automaton
!= ((state_t
) state_2
)->automaton
)
4116 else if (((state_t
) state_1
)->component_states
== NULL
4117 && ((state_t
) state_2
)->component_states
== NULL
)
4118 return reserv_sets_eq (((state_t
) state_1
)->reservs
,
4119 ((state_t
) state_2
)->reservs
);
4120 else if (((state_t
) state_1
)->component_states
!= NULL
4121 && ((state_t
) state_2
)->component_states
!= NULL
)
4123 for (alt_state_1
= ((state_t
) state_1
)->component_states
,
4124 alt_state_2
= ((state_t
) state_2
)->component_states
;
4125 alt_state_1
!= NULL
&& alt_state_2
!= NULL
;
4126 alt_state_1
= alt_state_1
->next_sorted_alt_state
,
4127 alt_state_2
= alt_state_2
->next_sorted_alt_state
)
4128 /* All state in the list must be already in the hash table.
4129 Also the lists must be sorted. */
4130 if (alt_state_1
->state
!= alt_state_2
->state
)
4132 return alt_state_1
== alt_state_2
;
4138 /* Insert STATE into the state table. */
4140 insert_state (state_t state
)
4144 entry_ptr
= htab_find_slot (state_table
, (void *) state
, 1);
4145 if (*entry_ptr
== NULL
)
4146 *entry_ptr
= (void *) state
;
4147 return (state_t
) *entry_ptr
;
4150 /* Add reservation of unit with UNIT_NUM on cycle CYCLE_NUM to
4151 deterministic STATE. */
4153 set_state_reserv (state_t state
, int cycle_num
, int unit_num
)
4155 set_unit_reserv (state
->reservs
, cycle_num
, unit_num
);
4158 /* Return nonzero value if the deterministic states contains a
4159 reservation of the same cpu unit on the same cpu cycle. */
4161 intersected_state_reservs_p (state_t state1
, state_t state2
)
4163 if (state1
->automaton
!= state2
->automaton
)
4165 return reserv_sets_are_intersected (state1
->reservs
, state2
->reservs
);
4168 /* Return deterministic state (inserted into the table) which
4169 representing the automaton state which is union of reservations of
4170 the deterministic states masked by RESERVS. */
4172 states_union (state_t state1
, state_t state2
, reserv_sets_t reservs
)
4175 state_t state_in_table
;
4177 if (state1
->automaton
!= state2
->automaton
)
4179 result
= get_free_state (1, state1
->automaton
);
4180 reserv_sets_or (result
->reservs
, state1
->reservs
, state2
->reservs
);
4181 reserv_sets_and (result
->reservs
, result
->reservs
, reservs
);
4182 state_in_table
= insert_state (result
);
4183 if (result
!= state_in_table
)
4185 free_state (result
);
4186 result
= state_in_table
;
4191 /* Return deterministic state (inserted into the table) which
4192 represent the automaton state is obtained from deterministic STATE
4193 by advancing cpu cycle and masking by RESERVS. */
4195 state_shift (state_t state
, reserv_sets_t reservs
)
4198 state_t state_in_table
;
4200 result
= get_free_state (1, state
->automaton
);
4201 reserv_sets_shift (result
->reservs
, state
->reservs
);
4202 reserv_sets_and (result
->reservs
, result
->reservs
, reservs
);
4203 state_in_table
= insert_state (result
);
4204 if (result
!= state_in_table
)
4206 free_state (result
);
4207 result
= state_in_table
;
4212 /* Initialization of the abstract data. */
4214 initiate_states (void)
4219 VLA_PTR_CREATE (units_container
, description
->units_num
, "units_container");
4221 = (description
->decls_num
&& description
->units_num
4222 ? VLA_PTR_BEGIN (units_container
) : NULL
);
4223 for (i
= 0; i
< description
->decls_num
; i
++)
4225 decl
= description
->decls
[i
];
4226 if (decl
->mode
== dm_unit
)
4227 units_array
[DECL_UNIT (decl
)->unit_num
] = DECL_UNIT (decl
);
4229 max_cycles_num
= description
->max_insn_reserv_cycles
;
4231 = ((description
->units_num
+ sizeof (set_el_t
) * CHAR_BIT
- 1)
4232 / (sizeof (set_el_t
) * CHAR_BIT
));
4233 els_in_reservs
= els_in_cycle_reserv
* max_cycles_num
;
4234 curr_unique_state_num
= 0;
4235 initiate_alt_states ();
4236 VLA_PTR_CREATE (free_states
, 1500, "free states");
4237 state_table
= htab_create (1500, state_hash
, state_eq_p
, (htab_del
) 0);
4238 temp_reserv
= alloc_empty_reserv_sets ();
4241 /* Finishing work with the abstract data. */
4243 finish_states (void)
4245 VLA_PTR_DELETE (units_container
);
4246 htab_delete (state_table
);
4247 VLA_PTR_DELETE (free_states
);
4248 finish_alt_states ();
4253 /* Abstract data `arcs'. */
4255 /* List of free arcs. */
4256 static arc_t first_free_arc
;
4259 /* The following variables is maximal number of allocated nodes
4261 static int allocated_arcs_num
= 0;
4264 /* The function frees node ARC. */
4266 free_arc (arc_t arc
)
4268 arc
->next_out_arc
= first_free_arc
;
4269 first_free_arc
= arc
;
4272 /* The function removes and frees ARC staring from FROM_STATE. */
4274 remove_arc (state_t from_state
, arc_t arc
)
4281 for (prev_arc
= NULL
, curr_arc
= from_state
->first_out_arc
;
4283 prev_arc
= curr_arc
, curr_arc
= curr_arc
->next_out_arc
)
4284 if (curr_arc
== arc
)
4286 if (curr_arc
== NULL
)
4288 if (prev_arc
== NULL
)
4289 from_state
->first_out_arc
= arc
->next_out_arc
;
4291 prev_arc
->next_out_arc
= arc
->next_out_arc
;
4295 /* The functions returns arc with given characteristics (or NULL if
4296 the arc does not exist). */
4298 find_arc (state_t from_state
, state_t to_state
, ainsn_t insn
)
4302 for (arc
= first_out_arc (from_state
); arc
!= NULL
; arc
= next_out_arc (arc
))
4303 if (arc
->to_state
== to_state
&& arc
->insn
== insn
)
4308 /* The function adds arc from FROM_STATE to TO_STATE marked by AINSN
4309 and with given STATE_ALTS. The function returns added arc (or
4310 already existing arc). */
4312 add_arc (state_t from_state
, state_t to_state
, ainsn_t ainsn
,
4317 new_arc
= find_arc (from_state
, to_state
, ainsn
);
4318 if (new_arc
!= NULL
)
4320 if (first_free_arc
== NULL
)
4323 allocated_arcs_num
++;
4325 new_arc
= create_node (sizeof (struct arc
));
4326 new_arc
->to_state
= NULL
;
4327 new_arc
->insn
= NULL
;
4328 new_arc
->next_out_arc
= NULL
;
4332 new_arc
= first_free_arc
;
4333 first_free_arc
= first_free_arc
->next_out_arc
;
4335 new_arc
->to_state
= to_state
;
4336 new_arc
->insn
= ainsn
;
4337 ainsn
->arc_exists_p
= 1;
4338 new_arc
->next_out_arc
= from_state
->first_out_arc
;
4339 from_state
->first_out_arc
= new_arc
;
4340 new_arc
->next_arc_marked_by_insn
= NULL
;
4341 new_arc
->state_alts
= state_alts
;
4345 /* The function returns the first arc starting from STATE. */
4347 first_out_arc (state_t state
)
4349 return state
->first_out_arc
;
4352 /* The function returns next out arc after ARC. */
4354 next_out_arc (arc_t arc
)
4356 return arc
->next_out_arc
;
4359 /* Initialization of the abstract data. */
4361 initiate_arcs (void)
4363 first_free_arc
= NULL
;
4366 /* Finishing work with the abstract data. */
4374 /* Abstract data `automata lists'. */
4376 /* List of free states. */
4377 static automata_list_el_t first_free_automata_list_el
;
4379 /* The list being formed. */
4380 static automata_list_el_t current_automata_list
;
4382 /* Hash table of automata lists. */
4383 static htab_t automata_list_table
;
4385 /* The following function returns free automata list el. It may be
4386 new allocated node or node freed earlier. */
4387 static automata_list_el_t
4388 get_free_automata_list_el (void)
4390 automata_list_el_t result
;
4392 if (first_free_automata_list_el
!= NULL
)
4394 result
= first_free_automata_list_el
;
4395 first_free_automata_list_el
4396 = first_free_automata_list_el
->next_automata_list_el
;
4399 result
= create_node (sizeof (struct automata_list_el
));
4400 result
->automaton
= NULL
;
4401 result
->next_automata_list_el
= NULL
;
4405 /* The function frees node AUTOMATA_LIST_EL. */
4407 free_automata_list_el (automata_list_el_t automata_list_el
)
4409 if (automata_list_el
== NULL
)
4411 automata_list_el
->next_automata_list_el
= first_free_automata_list_el
;
4412 first_free_automata_list_el
= automata_list_el
;
4415 /* The function frees list AUTOMATA_LIST. */
4417 free_automata_list (automata_list_el_t automata_list
)
4419 automata_list_el_t curr_automata_list_el
;
4420 automata_list_el_t next_automata_list_el
;
4422 for (curr_automata_list_el
= automata_list
;
4423 curr_automata_list_el
!= NULL
;
4424 curr_automata_list_el
= next_automata_list_el
)
4426 next_automata_list_el
= curr_automata_list_el
->next_automata_list_el
;
4427 free_automata_list_el (curr_automata_list_el
);
4431 /* Hash value of AUTOMATA_LIST. */
4433 automata_list_hash (const void *automata_list
)
4435 unsigned int hash_value
;
4436 automata_list_el_t curr_automata_list_el
;
4439 for (curr_automata_list_el
= (automata_list_el_t
) automata_list
;
4440 curr_automata_list_el
!= NULL
;
4441 curr_automata_list_el
= curr_automata_list_el
->next_automata_list_el
)
4442 hash_value
= (((hash_value
>> (sizeof (unsigned) - 1) * CHAR_BIT
)
4443 | (hash_value
<< CHAR_BIT
))
4444 + curr_automata_list_el
->automaton
->automaton_order_num
);
4448 /* Return nonzero value if the automata_lists are the same. */
4450 automata_list_eq_p (const void *automata_list_1
, const void *automata_list_2
)
4452 automata_list_el_t automata_list_el_1
;
4453 automata_list_el_t automata_list_el_2
;
4455 for (automata_list_el_1
= (automata_list_el_t
) automata_list_1
,
4456 automata_list_el_2
= (automata_list_el_t
) automata_list_2
;
4457 automata_list_el_1
!= NULL
&& automata_list_el_2
!= NULL
;
4458 automata_list_el_1
= automata_list_el_1
->next_automata_list_el
,
4459 automata_list_el_2
= automata_list_el_2
->next_automata_list_el
)
4460 if (automata_list_el_1
->automaton
!= automata_list_el_2
->automaton
)
4462 return automata_list_el_1
== automata_list_el_2
;
4465 /* Initialization of the abstract data. */
4467 initiate_automata_lists (void)
4469 first_free_automata_list_el
= NULL
;
4470 automata_list_table
= htab_create (1500, automata_list_hash
,
4471 automata_list_eq_p
, (htab_del
) 0);
4474 /* The following function starts new automata list and makes it the
4477 automata_list_start (void)
4479 current_automata_list
= NULL
;
4482 /* The following function adds AUTOMATON to the current list. */
4484 automata_list_add (automaton_t automaton
)
4486 automata_list_el_t el
;
4488 el
= get_free_automata_list_el ();
4489 el
->automaton
= automaton
;
4490 el
->next_automata_list_el
= current_automata_list
;
4491 current_automata_list
= el
;
4494 /* The following function finishes forming the current list, inserts
4495 it into the table and returns it. */
4496 static automata_list_el_t
4497 automata_list_finish (void)
4501 if (current_automata_list
== NULL
)
4503 entry_ptr
= htab_find_slot (automata_list_table
,
4504 (void *) current_automata_list
, 1);
4505 if (*entry_ptr
== NULL
)
4506 *entry_ptr
= (void *) current_automata_list
;
4508 free_automata_list (current_automata_list
);
4509 current_automata_list
= NULL
;
4510 return (automata_list_el_t
) *entry_ptr
;
4513 /* Finishing work with the abstract data. */
4515 finish_automata_lists (void)
4517 htab_delete (automata_list_table
);
4522 /* The page contains abstract data for work with exclusion sets (see
4523 exclusion_set in file rtl.def). */
4525 /* The following variable refers to an exclusion set returned by
4526 get_excl_set. This is bit string of length equal to cpu units
4527 number. If exclusion set for given unit contains 1 for a unit,
4528 then simultaneous reservation of the units is prohibited. */
4529 static reserv_sets_t excl_set
;
4531 /* The array contains exclusion sets for each unit. */
4532 static reserv_sets_t
*unit_excl_set_table
;
4534 /* The following function forms the array containing exclusion sets
4537 initiate_excl_sets (void)
4540 reserv_sets_t unit_excl_set
;
4544 obstack_blank (&irp
, els_in_cycle_reserv
* sizeof (set_el_t
));
4545 excl_set
= (reserv_sets_t
) obstack_base (&irp
);
4546 obstack_finish (&irp
);
4547 obstack_blank (&irp
, description
->units_num
* sizeof (reserv_sets_t
));
4548 unit_excl_set_table
= (reserv_sets_t
*) obstack_base (&irp
);
4549 obstack_finish (&irp
);
4550 /* Evaluate unit exclusion sets. */
4551 for (i
= 0; i
< description
->decls_num
; i
++)
4553 decl
= description
->decls
[i
];
4554 if (decl
->mode
== dm_unit
)
4556 obstack_blank (&irp
, els_in_cycle_reserv
* sizeof (set_el_t
));
4557 unit_excl_set
= (reserv_sets_t
) obstack_base (&irp
);
4558 obstack_finish (&irp
);
4559 memset (unit_excl_set
, 0, els_in_cycle_reserv
* sizeof (set_el_t
));
4560 for (el
= DECL_UNIT (decl
)->excl_list
;
4562 el
= el
->next_unit_set_el
)
4564 SET_BIT (unit_excl_set
, el
->unit_decl
->unit_num
);
4565 el
->unit_decl
->in_set_p
= TRUE
;
4567 unit_excl_set_table
[DECL_UNIT (decl
)->unit_num
] = unit_excl_set
;
4572 /* The function sets up and return EXCL_SET which is union of
4573 exclusion sets for each unit in IN_SET. */
4574 static reserv_sets_t
4575 get_excl_set (reserv_sets_t in_set
)
4583 chars_num
= els_in_cycle_reserv
* sizeof (set_el_t
);
4584 memset (excl_set
, 0, chars_num
);
4585 for (excl_char_num
= 0; excl_char_num
< chars_num
; excl_char_num
++)
4586 if (((unsigned char *) in_set
) [excl_char_num
])
4587 for (i
= CHAR_BIT
- 1; i
>= 0; i
--)
4588 if ((((unsigned char *) in_set
) [excl_char_num
] >> i
) & 1)
4590 start_unit_num
= excl_char_num
* CHAR_BIT
+ i
;
4591 if (start_unit_num
>= description
->units_num
)
4593 for (unit_num
= 0; unit_num
< els_in_cycle_reserv
; unit_num
++)
4596 |= unit_excl_set_table
[start_unit_num
] [unit_num
];
4604 /* The page contains abstract data for work with presence/absence
4605 pattern sets (see presence_set/absence_set in file rtl.def). */
4607 /* The following arrays contain correspondingly presence, final
4608 presence, absence, and final absence patterns for each unit. */
4609 static pattern_reserv_t
*unit_presence_set_table
;
4610 static pattern_reserv_t
*unit_final_presence_set_table
;
4611 static pattern_reserv_t
*unit_absence_set_table
;
4612 static pattern_reserv_t
*unit_final_absence_set_table
;
4614 /* The following function forms list of reservation sets for given
4616 static pattern_reserv_t
4617 form_reserv_sets_list (pattern_set_el_t pattern_list
)
4619 pattern_set_el_t el
;
4620 pattern_reserv_t first
, curr
, prev
;
4623 prev
= first
= NULL
;
4624 for (el
= pattern_list
; el
!= NULL
; el
= el
->next_pattern_set_el
)
4626 curr
= create_node (sizeof (struct pattern_reserv
));
4627 curr
->reserv
= alloc_empty_reserv_sets ();
4628 curr
->next_pattern_reserv
= NULL
;
4629 for (i
= 0; i
< el
->units_num
; i
++)
4631 SET_BIT (curr
->reserv
, el
->unit_decls
[i
]->unit_num
);
4632 el
->unit_decls
[i
]->in_set_p
= TRUE
;
4635 prev
->next_pattern_reserv
= curr
;
4643 /* The following function forms the array containing presence and
4644 absence pattern sets for each unit. */
4646 initiate_presence_absence_pattern_sets (void)
4651 obstack_blank (&irp
, description
->units_num
* sizeof (pattern_reserv_t
));
4652 unit_presence_set_table
= (pattern_reserv_t
*) obstack_base (&irp
);
4653 obstack_finish (&irp
);
4654 obstack_blank (&irp
, description
->units_num
* sizeof (pattern_reserv_t
));
4655 unit_final_presence_set_table
= (pattern_reserv_t
*) obstack_base (&irp
);
4656 obstack_finish (&irp
);
4657 obstack_blank (&irp
, description
->units_num
* sizeof (pattern_reserv_t
));
4658 unit_absence_set_table
= (pattern_reserv_t
*) obstack_base (&irp
);
4659 obstack_finish (&irp
);
4660 obstack_blank (&irp
, description
->units_num
* sizeof (pattern_reserv_t
));
4661 unit_final_absence_set_table
= (pattern_reserv_t
*) obstack_base (&irp
);
4662 obstack_finish (&irp
);
4663 /* Evaluate unit presence/absence sets. */
4664 for (i
= 0; i
< description
->decls_num
; i
++)
4666 decl
= description
->decls
[i
];
4667 if (decl
->mode
== dm_unit
)
4669 unit_presence_set_table
[DECL_UNIT (decl
)->unit_num
]
4670 = form_reserv_sets_list (DECL_UNIT (decl
)->presence_list
);
4671 unit_final_presence_set_table
[DECL_UNIT (decl
)->unit_num
]
4672 = form_reserv_sets_list (DECL_UNIT (decl
)->final_presence_list
);
4673 unit_absence_set_table
[DECL_UNIT (decl
)->unit_num
]
4674 = form_reserv_sets_list (DECL_UNIT (decl
)->absence_list
);
4675 unit_final_absence_set_table
[DECL_UNIT (decl
)->unit_num
]
4676 = form_reserv_sets_list (DECL_UNIT (decl
)->final_absence_list
);
4681 /* The function checks that CHECKED_SET satisfies all presence pattern
4682 sets for units in ORIGIONAL_SET. The function returns TRUE if it
4685 check_presence_pattern_sets (reserv_sets_t checked_set
,
4686 reserv_sets_t origional_set
,
4695 pattern_reserv_t pat_reserv
;
4697 chars_num
= els_in_cycle_reserv
* sizeof (set_el_t
);
4698 for (char_num
= 0; char_num
< chars_num
; char_num
++)
4699 if (((unsigned char *) origional_set
) [char_num
])
4700 for (i
= CHAR_BIT
- 1; i
>= 0; i
--)
4701 if ((((unsigned char *) origional_set
) [char_num
] >> i
) & 1)
4703 start_unit_num
= char_num
* CHAR_BIT
+ i
;
4704 if (start_unit_num
>= description
->units_num
)
4707 && unit_final_presence_set_table
[start_unit_num
] == NULL
)
4709 && unit_presence_set_table
[start_unit_num
] == NULL
))
4712 for (pat_reserv
= (final_p
4713 ? unit_final_presence_set_table
[start_unit_num
]
4714 : unit_presence_set_table
[start_unit_num
]);
4716 pat_reserv
= pat_reserv
->next_pattern_reserv
)
4718 for (unit_num
= 0; unit_num
< els_in_cycle_reserv
; unit_num
++)
4719 if ((checked_set
[unit_num
] & pat_reserv
->reserv
[unit_num
])
4720 != pat_reserv
->reserv
[unit_num
])
4722 presence_p
= presence_p
|| unit_num
>= els_in_cycle_reserv
;
4730 /* The function checks that CHECKED_SET satisfies all absence pattern
4731 sets for units in ORIGIONAL_SET. The function returns TRUE if it
4734 check_absence_pattern_sets (reserv_sets_t checked_set
,
4735 reserv_sets_t origional_set
,
4743 pattern_reserv_t pat_reserv
;
4745 chars_num
= els_in_cycle_reserv
* sizeof (set_el_t
);
4746 for (char_num
= 0; char_num
< chars_num
; char_num
++)
4747 if (((unsigned char *) origional_set
) [char_num
])
4748 for (i
= CHAR_BIT
- 1; i
>= 0; i
--)
4749 if ((((unsigned char *) origional_set
) [char_num
] >> i
) & 1)
4751 start_unit_num
= char_num
* CHAR_BIT
+ i
;
4752 if (start_unit_num
>= description
->units_num
)
4754 for (pat_reserv
= (final_p
4755 ? unit_final_absence_set_table
[start_unit_num
]
4756 : unit_absence_set_table
[start_unit_num
]);
4758 pat_reserv
= pat_reserv
->next_pattern_reserv
)
4760 for (unit_num
= 0; unit_num
< els_in_cycle_reserv
; unit_num
++)
4761 if ((checked_set
[unit_num
] & pat_reserv
->reserv
[unit_num
])
4762 != pat_reserv
->reserv
[unit_num
]
4763 && pat_reserv
->reserv
[unit_num
])
4765 if (unit_num
>= els_in_cycle_reserv
)
4774 /* This page contains code for transformation of original reservations
4775 described in .md file. The main goal of transformations is
4776 simplifying reservation and lifting up all `|' on the top of IR
4777 reservation representation. */
4780 /* The following function makes copy of IR representation of
4781 reservation. The function also substitutes all reservations
4782 defined by define_reservation by corresponding value during making
4785 copy_insn_regexp (regexp_t regexp
)
4790 if (regexp
->mode
== rm_reserv
)
4791 result
= copy_insn_regexp (REGEXP_RESERV (regexp
)->reserv_decl
->regexp
);
4792 else if (regexp
->mode
== rm_unit
)
4793 result
= copy_node (regexp
, sizeof (struct regexp
));
4794 else if (regexp
->mode
== rm_repeat
)
4796 result
= copy_node (regexp
, sizeof (struct regexp
));
4797 REGEXP_REPEAT (result
)->regexp
4798 = copy_insn_regexp (REGEXP_REPEAT (regexp
)->regexp
);
4800 else if (regexp
->mode
== rm_sequence
)
4802 result
= copy_node (regexp
,
4803 sizeof (struct regexp
) + sizeof (regexp_t
)
4804 * (REGEXP_SEQUENCE (regexp
)->regexps_num
- 1));
4805 for (i
= 0; i
<REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
4806 REGEXP_SEQUENCE (result
)->regexps
[i
]
4807 = copy_insn_regexp (REGEXP_SEQUENCE (regexp
)->regexps
[i
]);
4809 else if (regexp
->mode
== rm_allof
)
4811 result
= copy_node (regexp
,
4812 sizeof (struct regexp
) + sizeof (regexp_t
)
4813 * (REGEXP_ALLOF (regexp
)->regexps_num
- 1));
4814 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
4815 REGEXP_ALLOF (result
)->regexps
[i
]
4816 = copy_insn_regexp (REGEXP_ALLOF (regexp
)->regexps
[i
]);
4818 else if (regexp
->mode
== rm_oneof
)
4820 result
= copy_node (regexp
,
4821 sizeof (struct regexp
) + sizeof (regexp_t
)
4822 * (REGEXP_ONEOF (regexp
)->regexps_num
- 1));
4823 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
4824 REGEXP_ONEOF (result
)->regexps
[i
]
4825 = copy_insn_regexp (REGEXP_ONEOF (regexp
)->regexps
[i
]);
4829 if (regexp
->mode
!= rm_nothing
)
4831 result
= copy_node (regexp
, sizeof (struct regexp
));
4836 /* The following variable is set up 1 if a transformation has been
4838 static int regexp_transformed_p
;
4840 /* The function makes transformation
4843 transform_1 (regexp_t regexp
)
4850 if (regexp
->mode
== rm_repeat
)
4852 repeat_num
= REGEXP_REPEAT (regexp
)->repeat_num
;
4853 if (repeat_num
<= 1)
4855 operand
= REGEXP_REPEAT (regexp
)->regexp
;
4857 regexp
= create_node (sizeof (struct regexp
) + sizeof (regexp_t
)
4858 * (repeat_num
- 1));
4859 regexp
->mode
= rm_sequence
;
4861 REGEXP_SEQUENCE (regexp
)->regexps_num
= repeat_num
;
4862 for (i
= 0; i
< repeat_num
; i
++)
4863 REGEXP_SEQUENCE (regexp
)->regexps
[i
] = copy_insn_regexp (operand
);
4864 regexp_transformed_p
= 1;
4869 /* The function makes transformations
4870 ...,(A,B,...),C,... -> ...,A,B,...,C,...
4871 ...+(A+B+...)+C+... -> ...+A+B+...+C+...
4872 ...|(A|B|...)|C|... -> ...|A|B|...|C|... */
4874 transform_2 (regexp_t regexp
)
4876 if (regexp
->mode
== rm_sequence
)
4878 regexp_t sequence
= NULL
;
4880 int sequence_index
= 0;
4883 for (i
= 0; i
< REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
4884 if (REGEXP_SEQUENCE (regexp
)->regexps
[i
]->mode
== rm_sequence
)
4887 sequence
= REGEXP_SEQUENCE (regexp
)->regexps
[i
];
4890 if (i
< REGEXP_SEQUENCE (regexp
)->regexps_num
)
4892 if ( REGEXP_SEQUENCE (sequence
)->regexps_num
<= 1
4893 || REGEXP_SEQUENCE (regexp
)->regexps_num
<= 1)
4895 result
= create_node (sizeof (struct regexp
)
4897 * (REGEXP_SEQUENCE (regexp
)->regexps_num
4898 + REGEXP_SEQUENCE (sequence
)->regexps_num
4900 result
->mode
= rm_sequence
;
4901 result
->pos
= regexp
->pos
;
4902 REGEXP_SEQUENCE (result
)->regexps_num
4903 = (REGEXP_SEQUENCE (regexp
)->regexps_num
4904 + REGEXP_SEQUENCE (sequence
)->regexps_num
- 1);
4905 for (i
= 0; i
< REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
4906 if (i
< sequence_index
)
4907 REGEXP_SEQUENCE (result
)->regexps
[i
]
4908 = copy_insn_regexp (REGEXP_SEQUENCE (regexp
)->regexps
[i
]);
4909 else if (i
> sequence_index
)
4910 REGEXP_SEQUENCE (result
)->regexps
4911 [i
+ REGEXP_SEQUENCE (sequence
)->regexps_num
- 1]
4912 = copy_insn_regexp (REGEXP_SEQUENCE (regexp
)->regexps
[i
]);
4914 for (j
= 0; j
< REGEXP_SEQUENCE (sequence
)->regexps_num
; j
++)
4915 REGEXP_SEQUENCE (result
)->regexps
[i
+ j
]
4916 = copy_insn_regexp (REGEXP_SEQUENCE (sequence
)->regexps
[j
]);
4917 regexp_transformed_p
= 1;
4921 else if (regexp
->mode
== rm_allof
)
4923 regexp_t allof
= NULL
;
4925 int allof_index
= 0;
4928 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
4929 if (REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
== rm_allof
)
4932 allof
= REGEXP_ALLOF (regexp
)->regexps
[i
];
4935 if (i
< REGEXP_ALLOF (regexp
)->regexps_num
)
4937 if (REGEXP_ALLOF (allof
)->regexps_num
<= 1
4938 || REGEXP_ALLOF (regexp
)->regexps_num
<= 1)
4940 result
= create_node (sizeof (struct regexp
)
4942 * (REGEXP_ALLOF (regexp
)->regexps_num
4943 + REGEXP_ALLOF (allof
)->regexps_num
- 2));
4944 result
->mode
= rm_allof
;
4945 result
->pos
= regexp
->pos
;
4946 REGEXP_ALLOF (result
)->regexps_num
4947 = (REGEXP_ALLOF (regexp
)->regexps_num
4948 + REGEXP_ALLOF (allof
)->regexps_num
- 1);
4949 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
4950 if (i
< allof_index
)
4951 REGEXP_ALLOF (result
)->regexps
[i
]
4952 = copy_insn_regexp (REGEXP_ALLOF (regexp
)->regexps
[i
]);
4953 else if (i
> allof_index
)
4954 REGEXP_ALLOF (result
)->regexps
4955 [i
+ REGEXP_ALLOF (allof
)->regexps_num
- 1]
4956 = copy_insn_regexp (REGEXP_ALLOF (regexp
)->regexps
[i
]);
4958 for (j
= 0; j
< REGEXP_ALLOF (allof
)->regexps_num
; j
++)
4959 REGEXP_ALLOF (result
)->regexps
[i
+ j
]
4960 = copy_insn_regexp (REGEXP_ALLOF (allof
)->regexps
[j
]);
4961 regexp_transformed_p
= 1;
4965 else if (regexp
->mode
== rm_oneof
)
4967 regexp_t oneof
= NULL
;
4969 int oneof_index
= 0;
4972 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
4973 if (REGEXP_ONEOF (regexp
)->regexps
[i
]->mode
== rm_oneof
)
4976 oneof
= REGEXP_ONEOF (regexp
)->regexps
[i
];
4979 if (i
< REGEXP_ONEOF (regexp
)->regexps_num
)
4981 if (REGEXP_ONEOF (oneof
)->regexps_num
<= 1
4982 || REGEXP_ONEOF (regexp
)->regexps_num
<= 1)
4984 result
= create_node (sizeof (struct regexp
)
4986 * (REGEXP_ONEOF (regexp
)->regexps_num
4987 + REGEXP_ONEOF (oneof
)->regexps_num
- 2));
4988 result
->mode
= rm_oneof
;
4989 result
->pos
= regexp
->pos
;
4990 REGEXP_ONEOF (result
)->regexps_num
4991 = (REGEXP_ONEOF (regexp
)->regexps_num
4992 + REGEXP_ONEOF (oneof
)->regexps_num
- 1);
4993 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
4994 if (i
< oneof_index
)
4995 REGEXP_ONEOF (result
)->regexps
[i
]
4996 = copy_insn_regexp (REGEXP_ONEOF (regexp
)->regexps
[i
]);
4997 else if (i
> oneof_index
)
4998 REGEXP_ONEOF (result
)->regexps
4999 [i
+ REGEXP_ONEOF (oneof
)->regexps_num
- 1]
5000 = copy_insn_regexp (REGEXP_ONEOF (regexp
)->regexps
[i
]);
5002 for (j
= 0; j
< REGEXP_ONEOF (oneof
)->regexps_num
; j
++)
5003 REGEXP_ONEOF (result
)->regexps
[i
+ j
]
5004 = copy_insn_regexp (REGEXP_ONEOF (oneof
)->regexps
[j
]);
5005 regexp_transformed_p
= 1;
5012 /* The function makes transformations
5013 ...,A|B|...,C,... -> (...,A,C,...)|(...,B,C,...)|...
5014 ...+(A|B|...)+C+... -> (...+A+C+...)|(...+B+C+...)|...
5015 ...+(A,B,...)+C+... -> (...+A+C+...),B,...
5016 ...+(A,B,...)+(C,D,...) -> (A+C),(B+D),... */
5018 transform_3 (regexp_t regexp
)
5020 if (regexp
->mode
== rm_sequence
)
5022 regexp_t oneof
= NULL
;
5023 int oneof_index
= 0;
5028 for (i
= 0; i
<REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
5029 if (REGEXP_SEQUENCE (regexp
)->regexps
[i
]->mode
== rm_oneof
)
5032 oneof
= REGEXP_SEQUENCE (regexp
)->regexps
[i
];
5035 if (i
< REGEXP_SEQUENCE (regexp
)->regexps_num
)
5037 if (REGEXP_ONEOF (oneof
)->regexps_num
<= 1
5038 || REGEXP_SEQUENCE (regexp
)->regexps_num
<= 1)
5040 result
= create_node (sizeof (struct regexp
)
5042 * (REGEXP_ONEOF (oneof
)->regexps_num
- 1));
5043 result
->mode
= rm_oneof
;
5044 result
->pos
= regexp
->pos
;
5045 REGEXP_ONEOF (result
)->regexps_num
5046 = REGEXP_ONEOF (oneof
)->regexps_num
;
5047 for (i
= 0; i
< REGEXP_ONEOF (result
)->regexps_num
; i
++)
5050 = create_node (sizeof (struct regexp
)
5052 * (REGEXP_SEQUENCE (regexp
)->regexps_num
- 1));
5053 sequence
->mode
= rm_sequence
;
5054 sequence
->pos
= regexp
->pos
;
5055 REGEXP_SEQUENCE (sequence
)->regexps_num
5056 = REGEXP_SEQUENCE (regexp
)->regexps_num
;
5057 REGEXP_ONEOF (result
)->regexps
[i
] = sequence
;
5058 for (j
= 0; j
< REGEXP_SEQUENCE (sequence
)->regexps_num
; j
++)
5059 if (j
!= oneof_index
)
5060 REGEXP_SEQUENCE (sequence
)->regexps
[j
]
5061 = copy_insn_regexp (REGEXP_SEQUENCE (regexp
)->regexps
[j
]);
5063 REGEXP_SEQUENCE (sequence
)->regexps
[j
]
5064 = copy_insn_regexp (REGEXP_ONEOF (oneof
)->regexps
[i
]);
5066 regexp_transformed_p
= 1;
5070 else if (regexp
->mode
== rm_allof
)
5072 regexp_t oneof
= NULL
;
5074 int oneof_index
= 0;
5075 int max_seq_length
, allof_length
;
5077 regexp_t allof
= NULL
;
5078 regexp_t allof_op
= NULL
;
5081 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
5082 if (REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
== rm_oneof
)
5085 oneof
= REGEXP_ALLOF (regexp
)->regexps
[i
];
5088 if (i
< REGEXP_ALLOF (regexp
)->regexps_num
)
5090 if (REGEXP_ONEOF (oneof
)->regexps_num
<= 1
5091 || REGEXP_ALLOF (regexp
)->regexps_num
<= 1)
5093 result
= create_node (sizeof (struct regexp
)
5095 * (REGEXP_ONEOF (oneof
)->regexps_num
- 1));
5096 result
->mode
= rm_oneof
;
5097 result
->pos
= regexp
->pos
;
5098 REGEXP_ONEOF (result
)->regexps_num
5099 = REGEXP_ONEOF (oneof
)->regexps_num
;
5100 for (i
= 0; i
< REGEXP_ONEOF (result
)->regexps_num
; i
++)
5103 = create_node (sizeof (struct regexp
)
5105 * (REGEXP_ALLOF (regexp
)->regexps_num
- 1));
5106 allof
->mode
= rm_allof
;
5107 allof
->pos
= regexp
->pos
;
5108 REGEXP_ALLOF (allof
)->regexps_num
5109 = REGEXP_ALLOF (regexp
)->regexps_num
;
5110 REGEXP_ONEOF (result
)->regexps
[i
] = allof
;
5111 for (j
= 0; j
< REGEXP_ALLOF (allof
)->regexps_num
; j
++)
5112 if (j
!= oneof_index
)
5113 REGEXP_ALLOF (allof
)->regexps
[j
]
5114 = copy_insn_regexp (REGEXP_ALLOF (regexp
)->regexps
[j
]);
5116 REGEXP_ALLOF (allof
)->regexps
[j
]
5117 = copy_insn_regexp (REGEXP_ONEOF (oneof
)->regexps
[i
]);
5119 regexp_transformed_p
= 1;
5123 if (regexp
->mode
== rm_allof
)
5124 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
5126 if (REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
== rm_sequence
)
5128 seq
= REGEXP_ALLOF (regexp
)->regexps
[i
];
5129 if (max_seq_length
< REGEXP_SEQUENCE (seq
)->regexps_num
)
5130 max_seq_length
= REGEXP_SEQUENCE (seq
)->regexps_num
;
5132 else if (REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
!= rm_unit
5133 && REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
!= rm_nothing
)
5139 if (max_seq_length
!= 0)
5141 if (max_seq_length
== 1 || REGEXP_ALLOF (regexp
)->regexps_num
<= 1)
5143 result
= create_node (sizeof (struct regexp
)
5144 + sizeof (regexp_t
) * (max_seq_length
- 1));
5145 result
->mode
= rm_sequence
;
5146 result
->pos
= regexp
->pos
;
5147 REGEXP_SEQUENCE (result
)->regexps_num
= max_seq_length
;
5148 for (i
= 0; i
< max_seq_length
; i
++)
5151 for (j
= 0; j
< REGEXP_ALLOF (regexp
)->regexps_num
; j
++)
5152 if (REGEXP_ALLOF (regexp
)->regexps
[j
]->mode
== rm_sequence
5153 && (i
< (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp
)
5154 ->regexps
[j
])->regexps_num
)))
5157 = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp
)->regexps
[j
])
5162 && (REGEXP_ALLOF (regexp
)->regexps
[j
]->mode
5164 || (REGEXP_ALLOF (regexp
)->regexps
[j
]->mode
5167 allof_op
= REGEXP_ALLOF (regexp
)->regexps
[j
];
5170 if (allof_length
== 1)
5171 REGEXP_SEQUENCE (result
)->regexps
[i
] = allof_op
;
5174 allof
= create_node (sizeof (struct regexp
)
5176 * (allof_length
- 1));
5177 allof
->mode
= rm_allof
;
5178 allof
->pos
= regexp
->pos
;
5179 REGEXP_ALLOF (allof
)->regexps_num
= allof_length
;
5180 REGEXP_SEQUENCE (result
)->regexps
[i
] = allof
;
5182 for (j
= 0; j
< REGEXP_ALLOF (regexp
)->regexps_num
; j
++)
5183 if (REGEXP_ALLOF (regexp
)->regexps
[j
]->mode
== rm_sequence
5185 (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp
)
5186 ->regexps
[j
])->regexps_num
)))
5188 allof_op
= (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp
)
5191 REGEXP_ALLOF (allof
)->regexps
[allof_length
]
5196 && (REGEXP_ALLOF (regexp
)->regexps
[j
]->mode
5198 || (REGEXP_ALLOF (regexp
)->regexps
[j
]->mode
5201 allof_op
= REGEXP_ALLOF (regexp
)->regexps
[j
];
5202 REGEXP_ALLOF (allof
)->regexps
[allof_length
]
5208 regexp_transformed_p
= 1;
5215 /* The function traverses IR of reservation and applies transformations
5216 implemented by FUNC. */
5218 regexp_transform_func (regexp_t regexp
, regexp_t (*func
) (regexp_t regexp
))
5222 if (regexp
->mode
== rm_sequence
)
5223 for (i
= 0; i
< REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
5224 REGEXP_SEQUENCE (regexp
)->regexps
[i
]
5225 = regexp_transform_func (REGEXP_SEQUENCE (regexp
)->regexps
[i
], func
);
5226 else if (regexp
->mode
== rm_allof
)
5227 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
5228 REGEXP_ALLOF (regexp
)->regexps
[i
]
5229 = regexp_transform_func (REGEXP_ALLOF (regexp
)->regexps
[i
], func
);
5230 else if (regexp
->mode
== rm_oneof
)
5231 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
5232 REGEXP_ONEOF (regexp
)->regexps
[i
]
5233 = regexp_transform_func (REGEXP_ONEOF (regexp
)->regexps
[i
], func
);
5234 else if (regexp
->mode
== rm_repeat
)
5235 REGEXP_REPEAT (regexp
)->regexp
5236 = regexp_transform_func (REGEXP_REPEAT (regexp
)->regexp
, func
);
5237 else if (regexp
->mode
!= rm_nothing
&& regexp
->mode
!= rm_unit
)
5239 return (*func
) (regexp
);
5242 /* The function applies all transformations for IR representation of
5243 reservation REGEXP. */
5245 transform_regexp (regexp_t regexp
)
5247 regexp
= regexp_transform_func (regexp
, transform_1
);
5250 regexp_transformed_p
= 0;
5251 regexp
= regexp_transform_func (regexp
, transform_2
);
5252 regexp
= regexp_transform_func (regexp
, transform_3
);
5254 while (regexp_transformed_p
);
5258 /* The function applies all transformations for reservations of all
5259 insn declarations. */
5261 transform_insn_regexps (void)
5266 transform_time
= create_ticker ();
5267 add_advance_cycle_insn_decl ();
5268 fprintf (stderr
, "Reservation transformation...");
5270 for (i
= 0; i
< description
->decls_num
; i
++)
5272 decl
= description
->decls
[i
];
5273 if (decl
->mode
== dm_insn_reserv
&& decl
!= advance_cycle_insn_decl
)
5274 DECL_INSN_RESERV (decl
)->transformed_regexp
5275 = transform_regexp (copy_insn_regexp
5276 (DECL_INSN_RESERV (decl
)->regexp
));
5278 fprintf (stderr
, "done\n");
5279 ticker_off (&transform_time
);
5285 /* The following variable value is TRUE if the first annotated message
5286 about units to automata distribution has been output. */
5287 static int annotation_message_reported_p
;
5289 /* The following structure describes usage of a unit in a reservation. */
5292 unit_decl_t unit_decl
;
5293 /* The following forms a list of units used on the same cycle in the
5294 same alternative. */
5295 struct unit_usage
*next
;
5298 /* Obstack for unit_usage structures. */
5299 static struct obstack unit_usages
;
5301 /* VLA for representation of array of pointers to unit usage
5302 structures. There is an element for each combination of
5303 (alternative number, cycle). Unit usages on given cycle in
5304 alternative with given number are referred through element with
5305 index equals to the cycle * number of all alternatives in the regexp
5306 + the alternative number. */
5307 static vla_ptr_t cycle_alt_unit_usages
;
5309 /* The following function creates the structure unit_usage for UNIT on
5310 CYCLE in REGEXP alternative with ALT_NUM. The structure is made
5311 accessed through cycle_alt_unit_usages. */
5313 store_alt_unit_usage (regexp_t regexp
, regexp_t unit
, int cycle
,
5316 size_t i
, length
, old_length
;
5317 unit_decl_t unit_decl
;
5318 struct unit_usage
*unit_usage_ptr
;
5321 if (regexp
== NULL
|| regexp
->mode
!= rm_oneof
5322 || alt_num
>= REGEXP_ONEOF (regexp
)->regexps_num
)
5324 unit_decl
= REGEXP_UNIT (unit
)->unit_decl
;
5325 old_length
= VLA_PTR_LENGTH (cycle_alt_unit_usages
);
5326 length
= (cycle
+ 1) * REGEXP_ONEOF (regexp
)->regexps_num
;
5327 if (old_length
< length
)
5329 VLA_PTR_EXPAND (cycle_alt_unit_usages
, length
- old_length
);
5330 for (i
= old_length
; i
< length
; i
++)
5331 VLA_PTR (cycle_alt_unit_usages
, i
) = NULL
;
5333 obstack_blank (&unit_usages
, sizeof (struct unit_usage
));
5334 unit_usage_ptr
= (struct unit_usage
*) obstack_base (&unit_usages
);
5335 obstack_finish (&unit_usages
);
5336 unit_usage_ptr
->unit_decl
= unit_decl
;
5337 index
= cycle
* REGEXP_ONEOF (regexp
)->regexps_num
+ alt_num
;
5338 unit_usage_ptr
->next
= VLA_PTR (cycle_alt_unit_usages
, index
);
5339 VLA_PTR (cycle_alt_unit_usages
, index
) = unit_usage_ptr
;
5340 unit_decl
->last_distribution_check_cycle
= -1; /* undefined */
5343 /* The function processes given REGEXP to find units with the wrong
5346 check_regexp_units_distribution (const char *insn_reserv_name
,
5350 regexp_t seq
, allof
, unit
;
5351 struct unit_usage
*unit_usage_ptr
, *other_unit_usage_ptr
;
5353 if (regexp
== NULL
|| regexp
->mode
!= rm_oneof
)
5355 /* Store all unit usages in the regexp: */
5356 obstack_init (&unit_usages
);
5357 VLA_PTR_CREATE (cycle_alt_unit_usages
, 100, "unit usages on cycles");
5358 for (i
= REGEXP_ONEOF (regexp
)->regexps_num
- 1; i
>= 0; i
--)
5360 seq
= REGEXP_ONEOF (regexp
)->regexps
[i
];
5361 if (seq
->mode
== rm_sequence
)
5362 for (j
= 0; j
< REGEXP_SEQUENCE (seq
)->regexps_num
; j
++)
5364 allof
= REGEXP_SEQUENCE (seq
)->regexps
[j
];
5365 if (allof
->mode
== rm_allof
)
5366 for (k
= 0; k
< REGEXP_ALLOF (allof
)->regexps_num
; k
++)
5368 unit
= REGEXP_ALLOF (allof
)->regexps
[k
];
5369 if (unit
->mode
== rm_unit
)
5370 store_alt_unit_usage (regexp
, unit
, j
, i
);
5371 else if (unit
->mode
!= rm_nothing
)
5374 else if (allof
->mode
== rm_unit
)
5375 store_alt_unit_usage (regexp
, allof
, j
, i
);
5376 else if (allof
->mode
!= rm_nothing
)
5379 else if (seq
->mode
== rm_allof
)
5380 for (k
= 0; k
< REGEXP_ALLOF (seq
)->regexps_num
; k
++)
5382 unit
= REGEXP_ALLOF (seq
)->regexps
[k
];
5383 if (unit
->mode
== rm_unit
)
5384 store_alt_unit_usage (regexp
, unit
, 0, i
);
5385 else if (unit
->mode
!= rm_nothing
)
5388 else if (seq
->mode
== rm_unit
)
5389 store_alt_unit_usage (regexp
, seq
, 0, i
);
5390 else if (seq
->mode
!= rm_nothing
)
5393 /* Check distribution: */
5394 for (i
= 0; i
< (int) VLA_PTR_LENGTH (cycle_alt_unit_usages
); i
++)
5396 cycle
= i
/ REGEXP_ONEOF (regexp
)->regexps_num
;
5397 for (unit_usage_ptr
= VLA_PTR (cycle_alt_unit_usages
, i
);
5398 unit_usage_ptr
!= NULL
;
5399 unit_usage_ptr
= unit_usage_ptr
->next
)
5400 if (cycle
!= unit_usage_ptr
->unit_decl
->last_distribution_check_cycle
)
5402 unit_usage_ptr
->unit_decl
->last_distribution_check_cycle
= cycle
;
5403 for (k
= cycle
* REGEXP_ONEOF (regexp
)->regexps_num
;
5404 k
< (int) VLA_PTR_LENGTH (cycle_alt_unit_usages
)
5405 && k
== cycle
* REGEXP_ONEOF (regexp
)->regexps_num
;
5408 for (other_unit_usage_ptr
= VLA_PTR (cycle_alt_unit_usages
, k
);
5409 other_unit_usage_ptr
!= NULL
;
5410 other_unit_usage_ptr
= other_unit_usage_ptr
->next
)
5411 if (unit_usage_ptr
->unit_decl
->automaton_decl
5412 == other_unit_usage_ptr
->unit_decl
->automaton_decl
)
5414 if (other_unit_usage_ptr
== NULL
5415 && VLA_PTR (cycle_alt_unit_usages
, k
) != NULL
)
5418 if (k
< (int) VLA_PTR_LENGTH (cycle_alt_unit_usages
)
5419 && k
== cycle
* REGEXP_ONEOF (regexp
)->regexps_num
)
5421 if (!annotation_message_reported_p
)
5423 fprintf (stderr
, "\n");
5424 error ("The following units do not satisfy units-automata distribution rule");
5425 error (" (A unit of given unit automaton should be on each reserv. altern.)");
5426 annotation_message_reported_p
= TRUE
;
5428 error ("Unit %s, reserv. %s, cycle %d",
5429 unit_usage_ptr
->unit_decl
->name
, insn_reserv_name
,
5434 VLA_PTR_DELETE (cycle_alt_unit_usages
);
5435 obstack_free (&unit_usages
, NULL
);
5438 /* The function finds units which violates units to automata
5439 distribution rule. If the units exist, report about them. */
5441 check_unit_distributions_to_automata (void)
5446 fprintf (stderr
, "Check unit distributions to automata...");
5447 annotation_message_reported_p
= FALSE
;
5448 for (i
= 0; i
< description
->decls_num
; i
++)
5450 decl
= description
->decls
[i
];
5451 if (decl
->mode
== dm_insn_reserv
)
5452 check_regexp_units_distribution
5453 (DECL_INSN_RESERV (decl
)->name
,
5454 DECL_INSN_RESERV (decl
)->transformed_regexp
);
5456 fprintf (stderr
, "done\n");
5461 /* The page contains code for building alt_states (see comments for
5462 IR) describing all possible insns reservations of an automaton. */
5464 /* Current state being formed for which the current alt_state
5466 static state_t state_being_formed
;
5468 /* Current alt_state being formed. */
5469 static alt_state_t alt_state_being_formed
;
5471 /* This recursive function processes `,' and units in reservation
5472 REGEXP for forming alt_states of AUTOMATON. It is believed that
5473 CURR_CYCLE is start cycle of all reservation REGEXP. */
5475 process_seq_for_forming_states (regexp_t regexp
, automaton_t automaton
,
5482 else if (regexp
->mode
== rm_unit
)
5484 if (REGEXP_UNIT (regexp
)->unit_decl
->corresponding_automaton_num
5485 == automaton
->automaton_order_num
)
5486 set_state_reserv (state_being_formed
, curr_cycle
,
5487 REGEXP_UNIT (regexp
)->unit_decl
->unit_num
);
5490 else if (regexp
->mode
== rm_sequence
)
5492 for (i
= 0; i
< REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
5494 = process_seq_for_forming_states
5495 (REGEXP_SEQUENCE (regexp
)->regexps
[i
], automaton
, curr_cycle
) + 1;
5498 else if (regexp
->mode
== rm_allof
)
5500 int finish_cycle
= 0;
5503 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
5505 cycle
= process_seq_for_forming_states (REGEXP_ALLOF (regexp
)
5507 automaton
, curr_cycle
);
5508 if (finish_cycle
< cycle
)
5509 finish_cycle
= cycle
;
5511 return finish_cycle
;
5515 if (regexp
->mode
!= rm_nothing
)
5521 /* This recursive function finishes forming ALT_STATE of AUTOMATON and
5522 inserts alt_state into the table. */
5524 finish_forming_alt_state (alt_state_t alt_state
,
5525 automaton_t automaton ATTRIBUTE_UNUSED
)
5527 state_t state_in_table
;
5528 state_t corresponding_state
;
5530 corresponding_state
= alt_state
->state
;
5531 state_in_table
= insert_state (corresponding_state
);
5532 if (state_in_table
!= corresponding_state
)
5534 free_state (corresponding_state
);
5535 alt_state
->state
= state_in_table
;
5539 /* The following variable value is current automaton insn for whose
5540 reservation the alt states are created. */
5541 static ainsn_t curr_ainsn
;
5543 /* This recursive function processes `|' in reservation REGEXP for
5544 forming alt_states of AUTOMATON. List of the alt states should
5545 have the same order as in the description. */
5547 process_alts_for_forming_states (regexp_t regexp
, automaton_t automaton
,
5552 if (regexp
->mode
!= rm_oneof
)
5554 alt_state_being_formed
= get_free_alt_state ();
5555 state_being_formed
= get_free_state (1, automaton
);
5556 alt_state_being_formed
->state
= state_being_formed
;
5557 /* We inserts in reverse order but we process alternatives also
5558 in reverse order. So we have the same order of alternative
5559 as in the description. */
5560 alt_state_being_formed
->next_alt_state
= curr_ainsn
->alt_states
;
5561 curr_ainsn
->alt_states
= alt_state_being_formed
;
5562 (void) process_seq_for_forming_states (regexp
, automaton
, 0);
5563 finish_forming_alt_state (alt_state_being_formed
, automaton
);
5569 /* We processes it in reverse order to get list with the same
5570 order as in the description. See also the previous
5572 for (i
= REGEXP_ONEOF (regexp
)->regexps_num
- 1; i
>= 0; i
--)
5573 process_alts_for_forming_states (REGEXP_ONEOF (regexp
)->regexps
[i
],
5578 /* Create nodes alt_state for all AUTOMATON insns. */
5580 create_alt_states (automaton_t automaton
)
5582 struct insn_reserv_decl
*reserv_decl
;
5584 for (curr_ainsn
= automaton
->ainsn_list
;
5586 curr_ainsn
= curr_ainsn
->next_ainsn
)
5588 reserv_decl
= curr_ainsn
->insn_reserv_decl
;
5589 if (reserv_decl
!= DECL_INSN_RESERV (advance_cycle_insn_decl
))
5591 curr_ainsn
->alt_states
= NULL
;
5592 process_alts_for_forming_states (reserv_decl
->transformed_regexp
,
5594 curr_ainsn
->sorted_alt_states
5595 = uniq_sort_alt_states (curr_ainsn
->alt_states
);
5602 /* The page contains major code for building DFA(s) for fast pipeline
5603 hazards recognition. */
5605 /* The function forms list of ainsns of AUTOMATON with the same
5608 form_ainsn_with_same_reservs (automaton_t automaton
)
5612 vla_ptr_t first_insns
;
5613 vla_ptr_t last_insns
;
5615 VLA_PTR_CREATE (first_insns
, 150, "first insns with the same reservs");
5616 VLA_PTR_CREATE (last_insns
, 150, "last insns with the same reservs");
5617 for (curr_ainsn
= automaton
->ainsn_list
;
5619 curr_ainsn
= curr_ainsn
->next_ainsn
)
5620 if (curr_ainsn
->insn_reserv_decl
5621 == DECL_INSN_RESERV (advance_cycle_insn_decl
))
5623 curr_ainsn
->next_same_reservs_insn
= NULL
;
5624 curr_ainsn
->first_insn_with_same_reservs
= 1;
5628 for (i
= 0; i
< VLA_PTR_LENGTH (first_insns
); i
++)
5630 (curr_ainsn
->sorted_alt_states
,
5631 ((ainsn_t
) VLA_PTR (first_insns
, i
))->sorted_alt_states
))
5633 curr_ainsn
->next_same_reservs_insn
= NULL
;
5634 if (i
< VLA_PTR_LENGTH (first_insns
))
5636 curr_ainsn
->first_insn_with_same_reservs
= 0;
5637 ((ainsn_t
) VLA_PTR (last_insns
, i
))->next_same_reservs_insn
5639 VLA_PTR (last_insns
, i
) = curr_ainsn
;
5643 VLA_PTR_ADD (first_insns
, curr_ainsn
);
5644 VLA_PTR_ADD (last_insns
, curr_ainsn
);
5645 curr_ainsn
->first_insn_with_same_reservs
= 1;
5648 VLA_PTR_DELETE (first_insns
);
5649 VLA_PTR_DELETE (last_insns
);
5652 /* Forming unit reservations which can affect creating the automaton
5653 states achieved from a given state. It permits to build smaller
5654 automata in many cases. We would have the same automata after
5655 the minimization without such optimization, but the automaton
5656 right after the building could be huge. So in other words, usage
5657 of reservs_matter means some minimization during building the
5659 static reserv_sets_t
5660 form_reservs_matter (automaton_t automaton
)
5663 reserv_sets_t reservs_matter
= alloc_empty_reserv_sets();
5665 for (cycle
= 0; cycle
< max_cycles_num
; cycle
++)
5666 for (unit
= 0; unit
< description
->units_num
; unit
++)
5667 if (units_array
[unit
]->automaton_decl
5668 == automaton
->corresponding_automaton_decl
5669 && (cycle
>= units_array
[unit
]->min_occ_cycle_num
5670 /* We can not remove queried unit from reservations. */
5671 || units_array
[unit
]->query_p
5672 /* We can not remove units which are used
5673 `exclusion_set', `presence_set',
5674 `final_presence_set', `absence_set', and
5675 `final_absence_set'. */
5676 || units_array
[unit
]->in_set_p
))
5677 set_unit_reserv (reservs_matter
, cycle
, unit
);
5678 return reservs_matter
;
5681 /* The following function creates all states of nondeterministic (if
5682 NDFA_FLAG has nonzero value) or deterministic AUTOMATON. */
5684 make_automaton (automaton_t automaton
)
5687 struct insn_reserv_decl
*insn_reserv_decl
;
5688 alt_state_t alt_state
;
5690 state_t start_state
;
5692 ainsn_t advance_cycle_ainsn
;
5694 vla_ptr_t state_stack
;
5696 reserv_sets_t reservs_matter
= form_reservs_matter (automaton
);
5698 VLA_PTR_CREATE (state_stack
, 150, "state stack");
5699 /* Create the start state (empty state). */
5700 start_state
= insert_state (get_free_state (1, automaton
));
5701 automaton
->start_state
= start_state
;
5702 start_state
->it_was_placed_in_stack_for_NDFA_forming
= 1;
5703 VLA_PTR_ADD (state_stack
, start_state
);
5705 while (VLA_PTR_LENGTH (state_stack
) != 0)
5707 state
= VLA_PTR (state_stack
, VLA_PTR_LENGTH (state_stack
) - 1);
5708 VLA_PTR_SHORTEN (state_stack
, 1);
5709 advance_cycle_ainsn
= NULL
;
5710 for (ainsn
= automaton
->ainsn_list
;
5712 ainsn
= ainsn
->next_ainsn
)
5713 if (ainsn
->first_insn_with_same_reservs
)
5715 insn_reserv_decl
= ainsn
->insn_reserv_decl
;
5716 if (insn_reserv_decl
!= DECL_INSN_RESERV (advance_cycle_insn_decl
))
5718 /* We process alt_states in the same order as they are
5719 present in the description. */
5721 for (alt_state
= ainsn
->alt_states
;
5723 alt_state
= alt_state
->next_alt_state
)
5725 state2
= alt_state
->state
;
5726 if (!intersected_state_reservs_p (state
, state2
))
5728 state2
= states_union (state
, state2
, reservs_matter
);
5729 if (!state2
->it_was_placed_in_stack_for_NDFA_forming
)
5731 state2
->it_was_placed_in_stack_for_NDFA_forming
5733 VLA_PTR_ADD (state_stack
, state2
);
5735 if (states_n
% 100 == 0)
5736 fprintf (stderr
, "*");
5738 added_arc
= add_arc (state
, state2
, ainsn
, 1);
5743 if (!ndfa_flag
&& added_arc
!= NULL
)
5745 added_arc
->state_alts
= 0;
5746 for (alt_state
= ainsn
->alt_states
;
5748 alt_state
= alt_state
->next_alt_state
)
5750 state2
= alt_state
->state
;
5751 if (!intersected_state_reservs_p (state
, state2
))
5752 added_arc
->state_alts
++;
5757 advance_cycle_ainsn
= ainsn
;
5759 /* Add transition to advance cycle. */
5760 state2
= state_shift (state
, reservs_matter
);
5761 if (!state2
->it_was_placed_in_stack_for_NDFA_forming
)
5763 state2
->it_was_placed_in_stack_for_NDFA_forming
= 1;
5764 VLA_PTR_ADD (state_stack
, state2
);
5766 if (states_n
% 100 == 0)
5767 fprintf (stderr
, "*");
5769 if (advance_cycle_ainsn
== NULL
)
5771 add_arc (state
, state2
, advance_cycle_ainsn
, 1);
5773 VLA_PTR_DELETE (state_stack
);
5776 /* Foms lists of all arcs of STATE marked by the same ainsn. */
5778 form_arcs_marked_by_insn (state_t state
)
5784 for (i
= 0; i
< description
->decls_num
; i
++)
5786 decl
= description
->decls
[i
];
5787 if (decl
->mode
== dm_insn_reserv
)
5788 DECL_INSN_RESERV (decl
)->arcs_marked_by_insn
= NULL
;
5790 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
5792 if (arc
->insn
== NULL
)
5794 arc
->next_arc_marked_by_insn
5795 = arc
->insn
->insn_reserv_decl
->arcs_marked_by_insn
;
5796 arc
->insn
->insn_reserv_decl
->arcs_marked_by_insn
= arc
;
5800 /* The function creates composed state (see comments for IR) from
5801 ORIGINAL_STATE and list of arcs ARCS_MARKED_BY_INSN marked by the
5802 same insn. If the composed state is not in STATE_STACK yet, it is
5803 pushed into STATE_STACK. */
5805 create_composed_state (state_t original_state
, arc_t arcs_marked_by_insn
,
5806 vla_ptr_t
*state_stack
)
5809 alt_state_t alt_state
, curr_alt_state
;
5810 alt_state_t new_alt_state
;
5813 state_t state_in_table
;
5815 alt_state_t canonical_alt_states_list
;
5817 int new_state_p
= 0;
5819 if (arcs_marked_by_insn
== NULL
)
5821 if (arcs_marked_by_insn
->next_arc_marked_by_insn
== NULL
)
5822 state
= arcs_marked_by_insn
->to_state
;
5827 /* Create composed state. */
5828 state
= get_free_state (0, arcs_marked_by_insn
->to_state
->automaton
);
5829 curr_alt_state
= NULL
;
5830 for (curr_arc
= arcs_marked_by_insn
;
5832 curr_arc
= curr_arc
->next_arc_marked_by_insn
)
5833 if (curr_arc
->to_state
->component_states
== NULL
)
5835 new_alt_state
= get_free_alt_state ();
5836 new_alt_state
->next_alt_state
= curr_alt_state
;
5837 new_alt_state
->state
= curr_arc
->to_state
;
5838 curr_alt_state
= new_alt_state
;
5841 for (alt_state
= curr_arc
->to_state
->component_states
;
5843 alt_state
= alt_state
->next_sorted_alt_state
)
5845 new_alt_state
= get_free_alt_state ();
5846 new_alt_state
->next_alt_state
= curr_alt_state
;
5847 new_alt_state
->state
= alt_state
->state
;
5848 if (alt_state
->state
->component_states
!= NULL
)
5850 curr_alt_state
= new_alt_state
;
5852 /* There are not identical sets in the alt state list. */
5853 canonical_alt_states_list
= uniq_sort_alt_states (curr_alt_state
);
5854 if (canonical_alt_states_list
->next_sorted_alt_state
== NULL
)
5857 state
= canonical_alt_states_list
->state
;
5858 free_state (temp_state
);
5862 state
->component_states
= canonical_alt_states_list
;
5863 state_in_table
= insert_state (state
);
5864 if (state_in_table
!= state
)
5866 if (!state_in_table
->it_was_placed_in_stack_for_DFA_forming
)
5869 state
= state_in_table
;
5873 if (state
->it_was_placed_in_stack_for_DFA_forming
)
5876 for (curr_alt_state
= state
->component_states
;
5877 curr_alt_state
!= NULL
;
5878 curr_alt_state
= curr_alt_state
->next_sorted_alt_state
)
5879 for (curr_arc
= first_out_arc (curr_alt_state
->state
);
5881 curr_arc
= next_out_arc (curr_arc
))
5882 add_arc (state
, curr_arc
->to_state
, curr_arc
->insn
, 1);
5884 arcs_marked_by_insn
->to_state
= state
;
5885 for (alts_number
= 0,
5886 curr_arc
= arcs_marked_by_insn
->next_arc_marked_by_insn
;
5888 curr_arc
= next_arc
)
5890 next_arc
= curr_arc
->next_arc_marked_by_insn
;
5891 remove_arc (original_state
, curr_arc
);
5894 arcs_marked_by_insn
->state_alts
= alts_number
;
5897 if (!state
->it_was_placed_in_stack_for_DFA_forming
)
5899 state
->it_was_placed_in_stack_for_DFA_forming
= 1;
5900 VLA_PTR_ADD (*state_stack
, state
);
5905 /* The function transforms nondeterministic AUTOMATON into
5908 NDFA_to_DFA (automaton_t automaton
)
5910 state_t start_state
;
5913 vla_ptr_t state_stack
;
5917 VLA_PTR_CREATE (state_stack
, 150, "state stack");
5918 /* Create the start state (empty state). */
5919 start_state
= automaton
->start_state
;
5920 start_state
->it_was_placed_in_stack_for_DFA_forming
= 1;
5921 VLA_PTR_ADD (state_stack
, start_state
);
5923 while (VLA_PTR_LENGTH (state_stack
) != 0)
5925 state
= VLA_PTR (state_stack
, VLA_PTR_LENGTH (state_stack
) - 1);
5926 VLA_PTR_SHORTEN (state_stack
, 1);
5927 form_arcs_marked_by_insn (state
);
5928 for (i
= 0; i
< description
->decls_num
; i
++)
5930 decl
= description
->decls
[i
];
5931 if (decl
->mode
== dm_insn_reserv
5932 && create_composed_state
5933 (state
, DECL_INSN_RESERV (decl
)->arcs_marked_by_insn
,
5937 if (states_n
% 100 == 0)
5938 fprintf (stderr
, "*");
5942 VLA_PTR_DELETE (state_stack
);
5945 /* The following variable value is current number (1, 2, ...) of passing
5947 static int curr_state_graph_pass_num
;
5949 /* This recursive function passes all states achieved from START_STATE
5950 and applies APPLIED_FUNC to them. */
5952 pass_state_graph (state_t start_state
, void (*applied_func
) (state_t state
))
5956 if (start_state
->pass_num
== curr_state_graph_pass_num
)
5958 start_state
->pass_num
= curr_state_graph_pass_num
;
5959 (*applied_func
) (start_state
);
5960 for (arc
= first_out_arc (start_state
);
5962 arc
= next_out_arc (arc
))
5963 pass_state_graph (arc
->to_state
, applied_func
);
5966 /* This recursive function passes all states of AUTOMATON and applies
5967 APPLIED_FUNC to them. */
5969 pass_states (automaton_t automaton
, void (*applied_func
) (state_t state
))
5971 curr_state_graph_pass_num
++;
5972 pass_state_graph (automaton
->start_state
, applied_func
);
5975 /* The function initializes code for passing of all states. */
5977 initiate_pass_states (void)
5979 curr_state_graph_pass_num
= 0;
5982 /* The following vla is used for storing pointers to all achieved
5984 static vla_ptr_t all_achieved_states
;
5986 /* This function is called by function pass_states to add an achieved
5989 add_achieved_state (state_t state
)
5991 VLA_PTR_ADD (all_achieved_states
, state
);
5994 /* The function sets up equivalence numbers of insns which mark all
5995 out arcs of STATE by equiv_class_num_1 (if ODD_ITERATION_FLAG has
5996 nonzero value) or by equiv_class_num_2 of the destination state.
5997 The function returns number of out arcs of STATE. */
5999 set_out_arc_insns_equiv_num (state_t state
, int odd_iteration_flag
)
6001 int state_out_arcs_num
;
6004 state_out_arcs_num
= 0;
6005 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
6007 if (arc
->insn
->insn_reserv_decl
->equiv_class_num
!= 0
6008 || arc
->insn
->insn_reserv_decl
->state_alts
!= 0)
6010 state_out_arcs_num
++;
6011 arc
->insn
->insn_reserv_decl
->equiv_class_num
6012 = (odd_iteration_flag
6013 ? arc
->to_state
->equiv_class_num_1
6014 : arc
->to_state
->equiv_class_num_2
);
6015 arc
->insn
->insn_reserv_decl
->state_alts
= arc
->state_alts
;
6016 if (arc
->insn
->insn_reserv_decl
->equiv_class_num
== 0
6017 || arc
->insn
->insn_reserv_decl
->state_alts
<= 0)
6020 return state_out_arcs_num
;
6023 /* The function clears equivalence numbers and alt_states in all insns
6024 which mark all out arcs of STATE. */
6026 clear_arc_insns_equiv_num (state_t state
)
6030 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
6032 arc
->insn
->insn_reserv_decl
->equiv_class_num
= 0;
6033 arc
->insn
->insn_reserv_decl
->state_alts
= 0;
6037 /* The function copies pointers to equivalent states from vla FROM
6040 copy_equiv_class (vla_ptr_t
*to
, const vla_ptr_t
*from
)
6044 VLA_PTR_NULLIFY (*to
);
6045 for (class_ptr
= VLA_PTR_BEGIN (*from
);
6046 class_ptr
<= (state_t
*) VLA_PTR_LAST (*from
);
6048 VLA_PTR_ADD (*to
, *class_ptr
);
6051 /* The following function returns TRUE if STATE reserves the unit with
6052 UNIT_NUM on the first cycle. */
6054 first_cycle_unit_presence (state_t state
, int unit_num
)
6058 if (state
->component_states
== NULL
)
6059 presence_p
= test_unit_reserv (state
->reservs
, 0, unit_num
);
6062 = test_unit_reserv (state
->component_states
->state
->reservs
,
6067 /* The function returns nonzero value if STATE is not equivalent to
6068 ANOTHER_STATE from the same current partition on equivalence
6069 classes. Another state has ANOTHER_STATE_OUT_ARCS_NUM number of
6070 output arcs. Iteration of making equivalence partition is defined
6071 by ODD_ITERATION_FLAG. */
6073 state_is_differed (state_t state
, state_t another_state
,
6074 int another_state_out_arcs_num
, int odd_iteration_flag
)
6077 int state_out_arcs_num
;
6078 int i
, presence1_p
, presence2_p
;
6080 state_out_arcs_num
= 0;
6081 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
6083 state_out_arcs_num
++;
6084 if ((odd_iteration_flag
6085 ? arc
->to_state
->equiv_class_num_1
6086 : arc
->to_state
->equiv_class_num_2
)
6087 != arc
->insn
->insn_reserv_decl
->equiv_class_num
6088 || (arc
->insn
->insn_reserv_decl
->state_alts
!= arc
->state_alts
))
6091 if (state_out_arcs_num
!= another_state_out_arcs_num
)
6093 /* Now we are looking at the states with the point of view of query
6095 for (i
= 0; i
< description
->units_num
; i
++)
6096 if (units_array
[i
]->query_p
)
6098 presence1_p
= first_cycle_unit_presence (state
, i
);
6099 presence2_p
= first_cycle_unit_presence (another_state
, i
);
6100 if ((presence1_p
&& !presence2_p
) || (!presence1_p
&& presence2_p
))
6106 /* The function makes initial partition of STATES on equivalent
6109 init_equiv_class (state_t
*states
, int states_num
)
6112 state_t result_equiv_class
;
6114 result_equiv_class
= NULL
;
6115 for (state_ptr
= states
; state_ptr
< states
+ states_num
; state_ptr
++)
6117 (*state_ptr
)->equiv_class_num_1
= 1;
6118 (*state_ptr
)->next_equiv_class_state
= result_equiv_class
;
6119 result_equiv_class
= *state_ptr
;
6121 return result_equiv_class
;
6124 /* The function processes equivalence class given by its pointer
6125 EQUIV_CLASS_PTR on odd iteration if ODD_ITERATION_FLAG. If there
6126 are not equivalent states, the function partitions the class
6127 removing nonequivalent states and placing them in
6128 *NEXT_ITERATION_CLASSES, increments *NEW_EQUIV_CLASS_NUM_PTR ans
6129 assigns it to the state equivalence number. If the class has been
6130 partitioned, the function returns nonzero value. */
6132 partition_equiv_class (state_t
*equiv_class_ptr
, int odd_iteration_flag
,
6133 vla_ptr_t
*next_iteration_classes
,
6134 int *new_equiv_class_num_ptr
)
6136 state_t new_equiv_class
;
6138 state_t first_state
;
6145 if (*equiv_class_ptr
== NULL
)
6147 for (first_state
= *equiv_class_ptr
;
6148 first_state
!= NULL
;
6149 first_state
= new_equiv_class
)
6151 new_equiv_class
= NULL
;
6152 if (first_state
->next_equiv_class_state
!= NULL
)
6154 /* There are more one states in the class equivalence. */
6155 out_arcs_num
= set_out_arc_insns_equiv_num (first_state
,
6156 odd_iteration_flag
);
6157 for (prev_state
= first_state
,
6158 curr_state
= first_state
->next_equiv_class_state
;
6160 curr_state
= next_state
)
6162 next_state
= curr_state
->next_equiv_class_state
;
6163 if (state_is_differed (curr_state
, first_state
, out_arcs_num
,
6164 odd_iteration_flag
))
6166 /* Remove curr state from the class equivalence. */
6167 prev_state
->next_equiv_class_state
= next_state
;
6168 /* Add curr state to the new class equivalence. */
6169 curr_state
->next_equiv_class_state
= new_equiv_class
;
6170 if (new_equiv_class
== NULL
)
6171 (*new_equiv_class_num_ptr
)++;
6172 if (odd_iteration_flag
)
6173 curr_state
->equiv_class_num_2
= *new_equiv_class_num_ptr
;
6175 curr_state
->equiv_class_num_1
= *new_equiv_class_num_ptr
;
6176 new_equiv_class
= curr_state
;
6180 prev_state
= curr_state
;
6182 clear_arc_insns_equiv_num (first_state
);
6184 if (new_equiv_class
!= NULL
)
6185 VLA_PTR_ADD (*next_iteration_classes
, new_equiv_class
);
6190 /* The function finds equivalent states of AUTOMATON. */
6192 evaluate_equiv_classes (automaton_t automaton
, vla_ptr_t
*equiv_classes
)
6194 state_t new_equiv_class
;
6195 int new_equiv_class_num
;
6196 int odd_iteration_flag
;
6198 vla_ptr_t next_iteration_classes
;
6199 state_t
*equiv_class_ptr
;
6202 VLA_PTR_CREATE (all_achieved_states
, 1500, "all achieved states");
6203 pass_states (automaton
, add_achieved_state
);
6204 new_equiv_class
= init_equiv_class (VLA_PTR_BEGIN (all_achieved_states
),
6205 VLA_PTR_LENGTH (all_achieved_states
));
6206 odd_iteration_flag
= 0;
6207 new_equiv_class_num
= 1;
6208 VLA_PTR_CREATE (next_iteration_classes
, 150, "next iteration classes");
6209 VLA_PTR_ADD (next_iteration_classes
, new_equiv_class
);
6212 odd_iteration_flag
= !odd_iteration_flag
;
6214 copy_equiv_class (equiv_classes
, &next_iteration_classes
);
6215 /* Transfer equiv numbers for the next iteration. */
6216 for (state_ptr
= VLA_PTR_BEGIN (all_achieved_states
);
6217 state_ptr
<= (state_t
*) VLA_PTR_LAST (all_achieved_states
);
6219 if (odd_iteration_flag
)
6220 (*state_ptr
)->equiv_class_num_2
= (*state_ptr
)->equiv_class_num_1
;
6222 (*state_ptr
)->equiv_class_num_1
= (*state_ptr
)->equiv_class_num_2
;
6223 for (equiv_class_ptr
= VLA_PTR_BEGIN (*equiv_classes
);
6224 equiv_class_ptr
<= (state_t
*) VLA_PTR_LAST (*equiv_classes
);
6226 if (partition_equiv_class (equiv_class_ptr
, odd_iteration_flag
,
6227 &next_iteration_classes
,
6228 &new_equiv_class_num
))
6231 while (!finish_flag
);
6232 VLA_PTR_DELETE (next_iteration_classes
);
6233 VLA_PTR_DELETE (all_achieved_states
);
6236 /* The function merges equivalent states of AUTOMATON. */
6238 merge_states (automaton_t automaton
, vla_ptr_t
*equiv_classes
)
6240 state_t
*equiv_class_ptr
;
6243 state_t first_class_state
;
6244 alt_state_t alt_states
;
6245 alt_state_t alt_state
, new_alt_state
;
6249 /* Create states corresponding to equivalence classes containing two
6251 for (equiv_class_ptr
= VLA_PTR_BEGIN (*equiv_classes
);
6252 equiv_class_ptr
<= (state_t
*) VLA_PTR_LAST (*equiv_classes
);
6254 if ((*equiv_class_ptr
)->next_equiv_class_state
!= NULL
)
6256 /* There are more one states in the class equivalence. */
6257 /* Create new compound state. */
6258 new_state
= get_free_state (0, automaton
);
6260 first_class_state
= *equiv_class_ptr
;
6261 for (curr_state
= first_class_state
;
6263 curr_state
= curr_state
->next_equiv_class_state
)
6265 curr_state
->equiv_class_state
= new_state
;
6266 if (curr_state
->component_states
== NULL
)
6268 new_alt_state
= get_free_alt_state ();
6269 new_alt_state
->state
= curr_state
;
6270 new_alt_state
->next_alt_state
= alt_states
;
6271 alt_states
= new_alt_state
;
6274 for (alt_state
= curr_state
->component_states
;
6276 alt_state
= alt_state
->next_sorted_alt_state
)
6278 new_alt_state
= get_free_alt_state ();
6279 new_alt_state
->state
= alt_state
->state
;
6280 new_alt_state
->next_alt_state
= alt_states
;
6281 alt_states
= new_alt_state
;
6284 /* Its is important that alt states were sorted before and
6285 after merging to have the same querying results. */
6286 new_state
->component_states
= uniq_sort_alt_states (alt_states
);
6289 (*equiv_class_ptr
)->equiv_class_state
= *equiv_class_ptr
;
6290 for (equiv_class_ptr
= VLA_PTR_BEGIN (*equiv_classes
);
6291 equiv_class_ptr
<= (state_t
*) VLA_PTR_LAST (*equiv_classes
);
6293 if ((*equiv_class_ptr
)->next_equiv_class_state
!= NULL
)
6295 first_class_state
= *equiv_class_ptr
;
6296 /* Create new arcs output from the state corresponding to
6298 for (curr_arc
= first_out_arc (first_class_state
);
6300 curr_arc
= next_out_arc (curr_arc
))
6301 add_arc (first_class_state
->equiv_class_state
,
6302 curr_arc
->to_state
->equiv_class_state
,
6303 curr_arc
->insn
, curr_arc
->state_alts
);
6304 /* Delete output arcs from states of given class equivalence. */
6305 for (curr_state
= first_class_state
;
6307 curr_state
= curr_state
->next_equiv_class_state
)
6309 if (automaton
->start_state
== curr_state
)
6310 automaton
->start_state
= curr_state
->equiv_class_state
;
6311 /* Delete the state and its output arcs. */
6312 for (curr_arc
= first_out_arc (curr_state
);
6314 curr_arc
= next_arc
)
6316 next_arc
= next_out_arc (curr_arc
);
6317 free_arc (curr_arc
);
6323 /* Change `to_state' of arcs output from the state of given
6324 equivalence class. */
6325 for (curr_arc
= first_out_arc (*equiv_class_ptr
);
6327 curr_arc
= next_out_arc (curr_arc
))
6328 curr_arc
->to_state
= curr_arc
->to_state
->equiv_class_state
;
6332 /* The function sets up new_cycle_p for states if there is arc to the
6333 state marked by advance_cycle_insn_decl. */
6335 set_new_cycle_flags (state_t state
)
6339 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
6340 if (arc
->insn
->insn_reserv_decl
6341 == DECL_INSN_RESERV (advance_cycle_insn_decl
))
6342 arc
->to_state
->new_cycle_p
= 1;
6345 /* The top level function for minimization of deterministic
6348 minimize_DFA (automaton_t automaton
)
6350 vla_ptr_t equiv_classes
;
6352 VLA_PTR_CREATE (equiv_classes
, 1500, "equivalence classes");
6353 evaluate_equiv_classes (automaton
, &equiv_classes
);
6354 merge_states (automaton
, &equiv_classes
);
6355 pass_states (automaton
, set_new_cycle_flags
);
6356 VLA_PTR_DELETE (equiv_classes
);
6359 /* Values of two variables are counted number of states and arcs in an
6361 static int curr_counted_states_num
;
6362 static int curr_counted_arcs_num
;
6364 /* The function is called by function `pass_states' to count states
6365 and arcs of an automaton. */
6367 incr_states_and_arcs_nums (state_t state
)
6371 curr_counted_states_num
++;
6372 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
6373 curr_counted_arcs_num
++;
6376 /* The function counts states and arcs of AUTOMATON. */
6378 count_states_and_arcs (automaton_t automaton
, int *states_num
,
6381 curr_counted_states_num
= 0;
6382 curr_counted_arcs_num
= 0;
6383 pass_states (automaton
, incr_states_and_arcs_nums
);
6384 *states_num
= curr_counted_states_num
;
6385 *arcs_num
= curr_counted_arcs_num
;
6388 /* The function builds one DFA AUTOMATON for fast pipeline hazards
6389 recognition after checking and simplifying IR of the
6392 build_automaton (automaton_t automaton
)
6397 ticker_on (&NDFA_time
);
6398 if (automaton
->corresponding_automaton_decl
== NULL
)
6399 fprintf (stderr
, "Create anonymous automaton (1 star is 100 new states):");
6401 fprintf (stderr
, "Create automaton `%s' (1 star is 100 new states):",
6402 automaton
->corresponding_automaton_decl
->name
);
6403 make_automaton (automaton
);
6404 fprintf (stderr
, " done\n");
6405 ticker_off (&NDFA_time
);
6406 count_states_and_arcs (automaton
, &states_num
, &arcs_num
);
6407 automaton
->NDFA_states_num
= states_num
;
6408 automaton
->NDFA_arcs_num
= arcs_num
;
6409 ticker_on (&NDFA_to_DFA_time
);
6410 if (automaton
->corresponding_automaton_decl
== NULL
)
6411 fprintf (stderr
, "Make anonymous DFA (1 star is 100 new states):");
6413 fprintf (stderr
, "Make DFA `%s' (1 star is 100 new states):",
6414 automaton
->corresponding_automaton_decl
->name
);
6415 NDFA_to_DFA (automaton
);
6416 fprintf (stderr
, " done\n");
6417 ticker_off (&NDFA_to_DFA_time
);
6418 count_states_and_arcs (automaton
, &states_num
, &arcs_num
);
6419 automaton
->DFA_states_num
= states_num
;
6420 automaton
->DFA_arcs_num
= arcs_num
;
6421 if (!no_minimization_flag
)
6423 ticker_on (&minimize_time
);
6424 if (automaton
->corresponding_automaton_decl
== NULL
)
6425 fprintf (stderr
, "Minimize anonymous DFA...");
6427 fprintf (stderr
, "Minimize DFA `%s'...",
6428 automaton
->corresponding_automaton_decl
->name
);
6429 minimize_DFA (automaton
);
6430 fprintf (stderr
, "done\n");
6431 ticker_off (&minimize_time
);
6432 count_states_and_arcs (automaton
, &states_num
, &arcs_num
);
6433 automaton
->minimal_DFA_states_num
= states_num
;
6434 automaton
->minimal_DFA_arcs_num
= arcs_num
;
6440 /* The page contains code for enumeration of all states of an automaton. */
6442 /* Variable used for enumeration of all states of an automaton. Its
6443 value is current number of automaton states. */
6444 static int curr_state_order_num
;
6446 /* The function is called by function `pass_states' for enumerating
6449 set_order_state_num (state_t state
)
6451 state
->order_state_num
= curr_state_order_num
;
6452 curr_state_order_num
++;
6455 /* The function enumerates all states of AUTOMATON. */
6457 enumerate_states (automaton_t automaton
)
6459 curr_state_order_num
= 0;
6460 pass_states (automaton
, set_order_state_num
);
6461 automaton
->achieved_states_num
= curr_state_order_num
;
6466 /* The page contains code for finding equivalent automaton insns
6469 /* The function inserts AINSN into cyclic list
6470 CYCLIC_EQUIV_CLASS_INSN_LIST of ainsns. */
6472 insert_ainsn_into_equiv_class (ainsn_t ainsn
,
6473 ainsn_t cyclic_equiv_class_insn_list
)
6475 if (cyclic_equiv_class_insn_list
== NULL
)
6476 ainsn
->next_equiv_class_insn
= ainsn
;
6479 ainsn
->next_equiv_class_insn
6480 = cyclic_equiv_class_insn_list
->next_equiv_class_insn
;
6481 cyclic_equiv_class_insn_list
->next_equiv_class_insn
= ainsn
;
6486 /* The function deletes equiv_class_insn into cyclic list of
6487 equivalent ainsns. */
6489 delete_ainsn_from_equiv_class (ainsn_t equiv_class_insn
)
6491 ainsn_t curr_equiv_class_insn
;
6492 ainsn_t prev_equiv_class_insn
;
6494 prev_equiv_class_insn
= equiv_class_insn
;
6495 for (curr_equiv_class_insn
= equiv_class_insn
->next_equiv_class_insn
;
6496 curr_equiv_class_insn
!= equiv_class_insn
;
6497 curr_equiv_class_insn
= curr_equiv_class_insn
->next_equiv_class_insn
)
6498 prev_equiv_class_insn
= curr_equiv_class_insn
;
6499 if (prev_equiv_class_insn
!= equiv_class_insn
)
6500 prev_equiv_class_insn
->next_equiv_class_insn
6501 = equiv_class_insn
->next_equiv_class_insn
;
6504 /* The function processes AINSN of a state in order to find equivalent
6505 ainsns. INSN_ARCS_ARRAY is table: code of insn -> out arc of the
6508 process_insn_equiv_class (ainsn_t ainsn
, arc_t
*insn_arcs_array
)
6512 ainsn_t cyclic_insn_list
;
6515 if (insn_arcs_array
[ainsn
->insn_reserv_decl
->insn_num
] == NULL
)
6518 /* New class of ainsns which are not equivalent to given ainsn. */
6519 cyclic_insn_list
= NULL
;
6522 next_insn
= curr_insn
->next_equiv_class_insn
;
6523 arc
= insn_arcs_array
[curr_insn
->insn_reserv_decl
->insn_num
];
6525 || (insn_arcs_array
[ainsn
->insn_reserv_decl
->insn_num
]->to_state
6528 delete_ainsn_from_equiv_class (curr_insn
);
6529 cyclic_insn_list
= insert_ainsn_into_equiv_class (curr_insn
,
6532 curr_insn
= next_insn
;
6534 while (curr_insn
!= ainsn
);
6537 /* The function processes STATE in order to find equivalent ainsns. */
6539 process_state_for_insn_equiv_partition (state_t state
)
6542 arc_t
*insn_arcs_array
;
6544 vla_ptr_t insn_arcs_vect
;
6546 VLA_PTR_CREATE (insn_arcs_vect
, 500, "insn arcs vector");
6547 VLA_PTR_EXPAND (insn_arcs_vect
, description
->insns_num
);
6548 insn_arcs_array
= VLA_PTR_BEGIN (insn_arcs_vect
);
6549 /* Process insns of the arcs. */
6550 for (i
= 0; i
< description
->insns_num
; i
++)
6551 insn_arcs_array
[i
] = NULL
;
6552 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
6553 insn_arcs_array
[arc
->insn
->insn_reserv_decl
->insn_num
] = arc
;
6554 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
6555 process_insn_equiv_class (arc
->insn
, insn_arcs_array
);
6556 VLA_PTR_DELETE (insn_arcs_vect
);
6559 /* The function searches for equivalent ainsns of AUTOMATON. */
6561 set_insn_equiv_classes (automaton_t automaton
)
6566 ainsn_t cyclic_insn_list
;
6567 ainsn_t insn_with_same_reservs
;
6568 int equiv_classes_num
;
6570 /* All insns are included in one equivalence class. */
6571 cyclic_insn_list
= NULL
;
6572 for (ainsn
= automaton
->ainsn_list
; ainsn
!= NULL
; ainsn
= ainsn
->next_ainsn
)
6573 if (ainsn
->first_insn_with_same_reservs
)
6574 cyclic_insn_list
= insert_ainsn_into_equiv_class (ainsn
,
6576 /* Process insns in order to make equivalence partition. */
6577 pass_states (automaton
, process_state_for_insn_equiv_partition
);
6578 /* Enumerate equiv classes. */
6579 for (ainsn
= automaton
->ainsn_list
; ainsn
!= NULL
; ainsn
= ainsn
->next_ainsn
)
6580 /* Set undefined value. */
6581 ainsn
->insn_equiv_class_num
= -1;
6582 equiv_classes_num
= 0;
6583 for (ainsn
= automaton
->ainsn_list
; ainsn
!= NULL
; ainsn
= ainsn
->next_ainsn
)
6584 if (ainsn
->insn_equiv_class_num
< 0)
6587 if (!first_insn
->first_insn_with_same_reservs
)
6589 first_insn
->first_ainsn_with_given_equialence_num
= 1;
6590 curr_insn
= first_insn
;
6593 for (insn_with_same_reservs
= curr_insn
;
6594 insn_with_same_reservs
!= NULL
;
6595 insn_with_same_reservs
6596 = insn_with_same_reservs
->next_same_reservs_insn
)
6597 insn_with_same_reservs
->insn_equiv_class_num
= equiv_classes_num
;
6598 curr_insn
= curr_insn
->next_equiv_class_insn
;
6600 while (curr_insn
!= first_insn
);
6601 equiv_classes_num
++;
6603 automaton
->insn_equiv_classes_num
= equiv_classes_num
;
6608 /* This page contains code for creating DFA(s) and calls functions
6612 /* The following value is used to prevent floating point overflow for
6613 estimating an automaton bound. The value should be less DBL_MAX on
6614 the host machine. We use here approximate minimum of maximal
6615 double floating point value required by ANSI C standard. It
6616 will work for non ANSI sun compiler too. */
6618 #define MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND 1.0E37
6620 /* The function estimate size of the single DFA used by PHR (pipeline
6621 hazards recognizer). */
6623 estimate_one_automaton_bound (void)
6626 double one_automaton_estimation_bound
;
6630 one_automaton_estimation_bound
= 1.0;
6631 for (i
= 0; i
< description
->decls_num
; i
++)
6633 decl
= description
->decls
[i
];
6634 if (decl
->mode
== dm_unit
)
6636 root_value
= exp (log (DECL_UNIT (decl
)->max_occ_cycle_num
6637 - DECL_UNIT (decl
)->min_occ_cycle_num
+ 1.0)
6639 if (MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND
/ root_value
6640 > one_automaton_estimation_bound
)
6641 one_automaton_estimation_bound
*= root_value
;
6644 return one_automaton_estimation_bound
;
6647 /* The function compares unit declarations according to their maximal
6648 cycle in reservations. */
6650 compare_max_occ_cycle_nums (const void *unit_decl_1
,
6651 const void *unit_decl_2
)
6653 if ((DECL_UNIT (*(decl_t
*) unit_decl_1
)->max_occ_cycle_num
)
6654 < (DECL_UNIT (*(decl_t
*) unit_decl_2
)->max_occ_cycle_num
))
6656 else if ((DECL_UNIT (*(decl_t
*) unit_decl_1
)->max_occ_cycle_num
)
6657 == (DECL_UNIT (*(decl_t
*) unit_decl_2
)->max_occ_cycle_num
))
6663 /* The function makes heuristic assigning automata to units. Actually
6664 efficacy of the algorithm has been checked yet??? */
6666 units_to_automata_heuristic_distr (void)
6668 double estimation_bound
;
6670 decl_t
*unit_decl_ptr
;
6674 vla_ptr_t unit_decls
;
6677 if (description
->units_num
== 0)
6679 estimation_bound
= estimate_one_automaton_bound ();
6680 VLA_PTR_CREATE (unit_decls
, 150, "unit decls");
6681 for (i
= 0; i
< description
->decls_num
; i
++)
6683 decl
= description
->decls
[i
];
6684 if (decl
->mode
== dm_unit
)
6685 VLA_PTR_ADD (unit_decls
, decl
);
6687 qsort (VLA_PTR_BEGIN (unit_decls
), VLA_PTR_LENGTH (unit_decls
),
6688 sizeof (decl_t
), compare_max_occ_cycle_nums
);
6690 unit_decl_ptr
= VLA_PTR_BEGIN (unit_decls
);
6691 bound_value
= DECL_UNIT (*unit_decl_ptr
)->max_occ_cycle_num
;
6692 DECL_UNIT (*unit_decl_ptr
)->corresponding_automaton_num
= automaton_num
;
6693 for (unit_decl_ptr
++;
6694 unit_decl_ptr
<= (decl_t
*) VLA_PTR_LAST (unit_decls
);
6698 = ((decl_t
*) VLA_PTR_LAST (unit_decls
) - unit_decl_ptr
+ 1);
6699 if (automata_num
- automaton_num
- 1 > rest_units_num
)
6701 if (automaton_num
< automata_num
- 1
6702 && ((automata_num
- automaton_num
- 1 == rest_units_num
)
6705 / (DECL_UNIT (*unit_decl_ptr
)->max_occ_cycle_num
)))))
6707 bound_value
= DECL_UNIT (*unit_decl_ptr
)->max_occ_cycle_num
;
6711 bound_value
*= DECL_UNIT (*unit_decl_ptr
)->max_occ_cycle_num
;
6712 DECL_UNIT (*unit_decl_ptr
)->corresponding_automaton_num
= automaton_num
;
6714 if (automaton_num
!= automata_num
- 1)
6716 VLA_PTR_DELETE (unit_decls
);
6719 /* The functions creates automaton insns for each automata. Automaton
6720 insn is simply insn for given automaton which makes reservation
6721 only of units of the automaton. */
6723 create_ainsns (void)
6726 ainsn_t first_ainsn
;
6733 for (i
= 0; i
< description
->decls_num
; i
++)
6735 decl
= description
->decls
[i
];
6736 if (decl
->mode
== dm_insn_reserv
)
6738 curr_ainsn
= create_node (sizeof (struct ainsn
));
6739 curr_ainsn
->insn_reserv_decl
= DECL_INSN_RESERV (decl
);
6740 curr_ainsn
->important_p
= FALSE
;
6741 curr_ainsn
->next_ainsn
= NULL
;
6742 if (prev_ainsn
== NULL
)
6743 first_ainsn
= curr_ainsn
;
6745 prev_ainsn
->next_ainsn
= curr_ainsn
;
6746 prev_ainsn
= curr_ainsn
;
6752 /* The function assigns automata to units according to constructions
6753 `define_automaton' in the description. */
6755 units_to_automata_distr (void)
6760 for (i
= 0; i
< description
->decls_num
; i
++)
6762 decl
= description
->decls
[i
];
6763 if (decl
->mode
== dm_unit
)
6765 if (DECL_UNIT (decl
)->automaton_decl
== NULL
6766 || (DECL_UNIT (decl
)->automaton_decl
->corresponding_automaton
6768 /* Distribute to the first automaton. */
6769 DECL_UNIT (decl
)->corresponding_automaton_num
= 0;
6771 DECL_UNIT (decl
)->corresponding_automaton_num
6772 = (DECL_UNIT (decl
)->automaton_decl
6773 ->corresponding_automaton
->automaton_order_num
);
6778 /* The function creates DFA(s) for fast pipeline hazards recognition
6779 after checking and simplifying IR of the description. */
6781 create_automata (void)
6783 automaton_t curr_automaton
;
6784 automaton_t prev_automaton
;
6786 int curr_automaton_num
;
6789 if (automata_num
!= 0)
6791 units_to_automata_heuristic_distr ();
6792 for (prev_automaton
= NULL
, curr_automaton_num
= 0;
6793 curr_automaton_num
< automata_num
;
6794 curr_automaton_num
++, prev_automaton
= curr_automaton
)
6796 curr_automaton
= create_node (sizeof (struct automaton
));
6797 curr_automaton
->ainsn_list
= create_ainsns ();
6798 curr_automaton
->corresponding_automaton_decl
= NULL
;
6799 curr_automaton
->next_automaton
= NULL
;
6800 curr_automaton
->automaton_order_num
= curr_automaton_num
;
6801 if (prev_automaton
== NULL
)
6802 description
->first_automaton
= curr_automaton
;
6804 prev_automaton
->next_automaton
= curr_automaton
;
6809 curr_automaton_num
= 0;
6810 prev_automaton
= NULL
;
6811 for (i
= 0; i
< description
->decls_num
; i
++)
6813 decl
= description
->decls
[i
];
6814 if (decl
->mode
== dm_automaton
6815 && DECL_AUTOMATON (decl
)->automaton_is_used
)
6817 curr_automaton
= create_node (sizeof (struct automaton
));
6818 curr_automaton
->ainsn_list
= create_ainsns ();
6819 curr_automaton
->corresponding_automaton_decl
6820 = DECL_AUTOMATON (decl
);
6821 curr_automaton
->next_automaton
= NULL
;
6822 DECL_AUTOMATON (decl
)->corresponding_automaton
= curr_automaton
;
6823 curr_automaton
->automaton_order_num
= curr_automaton_num
;
6824 if (prev_automaton
== NULL
)
6825 description
->first_automaton
= curr_automaton
;
6827 prev_automaton
->next_automaton
= curr_automaton
;
6828 curr_automaton_num
++;
6829 prev_automaton
= curr_automaton
;
6832 if (curr_automaton_num
== 0)
6834 curr_automaton
= create_node (sizeof (struct automaton
));
6835 curr_automaton
->ainsn_list
= create_ainsns ();
6836 curr_automaton
->corresponding_automaton_decl
= NULL
;
6837 curr_automaton
->next_automaton
= NULL
;
6838 description
->first_automaton
= curr_automaton
;
6840 units_to_automata_distr ();
6842 NDFA_time
= create_ticker ();
6843 ticker_off (&NDFA_time
);
6844 NDFA_to_DFA_time
= create_ticker ();
6845 ticker_off (&NDFA_to_DFA_time
);
6846 minimize_time
= create_ticker ();
6847 ticker_off (&minimize_time
);
6848 equiv_time
= create_ticker ();
6849 ticker_off (&equiv_time
);
6850 for (curr_automaton
= description
->first_automaton
;
6851 curr_automaton
!= NULL
;
6852 curr_automaton
= curr_automaton
->next_automaton
)
6854 if (curr_automaton
->corresponding_automaton_decl
== NULL
)
6855 fprintf (stderr
, "Prepare anonymous automaton creation ... ");
6857 fprintf (stderr
, "Prepare automaton `%s' creation...",
6858 curr_automaton
->corresponding_automaton_decl
->name
);
6859 create_alt_states (curr_automaton
);
6860 form_ainsn_with_same_reservs (curr_automaton
);
6861 fprintf (stderr
, "done\n");
6862 build_automaton (curr_automaton
);
6863 enumerate_states (curr_automaton
);
6864 ticker_on (&equiv_time
);
6865 set_insn_equiv_classes (curr_automaton
);
6866 ticker_off (&equiv_time
);
6872 /* This page contains code for forming string representation of
6873 regexp. The representation is formed on IR obstack. So you should
6874 not work with IR obstack between regexp_representation and
6875 finish_regexp_representation calls. */
6877 /* This recursive function forms string representation of regexp
6878 (without tailing '\0'). */
6880 form_regexp (regexp_t regexp
)
6884 if (regexp
->mode
== rm_unit
|| regexp
->mode
== rm_reserv
)
6886 const char *name
= (regexp
->mode
== rm_unit
6887 ? REGEXP_UNIT (regexp
)->name
6888 : REGEXP_RESERV (regexp
)->name
);
6890 obstack_grow (&irp
, name
, strlen (name
));
6892 else if (regexp
->mode
== rm_sequence
)
6893 for (i
= 0; i
< REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
6896 obstack_1grow (&irp
, ',');
6897 form_regexp (REGEXP_SEQUENCE (regexp
)->regexps
[i
]);
6899 else if (regexp
->mode
== rm_allof
)
6901 obstack_1grow (&irp
, '(');
6902 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
6905 obstack_1grow (&irp
, '+');
6906 if (REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
== rm_sequence
6907 || REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
== rm_oneof
)
6908 obstack_1grow (&irp
, '(');
6909 form_regexp (REGEXP_ALLOF (regexp
)->regexps
[i
]);
6910 if (REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
== rm_sequence
6911 || REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
== rm_oneof
)
6912 obstack_1grow (&irp
, ')');
6914 obstack_1grow (&irp
, ')');
6916 else if (regexp
->mode
== rm_oneof
)
6917 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
6920 obstack_1grow (&irp
, '|');
6921 if (REGEXP_ONEOF (regexp
)->regexps
[i
]->mode
== rm_sequence
)
6922 obstack_1grow (&irp
, '(');
6923 form_regexp (REGEXP_ONEOF (regexp
)->regexps
[i
]);
6924 if (REGEXP_ONEOF (regexp
)->regexps
[i
]->mode
== rm_sequence
)
6925 obstack_1grow (&irp
, ')');
6927 else if (regexp
->mode
== rm_repeat
)
6931 if (REGEXP_REPEAT (regexp
)->regexp
->mode
== rm_sequence
6932 || REGEXP_REPEAT (regexp
)->regexp
->mode
== rm_allof
6933 || REGEXP_REPEAT (regexp
)->regexp
->mode
== rm_oneof
)
6934 obstack_1grow (&irp
, '(');
6935 form_regexp (REGEXP_REPEAT (regexp
)->regexp
);
6936 if (REGEXP_REPEAT (regexp
)->regexp
->mode
== rm_sequence
6937 || REGEXP_REPEAT (regexp
)->regexp
->mode
== rm_allof
6938 || REGEXP_REPEAT (regexp
)->regexp
->mode
== rm_oneof
)
6939 obstack_1grow (&irp
, ')');
6940 sprintf (digits
, "*%d", REGEXP_REPEAT (regexp
)->repeat_num
);
6941 obstack_grow (&irp
, digits
, strlen (digits
));
6943 else if (regexp
->mode
== rm_nothing
)
6944 obstack_grow (&irp
, NOTHING_NAME
, strlen (NOTHING_NAME
));
6949 /* The function returns string representation of REGEXP on IR
6952 regexp_representation (regexp_t regexp
)
6954 form_regexp (regexp
);
6955 obstack_1grow (&irp
, '\0');
6956 return obstack_base (&irp
);
6959 /* The function frees memory allocated for last formed string
6960 representation of regexp. */
6962 finish_regexp_representation (void)
6964 int length
= obstack_object_size (&irp
);
6966 obstack_blank_fast (&irp
, -length
);
6971 /* This page contains code for output PHR (pipeline hazards recognizer). */
6973 /* The function outputs minimal C type which is sufficient for
6974 representation numbers in range min_range_value and
6975 max_range_value. Because host machine and build machine may be
6976 different, we use here minimal values required by ANSI C standard
6977 instead of UCHAR_MAX, SHRT_MAX, SHRT_MIN, etc. This is a good
6981 output_range_type (FILE *f
, long int min_range_value
,
6982 long int max_range_value
)
6984 if (min_range_value
>= 0 && max_range_value
<= 255)
6985 fprintf (f
, "unsigned char");
6986 else if (min_range_value
>= -127 && max_range_value
<= 127)
6987 fprintf (f
, "signed char");
6988 else if (min_range_value
>= 0 && max_range_value
<= 65535)
6989 fprintf (f
, "unsigned short");
6990 else if (min_range_value
>= -32767 && max_range_value
<= 32767)
6991 fprintf (f
, "short");
6996 /* The following macro value is used as value of member
6997 `longest_path_length' of state when we are processing path and the
6998 state on the path. */
7000 #define ON_THE_PATH -2
7002 /* The following recursive function searches for the length of the
7003 longest path starting from STATE which does not contain cycles and
7004 `cycle advance' arcs. */
7007 longest_path_length (state_t state
)
7012 if (state
->longest_path_length
== ON_THE_PATH
)
7013 /* We don't expect the path cycle here. Our graph may contain
7014 only cycles with one state on the path not containing `cycle
7015 advance' arcs -- see comment below. */
7017 else if (state
->longest_path_length
!= UNDEFINED_LONGEST_PATH_LENGTH
)
7018 /* We already visited the state. */
7019 return state
->longest_path_length
;
7022 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
7023 /* Ignore cycles containing one state and `cycle advance' arcs. */
7024 if (arc
->to_state
!= state
7025 && (arc
->insn
->insn_reserv_decl
7026 != DECL_INSN_RESERV (advance_cycle_insn_decl
)))
7028 length
= longest_path_length (arc
->to_state
);
7029 if (length
> result
)
7032 state
->longest_path_length
= result
+ 1;
7036 /* The following variable value is value of the corresponding global
7037 variable in the automaton based pipeline interface. */
7039 static int max_dfa_issue_rate
;
7041 /* The following function processes the longest path length staring
7042 from STATE to find MAX_DFA_ISSUE_RATE. */
7045 process_state_longest_path_length (state_t state
)
7049 value
= longest_path_length (state
);
7050 if (value
> max_dfa_issue_rate
)
7051 max_dfa_issue_rate
= value
;
7054 /* The following macro value is name of the corresponding global
7055 variable in the automaton based pipeline interface. */
7057 #define MAX_DFA_ISSUE_RATE_VAR_NAME "max_dfa_issue_rate"
7059 /* The following function calculates value of the corresponding
7060 global variable and outputs its declaration. */
7063 output_dfa_max_issue_rate (void)
7065 automaton_t automaton
;
7067 if (UNDEFINED_LONGEST_PATH_LENGTH
== ON_THE_PATH
|| ON_THE_PATH
>= 0)
7069 max_dfa_issue_rate
= 0;
7070 for (automaton
= description
->first_automaton
;
7072 automaton
= automaton
->next_automaton
)
7073 pass_states (automaton
, process_state_longest_path_length
);
7074 fprintf (output_file
, "\nint %s = %d;\n",
7075 MAX_DFA_ISSUE_RATE_VAR_NAME
, max_dfa_issue_rate
);
7078 /* The function outputs all initialization values of VECT with length
7081 output_vect (vect_el_t
*vect
, int vect_length
)
7086 if (vect_length
== 0)
7087 fprintf (output_file
,
7088 "0 /* This is dummy el because the vect is empty */");
7093 fprintf (output_file
, "%5ld", (long) *vect
);
7095 if (els_on_line
== 10)
7098 fprintf (output_file
, ",\n");
7100 else if (vect_length
!= 0)
7101 fprintf (output_file
, ", ");
7105 while (vect_length
!= 0);
7109 /* The following is name of the structure which represents DFA(s) for
7111 #define CHIP_NAME "DFA_chip"
7113 /* The following is name of member which represents state of a DFA for
7116 output_chip_member_name (FILE *f
, automaton_t automaton
)
7118 if (automaton
->corresponding_automaton_decl
== NULL
)
7119 fprintf (f
, "automaton_state_%d", automaton
->automaton_order_num
);
7121 fprintf (f
, "%s_automaton_state",
7122 automaton
->corresponding_automaton_decl
->name
);
7125 /* The following is name of temporary variable which stores state of a
7128 output_temp_chip_member_name (FILE *f
, automaton_t automaton
)
7131 output_chip_member_name (f
, automaton
);
7134 /* This is name of macro value which is code of pseudo_insn
7135 representing advancing cpu cycle. Its value is used as internal
7136 code unknown insn. */
7137 #define ADVANCE_CYCLE_VALUE_NAME "DFA__ADVANCE_CYCLE"
7139 /* Output name of translate vector for given automaton. */
7141 output_translate_vect_name (FILE *f
, automaton_t automaton
)
7143 if (automaton
->corresponding_automaton_decl
== NULL
)
7144 fprintf (f
, "translate_%d", automaton
->automaton_order_num
);
7146 fprintf (f
, "%s_translate", automaton
->corresponding_automaton_decl
->name
);
7149 /* Output name for simple transition table representation. */
7151 output_trans_full_vect_name (FILE *f
, automaton_t automaton
)
7153 if (automaton
->corresponding_automaton_decl
== NULL
)
7154 fprintf (f
, "transitions_%d", automaton
->automaton_order_num
);
7156 fprintf (f
, "%s_transitions",
7157 automaton
->corresponding_automaton_decl
->name
);
7160 /* Output name of comb vector of the transition table for given
7163 output_trans_comb_vect_name (FILE *f
, automaton_t automaton
)
7165 if (automaton
->corresponding_automaton_decl
== NULL
)
7166 fprintf (f
, "transitions_%d", automaton
->automaton_order_num
);
7168 fprintf (f
, "%s_transitions",
7169 automaton
->corresponding_automaton_decl
->name
);
7172 /* Output name of check vector of the transition table for given
7175 output_trans_check_vect_name (FILE *f
, automaton_t automaton
)
7177 if (automaton
->corresponding_automaton_decl
== NULL
)
7178 fprintf (f
, "check_%d", automaton
->automaton_order_num
);
7180 fprintf (f
, "%s_check", automaton
->corresponding_automaton_decl
->name
);
7183 /* Output name of base vector of the transition table for given
7186 output_trans_base_vect_name (FILE *f
, automaton_t automaton
)
7188 if (automaton
->corresponding_automaton_decl
== NULL
)
7189 fprintf (f
, "base_%d", automaton
->automaton_order_num
);
7191 fprintf (f
, "%s_base", automaton
->corresponding_automaton_decl
->name
);
7194 /* Output name for simple alternatives number representation. */
7196 output_state_alts_full_vect_name (FILE *f
, automaton_t automaton
)
7198 if (automaton
->corresponding_automaton_decl
== NULL
)
7199 fprintf (f
, "state_alts_%d", automaton
->automaton_order_num
);
7201 fprintf (f
, "%s_state_alts",
7202 automaton
->corresponding_automaton_decl
->name
);
7205 /* Output name of comb vector of the alternatives number table for given
7208 output_state_alts_comb_vect_name (FILE *f
, automaton_t automaton
)
7210 if (automaton
->corresponding_automaton_decl
== NULL
)
7211 fprintf (f
, "state_alts_%d", automaton
->automaton_order_num
);
7213 fprintf (f
, "%s_state_alts",
7214 automaton
->corresponding_automaton_decl
->name
);
7217 /* Output name of check vector of the alternatives number table for given
7220 output_state_alts_check_vect_name (FILE *f
, automaton_t automaton
)
7222 if (automaton
->corresponding_automaton_decl
== NULL
)
7223 fprintf (f
, "check_state_alts_%d", automaton
->automaton_order_num
);
7225 fprintf (f
, "%s_check_state_alts",
7226 automaton
->corresponding_automaton_decl
->name
);
7229 /* Output name of base vector of the alternatives number table for given
7232 output_state_alts_base_vect_name (FILE *f
, automaton_t automaton
)
7234 if (automaton
->corresponding_automaton_decl
== NULL
)
7235 fprintf (f
, "base_state_alts_%d", automaton
->automaton_order_num
);
7237 fprintf (f
, "%s_base_state_alts",
7238 automaton
->corresponding_automaton_decl
->name
);
7241 /* Output name of simple min issue delay table representation. */
7243 output_min_issue_delay_vect_name (FILE *f
, automaton_t automaton
)
7245 if (automaton
->corresponding_automaton_decl
== NULL
)
7246 fprintf (f
, "min_issue_delay_%d", automaton
->automaton_order_num
);
7248 fprintf (f
, "%s_min_issue_delay",
7249 automaton
->corresponding_automaton_decl
->name
);
7252 /* Output name of deadlock vector for given automaton. */
7254 output_dead_lock_vect_name (FILE *f
, automaton_t automaton
)
7256 if (automaton
->corresponding_automaton_decl
== NULL
)
7257 fprintf (f
, "dead_lock_%d", automaton
->automaton_order_num
);
7259 fprintf (f
, "%s_dead_lock", automaton
->corresponding_automaton_decl
->name
);
7262 /* Output name of reserved units table for AUTOMATON into file F. */
7264 output_reserved_units_table_name (FILE *f
, automaton_t automaton
)
7266 if (automaton
->corresponding_automaton_decl
== NULL
)
7267 fprintf (f
, "reserved_units_%d", automaton
->automaton_order_num
);
7269 fprintf (f
, "%s_reserved_units",
7270 automaton
->corresponding_automaton_decl
->name
);
7273 /* Name of the PHR interface macro. */
7274 #define AUTOMATON_STATE_ALTS_MACRO_NAME "AUTOMATON_STATE_ALTS"
7276 /* Name of the PHR interface macro. */
7277 #define CPU_UNITS_QUERY_MACRO_NAME "CPU_UNITS_QUERY"
7279 /* Names of an internal functions: */
7280 #define INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME "internal_min_issue_delay"
7282 /* This is external type of DFA(s) state. */
7283 #define STATE_TYPE_NAME "state_t"
7285 #define INTERNAL_TRANSITION_FUNC_NAME "internal_state_transition"
7287 #define INTERNAL_STATE_ALTS_FUNC_NAME "internal_state_alts"
7289 #define INTERNAL_RESET_FUNC_NAME "internal_reset"
7291 #define INTERNAL_DEAD_LOCK_FUNC_NAME "internal_state_dead_lock_p"
7293 #define INTERNAL_INSN_LATENCY_FUNC_NAME "internal_insn_latency"
7295 /* Name of cache of insn dfa codes. */
7296 #define DFA_INSN_CODES_VARIABLE_NAME "dfa_insn_codes"
7298 /* Name of length of cache of insn dfa codes. */
7299 #define DFA_INSN_CODES_LENGTH_VARIABLE_NAME "dfa_insn_codes_length"
7301 /* Names of the PHR interface functions: */
7302 #define SIZE_FUNC_NAME "state_size"
7304 #define TRANSITION_FUNC_NAME "state_transition"
7306 #define STATE_ALTS_FUNC_NAME "state_alts"
7308 #define MIN_ISSUE_DELAY_FUNC_NAME "min_issue_delay"
7310 #define MIN_INSN_CONFLICT_DELAY_FUNC_NAME "min_insn_conflict_delay"
7312 #define DEAD_LOCK_FUNC_NAME "state_dead_lock_p"
7314 #define RESET_FUNC_NAME "state_reset"
7316 #define INSN_LATENCY_FUNC_NAME "insn_latency"
7318 #define PRINT_RESERVATION_FUNC_NAME "print_reservation"
7320 #define GET_CPU_UNIT_CODE_FUNC_NAME "get_cpu_unit_code"
7322 #define CPU_UNIT_RESERVATION_P_FUNC_NAME "cpu_unit_reservation_p"
7324 #define DFA_CLEAN_INSN_CACHE_FUNC_NAME "dfa_clean_insn_cache"
7326 #define DFA_START_FUNC_NAME "dfa_start"
7328 #define DFA_FINISH_FUNC_NAME "dfa_finish"
7330 /* Names of parameters of the PHR interface functions. */
7331 #define STATE_NAME "state"
7333 #define INSN_PARAMETER_NAME "insn"
7335 #define INSN2_PARAMETER_NAME "insn2"
7337 #define CHIP_PARAMETER_NAME "chip"
7339 #define FILE_PARAMETER_NAME "f"
7341 #define CPU_UNIT_NAME_PARAMETER_NAME "cpu_unit_name"
7343 #define CPU_CODE_PARAMETER_NAME "cpu_unit_code"
7345 /* Names of the variables whose values are internal insn code of rtx
7347 #define INTERNAL_INSN_CODE_NAME "insn_code"
7349 #define INTERNAL_INSN2_CODE_NAME "insn2_code"
7351 /* Names of temporary variables in some functions. */
7352 #define TEMPORARY_VARIABLE_NAME "temp"
7354 #define I_VARIABLE_NAME "i"
7356 /* Name of result variable in some functions. */
7357 #define RESULT_VARIABLE_NAME "res"
7359 /* Name of function (attribute) to translate insn into internal insn
7361 #define INTERNAL_DFA_INSN_CODE_FUNC_NAME "internal_dfa_insn_code"
7363 /* Name of function (attribute) to translate insn into internal insn
7364 code with caching. */
7365 #define DFA_INSN_CODE_FUNC_NAME "dfa_insn_code"
7367 /* Name of function (attribute) to translate insn into internal insn
7369 #define INSN_DEFAULT_LATENCY_FUNC_NAME "insn_default_latency"
7371 /* Name of function (attribute) to translate insn into internal insn
7373 #define BYPASS_P_FUNC_NAME "bypass_p"
7375 /* Output C type which is used for representation of codes of states
7378 output_state_member_type (FILE *f
, automaton_t automaton
)
7380 output_range_type (f
, 0, automaton
->achieved_states_num
);
7383 /* Output definition of the structure representing current DFA(s)
7386 output_chip_definitions (void)
7388 automaton_t automaton
;
7390 fprintf (output_file
, "struct %s\n{\n", CHIP_NAME
);
7391 for (automaton
= description
->first_automaton
;
7393 automaton
= automaton
->next_automaton
)
7395 fprintf (output_file
, " ");
7396 output_state_member_type (output_file
, automaton
);
7397 fprintf (output_file
, " ");
7398 output_chip_member_name (output_file
, automaton
);
7399 fprintf (output_file
, ";\n");
7401 fprintf (output_file
, "};\n\n");
7403 fprintf (output_file
, "static struct %s %s;\n\n", CHIP_NAME
, CHIP_NAME
);
7408 /* The function outputs translate vector of internal insn code into
7409 insn equivalence class number. The equivalence class number is
7410 used to access to table and vectors representing DFA(s). */
7412 output_translate_vect (automaton_t automaton
)
7416 vla_hwint_t translate_vect
;
7418 VLA_HWINT_CREATE (translate_vect
, 250, "translate vector");
7419 VLA_HWINT_EXPAND (translate_vect
, description
->insns_num
);
7420 for (insn_value
= 0; insn_value
< description
->insns_num
; insn_value
++)
7421 /* Undefined value */
7422 VLA_HWINT (translate_vect
, insn_value
) = automaton
->insn_equiv_classes_num
;
7423 for (ainsn
= automaton
->ainsn_list
; ainsn
!= NULL
; ainsn
= ainsn
->next_ainsn
)
7424 VLA_HWINT (translate_vect
, ainsn
->insn_reserv_decl
->insn_num
)
7425 = ainsn
->insn_equiv_class_num
;
7426 fprintf (output_file
,
7427 "/* Vector translating external insn codes to internal ones.*/\n");
7428 fprintf (output_file
, "static const ");
7429 output_range_type (output_file
, 0, automaton
->insn_equiv_classes_num
);
7430 fprintf (output_file
, " ");
7431 output_translate_vect_name (output_file
, automaton
);
7432 fprintf (output_file
, "[] ATTRIBUTE_UNUSED = {\n");
7433 output_vect (VLA_HWINT_BEGIN (translate_vect
),
7434 VLA_HWINT_LENGTH (translate_vect
));
7435 fprintf (output_file
, "};\n\n");
7436 VLA_HWINT_DELETE (translate_vect
);
7439 /* The value in a table state x ainsn -> something which represents
7441 static int undefined_vect_el_value
;
7443 /* The following function returns nonzero value if the best
7444 representation of the table is comb vector. */
7446 comb_vect_p (state_ainsn_table_t tab
)
7448 return (2 * VLA_HWINT_LENGTH (tab
->full_vect
)
7449 > 5 * VLA_HWINT_LENGTH (tab
->comb_vect
));
7452 /* The following function creates new table for AUTOMATON. */
7453 static state_ainsn_table_t
7454 create_state_ainsn_table (automaton_t automaton
)
7456 state_ainsn_table_t tab
;
7457 int full_vect_length
;
7460 tab
= create_node (sizeof (struct state_ainsn_table
));
7461 tab
->automaton
= automaton
;
7462 VLA_HWINT_CREATE (tab
->comb_vect
, 10000, "comb vector");
7463 VLA_HWINT_CREATE (tab
->check_vect
, 10000, "check vector");
7464 VLA_HWINT_CREATE (tab
->base_vect
, 1000, "base vector");
7465 VLA_HWINT_EXPAND (tab
->base_vect
, automaton
->achieved_states_num
);
7466 VLA_HWINT_CREATE (tab
->full_vect
, 10000, "full vector");
7467 full_vect_length
= (automaton
->insn_equiv_classes_num
7468 * automaton
->achieved_states_num
);
7469 VLA_HWINT_EXPAND (tab
->full_vect
, full_vect_length
);
7470 for (i
= 0; i
< full_vect_length
; i
++)
7471 VLA_HWINT (tab
->full_vect
, i
) = undefined_vect_el_value
;
7472 tab
->min_base_vect_el_value
= 0;
7473 tab
->max_base_vect_el_value
= 0;
7474 tab
->min_comb_vect_el_value
= 0;
7475 tab
->max_comb_vect_el_value
= 0;
7479 /* The following function outputs the best C representation of the
7480 table TAB of given TABLE_NAME. */
7482 output_state_ainsn_table (state_ainsn_table_t tab
, char *table_name
,
7483 void (*output_full_vect_name_func
) (FILE *, automaton_t
),
7484 void (*output_comb_vect_name_func
) (FILE *, automaton_t
),
7485 void (*output_check_vect_name_func
) (FILE *, automaton_t
),
7486 void (*output_base_vect_name_func
) (FILE *, automaton_t
))
7488 if (!comb_vect_p (tab
))
7490 fprintf (output_file
, "/* Vector for %s. */\n", table_name
);
7491 fprintf (output_file
, "static const ");
7492 output_range_type (output_file
, tab
->min_comb_vect_el_value
,
7493 tab
->max_comb_vect_el_value
);
7494 fprintf (output_file
, " ");
7495 (*output_full_vect_name_func
) (output_file
, tab
->automaton
);
7496 fprintf (output_file
, "[] ATTRIBUTE_UNUSED = {\n");
7497 output_vect (VLA_HWINT_BEGIN (tab
->full_vect
),
7498 VLA_HWINT_LENGTH (tab
->full_vect
));
7499 fprintf (output_file
, "};\n\n");
7503 fprintf (output_file
, "/* Comb vector for %s. */\n", table_name
);
7504 fprintf (output_file
, "static const ");
7505 output_range_type (output_file
, tab
->min_comb_vect_el_value
,
7506 tab
->max_comb_vect_el_value
);
7507 fprintf (output_file
, " ");
7508 (*output_comb_vect_name_func
) (output_file
, tab
->automaton
);
7509 fprintf (output_file
, "[] ATTRIBUTE_UNUSED = {\n");
7510 output_vect (VLA_HWINT_BEGIN (tab
->comb_vect
),
7511 VLA_HWINT_LENGTH (tab
->comb_vect
));
7512 fprintf (output_file
, "};\n\n");
7513 fprintf (output_file
, "/* Check vector for %s. */\n", table_name
);
7514 fprintf (output_file
, "static const ");
7515 output_range_type (output_file
, 0, tab
->automaton
->achieved_states_num
);
7516 fprintf (output_file
, " ");
7517 (*output_check_vect_name_func
) (output_file
, tab
->automaton
);
7518 fprintf (output_file
, "[] = {\n");
7519 output_vect (VLA_HWINT_BEGIN (tab
->check_vect
),
7520 VLA_HWINT_LENGTH (tab
->check_vect
));
7521 fprintf (output_file
, "};\n\n");
7522 fprintf (output_file
, "/* Base vector for %s. */\n", table_name
);
7523 fprintf (output_file
, "static const ");
7524 output_range_type (output_file
, tab
->min_base_vect_el_value
,
7525 tab
->max_base_vect_el_value
);
7526 fprintf (output_file
, " ");
7527 (*output_base_vect_name_func
) (output_file
, tab
->automaton
);
7528 fprintf (output_file
, "[] = {\n");
7529 output_vect (VLA_HWINT_BEGIN (tab
->base_vect
),
7530 VLA_HWINT_LENGTH (tab
->base_vect
));
7531 fprintf (output_file
, "};\n\n");
7535 /* The following function adds vector with length VECT_LENGTH and
7536 elements pointed by VECT to table TAB as its line with number
7539 add_vect (state_ainsn_table_t tab
, int vect_num
, vect_el_t
*vect
,
7542 int real_vect_length
;
7543 vect_el_t
*comb_vect_start
;
7544 vect_el_t
*check_vect_start
;
7545 int comb_vect_index
;
7546 int comb_vect_els_num
;
7548 int first_unempty_vect_index
;
7549 int additional_els_num
;
7554 if (vect_length
== 0)
7556 real_vect_length
= tab
->automaton
->insn_equiv_classes_num
;
7557 if (vect
[vect_length
- 1] == undefined_vect_el_value
)
7559 /* Form full vector in the table: */
7560 for (i
= 0; i
< vect_length
; i
++)
7561 VLA_HWINT (tab
->full_vect
,
7562 i
+ tab
->automaton
->insn_equiv_classes_num
* vect_num
)
7564 /* Form comb vector in the table: */
7565 if (VLA_HWINT_LENGTH (tab
->comb_vect
) != VLA_HWINT_LENGTH (tab
->check_vect
))
7567 comb_vect_start
= VLA_HWINT_BEGIN (tab
->comb_vect
);
7568 comb_vect_els_num
= VLA_HWINT_LENGTH (tab
->comb_vect
);
7569 for (first_unempty_vect_index
= 0;
7570 first_unempty_vect_index
< vect_length
;
7571 first_unempty_vect_index
++)
7572 if (vect
[first_unempty_vect_index
] != undefined_vect_el_value
)
7574 /* Search for the place in comb vect for the inserted vect. */
7575 for (comb_vect_index
= 0;
7576 comb_vect_index
< comb_vect_els_num
;
7579 for (vect_index
= first_unempty_vect_index
;
7580 vect_index
< vect_length
7581 && vect_index
+ comb_vect_index
< comb_vect_els_num
;
7583 if (vect
[vect_index
] != undefined_vect_el_value
7584 && (comb_vect_start
[vect_index
+ comb_vect_index
]
7585 != undefined_vect_el_value
))
7587 if (vect_index
>= vect_length
7588 || vect_index
+ comb_vect_index
>= comb_vect_els_num
)
7591 /* Slot was found. */
7592 additional_els_num
= comb_vect_index
+ real_vect_length
- comb_vect_els_num
;
7593 if (additional_els_num
< 0)
7594 additional_els_num
= 0;
7595 /* Expand comb and check vectors. */
7596 vect_el
= undefined_vect_el_value
;
7597 no_state_value
= tab
->automaton
->achieved_states_num
;
7598 while (additional_els_num
> 0)
7600 VLA_HWINT_ADD (tab
->comb_vect
, vect_el
);
7601 VLA_HWINT_ADD (tab
->check_vect
, no_state_value
);
7602 additional_els_num
--;
7604 comb_vect_start
= VLA_HWINT_BEGIN (tab
->comb_vect
);
7605 check_vect_start
= VLA_HWINT_BEGIN (tab
->check_vect
);
7606 if (VLA_HWINT_LENGTH (tab
->comb_vect
)
7607 < (size_t) (comb_vect_index
+ real_vect_length
))
7609 /* Fill comb and check vectors. */
7610 for (vect_index
= 0; vect_index
< vect_length
; vect_index
++)
7611 if (vect
[vect_index
] != undefined_vect_el_value
)
7613 if (comb_vect_start
[comb_vect_index
+ vect_index
]
7614 != undefined_vect_el_value
)
7616 comb_vect_start
[comb_vect_index
+ vect_index
] = vect
[vect_index
];
7617 if (vect
[vect_index
] < 0)
7619 if (tab
->max_comb_vect_el_value
< vect
[vect_index
])
7620 tab
->max_comb_vect_el_value
= vect
[vect_index
];
7621 if (tab
->min_comb_vect_el_value
> vect
[vect_index
])
7622 tab
->min_comb_vect_el_value
= vect
[vect_index
];
7623 check_vect_start
[comb_vect_index
+ vect_index
] = vect_num
;
7625 if (tab
->max_comb_vect_el_value
< undefined_vect_el_value
)
7626 tab
->max_comb_vect_el_value
= undefined_vect_el_value
;
7627 if (tab
->min_comb_vect_el_value
> undefined_vect_el_value
)
7628 tab
->min_comb_vect_el_value
= undefined_vect_el_value
;
7629 if (tab
->max_base_vect_el_value
< comb_vect_index
)
7630 tab
->max_base_vect_el_value
= comb_vect_index
;
7631 if (tab
->min_base_vect_el_value
> comb_vect_index
)
7632 tab
->min_base_vect_el_value
= comb_vect_index
;
7633 VLA_HWINT (tab
->base_vect
, vect_num
) = comb_vect_index
;
7636 /* Return number of out arcs of STATE. */
7638 out_state_arcs_num (state_t state
)
7644 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
7646 if (arc
->insn
== NULL
)
7648 if (arc
->insn
->first_ainsn_with_given_equialence_num
)
7654 /* Compare number of possible transitions from the states. */
7656 compare_transition_els_num (const void *state_ptr_1
,
7657 const void *state_ptr_2
)
7659 int transition_els_num_1
;
7660 int transition_els_num_2
;
7662 transition_els_num_1
= out_state_arcs_num (*(state_t
*) state_ptr_1
);
7663 transition_els_num_2
= out_state_arcs_num (*(state_t
*) state_ptr_2
);
7664 if (transition_els_num_1
< transition_els_num_2
)
7666 else if (transition_els_num_1
== transition_els_num_2
)
7672 /* The function adds element EL_VALUE to vector VECT for a table state
7675 add_vect_el (vla_hwint_t
*vect
, ainsn_t ainsn
, int el_value
)
7677 int equiv_class_num
;
7682 equiv_class_num
= ainsn
->insn_equiv_class_num
;
7683 for (vect_index
= VLA_HWINT_LENGTH (*vect
);
7684 vect_index
<= equiv_class_num
;
7686 VLA_HWINT_ADD (*vect
, undefined_vect_el_value
);
7687 VLA_HWINT (*vect
, equiv_class_num
) = el_value
;
7690 /* This is for forming vector of states of an automaton. */
7691 static vla_ptr_t output_states_vect
;
7693 /* The function is called by function pass_states. The function adds
7694 STATE to `output_states_vect'. */
7696 add_states_vect_el (state_t state
)
7698 VLA_PTR_ADD (output_states_vect
, state
);
7701 /* Form and output vectors (comb, check, base or full vector)
7702 representing transition table of AUTOMATON. */
7704 output_trans_table (automaton_t automaton
)
7708 vla_hwint_t transition_vect
;
7710 undefined_vect_el_value
= automaton
->achieved_states_num
;
7711 automaton
->trans_table
= create_state_ainsn_table (automaton
);
7712 /* Create vect of pointers to states ordered by num of transitions
7713 from the state (state with the maximum num is the first). */
7714 VLA_PTR_CREATE (output_states_vect
, 1500, "output states vector");
7715 pass_states (automaton
, add_states_vect_el
);
7716 qsort (VLA_PTR_BEGIN (output_states_vect
),
7717 VLA_PTR_LENGTH (output_states_vect
),
7718 sizeof (state_t
), compare_transition_els_num
);
7719 VLA_HWINT_CREATE (transition_vect
, 500, "transition vector");
7720 for (state_ptr
= VLA_PTR_BEGIN (output_states_vect
);
7721 state_ptr
<= (state_t
*) VLA_PTR_LAST (output_states_vect
);
7724 VLA_HWINT_NULLIFY (transition_vect
);
7725 for (arc
= first_out_arc (*state_ptr
);
7727 arc
= next_out_arc (arc
))
7729 if (arc
->insn
== NULL
)
7731 if (arc
->insn
->first_ainsn_with_given_equialence_num
)
7732 add_vect_el (&transition_vect
, arc
->insn
,
7733 arc
->to_state
->order_state_num
);
7735 add_vect (automaton
->trans_table
, (*state_ptr
)->order_state_num
,
7736 VLA_HWINT_BEGIN (transition_vect
),
7737 VLA_HWINT_LENGTH (transition_vect
));
7739 output_state_ainsn_table
7740 (automaton
->trans_table
, (char *) "state transitions",
7741 output_trans_full_vect_name
, output_trans_comb_vect_name
,
7742 output_trans_check_vect_name
, output_trans_base_vect_name
);
7743 VLA_PTR_DELETE (output_states_vect
);
7744 VLA_HWINT_DELETE (transition_vect
);
7747 /* Form and output vectors (comb, check, base or simple vect)
7748 representing alts number table of AUTOMATON. The table is state x
7749 ainsn -> number of possible alternative reservations by the
7752 output_state_alts_table (automaton_t automaton
)
7756 vla_hwint_t state_alts_vect
;
7758 undefined_vect_el_value
= 0; /* no alts when transition is not possible */
7759 automaton
->state_alts_table
= create_state_ainsn_table (automaton
);
7760 /* Create vect of pointers to states ordered by num of transitions
7761 from the state (state with the maximum num is the first). */
7762 VLA_PTR_CREATE (output_states_vect
, 1500, "output states vector");
7763 pass_states (automaton
, add_states_vect_el
);
7764 qsort (VLA_PTR_BEGIN (output_states_vect
),
7765 VLA_PTR_LENGTH (output_states_vect
),
7766 sizeof (state_t
), compare_transition_els_num
);
7767 /* Create base, comb, and check vectors. */
7768 VLA_HWINT_CREATE (state_alts_vect
, 500, "state alts vector");
7769 for (state_ptr
= VLA_PTR_BEGIN (output_states_vect
);
7770 state_ptr
<= (state_t
*) VLA_PTR_LAST (output_states_vect
);
7773 VLA_HWINT_NULLIFY (state_alts_vect
);
7774 for (arc
= first_out_arc (*state_ptr
);
7776 arc
= next_out_arc (arc
))
7778 if (arc
->insn
== NULL
)
7780 if (arc
->insn
->first_ainsn_with_given_equialence_num
)
7781 add_vect_el (&state_alts_vect
, arc
->insn
, arc
->state_alts
);
7783 add_vect (automaton
->state_alts_table
, (*state_ptr
)->order_state_num
,
7784 VLA_HWINT_BEGIN (state_alts_vect
),
7785 VLA_HWINT_LENGTH (state_alts_vect
));
7787 output_state_ainsn_table
7788 (automaton
->state_alts_table
, (char *) "state insn alternatives",
7789 output_state_alts_full_vect_name
, output_state_alts_comb_vect_name
,
7790 output_state_alts_check_vect_name
, output_state_alts_base_vect_name
);
7791 VLA_PTR_DELETE (output_states_vect
);
7792 VLA_HWINT_DELETE (state_alts_vect
);
7795 /* The current number of passing states to find minimal issue delay
7796 value for an ainsn and state. */
7797 static int curr_state_pass_num
;
7799 /* This recursive function passes states to find minimal issue delay
7800 value for AINSN. The state being visited is STATE. The function
7801 returns minimal issue delay value for AINSN in STATE or -1 if we
7802 enter into a loop. */
7804 min_issue_delay_pass_states (state_t state
, ainsn_t ainsn
)
7807 int min_insn_issue_delay
, insn_issue_delay
;
7809 if (state
->state_pass_num
== curr_state_pass_num
7810 || state
->min_insn_issue_delay
!= -1)
7811 /* We've entered into a loop or already have the correct value for
7812 given state and ainsn. */
7813 return state
->min_insn_issue_delay
;
7814 state
->state_pass_num
= curr_state_pass_num
;
7815 min_insn_issue_delay
= -1;
7816 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
7817 if (arc
->insn
== ainsn
)
7819 min_insn_issue_delay
= 0;
7824 insn_issue_delay
= min_issue_delay_pass_states (arc
->to_state
, ainsn
);
7825 if (insn_issue_delay
!= -1)
7827 if (arc
->insn
->insn_reserv_decl
7828 == DECL_INSN_RESERV (advance_cycle_insn_decl
))
7830 if (min_insn_issue_delay
== -1
7831 || min_insn_issue_delay
> insn_issue_delay
)
7833 min_insn_issue_delay
= insn_issue_delay
;
7834 if (insn_issue_delay
== 0)
7839 return min_insn_issue_delay
;
7842 /* The function searches minimal issue delay value for AINSN in STATE.
7843 The function can return negative value if we can not issue AINSN. We
7844 will report about it later. */
7846 min_issue_delay (state_t state
, ainsn_t ainsn
)
7848 curr_state_pass_num
++;
7849 state
->min_insn_issue_delay
= min_issue_delay_pass_states (state
, ainsn
);
7850 return state
->min_insn_issue_delay
;
7853 /* The function initiates code for finding minimal issue delay values.
7854 It should be called only once. */
7856 initiate_min_issue_delay_pass_states (void)
7858 curr_state_pass_num
= 0;
7861 /* Form and output vectors representing minimal issue delay table of
7862 AUTOMATON. The table is state x ainsn -> minimal issue delay of
7865 output_min_issue_delay_table (automaton_t automaton
)
7867 vla_hwint_t min_issue_delay_vect
;
7868 vla_hwint_t compressed_min_issue_delay_vect
;
7869 vect_el_t min_delay
;
7874 /* Create vect of pointers to states ordered by num of transitions
7875 from the state (state with the maximum num is the first). */
7876 VLA_PTR_CREATE (output_states_vect
, 1500, "output states vector");
7877 pass_states (automaton
, add_states_vect_el
);
7878 VLA_HWINT_CREATE (min_issue_delay_vect
, 1500, "min issue delay vector");
7879 VLA_HWINT_EXPAND (min_issue_delay_vect
,
7880 VLA_HWINT_LENGTH (output_states_vect
)
7881 * automaton
->insn_equiv_classes_num
);
7883 i
< ((int) VLA_HWINT_LENGTH (output_states_vect
)
7884 * automaton
->insn_equiv_classes_num
);
7886 VLA_HWINT (min_issue_delay_vect
, i
) = 0;
7887 automaton
->max_min_delay
= 0;
7888 for (ainsn
= automaton
->ainsn_list
; ainsn
!= NULL
; ainsn
= ainsn
->next_ainsn
)
7889 if (ainsn
->first_ainsn_with_given_equialence_num
)
7891 for (state_ptr
= VLA_PTR_BEGIN (output_states_vect
);
7892 state_ptr
<= (state_t
*) VLA_PTR_LAST (output_states_vect
);
7894 (*state_ptr
)->min_insn_issue_delay
= -1;
7895 for (state_ptr
= VLA_PTR_BEGIN (output_states_vect
);
7896 state_ptr
<= (state_t
*) VLA_PTR_LAST (output_states_vect
);
7899 min_delay
= min_issue_delay (*state_ptr
, ainsn
);
7900 if (automaton
->max_min_delay
< min_delay
)
7901 automaton
->max_min_delay
= min_delay
;
7902 VLA_HWINT (min_issue_delay_vect
,
7903 (*state_ptr
)->order_state_num
7904 * automaton
->insn_equiv_classes_num
7905 + ainsn
->insn_equiv_class_num
) = min_delay
;
7908 fprintf (output_file
, "/* Vector of min issue delay of insns. */\n");
7909 fprintf (output_file
, "static const ");
7910 output_range_type (output_file
, 0, automaton
->max_min_delay
);
7911 fprintf (output_file
, " ");
7912 output_min_issue_delay_vect_name (output_file
, automaton
);
7913 fprintf (output_file
, "[] ATTRIBUTE_UNUSED = {\n");
7914 /* Compress the vector. */
7915 if (automaton
->max_min_delay
< 2)
7916 automaton
->min_issue_delay_table_compression_factor
= 8;
7917 else if (automaton
->max_min_delay
< 4)
7918 automaton
->min_issue_delay_table_compression_factor
= 4;
7919 else if (automaton
->max_min_delay
< 16)
7920 automaton
->min_issue_delay_table_compression_factor
= 2;
7922 automaton
->min_issue_delay_table_compression_factor
= 1;
7923 VLA_HWINT_CREATE (compressed_min_issue_delay_vect
, 1500,
7924 "compressed min issue delay vector");
7925 VLA_HWINT_EXPAND (compressed_min_issue_delay_vect
,
7926 (VLA_HWINT_LENGTH (min_issue_delay_vect
)
7927 + automaton
->min_issue_delay_table_compression_factor
7929 / automaton
->min_issue_delay_table_compression_factor
);
7931 i
< (int) VLA_HWINT_LENGTH (compressed_min_issue_delay_vect
);
7933 VLA_HWINT (compressed_min_issue_delay_vect
, i
) = 0;
7934 for (i
= 0; i
< (int) VLA_HWINT_LENGTH (min_issue_delay_vect
); i
++)
7935 VLA_HWINT (compressed_min_issue_delay_vect
,
7936 i
/ automaton
->min_issue_delay_table_compression_factor
)
7937 |= (VLA_HWINT (min_issue_delay_vect
, i
)
7938 << (8 - (i
% automaton
->min_issue_delay_table_compression_factor
7940 * (8 / automaton
->min_issue_delay_table_compression_factor
)));
7941 output_vect (VLA_HWINT_BEGIN (compressed_min_issue_delay_vect
),
7942 VLA_HWINT_LENGTH (compressed_min_issue_delay_vect
));
7943 fprintf (output_file
, "};\n\n");
7944 VLA_PTR_DELETE (output_states_vect
);
7945 VLA_HWINT_DELETE (min_issue_delay_vect
);
7946 VLA_HWINT_DELETE (compressed_min_issue_delay_vect
);
7950 /* Number of states which contains transition only by advancing cpu
7952 static int locked_states_num
;
7955 /* Form and output vector representing the locked states of
7958 output_dead_lock_vect (automaton_t automaton
)
7962 vla_hwint_t dead_lock_vect
;
7964 /* Create vect of pointers to states ordered by num of
7965 transitions from the state (state with the maximum num is the
7967 VLA_PTR_CREATE (output_states_vect
, 1500, "output states vector");
7968 pass_states (automaton
, add_states_vect_el
);
7969 VLA_HWINT_CREATE (dead_lock_vect
, 1500, "is dead locked vector");
7970 VLA_HWINT_EXPAND (dead_lock_vect
, VLA_HWINT_LENGTH (output_states_vect
));
7971 for (state_ptr
= VLA_PTR_BEGIN (output_states_vect
);
7972 state_ptr
<= (state_t
*) VLA_PTR_LAST (output_states_vect
);
7975 arc
= first_out_arc (*state_ptr
);
7978 VLA_HWINT (dead_lock_vect
, (*state_ptr
)->order_state_num
)
7979 = (next_out_arc (arc
) == NULL
7980 && (arc
->insn
->insn_reserv_decl
7981 == DECL_INSN_RESERV (advance_cycle_insn_decl
)) ? 1 : 0);
7983 if (VLA_HWINT (dead_lock_vect
, (*state_ptr
)->order_state_num
))
7984 locked_states_num
++;
7987 fprintf (output_file
, "/* Vector for locked state flags. */\n");
7988 fprintf (output_file
, "static const ");
7989 output_range_type (output_file
, 0, 1);
7990 fprintf (output_file
, " ");
7991 output_dead_lock_vect_name (output_file
, automaton
);
7992 fprintf (output_file
, "[] = {\n");
7993 output_vect (VLA_HWINT_BEGIN (dead_lock_vect
),
7994 VLA_HWINT_LENGTH (dead_lock_vect
));
7995 fprintf (output_file
, "};\n\n");
7996 VLA_HWINT_DELETE (dead_lock_vect
);
7997 VLA_PTR_DELETE (output_states_vect
);
8000 /* Form and output vector representing reserved units of the states of
8003 output_reserved_units_table (automaton_t automaton
)
8005 state_t
*curr_state_ptr
;
8006 vla_hwint_t reserved_units_table
;
8007 size_t state_byte_size
;
8010 /* Create vect of pointers to states. */
8011 VLA_PTR_CREATE (output_states_vect
, 1500, "output states vector");
8012 pass_states (automaton
, add_states_vect_el
);
8013 /* Create vector. */
8014 VLA_HWINT_CREATE (reserved_units_table
, 1500, "reserved units vector");
8015 state_byte_size
= (description
->query_units_num
+ 7) / 8;
8016 VLA_HWINT_EXPAND (reserved_units_table
,
8017 VLA_HWINT_LENGTH (output_states_vect
) * state_byte_size
);
8019 i
< (int) (VLA_HWINT_LENGTH (output_states_vect
) * state_byte_size
);
8021 VLA_HWINT (reserved_units_table
, i
) = 0;
8022 for (curr_state_ptr
= VLA_PTR_BEGIN (output_states_vect
);
8023 curr_state_ptr
<= (state_t
*) VLA_PTR_LAST (output_states_vect
);
8026 for (i
= 0; i
< description
->units_num
; i
++)
8027 if (units_array
[i
]->query_p
8028 && first_cycle_unit_presence (*curr_state_ptr
, i
))
8029 VLA_HWINT (reserved_units_table
,
8030 (*curr_state_ptr
)->order_state_num
* state_byte_size
8031 + units_array
[i
]->query_num
/ 8)
8032 += (1 << (units_array
[i
]->query_num
% 8));
8034 fprintf (output_file
, "/* Vector for reserved units of states. */\n");
8035 fprintf (output_file
, "static const ");
8036 output_range_type (output_file
, 0, 255);
8037 fprintf (output_file
, " ");
8038 output_reserved_units_table_name (output_file
, automaton
);
8039 fprintf (output_file
, "[] = {\n");
8040 output_vect (VLA_HWINT_BEGIN (reserved_units_table
),
8041 VLA_HWINT_LENGTH (reserved_units_table
));
8042 fprintf (output_file
, "};\n\n");
8043 VLA_HWINT_DELETE (reserved_units_table
);
8044 VLA_PTR_DELETE (output_states_vect
);
8047 /* The function outputs all tables representing DFA(s) used for fast
8048 pipeline hazards recognition. */
8050 output_tables (void)
8052 automaton_t automaton
;
8055 locked_states_num
= 0;
8057 initiate_min_issue_delay_pass_states ();
8058 for (automaton
= description
->first_automaton
;
8060 automaton
= automaton
->next_automaton
)
8062 output_translate_vect (automaton
);
8063 output_trans_table (automaton
);
8064 fprintf (output_file
, "\n#if %s\n", AUTOMATON_STATE_ALTS_MACRO_NAME
);
8065 output_state_alts_table (automaton
);
8066 fprintf (output_file
, "\n#endif /* #if %s */\n\n",
8067 AUTOMATON_STATE_ALTS_MACRO_NAME
);
8068 output_min_issue_delay_table (automaton
);
8069 output_dead_lock_vect (automaton
);
8070 fprintf (output_file
, "\n#if %s\n\n", CPU_UNITS_QUERY_MACRO_NAME
);
8071 output_reserved_units_table (automaton
);
8072 fprintf (output_file
, "\n#endif /* #if %s */\n\n",
8073 CPU_UNITS_QUERY_MACRO_NAME
);
8075 fprintf (output_file
, "\n#define %s %d\n\n", ADVANCE_CYCLE_VALUE_NAME
,
8076 DECL_INSN_RESERV (advance_cycle_insn_decl
)->insn_num
);
8079 /* The function outputs definition and value of PHR interface variable
8080 `max_insn_queue_index'. Its value is not less than maximal queue
8081 length needed for the insn scheduler. */
8083 output_max_insn_queue_index_def (void)
8085 int i
, max
, latency
;
8088 max
= description
->max_insn_reserv_cycles
;
8089 for (i
= 0; i
< description
->decls_num
; i
++)
8091 decl
= description
->decls
[i
];
8092 if (decl
->mode
== dm_insn_reserv
&& decl
!= advance_cycle_insn_decl
)
8094 latency
= DECL_INSN_RESERV (decl
)->default_latency
;
8098 else if (decl
->mode
== dm_bypass
)
8100 latency
= DECL_BYPASS (decl
)->latency
;
8105 for (i
= 0; (1 << i
) <= max
; i
++)
8109 fprintf (output_file
, "\nint max_insn_queue_index = %d;\n\n", (1 << i
) - 1);
8113 /* The function outputs switch cases for insn reservations using
8114 function *output_automata_list_code. */
8116 output_insn_code_cases (void (*output_automata_list_code
)
8117 (automata_list_el_t
))
8122 for (i
= 0; i
< description
->decls_num
; i
++)
8124 decl
= description
->decls
[i
];
8125 if (decl
->mode
== dm_insn_reserv
)
8126 DECL_INSN_RESERV (decl
)->processed_p
= FALSE
;
8128 for (i
= 0; i
< description
->decls_num
; i
++)
8130 decl
= description
->decls
[i
];
8131 if (decl
->mode
== dm_insn_reserv
8132 && !DECL_INSN_RESERV (decl
)->processed_p
)
8134 for (j
= i
; j
< description
->decls_num
; j
++)
8136 decl2
= description
->decls
[j
];
8137 if (decl2
->mode
== dm_insn_reserv
8138 && (DECL_INSN_RESERV (decl2
)->important_automata_list
8139 == DECL_INSN_RESERV (decl
)->important_automata_list
))
8141 DECL_INSN_RESERV (decl2
)->processed_p
= TRUE
;
8142 fprintf (output_file
, " case %d: /* %s */\n",
8143 DECL_INSN_RESERV (decl2
)->insn_num
,
8144 DECL_INSN_RESERV (decl2
)->name
);
8147 (*output_automata_list_code
)
8148 (DECL_INSN_RESERV (decl
)->important_automata_list
);
8154 /* The function outputs a code for evaluation of a minimal delay of
8155 issue of insns which have reservations in given AUTOMATA_LIST. */
8157 output_automata_list_min_issue_delay_code (automata_list_el_t automata_list
)
8159 automata_list_el_t el
;
8160 automaton_t automaton
;
8162 for (el
= automata_list
; el
!= NULL
; el
= el
->next_automata_list_el
)
8164 automaton
= el
->automaton
;
8165 fprintf (output_file
, "\n %s = ", TEMPORARY_VARIABLE_NAME
);
8166 output_min_issue_delay_vect_name (output_file
, automaton
);
8167 fprintf (output_file
,
8168 (automaton
->min_issue_delay_table_compression_factor
!= 1
8170 output_translate_vect_name (output_file
, automaton
);
8171 fprintf (output_file
, " [%s] + ", INTERNAL_INSN_CODE_NAME
);
8172 fprintf (output_file
, "%s->", CHIP_PARAMETER_NAME
);
8173 output_chip_member_name (output_file
, automaton
);
8174 fprintf (output_file
, " * %d", automaton
->insn_equiv_classes_num
);
8175 if (automaton
->min_issue_delay_table_compression_factor
== 1)
8176 fprintf (output_file
, "];\n");
8179 fprintf (output_file
, ") / %d];\n",
8180 automaton
->min_issue_delay_table_compression_factor
);
8181 fprintf (output_file
, " %s = (%s >> (8 - (",
8182 TEMPORARY_VARIABLE_NAME
, TEMPORARY_VARIABLE_NAME
);
8183 output_translate_vect_name (output_file
, automaton
);
8185 (output_file
, " [%s] %% %d + 1) * %d)) & %d;\n",
8186 INTERNAL_INSN_CODE_NAME
,
8187 automaton
->min_issue_delay_table_compression_factor
,
8188 8 / automaton
->min_issue_delay_table_compression_factor
,
8189 (1 << (8 / automaton
->min_issue_delay_table_compression_factor
))
8192 if (el
== automata_list
)
8193 fprintf (output_file
, " %s = %s;\n",
8194 RESULT_VARIABLE_NAME
, TEMPORARY_VARIABLE_NAME
);
8197 fprintf (output_file
, " if (%s > %s)\n",
8198 TEMPORARY_VARIABLE_NAME
, RESULT_VARIABLE_NAME
);
8199 fprintf (output_file
, " %s = %s;\n",
8200 RESULT_VARIABLE_NAME
, TEMPORARY_VARIABLE_NAME
);
8203 fprintf (output_file
, " break;\n\n");
8206 /* Output function `internal_min_issue_delay'. */
8208 output_internal_min_issue_delay_func (void)
8210 fprintf (output_file
,
8211 "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
8212 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
8213 CHIP_NAME
, CHIP_PARAMETER_NAME
);
8214 fprintf (output_file
, "{\n int %s ATTRIBUTE_UNUSED;\n int %s = -1;\n",
8215 TEMPORARY_VARIABLE_NAME
, RESULT_VARIABLE_NAME
);
8216 fprintf (output_file
, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME
);
8217 output_insn_code_cases (output_automata_list_min_issue_delay_code
);
8218 fprintf (output_file
,
8219 "\n default:\n %s = -1;\n break;\n }\n",
8220 RESULT_VARIABLE_NAME
);
8221 fprintf (output_file
, " return %s;\n", RESULT_VARIABLE_NAME
);
8222 fprintf (output_file
, "}\n\n");
8225 /* The function outputs a code changing state after issue of insns
8226 which have reservations in given AUTOMATA_LIST. */
8228 output_automata_list_transition_code (automata_list_el_t automata_list
)
8230 automata_list_el_t el
, next_el
;
8232 fprintf (output_file
, " {\n");
8233 if (automata_list
!= NULL
&& automata_list
->next_automata_list_el
!= NULL
)
8234 for (el
= automata_list
;; el
= next_el
)
8236 next_el
= el
->next_automata_list_el
;
8237 if (next_el
== NULL
)
8239 fprintf (output_file
, " ");
8240 output_state_member_type (output_file
, el
->automaton
);
8241 fprintf (output_file
, " ");
8242 output_temp_chip_member_name (output_file
, el
->automaton
);
8243 fprintf (output_file
, ";\n");
8245 for (el
= automata_list
; el
!= NULL
; el
= el
->next_automata_list_el
)
8246 if (comb_vect_p (el
->automaton
->trans_table
))
8248 fprintf (output_file
, "\n %s = ", TEMPORARY_VARIABLE_NAME
);
8249 output_trans_base_vect_name (output_file
, el
->automaton
);
8250 fprintf (output_file
, " [%s->", CHIP_PARAMETER_NAME
);
8251 output_chip_member_name (output_file
, el
->automaton
);
8252 fprintf (output_file
, "] + ");
8253 output_translate_vect_name (output_file
, el
->automaton
);
8254 fprintf (output_file
, " [%s];\n", INTERNAL_INSN_CODE_NAME
);
8255 fprintf (output_file
, " if (");
8256 output_trans_check_vect_name (output_file
, el
->automaton
);
8257 fprintf (output_file
, " [%s] != %s->",
8258 TEMPORARY_VARIABLE_NAME
, CHIP_PARAMETER_NAME
);
8259 output_chip_member_name (output_file
, el
->automaton
);
8260 fprintf (output_file
, ")\n");
8261 fprintf (output_file
, " return %s (%s, %s);\n",
8262 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
8263 CHIP_PARAMETER_NAME
);
8264 fprintf (output_file
, " else\n");
8265 fprintf (output_file
, " ");
8266 if (el
->next_automata_list_el
!= NULL
)
8267 output_temp_chip_member_name (output_file
, el
->automaton
);
8270 fprintf (output_file
, "%s->", CHIP_PARAMETER_NAME
);
8271 output_chip_member_name (output_file
, el
->automaton
);
8273 fprintf (output_file
, " = ");
8274 output_trans_comb_vect_name (output_file
, el
->automaton
);
8275 fprintf (output_file
, " [%s];\n", TEMPORARY_VARIABLE_NAME
);
8279 fprintf (output_file
, "\n %s = ", TEMPORARY_VARIABLE_NAME
);
8280 output_trans_full_vect_name (output_file
, el
->automaton
);
8281 fprintf (output_file
, " [");
8282 output_translate_vect_name (output_file
, el
->automaton
);
8283 fprintf (output_file
, " [%s] + ", INTERNAL_INSN_CODE_NAME
);
8284 fprintf (output_file
, "%s->", CHIP_PARAMETER_NAME
);
8285 output_chip_member_name (output_file
, el
->automaton
);
8286 fprintf (output_file
, " * %d];\n",
8287 el
->automaton
->insn_equiv_classes_num
);
8288 fprintf (output_file
, " if (%s >= %d)\n",
8289 TEMPORARY_VARIABLE_NAME
, el
->automaton
->achieved_states_num
);
8290 fprintf (output_file
, " return %s (%s, %s);\n",
8291 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
8292 CHIP_PARAMETER_NAME
);
8293 fprintf (output_file
, " else\n ");
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
, " = %s;\n", TEMPORARY_VARIABLE_NAME
);
8303 if (automata_list
!= NULL
&& automata_list
->next_automata_list_el
!= NULL
)
8304 for (el
= automata_list
;; el
= next_el
)
8306 next_el
= el
->next_automata_list_el
;
8307 if (next_el
== NULL
)
8309 fprintf (output_file
, " %s->", CHIP_PARAMETER_NAME
);
8310 output_chip_member_name (output_file
, el
->automaton
);
8311 fprintf (output_file
, " = ");
8312 output_temp_chip_member_name (output_file
, el
->automaton
);
8313 fprintf (output_file
, ";\n");
8315 fprintf (output_file
, " return -1;\n");
8316 fprintf (output_file
, " }\n");
8319 /* Output function `internal_state_transition'. */
8321 output_internal_trans_func (void)
8323 fprintf (output_file
,
8324 "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
8325 INTERNAL_TRANSITION_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
8326 CHIP_NAME
, CHIP_PARAMETER_NAME
);
8327 fprintf (output_file
, "{\n int %s ATTRIBUTE_UNUSED;\n", TEMPORARY_VARIABLE_NAME
);
8328 fprintf (output_file
, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME
);
8329 output_insn_code_cases (output_automata_list_transition_code
);
8330 fprintf (output_file
, "\n default:\n return -1;\n }\n");
8331 fprintf (output_file
, "}\n\n");
8338 insn_code = dfa_insn_code (insn);
8339 if (insn_code > DFA__ADVANCE_CYCLE)
8343 insn_code = DFA__ADVANCE_CYCLE;
8345 where insn denotes INSN_NAME, insn_code denotes INSN_CODE_NAME, and
8346 code denotes CODE. */
8348 output_internal_insn_code_evaluation (const char *insn_name
,
8349 const char *insn_code_name
,
8352 fprintf (output_file
, "\n if (%s != 0)\n {\n", insn_name
);
8353 fprintf (output_file
, " %s = %s (%s);\n", insn_code_name
,
8354 DFA_INSN_CODE_FUNC_NAME
, insn_name
);
8355 fprintf (output_file
, " if (%s > %s)\n return %d;\n",
8356 insn_code_name
, ADVANCE_CYCLE_VALUE_NAME
, code
);
8357 fprintf (output_file
, " }\n else\n %s = %s;\n\n",
8358 insn_code_name
, ADVANCE_CYCLE_VALUE_NAME
);
8362 /* This function outputs `dfa_insn_code' and its helper function
8363 `dfa_insn_code_enlarge'. */
8365 output_dfa_insn_code_func (void)
8367 /* Emacs c-mode gets really confused if there's a { or } in column 0
8368 inside a string, so don't do that. */
8369 fprintf (output_file
, "\
8371 dfa_insn_code_enlarge (int uid)\n\
8375 %s = xrealloc (%s,\n\
8376 %s * sizeof(int));\n\
8377 for (; i < %s; i++)\n\
8378 %s[i] = -1;\n}\n\n",
8379 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
,
8380 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
,
8381 DFA_INSN_CODES_VARIABLE_NAME
, DFA_INSN_CODES_VARIABLE_NAME
,
8382 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
,
8383 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
,
8384 DFA_INSN_CODES_VARIABLE_NAME
);
8385 fprintf (output_file
, "\
8386 static inline int\n%s (rtx %s)\n\
8388 int uid = INSN_UID (%s);\n\
8390 DFA_INSN_CODE_FUNC_NAME
, INSN_PARAMETER_NAME
,
8391 INSN_PARAMETER_NAME
, INTERNAL_INSN_CODE_NAME
);
8393 fprintf (output_file
,
8394 " if (uid >= %s)\n dfa_insn_code_enlarge (uid);\n\n",
8395 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
);
8396 fprintf (output_file
, " %s = %s[uid];\n",
8397 INTERNAL_INSN_CODE_NAME
, DFA_INSN_CODES_VARIABLE_NAME
);
8398 fprintf (output_file
, "\
8404 INTERNAL_INSN_CODE_NAME
,
8405 INTERNAL_INSN_CODE_NAME
,
8406 INTERNAL_DFA_INSN_CODE_FUNC_NAME
, INSN_PARAMETER_NAME
,
8407 DFA_INSN_CODES_VARIABLE_NAME
, INTERNAL_INSN_CODE_NAME
);
8408 fprintf (output_file
, " return %s;\n}\n\n", INTERNAL_INSN_CODE_NAME
);
8411 /* The function outputs PHR interface function `state_transition'. */
8413 output_trans_func (void)
8415 fprintf (output_file
, "int\n%s (%s %s, rtx %s)\n",
8416 TRANSITION_FUNC_NAME
, STATE_TYPE_NAME
, STATE_NAME
,
8417 INSN_PARAMETER_NAME
);
8418 fprintf (output_file
, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME
);
8419 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME
,
8420 INTERNAL_INSN_CODE_NAME
, -1);
8421 fprintf (output_file
, " return %s (%s, %s);\n}\n\n",
8422 INTERNAL_TRANSITION_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
, STATE_NAME
);
8425 /* The function outputs a code for evaluation of alternative states
8426 number for insns which have reservations in given AUTOMATA_LIST. */
8428 output_automata_list_state_alts_code (automata_list_el_t automata_list
)
8430 automata_list_el_t el
;
8431 automaton_t automaton
;
8433 fprintf (output_file
, " {\n");
8434 for (el
= automata_list
; el
!= NULL
; el
= el
->next_automata_list_el
)
8435 if (comb_vect_p (el
->automaton
->state_alts_table
))
8437 fprintf (output_file
, " int %s;\n", TEMPORARY_VARIABLE_NAME
);
8440 for (el
= automata_list
; el
!= NULL
; el
= el
->next_automata_list_el
)
8442 automaton
= el
->automaton
;
8443 if (comb_vect_p (automaton
->state_alts_table
))
8445 fprintf (output_file
, "\n %s = ", TEMPORARY_VARIABLE_NAME
);
8446 output_state_alts_base_vect_name (output_file
, automaton
);
8447 fprintf (output_file
, " [%s->", CHIP_PARAMETER_NAME
);
8448 output_chip_member_name (output_file
, automaton
);
8449 fprintf (output_file
, "] + ");
8450 output_translate_vect_name (output_file
, automaton
);
8451 fprintf (output_file
, " [%s];\n", INTERNAL_INSN_CODE_NAME
);
8452 fprintf (output_file
, " if (");
8453 output_state_alts_check_vect_name (output_file
, automaton
);
8454 fprintf (output_file
, " [%s] != %s->",
8455 TEMPORARY_VARIABLE_NAME
, CHIP_PARAMETER_NAME
);
8456 output_chip_member_name (output_file
, automaton
);
8457 fprintf (output_file
, ")\n");
8458 fprintf (output_file
, " return 0;\n");
8459 fprintf (output_file
, " else\n");
8460 fprintf (output_file
,
8461 (el
== automata_list
8462 ? " %s = " : " %s += "),
8463 RESULT_VARIABLE_NAME
);
8464 output_state_alts_comb_vect_name (output_file
, automaton
);
8465 fprintf (output_file
, " [%s];\n", TEMPORARY_VARIABLE_NAME
);
8469 fprintf (output_file
,
8470 (el
== automata_list
8471 ? "\n %s = " : " %s += "),
8472 RESULT_VARIABLE_NAME
);
8473 output_state_alts_full_vect_name (output_file
, automaton
);
8474 fprintf (output_file
, " [");
8475 output_translate_vect_name (output_file
, automaton
);
8476 fprintf (output_file
, " [%s] + ", INTERNAL_INSN_CODE_NAME
);
8477 fprintf (output_file
, "%s->", CHIP_PARAMETER_NAME
);
8478 output_chip_member_name (output_file
, automaton
);
8479 fprintf (output_file
, " * %d];\n",
8480 automaton
->insn_equiv_classes_num
);
8483 fprintf (output_file
, " break;\n }\n\n");
8486 /* Output function `internal_state_alts'. */
8488 output_internal_state_alts_func (void)
8490 fprintf (output_file
,
8491 "static int\n%s (int %s, struct %s *%s)\n",
8492 INTERNAL_STATE_ALTS_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
8493 CHIP_NAME
, CHIP_PARAMETER_NAME
);
8494 fprintf (output_file
, "{\n int %s;\n", RESULT_VARIABLE_NAME
);
8495 fprintf (output_file
, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME
);
8496 output_insn_code_cases (output_automata_list_state_alts_code
);
8497 fprintf (output_file
,
8498 "\n default:\n %s = 0;\n break;\n }\n",
8499 RESULT_VARIABLE_NAME
);
8500 fprintf (output_file
, " return %s;\n", RESULT_VARIABLE_NAME
);
8501 fprintf (output_file
, "}\n\n");
8504 /* The function outputs PHR interface function `state_alts'. */
8506 output_state_alts_func (void)
8508 fprintf (output_file
, "int\n%s (%s, %s)\n\t%s %s;\n\trtx %s;\n",
8509 STATE_ALTS_FUNC_NAME
, STATE_NAME
, INSN_PARAMETER_NAME
,
8510 STATE_TYPE_NAME
, STATE_NAME
, INSN_PARAMETER_NAME
);
8511 fprintf (output_file
, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME
);
8512 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME
,
8513 INTERNAL_INSN_CODE_NAME
, 0);
8514 fprintf (output_file
, " return %s (%s, %s);\n}\n\n",
8515 INTERNAL_STATE_ALTS_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
, STATE_NAME
);
8518 /* Output function `min_issue_delay'. */
8520 output_min_issue_delay_func (void)
8522 fprintf (output_file
, "int\n%s (%s %s, rtx %s)\n",
8523 MIN_ISSUE_DELAY_FUNC_NAME
, STATE_TYPE_NAME
, STATE_NAME
,
8524 INSN_PARAMETER_NAME
);
8525 fprintf (output_file
, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME
);
8526 fprintf (output_file
, "\n if (%s != 0)\n {\n", INSN_PARAMETER_NAME
);
8527 fprintf (output_file
, " %s = %s (%s);\n", INTERNAL_INSN_CODE_NAME
,
8528 DFA_INSN_CODE_FUNC_NAME
, INSN_PARAMETER_NAME
);
8529 fprintf (output_file
, " if (%s > %s)\n return 0;\n",
8530 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
8531 fprintf (output_file
, " }\n else\n %s = %s;\n",
8532 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
8533 fprintf (output_file
, "\n return %s (%s, %s);\n",
8534 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
8536 fprintf (output_file
, "}\n\n");
8539 /* Output function `internal_dead_lock'. */
8541 output_internal_dead_lock_func (void)
8543 automaton_t automaton
;
8545 fprintf (output_file
, "static int\n%s (struct %s *%s)\n",
8546 INTERNAL_DEAD_LOCK_FUNC_NAME
, CHIP_NAME
, CHIP_PARAMETER_NAME
);
8547 fprintf (output_file
, "{\n");
8548 for (automaton
= description
->first_automaton
;
8550 automaton
= automaton
->next_automaton
)
8552 fprintf (output_file
, " if (");
8553 output_dead_lock_vect_name (output_file
, automaton
);
8554 fprintf (output_file
, " [%s->", CHIP_PARAMETER_NAME
);
8555 output_chip_member_name (output_file
, automaton
);
8556 fprintf (output_file
, "])\n return 1/* TRUE */;\n");
8558 fprintf (output_file
, " return 0/* FALSE */;\n}\n\n");
8561 /* The function outputs PHR interface function `state_dead_lock_p'. */
8563 output_dead_lock_func (void)
8565 fprintf (output_file
, "int\n%s (%s %s)\n",
8566 DEAD_LOCK_FUNC_NAME
, STATE_TYPE_NAME
, STATE_NAME
);
8567 fprintf (output_file
, "{\n return %s (%s);\n}\n\n",
8568 INTERNAL_DEAD_LOCK_FUNC_NAME
, STATE_NAME
);
8571 /* Output function `internal_reset'. */
8573 output_internal_reset_func (void)
8575 fprintf (output_file
, "static inline void\n%s (struct %s *%s)\n",
8576 INTERNAL_RESET_FUNC_NAME
, CHIP_NAME
, CHIP_PARAMETER_NAME
);
8577 fprintf (output_file
, "{\n memset (%s, 0, sizeof (struct %s));\n}\n\n",
8578 CHIP_PARAMETER_NAME
, CHIP_NAME
);
8581 /* The function outputs PHR interface function `state_size'. */
8583 output_size_func (void)
8585 fprintf (output_file
, "int\n%s (void)\n", SIZE_FUNC_NAME
);
8586 fprintf (output_file
, "{\n return sizeof (struct %s);\n}\n\n", CHIP_NAME
);
8589 /* The function outputs PHR interface function `state_reset'. */
8591 output_reset_func (void)
8593 fprintf (output_file
, "void\n%s (%s %s)\n",
8594 RESET_FUNC_NAME
, STATE_TYPE_NAME
, STATE_NAME
);
8595 fprintf (output_file
, "{\n %s (%s);\n}\n\n", INTERNAL_RESET_FUNC_NAME
,
8599 /* Output function `min_insn_conflict_delay'. */
8601 output_min_insn_conflict_delay_func (void)
8603 fprintf (output_file
,
8604 "int\n%s (%s %s, rtx %s, rtx %s)\n",
8605 MIN_INSN_CONFLICT_DELAY_FUNC_NAME
, STATE_TYPE_NAME
,
8606 STATE_NAME
, INSN_PARAMETER_NAME
, INSN2_PARAMETER_NAME
);
8607 fprintf (output_file
, "{\n struct %s %s;\n int %s, %s;\n",
8608 CHIP_NAME
, CHIP_NAME
, INTERNAL_INSN_CODE_NAME
,
8609 INTERNAL_INSN2_CODE_NAME
);
8610 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME
,
8611 INTERNAL_INSN_CODE_NAME
, 0);
8612 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME
,
8613 INTERNAL_INSN2_CODE_NAME
, 0);
8614 fprintf (output_file
, " memcpy (&%s, %s, sizeof (%s));\n",
8615 CHIP_NAME
, STATE_NAME
, CHIP_NAME
);
8616 fprintf (output_file
, " %s (&%s);\n", INTERNAL_RESET_FUNC_NAME
, CHIP_NAME
);
8617 fprintf (output_file
, " if (%s (%s, &%s) > 0)\n abort ();\n",
8618 INTERNAL_TRANSITION_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
, CHIP_NAME
);
8619 fprintf (output_file
, " return %s (%s, &%s);\n",
8620 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME
, INTERNAL_INSN2_CODE_NAME
,
8622 fprintf (output_file
, "}\n\n");
8625 /* Output function `internal_insn_latency'. */
8627 output_internal_insn_latency_func (void)
8630 struct bypass_decl
*bypass
;
8632 const char *tabletype
= "unsigned char";
8634 /* Find the smallest integer type that can hold all the default
8636 for (i
= 0; i
< description
->decls_num
; i
++)
8637 if (description
->decls
[i
]->mode
== dm_insn_reserv
)
8639 decl
= description
->decls
[i
];
8640 if (DECL_INSN_RESERV (decl
)->default_latency
> UCHAR_MAX
8641 && tabletype
[0] != 'i') /* don't shrink it */
8642 tabletype
= "unsigned short";
8643 if (DECL_INSN_RESERV (decl
)->default_latency
> USHRT_MAX
)
8647 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",
8648 INTERNAL_INSN_LATENCY_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
8649 INTERNAL_INSN2_CODE_NAME
, INSN_PARAMETER_NAME
,
8650 INSN2_PARAMETER_NAME
);
8651 fprintf (output_file
, "{\n");
8653 if (DECL_INSN_RESERV (advance_cycle_insn_decl
)->insn_num
== 0)
8655 fputs (" return 0;\n}\n\n", output_file
);
8659 fprintf (output_file
, " static const %s default_latencies[] =\n {",
8662 for (i
= 0, j
= 0, col
= 7; i
< description
->decls_num
; i
++)
8663 if (description
->decls
[i
]->mode
== dm_insn_reserv
8664 && description
->decls
[i
] != advance_cycle_insn_decl
)
8666 if ((col
= (col
+1) % 8) == 0)
8667 fputs ("\n ", output_file
);
8668 decl
= description
->decls
[i
];
8669 if (j
++ != DECL_INSN_RESERV (decl
)->insn_num
)
8671 fprintf (output_file
, "% 4d,",
8672 DECL_INSN_RESERV (decl
)->default_latency
);
8674 if (j
!= DECL_INSN_RESERV (advance_cycle_insn_decl
)->insn_num
)
8676 fputs ("\n };\n", output_file
);
8678 fprintf (output_file
, " if (%s >= %s || %s >= %s)\n return 0;\n",
8679 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
,
8680 INTERNAL_INSN2_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
8682 fprintf (output_file
, " switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME
);
8683 for (i
= 0; i
< description
->decls_num
; i
++)
8684 if (description
->decls
[i
]->mode
== dm_insn_reserv
8685 && DECL_INSN_RESERV (description
->decls
[i
])->bypass_list
)
8687 decl
= description
->decls
[i
];
8688 fprintf (output_file
,
8689 " case %d:\n switch (%s)\n {\n",
8690 DECL_INSN_RESERV (decl
)->insn_num
,
8691 INTERNAL_INSN2_CODE_NAME
);
8692 for (bypass
= DECL_INSN_RESERV (decl
)->bypass_list
;
8694 bypass
= bypass
->next
)
8696 if (bypass
->in_insn_reserv
->insn_num
8697 == DECL_INSN_RESERV (advance_cycle_insn_decl
)->insn_num
)
8699 fprintf (output_file
, " case %d:\n",
8700 bypass
->in_insn_reserv
->insn_num
);
8701 if (bypass
->bypass_guard_name
== NULL
)
8702 fprintf (output_file
, " return %d;\n",
8706 fprintf (output_file
,
8707 " if (%s (%s, %s))\n",
8708 bypass
->bypass_guard_name
, INSN_PARAMETER_NAME
,
8709 INSN2_PARAMETER_NAME
);
8710 fprintf (output_file
,
8711 " return %d;\n break;\n",
8715 fputs (" }\n break;\n", output_file
);
8718 fprintf (output_file
, " }\n return default_latencies[%s];\n}\n\n",
8719 INTERNAL_INSN_CODE_NAME
);
8722 /* The function outputs PHR interface function `insn_latency'. */
8724 output_insn_latency_func (void)
8726 fprintf (output_file
, "int\n%s (rtx %s, rtx %s)\n",
8727 INSN_LATENCY_FUNC_NAME
, INSN_PARAMETER_NAME
, INSN2_PARAMETER_NAME
);
8728 fprintf (output_file
, "{\n int %s, %s;\n",
8729 INTERNAL_INSN_CODE_NAME
, INTERNAL_INSN2_CODE_NAME
);
8730 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME
,
8731 INTERNAL_INSN_CODE_NAME
, 0);
8732 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME
,
8733 INTERNAL_INSN2_CODE_NAME
, 0);
8734 fprintf (output_file
, " return %s (%s, %s, %s, %s);\n}\n\n",
8735 INTERNAL_INSN_LATENCY_FUNC_NAME
,
8736 INTERNAL_INSN_CODE_NAME
, INTERNAL_INSN2_CODE_NAME
,
8737 INSN_PARAMETER_NAME
, INSN2_PARAMETER_NAME
);
8740 /* The function outputs PHR interface function `print_reservation'. */
8742 output_print_reservation_func (void)
8747 fprintf (output_file
,
8748 "void\n%s (FILE *%s, rtx %s ATTRIBUTE_UNUSED)\n{\n",
8749 PRINT_RESERVATION_FUNC_NAME
, FILE_PARAMETER_NAME
,
8750 INSN_PARAMETER_NAME
);
8752 if (DECL_INSN_RESERV (advance_cycle_insn_decl
)->insn_num
== 0)
8754 fprintf (output_file
, " fputs (\"%s\", %s);\n}\n\n",
8755 NOTHING_NAME
, FILE_PARAMETER_NAME
);
8760 fputs (" static const char *const reservation_names[] =\n {",
8763 for (i
= 0, j
= 0; i
< description
->decls_num
; i
++)
8765 decl
= description
->decls
[i
];
8766 if (decl
->mode
== dm_insn_reserv
&& decl
!= advance_cycle_insn_decl
)
8768 if (j
++ != DECL_INSN_RESERV (decl
)->insn_num
)
8770 fprintf (output_file
, "\n \"%s\",",
8771 regexp_representation (DECL_INSN_RESERV (decl
)->regexp
));
8772 finish_regexp_representation ();
8775 if (j
!= DECL_INSN_RESERV (advance_cycle_insn_decl
)->insn_num
)
8778 fprintf (output_file
, "\n \"%s\"\n };\n int %s;\n\n",
8779 NOTHING_NAME
, INTERNAL_INSN_CODE_NAME
);
8781 fprintf (output_file
, " if (%s == 0)\n %s = %s;\n",
8782 INSN_PARAMETER_NAME
,
8783 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
8784 fprintf (output_file
, " else\n\
8790 INTERNAL_INSN_CODE_NAME
, DFA_INSN_CODE_FUNC_NAME
,
8791 INSN_PARAMETER_NAME
,
8792 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
,
8793 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
8795 fprintf (output_file
, " fputs (reservation_names[%s], %s);\n}\n\n",
8796 INTERNAL_INSN_CODE_NAME
, FILE_PARAMETER_NAME
);
8799 /* The following function is used to sort unit declaration by their
8802 units_cmp (const void *unit1
, const void *unit2
)
8804 const unit_decl_t u1
= *(unit_decl_t
*) unit1
;
8805 const unit_decl_t u2
= *(unit_decl_t
*) unit2
;
8807 return strcmp (u1
->name
, u2
->name
);
8810 /* The following macro value is name of struct containing unit name
8812 #define NAME_CODE_STRUCT_NAME "name_code"
8814 /* The following macro value is name of table of struct name_code. */
8815 #define NAME_CODE_TABLE_NAME "name_code_table"
8817 /* The following macro values are member names for struct name_code. */
8818 #define NAME_MEMBER_NAME "name"
8819 #define CODE_MEMBER_NAME "code"
8821 /* The following macro values are local variable names for function
8822 `get_cpu_unit_code'. */
8823 #define CMP_VARIABLE_NAME "cmp"
8824 #define LOW_VARIABLE_NAME "l"
8825 #define MIDDLE_VARIABLE_NAME "m"
8826 #define HIGH_VARIABLE_NAME "h"
8828 /* The following function outputs function to obtain internal cpu unit
8829 code by the cpu unit name. */
8831 output_get_cpu_unit_code_func (void)
8836 fprintf (output_file
, "int\n%s (%s)\n\tconst char *%s;\n",
8837 GET_CPU_UNIT_CODE_FUNC_NAME
, CPU_UNIT_NAME_PARAMETER_NAME
,
8838 CPU_UNIT_NAME_PARAMETER_NAME
);
8839 fprintf (output_file
, "{\n struct %s {const char *%s; int %s;};\n",
8840 NAME_CODE_STRUCT_NAME
, NAME_MEMBER_NAME
, CODE_MEMBER_NAME
);
8841 fprintf (output_file
, " int %s, %s, %s, %s;\n", CMP_VARIABLE_NAME
,
8842 LOW_VARIABLE_NAME
, MIDDLE_VARIABLE_NAME
, HIGH_VARIABLE_NAME
);
8843 fprintf (output_file
, " static struct %s %s [] =\n {\n",
8844 NAME_CODE_STRUCT_NAME
, NAME_CODE_TABLE_NAME
);
8845 units
= xmalloc (sizeof (unit_decl_t
) * description
->units_num
);
8846 memcpy (units
, units_array
, sizeof (unit_decl_t
) * description
->units_num
);
8847 qsort (units
, description
->units_num
, sizeof (unit_decl_t
), units_cmp
);
8848 for (i
= 0; i
< description
->units_num
; i
++)
8849 if (units
[i
]->query_p
)
8850 fprintf (output_file
, " {\"%s\", %d},\n",
8851 units
[i
]->name
, units
[i
]->query_num
);
8852 fprintf (output_file
, " };\n\n");
8853 fprintf (output_file
, " /* The following is binary search: */\n");
8854 fprintf (output_file
, " %s = 0;\n", LOW_VARIABLE_NAME
);
8855 fprintf (output_file
, " %s = sizeof (%s) / sizeof (struct %s) - 1;\n",
8856 HIGH_VARIABLE_NAME
, NAME_CODE_TABLE_NAME
, NAME_CODE_STRUCT_NAME
);
8857 fprintf (output_file
, " while (%s <= %s)\n {\n",
8858 LOW_VARIABLE_NAME
, HIGH_VARIABLE_NAME
);
8859 fprintf (output_file
, " %s = (%s + %s) / 2;\n",
8860 MIDDLE_VARIABLE_NAME
, LOW_VARIABLE_NAME
, HIGH_VARIABLE_NAME
);
8861 fprintf (output_file
, " %s = strcmp (%s, %s [%s].%s);\n",
8862 CMP_VARIABLE_NAME
, CPU_UNIT_NAME_PARAMETER_NAME
,
8863 NAME_CODE_TABLE_NAME
, MIDDLE_VARIABLE_NAME
, NAME_MEMBER_NAME
);
8864 fprintf (output_file
, " if (%s < 0)\n", CMP_VARIABLE_NAME
);
8865 fprintf (output_file
, " %s = %s - 1;\n",
8866 HIGH_VARIABLE_NAME
, MIDDLE_VARIABLE_NAME
);
8867 fprintf (output_file
, " else if (%s > 0)\n", CMP_VARIABLE_NAME
);
8868 fprintf (output_file
, " %s = %s + 1;\n",
8869 LOW_VARIABLE_NAME
, MIDDLE_VARIABLE_NAME
);
8870 fprintf (output_file
, " else\n");
8871 fprintf (output_file
, " return %s [%s].%s;\n }\n",
8872 NAME_CODE_TABLE_NAME
, MIDDLE_VARIABLE_NAME
, CODE_MEMBER_NAME
);
8873 fprintf (output_file
, " return -1;\n}\n\n");
8877 /* The following function outputs function to check reservation of cpu
8878 unit (its internal code will be passed as the function argument) in
8881 output_cpu_unit_reservation_p (void)
8883 automaton_t automaton
;
8885 fprintf (output_file
, "int\n%s (%s, %s)\n\t%s %s;\n\tint %s;\n",
8886 CPU_UNIT_RESERVATION_P_FUNC_NAME
, STATE_NAME
,
8887 CPU_CODE_PARAMETER_NAME
, STATE_TYPE_NAME
, STATE_NAME
,
8888 CPU_CODE_PARAMETER_NAME
);
8889 fprintf (output_file
, "{\n if (%s < 0 || %s >= %d)\n abort ();\n",
8890 CPU_CODE_PARAMETER_NAME
, CPU_CODE_PARAMETER_NAME
,
8891 description
->query_units_num
);
8892 for (automaton
= description
->first_automaton
;
8894 automaton
= automaton
->next_automaton
)
8896 fprintf (output_file
, " if ((");
8897 output_reserved_units_table_name (output_file
, automaton
);
8898 fprintf (output_file
, " [((struct %s *) %s)->", CHIP_NAME
, STATE_NAME
);
8899 output_chip_member_name (output_file
, automaton
);
8900 fprintf (output_file
, " * %d + %s / 8] >> (%s %% 8)) & 1)\n",
8901 (description
->query_units_num
+ 7) / 8,
8902 CPU_CODE_PARAMETER_NAME
, CPU_CODE_PARAMETER_NAME
);
8903 fprintf (output_file
, " return 1;\n");
8905 fprintf (output_file
, " return 0;\n}\n\n");
8908 /* The function outputs PHR interface function `dfa_clean_insn_cache'. */
8910 output_dfa_clean_insn_cache_func (void)
8912 fprintf (output_file
,
8913 "void\n%s (void)\n{\n int %s;\n\n",
8914 DFA_CLEAN_INSN_CACHE_FUNC_NAME
, I_VARIABLE_NAME
);
8915 fprintf (output_file
,
8916 " for (%s = 0; %s < %s; %s++)\n %s [%s] = -1;\n}\n\n",
8917 I_VARIABLE_NAME
, I_VARIABLE_NAME
,
8918 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
, I_VARIABLE_NAME
,
8919 DFA_INSN_CODES_VARIABLE_NAME
, I_VARIABLE_NAME
);
8922 /* The function outputs PHR interface function `dfa_start'. */
8924 output_dfa_start_func (void)
8926 fprintf (output_file
,
8927 "void\n%s (void)\n{\n %s = get_max_uid ();\n",
8928 DFA_START_FUNC_NAME
, DFA_INSN_CODES_LENGTH_VARIABLE_NAME
);
8929 fprintf (output_file
, " %s = xmalloc (%s * sizeof (int));\n",
8930 DFA_INSN_CODES_VARIABLE_NAME
, DFA_INSN_CODES_LENGTH_VARIABLE_NAME
);
8931 fprintf (output_file
, " %s ();\n}\n\n", DFA_CLEAN_INSN_CACHE_FUNC_NAME
);
8934 /* The function outputs PHR interface function `dfa_finish'. */
8936 output_dfa_finish_func (void)
8938 fprintf (output_file
, "void\n%s (void)\n{\n free (%s);\n}\n\n",
8939 DFA_FINISH_FUNC_NAME
, DFA_INSN_CODES_VARIABLE_NAME
);
8944 /* The page contains code for output description file (readable
8945 representation of original description and generated DFA(s). */
8947 /* The function outputs string representation of IR reservation. */
8949 output_regexp (regexp_t regexp
)
8951 fprintf (output_description_file
, "%s", regexp_representation (regexp
));
8952 finish_regexp_representation ();
8955 /* Output names of units in LIST separated by comma. */
8957 output_unit_set_el_list (unit_set_el_t list
)
8961 for (el
= list
; el
!= NULL
; el
= el
->next_unit_set_el
)
8964 fprintf (output_description_file
, ", ");
8965 fprintf (output_description_file
, "%s", el
->unit_decl
->name
);
8969 /* Output patterns in LIST separated by comma. */
8971 output_pattern_set_el_list (pattern_set_el_t list
)
8973 pattern_set_el_t el
;
8976 for (el
= list
; el
!= NULL
; el
= el
->next_pattern_set_el
)
8979 fprintf (output_description_file
, ", ");
8980 for (i
= 0; i
< el
->units_num
; i
++)
8981 fprintf (output_description_file
, (i
== 0 ? "%s" : " %s"),
8982 el
->unit_decls
[i
]->name
);
8986 /* The function outputs string representation of IR define_reservation
8987 and define_insn_reservation. */
8989 output_description (void)
8994 for (i
= 0; i
< description
->decls_num
; i
++)
8996 decl
= description
->decls
[i
];
8997 if (decl
->mode
== dm_unit
)
8999 if (DECL_UNIT (decl
)->excl_list
!= NULL
)
9001 fprintf (output_description_file
, "unit %s exlusion_set: ",
9002 DECL_UNIT (decl
)->name
);
9003 output_unit_set_el_list (DECL_UNIT (decl
)->excl_list
);
9004 fprintf (output_description_file
, "\n");
9006 if (DECL_UNIT (decl
)->presence_list
!= NULL
)
9008 fprintf (output_description_file
, "unit %s presence_set: ",
9009 DECL_UNIT (decl
)->name
);
9010 output_pattern_set_el_list (DECL_UNIT (decl
)->presence_list
);
9011 fprintf (output_description_file
, "\n");
9013 if (DECL_UNIT (decl
)->final_presence_list
!= NULL
)
9015 fprintf (output_description_file
, "unit %s final_presence_set: ",
9016 DECL_UNIT (decl
)->name
);
9017 output_pattern_set_el_list
9018 (DECL_UNIT (decl
)->final_presence_list
);
9019 fprintf (output_description_file
, "\n");
9021 if (DECL_UNIT (decl
)->absence_list
!= NULL
)
9023 fprintf (output_description_file
, "unit %s absence_set: ",
9024 DECL_UNIT (decl
)->name
);
9025 output_pattern_set_el_list (DECL_UNIT (decl
)->absence_list
);
9026 fprintf (output_description_file
, "\n");
9028 if (DECL_UNIT (decl
)->final_absence_list
!= NULL
)
9030 fprintf (output_description_file
, "unit %s final_absence_set: ",
9031 DECL_UNIT (decl
)->name
);
9032 output_pattern_set_el_list
9033 (DECL_UNIT (decl
)->final_absence_list
);
9034 fprintf (output_description_file
, "\n");
9038 fprintf (output_description_file
, "\n");
9039 for (i
= 0; i
< description
->decls_num
; i
++)
9041 decl
= description
->decls
[i
];
9042 if (decl
->mode
== dm_reserv
)
9044 fprintf (output_description_file
, "reservation %s: ",
9045 DECL_RESERV (decl
)->name
);
9046 output_regexp (DECL_RESERV (decl
)->regexp
);
9047 fprintf (output_description_file
, "\n");
9049 else if (decl
->mode
== dm_insn_reserv
&& decl
!= advance_cycle_insn_decl
)
9051 fprintf (output_description_file
, "insn reservation %s ",
9052 DECL_INSN_RESERV (decl
)->name
);
9053 print_rtl (output_description_file
,
9054 DECL_INSN_RESERV (decl
)->condexp
);
9055 fprintf (output_description_file
, ": ");
9056 output_regexp (DECL_INSN_RESERV (decl
)->regexp
);
9057 fprintf (output_description_file
, "\n");
9059 else if (decl
->mode
== dm_bypass
)
9060 fprintf (output_description_file
, "bypass %d %s %s\n",
9061 DECL_BYPASS (decl
)->latency
,
9062 DECL_BYPASS (decl
)->out_insn_name
,
9063 DECL_BYPASS (decl
)->in_insn_name
);
9065 fprintf (output_description_file
, "\n\f\n");
9068 /* The function outputs name of AUTOMATON. */
9070 output_automaton_name (FILE *f
, automaton_t automaton
)
9072 if (automaton
->corresponding_automaton_decl
== NULL
)
9073 fprintf (f
, "#%d", automaton
->automaton_order_num
);
9075 fprintf (f
, "`%s'", automaton
->corresponding_automaton_decl
->name
);
9078 /* Maximal length of line for pretty printing into description
9080 #define MAX_LINE_LENGTH 70
9082 /* The function outputs units name belonging to AUTOMATON. */
9084 output_automaton_units (automaton_t automaton
)
9088 int curr_line_length
;
9089 int there_is_an_automaton_unit
;
9092 fprintf (output_description_file
, "\n Coresponding units:\n");
9093 fprintf (output_description_file
, " ");
9094 curr_line_length
= 4;
9095 there_is_an_automaton_unit
= 0;
9096 for (i
= 0; i
< description
->decls_num
; i
++)
9098 decl
= description
->decls
[i
];
9099 if (decl
->mode
== dm_unit
9100 && (DECL_UNIT (decl
)->corresponding_automaton_num
9101 == automaton
->automaton_order_num
))
9103 there_is_an_automaton_unit
= 1;
9104 name
= DECL_UNIT (decl
)->name
;
9105 if (curr_line_length
+ strlen (name
) + 1 > MAX_LINE_LENGTH
)
9107 curr_line_length
= strlen (name
) + 4;
9108 fprintf (output_description_file
, "\n ");
9112 curr_line_length
+= strlen (name
) + 1;
9113 fprintf (output_description_file
, " ");
9115 fprintf (output_description_file
, "%s", name
);
9118 if (!there_is_an_automaton_unit
)
9119 fprintf (output_description_file
, "<None>");
9120 fprintf (output_description_file
, "\n\n");
9123 /* The following variable is used for forming array of all possible cpu unit
9124 reservations described by the current DFA state. */
9125 static vla_ptr_t state_reservs
;
9127 /* The function forms `state_reservs' for STATE. */
9129 add_state_reservs (state_t state
)
9131 alt_state_t curr_alt_state
;
9132 reserv_sets_t reservs
;
9134 if (state
->component_states
!= NULL
)
9135 for (curr_alt_state
= state
->component_states
;
9136 curr_alt_state
!= NULL
;
9137 curr_alt_state
= curr_alt_state
->next_sorted_alt_state
)
9138 add_state_reservs (curr_alt_state
->state
);
9141 reservs
= state
->reservs
;
9142 VLA_PTR_ADD (state_reservs
, reservs
);
9146 /* The function outputs readable representation of all out arcs of
9149 output_state_arcs (state_t state
)
9154 int curr_line_length
;
9156 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
9159 if (!ainsn
->first_insn_with_same_reservs
)
9161 fprintf (output_description_file
, " ");
9162 curr_line_length
= 7;
9163 fprintf (output_description_file
, "%2d: ", ainsn
->insn_equiv_class_num
);
9166 insn_name
= ainsn
->insn_reserv_decl
->name
;
9167 if (curr_line_length
+ strlen (insn_name
) > MAX_LINE_LENGTH
)
9169 if (ainsn
!= arc
->insn
)
9171 fprintf (output_description_file
, ",\n ");
9172 curr_line_length
= strlen (insn_name
) + 6;
9175 curr_line_length
+= strlen (insn_name
);
9179 curr_line_length
+= strlen (insn_name
);
9180 if (ainsn
!= arc
->insn
)
9182 curr_line_length
+= 2;
9183 fprintf (output_description_file
, ", ");
9186 fprintf (output_description_file
, "%s", insn_name
);
9187 ainsn
= ainsn
->next_same_reservs_insn
;
9189 while (ainsn
!= NULL
);
9190 fprintf (output_description_file
, " %d (%d)\n",
9191 arc
->to_state
->order_state_num
, arc
->state_alts
);
9193 fprintf (output_description_file
, "\n");
9196 /* The following function is used for sorting possible cpu unit
9197 reservation of a DFA state. */
9199 state_reservs_cmp (const void *reservs_ptr_1
, const void *reservs_ptr_2
)
9201 return reserv_sets_cmp (*(reserv_sets_t
*) reservs_ptr_1
,
9202 *(reserv_sets_t
*) reservs_ptr_2
);
9205 /* The following function is used for sorting possible cpu unit
9206 reservation of a DFA state. */
9208 remove_state_duplicate_reservs (void)
9210 reserv_sets_t
*reservs_ptr
;
9211 reserv_sets_t
*last_formed_reservs_ptr
;
9213 last_formed_reservs_ptr
= NULL
;
9214 for (reservs_ptr
= VLA_PTR_BEGIN (state_reservs
);
9215 reservs_ptr
<= (reserv_sets_t
*) VLA_PTR_LAST (state_reservs
);
9217 if (last_formed_reservs_ptr
== NULL
)
9218 last_formed_reservs_ptr
= reservs_ptr
;
9219 else if (reserv_sets_cmp (*last_formed_reservs_ptr
, *reservs_ptr
) != 0)
9221 ++last_formed_reservs_ptr
;
9222 *last_formed_reservs_ptr
= *reservs_ptr
;
9224 VLA_PTR_SHORTEN (state_reservs
, reservs_ptr
- last_formed_reservs_ptr
- 1);
9227 /* The following function output readable representation of DFA(s)
9228 state used for fast recognition of pipeline hazards. State is
9229 described by possible (current and scheduled) cpu unit
9232 output_state (state_t state
)
9234 reserv_sets_t
*reservs_ptr
;
9236 VLA_PTR_CREATE (state_reservs
, 150, "state reservations");
9237 fprintf (output_description_file
, " State #%d", state
->order_state_num
);
9238 fprintf (output_description_file
,
9239 state
->new_cycle_p
? " (new cycle)\n" : "\n");
9240 add_state_reservs (state
);
9241 qsort (VLA_PTR_BEGIN (state_reservs
), VLA_PTR_LENGTH (state_reservs
),
9242 sizeof (reserv_sets_t
), state_reservs_cmp
);
9243 remove_state_duplicate_reservs ();
9244 for (reservs_ptr
= VLA_PTR_BEGIN (state_reservs
);
9245 reservs_ptr
<= (reserv_sets_t
*) VLA_PTR_LAST (state_reservs
);
9248 fprintf (output_description_file
, " ");
9249 output_reserv_sets (output_description_file
, *reservs_ptr
);
9250 fprintf (output_description_file
, "\n");
9252 fprintf (output_description_file
, "\n");
9253 output_state_arcs (state
);
9254 VLA_PTR_DELETE (state_reservs
);
9257 /* The following function output readable representation of
9258 DFAs used for fast recognition of pipeline hazards. */
9260 output_automaton_descriptions (void)
9262 automaton_t automaton
;
9264 for (automaton
= description
->first_automaton
;
9266 automaton
= automaton
->next_automaton
)
9268 fprintf (output_description_file
, "\nAutomaton ");
9269 output_automaton_name (output_description_file
, automaton
);
9270 fprintf (output_description_file
, "\n");
9271 output_automaton_units (automaton
);
9272 pass_states (automaton
, output_state
);
9278 /* The page contains top level function for generation DFA(s) used for
9281 /* The function outputs statistics about work of different phases of
9284 output_statistics (FILE *f
)
9286 automaton_t automaton
;
9289 int transition_comb_vect_els
= 0;
9290 int transition_full_vect_els
= 0;
9291 int state_alts_comb_vect_els
= 0;
9292 int state_alts_full_vect_els
= 0;
9293 int min_issue_delay_vect_els
= 0;
9296 for (automaton
= description
->first_automaton
;
9298 automaton
= automaton
->next_automaton
)
9300 fprintf (f
, "\nAutomaton ");
9301 output_automaton_name (f
, automaton
);
9302 fprintf (f
, "\n %5d NDFA states, %5d NDFA arcs\n",
9303 automaton
->NDFA_states_num
, automaton
->NDFA_arcs_num
);
9304 fprintf (f
, " %5d DFA states, %5d DFA arcs\n",
9305 automaton
->DFA_states_num
, automaton
->DFA_arcs_num
);
9306 states_num
= automaton
->DFA_states_num
;
9307 if (!no_minimization_flag
)
9309 fprintf (f
, " %5d minimal DFA states, %5d minimal DFA arcs\n",
9310 automaton
->minimal_DFA_states_num
,
9311 automaton
->minimal_DFA_arcs_num
);
9312 states_num
= automaton
->minimal_DFA_states_num
;
9314 fprintf (f
, " %5d all insns %5d insn equivalence classes\n",
9315 description
->insns_num
, automaton
->insn_equiv_classes_num
);
9318 (f
, "%5ld transition comb vector els, %5ld trans table els: %s\n",
9319 (long) VLA_HWINT_LENGTH (automaton
->trans_table
->comb_vect
),
9320 (long) VLA_HWINT_LENGTH (automaton
->trans_table
->full_vect
),
9321 (comb_vect_p (automaton
->trans_table
)
9322 ? "use comb vect" : "use simple vect"));
9324 (f
, "%5ld state alts comb vector els, %5ld state alts table els: %s\n",
9325 (long) VLA_HWINT_LENGTH (automaton
->state_alts_table
->comb_vect
),
9326 (long) VLA_HWINT_LENGTH (automaton
->state_alts_table
->full_vect
),
9327 (comb_vect_p (automaton
->state_alts_table
)
9328 ? "use comb vect" : "use simple vect"));
9330 (f
, "%5ld min delay table els, compression factor %d\n",
9331 (long) states_num
* automaton
->insn_equiv_classes_num
,
9332 automaton
->min_issue_delay_table_compression_factor
);
9333 transition_comb_vect_els
9334 += VLA_HWINT_LENGTH (automaton
->trans_table
->comb_vect
);
9335 transition_full_vect_els
9336 += VLA_HWINT_LENGTH (automaton
->trans_table
->full_vect
);
9337 state_alts_comb_vect_els
9338 += VLA_HWINT_LENGTH (automaton
->state_alts_table
->comb_vect
);
9339 state_alts_full_vect_els
9340 += VLA_HWINT_LENGTH (automaton
->state_alts_table
->full_vect
);
9341 min_issue_delay_vect_els
9342 += states_num
* automaton
->insn_equiv_classes_num
;
9346 fprintf (f
, "\n%5d all allocated states, %5d all allocated arcs\n",
9347 allocated_states_num
, allocated_arcs_num
);
9348 fprintf (f
, "%5d all allocated alternative states\n",
9349 allocated_alt_states_num
);
9350 fprintf (f
, "%5d all transition comb vector els, %5d all trans table els\n",
9351 transition_comb_vect_els
, transition_full_vect_els
);
9353 (f
, "%5d all state alts comb vector els, %5d all state alts table els\n",
9354 state_alts_comb_vect_els
, state_alts_full_vect_els
);
9355 fprintf (f
, "%5d all min delay table els\n", min_issue_delay_vect_els
);
9356 fprintf (f
, "%5d locked states num\n", locked_states_num
);
9360 /* The function output times of work of different phases of DFA
9363 output_time_statistics (FILE *f
)
9365 fprintf (f
, "\n transformation: ");
9366 print_active_time (f
, transform_time
);
9367 fprintf (f
, (!ndfa_flag
? ", building DFA: " : ", building NDFA: "));
9368 print_active_time (f
, NDFA_time
);
9371 fprintf (f
, ", NDFA -> DFA: ");
9372 print_active_time (f
, NDFA_to_DFA_time
);
9374 fprintf (f
, "\n DFA minimization: ");
9375 print_active_time (f
, minimize_time
);
9376 fprintf (f
, ", making insn equivalence: ");
9377 print_active_time (f
, equiv_time
);
9378 fprintf (f
, "\n all automaton generation: ");
9379 print_active_time (f
, automaton_generation_time
);
9380 fprintf (f
, ", output: ");
9381 print_active_time (f
, output_time
);
9385 /* The function generates DFA (deterministic finite state automaton)
9386 for fast recognition of pipeline hazards. No errors during
9387 checking must be fixed before this function call. */
9391 automata_num
= split_argument
;
9392 if (description
->units_num
< automata_num
)
9393 automata_num
= description
->units_num
;
9396 initiate_automata_lists ();
9397 initiate_pass_states ();
9398 initiate_excl_sets ();
9399 initiate_presence_absence_pattern_sets ();
9400 automaton_generation_time
= create_ticker ();
9402 ticker_off (&automaton_generation_time
);
9407 /* The following function creates insn attribute whose values are
9408 number alternatives in insn reservations. */
9410 make_insn_alts_attr (void)
9416 condexp
= rtx_alloc (COND
);
9417 XVEC (condexp
, 0) = rtvec_alloc ((description
->insns_num
- 1) * 2);
9418 XEXP (condexp
, 1) = make_numeric_value (0);
9419 for (i
= insn_num
= 0; i
< description
->decls_num
; i
++)
9421 decl
= description
->decls
[i
];
9422 if (decl
->mode
== dm_insn_reserv
&& decl
!= advance_cycle_insn_decl
)
9424 XVECEXP (condexp
, 0, 2 * insn_num
)
9425 = DECL_INSN_RESERV (decl
)->condexp
;
9426 XVECEXP (condexp
, 0, 2 * insn_num
+ 1)
9427 = make_numeric_value
9428 (DECL_INSN_RESERV (decl
)->transformed_regexp
->mode
!= rm_oneof
9429 ? 1 : REGEXP_ONEOF (DECL_INSN_RESERV (decl
)
9430 ->transformed_regexp
)->regexps_num
);
9434 if (description
->insns_num
!= insn_num
+ 1)
9436 make_internal_attr (attr_printf (sizeof ("*")
9437 + strlen (INSN_ALTS_FUNC_NAME
) + 1,
9438 "*%s", INSN_ALTS_FUNC_NAME
),
9439 condexp
, ATTR_NONE
);
9444 /* The following function creates attribute which is order number of
9445 insn in pipeline hazard description translator. */
9447 make_internal_dfa_insn_code_attr (void)
9453 condexp
= rtx_alloc (COND
);
9454 XVEC (condexp
, 0) = rtvec_alloc ((description
->insns_num
- 1) * 2);
9456 = make_numeric_value (DECL_INSN_RESERV (advance_cycle_insn_decl
)
9458 for (i
= insn_num
= 0; i
< description
->decls_num
; i
++)
9460 decl
= description
->decls
[i
];
9461 if (decl
->mode
== dm_insn_reserv
&& decl
!= advance_cycle_insn_decl
)
9463 XVECEXP (condexp
, 0, 2 * insn_num
)
9464 = DECL_INSN_RESERV (decl
)->condexp
;
9465 XVECEXP (condexp
, 0, 2 * insn_num
+ 1)
9466 = make_numeric_value (DECL_INSN_RESERV (decl
)->insn_num
);
9470 if (description
->insns_num
!= insn_num
+ 1)
9473 (attr_printf (sizeof ("*")
9474 + strlen (INTERNAL_DFA_INSN_CODE_FUNC_NAME
) + 1,
9475 "*%s", INTERNAL_DFA_INSN_CODE_FUNC_NAME
),
9476 condexp
, ATTR_STATIC
);
9481 /* The following function creates attribute which order number of insn
9482 in pipeline hazard description translator. */
9484 make_default_insn_latency_attr (void)
9490 condexp
= rtx_alloc (COND
);
9491 XVEC (condexp
, 0) = rtvec_alloc ((description
->insns_num
- 1) * 2);
9492 XEXP (condexp
, 1) = make_numeric_value (0);
9493 for (i
= insn_num
= 0; i
< description
->decls_num
; i
++)
9495 decl
= description
->decls
[i
];
9496 if (decl
->mode
== dm_insn_reserv
&& decl
!= advance_cycle_insn_decl
)
9498 XVECEXP (condexp
, 0, 2 * insn_num
)
9499 = DECL_INSN_RESERV (decl
)->condexp
;
9500 XVECEXP (condexp
, 0, 2 * insn_num
+ 1)
9501 = make_numeric_value (DECL_INSN_RESERV (decl
)->default_latency
);
9505 if (description
->insns_num
!= insn_num
+ 1)
9507 make_internal_attr (attr_printf (sizeof ("*")
9508 + strlen (INSN_DEFAULT_LATENCY_FUNC_NAME
)
9509 + 1, "*%s", INSN_DEFAULT_LATENCY_FUNC_NAME
),
9510 condexp
, ATTR_NONE
);
9515 /* The following function creates attribute which returns 1 if given
9516 output insn has bypassing and 0 otherwise. */
9518 make_bypass_attr (void)
9521 int bypass_insns_num
= 0;
9525 for (i
= 0; i
< description
->decls_num
; i
++)
9527 decl
= description
->decls
[i
];
9528 if (decl
->mode
== dm_insn_reserv
9529 && DECL_INSN_RESERV (decl
)->condexp
!= NULL
9530 && DECL_INSN_RESERV (decl
)->bypass_list
!= NULL
)
9533 if (bypass_insns_num
== 0)
9534 result_rtx
= make_numeric_value (0);
9537 result_rtx
= rtx_alloc (COND
);
9538 XVEC (result_rtx
, 0) = rtvec_alloc (bypass_insns_num
* 2);
9539 XEXP (result_rtx
, 1) = make_numeric_value (0);
9541 for (i
= bypass_insn
= 0; i
< description
->decls_num
; i
++)
9543 decl
= description
->decls
[i
];
9544 if (decl
->mode
== dm_insn_reserv
9545 && DECL_INSN_RESERV (decl
)->condexp
!= NULL
9546 && DECL_INSN_RESERV (decl
)->bypass_list
!= NULL
)
9548 XVECEXP (result_rtx
, 0, 2 * bypass_insn
)
9549 = DECL_INSN_RESERV (decl
)->condexp
;
9550 XVECEXP (result_rtx
, 0, 2 * bypass_insn
+ 1)
9551 = make_numeric_value (1);
9556 make_internal_attr (attr_printf (sizeof ("*")
9557 + strlen (BYPASS_P_FUNC_NAME
) + 1,
9558 "*%s", BYPASS_P_FUNC_NAME
),
9559 result_rtx
, ATTR_NONE
);
9564 /* This page mainly contains top level functions of pipeline hazards
9565 description translator. */
9567 /* The following macro value is suffix of name of description file of
9568 pipeline hazards description translator. */
9569 #define STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX ".dfa"
9571 /* The function returns suffix of given file name. The returned
9572 string can not be changed. */
9574 file_name_suffix (const char *file_name
)
9576 const char *last_period
;
9578 for (last_period
= NULL
; *file_name
!= '\0'; file_name
++)
9579 if (*file_name
== '.')
9580 last_period
= file_name
;
9581 return (last_period
== NULL
? file_name
: last_period
);
9584 /* The function returns base name of given file name, i.e. pointer to
9585 first char after last `/' (or `\' for WIN32) in given file name,
9586 given file name itself if the directory name is absent. The
9587 returned string can not be changed. */
9589 base_file_name (const char *file_name
)
9591 int directory_name_length
;
9593 directory_name_length
= strlen (file_name
);
9595 while (directory_name_length
>= 0 && file_name
[directory_name_length
] != '/'
9596 && file_name
[directory_name_length
] != '\\')
9598 while (directory_name_length
>= 0 && file_name
[directory_name_length
] != '/')
9600 directory_name_length
--;
9601 return file_name
+ directory_name_length
+ 1;
9604 /* The following is top level function to initialize the work of
9605 pipeline hazards description translator. */
9607 initiate_automaton_gen (int argc
, char **argv
)
9609 const char *base_name
;
9613 split_argument
= 0; /* default value */
9614 no_minimization_flag
= 0;
9618 for (i
= 2; i
< argc
; i
++)
9619 if (strcmp (argv
[i
], NO_MINIMIZATION_OPTION
) == 0)
9620 no_minimization_flag
= 1;
9621 else if (strcmp (argv
[i
], TIME_OPTION
) == 0)
9623 else if (strcmp (argv
[i
], V_OPTION
) == 0)
9625 else if (strcmp (argv
[i
], W_OPTION
) == 0)
9627 else if (strcmp (argv
[i
], NDFA_OPTION
) == 0)
9629 else if (strcmp (argv
[i
], "-split") == 0)
9632 fatal ("-split has no argument.");
9633 fatal ("option `-split' has not been implemented yet\n");
9634 /* split_argument = atoi (argument_vect [i + 1]); */
9636 VLA_PTR_CREATE (decls
, 150, "decls");
9637 /* Initialize IR storage. */
9638 obstack_init (&irp
);
9639 initiate_automaton_decl_table ();
9640 initiate_insn_decl_table ();
9641 initiate_decl_table ();
9642 output_file
= stdout
;
9643 output_description_file
= NULL
;
9644 base_name
= base_file_name (argv
[1]);
9645 obstack_grow (&irp
, base_name
,
9646 strlen (base_name
) - strlen (file_name_suffix (base_name
)));
9647 obstack_grow (&irp
, STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX
,
9648 strlen (STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX
) + 1);
9649 obstack_1grow (&irp
, '\0');
9650 output_description_file_name
= obstack_base (&irp
);
9651 obstack_finish (&irp
);
9654 /* The following function checks existence at least one arc marked by
9657 check_automata_insn_issues (void)
9659 automaton_t automaton
;
9660 ainsn_t ainsn
, reserv_ainsn
;
9662 for (automaton
= description
->first_automaton
;
9664 automaton
= automaton
->next_automaton
)
9666 for (ainsn
= automaton
->ainsn_list
;
9668 ainsn
= ainsn
->next_ainsn
)
9669 if (ainsn
->first_insn_with_same_reservs
&& !ainsn
->arc_exists_p
)
9671 for (reserv_ainsn
= ainsn
;
9672 reserv_ainsn
!= NULL
;
9673 reserv_ainsn
= reserv_ainsn
->next_same_reservs_insn
)
9674 if (automaton
->corresponding_automaton_decl
!= NULL
)
9677 error ("Automaton `%s': Insn `%s' will never be issued",
9678 automaton
->corresponding_automaton_decl
->name
,
9679 reserv_ainsn
->insn_reserv_decl
->name
);
9682 ("Automaton `%s': Insn `%s' will never be issued",
9683 automaton
->corresponding_automaton_decl
->name
,
9684 reserv_ainsn
->insn_reserv_decl
->name
);
9689 error ("Insn `%s' will never be issued",
9690 reserv_ainsn
->insn_reserv_decl
->name
);
9692 warning ("Insn `%s' will never be issued",
9693 reserv_ainsn
->insn_reserv_decl
->name
);
9699 /* The following vla is used for storing pointers to all achieved
9701 static vla_ptr_t automaton_states
;
9703 /* This function is called by function pass_states to add an achieved
9706 add_automaton_state (state_t state
)
9708 VLA_PTR_ADD (automaton_states
, state
);
9711 /* The following function forms list of important automata (whose
9712 states may be changed after the insn issue) for each insn. */
9714 form_important_insn_automata_lists (void)
9716 automaton_t automaton
;
9723 VLA_PTR_CREATE (automaton_states
, 1500,
9724 "automaton states for forming important insn automata sets");
9725 /* Mark important ainsns. */
9726 for (automaton
= description
->first_automaton
;
9728 automaton
= automaton
->next_automaton
)
9730 VLA_PTR_NULLIFY (automaton_states
);
9731 pass_states (automaton
, add_automaton_state
);
9732 for (state_ptr
= VLA_PTR_BEGIN (automaton_states
);
9733 state_ptr
<= (state_t
*) VLA_PTR_LAST (automaton_states
);
9736 for (arc
= first_out_arc (*state_ptr
);
9738 arc
= next_out_arc (arc
))
9739 if (arc
->to_state
!= *state_ptr
)
9741 if (!arc
->insn
->first_insn_with_same_reservs
)
9743 for (ainsn
= arc
->insn
;
9745 ainsn
= ainsn
->next_same_reservs_insn
)
9746 ainsn
->important_p
= TRUE
;
9750 VLA_PTR_DELETE (automaton_states
);
9751 /* Create automata sets for the insns. */
9752 for (i
= 0; i
< description
->decls_num
; i
++)
9754 decl
= description
->decls
[i
];
9755 if (decl
->mode
== dm_insn_reserv
)
9757 automata_list_start ();
9758 for (automaton
= description
->first_automaton
;
9760 automaton
= automaton
->next_automaton
)
9761 for (ainsn
= automaton
->ainsn_list
;
9763 ainsn
= ainsn
->next_ainsn
)
9764 if (ainsn
->important_p
9765 && ainsn
->insn_reserv_decl
== DECL_INSN_RESERV (decl
))
9767 automata_list_add (automaton
);
9770 DECL_INSN_RESERV (decl
)->important_automata_list
9771 = automata_list_finish ();
9777 /* The following is top level function to generate automat(a,on) for
9778 fast recognition of pipeline hazards. */
9780 expand_automata (void)
9784 description
= create_node (sizeof (struct description
)
9785 /* One entry for cycle advancing insn. */
9786 + sizeof (decl_t
) * VLA_PTR_LENGTH (decls
));
9787 description
->decls_num
= VLA_PTR_LENGTH (decls
);
9788 description
->query_units_num
= 0;
9789 for (i
= 0; i
< description
->decls_num
; i
++)
9791 description
->decls
[i
] = VLA_PTR (decls
, i
);
9792 if (description
->decls
[i
]->mode
== dm_unit
9793 && DECL_UNIT (description
->decls
[i
])->query_p
)
9794 DECL_UNIT (description
->decls
[i
])->query_num
9795 = description
->query_units_num
++;
9797 all_time
= create_ticker ();
9798 check_time
= create_ticker ();
9799 fprintf (stderr
, "Check description...");
9801 check_all_description ();
9802 fprintf (stderr
, "done\n");
9803 ticker_off (&check_time
);
9804 generation_time
= create_ticker ();
9807 transform_insn_regexps ();
9808 check_unit_distributions_to_automata ();
9813 check_automata_insn_issues ();
9817 form_important_insn_automata_lists ();
9818 fprintf (stderr
, "Generation of attributes...");
9820 make_internal_dfa_insn_code_attr ();
9821 make_insn_alts_attr ();
9822 make_default_insn_latency_attr ();
9823 make_bypass_attr ();
9824 fprintf (stderr
, "done\n");
9826 ticker_off (&generation_time
);
9827 ticker_off (&all_time
);
9828 fprintf (stderr
, "All other genattrtab stuff...");
9832 /* The following is top level function to output PHR and to finish
9833 work with pipeline description translator. */
9835 write_automata (void)
9837 fprintf (stderr
, "done\n");
9839 fatal ("Errors in DFA description");
9840 ticker_on (&all_time
);
9841 output_time
= create_ticker ();
9842 fprintf (stderr
, "Forming and outputting automata tables...");
9844 output_dfa_max_issue_rate ();
9846 fprintf (stderr
, "done\n");
9847 fprintf (stderr
, "Output functions to work with automata...");
9849 output_chip_definitions ();
9850 output_max_insn_queue_index_def ();
9851 output_internal_min_issue_delay_func ();
9852 output_internal_trans_func ();
9853 /* Cache of insn dfa codes: */
9854 fprintf (output_file
, "\nstatic int *%s;\n", DFA_INSN_CODES_VARIABLE_NAME
);
9855 fprintf (output_file
, "\nstatic int %s;\n\n",
9856 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
);
9857 output_dfa_insn_code_func ();
9858 output_trans_func ();
9859 fprintf (output_file
, "\n#if %s\n\n", AUTOMATON_STATE_ALTS_MACRO_NAME
);
9860 output_internal_state_alts_func ();
9861 output_state_alts_func ();
9862 fprintf (output_file
, "\n#endif /* #if %s */\n\n",
9863 AUTOMATON_STATE_ALTS_MACRO_NAME
);
9864 output_min_issue_delay_func ();
9865 output_internal_dead_lock_func ();
9866 output_dead_lock_func ();
9867 output_size_func ();
9868 output_internal_reset_func ();
9869 output_reset_func ();
9870 output_min_insn_conflict_delay_func ();
9871 output_internal_insn_latency_func ();
9872 output_insn_latency_func ();
9873 output_print_reservation_func ();
9874 /* Output function get_cpu_unit_code. */
9875 fprintf (output_file
, "\n#if %s\n\n", CPU_UNITS_QUERY_MACRO_NAME
);
9876 output_get_cpu_unit_code_func ();
9877 output_cpu_unit_reservation_p ();
9878 fprintf (output_file
, "\n#endif /* #if %s */\n\n",
9879 CPU_UNITS_QUERY_MACRO_NAME
);
9880 output_dfa_clean_insn_cache_func ();
9881 output_dfa_start_func ();
9882 output_dfa_finish_func ();
9883 fprintf (stderr
, "done\n");
9886 output_description_file
= fopen (output_description_file_name
, "w");
9887 if (output_description_file
== NULL
)
9889 perror (output_description_file_name
);
9890 exit (FATAL_EXIT_CODE
);
9892 fprintf (stderr
, "Output automata description...");
9894 output_description ();
9895 output_automaton_descriptions ();
9896 fprintf (stderr
, "done\n");
9897 output_statistics (output_description_file
);
9899 output_statistics (stderr
);
9900 ticker_off (&output_time
);
9901 output_time_statistics (stderr
);
9904 finish_automata_lists ();
9907 fprintf (stderr
, "Summary:\n");
9908 fprintf (stderr
, " check time ");
9909 print_active_time (stderr
, check_time
);
9910 fprintf (stderr
, ", generation time ");
9911 print_active_time (stderr
, generation_time
);
9912 fprintf (stderr
, ", all time ");
9913 print_active_time (stderr
, all_time
);
9914 fprintf (stderr
, "\n");
9916 /* Finish all work. */
9917 if (output_description_file
!= NULL
)
9919 fflush (output_description_file
);
9920 if (ferror (stdout
) != 0)
9921 fatal ("Error in writing DFA description file %s",
9922 output_description_file_name
);
9923 fclose (output_description_file
);
9925 finish_automaton_decl_table ();
9926 finish_insn_decl_table ();
9927 finish_decl_table ();
9928 obstack_free (&irp
, NULL
);
9929 if (have_error
&& output_description_file
!= NULL
)
9930 remove (output_description_file_name
);