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