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