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