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