1117395Skan/* Pipeline hazard description translator. 2169689Skan Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 3169689Skan Free Software Foundation, Inc. 4117395Skan 5117395Skan Written by Vladimir Makarov <vmakarov@redhat.com> 6117395Skan 7132718SkanThis file is part of GCC. 8132718Skan 9132718SkanGCC is free software; you can redistribute it and/or modify it 10117395Skanunder the terms of the GNU General Public License as published by the 11117395SkanFree Software Foundation; either version 2, or (at your option) any 12117395Skanlater version. 13117395Skan 14132718SkanGCC is distributed in the hope that it will be useful, but WITHOUT 15117395SkanANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 16117395SkanFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 17117395Skanfor more details. 18117395Skan 19117395SkanYou should have received a copy of the GNU General Public License 20132718Skanalong with GCC; see the file COPYING. If not, write to the Free 21169689SkanSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 22169689Skan02110-1301, USA. */ 23117395Skan 24117395Skan/* References: 25132718Skan 26117395Skan 1. Detecting pipeline structural hazards quickly. T. Proebsting, 27117395Skan C. Fraser. Proceedings of ACM SIGPLAN-SIGACT Symposium on 28117395Skan Principles of Programming Languages, pages 280--286, 1994. 29117395Skan 30117395Skan This article is a good start point to understand usage of finite 31117395Skan state automata for pipeline hazard recognizers. But I'd 32117395Skan recommend the 2nd article for more deep understanding. 33117395Skan 34117395Skan 2. Efficient Instruction Scheduling Using Finite State Automata: 35117395Skan V. Bala and N. Rubin, Proceedings of MICRO-28. This is the best 36117395Skan article about usage of finite state automata for pipeline hazard 37117395Skan recognizers. 38117395Skan 39117395Skan The current implementation is different from the 2nd article in the 40117395Skan following: 41117395Skan 42117395Skan 1. New operator `|' (alternative) is permitted in functional unit 43132718Skan reservation which can be treated deterministically and 44132718Skan non-deterministically. 45117395Skan 46117395Skan 2. Possibility of usage of nondeterministic automata too. 47117395Skan 48117395Skan 3. Possibility to query functional unit reservations for given 49117395Skan automaton state. 50117395Skan 51117395Skan 4. Several constructions to describe impossible reservations 52132718Skan (`exclusion_set', `presence_set', `final_presence_set', 53132718Skan `absence_set', and `final_absence_set'). 54117395Skan 55117395Skan 5. No reverse automata are generated. Trace instruction scheduling 56117395Skan requires this. It can be easily added in the future if we 57117395Skan really need this. 58117395Skan 59117395Skan 6. Union of automaton states are not generated yet. It is planned 60117395Skan to be implemented. Such feature is needed to make more accurate 61117395Skan interlock insn scheduling to get state describing functional 62132718Skan unit reservation in a joint CFG point. */ 63117395Skan 64117395Skan/* This file code processes constructions of machine description file 65117395Skan which describes automaton used for recognition of processor pipeline 66117395Skan hazards by insn scheduler and can be used for other tasks (such as 67117395Skan VLIW insn packing. 68117395Skan 69117395Skan The translator functions `gen_cpu_unit', `gen_query_cpu_unit', 70117395Skan `gen_bypass', `gen_excl_set', `gen_presence_set', 71132718Skan `gen_final_presence_set', `gen_absence_set', 72132718Skan `gen_final_absence_set', `gen_automaton', `gen_automata_option', 73117395Skan `gen_reserv', `gen_insn_reserv' are called from file 74117395Skan `genattrtab.c'. They transform RTL constructions describing 75117395Skan automata in .md file into internal representation convenient for 76117395Skan further processing. 77132718Skan 78117395Skan The translator major function `expand_automata' processes the 79117395Skan description internal representation into finite state automaton. 80117395Skan It can be divided on: 81117395Skan 82117395Skan o checking correctness of the automaton pipeline description 83117395Skan (major function is `check_all_description'). 84117395Skan 85117395Skan o generating automaton (automata) from the description (major 86117395Skan function is `make_automaton'). 87117395Skan 88117395Skan o optional transformation of nondeterministic finite state 89117395Skan automata into deterministic ones if the alternative operator 90132718Skan `|' is treated nondeterministically in the description (major 91117395Skan function is NDFA_to_DFA). 92117395Skan 93117395Skan o optional minimization of the finite state automata by merging 94117395Skan equivalent automaton states (major function is `minimize_DFA'). 95117395Skan 96117395Skan o forming tables (some as comb vectors) and attributes 97117395Skan representing the automata (functions output_..._table). 98117395Skan 99117395Skan Function `write_automata' outputs the created finite state 100117395Skan automaton as different tables and functions which works with the 101117395Skan automata to inquire automaton state and to change its state. These 102117395Skan function are used by gcc instruction scheduler and may be some 103117395Skan other gcc code. */ 104117395Skan 105132718Skan#include "bconfig.h" 106117395Skan#include "system.h" 107132718Skan#include "coretypes.h" 108132718Skan#include "tm.h" 109117395Skan#include "rtl.h" 110117395Skan#include "obstack.h" 111117395Skan#include "errors.h" 112169689Skan#include "gensupport.h" 113117395Skan 114117395Skan#include <math.h> 115117395Skan#include "hashtab.h" 116169689Skan#include "vec.h" 117117395Skan 118117395Skan#ifndef CHAR_BIT 119117395Skan#define CHAR_BIT 8 120117395Skan#endif 121117395Skan 122117395Skan/* Positions in machine description file. Now they are not used. But 123117395Skan they could be used in the future for better diagnostic messages. */ 124117395Skantypedef int pos_t; 125117395Skan 126117395Skan/* The following is element of vector of current (and planned in the 127117395Skan future) functional unit reservations. */ 128117395Skantypedef unsigned HOST_WIDE_INT set_el_t; 129117395Skan 130117395Skan/* Reservations of function units are represented by value of the following 131117395Skan type. */ 132117395Skantypedef set_el_t *reserv_sets_t; 133117395Skan 134117395Skan/* The following structure describes a ticker. */ 135117395Skanstruct ticker 136117395Skan{ 137117395Skan /* The following member value is time of the ticker creation with 138117395Skan taking into account time when the ticker is off. Active time of 139117395Skan the ticker is current time minus the value. */ 140117395Skan int modified_creation_time; 141117395Skan /* The following member value is time (incremented by one) when the 142117395Skan ticker was off. Zero value means that now the ticker is on. */ 143117395Skan int incremented_off_time; 144117395Skan}; 145117395Skan 146117395Skan/* The ticker is represented by the following type. */ 147117395Skantypedef struct ticker ticker_t; 148117395Skan 149117395Skan/* The following type describes elements of output vectors. */ 150117395Skantypedef HOST_WIDE_INT vect_el_t; 151117395Skan 152117395Skan/* Forward declaration of structures of internal representation of 153117395Skan pipeline description based on NDFA. */ 154117395Skan 155117395Skanstruct unit_decl; 156117395Skanstruct bypass_decl; 157117395Skanstruct result_decl; 158117395Skanstruct automaton_decl; 159132718Skanstruct unit_pattern_rel_decl; 160117395Skanstruct reserv_decl; 161117395Skanstruct insn_reserv_decl; 162117395Skanstruct decl; 163117395Skanstruct unit_regexp; 164117395Skanstruct result_regexp; 165117395Skanstruct reserv_regexp; 166117395Skanstruct nothing_regexp; 167117395Skanstruct sequence_regexp; 168117395Skanstruct repeat_regexp; 169117395Skanstruct allof_regexp; 170117395Skanstruct oneof_regexp; 171117395Skanstruct regexp; 172117395Skanstruct description; 173117395Skanstruct unit_set_el; 174132718Skanstruct pattern_set_el; 175132718Skanstruct pattern_reserv; 176117395Skanstruct state; 177117395Skanstruct alt_state; 178117395Skanstruct arc; 179117395Skanstruct ainsn; 180117395Skanstruct automaton; 181117395Skanstruct state_ainsn_table; 182117395Skan 183117395Skan/* The following typedefs are for brevity. */ 184117395Skantypedef struct unit_decl *unit_decl_t; 185117395Skantypedef struct decl *decl_t; 186117395Skantypedef struct regexp *regexp_t; 187117395Skantypedef struct unit_set_el *unit_set_el_t; 188132718Skantypedef struct pattern_set_el *pattern_set_el_t; 189132718Skantypedef struct pattern_reserv *pattern_reserv_t; 190117395Skantypedef struct alt_state *alt_state_t; 191117395Skantypedef struct state *state_t; 192117395Skantypedef struct arc *arc_t; 193117395Skantypedef struct ainsn *ainsn_t; 194117395Skantypedef struct automaton *automaton_t; 195117395Skantypedef struct automata_list_el *automata_list_el_t; 196117395Skantypedef struct state_ainsn_table *state_ainsn_table_t; 197117395Skan 198117395Skan/* Undefined position. */ 199117395Skanstatic pos_t no_pos = 0; 200117395Skan 201117395Skan/* All IR is stored in the following obstack. */ 202117395Skanstatic struct obstack irp; 203117395Skan 204117395Skan 205169689Skan/* Declare vector types for various data structures: */ 206117395Skan 207169689SkanDEF_VEC_P(alt_state_t); 208169689SkanDEF_VEC_ALLOC_P(alt_state_t,heap); 209169689SkanDEF_VEC_P(ainsn_t); 210169689SkanDEF_VEC_ALLOC_P(ainsn_t,heap); 211169689SkanDEF_VEC_P(state_t); 212169689SkanDEF_VEC_ALLOC_P(state_t,heap); 213169689SkanDEF_VEC_P(decl_t); 214169689SkanDEF_VEC_ALLOC_P(decl_t,heap); 215169689SkanDEF_VEC_P(reserv_sets_t); 216169689SkanDEF_VEC_ALLOC_P(reserv_sets_t,heap); 217117395Skan 218169689SkanDEF_VEC_I(vect_el_t); 219169689SkanDEF_VEC_ALLOC_I(vect_el_t, heap); 220169689Skantypedef VEC(vect_el_t,heap) *vla_hwint_t; 221169689Skan 222169689Skan/* Forward declarations of functions used before their definitions, only. */ 223169689Skanstatic regexp_t gen_regexp_sequence (const char *); 224169689Skanstatic void reserv_sets_or (reserv_sets_t, reserv_sets_t, 225169689Skan reserv_sets_t); 226169689Skanstatic reserv_sets_t get_excl_set (reserv_sets_t); 227169689Skanstatic int check_presence_pattern_sets (reserv_sets_t, 228169689Skan reserv_sets_t, int); 229169689Skanstatic int check_absence_pattern_sets (reserv_sets_t, reserv_sets_t, 230169689Skan int); 231169689Skanstatic arc_t first_out_arc (state_t); 232169689Skanstatic arc_t next_out_arc (arc_t); 233117395Skan 234117395Skan 235117395Skan 236117395Skan/* Options with the following names can be set up in automata_option 237117395Skan construction. Because the strings occur more one time we use the 238117395Skan macros. */ 239117395Skan 240117395Skan#define NO_MINIMIZATION_OPTION "-no-minimization" 241117395Skan 242117395Skan#define TIME_OPTION "-time" 243117395Skan 244117395Skan#define V_OPTION "-v" 245117395Skan 246117395Skan#define W_OPTION "-w" 247117395Skan 248117395Skan#define NDFA_OPTION "-ndfa" 249117395Skan 250132718Skan#define PROGRESS_OPTION "-progress" 251132718Skan 252117395Skan/* The following flags are set up by function `initiate_automaton_gen'. */ 253117395Skan 254117395Skan/* Make automata with nondeterministic reservation by insns (`-ndfa'). */ 255117395Skanstatic int ndfa_flag; 256117395Skan 257117395Skan/* Do not make minimization of DFA (`-no-minimization'). */ 258117395Skanstatic int no_minimization_flag; 259117395Skan 260117395Skan/* Value of this variable is number of automata being generated. The 261117395Skan actual number of automata may be less this value if there is not 262117395Skan sufficient number of units. This value is defined by argument of 263117395Skan option `-split' or by constructions automaton if the value is zero 264117395Skan (it is default value of the argument). */ 265117395Skanstatic int split_argument; 266117395Skan 267117395Skan/* Flag of output time statistics (`-time'). */ 268117395Skanstatic int time_flag; 269117395Skan 270117395Skan/* Flag of creation of description file which contains description of 271117395Skan result automaton and statistics information (`-v'). */ 272117395Skanstatic int v_flag; 273117395Skan 274132718Skan/* Flag of output of a progress bar showing how many states were 275132718Skan generated so far for automaton being processed (`-progress'). */ 276132718Skanstatic int progress_flag; 277132718Skan 278117395Skan/* Flag of generating warning instead of error for non-critical errors 279117395Skan (`-w'). */ 280117395Skanstatic int w_flag; 281117395Skan 282117395Skan 283117395Skan/* Output file for pipeline hazard recognizer (PHR) being generated. 284117395Skan The value is NULL if the file is not defined. */ 285117395Skanstatic FILE *output_file; 286117395Skan 287117395Skan/* Description file of PHR. The value is NULL if the file is not 288117395Skan created. */ 289117395Skanstatic FILE *output_description_file; 290117395Skan 291117395Skan/* PHR description file name. */ 292117395Skanstatic char *output_description_file_name; 293117395Skan 294117395Skan/* Value of the following variable is node representing description 295117395Skan being processed. This is start point of IR. */ 296117395Skanstatic struct description *description; 297117395Skan 298117395Skan 299117395Skan 300117395Skan/* This page contains description of IR structure (nodes). */ 301117395Skan 302117395Skanenum decl_mode 303117395Skan{ 304117395Skan dm_unit, 305117395Skan dm_bypass, 306117395Skan dm_automaton, 307117395Skan dm_excl, 308117395Skan dm_presence, 309117395Skan dm_absence, 310117395Skan dm_reserv, 311117395Skan dm_insn_reserv 312117395Skan}; 313117395Skan 314117395Skan/* This describes define_cpu_unit and define_query_cpu_unit (see file 315117395Skan rtl.def). */ 316117395Skanstruct unit_decl 317117395Skan{ 318169689Skan const char *name; 319117395Skan /* NULL if the automaton name is absent. */ 320169689Skan const char *automaton_name; 321117395Skan /* If the following value is not zero, the cpu unit reservation is 322117395Skan described in define_query_cpu_unit. */ 323117395Skan char query_p; 324117395Skan 325117395Skan /* The following fields are defined by checker. */ 326117395Skan 327117395Skan /* The following field value is nonzero if the unit is used in an 328117395Skan regexp. */ 329117395Skan char unit_is_used; 330117395Skan 331117395Skan /* The following field value is order number (0, 1, ...) of given 332117395Skan unit. */ 333117395Skan int unit_num; 334117395Skan /* The following field value is corresponding declaration of 335117395Skan automaton which was given in description. If the field value is 336117395Skan NULL then automaton in the unit declaration was absent. */ 337117395Skan struct automaton_decl *automaton_decl; 338117395Skan /* The following field value is maximal cycle number (1, ...) on 339117395Skan which given unit occurs in insns. Zero value means that given 340117395Skan unit is not used in insns. */ 341117395Skan int max_occ_cycle_num; 342132718Skan /* The following field value is minimal cycle number (0, ...) on 343132718Skan which given unit occurs in insns. -1 value means that given 344132718Skan unit is not used in insns. */ 345132718Skan int min_occ_cycle_num; 346117395Skan /* The following list contains units which conflict with given 347117395Skan unit. */ 348117395Skan unit_set_el_t excl_list; 349132718Skan /* The following list contains patterns which are required to 350117395Skan reservation of given unit. */ 351132718Skan pattern_set_el_t presence_list; 352132718Skan pattern_set_el_t final_presence_list; 353132718Skan /* The following list contains patterns which should be not present 354132718Skan in reservation for given unit. */ 355132718Skan pattern_set_el_t absence_list; 356132718Skan pattern_set_el_t final_absence_list; 357117395Skan /* The following is used only when `query_p' has nonzero value. 358117395Skan This is query number for the unit. */ 359117395Skan int query_num; 360132718Skan /* The following is the last cycle on which the unit was checked for 361132718Skan correct distributions of units to automata in a regexp. */ 362132718Skan int last_distribution_check_cycle; 363117395Skan 364117395Skan /* The following fields are defined by automaton generator. */ 365117395Skan 366117395Skan /* The following field value is number of the automaton to which 367117395Skan given unit belongs. */ 368117395Skan int corresponding_automaton_num; 369132718Skan /* If the following value is not zero, the cpu unit is present in a 370132718Skan `exclusion_set' or in right part of a `presence_set', 371132718Skan `final_presence_set', `absence_set', and 372132718Skan `final_absence_set'define_query_cpu_unit. */ 373132718Skan char in_set_p; 374117395Skan}; 375117395Skan 376117395Skan/* This describes define_bypass (see file rtl.def). */ 377117395Skanstruct bypass_decl 378117395Skan{ 379117395Skan int latency; 380169689Skan const char *out_insn_name; 381169689Skan const char *in_insn_name; 382169689Skan const char *bypass_guard_name; 383117395Skan 384117395Skan /* The following fields are defined by checker. */ 385117395Skan 386117395Skan /* output and input insns of given bypass. */ 387117395Skan struct insn_reserv_decl *out_insn_reserv; 388117395Skan struct insn_reserv_decl *in_insn_reserv; 389117395Skan /* The next bypass for given output insn. */ 390117395Skan struct bypass_decl *next; 391117395Skan}; 392117395Skan 393117395Skan/* This describes define_automaton (see file rtl.def). */ 394117395Skanstruct automaton_decl 395117395Skan{ 396169689Skan const char *name; 397117395Skan 398117395Skan /* The following fields are defined by automaton generator. */ 399117395Skan 400117395Skan /* The following field value is nonzero if the automaton is used in 401117395Skan an regexp definition. */ 402117395Skan char automaton_is_used; 403117395Skan 404117395Skan /* The following fields are defined by checker. */ 405117395Skan 406117395Skan /* The following field value is the corresponding automaton. This 407117395Skan field is not NULL only if the automaton is present in unit 408117395Skan declarations and the automatic partition on automata is not 409117395Skan used. */ 410117395Skan automaton_t corresponding_automaton; 411117395Skan}; 412117395Skan 413132718Skan/* This describes exclusion relations: exclusion_set (see file 414132718Skan rtl.def). */ 415132718Skanstruct excl_rel_decl 416117395Skan{ 417132718Skan int all_names_num; 418117395Skan int first_list_length; 419117395Skan char *names [1]; 420117395Skan}; 421117395Skan 422132718Skan/* This describes unit relations: [final_]presence_set or 423132718Skan [final_]absence_set (see file rtl.def). */ 424132718Skanstruct unit_pattern_rel_decl 425132718Skan{ 426132718Skan int final_p; 427132718Skan int names_num; 428132718Skan int patterns_num; 429132718Skan char **names; 430132718Skan char ***patterns; 431132718Skan}; 432132718Skan 433117395Skan/* This describes define_reservation (see file rtl.def). */ 434117395Skanstruct reserv_decl 435117395Skan{ 436169689Skan const char *name; 437117395Skan regexp_t regexp; 438117395Skan 439117395Skan /* The following fields are defined by checker. */ 440117395Skan 441117395Skan /* The following field value is nonzero if the unit is used in an 442117395Skan regexp. */ 443117395Skan char reserv_is_used; 444117395Skan /* The following field is used to check up cycle in expression 445117395Skan definition. */ 446117395Skan int loop_pass_num; 447117395Skan}; 448117395Skan 449132718Skan/* This describes define_insn_reservation (see file rtl.def). */ 450117395Skanstruct insn_reserv_decl 451117395Skan{ 452117395Skan rtx condexp; 453117395Skan int default_latency; 454117395Skan regexp_t regexp; 455169689Skan const char *name; 456117395Skan 457117395Skan /* The following fields are defined by checker. */ 458117395Skan 459117395Skan /* The following field value is order number (0, 1, ...) of given 460117395Skan insn. */ 461117395Skan int insn_num; 462117395Skan /* The following field value is list of bypasses in which given insn 463117395Skan is output insn. */ 464117395Skan struct bypass_decl *bypass_list; 465117395Skan 466117395Skan /* The following fields are defined by automaton generator. */ 467117395Skan 468117395Skan /* The following field is the insn regexp transformed that 469117395Skan the regexp has not optional regexp, repetition regexp, and an 470117395Skan reservation name (i.e. reservation identifiers are changed by the 471117395Skan corresponding regexp) and all alternations are the topest level 472117395Skan of the regexp. The value can be NULL only if it is special 473117395Skan insn `cycle advancing'. */ 474117395Skan regexp_t transformed_regexp; 475117395Skan /* The following field value is list of arcs marked given 476132718Skan insn. The field is used in transformation NDFA -> DFA. */ 477117395Skan arc_t arcs_marked_by_insn; 478117395Skan /* The two following fields are used during minimization of a finite state 479117395Skan automaton. */ 480117395Skan /* The field value is number of equivalence class of state into 481117395Skan which arc marked by given insn enters from a state (fixed during 482117395Skan an automaton minimization). */ 483117395Skan int equiv_class_num; 484117395Skan /* The following member value is the list to automata which can be 485117395Skan changed by the insn issue. */ 486117395Skan automata_list_el_t important_automata_list; 487117395Skan /* The following member is used to process insn once for output. */ 488117395Skan int processed_p; 489117395Skan}; 490117395Skan 491117395Skan/* This contains a declaration mentioned above. */ 492117395Skanstruct decl 493117395Skan{ 494117395Skan /* What node in the union? */ 495117395Skan enum decl_mode mode; 496117395Skan pos_t pos; 497117395Skan union 498117395Skan { 499117395Skan struct unit_decl unit; 500117395Skan struct bypass_decl bypass; 501117395Skan struct automaton_decl automaton; 502132718Skan struct excl_rel_decl excl; 503132718Skan struct unit_pattern_rel_decl presence; 504132718Skan struct unit_pattern_rel_decl absence; 505117395Skan struct reserv_decl reserv; 506117395Skan struct insn_reserv_decl insn_reserv; 507117395Skan } decl; 508117395Skan}; 509117395Skan 510117395Skan/* The following structures represent parsed reservation strings. */ 511117395Skanenum regexp_mode 512117395Skan{ 513117395Skan rm_unit, 514117395Skan rm_reserv, 515117395Skan rm_nothing, 516117395Skan rm_sequence, 517117395Skan rm_repeat, 518117395Skan rm_allof, 519117395Skan rm_oneof 520117395Skan}; 521117395Skan 522117395Skan/* Cpu unit in reservation. */ 523117395Skanstruct unit_regexp 524117395Skan{ 525169689Skan const char *name; 526117395Skan unit_decl_t unit_decl; 527117395Skan}; 528117395Skan 529117395Skan/* Define_reservation in a reservation. */ 530117395Skanstruct reserv_regexp 531117395Skan{ 532169689Skan const char *name; 533117395Skan struct reserv_decl *reserv_decl; 534117395Skan}; 535117395Skan 536117395Skan/* Absence of reservation (represented by string `nothing'). */ 537117395Skanstruct nothing_regexp 538117395Skan{ 539117395Skan /* This used to be empty but ISO C doesn't allow that. */ 540117395Skan char unused; 541117395Skan}; 542117395Skan 543117395Skan/* Representation of reservations separated by ',' (see file 544117395Skan rtl.def). */ 545117395Skanstruct sequence_regexp 546117395Skan{ 547117395Skan int regexps_num; 548117395Skan regexp_t regexps [1]; 549117395Skan}; 550117395Skan 551117395Skan/* Representation of construction `repeat' (see file rtl.def). */ 552117395Skanstruct repeat_regexp 553117395Skan{ 554117395Skan int repeat_num; 555117395Skan regexp_t regexp; 556117395Skan}; 557117395Skan 558117395Skan/* Representation of reservations separated by '+' (see file 559117395Skan rtl.def). */ 560117395Skanstruct allof_regexp 561117395Skan{ 562117395Skan int regexps_num; 563117395Skan regexp_t regexps [1]; 564117395Skan}; 565117395Skan 566117395Skan/* Representation of reservations separated by '|' (see file 567117395Skan rtl.def). */ 568117395Skanstruct oneof_regexp 569117395Skan{ 570117395Skan int regexps_num; 571117395Skan regexp_t regexps [1]; 572117395Skan}; 573117395Skan 574117395Skan/* Representation of a reservation string. */ 575117395Skanstruct regexp 576117395Skan{ 577117395Skan /* What node in the union? */ 578117395Skan enum regexp_mode mode; 579117395Skan pos_t pos; 580117395Skan union 581117395Skan { 582117395Skan struct unit_regexp unit; 583117395Skan struct reserv_regexp reserv; 584117395Skan struct nothing_regexp nothing; 585117395Skan struct sequence_regexp sequence; 586117395Skan struct repeat_regexp repeat; 587117395Skan struct allof_regexp allof; 588117395Skan struct oneof_regexp oneof; 589117395Skan } regexp; 590117395Skan}; 591117395Skan 592132718Skan/* Represents description of pipeline hazard description based on 593117395Skan NDFA. */ 594117395Skanstruct description 595117395Skan{ 596117395Skan int decls_num; 597117395Skan 598117395Skan /* The following fields are defined by checker. */ 599117395Skan 600117395Skan /* The following fields values are correspondingly number of all 601117395Skan units, query units, and insns in the description. */ 602117395Skan int units_num; 603117395Skan int query_units_num; 604117395Skan int insns_num; 605117395Skan /* The following field value is max length (in cycles) of 606117395Skan reservations of insns. The field value is defined only for 607117395Skan correct programs. */ 608117395Skan int max_insn_reserv_cycles; 609117395Skan 610117395Skan /* The following fields are defined by automaton generator. */ 611117395Skan 612117395Skan /* The following field value is the first automaton. */ 613117395Skan automaton_t first_automaton; 614117395Skan 615117395Skan /* The following field is created by pipeline hazard parser and 616117395Skan contains all declarations. We allocate additional entry for 617117395Skan special insn "cycle advancing" which is added by the automaton 618117395Skan generator. */ 619117395Skan decl_t decls [1]; 620117395Skan}; 621117395Skan 622117395Skan 623117395Skan/* The following nodes are created in automaton checker. */ 624117395Skan 625132718Skan/* The following nodes represent exclusion set for cpu units. Each 626132718Skan element is accessed through only one excl_list. */ 627117395Skanstruct unit_set_el 628117395Skan{ 629117395Skan unit_decl_t unit_decl; 630117395Skan unit_set_el_t next_unit_set_el; 631117395Skan}; 632117395Skan 633132718Skan/* The following nodes represent presence or absence pattern for cpu 634132718Skan units. Each element is accessed through only one presence_list or 635132718Skan absence_list. */ 636132718Skanstruct pattern_set_el 637132718Skan{ 638132718Skan /* The number of units in unit_decls. */ 639132718Skan int units_num; 640132718Skan /* The units forming the pattern. */ 641132718Skan struct unit_decl **unit_decls; 642132718Skan pattern_set_el_t next_pattern_set_el; 643132718Skan}; 644117395Skan 645117395Skan 646117395Skan/* The following nodes are created in automaton generator. */ 647117395Skan 648132718Skan 649132718Skan/* The following nodes represent presence or absence pattern for cpu 650132718Skan units. Each element is accessed through only one element of 651132718Skan unit_presence_set_table or unit_absence_set_table. */ 652132718Skanstruct pattern_reserv 653132718Skan{ 654132718Skan reserv_sets_t reserv; 655132718Skan pattern_reserv_t next_pattern_reserv; 656132718Skan}; 657132718Skan 658117395Skan/* The following node type describes state automaton. The state may 659117395Skan be deterministic or non-deterministic. Non-deterministic state has 660117395Skan several component states which represent alternative cpu units 661117395Skan reservations. The state also is used for describing a 662117395Skan deterministic reservation of automaton insn. */ 663117395Skanstruct state 664117395Skan{ 665117395Skan /* The following member value is nonzero if there is a transition by 666117395Skan cycle advancing. */ 667117395Skan int new_cycle_p; 668117395Skan /* The following field is list of processor unit reservations on 669117395Skan each cycle. */ 670117395Skan reserv_sets_t reservs; 671117395Skan /* The following field is unique number of given state between other 672117395Skan states. */ 673117395Skan int unique_num; 674117395Skan /* The following field value is automaton to which given state 675117395Skan belongs. */ 676117395Skan automaton_t automaton; 677117395Skan /* The following field value is the first arc output from given 678117395Skan state. */ 679117395Skan arc_t first_out_arc; 680169689Skan unsigned int num_out_arcs; 681117395Skan /* The following field is used to form NDFA. */ 682117395Skan char it_was_placed_in_stack_for_NDFA_forming; 683117395Skan /* The following field is used to form DFA. */ 684117395Skan char it_was_placed_in_stack_for_DFA_forming; 685132718Skan /* The following field is used to transform NDFA to DFA and DFA 686132718Skan minimization. The field value is not NULL if the state is a 687132718Skan compound state. In this case the value of field `unit_sets_list' 688132718Skan is NULL. All states in the list are in the hash table. The list 689132718Skan is formed through field `next_sorted_alt_state'. We should 690132718Skan support only one level of nesting state. */ 691117395Skan alt_state_t component_states; 692117395Skan /* The following field is used for passing graph of states. */ 693117395Skan int pass_num; 694117395Skan /* The list of states belonging to one equivalence class is formed 695117395Skan with the aid of the following field. */ 696117395Skan state_t next_equiv_class_state; 697117395Skan /* The two following fields are used during minimization of a finite 698117395Skan state automaton. */ 699117395Skan int equiv_class_num_1, equiv_class_num_2; 700117395Skan /* The following field is used during minimization of a finite state 701117395Skan automaton. The field value is state corresponding to equivalence 702117395Skan class to which given state belongs. */ 703117395Skan state_t equiv_class_state; 704169689Skan unsigned int *presence_signature; 705117395Skan /* The following field value is the order number of given state. 706117395Skan The states in final DFA is enumerated with the aid of the 707117395Skan following field. */ 708117395Skan int order_state_num; 709117395Skan /* This member is used for passing states for searching minimal 710117395Skan delay time. */ 711117395Skan int state_pass_num; 712117395Skan /* The following member is used to evaluate min issue delay of insn 713117395Skan for a state. */ 714117395Skan int min_insn_issue_delay; 715117395Skan /* The following member is used to evaluate max issue rate of the 716117395Skan processor. The value of the member is maximal length of the path 717117395Skan from given state no containing arcs marked by special insn `cycle 718117395Skan advancing'. */ 719117395Skan int longest_path_length; 720117395Skan}; 721117395Skan 722117395Skan/* The following macro is an initial value of member 723117395Skan `longest_path_length' of a state. */ 724117395Skan#define UNDEFINED_LONGEST_PATH_LENGTH -1 725117395Skan 726117395Skan/* Automaton arc. */ 727117395Skanstruct arc 728117395Skan{ 729117395Skan /* The following field refers for the state into which given arc 730117395Skan enters. */ 731117395Skan state_t to_state; 732117395Skan /* The following field describes that the insn issue (with cycle 733117395Skan advancing for special insn `cycle advancing' and without cycle 734117395Skan advancing for others) makes transition from given state to 735117395Skan another given state. */ 736117395Skan ainsn_t insn; 737117395Skan /* The following field value is the next arc output from the same 738117395Skan state. */ 739117395Skan arc_t next_out_arc; 740117395Skan /* List of arcs marked given insn is formed with the following 741132718Skan field. The field is used in transformation NDFA -> DFA. */ 742117395Skan arc_t next_arc_marked_by_insn; 743117395Skan}; 744117395Skan 745117395Skan/* The following node type describes a deterministic alternative in 746117395Skan non-deterministic state which characterizes cpu unit reservations 747117395Skan of automaton insn or which is part of NDFA. */ 748117395Skanstruct alt_state 749117395Skan{ 750132718Skan /* The following field is a deterministic state which characterizes 751117395Skan unit reservations of the instruction. */ 752117395Skan state_t state; 753117395Skan /* The following field refers to the next state which characterizes 754117395Skan unit reservations of the instruction. */ 755117395Skan alt_state_t next_alt_state; 756117395Skan /* The following field refers to the next state in sorted list. */ 757117395Skan alt_state_t next_sorted_alt_state; 758117395Skan}; 759117395Skan 760117395Skan/* The following node type describes insn of automaton. They are 761117395Skan labels of FA arcs. */ 762117395Skanstruct ainsn 763117395Skan{ 764117395Skan /* The following field value is the corresponding insn declaration 765117395Skan of description. */ 766117395Skan struct insn_reserv_decl *insn_reserv_decl; 767117395Skan /* The following field value is the next insn declaration for an 768117395Skan automaton. */ 769117395Skan ainsn_t next_ainsn; 770117395Skan /* The following field is states which characterize automaton unit 771117395Skan reservations of the instruction. The value can be NULL only if it 772117395Skan is special insn `cycle advancing'. */ 773117395Skan alt_state_t alt_states; 774117395Skan /* The following field is sorted list of states which characterize 775117395Skan automaton unit reservations of the instruction. The value can be 776117395Skan NULL only if it is special insn `cycle advancing'. */ 777117395Skan alt_state_t sorted_alt_states; 778117395Skan /* The following field refers the next automaton insn with 779117395Skan the same reservations. */ 780117395Skan ainsn_t next_same_reservs_insn; 781117395Skan /* The following field is flag of the first automaton insn with the 782117395Skan same reservations in the declaration list. Only arcs marked such 783117395Skan insn is present in the automaton. This significantly decreases 784117395Skan memory requirements especially when several automata are 785117395Skan formed. */ 786117395Skan char first_insn_with_same_reservs; 787117395Skan /* The following member has nonzero value if there is arc from state of 788117395Skan the automaton marked by the ainsn. */ 789117395Skan char arc_exists_p; 790117395Skan /* Cyclic list of insns of an equivalence class is formed with the 791117395Skan aid of the following field. */ 792117395Skan ainsn_t next_equiv_class_insn; 793117395Skan /* The following field value is nonzero if the insn declaration is 794117395Skan the first insn declaration with given equivalence number. */ 795169689Skan char first_ainsn_with_given_equivalence_num; 796117395Skan /* The following field is number of class of equivalence of insns. 797117395Skan It is necessary because many insns may be equivalent with the 798117395Skan point of view of pipeline hazards. */ 799117395Skan int insn_equiv_class_num; 800117395Skan /* The following member value is TRUE if there is an arc in the 801117395Skan automaton marked by the insn into another state. In other 802117395Skan words, the insn can change the state of the automaton. */ 803117395Skan int important_p; 804117395Skan}; 805117395Skan 806132718Skan/* The following describes an automaton for PHR. */ 807117395Skanstruct automaton 808117395Skan{ 809117395Skan /* The following field value is the list of insn declarations for 810117395Skan given automaton. */ 811117395Skan ainsn_t ainsn_list; 812117395Skan /* The following field value is the corresponding automaton 813117395Skan declaration. This field is not NULL only if the automatic 814117395Skan partition on automata is not used. */ 815117395Skan struct automaton_decl *corresponding_automaton_decl; 816117395Skan /* The following field value is the next automaton. */ 817117395Skan automaton_t next_automaton; 818117395Skan /* The following field is start state of FA. There are not unit 819117395Skan reservations in the state. */ 820117395Skan state_t start_state; 821117395Skan /* The following field value is number of equivalence classes of 822117395Skan insns (see field `insn_equiv_class_num' in 823117395Skan `insn_reserv_decl'). */ 824117395Skan int insn_equiv_classes_num; 825117395Skan /* The following field value is number of states of final DFA. */ 826117395Skan int achieved_states_num; 827117395Skan /* The following field value is the order number (0, 1, ...) of 828117395Skan given automaton. */ 829117395Skan int automaton_order_num; 830117395Skan /* The following fields contain statistics information about 831117395Skan building automaton. */ 832117395Skan int NDFA_states_num, DFA_states_num; 833117395Skan /* The following field value is defined only if minimization of DFA 834117395Skan is used. */ 835117395Skan int minimal_DFA_states_num; 836117395Skan int NDFA_arcs_num, DFA_arcs_num; 837117395Skan /* The following field value is defined only if minimization of DFA 838117395Skan is used. */ 839117395Skan int minimal_DFA_arcs_num; 840169689Skan /* The following member refers for two table state x ainsn -> int. 841169689Skan ??? Above sentence is incomprehensible. */ 842117395Skan state_ainsn_table_t trans_table; 843117395Skan /* The following member value is maximal value of min issue delay 844117395Skan for insns of the automaton. */ 845117395Skan int max_min_delay; 846117395Skan /* Usually min issue delay is small and we can place several (2, 4, 847117395Skan 8) elements in one vector element. So the compression factor can 848117395Skan be 1 (no compression), 2, 4, 8. */ 849117395Skan int min_issue_delay_table_compression_factor; 850169689Skan /* Total number of locked states in this automaton. */ 851169689Skan int locked_states; 852117395Skan}; 853117395Skan 854117395Skan/* The following is the element of the list of automata. */ 855117395Skanstruct automata_list_el 856117395Skan{ 857117395Skan /* The automaton itself. */ 858117395Skan automaton_t automaton; 859117395Skan /* The next automata set element. */ 860117395Skan automata_list_el_t next_automata_list_el; 861117395Skan}; 862117395Skan 863117395Skan/* The following structure describes a table state X ainsn -> int(>= 0). */ 864117395Skanstruct state_ainsn_table 865117395Skan{ 866117395Skan /* Automaton to which given table belongs. */ 867117395Skan automaton_t automaton; 868117395Skan /* The following tree vectors for comb vector implementation of the 869117395Skan table. */ 870117395Skan vla_hwint_t comb_vect; 871117395Skan vla_hwint_t check_vect; 872117395Skan vla_hwint_t base_vect; 873117395Skan /* This is simple implementation of the table. */ 874117395Skan vla_hwint_t full_vect; 875117395Skan /* Minimal and maximal values of the previous vectors. */ 876117395Skan int min_comb_vect_el_value, max_comb_vect_el_value; 877117395Skan int min_base_vect_el_value, max_base_vect_el_value; 878117395Skan}; 879117395Skan 880117395Skan/* Macros to access members of unions. Use only them for access to 881117395Skan union members of declarations and regexps. */ 882117395Skan 883117395Skan#if defined ENABLE_CHECKING && (GCC_VERSION >= 2007) 884117395Skan 885117395Skan#define DECL_UNIT(d) __extension__ \ 886117395Skan(({ struct decl *const _decl = (d); \ 887117395Skan if (_decl->mode != dm_unit) \ 888117395Skan decl_mode_check_failed (_decl->mode, "dm_unit", \ 889117395Skan __FILE__, __LINE__, __FUNCTION__); \ 890117395Skan &(_decl)->decl.unit; })) 891117395Skan 892117395Skan#define DECL_BYPASS(d) __extension__ \ 893117395Skan(({ struct decl *const _decl = (d); \ 894117395Skan if (_decl->mode != dm_bypass) \ 895117395Skan decl_mode_check_failed (_decl->mode, "dm_bypass", \ 896117395Skan __FILE__, __LINE__, __FUNCTION__); \ 897117395Skan &(_decl)->decl.bypass; })) 898117395Skan 899117395Skan#define DECL_AUTOMATON(d) __extension__ \ 900132718Skan(({ struct decl *const _decl = (d); \ 901117395Skan if (_decl->mode != dm_automaton) \ 902117395Skan decl_mode_check_failed (_decl->mode, "dm_automaton", \ 903117395Skan __FILE__, __LINE__, __FUNCTION__); \ 904117395Skan &(_decl)->decl.automaton; })) 905117395Skan 906117395Skan#define DECL_EXCL(d) __extension__ \ 907132718Skan(({ struct decl *const _decl = (d); \ 908117395Skan if (_decl->mode != dm_excl) \ 909117395Skan decl_mode_check_failed (_decl->mode, "dm_excl", \ 910117395Skan __FILE__, __LINE__, __FUNCTION__); \ 911117395Skan &(_decl)->decl.excl; })) 912117395Skan 913117395Skan#define DECL_PRESENCE(d) __extension__ \ 914117395Skan(({ struct decl *const _decl = (d); \ 915117395Skan if (_decl->mode != dm_presence) \ 916117395Skan decl_mode_check_failed (_decl->mode, "dm_presence", \ 917117395Skan __FILE__, __LINE__, __FUNCTION__); \ 918117395Skan &(_decl)->decl.presence; })) 919117395Skan 920117395Skan#define DECL_ABSENCE(d) __extension__ \ 921132718Skan(({ struct decl *const _decl = (d); \ 922117395Skan if (_decl->mode != dm_absence) \ 923117395Skan decl_mode_check_failed (_decl->mode, "dm_absence", \ 924117395Skan __FILE__, __LINE__, __FUNCTION__); \ 925117395Skan &(_decl)->decl.absence; })) 926117395Skan 927117395Skan#define DECL_RESERV(d) __extension__ \ 928117395Skan(({ struct decl *const _decl = (d); \ 929117395Skan if (_decl->mode != dm_reserv) \ 930117395Skan decl_mode_check_failed (_decl->mode, "dm_reserv", \ 931117395Skan __FILE__, __LINE__, __FUNCTION__); \ 932117395Skan &(_decl)->decl.reserv; })) 933117395Skan 934117395Skan#define DECL_INSN_RESERV(d) __extension__ \ 935132718Skan(({ struct decl *const _decl = (d); \ 936117395Skan if (_decl->mode != dm_insn_reserv) \ 937117395Skan decl_mode_check_failed (_decl->mode, "dm_insn_reserv", \ 938117395Skan __FILE__, __LINE__, __FUNCTION__); \ 939117395Skan &(_decl)->decl.insn_reserv; })) 940117395Skan 941132718Skanstatic const char *decl_name (enum decl_mode); 942132718Skanstatic void decl_mode_check_failed (enum decl_mode, const char *, 943169689Skan const char *, int, const char *) 944169689Skan ATTRIBUTE_NORETURN; 945117395Skan 946117395Skan/* Return string representation of declaration mode MODE. */ 947117395Skanstatic const char * 948132718Skandecl_name (enum decl_mode mode) 949117395Skan{ 950117395Skan static char str [100]; 951117395Skan 952117395Skan if (mode == dm_unit) 953117395Skan return "dm_unit"; 954117395Skan else if (mode == dm_bypass) 955117395Skan return "dm_bypass"; 956117395Skan else if (mode == dm_automaton) 957117395Skan return "dm_automaton"; 958117395Skan else if (mode == dm_excl) 959117395Skan return "dm_excl"; 960117395Skan else if (mode == dm_presence) 961117395Skan return "dm_presence"; 962117395Skan else if (mode == dm_absence) 963117395Skan return "dm_absence"; 964117395Skan else if (mode == dm_reserv) 965117395Skan return "dm_reserv"; 966117395Skan else if (mode == dm_insn_reserv) 967117395Skan return "dm_insn_reserv"; 968117395Skan else 969117395Skan sprintf (str, "unknown (%d)", (int) mode); 970117395Skan return str; 971117395Skan} 972117395Skan 973117395Skan/* The function prints message about unexpected declaration and finish 974117395Skan the program. */ 975117395Skanstatic void 976132718Skandecl_mode_check_failed (enum decl_mode mode, const char *expected_mode_str, 977132718Skan const char *file, int line, const char *func) 978117395Skan{ 979117395Skan fprintf 980117395Skan (stderr, 981117395Skan "\n%s: %d: error in %s: DECL check: expected decl %s, have %s\n", 982117395Skan file, line, func, expected_mode_str, decl_name (mode)); 983117395Skan exit (1); 984117395Skan} 985117395Skan 986117395Skan 987117395Skan#define REGEXP_UNIT(r) __extension__ \ 988117395Skan(({ struct regexp *const _regexp = (r); \ 989117395Skan if (_regexp->mode != rm_unit) \ 990117395Skan regexp_mode_check_failed (_regexp->mode, "rm_unit", \ 991117395Skan __FILE__, __LINE__, __FUNCTION__); \ 992117395Skan &(_regexp)->regexp.unit; })) 993117395Skan 994117395Skan#define REGEXP_RESERV(r) __extension__ \ 995117395Skan(({ struct regexp *const _regexp = (r); \ 996117395Skan if (_regexp->mode != rm_reserv) \ 997117395Skan regexp_mode_check_failed (_regexp->mode, "rm_reserv", \ 998117395Skan __FILE__, __LINE__, __FUNCTION__); \ 999117395Skan &(_regexp)->regexp.reserv; })) 1000117395Skan 1001117395Skan#define REGEXP_SEQUENCE(r) __extension__ \ 1002117395Skan(({ struct regexp *const _regexp = (r); \ 1003117395Skan if (_regexp->mode != rm_sequence) \ 1004117395Skan regexp_mode_check_failed (_regexp->mode, "rm_sequence", \ 1005117395Skan __FILE__, __LINE__, __FUNCTION__); \ 1006117395Skan &(_regexp)->regexp.sequence; })) 1007117395Skan 1008117395Skan#define REGEXP_REPEAT(r) __extension__ \ 1009117395Skan(({ struct regexp *const _regexp = (r); \ 1010117395Skan if (_regexp->mode != rm_repeat) \ 1011117395Skan regexp_mode_check_failed (_regexp->mode, "rm_repeat", \ 1012117395Skan __FILE__, __LINE__, __FUNCTION__); \ 1013117395Skan &(_regexp)->regexp.repeat; })) 1014117395Skan 1015117395Skan#define REGEXP_ALLOF(r) __extension__ \ 1016117395Skan(({ struct regexp *const _regexp = (r); \ 1017117395Skan if (_regexp->mode != rm_allof) \ 1018117395Skan regexp_mode_check_failed (_regexp->mode, "rm_allof", \ 1019117395Skan __FILE__, __LINE__, __FUNCTION__); \ 1020117395Skan &(_regexp)->regexp.allof; })) 1021117395Skan 1022117395Skan#define REGEXP_ONEOF(r) __extension__ \ 1023117395Skan(({ struct regexp *const _regexp = (r); \ 1024117395Skan if (_regexp->mode != rm_oneof) \ 1025117395Skan regexp_mode_check_failed (_regexp->mode, "rm_oneof", \ 1026117395Skan __FILE__, __LINE__, __FUNCTION__); \ 1027117395Skan &(_regexp)->regexp.oneof; })) 1028117395Skan 1029132718Skanstatic const char *regexp_name (enum regexp_mode); 1030132718Skanstatic void regexp_mode_check_failed (enum regexp_mode, const char *, 1031132718Skan const char *, int, 1032169689Skan const char *) ATTRIBUTE_NORETURN; 1033117395Skan 1034117395Skan 1035117395Skan/* Return string representation of regexp mode MODE. */ 1036117395Skanstatic const char * 1037132718Skanregexp_name (enum regexp_mode mode) 1038117395Skan{ 1039169689Skan switch (mode) 1040169689Skan { 1041169689Skan case rm_unit: 1042169689Skan return "rm_unit"; 1043169689Skan case rm_reserv: 1044169689Skan return "rm_reserv"; 1045169689Skan case rm_nothing: 1046169689Skan return "rm_nothing"; 1047169689Skan case rm_sequence: 1048169689Skan return "rm_sequence"; 1049169689Skan case rm_repeat: 1050169689Skan return "rm_repeat"; 1051169689Skan case rm_allof: 1052169689Skan return "rm_allof"; 1053169689Skan case rm_oneof: 1054169689Skan return "rm_oneof"; 1055169689Skan default: 1056169689Skan gcc_unreachable (); 1057169689Skan } 1058117395Skan} 1059117395Skan 1060117395Skan/* The function prints message about unexpected regexp and finish the 1061117395Skan program. */ 1062117395Skanstatic void 1063132718Skanregexp_mode_check_failed (enum regexp_mode mode, 1064132718Skan const char *expected_mode_str, 1065132718Skan const char *file, int line, const char *func) 1066117395Skan{ 1067117395Skan fprintf 1068117395Skan (stderr, 1069117395Skan "\n%s: %d: error in %s: REGEXP check: expected decl %s, have %s\n", 1070117395Skan file, line, func, expected_mode_str, regexp_name (mode)); 1071117395Skan exit (1); 1072117395Skan} 1073117395Skan 1074117395Skan#else /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */ 1075117395Skan 1076117395Skan#define DECL_UNIT(d) (&(d)->decl.unit) 1077117395Skan#define DECL_BYPASS(d) (&(d)->decl.bypass) 1078117395Skan#define DECL_AUTOMATON(d) (&(d)->decl.automaton) 1079117395Skan#define DECL_EXCL(d) (&(d)->decl.excl) 1080117395Skan#define DECL_PRESENCE(d) (&(d)->decl.presence) 1081117395Skan#define DECL_ABSENCE(d) (&(d)->decl.absence) 1082117395Skan#define DECL_RESERV(d) (&(d)->decl.reserv) 1083117395Skan#define DECL_INSN_RESERV(d) (&(d)->decl.insn_reserv) 1084117395Skan 1085117395Skan#define REGEXP_UNIT(r) (&(r)->regexp.unit) 1086117395Skan#define REGEXP_RESERV(r) (&(r)->regexp.reserv) 1087117395Skan#define REGEXP_SEQUENCE(r) (&(r)->regexp.sequence) 1088117395Skan#define REGEXP_REPEAT(r) (&(r)->regexp.repeat) 1089117395Skan#define REGEXP_ALLOF(r) (&(r)->regexp.allof) 1090117395Skan#define REGEXP_ONEOF(r) (&(r)->regexp.oneof) 1091117395Skan 1092117395Skan#endif /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */ 1093117395Skan 1094117395Skan/* Create IR structure (node). */ 1095117395Skanstatic void * 1096132718Skancreate_node (size_t size) 1097117395Skan{ 1098117395Skan void *result; 1099117395Skan 1100117395Skan obstack_blank (&irp, size); 1101117395Skan result = obstack_base (&irp); 1102222097Sbenl (void) obstack_finish (&irp); 1103117395Skan /* Default values of members are NULL and zero. */ 1104117395Skan memset (result, 0, size); 1105117395Skan return result; 1106117395Skan} 1107117395Skan 1108117395Skan/* Copy IR structure (node). */ 1109117395Skanstatic void * 1110132718Skancopy_node (const void *from, size_t size) 1111117395Skan{ 1112117395Skan void *const result = create_node (size); 1113117395Skan memcpy (result, from, size); 1114117395Skan return result; 1115117395Skan} 1116117395Skan 1117117395Skan/* The function checks that NAME does not contain quotes (`"'). */ 1118169689Skanstatic const char * 1119169689Skancheck_name (const char * name, pos_t pos ATTRIBUTE_UNUSED) 1120117395Skan{ 1121117395Skan const char *str; 1122117395Skan 1123117395Skan for (str = name; *str != '\0'; str++) 1124117395Skan if (*str == '\"') 1125117395Skan error ("Name `%s' contains quotes", name); 1126117395Skan return name; 1127117395Skan} 1128117395Skan 1129132718Skan/* Pointers to all declarations during IR generation are stored in the 1130117395Skan following. */ 1131169689Skanstatic VEC(decl_t,heap) *decls; 1132117395Skan 1133117395Skan/* Given a pointer to a (char *) and a separator, return an alloc'ed 1134117395Skan string containing the next separated element, taking parentheses 1135117395Skan into account if PAR_FLAG has nonzero value. Advance the pointer to 1136117395Skan after the string scanned, or the end-of-string. Return NULL if at 1137117395Skan end of string. */ 1138117395Skanstatic char * 1139169689Skannext_sep_el (const char **pstr, int sep, int par_flag) 1140117395Skan{ 1141117395Skan char *out_str; 1142169689Skan const char *p; 1143117395Skan int pars_num; 1144117395Skan int n_spaces; 1145117395Skan 1146117395Skan /* Remove leading whitespaces. */ 1147117395Skan while (ISSPACE ((int) **pstr)) 1148117395Skan (*pstr)++; 1149117395Skan 1150117395Skan if (**pstr == '\0') 1151117395Skan return NULL; 1152117395Skan 1153117395Skan n_spaces = 0; 1154117395Skan for (pars_num = 0, p = *pstr; *p != '\0'; p++) 1155117395Skan { 1156117395Skan if (par_flag && *p == '(') 1157117395Skan pars_num++; 1158117395Skan else if (par_flag && *p == ')') 1159117395Skan pars_num--; 1160117395Skan else if (pars_num == 0 && *p == sep) 1161117395Skan break; 1162117395Skan if (pars_num == 0 && ISSPACE ((int) *p)) 1163117395Skan n_spaces++; 1164117395Skan else 1165117395Skan { 1166117395Skan for (; n_spaces != 0; n_spaces--) 1167117395Skan obstack_1grow (&irp, p [-n_spaces]); 1168117395Skan obstack_1grow (&irp, *p); 1169117395Skan } 1170117395Skan } 1171117395Skan obstack_1grow (&irp, '\0'); 1172117395Skan out_str = obstack_base (&irp); 1173222097Sbenl (void) obstack_finish (&irp); 1174117395Skan 1175117395Skan *pstr = p; 1176117395Skan if (**pstr == sep) 1177117395Skan (*pstr)++; 1178117395Skan 1179117395Skan return out_str; 1180117395Skan} 1181117395Skan 1182117395Skan/* Given a string and a separator, return the number of separated 1183117395Skan elements in it, taking parentheses into account if PAR_FLAG has 1184132718Skan nonzero value. Return 0 for the null string, -1 if parentheses is 1185117395Skan not balanced. */ 1186117395Skanstatic int 1187169689Skann_sep_els (const char *s, int sep, int par_flag) 1188117395Skan{ 1189117395Skan int n; 1190117395Skan int pars_num; 1191117395Skan 1192117395Skan if (*s == '\0') 1193117395Skan return 0; 1194117395Skan 1195117395Skan for (pars_num = 0, n = 1; *s; s++) 1196117395Skan if (par_flag && *s == '(') 1197117395Skan pars_num++; 1198117395Skan else if (par_flag && *s == ')') 1199117395Skan pars_num--; 1200117395Skan else if (pars_num == 0 && *s == sep) 1201117395Skan n++; 1202117395Skan 1203117395Skan return (pars_num != 0 ? -1 : n); 1204117395Skan} 1205117395Skan 1206117395Skan/* Given a string and a separator, return vector of strings which are 1207117395Skan elements in the string and number of elements through els_num. 1208132718Skan Take parentheses into account if PAREN_P has nonzero value. The 1209132718Skan function also inserts the end marker NULL at the end of vector. 1210132718Skan Return 0 for the null string, -1 if parentheses are not balanced. */ 1211117395Skanstatic char ** 1212169689Skanget_str_vect (const char *str, int *els_num, int sep, int paren_p) 1213117395Skan{ 1214117395Skan int i; 1215117395Skan char **vect; 1216169689Skan const char **pstr; 1217169689Skan char *trail; 1218117395Skan 1219132718Skan *els_num = n_sep_els (str, sep, paren_p); 1220117395Skan if (*els_num <= 0) 1221117395Skan return NULL; 1222132718Skan obstack_blank (&irp, sizeof (char *) * (*els_num + 1)); 1223117395Skan vect = (char **) obstack_base (&irp); 1224222097Sbenl (void) obstack_finish (&irp); 1225117395Skan pstr = &str; 1226117395Skan for (i = 0; i < *els_num; i++) 1227132718Skan vect [i] = next_sep_el (pstr, sep, paren_p); 1228169689Skan trail = next_sep_el (pstr, sep, paren_p); 1229169689Skan gcc_assert (!trail); 1230132718Skan vect [i] = NULL; 1231117395Skan return vect; 1232117395Skan} 1233117395Skan 1234132718Skan/* Process a DEFINE_CPU_UNIT. 1235117395Skan 1236117395Skan This gives information about a unit contained in CPU. We fill a 1237117395Skan struct unit_decl with information used later by `expand_automata'. */ 1238169689Skanstatic void 1239132718Skangen_cpu_unit (rtx def) 1240117395Skan{ 1241117395Skan decl_t decl; 1242117395Skan char **str_cpu_units; 1243117395Skan int vect_length; 1244117395Skan int i; 1245117395Skan 1246169689Skan str_cpu_units = get_str_vect (XSTR (def, 0), &vect_length, ',', FALSE); 1247117395Skan if (str_cpu_units == NULL) 1248117395Skan fatal ("invalid string `%s' in define_cpu_unit", XSTR (def, 0)); 1249117395Skan for (i = 0; i < vect_length; i++) 1250117395Skan { 1251117395Skan decl = create_node (sizeof (struct decl)); 1252117395Skan decl->mode = dm_unit; 1253117395Skan decl->pos = 0; 1254117395Skan DECL_UNIT (decl)->name = check_name (str_cpu_units [i], decl->pos); 1255169689Skan DECL_UNIT (decl)->automaton_name = XSTR (def, 1); 1256117395Skan DECL_UNIT (decl)->query_p = 0; 1257132718Skan DECL_UNIT (decl)->min_occ_cycle_num = -1; 1258132718Skan DECL_UNIT (decl)->in_set_p = 0; 1259169689Skan VEC_safe_push (decl_t,heap, decls, decl); 1260117395Skan } 1261117395Skan} 1262117395Skan 1263132718Skan/* Process a DEFINE_QUERY_CPU_UNIT. 1264117395Skan 1265117395Skan This gives information about a unit contained in CPU. We fill a 1266117395Skan struct unit_decl with information used later by `expand_automata'. */ 1267169689Skanstatic void 1268132718Skangen_query_cpu_unit (rtx def) 1269117395Skan{ 1270117395Skan decl_t decl; 1271117395Skan char **str_cpu_units; 1272117395Skan int vect_length; 1273117395Skan int i; 1274117395Skan 1275169689Skan str_cpu_units = get_str_vect (XSTR (def, 0), &vect_length, ',', 1276132718Skan FALSE); 1277117395Skan if (str_cpu_units == NULL) 1278117395Skan fatal ("invalid string `%s' in define_query_cpu_unit", XSTR (def, 0)); 1279117395Skan for (i = 0; i < vect_length; i++) 1280117395Skan { 1281117395Skan decl = create_node (sizeof (struct decl)); 1282117395Skan decl->mode = dm_unit; 1283117395Skan decl->pos = 0; 1284117395Skan DECL_UNIT (decl)->name = check_name (str_cpu_units [i], decl->pos); 1285169689Skan DECL_UNIT (decl)->automaton_name = XSTR (def, 1); 1286117395Skan DECL_UNIT (decl)->query_p = 1; 1287169689Skan VEC_safe_push (decl_t,heap, decls, decl); 1288117395Skan } 1289117395Skan} 1290117395Skan 1291132718Skan/* Process a DEFINE_BYPASS. 1292117395Skan 1293117395Skan This gives information about a unit contained in the CPU. We fill 1294117395Skan in a struct bypass_decl with information used later by 1295117395Skan `expand_automata'. */ 1296169689Skanstatic void 1297132718Skangen_bypass (rtx def) 1298117395Skan{ 1299117395Skan decl_t decl; 1300117395Skan char **out_insns; 1301117395Skan int out_length; 1302117395Skan char **in_insns; 1303117395Skan int in_length; 1304117395Skan int i, j; 1305117395Skan 1306169689Skan out_insns = get_str_vect (XSTR (def, 1), &out_length, ',', FALSE); 1307117395Skan if (out_insns == NULL) 1308117395Skan fatal ("invalid string `%s' in define_bypass", XSTR (def, 1)); 1309169689Skan in_insns = get_str_vect (XSTR (def, 2), &in_length, ',', FALSE); 1310117395Skan if (in_insns == NULL) 1311117395Skan fatal ("invalid string `%s' in define_bypass", XSTR (def, 2)); 1312117395Skan for (i = 0; i < out_length; i++) 1313117395Skan for (j = 0; j < in_length; j++) 1314117395Skan { 1315117395Skan decl = create_node (sizeof (struct decl)); 1316117395Skan decl->mode = dm_bypass; 1317117395Skan decl->pos = 0; 1318117395Skan DECL_BYPASS (decl)->latency = XINT (def, 0); 1319117395Skan DECL_BYPASS (decl)->out_insn_name = out_insns [i]; 1320117395Skan DECL_BYPASS (decl)->in_insn_name = in_insns [j]; 1321169689Skan DECL_BYPASS (decl)->bypass_guard_name = XSTR (def, 3); 1322169689Skan VEC_safe_push (decl_t,heap, decls, decl); 1323117395Skan } 1324117395Skan} 1325117395Skan 1326132718Skan/* Process an EXCLUSION_SET. 1327117395Skan 1328117395Skan This gives information about a cpu unit conflicts. We fill a 1329132718Skan struct excl_rel_decl (excl) with information used later by 1330117395Skan `expand_automata'. */ 1331169689Skanstatic void 1332132718Skangen_excl_set (rtx def) 1333117395Skan{ 1334117395Skan decl_t decl; 1335117395Skan char **first_str_cpu_units; 1336117395Skan char **second_str_cpu_units; 1337117395Skan int first_vect_length; 1338117395Skan int length; 1339117395Skan int i; 1340117395Skan 1341117395Skan first_str_cpu_units 1342169689Skan = get_str_vect (XSTR (def, 0), &first_vect_length, ',', FALSE); 1343117395Skan if (first_str_cpu_units == NULL) 1344117395Skan fatal ("invalid first string `%s' in exclusion_set", XSTR (def, 0)); 1345169689Skan second_str_cpu_units = get_str_vect (XSTR (def, 1), &length, ',', 1346132718Skan FALSE); 1347117395Skan if (second_str_cpu_units == NULL) 1348117395Skan fatal ("invalid second string `%s' in exclusion_set", XSTR (def, 1)); 1349117395Skan length += first_vect_length; 1350117395Skan decl = create_node (sizeof (struct decl) + (length - 1) * sizeof (char *)); 1351117395Skan decl->mode = dm_excl; 1352117395Skan decl->pos = 0; 1353132718Skan DECL_EXCL (decl)->all_names_num = length; 1354117395Skan DECL_EXCL (decl)->first_list_length = first_vect_length; 1355117395Skan for (i = 0; i < length; i++) 1356117395Skan if (i < first_vect_length) 1357117395Skan DECL_EXCL (decl)->names [i] = first_str_cpu_units [i]; 1358117395Skan else 1359117395Skan DECL_EXCL (decl)->names [i] 1360117395Skan = second_str_cpu_units [i - first_vect_length]; 1361169689Skan VEC_safe_push (decl_t,heap, decls, decl); 1362117395Skan} 1363117395Skan 1364132718Skan/* Process a PRESENCE_SET, a FINAL_PRESENCE_SET, an ABSENCE_SET, 1365132718Skan FINAL_ABSENCE_SET (it is depended on PRESENCE_P and FINAL_P). 1366117395Skan 1367117395Skan This gives information about a cpu unit reservation requirements. 1368132718Skan We fill a struct unit_pattern_rel_decl with information used later 1369132718Skan by `expand_automata'. */ 1370132718Skanstatic void 1371132718Skangen_presence_absence_set (rtx def, int presence_p, int final_p) 1372117395Skan{ 1373117395Skan decl_t decl; 1374132718Skan char **str_cpu_units; 1375169689Skan char **str_pattern_lists; 1376132718Skan char ***str_patterns; 1377132718Skan int cpu_units_length; 1378117395Skan int length; 1379132718Skan int patterns_length; 1380117395Skan int i; 1381117395Skan 1382169689Skan str_cpu_units = get_str_vect (XSTR (def, 0), &cpu_units_length, ',', 1383132718Skan FALSE); 1384132718Skan if (str_cpu_units == NULL) 1385132718Skan fatal ((presence_p 1386132718Skan ? (final_p 1387132718Skan ? "invalid first string `%s' in final_presence_set" 1388132718Skan : "invalid first string `%s' in presence_set") 1389132718Skan : (final_p 1390132718Skan ? "invalid first string `%s' in final_absence_set" 1391132718Skan : "invalid first string `%s' in absence_set")), 1392132718Skan XSTR (def, 0)); 1393169689Skan str_pattern_lists = get_str_vect (XSTR (def, 1), 1394169689Skan &patterns_length, ',', FALSE); 1395169689Skan if (str_pattern_lists == NULL) 1396132718Skan fatal ((presence_p 1397132718Skan ? (final_p 1398132718Skan ? "invalid second string `%s' in final_presence_set" 1399132718Skan : "invalid second string `%s' in presence_set") 1400132718Skan : (final_p 1401132718Skan ? "invalid second string `%s' in final_absence_set" 1402132718Skan : "invalid second string `%s' in absence_set")), XSTR (def, 1)); 1403169689Skan str_patterns = obstack_alloc (&irp, patterns_length * sizeof (char **)); 1404132718Skan for (i = 0; i < patterns_length; i++) 1405132718Skan { 1406169689Skan str_patterns [i] = get_str_vect (str_pattern_lists [i], 1407169689Skan &length, ' ', FALSE); 1408169689Skan gcc_assert (str_patterns [i]); 1409132718Skan } 1410132718Skan decl = create_node (sizeof (struct decl)); 1411117395Skan decl->pos = 0; 1412132718Skan if (presence_p) 1413132718Skan { 1414132718Skan decl->mode = dm_presence; 1415132718Skan DECL_PRESENCE (decl)->names_num = cpu_units_length; 1416132718Skan DECL_PRESENCE (decl)->names = str_cpu_units; 1417132718Skan DECL_PRESENCE (decl)->patterns = str_patterns; 1418132718Skan DECL_PRESENCE (decl)->patterns_num = patterns_length; 1419132718Skan DECL_PRESENCE (decl)->final_p = final_p; 1420132718Skan } 1421132718Skan else 1422132718Skan { 1423132718Skan decl->mode = dm_absence; 1424132718Skan DECL_ABSENCE (decl)->names_num = cpu_units_length; 1425132718Skan DECL_ABSENCE (decl)->names = str_cpu_units; 1426132718Skan DECL_ABSENCE (decl)->patterns = str_patterns; 1427132718Skan DECL_ABSENCE (decl)->patterns_num = patterns_length; 1428132718Skan DECL_ABSENCE (decl)->final_p = final_p; 1429132718Skan } 1430169689Skan VEC_safe_push (decl_t,heap, decls, decl); 1431117395Skan} 1432117395Skan 1433132718Skan/* Process a PRESENCE_SET. 1434117395Skan 1435132718Skan This gives information about a cpu unit reservation requirements. 1436132718Skan We fill a struct unit_pattern_rel_decl (presence) with information 1437132718Skan used later by `expand_automata'. */ 1438169689Skanstatic void 1439132718Skangen_presence_set (rtx def) 1440132718Skan{ 1441132718Skan gen_presence_absence_set (def, TRUE, FALSE); 1442132718Skan} 1443132718Skan 1444132718Skan/* Process a FINAL_PRESENCE_SET. 1445132718Skan 1446117395Skan This gives information about a cpu unit reservation requirements. 1447132718Skan We fill a struct unit_pattern_rel_decl (presence) with information 1448132718Skan used later by `expand_automata'. */ 1449169689Skanstatic void 1450132718Skangen_final_presence_set (rtx def) 1451117395Skan{ 1452132718Skan gen_presence_absence_set (def, TRUE, TRUE); 1453132718Skan} 1454117395Skan 1455132718Skan/* Process an ABSENCE_SET. 1456132718Skan 1457132718Skan This gives information about a cpu unit reservation requirements. 1458132718Skan We fill a struct unit_pattern_rel_decl (absence) with information 1459132718Skan used later by `expand_automata'. */ 1460169689Skanstatic void 1461132718Skangen_absence_set (rtx def) 1462132718Skan{ 1463132718Skan gen_presence_absence_set (def, FALSE, FALSE); 1464117395Skan} 1465117395Skan 1466132718Skan/* Process a FINAL_ABSENCE_SET. 1467117395Skan 1468132718Skan This gives information about a cpu unit reservation requirements. 1469132718Skan We fill a struct unit_pattern_rel_decl (absence) with information 1470132718Skan used later by `expand_automata'. */ 1471169689Skanstatic void 1472132718Skangen_final_absence_set (rtx def) 1473132718Skan{ 1474132718Skan gen_presence_absence_set (def, FALSE, TRUE); 1475132718Skan} 1476132718Skan 1477132718Skan/* Process a DEFINE_AUTOMATON. 1478132718Skan 1479117395Skan This gives information about a finite state automaton used for 1480117395Skan recognizing pipeline hazards. We fill a struct automaton_decl 1481117395Skan with information used later by `expand_automata'. */ 1482169689Skanstatic void 1483132718Skangen_automaton (rtx def) 1484117395Skan{ 1485117395Skan decl_t decl; 1486117395Skan char **str_automata; 1487117395Skan int vect_length; 1488117395Skan int i; 1489117395Skan 1490169689Skan str_automata = get_str_vect (XSTR (def, 0), &vect_length, ',', FALSE); 1491117395Skan if (str_automata == NULL) 1492117395Skan fatal ("invalid string `%s' in define_automaton", XSTR (def, 0)); 1493117395Skan for (i = 0; i < vect_length; i++) 1494117395Skan { 1495117395Skan decl = create_node (sizeof (struct decl)); 1496117395Skan decl->mode = dm_automaton; 1497117395Skan decl->pos = 0; 1498117395Skan DECL_AUTOMATON (decl)->name = check_name (str_automata [i], decl->pos); 1499169689Skan VEC_safe_push (decl_t,heap, decls, decl); 1500117395Skan } 1501117395Skan} 1502117395Skan 1503132718Skan/* Process an AUTOMATA_OPTION. 1504117395Skan 1505117395Skan This gives information how to generate finite state automaton used 1506117395Skan for recognizing pipeline hazards. */ 1507169689Skanstatic void 1508132718Skangen_automata_option (rtx def) 1509117395Skan{ 1510132718Skan if (strcmp (XSTR (def, 0), NO_MINIMIZATION_OPTION + 1) == 0) 1511117395Skan no_minimization_flag = 1; 1512132718Skan else if (strcmp (XSTR (def, 0), TIME_OPTION + 1) == 0) 1513117395Skan time_flag = 1; 1514132718Skan else if (strcmp (XSTR (def, 0), V_OPTION + 1) == 0) 1515117395Skan v_flag = 1; 1516132718Skan else if (strcmp (XSTR (def, 0), W_OPTION + 1) == 0) 1517117395Skan w_flag = 1; 1518132718Skan else if (strcmp (XSTR (def, 0), NDFA_OPTION + 1) == 0) 1519117395Skan ndfa_flag = 1; 1520132718Skan else if (strcmp (XSTR (def, 0), PROGRESS_OPTION + 1) == 0) 1521132718Skan progress_flag = 1; 1522117395Skan else 1523117395Skan fatal ("invalid option `%s' in automata_option", XSTR (def, 0)); 1524117395Skan} 1525117395Skan 1526117395Skan/* Name in reservation to denote absence reservation. */ 1527117395Skan#define NOTHING_NAME "nothing" 1528117395Skan 1529117395Skan/* The following string contains original reservation string being 1530117395Skan parsed. */ 1531169689Skanstatic const char *reserv_str; 1532117395Skan 1533117395Skan/* Parse an element in STR. */ 1534117395Skanstatic regexp_t 1535169689Skangen_regexp_el (const char *str) 1536117395Skan{ 1537117395Skan regexp_t regexp; 1538169689Skan char *dstr; 1539117395Skan int len; 1540117395Skan 1541117395Skan if (*str == '(') 1542117395Skan { 1543117395Skan len = strlen (str); 1544117395Skan if (str [len - 1] != ')') 1545117395Skan fatal ("garbage after ) in reservation `%s'", reserv_str); 1546169689Skan dstr = alloca (len - 1); 1547169689Skan memcpy (dstr, str + 1, len - 2); 1548169689Skan dstr [len-2] = '\0'; 1549169689Skan regexp = gen_regexp_sequence (dstr); 1550117395Skan } 1551117395Skan else if (strcmp (str, NOTHING_NAME) == 0) 1552117395Skan { 1553117395Skan regexp = create_node (sizeof (struct decl)); 1554117395Skan regexp->mode = rm_nothing; 1555117395Skan } 1556117395Skan else 1557117395Skan { 1558117395Skan regexp = create_node (sizeof (struct decl)); 1559117395Skan regexp->mode = rm_unit; 1560117395Skan REGEXP_UNIT (regexp)->name = str; 1561117395Skan } 1562117395Skan return regexp; 1563117395Skan} 1564117395Skan 1565117395Skan/* Parse construction `repeat' in STR. */ 1566117395Skanstatic regexp_t 1567169689Skangen_regexp_repeat (const char *str) 1568117395Skan{ 1569117395Skan regexp_t regexp; 1570117395Skan regexp_t repeat; 1571117395Skan char **repeat_vect; 1572117395Skan int els_num; 1573117395Skan int i; 1574117395Skan 1575132718Skan repeat_vect = get_str_vect (str, &els_num, '*', TRUE); 1576117395Skan if (repeat_vect == NULL) 1577117395Skan fatal ("invalid `%s' in reservation `%s'", str, reserv_str); 1578117395Skan if (els_num > 1) 1579117395Skan { 1580117395Skan regexp = gen_regexp_el (repeat_vect [0]); 1581117395Skan for (i = 1; i < els_num; i++) 1582117395Skan { 1583117395Skan repeat = create_node (sizeof (struct regexp)); 1584117395Skan repeat->mode = rm_repeat; 1585117395Skan REGEXP_REPEAT (repeat)->regexp = regexp; 1586117395Skan REGEXP_REPEAT (repeat)->repeat_num = atoi (repeat_vect [i]); 1587117395Skan if (REGEXP_REPEAT (repeat)->repeat_num <= 1) 1588117395Skan fatal ("repetition `%s' <= 1 in reservation `%s'", 1589117395Skan str, reserv_str); 1590117395Skan regexp = repeat; 1591117395Skan } 1592117395Skan return regexp; 1593117395Skan } 1594117395Skan else 1595117395Skan return gen_regexp_el (str); 1596117395Skan} 1597117395Skan 1598117395Skan/* Parse reservation STR which possibly contains separator '+'. */ 1599117395Skanstatic regexp_t 1600169689Skangen_regexp_allof (const char *str) 1601117395Skan{ 1602117395Skan regexp_t allof; 1603117395Skan char **allof_vect; 1604117395Skan int els_num; 1605117395Skan int i; 1606117395Skan 1607132718Skan allof_vect = get_str_vect (str, &els_num, '+', TRUE); 1608117395Skan if (allof_vect == NULL) 1609117395Skan fatal ("invalid `%s' in reservation `%s'", str, reserv_str); 1610117395Skan if (els_num > 1) 1611117395Skan { 1612117395Skan allof = create_node (sizeof (struct regexp) 1613117395Skan + sizeof (regexp_t) * (els_num - 1)); 1614117395Skan allof->mode = rm_allof; 1615117395Skan REGEXP_ALLOF (allof)->regexps_num = els_num; 1616117395Skan for (i = 0; i < els_num; i++) 1617117395Skan REGEXP_ALLOF (allof)->regexps [i] = gen_regexp_repeat (allof_vect [i]); 1618117395Skan return allof; 1619117395Skan } 1620117395Skan else 1621117395Skan return gen_regexp_repeat (str); 1622117395Skan} 1623117395Skan 1624117395Skan/* Parse reservation STR which possibly contains separator '|'. */ 1625117395Skanstatic regexp_t 1626169689Skangen_regexp_oneof (const char *str) 1627117395Skan{ 1628117395Skan regexp_t oneof; 1629117395Skan char **oneof_vect; 1630117395Skan int els_num; 1631117395Skan int i; 1632117395Skan 1633132718Skan oneof_vect = get_str_vect (str, &els_num, '|', TRUE); 1634117395Skan if (oneof_vect == NULL) 1635117395Skan fatal ("invalid `%s' in reservation `%s'", str, reserv_str); 1636117395Skan if (els_num > 1) 1637117395Skan { 1638117395Skan oneof = create_node (sizeof (struct regexp) 1639117395Skan + sizeof (regexp_t) * (els_num - 1)); 1640117395Skan oneof->mode = rm_oneof; 1641117395Skan REGEXP_ONEOF (oneof)->regexps_num = els_num; 1642117395Skan for (i = 0; i < els_num; i++) 1643117395Skan REGEXP_ONEOF (oneof)->regexps [i] = gen_regexp_allof (oneof_vect [i]); 1644117395Skan return oneof; 1645117395Skan } 1646117395Skan else 1647117395Skan return gen_regexp_allof (str); 1648117395Skan} 1649117395Skan 1650117395Skan/* Parse reservation STR which possibly contains separator ','. */ 1651117395Skanstatic regexp_t 1652169689Skangen_regexp_sequence (const char *str) 1653117395Skan{ 1654117395Skan regexp_t sequence; 1655117395Skan char **sequence_vect; 1656117395Skan int els_num; 1657117395Skan int i; 1658117395Skan 1659132718Skan sequence_vect = get_str_vect (str, &els_num, ',', TRUE); 1660117395Skan if (els_num > 1) 1661117395Skan { 1662117395Skan sequence = create_node (sizeof (struct regexp) 1663117395Skan + sizeof (regexp_t) * (els_num - 1)); 1664117395Skan sequence->mode = rm_sequence; 1665117395Skan REGEXP_SEQUENCE (sequence)->regexps_num = els_num; 1666117395Skan for (i = 0; i < els_num; i++) 1667117395Skan REGEXP_SEQUENCE (sequence)->regexps [i] 1668117395Skan = gen_regexp_oneof (sequence_vect [i]); 1669117395Skan return sequence; 1670117395Skan } 1671117395Skan else 1672117395Skan return gen_regexp_oneof (str); 1673117395Skan} 1674117395Skan 1675117395Skan/* Parse construction reservation STR. */ 1676117395Skanstatic regexp_t 1677169689Skangen_regexp (const char *str) 1678117395Skan{ 1679117395Skan reserv_str = str; 1680117395Skan return gen_regexp_sequence (str);; 1681117395Skan} 1682117395Skan 1683117395Skan/* Process a DEFINE_RESERVATION. 1684117395Skan 1685117395Skan This gives information about a reservation of cpu units. We fill 1686117395Skan in a struct reserv_decl with information used later by 1687117395Skan `expand_automata'. */ 1688169689Skanstatic void 1689132718Skangen_reserv (rtx def) 1690117395Skan{ 1691117395Skan decl_t decl; 1692117395Skan 1693117395Skan decl = create_node (sizeof (struct decl)); 1694117395Skan decl->mode = dm_reserv; 1695117395Skan decl->pos = 0; 1696169689Skan DECL_RESERV (decl)->name = check_name (XSTR (def, 0), decl->pos); 1697169689Skan DECL_RESERV (decl)->regexp = gen_regexp (XSTR (def, 1)); 1698169689Skan VEC_safe_push (decl_t,heap, decls, decl); 1699117395Skan} 1700117395Skan 1701117395Skan/* Process a DEFINE_INSN_RESERVATION. 1702117395Skan 1703117395Skan This gives information about the reservation of cpu units by an 1704117395Skan insn. We fill a struct insn_reserv_decl with information used 1705117395Skan later by `expand_automata'. */ 1706169689Skanstatic void 1707132718Skangen_insn_reserv (rtx def) 1708117395Skan{ 1709117395Skan decl_t decl; 1710117395Skan 1711117395Skan decl = create_node (sizeof (struct decl)); 1712117395Skan decl->mode = dm_insn_reserv; 1713117395Skan decl->pos = 0; 1714117395Skan DECL_INSN_RESERV (decl)->name 1715169689Skan = check_name (XSTR (def, 0), decl->pos); 1716117395Skan DECL_INSN_RESERV (decl)->default_latency = XINT (def, 1); 1717117395Skan DECL_INSN_RESERV (decl)->condexp = XEXP (def, 2); 1718169689Skan DECL_INSN_RESERV (decl)->regexp = gen_regexp (XSTR (def, 3)); 1719169689Skan VEC_safe_push (decl_t,heap, decls, decl); 1720117395Skan} 1721117395Skan 1722117395Skan 1723117395Skan 1724117395Skan/* The function evaluates hash value (0..UINT_MAX) of string. */ 1725117395Skanstatic unsigned 1726132718Skanstring_hash (const char *string) 1727117395Skan{ 1728117395Skan unsigned result, i; 1729117395Skan 1730117395Skan for (result = i = 0;*string++ != '\0'; i++) 1731117395Skan result += ((unsigned char) *string << (i % CHAR_BIT)); 1732117395Skan return result; 1733117395Skan} 1734117395Skan 1735117395Skan 1736117395Skan 1737117395Skan/* This page contains abstract data `table of automaton declarations'. 1738117395Skan Elements of the table is nodes representing automaton declarations. 1739132718Skan Key of the table elements is name of given automaton. Remember 1740117395Skan that automaton names have own space. */ 1741117395Skan 1742117395Skan/* The function evaluates hash value of an automaton declaration. The 1743117395Skan function is used by abstract data `hashtab'. The function returns 1744117395Skan hash value (0..UINT_MAX) of given automaton declaration. */ 1745117395Skanstatic hashval_t 1746132718Skanautomaton_decl_hash (const void *automaton_decl) 1747117395Skan{ 1748117395Skan const decl_t decl = (decl_t) automaton_decl; 1749117395Skan 1750169689Skan gcc_assert (decl->mode != dm_automaton 1751169689Skan || DECL_AUTOMATON (decl)->name); 1752117395Skan return string_hash (DECL_AUTOMATON (decl)->name); 1753117395Skan} 1754117395Skan 1755117395Skan/* The function tests automaton declarations on equality of their 1756117395Skan keys. The function is used by abstract data `hashtab'. The 1757117395Skan function returns 1 if the declarations have the same key, 0 1758117395Skan otherwise. */ 1759117395Skanstatic int 1760132718Skanautomaton_decl_eq_p (const void* automaton_decl_1, 1761132718Skan const void* automaton_decl_2) 1762117395Skan{ 1763117395Skan const decl_t decl1 = (decl_t) automaton_decl_1; 1764117395Skan const decl_t decl2 = (decl_t) automaton_decl_2; 1765117395Skan 1766169689Skan gcc_assert (decl1->mode == dm_automaton 1767169689Skan && DECL_AUTOMATON (decl1)->name 1768169689Skan && decl2->mode == dm_automaton 1769169689Skan && DECL_AUTOMATON (decl2)->name); 1770117395Skan return strcmp (DECL_AUTOMATON (decl1)->name, 1771117395Skan DECL_AUTOMATON (decl2)->name) == 0; 1772117395Skan} 1773117395Skan 1774117395Skan/* The automaton declaration table itself is represented by the 1775117395Skan following variable. */ 1776117395Skanstatic htab_t automaton_decl_table; 1777117395Skan 1778117395Skan/* The function inserts automaton declaration into the table. The 1779117395Skan function does nothing if an automaton declaration with the same key 1780117395Skan exists already in the table. The function returns automaton 1781117395Skan declaration node in the table with the same key as given automaton 1782117395Skan declaration node. */ 1783117395Skanstatic decl_t 1784132718Skaninsert_automaton_decl (decl_t automaton_decl) 1785117395Skan{ 1786117395Skan void **entry_ptr; 1787117395Skan 1788117395Skan entry_ptr = htab_find_slot (automaton_decl_table, automaton_decl, 1); 1789117395Skan if (*entry_ptr == NULL) 1790117395Skan *entry_ptr = (void *) automaton_decl; 1791117395Skan return (decl_t) *entry_ptr; 1792117395Skan} 1793117395Skan 1794117395Skan/* The following variable value is node representing automaton 1795117395Skan declaration. The node used for searching automaton declaration 1796117395Skan with given name. */ 1797117395Skanstatic struct decl work_automaton_decl; 1798117395Skan 1799117395Skan/* The function searches for automaton declaration in the table with 1800117395Skan the same key as node representing name of the automaton 1801117395Skan declaration. The function returns node found in the table, NULL if 1802117395Skan such node does not exist in the table. */ 1803117395Skanstatic decl_t 1804169689Skanfind_automaton_decl (const char *name) 1805117395Skan{ 1806117395Skan void *entry; 1807117395Skan 1808117395Skan work_automaton_decl.mode = dm_automaton; 1809117395Skan DECL_AUTOMATON (&work_automaton_decl)->name = name; 1810117395Skan entry = htab_find (automaton_decl_table, &work_automaton_decl); 1811117395Skan return (decl_t) entry; 1812117395Skan} 1813117395Skan 1814117395Skan/* The function creates empty automaton declaration table and node 1815117395Skan representing automaton declaration and used for searching automaton 1816117395Skan declaration with given name. The function must be called only once 1817117395Skan before any work with the automaton declaration table. */ 1818117395Skanstatic void 1819132718Skaninitiate_automaton_decl_table (void) 1820117395Skan{ 1821117395Skan work_automaton_decl.mode = dm_automaton; 1822117395Skan automaton_decl_table = htab_create (10, automaton_decl_hash, 1823117395Skan automaton_decl_eq_p, (htab_del) 0); 1824117395Skan} 1825117395Skan 1826117395Skan/* The function deletes the automaton declaration table. Only call of 1827117395Skan function `initiate_automaton_decl_table' is possible immediately 1828117395Skan after this function call. */ 1829117395Skanstatic void 1830132718Skanfinish_automaton_decl_table (void) 1831117395Skan{ 1832117395Skan htab_delete (automaton_decl_table); 1833117395Skan} 1834117395Skan 1835117395Skan 1836117395Skan 1837117395Skan/* This page contains abstract data `table of insn declarations'. 1838117395Skan Elements of the table is nodes representing insn declarations. Key 1839117395Skan of the table elements is name of given insn (in corresponding 1840132718Skan define_insn_reservation). Remember that insn names have own 1841117395Skan space. */ 1842117395Skan 1843117395Skan/* The function evaluates hash value of an insn declaration. The 1844117395Skan function is used by abstract data `hashtab'. The function returns 1845117395Skan hash value (0..UINT_MAX) of given insn declaration. */ 1846117395Skanstatic hashval_t 1847132718Skaninsn_decl_hash (const void *insn_decl) 1848117395Skan{ 1849117395Skan const decl_t decl = (decl_t) insn_decl; 1850117395Skan 1851169689Skan gcc_assert (decl->mode == dm_insn_reserv 1852169689Skan && DECL_INSN_RESERV (decl)->name); 1853117395Skan return string_hash (DECL_INSN_RESERV (decl)->name); 1854117395Skan} 1855117395Skan 1856117395Skan/* The function tests insn declarations on equality of their keys. 1857117395Skan The function is used by abstract data `hashtab'. The function 1858117395Skan returns 1 if declarations have the same key, 0 otherwise. */ 1859117395Skanstatic int 1860132718Skaninsn_decl_eq_p (const void *insn_decl_1, const void *insn_decl_2) 1861117395Skan{ 1862117395Skan const decl_t decl1 = (decl_t) insn_decl_1; 1863117395Skan const decl_t decl2 = (decl_t) insn_decl_2; 1864117395Skan 1865169689Skan gcc_assert (decl1->mode == dm_insn_reserv 1866169689Skan && DECL_INSN_RESERV (decl1)->name 1867169689Skan && decl2->mode == dm_insn_reserv 1868169689Skan && DECL_INSN_RESERV (decl2)->name); 1869117395Skan return strcmp (DECL_INSN_RESERV (decl1)->name, 1870117395Skan DECL_INSN_RESERV (decl2)->name) == 0; 1871117395Skan} 1872117395Skan 1873117395Skan/* The insn declaration table itself is represented by the following 1874117395Skan variable. The table does not contain insn reservation 1875117395Skan declarations. */ 1876117395Skanstatic htab_t insn_decl_table; 1877117395Skan 1878117395Skan/* The function inserts insn declaration into the table. The function 1879117395Skan does nothing if an insn declaration with the same key exists 1880117395Skan already in the table. The function returns insn declaration node 1881117395Skan in the table with the same key as given insn declaration node. */ 1882117395Skanstatic decl_t 1883132718Skaninsert_insn_decl (decl_t insn_decl) 1884117395Skan{ 1885117395Skan void **entry_ptr; 1886117395Skan 1887117395Skan entry_ptr = htab_find_slot (insn_decl_table, insn_decl, 1); 1888117395Skan if (*entry_ptr == NULL) 1889117395Skan *entry_ptr = (void *) insn_decl; 1890117395Skan return (decl_t) *entry_ptr; 1891117395Skan} 1892117395Skan 1893117395Skan/* The following variable value is node representing insn reservation 1894117395Skan declaration. The node used for searching insn reservation 1895117395Skan declaration with given name. */ 1896117395Skanstatic struct decl work_insn_decl; 1897117395Skan 1898117395Skan/* The function searches for insn reservation declaration in the table 1899117395Skan with the same key as node representing name of the insn reservation 1900117395Skan declaration. The function returns node found in the table, NULL if 1901117395Skan such node does not exist in the table. */ 1902117395Skanstatic decl_t 1903169689Skanfind_insn_decl (const char *name) 1904117395Skan{ 1905117395Skan void *entry; 1906117395Skan 1907117395Skan work_insn_decl.mode = dm_insn_reserv; 1908117395Skan DECL_INSN_RESERV (&work_insn_decl)->name = name; 1909117395Skan entry = htab_find (insn_decl_table, &work_insn_decl); 1910117395Skan return (decl_t) entry; 1911117395Skan} 1912117395Skan 1913117395Skan/* The function creates empty insn declaration table and node 1914117395Skan representing insn declaration and used for searching insn 1915117395Skan declaration with given name. The function must be called only once 1916117395Skan before any work with the insn declaration table. */ 1917117395Skanstatic void 1918132718Skaninitiate_insn_decl_table (void) 1919117395Skan{ 1920117395Skan work_insn_decl.mode = dm_insn_reserv; 1921117395Skan insn_decl_table = htab_create (10, insn_decl_hash, insn_decl_eq_p, 1922117395Skan (htab_del) 0); 1923117395Skan} 1924117395Skan 1925117395Skan/* The function deletes the insn declaration table. Only call of 1926117395Skan function `initiate_insn_decl_table' is possible immediately after 1927117395Skan this function call. */ 1928117395Skanstatic void 1929132718Skanfinish_insn_decl_table (void) 1930117395Skan{ 1931117395Skan htab_delete (insn_decl_table); 1932117395Skan} 1933117395Skan 1934117395Skan 1935117395Skan 1936117395Skan/* This page contains abstract data `table of declarations'. Elements 1937117395Skan of the table is nodes representing declarations (of units and 1938117395Skan reservations). Key of the table elements is names of given 1939117395Skan declarations. */ 1940117395Skan 1941117395Skan/* The function evaluates hash value of a declaration. The function 1942117395Skan is used by abstract data `hashtab'. The function returns hash 1943117395Skan value (0..UINT_MAX) of given declaration. */ 1944117395Skanstatic hashval_t 1945132718Skandecl_hash (const void *decl) 1946117395Skan{ 1947117395Skan const decl_t d = (const decl_t) decl; 1948117395Skan 1949169689Skan gcc_assert ((d->mode == dm_unit && DECL_UNIT (d)->name) 1950169689Skan || (d->mode == dm_reserv && DECL_RESERV (d)->name)); 1951117395Skan return string_hash (d->mode == dm_unit 1952117395Skan ? DECL_UNIT (d)->name : DECL_RESERV (d)->name); 1953117395Skan} 1954117395Skan 1955117395Skan/* The function tests declarations on equality of their keys. The 1956169689Skan function is used by abstract data 'hashtab'. The function 1957117395Skan returns 1 if the declarations have the same key, 0 otherwise. */ 1958117395Skanstatic int 1959132718Skandecl_eq_p (const void *decl_1, const void *decl_2) 1960117395Skan{ 1961117395Skan const decl_t d1 = (const decl_t) decl_1; 1962117395Skan const decl_t d2 = (const decl_t) decl_2; 1963117395Skan 1964169689Skan gcc_assert ((d1->mode == dm_unit && DECL_UNIT (d1)->name) 1965169689Skan || (d1->mode == dm_reserv && DECL_RESERV (d1)->name)); 1966169689Skan gcc_assert ((d2->mode == dm_unit && DECL_UNIT (d2)->name) 1967169689Skan || (d2->mode == dm_reserv && DECL_RESERV (d2)->name)); 1968117395Skan return strcmp ((d1->mode == dm_unit 1969117395Skan ? DECL_UNIT (d1)->name : DECL_RESERV (d1)->name), 1970117395Skan (d2->mode == dm_unit 1971117395Skan ? DECL_UNIT (d2)->name : DECL_RESERV (d2)->name)) == 0; 1972117395Skan} 1973117395Skan 1974117395Skan/* The declaration table itself is represented by the following 1975117395Skan variable. */ 1976117395Skanstatic htab_t decl_table; 1977117395Skan 1978117395Skan/* The function inserts declaration into the table. The function does 1979117395Skan nothing if a declaration with the same key exists already in the 1980117395Skan table. The function returns declaration node in the table with the 1981117395Skan same key as given declaration node. */ 1982117395Skan 1983117395Skanstatic decl_t 1984132718Skaninsert_decl (decl_t decl) 1985117395Skan{ 1986117395Skan void **entry_ptr; 1987117395Skan 1988117395Skan entry_ptr = htab_find_slot (decl_table, decl, 1); 1989117395Skan if (*entry_ptr == NULL) 1990117395Skan *entry_ptr = (void *) decl; 1991117395Skan return (decl_t) *entry_ptr; 1992117395Skan} 1993117395Skan 1994117395Skan/* The following variable value is node representing declaration. The 1995117395Skan node used for searching declaration with given name. */ 1996117395Skanstatic struct decl work_decl; 1997117395Skan 1998117395Skan/* The function searches for declaration in the table with the same 1999117395Skan key as node representing name of the declaration. The function 2000117395Skan returns node found in the table, NULL if such node does not exist 2001117395Skan in the table. */ 2002117395Skanstatic decl_t 2003169689Skanfind_decl (const char *name) 2004117395Skan{ 2005117395Skan void *entry; 2006117395Skan 2007117395Skan work_decl.mode = dm_unit; 2008117395Skan DECL_UNIT (&work_decl)->name = name; 2009117395Skan entry = htab_find (decl_table, &work_decl); 2010117395Skan return (decl_t) entry; 2011117395Skan} 2012117395Skan 2013117395Skan/* The function creates empty declaration table and node representing 2014117395Skan declaration and used for searching declaration with given name. 2015117395Skan The function must be called only once before any work with the 2016117395Skan declaration table. */ 2017117395Skanstatic void 2018132718Skaninitiate_decl_table (void) 2019117395Skan{ 2020117395Skan work_decl.mode = dm_unit; 2021117395Skan decl_table = htab_create (10, decl_hash, decl_eq_p, (htab_del) 0); 2022117395Skan} 2023117395Skan 2024117395Skan/* The function deletes the declaration table. Only call of function 2025117395Skan `initiate_declaration_table' is possible immediately after this 2026117395Skan function call. */ 2027117395Skanstatic void 2028132718Skanfinish_decl_table (void) 2029117395Skan{ 2030117395Skan htab_delete (decl_table); 2031117395Skan} 2032117395Skan 2033117395Skan 2034117395Skan 2035117395Skan/* This page contains checker of pipeline hazard description. */ 2036117395Skan 2037117395Skan/* Checking NAMES in an exclusion clause vector and returning formed 2038117395Skan unit_set_el_list. */ 2039117395Skanstatic unit_set_el_t 2040132718Skanprocess_excls (char **names, int num, pos_t excl_pos ATTRIBUTE_UNUSED) 2041117395Skan{ 2042117395Skan unit_set_el_t el_list; 2043117395Skan unit_set_el_t last_el; 2044117395Skan unit_set_el_t new_el; 2045117395Skan decl_t decl_in_table; 2046117395Skan int i; 2047117395Skan 2048117395Skan el_list = NULL; 2049117395Skan last_el = NULL; 2050117395Skan for (i = 0; i < num; i++) 2051117395Skan { 2052117395Skan decl_in_table = find_decl (names [i]); 2053117395Skan if (decl_in_table == NULL) 2054117395Skan error ("unit `%s' in exclusion is not declared", names [i]); 2055117395Skan else if (decl_in_table->mode != dm_unit) 2056117395Skan error ("`%s' in exclusion is not unit", names [i]); 2057117395Skan else 2058117395Skan { 2059117395Skan new_el = create_node (sizeof (struct unit_set_el)); 2060117395Skan new_el->unit_decl = DECL_UNIT (decl_in_table); 2061117395Skan new_el->next_unit_set_el = NULL; 2062117395Skan if (last_el == NULL) 2063117395Skan el_list = last_el = new_el; 2064117395Skan else 2065117395Skan { 2066117395Skan last_el->next_unit_set_el = new_el; 2067117395Skan last_el = last_el->next_unit_set_el; 2068117395Skan } 2069117395Skan } 2070117395Skan } 2071117395Skan return el_list; 2072117395Skan} 2073117395Skan 2074117395Skan/* The function adds each element from SOURCE_LIST to the exclusion 2075117395Skan list of the each element from DEST_LIST. Checking situation "unit 2076117395Skan excludes itself". */ 2077117395Skanstatic void 2078132718Skanadd_excls (unit_set_el_t dest_list, unit_set_el_t source_list, 2079132718Skan pos_t excl_pos ATTRIBUTE_UNUSED) 2080117395Skan{ 2081117395Skan unit_set_el_t dst; 2082117395Skan unit_set_el_t src; 2083117395Skan unit_set_el_t curr_el; 2084117395Skan unit_set_el_t prev_el; 2085117395Skan unit_set_el_t copy; 2086117395Skan 2087117395Skan for (dst = dest_list; dst != NULL; dst = dst->next_unit_set_el) 2088117395Skan for (src = source_list; src != NULL; src = src->next_unit_set_el) 2089117395Skan { 2090117395Skan if (dst->unit_decl == src->unit_decl) 2091117395Skan { 2092117395Skan error ("unit `%s' excludes itself", src->unit_decl->name); 2093117395Skan continue; 2094117395Skan } 2095117395Skan if (dst->unit_decl->automaton_name != NULL 2096117395Skan && src->unit_decl->automaton_name != NULL 2097117395Skan && strcmp (dst->unit_decl->automaton_name, 2098117395Skan src->unit_decl->automaton_name) != 0) 2099117395Skan { 2100117395Skan error ("units `%s' and `%s' in exclusion set belong to different automata", 2101117395Skan src->unit_decl->name, dst->unit_decl->name); 2102117395Skan continue; 2103117395Skan } 2104117395Skan for (curr_el = dst->unit_decl->excl_list, prev_el = NULL; 2105117395Skan curr_el != NULL; 2106117395Skan prev_el = curr_el, curr_el = curr_el->next_unit_set_el) 2107117395Skan if (curr_el->unit_decl == src->unit_decl) 2108117395Skan break; 2109117395Skan if (curr_el == NULL) 2110117395Skan { 2111117395Skan /* Element not found - insert. */ 2112117395Skan copy = copy_node (src, sizeof (*src)); 2113117395Skan copy->next_unit_set_el = NULL; 2114117395Skan if (prev_el == NULL) 2115117395Skan dst->unit_decl->excl_list = copy; 2116117395Skan else 2117117395Skan prev_el->next_unit_set_el = copy; 2118117395Skan } 2119117395Skan } 2120117395Skan} 2121117395Skan 2122132718Skan/* Checking NAMES in presence/absence clause and returning the 2123132718Skan formed unit_set_el_list. The function is called only after 2124132718Skan processing all exclusion sets. */ 2125117395Skanstatic unit_set_el_t 2126132718Skanprocess_presence_absence_names (char **names, int num, 2127132718Skan pos_t req_pos ATTRIBUTE_UNUSED, 2128132718Skan int presence_p, int final_p) 2129117395Skan{ 2130117395Skan unit_set_el_t el_list; 2131117395Skan unit_set_el_t last_el; 2132117395Skan unit_set_el_t new_el; 2133117395Skan decl_t decl_in_table; 2134117395Skan int i; 2135117395Skan 2136117395Skan el_list = NULL; 2137117395Skan last_el = NULL; 2138117395Skan for (i = 0; i < num; i++) 2139117395Skan { 2140117395Skan decl_in_table = find_decl (names [i]); 2141117395Skan if (decl_in_table == NULL) 2142117395Skan error ((presence_p 2143132718Skan ? (final_p 2144132718Skan ? "unit `%s' in final presence set is not declared" 2145132718Skan : "unit `%s' in presence set is not declared") 2146132718Skan : (final_p 2147132718Skan ? "unit `%s' in final absence set is not declared" 2148132718Skan : "unit `%s' in absence set is not declared")), names [i]); 2149117395Skan else if (decl_in_table->mode != dm_unit) 2150117395Skan error ((presence_p 2151132718Skan ? (final_p 2152132718Skan ? "`%s' in final presence set is not unit" 2153132718Skan : "`%s' in presence set is not unit") 2154132718Skan : (final_p 2155132718Skan ? "`%s' in final absence set is not unit" 2156132718Skan : "`%s' in absence set is not unit")), names [i]); 2157117395Skan else 2158117395Skan { 2159117395Skan new_el = create_node (sizeof (struct unit_set_el)); 2160117395Skan new_el->unit_decl = DECL_UNIT (decl_in_table); 2161117395Skan new_el->next_unit_set_el = NULL; 2162117395Skan if (last_el == NULL) 2163117395Skan el_list = last_el = new_el; 2164117395Skan else 2165117395Skan { 2166117395Skan last_el->next_unit_set_el = new_el; 2167117395Skan last_el = last_el->next_unit_set_el; 2168117395Skan } 2169117395Skan } 2170117395Skan } 2171117395Skan return el_list; 2172117395Skan} 2173117395Skan 2174132718Skan/* Checking NAMES in patterns of a presence/absence clause and 2175132718Skan returning the formed pattern_set_el_list. The function is called 2176132718Skan only after processing all exclusion sets. */ 2177132718Skanstatic pattern_set_el_t 2178132718Skanprocess_presence_absence_patterns (char ***patterns, int num, 2179132718Skan pos_t req_pos ATTRIBUTE_UNUSED, 2180132718Skan int presence_p, int final_p) 2181132718Skan{ 2182132718Skan pattern_set_el_t el_list; 2183132718Skan pattern_set_el_t last_el; 2184132718Skan pattern_set_el_t new_el; 2185132718Skan decl_t decl_in_table; 2186132718Skan int i, j; 2187132718Skan 2188132718Skan el_list = NULL; 2189132718Skan last_el = NULL; 2190132718Skan for (i = 0; i < num; i++) 2191132718Skan { 2192132718Skan for (j = 0; patterns [i] [j] != NULL; j++) 2193132718Skan ; 2194132718Skan new_el = create_node (sizeof (struct pattern_set_el) 2195132718Skan + sizeof (struct unit_decl *) * j); 2196132718Skan new_el->unit_decls 2197132718Skan = (struct unit_decl **) ((char *) new_el 2198132718Skan + sizeof (struct pattern_set_el)); 2199132718Skan new_el->next_pattern_set_el = NULL; 2200132718Skan if (last_el == NULL) 2201132718Skan el_list = last_el = new_el; 2202132718Skan else 2203132718Skan { 2204132718Skan last_el->next_pattern_set_el = new_el; 2205132718Skan last_el = last_el->next_pattern_set_el; 2206132718Skan } 2207132718Skan new_el->units_num = 0; 2208132718Skan for (j = 0; patterns [i] [j] != NULL; j++) 2209132718Skan { 2210132718Skan decl_in_table = find_decl (patterns [i] [j]); 2211132718Skan if (decl_in_table == NULL) 2212132718Skan error ((presence_p 2213132718Skan ? (final_p 2214132718Skan ? "unit `%s' in final presence set is not declared" 2215132718Skan : "unit `%s' in presence set is not declared") 2216132718Skan : (final_p 2217132718Skan ? "unit `%s' in final absence set is not declared" 2218132718Skan : "unit `%s' in absence set is not declared")), 2219132718Skan patterns [i] [j]); 2220132718Skan else if (decl_in_table->mode != dm_unit) 2221132718Skan error ((presence_p 2222132718Skan ? (final_p 2223132718Skan ? "`%s' in final presence set is not unit" 2224132718Skan : "`%s' in presence set is not unit") 2225132718Skan : (final_p 2226132718Skan ? "`%s' in final absence set is not unit" 2227132718Skan : "`%s' in absence set is not unit")), 2228132718Skan patterns [i] [j]); 2229132718Skan else 2230132718Skan { 2231132718Skan new_el->unit_decls [new_el->units_num] 2232132718Skan = DECL_UNIT (decl_in_table); 2233132718Skan new_el->units_num++; 2234132718Skan } 2235132718Skan } 2236132718Skan } 2237132718Skan return el_list; 2238132718Skan} 2239132718Skan 2240132718Skan/* The function adds each element from PATTERN_LIST to presence (if 2241117395Skan PRESENCE_P) or absence list of the each element from DEST_LIST. 2242132718Skan Checking situations "unit requires own absence", and "unit excludes 2243132718Skan and requires presence of ...", "unit requires absence and presence 2244132718Skan of ...", "units in (final) presence set belong to different 2245132718Skan automata", and "units in (final) absence set belong to different 2246132718Skan automata". Remember that we process absence sets only after all 2247132718Skan presence sets. */ 2248117395Skanstatic void 2249132718Skanadd_presence_absence (unit_set_el_t dest_list, 2250132718Skan pattern_set_el_t pattern_list, 2251132718Skan pos_t req_pos ATTRIBUTE_UNUSED, 2252132718Skan int presence_p, int final_p) 2253117395Skan{ 2254117395Skan unit_set_el_t dst; 2255132718Skan pattern_set_el_t pat; 2256132718Skan struct unit_decl *unit; 2257132718Skan unit_set_el_t curr_excl_el; 2258132718Skan pattern_set_el_t curr_pat_el; 2259132718Skan pattern_set_el_t prev_el; 2260132718Skan pattern_set_el_t copy; 2261132718Skan int i; 2262132718Skan int no_error_flag; 2263117395Skan 2264117395Skan for (dst = dest_list; dst != NULL; dst = dst->next_unit_set_el) 2265132718Skan for (pat = pattern_list; pat != NULL; pat = pat->next_pattern_set_el) 2266117395Skan { 2267132718Skan for (i = 0; i < pat->units_num; i++) 2268117395Skan { 2269132718Skan unit = pat->unit_decls [i]; 2270132718Skan if (dst->unit_decl == unit && pat->units_num == 1 && !presence_p) 2271132718Skan { 2272132718Skan error ("unit `%s' requires own absence", unit->name); 2273132718Skan continue; 2274132718Skan } 2275132718Skan if (dst->unit_decl->automaton_name != NULL 2276132718Skan && unit->automaton_name != NULL 2277132718Skan && strcmp (dst->unit_decl->automaton_name, 2278132718Skan unit->automaton_name) != 0) 2279132718Skan { 2280132718Skan error ((presence_p 2281132718Skan ? (final_p 2282132718Skan ? "units `%s' and `%s' in final presence set belong to different automata" 2283132718Skan : "units `%s' and `%s' in presence set belong to different automata") 2284132718Skan : (final_p 2285132718Skan ? "units `%s' and `%s' in final absence set belong to different automata" 2286132718Skan : "units `%s' and `%s' in absence set belong to different automata")), 2287132718Skan unit->name, dst->unit_decl->name); 2288132718Skan continue; 2289132718Skan } 2290132718Skan no_error_flag = 1; 2291117395Skan if (presence_p) 2292132718Skan for (curr_excl_el = dst->unit_decl->excl_list; 2293132718Skan curr_excl_el != NULL; 2294132718Skan curr_excl_el = curr_excl_el->next_unit_set_el) 2295117395Skan { 2296132718Skan if (unit == curr_excl_el->unit_decl && pat->units_num == 1) 2297117395Skan { 2298117395Skan if (!w_flag) 2299117395Skan { 2300132718Skan error ("unit `%s' excludes and requires presence of `%s'", 2301132718Skan dst->unit_decl->name, unit->name); 2302117395Skan no_error_flag = 0; 2303117395Skan } 2304117395Skan else 2305117395Skan warning 2306169689Skan (0, "unit `%s' excludes and requires presence of `%s'", 2307132718Skan dst->unit_decl->name, unit->name); 2308117395Skan } 2309117395Skan } 2310132718Skan else if (pat->units_num == 1) 2311132718Skan for (curr_pat_el = dst->unit_decl->presence_list; 2312132718Skan curr_pat_el != NULL; 2313132718Skan curr_pat_el = curr_pat_el->next_pattern_set_el) 2314132718Skan if (curr_pat_el->units_num == 1 2315132718Skan && unit == curr_pat_el->unit_decls [0]) 2316132718Skan { 2317132718Skan if (!w_flag) 2318132718Skan { 2319132718Skan error 2320117395Skan ("unit `%s' requires absence and presence of `%s'", 2321132718Skan dst->unit_decl->name, unit->name); 2322132718Skan no_error_flag = 0; 2323132718Skan } 2324132718Skan else 2325132718Skan warning 2326169689Skan (0, "unit `%s' requires absence and presence of `%s'", 2327132718Skan dst->unit_decl->name, unit->name); 2328132718Skan } 2329117395Skan if (no_error_flag) 2330117395Skan { 2331132718Skan for (prev_el = (presence_p 2332132718Skan ? (final_p 2333132718Skan ? dst->unit_decl->final_presence_list 2334132718Skan : dst->unit_decl->final_presence_list) 2335132718Skan : (final_p 2336132718Skan ? dst->unit_decl->final_absence_list 2337132718Skan : dst->unit_decl->absence_list)); 2338132718Skan prev_el != NULL && prev_el->next_pattern_set_el != NULL; 2339132718Skan prev_el = prev_el->next_pattern_set_el) 2340132718Skan ; 2341132718Skan copy = copy_node (pat, sizeof (*pat)); 2342132718Skan copy->next_pattern_set_el = NULL; 2343117395Skan if (prev_el == NULL) 2344117395Skan { 2345117395Skan if (presence_p) 2346132718Skan { 2347132718Skan if (final_p) 2348132718Skan dst->unit_decl->final_presence_list = copy; 2349132718Skan else 2350132718Skan dst->unit_decl->presence_list = copy; 2351132718Skan } 2352132718Skan else if (final_p) 2353132718Skan dst->unit_decl->final_absence_list = copy; 2354117395Skan else 2355117395Skan dst->unit_decl->absence_list = copy; 2356117395Skan } 2357117395Skan else 2358132718Skan prev_el->next_pattern_set_el = copy; 2359117395Skan } 2360132718Skan } 2361132718Skan } 2362117395Skan} 2363117395Skan 2364132718Skan 2365117395Skan/* The function searches for bypass with given IN_INSN_RESERV in given 2366117395Skan BYPASS_LIST. */ 2367117395Skanstatic struct bypass_decl * 2368132718Skanfind_bypass (struct bypass_decl *bypass_list, 2369132718Skan struct insn_reserv_decl *in_insn_reserv) 2370117395Skan{ 2371117395Skan struct bypass_decl *bypass; 2372117395Skan 2373117395Skan for (bypass = bypass_list; bypass != NULL; bypass = bypass->next) 2374117395Skan if (bypass->in_insn_reserv == in_insn_reserv) 2375117395Skan break; 2376117395Skan return bypass; 2377117395Skan} 2378117395Skan 2379117395Skan/* The function processes pipeline description declarations, checks 2380117395Skan their correctness, and forms exclusion/presence/absence sets. */ 2381117395Skanstatic void 2382132718Skanprocess_decls (void) 2383117395Skan{ 2384117395Skan decl_t decl; 2385117395Skan decl_t automaton_decl; 2386117395Skan decl_t decl_in_table; 2387117395Skan decl_t out_insn_reserv; 2388117395Skan decl_t in_insn_reserv; 2389117395Skan struct bypass_decl *bypass; 2390117395Skan int automaton_presence; 2391117395Skan int i; 2392117395Skan 2393117395Skan /* Checking repeated automata declarations. */ 2394117395Skan automaton_presence = 0; 2395117395Skan for (i = 0; i < description->decls_num; i++) 2396117395Skan { 2397117395Skan decl = description->decls [i]; 2398117395Skan if (decl->mode == dm_automaton) 2399117395Skan { 2400117395Skan automaton_presence = 1; 2401117395Skan decl_in_table = insert_automaton_decl (decl); 2402117395Skan if (decl_in_table != decl) 2403117395Skan { 2404117395Skan if (!w_flag) 2405117395Skan error ("repeated declaration of automaton `%s'", 2406117395Skan DECL_AUTOMATON (decl)->name); 2407117395Skan else 2408169689Skan warning (0, "repeated declaration of automaton `%s'", 2409117395Skan DECL_AUTOMATON (decl)->name); 2410117395Skan } 2411117395Skan } 2412117395Skan } 2413117395Skan /* Checking undeclared automata, repeated declarations (except for 2414117395Skan automata) and correctness of their attributes (insn latency times 2415117395Skan etc.). */ 2416117395Skan for (i = 0; i < description->decls_num; i++) 2417117395Skan { 2418117395Skan decl = description->decls [i]; 2419117395Skan if (decl->mode == dm_insn_reserv) 2420117395Skan { 2421117395Skan if (DECL_INSN_RESERV (decl)->default_latency < 0) 2422117395Skan error ("define_insn_reservation `%s' has negative latency time", 2423117395Skan DECL_INSN_RESERV (decl)->name); 2424117395Skan DECL_INSN_RESERV (decl)->insn_num = description->insns_num; 2425117395Skan description->insns_num++; 2426117395Skan decl_in_table = insert_insn_decl (decl); 2427117395Skan if (decl_in_table != decl) 2428117395Skan error ("`%s' is already used as insn reservation name", 2429117395Skan DECL_INSN_RESERV (decl)->name); 2430117395Skan } 2431117395Skan else if (decl->mode == dm_bypass) 2432117395Skan { 2433117395Skan if (DECL_BYPASS (decl)->latency < 0) 2434117395Skan error ("define_bypass `%s - %s' has negative latency time", 2435117395Skan DECL_BYPASS (decl)->out_insn_name, 2436117395Skan DECL_BYPASS (decl)->in_insn_name); 2437117395Skan } 2438117395Skan else if (decl->mode == dm_unit || decl->mode == dm_reserv) 2439117395Skan { 2440117395Skan if (decl->mode == dm_unit) 2441117395Skan { 2442117395Skan DECL_UNIT (decl)->automaton_decl = NULL; 2443117395Skan if (DECL_UNIT (decl)->automaton_name != NULL) 2444117395Skan { 2445117395Skan automaton_decl 2446117395Skan = find_automaton_decl (DECL_UNIT (decl)->automaton_name); 2447117395Skan if (automaton_decl == NULL) 2448117395Skan error ("automaton `%s' is not declared", 2449117395Skan DECL_UNIT (decl)->automaton_name); 2450117395Skan else 2451117395Skan { 2452117395Skan DECL_AUTOMATON (automaton_decl)->automaton_is_used = 1; 2453117395Skan DECL_UNIT (decl)->automaton_decl 2454117395Skan = DECL_AUTOMATON (automaton_decl); 2455117395Skan } 2456117395Skan } 2457117395Skan else if (automaton_presence) 2458117395Skan error ("define_unit `%s' without automaton when one defined", 2459117395Skan DECL_UNIT (decl)->name); 2460117395Skan DECL_UNIT (decl)->unit_num = description->units_num; 2461117395Skan description->units_num++; 2462117395Skan if (strcmp (DECL_UNIT (decl)->name, NOTHING_NAME) == 0) 2463117395Skan { 2464117395Skan error ("`%s' is declared as cpu unit", NOTHING_NAME); 2465117395Skan continue; 2466117395Skan } 2467117395Skan decl_in_table = find_decl (DECL_UNIT (decl)->name); 2468117395Skan } 2469117395Skan else 2470117395Skan { 2471117395Skan if (strcmp (DECL_RESERV (decl)->name, NOTHING_NAME) == 0) 2472117395Skan { 2473117395Skan error ("`%s' is declared as cpu reservation", NOTHING_NAME); 2474117395Skan continue; 2475117395Skan } 2476117395Skan decl_in_table = find_decl (DECL_RESERV (decl)->name); 2477117395Skan } 2478117395Skan if (decl_in_table == NULL) 2479117395Skan decl_in_table = insert_decl (decl); 2480117395Skan else 2481117395Skan { 2482117395Skan if (decl->mode == dm_unit) 2483117395Skan error ("repeated declaration of unit `%s'", 2484117395Skan DECL_UNIT (decl)->name); 2485117395Skan else 2486117395Skan error ("repeated declaration of reservation `%s'", 2487117395Skan DECL_RESERV (decl)->name); 2488117395Skan } 2489117395Skan } 2490117395Skan } 2491117395Skan /* Check bypasses and form list of bypasses for each (output) 2492117395Skan insn. */ 2493117395Skan for (i = 0; i < description->decls_num; i++) 2494117395Skan { 2495117395Skan decl = description->decls [i]; 2496117395Skan if (decl->mode == dm_bypass) 2497117395Skan { 2498117395Skan out_insn_reserv = find_insn_decl (DECL_BYPASS (decl)->out_insn_name); 2499117395Skan in_insn_reserv = find_insn_decl (DECL_BYPASS (decl)->in_insn_name); 2500117395Skan if (out_insn_reserv == NULL) 2501117395Skan error ("there is no insn reservation `%s'", 2502117395Skan DECL_BYPASS (decl)->out_insn_name); 2503117395Skan else if (in_insn_reserv == NULL) 2504117395Skan error ("there is no insn reservation `%s'", 2505117395Skan DECL_BYPASS (decl)->in_insn_name); 2506117395Skan else 2507117395Skan { 2508117395Skan DECL_BYPASS (decl)->out_insn_reserv 2509117395Skan = DECL_INSN_RESERV (out_insn_reserv); 2510117395Skan DECL_BYPASS (decl)->in_insn_reserv 2511117395Skan = DECL_INSN_RESERV (in_insn_reserv); 2512117395Skan bypass 2513117395Skan = find_bypass (DECL_INSN_RESERV (out_insn_reserv)->bypass_list, 2514117395Skan DECL_BYPASS (decl)->in_insn_reserv); 2515117395Skan if (bypass != NULL) 2516117395Skan { 2517117395Skan if (DECL_BYPASS (decl)->latency == bypass->latency) 2518117395Skan { 2519117395Skan if (!w_flag) 2520117395Skan error 2521117395Skan ("the same bypass `%s - %s' is already defined", 2522117395Skan DECL_BYPASS (decl)->out_insn_name, 2523117395Skan DECL_BYPASS (decl)->in_insn_name); 2524117395Skan else 2525117395Skan warning 2526169689Skan (0, "the same bypass `%s - %s' is already defined", 2527117395Skan DECL_BYPASS (decl)->out_insn_name, 2528117395Skan DECL_BYPASS (decl)->in_insn_name); 2529117395Skan } 2530117395Skan else 2531117395Skan error ("bypass `%s - %s' is already defined", 2532117395Skan DECL_BYPASS (decl)->out_insn_name, 2533117395Skan DECL_BYPASS (decl)->in_insn_name); 2534117395Skan } 2535117395Skan else 2536117395Skan { 2537117395Skan DECL_BYPASS (decl)->next 2538117395Skan = DECL_INSN_RESERV (out_insn_reserv)->bypass_list; 2539117395Skan DECL_INSN_RESERV (out_insn_reserv)->bypass_list 2540117395Skan = DECL_BYPASS (decl); 2541117395Skan } 2542117395Skan } 2543117395Skan } 2544117395Skan } 2545117395Skan 2546132718Skan /* Check exclusion set declarations and form exclusion sets. */ 2547117395Skan for (i = 0; i < description->decls_num; i++) 2548117395Skan { 2549117395Skan decl = description->decls [i]; 2550117395Skan if (decl->mode == dm_excl) 2551117395Skan { 2552117395Skan unit_set_el_t unit_set_el_list; 2553117395Skan unit_set_el_t unit_set_el_list_2; 2554132718Skan 2555117395Skan unit_set_el_list 2556117395Skan = process_excls (DECL_EXCL (decl)->names, 2557117395Skan DECL_EXCL (decl)->first_list_length, decl->pos); 2558117395Skan unit_set_el_list_2 2559117395Skan = process_excls (&DECL_EXCL (decl)->names 2560117395Skan [DECL_EXCL (decl)->first_list_length], 2561132718Skan DECL_EXCL (decl)->all_names_num 2562117395Skan - DECL_EXCL (decl)->first_list_length, 2563117395Skan decl->pos); 2564117395Skan add_excls (unit_set_el_list, unit_set_el_list_2, decl->pos); 2565117395Skan add_excls (unit_set_el_list_2, unit_set_el_list, decl->pos); 2566117395Skan } 2567117395Skan } 2568117395Skan 2569117395Skan /* Check presence set declarations and form presence sets. */ 2570117395Skan for (i = 0; i < description->decls_num; i++) 2571117395Skan { 2572117395Skan decl = description->decls [i]; 2573117395Skan if (decl->mode == dm_presence) 2574117395Skan { 2575117395Skan unit_set_el_t unit_set_el_list; 2576132718Skan pattern_set_el_t pattern_set_el_list; 2577132718Skan 2578117395Skan unit_set_el_list 2579132718Skan = process_presence_absence_names 2580132718Skan (DECL_PRESENCE (decl)->names, DECL_PRESENCE (decl)->names_num, 2581132718Skan decl->pos, TRUE, DECL_PRESENCE (decl)->final_p); 2582132718Skan pattern_set_el_list 2583132718Skan = process_presence_absence_patterns 2584132718Skan (DECL_PRESENCE (decl)->patterns, 2585132718Skan DECL_PRESENCE (decl)->patterns_num, 2586132718Skan decl->pos, TRUE, DECL_PRESENCE (decl)->final_p); 2587132718Skan add_presence_absence (unit_set_el_list, pattern_set_el_list, 2588132718Skan decl->pos, TRUE, 2589132718Skan DECL_PRESENCE (decl)->final_p); 2590117395Skan } 2591117395Skan } 2592117395Skan 2593117395Skan /* Check absence set declarations and form absence sets. */ 2594117395Skan for (i = 0; i < description->decls_num; i++) 2595117395Skan { 2596117395Skan decl = description->decls [i]; 2597117395Skan if (decl->mode == dm_absence) 2598117395Skan { 2599117395Skan unit_set_el_t unit_set_el_list; 2600132718Skan pattern_set_el_t pattern_set_el_list; 2601132718Skan 2602117395Skan unit_set_el_list 2603132718Skan = process_presence_absence_names 2604132718Skan (DECL_ABSENCE (decl)->names, DECL_ABSENCE (decl)->names_num, 2605132718Skan decl->pos, FALSE, DECL_ABSENCE (decl)->final_p); 2606132718Skan pattern_set_el_list 2607132718Skan = process_presence_absence_patterns 2608132718Skan (DECL_ABSENCE (decl)->patterns, 2609132718Skan DECL_ABSENCE (decl)->patterns_num, 2610132718Skan decl->pos, FALSE, DECL_ABSENCE (decl)->final_p); 2611132718Skan add_presence_absence (unit_set_el_list, pattern_set_el_list, 2612132718Skan decl->pos, FALSE, 2613132718Skan DECL_ABSENCE (decl)->final_p); 2614117395Skan } 2615117395Skan } 2616117395Skan} 2617117395Skan 2618117395Skan/* The following function checks that declared automaton is used. If 2619117395Skan the automaton is not used, the function fixes error/warning. The 2620117395Skan following function must be called only after `process_decls'. */ 2621117395Skanstatic void 2622132718Skancheck_automaton_usage (void) 2623117395Skan{ 2624117395Skan decl_t decl; 2625117395Skan int i; 2626117395Skan 2627117395Skan for (i = 0; i < description->decls_num; i++) 2628117395Skan { 2629117395Skan decl = description->decls [i]; 2630117395Skan if (decl->mode == dm_automaton 2631117395Skan && !DECL_AUTOMATON (decl)->automaton_is_used) 2632117395Skan { 2633117395Skan if (!w_flag) 2634117395Skan error ("automaton `%s' is not used", DECL_AUTOMATON (decl)->name); 2635117395Skan else 2636169689Skan warning (0, "automaton `%s' is not used", 2637117395Skan DECL_AUTOMATON (decl)->name); 2638117395Skan } 2639117395Skan } 2640117395Skan} 2641117395Skan 2642117395Skan/* The following recursive function processes all regexp in order to 2643117395Skan fix usage of units or reservations and to fix errors of undeclared 2644117395Skan name. The function may change unit_regexp onto reserv_regexp. 2645117395Skan Remember that reserv_regexp does not exist before the function 2646117395Skan call. */ 2647117395Skanstatic regexp_t 2648132718Skanprocess_regexp (regexp_t regexp) 2649117395Skan{ 2650117395Skan decl_t decl_in_table; 2651117395Skan regexp_t new_regexp; 2652117395Skan int i; 2653132718Skan 2654169689Skan switch (regexp->mode) 2655117395Skan { 2656169689Skan case rm_unit: 2657117395Skan decl_in_table = find_decl (REGEXP_UNIT (regexp)->name); 2658117395Skan if (decl_in_table == NULL) 2659117395Skan error ("undeclared unit or reservation `%s'", 2660117395Skan REGEXP_UNIT (regexp)->name); 2661169689Skan else 2662169689Skan switch (decl_in_table->mode) 2663169689Skan { 2664169689Skan case dm_unit: 2665169689Skan DECL_UNIT (decl_in_table)->unit_is_used = 1; 2666169689Skan REGEXP_UNIT (regexp)->unit_decl = DECL_UNIT (decl_in_table); 2667169689Skan break; 2668169689Skan 2669169689Skan case dm_reserv: 2670169689Skan DECL_RESERV (decl_in_table)->reserv_is_used = 1; 2671169689Skan new_regexp = create_node (sizeof (struct regexp)); 2672169689Skan new_regexp->mode = rm_reserv; 2673169689Skan new_regexp->pos = regexp->pos; 2674169689Skan REGEXP_RESERV (new_regexp)->name = REGEXP_UNIT (regexp)->name; 2675169689Skan REGEXP_RESERV (new_regexp)->reserv_decl 2676169689Skan = DECL_RESERV (decl_in_table); 2677169689Skan regexp = new_regexp; 2678169689Skan break; 2679169689Skan 2680169689Skan default: 2681169689Skan gcc_unreachable (); 2682117395Skan } 2683169689Skan break; 2684169689Skan case rm_sequence: 2685169689Skan for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++) 2686169689Skan REGEXP_SEQUENCE (regexp)->regexps [i] 2687169689Skan = process_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]); 2688169689Skan break; 2689169689Skan case rm_allof: 2690169689Skan for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++) 2691169689Skan REGEXP_ALLOF (regexp)->regexps [i] 2692169689Skan = process_regexp (REGEXP_ALLOF (regexp)->regexps [i]); 2693169689Skan break; 2694169689Skan case rm_oneof: 2695169689Skan for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++) 2696169689Skan REGEXP_ONEOF (regexp)->regexps [i] 2697169689Skan = process_regexp (REGEXP_ONEOF (regexp)->regexps [i]); 2698169689Skan break; 2699169689Skan case rm_repeat: 2700169689Skan REGEXP_REPEAT (regexp)->regexp 2701169689Skan = process_regexp (REGEXP_REPEAT (regexp)->regexp); 2702169689Skan break; 2703169689Skan case rm_nothing: 2704169689Skan break; 2705169689Skan default: 2706169689Skan gcc_unreachable (); 2707117395Skan } 2708117395Skan return regexp; 2709117395Skan} 2710117395Skan 2711117395Skan/* The following function processes regexp of define_reservation and 2712117395Skan define_insn_reservation with the aid of function 2713117395Skan `process_regexp'. */ 2714117395Skanstatic void 2715132718Skanprocess_regexp_decls (void) 2716117395Skan{ 2717117395Skan decl_t decl; 2718117395Skan int i; 2719117395Skan 2720117395Skan for (i = 0; i < description->decls_num; i++) 2721117395Skan { 2722117395Skan decl = description->decls [i]; 2723117395Skan if (decl->mode == dm_reserv) 2724117395Skan DECL_RESERV (decl)->regexp 2725117395Skan = process_regexp (DECL_RESERV (decl)->regexp); 2726117395Skan else if (decl->mode == dm_insn_reserv) 2727117395Skan DECL_INSN_RESERV (decl)->regexp 2728117395Skan = process_regexp (DECL_INSN_RESERV (decl)->regexp); 2729117395Skan } 2730117395Skan} 2731117395Skan 2732117395Skan/* The following function checks that declared unit is used. If the 2733117395Skan unit is not used, the function fixes errors/warnings. The 2734117395Skan following function must be called only after `process_decls', 2735117395Skan `process_regexp_decls'. */ 2736117395Skanstatic void 2737132718Skancheck_usage (void) 2738117395Skan{ 2739117395Skan decl_t decl; 2740117395Skan int i; 2741117395Skan 2742117395Skan for (i = 0; i < description->decls_num; i++) 2743117395Skan { 2744117395Skan decl = description->decls [i]; 2745117395Skan if (decl->mode == dm_unit && !DECL_UNIT (decl)->unit_is_used) 2746117395Skan { 2747117395Skan if (!w_flag) 2748117395Skan error ("unit `%s' is not used", DECL_UNIT (decl)->name); 2749117395Skan else 2750169689Skan warning (0, "unit `%s' is not used", DECL_UNIT (decl)->name); 2751117395Skan } 2752117395Skan else if (decl->mode == dm_reserv && !DECL_RESERV (decl)->reserv_is_used) 2753117395Skan { 2754117395Skan if (!w_flag) 2755117395Skan error ("reservation `%s' is not used", DECL_RESERV (decl)->name); 2756117395Skan else 2757169689Skan warning (0, "reservation `%s' is not used", DECL_RESERV (decl)->name); 2758117395Skan } 2759117395Skan } 2760117395Skan} 2761117395Skan 2762117395Skan/* The following variable value is number of reservation being 2763117395Skan processed on loop recognition. */ 2764117395Skanstatic int curr_loop_pass_num; 2765117395Skan 2766117395Skan/* The following recursive function returns nonzero value if REGEXP 2767117395Skan contains given decl or reservations in given regexp refers for 2768117395Skan given decl. */ 2769117395Skanstatic int 2770132718Skanloop_in_regexp (regexp_t regexp, decl_t start_decl) 2771117395Skan{ 2772117395Skan int i; 2773117395Skan 2774117395Skan if (regexp == NULL) 2775117395Skan return 0; 2776169689Skan switch (regexp->mode) 2777117395Skan { 2778169689Skan case rm_unit: 2779169689Skan return 0; 2780169689Skan 2781169689Skan case rm_reserv: 2782117395Skan if (start_decl->mode == dm_reserv 2783117395Skan && REGEXP_RESERV (regexp)->reserv_decl == DECL_RESERV (start_decl)) 2784117395Skan return 1; 2785117395Skan else if (REGEXP_RESERV (regexp)->reserv_decl->loop_pass_num 2786117395Skan == curr_loop_pass_num) 2787117395Skan /* declaration has been processed. */ 2788117395Skan return 0; 2789117395Skan else 2790117395Skan { 2791117395Skan REGEXP_RESERV (regexp)->reserv_decl->loop_pass_num 2792117395Skan = curr_loop_pass_num; 2793117395Skan return loop_in_regexp (REGEXP_RESERV (regexp)->reserv_decl->regexp, 2794117395Skan start_decl); 2795117395Skan } 2796169689Skan 2797169689Skan case rm_sequence: 2798117395Skan for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++) 2799117395Skan if (loop_in_regexp (REGEXP_SEQUENCE (regexp)->regexps [i], start_decl)) 2800117395Skan return 1; 2801117395Skan return 0; 2802169689Skan 2803169689Skan case rm_allof: 2804117395Skan for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++) 2805117395Skan if (loop_in_regexp (REGEXP_ALLOF (regexp)->regexps [i], start_decl)) 2806117395Skan return 1; 2807117395Skan return 0; 2808169689Skan 2809169689Skan case rm_oneof: 2810117395Skan for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++) 2811117395Skan if (loop_in_regexp (REGEXP_ONEOF (regexp)->regexps [i], start_decl)) 2812117395Skan return 1; 2813117395Skan return 0; 2814169689Skan 2815169689Skan case rm_repeat: 2816169689Skan return loop_in_regexp (REGEXP_REPEAT (regexp)->regexp, start_decl); 2817169689Skan 2818169689Skan case rm_nothing: 2819117395Skan return 0; 2820169689Skan 2821169689Skan default: 2822169689Skan gcc_unreachable (); 2823117395Skan } 2824117395Skan} 2825117395Skan 2826117395Skan/* The following function fixes errors "cycle in definition ...". The 2827117395Skan function uses function `loop_in_regexp' for that. */ 2828117395Skanstatic void 2829132718Skancheck_loops_in_regexps (void) 2830117395Skan{ 2831117395Skan decl_t decl; 2832117395Skan int i; 2833117395Skan 2834117395Skan for (i = 0; i < description->decls_num; i++) 2835117395Skan { 2836117395Skan decl = description->decls [i]; 2837117395Skan if (decl->mode == dm_reserv) 2838117395Skan DECL_RESERV (decl)->loop_pass_num = 0; 2839117395Skan } 2840117395Skan for (i = 0; i < description->decls_num; i++) 2841117395Skan { 2842117395Skan decl = description->decls [i]; 2843117395Skan curr_loop_pass_num = i; 2844132718Skan 2845117395Skan if (decl->mode == dm_reserv) 2846117395Skan { 2847117395Skan DECL_RESERV (decl)->loop_pass_num = curr_loop_pass_num; 2848117395Skan if (loop_in_regexp (DECL_RESERV (decl)->regexp, decl)) 2849117395Skan { 2850169689Skan gcc_assert (DECL_RESERV (decl)->regexp); 2851117395Skan error ("cycle in definition of reservation `%s'", 2852117395Skan DECL_RESERV (decl)->name); 2853117395Skan } 2854117395Skan } 2855117395Skan } 2856117395Skan} 2857117395Skan 2858117395Skan/* The function recursively processes IR of reservation and defines 2859132718Skan max and min cycle for reservation of unit. */ 2860132718Skanstatic void 2861132718Skanprocess_regexp_cycles (regexp_t regexp, int max_start_cycle, 2862132718Skan int min_start_cycle, int *max_finish_cycle, 2863132718Skan int *min_finish_cycle) 2864117395Skan{ 2865117395Skan int i; 2866117395Skan 2867169689Skan switch (regexp->mode) 2868117395Skan { 2869169689Skan case rm_unit: 2870132718Skan if (REGEXP_UNIT (regexp)->unit_decl->max_occ_cycle_num < max_start_cycle) 2871132718Skan REGEXP_UNIT (regexp)->unit_decl->max_occ_cycle_num = max_start_cycle; 2872132718Skan if (REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num > min_start_cycle 2873132718Skan || REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num == -1) 2874132718Skan REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num = min_start_cycle; 2875132718Skan *max_finish_cycle = max_start_cycle; 2876132718Skan *min_finish_cycle = min_start_cycle; 2877169689Skan break; 2878169689Skan 2879169689Skan case rm_reserv: 2880169689Skan process_regexp_cycles (REGEXP_RESERV (regexp)->reserv_decl->regexp, 2881169689Skan max_start_cycle, min_start_cycle, 2882169689Skan max_finish_cycle, min_finish_cycle); 2883169689Skan break; 2884169689Skan 2885169689Skan case rm_repeat: 2886117395Skan for (i = 0; i < REGEXP_REPEAT (regexp)->repeat_num; i++) 2887132718Skan { 2888132718Skan process_regexp_cycles (REGEXP_REPEAT (regexp)->regexp, 2889132718Skan max_start_cycle, min_start_cycle, 2890132718Skan max_finish_cycle, min_finish_cycle); 2891132718Skan max_start_cycle = *max_finish_cycle + 1; 2892132718Skan min_start_cycle = *min_finish_cycle + 1; 2893132718Skan } 2894169689Skan break; 2895169689Skan 2896169689Skan case rm_sequence: 2897117395Skan for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++) 2898132718Skan { 2899132718Skan process_regexp_cycles (REGEXP_SEQUENCE (regexp)->regexps [i], 2900132718Skan max_start_cycle, min_start_cycle, 2901132718Skan max_finish_cycle, min_finish_cycle); 2902132718Skan max_start_cycle = *max_finish_cycle + 1; 2903132718Skan min_start_cycle = *min_finish_cycle + 1; 2904132718Skan } 2905169689Skan break; 2906117395Skan 2907169689Skan case rm_allof: 2908169689Skan { 2909169689Skan int max_cycle = 0; 2910169689Skan int min_cycle = 0; 2911169689Skan 2912169689Skan for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++) 2913169689Skan { 2914169689Skan process_regexp_cycles (REGEXP_ALLOF (regexp)->regexps [i], 2915169689Skan max_start_cycle, min_start_cycle, 2916169689Skan max_finish_cycle, min_finish_cycle); 2917169689Skan if (max_cycle < *max_finish_cycle) 2918169689Skan max_cycle = *max_finish_cycle; 2919169689Skan if (i == 0 || min_cycle > *min_finish_cycle) 2920169689Skan min_cycle = *min_finish_cycle; 2921169689Skan } 2922169689Skan *max_finish_cycle = max_cycle; 2923169689Skan *min_finish_cycle = min_cycle; 2924169689Skan } 2925169689Skan break; 2926117395Skan 2927169689Skan case rm_oneof: 2928169689Skan { 2929169689Skan int max_cycle = 0; 2930169689Skan int min_cycle = 0; 2931169689Skan 2932169689Skan for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++) 2933169689Skan { 2934169689Skan process_regexp_cycles (REGEXP_ONEOF (regexp)->regexps [i], 2935169689Skan max_start_cycle, min_start_cycle, 2936169689Skan max_finish_cycle, min_finish_cycle); 2937169689Skan if (max_cycle < *max_finish_cycle) 2938169689Skan max_cycle = *max_finish_cycle; 2939169689Skan if (i == 0 || min_cycle > *min_finish_cycle) 2940169689Skan min_cycle = *min_finish_cycle; 2941169689Skan } 2942169689Skan *max_finish_cycle = max_cycle; 2943169689Skan *min_finish_cycle = min_cycle; 2944169689Skan } 2945169689Skan break; 2946169689Skan 2947169689Skan case rm_nothing: 2948132718Skan *max_finish_cycle = max_start_cycle; 2949132718Skan *min_finish_cycle = min_start_cycle; 2950169689Skan break; 2951169689Skan 2952169689Skan default: 2953169689Skan gcc_unreachable (); 2954117395Skan } 2955117395Skan} 2956117395Skan 2957117395Skan/* The following function is called only for correct program. The 2958117395Skan function defines max reservation of insns in cycles. */ 2959117395Skanstatic void 2960132718Skanevaluate_max_reserv_cycles (void) 2961117395Skan{ 2962117395Skan int max_insn_cycles_num; 2963132718Skan int min_insn_cycles_num; 2964117395Skan decl_t decl; 2965117395Skan int i; 2966117395Skan 2967117395Skan description->max_insn_reserv_cycles = 0; 2968117395Skan for (i = 0; i < description->decls_num; i++) 2969117395Skan { 2970117395Skan decl = description->decls [i]; 2971117395Skan if (decl->mode == dm_insn_reserv) 2972117395Skan { 2973132718Skan process_regexp_cycles (DECL_INSN_RESERV (decl)->regexp, 0, 0, 2974132718Skan &max_insn_cycles_num, &min_insn_cycles_num); 2975117395Skan if (description->max_insn_reserv_cycles < max_insn_cycles_num) 2976117395Skan description->max_insn_reserv_cycles = max_insn_cycles_num; 2977117395Skan } 2978117395Skan } 2979117395Skan description->max_insn_reserv_cycles++; 2980117395Skan} 2981117395Skan 2982117395Skan/* The following function calls functions for checking all 2983117395Skan description. */ 2984117395Skanstatic void 2985132718Skancheck_all_description (void) 2986117395Skan{ 2987117395Skan process_decls (); 2988117395Skan check_automaton_usage (); 2989117395Skan process_regexp_decls (); 2990117395Skan check_usage (); 2991117395Skan check_loops_in_regexps (); 2992117395Skan if (!have_error) 2993117395Skan evaluate_max_reserv_cycles (); 2994117395Skan} 2995117395Skan 2996117395Skan 2997117395Skan 2998117395Skan/* The page contains abstract data `ticker'. This data is used to 2999117395Skan report time of different phases of building automata. It is 3000117395Skan possibly to write a description for which automata will be built 3001117395Skan during several minutes even on fast machine. */ 3002117395Skan 3003117395Skan/* The following function creates ticker and makes it active. */ 3004117395Skanstatic ticker_t 3005132718Skancreate_ticker (void) 3006117395Skan{ 3007117395Skan ticker_t ticker; 3008117395Skan 3009117395Skan ticker.modified_creation_time = get_run_time (); 3010117395Skan ticker.incremented_off_time = 0; 3011117395Skan return ticker; 3012117395Skan} 3013117395Skan 3014117395Skan/* The following function switches off given ticker. */ 3015117395Skanstatic void 3016132718Skanticker_off (ticker_t *ticker) 3017117395Skan{ 3018117395Skan if (ticker->incremented_off_time == 0) 3019117395Skan ticker->incremented_off_time = get_run_time () + 1; 3020117395Skan} 3021117395Skan 3022117395Skan/* The following function switches on given ticker. */ 3023117395Skanstatic void 3024132718Skanticker_on (ticker_t *ticker) 3025117395Skan{ 3026117395Skan if (ticker->incremented_off_time != 0) 3027117395Skan { 3028117395Skan ticker->modified_creation_time 3029117395Skan += get_run_time () - ticker->incremented_off_time + 1; 3030117395Skan ticker->incremented_off_time = 0; 3031117395Skan } 3032117395Skan} 3033117395Skan 3034117395Skan/* The following function returns current time in milliseconds since 3035117395Skan the moment when given ticker was created. */ 3036117395Skanstatic int 3037132718Skanactive_time (ticker_t ticker) 3038117395Skan{ 3039117395Skan if (ticker.incremented_off_time != 0) 3040117395Skan return ticker.incremented_off_time - 1 - ticker.modified_creation_time; 3041117395Skan else 3042117395Skan return get_run_time () - ticker.modified_creation_time; 3043117395Skan} 3044117395Skan 3045117395Skan/* The following function returns string representation of active time 3046117395Skan of given ticker. The result is string representation of seconds 3047117395Skan with accuracy of 1/100 second. Only result of the last call of the 3048117395Skan function exists. Therefore the following code is not correct 3049117395Skan 3050117395Skan printf ("parser time: %s\ngeneration time: %s\n", 3051117395Skan active_time_string (parser_ticker), 3052117395Skan active_time_string (generation_ticker)); 3053117395Skan 3054117395Skan Correct code has to be the following 3055117395Skan 3056117395Skan printf ("parser time: %s\n", active_time_string (parser_ticker)); 3057117395Skan printf ("generation time: %s\n", 3058117395Skan active_time_string (generation_ticker)); 3059117395Skan 3060117395Skan*/ 3061117395Skanstatic void 3062132718Skanprint_active_time (FILE *f, ticker_t ticker) 3063117395Skan{ 3064117395Skan int msecs; 3065117395Skan 3066117395Skan msecs = active_time (ticker); 3067117395Skan fprintf (f, "%d.%06d", msecs / 1000000, msecs % 1000000); 3068117395Skan} 3069117395Skan 3070117395Skan 3071117395Skan 3072117395Skan/* The following variable value is number of automaton which are 3073117395Skan really being created. This value is defined on the base of 3074117395Skan argument of option `-split'. If the variable has zero value the 3075117395Skan number of automata is defined by the constructions `%automaton'. 3076132718Skan This case occurs when option `-split' is absent or has zero 3077117395Skan argument. If constructions `define_automaton' is absent only one 3078117395Skan automaton is created. */ 3079117395Skanstatic int automata_num; 3080117395Skan 3081117395Skan/* The following variable values are times of 3082117395Skan o transformation of regular expressions 3083117395Skan o building NDFA (DFA if !ndfa_flag) 3084117395Skan o NDFA -> DFA (simply the same automaton if !ndfa_flag) 3085117395Skan o DFA minimization 3086117395Skan o building insn equivalence classes 3087117395Skan o all previous ones 3088117395Skan o code output */ 3089117395Skanstatic ticker_t transform_time; 3090117395Skanstatic ticker_t NDFA_time; 3091117395Skanstatic ticker_t NDFA_to_DFA_time; 3092117395Skanstatic ticker_t minimize_time; 3093117395Skanstatic ticker_t equiv_time; 3094117395Skanstatic ticker_t automaton_generation_time; 3095117395Skanstatic ticker_t output_time; 3096117395Skan 3097117395Skan/* The following variable values are times of 3098117395Skan all checking 3099117395Skan all generation 3100117395Skan all pipeline hazard translator work */ 3101117395Skanstatic ticker_t check_time; 3102117395Skanstatic ticker_t generation_time; 3103117395Skanstatic ticker_t all_time; 3104117395Skan 3105117395Skan 3106117395Skan 3107117395Skan/* Pseudo insn decl which denotes advancing cycle. */ 3108117395Skanstatic decl_t advance_cycle_insn_decl; 3109117395Skanstatic void 3110132718Skanadd_advance_cycle_insn_decl (void) 3111117395Skan{ 3112117395Skan advance_cycle_insn_decl = create_node (sizeof (struct decl)); 3113117395Skan advance_cycle_insn_decl->mode = dm_insn_reserv; 3114117395Skan advance_cycle_insn_decl->pos = no_pos; 3115117395Skan DECL_INSN_RESERV (advance_cycle_insn_decl)->regexp = NULL; 3116169689Skan DECL_INSN_RESERV (advance_cycle_insn_decl)->name = "$advance_cycle"; 3117117395Skan DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num 3118117395Skan = description->insns_num; 3119117395Skan description->decls [description->decls_num] = advance_cycle_insn_decl; 3120117395Skan description->decls_num++; 3121117395Skan description->insns_num++; 3122117395Skan} 3123117395Skan 3124117395Skan 3125132718Skan/* Abstract data `alternative states' which represents 3126117395Skan nondeterministic nature of the description (see comments for 3127117395Skan structures alt_state and state). */ 3128117395Skan 3129117395Skan/* List of free states. */ 3130117395Skanstatic alt_state_t first_free_alt_state; 3131117395Skan 3132117395Skan#ifndef NDEBUG 3133117395Skan/* The following variables is maximal number of allocated nodes 3134117395Skan alt_state. */ 3135117395Skanstatic int allocated_alt_states_num = 0; 3136117395Skan#endif 3137117395Skan 3138117395Skan/* The following function returns free node alt_state. It may be new 3139132718Skan allocated node or node freed earlier. */ 3140132718Skanstatic alt_state_t 3141132718Skanget_free_alt_state (void) 3142117395Skan{ 3143117395Skan alt_state_t result; 3144117395Skan 3145117395Skan if (first_free_alt_state != NULL) 3146117395Skan { 3147117395Skan result = first_free_alt_state; 3148117395Skan first_free_alt_state = first_free_alt_state->next_alt_state; 3149117395Skan } 3150117395Skan else 3151117395Skan { 3152117395Skan#ifndef NDEBUG 3153117395Skan allocated_alt_states_num++; 3154117395Skan#endif 3155117395Skan result = create_node (sizeof (struct alt_state)); 3156117395Skan } 3157117395Skan result->state = NULL; 3158117395Skan result->next_alt_state = NULL; 3159117395Skan result->next_sorted_alt_state = NULL; 3160117395Skan return result; 3161117395Skan} 3162117395Skan 3163117395Skan/* The function frees node ALT_STATE. */ 3164117395Skanstatic void 3165132718Skanfree_alt_state (alt_state_t alt_state) 3166117395Skan{ 3167117395Skan if (alt_state == NULL) 3168117395Skan return; 3169117395Skan alt_state->next_alt_state = first_free_alt_state; 3170117395Skan first_free_alt_state = alt_state; 3171117395Skan} 3172117395Skan 3173117395Skan/* The function frees list started with node ALT_STATE_LIST. */ 3174117395Skanstatic void 3175132718Skanfree_alt_states (alt_state_t alt_states_list) 3176117395Skan{ 3177117395Skan alt_state_t curr_alt_state; 3178117395Skan alt_state_t next_alt_state; 3179117395Skan 3180117395Skan for (curr_alt_state = alt_states_list; 3181117395Skan curr_alt_state != NULL; 3182117395Skan curr_alt_state = next_alt_state) 3183117395Skan { 3184117395Skan next_alt_state = curr_alt_state->next_alt_state; 3185117395Skan free_alt_state (curr_alt_state); 3186117395Skan } 3187117395Skan} 3188117395Skan 3189117395Skan/* The function compares unique numbers of alt states. */ 3190117395Skanstatic int 3191132718Skanalt_state_cmp (const void *alt_state_ptr_1, const void *alt_state_ptr_2) 3192117395Skan{ 3193117395Skan if ((*(alt_state_t *) alt_state_ptr_1)->state->unique_num 3194117395Skan == (*(alt_state_t *) alt_state_ptr_2)->state->unique_num) 3195117395Skan return 0; 3196117395Skan else if ((*(alt_state_t *) alt_state_ptr_1)->state->unique_num 3197117395Skan < (*(alt_state_t *) alt_state_ptr_2)->state->unique_num) 3198117395Skan return -1; 3199117395Skan else 3200117395Skan return 1; 3201117395Skan} 3202117395Skan 3203117395Skan/* The function sorts ALT_STATES_LIST and removes duplicated alt 3204117395Skan states from the list. The comparison key is alt state unique 3205117395Skan number. */ 3206169689Skan 3207132718Skanstatic alt_state_t 3208132718Skanuniq_sort_alt_states (alt_state_t alt_states_list) 3209117395Skan{ 3210117395Skan alt_state_t curr_alt_state; 3211169689Skan VEC(alt_state_t,heap) *alt_states; 3212117395Skan size_t i; 3213117395Skan size_t prev_unique_state_ind; 3214117395Skan alt_state_t result; 3215117395Skan 3216169689Skan if (alt_states_list == 0) 3217169689Skan return 0; 3218169689Skan if (alt_states_list->next_alt_state == 0) 3219169689Skan return alt_states_list; 3220169689Skan 3221169689Skan alt_states = VEC_alloc (alt_state_t,heap, 150); 3222117395Skan for (curr_alt_state = alt_states_list; 3223117395Skan curr_alt_state != NULL; 3224117395Skan curr_alt_state = curr_alt_state->next_alt_state) 3225169689Skan VEC_safe_push (alt_state_t,heap, alt_states, curr_alt_state); 3226169689Skan 3227169689Skan qsort (VEC_address (alt_state_t, alt_states), 3228169689Skan VEC_length (alt_state_t, alt_states), 3229117395Skan sizeof (alt_state_t), alt_state_cmp); 3230169689Skan 3231169689Skan prev_unique_state_ind = 0; 3232169689Skan for (i = 1; i < VEC_length (alt_state_t, alt_states); i++) 3233169689Skan if (VEC_index (alt_state_t, alt_states, prev_unique_state_ind)->state 3234169689Skan != VEC_index (alt_state_t, alt_states, i)->state) 3235169689Skan { 3236169689Skan prev_unique_state_ind++; 3237169689Skan VEC_replace (alt_state_t, alt_states, prev_unique_state_ind, 3238169689Skan VEC_index (alt_state_t, alt_states, i)); 3239169689Skan } 3240169689Skan VEC_truncate (alt_state_t, alt_states, prev_unique_state_ind + 1); 3241169689Skan 3242169689Skan for (i = 1; i < VEC_length (alt_state_t, alt_states); i++) 3243169689Skan VEC_index (alt_state_t, alt_states, i-1)->next_sorted_alt_state 3244169689Skan = VEC_index (alt_state_t, alt_states, i); 3245169689Skan VEC_last (alt_state_t, alt_states)->next_sorted_alt_state = 0; 3246169689Skan 3247169689Skan result = VEC_index (alt_state_t, alt_states, 0); 3248169689Skan 3249169689Skan VEC_free (alt_state_t,heap, alt_states); 3250117395Skan return result; 3251117395Skan} 3252117395Skan 3253117395Skan/* The function checks equality of alt state lists. Remember that the 3254117395Skan lists must be already sorted by the previous function. */ 3255117395Skanstatic int 3256132718Skanalt_states_eq (alt_state_t alt_states_1, alt_state_t alt_states_2) 3257117395Skan{ 3258117395Skan while (alt_states_1 != NULL && alt_states_2 != NULL 3259117395Skan && alt_state_cmp (&alt_states_1, &alt_states_2) == 0) 3260117395Skan { 3261117395Skan alt_states_1 = alt_states_1->next_sorted_alt_state; 3262117395Skan alt_states_2 = alt_states_2->next_sorted_alt_state; 3263117395Skan } 3264117395Skan return alt_states_1 == alt_states_2; 3265117395Skan} 3266117395Skan 3267117395Skan/* Initialization of the abstract data. */ 3268117395Skanstatic void 3269132718Skaninitiate_alt_states (void) 3270117395Skan{ 3271117395Skan first_free_alt_state = NULL; 3272117395Skan} 3273117395Skan 3274117395Skan/* Finishing work with the abstract data. */ 3275117395Skanstatic void 3276132718Skanfinish_alt_states (void) 3277117395Skan{ 3278117395Skan} 3279117395Skan 3280117395Skan 3281117395Skan 3282117395Skan/* The page contains macros for work with bits strings. We could use 3283117395Skan standard gcc bitmap or sbitmap but it would result in difficulties 3284117395Skan of building canadian cross. */ 3285117395Skan 3286117395Skan/* Set bit number bitno in the bit string. The macro is not side 3287117395Skan effect proof. */ 3288117395Skan#define SET_BIT(bitstring, bitno) \ 3289117395Skan (((char *) (bitstring)) [(bitno) / CHAR_BIT] |= 1 << (bitno) % CHAR_BIT) 3290117395Skan 3291132718Skan#define CLEAR_BIT(bitstring, bitno) \ 3292132718Skan (((char *) (bitstring)) [(bitno) / CHAR_BIT] &= ~(1 << (bitno) % CHAR_BIT)) 3293132718Skan 3294117395Skan/* Test if bit number bitno in the bitstring is set. The macro is not 3295117395Skan side effect proof. */ 3296117395Skan#define TEST_BIT(bitstring, bitno) \ 3297117395Skan (((char *) (bitstring)) [(bitno) / CHAR_BIT] >> (bitno) % CHAR_BIT & 1) 3298117395Skan 3299117395Skan 3300117395Skan 3301117395Skan/* This page contains abstract data `state'. */ 3302117395Skan 3303117395Skan/* Maximal length of reservations in cycles (>= 1). */ 3304117395Skanstatic int max_cycles_num; 3305117395Skan 3306117395Skan/* Number of set elements (see type set_el_t) needed for 3307117395Skan representation of one cycle reservation. It is depended on units 3308117395Skan number. */ 3309117395Skanstatic int els_in_cycle_reserv; 3310117395Skan 3311117395Skan/* Number of set elements (see type set_el_t) needed for 3312117395Skan representation of maximal length reservation. Deterministic 3313117395Skan reservation is stored as set (bit string) of length equal to the 3314117395Skan variable value * number of bits in set_el_t. */ 3315117395Skanstatic int els_in_reservs; 3316117395Skan 3317169689Skan/* Array of pointers to unit declarations. */ 3318117395Skanstatic unit_decl_t *units_array; 3319117395Skan 3320132718Skan/* Temporary reservation of maximal length. */ 3321132718Skanstatic reserv_sets_t temp_reserv; 3322117395Skan 3323117395Skan/* The state table itself is represented by the following variable. */ 3324117395Skanstatic htab_t state_table; 3325117395Skan 3326169689Skan/* Linked list of free 'state' structures to be recycled. The 3327169689Skan next_equiv_class_state pointer is borrowed for a free list. */ 3328169689Skanstatic state_t first_free_state; 3329117395Skan 3330117395Skanstatic int curr_unique_state_num; 3331117395Skan 3332117395Skan#ifndef NDEBUG 3333117395Skan/* The following variables is maximal number of allocated nodes 3334117395Skan `state'. */ 3335117395Skanstatic int allocated_states_num = 0; 3336117395Skan#endif 3337117395Skan 3338117395Skan/* Allocate new reservation set. */ 3339117395Skanstatic reserv_sets_t 3340132718Skanalloc_empty_reserv_sets (void) 3341117395Skan{ 3342117395Skan reserv_sets_t result; 3343117395Skan 3344117395Skan obstack_blank (&irp, els_in_reservs * sizeof (set_el_t)); 3345117395Skan result = (reserv_sets_t) obstack_base (&irp); 3346222097Sbenl (void) obstack_finish (&irp); 3347117395Skan memset (result, 0, els_in_reservs * sizeof (set_el_t)); 3348117395Skan return result; 3349117395Skan} 3350117395Skan 3351117395Skan/* Hash value of reservation set. */ 3352117395Skanstatic unsigned 3353132718Skanreserv_sets_hash_value (reserv_sets_t reservs) 3354117395Skan{ 3355117395Skan set_el_t hash_value; 3356117395Skan unsigned result; 3357117395Skan int reservs_num, i; 3358117395Skan set_el_t *reserv_ptr; 3359117395Skan 3360117395Skan hash_value = 0; 3361117395Skan reservs_num = els_in_reservs; 3362117395Skan reserv_ptr = reservs; 3363117395Skan i = 0; 3364117395Skan while (reservs_num != 0) 3365117395Skan { 3366117395Skan reservs_num--; 3367117395Skan hash_value += ((*reserv_ptr >> i) 3368117395Skan | (*reserv_ptr << (sizeof (set_el_t) * CHAR_BIT - i))); 3369117395Skan i++; 3370117395Skan if (i == sizeof (set_el_t) * CHAR_BIT) 3371117395Skan i = 0; 3372117395Skan reserv_ptr++; 3373117395Skan } 3374117395Skan if (sizeof (set_el_t) <= sizeof (unsigned)) 3375117395Skan return hash_value; 3376117395Skan result = 0; 3377117395Skan for (i = sizeof (set_el_t); i > 0; i -= sizeof (unsigned) - 1) 3378117395Skan { 3379117395Skan result += (unsigned) hash_value; 3380117395Skan hash_value >>= (sizeof (unsigned) - 1) * CHAR_BIT; 3381117395Skan } 3382117395Skan return result; 3383117395Skan} 3384117395Skan 3385117395Skan/* Comparison of given reservation sets. */ 3386117395Skanstatic int 3387132718Skanreserv_sets_cmp (reserv_sets_t reservs_1, reserv_sets_t reservs_2) 3388117395Skan{ 3389117395Skan int reservs_num; 3390117395Skan set_el_t *reserv_ptr_1; 3391117395Skan set_el_t *reserv_ptr_2; 3392117395Skan 3393169689Skan gcc_assert (reservs_1 && reservs_2); 3394117395Skan reservs_num = els_in_reservs; 3395117395Skan reserv_ptr_1 = reservs_1; 3396117395Skan reserv_ptr_2 = reservs_2; 3397117395Skan while (reservs_num != 0 && *reserv_ptr_1 == *reserv_ptr_2) 3398117395Skan { 3399117395Skan reservs_num--; 3400117395Skan reserv_ptr_1++; 3401117395Skan reserv_ptr_2++; 3402117395Skan } 3403117395Skan if (reservs_num == 0) 3404117395Skan return 0; 3405117395Skan else if (*reserv_ptr_1 < *reserv_ptr_2) 3406117395Skan return -1; 3407117395Skan else 3408117395Skan return 1; 3409117395Skan} 3410117395Skan 3411117395Skan/* The function checks equality of the reservation sets. */ 3412117395Skanstatic int 3413132718Skanreserv_sets_eq (reserv_sets_t reservs_1, reserv_sets_t reservs_2) 3414117395Skan{ 3415117395Skan return reserv_sets_cmp (reservs_1, reservs_2) == 0; 3416117395Skan} 3417117395Skan 3418117395Skan/* Set up in the reservation set that unit with UNIT_NUM is used on 3419117395Skan CYCLE_NUM. */ 3420117395Skanstatic void 3421132718Skanset_unit_reserv (reserv_sets_t reservs, int cycle_num, int unit_num) 3422117395Skan{ 3423169689Skan gcc_assert (cycle_num < max_cycles_num); 3424117395Skan SET_BIT (reservs, cycle_num * els_in_cycle_reserv 3425117395Skan * sizeof (set_el_t) * CHAR_BIT + unit_num); 3426117395Skan} 3427117395Skan 3428117395Skan/* Set up in the reservation set RESERVS that unit with UNIT_NUM is 3429117395Skan used on CYCLE_NUM. */ 3430117395Skanstatic int 3431132718Skantest_unit_reserv (reserv_sets_t reservs, int cycle_num, int unit_num) 3432117395Skan{ 3433169689Skan gcc_assert (cycle_num < max_cycles_num); 3434117395Skan return TEST_BIT (reservs, cycle_num * els_in_cycle_reserv 3435117395Skan * sizeof (set_el_t) * CHAR_BIT + unit_num); 3436117395Skan} 3437117395Skan 3438117395Skan/* The function checks that the reservation sets are intersected, 3439117395Skan i.e. there is a unit reservation on a cycle in both reservation 3440117395Skan sets. */ 3441117395Skanstatic int 3442132718Skanreserv_sets_are_intersected (reserv_sets_t operand_1, 3443132718Skan reserv_sets_t operand_2) 3444117395Skan{ 3445117395Skan set_el_t *el_ptr_1; 3446117395Skan set_el_t *el_ptr_2; 3447117395Skan set_el_t *cycle_ptr_1; 3448117395Skan set_el_t *cycle_ptr_2; 3449117395Skan 3450169689Skan gcc_assert (operand_1 && operand_2); 3451117395Skan for (el_ptr_1 = operand_1, el_ptr_2 = operand_2; 3452117395Skan el_ptr_1 < operand_1 + els_in_reservs; 3453117395Skan el_ptr_1++, el_ptr_2++) 3454117395Skan if (*el_ptr_1 & *el_ptr_2) 3455117395Skan return 1; 3456132718Skan reserv_sets_or (temp_reserv, operand_1, operand_2); 3457117395Skan for (cycle_ptr_1 = operand_1, cycle_ptr_2 = operand_2; 3458117395Skan cycle_ptr_1 < operand_1 + els_in_reservs; 3459117395Skan cycle_ptr_1 += els_in_cycle_reserv, cycle_ptr_2 += els_in_cycle_reserv) 3460117395Skan { 3461117395Skan for (el_ptr_1 = cycle_ptr_1, el_ptr_2 = get_excl_set (cycle_ptr_2); 3462117395Skan el_ptr_1 < cycle_ptr_1 + els_in_cycle_reserv; 3463117395Skan el_ptr_1++, el_ptr_2++) 3464117395Skan if (*el_ptr_1 & *el_ptr_2) 3465117395Skan return 1; 3466132718Skan if (!check_presence_pattern_sets (cycle_ptr_1, cycle_ptr_2, FALSE)) 3467117395Skan return 1; 3468132718Skan if (!check_presence_pattern_sets (temp_reserv + (cycle_ptr_2 3469132718Skan - operand_2), 3470132718Skan cycle_ptr_2, TRUE)) 3471132718Skan return 1; 3472132718Skan if (!check_absence_pattern_sets (cycle_ptr_1, cycle_ptr_2, FALSE)) 3473132718Skan return 1; 3474132718Skan if (!check_absence_pattern_sets (temp_reserv + (cycle_ptr_2 - operand_2), 3475132718Skan cycle_ptr_2, TRUE)) 3476132718Skan return 1; 3477117395Skan } 3478117395Skan return 0; 3479117395Skan} 3480117395Skan 3481117395Skan/* The function sets up RESULT bits by bits of OPERAND shifted on one 3482117395Skan cpu cycle. The remaining bits of OPERAND (representing the last 3483132718Skan cycle unit reservations) are not changed. */ 3484117395Skanstatic void 3485132718Skanreserv_sets_shift (reserv_sets_t result, reserv_sets_t operand) 3486117395Skan{ 3487117395Skan int i; 3488117395Skan 3489169689Skan gcc_assert (result && operand && result != operand); 3490117395Skan for (i = els_in_cycle_reserv; i < els_in_reservs; i++) 3491117395Skan result [i - els_in_cycle_reserv] = operand [i]; 3492117395Skan} 3493117395Skan 3494117395Skan/* OR of the reservation sets. */ 3495117395Skanstatic void 3496132718Skanreserv_sets_or (reserv_sets_t result, reserv_sets_t operand_1, 3497132718Skan reserv_sets_t operand_2) 3498117395Skan{ 3499117395Skan set_el_t *el_ptr_1; 3500117395Skan set_el_t *el_ptr_2; 3501117395Skan set_el_t *result_set_el_ptr; 3502117395Skan 3503169689Skan gcc_assert (result && operand_1 && operand_2); 3504117395Skan for (el_ptr_1 = operand_1, el_ptr_2 = operand_2, result_set_el_ptr = result; 3505117395Skan el_ptr_1 < operand_1 + els_in_reservs; 3506117395Skan el_ptr_1++, el_ptr_2++, result_set_el_ptr++) 3507117395Skan *result_set_el_ptr = *el_ptr_1 | *el_ptr_2; 3508117395Skan} 3509117395Skan 3510117395Skan/* AND of the reservation sets. */ 3511117395Skanstatic void 3512132718Skanreserv_sets_and (reserv_sets_t result, reserv_sets_t operand_1, 3513132718Skan reserv_sets_t operand_2) 3514117395Skan{ 3515117395Skan set_el_t *el_ptr_1; 3516117395Skan set_el_t *el_ptr_2; 3517117395Skan set_el_t *result_set_el_ptr; 3518117395Skan 3519169689Skan gcc_assert (result && operand_1 && operand_2); 3520117395Skan for (el_ptr_1 = operand_1, el_ptr_2 = operand_2, result_set_el_ptr = result; 3521117395Skan el_ptr_1 < operand_1 + els_in_reservs; 3522117395Skan el_ptr_1++, el_ptr_2++, result_set_el_ptr++) 3523117395Skan *result_set_el_ptr = *el_ptr_1 & *el_ptr_2; 3524117395Skan} 3525117395Skan 3526117395Skan/* The function outputs string representation of units reservation on 3527117395Skan cycle START_CYCLE in the reservation set. The function uses repeat 3528117395Skan construction if REPETITION_NUM > 1. */ 3529117395Skanstatic void 3530132718Skanoutput_cycle_reservs (FILE *f, reserv_sets_t reservs, int start_cycle, 3531132718Skan int repetition_num) 3532117395Skan{ 3533117395Skan int unit_num; 3534117395Skan int reserved_units_num; 3535117395Skan 3536117395Skan reserved_units_num = 0; 3537117395Skan for (unit_num = 0; unit_num < description->units_num; unit_num++) 3538117395Skan if (TEST_BIT (reservs, start_cycle * els_in_cycle_reserv 3539117395Skan * sizeof (set_el_t) * CHAR_BIT + unit_num)) 3540117395Skan reserved_units_num++; 3541169689Skan gcc_assert (repetition_num > 0); 3542117395Skan if (repetition_num != 1 && reserved_units_num > 1) 3543117395Skan fprintf (f, "("); 3544117395Skan reserved_units_num = 0; 3545117395Skan for (unit_num = 0; 3546117395Skan unit_num < description->units_num; 3547117395Skan unit_num++) 3548117395Skan if (TEST_BIT (reservs, start_cycle * els_in_cycle_reserv 3549117395Skan * sizeof (set_el_t) * CHAR_BIT + unit_num)) 3550117395Skan { 3551117395Skan if (reserved_units_num != 0) 3552117395Skan fprintf (f, "+"); 3553117395Skan reserved_units_num++; 3554117395Skan fprintf (f, "%s", units_array [unit_num]->name); 3555117395Skan } 3556117395Skan if (reserved_units_num == 0) 3557117395Skan fprintf (f, NOTHING_NAME); 3558169689Skan gcc_assert (repetition_num > 0); 3559132718Skan if (repetition_num != 1 && reserved_units_num > 1) 3560117395Skan fprintf (f, ")"); 3561117395Skan if (repetition_num != 1) 3562117395Skan fprintf (f, "*%d", repetition_num); 3563117395Skan} 3564117395Skan 3565117395Skan/* The function outputs string representation of units reservation in 3566117395Skan the reservation set. */ 3567117395Skanstatic void 3568132718Skanoutput_reserv_sets (FILE *f, reserv_sets_t reservs) 3569117395Skan{ 3570117395Skan int start_cycle = 0; 3571117395Skan int cycle; 3572117395Skan int repetition_num; 3573117395Skan 3574117395Skan repetition_num = 0; 3575117395Skan for (cycle = 0; cycle < max_cycles_num; cycle++) 3576117395Skan if (repetition_num == 0) 3577117395Skan { 3578117395Skan repetition_num++; 3579117395Skan start_cycle = cycle; 3580117395Skan } 3581117395Skan else if (memcmp 3582117395Skan ((char *) reservs + start_cycle * els_in_cycle_reserv 3583117395Skan * sizeof (set_el_t), 3584117395Skan (char *) reservs + cycle * els_in_cycle_reserv 3585117395Skan * sizeof (set_el_t), 3586117395Skan els_in_cycle_reserv * sizeof (set_el_t)) == 0) 3587117395Skan repetition_num++; 3588117395Skan else 3589117395Skan { 3590117395Skan if (start_cycle != 0) 3591117395Skan fprintf (f, ", "); 3592117395Skan output_cycle_reservs (f, reservs, start_cycle, repetition_num); 3593117395Skan repetition_num = 1; 3594117395Skan start_cycle = cycle; 3595117395Skan } 3596117395Skan if (start_cycle < max_cycles_num) 3597117395Skan { 3598117395Skan if (start_cycle != 0) 3599117395Skan fprintf (f, ", "); 3600117395Skan output_cycle_reservs (f, reservs, start_cycle, repetition_num); 3601117395Skan } 3602117395Skan} 3603117395Skan 3604117395Skan/* The following function returns free node state for AUTOMATON. It 3605132718Skan may be new allocated node or node freed earlier. The function also 3606117395Skan allocates reservation set if WITH_RESERVS has nonzero value. */ 3607117395Skanstatic state_t 3608132718Skanget_free_state (int with_reservs, automaton_t automaton) 3609117395Skan{ 3610117395Skan state_t result; 3611117395Skan 3612169689Skan gcc_assert (max_cycles_num > 0 && automaton); 3613169689Skan if (first_free_state) 3614117395Skan { 3615169689Skan result = first_free_state; 3616169689Skan first_free_state = result->next_equiv_class_state; 3617169689Skan 3618169689Skan result->next_equiv_class_state = NULL; 3619117395Skan result->automaton = automaton; 3620117395Skan result->first_out_arc = NULL; 3621117395Skan result->it_was_placed_in_stack_for_NDFA_forming = 0; 3622117395Skan result->it_was_placed_in_stack_for_DFA_forming = 0; 3623117395Skan result->component_states = NULL; 3624117395Skan result->longest_path_length = UNDEFINED_LONGEST_PATH_LENGTH; 3625117395Skan } 3626117395Skan else 3627117395Skan { 3628117395Skan#ifndef NDEBUG 3629117395Skan allocated_states_num++; 3630117395Skan#endif 3631117395Skan result = create_node (sizeof (struct state)); 3632117395Skan result->automaton = automaton; 3633117395Skan result->first_out_arc = NULL; 3634117395Skan result->unique_num = curr_unique_state_num; 3635117395Skan result->longest_path_length = UNDEFINED_LONGEST_PATH_LENGTH; 3636117395Skan curr_unique_state_num++; 3637117395Skan } 3638117395Skan if (with_reservs) 3639117395Skan { 3640117395Skan if (result->reservs == NULL) 3641117395Skan result->reservs = alloc_empty_reserv_sets (); 3642117395Skan else 3643117395Skan memset (result->reservs, 0, els_in_reservs * sizeof (set_el_t)); 3644117395Skan } 3645117395Skan return result; 3646117395Skan} 3647117395Skan 3648117395Skan/* The function frees node STATE. */ 3649117395Skanstatic void 3650132718Skanfree_state (state_t state) 3651117395Skan{ 3652117395Skan free_alt_states (state->component_states); 3653169689Skan state->next_equiv_class_state = first_free_state; 3654169689Skan first_free_state = state; 3655117395Skan} 3656117395Skan 3657117395Skan/* Hash value of STATE. If STATE represents deterministic state it is 3658117395Skan simply hash value of the corresponding reservation set. Otherwise 3659117395Skan it is formed from hash values of the component deterministic 3660117395Skan states. One more key is order number of state automaton. */ 3661117395Skanstatic hashval_t 3662132718Skanstate_hash (const void *state) 3663117395Skan{ 3664117395Skan unsigned int hash_value; 3665117395Skan alt_state_t alt_state; 3666117395Skan 3667117395Skan if (((state_t) state)->component_states == NULL) 3668117395Skan hash_value = reserv_sets_hash_value (((state_t) state)->reservs); 3669117395Skan else 3670117395Skan { 3671117395Skan hash_value = 0; 3672117395Skan for (alt_state = ((state_t) state)->component_states; 3673117395Skan alt_state != NULL; 3674117395Skan alt_state = alt_state->next_sorted_alt_state) 3675117395Skan hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT) 3676117395Skan | (hash_value << CHAR_BIT)) 3677117395Skan + alt_state->state->unique_num); 3678117395Skan } 3679117395Skan hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT) 3680117395Skan | (hash_value << CHAR_BIT)) 3681117395Skan + ((state_t) state)->automaton->automaton_order_num); 3682117395Skan return hash_value; 3683117395Skan} 3684117395Skan 3685117395Skan/* Return nonzero value if the states are the same. */ 3686117395Skanstatic int 3687132718Skanstate_eq_p (const void *state_1, const void *state_2) 3688117395Skan{ 3689117395Skan alt_state_t alt_state_1; 3690117395Skan alt_state_t alt_state_2; 3691117395Skan 3692117395Skan if (((state_t) state_1)->automaton != ((state_t) state_2)->automaton) 3693117395Skan return 0; 3694117395Skan else if (((state_t) state_1)->component_states == NULL 3695117395Skan && ((state_t) state_2)->component_states == NULL) 3696117395Skan return reserv_sets_eq (((state_t) state_1)->reservs, 3697117395Skan ((state_t) state_2)->reservs); 3698117395Skan else if (((state_t) state_1)->component_states != NULL 3699117395Skan && ((state_t) state_2)->component_states != NULL) 3700117395Skan { 3701117395Skan for (alt_state_1 = ((state_t) state_1)->component_states, 3702117395Skan alt_state_2 = ((state_t) state_2)->component_states; 3703117395Skan alt_state_1 != NULL && alt_state_2 != NULL; 3704117395Skan alt_state_1 = alt_state_1->next_sorted_alt_state, 3705117395Skan alt_state_2 = alt_state_2->next_sorted_alt_state) 3706117395Skan /* All state in the list must be already in the hash table. 3707117395Skan Also the lists must be sorted. */ 3708117395Skan if (alt_state_1->state != alt_state_2->state) 3709117395Skan return 0; 3710117395Skan return alt_state_1 == alt_state_2; 3711117395Skan } 3712117395Skan else 3713117395Skan return 0; 3714117395Skan} 3715117395Skan 3716117395Skan/* Insert STATE into the state table. */ 3717117395Skanstatic state_t 3718132718Skaninsert_state (state_t state) 3719117395Skan{ 3720117395Skan void **entry_ptr; 3721117395Skan 3722117395Skan entry_ptr = htab_find_slot (state_table, (void *) state, 1); 3723117395Skan if (*entry_ptr == NULL) 3724117395Skan *entry_ptr = (void *) state; 3725117395Skan return (state_t) *entry_ptr; 3726117395Skan} 3727117395Skan 3728117395Skan/* Add reservation of unit with UNIT_NUM on cycle CYCLE_NUM to 3729117395Skan deterministic STATE. */ 3730117395Skanstatic void 3731132718Skanset_state_reserv (state_t state, int cycle_num, int unit_num) 3732117395Skan{ 3733117395Skan set_unit_reserv (state->reservs, cycle_num, unit_num); 3734117395Skan} 3735117395Skan 3736117395Skan/* Return nonzero value if the deterministic states contains a 3737117395Skan reservation of the same cpu unit on the same cpu cycle. */ 3738117395Skanstatic int 3739132718Skanintersected_state_reservs_p (state_t state1, state_t state2) 3740117395Skan{ 3741169689Skan gcc_assert (state1->automaton == state2->automaton); 3742117395Skan return reserv_sets_are_intersected (state1->reservs, state2->reservs); 3743117395Skan} 3744117395Skan 3745117395Skan/* Return deterministic state (inserted into the table) which 3746132718Skan representing the automaton state which is union of reservations of 3747132718Skan the deterministic states masked by RESERVS. */ 3748117395Skanstatic state_t 3749132718Skanstates_union (state_t state1, state_t state2, reserv_sets_t reservs) 3750117395Skan{ 3751117395Skan state_t result; 3752117395Skan state_t state_in_table; 3753117395Skan 3754169689Skan gcc_assert (state1->automaton == state2->automaton); 3755117395Skan result = get_free_state (1, state1->automaton); 3756117395Skan reserv_sets_or (result->reservs, state1->reservs, state2->reservs); 3757132718Skan reserv_sets_and (result->reservs, result->reservs, reservs); 3758117395Skan state_in_table = insert_state (result); 3759117395Skan if (result != state_in_table) 3760117395Skan { 3761117395Skan free_state (result); 3762117395Skan result = state_in_table; 3763117395Skan } 3764117395Skan return result; 3765117395Skan} 3766117395Skan 3767117395Skan/* Return deterministic state (inserted into the table) which 3768117395Skan represent the automaton state is obtained from deterministic STATE 3769132718Skan by advancing cpu cycle and masking by RESERVS. */ 3770117395Skanstatic state_t 3771132718Skanstate_shift (state_t state, reserv_sets_t reservs) 3772117395Skan{ 3773117395Skan state_t result; 3774117395Skan state_t state_in_table; 3775117395Skan 3776117395Skan result = get_free_state (1, state->automaton); 3777117395Skan reserv_sets_shift (result->reservs, state->reservs); 3778132718Skan reserv_sets_and (result->reservs, result->reservs, reservs); 3779117395Skan state_in_table = insert_state (result); 3780117395Skan if (result != state_in_table) 3781117395Skan { 3782117395Skan free_state (result); 3783117395Skan result = state_in_table; 3784117395Skan } 3785117395Skan return result; 3786117395Skan} 3787117395Skan 3788117395Skan/* Initialization of the abstract data. */ 3789117395Skanstatic void 3790132718Skaninitiate_states (void) 3791117395Skan{ 3792117395Skan decl_t decl; 3793117395Skan int i; 3794117395Skan 3795169689Skan if (description->units_num) 3796169689Skan units_array = XNEWVEC (unit_decl_t, description->units_num); 3797169689Skan else 3798169689Skan units_array = 0; 3799169689Skan 3800117395Skan for (i = 0; i < description->decls_num; i++) 3801117395Skan { 3802117395Skan decl = description->decls [i]; 3803117395Skan if (decl->mode == dm_unit) 3804117395Skan units_array [DECL_UNIT (decl)->unit_num] = DECL_UNIT (decl); 3805117395Skan } 3806117395Skan max_cycles_num = description->max_insn_reserv_cycles; 3807117395Skan els_in_cycle_reserv 3808117395Skan = ((description->units_num + sizeof (set_el_t) * CHAR_BIT - 1) 3809117395Skan / (sizeof (set_el_t) * CHAR_BIT)); 3810117395Skan els_in_reservs = els_in_cycle_reserv * max_cycles_num; 3811117395Skan curr_unique_state_num = 0; 3812117395Skan initiate_alt_states (); 3813117395Skan state_table = htab_create (1500, state_hash, state_eq_p, (htab_del) 0); 3814132718Skan temp_reserv = alloc_empty_reserv_sets (); 3815117395Skan} 3816117395Skan 3817132718Skan/* Finishing work with the abstract data. */ 3818117395Skanstatic void 3819132718Skanfinish_states (void) 3820117395Skan{ 3821169689Skan free (units_array); 3822169689Skan units_array = 0; 3823117395Skan htab_delete (state_table); 3824169689Skan first_free_state = NULL; 3825117395Skan finish_alt_states (); 3826117395Skan} 3827117395Skan 3828117395Skan 3829117395Skan 3830117395Skan/* Abstract data `arcs'. */ 3831117395Skan 3832117395Skan/* List of free arcs. */ 3833117395Skanstatic arc_t first_free_arc; 3834117395Skan 3835117395Skan#ifndef NDEBUG 3836117395Skan/* The following variables is maximal number of allocated nodes 3837117395Skan `arc'. */ 3838117395Skanstatic int allocated_arcs_num = 0; 3839117395Skan#endif 3840117395Skan 3841117395Skan/* The function frees node ARC. */ 3842117395Skanstatic void 3843132718Skanfree_arc (arc_t arc) 3844117395Skan{ 3845117395Skan arc->next_out_arc = first_free_arc; 3846117395Skan first_free_arc = arc; 3847117395Skan} 3848117395Skan 3849117395Skan/* The function removes and frees ARC staring from FROM_STATE. */ 3850117395Skanstatic void 3851132718Skanremove_arc (state_t from_state, arc_t arc) 3852117395Skan{ 3853117395Skan arc_t prev_arc; 3854117395Skan arc_t curr_arc; 3855117395Skan 3856169689Skan gcc_assert (arc); 3857117395Skan for (prev_arc = NULL, curr_arc = from_state->first_out_arc; 3858117395Skan curr_arc != NULL; 3859117395Skan prev_arc = curr_arc, curr_arc = curr_arc->next_out_arc) 3860117395Skan if (curr_arc == arc) 3861117395Skan break; 3862169689Skan gcc_assert (curr_arc); 3863117395Skan if (prev_arc == NULL) 3864117395Skan from_state->first_out_arc = arc->next_out_arc; 3865117395Skan else 3866117395Skan prev_arc->next_out_arc = arc->next_out_arc; 3867169689Skan from_state->num_out_arcs--; 3868117395Skan free_arc (arc); 3869117395Skan} 3870117395Skan 3871117395Skan/* The functions returns arc with given characteristics (or NULL if 3872117395Skan the arc does not exist). */ 3873117395Skanstatic arc_t 3874132718Skanfind_arc (state_t from_state, state_t to_state, ainsn_t insn) 3875117395Skan{ 3876117395Skan arc_t arc; 3877117395Skan 3878117395Skan for (arc = first_out_arc (from_state); arc != NULL; arc = next_out_arc (arc)) 3879117395Skan if (arc->to_state == to_state && arc->insn == insn) 3880117395Skan return arc; 3881117395Skan return NULL; 3882117395Skan} 3883117395Skan 3884169689Skan/* The function adds arc from FROM_STATE to TO_STATE marked by AINSN. 3885169689Skan The function returns added arc (or already existing arc). */ 3886117395Skanstatic arc_t 3887169689Skanadd_arc (state_t from_state, state_t to_state, ainsn_t ainsn) 3888117395Skan{ 3889117395Skan arc_t new_arc; 3890117395Skan 3891117395Skan new_arc = find_arc (from_state, to_state, ainsn); 3892117395Skan if (new_arc != NULL) 3893117395Skan return new_arc; 3894117395Skan if (first_free_arc == NULL) 3895117395Skan { 3896117395Skan#ifndef NDEBUG 3897117395Skan allocated_arcs_num++; 3898117395Skan#endif 3899117395Skan new_arc = create_node (sizeof (struct arc)); 3900117395Skan new_arc->to_state = NULL; 3901117395Skan new_arc->insn = NULL; 3902117395Skan new_arc->next_out_arc = NULL; 3903117395Skan } 3904117395Skan else 3905117395Skan { 3906117395Skan new_arc = first_free_arc; 3907117395Skan first_free_arc = first_free_arc->next_out_arc; 3908117395Skan } 3909117395Skan new_arc->to_state = to_state; 3910117395Skan new_arc->insn = ainsn; 3911117395Skan ainsn->arc_exists_p = 1; 3912117395Skan new_arc->next_out_arc = from_state->first_out_arc; 3913117395Skan from_state->first_out_arc = new_arc; 3914169689Skan from_state->num_out_arcs++; 3915117395Skan new_arc->next_arc_marked_by_insn = NULL; 3916117395Skan return new_arc; 3917117395Skan} 3918117395Skan 3919117395Skan/* The function returns the first arc starting from STATE. */ 3920117395Skanstatic arc_t 3921132718Skanfirst_out_arc (state_t state) 3922117395Skan{ 3923117395Skan return state->first_out_arc; 3924117395Skan} 3925117395Skan 3926117395Skan/* The function returns next out arc after ARC. */ 3927117395Skanstatic arc_t 3928132718Skannext_out_arc (arc_t arc) 3929117395Skan{ 3930117395Skan return arc->next_out_arc; 3931117395Skan} 3932117395Skan 3933117395Skan/* Initialization of the abstract data. */ 3934117395Skanstatic void 3935132718Skaninitiate_arcs (void) 3936117395Skan{ 3937117395Skan first_free_arc = NULL; 3938117395Skan} 3939117395Skan 3940117395Skan/* Finishing work with the abstract data. */ 3941117395Skanstatic void 3942132718Skanfinish_arcs (void) 3943117395Skan{ 3944117395Skan} 3945117395Skan 3946117395Skan 3947117395Skan 3948117395Skan/* Abstract data `automata lists'. */ 3949117395Skan 3950117395Skan/* List of free states. */ 3951117395Skanstatic automata_list_el_t first_free_automata_list_el; 3952117395Skan 3953117395Skan/* The list being formed. */ 3954117395Skanstatic automata_list_el_t current_automata_list; 3955117395Skan 3956117395Skan/* Hash table of automata lists. */ 3957117395Skanstatic htab_t automata_list_table; 3958117395Skan 3959117395Skan/* The following function returns free automata list el. It may be 3960117395Skan new allocated node or node freed earlier. */ 3961132718Skanstatic automata_list_el_t 3962132718Skanget_free_automata_list_el (void) 3963117395Skan{ 3964117395Skan automata_list_el_t result; 3965117395Skan 3966117395Skan if (first_free_automata_list_el != NULL) 3967117395Skan { 3968117395Skan result = first_free_automata_list_el; 3969117395Skan first_free_automata_list_el 3970117395Skan = first_free_automata_list_el->next_automata_list_el; 3971117395Skan } 3972117395Skan else 3973117395Skan result = create_node (sizeof (struct automata_list_el)); 3974117395Skan result->automaton = NULL; 3975117395Skan result->next_automata_list_el = NULL; 3976117395Skan return result; 3977117395Skan} 3978117395Skan 3979117395Skan/* The function frees node AUTOMATA_LIST_EL. */ 3980117395Skanstatic void 3981132718Skanfree_automata_list_el (automata_list_el_t automata_list_el) 3982117395Skan{ 3983117395Skan if (automata_list_el == NULL) 3984117395Skan return; 3985117395Skan automata_list_el->next_automata_list_el = first_free_automata_list_el; 3986117395Skan first_free_automata_list_el = automata_list_el; 3987117395Skan} 3988117395Skan 3989117395Skan/* The function frees list AUTOMATA_LIST. */ 3990117395Skanstatic void 3991132718Skanfree_automata_list (automata_list_el_t automata_list) 3992117395Skan{ 3993117395Skan automata_list_el_t curr_automata_list_el; 3994117395Skan automata_list_el_t next_automata_list_el; 3995117395Skan 3996117395Skan for (curr_automata_list_el = automata_list; 3997117395Skan curr_automata_list_el != NULL; 3998117395Skan curr_automata_list_el = next_automata_list_el) 3999117395Skan { 4000117395Skan next_automata_list_el = curr_automata_list_el->next_automata_list_el; 4001117395Skan free_automata_list_el (curr_automata_list_el); 4002117395Skan } 4003117395Skan} 4004117395Skan 4005117395Skan/* Hash value of AUTOMATA_LIST. */ 4006117395Skanstatic hashval_t 4007132718Skanautomata_list_hash (const void *automata_list) 4008117395Skan{ 4009117395Skan unsigned int hash_value; 4010117395Skan automata_list_el_t curr_automata_list_el; 4011117395Skan 4012117395Skan hash_value = 0; 4013117395Skan for (curr_automata_list_el = (automata_list_el_t) automata_list; 4014117395Skan curr_automata_list_el != NULL; 4015117395Skan curr_automata_list_el = curr_automata_list_el->next_automata_list_el) 4016117395Skan hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT) 4017117395Skan | (hash_value << CHAR_BIT)) 4018117395Skan + curr_automata_list_el->automaton->automaton_order_num); 4019117395Skan return hash_value; 4020117395Skan} 4021117395Skan 4022117395Skan/* Return nonzero value if the automata_lists are the same. */ 4023117395Skanstatic int 4024132718Skanautomata_list_eq_p (const void *automata_list_1, const void *automata_list_2) 4025117395Skan{ 4026117395Skan automata_list_el_t automata_list_el_1; 4027117395Skan automata_list_el_t automata_list_el_2; 4028117395Skan 4029117395Skan for (automata_list_el_1 = (automata_list_el_t) automata_list_1, 4030117395Skan automata_list_el_2 = (automata_list_el_t) automata_list_2; 4031117395Skan automata_list_el_1 != NULL && automata_list_el_2 != NULL; 4032117395Skan automata_list_el_1 = automata_list_el_1->next_automata_list_el, 4033117395Skan automata_list_el_2 = automata_list_el_2->next_automata_list_el) 4034117395Skan if (automata_list_el_1->automaton != automata_list_el_2->automaton) 4035117395Skan return 0; 4036117395Skan return automata_list_el_1 == automata_list_el_2; 4037117395Skan} 4038117395Skan 4039117395Skan/* Initialization of the abstract data. */ 4040117395Skanstatic void 4041132718Skaninitiate_automata_lists (void) 4042117395Skan{ 4043117395Skan first_free_automata_list_el = NULL; 4044117395Skan automata_list_table = htab_create (1500, automata_list_hash, 4045117395Skan automata_list_eq_p, (htab_del) 0); 4046117395Skan} 4047117395Skan 4048117395Skan/* The following function starts new automata list and makes it the 4049117395Skan current one. */ 4050117395Skanstatic void 4051132718Skanautomata_list_start (void) 4052117395Skan{ 4053117395Skan current_automata_list = NULL; 4054117395Skan} 4055117395Skan 4056117395Skan/* The following function adds AUTOMATON to the current list. */ 4057117395Skanstatic void 4058132718Skanautomata_list_add (automaton_t automaton) 4059117395Skan{ 4060117395Skan automata_list_el_t el; 4061117395Skan 4062117395Skan el = get_free_automata_list_el (); 4063117395Skan el->automaton = automaton; 4064117395Skan el->next_automata_list_el = current_automata_list; 4065117395Skan current_automata_list = el; 4066117395Skan} 4067117395Skan 4068117395Skan/* The following function finishes forming the current list, inserts 4069117395Skan it into the table and returns it. */ 4070117395Skanstatic automata_list_el_t 4071132718Skanautomata_list_finish (void) 4072117395Skan{ 4073117395Skan void **entry_ptr; 4074117395Skan 4075117395Skan if (current_automata_list == NULL) 4076117395Skan return NULL; 4077117395Skan entry_ptr = htab_find_slot (automata_list_table, 4078117395Skan (void *) current_automata_list, 1); 4079117395Skan if (*entry_ptr == NULL) 4080117395Skan *entry_ptr = (void *) current_automata_list; 4081117395Skan else 4082117395Skan free_automata_list (current_automata_list); 4083117395Skan current_automata_list = NULL; 4084117395Skan return (automata_list_el_t) *entry_ptr; 4085117395Skan} 4086117395Skan 4087117395Skan/* Finishing work with the abstract data. */ 4088117395Skanstatic void 4089132718Skanfinish_automata_lists (void) 4090117395Skan{ 4091117395Skan htab_delete (automata_list_table); 4092117395Skan} 4093117395Skan 4094117395Skan 4095117395Skan 4096117395Skan/* The page contains abstract data for work with exclusion sets (see 4097117395Skan exclusion_set in file rtl.def). */ 4098117395Skan 4099117395Skan/* The following variable refers to an exclusion set returned by 4100117395Skan get_excl_set. This is bit string of length equal to cpu units 4101117395Skan number. If exclusion set for given unit contains 1 for a unit, 4102117395Skan then simultaneous reservation of the units is prohibited. */ 4103117395Skanstatic reserv_sets_t excl_set; 4104117395Skan 4105117395Skan/* The array contains exclusion sets for each unit. */ 4106117395Skanstatic reserv_sets_t *unit_excl_set_table; 4107117395Skan 4108117395Skan/* The following function forms the array containing exclusion sets 4109117395Skan for each unit. */ 4110117395Skanstatic void 4111132718Skaninitiate_excl_sets (void) 4112117395Skan{ 4113117395Skan decl_t decl; 4114117395Skan reserv_sets_t unit_excl_set; 4115117395Skan unit_set_el_t el; 4116117395Skan int i; 4117117395Skan 4118117395Skan obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t)); 4119117395Skan excl_set = (reserv_sets_t) obstack_base (&irp); 4120222097Sbenl (void) obstack_finish (&irp); 4121117395Skan obstack_blank (&irp, description->units_num * sizeof (reserv_sets_t)); 4122117395Skan unit_excl_set_table = (reserv_sets_t *) obstack_base (&irp); 4123222097Sbenl (void) obstack_finish (&irp); 4124117395Skan /* Evaluate unit exclusion sets. */ 4125117395Skan for (i = 0; i < description->decls_num; i++) 4126117395Skan { 4127117395Skan decl = description->decls [i]; 4128117395Skan if (decl->mode == dm_unit) 4129117395Skan { 4130117395Skan obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t)); 4131117395Skan unit_excl_set = (reserv_sets_t) obstack_base (&irp); 4132222097Sbenl (void) obstack_finish (&irp); 4133117395Skan memset (unit_excl_set, 0, els_in_cycle_reserv * sizeof (set_el_t)); 4134117395Skan for (el = DECL_UNIT (decl)->excl_list; 4135117395Skan el != NULL; 4136117395Skan el = el->next_unit_set_el) 4137132718Skan { 4138132718Skan SET_BIT (unit_excl_set, el->unit_decl->unit_num); 4139132718Skan el->unit_decl->in_set_p = TRUE; 4140132718Skan } 4141117395Skan unit_excl_set_table [DECL_UNIT (decl)->unit_num] = unit_excl_set; 4142117395Skan } 4143117395Skan } 4144117395Skan} 4145117395Skan 4146117395Skan/* The function sets up and return EXCL_SET which is union of 4147117395Skan exclusion sets for each unit in IN_SET. */ 4148117395Skanstatic reserv_sets_t 4149132718Skanget_excl_set (reserv_sets_t in_set) 4150117395Skan{ 4151117395Skan int excl_char_num; 4152117395Skan int chars_num; 4153117395Skan int i; 4154117395Skan int start_unit_num; 4155117395Skan int unit_num; 4156117395Skan 4157117395Skan chars_num = els_in_cycle_reserv * sizeof (set_el_t); 4158117395Skan memset (excl_set, 0, chars_num); 4159117395Skan for (excl_char_num = 0; excl_char_num < chars_num; excl_char_num++) 4160117395Skan if (((unsigned char *) in_set) [excl_char_num]) 4161117395Skan for (i = CHAR_BIT - 1; i >= 0; i--) 4162117395Skan if ((((unsigned char *) in_set) [excl_char_num] >> i) & 1) 4163117395Skan { 4164117395Skan start_unit_num = excl_char_num * CHAR_BIT + i; 4165117395Skan if (start_unit_num >= description->units_num) 4166117395Skan return excl_set; 4167117395Skan for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++) 4168117395Skan { 4169117395Skan excl_set [unit_num] 4170117395Skan |= unit_excl_set_table [start_unit_num] [unit_num]; 4171117395Skan } 4172117395Skan } 4173117395Skan return excl_set; 4174117395Skan} 4175117395Skan 4176117395Skan 4177117395Skan 4178132718Skan/* The page contains abstract data for work with presence/absence 4179132718Skan pattern sets (see presence_set/absence_set in file rtl.def). */ 4180117395Skan 4181132718Skan/* The following arrays contain correspondingly presence, final 4182132718Skan presence, absence, and final absence patterns for each unit. */ 4183132718Skanstatic pattern_reserv_t *unit_presence_set_table; 4184132718Skanstatic pattern_reserv_t *unit_final_presence_set_table; 4185132718Skanstatic pattern_reserv_t *unit_absence_set_table; 4186132718Skanstatic pattern_reserv_t *unit_final_absence_set_table; 4187117395Skan 4188132718Skan/* The following function forms list of reservation sets for given 4189132718Skan PATTERN_LIST. */ 4190132718Skanstatic pattern_reserv_t 4191132718Skanform_reserv_sets_list (pattern_set_el_t pattern_list) 4192132718Skan{ 4193132718Skan pattern_set_el_t el; 4194132718Skan pattern_reserv_t first, curr, prev; 4195132718Skan int i; 4196117395Skan 4197132718Skan prev = first = NULL; 4198132718Skan for (el = pattern_list; el != NULL; el = el->next_pattern_set_el) 4199132718Skan { 4200132718Skan curr = create_node (sizeof (struct pattern_reserv)); 4201132718Skan curr->reserv = alloc_empty_reserv_sets (); 4202132718Skan curr->next_pattern_reserv = NULL; 4203132718Skan for (i = 0; i < el->units_num; i++) 4204132718Skan { 4205132718Skan SET_BIT (curr->reserv, el->unit_decls [i]->unit_num); 4206132718Skan el->unit_decls [i]->in_set_p = TRUE; 4207132718Skan } 4208132718Skan if (prev != NULL) 4209132718Skan prev->next_pattern_reserv = curr; 4210132718Skan else 4211132718Skan first = curr; 4212132718Skan prev = curr; 4213132718Skan } 4214132718Skan return first; 4215132718Skan} 4216132718Skan 4217132718Skan /* The following function forms the array containing presence and 4218132718Skan absence pattern sets for each unit. */ 4219117395Skanstatic void 4220132718Skaninitiate_presence_absence_pattern_sets (void) 4221117395Skan{ 4222117395Skan decl_t decl; 4223117395Skan int i; 4224117395Skan 4225132718Skan obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t)); 4226132718Skan unit_presence_set_table = (pattern_reserv_t *) obstack_base (&irp); 4227222097Sbenl (void) obstack_finish (&irp); 4228132718Skan obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t)); 4229132718Skan unit_final_presence_set_table = (pattern_reserv_t *) obstack_base (&irp); 4230222097Sbenl (void) obstack_finish (&irp); 4231132718Skan obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t)); 4232132718Skan unit_absence_set_table = (pattern_reserv_t *) obstack_base (&irp); 4233222097Sbenl (void) obstack_finish (&irp); 4234132718Skan obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t)); 4235132718Skan unit_final_absence_set_table = (pattern_reserv_t *) obstack_base (&irp); 4236222097Sbenl (void) obstack_finish (&irp); 4237117395Skan /* Evaluate unit presence/absence sets. */ 4238117395Skan for (i = 0; i < description->decls_num; i++) 4239117395Skan { 4240117395Skan decl = description->decls [i]; 4241117395Skan if (decl->mode == dm_unit) 4242117395Skan { 4243132718Skan unit_presence_set_table [DECL_UNIT (decl)->unit_num] 4244132718Skan = form_reserv_sets_list (DECL_UNIT (decl)->presence_list); 4245132718Skan unit_final_presence_set_table [DECL_UNIT (decl)->unit_num] 4246132718Skan = form_reserv_sets_list (DECL_UNIT (decl)->final_presence_list); 4247132718Skan unit_absence_set_table [DECL_UNIT (decl)->unit_num] 4248132718Skan = form_reserv_sets_list (DECL_UNIT (decl)->absence_list); 4249132718Skan unit_final_absence_set_table [DECL_UNIT (decl)->unit_num] 4250132718Skan = form_reserv_sets_list (DECL_UNIT (decl)->final_absence_list); 4251117395Skan } 4252117395Skan } 4253117395Skan} 4254117395Skan 4255132718Skan/* The function checks that CHECKED_SET satisfies all presence pattern 4256132718Skan sets for units in ORIGIONAL_SET. The function returns TRUE if it 4257132718Skan is ok. */ 4258132718Skanstatic int 4259132718Skancheck_presence_pattern_sets (reserv_sets_t checked_set, 4260132718Skan reserv_sets_t origional_set, 4261132718Skan int final_p) 4262117395Skan{ 4263117395Skan int char_num; 4264117395Skan int chars_num; 4265117395Skan int i; 4266117395Skan int start_unit_num; 4267117395Skan int unit_num; 4268132718Skan int presence_p; 4269132718Skan pattern_reserv_t pat_reserv; 4270117395Skan 4271117395Skan chars_num = els_in_cycle_reserv * sizeof (set_el_t); 4272117395Skan for (char_num = 0; char_num < chars_num; char_num++) 4273132718Skan if (((unsigned char *) origional_set) [char_num]) 4274117395Skan for (i = CHAR_BIT - 1; i >= 0; i--) 4275132718Skan if ((((unsigned char *) origional_set) [char_num] >> i) & 1) 4276117395Skan { 4277117395Skan start_unit_num = char_num * CHAR_BIT + i; 4278117395Skan if (start_unit_num >= description->units_num) 4279132718Skan break; 4280132718Skan if ((final_p 4281132718Skan && unit_final_presence_set_table [start_unit_num] == NULL) 4282132718Skan || (!final_p 4283132718Skan && unit_presence_set_table [start_unit_num] == NULL)) 4284132718Skan continue; 4285132718Skan presence_p = FALSE; 4286132718Skan for (pat_reserv = (final_p 4287132718Skan ? unit_final_presence_set_table [start_unit_num] 4288132718Skan : unit_presence_set_table [start_unit_num]); 4289132718Skan pat_reserv != NULL; 4290132718Skan pat_reserv = pat_reserv->next_pattern_reserv) 4291132718Skan { 4292132718Skan for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++) 4293132718Skan if ((checked_set [unit_num] & pat_reserv->reserv [unit_num]) 4294132718Skan != pat_reserv->reserv [unit_num]) 4295132718Skan break; 4296132718Skan presence_p = presence_p || unit_num >= els_in_cycle_reserv; 4297132718Skan } 4298132718Skan if (!presence_p) 4299132718Skan return FALSE; 4300117395Skan } 4301132718Skan return TRUE; 4302117395Skan} 4303117395Skan 4304132718Skan/* The function checks that CHECKED_SET satisfies all absence pattern 4305132718Skan sets for units in ORIGIONAL_SET. The function returns TRUE if it 4306132718Skan is ok. */ 4307132718Skanstatic int 4308132718Skancheck_absence_pattern_sets (reserv_sets_t checked_set, 4309132718Skan reserv_sets_t origional_set, 4310132718Skan int final_p) 4311132718Skan{ 4312132718Skan int char_num; 4313132718Skan int chars_num; 4314132718Skan int i; 4315132718Skan int start_unit_num; 4316132718Skan int unit_num; 4317132718Skan pattern_reserv_t pat_reserv; 4318132718Skan 4319132718Skan chars_num = els_in_cycle_reserv * sizeof (set_el_t); 4320132718Skan for (char_num = 0; char_num < chars_num; char_num++) 4321132718Skan if (((unsigned char *) origional_set) [char_num]) 4322132718Skan for (i = CHAR_BIT - 1; i >= 0; i--) 4323132718Skan if ((((unsigned char *) origional_set) [char_num] >> i) & 1) 4324132718Skan { 4325132718Skan start_unit_num = char_num * CHAR_BIT + i; 4326132718Skan if (start_unit_num >= description->units_num) 4327132718Skan break; 4328132718Skan for (pat_reserv = (final_p 4329132718Skan ? unit_final_absence_set_table [start_unit_num] 4330132718Skan : unit_absence_set_table [start_unit_num]); 4331132718Skan pat_reserv != NULL; 4332132718Skan pat_reserv = pat_reserv->next_pattern_reserv) 4333132718Skan { 4334132718Skan for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++) 4335132718Skan if ((checked_set [unit_num] & pat_reserv->reserv [unit_num]) 4336132718Skan != pat_reserv->reserv [unit_num] 4337132718Skan && pat_reserv->reserv [unit_num]) 4338132718Skan break; 4339132718Skan if (unit_num >= els_in_cycle_reserv) 4340132718Skan return FALSE; 4341132718Skan } 4342132718Skan } 4343132718Skan return TRUE; 4344132718Skan} 4345132718Skan 4346117395Skan 4347117395Skan 4348117395Skan/* This page contains code for transformation of original reservations 4349117395Skan described in .md file. The main goal of transformations is 4350117395Skan simplifying reservation and lifting up all `|' on the top of IR 4351117395Skan reservation representation. */ 4352117395Skan 4353117395Skan 4354117395Skan/* The following function makes copy of IR representation of 4355117395Skan reservation. The function also substitutes all reservations 4356117395Skan defined by define_reservation by corresponding value during making 4357117395Skan the copy. */ 4358117395Skanstatic regexp_t 4359132718Skancopy_insn_regexp (regexp_t regexp) 4360117395Skan{ 4361117395Skan regexp_t result; 4362117395Skan int i; 4363117395Skan 4364169689Skan switch (regexp->mode) 4365117395Skan { 4366169689Skan case rm_reserv: 4367169689Skan result = copy_insn_regexp (REGEXP_RESERV (regexp)->reserv_decl->regexp); 4368169689Skan break; 4369169689Skan 4370169689Skan case rm_unit: 4371117395Skan result = copy_node (regexp, sizeof (struct regexp)); 4372169689Skan break; 4373169689Skan 4374169689Skan case rm_repeat: 4375169689Skan result = copy_node (regexp, sizeof (struct regexp)); 4376117395Skan REGEXP_REPEAT (result)->regexp 4377117395Skan = copy_insn_regexp (REGEXP_REPEAT (regexp)->regexp); 4378169689Skan break; 4379169689Skan 4380169689Skan case rm_sequence: 4381117395Skan result = copy_node (regexp, 4382117395Skan sizeof (struct regexp) + sizeof (regexp_t) 4383117395Skan * (REGEXP_SEQUENCE (regexp)->regexps_num - 1)); 4384117395Skan for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++) 4385117395Skan REGEXP_SEQUENCE (result)->regexps [i] 4386117395Skan = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]); 4387169689Skan break; 4388169689Skan 4389169689Skan case rm_allof: 4390117395Skan result = copy_node (regexp, 4391117395Skan sizeof (struct regexp) + sizeof (regexp_t) 4392117395Skan * (REGEXP_ALLOF (regexp)->regexps_num - 1)); 4393117395Skan for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++) 4394117395Skan REGEXP_ALLOF (result)->regexps [i] 4395117395Skan = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]); 4396169689Skan break; 4397169689Skan 4398169689Skan case rm_oneof: 4399117395Skan result = copy_node (regexp, 4400117395Skan sizeof (struct regexp) + sizeof (regexp_t) 4401117395Skan * (REGEXP_ONEOF (regexp)->regexps_num - 1)); 4402117395Skan for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++) 4403117395Skan REGEXP_ONEOF (result)->regexps [i] 4404117395Skan = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]); 4405169689Skan break; 4406169689Skan 4407169689Skan case rm_nothing: 4408117395Skan result = copy_node (regexp, sizeof (struct regexp)); 4409169689Skan break; 4410169689Skan 4411169689Skan default: 4412169689Skan gcc_unreachable (); 4413117395Skan } 4414117395Skan return result; 4415117395Skan} 4416117395Skan 4417117395Skan/* The following variable is set up 1 if a transformation has been 4418117395Skan applied. */ 4419117395Skanstatic int regexp_transformed_p; 4420117395Skan 4421117395Skan/* The function makes transformation 4422117395Skan A*N -> A, A, ... */ 4423117395Skanstatic regexp_t 4424132718Skantransform_1 (regexp_t regexp) 4425117395Skan{ 4426117395Skan int i; 4427117395Skan int repeat_num; 4428117395Skan regexp_t operand; 4429117395Skan pos_t pos; 4430117395Skan 4431117395Skan if (regexp->mode == rm_repeat) 4432117395Skan { 4433117395Skan repeat_num = REGEXP_REPEAT (regexp)->repeat_num; 4434169689Skan gcc_assert (repeat_num > 1); 4435117395Skan operand = REGEXP_REPEAT (regexp)->regexp; 4436117395Skan pos = regexp->mode; 4437117395Skan regexp = create_node (sizeof (struct regexp) + sizeof (regexp_t) 4438117395Skan * (repeat_num - 1)); 4439117395Skan regexp->mode = rm_sequence; 4440117395Skan regexp->pos = pos; 4441117395Skan REGEXP_SEQUENCE (regexp)->regexps_num = repeat_num; 4442117395Skan for (i = 0; i < repeat_num; i++) 4443117395Skan REGEXP_SEQUENCE (regexp)->regexps [i] = copy_insn_regexp (operand); 4444117395Skan regexp_transformed_p = 1; 4445117395Skan } 4446117395Skan return regexp; 4447117395Skan} 4448117395Skan 4449117395Skan/* The function makes transformations 4450117395Skan ...,(A,B,...),C,... -> ...,A,B,...,C,... 4451117395Skan ...+(A+B+...)+C+... -> ...+A+B+...+C+... 4452117395Skan ...|(A|B|...)|C|... -> ...|A|B|...|C|... */ 4453117395Skanstatic regexp_t 4454132718Skantransform_2 (regexp_t regexp) 4455117395Skan{ 4456117395Skan if (regexp->mode == rm_sequence) 4457117395Skan { 4458117395Skan regexp_t sequence = NULL; 4459117395Skan regexp_t result; 4460117395Skan int sequence_index = 0; 4461117395Skan int i, j; 4462117395Skan 4463117395Skan for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++) 4464117395Skan if (REGEXP_SEQUENCE (regexp)->regexps [i]->mode == rm_sequence) 4465117395Skan { 4466117395Skan sequence_index = i; 4467117395Skan sequence = REGEXP_SEQUENCE (regexp)->regexps [i]; 4468117395Skan break; 4469117395Skan } 4470117395Skan if (i < REGEXP_SEQUENCE (regexp)->regexps_num) 4471117395Skan { 4472169689Skan gcc_assert (REGEXP_SEQUENCE (sequence)->regexps_num > 1 4473169689Skan && REGEXP_SEQUENCE (regexp)->regexps_num > 1); 4474117395Skan result = create_node (sizeof (struct regexp) 4475117395Skan + sizeof (regexp_t) 4476117395Skan * (REGEXP_SEQUENCE (regexp)->regexps_num 4477117395Skan + REGEXP_SEQUENCE (sequence)->regexps_num 4478117395Skan - 2)); 4479117395Skan result->mode = rm_sequence; 4480117395Skan result->pos = regexp->pos; 4481117395Skan REGEXP_SEQUENCE (result)->regexps_num 4482117395Skan = (REGEXP_SEQUENCE (regexp)->regexps_num 4483117395Skan + REGEXP_SEQUENCE (sequence)->regexps_num - 1); 4484117395Skan for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++) 4485117395Skan if (i < sequence_index) 4486117395Skan REGEXP_SEQUENCE (result)->regexps [i] 4487117395Skan = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]); 4488117395Skan else if (i > sequence_index) 4489117395Skan REGEXP_SEQUENCE (result)->regexps 4490117395Skan [i + REGEXP_SEQUENCE (sequence)->regexps_num - 1] 4491117395Skan = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]); 4492117395Skan else 4493117395Skan for (j = 0; j < REGEXP_SEQUENCE (sequence)->regexps_num; j++) 4494117395Skan REGEXP_SEQUENCE (result)->regexps [i + j] 4495117395Skan = copy_insn_regexp (REGEXP_SEQUENCE (sequence)->regexps [j]); 4496117395Skan regexp_transformed_p = 1; 4497117395Skan regexp = result; 4498117395Skan } 4499117395Skan } 4500117395Skan else if (regexp->mode == rm_allof) 4501117395Skan { 4502117395Skan regexp_t allof = NULL; 4503117395Skan regexp_t result; 4504117395Skan int allof_index = 0; 4505117395Skan int i, j; 4506117395Skan 4507117395Skan for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++) 4508117395Skan if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_allof) 4509117395Skan { 4510117395Skan allof_index = i; 4511117395Skan allof = REGEXP_ALLOF (regexp)->regexps [i]; 4512117395Skan break; 4513117395Skan } 4514117395Skan if (i < REGEXP_ALLOF (regexp)->regexps_num) 4515117395Skan { 4516169689Skan gcc_assert (REGEXP_ALLOF (allof)->regexps_num > 1 4517169689Skan && REGEXP_ALLOF (regexp)->regexps_num > 1); 4518117395Skan result = create_node (sizeof (struct regexp) 4519117395Skan + sizeof (regexp_t) 4520117395Skan * (REGEXP_ALLOF (regexp)->regexps_num 4521117395Skan + REGEXP_ALLOF (allof)->regexps_num - 2)); 4522117395Skan result->mode = rm_allof; 4523117395Skan result->pos = regexp->pos; 4524117395Skan REGEXP_ALLOF (result)->regexps_num 4525117395Skan = (REGEXP_ALLOF (regexp)->regexps_num 4526117395Skan + REGEXP_ALLOF (allof)->regexps_num - 1); 4527117395Skan for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++) 4528117395Skan if (i < allof_index) 4529117395Skan REGEXP_ALLOF (result)->regexps [i] 4530117395Skan = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]); 4531117395Skan else if (i > allof_index) 4532117395Skan REGEXP_ALLOF (result)->regexps 4533117395Skan [i + REGEXP_ALLOF (allof)->regexps_num - 1] 4534117395Skan = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]); 4535117395Skan else 4536117395Skan for (j = 0; j < REGEXP_ALLOF (allof)->regexps_num; j++) 4537117395Skan REGEXP_ALLOF (result)->regexps [i + j] 4538117395Skan = copy_insn_regexp (REGEXP_ALLOF (allof)->regexps [j]); 4539117395Skan regexp_transformed_p = 1; 4540117395Skan regexp = result; 4541117395Skan } 4542117395Skan } 4543117395Skan else if (regexp->mode == rm_oneof) 4544117395Skan { 4545117395Skan regexp_t oneof = NULL; 4546117395Skan regexp_t result; 4547117395Skan int oneof_index = 0; 4548117395Skan int i, j; 4549117395Skan 4550117395Skan for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++) 4551117395Skan if (REGEXP_ONEOF (regexp)->regexps [i]->mode == rm_oneof) 4552117395Skan { 4553117395Skan oneof_index = i; 4554117395Skan oneof = REGEXP_ONEOF (regexp)->regexps [i]; 4555117395Skan break; 4556117395Skan } 4557117395Skan if (i < REGEXP_ONEOF (regexp)->regexps_num) 4558117395Skan { 4559169689Skan gcc_assert (REGEXP_ONEOF (oneof)->regexps_num > 1 4560169689Skan && REGEXP_ONEOF (regexp)->regexps_num > 1); 4561117395Skan result = create_node (sizeof (struct regexp) 4562117395Skan + sizeof (regexp_t) 4563117395Skan * (REGEXP_ONEOF (regexp)->regexps_num 4564117395Skan + REGEXP_ONEOF (oneof)->regexps_num - 2)); 4565117395Skan result->mode = rm_oneof; 4566117395Skan result->pos = regexp->pos; 4567117395Skan REGEXP_ONEOF (result)->regexps_num 4568117395Skan = (REGEXP_ONEOF (regexp)->regexps_num 4569117395Skan + REGEXP_ONEOF (oneof)->regexps_num - 1); 4570117395Skan for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++) 4571117395Skan if (i < oneof_index) 4572117395Skan REGEXP_ONEOF (result)->regexps [i] 4573117395Skan = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]); 4574117395Skan else if (i > oneof_index) 4575117395Skan REGEXP_ONEOF (result)->regexps 4576117395Skan [i + REGEXP_ONEOF (oneof)->regexps_num - 1] 4577117395Skan = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]); 4578117395Skan else 4579117395Skan for (j = 0; j < REGEXP_ONEOF (oneof)->regexps_num; j++) 4580117395Skan REGEXP_ONEOF (result)->regexps [i + j] 4581117395Skan = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [j]); 4582117395Skan regexp_transformed_p = 1; 4583117395Skan regexp = result; 4584117395Skan } 4585117395Skan } 4586117395Skan return regexp; 4587117395Skan} 4588117395Skan 4589117395Skan/* The function makes transformations 4590117395Skan ...,A|B|...,C,... -> (...,A,C,...)|(...,B,C,...)|... 4591117395Skan ...+(A|B|...)+C+... -> (...+A+C+...)|(...+B+C+...)|... 4592117395Skan ...+(A,B,...)+C+... -> (...+A+C+...),B,... 4593117395Skan ...+(A,B,...)+(C,D,...) -> (A+C),(B+D),... */ 4594117395Skanstatic regexp_t 4595132718Skantransform_3 (regexp_t regexp) 4596117395Skan{ 4597117395Skan if (regexp->mode == rm_sequence) 4598117395Skan { 4599117395Skan regexp_t oneof = NULL; 4600117395Skan int oneof_index = 0; 4601117395Skan regexp_t result; 4602117395Skan regexp_t sequence; 4603117395Skan int i, j; 4604117395Skan 4605117395Skan for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++) 4606117395Skan if (REGEXP_SEQUENCE (regexp)->regexps [i]->mode == rm_oneof) 4607117395Skan { 4608117395Skan oneof_index = i; 4609117395Skan oneof = REGEXP_SEQUENCE (regexp)->regexps [i]; 4610117395Skan break; 4611117395Skan } 4612117395Skan if (i < REGEXP_SEQUENCE (regexp)->regexps_num) 4613117395Skan { 4614169689Skan gcc_assert (REGEXP_ONEOF (oneof)->regexps_num > 1 4615169689Skan && REGEXP_SEQUENCE (regexp)->regexps_num > 1); 4616117395Skan result = create_node (sizeof (struct regexp) 4617117395Skan + sizeof (regexp_t) 4618117395Skan * (REGEXP_ONEOF (oneof)->regexps_num - 1)); 4619117395Skan result->mode = rm_oneof; 4620117395Skan result->pos = regexp->pos; 4621117395Skan REGEXP_ONEOF (result)->regexps_num 4622117395Skan = REGEXP_ONEOF (oneof)->regexps_num; 4623117395Skan for (i = 0; i < REGEXP_ONEOF (result)->regexps_num; i++) 4624117395Skan { 4625117395Skan sequence 4626117395Skan = create_node (sizeof (struct regexp) 4627117395Skan + sizeof (regexp_t) 4628117395Skan * (REGEXP_SEQUENCE (regexp)->regexps_num - 1)); 4629117395Skan sequence->mode = rm_sequence; 4630117395Skan sequence->pos = regexp->pos; 4631117395Skan REGEXP_SEQUENCE (sequence)->regexps_num 4632117395Skan = REGEXP_SEQUENCE (regexp)->regexps_num; 4633117395Skan REGEXP_ONEOF (result)->regexps [i] = sequence; 4634117395Skan for (j = 0; j < REGEXP_SEQUENCE (sequence)->regexps_num; j++) 4635117395Skan if (j != oneof_index) 4636117395Skan REGEXP_SEQUENCE (sequence)->regexps [j] 4637117395Skan = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [j]); 4638117395Skan else 4639117395Skan REGEXP_SEQUENCE (sequence)->regexps [j] 4640117395Skan = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [i]); 4641117395Skan } 4642117395Skan regexp_transformed_p = 1; 4643117395Skan regexp = result; 4644117395Skan } 4645117395Skan } 4646117395Skan else if (regexp->mode == rm_allof) 4647117395Skan { 4648132718Skan regexp_t oneof = NULL; 4649132718Skan regexp_t seq; 4650132718Skan int oneof_index = 0; 4651132718Skan int max_seq_length, allof_length; 4652117395Skan regexp_t result; 4653132718Skan regexp_t allof = NULL; 4654132718Skan regexp_t allof_op = NULL; 4655117395Skan int i, j; 4656117395Skan 4657117395Skan for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++) 4658117395Skan if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_oneof) 4659117395Skan { 4660117395Skan oneof_index = i; 4661117395Skan oneof = REGEXP_ALLOF (regexp)->regexps [i]; 4662117395Skan break; 4663117395Skan } 4664117395Skan if (i < REGEXP_ALLOF (regexp)->regexps_num) 4665117395Skan { 4666169689Skan gcc_assert (REGEXP_ONEOF (oneof)->regexps_num > 1 4667169689Skan && REGEXP_ALLOF (regexp)->regexps_num > 1); 4668117395Skan result = create_node (sizeof (struct regexp) 4669117395Skan + sizeof (regexp_t) 4670117395Skan * (REGEXP_ONEOF (oneof)->regexps_num - 1)); 4671117395Skan result->mode = rm_oneof; 4672117395Skan result->pos = regexp->pos; 4673117395Skan REGEXP_ONEOF (result)->regexps_num 4674117395Skan = REGEXP_ONEOF (oneof)->regexps_num; 4675117395Skan for (i = 0; i < REGEXP_ONEOF (result)->regexps_num; i++) 4676117395Skan { 4677117395Skan allof 4678117395Skan = create_node (sizeof (struct regexp) 4679117395Skan + sizeof (regexp_t) 4680117395Skan * (REGEXP_ALLOF (regexp)->regexps_num - 1)); 4681117395Skan allof->mode = rm_allof; 4682117395Skan allof->pos = regexp->pos; 4683117395Skan REGEXP_ALLOF (allof)->regexps_num 4684117395Skan = REGEXP_ALLOF (regexp)->regexps_num; 4685117395Skan REGEXP_ONEOF (result)->regexps [i] = allof; 4686117395Skan for (j = 0; j < REGEXP_ALLOF (allof)->regexps_num; j++) 4687117395Skan if (j != oneof_index) 4688117395Skan REGEXP_ALLOF (allof)->regexps [j] 4689117395Skan = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [j]); 4690117395Skan else 4691117395Skan REGEXP_ALLOF (allof)->regexps [j] 4692117395Skan = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [i]); 4693117395Skan } 4694117395Skan regexp_transformed_p = 1; 4695117395Skan regexp = result; 4696117395Skan } 4697117395Skan max_seq_length = 0; 4698117395Skan if (regexp->mode == rm_allof) 4699117395Skan for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++) 4700117395Skan { 4701169689Skan switch (REGEXP_ALLOF (regexp)->regexps [i]->mode) 4702117395Skan { 4703169689Skan case rm_sequence: 4704117395Skan seq = REGEXP_ALLOF (regexp)->regexps [i]; 4705117395Skan if (max_seq_length < REGEXP_SEQUENCE (seq)->regexps_num) 4706117395Skan max_seq_length = REGEXP_SEQUENCE (seq)->regexps_num; 4707169689Skan break; 4708169689Skan 4709169689Skan case rm_unit: 4710169689Skan case rm_nothing: 4711169689Skan break; 4712169689Skan 4713169689Skan default: 4714117395Skan max_seq_length = 0; 4715169689Skan goto break_for; 4716117395Skan } 4717117395Skan } 4718169689Skan break_for: 4719117395Skan if (max_seq_length != 0) 4720117395Skan { 4721169689Skan gcc_assert (max_seq_length != 1 4722169689Skan && REGEXP_ALLOF (regexp)->regexps_num > 1); 4723117395Skan result = create_node (sizeof (struct regexp) 4724117395Skan + sizeof (regexp_t) * (max_seq_length - 1)); 4725117395Skan result->mode = rm_sequence; 4726117395Skan result->pos = regexp->pos; 4727117395Skan REGEXP_SEQUENCE (result)->regexps_num = max_seq_length; 4728117395Skan for (i = 0; i < max_seq_length; i++) 4729117395Skan { 4730117395Skan allof_length = 0; 4731117395Skan for (j = 0; j < REGEXP_ALLOF (regexp)->regexps_num; j++) 4732169689Skan switch (REGEXP_ALLOF (regexp)->regexps [j]->mode) 4733117395Skan { 4734169689Skan case rm_sequence: 4735169689Skan if (i < (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp) 4736169689Skan ->regexps [j])->regexps_num)) 4737169689Skan { 4738169689Skan allof_op 4739169689Skan = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp) 4740169689Skan ->regexps [j]) 4741169689Skan ->regexps [i]); 4742169689Skan allof_length++; 4743169689Skan } 4744169689Skan break; 4745169689Skan case rm_unit: 4746169689Skan case rm_nothing: 4747169689Skan if (i == 0) 4748169689Skan { 4749169689Skan allof_op = REGEXP_ALLOF (regexp)->regexps [j]; 4750169689Skan allof_length++; 4751169689Skan } 4752169689Skan break; 4753169689Skan default: 4754169689Skan break; 4755117395Skan } 4756169689Skan 4757117395Skan if (allof_length == 1) 4758117395Skan REGEXP_SEQUENCE (result)->regexps [i] = allof_op; 4759117395Skan else 4760117395Skan { 4761117395Skan allof = create_node (sizeof (struct regexp) 4762117395Skan + sizeof (regexp_t) 4763117395Skan * (allof_length - 1)); 4764117395Skan allof->mode = rm_allof; 4765117395Skan allof->pos = regexp->pos; 4766117395Skan REGEXP_ALLOF (allof)->regexps_num = allof_length; 4767117395Skan REGEXP_SEQUENCE (result)->regexps [i] = allof; 4768117395Skan allof_length = 0; 4769117395Skan for (j = 0; j < REGEXP_ALLOF (regexp)->regexps_num; j++) 4770117395Skan if (REGEXP_ALLOF (regexp)->regexps [j]->mode == rm_sequence 4771117395Skan && (i < 4772117395Skan (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp) 4773117395Skan ->regexps [j])->regexps_num))) 4774117395Skan { 4775117395Skan allof_op = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp) 4776117395Skan ->regexps [j]) 4777117395Skan ->regexps [i]); 4778117395Skan REGEXP_ALLOF (allof)->regexps [allof_length] 4779117395Skan = allof_op; 4780117395Skan allof_length++; 4781117395Skan } 4782117395Skan else if (i == 0 4783117395Skan && (REGEXP_ALLOF (regexp)->regexps [j]->mode 4784132718Skan == rm_unit 4785132718Skan || (REGEXP_ALLOF (regexp)->regexps [j]->mode 4786132718Skan == rm_nothing))) 4787117395Skan { 4788117395Skan allof_op = REGEXP_ALLOF (regexp)->regexps [j]; 4789117395Skan REGEXP_ALLOF (allof)->regexps [allof_length] 4790117395Skan = allof_op; 4791117395Skan allof_length++; 4792117395Skan } 4793117395Skan } 4794117395Skan } 4795117395Skan regexp_transformed_p = 1; 4796117395Skan regexp = result; 4797117395Skan } 4798117395Skan } 4799117395Skan return regexp; 4800117395Skan} 4801117395Skan 4802117395Skan/* The function traverses IR of reservation and applies transformations 4803117395Skan implemented by FUNC. */ 4804117395Skanstatic regexp_t 4805132718Skanregexp_transform_func (regexp_t regexp, regexp_t (*func) (regexp_t regexp)) 4806117395Skan{ 4807117395Skan int i; 4808117395Skan 4809169689Skan switch (regexp->mode) 4810169689Skan { 4811169689Skan case rm_sequence: 4812169689Skan for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++) 4813169689Skan REGEXP_SEQUENCE (regexp)->regexps [i] 4814169689Skan = regexp_transform_func (REGEXP_SEQUENCE (regexp)->regexps [i], 4815169689Skan func); 4816169689Skan break; 4817169689Skan 4818169689Skan case rm_allof: 4819169689Skan for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++) 4820169689Skan REGEXP_ALLOF (regexp)->regexps [i] 4821169689Skan = regexp_transform_func (REGEXP_ALLOF (regexp)->regexps [i], func); 4822169689Skan break; 4823169689Skan 4824169689Skan case rm_oneof: 4825169689Skan for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++) 4826169689Skan REGEXP_ONEOF (regexp)->regexps [i] 4827169689Skan = regexp_transform_func (REGEXP_ONEOF (regexp)->regexps [i], func); 4828169689Skan break; 4829169689Skan 4830169689Skan case rm_repeat: 4831169689Skan REGEXP_REPEAT (regexp)->regexp 4832169689Skan = regexp_transform_func (REGEXP_REPEAT (regexp)->regexp, func); 4833169689Skan break; 4834169689Skan 4835169689Skan case rm_nothing: 4836169689Skan case rm_unit: 4837169689Skan break; 4838169689Skan 4839169689Skan default: 4840169689Skan gcc_unreachable (); 4841169689Skan } 4842117395Skan return (*func) (regexp); 4843117395Skan} 4844117395Skan 4845117395Skan/* The function applies all transformations for IR representation of 4846117395Skan reservation REGEXP. */ 4847117395Skanstatic regexp_t 4848132718Skantransform_regexp (regexp_t regexp) 4849117395Skan{ 4850132718Skan regexp = regexp_transform_func (regexp, transform_1); 4851117395Skan do 4852117395Skan { 4853117395Skan regexp_transformed_p = 0; 4854117395Skan regexp = regexp_transform_func (regexp, transform_2); 4855117395Skan regexp = regexp_transform_func (regexp, transform_3); 4856117395Skan } 4857117395Skan while (regexp_transformed_p); 4858117395Skan return regexp; 4859117395Skan} 4860117395Skan 4861132718Skan/* The function applies all transformations for reservations of all 4862117395Skan insn declarations. */ 4863117395Skanstatic void 4864132718Skantransform_insn_regexps (void) 4865117395Skan{ 4866117395Skan decl_t decl; 4867117395Skan int i; 4868117395Skan 4869117395Skan transform_time = create_ticker (); 4870117395Skan add_advance_cycle_insn_decl (); 4871132718Skan if (progress_flag) 4872132718Skan fprintf (stderr, "Reservation transformation..."); 4873117395Skan for (i = 0; i < description->decls_num; i++) 4874117395Skan { 4875117395Skan decl = description->decls [i]; 4876117395Skan if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl) 4877117395Skan DECL_INSN_RESERV (decl)->transformed_regexp 4878117395Skan = transform_regexp (copy_insn_regexp 4879117395Skan (DECL_INSN_RESERV (decl)->regexp)); 4880117395Skan } 4881132718Skan if (progress_flag) 4882132718Skan fprintf (stderr, "done\n"); 4883117395Skan ticker_off (&transform_time); 4884117395Skan} 4885117395Skan 4886117395Skan 4887117395Skan 4888132718Skan/* The following variable value is TRUE if the first annotated message 4889132718Skan about units to automata distribution has been output. */ 4890132718Skanstatic int annotation_message_reported_p; 4891117395Skan 4892132718Skan/* The following structure describes usage of a unit in a reservation. */ 4893132718Skanstruct unit_usage 4894132718Skan{ 4895132718Skan unit_decl_t unit_decl; 4896132718Skan /* The following forms a list of units used on the same cycle in the 4897132718Skan same alternative. */ 4898132718Skan struct unit_usage *next; 4899132718Skan}; 4900169689Skantypedef struct unit_usage *unit_usage_t; 4901132718Skan 4902169689SkanDEF_VEC_P(unit_usage_t); 4903169689SkanDEF_VEC_ALLOC_P(unit_usage_t,heap); 4904169689Skan 4905132718Skan/* Obstack for unit_usage structures. */ 4906132718Skanstatic struct obstack unit_usages; 4907132718Skan 4908132718Skan/* VLA for representation of array of pointers to unit usage 4909132718Skan structures. There is an element for each combination of 4910132718Skan (alternative number, cycle). Unit usages on given cycle in 4911132718Skan alternative with given number are referred through element with 4912132718Skan index equals to the cycle * number of all alternatives in the regexp 4913132718Skan + the alternative number. */ 4914169689Skanstatic VEC(unit_usage_t,heap) *cycle_alt_unit_usages; 4915132718Skan 4916132718Skan/* The following function creates the structure unit_usage for UNIT on 4917132718Skan CYCLE in REGEXP alternative with ALT_NUM. The structure is made 4918132718Skan accessed through cycle_alt_unit_usages. */ 4919117395Skanstatic void 4920132718Skanstore_alt_unit_usage (regexp_t regexp, regexp_t unit, int cycle, 4921132718Skan int alt_num) 4922117395Skan{ 4923169689Skan size_t length; 4924132718Skan unit_decl_t unit_decl; 4925169689Skan unit_usage_t unit_usage_ptr; 4926132718Skan int index; 4927117395Skan 4928169689Skan gcc_assert (regexp && regexp->mode == rm_oneof 4929169689Skan && alt_num < REGEXP_ONEOF (regexp)->regexps_num); 4930117395Skan unit_decl = REGEXP_UNIT (unit)->unit_decl; 4931169689Skan 4932132718Skan length = (cycle + 1) * REGEXP_ONEOF (regexp)->regexps_num; 4933169689Skan while (VEC_length (unit_usage_t, cycle_alt_unit_usages) < length) 4934169689Skan VEC_safe_push (unit_usage_t,heap, cycle_alt_unit_usages, 0); 4935169689Skan 4936132718Skan obstack_blank (&unit_usages, sizeof (struct unit_usage)); 4937132718Skan unit_usage_ptr = (struct unit_usage *) obstack_base (&unit_usages); 4938222097Sbenl (void) obstack_finish (&unit_usages); 4939132718Skan unit_usage_ptr->unit_decl = unit_decl; 4940132718Skan index = cycle * REGEXP_ONEOF (regexp)->regexps_num + alt_num; 4941169689Skan unit_usage_ptr->next = VEC_index (unit_usage_t, cycle_alt_unit_usages, index); 4942169689Skan VEC_replace (unit_usage_t, cycle_alt_unit_usages, index, unit_usage_ptr); 4943132718Skan unit_decl->last_distribution_check_cycle = -1; /* undefined */ 4944117395Skan} 4945117395Skan 4946132718Skan/* The function processes given REGEXP to find units with the wrong 4947132718Skan distribution. */ 4948117395Skanstatic void 4949132718Skancheck_regexp_units_distribution (const char *insn_reserv_name, 4950132718Skan regexp_t regexp) 4951117395Skan{ 4952132718Skan int i, j, k, cycle; 4953117395Skan regexp_t seq, allof, unit; 4954132718Skan struct unit_usage *unit_usage_ptr, *other_unit_usage_ptr; 4955117395Skan 4956117395Skan if (regexp == NULL || regexp->mode != rm_oneof) 4957117395Skan return; 4958132718Skan /* Store all unit usages in the regexp: */ 4959132718Skan obstack_init (&unit_usages); 4960169689Skan cycle_alt_unit_usages = 0; 4961169689Skan 4962117395Skan for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--) 4963117395Skan { 4964117395Skan seq = REGEXP_ONEOF (regexp)->regexps [i]; 4965169689Skan switch (seq->mode) 4966169689Skan { 4967169689Skan case rm_sequence: 4968169689Skan for (j = 0; j < REGEXP_SEQUENCE (seq)->regexps_num; j++) 4969169689Skan { 4970169689Skan allof = REGEXP_SEQUENCE (seq)->regexps [j]; 4971169689Skan switch (allof->mode) 4972117395Skan { 4973169689Skan case rm_allof: 4974169689Skan for (k = 0; k < REGEXP_ALLOF (allof)->regexps_num; k++) 4975169689Skan { 4976169689Skan unit = REGEXP_ALLOF (allof)->regexps [k]; 4977169689Skan if (unit->mode == rm_unit) 4978169689Skan store_alt_unit_usage (regexp, unit, j, i); 4979169689Skan else 4980169689Skan gcc_assert (unit->mode == rm_nothing); 4981169689Skan } 4982169689Skan break; 4983169689Skan 4984169689Skan case rm_unit: 4985169689Skan store_alt_unit_usage (regexp, allof, j, i); 4986169689Skan break; 4987169689Skan 4988169689Skan case rm_nothing: 4989169689Skan break; 4990169689Skan 4991169689Skan default: 4992169689Skan gcc_unreachable (); 4993117395Skan } 4994169689Skan } 4995169689Skan break; 4996169689Skan 4997169689Skan case rm_allof: 4998169689Skan for (k = 0; k < REGEXP_ALLOF (seq)->regexps_num; k++) 4999169689Skan { 5000169689Skan unit = REGEXP_ALLOF (seq)->regexps [k]; 5001169689Skan switch (unit->mode) 5002169689Skan { 5003169689Skan case rm_unit: 5004169689Skan store_alt_unit_usage (regexp, unit, 0, i); 5005169689Skan break; 5006169689Skan 5007169689Skan case rm_nothing: 5008169689Skan break; 5009169689Skan 5010169689Skan default: 5011169689Skan gcc_unreachable (); 5012169689Skan } 5013169689Skan } 5014169689Skan break; 5015169689Skan 5016169689Skan case rm_unit: 5017169689Skan store_alt_unit_usage (regexp, seq, 0, i); 5018169689Skan break; 5019169689Skan 5020169689Skan case rm_nothing: 5021169689Skan break; 5022169689Skan 5023169689Skan default: 5024169689Skan gcc_unreachable (); 5025169689Skan } 5026117395Skan } 5027132718Skan /* Check distribution: */ 5028169689Skan for (i = 0; i < (int) VEC_length (unit_usage_t, cycle_alt_unit_usages); i++) 5029117395Skan { 5030132718Skan cycle = i / REGEXP_ONEOF (regexp)->regexps_num; 5031169689Skan for (unit_usage_ptr = VEC_index (unit_usage_t, cycle_alt_unit_usages, i); 5032132718Skan unit_usage_ptr != NULL; 5033132718Skan unit_usage_ptr = unit_usage_ptr->next) 5034132718Skan if (cycle != unit_usage_ptr->unit_decl->last_distribution_check_cycle) 5035132718Skan { 5036132718Skan unit_usage_ptr->unit_decl->last_distribution_check_cycle = cycle; 5037132718Skan for (k = cycle * REGEXP_ONEOF (regexp)->regexps_num; 5038169689Skan k < (int) VEC_length (unit_usage_t, cycle_alt_unit_usages) 5039132718Skan && k == cycle * REGEXP_ONEOF (regexp)->regexps_num; 5040132718Skan k++) 5041132718Skan { 5042169689Skan for (other_unit_usage_ptr 5043169689Skan = VEC_index (unit_usage_t, cycle_alt_unit_usages, k); 5044132718Skan other_unit_usage_ptr != NULL; 5045132718Skan other_unit_usage_ptr = other_unit_usage_ptr->next) 5046132718Skan if (unit_usage_ptr->unit_decl->automaton_decl 5047132718Skan == other_unit_usage_ptr->unit_decl->automaton_decl) 5048132718Skan break; 5049132718Skan if (other_unit_usage_ptr == NULL 5050169689Skan && (VEC_index (unit_usage_t, cycle_alt_unit_usages, k) 5051169689Skan != NULL)) 5052132718Skan break; 5053132718Skan } 5054169689Skan if (k < (int) VEC_length (unit_usage_t, cycle_alt_unit_usages) 5055132718Skan && k == cycle * REGEXP_ONEOF (regexp)->regexps_num) 5056132718Skan { 5057132718Skan if (!annotation_message_reported_p) 5058132718Skan { 5059132718Skan fprintf (stderr, "\n"); 5060132718Skan error ("The following units do not satisfy units-automata distribution rule"); 5061132718Skan error (" (A unit of given unit automaton should be on each reserv. altern.)"); 5062132718Skan annotation_message_reported_p = TRUE; 5063132718Skan } 5064132718Skan error ("Unit %s, reserv. %s, cycle %d", 5065132718Skan unit_usage_ptr->unit_decl->name, insn_reserv_name, 5066132718Skan cycle); 5067132718Skan } 5068132718Skan } 5069117395Skan } 5070169689Skan VEC_free (unit_usage_t,heap, cycle_alt_unit_usages); 5071132718Skan obstack_free (&unit_usages, NULL); 5072117395Skan} 5073117395Skan 5074132718Skan/* The function finds units which violates units to automata 5075132718Skan distribution rule. If the units exist, report about them. */ 5076117395Skanstatic void 5077132718Skancheck_unit_distributions_to_automata (void) 5078117395Skan{ 5079117395Skan decl_t decl; 5080117395Skan int i; 5081117395Skan 5082132718Skan if (progress_flag) 5083132718Skan fprintf (stderr, "Check unit distributions to automata..."); 5084132718Skan annotation_message_reported_p = FALSE; 5085117395Skan for (i = 0; i < description->decls_num; i++) 5086117395Skan { 5087117395Skan decl = description->decls [i]; 5088132718Skan if (decl->mode == dm_insn_reserv) 5089132718Skan check_regexp_units_distribution 5090132718Skan (DECL_INSN_RESERV (decl)->name, 5091132718Skan DECL_INSN_RESERV (decl)->transformed_regexp); 5092117395Skan } 5093132718Skan if (progress_flag) 5094132718Skan fprintf (stderr, "done\n"); 5095117395Skan} 5096117395Skan 5097117395Skan 5098117395Skan 5099117395Skan/* The page contains code for building alt_states (see comments for 5100117395Skan IR) describing all possible insns reservations of an automaton. */ 5101117395Skan 5102117395Skan/* Current state being formed for which the current alt_state 5103117395Skan refers. */ 5104117395Skanstatic state_t state_being_formed; 5105117395Skan 5106117395Skan/* Current alt_state being formed. */ 5107117395Skanstatic alt_state_t alt_state_being_formed; 5108132718Skan 5109117395Skan/* This recursive function processes `,' and units in reservation 5110117395Skan REGEXP for forming alt_states of AUTOMATON. It is believed that 5111117395Skan CURR_CYCLE is start cycle of all reservation REGEXP. */ 5112117395Skanstatic int 5113132718Skanprocess_seq_for_forming_states (regexp_t regexp, automaton_t automaton, 5114132718Skan int curr_cycle) 5115117395Skan{ 5116117395Skan int i; 5117117395Skan 5118117395Skan if (regexp == NULL) 5119117395Skan return curr_cycle; 5120169689Skan 5121169689Skan switch (regexp->mode) 5122117395Skan { 5123169689Skan case rm_unit: 5124117395Skan if (REGEXP_UNIT (regexp)->unit_decl->corresponding_automaton_num 5125117395Skan == automaton->automaton_order_num) 5126117395Skan set_state_reserv (state_being_formed, curr_cycle, 5127117395Skan REGEXP_UNIT (regexp)->unit_decl->unit_num); 5128117395Skan return curr_cycle; 5129169689Skan 5130169689Skan case rm_sequence: 5131117395Skan for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++) 5132117395Skan curr_cycle 5133117395Skan = process_seq_for_forming_states 5134117395Skan (REGEXP_SEQUENCE (regexp)->regexps [i], automaton, curr_cycle) + 1; 5135117395Skan return curr_cycle; 5136117395Skan 5137169689Skan case rm_allof: 5138169689Skan { 5139169689Skan int finish_cycle = 0; 5140169689Skan int cycle; 5141169689Skan 5142169689Skan for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++) 5143169689Skan { 5144169689Skan cycle = process_seq_for_forming_states (REGEXP_ALLOF (regexp) 5145169689Skan ->regexps [i], 5146169689Skan automaton, curr_cycle); 5147169689Skan if (finish_cycle < cycle) 5148169689Skan finish_cycle = cycle; 5149169689Skan } 5150169689Skan return finish_cycle; 5151169689Skan } 5152169689Skan 5153169689Skan case rm_nothing: 5154117395Skan return curr_cycle; 5155169689Skan 5156169689Skan default: 5157169689Skan gcc_unreachable (); 5158117395Skan } 5159117395Skan} 5160117395Skan 5161117395Skan/* This recursive function finishes forming ALT_STATE of AUTOMATON and 5162117395Skan inserts alt_state into the table. */ 5163117395Skanstatic void 5164132718Skanfinish_forming_alt_state (alt_state_t alt_state, 5165132718Skan automaton_t automaton ATTRIBUTE_UNUSED) 5166117395Skan{ 5167117395Skan state_t state_in_table; 5168117395Skan state_t corresponding_state; 5169117395Skan 5170117395Skan corresponding_state = alt_state->state; 5171117395Skan state_in_table = insert_state (corresponding_state); 5172117395Skan if (state_in_table != corresponding_state) 5173117395Skan { 5174117395Skan free_state (corresponding_state); 5175117395Skan alt_state->state = state_in_table; 5176117395Skan } 5177117395Skan} 5178117395Skan 5179117395Skan/* The following variable value is current automaton insn for whose 5180117395Skan reservation the alt states are created. */ 5181117395Skanstatic ainsn_t curr_ainsn; 5182117395Skan 5183117395Skan/* This recursive function processes `|' in reservation REGEXP for 5184117395Skan forming alt_states of AUTOMATON. List of the alt states should 5185117395Skan have the same order as in the description. */ 5186117395Skanstatic void 5187132718Skanprocess_alts_for_forming_states (regexp_t regexp, automaton_t automaton, 5188132718Skan int inside_oneof_p) 5189117395Skan{ 5190117395Skan int i; 5191117395Skan 5192117395Skan if (regexp->mode != rm_oneof) 5193117395Skan { 5194117395Skan alt_state_being_formed = get_free_alt_state (); 5195117395Skan state_being_formed = get_free_state (1, automaton); 5196117395Skan alt_state_being_formed->state = state_being_formed; 5197117395Skan /* We inserts in reverse order but we process alternatives also 5198117395Skan in reverse order. So we have the same order of alternative 5199117395Skan as in the description. */ 5200117395Skan alt_state_being_formed->next_alt_state = curr_ainsn->alt_states; 5201117395Skan curr_ainsn->alt_states = alt_state_being_formed; 5202117395Skan (void) process_seq_for_forming_states (regexp, automaton, 0); 5203117395Skan finish_forming_alt_state (alt_state_being_formed, automaton); 5204117395Skan } 5205117395Skan else 5206117395Skan { 5207169689Skan gcc_assert (!inside_oneof_p); 5208117395Skan /* We processes it in reverse order to get list with the same 5209117395Skan order as in the description. See also the previous 5210117395Skan commentary. */ 5211117395Skan for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--) 5212117395Skan process_alts_for_forming_states (REGEXP_ONEOF (regexp)->regexps [i], 5213117395Skan automaton, 1); 5214117395Skan } 5215117395Skan} 5216117395Skan 5217117395Skan/* Create nodes alt_state for all AUTOMATON insns. */ 5218117395Skanstatic void 5219132718Skancreate_alt_states (automaton_t automaton) 5220117395Skan{ 5221117395Skan struct insn_reserv_decl *reserv_decl; 5222117395Skan 5223117395Skan for (curr_ainsn = automaton->ainsn_list; 5224117395Skan curr_ainsn != NULL; 5225117395Skan curr_ainsn = curr_ainsn->next_ainsn) 5226117395Skan { 5227117395Skan reserv_decl = curr_ainsn->insn_reserv_decl; 5228117395Skan if (reserv_decl != DECL_INSN_RESERV (advance_cycle_insn_decl)) 5229117395Skan { 5230117395Skan curr_ainsn->alt_states = NULL; 5231117395Skan process_alts_for_forming_states (reserv_decl->transformed_regexp, 5232117395Skan automaton, 0); 5233117395Skan curr_ainsn->sorted_alt_states 5234117395Skan = uniq_sort_alt_states (curr_ainsn->alt_states); 5235117395Skan } 5236117395Skan } 5237117395Skan} 5238117395Skan 5239117395Skan 5240117395Skan 5241117395Skan/* The page contains major code for building DFA(s) for fast pipeline 5242117395Skan hazards recognition. */ 5243117395Skan 5244117395Skan/* The function forms list of ainsns of AUTOMATON with the same 5245117395Skan reservation. */ 5246169689Skan 5247117395Skanstatic void 5248132718Skanform_ainsn_with_same_reservs (automaton_t automaton) 5249117395Skan{ 5250117395Skan ainsn_t curr_ainsn; 5251117395Skan size_t i; 5252169689Skan VEC(ainsn_t,heap) *last_insns = VEC_alloc (ainsn_t,heap, 150); 5253117395Skan 5254117395Skan for (curr_ainsn = automaton->ainsn_list; 5255117395Skan curr_ainsn != NULL; 5256117395Skan curr_ainsn = curr_ainsn->next_ainsn) 5257117395Skan if (curr_ainsn->insn_reserv_decl 5258117395Skan == DECL_INSN_RESERV (advance_cycle_insn_decl)) 5259117395Skan { 5260117395Skan curr_ainsn->next_same_reservs_insn = NULL; 5261117395Skan curr_ainsn->first_insn_with_same_reservs = 1; 5262117395Skan } 5263117395Skan else 5264117395Skan { 5265169689Skan for (i = 0; i < VEC_length (ainsn_t, last_insns); i++) 5266117395Skan if (alt_states_eq 5267117395Skan (curr_ainsn->sorted_alt_states, 5268169689Skan VEC_index (ainsn_t, last_insns, i)->sorted_alt_states)) 5269117395Skan break; 5270117395Skan curr_ainsn->next_same_reservs_insn = NULL; 5271169689Skan if (i < VEC_length (ainsn_t, last_insns)) 5272117395Skan { 5273117395Skan curr_ainsn->first_insn_with_same_reservs = 0; 5274169689Skan VEC_index (ainsn_t, last_insns, i)->next_same_reservs_insn 5275117395Skan = curr_ainsn; 5276169689Skan VEC_replace (ainsn_t, last_insns, i, curr_ainsn); 5277117395Skan } 5278117395Skan else 5279117395Skan { 5280169689Skan VEC_safe_push (ainsn_t, heap, last_insns, curr_ainsn); 5281117395Skan curr_ainsn->first_insn_with_same_reservs = 1; 5282117395Skan } 5283117395Skan } 5284169689Skan VEC_free (ainsn_t,heap, last_insns); 5285117395Skan} 5286117395Skan 5287132718Skan/* Forming unit reservations which can affect creating the automaton 5288132718Skan states achieved from a given state. It permits to build smaller 5289132718Skan automata in many cases. We would have the same automata after 5290132718Skan the minimization without such optimization, but the automaton 5291132718Skan right after the building could be huge. So in other words, usage 5292132718Skan of reservs_matter means some minimization during building the 5293132718Skan automaton. */ 5294132718Skanstatic reserv_sets_t 5295132718Skanform_reservs_matter (automaton_t automaton) 5296132718Skan{ 5297132718Skan int cycle, unit; 5298132718Skan reserv_sets_t reservs_matter = alloc_empty_reserv_sets(); 5299132718Skan 5300132718Skan for (cycle = 0; cycle < max_cycles_num; cycle++) 5301132718Skan for (unit = 0; unit < description->units_num; unit++) 5302132718Skan if (units_array [unit]->automaton_decl 5303132718Skan == automaton->corresponding_automaton_decl 5304132718Skan && (cycle >= units_array [unit]->min_occ_cycle_num 5305132718Skan /* We can not remove queried unit from reservations. */ 5306132718Skan || units_array [unit]->query_p 5307132718Skan /* We can not remove units which are used 5308132718Skan `exclusion_set', `presence_set', 5309132718Skan `final_presence_set', `absence_set', and 5310132718Skan `final_absence_set'. */ 5311132718Skan || units_array [unit]->in_set_p)) 5312132718Skan set_unit_reserv (reservs_matter, cycle, unit); 5313132718Skan return reservs_matter; 5314132718Skan} 5315132718Skan 5316169689Skan/* The following function creates all states of nondeterministic AUTOMATON. */ 5317117395Skanstatic void 5318132718Skanmake_automaton (automaton_t automaton) 5319117395Skan{ 5320117395Skan ainsn_t ainsn; 5321117395Skan struct insn_reserv_decl *insn_reserv_decl; 5322117395Skan alt_state_t alt_state; 5323117395Skan state_t state; 5324117395Skan state_t start_state; 5325117395Skan state_t state2; 5326117395Skan ainsn_t advance_cycle_ainsn; 5327117395Skan arc_t added_arc; 5328169689Skan VEC(state_t,heap) *state_stack = VEC_alloc(state_t,heap, 150); 5329132718Skan int states_n; 5330132718Skan reserv_sets_t reservs_matter = form_reservs_matter (automaton); 5331117395Skan 5332117395Skan /* Create the start state (empty state). */ 5333117395Skan start_state = insert_state (get_free_state (1, automaton)); 5334117395Skan automaton->start_state = start_state; 5335117395Skan start_state->it_was_placed_in_stack_for_NDFA_forming = 1; 5336169689Skan VEC_safe_push (state_t,heap, state_stack, start_state); 5337132718Skan states_n = 1; 5338169689Skan while (VEC_length (state_t, state_stack) != 0) 5339117395Skan { 5340169689Skan state = VEC_pop (state_t, state_stack); 5341117395Skan advance_cycle_ainsn = NULL; 5342117395Skan for (ainsn = automaton->ainsn_list; 5343117395Skan ainsn != NULL; 5344117395Skan ainsn = ainsn->next_ainsn) 5345117395Skan if (ainsn->first_insn_with_same_reservs) 5346117395Skan { 5347117395Skan insn_reserv_decl = ainsn->insn_reserv_decl; 5348117395Skan if (insn_reserv_decl != DECL_INSN_RESERV (advance_cycle_insn_decl)) 5349117395Skan { 5350117395Skan /* We process alt_states in the same order as they are 5351117395Skan present in the description. */ 5352117395Skan added_arc = NULL; 5353117395Skan for (alt_state = ainsn->alt_states; 5354117395Skan alt_state != NULL; 5355117395Skan alt_state = alt_state->next_alt_state) 5356117395Skan { 5357117395Skan state2 = alt_state->state; 5358117395Skan if (!intersected_state_reservs_p (state, state2)) 5359117395Skan { 5360132718Skan state2 = states_union (state, state2, reservs_matter); 5361117395Skan if (!state2->it_was_placed_in_stack_for_NDFA_forming) 5362117395Skan { 5363117395Skan state2->it_was_placed_in_stack_for_NDFA_forming 5364117395Skan = 1; 5365169689Skan VEC_safe_push (state_t,heap, state_stack, state2); 5366132718Skan states_n++; 5367132718Skan if (progress_flag && states_n % 100 == 0) 5368132718Skan fprintf (stderr, "."); 5369117395Skan } 5370169689Skan added_arc = add_arc (state, state2, ainsn); 5371117395Skan if (!ndfa_flag) 5372117395Skan break; 5373117395Skan } 5374117395Skan } 5375117395Skan if (!ndfa_flag && added_arc != NULL) 5376117395Skan { 5377117395Skan for (alt_state = ainsn->alt_states; 5378117395Skan alt_state != NULL; 5379117395Skan alt_state = alt_state->next_alt_state) 5380169689Skan state2 = alt_state->state; 5381117395Skan } 5382117395Skan } 5383117395Skan else 5384117395Skan advance_cycle_ainsn = ainsn; 5385117395Skan } 5386117395Skan /* Add transition to advance cycle. */ 5387132718Skan state2 = state_shift (state, reservs_matter); 5388117395Skan if (!state2->it_was_placed_in_stack_for_NDFA_forming) 5389117395Skan { 5390117395Skan state2->it_was_placed_in_stack_for_NDFA_forming = 1; 5391169689Skan VEC_safe_push (state_t,heap, state_stack, state2); 5392132718Skan states_n++; 5393132718Skan if (progress_flag && states_n % 100 == 0) 5394132718Skan fprintf (stderr, "."); 5395117395Skan } 5396169689Skan gcc_assert (advance_cycle_ainsn); 5397169689Skan add_arc (state, state2, advance_cycle_ainsn); 5398117395Skan } 5399169689Skan VEC_free (state_t,heap, state_stack); 5400117395Skan} 5401117395Skan 5402117395Skan/* Foms lists of all arcs of STATE marked by the same ainsn. */ 5403117395Skanstatic void 5404132718Skanform_arcs_marked_by_insn (state_t state) 5405117395Skan{ 5406117395Skan decl_t decl; 5407117395Skan arc_t arc; 5408117395Skan int i; 5409117395Skan 5410117395Skan for (i = 0; i < description->decls_num; i++) 5411117395Skan { 5412117395Skan decl = description->decls [i]; 5413117395Skan if (decl->mode == dm_insn_reserv) 5414117395Skan DECL_INSN_RESERV (decl)->arcs_marked_by_insn = NULL; 5415117395Skan } 5416117395Skan for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc)) 5417117395Skan { 5418169689Skan gcc_assert (arc->insn); 5419117395Skan arc->next_arc_marked_by_insn 5420117395Skan = arc->insn->insn_reserv_decl->arcs_marked_by_insn; 5421117395Skan arc->insn->insn_reserv_decl->arcs_marked_by_insn = arc; 5422117395Skan } 5423117395Skan} 5424117395Skan 5425117395Skan/* The function creates composed state (see comments for IR) from 5426117395Skan ORIGINAL_STATE and list of arcs ARCS_MARKED_BY_INSN marked by the 5427117395Skan same insn. If the composed state is not in STATE_STACK yet, it is 5428132718Skan pushed into STATE_STACK. */ 5429169689Skan 5430132718Skanstatic int 5431132718Skancreate_composed_state (state_t original_state, arc_t arcs_marked_by_insn, 5432169689Skan VEC(state_t,heap) **state_stack) 5433117395Skan{ 5434117395Skan state_t state; 5435132718Skan alt_state_t alt_state, curr_alt_state; 5436117395Skan alt_state_t new_alt_state; 5437117395Skan arc_t curr_arc; 5438117395Skan arc_t next_arc; 5439117395Skan state_t state_in_table; 5440117395Skan state_t temp_state; 5441117395Skan alt_state_t canonical_alt_states_list; 5442117395Skan int alts_number; 5443132718Skan int new_state_p = 0; 5444117395Skan 5445117395Skan if (arcs_marked_by_insn == NULL) 5446132718Skan return new_state_p; 5447117395Skan if (arcs_marked_by_insn->next_arc_marked_by_insn == NULL) 5448117395Skan state = arcs_marked_by_insn->to_state; 5449117395Skan else 5450117395Skan { 5451169689Skan gcc_assert (ndfa_flag); 5452117395Skan /* Create composed state. */ 5453117395Skan state = get_free_state (0, arcs_marked_by_insn->to_state->automaton); 5454117395Skan curr_alt_state = NULL; 5455117395Skan for (curr_arc = arcs_marked_by_insn; 5456117395Skan curr_arc != NULL; 5457117395Skan curr_arc = curr_arc->next_arc_marked_by_insn) 5458132718Skan if (curr_arc->to_state->component_states == NULL) 5459132718Skan { 5460132718Skan new_alt_state = get_free_alt_state (); 5461132718Skan new_alt_state->next_alt_state = curr_alt_state; 5462132718Skan new_alt_state->state = curr_arc->to_state; 5463132718Skan curr_alt_state = new_alt_state; 5464132718Skan } 5465132718Skan else 5466132718Skan for (alt_state = curr_arc->to_state->component_states; 5467132718Skan alt_state != NULL; 5468132718Skan alt_state = alt_state->next_sorted_alt_state) 5469132718Skan { 5470132718Skan new_alt_state = get_free_alt_state (); 5471132718Skan new_alt_state->next_alt_state = curr_alt_state; 5472132718Skan new_alt_state->state = alt_state->state; 5473169689Skan gcc_assert (!alt_state->state->component_states); 5474132718Skan curr_alt_state = new_alt_state; 5475132718Skan } 5476117395Skan /* There are not identical sets in the alt state list. */ 5477117395Skan canonical_alt_states_list = uniq_sort_alt_states (curr_alt_state); 5478117395Skan if (canonical_alt_states_list->next_sorted_alt_state == NULL) 5479117395Skan { 5480117395Skan temp_state = state; 5481117395Skan state = canonical_alt_states_list->state; 5482117395Skan free_state (temp_state); 5483117395Skan } 5484117395Skan else 5485117395Skan { 5486117395Skan state->component_states = canonical_alt_states_list; 5487117395Skan state_in_table = insert_state (state); 5488117395Skan if (state_in_table != state) 5489117395Skan { 5490169689Skan gcc_assert 5491169689Skan (state_in_table->it_was_placed_in_stack_for_DFA_forming); 5492117395Skan free_state (state); 5493117395Skan state = state_in_table; 5494117395Skan } 5495117395Skan else 5496117395Skan { 5497169689Skan gcc_assert (!state->it_was_placed_in_stack_for_DFA_forming); 5498132718Skan new_state_p = 1; 5499117395Skan for (curr_alt_state = state->component_states; 5500117395Skan curr_alt_state != NULL; 5501117395Skan curr_alt_state = curr_alt_state->next_sorted_alt_state) 5502117395Skan for (curr_arc = first_out_arc (curr_alt_state->state); 5503117395Skan curr_arc != NULL; 5504117395Skan curr_arc = next_out_arc (curr_arc)) 5505169689Skan add_arc (state, curr_arc->to_state, curr_arc->insn); 5506117395Skan } 5507117395Skan arcs_marked_by_insn->to_state = state; 5508117395Skan for (alts_number = 0, 5509117395Skan curr_arc = arcs_marked_by_insn->next_arc_marked_by_insn; 5510117395Skan curr_arc != NULL; 5511117395Skan curr_arc = next_arc) 5512117395Skan { 5513117395Skan next_arc = curr_arc->next_arc_marked_by_insn; 5514117395Skan remove_arc (original_state, curr_arc); 5515117395Skan alts_number++; 5516117395Skan } 5517117395Skan } 5518117395Skan } 5519117395Skan if (!state->it_was_placed_in_stack_for_DFA_forming) 5520117395Skan { 5521117395Skan state->it_was_placed_in_stack_for_DFA_forming = 1; 5522169689Skan VEC_safe_push (state_t,heap, *state_stack, state); 5523117395Skan } 5524132718Skan return new_state_p; 5525117395Skan} 5526117395Skan 5527132718Skan/* The function transforms nondeterministic AUTOMATON into 5528117395Skan deterministic. */ 5529169689Skan 5530117395Skanstatic void 5531132718SkanNDFA_to_DFA (automaton_t automaton) 5532117395Skan{ 5533117395Skan state_t start_state; 5534117395Skan state_t state; 5535117395Skan decl_t decl; 5536169689Skan VEC(state_t,heap) *state_stack; 5537117395Skan int i; 5538132718Skan int states_n; 5539117395Skan 5540169689Skan state_stack = VEC_alloc (state_t,heap, 0); 5541169689Skan 5542117395Skan /* Create the start state (empty state). */ 5543117395Skan start_state = automaton->start_state; 5544117395Skan start_state->it_was_placed_in_stack_for_DFA_forming = 1; 5545169689Skan VEC_safe_push (state_t,heap, state_stack, start_state); 5546132718Skan states_n = 1; 5547169689Skan while (VEC_length (state_t, state_stack) != 0) 5548117395Skan { 5549169689Skan state = VEC_pop (state_t, state_stack); 5550117395Skan form_arcs_marked_by_insn (state); 5551117395Skan for (i = 0; i < description->decls_num; i++) 5552117395Skan { 5553117395Skan decl = description->decls [i]; 5554132718Skan if (decl->mode == dm_insn_reserv 5555132718Skan && create_composed_state 5556132718Skan (state, DECL_INSN_RESERV (decl)->arcs_marked_by_insn, 5557132718Skan &state_stack)) 5558132718Skan { 5559132718Skan states_n++; 5560132718Skan if (progress_flag && states_n % 100 == 0) 5561132718Skan fprintf (stderr, "."); 5562132718Skan } 5563117395Skan } 5564117395Skan } 5565169689Skan VEC_free (state_t,heap, state_stack); 5566117395Skan} 5567117395Skan 5568117395Skan/* The following variable value is current number (1, 2, ...) of passing 5569117395Skan graph of states. */ 5570117395Skanstatic int curr_state_graph_pass_num; 5571117395Skan 5572117395Skan/* This recursive function passes all states achieved from START_STATE 5573117395Skan and applies APPLIED_FUNC to them. */ 5574117395Skanstatic void 5575132718Skanpass_state_graph (state_t start_state, void (*applied_func) (state_t state)) 5576117395Skan{ 5577117395Skan arc_t arc; 5578117395Skan 5579117395Skan if (start_state->pass_num == curr_state_graph_pass_num) 5580117395Skan return; 5581117395Skan start_state->pass_num = curr_state_graph_pass_num; 5582117395Skan (*applied_func) (start_state); 5583117395Skan for (arc = first_out_arc (start_state); 5584117395Skan arc != NULL; 5585117395Skan arc = next_out_arc (arc)) 5586117395Skan pass_state_graph (arc->to_state, applied_func); 5587117395Skan} 5588117395Skan 5589117395Skan/* This recursive function passes all states of AUTOMATON and applies 5590117395Skan APPLIED_FUNC to them. */ 5591117395Skanstatic void 5592132718Skanpass_states (automaton_t automaton, void (*applied_func) (state_t state)) 5593117395Skan{ 5594117395Skan curr_state_graph_pass_num++; 5595117395Skan pass_state_graph (automaton->start_state, applied_func); 5596117395Skan} 5597117395Skan 5598117395Skan/* The function initializes code for passing of all states. */ 5599117395Skanstatic void 5600132718Skaninitiate_pass_states (void) 5601117395Skan{ 5602117395Skan curr_state_graph_pass_num = 0; 5603117395Skan} 5604117395Skan 5605117395Skan/* The following vla is used for storing pointers to all achieved 5606117395Skan states. */ 5607169689Skanstatic VEC(state_t,heap) *all_achieved_states; 5608117395Skan 5609117395Skan/* This function is called by function pass_states to add an achieved 5610117395Skan STATE. */ 5611117395Skanstatic void 5612132718Skanadd_achieved_state (state_t state) 5613117395Skan{ 5614169689Skan VEC_safe_push (state_t,heap, all_achieved_states, state); 5615117395Skan} 5616117395Skan 5617117395Skan/* The function sets up equivalence numbers of insns which mark all 5618117395Skan out arcs of STATE by equiv_class_num_1 (if ODD_ITERATION_FLAG has 5619117395Skan nonzero value) or by equiv_class_num_2 of the destination state. 5620117395Skan The function returns number of out arcs of STATE. */ 5621169689Skanstatic void 5622132718Skanset_out_arc_insns_equiv_num (state_t state, int odd_iteration_flag) 5623117395Skan{ 5624117395Skan arc_t arc; 5625117395Skan 5626117395Skan for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc)) 5627117395Skan { 5628169689Skan gcc_assert (!arc->insn->insn_reserv_decl->equiv_class_num); 5629117395Skan arc->insn->insn_reserv_decl->equiv_class_num 5630117395Skan = (odd_iteration_flag 5631117395Skan ? arc->to_state->equiv_class_num_1 5632117395Skan : arc->to_state->equiv_class_num_2); 5633169689Skan gcc_assert (arc->insn->insn_reserv_decl->equiv_class_num); 5634117395Skan } 5635117395Skan} 5636117395Skan 5637117395Skan/* The function clears equivalence numbers and alt_states in all insns 5638117395Skan which mark all out arcs of STATE. */ 5639117395Skanstatic void 5640132718Skanclear_arc_insns_equiv_num (state_t state) 5641117395Skan{ 5642117395Skan arc_t arc; 5643117395Skan 5644117395Skan for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc)) 5645169689Skan arc->insn->insn_reserv_decl->equiv_class_num = 0; 5646117395Skan} 5647117395Skan 5648117395Skan 5649132718Skan/* The following function returns TRUE if STATE reserves the unit with 5650132718Skan UNIT_NUM on the first cycle. */ 5651132718Skanstatic int 5652132718Skanfirst_cycle_unit_presence (state_t state, int unit_num) 5653132718Skan{ 5654169689Skan alt_state_t alt_state; 5655132718Skan 5656132718Skan if (state->component_states == NULL) 5657169689Skan return test_unit_reserv (state->reservs, 0, unit_num); 5658132718Skan else 5659169689Skan { 5660169689Skan for (alt_state = state->component_states; 5661169689Skan alt_state != NULL; 5662169689Skan alt_state = alt_state->next_sorted_alt_state) 5663169689Skan if (test_unit_reserv (alt_state->state->reservs, 0, unit_num)) 5664169689Skan return true; 5665169689Skan } 5666169689Skan return false; 5667132718Skan} 5668132718Skan 5669169689Skan/* This fills in the presence_signature[] member of STATE. */ 5670169689Skanstatic void 5671169689Skancache_presence (state_t state) 5672169689Skan{ 5673169689Skan int i, num = 0; 5674169689Skan unsigned int sz; 5675169689Skan sz = (description->query_units_num + sizeof (int) * CHAR_BIT - 1) 5676169689Skan / (sizeof (int) * CHAR_BIT); 5677169689Skan 5678169689Skan state->presence_signature = create_node (sz * sizeof (int)); 5679169689Skan for (i = 0; i < description->units_num; i++) 5680169689Skan if (units_array [i]->query_p) 5681169689Skan { 5682169689Skan int presence1_p = first_cycle_unit_presence (state, i); 5683169689Skan state->presence_signature[num / (sizeof (int) * CHAR_BIT)] 5684169689Skan |= (!!presence1_p) << (num % (sizeof (int) * CHAR_BIT)); 5685169689Skan num++; 5686169689Skan } 5687169689Skan} 5688169689Skan 5689117395Skan/* The function returns nonzero value if STATE is not equivalent to 5690132718Skan ANOTHER_STATE from the same current partition on equivalence 5691132718Skan classes. Another state has ANOTHER_STATE_OUT_ARCS_NUM number of 5692117395Skan output arcs. Iteration of making equivalence partition is defined 5693117395Skan by ODD_ITERATION_FLAG. */ 5694117395Skanstatic int 5695132718Skanstate_is_differed (state_t state, state_t another_state, 5696169689Skan int odd_iteration_flag) 5697117395Skan{ 5698117395Skan arc_t arc; 5699169689Skan unsigned int sz, si; 5700117395Skan 5701169689Skan gcc_assert (state->num_out_arcs == another_state->num_out_arcs); 5702169689Skan 5703169689Skan sz = (description->query_units_num + sizeof (int) * CHAR_BIT - 1) 5704169689Skan / (sizeof (int) * CHAR_BIT); 5705169689Skan 5706169689Skan for (si = 0; si < sz; si++) 5707169689Skan gcc_assert (state->presence_signature[si] 5708169689Skan == another_state->presence_signature[si]); 5709169689Skan 5710117395Skan for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc)) 5711117395Skan { 5712117395Skan if ((odd_iteration_flag 5713117395Skan ? arc->to_state->equiv_class_num_1 5714117395Skan : arc->to_state->equiv_class_num_2) 5715169689Skan != arc->insn->insn_reserv_decl->equiv_class_num) 5716117395Skan return 1; 5717117395Skan } 5718169689Skan 5719169689Skan return 0; 5720169689Skan} 5721169689Skan 5722169689Skan/* Compares two states pointed to by STATE_PTR_1 and STATE_PTR_2 5723169689Skan and return -1, 0 or 1. This function can be used as predicate for 5724169689Skan qsort(). It requires the member presence_signature[] of both 5725169689Skan states be filled. */ 5726169689Skanstatic int 5727169689Skancompare_states_for_equiv (const void *state_ptr_1, 5728169689Skan const void *state_ptr_2) 5729169689Skan{ 5730169689Skan state_t s1 = *(state_t *)state_ptr_1; 5731169689Skan state_t s2 = *(state_t *)state_ptr_2; 5732169689Skan unsigned int sz, si; 5733169689Skan if (s1->num_out_arcs < s2->num_out_arcs) 5734169689Skan return -1; 5735169689Skan else if (s1->num_out_arcs > s2->num_out_arcs) 5736132718Skan return 1; 5737169689Skan 5738169689Skan sz = (description->query_units_num + sizeof (int) * CHAR_BIT - 1) 5739169689Skan / (sizeof (int) * CHAR_BIT); 5740169689Skan 5741169689Skan for (si = 0; si < sz; si++) 5742169689Skan if (s1->presence_signature[si] < s2->presence_signature[si]) 5743169689Skan return -1; 5744169689Skan else if (s1->presence_signature[si] > s2->presence_signature[si]) 5745169689Skan return 1; 5746132718Skan return 0; 5747117395Skan} 5748117395Skan 5749117395Skan/* The function makes initial partition of STATES on equivalent 5750169689Skan classes and saves it into *CLASSES. This function requires the input 5751169689Skan to be sorted via compare_states_for_equiv(). */ 5752169689Skanstatic int 5753169689Skaninit_equiv_class (VEC(state_t,heap) *states, VEC (state_t,heap) **classes) 5754117395Skan{ 5755169689Skan size_t i; 5756169689Skan state_t prev = 0; 5757169689Skan int class_num = 1; 5758117395Skan 5759169689Skan *classes = VEC_alloc (state_t,heap, 150); 5760169689Skan for (i = 0; i < VEC_length (state_t, states); i++) 5761117395Skan { 5762169689Skan state_t state = VEC_index (state_t, states, i); 5763169689Skan if (prev) 5764169689Skan { 5765169689Skan if (compare_states_for_equiv (&prev, &state) != 0) 5766169689Skan { 5767169689Skan VEC_safe_push (state_t,heap, *classes, prev); 5768169689Skan class_num++; 5769169689Skan prev = NULL; 5770169689Skan } 5771169689Skan } 5772169689Skan state->equiv_class_num_1 = class_num; 5773169689Skan state->next_equiv_class_state = prev; 5774169689Skan prev = state; 5775117395Skan } 5776169689Skan if (prev) 5777169689Skan VEC_safe_push (state_t,heap, *classes, prev); 5778169689Skan return class_num; 5779117395Skan} 5780117395Skan 5781169689Skan/* The function copies pointers to equivalent states from vla FROM 5782169689Skan into vla TO. */ 5783169689Skanstatic void 5784169689Skancopy_equiv_class (VEC(state_t,heap) **to, VEC(state_t,heap) *from) 5785169689Skan{ 5786169689Skan VEC_free (state_t,heap, *to); 5787169689Skan *to = VEC_copy (state_t,heap, from); 5788169689Skan} 5789169689Skan 5790169689Skan/* The function processes equivalence class given by its first state, 5791169689Skan FIRST_STATE, on odd iteration if ODD_ITERATION_FLAG. If there 5792132718Skan are not equivalent states, the function partitions the class 5793117395Skan removing nonequivalent states and placing them in 5794117395Skan *NEXT_ITERATION_CLASSES, increments *NEW_EQUIV_CLASS_NUM_PTR ans 5795117395Skan assigns it to the state equivalence number. If the class has been 5796117395Skan partitioned, the function returns nonzero value. */ 5797117395Skanstatic int 5798169689Skanpartition_equiv_class (state_t first_state, int odd_iteration_flag, 5799169689Skan VEC(state_t,heap) **next_iteration_classes, 5800132718Skan int *new_equiv_class_num_ptr) 5801117395Skan{ 5802117395Skan state_t new_equiv_class; 5803117395Skan int partition_p; 5804117395Skan state_t curr_state; 5805117395Skan state_t prev_state; 5806117395Skan state_t next_state; 5807117395Skan 5808117395Skan partition_p = 0; 5809169689Skan 5810169689Skan while (first_state != NULL) 5811117395Skan { 5812117395Skan new_equiv_class = NULL; 5813117395Skan if (first_state->next_equiv_class_state != NULL) 5814117395Skan { 5815117395Skan /* There are more one states in the class equivalence. */ 5816169689Skan set_out_arc_insns_equiv_num (first_state, odd_iteration_flag); 5817117395Skan for (prev_state = first_state, 5818117395Skan curr_state = first_state->next_equiv_class_state; 5819117395Skan curr_state != NULL; 5820117395Skan curr_state = next_state) 5821117395Skan { 5822117395Skan next_state = curr_state->next_equiv_class_state; 5823169689Skan if (state_is_differed (curr_state, first_state, 5824117395Skan odd_iteration_flag)) 5825117395Skan { 5826117395Skan /* Remove curr state from the class equivalence. */ 5827117395Skan prev_state->next_equiv_class_state = next_state; 5828117395Skan /* Add curr state to the new class equivalence. */ 5829117395Skan curr_state->next_equiv_class_state = new_equiv_class; 5830117395Skan if (new_equiv_class == NULL) 5831117395Skan (*new_equiv_class_num_ptr)++; 5832117395Skan if (odd_iteration_flag) 5833117395Skan curr_state->equiv_class_num_2 = *new_equiv_class_num_ptr; 5834117395Skan else 5835117395Skan curr_state->equiv_class_num_1 = *new_equiv_class_num_ptr; 5836117395Skan new_equiv_class = curr_state; 5837117395Skan partition_p = 1; 5838117395Skan } 5839117395Skan else 5840117395Skan prev_state = curr_state; 5841117395Skan } 5842117395Skan clear_arc_insns_equiv_num (first_state); 5843117395Skan } 5844117395Skan if (new_equiv_class != NULL) 5845169689Skan VEC_safe_push (state_t,heap, *next_iteration_classes, new_equiv_class); 5846169689Skan first_state = new_equiv_class; 5847117395Skan } 5848117395Skan return partition_p; 5849117395Skan} 5850117395Skan 5851117395Skan/* The function finds equivalent states of AUTOMATON. */ 5852117395Skanstatic void 5853169689Skanevaluate_equiv_classes (automaton_t automaton, 5854169689Skan VEC(state_t,heap) **equiv_classes) 5855117395Skan{ 5856117395Skan int new_equiv_class_num; 5857117395Skan int odd_iteration_flag; 5858117395Skan int finish_flag; 5859169689Skan VEC (state_t,heap) *next_iteration_classes; 5860169689Skan size_t i; 5861132718Skan 5862169689Skan all_achieved_states = VEC_alloc (state_t,heap, 1500); 5863117395Skan pass_states (automaton, add_achieved_state); 5864169689Skan pass_states (automaton, cache_presence); 5865169689Skan qsort (VEC_address (state_t, all_achieved_states), 5866169689Skan VEC_length (state_t, all_achieved_states), 5867169689Skan sizeof (state_t), compare_states_for_equiv); 5868169689Skan 5869117395Skan odd_iteration_flag = 0; 5870169689Skan new_equiv_class_num = init_equiv_class (all_achieved_states, 5871169689Skan &next_iteration_classes); 5872169689Skan 5873117395Skan do 5874117395Skan { 5875117395Skan odd_iteration_flag = !odd_iteration_flag; 5876117395Skan finish_flag = 1; 5877169689Skan copy_equiv_class (equiv_classes, next_iteration_classes); 5878169689Skan 5879117395Skan /* Transfer equiv numbers for the next iteration. */ 5880169689Skan for (i = 0; i < VEC_length (state_t, all_achieved_states); i++) 5881117395Skan if (odd_iteration_flag) 5882169689Skan VEC_index (state_t, all_achieved_states, i)->equiv_class_num_2 5883169689Skan = VEC_index (state_t, all_achieved_states, i)->equiv_class_num_1; 5884117395Skan else 5885169689Skan VEC_index (state_t, all_achieved_states, i)->equiv_class_num_1 5886169689Skan = VEC_index (state_t, all_achieved_states, i)->equiv_class_num_2; 5887169689Skan 5888169689Skan for (i = 0; i < VEC_length (state_t, *equiv_classes); i++) 5889169689Skan if (partition_equiv_class (VEC_index (state_t, *equiv_classes, i), 5890169689Skan odd_iteration_flag, 5891117395Skan &next_iteration_classes, 5892117395Skan &new_equiv_class_num)) 5893117395Skan finish_flag = 0; 5894117395Skan } 5895117395Skan while (!finish_flag); 5896169689Skan VEC_free (state_t,heap, next_iteration_classes); 5897169689Skan VEC_free (state_t,heap, all_achieved_states); 5898117395Skan} 5899117395Skan 5900117395Skan/* The function merges equivalent states of AUTOMATON. */ 5901117395Skanstatic void 5902169689Skanmerge_states (automaton_t automaton, VEC(state_t,heap) *equiv_classes) 5903117395Skan{ 5904117395Skan state_t curr_state; 5905117395Skan state_t new_state; 5906117395Skan state_t first_class_state; 5907117395Skan alt_state_t alt_states; 5908132718Skan alt_state_t alt_state, new_alt_state; 5909117395Skan arc_t curr_arc; 5910117395Skan arc_t next_arc; 5911169689Skan size_t i; 5912117395Skan 5913117395Skan /* Create states corresponding to equivalence classes containing two 5914117395Skan or more states. */ 5915169689Skan for (i = 0; i < VEC_length (state_t, equiv_classes); i++) 5916169689Skan { 5917169689Skan curr_state = VEC_index (state_t, equiv_classes, i); 5918169689Skan if (curr_state->next_equiv_class_state != NULL) 5919169689Skan { 5920169689Skan /* There are more one states in the class equivalence. */ 5921169689Skan /* Create new compound state. */ 5922169689Skan new_state = get_free_state (0, automaton); 5923169689Skan alt_states = NULL; 5924169689Skan first_class_state = curr_state; 5925169689Skan for (curr_state = first_class_state; 5926169689Skan curr_state != NULL; 5927169689Skan curr_state = curr_state->next_equiv_class_state) 5928169689Skan { 5929169689Skan curr_state->equiv_class_state = new_state; 5930169689Skan if (curr_state->component_states == NULL) 5931132718Skan { 5932132718Skan new_alt_state = get_free_alt_state (); 5933169689Skan new_alt_state->state = curr_state; 5934132718Skan new_alt_state->next_alt_state = alt_states; 5935132718Skan alt_states = new_alt_state; 5936132718Skan } 5937169689Skan else 5938169689Skan for (alt_state = curr_state->component_states; 5939169689Skan alt_state != NULL; 5940169689Skan alt_state = alt_state->next_sorted_alt_state) 5941169689Skan { 5942169689Skan new_alt_state = get_free_alt_state (); 5943169689Skan new_alt_state->state = alt_state->state; 5944169689Skan new_alt_state->next_alt_state = alt_states; 5945169689Skan alt_states = new_alt_state; 5946169689Skan } 5947169689Skan } 5948169689Skan /* Its is important that alt states were sorted before and 5949169689Skan after merging to have the same querying results. */ 5950169689Skan new_state->component_states = uniq_sort_alt_states (alt_states); 5951169689Skan } 5952169689Skan else 5953169689Skan curr_state->equiv_class_state = curr_state; 5954169689Skan } 5955169689Skan 5956169689Skan for (i = 0; i < VEC_length (state_t, equiv_classes); i++) 5957169689Skan { 5958169689Skan curr_state = VEC_index (state_t, equiv_classes, i); 5959169689Skan if (curr_state->next_equiv_class_state != NULL) 5960169689Skan { 5961169689Skan first_class_state = curr_state; 5962169689Skan /* Create new arcs output from the state corresponding to 5963169689Skan equiv class. */ 5964169689Skan for (curr_arc = first_out_arc (first_class_state); 5965169689Skan curr_arc != NULL; 5966169689Skan curr_arc = next_out_arc (curr_arc)) 5967169689Skan add_arc (first_class_state->equiv_class_state, 5968169689Skan curr_arc->to_state->equiv_class_state, 5969169689Skan curr_arc->insn); 5970169689Skan /* Delete output arcs from states of given class equivalence. */ 5971169689Skan for (curr_state = first_class_state; 5972169689Skan curr_state != NULL; 5973169689Skan curr_state = curr_state->next_equiv_class_state) 5974169689Skan { 5975169689Skan if (automaton->start_state == curr_state) 5976169689Skan automaton->start_state = curr_state->equiv_class_state; 5977169689Skan /* Delete the state and its output arcs. */ 5978169689Skan for (curr_arc = first_out_arc (curr_state); 5979169689Skan curr_arc != NULL; 5980169689Skan curr_arc = next_arc) 5981169689Skan { 5982169689Skan next_arc = next_out_arc (curr_arc); 5983169689Skan free_arc (curr_arc); 5984169689Skan } 5985169689Skan } 5986169689Skan } 5987169689Skan else 5988169689Skan { 5989169689Skan /* Change `to_state' of arcs output from the state of given 5990169689Skan equivalence class. */ 5991169689Skan for (curr_arc = first_out_arc (curr_state); 5992169689Skan curr_arc != NULL; 5993169689Skan curr_arc = next_out_arc (curr_arc)) 5994169689Skan curr_arc->to_state = curr_arc->to_state->equiv_class_state; 5995169689Skan } 5996169689Skan } 5997117395Skan} 5998117395Skan 5999117395Skan/* The function sets up new_cycle_p for states if there is arc to the 6000117395Skan state marked by advance_cycle_insn_decl. */ 6001117395Skanstatic void 6002132718Skanset_new_cycle_flags (state_t state) 6003117395Skan{ 6004117395Skan arc_t arc; 6005117395Skan 6006117395Skan for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc)) 6007117395Skan if (arc->insn->insn_reserv_decl 6008117395Skan == DECL_INSN_RESERV (advance_cycle_insn_decl)) 6009117395Skan arc->to_state->new_cycle_p = 1; 6010117395Skan} 6011117395Skan 6012117395Skan/* The top level function for minimization of deterministic 6013117395Skan AUTOMATON. */ 6014117395Skanstatic void 6015132718Skanminimize_DFA (automaton_t automaton) 6016117395Skan{ 6017169689Skan VEC(state_t,heap) *equiv_classes = 0; 6018117395Skan 6019117395Skan evaluate_equiv_classes (automaton, &equiv_classes); 6020169689Skan merge_states (automaton, equiv_classes); 6021117395Skan pass_states (automaton, set_new_cycle_flags); 6022169689Skan 6023169689Skan VEC_free (state_t,heap, equiv_classes); 6024117395Skan} 6025117395Skan 6026117395Skan/* Values of two variables are counted number of states and arcs in an 6027117395Skan automaton. */ 6028117395Skanstatic int curr_counted_states_num; 6029117395Skanstatic int curr_counted_arcs_num; 6030117395Skan 6031117395Skan/* The function is called by function `pass_states' to count states 6032117395Skan and arcs of an automaton. */ 6033117395Skanstatic void 6034132718Skanincr_states_and_arcs_nums (state_t state) 6035117395Skan{ 6036117395Skan arc_t arc; 6037117395Skan 6038117395Skan curr_counted_states_num++; 6039117395Skan for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc)) 6040117395Skan curr_counted_arcs_num++; 6041117395Skan} 6042117395Skan 6043117395Skan/* The function counts states and arcs of AUTOMATON. */ 6044117395Skanstatic void 6045132718Skancount_states_and_arcs (automaton_t automaton, int *states_num, 6046132718Skan int *arcs_num) 6047117395Skan{ 6048117395Skan curr_counted_states_num = 0; 6049117395Skan curr_counted_arcs_num = 0; 6050117395Skan pass_states (automaton, incr_states_and_arcs_nums); 6051117395Skan *states_num = curr_counted_states_num; 6052117395Skan *arcs_num = curr_counted_arcs_num; 6053117395Skan} 6054117395Skan 6055117395Skan/* The function builds one DFA AUTOMATON for fast pipeline hazards 6056117395Skan recognition after checking and simplifying IR of the 6057117395Skan description. */ 6058117395Skanstatic void 6059132718Skanbuild_automaton (automaton_t automaton) 6060117395Skan{ 6061117395Skan int states_num; 6062117395Skan int arcs_num; 6063117395Skan 6064117395Skan ticker_on (&NDFA_time); 6065132718Skan if (progress_flag) 6066132718Skan { 6067132718Skan if (automaton->corresponding_automaton_decl == NULL) 6068132718Skan fprintf (stderr, "Create anonymous automaton"); 6069132718Skan else 6070132718Skan fprintf (stderr, "Create automaton `%s'", 6071132718Skan automaton->corresponding_automaton_decl->name); 6072132718Skan fprintf (stderr, " (1 dot is 100 new states):"); 6073132718Skan } 6074117395Skan make_automaton (automaton); 6075132718Skan if (progress_flag) 6076132718Skan fprintf (stderr, " done\n"); 6077117395Skan ticker_off (&NDFA_time); 6078117395Skan count_states_and_arcs (automaton, &states_num, &arcs_num); 6079117395Skan automaton->NDFA_states_num = states_num; 6080117395Skan automaton->NDFA_arcs_num = arcs_num; 6081117395Skan ticker_on (&NDFA_to_DFA_time); 6082132718Skan if (progress_flag) 6083132718Skan { 6084132718Skan if (automaton->corresponding_automaton_decl == NULL) 6085132718Skan fprintf (stderr, "Make anonymous DFA"); 6086132718Skan else 6087132718Skan fprintf (stderr, "Make DFA `%s'", 6088132718Skan automaton->corresponding_automaton_decl->name); 6089132718Skan fprintf (stderr, " (1 dot is 100 new states):"); 6090132718Skan } 6091117395Skan NDFA_to_DFA (automaton); 6092132718Skan if (progress_flag) 6093132718Skan fprintf (stderr, " done\n"); 6094117395Skan ticker_off (&NDFA_to_DFA_time); 6095117395Skan count_states_and_arcs (automaton, &states_num, &arcs_num); 6096117395Skan automaton->DFA_states_num = states_num; 6097117395Skan automaton->DFA_arcs_num = arcs_num; 6098117395Skan if (!no_minimization_flag) 6099117395Skan { 6100117395Skan ticker_on (&minimize_time); 6101132718Skan if (progress_flag) 6102132718Skan { 6103132718Skan if (automaton->corresponding_automaton_decl == NULL) 6104132718Skan fprintf (stderr, "Minimize anonymous DFA..."); 6105132718Skan else 6106132718Skan fprintf (stderr, "Minimize DFA `%s'...", 6107132718Skan automaton->corresponding_automaton_decl->name); 6108132718Skan } 6109117395Skan minimize_DFA (automaton); 6110132718Skan if (progress_flag) 6111132718Skan fprintf (stderr, "done\n"); 6112117395Skan ticker_off (&minimize_time); 6113117395Skan count_states_and_arcs (automaton, &states_num, &arcs_num); 6114117395Skan automaton->minimal_DFA_states_num = states_num; 6115117395Skan automaton->minimal_DFA_arcs_num = arcs_num; 6116117395Skan } 6117117395Skan} 6118117395Skan 6119117395Skan 6120117395Skan 6121117395Skan/* The page contains code for enumeration of all states of an automaton. */ 6122117395Skan 6123117395Skan/* Variable used for enumeration of all states of an automaton. Its 6124117395Skan value is current number of automaton states. */ 6125117395Skanstatic int curr_state_order_num; 6126117395Skan 6127117395Skan/* The function is called by function `pass_states' for enumerating 6128117395Skan states. */ 6129117395Skanstatic void 6130132718Skanset_order_state_num (state_t state) 6131117395Skan{ 6132117395Skan state->order_state_num = curr_state_order_num; 6133117395Skan curr_state_order_num++; 6134117395Skan} 6135117395Skan 6136117395Skan/* The function enumerates all states of AUTOMATON. */ 6137117395Skanstatic void 6138132718Skanenumerate_states (automaton_t automaton) 6139117395Skan{ 6140117395Skan curr_state_order_num = 0; 6141117395Skan pass_states (automaton, set_order_state_num); 6142117395Skan automaton->achieved_states_num = curr_state_order_num; 6143117395Skan} 6144117395Skan 6145117395Skan 6146117395Skan 6147117395Skan/* The page contains code for finding equivalent automaton insns 6148117395Skan (ainsns). */ 6149117395Skan 6150117395Skan/* The function inserts AINSN into cyclic list 6151117395Skan CYCLIC_EQUIV_CLASS_INSN_LIST of ainsns. */ 6152117395Skanstatic ainsn_t 6153132718Skaninsert_ainsn_into_equiv_class (ainsn_t ainsn, 6154132718Skan ainsn_t cyclic_equiv_class_insn_list) 6155117395Skan{ 6156117395Skan if (cyclic_equiv_class_insn_list == NULL) 6157117395Skan ainsn->next_equiv_class_insn = ainsn; 6158117395Skan else 6159117395Skan { 6160117395Skan ainsn->next_equiv_class_insn 6161117395Skan = cyclic_equiv_class_insn_list->next_equiv_class_insn; 6162117395Skan cyclic_equiv_class_insn_list->next_equiv_class_insn = ainsn; 6163117395Skan } 6164117395Skan return ainsn; 6165117395Skan} 6166117395Skan 6167117395Skan/* The function deletes equiv_class_insn into cyclic list of 6168117395Skan equivalent ainsns. */ 6169117395Skanstatic void 6170132718Skandelete_ainsn_from_equiv_class (ainsn_t equiv_class_insn) 6171117395Skan{ 6172117395Skan ainsn_t curr_equiv_class_insn; 6173117395Skan ainsn_t prev_equiv_class_insn; 6174117395Skan 6175117395Skan prev_equiv_class_insn = equiv_class_insn; 6176117395Skan for (curr_equiv_class_insn = equiv_class_insn->next_equiv_class_insn; 6177117395Skan curr_equiv_class_insn != equiv_class_insn; 6178117395Skan curr_equiv_class_insn = curr_equiv_class_insn->next_equiv_class_insn) 6179117395Skan prev_equiv_class_insn = curr_equiv_class_insn; 6180117395Skan if (prev_equiv_class_insn != equiv_class_insn) 6181117395Skan prev_equiv_class_insn->next_equiv_class_insn 6182117395Skan = equiv_class_insn->next_equiv_class_insn; 6183117395Skan} 6184117395Skan 6185117395Skan/* The function processes AINSN of a state in order to find equivalent 6186117395Skan ainsns. INSN_ARCS_ARRAY is table: code of insn -> out arc of the 6187117395Skan state. */ 6188117395Skanstatic void 6189132718Skanprocess_insn_equiv_class (ainsn_t ainsn, arc_t *insn_arcs_array) 6190117395Skan{ 6191117395Skan ainsn_t next_insn; 6192117395Skan ainsn_t curr_insn; 6193117395Skan ainsn_t cyclic_insn_list; 6194117395Skan arc_t arc; 6195117395Skan 6196169689Skan gcc_assert (insn_arcs_array [ainsn->insn_reserv_decl->insn_num]); 6197117395Skan curr_insn = ainsn; 6198117395Skan /* New class of ainsns which are not equivalent to given ainsn. */ 6199117395Skan cyclic_insn_list = NULL; 6200117395Skan do 6201117395Skan { 6202117395Skan next_insn = curr_insn->next_equiv_class_insn; 6203117395Skan arc = insn_arcs_array [curr_insn->insn_reserv_decl->insn_num]; 6204117395Skan if (arc == NULL 6205117395Skan || (insn_arcs_array [ainsn->insn_reserv_decl->insn_num]->to_state 6206117395Skan != arc->to_state)) 6207117395Skan { 6208117395Skan delete_ainsn_from_equiv_class (curr_insn); 6209117395Skan cyclic_insn_list = insert_ainsn_into_equiv_class (curr_insn, 6210117395Skan cyclic_insn_list); 6211117395Skan } 6212117395Skan curr_insn = next_insn; 6213117395Skan } 6214117395Skan while (curr_insn != ainsn); 6215117395Skan} 6216117395Skan 6217117395Skan/* The function processes STATE in order to find equivalent ainsns. */ 6218117395Skanstatic void 6219132718Skanprocess_state_for_insn_equiv_partition (state_t state) 6220117395Skan{ 6221117395Skan arc_t arc; 6222169689Skan arc_t *insn_arcs_array = XCNEWVEC (arc_t, description->insns_num); 6223117395Skan 6224117395Skan /* Process insns of the arcs. */ 6225117395Skan for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc)) 6226117395Skan insn_arcs_array [arc->insn->insn_reserv_decl->insn_num] = arc; 6227117395Skan for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc)) 6228117395Skan process_insn_equiv_class (arc->insn, insn_arcs_array); 6229169689Skan 6230169689Skan free (insn_arcs_array); 6231117395Skan} 6232117395Skan 6233117395Skan/* The function searches for equivalent ainsns of AUTOMATON. */ 6234117395Skanstatic void 6235132718Skanset_insn_equiv_classes (automaton_t automaton) 6236117395Skan{ 6237117395Skan ainsn_t ainsn; 6238117395Skan ainsn_t first_insn; 6239117395Skan ainsn_t curr_insn; 6240117395Skan ainsn_t cyclic_insn_list; 6241117395Skan ainsn_t insn_with_same_reservs; 6242117395Skan int equiv_classes_num; 6243117395Skan 6244117395Skan /* All insns are included in one equivalence class. */ 6245117395Skan cyclic_insn_list = NULL; 6246117395Skan for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn) 6247117395Skan if (ainsn->first_insn_with_same_reservs) 6248117395Skan cyclic_insn_list = insert_ainsn_into_equiv_class (ainsn, 6249117395Skan cyclic_insn_list); 6250117395Skan /* Process insns in order to make equivalence partition. */ 6251117395Skan pass_states (automaton, process_state_for_insn_equiv_partition); 6252117395Skan /* Enumerate equiv classes. */ 6253117395Skan for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn) 6254117395Skan /* Set undefined value. */ 6255117395Skan ainsn->insn_equiv_class_num = -1; 6256117395Skan equiv_classes_num = 0; 6257117395Skan for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn) 6258117395Skan if (ainsn->insn_equiv_class_num < 0) 6259117395Skan { 6260117395Skan first_insn = ainsn; 6261169689Skan gcc_assert (first_insn->first_insn_with_same_reservs); 6262169689Skan first_insn->first_ainsn_with_given_equivalence_num = 1; 6263117395Skan curr_insn = first_insn; 6264117395Skan do 6265117395Skan { 6266117395Skan for (insn_with_same_reservs = curr_insn; 6267117395Skan insn_with_same_reservs != NULL; 6268117395Skan insn_with_same_reservs 6269117395Skan = insn_with_same_reservs->next_same_reservs_insn) 6270117395Skan insn_with_same_reservs->insn_equiv_class_num = equiv_classes_num; 6271117395Skan curr_insn = curr_insn->next_equiv_class_insn; 6272117395Skan } 6273117395Skan while (curr_insn != first_insn); 6274117395Skan equiv_classes_num++; 6275117395Skan } 6276117395Skan automaton->insn_equiv_classes_num = equiv_classes_num; 6277117395Skan} 6278117395Skan 6279117395Skan 6280117395Skan 6281117395Skan/* This page contains code for creating DFA(s) and calls functions 6282117395Skan building them. */ 6283117395Skan 6284117395Skan 6285117395Skan/* The following value is used to prevent floating point overflow for 6286117395Skan estimating an automaton bound. The value should be less DBL_MAX on 6287117395Skan the host machine. We use here approximate minimum of maximal 6288117395Skan double floating point value required by ANSI C standard. It 6289117395Skan will work for non ANSI sun compiler too. */ 6290117395Skan 6291117395Skan#define MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND 1.0E37 6292117395Skan 6293117395Skan/* The function estimate size of the single DFA used by PHR (pipeline 6294117395Skan hazards recognizer). */ 6295117395Skanstatic double 6296132718Skanestimate_one_automaton_bound (void) 6297117395Skan{ 6298117395Skan decl_t decl; 6299117395Skan double one_automaton_estimation_bound; 6300117395Skan double root_value; 6301117395Skan int i; 6302117395Skan 6303117395Skan one_automaton_estimation_bound = 1.0; 6304117395Skan for (i = 0; i < description->decls_num; i++) 6305117395Skan { 6306117395Skan decl = description->decls [i]; 6307117395Skan if (decl->mode == dm_unit) 6308117395Skan { 6309132718Skan root_value = exp (log (DECL_UNIT (decl)->max_occ_cycle_num 6310132718Skan - DECL_UNIT (decl)->min_occ_cycle_num + 1.0) 6311117395Skan / automata_num); 6312117395Skan if (MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND / root_value 6313117395Skan > one_automaton_estimation_bound) 6314117395Skan one_automaton_estimation_bound *= root_value; 6315117395Skan } 6316117395Skan } 6317117395Skan return one_automaton_estimation_bound; 6318117395Skan} 6319117395Skan 6320132718Skan/* The function compares unit declarations according to their maximal 6321117395Skan cycle in reservations. */ 6322117395Skanstatic int 6323132718Skancompare_max_occ_cycle_nums (const void *unit_decl_1, 6324132718Skan const void *unit_decl_2) 6325117395Skan{ 6326117395Skan if ((DECL_UNIT (*(decl_t *) unit_decl_1)->max_occ_cycle_num) 6327117395Skan < (DECL_UNIT (*(decl_t *) unit_decl_2)->max_occ_cycle_num)) 6328117395Skan return 1; 6329117395Skan else if ((DECL_UNIT (*(decl_t *) unit_decl_1)->max_occ_cycle_num) 6330117395Skan == (DECL_UNIT (*(decl_t *) unit_decl_2)->max_occ_cycle_num)) 6331117395Skan return 0; 6332117395Skan else 6333117395Skan return -1; 6334117395Skan} 6335117395Skan 6336117395Skan/* The function makes heuristic assigning automata to units. Actually 6337117395Skan efficacy of the algorithm has been checked yet??? */ 6338169689Skan 6339117395Skanstatic void 6340132718Skanunits_to_automata_heuristic_distr (void) 6341117395Skan{ 6342117395Skan double estimation_bound; 6343117395Skan int automaton_num; 6344117395Skan int rest_units_num; 6345117395Skan double bound_value; 6346169689Skan unit_decl_t *unit_decls; 6347169689Skan int i, j; 6348117395Skan 6349117395Skan if (description->units_num == 0) 6350117395Skan return; 6351117395Skan estimation_bound = estimate_one_automaton_bound (); 6352169689Skan unit_decls = XNEWVEC (unit_decl_t, description->units_num); 6353169689Skan 6354169689Skan for (i = 0, j = 0; i < description->decls_num; i++) 6355169689Skan if (description->decls[i]->mode == dm_unit) 6356169689Skan unit_decls[j++] = DECL_UNIT (description->decls[i]); 6357169689Skan gcc_assert (j == description->units_num); 6358169689Skan 6359169689Skan qsort (unit_decls, description->units_num, 6360169689Skan sizeof (unit_decl_t), compare_max_occ_cycle_nums); 6361169689Skan 6362117395Skan automaton_num = 0; 6363169689Skan bound_value = unit_decls[0]->max_occ_cycle_num; 6364169689Skan unit_decls[0]->corresponding_automaton_num = automaton_num; 6365169689Skan 6366169689Skan for (i = 1; i < description->units_num; i++) 6367117395Skan { 6368169689Skan rest_units_num = description->units_num - i + 1; 6369169689Skan gcc_assert (automata_num - automaton_num - 1 <= rest_units_num); 6370117395Skan if (automaton_num < automata_num - 1 6371117395Skan && ((automata_num - automaton_num - 1 == rest_units_num) 6372117395Skan || (bound_value 6373117395Skan > (estimation_bound 6374169689Skan / unit_decls[i]->max_occ_cycle_num)))) 6375117395Skan { 6376169689Skan bound_value = unit_decls[i]->max_occ_cycle_num; 6377117395Skan automaton_num++; 6378117395Skan } 6379117395Skan else 6380169689Skan bound_value *= unit_decls[i]->max_occ_cycle_num; 6381169689Skan unit_decls[i]->corresponding_automaton_num = automaton_num; 6382117395Skan } 6383169689Skan gcc_assert (automaton_num == automata_num - 1); 6384169689Skan free (unit_decls); 6385117395Skan} 6386117395Skan 6387117395Skan/* The functions creates automaton insns for each automata. Automaton 6388117395Skan insn is simply insn for given automaton which makes reservation 6389117395Skan only of units of the automaton. */ 6390117395Skanstatic ainsn_t 6391132718Skancreate_ainsns (void) 6392117395Skan{ 6393117395Skan decl_t decl; 6394117395Skan ainsn_t first_ainsn; 6395117395Skan ainsn_t curr_ainsn; 6396117395Skan ainsn_t prev_ainsn; 6397117395Skan int i; 6398117395Skan 6399117395Skan first_ainsn = NULL; 6400117395Skan prev_ainsn = NULL; 6401117395Skan for (i = 0; i < description->decls_num; i++) 6402117395Skan { 6403117395Skan decl = description->decls [i]; 6404117395Skan if (decl->mode == dm_insn_reserv) 6405117395Skan { 6406117395Skan curr_ainsn = create_node (sizeof (struct ainsn)); 6407117395Skan curr_ainsn->insn_reserv_decl = DECL_INSN_RESERV (decl); 6408117395Skan curr_ainsn->important_p = FALSE; 6409117395Skan curr_ainsn->next_ainsn = NULL; 6410117395Skan if (prev_ainsn == NULL) 6411117395Skan first_ainsn = curr_ainsn; 6412117395Skan else 6413117395Skan prev_ainsn->next_ainsn = curr_ainsn; 6414117395Skan prev_ainsn = curr_ainsn; 6415117395Skan } 6416117395Skan } 6417117395Skan return first_ainsn; 6418117395Skan} 6419117395Skan 6420117395Skan/* The function assigns automata to units according to constructions 6421117395Skan `define_automaton' in the description. */ 6422117395Skanstatic void 6423132718Skanunits_to_automata_distr (void) 6424117395Skan{ 6425117395Skan decl_t decl; 6426117395Skan int i; 6427132718Skan 6428117395Skan for (i = 0; i < description->decls_num; i++) 6429117395Skan { 6430117395Skan decl = description->decls [i]; 6431117395Skan if (decl->mode == dm_unit) 6432117395Skan { 6433117395Skan if (DECL_UNIT (decl)->automaton_decl == NULL 6434117395Skan || (DECL_UNIT (decl)->automaton_decl->corresponding_automaton 6435117395Skan == NULL)) 6436117395Skan /* Distribute to the first automaton. */ 6437117395Skan DECL_UNIT (decl)->corresponding_automaton_num = 0; 6438117395Skan else 6439117395Skan DECL_UNIT (decl)->corresponding_automaton_num 6440117395Skan = (DECL_UNIT (decl)->automaton_decl 6441117395Skan ->corresponding_automaton->automaton_order_num); 6442117395Skan } 6443117395Skan } 6444117395Skan} 6445117395Skan 6446117395Skan/* The function creates DFA(s) for fast pipeline hazards recognition 6447117395Skan after checking and simplifying IR of the description. */ 6448117395Skanstatic void 6449132718Skancreate_automata (void) 6450117395Skan{ 6451117395Skan automaton_t curr_automaton; 6452117395Skan automaton_t prev_automaton; 6453117395Skan decl_t decl; 6454117395Skan int curr_automaton_num; 6455117395Skan int i; 6456117395Skan 6457117395Skan if (automata_num != 0) 6458117395Skan { 6459117395Skan units_to_automata_heuristic_distr (); 6460117395Skan for (prev_automaton = NULL, curr_automaton_num = 0; 6461117395Skan curr_automaton_num < automata_num; 6462117395Skan curr_automaton_num++, prev_automaton = curr_automaton) 6463117395Skan { 6464117395Skan curr_automaton = create_node (sizeof (struct automaton)); 6465117395Skan curr_automaton->ainsn_list = create_ainsns (); 6466117395Skan curr_automaton->corresponding_automaton_decl = NULL; 6467117395Skan curr_automaton->next_automaton = NULL; 6468117395Skan curr_automaton->automaton_order_num = curr_automaton_num; 6469117395Skan if (prev_automaton == NULL) 6470117395Skan description->first_automaton = curr_automaton; 6471117395Skan else 6472117395Skan prev_automaton->next_automaton = curr_automaton; 6473117395Skan } 6474117395Skan } 6475117395Skan else 6476117395Skan { 6477117395Skan curr_automaton_num = 0; 6478117395Skan prev_automaton = NULL; 6479117395Skan for (i = 0; i < description->decls_num; i++) 6480117395Skan { 6481117395Skan decl = description->decls [i]; 6482117395Skan if (decl->mode == dm_automaton 6483117395Skan && DECL_AUTOMATON (decl)->automaton_is_used) 6484117395Skan { 6485117395Skan curr_automaton = create_node (sizeof (struct automaton)); 6486117395Skan curr_automaton->ainsn_list = create_ainsns (); 6487117395Skan curr_automaton->corresponding_automaton_decl 6488117395Skan = DECL_AUTOMATON (decl); 6489117395Skan curr_automaton->next_automaton = NULL; 6490117395Skan DECL_AUTOMATON (decl)->corresponding_automaton = curr_automaton; 6491117395Skan curr_automaton->automaton_order_num = curr_automaton_num; 6492117395Skan if (prev_automaton == NULL) 6493117395Skan description->first_automaton = curr_automaton; 6494117395Skan else 6495117395Skan prev_automaton->next_automaton = curr_automaton; 6496117395Skan curr_automaton_num++; 6497117395Skan prev_automaton = curr_automaton; 6498117395Skan } 6499117395Skan } 6500117395Skan if (curr_automaton_num == 0) 6501117395Skan { 6502117395Skan curr_automaton = create_node (sizeof (struct automaton)); 6503117395Skan curr_automaton->ainsn_list = create_ainsns (); 6504117395Skan curr_automaton->corresponding_automaton_decl = NULL; 6505117395Skan curr_automaton->next_automaton = NULL; 6506117395Skan description->first_automaton = curr_automaton; 6507117395Skan } 6508117395Skan units_to_automata_distr (); 6509117395Skan } 6510117395Skan NDFA_time = create_ticker (); 6511117395Skan ticker_off (&NDFA_time); 6512117395Skan NDFA_to_DFA_time = create_ticker (); 6513117395Skan ticker_off (&NDFA_to_DFA_time); 6514117395Skan minimize_time = create_ticker (); 6515117395Skan ticker_off (&minimize_time); 6516117395Skan equiv_time = create_ticker (); 6517117395Skan ticker_off (&equiv_time); 6518117395Skan for (curr_automaton = description->first_automaton; 6519117395Skan curr_automaton != NULL; 6520117395Skan curr_automaton = curr_automaton->next_automaton) 6521117395Skan { 6522132718Skan if (progress_flag) 6523132718Skan { 6524132718Skan if (curr_automaton->corresponding_automaton_decl == NULL) 6525132718Skan fprintf (stderr, "Prepare anonymous automaton creation ... "); 6526132718Skan else 6527132718Skan fprintf (stderr, "Prepare automaton `%s' creation...", 6528132718Skan curr_automaton->corresponding_automaton_decl->name); 6529132718Skan } 6530117395Skan create_alt_states (curr_automaton); 6531117395Skan form_ainsn_with_same_reservs (curr_automaton); 6532132718Skan if (progress_flag) 6533132718Skan fprintf (stderr, "done\n"); 6534117395Skan build_automaton (curr_automaton); 6535117395Skan enumerate_states (curr_automaton); 6536117395Skan ticker_on (&equiv_time); 6537117395Skan set_insn_equiv_classes (curr_automaton); 6538117395Skan ticker_off (&equiv_time); 6539117395Skan } 6540117395Skan} 6541117395Skan 6542117395Skan 6543117395Skan 6544117395Skan/* This page contains code for forming string representation of 6545117395Skan regexp. The representation is formed on IR obstack. So you should 6546117395Skan not work with IR obstack between regexp_representation and 6547117395Skan finish_regexp_representation calls. */ 6548117395Skan 6549117395Skan/* This recursive function forms string representation of regexp 6550117395Skan (without tailing '\0'). */ 6551117395Skanstatic void 6552132718Skanform_regexp (regexp_t regexp) 6553117395Skan{ 6554117395Skan int i; 6555132718Skan 6556169689Skan switch (regexp->mode) 6557117395Skan { 6558169689Skan case rm_unit: case rm_reserv: 6559117395Skan { 6560169689Skan const char *name = (regexp->mode == rm_unit 6561169689Skan ? REGEXP_UNIT (regexp)->name 6562169689Skan : REGEXP_RESERV (regexp)->name); 6563169689Skan 6564169689Skan obstack_grow (&irp, name, strlen (name)); 6565169689Skan break; 6566117395Skan } 6567169689Skan 6568169689Skan case rm_sequence: 6569169689Skan for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++) 6570169689Skan { 6571169689Skan if (i != 0) 6572169689Skan obstack_1grow (&irp, ','); 6573169689Skan form_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]); 6574169689Skan } 6575169689Skan break; 6576169689Skan 6577169689Skan case rm_allof: 6578117395Skan obstack_1grow (&irp, '('); 6579117395Skan for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++) 6580117395Skan { 6581117395Skan if (i != 0) 6582117395Skan obstack_1grow (&irp, '+'); 6583117395Skan if (REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_sequence 6584117395Skan || REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_oneof) 6585117395Skan obstack_1grow (&irp, '('); 6586117395Skan form_regexp (REGEXP_ALLOF (regexp)->regexps [i]); 6587117395Skan if (REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_sequence 6588117395Skan || REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_oneof) 6589117395Skan obstack_1grow (&irp, ')'); 6590117395Skan } 6591117395Skan obstack_1grow (&irp, ')'); 6592169689Skan break; 6593169689Skan 6594169689Skan case rm_oneof: 6595169689Skan for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++) 6596169689Skan { 6597169689Skan if (i != 0) 6598169689Skan obstack_1grow (&irp, '|'); 6599169689Skan if (REGEXP_ONEOF (regexp)->regexps[i]->mode == rm_sequence) 6600169689Skan obstack_1grow (&irp, '('); 6601169689Skan form_regexp (REGEXP_ONEOF (regexp)->regexps [i]); 6602169689Skan if (REGEXP_ONEOF (regexp)->regexps[i]->mode == rm_sequence) 6603169689Skan obstack_1grow (&irp, ')'); 6604169689Skan } 6605169689Skan break; 6606169689Skan 6607169689Skan case rm_repeat: 6608117395Skan { 6609169689Skan char digits [30]; 6610169689Skan 6611169689Skan if (REGEXP_REPEAT (regexp)->regexp->mode == rm_sequence 6612169689Skan || REGEXP_REPEAT (regexp)->regexp->mode == rm_allof 6613169689Skan || REGEXP_REPEAT (regexp)->regexp->mode == rm_oneof) 6614169689Skan obstack_1grow (&irp, '('); 6615169689Skan form_regexp (REGEXP_REPEAT (regexp)->regexp); 6616169689Skan if (REGEXP_REPEAT (regexp)->regexp->mode == rm_sequence 6617169689Skan || REGEXP_REPEAT (regexp)->regexp->mode == rm_allof 6618169689Skan || REGEXP_REPEAT (regexp)->regexp->mode == rm_oneof) 6619169689Skan obstack_1grow (&irp, ')'); 6620169689Skan sprintf (digits, "*%d", REGEXP_REPEAT (regexp)->repeat_num); 6621169689Skan obstack_grow (&irp, digits, strlen (digits)); 6622169689Skan break; 6623117395Skan } 6624117395Skan 6625169689Skan case rm_nothing: 6626169689Skan obstack_grow (&irp, NOTHING_NAME, strlen (NOTHING_NAME)); 6627169689Skan break; 6628169689Skan 6629169689Skan default: 6630169689Skan gcc_unreachable (); 6631117395Skan } 6632117395Skan} 6633117395Skan 6634117395Skan/* The function returns string representation of REGEXP on IR 6635117395Skan obstack. */ 6636117395Skanstatic const char * 6637132718Skanregexp_representation (regexp_t regexp) 6638117395Skan{ 6639117395Skan form_regexp (regexp); 6640117395Skan obstack_1grow (&irp, '\0'); 6641117395Skan return obstack_base (&irp); 6642117395Skan} 6643117395Skan 6644117395Skan/* The function frees memory allocated for last formed string 6645117395Skan representation of regexp. */ 6646117395Skanstatic void 6647132718Skanfinish_regexp_representation (void) 6648117395Skan{ 6649117395Skan int length = obstack_object_size (&irp); 6650132718Skan 6651117395Skan obstack_blank_fast (&irp, -length); 6652117395Skan} 6653117395Skan 6654117395Skan 6655117395Skan 6656117395Skan/* This page contains code for output PHR (pipeline hazards recognizer). */ 6657117395Skan 6658117395Skan/* The function outputs minimal C type which is sufficient for 6659117395Skan representation numbers in range min_range_value and 6660117395Skan max_range_value. Because host machine and build machine may be 6661117395Skan different, we use here minimal values required by ANSI C standard 6662117395Skan instead of UCHAR_MAX, SHRT_MAX, SHRT_MIN, etc. This is a good 6663117395Skan approximation. */ 6664117395Skan 6665117395Skanstatic void 6666132718Skanoutput_range_type (FILE *f, long int min_range_value, 6667132718Skan long int max_range_value) 6668117395Skan{ 6669117395Skan if (min_range_value >= 0 && max_range_value <= 255) 6670117395Skan fprintf (f, "unsigned char"); 6671117395Skan else if (min_range_value >= -127 && max_range_value <= 127) 6672117395Skan fprintf (f, "signed char"); 6673117395Skan else if (min_range_value >= 0 && max_range_value <= 65535) 6674117395Skan fprintf (f, "unsigned short"); 6675117395Skan else if (min_range_value >= -32767 && max_range_value <= 32767) 6676117395Skan fprintf (f, "short"); 6677117395Skan else 6678117395Skan fprintf (f, "int"); 6679117395Skan} 6680117395Skan 6681117395Skan/* The following macro value is used as value of member 6682117395Skan `longest_path_length' of state when we are processing path and the 6683117395Skan state on the path. */ 6684117395Skan 6685117395Skan#define ON_THE_PATH -2 6686117395Skan 6687117395Skan/* The following recursive function searches for the length of the 6688117395Skan longest path starting from STATE which does not contain cycles and 6689117395Skan `cycle advance' arcs. */ 6690117395Skan 6691117395Skanstatic int 6692132718Skanlongest_path_length (state_t state) 6693117395Skan{ 6694117395Skan arc_t arc; 6695117395Skan int length, result; 6696132718Skan 6697169689Skan if (state->longest_path_length != UNDEFINED_LONGEST_PATH_LENGTH) 6698169689Skan { 6699169689Skan /* We don't expect the path cycle here. Our graph may contain 6700169689Skan only cycles with one state on the path not containing `cycle 6701169689Skan advance' arcs -- see comment below. */ 6702169689Skan gcc_assert (state->longest_path_length != ON_THE_PATH); 6703169689Skan 6704169689Skan /* We already visited the state. */ 6705169689Skan return state->longest_path_length; 6706169689Skan } 6707117395Skan 6708117395Skan result = 0; 6709117395Skan for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc)) 6710117395Skan /* Ignore cycles containing one state and `cycle advance' arcs. */ 6711117395Skan if (arc->to_state != state 6712117395Skan && (arc->insn->insn_reserv_decl 6713117395Skan != DECL_INSN_RESERV (advance_cycle_insn_decl))) 6714117395Skan { 6715117395Skan length = longest_path_length (arc->to_state); 6716117395Skan if (length > result) 6717117395Skan result = length; 6718117395Skan } 6719117395Skan state->longest_path_length = result + 1; 6720117395Skan return result; 6721117395Skan} 6722117395Skan 6723169689Skan/* The function outputs all initialization values of VECT. */ 6724117395Skanstatic void 6725169689Skanoutput_vect (vla_hwint_t vect) 6726117395Skan{ 6727117395Skan int els_on_line; 6728169689Skan size_t vect_length = VEC_length (vect_el_t, vect); 6729169689Skan size_t i; 6730117395Skan 6731117395Skan els_on_line = 1; 6732117395Skan if (vect_length == 0) 6733169689Skan fputs ("0 /* This is dummy el because the vect is empty */", output_file); 6734117395Skan else 6735169689Skan for (i = 0; i < vect_length; i++) 6736169689Skan { 6737169689Skan fprintf (output_file, "%5ld", (long) VEC_index (vect_el_t, vect, i)); 6738169689Skan if (els_on_line == 10) 6739169689Skan { 6740169689Skan els_on_line = 0; 6741169689Skan fputs (",\n", output_file); 6742169689Skan } 6743169689Skan else if (i < vect_length-1) 6744169689Skan fputs (", ", output_file); 6745169689Skan els_on_line++; 6746169689Skan } 6747117395Skan} 6748117395Skan 6749117395Skan/* The following is name of the structure which represents DFA(s) for 6750117395Skan PHR. */ 6751117395Skan#define CHIP_NAME "DFA_chip" 6752117395Skan 6753117395Skan/* The following is name of member which represents state of a DFA for 6754117395Skan PHR. */ 6755117395Skanstatic void 6756132718Skanoutput_chip_member_name (FILE *f, automaton_t automaton) 6757117395Skan{ 6758117395Skan if (automaton->corresponding_automaton_decl == NULL) 6759117395Skan fprintf (f, "automaton_state_%d", automaton->automaton_order_num); 6760117395Skan else 6761117395Skan fprintf (f, "%s_automaton_state", 6762117395Skan automaton->corresponding_automaton_decl->name); 6763117395Skan} 6764117395Skan 6765117395Skan/* The following is name of temporary variable which stores state of a 6766117395Skan DFA for PHR. */ 6767117395Skanstatic void 6768132718Skanoutput_temp_chip_member_name (FILE *f, automaton_t automaton) 6769117395Skan{ 6770117395Skan fprintf (f, "_"); 6771117395Skan output_chip_member_name (f, automaton); 6772117395Skan} 6773117395Skan 6774117395Skan/* This is name of macro value which is code of pseudo_insn 6775117395Skan representing advancing cpu cycle. Its value is used as internal 6776117395Skan code unknown insn. */ 6777117395Skan#define ADVANCE_CYCLE_VALUE_NAME "DFA__ADVANCE_CYCLE" 6778117395Skan 6779117395Skan/* Output name of translate vector for given automaton. */ 6780117395Skanstatic void 6781132718Skanoutput_translate_vect_name (FILE *f, automaton_t automaton) 6782117395Skan{ 6783117395Skan if (automaton->corresponding_automaton_decl == NULL) 6784117395Skan fprintf (f, "translate_%d", automaton->automaton_order_num); 6785117395Skan else 6786117395Skan fprintf (f, "%s_translate", automaton->corresponding_automaton_decl->name); 6787117395Skan} 6788117395Skan 6789117395Skan/* Output name for simple transition table representation. */ 6790117395Skanstatic void 6791132718Skanoutput_trans_full_vect_name (FILE *f, automaton_t automaton) 6792117395Skan{ 6793117395Skan if (automaton->corresponding_automaton_decl == NULL) 6794117395Skan fprintf (f, "transitions_%d", automaton->automaton_order_num); 6795117395Skan else 6796117395Skan fprintf (f, "%s_transitions", 6797117395Skan automaton->corresponding_automaton_decl->name); 6798117395Skan} 6799117395Skan 6800117395Skan/* Output name of comb vector of the transition table for given 6801117395Skan automaton. */ 6802117395Skanstatic void 6803132718Skanoutput_trans_comb_vect_name (FILE *f, automaton_t automaton) 6804117395Skan{ 6805117395Skan if (automaton->corresponding_automaton_decl == NULL) 6806117395Skan fprintf (f, "transitions_%d", automaton->automaton_order_num); 6807117395Skan else 6808117395Skan fprintf (f, "%s_transitions", 6809117395Skan automaton->corresponding_automaton_decl->name); 6810117395Skan} 6811117395Skan 6812117395Skan/* Output name of check vector of the transition table for given 6813117395Skan automaton. */ 6814117395Skanstatic void 6815132718Skanoutput_trans_check_vect_name (FILE *f, automaton_t automaton) 6816117395Skan{ 6817117395Skan if (automaton->corresponding_automaton_decl == NULL) 6818117395Skan fprintf (f, "check_%d", automaton->automaton_order_num); 6819117395Skan else 6820117395Skan fprintf (f, "%s_check", automaton->corresponding_automaton_decl->name); 6821117395Skan} 6822117395Skan 6823117395Skan/* Output name of base vector of the transition table for given 6824117395Skan automaton. */ 6825117395Skanstatic void 6826132718Skanoutput_trans_base_vect_name (FILE *f, automaton_t automaton) 6827117395Skan{ 6828117395Skan if (automaton->corresponding_automaton_decl == NULL) 6829117395Skan fprintf (f, "base_%d", automaton->automaton_order_num); 6830117395Skan else 6831117395Skan fprintf (f, "%s_base", automaton->corresponding_automaton_decl->name); 6832117395Skan} 6833117395Skan 6834117395Skan/* Output name of simple min issue delay table representation. */ 6835117395Skanstatic void 6836132718Skanoutput_min_issue_delay_vect_name (FILE *f, automaton_t automaton) 6837117395Skan{ 6838117395Skan if (automaton->corresponding_automaton_decl == NULL) 6839117395Skan fprintf (f, "min_issue_delay_%d", automaton->automaton_order_num); 6840117395Skan else 6841117395Skan fprintf (f, "%s_min_issue_delay", 6842117395Skan automaton->corresponding_automaton_decl->name); 6843117395Skan} 6844117395Skan 6845117395Skan/* Output name of deadlock vector for given automaton. */ 6846117395Skanstatic void 6847132718Skanoutput_dead_lock_vect_name (FILE *f, automaton_t automaton) 6848117395Skan{ 6849117395Skan if (automaton->corresponding_automaton_decl == NULL) 6850117395Skan fprintf (f, "dead_lock_%d", automaton->automaton_order_num); 6851117395Skan else 6852117395Skan fprintf (f, "%s_dead_lock", automaton->corresponding_automaton_decl->name); 6853117395Skan} 6854117395Skan 6855117395Skan/* Output name of reserved units table for AUTOMATON into file F. */ 6856117395Skanstatic void 6857132718Skanoutput_reserved_units_table_name (FILE *f, automaton_t automaton) 6858117395Skan{ 6859117395Skan if (automaton->corresponding_automaton_decl == NULL) 6860117395Skan fprintf (f, "reserved_units_%d", automaton->automaton_order_num); 6861117395Skan else 6862117395Skan fprintf (f, "%s_reserved_units", 6863117395Skan automaton->corresponding_automaton_decl->name); 6864117395Skan} 6865117395Skan 6866117395Skan/* Name of the PHR interface macro. */ 6867117395Skan#define CPU_UNITS_QUERY_MACRO_NAME "CPU_UNITS_QUERY" 6868117395Skan 6869117395Skan/* Names of an internal functions: */ 6870117395Skan#define INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME "internal_min_issue_delay" 6871117395Skan 6872117395Skan/* This is external type of DFA(s) state. */ 6873117395Skan#define STATE_TYPE_NAME "state_t" 6874117395Skan 6875117395Skan#define INTERNAL_TRANSITION_FUNC_NAME "internal_state_transition" 6876117395Skan 6877117395Skan#define INTERNAL_RESET_FUNC_NAME "internal_reset" 6878117395Skan 6879117395Skan#define INTERNAL_DEAD_LOCK_FUNC_NAME "internal_state_dead_lock_p" 6880117395Skan 6881117395Skan#define INTERNAL_INSN_LATENCY_FUNC_NAME "internal_insn_latency" 6882117395Skan 6883117395Skan/* Name of cache of insn dfa codes. */ 6884117395Skan#define DFA_INSN_CODES_VARIABLE_NAME "dfa_insn_codes" 6885117395Skan 6886117395Skan/* Name of length of cache of insn dfa codes. */ 6887117395Skan#define DFA_INSN_CODES_LENGTH_VARIABLE_NAME "dfa_insn_codes_length" 6888117395Skan 6889117395Skan/* Names of the PHR interface functions: */ 6890117395Skan#define SIZE_FUNC_NAME "state_size" 6891117395Skan 6892117395Skan#define TRANSITION_FUNC_NAME "state_transition" 6893117395Skan 6894117395Skan#define MIN_ISSUE_DELAY_FUNC_NAME "min_issue_delay" 6895117395Skan 6896117395Skan#define MIN_INSN_CONFLICT_DELAY_FUNC_NAME "min_insn_conflict_delay" 6897117395Skan 6898117395Skan#define DEAD_LOCK_FUNC_NAME "state_dead_lock_p" 6899117395Skan 6900117395Skan#define RESET_FUNC_NAME "state_reset" 6901117395Skan 6902117395Skan#define INSN_LATENCY_FUNC_NAME "insn_latency" 6903117395Skan 6904117395Skan#define PRINT_RESERVATION_FUNC_NAME "print_reservation" 6905117395Skan 6906117395Skan#define GET_CPU_UNIT_CODE_FUNC_NAME "get_cpu_unit_code" 6907117395Skan 6908117395Skan#define CPU_UNIT_RESERVATION_P_FUNC_NAME "cpu_unit_reservation_p" 6909117395Skan 6910132718Skan#define DFA_CLEAN_INSN_CACHE_FUNC_NAME "dfa_clean_insn_cache" 6911132718Skan 6912169689Skan#define DFA_CLEAR_SINGLE_INSN_CACHE_FUNC_NAME "dfa_clear_single_insn_cache" 6913169689Skan 6914117395Skan#define DFA_START_FUNC_NAME "dfa_start" 6915117395Skan 6916117395Skan#define DFA_FINISH_FUNC_NAME "dfa_finish" 6917117395Skan 6918117395Skan/* Names of parameters of the PHR interface functions. */ 6919117395Skan#define STATE_NAME "state" 6920117395Skan 6921117395Skan#define INSN_PARAMETER_NAME "insn" 6922117395Skan 6923117395Skan#define INSN2_PARAMETER_NAME "insn2" 6924117395Skan 6925117395Skan#define CHIP_PARAMETER_NAME "chip" 6926117395Skan 6927117395Skan#define FILE_PARAMETER_NAME "f" 6928117395Skan 6929117395Skan#define CPU_UNIT_NAME_PARAMETER_NAME "cpu_unit_name" 6930117395Skan 6931117395Skan#define CPU_CODE_PARAMETER_NAME "cpu_unit_code" 6932117395Skan 6933117395Skan/* Names of the variables whose values are internal insn code of rtx 6934117395Skan insn. */ 6935117395Skan#define INTERNAL_INSN_CODE_NAME "insn_code" 6936117395Skan 6937117395Skan#define INTERNAL_INSN2_CODE_NAME "insn2_code" 6938117395Skan 6939117395Skan/* Names of temporary variables in some functions. */ 6940117395Skan#define TEMPORARY_VARIABLE_NAME "temp" 6941117395Skan 6942117395Skan#define I_VARIABLE_NAME "i" 6943117395Skan 6944117395Skan/* Name of result variable in some functions. */ 6945117395Skan#define RESULT_VARIABLE_NAME "res" 6946117395Skan 6947117395Skan/* Name of function (attribute) to translate insn into internal insn 6948117395Skan code. */ 6949117395Skan#define INTERNAL_DFA_INSN_CODE_FUNC_NAME "internal_dfa_insn_code" 6950117395Skan 6951117395Skan/* Name of function (attribute) to translate insn into internal insn 6952117395Skan code with caching. */ 6953117395Skan#define DFA_INSN_CODE_FUNC_NAME "dfa_insn_code" 6954117395Skan 6955117395Skan/* Output C type which is used for representation of codes of states 6956117395Skan of AUTOMATON. */ 6957117395Skanstatic void 6958132718Skanoutput_state_member_type (FILE *f, automaton_t automaton) 6959117395Skan{ 6960117395Skan output_range_type (f, 0, automaton->achieved_states_num); 6961117395Skan} 6962117395Skan 6963117395Skan/* Output definition of the structure representing current DFA(s) 6964117395Skan state(s). */ 6965117395Skanstatic void 6966132718Skanoutput_chip_definitions (void) 6967117395Skan{ 6968117395Skan automaton_t automaton; 6969117395Skan 6970117395Skan fprintf (output_file, "struct %s\n{\n", CHIP_NAME); 6971117395Skan for (automaton = description->first_automaton; 6972117395Skan automaton != NULL; 6973117395Skan automaton = automaton->next_automaton) 6974117395Skan { 6975117395Skan fprintf (output_file, " "); 6976117395Skan output_state_member_type (output_file, automaton); 6977117395Skan fprintf (output_file, " "); 6978117395Skan output_chip_member_name (output_file, automaton); 6979117395Skan fprintf (output_file, ";\n"); 6980117395Skan } 6981117395Skan fprintf (output_file, "};\n\n"); 6982117395Skan#if 0 6983117395Skan fprintf (output_file, "static struct %s %s;\n\n", CHIP_NAME, CHIP_NAME); 6984117395Skan#endif 6985117395Skan} 6986117395Skan 6987117395Skan 6988117395Skan/* The function outputs translate vector of internal insn code into 6989117395Skan insn equivalence class number. The equivalence class number is 6990132718Skan used to access to table and vectors representing DFA(s). */ 6991117395Skanstatic void 6992132718Skanoutput_translate_vect (automaton_t automaton) 6993117395Skan{ 6994117395Skan ainsn_t ainsn; 6995117395Skan int insn_value; 6996117395Skan vla_hwint_t translate_vect; 6997117395Skan 6998169689Skan translate_vect = VEC_alloc (vect_el_t,heap, description->insns_num); 6999169689Skan 7000132718Skan for (insn_value = 0; insn_value < description->insns_num; insn_value++) 7001117395Skan /* Undefined value */ 7002169689Skan VEC_quick_push (vect_el_t, translate_vect, 7003169689Skan automaton->insn_equiv_classes_num); 7004169689Skan 7005117395Skan for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn) 7006169689Skan VEC_replace (vect_el_t, translate_vect, 7007169689Skan ainsn->insn_reserv_decl->insn_num, 7008169689Skan ainsn->insn_equiv_class_num); 7009169689Skan 7010117395Skan fprintf (output_file, 7011117395Skan "/* Vector translating external insn codes to internal ones.*/\n"); 7012117395Skan fprintf (output_file, "static const "); 7013117395Skan output_range_type (output_file, 0, automaton->insn_equiv_classes_num); 7014117395Skan fprintf (output_file, " "); 7015117395Skan output_translate_vect_name (output_file, automaton); 7016117395Skan fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n"); 7017169689Skan output_vect (translate_vect); 7018117395Skan fprintf (output_file, "};\n\n"); 7019169689Skan VEC_free (vect_el_t,heap, translate_vect); 7020117395Skan} 7021117395Skan 7022117395Skan/* The value in a table state x ainsn -> something which represents 7023117395Skan undefined value. */ 7024117395Skanstatic int undefined_vect_el_value; 7025117395Skan 7026117395Skan/* The following function returns nonzero value if the best 7027117395Skan representation of the table is comb vector. */ 7028117395Skanstatic int 7029132718Skancomb_vect_p (state_ainsn_table_t tab) 7030117395Skan{ 7031169689Skan return (2 * VEC_length (vect_el_t, tab->full_vect) 7032169689Skan > 5 * VEC_length (vect_el_t, tab->comb_vect)); 7033117395Skan} 7034117395Skan 7035117395Skan/* The following function creates new table for AUTOMATON. */ 7036117395Skanstatic state_ainsn_table_t 7037132718Skancreate_state_ainsn_table (automaton_t automaton) 7038117395Skan{ 7039117395Skan state_ainsn_table_t tab; 7040117395Skan int full_vect_length; 7041117395Skan int i; 7042117395Skan 7043117395Skan tab = create_node (sizeof (struct state_ainsn_table)); 7044117395Skan tab->automaton = automaton; 7045169689Skan 7046169689Skan tab->comb_vect = VEC_alloc (vect_el_t,heap, 10000); 7047169689Skan tab->check_vect = VEC_alloc (vect_el_t,heap, 10000); 7048169689Skan 7049169689Skan tab->base_vect = 0; 7050169689Skan VEC_safe_grow (vect_el_t,heap, tab->base_vect, 7051169689Skan automaton->achieved_states_num); 7052169689Skan 7053117395Skan full_vect_length = (automaton->insn_equiv_classes_num 7054117395Skan * automaton->achieved_states_num); 7055169689Skan tab->full_vect = VEC_alloc (vect_el_t,heap, full_vect_length); 7056117395Skan for (i = 0; i < full_vect_length; i++) 7057169689Skan VEC_quick_push (vect_el_t, tab->full_vect, undefined_vect_el_value); 7058169689Skan 7059117395Skan tab->min_base_vect_el_value = 0; 7060117395Skan tab->max_base_vect_el_value = 0; 7061117395Skan tab->min_comb_vect_el_value = 0; 7062117395Skan tab->max_comb_vect_el_value = 0; 7063117395Skan return tab; 7064117395Skan} 7065117395Skan 7066117395Skan/* The following function outputs the best C representation of the 7067117395Skan table TAB of given TABLE_NAME. */ 7068117395Skanstatic void 7069169689Skanoutput_state_ainsn_table (state_ainsn_table_t tab, const char *table_name, 7070132718Skan void (*output_full_vect_name_func) (FILE *, automaton_t), 7071132718Skan void (*output_comb_vect_name_func) (FILE *, automaton_t), 7072132718Skan void (*output_check_vect_name_func) (FILE *, automaton_t), 7073132718Skan void (*output_base_vect_name_func) (FILE *, automaton_t)) 7074117395Skan{ 7075117395Skan if (!comb_vect_p (tab)) 7076117395Skan { 7077117395Skan fprintf (output_file, "/* Vector for %s. */\n", table_name); 7078117395Skan fprintf (output_file, "static const "); 7079117395Skan output_range_type (output_file, tab->min_comb_vect_el_value, 7080117395Skan tab->max_comb_vect_el_value); 7081117395Skan fprintf (output_file, " "); 7082117395Skan (*output_full_vect_name_func) (output_file, tab->automaton); 7083117395Skan fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n"); 7084169689Skan output_vect (tab->full_vect); 7085117395Skan fprintf (output_file, "};\n\n"); 7086117395Skan } 7087117395Skan else 7088117395Skan { 7089117395Skan fprintf (output_file, "/* Comb vector for %s. */\n", table_name); 7090117395Skan fprintf (output_file, "static const "); 7091117395Skan output_range_type (output_file, tab->min_comb_vect_el_value, 7092117395Skan tab->max_comb_vect_el_value); 7093117395Skan fprintf (output_file, " "); 7094117395Skan (*output_comb_vect_name_func) (output_file, tab->automaton); 7095117395Skan fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n"); 7096169689Skan output_vect (tab->comb_vect); 7097117395Skan fprintf (output_file, "};\n\n"); 7098117395Skan fprintf (output_file, "/* Check vector for %s. */\n", table_name); 7099117395Skan fprintf (output_file, "static const "); 7100117395Skan output_range_type (output_file, 0, tab->automaton->achieved_states_num); 7101117395Skan fprintf (output_file, " "); 7102117395Skan (*output_check_vect_name_func) (output_file, tab->automaton); 7103117395Skan fprintf (output_file, "[] = {\n"); 7104169689Skan output_vect (tab->check_vect); 7105117395Skan fprintf (output_file, "};\n\n"); 7106117395Skan fprintf (output_file, "/* Base vector for %s. */\n", table_name); 7107117395Skan fprintf (output_file, "static const "); 7108117395Skan output_range_type (output_file, tab->min_base_vect_el_value, 7109117395Skan tab->max_base_vect_el_value); 7110117395Skan fprintf (output_file, " "); 7111117395Skan (*output_base_vect_name_func) (output_file, tab->automaton); 7112117395Skan fprintf (output_file, "[] = {\n"); 7113169689Skan output_vect (tab->base_vect); 7114117395Skan fprintf (output_file, "};\n\n"); 7115117395Skan } 7116117395Skan} 7117117395Skan 7118169689Skan/* The following function adds vector VECT to table TAB as its line 7119169689Skan with number VECT_NUM. */ 7120117395Skanstatic void 7121169689Skanadd_vect (state_ainsn_table_t tab, int vect_num, vla_hwint_t vect) 7122117395Skan{ 7123169689Skan int vect_length; 7124169689Skan size_t real_vect_length; 7125117395Skan int comb_vect_index; 7126117395Skan int comb_vect_els_num; 7127117395Skan int vect_index; 7128117395Skan int first_unempty_vect_index; 7129117395Skan int additional_els_num; 7130117395Skan int no_state_value; 7131117395Skan vect_el_t vect_el; 7132117395Skan int i; 7133169689Skan unsigned long vect_mask, comb_vect_mask; 7134117395Skan 7135169689Skan vect_length = VEC_length (vect_el_t, vect); 7136169689Skan gcc_assert (vect_length); 7137169689Skan gcc_assert (VEC_last (vect_el_t, vect) != undefined_vect_el_value); 7138117395Skan real_vect_length = tab->automaton->insn_equiv_classes_num; 7139117395Skan /* Form full vector in the table: */ 7140169689Skan { 7141169689Skan size_t full_base = tab->automaton->insn_equiv_classes_num * vect_num; 7142169689Skan if (VEC_length (vect_el_t, tab->full_vect) < full_base + vect_length) 7143169689Skan VEC_safe_grow (vect_el_t,heap, tab->full_vect, 7144169689Skan full_base + vect_length); 7145169689Skan for (i = 0; i < vect_length; i++) 7146169689Skan VEC_replace (vect_el_t, tab->full_vect, full_base + i, 7147169689Skan VEC_index (vect_el_t, vect, i)); 7148169689Skan } 7149117395Skan /* Form comb vector in the table: */ 7150169689Skan gcc_assert (VEC_length (vect_el_t, tab->comb_vect) 7151169689Skan == VEC_length (vect_el_t, tab->check_vect)); 7152169689Skan 7153169689Skan comb_vect_els_num = VEC_length (vect_el_t, tab->comb_vect); 7154117395Skan for (first_unempty_vect_index = 0; 7155117395Skan first_unempty_vect_index < vect_length; 7156117395Skan first_unempty_vect_index++) 7157169689Skan if (VEC_index (vect_el_t, vect, first_unempty_vect_index) 7158169689Skan != undefined_vect_el_value) 7159117395Skan break; 7160169689Skan 7161117395Skan /* Search for the place in comb vect for the inserted vect. */ 7162169689Skan 7163169689Skan /* Slow case. */ 7164169689Skan if (vect_length - first_unempty_vect_index >= SIZEOF_LONG * CHAR_BIT) 7165117395Skan { 7166169689Skan for (comb_vect_index = 0; 7167169689Skan comb_vect_index < comb_vect_els_num; 7168169689Skan comb_vect_index++) 7169169689Skan { 7170169689Skan for (vect_index = first_unempty_vect_index; 7171169689Skan vect_index < vect_length 7172169689Skan && vect_index + comb_vect_index < comb_vect_els_num; 7173169689Skan vect_index++) 7174169689Skan if (VEC_index (vect_el_t, vect, vect_index) 7175169689Skan != undefined_vect_el_value 7176169689Skan && (VEC_index (vect_el_t, tab->comb_vect, 7177169689Skan vect_index + comb_vect_index) 7178169689Skan != undefined_vect_el_value)) 7179169689Skan break; 7180169689Skan if (vect_index >= vect_length 7181169689Skan || vect_index + comb_vect_index >= comb_vect_els_num) 7182169689Skan break; 7183169689Skan } 7184169689Skan goto found; 7185117395Skan } 7186169689Skan 7187169689Skan /* Fast case. */ 7188169689Skan vect_mask = 0; 7189169689Skan for (vect_index = first_unempty_vect_index; 7190169689Skan vect_index < vect_length; 7191169689Skan vect_index++) 7192169689Skan { 7193169689Skan vect_mask = vect_mask << 1; 7194169689Skan if (VEC_index (vect_el_t, vect, vect_index) != undefined_vect_el_value) 7195169689Skan vect_mask |= 1; 7196169689Skan } 7197169689Skan 7198169689Skan /* Search for the place in comb vect for the inserted vect. */ 7199169689Skan comb_vect_index = 0; 7200169689Skan if (comb_vect_els_num == 0) 7201169689Skan goto found; 7202169689Skan 7203169689Skan comb_vect_mask = 0; 7204169689Skan for (vect_index = first_unempty_vect_index; 7205169689Skan vect_index < vect_length && vect_index < comb_vect_els_num; 7206169689Skan vect_index++) 7207169689Skan { 7208169689Skan comb_vect_mask <<= 1; 7209169689Skan if (vect_index + comb_vect_index < comb_vect_els_num 7210169689Skan && VEC_index (vect_el_t, tab->comb_vect, vect_index + comb_vect_index) 7211169689Skan != undefined_vect_el_value) 7212169689Skan comb_vect_mask |= 1; 7213169689Skan } 7214169689Skan if ((vect_mask & comb_vect_mask) == 0) 7215169689Skan goto found; 7216169689Skan 7217169689Skan for (comb_vect_index = 1, i = vect_length; i < comb_vect_els_num; 7218169689Skan comb_vect_index++, i++) 7219169689Skan { 7220169689Skan comb_vect_mask = (comb_vect_mask << 1) | 1; 7221169689Skan comb_vect_mask ^= (VEC_index (vect_el_t, tab->comb_vect, i) 7222169689Skan == undefined_vect_el_value); 7223169689Skan if ((vect_mask & comb_vect_mask) == 0) 7224169689Skan goto found; 7225169689Skan } 7226169689Skan for ( ; comb_vect_index < comb_vect_els_num; comb_vect_index++) 7227169689Skan { 7228169689Skan comb_vect_mask <<= 1; 7229169689Skan if ((vect_mask & comb_vect_mask) == 0) 7230169689Skan goto found; 7231169689Skan } 7232169689Skan 7233169689Skan found: 7234117395Skan /* Slot was found. */ 7235117395Skan additional_els_num = comb_vect_index + real_vect_length - comb_vect_els_num; 7236117395Skan if (additional_els_num < 0) 7237117395Skan additional_els_num = 0; 7238117395Skan /* Expand comb and check vectors. */ 7239117395Skan vect_el = undefined_vect_el_value; 7240117395Skan no_state_value = tab->automaton->achieved_states_num; 7241117395Skan while (additional_els_num > 0) 7242117395Skan { 7243169689Skan VEC_safe_push (vect_el_t,heap, tab->comb_vect, vect_el); 7244169689Skan VEC_safe_push (vect_el_t,heap, tab->check_vect, no_state_value); 7245117395Skan additional_els_num--; 7246117395Skan } 7247169689Skan gcc_assert (VEC_length (vect_el_t, tab->comb_vect) 7248169689Skan >= comb_vect_index + real_vect_length); 7249117395Skan /* Fill comb and check vectors. */ 7250117395Skan for (vect_index = 0; vect_index < vect_length; vect_index++) 7251169689Skan if (VEC_index (vect_el_t, vect, vect_index) != undefined_vect_el_value) 7252117395Skan { 7253169689Skan vect_el_t x = VEC_index (vect_el_t, vect, vect_index); 7254169689Skan gcc_assert (VEC_index (vect_el_t, tab->comb_vect, 7255169689Skan comb_vect_index + vect_index) 7256169689Skan == undefined_vect_el_value); 7257169689Skan gcc_assert (x >= 0); 7258169689Skan if (tab->max_comb_vect_el_value < x) 7259169689Skan tab->max_comb_vect_el_value = x; 7260169689Skan if (tab->min_comb_vect_el_value > x) 7261169689Skan tab->min_comb_vect_el_value = x; 7262169689Skan VEC_replace (vect_el_t, tab->comb_vect, 7263169689Skan comb_vect_index + vect_index, x); 7264169689Skan VEC_replace (vect_el_t, tab->check_vect, 7265169689Skan comb_vect_index + vect_index, vect_num); 7266117395Skan } 7267132718Skan if (tab->max_comb_vect_el_value < undefined_vect_el_value) 7268132718Skan tab->max_comb_vect_el_value = undefined_vect_el_value; 7269132718Skan if (tab->min_comb_vect_el_value > undefined_vect_el_value) 7270132718Skan tab->min_comb_vect_el_value = undefined_vect_el_value; 7271117395Skan if (tab->max_base_vect_el_value < comb_vect_index) 7272117395Skan tab->max_base_vect_el_value = comb_vect_index; 7273117395Skan if (tab->min_base_vect_el_value > comb_vect_index) 7274117395Skan tab->min_base_vect_el_value = comb_vect_index; 7275169689Skan 7276169689Skan VEC_replace (vect_el_t, tab->base_vect, vect_num, comb_vect_index); 7277117395Skan} 7278117395Skan 7279117395Skan/* Return number of out arcs of STATE. */ 7280117395Skanstatic int 7281132718Skanout_state_arcs_num (state_t state) 7282117395Skan{ 7283117395Skan int result; 7284117395Skan arc_t arc; 7285117395Skan 7286117395Skan result = 0; 7287117395Skan for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc)) 7288117395Skan { 7289169689Skan gcc_assert (arc->insn); 7290169689Skan if (arc->insn->first_ainsn_with_given_equivalence_num) 7291117395Skan result++; 7292117395Skan } 7293117395Skan return result; 7294117395Skan} 7295117395Skan 7296117395Skan/* Compare number of possible transitions from the states. */ 7297117395Skanstatic int 7298132718Skancompare_transition_els_num (const void *state_ptr_1, 7299132718Skan const void *state_ptr_2) 7300117395Skan{ 7301117395Skan int transition_els_num_1; 7302117395Skan int transition_els_num_2; 7303117395Skan 7304117395Skan transition_els_num_1 = out_state_arcs_num (*(state_t *) state_ptr_1); 7305117395Skan transition_els_num_2 = out_state_arcs_num (*(state_t *) state_ptr_2); 7306117395Skan if (transition_els_num_1 < transition_els_num_2) 7307117395Skan return 1; 7308117395Skan else if (transition_els_num_1 == transition_els_num_2) 7309117395Skan return 0; 7310117395Skan else 7311117395Skan return -1; 7312117395Skan} 7313117395Skan 7314117395Skan/* The function adds element EL_VALUE to vector VECT for a table state 7315117395Skan x AINSN. */ 7316117395Skanstatic void 7317132718Skanadd_vect_el (vla_hwint_t *vect, ainsn_t ainsn, int el_value) 7318117395Skan{ 7319117395Skan int equiv_class_num; 7320117395Skan int vect_index; 7321117395Skan 7322169689Skan gcc_assert (ainsn); 7323117395Skan equiv_class_num = ainsn->insn_equiv_class_num; 7324169689Skan for (vect_index = VEC_length (vect_el_t, *vect); 7325117395Skan vect_index <= equiv_class_num; 7326117395Skan vect_index++) 7327169689Skan VEC_safe_push (vect_el_t,heap, *vect, undefined_vect_el_value); 7328169689Skan VEC_replace (vect_el_t, *vect, equiv_class_num, el_value); 7329117395Skan} 7330117395Skan 7331117395Skan/* This is for forming vector of states of an automaton. */ 7332169689Skanstatic VEC(state_t,heap) *output_states_vect; 7333117395Skan 7334117395Skan/* The function is called by function pass_states. The function adds 7335117395Skan STATE to `output_states_vect'. */ 7336117395Skanstatic void 7337132718Skanadd_states_vect_el (state_t state) 7338117395Skan{ 7339169689Skan VEC_safe_push (state_t,heap, output_states_vect, state); 7340117395Skan} 7341117395Skan 7342117395Skan/* Form and output vectors (comb, check, base or full vector) 7343117395Skan representing transition table of AUTOMATON. */ 7344117395Skanstatic void 7345132718Skanoutput_trans_table (automaton_t automaton) 7346117395Skan{ 7347169689Skan size_t i; 7348117395Skan arc_t arc; 7349169689Skan vla_hwint_t transition_vect = 0; 7350117395Skan 7351117395Skan undefined_vect_el_value = automaton->achieved_states_num; 7352117395Skan automaton->trans_table = create_state_ainsn_table (automaton); 7353117395Skan /* Create vect of pointers to states ordered by num of transitions 7354117395Skan from the state (state with the maximum num is the first). */ 7355169689Skan output_states_vect = 0; 7356117395Skan pass_states (automaton, add_states_vect_el); 7357169689Skan qsort (VEC_address (state_t, output_states_vect), 7358169689Skan VEC_length (state_t, output_states_vect), 7359117395Skan sizeof (state_t), compare_transition_els_num); 7360169689Skan 7361169689Skan for (i = 0; i < VEC_length (state_t, output_states_vect); i++) 7362117395Skan { 7363169689Skan VEC_truncate (vect_el_t, transition_vect, 0); 7364169689Skan for (arc = first_out_arc (VEC_index (state_t, output_states_vect, i)); 7365117395Skan arc != NULL; 7366117395Skan arc = next_out_arc (arc)) 7367117395Skan { 7368169689Skan gcc_assert (arc->insn); 7369169689Skan if (arc->insn->first_ainsn_with_given_equivalence_num) 7370117395Skan add_vect_el (&transition_vect, arc->insn, 7371117395Skan arc->to_state->order_state_num); 7372117395Skan } 7373169689Skan add_vect (automaton->trans_table, 7374169689Skan VEC_index (state_t, output_states_vect, i)->order_state_num, 7375169689Skan transition_vect); 7376117395Skan } 7377117395Skan output_state_ainsn_table 7378169689Skan (automaton->trans_table, "state transitions", 7379117395Skan output_trans_full_vect_name, output_trans_comb_vect_name, 7380117395Skan output_trans_check_vect_name, output_trans_base_vect_name); 7381117395Skan 7382169689Skan VEC_free (state_t,heap, output_states_vect); 7383169689Skan VEC_free (vect_el_t,heap, transition_vect); 7384117395Skan} 7385117395Skan 7386117395Skan/* The current number of passing states to find minimal issue delay 7387117395Skan value for an ainsn and state. */ 7388117395Skanstatic int curr_state_pass_num; 7389117395Skan 7390117395Skan/* This recursive function passes states to find minimal issue delay 7391117395Skan value for AINSN. The state being visited is STATE. The function 7392117395Skan returns minimal issue delay value for AINSN in STATE or -1 if we 7393117395Skan enter into a loop. */ 7394117395Skanstatic int 7395132718Skanmin_issue_delay_pass_states (state_t state, ainsn_t ainsn) 7396117395Skan{ 7397117395Skan arc_t arc; 7398117395Skan int min_insn_issue_delay, insn_issue_delay; 7399117395Skan 7400117395Skan if (state->state_pass_num == curr_state_pass_num 7401117395Skan || state->min_insn_issue_delay != -1) 7402117395Skan /* We've entered into a loop or already have the correct value for 7403117395Skan given state and ainsn. */ 7404117395Skan return state->min_insn_issue_delay; 7405117395Skan state->state_pass_num = curr_state_pass_num; 7406117395Skan min_insn_issue_delay = -1; 7407117395Skan for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc)) 7408117395Skan if (arc->insn == ainsn) 7409117395Skan { 7410117395Skan min_insn_issue_delay = 0; 7411117395Skan break; 7412117395Skan } 7413117395Skan else 7414117395Skan { 7415117395Skan insn_issue_delay = min_issue_delay_pass_states (arc->to_state, ainsn); 7416117395Skan if (insn_issue_delay != -1) 7417117395Skan { 7418117395Skan if (arc->insn->insn_reserv_decl 7419117395Skan == DECL_INSN_RESERV (advance_cycle_insn_decl)) 7420117395Skan insn_issue_delay++; 7421117395Skan if (min_insn_issue_delay == -1 7422117395Skan || min_insn_issue_delay > insn_issue_delay) 7423117395Skan { 7424117395Skan min_insn_issue_delay = insn_issue_delay; 7425117395Skan if (insn_issue_delay == 0) 7426117395Skan break; 7427117395Skan } 7428117395Skan } 7429117395Skan } 7430117395Skan return min_insn_issue_delay; 7431117395Skan} 7432117395Skan 7433117395Skan/* The function searches minimal issue delay value for AINSN in STATE. 7434117395Skan The function can return negative value if we can not issue AINSN. We 7435117395Skan will report about it later. */ 7436117395Skanstatic int 7437132718Skanmin_issue_delay (state_t state, ainsn_t ainsn) 7438117395Skan{ 7439117395Skan curr_state_pass_num++; 7440117395Skan state->min_insn_issue_delay = min_issue_delay_pass_states (state, ainsn); 7441117395Skan return state->min_insn_issue_delay; 7442117395Skan} 7443117395Skan 7444117395Skan/* The function initiates code for finding minimal issue delay values. 7445117395Skan It should be called only once. */ 7446117395Skanstatic void 7447132718Skaninitiate_min_issue_delay_pass_states (void) 7448117395Skan{ 7449117395Skan curr_state_pass_num = 0; 7450117395Skan} 7451117395Skan 7452117395Skan/* Form and output vectors representing minimal issue delay table of 7453117395Skan AUTOMATON. The table is state x ainsn -> minimal issue delay of 7454117395Skan the ainsn. */ 7455117395Skanstatic void 7456132718Skanoutput_min_issue_delay_table (automaton_t automaton) 7457117395Skan{ 7458117395Skan vla_hwint_t min_issue_delay_vect; 7459117395Skan vla_hwint_t compressed_min_issue_delay_vect; 7460117395Skan vect_el_t min_delay; 7461117395Skan ainsn_t ainsn; 7462169689Skan size_t i, min_issue_delay_len; 7463169689Skan size_t compressed_min_issue_delay_len; 7464169689Skan size_t cfactor; 7465117395Skan 7466117395Skan /* Create vect of pointers to states ordered by num of transitions 7467117395Skan from the state (state with the maximum num is the first). */ 7468169689Skan output_states_vect = 0; 7469117395Skan pass_states (automaton, add_states_vect_el); 7470169689Skan 7471169689Skan min_issue_delay_len = (VEC_length (state_t, output_states_vect) 7472169689Skan * automaton->insn_equiv_classes_num); 7473169689Skan min_issue_delay_vect = VEC_alloc (vect_el_t,heap, min_issue_delay_len); 7474169689Skan for (i = 0; i < min_issue_delay_len; i++) 7475169689Skan VEC_quick_push (vect_el_t, min_issue_delay_vect, 0); 7476169689Skan 7477117395Skan automaton->max_min_delay = 0; 7478117395Skan for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn) 7479169689Skan if (ainsn->first_ainsn_with_given_equivalence_num) 7480117395Skan { 7481169689Skan for (i = 0; i < VEC_length (state_t, output_states_vect); i++) 7482169689Skan VEC_index (state_t, output_states_vect, i)->min_insn_issue_delay = -1; 7483169689Skan for (i = 0; i < VEC_length (state_t, output_states_vect); i++) 7484117395Skan { 7485169689Skan state_t s = VEC_index (state_t, output_states_vect, i); 7486169689Skan min_delay = min_issue_delay (s, ainsn); 7487117395Skan if (automaton->max_min_delay < min_delay) 7488117395Skan automaton->max_min_delay = min_delay; 7489169689Skan VEC_replace (vect_el_t, min_issue_delay_vect, 7490169689Skan s->order_state_num 7491169689Skan * automaton->insn_equiv_classes_num 7492169689Skan + ainsn->insn_equiv_class_num, 7493169689Skan min_delay); 7494117395Skan } 7495117395Skan } 7496132718Skan fprintf (output_file, "/* Vector of min issue delay of insns. */\n"); 7497117395Skan fprintf (output_file, "static const "); 7498117395Skan output_range_type (output_file, 0, automaton->max_min_delay); 7499117395Skan fprintf (output_file, " "); 7500117395Skan output_min_issue_delay_vect_name (output_file, automaton); 7501117395Skan fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n"); 7502132718Skan /* Compress the vector. */ 7503117395Skan if (automaton->max_min_delay < 2) 7504169689Skan cfactor = 8; 7505117395Skan else if (automaton->max_min_delay < 4) 7506169689Skan cfactor = 4; 7507117395Skan else if (automaton->max_min_delay < 16) 7508169689Skan cfactor = 2; 7509117395Skan else 7510169689Skan cfactor = 1; 7511169689Skan automaton->min_issue_delay_table_compression_factor = cfactor; 7512169689Skan 7513169689Skan compressed_min_issue_delay_len = (min_issue_delay_len+cfactor-1) / cfactor; 7514169689Skan compressed_min_issue_delay_vect 7515169689Skan = VEC_alloc (vect_el_t,heap, compressed_min_issue_delay_len); 7516169689Skan 7517169689Skan for (i = 0; i < compressed_min_issue_delay_len; i++) 7518169689Skan VEC_quick_push (vect_el_t, compressed_min_issue_delay_vect, 0); 7519169689Skan 7520169689Skan for (i = 0; i < min_issue_delay_len; i++) 7521169689Skan { 7522169689Skan size_t ci = i / cfactor; 7523169689Skan vect_el_t x = VEC_index (vect_el_t, min_issue_delay_vect, i); 7524169689Skan vect_el_t cx = VEC_index (vect_el_t, compressed_min_issue_delay_vect, ci); 7525169689Skan 7526169689Skan cx |= x << (8 - (i % cfactor + 1) * (8 / cfactor)); 7527169689Skan VEC_replace (vect_el_t, compressed_min_issue_delay_vect, ci, cx); 7528169689Skan } 7529169689Skan output_vect (compressed_min_issue_delay_vect); 7530117395Skan fprintf (output_file, "};\n\n"); 7531169689Skan VEC_free (state_t,heap, output_states_vect); 7532169689Skan VEC_free (vect_el_t,heap, min_issue_delay_vect); 7533169689Skan VEC_free (vect_el_t,heap, compressed_min_issue_delay_vect); 7534117395Skan} 7535117395Skan 7536117395Skan/* Form and output vector representing the locked states of 7537117395Skan AUTOMATON. */ 7538117395Skanstatic void 7539132718Skanoutput_dead_lock_vect (automaton_t automaton) 7540117395Skan{ 7541169689Skan size_t i; 7542117395Skan arc_t arc; 7543169689Skan vla_hwint_t dead_lock_vect = 0; 7544117395Skan 7545117395Skan /* Create vect of pointers to states ordered by num of 7546117395Skan transitions from the state (state with the maximum num is the 7547117395Skan first). */ 7548169689Skan automaton->locked_states = 0; 7549169689Skan output_states_vect = 0; 7550117395Skan pass_states (automaton, add_states_vect_el); 7551169689Skan 7552169689Skan VEC_safe_grow (vect_el_t,heap, dead_lock_vect, 7553169689Skan VEC_length (state_t, output_states_vect)); 7554169689Skan for (i = 0; i < VEC_length (state_t, output_states_vect); i++) 7555117395Skan { 7556169689Skan state_t s = VEC_index (state_t, output_states_vect, i); 7557169689Skan arc = first_out_arc (s); 7558169689Skan gcc_assert (arc); 7559169689Skan if (next_out_arc (arc) == NULL 7560169689Skan && (arc->insn->insn_reserv_decl 7561169689Skan == DECL_INSN_RESERV (advance_cycle_insn_decl))) 7562169689Skan { 7563169689Skan VEC_replace (vect_el_t, dead_lock_vect, s->order_state_num, 1); 7564169689Skan automaton->locked_states++; 7565169689Skan } 7566169689Skan else 7567169689Skan VEC_replace (vect_el_t, dead_lock_vect, s->order_state_num, 0); 7568117395Skan } 7569169689Skan if (automaton->locked_states == 0) 7570169689Skan return; 7571169689Skan 7572117395Skan fprintf (output_file, "/* Vector for locked state flags. */\n"); 7573117395Skan fprintf (output_file, "static const "); 7574117395Skan output_range_type (output_file, 0, 1); 7575117395Skan fprintf (output_file, " "); 7576117395Skan output_dead_lock_vect_name (output_file, automaton); 7577117395Skan fprintf (output_file, "[] = {\n"); 7578169689Skan output_vect (dead_lock_vect); 7579117395Skan fprintf (output_file, "};\n\n"); 7580169689Skan VEC_free (state_t,heap, output_states_vect); 7581169689Skan VEC_free (vect_el_t,heap, dead_lock_vect); 7582117395Skan} 7583117395Skan 7584117395Skan/* Form and output vector representing reserved units of the states of 7585117395Skan AUTOMATON. */ 7586117395Skanstatic void 7587132718Skanoutput_reserved_units_table (automaton_t automaton) 7588117395Skan{ 7589169689Skan vla_hwint_t reserved_units_table = 0; 7590169689Skan int state_byte_size; 7591169689Skan int reserved_units_size; 7592169689Skan size_t n; 7593117395Skan int i; 7594117395Skan 7595169689Skan if (description->query_units_num == 0) 7596169689Skan return; 7597169689Skan 7598117395Skan /* Create vect of pointers to states. */ 7599169689Skan output_states_vect = 0; 7600117395Skan pass_states (automaton, add_states_vect_el); 7601117395Skan /* Create vector. */ 7602117395Skan state_byte_size = (description->query_units_num + 7) / 8; 7603169689Skan reserved_units_size = (VEC_length (state_t, output_states_vect) 7604169689Skan * state_byte_size); 7605169689Skan 7606169689Skan reserved_units_table = VEC_alloc (vect_el_t,heap, reserved_units_size); 7607169689Skan 7608169689Skan for (i = 0; i < reserved_units_size; i++) 7609169689Skan VEC_quick_push (vect_el_t, reserved_units_table, 0); 7610169689Skan for (n = 0; n < VEC_length (state_t, output_states_vect); n++) 7611117395Skan { 7612169689Skan state_t s = VEC_index (state_t, output_states_vect, n); 7613117395Skan for (i = 0; i < description->units_num; i++) 7614132718Skan if (units_array [i]->query_p 7615169689Skan && first_cycle_unit_presence (s, i)) 7616169689Skan { 7617169689Skan int ri = (s->order_state_num * state_byte_size 7618169689Skan + units_array [i]->query_num / 8); 7619169689Skan vect_el_t x = VEC_index (vect_el_t, reserved_units_table, ri); 7620169689Skan 7621169689Skan x += 1 << (units_array [i]->query_num % 8); 7622169689Skan VEC_replace (vect_el_t, reserved_units_table, ri, x); 7623169689Skan } 7624117395Skan } 7625169689Skan fprintf (output_file, "\n#if %s\n", CPU_UNITS_QUERY_MACRO_NAME); 7626117395Skan fprintf (output_file, "/* Vector for reserved units of states. */\n"); 7627117395Skan fprintf (output_file, "static const "); 7628117395Skan output_range_type (output_file, 0, 255); 7629117395Skan fprintf (output_file, " "); 7630117395Skan output_reserved_units_table_name (output_file, automaton); 7631117395Skan fprintf (output_file, "[] = {\n"); 7632169689Skan output_vect (reserved_units_table); 7633169689Skan fprintf (output_file, "};\n#endif /* #if %s */\n\n", 7634169689Skan CPU_UNITS_QUERY_MACRO_NAME); 7635169689Skan 7636169689Skan VEC_free (state_t,heap, output_states_vect); 7637169689Skan VEC_free (vect_el_t,heap, reserved_units_table); 7638117395Skan} 7639117395Skan 7640117395Skan/* The function outputs all tables representing DFA(s) used for fast 7641117395Skan pipeline hazards recognition. */ 7642117395Skanstatic void 7643132718Skanoutput_tables (void) 7644117395Skan{ 7645117395Skan automaton_t automaton; 7646117395Skan 7647117395Skan initiate_min_issue_delay_pass_states (); 7648117395Skan for (automaton = description->first_automaton; 7649117395Skan automaton != NULL; 7650117395Skan automaton = automaton->next_automaton) 7651117395Skan { 7652117395Skan output_translate_vect (automaton); 7653117395Skan output_trans_table (automaton); 7654117395Skan output_min_issue_delay_table (automaton); 7655117395Skan output_dead_lock_vect (automaton); 7656132718Skan output_reserved_units_table (automaton); 7657117395Skan } 7658117395Skan fprintf (output_file, "\n#define %s %d\n\n", ADVANCE_CYCLE_VALUE_NAME, 7659117395Skan DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num); 7660117395Skan} 7661117395Skan 7662117395Skan/* The function outputs definition and value of PHR interface variable 7663117395Skan `max_insn_queue_index'. Its value is not less than maximal queue 7664117395Skan length needed for the insn scheduler. */ 7665117395Skanstatic void 7666132718Skanoutput_max_insn_queue_index_def (void) 7667117395Skan{ 7668117395Skan int i, max, latency; 7669117395Skan decl_t decl; 7670117395Skan 7671117395Skan max = description->max_insn_reserv_cycles; 7672117395Skan for (i = 0; i < description->decls_num; i++) 7673117395Skan { 7674117395Skan decl = description->decls [i]; 7675117395Skan if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl) 7676117395Skan { 7677117395Skan latency = DECL_INSN_RESERV (decl)->default_latency; 7678117395Skan if (latency > max) 7679117395Skan max = latency; 7680117395Skan } 7681117395Skan else if (decl->mode == dm_bypass) 7682117395Skan { 7683117395Skan latency = DECL_BYPASS (decl)->latency; 7684117395Skan if (latency > max) 7685117395Skan max = latency; 7686117395Skan } 7687117395Skan } 7688117395Skan for (i = 0; (1 << i) <= max; i++) 7689117395Skan ; 7690169689Skan gcc_assert (i >= 0); 7691169689Skan fprintf (output_file, "\nconst int max_insn_queue_index = %d;\n\n", 7692169689Skan (1 << i) - 1); 7693117395Skan} 7694117395Skan 7695132718Skan/* The function outputs switch cases for insn reservations using 7696117395Skan function *output_automata_list_code. */ 7697117395Skanstatic void 7698132718Skanoutput_insn_code_cases (void (*output_automata_list_code) 7699132718Skan (automata_list_el_t)) 7700117395Skan{ 7701117395Skan decl_t decl, decl2; 7702117395Skan int i, j; 7703117395Skan 7704117395Skan for (i = 0; i < description->decls_num; i++) 7705117395Skan { 7706117395Skan decl = description->decls [i]; 7707117395Skan if (decl->mode == dm_insn_reserv) 7708117395Skan DECL_INSN_RESERV (decl)->processed_p = FALSE; 7709117395Skan } 7710117395Skan for (i = 0; i < description->decls_num; i++) 7711117395Skan { 7712117395Skan decl = description->decls [i]; 7713117395Skan if (decl->mode == dm_insn_reserv 7714117395Skan && !DECL_INSN_RESERV (decl)->processed_p) 7715117395Skan { 7716117395Skan for (j = i; j < description->decls_num; j++) 7717117395Skan { 7718117395Skan decl2 = description->decls [j]; 7719117395Skan if (decl2->mode == dm_insn_reserv 7720117395Skan && (DECL_INSN_RESERV (decl2)->important_automata_list 7721117395Skan == DECL_INSN_RESERV (decl)->important_automata_list)) 7722117395Skan { 7723117395Skan DECL_INSN_RESERV (decl2)->processed_p = TRUE; 7724117395Skan fprintf (output_file, " case %d: /* %s */\n", 7725117395Skan DECL_INSN_RESERV (decl2)->insn_num, 7726117395Skan DECL_INSN_RESERV (decl2)->name); 7727117395Skan } 7728117395Skan } 7729117395Skan (*output_automata_list_code) 7730117395Skan (DECL_INSN_RESERV (decl)->important_automata_list); 7731117395Skan } 7732117395Skan } 7733117395Skan} 7734117395Skan 7735117395Skan 7736117395Skan/* The function outputs a code for evaluation of a minimal delay of 7737117395Skan issue of insns which have reservations in given AUTOMATA_LIST. */ 7738117395Skanstatic void 7739132718Skanoutput_automata_list_min_issue_delay_code (automata_list_el_t automata_list) 7740117395Skan{ 7741117395Skan automata_list_el_t el; 7742117395Skan automaton_t automaton; 7743117395Skan 7744117395Skan for (el = automata_list; el != NULL; el = el->next_automata_list_el) 7745117395Skan { 7746117395Skan automaton = el->automaton; 7747117395Skan fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME); 7748117395Skan output_min_issue_delay_vect_name (output_file, automaton); 7749117395Skan fprintf (output_file, 7750117395Skan (automaton->min_issue_delay_table_compression_factor != 1 7751117395Skan ? " [(" : " [")); 7752117395Skan output_translate_vect_name (output_file, automaton); 7753117395Skan fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME); 7754117395Skan fprintf (output_file, "%s->", CHIP_PARAMETER_NAME); 7755117395Skan output_chip_member_name (output_file, automaton); 7756117395Skan fprintf (output_file, " * %d", automaton->insn_equiv_classes_num); 7757117395Skan if (automaton->min_issue_delay_table_compression_factor == 1) 7758117395Skan fprintf (output_file, "];\n"); 7759117395Skan else 7760117395Skan { 7761117395Skan fprintf (output_file, ") / %d];\n", 7762117395Skan automaton->min_issue_delay_table_compression_factor); 7763117395Skan fprintf (output_file, " %s = (%s >> (8 - (", 7764117395Skan TEMPORARY_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME); 7765117395Skan output_translate_vect_name (output_file, automaton); 7766117395Skan fprintf 7767117395Skan (output_file, " [%s] %% %d + 1) * %d)) & %d;\n", 7768117395Skan INTERNAL_INSN_CODE_NAME, 7769117395Skan automaton->min_issue_delay_table_compression_factor, 7770117395Skan 8 / automaton->min_issue_delay_table_compression_factor, 7771117395Skan (1 << (8 / automaton->min_issue_delay_table_compression_factor)) 7772117395Skan - 1); 7773117395Skan } 7774117395Skan if (el == automata_list) 7775117395Skan fprintf (output_file, " %s = %s;\n", 7776117395Skan RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME); 7777117395Skan else 7778117395Skan { 7779117395Skan fprintf (output_file, " if (%s > %s)\n", 7780117395Skan TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME); 7781117395Skan fprintf (output_file, " %s = %s;\n", 7782117395Skan RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME); 7783117395Skan } 7784117395Skan } 7785117395Skan fprintf (output_file, " break;\n\n"); 7786117395Skan} 7787117395Skan 7788117395Skan/* Output function `internal_min_issue_delay'. */ 7789117395Skanstatic void 7790132718Skanoutput_internal_min_issue_delay_func (void) 7791117395Skan{ 7792117395Skan fprintf (output_file, 7793132718Skan "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n", 7794117395Skan INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME, 7795132718Skan CHIP_NAME, CHIP_PARAMETER_NAME); 7796117395Skan fprintf (output_file, "{\n int %s ATTRIBUTE_UNUSED;\n int %s = -1;\n", 7797117395Skan TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME); 7798117395Skan fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME); 7799117395Skan output_insn_code_cases (output_automata_list_min_issue_delay_code); 7800117395Skan fprintf (output_file, 7801117395Skan "\n default:\n %s = -1;\n break;\n }\n", 7802117395Skan RESULT_VARIABLE_NAME); 7803117395Skan fprintf (output_file, " return %s;\n", RESULT_VARIABLE_NAME); 7804117395Skan fprintf (output_file, "}\n\n"); 7805117395Skan} 7806117395Skan 7807117395Skan/* The function outputs a code changing state after issue of insns 7808117395Skan which have reservations in given AUTOMATA_LIST. */ 7809117395Skanstatic void 7810132718Skanoutput_automata_list_transition_code (automata_list_el_t automata_list) 7811117395Skan{ 7812117395Skan automata_list_el_t el, next_el; 7813117395Skan 7814117395Skan fprintf (output_file, " {\n"); 7815117395Skan if (automata_list != NULL && automata_list->next_automata_list_el != NULL) 7816117395Skan for (el = automata_list;; el = next_el) 7817117395Skan { 7818117395Skan next_el = el->next_automata_list_el; 7819117395Skan if (next_el == NULL) 7820117395Skan break; 7821117395Skan fprintf (output_file, " "); 7822117395Skan output_state_member_type (output_file, el->automaton); 7823117395Skan fprintf (output_file, " "); 7824117395Skan output_temp_chip_member_name (output_file, el->automaton); 7825117395Skan fprintf (output_file, ";\n"); 7826117395Skan } 7827117395Skan for (el = automata_list; el != NULL; el = el->next_automata_list_el) 7828117395Skan if (comb_vect_p (el->automaton->trans_table)) 7829117395Skan { 7830117395Skan fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME); 7831117395Skan output_trans_base_vect_name (output_file, el->automaton); 7832117395Skan fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME); 7833117395Skan output_chip_member_name (output_file, el->automaton); 7834117395Skan fprintf (output_file, "] + "); 7835117395Skan output_translate_vect_name (output_file, el->automaton); 7836117395Skan fprintf (output_file, " [%s];\n", INTERNAL_INSN_CODE_NAME); 7837117395Skan fprintf (output_file, " if ("); 7838117395Skan output_trans_check_vect_name (output_file, el->automaton); 7839117395Skan fprintf (output_file, " [%s] != %s->", 7840117395Skan TEMPORARY_VARIABLE_NAME, CHIP_PARAMETER_NAME); 7841117395Skan output_chip_member_name (output_file, el->automaton); 7842117395Skan fprintf (output_file, ")\n"); 7843117395Skan fprintf (output_file, " return %s (%s, %s);\n", 7844117395Skan INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME, 7845117395Skan CHIP_PARAMETER_NAME); 7846117395Skan fprintf (output_file, " else\n"); 7847117395Skan fprintf (output_file, " "); 7848117395Skan if (el->next_automata_list_el != NULL) 7849117395Skan output_temp_chip_member_name (output_file, el->automaton); 7850117395Skan else 7851117395Skan { 7852117395Skan fprintf (output_file, "%s->", CHIP_PARAMETER_NAME); 7853117395Skan output_chip_member_name (output_file, el->automaton); 7854117395Skan } 7855117395Skan fprintf (output_file, " = "); 7856117395Skan output_trans_comb_vect_name (output_file, el->automaton); 7857117395Skan fprintf (output_file, " [%s];\n", TEMPORARY_VARIABLE_NAME); 7858117395Skan } 7859117395Skan else 7860117395Skan { 7861117395Skan fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME); 7862117395Skan output_trans_full_vect_name (output_file, el->automaton); 7863117395Skan fprintf (output_file, " ["); 7864117395Skan output_translate_vect_name (output_file, el->automaton); 7865117395Skan fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME); 7866117395Skan fprintf (output_file, "%s->", CHIP_PARAMETER_NAME); 7867117395Skan output_chip_member_name (output_file, el->automaton); 7868117395Skan fprintf (output_file, " * %d];\n", 7869117395Skan el->automaton->insn_equiv_classes_num); 7870117395Skan fprintf (output_file, " if (%s >= %d)\n", 7871117395Skan TEMPORARY_VARIABLE_NAME, el->automaton->achieved_states_num); 7872117395Skan fprintf (output_file, " return %s (%s, %s);\n", 7873117395Skan INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME, 7874117395Skan CHIP_PARAMETER_NAME); 7875117395Skan fprintf (output_file, " else\n "); 7876117395Skan if (el->next_automata_list_el != NULL) 7877117395Skan output_temp_chip_member_name (output_file, el->automaton); 7878117395Skan else 7879117395Skan { 7880117395Skan fprintf (output_file, "%s->", CHIP_PARAMETER_NAME); 7881117395Skan output_chip_member_name (output_file, el->automaton); 7882117395Skan } 7883117395Skan fprintf (output_file, " = %s;\n", TEMPORARY_VARIABLE_NAME); 7884117395Skan } 7885117395Skan if (automata_list != NULL && automata_list->next_automata_list_el != NULL) 7886117395Skan for (el = automata_list;; el = next_el) 7887117395Skan { 7888117395Skan next_el = el->next_automata_list_el; 7889117395Skan if (next_el == NULL) 7890117395Skan break; 7891117395Skan fprintf (output_file, " %s->", CHIP_PARAMETER_NAME); 7892117395Skan output_chip_member_name (output_file, el->automaton); 7893117395Skan fprintf (output_file, " = "); 7894117395Skan output_temp_chip_member_name (output_file, el->automaton); 7895117395Skan fprintf (output_file, ";\n"); 7896117395Skan } 7897117395Skan fprintf (output_file, " return -1;\n"); 7898117395Skan fprintf (output_file, " }\n"); 7899117395Skan} 7900117395Skan 7901117395Skan/* Output function `internal_state_transition'. */ 7902117395Skanstatic void 7903132718Skanoutput_internal_trans_func (void) 7904117395Skan{ 7905117395Skan fprintf (output_file, 7906132718Skan "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n", 7907117395Skan INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, 7908117395Skan CHIP_NAME, CHIP_PARAMETER_NAME); 7909117395Skan fprintf (output_file, "{\n int %s ATTRIBUTE_UNUSED;\n", TEMPORARY_VARIABLE_NAME); 7910117395Skan fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME); 7911117395Skan output_insn_code_cases (output_automata_list_transition_code); 7912117395Skan fprintf (output_file, "\n default:\n return -1;\n }\n"); 7913117395Skan fprintf (output_file, "}\n\n"); 7914117395Skan} 7915117395Skan 7916117395Skan/* Output code 7917117395Skan 7918117395Skan if (insn != 0) 7919117395Skan { 7920117395Skan insn_code = dfa_insn_code (insn); 7921117395Skan if (insn_code > DFA__ADVANCE_CYCLE) 7922117395Skan return code; 7923117395Skan } 7924117395Skan else 7925117395Skan insn_code = DFA__ADVANCE_CYCLE; 7926117395Skan 7927117395Skan where insn denotes INSN_NAME, insn_code denotes INSN_CODE_NAME, and 7928117395Skan code denotes CODE. */ 7929117395Skanstatic void 7930132718Skanoutput_internal_insn_code_evaluation (const char *insn_name, 7931132718Skan const char *insn_code_name, 7932132718Skan int code) 7933117395Skan{ 7934117395Skan fprintf (output_file, "\n if (%s != 0)\n {\n", insn_name); 7935117395Skan fprintf (output_file, " %s = %s (%s);\n", insn_code_name, 7936117395Skan DFA_INSN_CODE_FUNC_NAME, insn_name); 7937117395Skan fprintf (output_file, " if (%s > %s)\n return %d;\n", 7938117395Skan insn_code_name, ADVANCE_CYCLE_VALUE_NAME, code); 7939117395Skan fprintf (output_file, " }\n else\n %s = %s;\n\n", 7940117395Skan insn_code_name, ADVANCE_CYCLE_VALUE_NAME); 7941117395Skan} 7942117395Skan 7943117395Skan 7944132718Skan/* This function outputs `dfa_insn_code' and its helper function 7945132718Skan `dfa_insn_code_enlarge'. */ 7946117395Skanstatic void 7947132718Skanoutput_dfa_insn_code_func (void) 7948117395Skan{ 7949132718Skan /* Emacs c-mode gets really confused if there's a { or } in column 0 7950132718Skan inside a string, so don't do that. */ 7951132718Skan fprintf (output_file, "\ 7952132718Skanstatic void\n\ 7953132718Skandfa_insn_code_enlarge (int uid)\n\ 7954132718Skan{\n\ 7955132718Skan int i = %s;\n\ 7956132718Skan %s = 2 * uid;\n\ 7957132718Skan %s = xrealloc (%s,\n\ 7958132718Skan %s * sizeof(int));\n\ 7959132718Skan for (; i < %s; i++)\n\ 7960132718Skan %s[i] = -1;\n}\n\n", 7961132718Skan DFA_INSN_CODES_LENGTH_VARIABLE_NAME, 7962132718Skan DFA_INSN_CODES_LENGTH_VARIABLE_NAME, 7963117395Skan DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME, 7964132718Skan DFA_INSN_CODES_LENGTH_VARIABLE_NAME, 7965132718Skan DFA_INSN_CODES_LENGTH_VARIABLE_NAME, 7966132718Skan DFA_INSN_CODES_VARIABLE_NAME); 7967132718Skan fprintf (output_file, "\ 7968132718Skanstatic inline int\n%s (rtx %s)\n\ 7969132718Skan{\n\ 7970132718Skan int uid = INSN_UID (%s);\n\ 7971132718Skan int %s;\n\n", 7972132718Skan DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME, 7973132718Skan INSN_PARAMETER_NAME, INTERNAL_INSN_CODE_NAME); 7974132718Skan 7975132718Skan fprintf (output_file, 7976132718Skan " if (uid >= %s)\n dfa_insn_code_enlarge (uid);\n\n", 7977117395Skan DFA_INSN_CODES_LENGTH_VARIABLE_NAME); 7978132718Skan fprintf (output_file, " %s = %s[uid];\n", 7979132718Skan INTERNAL_INSN_CODE_NAME, DFA_INSN_CODES_VARIABLE_NAME); 7980132718Skan fprintf (output_file, "\ 7981132718Skan if (%s < 0)\n\ 7982132718Skan {\n\ 7983132718Skan %s = %s (%s);\n\ 7984132718Skan %s[uid] = %s;\n\ 7985132718Skan }\n", 7986132718Skan INTERNAL_INSN_CODE_NAME, 7987132718Skan INTERNAL_INSN_CODE_NAME, 7988132718Skan INTERNAL_DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME, 7989132718Skan DFA_INSN_CODES_VARIABLE_NAME, INTERNAL_INSN_CODE_NAME); 7990132718Skan fprintf (output_file, " return %s;\n}\n\n", INTERNAL_INSN_CODE_NAME); 7991117395Skan} 7992117395Skan 7993117395Skan/* The function outputs PHR interface function `state_transition'. */ 7994117395Skanstatic void 7995132718Skanoutput_trans_func (void) 7996117395Skan{ 7997132718Skan fprintf (output_file, "int\n%s (%s %s, rtx %s)\n", 7998132718Skan TRANSITION_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME, 7999132718Skan INSN_PARAMETER_NAME); 8000117395Skan fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME); 8001117395Skan output_internal_insn_code_evaluation (INSN_PARAMETER_NAME, 8002117395Skan INTERNAL_INSN_CODE_NAME, -1); 8003117395Skan fprintf (output_file, " return %s (%s, %s);\n}\n\n", 8004117395Skan INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, STATE_NAME); 8005117395Skan} 8006117395Skan 8007117395Skan/* Output function `min_issue_delay'. */ 8008117395Skanstatic void 8009132718Skanoutput_min_issue_delay_func (void) 8010117395Skan{ 8011132718Skan fprintf (output_file, "int\n%s (%s %s, rtx %s)\n", 8012132718Skan MIN_ISSUE_DELAY_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME, 8013132718Skan INSN_PARAMETER_NAME); 8014117395Skan fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME); 8015117395Skan fprintf (output_file, "\n if (%s != 0)\n {\n", INSN_PARAMETER_NAME); 8016117395Skan fprintf (output_file, " %s = %s (%s);\n", INTERNAL_INSN_CODE_NAME, 8017117395Skan DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME); 8018117395Skan fprintf (output_file, " if (%s > %s)\n return 0;\n", 8019117395Skan INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME); 8020117395Skan fprintf (output_file, " }\n else\n %s = %s;\n", 8021117395Skan INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME); 8022117395Skan fprintf (output_file, "\n return %s (%s, %s);\n", 8023132718Skan INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME, 8024117395Skan STATE_NAME); 8025117395Skan fprintf (output_file, "}\n\n"); 8026117395Skan} 8027117395Skan 8028117395Skan/* Output function `internal_dead_lock'. */ 8029117395Skanstatic void 8030132718Skanoutput_internal_dead_lock_func (void) 8031117395Skan{ 8032117395Skan automaton_t automaton; 8033117395Skan 8034169689Skan fprintf (output_file, "static int\n%s (struct %s *ARG_UNUSED (%s))\n", 8035132718Skan INTERNAL_DEAD_LOCK_FUNC_NAME, CHIP_NAME, CHIP_PARAMETER_NAME); 8036117395Skan fprintf (output_file, "{\n"); 8037117395Skan for (automaton = description->first_automaton; 8038117395Skan automaton != NULL; 8039117395Skan automaton = automaton->next_automaton) 8040169689Skan if (automaton->locked_states) 8041169689Skan { 8042169689Skan fprintf (output_file, " if ("); 8043169689Skan output_dead_lock_vect_name (output_file, automaton); 8044169689Skan fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME); 8045169689Skan output_chip_member_name (output_file, automaton); 8046169689Skan fprintf (output_file, "])\n return 1/* TRUE */;\n"); 8047169689Skan } 8048117395Skan fprintf (output_file, " return 0/* FALSE */;\n}\n\n"); 8049117395Skan} 8050117395Skan 8051117395Skan/* The function outputs PHR interface function `state_dead_lock_p'. */ 8052117395Skanstatic void 8053132718Skanoutput_dead_lock_func (void) 8054117395Skan{ 8055132718Skan fprintf (output_file, "int\n%s (%s %s)\n", 8056132718Skan DEAD_LOCK_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME); 8057117395Skan fprintf (output_file, "{\n return %s (%s);\n}\n\n", 8058117395Skan INTERNAL_DEAD_LOCK_FUNC_NAME, STATE_NAME); 8059117395Skan} 8060117395Skan 8061117395Skan/* Output function `internal_reset'. */ 8062117395Skanstatic void 8063132718Skanoutput_internal_reset_func (void) 8064117395Skan{ 8065132718Skan fprintf (output_file, "static inline void\n%s (struct %s *%s)\n", 8066132718Skan INTERNAL_RESET_FUNC_NAME, CHIP_NAME, CHIP_PARAMETER_NAME); 8067117395Skan fprintf (output_file, "{\n memset (%s, 0, sizeof (struct %s));\n}\n\n", 8068117395Skan CHIP_PARAMETER_NAME, CHIP_NAME); 8069117395Skan} 8070117395Skan 8071117395Skan/* The function outputs PHR interface function `state_size'. */ 8072117395Skanstatic void 8073132718Skanoutput_size_func (void) 8074117395Skan{ 8075132718Skan fprintf (output_file, "int\n%s (void)\n", SIZE_FUNC_NAME); 8076117395Skan fprintf (output_file, "{\n return sizeof (struct %s);\n}\n\n", CHIP_NAME); 8077117395Skan} 8078117395Skan 8079117395Skan/* The function outputs PHR interface function `state_reset'. */ 8080117395Skanstatic void 8081132718Skanoutput_reset_func (void) 8082117395Skan{ 8083132718Skan fprintf (output_file, "void\n%s (%s %s)\n", 8084132718Skan RESET_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME); 8085117395Skan fprintf (output_file, "{\n %s (%s);\n}\n\n", INTERNAL_RESET_FUNC_NAME, 8086117395Skan STATE_NAME); 8087117395Skan} 8088117395Skan 8089117395Skan/* Output function `min_insn_conflict_delay'. */ 8090117395Skanstatic void 8091132718Skanoutput_min_insn_conflict_delay_func (void) 8092117395Skan{ 8093117395Skan fprintf (output_file, 8094132718Skan "int\n%s (%s %s, rtx %s, rtx %s)\n", 8095132718Skan MIN_INSN_CONFLICT_DELAY_FUNC_NAME, STATE_TYPE_NAME, 8096132718Skan STATE_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME); 8097169689Skan fprintf (output_file, "{\n struct %s %s;\n int %s, %s, transition;\n", 8098117395Skan CHIP_NAME, CHIP_NAME, INTERNAL_INSN_CODE_NAME, 8099117395Skan INTERNAL_INSN2_CODE_NAME); 8100117395Skan output_internal_insn_code_evaluation (INSN_PARAMETER_NAME, 8101117395Skan INTERNAL_INSN_CODE_NAME, 0); 8102117395Skan output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME, 8103117395Skan INTERNAL_INSN2_CODE_NAME, 0); 8104117395Skan fprintf (output_file, " memcpy (&%s, %s, sizeof (%s));\n", 8105117395Skan CHIP_NAME, STATE_NAME, CHIP_NAME); 8106117395Skan fprintf (output_file, " %s (&%s);\n", INTERNAL_RESET_FUNC_NAME, CHIP_NAME); 8107169689Skan fprintf (output_file, " transition = %s (%s, &%s);\n", 8108117395Skan INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME); 8109169689Skan fprintf (output_file, " gcc_assert (transition <= 0);\n"); 8110117395Skan fprintf (output_file, " return %s (%s, &%s);\n", 8111117395Skan INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN2_CODE_NAME, 8112117395Skan CHIP_NAME); 8113117395Skan fprintf (output_file, "}\n\n"); 8114117395Skan} 8115117395Skan 8116117395Skan/* Output function `internal_insn_latency'. */ 8117117395Skanstatic void 8118132718Skanoutput_internal_insn_latency_func (void) 8119117395Skan{ 8120117395Skan decl_t decl; 8121117395Skan struct bypass_decl *bypass; 8122132718Skan int i, j, col; 8123132718Skan const char *tabletype = "unsigned char"; 8124117395Skan 8125132718Skan /* Find the smallest integer type that can hold all the default 8126132718Skan latency values. */ 8127132718Skan for (i = 0; i < description->decls_num; i++) 8128132718Skan if (description->decls[i]->mode == dm_insn_reserv) 8129132718Skan { 8130132718Skan decl = description->decls[i]; 8131132718Skan if (DECL_INSN_RESERV (decl)->default_latency > UCHAR_MAX 8132132718Skan && tabletype[0] != 'i') /* Don't shrink it. */ 8133132718Skan tabletype = "unsigned short"; 8134132718Skan if (DECL_INSN_RESERV (decl)->default_latency > USHRT_MAX) 8135132718Skan tabletype = "int"; 8136132718Skan } 8137132718Skan 8138132718Skan 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", 8139117395Skan INTERNAL_INSN_LATENCY_FUNC_NAME, INTERNAL_INSN_CODE_NAME, 8140117395Skan INTERNAL_INSN2_CODE_NAME, INSN_PARAMETER_NAME, 8141117395Skan INSN2_PARAMETER_NAME); 8142132718Skan fprintf (output_file, "{\n"); 8143132718Skan 8144132718Skan if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0) 8145117395Skan { 8146132718Skan fputs (" return 0;\n}\n\n", output_file); 8147132718Skan return; 8148117395Skan } 8149132718Skan 8150132718Skan fprintf (output_file, " static const %s default_latencies[] =\n {", 8151132718Skan tabletype); 8152132718Skan 8153132718Skan for (i = 0, j = 0, col = 7; i < description->decls_num; i++) 8154132718Skan if (description->decls[i]->mode == dm_insn_reserv 8155132718Skan && description->decls[i] != advance_cycle_insn_decl) 8156132718Skan { 8157132718Skan if ((col = (col+1) % 8) == 0) 8158132718Skan fputs ("\n ", output_file); 8159132718Skan decl = description->decls[i]; 8160169689Skan gcc_assert (j++ == DECL_INSN_RESERV (decl)->insn_num); 8161132718Skan fprintf (output_file, "% 4d,", 8162132718Skan DECL_INSN_RESERV (decl)->default_latency); 8163132718Skan } 8164169689Skan gcc_assert (j == DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num); 8165132718Skan fputs ("\n };\n", output_file); 8166132718Skan 8167132718Skan fprintf (output_file, " if (%s >= %s || %s >= %s)\n return 0;\n", 8168132718Skan INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME, 8169132718Skan INTERNAL_INSN2_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME); 8170132718Skan 8171132718Skan fprintf (output_file, " switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME); 8172132718Skan for (i = 0; i < description->decls_num; i++) 8173132718Skan if (description->decls[i]->mode == dm_insn_reserv 8174132718Skan && DECL_INSN_RESERV (description->decls[i])->bypass_list) 8175132718Skan { 8176132718Skan decl = description->decls [i]; 8177132718Skan fprintf (output_file, 8178132718Skan " case %d:\n switch (%s)\n {\n", 8179132718Skan DECL_INSN_RESERV (decl)->insn_num, 8180132718Skan INTERNAL_INSN2_CODE_NAME); 8181132718Skan for (bypass = DECL_INSN_RESERV (decl)->bypass_list; 8182132718Skan bypass != NULL; 8183132718Skan bypass = bypass->next) 8184132718Skan { 8185169689Skan gcc_assert (bypass->in_insn_reserv->insn_num 8186169689Skan != (DECL_INSN_RESERV 8187169689Skan (advance_cycle_insn_decl)->insn_num)); 8188132718Skan fprintf (output_file, " case %d:\n", 8189132718Skan bypass->in_insn_reserv->insn_num); 8190132718Skan if (bypass->bypass_guard_name == NULL) 8191132718Skan fprintf (output_file, " return %d;\n", 8192132718Skan bypass->latency); 8193132718Skan else 8194132718Skan { 8195132718Skan fprintf (output_file, 8196132718Skan " if (%s (%s, %s))\n", 8197132718Skan bypass->bypass_guard_name, INSN_PARAMETER_NAME, 8198132718Skan INSN2_PARAMETER_NAME); 8199132718Skan fprintf (output_file, 8200132718Skan " return %d;\n break;\n", 8201132718Skan bypass->latency); 8202132718Skan } 8203132718Skan } 8204132718Skan fputs (" }\n break;\n", output_file); 8205132718Skan } 8206132718Skan 8207132718Skan fprintf (output_file, " }\n return default_latencies[%s];\n}\n\n", 8208132718Skan INTERNAL_INSN_CODE_NAME); 8209117395Skan} 8210117395Skan 8211117395Skan/* The function outputs PHR interface function `insn_latency'. */ 8212117395Skanstatic void 8213132718Skanoutput_insn_latency_func (void) 8214117395Skan{ 8215132718Skan fprintf (output_file, "int\n%s (rtx %s, rtx %s)\n", 8216132718Skan INSN_LATENCY_FUNC_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME); 8217117395Skan fprintf (output_file, "{\n int %s, %s;\n", 8218117395Skan INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME); 8219117395Skan output_internal_insn_code_evaluation (INSN_PARAMETER_NAME, 8220117395Skan INTERNAL_INSN_CODE_NAME, 0); 8221117395Skan output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME, 8222117395Skan INTERNAL_INSN2_CODE_NAME, 0); 8223117395Skan fprintf (output_file, " return %s (%s, %s, %s, %s);\n}\n\n", 8224117395Skan INTERNAL_INSN_LATENCY_FUNC_NAME, 8225117395Skan INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME, 8226117395Skan INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME); 8227117395Skan} 8228117395Skan 8229117395Skan/* The function outputs PHR interface function `print_reservation'. */ 8230117395Skanstatic void 8231132718Skanoutput_print_reservation_func (void) 8232117395Skan{ 8233117395Skan decl_t decl; 8234132718Skan int i, j; 8235117395Skan 8236132718Skan fprintf (output_file, 8237132718Skan "void\n%s (FILE *%s, rtx %s ATTRIBUTE_UNUSED)\n{\n", 8238117395Skan PRINT_RESERVATION_FUNC_NAME, FILE_PARAMETER_NAME, 8239117395Skan INSN_PARAMETER_NAME); 8240132718Skan 8241132718Skan if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0) 8242117395Skan { 8243132718Skan fprintf (output_file, " fputs (\"%s\", %s);\n}\n\n", 8244132718Skan NOTHING_NAME, FILE_PARAMETER_NAME); 8245132718Skan return; 8246132718Skan } 8247132718Skan 8248132718Skan 8249132718Skan fputs (" static const char *const reservation_names[] =\n {", 8250132718Skan output_file); 8251132718Skan 8252132718Skan for (i = 0, j = 0; i < description->decls_num; i++) 8253132718Skan { 8254117395Skan decl = description->decls [i]; 8255117395Skan if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl) 8256117395Skan { 8257169689Skan gcc_assert (j == DECL_INSN_RESERV (decl)->insn_num); 8258169689Skan j++; 8259169689Skan 8260132718Skan fprintf (output_file, "\n \"%s\",", 8261132718Skan regexp_representation (DECL_INSN_RESERV (decl)->regexp)); 8262132718Skan finish_regexp_representation (); 8263132718Skan } 8264117395Skan } 8265169689Skan gcc_assert (j == DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num); 8266132718Skan 8267132718Skan fprintf (output_file, "\n \"%s\"\n };\n int %s;\n\n", 8268132718Skan NOTHING_NAME, INTERNAL_INSN_CODE_NAME); 8269132718Skan 8270132718Skan fprintf (output_file, " if (%s == 0)\n %s = %s;\n", 8271132718Skan INSN_PARAMETER_NAME, 8272132718Skan INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME); 8273132718Skan fprintf (output_file, " else\n\ 8274132718Skan {\n\ 8275132718Skan %s = %s (%s);\n\ 8276132718Skan if (%s > %s)\n\ 8277132718Skan %s = %s;\n\ 8278132718Skan }\n", 8279132718Skan INTERNAL_INSN_CODE_NAME, DFA_INSN_CODE_FUNC_NAME, 8280132718Skan INSN_PARAMETER_NAME, 8281132718Skan INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME, 8282132718Skan INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME); 8283132718Skan 8284132718Skan fprintf (output_file, " fputs (reservation_names[%s], %s);\n}\n\n", 8285132718Skan INTERNAL_INSN_CODE_NAME, FILE_PARAMETER_NAME); 8286117395Skan} 8287117395Skan 8288117395Skan/* The following function is used to sort unit declaration by their 8289117395Skan names. */ 8290117395Skanstatic int 8291132718Skanunits_cmp (const void *unit1, const void *unit2) 8292117395Skan{ 8293117395Skan const unit_decl_t u1 = *(unit_decl_t *) unit1; 8294117395Skan const unit_decl_t u2 = *(unit_decl_t *) unit2; 8295117395Skan 8296117395Skan return strcmp (u1->name, u2->name); 8297117395Skan} 8298117395Skan 8299117395Skan/* The following macro value is name of struct containing unit name 8300117395Skan and unit code. */ 8301117395Skan#define NAME_CODE_STRUCT_NAME "name_code" 8302117395Skan 8303117395Skan/* The following macro value is name of table of struct name_code. */ 8304117395Skan#define NAME_CODE_TABLE_NAME "name_code_table" 8305117395Skan 8306117395Skan/* The following macro values are member names for struct name_code. */ 8307117395Skan#define NAME_MEMBER_NAME "name" 8308117395Skan#define CODE_MEMBER_NAME "code" 8309117395Skan 8310117395Skan/* The following macro values are local variable names for function 8311117395Skan `get_cpu_unit_code'. */ 8312117395Skan#define CMP_VARIABLE_NAME "cmp" 8313117395Skan#define LOW_VARIABLE_NAME "l" 8314117395Skan#define MIDDLE_VARIABLE_NAME "m" 8315117395Skan#define HIGH_VARIABLE_NAME "h" 8316117395Skan 8317117395Skan/* The following function outputs function to obtain internal cpu unit 8318117395Skan code by the cpu unit name. */ 8319117395Skanstatic void 8320132718Skanoutput_get_cpu_unit_code_func (void) 8321117395Skan{ 8322117395Skan int i; 8323117395Skan unit_decl_t *units; 8324132718Skan 8325169689Skan fprintf (output_file, "int\n%s (const char *%s)\n", 8326169689Skan GET_CPU_UNIT_CODE_FUNC_NAME, CPU_UNIT_NAME_PARAMETER_NAME); 8327117395Skan fprintf (output_file, "{\n struct %s {const char *%s; int %s;};\n", 8328117395Skan NAME_CODE_STRUCT_NAME, NAME_MEMBER_NAME, CODE_MEMBER_NAME); 8329117395Skan fprintf (output_file, " int %s, %s, %s, %s;\n", CMP_VARIABLE_NAME, 8330117395Skan LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME, HIGH_VARIABLE_NAME); 8331117395Skan fprintf (output_file, " static struct %s %s [] =\n {\n", 8332117395Skan NAME_CODE_STRUCT_NAME, NAME_CODE_TABLE_NAME); 8333132718Skan units = xmalloc (sizeof (unit_decl_t) * description->units_num); 8334117395Skan memcpy (units, units_array, sizeof (unit_decl_t) * description->units_num); 8335117395Skan qsort (units, description->units_num, sizeof (unit_decl_t), units_cmp); 8336117395Skan for (i = 0; i < description->units_num; i++) 8337117395Skan if (units [i]->query_p) 8338117395Skan fprintf (output_file, " {\"%s\", %d},\n", 8339117395Skan units[i]->name, units[i]->query_num); 8340117395Skan fprintf (output_file, " };\n\n"); 8341117395Skan fprintf (output_file, " /* The following is binary search: */\n"); 8342117395Skan fprintf (output_file, " %s = 0;\n", LOW_VARIABLE_NAME); 8343117395Skan fprintf (output_file, " %s = sizeof (%s) / sizeof (struct %s) - 1;\n", 8344117395Skan HIGH_VARIABLE_NAME, NAME_CODE_TABLE_NAME, NAME_CODE_STRUCT_NAME); 8345117395Skan fprintf (output_file, " while (%s <= %s)\n {\n", 8346117395Skan LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME); 8347117395Skan fprintf (output_file, " %s = (%s + %s) / 2;\n", 8348117395Skan MIDDLE_VARIABLE_NAME, LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME); 8349117395Skan fprintf (output_file, " %s = strcmp (%s, %s [%s].%s);\n", 8350117395Skan CMP_VARIABLE_NAME, CPU_UNIT_NAME_PARAMETER_NAME, 8351117395Skan NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, NAME_MEMBER_NAME); 8352117395Skan fprintf (output_file, " if (%s < 0)\n", CMP_VARIABLE_NAME); 8353117395Skan fprintf (output_file, " %s = %s - 1;\n", 8354117395Skan HIGH_VARIABLE_NAME, MIDDLE_VARIABLE_NAME); 8355117395Skan fprintf (output_file, " else if (%s > 0)\n", CMP_VARIABLE_NAME); 8356117395Skan fprintf (output_file, " %s = %s + 1;\n", 8357117395Skan LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME); 8358117395Skan fprintf (output_file, " else\n"); 8359117395Skan fprintf (output_file, " return %s [%s].%s;\n }\n", 8360117395Skan NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, CODE_MEMBER_NAME); 8361117395Skan fprintf (output_file, " return -1;\n}\n\n"); 8362117395Skan free (units); 8363117395Skan} 8364117395Skan 8365117395Skan/* The following function outputs function to check reservation of cpu 8366117395Skan unit (its internal code will be passed as the function argument) in 8367117395Skan given cpu state. */ 8368117395Skanstatic void 8369132718Skanoutput_cpu_unit_reservation_p (void) 8370117395Skan{ 8371117395Skan automaton_t automaton; 8372117395Skan 8373169689Skan fprintf (output_file, "int\n%s (%s %s, int %s)\n", 8374169689Skan CPU_UNIT_RESERVATION_P_FUNC_NAME, 8375169689Skan STATE_TYPE_NAME, STATE_NAME, 8376117395Skan CPU_CODE_PARAMETER_NAME); 8377169689Skan fprintf (output_file, "{\n gcc_assert (%s >= 0 && %s < %d);\n", 8378117395Skan CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME, 8379117395Skan description->query_units_num); 8380169689Skan if (description->query_units_num > 0) 8381169689Skan for (automaton = description->first_automaton; 8382169689Skan automaton != NULL; 8383169689Skan automaton = automaton->next_automaton) 8384169689Skan { 8385169689Skan fprintf (output_file, " if (("); 8386169689Skan output_reserved_units_table_name (output_file, automaton); 8387169689Skan fprintf (output_file, " [((struct %s *) %s)->", CHIP_NAME, STATE_NAME); 8388169689Skan output_chip_member_name (output_file, automaton); 8389169689Skan fprintf (output_file, " * %d + %s / 8] >> (%s %% 8)) & 1)\n", 8390169689Skan (description->query_units_num + 7) / 8, 8391169689Skan CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME); 8392169689Skan fprintf (output_file, " return 1;\n"); 8393169689Skan } 8394117395Skan fprintf (output_file, " return 0;\n}\n\n"); 8395117395Skan} 8396117395Skan 8397169689Skan/* The function outputs PHR interface functions `dfa_clean_insn_cache' 8398169689Skan and 'dfa_clear_single_insn_cache'. */ 8399117395Skanstatic void 8400132718Skanoutput_dfa_clean_insn_cache_func (void) 8401117395Skan{ 8402117395Skan fprintf (output_file, 8403132718Skan "void\n%s (void)\n{\n int %s;\n\n", 8404132718Skan DFA_CLEAN_INSN_CACHE_FUNC_NAME, I_VARIABLE_NAME); 8405117395Skan fprintf (output_file, 8406117395Skan " for (%s = 0; %s < %s; %s++)\n %s [%s] = -1;\n}\n\n", 8407117395Skan I_VARIABLE_NAME, I_VARIABLE_NAME, 8408117395Skan DFA_INSN_CODES_LENGTH_VARIABLE_NAME, I_VARIABLE_NAME, 8409117395Skan DFA_INSN_CODES_VARIABLE_NAME, I_VARIABLE_NAME); 8410169689Skan 8411169689Skan fprintf (output_file, 8412169689Skan "void\n%s (rtx %s)\n{\n int %s;\n\n", 8413169689Skan DFA_CLEAR_SINGLE_INSN_CACHE_FUNC_NAME, INSN_PARAMETER_NAME, 8414169689Skan I_VARIABLE_NAME); 8415169689Skan fprintf (output_file, 8416169689Skan " %s = INSN_UID (%s);\n if (%s < %s)\n %s [%s] = -1;\n}\n\n", 8417169689Skan I_VARIABLE_NAME, INSN_PARAMETER_NAME, I_VARIABLE_NAME, 8418169689Skan DFA_INSN_CODES_LENGTH_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME, 8419169689Skan I_VARIABLE_NAME); 8420117395Skan} 8421117395Skan 8422132718Skan/* The function outputs PHR interface function `dfa_start'. */ 8423132718Skanstatic void 8424132718Skanoutput_dfa_start_func (void) 8425132718Skan{ 8426132718Skan fprintf (output_file, 8427132718Skan "void\n%s (void)\n{\n %s = get_max_uid ();\n", 8428132718Skan DFA_START_FUNC_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME); 8429132718Skan fprintf (output_file, " %s = xmalloc (%s * sizeof (int));\n", 8430132718Skan DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME); 8431132718Skan fprintf (output_file, " %s ();\n}\n\n", DFA_CLEAN_INSN_CACHE_FUNC_NAME); 8432132718Skan} 8433132718Skan 8434117395Skan/* The function outputs PHR interface function `dfa_finish'. */ 8435117395Skanstatic void 8436132718Skanoutput_dfa_finish_func (void) 8437117395Skan{ 8438132718Skan fprintf (output_file, "void\n%s (void)\n{\n free (%s);\n}\n\n", 8439117395Skan DFA_FINISH_FUNC_NAME, DFA_INSN_CODES_VARIABLE_NAME); 8440117395Skan} 8441117395Skan 8442117395Skan 8443117395Skan 8444117395Skan/* The page contains code for output description file (readable 8445117395Skan representation of original description and generated DFA(s). */ 8446117395Skan 8447117395Skan/* The function outputs string representation of IR reservation. */ 8448117395Skanstatic void 8449132718Skanoutput_regexp (regexp_t regexp) 8450117395Skan{ 8451117395Skan fprintf (output_description_file, "%s", regexp_representation (regexp)); 8452117395Skan finish_regexp_representation (); 8453117395Skan} 8454117395Skan 8455117395Skan/* Output names of units in LIST separated by comma. */ 8456117395Skanstatic void 8457132718Skanoutput_unit_set_el_list (unit_set_el_t list) 8458117395Skan{ 8459117395Skan unit_set_el_t el; 8460117395Skan 8461117395Skan for (el = list; el != NULL; el = el->next_unit_set_el) 8462117395Skan { 8463117395Skan if (el != list) 8464132718Skan fprintf (output_description_file, ", "); 8465117395Skan fprintf (output_description_file, "%s", el->unit_decl->name); 8466117395Skan } 8467117395Skan} 8468117395Skan 8469132718Skan/* Output patterns in LIST separated by comma. */ 8470132718Skanstatic void 8471132718Skanoutput_pattern_set_el_list (pattern_set_el_t list) 8472132718Skan{ 8473132718Skan pattern_set_el_t el; 8474132718Skan int i; 8475132718Skan 8476132718Skan for (el = list; el != NULL; el = el->next_pattern_set_el) 8477132718Skan { 8478132718Skan if (el != list) 8479132718Skan fprintf (output_description_file, ", "); 8480132718Skan for (i = 0; i < el->units_num; i++) 8481132718Skan fprintf (output_description_file, (i == 0 ? "%s" : " %s"), 8482132718Skan el->unit_decls [i]->name); 8483132718Skan } 8484132718Skan} 8485132718Skan 8486117395Skan/* The function outputs string representation of IR define_reservation 8487117395Skan and define_insn_reservation. */ 8488117395Skanstatic void 8489132718Skanoutput_description (void) 8490117395Skan{ 8491117395Skan decl_t decl; 8492117395Skan int i; 8493117395Skan 8494117395Skan for (i = 0; i < description->decls_num; i++) 8495117395Skan { 8496117395Skan decl = description->decls [i]; 8497117395Skan if (decl->mode == dm_unit) 8498117395Skan { 8499117395Skan if (DECL_UNIT (decl)->excl_list != NULL) 8500117395Skan { 8501117395Skan fprintf (output_description_file, "unit %s exlusion_set: ", 8502117395Skan DECL_UNIT (decl)->name); 8503117395Skan output_unit_set_el_list (DECL_UNIT (decl)->excl_list); 8504117395Skan fprintf (output_description_file, "\n"); 8505117395Skan } 8506117395Skan if (DECL_UNIT (decl)->presence_list != NULL) 8507117395Skan { 8508117395Skan fprintf (output_description_file, "unit %s presence_set: ", 8509117395Skan DECL_UNIT (decl)->name); 8510132718Skan output_pattern_set_el_list (DECL_UNIT (decl)->presence_list); 8511117395Skan fprintf (output_description_file, "\n"); 8512117395Skan } 8513132718Skan if (DECL_UNIT (decl)->final_presence_list != NULL) 8514132718Skan { 8515132718Skan fprintf (output_description_file, "unit %s final_presence_set: ", 8516132718Skan DECL_UNIT (decl)->name); 8517132718Skan output_pattern_set_el_list 8518132718Skan (DECL_UNIT (decl)->final_presence_list); 8519132718Skan fprintf (output_description_file, "\n"); 8520132718Skan } 8521117395Skan if (DECL_UNIT (decl)->absence_list != NULL) 8522117395Skan { 8523117395Skan fprintf (output_description_file, "unit %s absence_set: ", 8524117395Skan DECL_UNIT (decl)->name); 8525132718Skan output_pattern_set_el_list (DECL_UNIT (decl)->absence_list); 8526117395Skan fprintf (output_description_file, "\n"); 8527117395Skan } 8528132718Skan if (DECL_UNIT (decl)->final_absence_list != NULL) 8529132718Skan { 8530132718Skan fprintf (output_description_file, "unit %s final_absence_set: ", 8531132718Skan DECL_UNIT (decl)->name); 8532132718Skan output_pattern_set_el_list 8533132718Skan (DECL_UNIT (decl)->final_absence_list); 8534132718Skan fprintf (output_description_file, "\n"); 8535132718Skan } 8536117395Skan } 8537117395Skan } 8538117395Skan fprintf (output_description_file, "\n"); 8539117395Skan for (i = 0; i < description->decls_num; i++) 8540117395Skan { 8541117395Skan decl = description->decls [i]; 8542117395Skan if (decl->mode == dm_reserv) 8543117395Skan { 8544132718Skan fprintf (output_description_file, "reservation %s: ", 8545132718Skan DECL_RESERV (decl)->name); 8546117395Skan output_regexp (DECL_RESERV (decl)->regexp); 8547117395Skan fprintf (output_description_file, "\n"); 8548117395Skan } 8549117395Skan else if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl) 8550117395Skan { 8551117395Skan fprintf (output_description_file, "insn reservation %s ", 8552117395Skan DECL_INSN_RESERV (decl)->name); 8553117395Skan print_rtl (output_description_file, 8554117395Skan DECL_INSN_RESERV (decl)->condexp); 8555117395Skan fprintf (output_description_file, ": "); 8556117395Skan output_regexp (DECL_INSN_RESERV (decl)->regexp); 8557117395Skan fprintf (output_description_file, "\n"); 8558117395Skan } 8559117395Skan else if (decl->mode == dm_bypass) 8560117395Skan fprintf (output_description_file, "bypass %d %s %s\n", 8561117395Skan DECL_BYPASS (decl)->latency, 8562117395Skan DECL_BYPASS (decl)->out_insn_name, 8563117395Skan DECL_BYPASS (decl)->in_insn_name); 8564117395Skan } 8565117395Skan fprintf (output_description_file, "\n\f\n"); 8566117395Skan} 8567117395Skan 8568117395Skan/* The function outputs name of AUTOMATON. */ 8569117395Skanstatic void 8570132718Skanoutput_automaton_name (FILE *f, automaton_t automaton) 8571117395Skan{ 8572117395Skan if (automaton->corresponding_automaton_decl == NULL) 8573117395Skan fprintf (f, "#%d", automaton->automaton_order_num); 8574117395Skan else 8575117395Skan fprintf (f, "`%s'", automaton->corresponding_automaton_decl->name); 8576117395Skan} 8577117395Skan 8578117395Skan/* Maximal length of line for pretty printing into description 8579117395Skan file. */ 8580117395Skan#define MAX_LINE_LENGTH 70 8581117395Skan 8582117395Skan/* The function outputs units name belonging to AUTOMATON. */ 8583117395Skanstatic void 8584132718Skanoutput_automaton_units (automaton_t automaton) 8585117395Skan{ 8586117395Skan decl_t decl; 8587169689Skan const char *name; 8588117395Skan int curr_line_length; 8589117395Skan int there_is_an_automaton_unit; 8590117395Skan int i; 8591117395Skan 8592169689Skan fprintf (output_description_file, "\n Corresponding units:\n"); 8593117395Skan fprintf (output_description_file, " "); 8594117395Skan curr_line_length = 4; 8595117395Skan there_is_an_automaton_unit = 0; 8596117395Skan for (i = 0; i < description->decls_num; i++) 8597117395Skan { 8598117395Skan decl = description->decls [i]; 8599117395Skan if (decl->mode == dm_unit 8600117395Skan && (DECL_UNIT (decl)->corresponding_automaton_num 8601117395Skan == automaton->automaton_order_num)) 8602117395Skan { 8603117395Skan there_is_an_automaton_unit = 1; 8604117395Skan name = DECL_UNIT (decl)->name; 8605117395Skan if (curr_line_length + strlen (name) + 1 > MAX_LINE_LENGTH ) 8606117395Skan { 8607117395Skan curr_line_length = strlen (name) + 4; 8608117395Skan fprintf (output_description_file, "\n "); 8609117395Skan } 8610117395Skan else 8611117395Skan { 8612117395Skan curr_line_length += strlen (name) + 1; 8613117395Skan fprintf (output_description_file, " "); 8614117395Skan } 8615132718Skan fprintf (output_description_file, "%s", name); 8616117395Skan } 8617117395Skan } 8618117395Skan if (!there_is_an_automaton_unit) 8619117395Skan fprintf (output_description_file, "<None>"); 8620117395Skan fprintf (output_description_file, "\n\n"); 8621117395Skan} 8622117395Skan 8623117395Skan/* The following variable is used for forming array of all possible cpu unit 8624117395Skan reservations described by the current DFA state. */ 8625169689Skanstatic VEC(reserv_sets_t,heap) *state_reservs; 8626117395Skan 8627117395Skan/* The function forms `state_reservs' for STATE. */ 8628117395Skanstatic void 8629132718Skanadd_state_reservs (state_t state) 8630117395Skan{ 8631117395Skan alt_state_t curr_alt_state; 8632117395Skan 8633117395Skan if (state->component_states != NULL) 8634117395Skan for (curr_alt_state = state->component_states; 8635117395Skan curr_alt_state != NULL; 8636117395Skan curr_alt_state = curr_alt_state->next_sorted_alt_state) 8637117395Skan add_state_reservs (curr_alt_state->state); 8638117395Skan else 8639169689Skan VEC_safe_push (reserv_sets_t,heap, state_reservs, state->reservs); 8640117395Skan} 8641117395Skan 8642132718Skan/* The function outputs readable representation of all out arcs of 8643117395Skan STATE. */ 8644117395Skanstatic void 8645132718Skanoutput_state_arcs (state_t state) 8646117395Skan{ 8647117395Skan arc_t arc; 8648117395Skan ainsn_t ainsn; 8649169689Skan const char *insn_name; 8650117395Skan int curr_line_length; 8651117395Skan 8652117395Skan for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc)) 8653117395Skan { 8654117395Skan ainsn = arc->insn; 8655169689Skan gcc_assert (ainsn->first_insn_with_same_reservs); 8656117395Skan fprintf (output_description_file, " "); 8657117395Skan curr_line_length = 7; 8658117395Skan fprintf (output_description_file, "%2d: ", ainsn->insn_equiv_class_num); 8659117395Skan do 8660117395Skan { 8661117395Skan insn_name = ainsn->insn_reserv_decl->name; 8662117395Skan if (curr_line_length + strlen (insn_name) > MAX_LINE_LENGTH) 8663117395Skan { 8664117395Skan if (ainsn != arc->insn) 8665117395Skan { 8666117395Skan fprintf (output_description_file, ",\n "); 8667117395Skan curr_line_length = strlen (insn_name) + 6; 8668117395Skan } 8669117395Skan else 8670117395Skan curr_line_length += strlen (insn_name); 8671117395Skan } 8672117395Skan else 8673117395Skan { 8674117395Skan curr_line_length += strlen (insn_name); 8675117395Skan if (ainsn != arc->insn) 8676117395Skan { 8677117395Skan curr_line_length += 2; 8678117395Skan fprintf (output_description_file, ", "); 8679117395Skan } 8680117395Skan } 8681132718Skan fprintf (output_description_file, "%s", insn_name); 8682117395Skan ainsn = ainsn->next_same_reservs_insn; 8683117395Skan } 8684117395Skan while (ainsn != NULL); 8685169689Skan fprintf (output_description_file, " %d \n", 8686169689Skan arc->to_state->order_state_num); 8687117395Skan } 8688117395Skan fprintf (output_description_file, "\n"); 8689117395Skan} 8690117395Skan 8691117395Skan/* The following function is used for sorting possible cpu unit 8692117395Skan reservation of a DFA state. */ 8693117395Skanstatic int 8694132718Skanstate_reservs_cmp (const void *reservs_ptr_1, const void *reservs_ptr_2) 8695117395Skan{ 8696117395Skan return reserv_sets_cmp (*(reserv_sets_t *) reservs_ptr_1, 8697117395Skan *(reserv_sets_t *) reservs_ptr_2); 8698117395Skan} 8699117395Skan 8700117395Skan/* The following function is used for sorting possible cpu unit 8701117395Skan reservation of a DFA state. */ 8702117395Skanstatic void 8703132718Skanremove_state_duplicate_reservs (void) 8704117395Skan{ 8705169689Skan size_t i, j; 8706117395Skan 8707169689Skan for (i = 1, j = 0; i < VEC_length (reserv_sets_t, state_reservs); i++) 8708169689Skan if (reserv_sets_cmp (VEC_index (reserv_sets_t, state_reservs, j), 8709169689Skan VEC_index (reserv_sets_t, state_reservs, i))) 8710117395Skan { 8711169689Skan j++; 8712169689Skan VEC_replace (reserv_sets_t, state_reservs, j, 8713169689Skan VEC_index (reserv_sets_t, state_reservs, i)); 8714117395Skan } 8715169689Skan VEC_truncate (reserv_sets_t, state_reservs, j + 1); 8716117395Skan} 8717117395Skan 8718117395Skan/* The following function output readable representation of DFA(s) 8719117395Skan state used for fast recognition of pipeline hazards. State is 8720132718Skan described by possible (current and scheduled) cpu unit 8721117395Skan reservations. */ 8722117395Skanstatic void 8723132718Skanoutput_state (state_t state) 8724117395Skan{ 8725169689Skan size_t i; 8726117395Skan 8727169689Skan state_reservs = 0; 8728169689Skan 8729117395Skan fprintf (output_description_file, " State #%d", state->order_state_num); 8730117395Skan fprintf (output_description_file, 8731117395Skan state->new_cycle_p ? " (new cycle)\n" : "\n"); 8732117395Skan add_state_reservs (state); 8733169689Skan qsort (VEC_address (reserv_sets_t, state_reservs), 8734169689Skan VEC_length (reserv_sets_t, state_reservs), 8735117395Skan sizeof (reserv_sets_t), state_reservs_cmp); 8736117395Skan remove_state_duplicate_reservs (); 8737169689Skan for (i = 1; i < VEC_length (reserv_sets_t, state_reservs); i++) 8738117395Skan { 8739117395Skan fprintf (output_description_file, " "); 8740169689Skan output_reserv_sets (output_description_file, 8741169689Skan VEC_index (reserv_sets_t, state_reservs, i)); 8742117395Skan fprintf (output_description_file, "\n"); 8743117395Skan } 8744117395Skan fprintf (output_description_file, "\n"); 8745117395Skan output_state_arcs (state); 8746169689Skan VEC_free (reserv_sets_t,heap, state_reservs); 8747117395Skan} 8748117395Skan 8749117395Skan/* The following function output readable representation of 8750117395Skan DFAs used for fast recognition of pipeline hazards. */ 8751117395Skanstatic void 8752132718Skanoutput_automaton_descriptions (void) 8753117395Skan{ 8754117395Skan automaton_t automaton; 8755117395Skan 8756117395Skan for (automaton = description->first_automaton; 8757117395Skan automaton != NULL; 8758117395Skan automaton = automaton->next_automaton) 8759117395Skan { 8760117395Skan fprintf (output_description_file, "\nAutomaton "); 8761117395Skan output_automaton_name (output_description_file, automaton); 8762117395Skan fprintf (output_description_file, "\n"); 8763117395Skan output_automaton_units (automaton); 8764117395Skan pass_states (automaton, output_state); 8765117395Skan } 8766117395Skan} 8767117395Skan 8768117395Skan 8769117395Skan 8770117395Skan/* The page contains top level function for generation DFA(s) used for 8771117395Skan PHR. */ 8772117395Skan 8773117395Skan/* The function outputs statistics about work of different phases of 8774117395Skan DFA generator. */ 8775117395Skanstatic void 8776132718Skanoutput_statistics (FILE *f) 8777117395Skan{ 8778117395Skan automaton_t automaton; 8779132718Skan int states_num; 8780117395Skan#ifndef NDEBUG 8781117395Skan int transition_comb_vect_els = 0; 8782117395Skan int transition_full_vect_els = 0; 8783117395Skan int min_issue_delay_vect_els = 0; 8784169689Skan int locked_states = 0; 8785117395Skan#endif 8786117395Skan 8787117395Skan for (automaton = description->first_automaton; 8788117395Skan automaton != NULL; 8789117395Skan automaton = automaton->next_automaton) 8790117395Skan { 8791117395Skan fprintf (f, "\nAutomaton "); 8792117395Skan output_automaton_name (f, automaton); 8793117395Skan fprintf (f, "\n %5d NDFA states, %5d NDFA arcs\n", 8794117395Skan automaton->NDFA_states_num, automaton->NDFA_arcs_num); 8795117395Skan fprintf (f, " %5d DFA states, %5d DFA arcs\n", 8796117395Skan automaton->DFA_states_num, automaton->DFA_arcs_num); 8797132718Skan states_num = automaton->DFA_states_num; 8798117395Skan if (!no_minimization_flag) 8799132718Skan { 8800132718Skan fprintf (f, " %5d minimal DFA states, %5d minimal DFA arcs\n", 8801132718Skan automaton->minimal_DFA_states_num, 8802132718Skan automaton->minimal_DFA_arcs_num); 8803132718Skan states_num = automaton->minimal_DFA_states_num; 8804132718Skan } 8805117395Skan fprintf (f, " %5d all insns %5d insn equivalence classes\n", 8806117395Skan description->insns_num, automaton->insn_equiv_classes_num); 8807169689Skan fprintf (f, " %d locked states\n", automaton->locked_states); 8808117395Skan#ifndef NDEBUG 8809117395Skan fprintf 8810117395Skan (f, "%5ld transition comb vector els, %5ld trans table els: %s\n", 8811169689Skan (long) VEC_length (vect_el_t, automaton->trans_table->comb_vect), 8812169689Skan (long) VEC_length (vect_el_t, automaton->trans_table->full_vect), 8813117395Skan (comb_vect_p (automaton->trans_table) 8814117395Skan ? "use comb vect" : "use simple vect")); 8815117395Skan fprintf 8816117395Skan (f, "%5ld min delay table els, compression factor %d\n", 8817132718Skan (long) states_num * automaton->insn_equiv_classes_num, 8818117395Skan automaton->min_issue_delay_table_compression_factor); 8819117395Skan transition_comb_vect_els 8820169689Skan += VEC_length (vect_el_t, automaton->trans_table->comb_vect); 8821132718Skan transition_full_vect_els 8822169689Skan += VEC_length (vect_el_t, automaton->trans_table->full_vect); 8823117395Skan min_issue_delay_vect_els 8824132718Skan += states_num * automaton->insn_equiv_classes_num; 8825169689Skan locked_states 8826169689Skan += automaton->locked_states; 8827117395Skan#endif 8828117395Skan } 8829117395Skan#ifndef NDEBUG 8830117395Skan fprintf (f, "\n%5d all allocated states, %5d all allocated arcs\n", 8831117395Skan allocated_states_num, allocated_arcs_num); 8832117395Skan fprintf (f, "%5d all allocated alternative states\n", 8833117395Skan allocated_alt_states_num); 8834117395Skan fprintf (f, "%5d all transition comb vector els, %5d all trans table els\n", 8835117395Skan transition_comb_vect_els, transition_full_vect_els); 8836117395Skan fprintf (f, "%5d all min delay table els\n", min_issue_delay_vect_els); 8837169689Skan fprintf (f, "%5d all locked states\n", locked_states); 8838117395Skan#endif 8839117395Skan} 8840117395Skan 8841117395Skan/* The function output times of work of different phases of DFA 8842117395Skan generator. */ 8843117395Skanstatic void 8844132718Skanoutput_time_statistics (FILE *f) 8845117395Skan{ 8846117395Skan fprintf (f, "\n transformation: "); 8847117395Skan print_active_time (f, transform_time); 8848117395Skan fprintf (f, (!ndfa_flag ? ", building DFA: " : ", building NDFA: ")); 8849117395Skan print_active_time (f, NDFA_time); 8850117395Skan if (ndfa_flag) 8851117395Skan { 8852117395Skan fprintf (f, ", NDFA -> DFA: "); 8853117395Skan print_active_time (f, NDFA_to_DFA_time); 8854117395Skan } 8855117395Skan fprintf (f, "\n DFA minimization: "); 8856117395Skan print_active_time (f, minimize_time); 8857117395Skan fprintf (f, ", making insn equivalence: "); 8858117395Skan print_active_time (f, equiv_time); 8859117395Skan fprintf (f, "\n all automaton generation: "); 8860117395Skan print_active_time (f, automaton_generation_time); 8861117395Skan fprintf (f, ", output: "); 8862117395Skan print_active_time (f, output_time); 8863117395Skan fprintf (f, "\n"); 8864117395Skan} 8865117395Skan 8866132718Skan/* The function generates DFA (deterministic finite state automaton) 8867117395Skan for fast recognition of pipeline hazards. No errors during 8868117395Skan checking must be fixed before this function call. */ 8869117395Skanstatic void 8870132718Skangenerate (void) 8871117395Skan{ 8872117395Skan automata_num = split_argument; 8873117395Skan if (description->units_num < automata_num) 8874117395Skan automata_num = description->units_num; 8875117395Skan initiate_states (); 8876117395Skan initiate_arcs (); 8877117395Skan initiate_automata_lists (); 8878117395Skan initiate_pass_states (); 8879117395Skan initiate_excl_sets (); 8880132718Skan initiate_presence_absence_pattern_sets (); 8881117395Skan automaton_generation_time = create_ticker (); 8882117395Skan create_automata (); 8883117395Skan ticker_off (&automaton_generation_time); 8884117395Skan} 8885117395Skan 8886117395Skan 8887117395Skan 8888117395Skan/* This page mainly contains top level functions of pipeline hazards 8889117395Skan description translator. */ 8890117395Skan 8891117395Skan/* The following macro value is suffix of name of description file of 8892117395Skan pipeline hazards description translator. */ 8893117395Skan#define STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX ".dfa" 8894117395Skan 8895117395Skan/* The function returns suffix of given file name. The returned 8896117395Skan string can not be changed. */ 8897117395Skanstatic const char * 8898132718Skanfile_name_suffix (const char *file_name) 8899117395Skan{ 8900117395Skan const char *last_period; 8901117395Skan 8902117395Skan for (last_period = NULL; *file_name != '\0'; file_name++) 8903117395Skan if (*file_name == '.') 8904117395Skan last_period = file_name; 8905117395Skan return (last_period == NULL ? file_name : last_period); 8906117395Skan} 8907117395Skan 8908117395Skan/* The function returns base name of given file name, i.e. pointer to 8909117395Skan first char after last `/' (or `\' for WIN32) in given file name, 8910117395Skan given file name itself if the directory name is absent. The 8911117395Skan returned string can not be changed. */ 8912117395Skanstatic const char * 8913132718Skanbase_file_name (const char *file_name) 8914117395Skan{ 8915117395Skan int directory_name_length; 8916117395Skan 8917117395Skan directory_name_length = strlen (file_name); 8918117395Skan#ifdef WIN32 8919117395Skan while (directory_name_length >= 0 && file_name[directory_name_length] != '/' 8920117395Skan && file_name[directory_name_length] != '\\') 8921117395Skan#else 8922117395Skan while (directory_name_length >= 0 && file_name[directory_name_length] != '/') 8923117395Skan#endif 8924117395Skan directory_name_length--; 8925117395Skan return file_name + directory_name_length + 1; 8926117395Skan} 8927117395Skan 8928117395Skan/* The following is top level function to initialize the work of 8929117395Skan pipeline hazards description translator. */ 8930169689Skanstatic void 8931132718Skaninitiate_automaton_gen (int argc, char **argv) 8932117395Skan{ 8933117395Skan const char *base_name; 8934117395Skan int i; 8935117395Skan 8936117395Skan ndfa_flag = 0; 8937117395Skan split_argument = 0; /* default value */ 8938117395Skan no_minimization_flag = 0; 8939117395Skan time_flag = 0; 8940117395Skan v_flag = 0; 8941117395Skan w_flag = 0; 8942132718Skan progress_flag = 0; 8943117395Skan for (i = 2; i < argc; i++) 8944117395Skan if (strcmp (argv [i], NO_MINIMIZATION_OPTION) == 0) 8945117395Skan no_minimization_flag = 1; 8946117395Skan else if (strcmp (argv [i], TIME_OPTION) == 0) 8947117395Skan time_flag = 1; 8948117395Skan else if (strcmp (argv [i], V_OPTION) == 0) 8949117395Skan v_flag = 1; 8950117395Skan else if (strcmp (argv [i], W_OPTION) == 0) 8951117395Skan w_flag = 1; 8952117395Skan else if (strcmp (argv [i], NDFA_OPTION) == 0) 8953117395Skan ndfa_flag = 1; 8954132718Skan else if (strcmp (argv [i], PROGRESS_OPTION) == 0) 8955132718Skan progress_flag = 1; 8956117395Skan else if (strcmp (argv [i], "-split") == 0) 8957117395Skan { 8958117395Skan if (i + 1 >= argc) 8959117395Skan fatal ("-split has no argument."); 8960117395Skan fatal ("option `-split' has not been implemented yet\n"); 8961117395Skan /* split_argument = atoi (argument_vect [i + 1]); */ 8962117395Skan } 8963169689Skan 8964117395Skan /* Initialize IR storage. */ 8965117395Skan obstack_init (&irp); 8966117395Skan initiate_automaton_decl_table (); 8967117395Skan initiate_insn_decl_table (); 8968117395Skan initiate_decl_table (); 8969117395Skan output_file = stdout; 8970117395Skan output_description_file = NULL; 8971117395Skan base_name = base_file_name (argv[1]); 8972117395Skan obstack_grow (&irp, base_name, 8973117395Skan strlen (base_name) - strlen (file_name_suffix (base_name))); 8974117395Skan obstack_grow (&irp, STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX, 8975117395Skan strlen (STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX) + 1); 8976117395Skan obstack_1grow (&irp, '\0'); 8977117395Skan output_description_file_name = obstack_base (&irp); 8978222097Sbenl (void) obstack_finish (&irp); 8979117395Skan} 8980117395Skan 8981117395Skan/* The following function checks existence at least one arc marked by 8982117395Skan each insn. */ 8983117395Skanstatic void 8984132718Skancheck_automata_insn_issues (void) 8985117395Skan{ 8986117395Skan automaton_t automaton; 8987117395Skan ainsn_t ainsn, reserv_ainsn; 8988117395Skan 8989117395Skan for (automaton = description->first_automaton; 8990117395Skan automaton != NULL; 8991117395Skan automaton = automaton->next_automaton) 8992117395Skan { 8993117395Skan for (ainsn = automaton->ainsn_list; 8994117395Skan ainsn != NULL; 8995117395Skan ainsn = ainsn->next_ainsn) 8996117395Skan if (ainsn->first_insn_with_same_reservs && !ainsn->arc_exists_p) 8997117395Skan { 8998117395Skan for (reserv_ainsn = ainsn; 8999117395Skan reserv_ainsn != NULL; 9000117395Skan reserv_ainsn = reserv_ainsn->next_same_reservs_insn) 9001117395Skan if (automaton->corresponding_automaton_decl != NULL) 9002117395Skan { 9003117395Skan if (!w_flag) 9004117395Skan error ("Automaton `%s': Insn `%s' will never be issued", 9005117395Skan automaton->corresponding_automaton_decl->name, 9006117395Skan reserv_ainsn->insn_reserv_decl->name); 9007117395Skan else 9008117395Skan warning 9009169689Skan (0, "Automaton `%s': Insn `%s' will never be issued", 9010117395Skan automaton->corresponding_automaton_decl->name, 9011117395Skan reserv_ainsn->insn_reserv_decl->name); 9012117395Skan } 9013117395Skan else 9014117395Skan { 9015117395Skan if (!w_flag) 9016117395Skan error ("Insn `%s' will never be issued", 9017117395Skan reserv_ainsn->insn_reserv_decl->name); 9018117395Skan else 9019169689Skan warning (0, "Insn `%s' will never be issued", 9020117395Skan reserv_ainsn->insn_reserv_decl->name); 9021117395Skan } 9022117395Skan } 9023117395Skan } 9024117395Skan} 9025117395Skan 9026117395Skan/* The following vla is used for storing pointers to all achieved 9027117395Skan states. */ 9028169689Skanstatic VEC(state_t,heap) *automaton_states; 9029117395Skan 9030117395Skan/* This function is called by function pass_states to add an achieved 9031117395Skan STATE. */ 9032117395Skanstatic void 9033132718Skanadd_automaton_state (state_t state) 9034117395Skan{ 9035169689Skan VEC_safe_push (state_t,heap, automaton_states, state); 9036117395Skan} 9037117395Skan 9038117395Skan/* The following function forms list of important automata (whose 9039117395Skan states may be changed after the insn issue) for each insn. */ 9040117395Skanstatic void 9041132718Skanform_important_insn_automata_lists (void) 9042117395Skan{ 9043117395Skan automaton_t automaton; 9044117395Skan decl_t decl; 9045117395Skan ainsn_t ainsn; 9046117395Skan arc_t arc; 9047117395Skan int i; 9048169689Skan size_t n; 9049117395Skan 9050169689Skan automaton_states = 0; 9051117395Skan /* Mark important ainsns. */ 9052117395Skan for (automaton = description->first_automaton; 9053117395Skan automaton != NULL; 9054117395Skan automaton = automaton->next_automaton) 9055117395Skan { 9056169689Skan VEC_truncate (state_t, automaton_states, 0); 9057117395Skan pass_states (automaton, add_automaton_state); 9058169689Skan for (n = 0; n < VEC_length (state_t, automaton_states); n++) 9059117395Skan { 9060169689Skan state_t s = VEC_index (state_t, automaton_states, n); 9061169689Skan for (arc = first_out_arc (s); 9062117395Skan arc != NULL; 9063117395Skan arc = next_out_arc (arc)) 9064169689Skan if (arc->to_state != s) 9065117395Skan { 9066169689Skan gcc_assert (arc->insn->first_insn_with_same_reservs); 9067117395Skan for (ainsn = arc->insn; 9068117395Skan ainsn != NULL; 9069117395Skan ainsn = ainsn->next_same_reservs_insn) 9070117395Skan ainsn->important_p = TRUE; 9071117395Skan } 9072117395Skan } 9073117395Skan } 9074169689Skan VEC_free (state_t,heap, automaton_states); 9075169689Skan 9076117395Skan /* Create automata sets for the insns. */ 9077117395Skan for (i = 0; i < description->decls_num; i++) 9078117395Skan { 9079117395Skan decl = description->decls [i]; 9080117395Skan if (decl->mode == dm_insn_reserv) 9081117395Skan { 9082117395Skan automata_list_start (); 9083117395Skan for (automaton = description->first_automaton; 9084117395Skan automaton != NULL; 9085117395Skan automaton = automaton->next_automaton) 9086117395Skan for (ainsn = automaton->ainsn_list; 9087117395Skan ainsn != NULL; 9088117395Skan ainsn = ainsn->next_ainsn) 9089117395Skan if (ainsn->important_p 9090117395Skan && ainsn->insn_reserv_decl == DECL_INSN_RESERV (decl)) 9091117395Skan { 9092117395Skan automata_list_add (automaton); 9093117395Skan break; 9094117395Skan } 9095117395Skan DECL_INSN_RESERV (decl)->important_automata_list 9096117395Skan = automata_list_finish (); 9097117395Skan } 9098117395Skan } 9099117395Skan} 9100117395Skan 9101117395Skan 9102117395Skan/* The following is top level function to generate automat(a,on) for 9103117395Skan fast recognition of pipeline hazards. */ 9104169689Skanstatic void 9105132718Skanexpand_automata (void) 9106117395Skan{ 9107117395Skan int i; 9108117395Skan 9109117395Skan description = create_node (sizeof (struct description) 9110117395Skan /* One entry for cycle advancing insn. */ 9111169689Skan + sizeof (decl_t) * VEC_length (decl_t, decls)); 9112169689Skan description->decls_num = VEC_length (decl_t, decls); 9113117395Skan description->query_units_num = 0; 9114117395Skan for (i = 0; i < description->decls_num; i++) 9115117395Skan { 9116169689Skan description->decls [i] = VEC_index (decl_t, decls, i); 9117117395Skan if (description->decls [i]->mode == dm_unit 9118117395Skan && DECL_UNIT (description->decls [i])->query_p) 9119117395Skan DECL_UNIT (description->decls [i])->query_num 9120117395Skan = description->query_units_num++; 9121117395Skan } 9122117395Skan all_time = create_ticker (); 9123117395Skan check_time = create_ticker (); 9124132718Skan if (progress_flag) 9125132718Skan fprintf (stderr, "Check description..."); 9126117395Skan check_all_description (); 9127132718Skan if (progress_flag) 9128132718Skan fprintf (stderr, "done\n"); 9129117395Skan ticker_off (&check_time); 9130117395Skan generation_time = create_ticker (); 9131117395Skan if (!have_error) 9132117395Skan { 9133117395Skan transform_insn_regexps (); 9134117395Skan check_unit_distributions_to_automata (); 9135117395Skan } 9136117395Skan if (!have_error) 9137117395Skan { 9138117395Skan generate (); 9139117395Skan check_automata_insn_issues (); 9140117395Skan } 9141117395Skan if (!have_error) 9142117395Skan { 9143117395Skan form_important_insn_automata_lists (); 9144117395Skan } 9145117395Skan ticker_off (&generation_time); 9146117395Skan} 9147117395Skan 9148117395Skan/* The following is top level function to output PHR and to finish 9149117395Skan work with pipeline description translator. */ 9150169689Skanstatic void 9151132718Skanwrite_automata (void) 9152117395Skan{ 9153117395Skan output_time = create_ticker (); 9154132718Skan if (progress_flag) 9155132718Skan fprintf (stderr, "Forming and outputting automata tables..."); 9156117395Skan output_tables (); 9157132718Skan if (progress_flag) 9158132718Skan { 9159132718Skan fprintf (stderr, "done\n"); 9160132718Skan fprintf (stderr, "Output functions to work with automata..."); 9161132718Skan } 9162117395Skan output_chip_definitions (); 9163117395Skan output_max_insn_queue_index_def (); 9164117395Skan output_internal_min_issue_delay_func (); 9165117395Skan output_internal_trans_func (); 9166117395Skan /* Cache of insn dfa codes: */ 9167117395Skan fprintf (output_file, "\nstatic int *%s;\n", DFA_INSN_CODES_VARIABLE_NAME); 9168117395Skan fprintf (output_file, "\nstatic int %s;\n\n", 9169117395Skan DFA_INSN_CODES_LENGTH_VARIABLE_NAME); 9170117395Skan output_dfa_insn_code_func (); 9171117395Skan output_trans_func (); 9172117395Skan output_min_issue_delay_func (); 9173117395Skan output_internal_dead_lock_func (); 9174117395Skan output_dead_lock_func (); 9175117395Skan output_size_func (); 9176117395Skan output_internal_reset_func (); 9177117395Skan output_reset_func (); 9178117395Skan output_min_insn_conflict_delay_func (); 9179117395Skan output_internal_insn_latency_func (); 9180117395Skan output_insn_latency_func (); 9181117395Skan output_print_reservation_func (); 9182132718Skan /* Output function get_cpu_unit_code. */ 9183132718Skan fprintf (output_file, "\n#if %s\n\n", CPU_UNITS_QUERY_MACRO_NAME); 9184132718Skan output_get_cpu_unit_code_func (); 9185132718Skan output_cpu_unit_reservation_p (); 9186132718Skan fprintf (output_file, "\n#endif /* #if %s */\n\n", 9187132718Skan CPU_UNITS_QUERY_MACRO_NAME); 9188132718Skan output_dfa_clean_insn_cache_func (); 9189117395Skan output_dfa_start_func (); 9190117395Skan output_dfa_finish_func (); 9191132718Skan if (progress_flag) 9192132718Skan fprintf (stderr, "done\n"); 9193117395Skan if (v_flag) 9194117395Skan { 9195117395Skan output_description_file = fopen (output_description_file_name, "w"); 9196117395Skan if (output_description_file == NULL) 9197117395Skan { 9198117395Skan perror (output_description_file_name); 9199117395Skan exit (FATAL_EXIT_CODE); 9200117395Skan } 9201132718Skan if (progress_flag) 9202132718Skan fprintf (stderr, "Output automata description..."); 9203117395Skan output_description (); 9204117395Skan output_automaton_descriptions (); 9205132718Skan if (progress_flag) 9206132718Skan fprintf (stderr, "done\n"); 9207117395Skan output_statistics (output_description_file); 9208117395Skan } 9209117395Skan output_statistics (stderr); 9210117395Skan ticker_off (&output_time); 9211117395Skan output_time_statistics (stderr); 9212117395Skan finish_states (); 9213117395Skan finish_arcs (); 9214117395Skan finish_automata_lists (); 9215117395Skan if (time_flag) 9216117395Skan { 9217117395Skan fprintf (stderr, "Summary:\n"); 9218117395Skan fprintf (stderr, " check time "); 9219117395Skan print_active_time (stderr, check_time); 9220117395Skan fprintf (stderr, ", generation time "); 9221117395Skan print_active_time (stderr, generation_time); 9222117395Skan fprintf (stderr, ", all time "); 9223117395Skan print_active_time (stderr, all_time); 9224117395Skan fprintf (stderr, "\n"); 9225117395Skan } 9226117395Skan /* Finish all work. */ 9227117395Skan if (output_description_file != NULL) 9228117395Skan { 9229117395Skan fflush (output_description_file); 9230117395Skan if (ferror (stdout) != 0) 9231117395Skan fatal ("Error in writing DFA description file %s", 9232117395Skan output_description_file_name); 9233117395Skan fclose (output_description_file); 9234117395Skan } 9235117395Skan finish_automaton_decl_table (); 9236117395Skan finish_insn_decl_table (); 9237117395Skan finish_decl_table (); 9238117395Skan obstack_free (&irp, NULL); 9239117395Skan if (have_error && output_description_file != NULL) 9240117395Skan remove (output_description_file_name); 9241117395Skan} 9242169689Skan 9243169689Skanint 9244169689Skanmain (int argc, char **argv) 9245169689Skan{ 9246169689Skan rtx desc; 9247169689Skan 9248169689Skan progname = "genautomata"; 9249169689Skan 9250169689Skan if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE) 9251169689Skan return (FATAL_EXIT_CODE); 9252169689Skan 9253169689Skan initiate_automaton_gen (argc, argv); 9254169689Skan while (1) 9255169689Skan { 9256169689Skan int lineno; 9257169689Skan int insn_code_number; 9258169689Skan 9259169689Skan desc = read_md_rtx (&lineno, &insn_code_number); 9260169689Skan if (desc == NULL) 9261169689Skan break; 9262169689Skan 9263169689Skan switch (GET_CODE (desc)) 9264169689Skan { 9265169689Skan case DEFINE_CPU_UNIT: 9266169689Skan gen_cpu_unit (desc); 9267169689Skan break; 9268169689Skan 9269169689Skan case DEFINE_QUERY_CPU_UNIT: 9270169689Skan gen_query_cpu_unit (desc); 9271169689Skan break; 9272169689Skan 9273169689Skan case DEFINE_BYPASS: 9274169689Skan gen_bypass (desc); 9275169689Skan break; 9276169689Skan 9277169689Skan case EXCLUSION_SET: 9278169689Skan gen_excl_set (desc); 9279169689Skan break; 9280169689Skan 9281169689Skan case PRESENCE_SET: 9282169689Skan gen_presence_set (desc); 9283169689Skan break; 9284169689Skan 9285169689Skan case FINAL_PRESENCE_SET: 9286169689Skan gen_final_presence_set (desc); 9287169689Skan break; 9288169689Skan 9289169689Skan case ABSENCE_SET: 9290169689Skan gen_absence_set (desc); 9291169689Skan break; 9292169689Skan 9293169689Skan case FINAL_ABSENCE_SET: 9294169689Skan gen_final_absence_set (desc); 9295169689Skan break; 9296169689Skan 9297169689Skan case DEFINE_AUTOMATON: 9298169689Skan gen_automaton (desc); 9299169689Skan break; 9300169689Skan 9301169689Skan case AUTOMATA_OPTION: 9302169689Skan gen_automata_option (desc); 9303169689Skan break; 9304169689Skan 9305169689Skan case DEFINE_RESERVATION: 9306169689Skan gen_reserv (desc); 9307169689Skan break; 9308169689Skan 9309169689Skan case DEFINE_INSN_RESERVATION: 9310169689Skan gen_insn_reserv (desc); 9311169689Skan break; 9312169689Skan 9313169689Skan default: 9314169689Skan break; 9315169689Skan } 9316169689Skan } 9317169689Skan 9318169689Skan if (have_error) 9319169689Skan return FATAL_EXIT_CODE; 9320169689Skan 9321169689Skan puts ("/* Generated automatically by the program `genautomata'\n" 9322169689Skan " from the machine description file `md'. */\n\n" 9323169689Skan "#include \"config.h\"\n" 9324169689Skan "#include \"system.h\"\n" 9325169689Skan "#include \"coretypes.h\"\n" 9326169689Skan "#include \"tm.h\"\n" 9327169689Skan "#include \"rtl.h\"\n" 9328169689Skan "#include \"tm_p.h\"\n" 9329169689Skan "#include \"insn-config.h\"\n" 9330169689Skan "#include \"recog.h\"\n" 9331169689Skan "#include \"regs.h\"\n" 9332169689Skan "#include \"real.h\"\n" 9333169689Skan "#include \"output.h\"\n" 9334169689Skan "#include \"insn-attr.h\"\n" 9335169689Skan "#include \"toplev.h\"\n" 9336169689Skan "#include \"flags.h\"\n" 9337169689Skan "#include \"function.h\"\n"); 9338169689Skan 9339169689Skan if (VEC_length (decl_t, decls) > 0) 9340169689Skan { 9341169689Skan expand_automata (); 9342169689Skan write_automata (); 9343169689Skan } 9344169689Skan 9345169689Skan fflush (stdout); 9346169689Skan return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE); 9347169689Skan} 9348