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