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