• Main Page
  • Modules
  • Data Types
  • Files

osprey-gcc/gcc/genautomata.c

Go to the documentation of this file.
00001 /* Pipeline hazard description translator.
00002    Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005
00003    Free Software Foundation, Inc.
00004 
00005    Written by Vladimir Makarov <vmakarov@redhat.com>
00006 
00007 This file is part of GCC.
00008 
00009 GCC is free software; you can redistribute it and/or modify it
00010 under the terms of the GNU General Public License as published by the
00011 Free Software Foundation; either version 2, or (at your option) any
00012 later version.
00013 
00014 GCC is distributed in the hope that it will be useful, but WITHOUT
00015 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00016 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00017 for more details.
00018 
00019 You should have received a copy of the GNU General Public License
00020 along with GCC; see the file COPYING.  If not, write to the Free
00021 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
00022 02111-1307, USA.  */
00023 
00024 /* References:
00025 
00026    1. Detecting pipeline structural hazards quickly. T. Proebsting,
00027       C. Fraser. Proceedings of ACM SIGPLAN-SIGACT Symposium on
00028       Principles of Programming Languages, pages 280--286, 1994.
00029 
00030       This article is a good start point to understand usage of finite
00031       state automata for pipeline hazard recognizers.  But I'd
00032       recommend the 2nd article for more deep understanding.
00033 
00034    2. Efficient Instruction Scheduling Using Finite State Automata:
00035       V. Bala and N. Rubin, Proceedings of MICRO-28.  This is the best
00036       article about usage of finite state automata for pipeline hazard
00037       recognizers.
00038 
00039    The current implementation is different from the 2nd article in the
00040    following:
00041 
00042    1. New operator `|' (alternative) is permitted in functional unit
00043       reservation which can be treated deterministically and
00044       non-deterministically.
00045 
00046    2. Possibility of usage of nondeterministic automata too.
00047 
00048    3. Possibility to query functional unit reservations for given
00049       automaton state.
00050 
00051    4. Several constructions to describe impossible reservations
00052       (`exclusion_set', `presence_set', `final_presence_set',
00053       `absence_set', and `final_absence_set').
00054 
00055    5. No reverse automata are generated.  Trace instruction scheduling
00056       requires this.  It can be easily added in the future if we
00057       really need this.
00058 
00059    6. Union of automaton states are not generated yet.  It is planned
00060       to be implemented.  Such feature is needed to make more accurate
00061       interlock insn scheduling to get state describing functional
00062       unit reservation in a joint CFG point.  */
00063 
00064 /* This file code processes constructions of machine description file
00065    which describes automaton used for recognition of processor pipeline
00066    hazards by insn scheduler and can be used for other tasks (such as
00067    VLIW insn packing.
00068 
00069    The translator functions `gen_cpu_unit', `gen_query_cpu_unit',
00070    `gen_bypass', `gen_excl_set', `gen_presence_set',
00071    `gen_final_presence_set', `gen_absence_set',
00072    `gen_final_absence_set', `gen_automaton', `gen_automata_option',
00073    `gen_reserv', `gen_insn_reserv' are called from file
00074    `genattrtab.c'.  They transform RTL constructions describing
00075    automata in .md file into internal representation convenient for
00076    further processing.
00077 
00078    The translator major function `expand_automata' processes the
00079    description internal representation into finite state automaton.
00080    It can be divided on:
00081 
00082      o checking correctness of the automaton pipeline description
00083        (major function is `check_all_description').
00084 
00085      o generating automaton (automata) from the description (major
00086        function is `make_automaton').
00087 
00088      o optional transformation of nondeterministic finite state
00089        automata into deterministic ones if the alternative operator
00090        `|' is treated nondeterministically in the description (major
00091        function is NDFA_to_DFA).
00092 
00093      o optional minimization of the finite state automata by merging
00094        equivalent automaton states (major function is `minimize_DFA').
00095 
00096      o forming tables (some as comb vectors) and attributes
00097        representing the automata (functions output_..._table).
00098 
00099    Function `write_automata' outputs the created finite state
00100    automaton as different tables and functions which works with the
00101    automata to inquire automaton state and to change its state.  These
00102    function are used by gcc instruction scheduler and may be some
00103    other gcc code.  */
00104 
00105 #include "bconfig.h"
00106 #include "system.h"
00107 #include "coretypes.h"
00108 #include "tm.h"
00109 #include "rtl.h"
00110 #include "obstack.h"
00111 #include "errors.h"
00112 
00113 #include <math.h>
00114 #include "hashtab.h"
00115 #include "varray.h"
00116 
00117 #ifndef CHAR_BIT
00118 #define CHAR_BIT 8
00119 #endif
00120 
00121 #include "genattrtab.h"
00122 
00123 /* Positions in machine description file.  Now they are not used.  But
00124    they could be used in the future for better diagnostic messages.  */
00125 typedef int pos_t;
00126 
00127 /* The following is element of vector of current (and planned in the
00128    future) functional unit reservations.  */
00129 typedef unsigned HOST_WIDE_INT set_el_t;
00130 
00131 /* Reservations of function units are represented by value of the following
00132    type.  */
00133 typedef set_el_t *reserv_sets_t;
00134 
00135 /* The following structure represents variable length array (vla) of
00136    pointers and HOST WIDE INTs.  We could be use only varray.  But we
00137    add new lay because we add elements very frequently and this could
00138    stress OS allocator when varray is used only.  */
00139 typedef struct {
00140   size_t length;      /* current size of vla.  */
00141   varray_type varray; /* container for vla.  */
00142 } vla_ptr_t;
00143 
00144 typedef vla_ptr_t vla_hwint_t;
00145 
00146 /* The following structure describes a ticker.  */
00147 struct ticker
00148 {
00149   /* The following member value is time of the ticker creation with
00150      taking into account time when the ticker is off.  Active time of
00151      the ticker is current time minus the value.  */
00152   int modified_creation_time;
00153   /* The following member value is time (incremented by one) when the
00154      ticker was off.  Zero value means that now the ticker is on.  */
00155   int incremented_off_time;
00156 };
00157 
00158 /* The ticker is represented by the following type.  */
00159 typedef struct ticker ticker_t;
00160 
00161 /* The following type describes elements of output vectors.  */
00162 typedef HOST_WIDE_INT vect_el_t;
00163 
00164 /* Forward declaration of structures of internal representation of
00165    pipeline description based on NDFA.  */
00166 
00167 struct unit_decl;
00168 struct bypass_decl;
00169 struct result_decl;
00170 struct automaton_decl;
00171 struct unit_pattern_rel_decl;
00172 struct reserv_decl;
00173 struct insn_reserv_decl;
00174 struct decl;
00175 struct unit_regexp;
00176 struct result_regexp;
00177 struct reserv_regexp;
00178 struct nothing_regexp;
00179 struct sequence_regexp;
00180 struct repeat_regexp;
00181 struct allof_regexp;
00182 struct oneof_regexp;
00183 struct regexp;
00184 struct description;
00185 struct unit_set_el;
00186 struct pattern_set_el;
00187 struct pattern_reserv;
00188 struct state;
00189 struct alt_state;
00190 struct arc;
00191 struct ainsn;
00192 struct automaton;
00193 struct state_ainsn_table;
00194 
00195 /* The following typedefs are for brevity.  */
00196 typedef struct unit_decl *unit_decl_t;
00197 typedef struct decl *decl_t;
00198 typedef struct regexp *regexp_t;
00199 typedef struct unit_set_el *unit_set_el_t;
00200 typedef struct pattern_set_el *pattern_set_el_t;
00201 typedef struct pattern_reserv *pattern_reserv_t;
00202 typedef struct alt_state *alt_state_t;
00203 typedef struct state *state_t;
00204 typedef struct arc *arc_t;
00205 typedef struct ainsn *ainsn_t;
00206 typedef struct automaton *automaton_t;
00207 typedef struct automata_list_el *automata_list_el_t;
00208 typedef struct state_ainsn_table *state_ainsn_table_t;
00209 
00210 
00211 /* Prototypes of functions gen_cpu_unit, gen_query_cpu_unit,
00212    gen_bypass, gen_excl_set, gen_presence_set, gen_final_presence_set,
00213    gen_absence_set, gen_final_absence_set, gen_automaton,
00214    gen_automata_option, gen_reserv, gen_insn_reserv,
00215    initiate_automaton_gen, expand_automata, write_automata are
00216    described on the file top because the functions are called from
00217    function `main'.  */
00218 
00219 static void *create_node             (size_t);
00220 static void *copy_node               (const void *, size_t);
00221 static char *check_name              (char *, pos_t);
00222 static char *next_sep_el             (char **, int, int);
00223 static int n_sep_els                 (char *, int, int);
00224 static char **get_str_vect           (char *, int *, int, int);
00225 static void gen_presence_absence_set (rtx, int, int);
00226 static regexp_t gen_regexp_el        (char *);
00227 static regexp_t gen_regexp_repeat    (char *);
00228 static regexp_t gen_regexp_allof     (char *);
00229 static regexp_t gen_regexp_oneof     (char *);
00230 static regexp_t gen_regexp_sequence  (char *);
00231 static regexp_t gen_regexp           (char *);
00232 
00233 static unsigned string_hash          (const char *);
00234 static unsigned automaton_decl_hash  (const void *);
00235 static int automaton_decl_eq_p       (const void *,
00236               const void *);
00237 static decl_t insert_automaton_decl       (decl_t);
00238 static decl_t find_automaton_decl         (char *);
00239 static void initiate_automaton_decl_table (void);
00240 static void finish_automaton_decl_table   (void);
00241 
00242 static hashval_t insn_decl_hash           (const void *);
00243 static int insn_decl_eq_p                 (const void *,
00244              const void *);
00245 static decl_t insert_insn_decl            (decl_t);
00246 static decl_t find_insn_decl              (char *);
00247 static void initiate_insn_decl_table      (void);
00248 static void finish_insn_decl_table        (void);
00249 
00250 static hashval_t decl_hash                (const void *);
00251 static int decl_eq_p                      (const void *,
00252              const void *);
00253 static decl_t insert_decl                 (decl_t);
00254 static decl_t find_decl                   (char *);
00255 static void initiate_decl_table           (void);
00256 static void finish_decl_table             (void);
00257 
00258 static unit_set_el_t process_excls       (char **, int, pos_t);
00259 static void add_excls                    (unit_set_el_t, unit_set_el_t,
00260             pos_t);
00261 static unit_set_el_t process_presence_absence_names
00262            (char **, int, pos_t,
00263             int, int);
00264 static pattern_set_el_t process_presence_absence_patterns
00265            (char ***, int, pos_t,
00266             int, int);
00267 static void add_presence_absence   (unit_set_el_t,
00268             pattern_set_el_t,
00269             pos_t, int, int);
00270 static void process_decls                (void);
00271 static struct bypass_decl *find_bypass   (struct bypass_decl *,
00272             struct insn_reserv_decl *);
00273 static void check_automaton_usage        (void);
00274 static regexp_t process_regexp           (regexp_t);
00275 static void process_regexp_decls         (void);
00276 static void check_usage                  (void);
00277 static int loop_in_regexp                (regexp_t, decl_t);
00278 static void check_loops_in_regexps       (void);
00279 static void process_regexp_cycles        (regexp_t, int, int,
00280             int *, int *);
00281 static void evaluate_max_reserv_cycles   (void);
00282 static void check_all_description        (void);
00283 
00284 static ticker_t create_ticker               (void);
00285 static void ticker_off                      (ticker_t *);
00286 static void ticker_on                       (ticker_t *);
00287 static int active_time                      (ticker_t);
00288 static void print_active_time               (FILE *, ticker_t);
00289 
00290 static void add_advance_cycle_insn_decl     (void);
00291 
00292 static alt_state_t get_free_alt_state (void);
00293 static void free_alt_state              (alt_state_t);
00294 static void free_alt_states             (alt_state_t);
00295 static int alt_state_cmp                (const void *alt_state_ptr_1,
00296            const void *alt_state_ptr_2);
00297 static alt_state_t uniq_sort_alt_states (alt_state_t);
00298 static int alt_states_eq                (alt_state_t, alt_state_t);
00299 static void initiate_alt_states         (void);
00300 static void finish_alt_states           (void);
00301 
00302 static reserv_sets_t alloc_empty_reserv_sets (void);
00303 static unsigned reserv_sets_hash_value (reserv_sets_t);
00304 static int reserv_sets_cmp             (reserv_sets_t, reserv_sets_t);
00305 static int reserv_sets_eq              (reserv_sets_t, reserv_sets_t);
00306 static void set_unit_reserv            (reserv_sets_t, int, int);
00307 static int test_unit_reserv            (reserv_sets_t, int, int);
00308 static int it_is_empty_reserv_sets     (reserv_sets_t)
00309                                             ATTRIBUTE_UNUSED;
00310 static int reserv_sets_are_intersected (reserv_sets_t, reserv_sets_t);
00311 static void reserv_sets_shift          (reserv_sets_t, reserv_sets_t);
00312 static void reserv_sets_or             (reserv_sets_t, reserv_sets_t,
00313           reserv_sets_t);
00314 static void reserv_sets_and            (reserv_sets_t, reserv_sets_t,
00315           reserv_sets_t)
00316                                             ATTRIBUTE_UNUSED;
00317 static void output_cycle_reservs       (FILE *, reserv_sets_t,
00318           int, int);
00319 static void output_reserv_sets         (FILE *, reserv_sets_t);
00320 static state_t get_free_state          (int, automaton_t);
00321 static void free_state                 (state_t);
00322 static hashval_t state_hash            (const void *);
00323 static int state_eq_p                  (const void *, const void *);
00324 static state_t insert_state            (state_t);
00325 static void set_state_reserv           (state_t, int, int);
00326 static int intersected_state_reservs_p (state_t, state_t);
00327 static state_t states_union            (state_t, state_t, reserv_sets_t);
00328 static state_t state_shift             (state_t, reserv_sets_t);
00329 static void initiate_states            (void);
00330 static void finish_states              (void);
00331 
00332 static void free_arc           (arc_t);
00333 static void remove_arc         (state_t, arc_t);
00334 static arc_t find_arc          (state_t, state_t, ainsn_t);
00335 static arc_t add_arc           (state_t, state_t, ainsn_t, int);
00336 static arc_t first_out_arc     (state_t);
00337 static arc_t next_out_arc      (arc_t);
00338 static void initiate_arcs      (void);
00339 static void finish_arcs        (void);
00340 
00341 static automata_list_el_t get_free_automata_list_el (void);
00342 static void free_automata_list_el (automata_list_el_t);
00343 static void free_automata_list (automata_list_el_t);
00344 static hashval_t automata_list_hash (const void *);
00345 static int automata_list_eq_p (const void *, const void *);
00346 static void initiate_automata_lists (void);
00347 static void automata_list_start (void);
00348 static void automata_list_add (automaton_t);
00349 static automata_list_el_t automata_list_finish (void);
00350 static void finish_automata_lists (void);
00351 
00352 static void initiate_excl_sets             (void);
00353 static reserv_sets_t get_excl_set          (reserv_sets_t);
00354 
00355 static pattern_reserv_t form_reserv_sets_list (pattern_set_el_t);
00356 static void initiate_presence_absence_pattern_sets     (void);
00357 static int check_presence_pattern_sets     (reserv_sets_t,
00358               reserv_sets_t, int);
00359 static int check_absence_pattern_sets  (reserv_sets_t, reserv_sets_t,
00360           int);
00361 
00362 static regexp_t copy_insn_regexp     (regexp_t);
00363 static regexp_t transform_1          (regexp_t);
00364 static regexp_t transform_2          (regexp_t);
00365 static regexp_t transform_3          (regexp_t);
00366 static regexp_t regexp_transform_func
00367                        (regexp_t, regexp_t (*) (regexp_t));
00368 static regexp_t transform_regexp            (regexp_t);
00369 static void transform_insn_regexps          (void);
00370 
00371 static void store_alt_unit_usage (regexp_t, regexp_t, int, int);
00372 static void check_regexp_units_distribution   (const char *, regexp_t);
00373 static void check_unit_distributions_to_automata (void);
00374 
00375 static int process_seq_for_forming_states   (regexp_t, automaton_t,
00376                int);
00377 static void finish_forming_alt_state        (alt_state_t,
00378                automaton_t);
00379 static void process_alts_for_forming_states (regexp_t,
00380                automaton_t, int);
00381 static void create_alt_states               (automaton_t);
00382 
00383 static void form_ainsn_with_same_reservs    (automaton_t);
00384 
00385 static reserv_sets_t form_reservs_matter (automaton_t);
00386 static void make_automaton           (automaton_t);
00387 static void form_arcs_marked_by_insn (state_t);
00388 static int create_composed_state     (state_t, arc_t, vla_ptr_t *);
00389 static void NDFA_to_DFA              (automaton_t);
00390 static void pass_state_graph         (state_t, void (*) (state_t));
00391 static void pass_states              (automaton_t,
00392               void (*) (state_t));
00393 static void initiate_pass_states       (void);
00394 static void add_achieved_state         (state_t);
00395 static int set_out_arc_insns_equiv_num (state_t, int);
00396 static void clear_arc_insns_equiv_num  (state_t);
00397 static void copy_equiv_class           (vla_ptr_t *to,
00398           const vla_ptr_t *from);
00399 static int first_cycle_unit_presence   (state_t, int);
00400 static int state_is_differed           (state_t, state_t, int, int);
00401 static state_t init_equiv_class        (state_t *states, int);
00402 static int partition_equiv_class       (state_t *, int,
00403           vla_ptr_t *, int *);
00404 static void evaluate_equiv_classes     (automaton_t, vla_ptr_t *);
00405 static void merge_states               (automaton_t, vla_ptr_t *);
00406 static void set_new_cycle_flags        (state_t);
00407 static void minimize_DFA               (automaton_t);
00408 static void incr_states_and_arcs_nums  (state_t);
00409 static void count_states_and_arcs      (automaton_t, int *, int *);
00410 static void build_automaton            (automaton_t);
00411 
00412 static void set_order_state_num              (state_t);
00413 static void enumerate_states                 (automaton_t);
00414 
00415 static ainsn_t insert_ainsn_into_equiv_class       (ainsn_t, ainsn_t);
00416 static void delete_ainsn_from_equiv_class          (ainsn_t);
00417 static void process_insn_equiv_class               (ainsn_t, arc_t *);
00418 static void process_state_for_insn_equiv_partition (state_t);
00419 static void set_insn_equiv_classes                 (automaton_t);
00420 
00421 static double estimate_one_automaton_bound     (void);
00422 static int compare_max_occ_cycle_nums          (const void *,
00423             const void *);
00424 static void units_to_automata_heuristic_distr  (void);
00425 static ainsn_t create_ainsns                   (void);
00426 static void units_to_automata_distr            (void);
00427 static void create_automata                    (void);
00428 
00429 static void form_regexp                      (regexp_t);
00430 static const char *regexp_representation     (regexp_t);
00431 static void finish_regexp_representation     (void);
00432 
00433 static void output_range_type            (FILE *, long int, long int);
00434 static int longest_path_length           (state_t);
00435 static void process_state_longest_path_length (state_t);
00436 static void output_dfa_max_issue_rate    (void);
00437 static void output_vect                  (vect_el_t *, int);
00438 static void output_chip_member_name      (FILE *, automaton_t);
00439 static void output_temp_chip_member_name (FILE *, automaton_t);
00440 static void output_translate_vect_name   (FILE *, automaton_t);
00441 static void output_trans_full_vect_name  (FILE *, automaton_t);
00442 static void output_trans_comb_vect_name  (FILE *, automaton_t);
00443 static void output_trans_check_vect_name (FILE *, automaton_t);
00444 static void output_trans_base_vect_name  (FILE *, automaton_t);
00445 static void output_state_alts_full_vect_name    (FILE *, automaton_t);
00446 static void output_state_alts_comb_vect_name    (FILE *, automaton_t);
00447 static void output_state_alts_check_vect_name   (FILE *, automaton_t);
00448 static void output_state_alts_base_vect_name    (FILE *, automaton_t);
00449 static void output_min_issue_delay_vect_name    (FILE *, automaton_t);
00450 static void output_dead_lock_vect_name   (FILE *, automaton_t);
00451 static void output_reserved_units_table_name    (FILE *, automaton_t);
00452 static void output_state_member_type     (FILE *, automaton_t);
00453 static void output_chip_definitions      (void);
00454 static void output_translate_vect        (automaton_t);
00455 static int comb_vect_p                   (state_ainsn_table_t);
00456 static state_ainsn_table_t create_state_ainsn_table (automaton_t);
00457 static void output_state_ainsn_table
00458    (state_ainsn_table_t, char *, void (*) (FILE *, automaton_t),
00459     void (*) (FILE *, automaton_t), void (*) (FILE *, automaton_t),
00460     void (*) (FILE *, automaton_t));
00461 static void add_vect                     (state_ainsn_table_t,
00462             int, vect_el_t *, int);
00463 static int out_state_arcs_num            (state_t);
00464 static int compare_transition_els_num    (const void *, const void *);
00465 static void add_vect_el          (vla_hwint_t *,
00466             ainsn_t, int);
00467 static void add_states_vect_el           (state_t);
00468 static void output_trans_table           (automaton_t);
00469 static void output_state_alts_table      (automaton_t);
00470 static int min_issue_delay_pass_states   (state_t, ainsn_t);
00471 static int min_issue_delay               (state_t, ainsn_t);
00472 static void initiate_min_issue_delay_pass_states (void);
00473 static void output_min_issue_delay_table (automaton_t);
00474 static void output_dead_lock_vect        (automaton_t);
00475 static void output_reserved_units_table  (automaton_t);
00476 static void output_tables                (void);
00477 static void output_max_insn_queue_index_def (void);
00478 static void output_insn_code_cases   (void (*) (automata_list_el_t));
00479 static void output_automata_list_min_issue_delay_code (automata_list_el_t);
00480 static void output_internal_min_issue_delay_func (void);
00481 static void output_automata_list_transition_code (automata_list_el_t);
00482 static void output_internal_trans_func   (void);
00483 static void output_internal_insn_code_evaluation (const char *,
00484               const char *, int);
00485 static void output_dfa_insn_code_func         (void);
00486 static void output_trans_func                   (void);
00487 static void output_automata_list_state_alts_code (automata_list_el_t);
00488 static void output_internal_state_alts_func     (void);
00489 static void output_state_alts_func              (void);
00490 static void output_min_issue_delay_func         (void);
00491 static void output_internal_dead_lock_func      (void);
00492 static void output_dead_lock_func               (void);
00493 static void output_internal_reset_func          (void);
00494 static void output_size_func            (void);
00495 static void output_reset_func                   (void);
00496 static void output_min_insn_conflict_delay_func (void);
00497 static void output_internal_insn_latency_func   (void);
00498 static void output_insn_latency_func            (void);
00499 static void output_print_reservation_func       (void);
00500 static int units_cmp              (const void *,
00501              const void *);
00502 static void output_get_cpu_unit_code_func       (void);
00503 static void output_cpu_unit_reservation_p       (void);
00504 static void output_dfa_clean_insn_cache_func    (void);
00505 static void output_dfa_start_func         (void);
00506 static void output_dfa_finish_func          (void);
00507 
00508 static void output_regexp                  (regexp_t );
00509 static void output_unit_set_el_list    (unit_set_el_t);
00510 static void output_pattern_set_el_list     (pattern_set_el_t);
00511 static void output_description             (void);
00512 static void output_automaton_name          (FILE *, automaton_t);
00513 static void output_automaton_units         (automaton_t);
00514 static void add_state_reservs              (state_t);
00515 static void output_state_arcs              (state_t);
00516 static int state_reservs_cmp               (const void *,
00517               const void *);
00518 static void remove_state_duplicate_reservs (void);
00519 static void output_state                   (state_t);
00520 static void output_automaton_descriptions  (void);
00521 static void output_statistics              (FILE *);
00522 static void output_time_statistics         (FILE *);
00523 static void generate                       (void);
00524 
00525 static void make_insn_alts_attr                (void);
00526 static void make_internal_dfa_insn_code_attr   (void);
00527 static void make_default_insn_latency_attr     (void);
00528 static void make_bypass_attr                   (void);
00529 static const char *file_name_suffix            (const char *);
00530 static const char *base_file_name              (const char *);
00531 static void check_automata_insn_issues         (void);
00532 static void add_automaton_state                (state_t);
00533 static void form_important_insn_automata_lists (void);
00534 
00535 /* Undefined position.  */
00536 static pos_t no_pos = 0;
00537 
00538 /* All IR is stored in the following obstack.  */
00539 static struct obstack irp;
00540 
00541 
00542 
00543 /* This page contains code for work with variable length array (vla)
00544    of pointers.  We could be use only varray.  But we add new lay
00545    because we add elements very frequently and this could stress OS
00546    allocator when varray is used only.  */
00547 
00548 /* Start work with vla.  */
00549 #define VLA_PTR_CREATE(vla, allocated_length, name)  \
00550   do                   \
00551     {  \
00552       vla_ptr_t *const _vla_ptr = &(vla);                                \
00553    \
00554       VARRAY_GENERIC_PTR_INIT (_vla_ptr->varray, allocated_length, name);\
00555       _vla_ptr->length = 0;                                              \
00556     }                  \
00557   while (0)
00558 
00559 /* Finish work with the vla.  */
00560 #define VLA_PTR_DELETE(vla) VARRAY_FREE ((vla).varray)
00561 
00562 /* Return start address of the vla.  */
00563 #define VLA_PTR_BEGIN(vla) ((void *) &VARRAY_GENERIC_PTR ((vla).varray, 0))
00564 
00565 /* Address of the last element of the vla.  Do not use side effects in
00566    the macro argument.  */
00567 #define VLA_PTR_LAST(vla) (&VARRAY_GENERIC_PTR ((vla).varray,         \
00568                                                 (vla).length - 1))
00569 /* Nullify the vla.  */
00570 #define VLA_PTR_NULLIFY(vla)  ((vla).length = 0)
00571 
00572 /* Shorten the vla on given number bytes.  */
00573 #define VLA_PTR_SHORTEN(vla, n)  ((vla).length -= (n))
00574 
00575 /* Expand the vla on N elements.  The values of new elements are
00576    undefined.  */
00577 #define VLA_PTR_EXPAND(vla, n)                                        \
00578   do {                                                                \
00579     vla_ptr_t *const _expand_vla_ptr = &(vla);                        \
00580     const size_t _new_length = (n) + _expand_vla_ptr->length;         \
00581                                                                       \
00582     if (VARRAY_SIZE (_expand_vla_ptr->varray) < _new_length)          \
00583       VARRAY_GROW (_expand_vla_ptr->varray,                           \
00584                    (_new_length - _expand_vla_ptr->length < 128       \
00585                     ? _expand_vla_ptr->length + 128 : _new_length));  \
00586     _expand_vla_ptr->length = _new_length;                            \
00587   } while (0)
00588 
00589 /* Add element to the end of the vla.  */
00590 #define VLA_PTR_ADD(vla, ptr)                                           \
00591   do {                                                                  \
00592     vla_ptr_t *const _vla_ptr = &(vla);                                 \
00593                                                                         \
00594     VLA_PTR_EXPAND (*_vla_ptr, 1);                                      \
00595     VARRAY_GENERIC_PTR (_vla_ptr->varray, _vla_ptr->length - 1) = (ptr);\
00596   } while (0)
00597 
00598 /* Length of the vla in elements.  */
00599 #define VLA_PTR_LENGTH(vla) ((vla).length)
00600 
00601 /* N-th element of the vla.  */
00602 #define VLA_PTR(vla, n) VARRAY_GENERIC_PTR ((vla).varray, n)
00603 
00604 
00605 /* The following macros are analogous to the previous ones but for
00606    VLAs of HOST WIDE INTs.  */
00607 
00608 #define VLA_HWINT_CREATE(vla, allocated_length, name)                 \
00609   do {                                                                \
00610     vla_hwint_t *const _vla_ptr = &(vla);                             \
00611                                                                       \
00612     VARRAY_WIDE_INT_INIT (_vla_ptr->varray, allocated_length, name);  \
00613     _vla_ptr->length = 0;                                             \
00614   } while (0)
00615 
00616 #define VLA_HWINT_DELETE(vla) VARRAY_FREE ((vla).varray)
00617 
00618 #define VLA_HWINT_BEGIN(vla) (&VARRAY_WIDE_INT ((vla).varray, 0))
00619 
00620 #define VLA_HWINT_NULLIFY(vla)  ((vla).length = 0)
00621 
00622 #define VLA_HWINT_EXPAND(vla, n)                                      \
00623   do {                                                                \
00624     vla_hwint_t *const _expand_vla_ptr = &(vla);                      \
00625     const size_t _new_length = (n) + _expand_vla_ptr->length;         \
00626                                                                       \
00627     if (VARRAY_SIZE (_expand_vla_ptr->varray) < _new_length)          \
00628       VARRAY_GROW (_expand_vla_ptr->varray,                           \
00629                    (_new_length - _expand_vla_ptr->length < 128       \
00630                     ? _expand_vla_ptr->length + 128 : _new_length));  \
00631     _expand_vla_ptr->length = _new_length;                            \
00632   } while (0)
00633 
00634 #define VLA_HWINT_ADD(vla, ptr)                                       \
00635   do {                                                                \
00636     vla_hwint_t *const _vla_ptr = &(vla);                             \
00637                                                                       \
00638     VLA_HWINT_EXPAND (*_vla_ptr, 1);                                  \
00639     VARRAY_WIDE_INT (_vla_ptr->varray, _vla_ptr->length - 1) = (ptr); \
00640   } while (0)
00641 
00642 #define VLA_HWINT_LENGTH(vla) ((vla).length)
00643 
00644 #define VLA_HWINT(vla, n) VARRAY_WIDE_INT ((vla).varray, n)
00645 
00646 
00647 
00648 /* Options with the following names can be set up in automata_option
00649    construction.  Because the strings occur more one time we use the
00650    macros.  */
00651 
00652 #define NO_MINIMIZATION_OPTION "-no-minimization"
00653 
00654 #define TIME_OPTION "-time"
00655 
00656 #define V_OPTION "-v"
00657 
00658 #define W_OPTION "-w"
00659 
00660 #define NDFA_OPTION "-ndfa"
00661 
00662 #define PROGRESS_OPTION "-progress"
00663 
00664 /* The following flags are set up by function `initiate_automaton_gen'.  */
00665 
00666 /* Make automata with nondeterministic reservation by insns (`-ndfa').  */
00667 static int ndfa_flag;
00668 
00669 /* Do not make minimization of DFA (`-no-minimization').  */
00670 static int no_minimization_flag;
00671 
00672 /* Value of this variable is number of automata being generated.  The
00673    actual number of automata may be less this value if there is not
00674    sufficient number of units.  This value is defined by argument of
00675    option `-split' or by constructions automaton if the value is zero
00676    (it is default value of the argument).  */
00677 static int split_argument;
00678 
00679 /* Flag of output time statistics (`-time').  */
00680 static int time_flag;
00681 
00682 /* Flag of creation of description file which contains description of
00683    result automaton and statistics information (`-v').  */
00684 static int v_flag;
00685 
00686 /* Flag of output of a progress bar showing how many states were
00687    generated so far for automaton being processed (`-progress').  */
00688 static int progress_flag;
00689 
00690 /* Flag of generating warning instead of error for non-critical errors
00691    (`-w').  */
00692 static int w_flag;
00693 
00694 
00695 /* Output file for pipeline hazard recognizer (PHR) being generated.
00696    The value is NULL if the file is not defined.  */
00697 static FILE *output_file;
00698 
00699 /* Description file of PHR.  The value is NULL if the file is not
00700    created.  */
00701 static FILE *output_description_file;
00702 
00703 /* PHR description file name.  */
00704 static char *output_description_file_name;
00705 
00706 /* Value of the following variable is node representing description
00707    being processed.  This is start point of IR.  */
00708 static struct description *description;
00709 
00710 
00711 
00712 /* This page contains description of IR structure (nodes).  */
00713 
00714 enum decl_mode
00715 {
00716   dm_unit,
00717   dm_bypass,
00718   dm_automaton,
00719   dm_excl,
00720   dm_presence,
00721   dm_absence,
00722   dm_reserv,
00723   dm_insn_reserv
00724 };
00725 
00726 /* This describes define_cpu_unit and define_query_cpu_unit (see file
00727    rtl.def).  */
00728 struct unit_decl
00729 {
00730   char *name;
00731   /* NULL if the automaton name is absent.  */
00732   char *automaton_name;
00733   /* If the following value is not zero, the cpu unit reservation is
00734      described in define_query_cpu_unit.  */
00735   char query_p;
00736 
00737   /* The following fields are defined by checker.  */
00738 
00739   /* The following field value is nonzero if the unit is used in an
00740      regexp.  */
00741   char unit_is_used;
00742 
00743   /* The following field value is order number (0, 1, ...) of given
00744      unit.  */
00745   int unit_num;
00746   /* The following field value is corresponding declaration of
00747      automaton which was given in description.  If the field value is
00748      NULL then automaton in the unit declaration was absent.  */
00749   struct automaton_decl *automaton_decl;
00750   /* The following field value is maximal cycle number (1, ...) on
00751      which given unit occurs in insns.  Zero value means that given
00752      unit is not used in insns.  */
00753   int max_occ_cycle_num;
00754   /* The following field value is minimal cycle number (0, ...) on
00755      which given unit occurs in insns.  -1 value means that given
00756      unit is not used in insns.  */
00757   int min_occ_cycle_num;
00758   /* The following list contains units which conflict with given
00759      unit.  */
00760   unit_set_el_t excl_list;
00761   /* The following list contains patterns which are required to
00762      reservation of given unit.  */
00763   pattern_set_el_t presence_list;
00764   pattern_set_el_t final_presence_list;
00765   /* The following list contains patterns which should be not present
00766      in reservation for given unit.  */
00767   pattern_set_el_t absence_list;
00768   pattern_set_el_t final_absence_list;
00769   /* The following is used only when `query_p' has nonzero value.
00770      This is query number for the unit.  */
00771   int query_num;
00772   /* The following is the last cycle on which the unit was checked for
00773      correct distributions of units to automata in a regexp.  */
00774   int last_distribution_check_cycle;
00775 
00776   /* The following fields are defined by automaton generator.  */
00777 
00778   /* The following field value is number of the automaton to which
00779      given unit belongs.  */
00780   int corresponding_automaton_num;
00781   /* If the following value is not zero, the cpu unit is present in a
00782      `exclusion_set' or in right part of a `presence_set',
00783      `final_presence_set', `absence_set', and
00784      `final_absence_set'define_query_cpu_unit.  */
00785   char in_set_p;
00786 };
00787 
00788 /* This describes define_bypass (see file rtl.def).  */
00789 struct bypass_decl
00790 {
00791   int latency;
00792   char *out_insn_name;
00793   char *in_insn_name;
00794   char *bypass_guard_name;
00795 
00796   /* The following fields are defined by checker.  */
00797 
00798   /* output and input insns of given bypass.  */
00799   struct insn_reserv_decl *out_insn_reserv;
00800   struct insn_reserv_decl *in_insn_reserv;
00801   /* The next bypass for given output insn.  */
00802   struct bypass_decl *next;
00803 };
00804 
00805 /* This describes define_automaton (see file rtl.def).  */
00806 struct automaton_decl
00807 {
00808   char *name;
00809 
00810   /* The following fields are defined by automaton generator.  */
00811 
00812   /* The following field value is nonzero if the automaton is used in
00813      an regexp definition.  */
00814   char automaton_is_used;
00815 
00816   /* The following fields are defined by checker.  */
00817 
00818   /* The following field value is the corresponding automaton.  This
00819      field is not NULL only if the automaton is present in unit
00820      declarations and the automatic partition on automata is not
00821      used.  */
00822   automaton_t corresponding_automaton;
00823 };
00824 
00825 /* This describes exclusion relations: exclusion_set (see file
00826    rtl.def).  */
00827 struct excl_rel_decl
00828 {
00829   int all_names_num;
00830   int first_list_length;
00831   char *names [1];
00832 };
00833 
00834 /* This describes unit relations: [final_]presence_set or
00835    [final_]absence_set (see file rtl.def).  */
00836 struct unit_pattern_rel_decl
00837 {
00838   int final_p;
00839   int names_num;
00840   int patterns_num;
00841   char **names;
00842   char ***patterns;
00843 };
00844 
00845 /* This describes define_reservation (see file rtl.def).  */
00846 struct reserv_decl
00847 {
00848   char *name;
00849   regexp_t regexp;
00850 
00851   /* The following fields are defined by checker.  */
00852 
00853   /* The following field value is nonzero if the unit is used in an
00854      regexp.  */
00855   char reserv_is_used;
00856   /* The following field is used to check up cycle in expression
00857      definition.  */
00858   int loop_pass_num;
00859 };
00860 
00861 /* This describes define_insn_reservation (see file rtl.def).  */
00862 struct insn_reserv_decl
00863 {
00864   rtx condexp;
00865   int default_latency;
00866   regexp_t regexp;
00867   char *name;
00868 
00869   /* The following fields are defined by checker.  */
00870 
00871   /* The following field value is order number (0, 1, ...) of given
00872      insn.  */
00873   int insn_num;
00874   /* The following field value is list of bypasses in which given insn
00875      is output insn.  */
00876   struct bypass_decl *bypass_list;
00877 
00878   /* The following fields are defined by automaton generator.  */
00879 
00880   /* The following field is the insn regexp transformed that
00881      the regexp has not optional regexp, repetition regexp, and an
00882      reservation name (i.e. reservation identifiers are changed by the
00883      corresponding regexp) and all alternations are the topest level
00884      of the regexp.  The value can be NULL only if it is special
00885      insn `cycle advancing'.  */
00886   regexp_t transformed_regexp;
00887   /* The following field value is list of arcs marked given
00888      insn.  The field is used in transformation NDFA -> DFA.  */
00889   arc_t arcs_marked_by_insn;
00890   /* The two following fields are used during minimization of a finite state
00891      automaton.  */
00892   /* The field value is number of equivalence class of state into
00893      which arc marked by given insn enters from a state (fixed during
00894      an automaton minimization).  */
00895   int equiv_class_num;
00896   /* The field value is state_alts of arc leaving a state (fixed
00897      during an automaton minimization) and marked by given insn
00898      enters.  */
00899   int state_alts;
00900   /* The following member value is the list to automata which can be
00901      changed by the insn issue.  */
00902   automata_list_el_t important_automata_list;
00903   /* The following member is used to process insn once for output.  */
00904   int processed_p;
00905 };
00906 
00907 /* This contains a declaration mentioned above.  */
00908 struct decl
00909 {
00910   /* What node in the union? */
00911   enum decl_mode mode;
00912   pos_t pos;
00913   union
00914   {
00915     struct unit_decl unit;
00916     struct bypass_decl bypass;
00917     struct automaton_decl automaton;
00918     struct excl_rel_decl excl;
00919     struct unit_pattern_rel_decl presence;
00920     struct unit_pattern_rel_decl absence;
00921     struct reserv_decl reserv;
00922     struct insn_reserv_decl insn_reserv;
00923   } decl;
00924 };
00925 
00926 /* The following structures represent parsed reservation strings.  */
00927 enum regexp_mode
00928 {
00929   rm_unit,
00930   rm_reserv,
00931   rm_nothing,
00932   rm_sequence,
00933   rm_repeat,
00934   rm_allof,
00935   rm_oneof
00936 };
00937 
00938 /* Cpu unit in reservation.  */
00939 struct unit_regexp
00940 {
00941   char *name;
00942   unit_decl_t unit_decl;
00943 };
00944 
00945 /* Define_reservation in a reservation.  */
00946 struct reserv_regexp
00947 {
00948   char *name;
00949   struct reserv_decl *reserv_decl;
00950 };
00951 
00952 /* Absence of reservation (represented by string `nothing').  */
00953 struct nothing_regexp
00954 {
00955   /* This used to be empty but ISO C doesn't allow that.  */
00956   char unused;
00957 };
00958 
00959 /* Representation of reservations separated by ',' (see file
00960    rtl.def).  */
00961 struct sequence_regexp
00962 {
00963   int regexps_num;
00964   regexp_t regexps [1];
00965 };
00966 
00967 /* Representation of construction `repeat' (see file rtl.def).  */
00968 struct repeat_regexp
00969 {
00970   int repeat_num;
00971   regexp_t regexp;
00972 };
00973 
00974 /* Representation of reservations separated by '+' (see file
00975    rtl.def).  */
00976 struct allof_regexp
00977 {
00978   int regexps_num;
00979   regexp_t regexps [1];
00980 };
00981 
00982 /* Representation of reservations separated by '|' (see file
00983    rtl.def).  */
00984 struct oneof_regexp
00985 {
00986   int regexps_num;
00987   regexp_t regexps [1];
00988 };
00989 
00990 /* Representation of a reservation string.  */
00991 struct regexp
00992 {
00993   /* What node in the union? */
00994   enum regexp_mode mode;
00995   pos_t pos;
00996   union
00997   {
00998     struct unit_regexp unit;
00999     struct reserv_regexp reserv;
01000     struct nothing_regexp nothing;
01001     struct sequence_regexp sequence;
01002     struct repeat_regexp repeat;
01003     struct allof_regexp allof;
01004     struct oneof_regexp oneof;
01005   } regexp;
01006 };
01007 
01008 /* Represents description of pipeline hazard description based on
01009    NDFA.  */
01010 struct description
01011 {
01012   int decls_num;
01013 
01014   /* The following fields are defined by checker.  */
01015 
01016   /* The following fields values are correspondingly number of all
01017      units, query units, and insns in the description.  */
01018   int units_num;
01019   int query_units_num;
01020   int insns_num;
01021   /* The following field value is max length (in cycles) of
01022      reservations of insns.  The field value is defined only for
01023      correct programs.  */
01024   int max_insn_reserv_cycles;
01025 
01026   /* The following fields are defined by automaton generator.  */
01027 
01028   /* The following field value is the first automaton.  */
01029   automaton_t first_automaton;
01030 
01031   /* The following field is created by pipeline hazard parser and
01032      contains all declarations.  We allocate additional entry for
01033      special insn "cycle advancing" which is added by the automaton
01034      generator.  */
01035   decl_t decls [1];
01036 };
01037 
01038 
01039 /* The following nodes are created in automaton checker.  */
01040 
01041 /* The following nodes represent exclusion set for cpu units.  Each
01042    element is accessed through only one excl_list.  */
01043 struct unit_set_el
01044 {
01045   unit_decl_t unit_decl;
01046   unit_set_el_t next_unit_set_el;
01047 };
01048 
01049 /* The following nodes represent presence or absence pattern for cpu
01050    units.  Each element is accessed through only one presence_list or
01051    absence_list.  */
01052 struct pattern_set_el
01053 {
01054   /* The number of units in unit_decls.  */
01055   int units_num;
01056   /* The units forming the pattern.  */
01057   struct unit_decl **unit_decls;
01058   pattern_set_el_t next_pattern_set_el;
01059 };
01060 
01061 
01062 /* The following nodes are created in automaton generator.  */
01063 
01064 
01065 /* The following nodes represent presence or absence pattern for cpu
01066    units.  Each element is accessed through only one element of
01067    unit_presence_set_table or unit_absence_set_table.  */
01068 struct pattern_reserv
01069 {
01070   reserv_sets_t reserv;
01071   pattern_reserv_t next_pattern_reserv;
01072 };
01073 
01074 /* The following node type describes state automaton.  The state may
01075    be deterministic or non-deterministic.  Non-deterministic state has
01076    several component states which represent alternative cpu units
01077    reservations.  The state also is used for describing a
01078    deterministic reservation of automaton insn.  */
01079 struct state
01080 {
01081   /* The following member value is nonzero if there is a transition by
01082      cycle advancing.  */
01083   int new_cycle_p;
01084   /* The following field is list of processor unit reservations on
01085      each cycle.  */
01086   reserv_sets_t reservs;
01087   /* The following field is unique number of given state between other
01088      states.  */
01089   int unique_num;
01090   /* The following field value is automaton to which given state
01091      belongs.  */
01092   automaton_t automaton;
01093   /* The following field value is the first arc output from given
01094      state.  */
01095   arc_t first_out_arc;
01096   /* The following field is used to form NDFA.  */
01097   char it_was_placed_in_stack_for_NDFA_forming;
01098   /* The following field is used to form DFA.  */
01099   char it_was_placed_in_stack_for_DFA_forming;
01100   /* The following field is used to transform NDFA to DFA and DFA
01101      minimization.  The field value is not NULL if the state is a
01102      compound state.  In this case the value of field `unit_sets_list'
01103      is NULL.  All states in the list are in the hash table.  The list
01104      is formed through field `next_sorted_alt_state'.  We should
01105      support only one level of nesting state.  */
01106   alt_state_t component_states;
01107   /* The following field is used for passing graph of states.  */
01108   int pass_num;
01109   /* The list of states belonging to one equivalence class is formed
01110      with the aid of the following field.  */
01111   state_t next_equiv_class_state;
01112   /* The two following fields are used during minimization of a finite
01113      state automaton.  */
01114   int equiv_class_num_1, equiv_class_num_2;
01115   /* The following field is used during minimization of a finite state
01116      automaton.  The field value is state corresponding to equivalence
01117      class to which given state belongs.  */
01118   state_t equiv_class_state;
01119   /* The following field value is the order number of given state.
01120      The states in final DFA is enumerated with the aid of the
01121      following field.  */
01122   int order_state_num;
01123   /* This member is used for passing states for searching minimal
01124      delay time.  */
01125   int state_pass_num;
01126   /* The following member is used to evaluate min issue delay of insn
01127      for a state.  */
01128   int min_insn_issue_delay;
01129   /* The following member is used to evaluate max issue rate of the
01130      processor.  The value of the member is maximal length of the path
01131      from given state no containing arcs marked by special insn `cycle
01132      advancing'.  */
01133   int longest_path_length;
01134 };
01135 
01136 /* The following macro is an initial value of member
01137    `longest_path_length' of a state.  */
01138 #define UNDEFINED_LONGEST_PATH_LENGTH -1
01139 
01140 /* Automaton arc.  */
01141 struct arc
01142 {
01143   /* The following field refers for the state into which given arc
01144      enters.  */
01145   state_t to_state;
01146   /* The following field describes that the insn issue (with cycle
01147      advancing for special insn `cycle advancing' and without cycle
01148      advancing for others) makes transition from given state to
01149      another given state.  */
01150   ainsn_t insn;
01151   /* The following field value is the next arc output from the same
01152      state.  */
01153   arc_t next_out_arc;
01154   /* List of arcs marked given insn is formed with the following
01155      field.  The field is used in transformation NDFA -> DFA.  */
01156   arc_t next_arc_marked_by_insn;
01157   /* The following field is defined if NDFA_FLAG is zero.  The member
01158      value is number of alternative reservations which can be used for
01159      transition for given state by given insn.  */
01160   int state_alts;
01161 };
01162 
01163 /* The following node type describes a deterministic alternative in
01164    non-deterministic state which characterizes cpu unit reservations
01165    of automaton insn or which is part of NDFA.  */
01166 struct alt_state
01167 {
01168   /* The following field is a deterministic state which characterizes
01169      unit reservations of the instruction.  */
01170   state_t state;
01171   /* The following field refers to the next state which characterizes
01172      unit reservations of the instruction.  */
01173   alt_state_t next_alt_state;
01174   /* The following field refers to the next state in sorted list.  */
01175   alt_state_t next_sorted_alt_state;
01176 };
01177 
01178 /* The following node type describes insn of automaton.  They are
01179    labels of FA arcs.  */
01180 struct ainsn
01181 {
01182   /* The following field value is the corresponding insn declaration
01183      of description.  */
01184   struct insn_reserv_decl *insn_reserv_decl;
01185   /* The following field value is the next insn declaration for an
01186      automaton.  */
01187   ainsn_t next_ainsn;
01188   /* The following field is states which characterize automaton unit
01189      reservations of the instruction.  The value can be NULL only if it
01190      is special insn `cycle advancing'.  */
01191   alt_state_t alt_states;
01192   /* The following field is sorted list of states which characterize
01193      automaton unit reservations of the instruction.  The value can be
01194      NULL only if it is special insn `cycle advancing'.  */
01195   alt_state_t sorted_alt_states;
01196   /* The following field refers the next automaton insn with
01197      the same reservations.  */
01198   ainsn_t next_same_reservs_insn;
01199   /* The following field is flag of the first automaton insn with the
01200      same reservations in the declaration list.  Only arcs marked such
01201      insn is present in the automaton.  This significantly decreases
01202      memory requirements especially when several automata are
01203      formed.  */
01204   char first_insn_with_same_reservs;
01205   /* The following member has nonzero value if there is arc from state of
01206      the automaton marked by the ainsn.  */
01207   char arc_exists_p;
01208   /* Cyclic list of insns of an equivalence class is formed with the
01209      aid of the following field.  */
01210   ainsn_t next_equiv_class_insn;
01211   /* The following field value is nonzero if the insn declaration is
01212      the first insn declaration with given equivalence number.  */
01213   char first_ainsn_with_given_equivalence_num;
01214   /* The following field is number of class of equivalence of insns.
01215      It is necessary because many insns may be equivalent with the
01216      point of view of pipeline hazards.  */
01217   int insn_equiv_class_num;
01218   /* The following member value is TRUE if there is an arc in the
01219      automaton marked by the insn into another state.  In other
01220      words, the insn can change the state of the automaton.  */
01221   int important_p;
01222 };
01223 
01224 /* The following describes an automaton for PHR.  */
01225 struct automaton
01226 {
01227   /* The following field value is the list of insn declarations for
01228      given automaton.  */
01229   ainsn_t ainsn_list;
01230   /* The following field value is the corresponding automaton
01231      declaration.  This field is not NULL only if the automatic
01232      partition on automata is not used.  */
01233   struct automaton_decl *corresponding_automaton_decl;
01234   /* The following field value is the next automaton.  */
01235   automaton_t next_automaton;
01236   /* The following field is start state of FA.  There are not unit
01237      reservations in the state.  */
01238   state_t start_state;
01239   /* The following field value is number of equivalence classes of
01240      insns (see field `insn_equiv_class_num' in
01241      `insn_reserv_decl').  */
01242   int insn_equiv_classes_num;
01243   /* The following field value is number of states of final DFA.  */
01244   int achieved_states_num;
01245   /* The following field value is the order number (0, 1, ...) of
01246      given automaton.  */
01247   int automaton_order_num;
01248   /* The following fields contain statistics information about
01249      building automaton.  */
01250   int NDFA_states_num, DFA_states_num;
01251   /* The following field value is defined only if minimization of DFA
01252      is used.  */
01253   int minimal_DFA_states_num;
01254   int NDFA_arcs_num, DFA_arcs_num;
01255   /* The following field value is defined only if minimization of DFA
01256      is used.  */
01257   int minimal_DFA_arcs_num;
01258   /* The following two members refer for two table state x ainsn ->
01259      int.  */
01260   state_ainsn_table_t trans_table;
01261   state_ainsn_table_t state_alts_table;
01262   /* The following member value is maximal value of min issue delay
01263      for insns of the automaton.  */
01264   int max_min_delay;
01265   /* Usually min issue delay is small and we can place several (2, 4,
01266      8) elements in one vector element.  So the compression factor can
01267      be 1 (no compression), 2, 4, 8.  */
01268   int min_issue_delay_table_compression_factor;
01269 };
01270 
01271 /* The following is the element of the list of automata.  */
01272 struct automata_list_el
01273 {
01274   /* The automaton itself.  */
01275   automaton_t automaton;
01276   /* The next automata set element.  */
01277   automata_list_el_t next_automata_list_el;
01278 };
01279 
01280 /* The following structure describes a table state X ainsn -> int(>= 0).  */
01281 struct state_ainsn_table
01282 {
01283   /* Automaton to which given table belongs.  */
01284   automaton_t automaton;
01285   /* The following tree vectors for comb vector implementation of the
01286      table.  */
01287   vla_hwint_t comb_vect;
01288   vla_hwint_t check_vect;
01289   vla_hwint_t base_vect;
01290   /* This is simple implementation of the table.  */
01291   vla_hwint_t full_vect;
01292   /* Minimal and maximal values of the previous vectors.  */
01293   int min_comb_vect_el_value, max_comb_vect_el_value;
01294   int min_base_vect_el_value, max_base_vect_el_value;
01295 };
01296 
01297 /* Macros to access members of unions.  Use only them for access to
01298    union members of declarations and regexps.  */
01299 
01300 #if defined ENABLE_CHECKING && (GCC_VERSION >= 2007)
01301 
01302 #define DECL_UNIT(d) __extension__          \
01303 (({ struct decl *const _decl = (d);         \
01304      if (_decl->mode != dm_unit)          \
01305        decl_mode_check_failed (_decl->mode, "dm_unit",      \
01306              __FILE__, __LINE__, __FUNCTION__); \
01307      &(_decl)->decl.unit; }))
01308 
01309 #define DECL_BYPASS(d) __extension__          \
01310 (({ struct decl *const _decl = (d);         \
01311      if (_decl->mode != dm_bypass)          \
01312        decl_mode_check_failed (_decl->mode, "dm_bypass",    \
01313              __FILE__, __LINE__, __FUNCTION__); \
01314      &(_decl)->decl.bypass; }))
01315 
01316 #define DECL_AUTOMATON(d) __extension__         \
01317 (({ struct decl *const _decl = (d);         \
01318      if (_decl->mode != dm_automaton)         \
01319        decl_mode_check_failed (_decl->mode, "dm_automaton",   \
01320              __FILE__, __LINE__, __FUNCTION__); \
01321      &(_decl)->decl.automaton; }))
01322 
01323 #define DECL_EXCL(d) __extension__          \
01324 (({ struct decl *const _decl = (d);         \
01325      if (_decl->mode != dm_excl)          \
01326        decl_mode_check_failed (_decl->mode, "dm_excl",      \
01327              __FILE__, __LINE__, __FUNCTION__); \
01328      &(_decl)->decl.excl; }))
01329 
01330 #define DECL_PRESENCE(d) __extension__          \
01331 (({ struct decl *const _decl = (d);         \
01332      if (_decl->mode != dm_presence)          \
01333        decl_mode_check_failed (_decl->mode, "dm_presence",    \
01334              __FILE__, __LINE__, __FUNCTION__); \
01335      &(_decl)->decl.presence; }))
01336 
01337 #define DECL_ABSENCE(d) __extension__         \
01338 (({ struct decl *const _decl = (d);         \
01339      if (_decl->mode != dm_absence)         \
01340        decl_mode_check_failed (_decl->mode, "dm_absence",   \
01341              __FILE__, __LINE__, __FUNCTION__); \
01342      &(_decl)->decl.absence; }))
01343 
01344 #define DECL_RESERV(d) __extension__          \
01345 (({ struct decl *const _decl = (d);         \
01346      if (_decl->mode != dm_reserv)          \
01347        decl_mode_check_failed (_decl->mode, "dm_reserv",    \
01348              __FILE__, __LINE__, __FUNCTION__); \
01349      &(_decl)->decl.reserv; }))
01350 
01351 #define DECL_INSN_RESERV(d) __extension__       \
01352 (({ struct decl *const _decl = (d);         \
01353      if (_decl->mode != dm_insn_reserv)         \
01354        decl_mode_check_failed (_decl->mode, "dm_insn_reserv",   \
01355              __FILE__, __LINE__, __FUNCTION__); \
01356      &(_decl)->decl.insn_reserv; }))
01357 
01358 static const char *decl_name (enum decl_mode);
01359 static void decl_mode_check_failed (enum decl_mode, const char *,
01360             const char *, int, const char *);
01361 
01362 /* Return string representation of declaration mode MODE.  */
01363 static const char *
01364 decl_name (enum decl_mode mode)
01365 {
01366   static char str [100];
01367 
01368   if (mode == dm_unit)
01369     return "dm_unit";
01370   else if (mode == dm_bypass)
01371     return "dm_bypass";
01372   else if (mode == dm_automaton)
01373     return "dm_automaton";
01374   else if (mode == dm_excl)
01375     return "dm_excl";
01376   else if (mode == dm_presence)
01377     return "dm_presence";
01378   else if (mode == dm_absence)
01379     return "dm_absence";
01380   else if (mode == dm_reserv)
01381     return "dm_reserv";
01382   else if (mode == dm_insn_reserv)
01383     return "dm_insn_reserv";
01384   else
01385     sprintf (str, "unknown (%d)", (int) mode);
01386   return str;
01387 }
01388 
01389 /* The function prints message about unexpected declaration and finish
01390    the program.  */
01391 static void
01392 decl_mode_check_failed (enum decl_mode mode, const char *expected_mode_str,
01393       const char *file, int line, const char *func)
01394 {
01395   fprintf
01396     (stderr,
01397      "\n%s: %d: error in %s: DECL check: expected decl %s, have %s\n",
01398      file, line, func, expected_mode_str, decl_name (mode));
01399   exit (1);
01400 }
01401 
01402 
01403 #define REGEXP_UNIT(r) __extension__          \
01404 (({ struct regexp *const _regexp = (r);         \
01405      if (_regexp->mode != rm_unit)          \
01406        regexp_mode_check_failed (_regexp->mode, "rm_unit",    \
01407              __FILE__, __LINE__, __FUNCTION__); \
01408      &(_regexp)->regexp.unit; }))
01409 
01410 #define REGEXP_RESERV(r) __extension__          \
01411 (({ struct regexp *const _regexp = (r);         \
01412      if (_regexp->mode != rm_reserv)          \
01413        regexp_mode_check_failed (_regexp->mode, "rm_reserv",    \
01414              __FILE__, __LINE__, __FUNCTION__); \
01415      &(_regexp)->regexp.reserv; }))
01416 
01417 #define REGEXP_SEQUENCE(r) __extension__        \
01418 (({ struct regexp *const _regexp = (r);         \
01419      if (_regexp->mode != rm_sequence)          \
01420        regexp_mode_check_failed (_regexp->mode, "rm_sequence",    \
01421              __FILE__, __LINE__, __FUNCTION__); \
01422      &(_regexp)->regexp.sequence; }))
01423 
01424 #define REGEXP_REPEAT(r) __extension__          \
01425 (({ struct regexp *const _regexp = (r);         \
01426      if (_regexp->mode != rm_repeat)          \
01427        regexp_mode_check_failed (_regexp->mode, "rm_repeat",    \
01428              __FILE__, __LINE__, __FUNCTION__); \
01429      &(_regexp)->regexp.repeat; }))
01430 
01431 #define REGEXP_ALLOF(r) __extension__         \
01432 (({ struct regexp *const _regexp = (r);         \
01433      if (_regexp->mode != rm_allof)         \
01434        regexp_mode_check_failed (_regexp->mode, "rm_allof",   \
01435              __FILE__, __LINE__, __FUNCTION__); \
01436      &(_regexp)->regexp.allof; }))
01437 
01438 #define REGEXP_ONEOF(r) __extension__         \
01439 (({ struct regexp *const _regexp = (r);         \
01440      if (_regexp->mode != rm_oneof)         \
01441        regexp_mode_check_failed (_regexp->mode, "rm_oneof",   \
01442              __FILE__, __LINE__, __FUNCTION__); \
01443      &(_regexp)->regexp.oneof; }))
01444 
01445 static const char *regexp_name (enum regexp_mode);
01446 static void regexp_mode_check_failed (enum regexp_mode, const char *,
01447               const char *, int,
01448               const char *);
01449 
01450 
01451 /* Return string representation of regexp mode MODE.  */
01452 static const char *
01453 regexp_name (enum regexp_mode mode)
01454 {
01455   switch (mode)
01456     {
01457     case rm_unit:
01458       return "rm_unit";
01459     case rm_reserv:
01460       return "rm_reserv";
01461     case rm_nothing:
01462       return "rm_nothing";
01463     case rm_sequence:
01464       return "rm_sequence";
01465     case rm_repeat:
01466       return "rm_repeat";
01467     case rm_allof:
01468       return "rm_allof";
01469     case rm_oneof:
01470       return "rm_oneof";
01471     default:
01472       gcc_unreachable ();
01473     }
01474 }
01475 
01476 /* The function prints message about unexpected regexp and finish the
01477    program.  */
01478 static void
01479 regexp_mode_check_failed (enum regexp_mode mode,
01480         const char *expected_mode_str,
01481         const char *file, int line, const char *func)
01482 {
01483   fprintf
01484     (stderr,
01485      "\n%s: %d: error in %s: REGEXP check: expected decl %s, have %s\n",
01486      file, line, func, expected_mode_str, regexp_name (mode));
01487   exit (1);
01488 }
01489 
01490 #else /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */
01491 
01492 #define DECL_UNIT(d) (&(d)->decl.unit)
01493 #define DECL_BYPASS(d) (&(d)->decl.bypass)
01494 #define DECL_AUTOMATON(d) (&(d)->decl.automaton)
01495 #define DECL_EXCL(d) (&(d)->decl.excl)
01496 #define DECL_PRESENCE(d) (&(d)->decl.presence)
01497 #define DECL_ABSENCE(d) (&(d)->decl.absence)
01498 #define DECL_RESERV(d) (&(d)->decl.reserv)
01499 #define DECL_INSN_RESERV(d) (&(d)->decl.insn_reserv)
01500 
01501 #define REGEXP_UNIT(r) (&(r)->regexp.unit)
01502 #define REGEXP_RESERV(r) (&(r)->regexp.reserv)
01503 #define REGEXP_SEQUENCE(r) (&(r)->regexp.sequence)
01504 #define REGEXP_REPEAT(r) (&(r)->regexp.repeat)
01505 #define REGEXP_ALLOF(r) (&(r)->regexp.allof)
01506 #define REGEXP_ONEOF(r) (&(r)->regexp.oneof)
01507 
01508 #endif /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */
01509 
01510 /* Create IR structure (node).  */
01511 static void *
01512 create_node (size_t size)
01513 {
01514   void *result;
01515 
01516   obstack_blank (&irp, size);
01517   result = obstack_base (&irp);
01518   obstack_finish (&irp);
01519   /* Default values of members are NULL and zero.  */
01520   memset (result, 0, size);
01521   return result;
01522 }
01523 
01524 /* Copy IR structure (node).  */
01525 static void *
01526 copy_node (const void *from, size_t size)
01527 {
01528   void *const result = create_node (size);
01529   memcpy (result, from, size);
01530   return result;
01531 }
01532 
01533 /* The function checks that NAME does not contain quotes (`"').  */
01534 static char *
01535 check_name (char * name, pos_t pos ATTRIBUTE_UNUSED)
01536 {
01537   const char *str;
01538 
01539   for (str = name; *str != '\0'; str++)
01540     if (*str == '\"')
01541       error ("Name `%s' contains quotes", name);
01542   return name;
01543 }
01544 
01545 /* Pointers to all declarations during IR generation are stored in the
01546    following.  */
01547 static vla_ptr_t decls;
01548 
01549 /* Given a pointer to a (char *) and a separator, return an alloc'ed
01550    string containing the next separated element, taking parentheses
01551    into account if PAR_FLAG has nonzero value.  Advance the pointer to
01552    after the string scanned, or the end-of-string.  Return NULL if at
01553    end of string.  */
01554 static char *
01555 next_sep_el (char **pstr, int sep, int par_flag)
01556 {
01557   char *out_str;
01558   char *p;
01559   int pars_num;
01560   int n_spaces;
01561 
01562   /* Remove leading whitespaces.  */
01563   while (ISSPACE ((int) **pstr))
01564     (*pstr)++;
01565 
01566   if (**pstr == '\0')
01567     return NULL;
01568 
01569   n_spaces = 0;
01570   for (pars_num = 0, p = *pstr; *p != '\0'; p++)
01571     {
01572       if (par_flag && *p == '(')
01573   pars_num++;
01574       else if (par_flag && *p == ')')
01575   pars_num--;
01576       else if (pars_num == 0 && *p == sep)
01577   break;
01578       if (pars_num == 0 && ISSPACE ((int) *p))
01579   n_spaces++;
01580       else
01581   {
01582     for (; n_spaces != 0; n_spaces--)
01583       obstack_1grow (&irp, p [-n_spaces]);
01584     obstack_1grow (&irp, *p);
01585   }
01586     }
01587   obstack_1grow (&irp, '\0');
01588   out_str = obstack_base (&irp);
01589   obstack_finish (&irp);
01590 
01591   *pstr = p;
01592   if (**pstr == sep)
01593     (*pstr)++;
01594 
01595   return out_str;
01596 }
01597 
01598 /* Given a string and a separator, return the number of separated
01599    elements in it, taking parentheses into account if PAR_FLAG has
01600    nonzero value.  Return 0 for the null string, -1 if parentheses is
01601    not balanced.  */
01602 static int
01603 n_sep_els (char *s, int sep, int par_flag)
01604 {
01605   int n;
01606   int pars_num;
01607 
01608   if (*s == '\0')
01609     return 0;
01610 
01611   for (pars_num = 0, n = 1; *s; s++)
01612     if (par_flag && *s == '(')
01613       pars_num++;
01614     else if (par_flag && *s == ')')
01615       pars_num--;
01616     else if (pars_num == 0 && *s == sep)
01617       n++;
01618 
01619   return (pars_num != 0 ? -1 : n);
01620 }
01621 
01622 /* Given a string and a separator, return vector of strings which are
01623    elements in the string and number of elements through els_num.
01624    Take parentheses into account if PAREN_P has nonzero value.  The
01625    function also inserts the end marker NULL at the end of vector.
01626    Return 0 for the null string, -1 if parentheses are not balanced.  */
01627 static char **
01628 get_str_vect (char *str, int *els_num, int sep, int paren_p)
01629 {
01630   int i;
01631   char **vect;
01632   char **pstr;
01633   char *trail;
01634 
01635   *els_num = n_sep_els (str, sep, paren_p);
01636   if (*els_num <= 0)
01637     return NULL;
01638   obstack_blank (&irp, sizeof (char *) * (*els_num + 1));
01639   vect = (char **) obstack_base (&irp);
01640   obstack_finish (&irp);
01641   pstr = &str;
01642   for (i = 0; i < *els_num; i++)
01643     vect [i] = next_sep_el (pstr, sep, paren_p);
01644   trail = next_sep_el (pstr, sep, paren_p);
01645   gcc_assert (!trail);
01646   vect [i] = NULL;
01647   return vect;
01648 }
01649 
01650 /* Process a DEFINE_CPU_UNIT.
01651 
01652    This gives information about a unit contained in CPU.  We fill a
01653    struct unit_decl with information used later by `expand_automata'.  */
01654 void
01655 gen_cpu_unit (rtx def)
01656 {
01657   decl_t decl;
01658   char **str_cpu_units;
01659   int vect_length;
01660   int i;
01661 
01662   str_cpu_units = get_str_vect ((char *) XSTR (def, 0), &vect_length, ',',
01663         FALSE);
01664   if (str_cpu_units == NULL)
01665     fatal ("invalid string `%s' in define_cpu_unit", XSTR (def, 0));
01666   for (i = 0; i < vect_length; i++)
01667     {
01668       decl = create_node (sizeof (struct decl));
01669       decl->mode = dm_unit;
01670       decl->pos = 0;
01671       DECL_UNIT (decl)->name = check_name (str_cpu_units [i], decl->pos);
01672       DECL_UNIT (decl)->automaton_name = (char *) XSTR (def, 1);
01673       DECL_UNIT (decl)->query_p = 0;
01674       DECL_UNIT (decl)->min_occ_cycle_num = -1;
01675       DECL_UNIT (decl)->in_set_p = 0;
01676       VLA_PTR_ADD (decls, decl);
01677       num_dfa_decls++;
01678     }
01679 }
01680 
01681 /* Process a DEFINE_QUERY_CPU_UNIT.
01682 
01683    This gives information about a unit contained in CPU.  We fill a
01684    struct unit_decl with information used later by `expand_automata'.  */
01685 void
01686 gen_query_cpu_unit (rtx def)
01687 {
01688   decl_t decl;
01689   char **str_cpu_units;
01690   int vect_length;
01691   int i;
01692 
01693   str_cpu_units = get_str_vect ((char *) XSTR (def, 0), &vect_length, ',',
01694         FALSE);
01695   if (str_cpu_units == NULL)
01696     fatal ("invalid string `%s' in define_query_cpu_unit", XSTR (def, 0));
01697   for (i = 0; i < vect_length; i++)
01698     {
01699       decl = create_node (sizeof (struct decl));
01700       decl->mode = dm_unit;
01701       decl->pos = 0;
01702       DECL_UNIT (decl)->name = check_name (str_cpu_units [i], decl->pos);
01703       DECL_UNIT (decl)->automaton_name = (char *) XSTR (def, 1);
01704       DECL_UNIT (decl)->query_p = 1;
01705       VLA_PTR_ADD (decls, decl);
01706       num_dfa_decls++;
01707     }
01708 }
01709 
01710 /* Process a DEFINE_BYPASS.
01711 
01712    This gives information about a unit contained in the CPU.  We fill
01713    in a struct bypass_decl with information used later by
01714    `expand_automata'.  */
01715 void
01716 gen_bypass (rtx def)
01717 {
01718   decl_t decl;
01719   char **out_insns;
01720   int out_length;
01721   char **in_insns;
01722   int in_length;
01723   int i, j;
01724 
01725   out_insns = get_str_vect ((char *) XSTR (def, 1), &out_length, ',', FALSE);
01726   if (out_insns == NULL)
01727     fatal ("invalid string `%s' in define_bypass", XSTR (def, 1));
01728   in_insns = get_str_vect ((char *) XSTR (def, 2), &in_length, ',', FALSE);
01729   if (in_insns == NULL)
01730     fatal ("invalid string `%s' in define_bypass", XSTR (def, 2));
01731   for (i = 0; i < out_length; i++)
01732     for (j = 0; j < in_length; j++)
01733       {
01734   decl = create_node (sizeof (struct decl));
01735   decl->mode = dm_bypass;
01736   decl->pos = 0;
01737   DECL_BYPASS (decl)->latency = XINT (def, 0);
01738   DECL_BYPASS (decl)->out_insn_name = out_insns [i];
01739   DECL_BYPASS (decl)->in_insn_name = in_insns [j];
01740   DECL_BYPASS (decl)->bypass_guard_name = (char *) XSTR (def, 3);
01741   VLA_PTR_ADD (decls, decl);
01742   num_dfa_decls++;
01743       }
01744 }
01745 
01746 /* Process an EXCLUSION_SET.
01747 
01748    This gives information about a cpu unit conflicts.  We fill a
01749    struct excl_rel_decl (excl) with information used later by
01750    `expand_automata'.  */
01751 void
01752 gen_excl_set (rtx def)
01753 {
01754   decl_t decl;
01755   char **first_str_cpu_units;
01756   char **second_str_cpu_units;
01757   int first_vect_length;
01758   int length;
01759   int i;
01760 
01761   first_str_cpu_units
01762     = get_str_vect ((char *) XSTR (def, 0), &first_vect_length, ',', FALSE);
01763   if (first_str_cpu_units == NULL)
01764     fatal ("invalid first string `%s' in exclusion_set", XSTR (def, 0));
01765   second_str_cpu_units = get_str_vect ((char *) XSTR (def, 1), &length, ',',
01766                FALSE);
01767   if (second_str_cpu_units == NULL)
01768     fatal ("invalid second string `%s' in exclusion_set", XSTR (def, 1));
01769   length += first_vect_length;
01770   decl = create_node (sizeof (struct decl) + (length - 1) * sizeof (char *));
01771   decl->mode = dm_excl;
01772   decl->pos = 0;
01773   DECL_EXCL (decl)->all_names_num = length;
01774   DECL_EXCL (decl)->first_list_length = first_vect_length;
01775   for (i = 0; i < length; i++)
01776     if (i < first_vect_length)
01777       DECL_EXCL (decl)->names [i] = first_str_cpu_units [i];
01778     else
01779       DECL_EXCL (decl)->names [i]
01780   = second_str_cpu_units [i - first_vect_length];
01781   VLA_PTR_ADD (decls, decl);
01782   num_dfa_decls++;
01783 }
01784 
01785 /* Process a PRESENCE_SET, a FINAL_PRESENCE_SET, an ABSENCE_SET,
01786    FINAL_ABSENCE_SET (it is depended on PRESENCE_P and FINAL_P).
01787 
01788    This gives information about a cpu unit reservation requirements.
01789    We fill a struct unit_pattern_rel_decl with information used later
01790    by `expand_automata'.  */
01791 static void
01792 gen_presence_absence_set (rtx def, int presence_p, int final_p)
01793 {
01794   decl_t decl;
01795   char **str_cpu_units;
01796   char ***str_patterns;
01797   int cpu_units_length;
01798   int length;
01799   int patterns_length;
01800   int i;
01801 
01802   str_cpu_units = get_str_vect ((char *) XSTR (def, 0), &cpu_units_length, ',',
01803         FALSE);
01804   if (str_cpu_units == NULL)
01805     fatal ((presence_p
01806       ? (final_p
01807          ? "invalid first string `%s' in final_presence_set"
01808          : "invalid first string `%s' in presence_set")
01809       : (final_p
01810          ? "invalid first string `%s' in final_absence_set"
01811          : "invalid first string `%s' in absence_set")),
01812      XSTR (def, 0));
01813   str_patterns = (char ***) get_str_vect ((char *) XSTR (def, 1),
01814             &patterns_length, ',', FALSE);
01815   if (str_patterns == NULL)
01816     fatal ((presence_p
01817       ? (final_p
01818          ? "invalid second string `%s' in final_presence_set"
01819          : "invalid second string `%s' in presence_set")
01820       : (final_p
01821          ? "invalid second string `%s' in final_absence_set"
01822          : "invalid second string `%s' in absence_set")), XSTR (def, 1));
01823   for (i = 0; i < patterns_length; i++)
01824     {
01825       str_patterns [i] = get_str_vect ((char *) str_patterns [i], &length, ' ',
01826                FALSE);
01827       gcc_assert (str_patterns [i]);
01828     }
01829   decl = create_node (sizeof (struct decl));
01830   decl->pos = 0;
01831   if (presence_p)
01832     {
01833       decl->mode = dm_presence;
01834       DECL_PRESENCE (decl)->names_num = cpu_units_length;
01835       DECL_PRESENCE (decl)->names = str_cpu_units;
01836       DECL_PRESENCE (decl)->patterns = str_patterns;
01837       DECL_PRESENCE (decl)->patterns_num = patterns_length;
01838       DECL_PRESENCE (decl)->final_p = final_p;
01839     }
01840   else
01841     {
01842       decl->mode = dm_absence;
01843       DECL_ABSENCE (decl)->names_num = cpu_units_length;
01844       DECL_ABSENCE (decl)->names = str_cpu_units;
01845       DECL_ABSENCE (decl)->patterns = str_patterns;
01846       DECL_ABSENCE (decl)->patterns_num = patterns_length;
01847       DECL_ABSENCE (decl)->final_p = final_p;
01848     }
01849   VLA_PTR_ADD (decls, decl);
01850   num_dfa_decls++;
01851 }
01852 
01853 /* Process a PRESENCE_SET.
01854 
01855     This gives information about a cpu unit reservation requirements.
01856    We fill a struct unit_pattern_rel_decl (presence) with information
01857    used later by `expand_automata'.  */
01858 void
01859 gen_presence_set (rtx def)
01860 {
01861   gen_presence_absence_set (def, TRUE, FALSE);
01862 }
01863 
01864 /* Process a FINAL_PRESENCE_SET.
01865 
01866    This gives information about a cpu unit reservation requirements.
01867    We fill a struct unit_pattern_rel_decl (presence) with information
01868    used later by `expand_automata'.  */
01869 void
01870 gen_final_presence_set (rtx def)
01871 {
01872   gen_presence_absence_set (def, TRUE, TRUE);
01873 }
01874 
01875 /* Process an ABSENCE_SET.
01876 
01877    This gives information about a cpu unit reservation requirements.
01878    We fill a struct unit_pattern_rel_decl (absence) with information
01879    used later by `expand_automata'.  */
01880 void
01881 gen_absence_set (rtx def)
01882 {
01883   gen_presence_absence_set (def, FALSE, FALSE);
01884 }
01885 
01886 /* Process a FINAL_ABSENCE_SET.
01887 
01888    This gives information about a cpu unit reservation requirements.
01889    We fill a struct unit_pattern_rel_decl (absence) with information
01890    used later by `expand_automata'.  */
01891 void
01892 gen_final_absence_set (rtx def)
01893 {
01894   gen_presence_absence_set (def, FALSE, TRUE);
01895 }
01896 
01897 /* Process a DEFINE_AUTOMATON.
01898 
01899    This gives information about a finite state automaton used for
01900    recognizing pipeline hazards.  We fill a struct automaton_decl
01901    with information used later by `expand_automata'.  */
01902 void
01903 gen_automaton (rtx def)
01904 {
01905   decl_t decl;
01906   char **str_automata;
01907   int vect_length;
01908   int i;
01909 
01910   str_automata = get_str_vect ((char *) XSTR (def, 0), &vect_length, ',',
01911              FALSE);
01912   if (str_automata == NULL)
01913     fatal ("invalid string `%s' in define_automaton", XSTR (def, 0));
01914   for (i = 0; i < vect_length; i++)
01915     {
01916       decl = create_node (sizeof (struct decl));
01917       decl->mode = dm_automaton;
01918       decl->pos = 0;
01919       DECL_AUTOMATON (decl)->name = check_name (str_automata [i], decl->pos);
01920       VLA_PTR_ADD (decls, decl);
01921       num_dfa_decls++;
01922     }
01923 }
01924 
01925 /* Process an AUTOMATA_OPTION.
01926 
01927    This gives information how to generate finite state automaton used
01928    for recognizing pipeline hazards.  */
01929 void
01930 gen_automata_option (rtx def)
01931 {
01932   if (strcmp (XSTR (def, 0), NO_MINIMIZATION_OPTION + 1) == 0)
01933     no_minimization_flag = 1;
01934   else if (strcmp (XSTR (def, 0), TIME_OPTION + 1) == 0)
01935     time_flag = 1;
01936   else if (strcmp (XSTR (def, 0), V_OPTION + 1) == 0)
01937     v_flag = 1;
01938   else if (strcmp (XSTR (def, 0), W_OPTION + 1) == 0)
01939     w_flag = 1;
01940   else if (strcmp (XSTR (def, 0), NDFA_OPTION + 1) == 0)
01941     ndfa_flag = 1;
01942   else if (strcmp (XSTR (def, 0), PROGRESS_OPTION + 1) == 0)
01943     progress_flag = 1;
01944   else
01945     fatal ("invalid option `%s' in automata_option", XSTR (def, 0));
01946 }
01947 
01948 /* Name in reservation to denote absence reservation.  */
01949 #define NOTHING_NAME "nothing"
01950 
01951 /* The following string contains original reservation string being
01952    parsed.  */
01953 static char *reserv_str;
01954 
01955 /* Parse an element in STR.  */
01956 static regexp_t
01957 gen_regexp_el (char *str)
01958 {
01959   regexp_t regexp;
01960   int len;
01961 
01962   if (*str == '(')
01963     {
01964       len = strlen (str);
01965       if (str [len - 1] != ')')
01966   fatal ("garbage after ) in reservation `%s'", reserv_str);
01967       str [len - 1] = '\0';
01968       regexp = gen_regexp_sequence (str + 1);
01969     }
01970   else if (strcmp (str, NOTHING_NAME) == 0)
01971     {
01972       regexp = create_node (sizeof (struct decl));
01973       regexp->mode = rm_nothing;
01974     }
01975   else
01976     {
01977       regexp = create_node (sizeof (struct decl));
01978       regexp->mode = rm_unit;
01979       REGEXP_UNIT (regexp)->name = str;
01980     }
01981   return regexp;
01982 }
01983 
01984 /* Parse construction `repeat' in STR.  */
01985 static regexp_t
01986 gen_regexp_repeat (char *str)
01987 {
01988   regexp_t regexp;
01989   regexp_t repeat;
01990   char **repeat_vect;
01991   int els_num;
01992   int i;
01993 
01994   repeat_vect = get_str_vect (str, &els_num, '*', TRUE);
01995   if (repeat_vect == NULL)
01996     fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
01997   if (els_num > 1)
01998     {
01999       regexp = gen_regexp_el (repeat_vect [0]);
02000       for (i = 1; i < els_num; i++)
02001   {
02002     repeat = create_node (sizeof (struct regexp));
02003     repeat->mode = rm_repeat;
02004     REGEXP_REPEAT (repeat)->regexp = regexp;
02005     REGEXP_REPEAT (repeat)->repeat_num = atoi (repeat_vect [i]);
02006           if (REGEXP_REPEAT (repeat)->repeat_num <= 1)
02007             fatal ("repetition `%s' <= 1 in reservation `%s'",
02008                    str, reserv_str);
02009           regexp = repeat;
02010   }
02011       return regexp;
02012     }
02013   else
02014     return gen_regexp_el (str);
02015 }
02016 
02017 /* Parse reservation STR which possibly contains separator '+'.  */
02018 static regexp_t
02019 gen_regexp_allof (char *str)
02020 {
02021   regexp_t allof;
02022   char **allof_vect;
02023   int els_num;
02024   int i;
02025 
02026   allof_vect = get_str_vect (str, &els_num, '+', TRUE);
02027   if (allof_vect == NULL)
02028     fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
02029   if (els_num > 1)
02030     {
02031       allof = create_node (sizeof (struct regexp)
02032          + sizeof (regexp_t) * (els_num - 1));
02033       allof->mode = rm_allof;
02034       REGEXP_ALLOF (allof)->regexps_num = els_num;
02035       for (i = 0; i < els_num; i++)
02036   REGEXP_ALLOF (allof)->regexps [i] = gen_regexp_repeat (allof_vect [i]);
02037       return allof;
02038     }
02039   else
02040     return gen_regexp_repeat (str);
02041 }
02042 
02043 /* Parse reservation STR which possibly contains separator '|'.  */
02044 static regexp_t
02045 gen_regexp_oneof (char *str)
02046 {
02047   regexp_t oneof;
02048   char **oneof_vect;
02049   int els_num;
02050   int i;
02051 
02052   oneof_vect = get_str_vect (str, &els_num, '|', TRUE);
02053   if (oneof_vect == NULL)
02054     fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
02055   if (els_num > 1)
02056     {
02057       oneof = create_node (sizeof (struct regexp)
02058          + sizeof (regexp_t) * (els_num - 1));
02059       oneof->mode = rm_oneof;
02060       REGEXP_ONEOF (oneof)->regexps_num = els_num;
02061       for (i = 0; i < els_num; i++)
02062   REGEXP_ONEOF (oneof)->regexps [i] = gen_regexp_allof (oneof_vect [i]);
02063       return oneof;
02064     }
02065   else
02066     return gen_regexp_allof (str);
02067 }
02068 
02069 /* Parse reservation STR which possibly contains separator ','.  */
02070 static regexp_t
02071 gen_regexp_sequence (char *str)
02072 {
02073   regexp_t sequence;
02074   char **sequence_vect;
02075   int els_num;
02076   int i;
02077 
02078   sequence_vect = get_str_vect (str, &els_num, ',', TRUE);
02079   if (els_num > 1)
02080     {
02081       sequence = create_node (sizeof (struct regexp)
02082             + sizeof (regexp_t) * (els_num - 1));
02083       sequence->mode = rm_sequence;
02084       REGEXP_SEQUENCE (sequence)->regexps_num = els_num;
02085       for (i = 0; i < els_num; i++)
02086   REGEXP_SEQUENCE (sequence)->regexps [i]
02087           = gen_regexp_oneof (sequence_vect [i]);
02088       return sequence;
02089     }
02090   else
02091     return gen_regexp_oneof (str);
02092 }
02093 
02094 /* Parse construction reservation STR.  */
02095 static regexp_t
02096 gen_regexp (char *str)
02097 {
02098   reserv_str = str;
02099   return gen_regexp_sequence (str);;
02100 }
02101 
02102 /* Process a DEFINE_RESERVATION.
02103 
02104    This gives information about a reservation of cpu units.  We fill
02105    in a struct reserv_decl with information used later by
02106    `expand_automata'.  */
02107 void
02108 gen_reserv (rtx def)
02109 {
02110   decl_t decl;
02111 
02112   decl = create_node (sizeof (struct decl));
02113   decl->mode = dm_reserv;
02114   decl->pos = 0;
02115   DECL_RESERV (decl)->name = check_name ((char *) XSTR (def, 0), decl->pos);
02116   DECL_RESERV (decl)->regexp = gen_regexp ((char *) XSTR (def, 1));
02117   VLA_PTR_ADD (decls, decl);
02118   num_dfa_decls++;
02119 }
02120 
02121 /* Process a DEFINE_INSN_RESERVATION.
02122 
02123    This gives information about the reservation of cpu units by an
02124    insn.  We fill a struct insn_reserv_decl with information used
02125    later by `expand_automata'.  */
02126 void
02127 gen_insn_reserv (rtx def)
02128 {
02129   decl_t decl;
02130 
02131   decl = create_node (sizeof (struct decl));
02132   decl->mode = dm_insn_reserv;
02133   decl->pos = 0;
02134   DECL_INSN_RESERV (decl)->name
02135     = check_name ((char *) XSTR (def, 0), decl->pos);
02136   DECL_INSN_RESERV (decl)->default_latency = XINT (def, 1);
02137   DECL_INSN_RESERV (decl)->condexp = XEXP (def, 2);
02138   DECL_INSN_RESERV (decl)->regexp = gen_regexp ((char *) XSTR (def, 3));
02139   VLA_PTR_ADD (decls, decl);
02140   num_dfa_decls++;
02141 }
02142 
02143 
02144 
02145 /* The function evaluates hash value (0..UINT_MAX) of string.  */
02146 static unsigned
02147 string_hash (const char *string)
02148 {
02149   unsigned result, i;
02150 
02151   for (result = i = 0;*string++ != '\0'; i++)
02152     result += ((unsigned char) *string << (i % CHAR_BIT));
02153   return result;
02154 }
02155 
02156 
02157 
02158 /* This page contains abstract data `table of automaton declarations'.
02159    Elements of the table is nodes representing automaton declarations.
02160    Key of the table elements is name of given automaton.  Remember
02161    that automaton names have own space.  */
02162 
02163 /* The function evaluates hash value of an automaton declaration.  The
02164    function is used by abstract data `hashtab'.  The function returns
02165    hash value (0..UINT_MAX) of given automaton declaration.  */
02166 static hashval_t
02167 automaton_decl_hash (const void *automaton_decl)
02168 {
02169   const decl_t decl = (decl_t) automaton_decl;
02170 
02171   gcc_assert (decl->mode != dm_automaton
02172         || DECL_AUTOMATON (decl)->name);
02173   return string_hash (DECL_AUTOMATON (decl)->name);
02174 }
02175 
02176 /* The function tests automaton declarations on equality of their
02177    keys.  The function is used by abstract data `hashtab'.  The
02178    function returns 1 if the declarations have the same key, 0
02179    otherwise.  */
02180 static int
02181 automaton_decl_eq_p (const void* automaton_decl_1,
02182          const void* automaton_decl_2)
02183 {
02184   const decl_t decl1 = (decl_t) automaton_decl_1;
02185   const decl_t decl2 = (decl_t) automaton_decl_2;
02186 
02187   gcc_assert (decl1->mode == dm_automaton
02188         && DECL_AUTOMATON (decl1)->name
02189         && decl2->mode == dm_automaton
02190         && DECL_AUTOMATON (decl2)->name);
02191   return strcmp (DECL_AUTOMATON (decl1)->name,
02192      DECL_AUTOMATON (decl2)->name) == 0;
02193 }
02194 
02195 /* The automaton declaration table itself is represented by the
02196    following variable.  */
02197 static htab_t automaton_decl_table;
02198 
02199 /* The function inserts automaton declaration into the table.  The
02200    function does nothing if an automaton declaration with the same key
02201    exists already in the table.  The function returns automaton
02202    declaration node in the table with the same key as given automaton
02203    declaration node.  */
02204 static decl_t
02205 insert_automaton_decl (decl_t automaton_decl)
02206 {
02207   void **entry_ptr;
02208 
02209   entry_ptr = htab_find_slot (automaton_decl_table, automaton_decl, 1);
02210   if (*entry_ptr == NULL)
02211     *entry_ptr = (void *) automaton_decl;
02212   return (decl_t) *entry_ptr;
02213 }
02214 
02215 /* The following variable value is node representing automaton
02216    declaration.  The node used for searching automaton declaration
02217    with given name.  */
02218 static struct decl work_automaton_decl;
02219 
02220 /* The function searches for automaton declaration in the table with
02221    the same key as node representing name of the automaton
02222    declaration.  The function returns node found in the table, NULL if
02223    such node does not exist in the table.  */
02224 static decl_t
02225 find_automaton_decl (char *name)
02226 {
02227   void *entry;
02228 
02229   work_automaton_decl.mode = dm_automaton;
02230   DECL_AUTOMATON (&work_automaton_decl)->name = name;
02231   entry = htab_find (automaton_decl_table, &work_automaton_decl);
02232   return (decl_t) entry;
02233 }
02234 
02235 /* The function creates empty automaton declaration table and node
02236    representing automaton declaration and used for searching automaton
02237    declaration with given name.  The function must be called only once
02238    before any work with the automaton declaration table.  */
02239 static void
02240 initiate_automaton_decl_table (void)
02241 {
02242   work_automaton_decl.mode = dm_automaton;
02243   automaton_decl_table = htab_create (10, automaton_decl_hash,
02244               automaton_decl_eq_p, (htab_del) 0);
02245 }
02246 
02247 /* The function deletes the automaton declaration table.  Only call of
02248    function `initiate_automaton_decl_table' is possible immediately
02249    after this function call.  */
02250 static void
02251 finish_automaton_decl_table (void)
02252 {
02253   htab_delete (automaton_decl_table);
02254 }
02255 
02256 
02257 
02258 /* This page contains abstract data `table of insn declarations'.
02259    Elements of the table is nodes representing insn declarations.  Key
02260    of the table elements is name of given insn (in corresponding
02261    define_insn_reservation).  Remember that insn names have own
02262    space.  */
02263 
02264 /* The function evaluates hash value of an insn declaration.  The
02265    function is used by abstract data `hashtab'.  The function returns
02266    hash value (0..UINT_MAX) of given insn declaration.  */
02267 static hashval_t
02268 insn_decl_hash (const void *insn_decl)
02269 {
02270   const decl_t decl = (decl_t) insn_decl;
02271 
02272   gcc_assert (decl->mode == dm_insn_reserv
02273         && DECL_INSN_RESERV (decl)->name);
02274   return string_hash (DECL_INSN_RESERV (decl)->name);
02275 }
02276 
02277 /* The function tests insn declarations on equality of their keys.
02278    The function is used by abstract data `hashtab'.  The function
02279    returns 1 if declarations have the same key, 0 otherwise.  */
02280 static int
02281 insn_decl_eq_p (const void *insn_decl_1, const void *insn_decl_2)
02282 {
02283   const decl_t decl1 = (decl_t) insn_decl_1;
02284   const decl_t decl2 = (decl_t) insn_decl_2;
02285 
02286   gcc_assert (decl1->mode == dm_insn_reserv
02287         && DECL_INSN_RESERV (decl1)->name
02288         && decl2->mode == dm_insn_reserv
02289         && DECL_INSN_RESERV (decl2)->name);
02290   return strcmp (DECL_INSN_RESERV (decl1)->name,
02291                  DECL_INSN_RESERV (decl2)->name) == 0;
02292 }
02293 
02294 /* The insn declaration table itself is represented by the following
02295    variable.  The table does not contain insn reservation
02296    declarations.  */
02297 static htab_t insn_decl_table;
02298 
02299 /* The function inserts insn declaration into the table.  The function
02300    does nothing if an insn declaration with the same key exists
02301    already in the table.  The function returns insn declaration node
02302    in the table with the same key as given insn declaration node.  */
02303 static decl_t
02304 insert_insn_decl (decl_t insn_decl)
02305 {
02306   void **entry_ptr;
02307 
02308   entry_ptr = htab_find_slot (insn_decl_table, insn_decl, 1);
02309   if (*entry_ptr == NULL)
02310     *entry_ptr = (void *) insn_decl;
02311   return (decl_t) *entry_ptr;
02312 }
02313 
02314 /* The following variable value is node representing insn reservation
02315    declaration.  The node used for searching insn reservation
02316    declaration with given name.  */
02317 static struct decl work_insn_decl;
02318 
02319 /* The function searches for insn reservation declaration in the table
02320    with the same key as node representing name of the insn reservation
02321    declaration.  The function returns node found in the table, NULL if
02322    such node does not exist in the table.  */
02323 static decl_t
02324 find_insn_decl (char *name)
02325 {
02326   void *entry;
02327 
02328   work_insn_decl.mode = dm_insn_reserv;
02329   DECL_INSN_RESERV (&work_insn_decl)->name = name;
02330   entry = htab_find (insn_decl_table, &work_insn_decl);
02331   return (decl_t) entry;
02332 }
02333 
02334 /* The function creates empty insn declaration table and node
02335    representing insn declaration and used for searching insn
02336    declaration with given name.  The function must be called only once
02337    before any work with the insn declaration table.  */
02338 static void
02339 initiate_insn_decl_table (void)
02340 {
02341   work_insn_decl.mode = dm_insn_reserv;
02342   insn_decl_table = htab_create (10, insn_decl_hash, insn_decl_eq_p,
02343          (htab_del) 0);
02344 }
02345 
02346 /* The function deletes the insn declaration table.  Only call of
02347    function `initiate_insn_decl_table' is possible immediately after
02348    this function call.  */
02349 static void
02350 finish_insn_decl_table (void)
02351 {
02352   htab_delete (insn_decl_table);
02353 }
02354 
02355 
02356 
02357 /* This page contains abstract data `table of declarations'.  Elements
02358    of the table is nodes representing declarations (of units and
02359    reservations).  Key of the table elements is names of given
02360    declarations.  */
02361 
02362 /* The function evaluates hash value of a declaration.  The function
02363    is used by abstract data `hashtab'.  The function returns hash
02364    value (0..UINT_MAX) of given declaration.  */
02365 static hashval_t
02366 decl_hash (const void *decl)
02367 {
02368   const decl_t d = (const decl_t) decl;
02369 
02370   gcc_assert ((d->mode == dm_unit && DECL_UNIT (d)->name)
02371         || (d->mode == dm_reserv && DECL_RESERV (d)->name));
02372   return string_hash (d->mode == dm_unit
02373           ? DECL_UNIT (d)->name : DECL_RESERV (d)->name);
02374 }
02375 
02376 /* The function tests declarations on equality of their keys.  The
02377    function is used by abstract data 'hashtab'.  The function
02378    returns 1 if the declarations have the same key, 0 otherwise.  */
02379 static int
02380 decl_eq_p (const void *decl_1, const void *decl_2)
02381 {
02382   const decl_t d1 = (const decl_t) decl_1;
02383   const decl_t d2 = (const decl_t) decl_2;
02384 
02385   gcc_assert ((d1->mode == dm_unit && DECL_UNIT (d1)->name)
02386         || (d1->mode == dm_reserv && DECL_RESERV (d1)->name));
02387   gcc_assert ((d2->mode == dm_unit && DECL_UNIT (d2)->name)
02388         || (d2->mode == dm_reserv && DECL_RESERV (d2)->name));
02389   return strcmp ((d1->mode == dm_unit
02390                   ? DECL_UNIT (d1)->name : DECL_RESERV (d1)->name),
02391                  (d2->mode == dm_unit
02392                   ? DECL_UNIT (d2)->name : DECL_RESERV (d2)->name)) == 0;
02393 }
02394 
02395 /* The declaration table itself is represented by the following
02396    variable.  */
02397 static htab_t decl_table;
02398 
02399 /* The function inserts declaration into the table.  The function does
02400    nothing if a declaration with the same key exists already in the
02401    table.  The function returns declaration node in the table with the
02402    same key as given declaration node.  */
02403 
02404 static decl_t
02405 insert_decl (decl_t decl)
02406 {
02407   void **entry_ptr;
02408 
02409   entry_ptr = htab_find_slot (decl_table, decl, 1);
02410   if (*entry_ptr == NULL)
02411     *entry_ptr = (void *) decl;
02412   return (decl_t) *entry_ptr;
02413 }
02414 
02415 /* The following variable value is node representing declaration.  The
02416    node used for searching declaration with given name.  */
02417 static struct decl work_decl;
02418 
02419 /* The function searches for declaration in the table with the same
02420    key as node representing name of the declaration.  The function
02421    returns node found in the table, NULL if such node does not exist
02422    in the table.  */
02423 static decl_t
02424 find_decl (char *name)
02425 {
02426   void *entry;
02427 
02428   work_decl.mode = dm_unit;
02429   DECL_UNIT (&work_decl)->name = name;
02430   entry = htab_find (decl_table, &work_decl);
02431   return (decl_t) entry;
02432 }
02433 
02434 /* The function creates empty declaration table and node representing
02435    declaration and used for searching declaration with given name.
02436    The function must be called only once before any work with the
02437    declaration table.  */
02438 static void
02439 initiate_decl_table (void)
02440 {
02441   work_decl.mode = dm_unit;
02442   decl_table = htab_create (10, decl_hash, decl_eq_p, (htab_del) 0);
02443 }
02444 
02445 /* The function deletes the declaration table.  Only call of function
02446    `initiate_declaration_table' is possible immediately after this
02447    function call.  */
02448 static void
02449 finish_decl_table (void)
02450 {
02451   htab_delete (decl_table);
02452 }
02453 
02454 
02455 
02456 /* This page contains checker of pipeline hazard description.  */
02457 
02458 /* Checking NAMES in an exclusion clause vector and returning formed
02459    unit_set_el_list.  */
02460 static unit_set_el_t
02461 process_excls (char **names, int num, pos_t excl_pos ATTRIBUTE_UNUSED)
02462 {
02463   unit_set_el_t el_list;
02464   unit_set_el_t last_el;
02465   unit_set_el_t new_el;
02466   decl_t decl_in_table;
02467   int i;
02468 
02469   el_list = NULL;
02470   last_el = NULL;
02471   for (i = 0; i < num; i++)
02472     {
02473       decl_in_table = find_decl (names [i]);
02474       if (decl_in_table == NULL)
02475   error ("unit `%s' in exclusion is not declared", names [i]);
02476       else if (decl_in_table->mode != dm_unit)
02477   error ("`%s' in exclusion is not unit", names [i]);
02478       else
02479   {
02480     new_el = create_node (sizeof (struct unit_set_el));
02481     new_el->unit_decl = DECL_UNIT (decl_in_table);
02482     new_el->next_unit_set_el = NULL;
02483     if (last_el == NULL)
02484       el_list = last_el = new_el;
02485     else
02486       {
02487         last_el->next_unit_set_el = new_el;
02488         last_el = last_el->next_unit_set_el;
02489       }
02490   }
02491     }
02492   return el_list;
02493 }
02494 
02495 /* The function adds each element from SOURCE_LIST to the exclusion
02496    list of the each element from DEST_LIST.  Checking situation "unit
02497    excludes itself".  */
02498 static void
02499 add_excls (unit_set_el_t dest_list, unit_set_el_t source_list,
02500      pos_t excl_pos ATTRIBUTE_UNUSED)
02501 {
02502   unit_set_el_t dst;
02503   unit_set_el_t src;
02504   unit_set_el_t curr_el;
02505   unit_set_el_t prev_el;
02506   unit_set_el_t copy;
02507 
02508   for (dst = dest_list; dst != NULL; dst = dst->next_unit_set_el)
02509     for (src = source_list; src != NULL; src = src->next_unit_set_el)
02510       {
02511   if (dst->unit_decl == src->unit_decl)
02512     {
02513       error ("unit `%s' excludes itself", src->unit_decl->name);
02514       continue;
02515     }
02516   if (dst->unit_decl->automaton_name != NULL
02517       && src->unit_decl->automaton_name != NULL
02518       && strcmp (dst->unit_decl->automaton_name,
02519            src->unit_decl->automaton_name) != 0)
02520     {
02521       error ("units `%s' and `%s' in exclusion set belong to different automata",
02522        src->unit_decl->name, dst->unit_decl->name);
02523       continue;
02524     }
02525   for (curr_el = dst->unit_decl->excl_list, prev_el = NULL;
02526        curr_el != NULL;
02527        prev_el = curr_el, curr_el = curr_el->next_unit_set_el)
02528     if (curr_el->unit_decl == src->unit_decl)
02529       break;
02530   if (curr_el == NULL)
02531     {
02532       /* Element not found - insert.  */
02533       copy = copy_node (src, sizeof (*src));
02534       copy->next_unit_set_el = NULL;
02535       if (prev_el == NULL)
02536         dst->unit_decl->excl_list = copy;
02537       else
02538         prev_el->next_unit_set_el = copy;
02539   }
02540     }
02541 }
02542 
02543 /* Checking NAMES in presence/absence clause and returning the
02544    formed unit_set_el_list.  The function is called only after
02545    processing all exclusion sets.  */
02546 static unit_set_el_t
02547 process_presence_absence_names (char **names, int num,
02548         pos_t req_pos ATTRIBUTE_UNUSED,
02549         int presence_p, int final_p)
02550 {
02551   unit_set_el_t el_list;
02552   unit_set_el_t last_el;
02553   unit_set_el_t new_el;
02554   decl_t decl_in_table;
02555   int i;
02556 
02557   el_list = NULL;
02558   last_el = NULL;
02559   for (i = 0; i < num; i++)
02560     {
02561       decl_in_table = find_decl (names [i]);
02562       if (decl_in_table == NULL)
02563   error ((presence_p
02564     ? (final_p
02565        ? "unit `%s' in final presence set is not declared"
02566        : "unit `%s' in presence set is not declared")
02567     : (final_p
02568        ? "unit `%s' in final absence set is not declared"
02569        : "unit `%s' in absence set is not declared")), names [i]);
02570       else if (decl_in_table->mode != dm_unit)
02571   error ((presence_p
02572     ? (final_p
02573        ? "`%s' in final presence set is not unit"
02574        : "`%s' in presence set is not unit")
02575     : (final_p
02576        ? "`%s' in final absence set is not unit"
02577        : "`%s' in absence set is not unit")), names [i]);
02578       else
02579   {
02580     new_el = create_node (sizeof (struct unit_set_el));
02581     new_el->unit_decl = DECL_UNIT (decl_in_table);
02582     new_el->next_unit_set_el = NULL;
02583     if (last_el == NULL)
02584       el_list = last_el = new_el;
02585     else
02586       {
02587         last_el->next_unit_set_el = new_el;
02588         last_el = last_el->next_unit_set_el;
02589       }
02590   }
02591     }
02592   return el_list;
02593 }
02594 
02595 /* Checking NAMES in patterns of a presence/absence clause and
02596    returning the formed pattern_set_el_list.  The function is called
02597    only after processing all exclusion sets.  */
02598 static pattern_set_el_t
02599 process_presence_absence_patterns (char ***patterns, int num,
02600            pos_t req_pos ATTRIBUTE_UNUSED,
02601            int presence_p, int final_p)
02602 {
02603   pattern_set_el_t el_list;
02604   pattern_set_el_t last_el;
02605   pattern_set_el_t new_el;
02606   decl_t decl_in_table;
02607   int i, j;
02608 
02609   el_list = NULL;
02610   last_el = NULL;
02611   for (i = 0; i < num; i++)
02612     {
02613       for (j = 0; patterns [i] [j] != NULL; j++)
02614   ;
02615       new_el = create_node (sizeof (struct pattern_set_el)
02616           + sizeof (struct unit_decl *) * j);
02617       new_el->unit_decls
02618   = (struct unit_decl **) ((char *) new_el
02619          + sizeof (struct pattern_set_el));
02620       new_el->next_pattern_set_el = NULL;
02621       if (last_el == NULL)
02622   el_list = last_el = new_el;
02623       else
02624   {
02625     last_el->next_pattern_set_el = new_el;
02626     last_el = last_el->next_pattern_set_el;
02627   }
02628       new_el->units_num = 0;
02629       for (j = 0; patterns [i] [j] != NULL; j++)
02630   {
02631     decl_in_table = find_decl (patterns [i] [j]);
02632     if (decl_in_table == NULL)
02633       error ((presence_p
02634         ? (final_p
02635            ? "unit `%s' in final presence set is not declared"
02636            : "unit `%s' in presence set is not declared")
02637         : (final_p
02638            ? "unit `%s' in final absence set is not declared"
02639            : "unit `%s' in absence set is not declared")),
02640        patterns [i] [j]);
02641     else if (decl_in_table->mode != dm_unit)
02642       error ((presence_p
02643         ? (final_p
02644            ? "`%s' in final presence set is not unit"
02645            : "`%s' in presence set is not unit")
02646         : (final_p
02647            ? "`%s' in final absence set is not unit"
02648            : "`%s' in absence set is not unit")),
02649        patterns [i] [j]);
02650     else
02651       {
02652         new_el->unit_decls [new_el->units_num]
02653     = DECL_UNIT (decl_in_table);
02654         new_el->units_num++;
02655       }
02656   }
02657     }
02658   return el_list;
02659 }
02660 
02661 /* The function adds each element from PATTERN_LIST to presence (if
02662    PRESENCE_P) or absence list of the each element from DEST_LIST.
02663    Checking situations "unit requires own absence", and "unit excludes
02664    and requires presence of ...", "unit requires absence and presence
02665    of ...", "units in (final) presence set belong to different
02666    automata", and "units in (final) absence set belong to different
02667    automata".  Remember that we process absence sets only after all
02668    presence sets.  */
02669 static void
02670 add_presence_absence (unit_set_el_t dest_list,
02671           pattern_set_el_t pattern_list,
02672           pos_t req_pos ATTRIBUTE_UNUSED,
02673           int presence_p, int final_p)
02674 {
02675   unit_set_el_t dst;
02676   pattern_set_el_t pat;
02677   struct unit_decl *unit;
02678   unit_set_el_t curr_excl_el;
02679   pattern_set_el_t curr_pat_el;
02680   pattern_set_el_t prev_el;
02681   pattern_set_el_t copy;
02682   int i;
02683   int no_error_flag;
02684 
02685   for (dst = dest_list; dst != NULL; dst = dst->next_unit_set_el)
02686     for (pat = pattern_list; pat != NULL; pat = pat->next_pattern_set_el)
02687       {
02688   for (i = 0; i < pat->units_num; i++)
02689     {
02690       unit = pat->unit_decls [i];
02691       if (dst->unit_decl == unit && pat->units_num == 1 && !presence_p)
02692         {
02693     error ("unit `%s' requires own absence", unit->name);
02694     continue;
02695         }
02696       if (dst->unit_decl->automaton_name != NULL
02697     && unit->automaton_name != NULL
02698     && strcmp (dst->unit_decl->automaton_name,
02699          unit->automaton_name) != 0)
02700         {
02701     error ((presence_p
02702       ? (final_p
02703          ? "units `%s' and `%s' in final presence set belong to different automata"
02704          : "units `%s' and `%s' in presence set belong to different automata")
02705       : (final_p
02706          ? "units `%s' and `%s' in final absence set belong to different automata"
02707          : "units `%s' and `%s' in absence set belong to different automata")),
02708            unit->name, dst->unit_decl->name);
02709     continue;
02710         }
02711       no_error_flag = 1;
02712       if (presence_p)
02713         for (curr_excl_el = dst->unit_decl->excl_list;
02714        curr_excl_el != NULL;
02715        curr_excl_el = curr_excl_el->next_unit_set_el)
02716     {
02717       if (unit == curr_excl_el->unit_decl && pat->units_num == 1)
02718         {
02719           if (!w_flag)
02720       {
02721         error ("unit `%s' excludes and requires presence of `%s'",
02722          dst->unit_decl->name, unit->name);
02723         no_error_flag = 0;
02724       }
02725           else
02726       warning
02727         ("unit `%s' excludes and requires presence of `%s'",
02728          dst->unit_decl->name, unit->name);
02729         }
02730     }
02731       else if (pat->units_num == 1)
02732         for (curr_pat_el = dst->unit_decl->presence_list;
02733        curr_pat_el != NULL;
02734        curr_pat_el = curr_pat_el->next_pattern_set_el)
02735     if (curr_pat_el->units_num == 1
02736         && unit == curr_pat_el->unit_decls [0])
02737       {
02738         if (!w_flag)
02739           {
02740       error
02741         ("unit `%s' requires absence and presence of `%s'",
02742          dst->unit_decl->name, unit->name);
02743       no_error_flag = 0;
02744           }
02745         else
02746           warning
02747       ("unit `%s' requires absence and presence of `%s'",
02748        dst->unit_decl->name, unit->name);
02749       }
02750       if (no_error_flag)
02751         {
02752     for (prev_el = (presence_p
02753         ? (final_p
02754            ? dst->unit_decl->final_presence_list
02755            : dst->unit_decl->final_presence_list)
02756         : (final_p
02757            ? dst->unit_decl->final_absence_list
02758            : dst->unit_decl->absence_list));
02759          prev_el != NULL && prev_el->next_pattern_set_el != NULL;
02760          prev_el = prev_el->next_pattern_set_el)
02761       ;
02762     copy = copy_node (pat, sizeof (*pat));
02763     copy->next_pattern_set_el = NULL;
02764     if (prev_el == NULL)
02765       {
02766         if (presence_p)
02767           {
02768       if (final_p)
02769         dst->unit_decl->final_presence_list = copy;
02770       else
02771         dst->unit_decl->presence_list = copy;
02772           }
02773         else if (final_p)
02774           dst->unit_decl->final_absence_list = copy;
02775         else
02776           dst->unit_decl->absence_list = copy;
02777       }
02778     else
02779       prev_el->next_pattern_set_el = copy;
02780         }
02781     }
02782       }
02783 }
02784 
02785 
02786 /* The function searches for bypass with given IN_INSN_RESERV in given
02787    BYPASS_LIST.  */
02788 static struct bypass_decl *
02789 find_bypass (struct bypass_decl *bypass_list,
02790        struct insn_reserv_decl *in_insn_reserv)
02791 {
02792   struct bypass_decl *bypass;
02793 
02794   for (bypass = bypass_list; bypass != NULL; bypass = bypass->next)
02795     if (bypass->in_insn_reserv == in_insn_reserv)
02796       break;
02797   return bypass;
02798 }
02799 
02800 /* The function processes pipeline description declarations, checks
02801    their correctness, and forms exclusion/presence/absence sets.  */
02802 static void
02803 process_decls (void)
02804 {
02805   decl_t decl;
02806   decl_t automaton_decl;
02807   decl_t decl_in_table;
02808   decl_t out_insn_reserv;
02809   decl_t in_insn_reserv;
02810   struct bypass_decl *bypass;
02811   int automaton_presence;
02812   int i;
02813 
02814   /* Checking repeated automata declarations.  */
02815   automaton_presence = 0;
02816   for (i = 0; i < description->decls_num; i++)
02817     {
02818       decl = description->decls [i];
02819       if (decl->mode == dm_automaton)
02820   {
02821     automaton_presence = 1;
02822     decl_in_table = insert_automaton_decl (decl);
02823     if (decl_in_table != decl)
02824       {
02825         if (!w_flag)
02826     error ("repeated declaration of automaton `%s'",
02827            DECL_AUTOMATON (decl)->name);
02828         else
02829     warning ("repeated declaration of automaton `%s'",
02830        DECL_AUTOMATON (decl)->name);
02831       }
02832   }
02833     }
02834   /* Checking undeclared automata, repeated declarations (except for
02835      automata) and correctness of their attributes (insn latency times
02836      etc.).  */
02837   for (i = 0; i < description->decls_num; i++)
02838     {
02839       decl = description->decls [i];
02840       if (decl->mode == dm_insn_reserv)
02841   {
02842           DECL_INSN_RESERV (decl)->condexp
02843       = check_attr_test (DECL_INSN_RESERV (decl)->condexp, 0, 0);
02844     if (DECL_INSN_RESERV (decl)->default_latency < 0)
02845       error ("define_insn_reservation `%s' has negative latency time",
02846        DECL_INSN_RESERV (decl)->name);
02847     DECL_INSN_RESERV (decl)->insn_num = description->insns_num;
02848     description->insns_num++;
02849     decl_in_table = insert_insn_decl (decl);
02850     if (decl_in_table != decl)
02851       error ("`%s' is already used as insn reservation name",
02852        DECL_INSN_RESERV (decl)->name);
02853   }
02854       else if (decl->mode == dm_bypass)
02855   {
02856     if (DECL_BYPASS (decl)->latency < 0)
02857       error ("define_bypass `%s - %s' has negative latency time",
02858        DECL_BYPASS (decl)->out_insn_name,
02859        DECL_BYPASS (decl)->in_insn_name);
02860   }
02861       else if (decl->mode == dm_unit || decl->mode == dm_reserv)
02862   {
02863     if (decl->mode == dm_unit)
02864       {
02865         DECL_UNIT (decl)->automaton_decl = NULL;
02866         if (DECL_UNIT (decl)->automaton_name != NULL)
02867     {
02868       automaton_decl
02869                     = find_automaton_decl (DECL_UNIT (decl)->automaton_name);
02870       if (automaton_decl == NULL)
02871         error ("automaton `%s' is not declared",
02872          DECL_UNIT (decl)->automaton_name);
02873       else
02874         {
02875           DECL_AUTOMATON (automaton_decl)->automaton_is_used = 1;
02876           DECL_UNIT (decl)->automaton_decl
02877       = DECL_AUTOMATON (automaton_decl);
02878         }
02879     }
02880         else if (automaton_presence)
02881     error ("define_unit `%s' without automaton when one defined",
02882            DECL_UNIT (decl)->name);
02883         DECL_UNIT (decl)->unit_num = description->units_num;
02884         description->units_num++;
02885         if (strcmp (DECL_UNIT (decl)->name, NOTHING_NAME) == 0)
02886     {
02887       error ("`%s' is declared as cpu unit", NOTHING_NAME);
02888       continue;
02889     }
02890         decl_in_table = find_decl (DECL_UNIT (decl)->name);
02891       }
02892     else
02893       {
02894         if (strcmp (DECL_RESERV (decl)->name, NOTHING_NAME) == 0)
02895     {
02896       error ("`%s' is declared as cpu reservation", NOTHING_NAME);
02897       continue;
02898     }
02899         decl_in_table = find_decl (DECL_RESERV (decl)->name);
02900       }
02901     if (decl_in_table == NULL)
02902       decl_in_table = insert_decl (decl);
02903     else
02904       {
02905         if (decl->mode == dm_unit)
02906     error ("repeated declaration of unit `%s'",
02907            DECL_UNIT (decl)->name);
02908         else
02909     error ("repeated declaration of reservation `%s'",
02910            DECL_RESERV (decl)->name);
02911       }
02912   }
02913     }
02914   /* Check bypasses and form list of bypasses for each (output)
02915      insn.  */
02916   for (i = 0; i < description->decls_num; i++)
02917     {
02918       decl = description->decls [i];
02919       if (decl->mode == dm_bypass)
02920   {
02921     out_insn_reserv = find_insn_decl (DECL_BYPASS (decl)->out_insn_name);
02922     in_insn_reserv = find_insn_decl (DECL_BYPASS (decl)->in_insn_name);
02923     if (out_insn_reserv == NULL)
02924       error ("there is no insn reservation `%s'",
02925        DECL_BYPASS (decl)->out_insn_name);
02926     else if (in_insn_reserv == NULL)
02927       error ("there is no insn reservation `%s'",
02928        DECL_BYPASS (decl)->in_insn_name);
02929     else
02930       {
02931         DECL_BYPASS (decl)->out_insn_reserv
02932     = DECL_INSN_RESERV (out_insn_reserv);
02933         DECL_BYPASS (decl)->in_insn_reserv
02934     = DECL_INSN_RESERV (in_insn_reserv);
02935         bypass
02936     = find_bypass (DECL_INSN_RESERV (out_insn_reserv)->bypass_list,
02937              DECL_BYPASS (decl)->in_insn_reserv);
02938         if (bypass != NULL)
02939     {
02940       if (DECL_BYPASS (decl)->latency == bypass->latency)
02941         {
02942           if (!w_flag)
02943       error
02944         ("the same bypass `%s - %s' is already defined",
02945          DECL_BYPASS (decl)->out_insn_name,
02946          DECL_BYPASS (decl)->in_insn_name);
02947           else
02948       warning
02949         ("the same bypass `%s - %s' is already defined",
02950          DECL_BYPASS (decl)->out_insn_name,
02951          DECL_BYPASS (decl)->in_insn_name);
02952         }
02953       else
02954         error ("bypass `%s - %s' is already defined",
02955          DECL_BYPASS (decl)->out_insn_name,
02956          DECL_BYPASS (decl)->in_insn_name);
02957     }
02958         else
02959     {
02960       DECL_BYPASS (decl)->next
02961         = DECL_INSN_RESERV (out_insn_reserv)->bypass_list;
02962       DECL_INSN_RESERV (out_insn_reserv)->bypass_list
02963         = DECL_BYPASS (decl);
02964     }
02965       }
02966   }
02967     }
02968 
02969   /* Check exclusion set declarations and form exclusion sets.  */
02970   for (i = 0; i < description->decls_num; i++)
02971     {
02972       decl = description->decls [i];
02973       if (decl->mode == dm_excl)
02974   {
02975     unit_set_el_t unit_set_el_list;
02976     unit_set_el_t unit_set_el_list_2;
02977 
02978     unit_set_el_list
02979             = process_excls (DECL_EXCL (decl)->names,
02980            DECL_EXCL (decl)->first_list_length, decl->pos);
02981     unit_set_el_list_2
02982       = process_excls (&DECL_EXCL (decl)->names
02983            [DECL_EXCL (decl)->first_list_length],
02984                              DECL_EXCL (decl)->all_names_num
02985                              - DECL_EXCL (decl)->first_list_length,
02986                              decl->pos);
02987     add_excls (unit_set_el_list, unit_set_el_list_2, decl->pos);
02988     add_excls (unit_set_el_list_2, unit_set_el_list, decl->pos);
02989   }
02990     }
02991 
02992   /* Check presence set declarations and form presence sets.  */
02993   for (i = 0; i < description->decls_num; i++)
02994     {
02995       decl = description->decls [i];
02996       if (decl->mode == dm_presence)
02997   {
02998     unit_set_el_t unit_set_el_list;
02999     pattern_set_el_t pattern_set_el_list;
03000 
03001     unit_set_el_list
03002             = process_presence_absence_names
03003         (DECL_PRESENCE (decl)->names, DECL_PRESENCE (decl)->names_num,
03004          decl->pos, TRUE, DECL_PRESENCE (decl)->final_p);
03005     pattern_set_el_list
03006       = process_presence_absence_patterns
03007         (DECL_PRESENCE (decl)->patterns,
03008          DECL_PRESENCE (decl)->patterns_num,
03009          decl->pos, TRUE, DECL_PRESENCE (decl)->final_p);
03010     add_presence_absence (unit_set_el_list, pattern_set_el_list,
03011         decl->pos, TRUE,
03012         DECL_PRESENCE (decl)->final_p);
03013   }
03014     }
03015 
03016   /* Check absence set declarations and form absence sets.  */
03017   for (i = 0; i < description->decls_num; i++)
03018     {
03019       decl = description->decls [i];
03020       if (decl->mode == dm_absence)
03021   {
03022     unit_set_el_t unit_set_el_list;
03023     pattern_set_el_t pattern_set_el_list;
03024 
03025     unit_set_el_list
03026             = process_presence_absence_names
03027         (DECL_ABSENCE (decl)->names, DECL_ABSENCE (decl)->names_num,
03028          decl->pos, FALSE, DECL_ABSENCE (decl)->final_p);
03029     pattern_set_el_list
03030       = process_presence_absence_patterns
03031         (DECL_ABSENCE (decl)->patterns,
03032          DECL_ABSENCE (decl)->patterns_num,
03033          decl->pos, FALSE, DECL_ABSENCE (decl)->final_p);
03034     add_presence_absence (unit_set_el_list, pattern_set_el_list,
03035         decl->pos, FALSE,
03036         DECL_ABSENCE (decl)->final_p);
03037   }
03038     }
03039 }
03040 
03041 /* The following function checks that declared automaton is used.  If
03042    the automaton is not used, the function fixes error/warning.  The
03043    following function must be called only after `process_decls'.  */
03044 static void
03045 check_automaton_usage (void)
03046 {
03047   decl_t decl;
03048   int i;
03049 
03050   for (i = 0; i < description->decls_num; i++)
03051     {
03052       decl = description->decls [i];
03053       if (decl->mode == dm_automaton
03054     && !DECL_AUTOMATON (decl)->automaton_is_used)
03055   {
03056     if (!w_flag)
03057       error ("automaton `%s' is not used", DECL_AUTOMATON (decl)->name);
03058     else
03059       warning ("automaton `%s' is not used",
03060          DECL_AUTOMATON (decl)->name);
03061   }
03062     }
03063 }
03064 
03065 /* The following recursive function processes all regexp in order to
03066    fix usage of units or reservations and to fix errors of undeclared
03067    name.  The function may change unit_regexp onto reserv_regexp.
03068    Remember that reserv_regexp does not exist before the function
03069    call.  */
03070 static regexp_t
03071 process_regexp (regexp_t regexp)
03072 {
03073   decl_t decl_in_table;
03074   regexp_t new_regexp;
03075   int i;
03076 
03077   switch (regexp->mode)
03078     {
03079     case rm_unit:
03080       decl_in_table = find_decl (REGEXP_UNIT (regexp)->name);
03081       if (decl_in_table == NULL)
03082         error ("undeclared unit or reservation `%s'",
03083          REGEXP_UNIT (regexp)->name);
03084       else
03085   switch (decl_in_table->mode)
03086     {
03087     case dm_unit:
03088       DECL_UNIT (decl_in_table)->unit_is_used = 1;
03089       REGEXP_UNIT (regexp)->unit_decl = DECL_UNIT (decl_in_table);
03090       break;
03091 
03092     case dm_reserv:
03093       DECL_RESERV (decl_in_table)->reserv_is_used = 1;
03094       new_regexp = create_node (sizeof (struct regexp));
03095       new_regexp->mode = rm_reserv;
03096       new_regexp->pos = regexp->pos;
03097       REGEXP_RESERV (new_regexp)->name = REGEXP_UNIT (regexp)->name;
03098       REGEXP_RESERV (new_regexp)->reserv_decl
03099         = DECL_RESERV (decl_in_table);
03100       regexp = new_regexp;
03101       break;
03102 
03103     default:
03104       gcc_unreachable ();
03105   }
03106       break;
03107     case rm_sequence:
03108       for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
03109   REGEXP_SEQUENCE (regexp)->regexps [i]
03110     = process_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
03111       break;
03112     case rm_allof:
03113       for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
03114   REGEXP_ALLOF (regexp)->regexps [i]
03115     = process_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
03116       break;
03117     case rm_oneof:
03118       for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
03119   REGEXP_ONEOF (regexp)->regexps [i]
03120     = process_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
03121       break;
03122     case rm_repeat:
03123       REGEXP_REPEAT (regexp)->regexp
03124   = process_regexp (REGEXP_REPEAT (regexp)->regexp);
03125       break;
03126     case rm_nothing:
03127       break;
03128     default:
03129       gcc_unreachable ();
03130     }
03131   return regexp;
03132 }
03133 
03134 /* The following function processes regexp of define_reservation and
03135    define_insn_reservation with the aid of function
03136    `process_regexp'.  */
03137 static void
03138 process_regexp_decls (void)
03139 {
03140   decl_t decl;
03141   int i;
03142 
03143   for (i = 0; i < description->decls_num; i++)
03144     {
03145       decl = description->decls [i];
03146       if (decl->mode == dm_reserv)
03147   DECL_RESERV (decl)->regexp
03148     = process_regexp (DECL_RESERV (decl)->regexp);
03149       else if (decl->mode == dm_insn_reserv)
03150   DECL_INSN_RESERV (decl)->regexp
03151     = process_regexp (DECL_INSN_RESERV (decl)->regexp);
03152     }
03153 }
03154 
03155 /* The following function checks that declared unit is used.  If the
03156    unit is not used, the function fixes errors/warnings.  The
03157    following function must be called only after `process_decls',
03158    `process_regexp_decls'.  */
03159 static void
03160 check_usage (void)
03161 {
03162   decl_t decl;
03163   int i;
03164 
03165   for (i = 0; i < description->decls_num; i++)
03166     {
03167       decl = description->decls [i];
03168       if (decl->mode == dm_unit && !DECL_UNIT (decl)->unit_is_used)
03169   {
03170     if (!w_flag)
03171       error ("unit `%s' is not used", DECL_UNIT (decl)->name);
03172     else
03173       warning ("unit `%s' is not used", DECL_UNIT (decl)->name);
03174   }
03175       else if (decl->mode == dm_reserv && !DECL_RESERV (decl)->reserv_is_used)
03176   {
03177     if (!w_flag)
03178       error ("reservation `%s' is not used", DECL_RESERV (decl)->name);
03179     else
03180       warning ("reservation `%s' is not used", DECL_RESERV (decl)->name);
03181   }
03182     }
03183 }
03184 
03185 /* The following variable value is number of reservation being
03186    processed on loop recognition.  */
03187 static int curr_loop_pass_num;
03188 
03189 /* The following recursive function returns nonzero value if REGEXP
03190    contains given decl or reservations in given regexp refers for
03191    given decl.  */
03192 static int
03193 loop_in_regexp (regexp_t regexp, decl_t start_decl)
03194 {
03195   int i;
03196 
03197   if (regexp == NULL)
03198     return 0;
03199   switch (regexp->mode)
03200     {
03201       case rm_unit:
03202   return 0;
03203 
03204     case rm_reserv:
03205       if (start_decl->mode == dm_reserv
03206           && REGEXP_RESERV (regexp)->reserv_decl == DECL_RESERV (start_decl))
03207         return 1;
03208       else if (REGEXP_RESERV (regexp)->reserv_decl->loop_pass_num
03209          == curr_loop_pass_num)
03210         /* declaration has been processed.  */
03211         return 0;
03212       else
03213         {
03214     REGEXP_RESERV (regexp)->reserv_decl->loop_pass_num
03215             = curr_loop_pass_num;
03216           return loop_in_regexp (REGEXP_RESERV (regexp)->reserv_decl->regexp,
03217                                  start_decl);
03218         }
03219 
03220     case rm_sequence:
03221       for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
03222   if (loop_in_regexp (REGEXP_SEQUENCE (regexp)->regexps [i], start_decl))
03223     return 1;
03224       return 0;
03225 
03226     case rm_allof:
03227       for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
03228   if (loop_in_regexp (REGEXP_ALLOF (regexp)->regexps [i], start_decl))
03229     return 1;
03230       return 0;
03231 
03232     case rm_oneof:
03233       for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
03234   if (loop_in_regexp (REGEXP_ONEOF (regexp)->regexps [i], start_decl))
03235     return 1;
03236       return 0;
03237 
03238     case rm_repeat:
03239       return loop_in_regexp (REGEXP_REPEAT (regexp)->regexp, start_decl);
03240 
03241     case rm_nothing:
03242       return 0;
03243 
03244     default:
03245       gcc_unreachable ();
03246     }
03247 }
03248 
03249 /* The following function fixes errors "cycle in definition ...".  The
03250    function uses function `loop_in_regexp' for that.  */
03251 static void
03252 check_loops_in_regexps (void)
03253 {
03254   decl_t decl;
03255   int i;
03256 
03257   for (i = 0; i < description->decls_num; i++)
03258     {
03259       decl = description->decls [i];
03260       if (decl->mode == dm_reserv)
03261   DECL_RESERV (decl)->loop_pass_num = 0;
03262     }
03263   for (i = 0; i < description->decls_num; i++)
03264     {
03265       decl = description->decls [i];
03266       curr_loop_pass_num = i;
03267 
03268       if (decl->mode == dm_reserv)
03269     {
03270       DECL_RESERV (decl)->loop_pass_num = curr_loop_pass_num;
03271       if (loop_in_regexp (DECL_RESERV (decl)->regexp, decl))
03272         {
03273     gcc_assert (DECL_RESERV (decl)->regexp);
03274     error ("cycle in definition of reservation `%s'",
03275            DECL_RESERV (decl)->name);
03276         }
03277     }
03278     }
03279 }
03280 
03281 /* The function recursively processes IR of reservation and defines
03282    max and min cycle for reservation of unit.  */
03283 static void
03284 process_regexp_cycles (regexp_t regexp, int max_start_cycle,
03285            int min_start_cycle, int *max_finish_cycle,
03286            int *min_finish_cycle)
03287 {
03288   int i;
03289 
03290   switch (regexp->mode)
03291     {
03292     case rm_unit:
03293       if (REGEXP_UNIT (regexp)->unit_decl->max_occ_cycle_num < max_start_cycle)
03294   REGEXP_UNIT (regexp)->unit_decl->max_occ_cycle_num = max_start_cycle;
03295       if (REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num > min_start_cycle
03296     || REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num == -1)
03297   REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num = min_start_cycle;
03298       *max_finish_cycle = max_start_cycle;
03299       *min_finish_cycle = min_start_cycle;
03300       break;
03301 
03302     case rm_reserv:
03303       process_regexp_cycles (REGEXP_RESERV (regexp)->reserv_decl->regexp,
03304            max_start_cycle, min_start_cycle,
03305            max_finish_cycle, min_finish_cycle);
03306       break;
03307 
03308     case rm_repeat:
03309       for (i = 0; i < REGEXP_REPEAT (regexp)->repeat_num; i++)
03310   {
03311     process_regexp_cycles (REGEXP_REPEAT (regexp)->regexp,
03312          max_start_cycle, min_start_cycle,
03313          max_finish_cycle, min_finish_cycle);
03314     max_start_cycle = *max_finish_cycle + 1;
03315     min_start_cycle = *min_finish_cycle + 1;
03316   }
03317       break;
03318 
03319     case rm_sequence:
03320       for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
03321   {
03322     process_regexp_cycles (REGEXP_SEQUENCE (regexp)->regexps [i],
03323          max_start_cycle, min_start_cycle,
03324          max_finish_cycle, min_finish_cycle);
03325     max_start_cycle = *max_finish_cycle + 1;
03326     min_start_cycle = *min_finish_cycle + 1;
03327   }
03328       break;
03329 
03330     case rm_allof:
03331       {
03332   int max_cycle = 0;
03333   int min_cycle = 0;
03334   
03335   for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
03336     {
03337       process_regexp_cycles (REGEXP_ALLOF (regexp)->regexps [i],
03338            max_start_cycle, min_start_cycle,
03339            max_finish_cycle, min_finish_cycle);
03340       if (max_cycle < *max_finish_cycle)
03341         max_cycle = *max_finish_cycle;
03342       if (i == 0 || min_cycle > *min_finish_cycle)
03343         min_cycle = *min_finish_cycle;
03344     }
03345   *max_finish_cycle = max_cycle;
03346   *min_finish_cycle = min_cycle;
03347       }
03348       break;
03349 
03350     case rm_oneof:
03351       {
03352   int max_cycle = 0;
03353   int min_cycle = 0;
03354   
03355   for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
03356     {
03357       process_regexp_cycles (REGEXP_ONEOF (regexp)->regexps [i],
03358            max_start_cycle, min_start_cycle,
03359            max_finish_cycle, min_finish_cycle);
03360       if (max_cycle < *max_finish_cycle)
03361         max_cycle = *max_finish_cycle;
03362       if (i == 0 || min_cycle > *min_finish_cycle)
03363         min_cycle = *min_finish_cycle;
03364     }
03365   *max_finish_cycle = max_cycle;
03366   *min_finish_cycle = min_cycle;
03367       }
03368       break;
03369 
03370     case rm_nothing:
03371       *max_finish_cycle = max_start_cycle;
03372       *min_finish_cycle = min_start_cycle;
03373       break;
03374 
03375     default:
03376       gcc_unreachable ();
03377     }
03378 }
03379 
03380 /* The following function is called only for correct program.  The
03381    function defines max reservation of insns in cycles.  */
03382 static void
03383 evaluate_max_reserv_cycles (void)
03384 {
03385   int max_insn_cycles_num;
03386   int min_insn_cycles_num;
03387   decl_t decl;
03388   int i;
03389 
03390   description->max_insn_reserv_cycles = 0;
03391   for (i = 0; i < description->decls_num; i++)
03392     {
03393       decl = description->decls [i];
03394       if (decl->mode == dm_insn_reserv)
03395       {
03396         process_regexp_cycles (DECL_INSN_RESERV (decl)->regexp, 0, 0,
03397              &max_insn_cycles_num, &min_insn_cycles_num);
03398         if (description->max_insn_reserv_cycles < max_insn_cycles_num)
03399     description->max_insn_reserv_cycles = max_insn_cycles_num;
03400       }
03401     }
03402   description->max_insn_reserv_cycles++;
03403 }
03404 
03405 /* The following function calls functions for checking all
03406    description.  */
03407 static void
03408 check_all_description (void)
03409 {
03410   process_decls ();
03411   check_automaton_usage ();
03412   process_regexp_decls ();
03413   check_usage ();
03414   check_loops_in_regexps ();
03415   if (!have_error)
03416     evaluate_max_reserv_cycles ();
03417 }
03418 
03419 
03420 
03421 /* The page contains abstract data `ticker'.  This data is used to
03422    report time of different phases of building automata.  It is
03423    possibly to write a description for which automata will be built
03424    during several minutes even on fast machine.  */
03425 
03426 /* The following function creates ticker and makes it active.  */
03427 static ticker_t
03428 create_ticker (void)
03429 {
03430   ticker_t ticker;
03431 
03432   ticker.modified_creation_time = get_run_time ();
03433   ticker.incremented_off_time = 0;
03434   return ticker;
03435 }
03436 
03437 /* The following function switches off given ticker.  */
03438 static void
03439 ticker_off (ticker_t *ticker)
03440 {
03441   if (ticker->incremented_off_time == 0)
03442     ticker->incremented_off_time = get_run_time () + 1;
03443 }
03444 
03445 /* The following function switches on given ticker.  */
03446 static void
03447 ticker_on (ticker_t *ticker)
03448 {
03449   if (ticker->incremented_off_time != 0)
03450     {
03451       ticker->modified_creation_time
03452         += get_run_time () - ticker->incremented_off_time + 1;
03453       ticker->incremented_off_time = 0;
03454     }
03455 }
03456 
03457 /* The following function returns current time in milliseconds since
03458    the moment when given ticker was created.  */
03459 static int
03460 active_time (ticker_t ticker)
03461 {
03462   if (ticker.incremented_off_time != 0)
03463     return ticker.incremented_off_time - 1 - ticker.modified_creation_time;
03464   else
03465     return get_run_time () - ticker.modified_creation_time;
03466 }
03467 
03468 /* The following function returns string representation of active time
03469    of given ticker.  The result is string representation of seconds
03470    with accuracy of 1/100 second.  Only result of the last call of the
03471    function exists.  Therefore the following code is not correct
03472 
03473       printf ("parser time: %s\ngeneration time: %s\n",
03474               active_time_string (parser_ticker),
03475               active_time_string (generation_ticker));
03476 
03477    Correct code has to be the following
03478 
03479       printf ("parser time: %s\n", active_time_string (parser_ticker));
03480       printf ("generation time: %s\n",
03481               active_time_string (generation_ticker));
03482 
03483 */
03484 static void
03485 print_active_time (FILE *f, ticker_t ticker)
03486 {
03487   int msecs;
03488 
03489   msecs = active_time (ticker);
03490   fprintf (f, "%d.%06d", msecs / 1000000, msecs % 1000000);
03491 }
03492 
03493 
03494 
03495 /* The following variable value is number of automaton which are
03496    really being created.  This value is defined on the base of
03497    argument of option `-split'.  If the variable has zero value the
03498    number of automata is defined by the constructions `%automaton'.
03499    This case occurs when option `-split' is absent or has zero
03500    argument.  If constructions `define_automaton' is absent only one
03501    automaton is created.  */
03502 static int automata_num;
03503 
03504 /* The following variable values are times of
03505        o transformation of regular expressions
03506        o building NDFA (DFA if !ndfa_flag)
03507        o NDFA -> DFA   (simply the same automaton if !ndfa_flag)
03508        o DFA minimization
03509        o building insn equivalence classes
03510        o all previous ones
03511        o code output */
03512 static ticker_t transform_time;
03513 static ticker_t NDFA_time;
03514 static ticker_t NDFA_to_DFA_time;
03515 static ticker_t minimize_time;
03516 static ticker_t equiv_time;
03517 static ticker_t automaton_generation_time;
03518 static ticker_t output_time;
03519 
03520 /* The following variable values are times of
03521        all checking
03522        all generation
03523        all pipeline hazard translator work */
03524 static ticker_t check_time;
03525 static ticker_t generation_time;
03526 static ticker_t all_time;
03527 
03528 
03529 
03530 /* Pseudo insn decl which denotes advancing cycle.  */
03531 static decl_t advance_cycle_insn_decl;
03532 static void
03533 add_advance_cycle_insn_decl (void)
03534 {
03535   advance_cycle_insn_decl = create_node (sizeof (struct decl));
03536   advance_cycle_insn_decl->mode = dm_insn_reserv;
03537   advance_cycle_insn_decl->pos = no_pos;
03538   DECL_INSN_RESERV (advance_cycle_insn_decl)->regexp = NULL;
03539   DECL_INSN_RESERV (advance_cycle_insn_decl)->name = (char *) "$advance_cycle";
03540   DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num
03541     = description->insns_num;
03542   description->decls [description->decls_num] = advance_cycle_insn_decl;
03543   description->decls_num++;
03544   description->insns_num++;
03545   num_dfa_decls++;
03546 }
03547 
03548 
03549 /* Abstract data `alternative states' which represents
03550    nondeterministic nature of the description (see comments for
03551    structures alt_state and state).  */
03552 
03553 /* List of free states.  */
03554 static alt_state_t first_free_alt_state;
03555 
03556 #ifndef NDEBUG
03557 /* The following variables is maximal number of allocated nodes
03558    alt_state.  */
03559 static int allocated_alt_states_num = 0;
03560 #endif
03561 
03562 /* The following function returns free node alt_state.  It may be new
03563    allocated node or node freed earlier.  */
03564 static alt_state_t
03565 get_free_alt_state (void)
03566 {
03567   alt_state_t result;
03568 
03569   if (first_free_alt_state != NULL)
03570     {
03571       result = first_free_alt_state;
03572       first_free_alt_state = first_free_alt_state->next_alt_state;
03573     }
03574   else
03575     {
03576 #ifndef NDEBUG
03577       allocated_alt_states_num++;
03578 #endif
03579       result = create_node (sizeof (struct alt_state));
03580     }
03581   result->state = NULL;
03582   result->next_alt_state = NULL;
03583   result->next_sorted_alt_state = NULL;
03584   return result;
03585 }
03586 
03587 /* The function frees node ALT_STATE.  */
03588 static void
03589 free_alt_state (alt_state_t alt_state)
03590 {
03591   if (alt_state == NULL)
03592     return;
03593   alt_state->next_alt_state = first_free_alt_state;
03594   first_free_alt_state = alt_state;
03595 }
03596 
03597 /* The function frees list started with node ALT_STATE_LIST.  */
03598 static void
03599 free_alt_states (alt_state_t alt_states_list)
03600 {
03601   alt_state_t curr_alt_state;
03602   alt_state_t next_alt_state;
03603 
03604   for (curr_alt_state = alt_states_list;
03605        curr_alt_state != NULL;
03606        curr_alt_state = next_alt_state)
03607     {
03608       next_alt_state = curr_alt_state->next_alt_state;
03609       free_alt_state (curr_alt_state);
03610     }
03611 }
03612 
03613 /* The function compares unique numbers of alt states.  */
03614 static int
03615 alt_state_cmp (const void *alt_state_ptr_1, const void *alt_state_ptr_2)
03616 {
03617   if ((*(alt_state_t *) alt_state_ptr_1)->state->unique_num
03618       == (*(alt_state_t *) alt_state_ptr_2)->state->unique_num)
03619     return 0;
03620   else if ((*(alt_state_t *) alt_state_ptr_1)->state->unique_num
03621      < (*(alt_state_t *) alt_state_ptr_2)->state->unique_num)
03622     return -1;
03623   else
03624     return 1;
03625 }
03626 
03627 /* The function sorts ALT_STATES_LIST and removes duplicated alt
03628    states from the list.  The comparison key is alt state unique
03629    number.  */
03630 static alt_state_t
03631 uniq_sort_alt_states (alt_state_t alt_states_list)
03632 {
03633   alt_state_t curr_alt_state;
03634   vla_ptr_t alt_states;
03635   size_t i;
03636   size_t prev_unique_state_ind;
03637   alt_state_t result;
03638   alt_state_t *result_ptr;
03639 
03640   VLA_PTR_CREATE (alt_states, 150, "alt_states");
03641   for (curr_alt_state = alt_states_list;
03642        curr_alt_state != NULL;
03643        curr_alt_state = curr_alt_state->next_alt_state)
03644     VLA_PTR_ADD (alt_states, curr_alt_state);
03645   qsort (VLA_PTR_BEGIN (alt_states), VLA_PTR_LENGTH (alt_states),
03646    sizeof (alt_state_t), alt_state_cmp);
03647   if (VLA_PTR_LENGTH (alt_states) == 0)
03648     result = NULL;
03649   else
03650     {
03651       result_ptr = VLA_PTR_BEGIN (alt_states);
03652       prev_unique_state_ind = 0;
03653       for (i = 1; i < VLA_PTR_LENGTH (alt_states); i++)
03654         if (result_ptr [prev_unique_state_ind]->state != result_ptr [i]->state)
03655           {
03656             prev_unique_state_ind++;
03657             result_ptr [prev_unique_state_ind] = result_ptr [i];
03658           }
03659 #if 0
03660       for (i = prev_unique_state_ind + 1; i < VLA_PTR_LENGTH (alt_states); i++)
03661         free_alt_state (result_ptr [i]);
03662 #endif
03663       VLA_PTR_SHORTEN (alt_states, i - prev_unique_state_ind - 1);
03664       result_ptr = VLA_PTR_BEGIN (alt_states);
03665       for (i = 1; i < VLA_PTR_LENGTH (alt_states); i++)
03666         result_ptr [i - 1]->next_sorted_alt_state = result_ptr [i];
03667       result_ptr [i - 1]->next_sorted_alt_state = NULL;
03668       result = *result_ptr;
03669     }
03670   VLA_PTR_DELETE (alt_states);
03671   return result;
03672 }
03673 
03674 /* The function checks equality of alt state lists.  Remember that the
03675    lists must be already sorted by the previous function.  */
03676 static int
03677 alt_states_eq (alt_state_t alt_states_1, alt_state_t alt_states_2)
03678 {
03679   while (alt_states_1 != NULL && alt_states_2 != NULL
03680          && alt_state_cmp (&alt_states_1, &alt_states_2) == 0)
03681     {
03682       alt_states_1 = alt_states_1->next_sorted_alt_state;
03683       alt_states_2 = alt_states_2->next_sorted_alt_state;
03684     }
03685   return alt_states_1 == alt_states_2;
03686 }
03687 
03688 /* Initialization of the abstract data.  */
03689 static void
03690 initiate_alt_states (void)
03691 {
03692   first_free_alt_state = NULL;
03693 }
03694 
03695 /* Finishing work with the abstract data.  */
03696 static void
03697 finish_alt_states (void)
03698 {
03699 }
03700 
03701 
03702 
03703 /* The page contains macros for work with bits strings.  We could use
03704    standard gcc bitmap or sbitmap but it would result in difficulties
03705    of building canadian cross.  */
03706 
03707 /* Set bit number bitno in the bit string.  The macro is not side
03708    effect proof.  */
03709 #define SET_BIT(bitstring, bitno)           \
03710   (((char *) (bitstring)) [(bitno) / CHAR_BIT] |= 1 << (bitno) % CHAR_BIT)
03711 
03712 #define CLEAR_BIT(bitstring, bitno)           \
03713   (((char *) (bitstring)) [(bitno) / CHAR_BIT] &= ~(1 << (bitno) % CHAR_BIT))
03714 
03715 /* Test if bit number bitno in the bitstring is set.  The macro is not
03716    side effect proof.  */
03717 #define TEST_BIT(bitstring, bitno)                                        \
03718   (((char *) (bitstring)) [(bitno) / CHAR_BIT] >> (bitno) % CHAR_BIT & 1)
03719 
03720 
03721 
03722 /* This page contains abstract data `state'.  */
03723 
03724 /* Maximal length of reservations in cycles (>= 1).  */
03725 static int max_cycles_num;
03726 
03727 /* Number of set elements (see type set_el_t) needed for
03728    representation of one cycle reservation.  It is depended on units
03729    number.  */
03730 static int els_in_cycle_reserv;
03731 
03732 /* Number of set elements (see type set_el_t) needed for
03733    representation of maximal length reservation.  Deterministic
03734    reservation is stored as set (bit string) of length equal to the
03735    variable value * number of bits in set_el_t.  */
03736 static int els_in_reservs;
03737 
03738 /* VLA for representation of array of pointers to unit
03739    declarations.  */
03740 static vla_ptr_t units_container;
03741 
03742 /* The start address of the array.  */
03743 static unit_decl_t *units_array;
03744 
03745 /* Temporary reservation of maximal length.  */
03746 static reserv_sets_t temp_reserv;
03747 
03748 /* The state table itself is represented by the following variable.  */
03749 static htab_t state_table;
03750 
03751 /* VLA for representation of array of pointers to free nodes
03752    `state'.  */
03753 static vla_ptr_t free_states;
03754 
03755 static int curr_unique_state_num;
03756 
03757 #ifndef NDEBUG
03758 /* The following variables is maximal number of allocated nodes
03759    `state'.  */
03760 static int allocated_states_num = 0;
03761 #endif
03762 
03763 /* Allocate new reservation set.  */
03764 static reserv_sets_t
03765 alloc_empty_reserv_sets (void)
03766 {
03767   reserv_sets_t result;
03768 
03769   obstack_blank (&irp, els_in_reservs * sizeof (set_el_t));
03770   result = (reserv_sets_t) obstack_base (&irp);
03771   obstack_finish (&irp);
03772   memset (result, 0, els_in_reservs * sizeof (set_el_t));
03773   return result;
03774 }
03775 
03776 /* Hash value of reservation set.  */
03777 static unsigned
03778 reserv_sets_hash_value (reserv_sets_t reservs)
03779 {
03780   set_el_t hash_value;
03781   unsigned result;
03782   int reservs_num, i;
03783   set_el_t *reserv_ptr;
03784 
03785   hash_value = 0;
03786   reservs_num = els_in_reservs;
03787   reserv_ptr = reservs;
03788   i = 0;
03789   while (reservs_num != 0)
03790     {
03791       reservs_num--;
03792       hash_value += ((*reserv_ptr >> i)
03793          | (*reserv_ptr << (sizeof (set_el_t) * CHAR_BIT - i)));
03794       i++;
03795       if (i == sizeof (set_el_t) * CHAR_BIT)
03796   i = 0;
03797       reserv_ptr++;
03798     }
03799   if (sizeof (set_el_t) <= sizeof (unsigned))
03800     return hash_value;
03801   result = 0;
03802   for (i = sizeof (set_el_t); i > 0; i -= sizeof (unsigned) - 1)
03803     {
03804       result += (unsigned) hash_value;
03805       hash_value >>= (sizeof (unsigned) - 1) * CHAR_BIT;
03806     }
03807   return result;
03808 }
03809 
03810 /* Comparison of given reservation sets.  */
03811 static int
03812 reserv_sets_cmp (reserv_sets_t reservs_1, reserv_sets_t reservs_2)
03813 {
03814   int reservs_num;
03815   set_el_t *reserv_ptr_1;
03816   set_el_t *reserv_ptr_2;
03817 
03818   gcc_assert (reservs_1 && reservs_2);
03819   reservs_num = els_in_reservs;
03820   reserv_ptr_1 = reservs_1;
03821   reserv_ptr_2 = reservs_2;
03822   while (reservs_num != 0 && *reserv_ptr_1 == *reserv_ptr_2)
03823     {
03824       reservs_num--;
03825       reserv_ptr_1++;
03826       reserv_ptr_2++;
03827     }
03828   if (reservs_num == 0)
03829     return 0;
03830   else if (*reserv_ptr_1 < *reserv_ptr_2)
03831     return -1;
03832   else
03833     return 1;
03834 }
03835 
03836 /* The function checks equality of the reservation sets.  */
03837 static int
03838 reserv_sets_eq (reserv_sets_t reservs_1, reserv_sets_t reservs_2)
03839 {
03840   return reserv_sets_cmp (reservs_1, reservs_2) == 0;
03841 }
03842 
03843 /* Set up in the reservation set that unit with UNIT_NUM is used on
03844    CYCLE_NUM.  */
03845 static void
03846 set_unit_reserv (reserv_sets_t reservs, int cycle_num, int unit_num)
03847 {
03848   gcc_assert (cycle_num < max_cycles_num);
03849   SET_BIT (reservs, cycle_num * els_in_cycle_reserv
03850            * sizeof (set_el_t) * CHAR_BIT + unit_num);
03851 }
03852 
03853 /* Set up in the reservation set RESERVS that unit with UNIT_NUM is
03854    used on CYCLE_NUM.  */
03855 static int
03856 test_unit_reserv (reserv_sets_t reservs, int cycle_num, int unit_num)
03857 {
03858   gcc_assert (cycle_num < max_cycles_num);
03859   return TEST_BIT (reservs, cycle_num * els_in_cycle_reserv
03860        * sizeof (set_el_t) * CHAR_BIT + unit_num);
03861 }
03862 
03863 /* The function checks that the reservation set represents no one unit
03864    reservation.  */
03865 static int
03866 it_is_empty_reserv_sets (reserv_sets_t operand)
03867 {
03868   set_el_t *reserv_ptr;
03869   int reservs_num;
03870 
03871   gcc_assert (operand);
03872   for (reservs_num = els_in_reservs, reserv_ptr = operand;
03873        reservs_num != 0;
03874        reserv_ptr++, reservs_num--)
03875     if (*reserv_ptr != 0)
03876       return 0;
03877   return 1;
03878 }
03879 
03880 /* The function checks that the reservation sets are intersected,
03881    i.e. there is a unit reservation on a cycle in both reservation
03882    sets.  */
03883 static int
03884 reserv_sets_are_intersected (reserv_sets_t operand_1,
03885            reserv_sets_t operand_2)
03886 {
03887   set_el_t *el_ptr_1;
03888   set_el_t *el_ptr_2;
03889   set_el_t *cycle_ptr_1;
03890   set_el_t *cycle_ptr_2;
03891 
03892   gcc_assert (operand_1 && operand_2);
03893   for (el_ptr_1 = operand_1, el_ptr_2 = operand_2;
03894        el_ptr_1 < operand_1 + els_in_reservs;
03895        el_ptr_1++, el_ptr_2++)
03896     if (*el_ptr_1 & *el_ptr_2)
03897       return 1;
03898   reserv_sets_or (temp_reserv, operand_1, operand_2);
03899   for (cycle_ptr_1 = operand_1, cycle_ptr_2 = operand_2;
03900        cycle_ptr_1 < operand_1 + els_in_reservs;
03901        cycle_ptr_1 += els_in_cycle_reserv, cycle_ptr_2 += els_in_cycle_reserv)
03902     {
03903       for (el_ptr_1 = cycle_ptr_1, el_ptr_2 = get_excl_set (cycle_ptr_2);
03904      el_ptr_1 < cycle_ptr_1 + els_in_cycle_reserv;
03905      el_ptr_1++, el_ptr_2++)
03906   if (*el_ptr_1 & *el_ptr_2)
03907     return 1;
03908       if (!check_presence_pattern_sets (cycle_ptr_1, cycle_ptr_2, FALSE))
03909   return 1;
03910       if (!check_presence_pattern_sets (temp_reserv + (cycle_ptr_2
03911                    - operand_2),
03912           cycle_ptr_2, TRUE))
03913   return 1;
03914       if (!check_absence_pattern_sets (cycle_ptr_1, cycle_ptr_2, FALSE))
03915   return 1;
03916       if (!check_absence_pattern_sets (temp_reserv + (cycle_ptr_2 - operand_2),
03917                cycle_ptr_2, TRUE))
03918   return 1;
03919     }
03920   return 0;
03921 }
03922 
03923 /* The function sets up RESULT bits by bits of OPERAND shifted on one
03924    cpu cycle.  The remaining bits of OPERAND (representing the last
03925    cycle unit reservations) are not changed.  */
03926 static void
03927 reserv_sets_shift (reserv_sets_t result, reserv_sets_t operand)
03928 {
03929   int i;
03930 
03931   gcc_assert (result && operand && result != operand);
03932   for (i = els_in_cycle_reserv; i < els_in_reservs; i++)
03933     result [i - els_in_cycle_reserv] = operand [i];
03934 }
03935 
03936 /* OR of the reservation sets.  */
03937 static void
03938 reserv_sets_or (reserv_sets_t result, reserv_sets_t operand_1,
03939     reserv_sets_t operand_2)
03940 {
03941   set_el_t *el_ptr_1;
03942   set_el_t *el_ptr_2;
03943   set_el_t *result_set_el_ptr;
03944 
03945   gcc_assert (result && operand_1 && operand_2);
03946   for (el_ptr_1 = operand_1, el_ptr_2 = operand_2, result_set_el_ptr = result;
03947        el_ptr_1 < operand_1 + els_in_reservs;
03948        el_ptr_1++, el_ptr_2++, result_set_el_ptr++)
03949     *result_set_el_ptr = *el_ptr_1 | *el_ptr_2;
03950 }
03951 
03952 /* AND of the reservation sets.  */
03953 static void
03954 reserv_sets_and (reserv_sets_t result, reserv_sets_t operand_1,
03955     reserv_sets_t operand_2)
03956 {
03957   set_el_t *el_ptr_1;
03958   set_el_t *el_ptr_2;
03959   set_el_t *result_set_el_ptr;
03960 
03961   gcc_assert (result && operand_1 && operand_2);
03962   for (el_ptr_1 = operand_1, el_ptr_2 = operand_2, result_set_el_ptr = result;
03963        el_ptr_1 < operand_1 + els_in_reservs;
03964        el_ptr_1++, el_ptr_2++, result_set_el_ptr++)
03965     *result_set_el_ptr = *el_ptr_1 & *el_ptr_2;
03966 }
03967 
03968 /* The function outputs string representation of units reservation on
03969    cycle START_CYCLE in the reservation set.  The function uses repeat
03970    construction if REPETITION_NUM > 1.  */
03971 static void
03972 output_cycle_reservs (FILE *f, reserv_sets_t reservs, int start_cycle,
03973           int repetition_num)
03974 {
03975   int unit_num;
03976   int reserved_units_num;
03977 
03978   reserved_units_num = 0;
03979   for (unit_num = 0; unit_num < description->units_num; unit_num++)
03980     if (TEST_BIT (reservs, start_cycle * els_in_cycle_reserv
03981                   * sizeof (set_el_t) * CHAR_BIT + unit_num))
03982       reserved_units_num++;
03983   gcc_assert (repetition_num > 0);
03984   if (repetition_num != 1 && reserved_units_num > 1)
03985     fprintf (f, "(");
03986   reserved_units_num = 0;
03987   for (unit_num = 0;
03988        unit_num < description->units_num;
03989        unit_num++)
03990     if (TEST_BIT (reservs, start_cycle * els_in_cycle_reserv
03991       * sizeof (set_el_t) * CHAR_BIT + unit_num))
03992       {
03993         if (reserved_units_num != 0)
03994           fprintf (f, "+");
03995         reserved_units_num++;
03996         fprintf (f, "%s", units_array [unit_num]->name);
03997       }
03998   if (reserved_units_num == 0)
03999     fprintf (f, NOTHING_NAME);
04000   gcc_assert (repetition_num > 0);
04001   if (repetition_num != 1 && reserved_units_num > 1)
04002     fprintf (f, ")");
04003   if (repetition_num != 1)
04004     fprintf (f, "*%d", repetition_num);
04005 }
04006 
04007 /* The function outputs string representation of units reservation in
04008    the reservation set.  */
04009 static void
04010 output_reserv_sets (FILE *f, reserv_sets_t reservs)
04011 {
04012   int start_cycle = 0;
04013   int cycle;
04014   int repetition_num;
04015 
04016   repetition_num = 0;
04017   for (cycle = 0; cycle < max_cycles_num; cycle++)
04018     if (repetition_num == 0)
04019       {
04020         repetition_num++;
04021         start_cycle = cycle;
04022       }
04023     else if (memcmp
04024              ((char *) reservs + start_cycle * els_in_cycle_reserv
04025         * sizeof (set_el_t),
04026               (char *) reservs + cycle * els_in_cycle_reserv
04027         * sizeof (set_el_t),
04028         els_in_cycle_reserv * sizeof (set_el_t)) == 0)
04029       repetition_num++;
04030     else
04031       {
04032         if (start_cycle != 0)
04033           fprintf (f, ", ");
04034         output_cycle_reservs (f, reservs, start_cycle, repetition_num);
04035         repetition_num = 1;
04036         start_cycle = cycle;
04037       }
04038   if (start_cycle < max_cycles_num)
04039     {
04040       if (start_cycle != 0)
04041         fprintf (f, ", ");
04042       output_cycle_reservs (f, reservs, start_cycle, repetition_num);
04043     }
04044 }
04045 
04046 /* The following function returns free node state for AUTOMATON.  It
04047    may be new allocated node or node freed earlier.  The function also
04048    allocates reservation set if WITH_RESERVS has nonzero value.  */
04049 static state_t
04050 get_free_state (int with_reservs, automaton_t automaton)
04051 {
04052   state_t result;
04053 
04054   gcc_assert (max_cycles_num > 0 && automaton);
04055   if (VLA_PTR_LENGTH (free_states) != 0)
04056     {
04057       result = VLA_PTR (free_states, VLA_PTR_LENGTH (free_states) - 1);
04058       VLA_PTR_SHORTEN (free_states, 1);
04059       result->automaton = automaton;
04060       result->first_out_arc = NULL;
04061       result->it_was_placed_in_stack_for_NDFA_forming = 0;
04062       result->it_was_placed_in_stack_for_DFA_forming = 0;
04063       result->component_states = NULL;
04064       result->longest_path_length = UNDEFINED_LONGEST_PATH_LENGTH;
04065     }
04066   else
04067     {
04068 #ifndef NDEBUG
04069       allocated_states_num++;
04070 #endif
04071       result = create_node (sizeof (struct state));
04072       result->automaton = automaton;
04073       result->first_out_arc = NULL;
04074       result->unique_num = curr_unique_state_num;
04075       result->longest_path_length = UNDEFINED_LONGEST_PATH_LENGTH;
04076       curr_unique_state_num++;
04077     }
04078   if (with_reservs)
04079     {
04080       if (result->reservs == NULL)
04081         result->reservs = alloc_empty_reserv_sets ();
04082       else
04083         memset (result->reservs, 0, els_in_reservs * sizeof (set_el_t));
04084     }
04085   return result;
04086 }
04087 
04088 /* The function frees node STATE.  */
04089 static void
04090 free_state (state_t state)
04091 {
04092   free_alt_states (state->component_states);
04093   VLA_PTR_ADD (free_states, state);
04094 }
04095 
04096 /* Hash value of STATE.  If STATE represents deterministic state it is
04097    simply hash value of the corresponding reservation set.  Otherwise
04098    it is formed from hash values of the component deterministic
04099    states.  One more key is order number of state automaton.  */
04100 static hashval_t
04101 state_hash (const void *state)
04102 {
04103   unsigned int hash_value;
04104   alt_state_t alt_state;
04105 
04106   if (((state_t) state)->component_states == NULL)
04107     hash_value = reserv_sets_hash_value (((state_t) state)->reservs);
04108   else
04109     {
04110       hash_value = 0;
04111       for (alt_state = ((state_t) state)->component_states;
04112            alt_state != NULL;
04113            alt_state = alt_state->next_sorted_alt_state)
04114         hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
04115                        | (hash_value << CHAR_BIT))
04116                       + alt_state->state->unique_num);
04117     }
04118   hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
04119                  | (hash_value << CHAR_BIT))
04120                 + ((state_t) state)->automaton->automaton_order_num);
04121   return hash_value;
04122 }
04123 
04124 /* Return nonzero value if the states are the same.  */
04125 static int
04126 state_eq_p (const void *state_1, const void *state_2)
04127 {
04128   alt_state_t alt_state_1;
04129   alt_state_t alt_state_2;
04130 
04131   if (((state_t) state_1)->automaton != ((state_t) state_2)->automaton)
04132     return 0;
04133   else if (((state_t) state_1)->component_states == NULL
04134            && ((state_t) state_2)->component_states == NULL)
04135     return reserv_sets_eq (((state_t) state_1)->reservs,
04136          ((state_t) state_2)->reservs);
04137   else if (((state_t) state_1)->component_states != NULL
04138            && ((state_t) state_2)->component_states != NULL)
04139     {
04140       for (alt_state_1 = ((state_t) state_1)->component_states,
04141            alt_state_2 = ((state_t) state_2)->component_states;
04142            alt_state_1 != NULL && alt_state_2 != NULL;
04143            alt_state_1 = alt_state_1->next_sorted_alt_state,
04144      alt_state_2 = alt_state_2->next_sorted_alt_state)
04145         /* All state in the list must be already in the hash table.
04146            Also the lists must be sorted.  */
04147         if (alt_state_1->state != alt_state_2->state)
04148           return 0;
04149       return alt_state_1 == alt_state_2;
04150     }
04151   else
04152     return 0;
04153 }
04154 
04155 /* Insert STATE into the state table.  */
04156 static state_t
04157 insert_state (state_t state)
04158 {
04159   void **entry_ptr;
04160 
04161   entry_ptr = htab_find_slot (state_table, (void *) state, 1);
04162   if (*entry_ptr == NULL)
04163     *entry_ptr = (void *) state;
04164   return (state_t) *entry_ptr;
04165 }
04166 
04167 /* Add reservation of unit with UNIT_NUM on cycle CYCLE_NUM to
04168    deterministic STATE.  */
04169 static void
04170 set_state_reserv (state_t state, int cycle_num, int unit_num)
04171 {
04172   set_unit_reserv (state->reservs, cycle_num, unit_num);
04173 }
04174 
04175 /* Return nonzero value if the deterministic states contains a
04176    reservation of the same cpu unit on the same cpu cycle.  */
04177 static int
04178 intersected_state_reservs_p (state_t state1, state_t state2)
04179 {
04180   gcc_assert (state1->automaton == state2->automaton);
04181   return reserv_sets_are_intersected (state1->reservs, state2->reservs);
04182 }
04183 
04184 /* Return deterministic state (inserted into the table) which
04185    representing the automaton state which is union of reservations of
04186    the deterministic states masked by RESERVS.  */
04187 static state_t
04188 states_union (state_t state1, state_t state2, reserv_sets_t reservs)
04189 {
04190   state_t result;
04191   state_t state_in_table;
04192 
04193   gcc_assert (state1->automaton == state2->automaton);
04194   result = get_free_state (1, state1->automaton);
04195   reserv_sets_or (result->reservs, state1->reservs, state2->reservs);
04196   reserv_sets_and (result->reservs, result->reservs, reservs);
04197   state_in_table = insert_state (result);
04198   if (result != state_in_table)
04199     {
04200       free_state (result);
04201       result = state_in_table;
04202     }
04203   return result;
04204 }
04205 
04206 /* Return deterministic state (inserted into the table) which
04207    represent the automaton state is obtained from deterministic STATE
04208    by advancing cpu cycle and masking by RESERVS.  */
04209 static state_t
04210 state_shift (state_t state, reserv_sets_t reservs)
04211 {
04212   state_t result;
04213   state_t state_in_table;
04214 
04215   result = get_free_state (1, state->automaton);
04216   reserv_sets_shift (result->reservs, state->reservs);
04217   reserv_sets_and (result->reservs, result->reservs, reservs);
04218   state_in_table = insert_state (result);
04219   if (result != state_in_table)
04220     {
04221       free_state (result);
04222       result = state_in_table;
04223     }
04224   return result;
04225 }
04226 
04227 /* Initialization of the abstract data.  */
04228 static void
04229 initiate_states (void)
04230 {
04231   decl_t decl;
04232   int i;
04233 
04234   VLA_PTR_CREATE (units_container, description->units_num, "units_container");
04235   units_array
04236     = (description->decls_num && description->units_num
04237        ? VLA_PTR_BEGIN (units_container) : NULL);
04238   for (i = 0; i < description->decls_num; i++)
04239     {
04240       decl = description->decls [i];
04241       if (decl->mode == dm_unit)
04242   units_array [DECL_UNIT (decl)->unit_num] = DECL_UNIT (decl);
04243     }
04244   max_cycles_num = description->max_insn_reserv_cycles;
04245   els_in_cycle_reserv
04246     = ((description->units_num + sizeof (set_el_t) * CHAR_BIT - 1)
04247        / (sizeof (set_el_t) * CHAR_BIT));
04248   els_in_reservs = els_in_cycle_reserv * max_cycles_num;
04249   curr_unique_state_num = 0;
04250   initiate_alt_states ();
04251   VLA_PTR_CREATE (free_states, 1500, "free states");
04252   state_table = htab_create (1500, state_hash, state_eq_p, (htab_del) 0);
04253   temp_reserv = alloc_empty_reserv_sets ();
04254 }
04255 
04256 /* Finishing work with the abstract data.  */
04257 static void
04258 finish_states (void)
04259 {
04260   VLA_PTR_DELETE (units_container);
04261   htab_delete (state_table);
04262   VLA_PTR_DELETE (free_states);
04263   finish_alt_states ();
04264 }
04265 
04266 
04267 
04268 /* Abstract data `arcs'.  */
04269 
04270 /* List of free arcs.  */
04271 static arc_t first_free_arc;
04272 
04273 #ifndef NDEBUG
04274 /* The following variables is maximal number of allocated nodes
04275    `arc'.  */
04276 static int allocated_arcs_num = 0;
04277 #endif
04278 
04279 /* The function frees node ARC.  */
04280 static void
04281 free_arc (arc_t arc)
04282 {
04283   arc->next_out_arc = first_free_arc;
04284   first_free_arc = arc;
04285 }
04286 
04287 /* The function removes and frees ARC staring from FROM_STATE.  */
04288 static void
04289 remove_arc (state_t from_state, arc_t arc)
04290 {
04291   arc_t prev_arc;
04292   arc_t curr_arc;
04293 
04294   gcc_assert (arc);
04295   for (prev_arc = NULL, curr_arc = from_state->first_out_arc;
04296        curr_arc != NULL;
04297        prev_arc = curr_arc, curr_arc = curr_arc->next_out_arc)
04298     if (curr_arc == arc)
04299       break;
04300   gcc_assert (curr_arc);
04301   if (prev_arc == NULL)
04302     from_state->first_out_arc = arc->next_out_arc;
04303   else
04304     prev_arc->next_out_arc = arc->next_out_arc;
04305   free_arc (arc);
04306 }
04307 
04308 /* The functions returns arc with given characteristics (or NULL if
04309    the arc does not exist).  */
04310 static arc_t
04311 find_arc (state_t from_state, state_t to_state, ainsn_t insn)
04312 {
04313   arc_t arc;
04314 
04315   for (arc = first_out_arc (from_state); arc != NULL; arc = next_out_arc (arc))
04316     if (arc->to_state == to_state && arc->insn == insn)
04317       return arc;
04318   return NULL;
04319 }
04320 
04321 /* The function adds arc from FROM_STATE to TO_STATE marked by AINSN
04322    and with given STATE_ALTS.  The function returns added arc (or
04323    already existing arc).  */
04324 static arc_t
04325 add_arc (state_t from_state, state_t to_state, ainsn_t ainsn,
04326    int state_alts)
04327 {
04328   arc_t new_arc;
04329 
04330   new_arc = find_arc (from_state, to_state, ainsn);
04331   if (new_arc != NULL)
04332     return new_arc;
04333   if (first_free_arc == NULL)
04334     {
04335 #ifndef NDEBUG
04336       allocated_arcs_num++;
04337 #endif
04338       new_arc = create_node (sizeof (struct arc));
04339       new_arc->to_state = NULL;
04340       new_arc->insn = NULL;
04341       new_arc->next_out_arc = NULL;
04342     }
04343   else
04344     {
04345       new_arc = first_free_arc;
04346       first_free_arc =  first_free_arc->next_out_arc;
04347     }
04348   new_arc->to_state = to_state;
04349   new_arc->insn = ainsn;
04350   ainsn->arc_exists_p = 1;
04351   new_arc->next_out_arc = from_state->first_out_arc;
04352   from_state->first_out_arc = new_arc;
04353   new_arc->next_arc_marked_by_insn = NULL;
04354   new_arc->state_alts = state_alts;
04355   return new_arc;
04356 }
04357 
04358 /* The function returns the first arc starting from STATE.  */
04359 static arc_t
04360 first_out_arc (state_t state)
04361 {
04362   return state->first_out_arc;
04363 }
04364 
04365 /* The function returns next out arc after ARC.  */
04366 static arc_t
04367 next_out_arc (arc_t arc)
04368 {
04369   return arc->next_out_arc;
04370 }
04371 
04372 /* Initialization of the abstract data.  */
04373 static void
04374 initiate_arcs (void)
04375 {
04376   first_free_arc = NULL;
04377 }
04378 
04379 /* Finishing work with the abstract data.  */
04380 static void
04381 finish_arcs (void)
04382 {
04383 }
04384 
04385 
04386 
04387 /* Abstract data `automata lists'.  */
04388 
04389 /* List of free states.  */
04390 static automata_list_el_t first_free_automata_list_el;
04391 
04392 /* The list being formed.  */
04393 static automata_list_el_t current_automata_list;
04394 
04395 /* Hash table of automata lists.  */
04396 static htab_t automata_list_table;
04397 
04398 /* The following function returns free automata list el.  It may be
04399    new allocated node or node freed earlier.  */
04400 static automata_list_el_t
04401 get_free_automata_list_el (void)
04402 {
04403   automata_list_el_t result;
04404 
04405   if (first_free_automata_list_el != NULL)
04406     {
04407       result = first_free_automata_list_el;
04408       first_free_automata_list_el
04409   = first_free_automata_list_el->next_automata_list_el;
04410     }
04411   else
04412     result = create_node (sizeof (struct automata_list_el));
04413   result->automaton = NULL;
04414   result->next_automata_list_el = NULL;
04415   return result;
04416 }
04417 
04418 /* The function frees node AUTOMATA_LIST_EL.  */
04419 static void
04420 free_automata_list_el (automata_list_el_t automata_list_el)
04421 {
04422   if (automata_list_el == NULL)
04423     return;
04424   automata_list_el->next_automata_list_el = first_free_automata_list_el;
04425   first_free_automata_list_el = automata_list_el;
04426 }
04427 
04428 /* The function frees list AUTOMATA_LIST.  */
04429 static void
04430 free_automata_list (automata_list_el_t automata_list)
04431 {
04432   automata_list_el_t curr_automata_list_el;
04433   automata_list_el_t next_automata_list_el;
04434 
04435   for (curr_automata_list_el = automata_list;
04436        curr_automata_list_el != NULL;
04437        curr_automata_list_el = next_automata_list_el)
04438     {
04439       next_automata_list_el = curr_automata_list_el->next_automata_list_el;
04440       free_automata_list_el (curr_automata_list_el);
04441     }
04442 }
04443 
04444 /* Hash value of AUTOMATA_LIST.  */
04445 static hashval_t
04446 automata_list_hash (const void *automata_list)
04447 {
04448   unsigned int hash_value;
04449   automata_list_el_t curr_automata_list_el;
04450 
04451   hash_value = 0;
04452   for (curr_automata_list_el = (automata_list_el_t) automata_list;
04453        curr_automata_list_el != NULL;
04454        curr_automata_list_el = curr_automata_list_el->next_automata_list_el)
04455     hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
04456        | (hash_value << CHAR_BIT))
04457       + curr_automata_list_el->automaton->automaton_order_num);
04458   return hash_value;
04459 }
04460 
04461 /* Return nonzero value if the automata_lists are the same.  */
04462 static int
04463 automata_list_eq_p (const void *automata_list_1, const void *automata_list_2)
04464 {
04465   automata_list_el_t automata_list_el_1;
04466   automata_list_el_t automata_list_el_2;
04467 
04468   for (automata_list_el_1 = (automata_list_el_t) automata_list_1,
04469    automata_list_el_2 = (automata_list_el_t) automata_list_2;
04470        automata_list_el_1 != NULL && automata_list_el_2 != NULL;
04471        automata_list_el_1 = automata_list_el_1->next_automata_list_el,
04472    automata_list_el_2 = automata_list_el_2->next_automata_list_el)
04473     if (automata_list_el_1->automaton != automata_list_el_2->automaton)
04474       return 0;
04475   return automata_list_el_1 == automata_list_el_2;
04476 }
04477 
04478 /* Initialization of the abstract data.  */
04479 static void
04480 initiate_automata_lists (void)
04481 {
04482   first_free_automata_list_el = NULL;
04483   automata_list_table = htab_create (1500, automata_list_hash,
04484              automata_list_eq_p, (htab_del) 0);
04485 }
04486 
04487 /* The following function starts new automata list and makes it the
04488    current one.  */
04489 static void
04490 automata_list_start (void)
04491 {
04492   current_automata_list = NULL;
04493 }
04494 
04495 /* The following function adds AUTOMATON to the current list.  */
04496 static void
04497 automata_list_add (automaton_t automaton)
04498 {
04499   automata_list_el_t el;
04500 
04501   el = get_free_automata_list_el ();
04502   el->automaton = automaton;
04503   el->next_automata_list_el = current_automata_list;
04504   current_automata_list = el;
04505 }
04506 
04507 /* The following function finishes forming the current list, inserts
04508    it into the table and returns it.  */
04509 static automata_list_el_t
04510 automata_list_finish (void)
04511 {
04512   void **entry_ptr;
04513 
04514   if (current_automata_list == NULL)
04515     return NULL;
04516   entry_ptr = htab_find_slot (automata_list_table,
04517             (void *) current_automata_list, 1);
04518   if (*entry_ptr == NULL)
04519     *entry_ptr = (void *) current_automata_list;
04520   else
04521     free_automata_list (current_automata_list);
04522   current_automata_list = NULL;
04523   return (automata_list_el_t) *entry_ptr;
04524 }
04525 
04526 /* Finishing work with the abstract data.  */
04527 static void
04528 finish_automata_lists (void)
04529 {
04530   htab_delete (automata_list_table);
04531 }
04532 
04533 
04534 
04535 /* The page contains abstract data for work with exclusion sets (see
04536    exclusion_set in file rtl.def).  */
04537 
04538 /* The following variable refers to an exclusion set returned by
04539    get_excl_set.  This is bit string of length equal to cpu units
04540    number.  If exclusion set for given unit contains 1 for a unit,
04541    then simultaneous reservation of the units is prohibited.  */
04542 static reserv_sets_t excl_set;
04543 
04544 /* The array contains exclusion sets for each unit.  */
04545 static reserv_sets_t *unit_excl_set_table;
04546 
04547 /* The following function forms the array containing exclusion sets
04548    for each unit.  */
04549 static void
04550 initiate_excl_sets (void)
04551 {
04552   decl_t decl;
04553   reserv_sets_t unit_excl_set;
04554   unit_set_el_t el;
04555   int i;
04556 
04557   obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
04558   excl_set = (reserv_sets_t) obstack_base (&irp);
04559   obstack_finish (&irp);
04560   obstack_blank (&irp, description->units_num * sizeof (reserv_sets_t));
04561   unit_excl_set_table = (reserv_sets_t *) obstack_base (&irp);
04562   obstack_finish (&irp);
04563   /* Evaluate unit exclusion sets.  */
04564   for (i = 0; i < description->decls_num; i++)
04565     {
04566       decl = description->decls [i];
04567       if (decl->mode == dm_unit)
04568   {
04569     obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
04570     unit_excl_set = (reserv_sets_t) obstack_base (&irp);
04571     obstack_finish (&irp);
04572     memset (unit_excl_set, 0, els_in_cycle_reserv * sizeof (set_el_t));
04573     for (el = DECL_UNIT (decl)->excl_list;
04574          el != NULL;
04575          el = el->next_unit_set_el)
04576       {
04577         SET_BIT (unit_excl_set, el->unit_decl->unit_num);
04578         el->unit_decl->in_set_p = TRUE;
04579       }
04580           unit_excl_set_table [DECL_UNIT (decl)->unit_num] = unit_excl_set;
04581         }
04582     }
04583 }
04584 
04585 /* The function sets up and return EXCL_SET which is union of
04586    exclusion sets for each unit in IN_SET.  */
04587 static reserv_sets_t
04588 get_excl_set (reserv_sets_t in_set)
04589 {
04590   int excl_char_num;
04591   int chars_num;
04592   int i;
04593   int start_unit_num;
04594   int unit_num;
04595 
04596   chars_num = els_in_cycle_reserv * sizeof (set_el_t);
04597   memset (excl_set, 0, chars_num);
04598   for (excl_char_num = 0; excl_char_num < chars_num; excl_char_num++)
04599     if (((unsigned char *) in_set) [excl_char_num])
04600       for (i = CHAR_BIT - 1; i >= 0; i--)
04601   if ((((unsigned char *) in_set) [excl_char_num] >> i) & 1)
04602     {
04603       start_unit_num = excl_char_num * CHAR_BIT + i;
04604       if (start_unit_num >= description->units_num)
04605         return excl_set;
04606       for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
04607         {
04608     excl_set [unit_num]
04609       |= unit_excl_set_table [start_unit_num] [unit_num];
04610         }
04611     }
04612   return excl_set;
04613 }
04614 
04615 
04616 
04617 /* The page contains abstract data for work with presence/absence
04618    pattern sets (see presence_set/absence_set in file rtl.def).  */
04619 
04620 /* The following arrays contain correspondingly presence, final
04621    presence, absence, and final absence patterns for each unit.  */
04622 static pattern_reserv_t *unit_presence_set_table;
04623 static pattern_reserv_t *unit_final_presence_set_table;
04624 static pattern_reserv_t *unit_absence_set_table;
04625 static pattern_reserv_t *unit_final_absence_set_table;
04626 
04627 /* The following function forms list of reservation sets for given
04628    PATTERN_LIST.  */
04629 static pattern_reserv_t
04630 form_reserv_sets_list (pattern_set_el_t pattern_list)
04631 {
04632   pattern_set_el_t el;
04633   pattern_reserv_t first, curr, prev;
04634   int i;
04635 
04636   prev = first = NULL;
04637   for (el = pattern_list; el != NULL; el = el->next_pattern_set_el)
04638     {
04639       curr = create_node (sizeof (struct pattern_reserv));
04640       curr->reserv = alloc_empty_reserv_sets ();
04641       curr->next_pattern_reserv = NULL;
04642       for (i = 0; i < el->units_num; i++)
04643   {
04644     SET_BIT (curr->reserv, el->unit_decls [i]->unit_num);
04645     el->unit_decls [i]->in_set_p = TRUE;
04646   }
04647       if (prev != NULL)
04648   prev->next_pattern_reserv = curr;
04649       else
04650   first = curr;
04651       prev = curr;
04652     }
04653   return first;
04654 }
04655 
04656  /* The following function forms the array containing presence and
04657    absence pattern sets for each unit.  */
04658 static void
04659 initiate_presence_absence_pattern_sets (void)
04660 {
04661   decl_t decl;
04662   int i;
04663 
04664   obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
04665   unit_presence_set_table = (pattern_reserv_t *) obstack_base (&irp);
04666   obstack_finish (&irp);
04667   obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
04668   unit_final_presence_set_table = (pattern_reserv_t *) obstack_base (&irp);
04669   obstack_finish (&irp);
04670   obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
04671   unit_absence_set_table = (pattern_reserv_t *) obstack_base (&irp);
04672   obstack_finish (&irp);
04673   obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
04674   unit_final_absence_set_table = (pattern_reserv_t *) obstack_base (&irp);
04675   obstack_finish (&irp);
04676   /* Evaluate unit presence/absence sets.  */
04677   for (i = 0; i < description->decls_num; i++)
04678     {
04679       decl = description->decls [i];
04680       if (decl->mode == dm_unit)
04681   {
04682           unit_presence_set_table [DECL_UNIT (decl)->unit_num]
04683       = form_reserv_sets_list (DECL_UNIT (decl)->presence_list);
04684           unit_final_presence_set_table [DECL_UNIT (decl)->unit_num]
04685       = form_reserv_sets_list (DECL_UNIT (decl)->final_presence_list);
04686           unit_absence_set_table [DECL_UNIT (decl)->unit_num]
04687       = form_reserv_sets_list (DECL_UNIT (decl)->absence_list);
04688           unit_final_absence_set_table [DECL_UNIT (decl)->unit_num]
04689       = form_reserv_sets_list (DECL_UNIT (decl)->final_absence_list);
04690         }
04691     }
04692 }
04693 
04694 /* The function checks that CHECKED_SET satisfies all presence pattern
04695    sets for units in ORIGIONAL_SET.  The function returns TRUE if it
04696    is ok.  */
04697 static int
04698 check_presence_pattern_sets (reserv_sets_t checked_set,
04699            reserv_sets_t origional_set,
04700            int final_p)
04701 {
04702   int char_num;
04703   int chars_num;
04704   int i;
04705   int start_unit_num;
04706   int unit_num;
04707   int presence_p;
04708   pattern_reserv_t pat_reserv;
04709 
04710   chars_num = els_in_cycle_reserv * sizeof (set_el_t);
04711   for (char_num = 0; char_num < chars_num; char_num++)
04712     if (((unsigned char *) origional_set) [char_num])
04713       for (i = CHAR_BIT - 1; i >= 0; i--)
04714   if ((((unsigned char *) origional_set) [char_num] >> i) & 1)
04715     {
04716       start_unit_num = char_num * CHAR_BIT + i;
04717       if (start_unit_num >= description->units_num)
04718         break;
04719       if ((final_p
04720      && unit_final_presence_set_table [start_unit_num] == NULL)
04721     || (!final_p
04722         && unit_presence_set_table [start_unit_num] == NULL))
04723         continue;
04724       presence_p = FALSE;
04725       for (pat_reserv = (final_p
04726              ? unit_final_presence_set_table [start_unit_num]
04727              : unit_presence_set_table [start_unit_num]);
04728      pat_reserv != NULL;
04729      pat_reserv = pat_reserv->next_pattern_reserv)
04730         {
04731     for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
04732       if ((checked_set [unit_num] & pat_reserv->reserv [unit_num])
04733           != pat_reserv->reserv [unit_num])
04734         break;
04735     presence_p = presence_p || unit_num >= els_in_cycle_reserv;
04736         }
04737       if (!presence_p)
04738         return FALSE;
04739     }
04740   return TRUE;
04741 }
04742 
04743 /* The function checks that CHECKED_SET satisfies all absence pattern
04744    sets for units in ORIGIONAL_SET.  The function returns TRUE if it
04745    is ok.  */
04746 static int
04747 check_absence_pattern_sets (reserv_sets_t checked_set,
04748           reserv_sets_t origional_set,
04749           int final_p)
04750 {
04751   int char_num;
04752   int chars_num;
04753   int i;
04754   int start_unit_num;
04755   int unit_num;
04756   pattern_reserv_t pat_reserv;
04757 
04758   chars_num = els_in_cycle_reserv * sizeof (set_el_t);
04759   for (char_num = 0; char_num < chars_num; char_num++)
04760     if (((unsigned char *) origional_set) [char_num])
04761       for (i = CHAR_BIT - 1; i >= 0; i--)
04762   if ((((unsigned char *) origional_set) [char_num] >> i) & 1)
04763     {
04764       start_unit_num = char_num * CHAR_BIT + i;
04765       if (start_unit_num >= description->units_num)
04766         break;
04767       for (pat_reserv = (final_p
04768              ? unit_final_absence_set_table [start_unit_num]
04769              : unit_absence_set_table [start_unit_num]);
04770      pat_reserv != NULL;
04771      pat_reserv = pat_reserv->next_pattern_reserv)
04772         {
04773     for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
04774       if ((checked_set [unit_num] & pat_reserv->reserv [unit_num])
04775           != pat_reserv->reserv [unit_num]
04776           && pat_reserv->reserv [unit_num])
04777         break;
04778     if (unit_num >= els_in_cycle_reserv)
04779       return FALSE;
04780         }
04781     }
04782   return TRUE;
04783 }
04784 
04785 
04786 
04787 /* This page contains code for transformation of original reservations
04788    described in .md file.  The main goal of transformations is
04789    simplifying reservation and lifting up all `|' on the top of IR
04790    reservation representation.  */
04791 
04792 
04793 /* The following function makes copy of IR representation of
04794    reservation.  The function also substitutes all reservations
04795    defined by define_reservation by corresponding value during making
04796    the copy.  */
04797 static regexp_t
04798 copy_insn_regexp (regexp_t regexp)
04799 {
04800   regexp_t  result;
04801   int i;
04802 
04803   switch (regexp->mode)
04804     {
04805     case rm_reserv:
04806       result = copy_insn_regexp (REGEXP_RESERV (regexp)->reserv_decl->regexp);
04807       break;
04808 
04809     case rm_unit:
04810       result = copy_node (regexp, sizeof (struct regexp));
04811       break;
04812 
04813     case rm_repeat:
04814       result = copy_node (regexp, sizeof (struct regexp));
04815       REGEXP_REPEAT (result)->regexp
04816         = copy_insn_regexp (REGEXP_REPEAT (regexp)->regexp);
04817       break;
04818 
04819     case rm_sequence:
04820       result = copy_node (regexp,
04821                           sizeof (struct regexp) + sizeof (regexp_t)
04822         * (REGEXP_SEQUENCE (regexp)->regexps_num - 1));
04823       for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
04824   REGEXP_SEQUENCE (result)->regexps [i]
04825     = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
04826       break;
04827 
04828     case rm_allof:
04829       result = copy_node (regexp,
04830                           sizeof (struct regexp) + sizeof (regexp_t)
04831         * (REGEXP_ALLOF (regexp)->regexps_num - 1));
04832       for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
04833   REGEXP_ALLOF (result)->regexps [i]
04834     = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
04835       break;
04836 
04837     case rm_oneof:
04838       result = copy_node (regexp,
04839                           sizeof (struct regexp) + sizeof (regexp_t)
04840         * (REGEXP_ONEOF (regexp)->regexps_num - 1));
04841       for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
04842   REGEXP_ONEOF (result)->regexps [i]
04843     = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
04844       break;
04845 
04846     case rm_nothing:
04847       result = copy_node (regexp, sizeof (struct regexp));
04848       break;
04849 
04850     default:
04851       gcc_unreachable ();
04852     }
04853   return result;
04854 }
04855 
04856 /* The following variable is set up 1 if a transformation has been
04857    applied.  */
04858 static int regexp_transformed_p;
04859 
04860 /* The function makes transformation
04861    A*N -> A, A, ...  */
04862 static regexp_t
04863 transform_1 (regexp_t regexp)
04864 {
04865   int i;
04866   int repeat_num;
04867   regexp_t operand;
04868   pos_t pos;
04869 
04870   if (regexp->mode == rm_repeat)
04871     {
04872       repeat_num = REGEXP_REPEAT (regexp)->repeat_num;
04873       gcc_assert (repeat_num > 1);
04874       operand = REGEXP_REPEAT (regexp)->regexp;
04875       pos = regexp->mode;
04876       regexp = create_node (sizeof (struct regexp) + sizeof (regexp_t)
04877           * (repeat_num - 1));
04878       regexp->mode = rm_sequence;
04879       regexp->pos = pos;
04880       REGEXP_SEQUENCE (regexp)->regexps_num = repeat_num;
04881       for (i = 0; i < repeat_num; i++)
04882   REGEXP_SEQUENCE (regexp)->regexps [i] = copy_insn_regexp (operand);
04883       regexp_transformed_p = 1;
04884     }
04885   return regexp;
04886 }
04887 
04888 /* The function makes transformations
04889    ...,(A,B,...),C,... -> ...,A,B,...,C,...
04890    ...+(A+B+...)+C+... -> ...+A+B+...+C+...
04891    ...|(A|B|...)|C|... -> ...|A|B|...|C|...  */
04892 static regexp_t
04893 transform_2 (regexp_t regexp)
04894 {
04895   if (regexp->mode == rm_sequence)
04896     {
04897       regexp_t sequence = NULL;
04898       regexp_t result;
04899       int sequence_index = 0;
04900       int i, j;
04901 
04902       for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
04903   if (REGEXP_SEQUENCE (regexp)->regexps [i]->mode == rm_sequence)
04904     {
04905       sequence_index = i;
04906       sequence = REGEXP_SEQUENCE (regexp)->regexps [i];
04907       break;
04908     }
04909       if (i < REGEXP_SEQUENCE (regexp)->regexps_num)
04910   {
04911     gcc_assert (REGEXP_SEQUENCE (sequence)->regexps_num > 1
04912           && REGEXP_SEQUENCE (regexp)->regexps_num > 1);
04913     result = create_node (sizeof (struct regexp)
04914                                 + sizeof (regexp_t)
04915         * (REGEXP_SEQUENCE (regexp)->regexps_num
04916                                    + REGEXP_SEQUENCE (sequence)->regexps_num
04917                                    - 2));
04918     result->mode = rm_sequence;
04919     result->pos = regexp->pos;
04920     REGEXP_SEQUENCE (result)->regexps_num
04921             = (REGEXP_SEQUENCE (regexp)->regexps_num
04922                + REGEXP_SEQUENCE (sequence)->regexps_num - 1);
04923     for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
04924             if (i < sequence_index)
04925               REGEXP_SEQUENCE (result)->regexps [i]
04926                 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
04927             else if (i > sequence_index)
04928               REGEXP_SEQUENCE (result)->regexps
04929                 [i + REGEXP_SEQUENCE (sequence)->regexps_num - 1]
04930                 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
04931             else
04932               for (j = 0; j < REGEXP_SEQUENCE (sequence)->regexps_num; j++)
04933                 REGEXP_SEQUENCE (result)->regexps [i + j]
04934                   = copy_insn_regexp (REGEXP_SEQUENCE (sequence)->regexps [j]);
04935     regexp_transformed_p = 1;
04936     regexp = result;
04937   }
04938     }
04939   else if (regexp->mode == rm_allof)
04940     {
04941       regexp_t allof = NULL;
04942       regexp_t result;
04943       int allof_index = 0;
04944       int i, j;
04945 
04946       for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
04947   if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_allof)
04948     {
04949       allof_index = i;
04950       allof = REGEXP_ALLOF (regexp)->regexps [i];
04951       break;
04952     }
04953       if (i < REGEXP_ALLOF (regexp)->regexps_num)
04954   {
04955     gcc_assert (REGEXP_ALLOF (allof)->regexps_num > 1
04956           && REGEXP_ALLOF (regexp)->regexps_num > 1);
04957     result = create_node (sizeof (struct regexp)
04958                                 + sizeof (regexp_t)
04959         * (REGEXP_ALLOF (regexp)->regexps_num
04960                                    + REGEXP_ALLOF (allof)->regexps_num - 2));
04961     result->mode = rm_allof;
04962     result->pos = regexp->pos;
04963     REGEXP_ALLOF (result)->regexps_num
04964             = (REGEXP_ALLOF (regexp)->regexps_num
04965                + REGEXP_ALLOF (allof)->regexps_num - 1);
04966     for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
04967             if (i < allof_index)
04968               REGEXP_ALLOF (result)->regexps [i]
04969                 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
04970             else if (i > allof_index)
04971               REGEXP_ALLOF (result)->regexps
04972                 [i + REGEXP_ALLOF (allof)->regexps_num - 1]
04973                 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
04974             else
04975               for (j = 0; j < REGEXP_ALLOF (allof)->regexps_num; j++)
04976                 REGEXP_ALLOF (result)->regexps [i + j]
04977                   = copy_insn_regexp (REGEXP_ALLOF (allof)->regexps [j]);
04978     regexp_transformed_p = 1;
04979     regexp = result;
04980   }
04981     }
04982   else if (regexp->mode == rm_oneof)
04983     {
04984       regexp_t oneof = NULL;
04985       regexp_t result;
04986       int oneof_index = 0;
04987       int i, j;
04988 
04989       for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
04990   if (REGEXP_ONEOF (regexp)->regexps [i]->mode == rm_oneof)
04991     {
04992       oneof_index = i;
04993       oneof = REGEXP_ONEOF (regexp)->regexps [i];
04994       break;
04995     }
04996       if (i < REGEXP_ONEOF (regexp)->regexps_num)
04997   {
04998     gcc_assert (REGEXP_ONEOF (oneof)->regexps_num > 1
04999           && REGEXP_ONEOF (regexp)->regexps_num > 1);
05000     result = create_node (sizeof (struct regexp)
05001         + sizeof (regexp_t)
05002         * (REGEXP_ONEOF (regexp)->regexps_num
05003                                    + REGEXP_ONEOF (oneof)->regexps_num - 2));
05004     result->mode = rm_oneof;
05005     result->pos = regexp->pos;
05006     REGEXP_ONEOF (result)->regexps_num
05007       = (REGEXP_ONEOF (regexp)->regexps_num
05008                + REGEXP_ONEOF (oneof)->regexps_num - 1);
05009     for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
05010             if (i < oneof_index)
05011               REGEXP_ONEOF (result)->regexps [i]
05012                 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
05013             else if (i > oneof_index)
05014               REGEXP_ONEOF (result)->regexps
05015                 [i + REGEXP_ONEOF (oneof)->regexps_num - 1]
05016                 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
05017             else
05018               for (j = 0; j < REGEXP_ONEOF (oneof)->regexps_num; j++)
05019                 REGEXP_ONEOF (result)->regexps [i + j]
05020                   = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [j]);
05021     regexp_transformed_p = 1;
05022     regexp = result;
05023   }
05024     }
05025   return regexp;
05026 }
05027 
05028 /* The function makes transformations
05029    ...,A|B|...,C,... -> (...,A,C,...)|(...,B,C,...)|...
05030    ...+(A|B|...)+C+... -> (...+A+C+...)|(...+B+C+...)|...
05031    ...+(A,B,...)+C+... -> (...+A+C+...),B,...
05032    ...+(A,B,...)+(C,D,...) -> (A+C),(B+D),...  */
05033 static regexp_t
05034 transform_3 (regexp_t regexp)
05035 {
05036   if (regexp->mode == rm_sequence)
05037     {
05038       regexp_t oneof = NULL;
05039       int oneof_index = 0;
05040       regexp_t result;
05041       regexp_t sequence;
05042       int i, j;
05043 
05044       for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
05045   if (REGEXP_SEQUENCE (regexp)->regexps [i]->mode == rm_oneof)
05046     {
05047       oneof_index = i;
05048       oneof = REGEXP_SEQUENCE (regexp)->regexps [i];
05049       break;
05050     }
05051       if (i < REGEXP_SEQUENCE (regexp)->regexps_num)
05052   {
05053     gcc_assert (REGEXP_ONEOF (oneof)->regexps_num > 1
05054           && REGEXP_SEQUENCE (regexp)->regexps_num > 1);
05055     result = create_node (sizeof (struct regexp)
05056         + sizeof (regexp_t)
05057         * (REGEXP_ONEOF (oneof)->regexps_num - 1));
05058     result->mode = rm_oneof;
05059     result->pos = regexp->pos;
05060     REGEXP_ONEOF (result)->regexps_num
05061       = REGEXP_ONEOF (oneof)->regexps_num;
05062     for (i = 0; i < REGEXP_ONEOF (result)->regexps_num; i++)
05063       {
05064         sequence
05065                 = create_node (sizeof (struct regexp)
05066                                + sizeof (regexp_t)
05067                                * (REGEXP_SEQUENCE (regexp)->regexps_num - 1));
05068         sequence->mode = rm_sequence;
05069         sequence->pos = regexp->pos;
05070         REGEXP_SEQUENCE (sequence)->regexps_num
05071                 = REGEXP_SEQUENCE (regexp)->regexps_num;
05072               REGEXP_ONEOF (result)->regexps [i] = sequence;
05073         for (j = 0; j < REGEXP_SEQUENCE (sequence)->regexps_num; j++)
05074     if (j != oneof_index)
05075       REGEXP_SEQUENCE (sequence)->regexps [j]
05076         = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [j]);
05077     else
05078       REGEXP_SEQUENCE (sequence)->regexps [j]
05079         = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [i]);
05080       }
05081     regexp_transformed_p = 1;
05082     regexp = result;
05083   }
05084     }
05085   else if (regexp->mode == rm_allof)
05086     {
05087       regexp_t oneof = NULL;
05088       regexp_t seq;
05089       int oneof_index = 0;
05090       int max_seq_length, allof_length;
05091       regexp_t result;
05092       regexp_t allof = NULL;
05093       regexp_t allof_op = NULL;
05094       int i, j;
05095 
05096       for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
05097   if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_oneof)
05098     {
05099       oneof_index = i;
05100       oneof = REGEXP_ALLOF (regexp)->regexps [i];
05101       break;
05102     }
05103       if (i < REGEXP_ALLOF (regexp)->regexps_num)
05104   {
05105     gcc_assert (REGEXP_ONEOF (oneof)->regexps_num > 1
05106           && REGEXP_ALLOF (regexp)->regexps_num > 1);
05107     result = create_node (sizeof (struct regexp)
05108         + sizeof (regexp_t)
05109         * (REGEXP_ONEOF (oneof)->regexps_num - 1));
05110     result->mode = rm_oneof;
05111     result->pos = regexp->pos;
05112     REGEXP_ONEOF (result)->regexps_num
05113       = REGEXP_ONEOF (oneof)->regexps_num;
05114     for (i = 0; i < REGEXP_ONEOF (result)->regexps_num; i++)
05115       {
05116         allof
05117     = create_node (sizeof (struct regexp)
05118                                + sizeof (regexp_t)
05119              * (REGEXP_ALLOF (regexp)->regexps_num - 1));
05120         allof->mode = rm_allof;
05121         allof->pos = regexp->pos;
05122         REGEXP_ALLOF (allof)->regexps_num
05123                 = REGEXP_ALLOF (regexp)->regexps_num;
05124               REGEXP_ONEOF (result)->regexps [i] = allof;
05125         for (j = 0; j < REGEXP_ALLOF (allof)->regexps_num; j++)
05126     if (j != oneof_index)
05127       REGEXP_ALLOF (allof)->regexps [j]
05128         = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [j]);
05129     else
05130       REGEXP_ALLOF (allof)->regexps [j]
05131         = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [i]);
05132       }
05133     regexp_transformed_p = 1;
05134     regexp = result;
05135   }
05136       max_seq_length = 0;
05137       if (regexp->mode == rm_allof)
05138   for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
05139     {
05140       switch (REGEXP_ALLOF (regexp)->regexps [i]->mode)
05141         {
05142         case rm_sequence:
05143     seq = REGEXP_ALLOF (regexp)->regexps [i];
05144     if (max_seq_length < REGEXP_SEQUENCE (seq)->regexps_num)
05145       max_seq_length = REGEXP_SEQUENCE (seq)->regexps_num;
05146     break;
05147 
05148         case rm_unit:
05149         case rm_nothing:
05150     break;
05151 
05152         default:
05153     max_seq_length = 0;
05154     goto break_for;
05155         }
05156     }
05157     break_for:
05158       if (max_seq_length != 0)
05159   {
05160     gcc_assert (max_seq_length != 1
05161           && REGEXP_ALLOF (regexp)->regexps_num > 1);
05162     result = create_node (sizeof (struct regexp)
05163         + sizeof (regexp_t) * (max_seq_length - 1));
05164     result->mode = rm_sequence;
05165     result->pos = regexp->pos;
05166     REGEXP_SEQUENCE (result)->regexps_num = max_seq_length;
05167     for (i = 0; i < max_seq_length; i++)
05168       {
05169         allof_length = 0;
05170         for (j = 0; j < REGEXP_ALLOF (regexp)->regexps_num; j++)
05171     switch (REGEXP_ALLOF (regexp)->regexps [j]->mode)
05172       {
05173       case rm_sequence:
05174         if (i < (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
05175                 ->regexps [j])->regexps_num))
05176           {
05177       allof_op
05178         = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
05179                 ->regexps [j])
05180            ->regexps [i]);
05181       allof_length++;
05182           }
05183         break;
05184       case rm_unit:
05185       case rm_nothing:
05186         if (i == 0)
05187           {
05188       allof_op = REGEXP_ALLOF (regexp)->regexps [j];
05189       allof_length++;
05190           }
05191         break;
05192       default:
05193         break;
05194       }
05195         
05196         if (allof_length == 1)
05197     REGEXP_SEQUENCE (result)->regexps [i] = allof_op;
05198         else
05199     {
05200       allof = create_node (sizeof (struct regexp)
05201                + sizeof (regexp_t)
05202                * (allof_length - 1));
05203       allof->mode = rm_allof;
05204       allof->pos = regexp->pos;
05205       REGEXP_ALLOF (allof)->regexps_num = allof_length;
05206       REGEXP_SEQUENCE (result)->regexps [i] = allof;
05207       allof_length = 0;
05208       for (j = 0; j < REGEXP_ALLOF (regexp)->regexps_num; j++)
05209         if (REGEXP_ALLOF (regexp)->regexps [j]->mode == rm_sequence
05210       && (i <
05211           (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
05212                 ->regexps [j])->regexps_num)))
05213           {
05214       allof_op = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
05215                  ->regexps [j])
05216             ->regexps [i]);
05217       REGEXP_ALLOF (allof)->regexps [allof_length]
05218         = allof_op;
05219       allof_length++;
05220           }
05221         else if (i == 0
05222            && (REGEXP_ALLOF (regexp)->regexps [j]->mode
05223          == rm_unit
05224          || (REGEXP_ALLOF (regexp)->regexps [j]->mode
05225              == rm_nothing)))
05226           {
05227       allof_op = REGEXP_ALLOF (regexp)->regexps [j];
05228       REGEXP_ALLOF (allof)->regexps [allof_length]
05229         = allof_op;
05230       allof_length++;
05231           }
05232     }
05233       }
05234     regexp_transformed_p = 1;
05235     regexp = result;
05236   }
05237     }
05238   return regexp;
05239 }
05240 
05241 /* The function traverses IR of reservation and applies transformations
05242    implemented by FUNC.  */
05243 static regexp_t
05244 regexp_transform_func (regexp_t regexp, regexp_t (*func) (regexp_t regexp))
05245 {
05246   int i;
05247 
05248   switch (regexp->mode)
05249     {
05250     case rm_sequence:
05251       for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
05252   REGEXP_SEQUENCE (regexp)->regexps [i]
05253     = regexp_transform_func (REGEXP_SEQUENCE (regexp)->regexps [i],
05254            func);
05255       break;
05256 
05257     case rm_allof:
05258       for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
05259   REGEXP_ALLOF (regexp)->regexps [i]
05260     = regexp_transform_func (REGEXP_ALLOF (regexp)->regexps [i], func);
05261       break;
05262 
05263     case rm_oneof:
05264       for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
05265   REGEXP_ONEOF (regexp)->regexps [i]
05266     = regexp_transform_func (REGEXP_ONEOF (regexp)->regexps [i], func);
05267       break;
05268 
05269     case rm_repeat:
05270       REGEXP_REPEAT (regexp)->regexp
05271   = regexp_transform_func (REGEXP_REPEAT (regexp)->regexp, func);
05272       break;
05273 
05274     case rm_nothing:
05275     case rm_unit:
05276       break;
05277 
05278     default:
05279       gcc_unreachable ();
05280     }
05281   return (*func) (regexp);
05282 }
05283 
05284 /* The function applies all transformations for IR representation of
05285    reservation REGEXP.  */
05286 static regexp_t
05287 transform_regexp (regexp_t regexp)
05288 {
05289   regexp = regexp_transform_func (regexp, transform_1);
05290   do
05291     {
05292       regexp_transformed_p = 0;
05293       regexp = regexp_transform_func (regexp, transform_2);
05294       regexp = regexp_transform_func (regexp, transform_3);
05295     }
05296   while (regexp_transformed_p);
05297   return regexp;
05298 }
05299 
05300 /* The function applies all transformations for reservations of all
05301    insn declarations.  */
05302 static void
05303 transform_insn_regexps (void)
05304 {
05305   decl_t decl;
05306   int i;
05307 
05308   transform_time = create_ticker ();
05309   add_advance_cycle_insn_decl ();
05310   if (progress_flag)
05311     fprintf (stderr, "Reservation transformation...");
05312   for (i = 0; i < description->decls_num; i++)
05313     {
05314       decl = description->decls [i];
05315       if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
05316   DECL_INSN_RESERV (decl)->transformed_regexp
05317     = transform_regexp (copy_insn_regexp
05318             (DECL_INSN_RESERV (decl)->regexp));
05319     }
05320   if (progress_flag)
05321     fprintf (stderr, "done\n");
05322   ticker_off (&transform_time);
05323 }
05324 
05325 
05326 
05327 /* The following variable value is TRUE if the first annotated message
05328    about units to automata distribution has been output.  */
05329 static int annotation_message_reported_p;
05330 
05331 /* The following structure describes usage of a unit in a reservation.  */
05332 struct unit_usage
05333 {
05334   unit_decl_t unit_decl;
05335   /* The following forms a list of units used on the same cycle in the
05336      same alternative.  */
05337   struct unit_usage *next;
05338 };
05339 
05340 /* Obstack for unit_usage structures.  */
05341 static struct obstack unit_usages;
05342 
05343 /* VLA for representation of array of pointers to unit usage
05344    structures.  There is an element for each combination of
05345    (alternative number, cycle).  Unit usages on given cycle in
05346    alternative with given number are referred through element with
05347    index equals to the cycle * number of all alternatives in the regexp
05348    + the alternative number.  */
05349 static vla_ptr_t cycle_alt_unit_usages;
05350 
05351 /* The following function creates the structure unit_usage for UNIT on
05352    CYCLE in REGEXP alternative with ALT_NUM.  The structure is made
05353    accessed through cycle_alt_unit_usages.  */
05354 static void
05355 store_alt_unit_usage (regexp_t regexp, regexp_t unit, int cycle,
05356           int alt_num)
05357 {
05358   size_t i, length, old_length;
05359   unit_decl_t unit_decl;
05360   struct unit_usage *unit_usage_ptr;
05361   int index;
05362 
05363   gcc_assert (regexp && regexp->mode == rm_oneof
05364         && alt_num < REGEXP_ONEOF (regexp)->regexps_num);
05365   unit_decl = REGEXP_UNIT (unit)->unit_decl;
05366   old_length = VLA_PTR_LENGTH (cycle_alt_unit_usages);
05367   length = (cycle + 1) * REGEXP_ONEOF (regexp)->regexps_num;
05368   if (old_length < length)
05369     {
05370       VLA_PTR_EXPAND (cycle_alt_unit_usages, length - old_length);
05371       for (i = old_length; i < length; i++)
05372   VLA_PTR (cycle_alt_unit_usages, i) = NULL;
05373     }
05374   obstack_blank (&unit_usages, sizeof (struct unit_usage));
05375   unit_usage_ptr = (struct unit_usage *) obstack_base (&unit_usages);
05376   obstack_finish (&unit_usages);
05377   unit_usage_ptr->unit_decl = unit_decl;
05378   index = cycle * REGEXP_ONEOF (regexp)->regexps_num + alt_num;
05379   unit_usage_ptr->next = VLA_PTR (cycle_alt_unit_usages, index);
05380   VLA_PTR (cycle_alt_unit_usages, index) = unit_usage_ptr;
05381   unit_decl->last_distribution_check_cycle = -1; /* undefined */
05382 }
05383 
05384 /* The function processes given REGEXP to find units with the wrong
05385    distribution.  */
05386 static void
05387 check_regexp_units_distribution (const char *insn_reserv_name,
05388          regexp_t regexp)
05389 {
05390   int i, j, k, cycle;
05391   regexp_t seq, allof, unit;
05392   struct unit_usage *unit_usage_ptr, *other_unit_usage_ptr;
05393 
05394   if (regexp == NULL || regexp->mode != rm_oneof)
05395     return;
05396   /* Store all unit usages in the regexp:  */
05397   obstack_init (&unit_usages);
05398   VLA_PTR_CREATE (cycle_alt_unit_usages, 100, "unit usages on cycles");
05399   for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
05400     {
05401       seq = REGEXP_ONEOF (regexp)->regexps [i];
05402       switch (seq->mode)
05403   {
05404   case rm_sequence:
05405     for (j = 0; j < REGEXP_SEQUENCE (seq)->regexps_num; j++)
05406       {
05407         allof = REGEXP_SEQUENCE (seq)->regexps [j];
05408         switch (allof->mode)
05409     {
05410     case rm_allof:
05411       for (k = 0; k < REGEXP_ALLOF (allof)->regexps_num; k++)
05412         {
05413           unit = REGEXP_ALLOF (allof)->regexps [k];
05414           if (unit->mode == rm_unit)
05415       store_alt_unit_usage (regexp, unit, j, i);
05416           else
05417       gcc_assert (unit->mode == rm_nothing);
05418         }
05419       break;
05420       
05421     case rm_unit:
05422       store_alt_unit_usage (regexp, allof, j, i);
05423       break;
05424       
05425     case rm_nothing:
05426       break;
05427       
05428     default:
05429       gcc_unreachable ();
05430     }
05431       }
05432     break;
05433 
05434   case rm_allof:
05435     for (k = 0; k < REGEXP_ALLOF (seq)->regexps_num; k++)
05436       {
05437         unit = REGEXP_ALLOF (seq)->regexps [k];
05438         switch (unit->mode)
05439     {
05440     case rm_unit:
05441       store_alt_unit_usage (regexp, unit, 0, i);
05442       break;
05443       
05444     case rm_nothing:
05445       break;
05446       
05447     default:
05448       gcc_unreachable ();
05449     }
05450       }
05451     break;
05452 
05453   case rm_unit:
05454     store_alt_unit_usage (regexp, seq, 0, i);
05455     break;
05456 
05457   case rm_nothing:
05458     break;
05459 
05460   default:
05461     gcc_unreachable ();
05462   }
05463     }
05464   /* Check distribution:  */
05465   for (i = 0; i < (int) VLA_PTR_LENGTH (cycle_alt_unit_usages); i++)
05466     {
05467       cycle = i / REGEXP_ONEOF (regexp)->regexps_num;
05468       for (unit_usage_ptr = VLA_PTR (cycle_alt_unit_usages, i);
05469      unit_usage_ptr != NULL;
05470      unit_usage_ptr = unit_usage_ptr->next)
05471   if (cycle != unit_usage_ptr->unit_decl->last_distribution_check_cycle)
05472     {
05473       unit_usage_ptr->unit_decl->last_distribution_check_cycle = cycle;
05474       for (k = cycle * REGEXP_ONEOF (regexp)->regexps_num;
05475      k < (int) VLA_PTR_LENGTH (cycle_alt_unit_usages)
05476        && k == cycle * REGEXP_ONEOF (regexp)->regexps_num;
05477      k++)
05478         {
05479     for (other_unit_usage_ptr = VLA_PTR (cycle_alt_unit_usages, k);
05480          other_unit_usage_ptr != NULL;
05481          other_unit_usage_ptr = other_unit_usage_ptr->next)
05482       if (unit_usage_ptr->unit_decl->automaton_decl
05483           == other_unit_usage_ptr->unit_decl->automaton_decl)
05484         break;
05485     if (other_unit_usage_ptr == NULL
05486         && VLA_PTR (cycle_alt_unit_usages, k) != NULL)
05487       break;
05488         }
05489       if (k < (int) VLA_PTR_LENGTH (cycle_alt_unit_usages)
05490     && k == cycle * REGEXP_ONEOF (regexp)->regexps_num)
05491         {
05492     if (!annotation_message_reported_p)
05493       {
05494         fprintf (stderr, "\n");
05495         error ("The following units do not satisfy units-automata distribution rule");
05496         error (" (A unit of given unit automaton should be on each reserv. altern.)");
05497         annotation_message_reported_p = TRUE;
05498       }
05499     error ("Unit %s, reserv. %s, cycle %d",
05500            unit_usage_ptr->unit_decl->name, insn_reserv_name,
05501            cycle);
05502         }
05503     }
05504     }
05505   VLA_PTR_DELETE (cycle_alt_unit_usages);
05506   obstack_free (&unit_usages, NULL);
05507 }
05508 
05509 /* The function finds units which violates units to automata
05510    distribution rule.  If the units exist, report about them.  */
05511 static void
05512 check_unit_distributions_to_automata (void)
05513 {
05514   decl_t decl;
05515   int i;
05516 
05517   if (progress_flag)
05518     fprintf (stderr, "Check unit distributions to automata...");
05519   annotation_message_reported_p = FALSE;
05520   for (i = 0; i < description->decls_num; i++)
05521     {
05522       decl = description->decls [i];
05523       if (decl->mode == dm_insn_reserv)
05524   check_regexp_units_distribution
05525     (DECL_INSN_RESERV (decl)->name,
05526      DECL_INSN_RESERV (decl)->transformed_regexp);
05527     }
05528   if (progress_flag)
05529     fprintf (stderr, "done\n");
05530 }
05531 
05532 
05533 
05534 /* The page contains code for building alt_states (see comments for
05535    IR) describing all possible insns reservations of an automaton.  */
05536 
05537 /* Current state being formed for which the current alt_state
05538    refers.  */
05539 static state_t state_being_formed;
05540 
05541 /* Current alt_state being formed.  */
05542 static alt_state_t alt_state_being_formed;
05543 
05544 /* This recursive function processes `,' and units in reservation
05545    REGEXP for forming alt_states of AUTOMATON.  It is believed that
05546    CURR_CYCLE is start cycle of all reservation REGEXP.  */
05547 static int
05548 process_seq_for_forming_states (regexp_t regexp, automaton_t automaton,
05549         int curr_cycle)
05550 {
05551   int i;
05552 
05553   if (regexp == NULL)
05554     return curr_cycle;
05555 
05556   switch (regexp->mode)
05557     {
05558     case rm_unit:
05559       if (REGEXP_UNIT (regexp)->unit_decl->corresponding_automaton_num
05560           == automaton->automaton_order_num)
05561         set_state_reserv (state_being_formed, curr_cycle,
05562                           REGEXP_UNIT (regexp)->unit_decl->unit_num);
05563       return curr_cycle;
05564       
05565     case rm_sequence:
05566       for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
05567   curr_cycle
05568     = process_seq_for_forming_states
05569       (REGEXP_SEQUENCE (regexp)->regexps [i], automaton, curr_cycle) + 1;
05570       return curr_cycle;
05571 
05572     case rm_allof:
05573       {
05574   int finish_cycle = 0;
05575   int cycle;
05576   
05577   for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
05578     {
05579       cycle = process_seq_for_forming_states (REGEXP_ALLOF (regexp)
05580                 ->regexps [i],
05581                 automaton, curr_cycle);
05582       if (finish_cycle < cycle)
05583         finish_cycle = cycle;
05584     }
05585   return finish_cycle;
05586       }
05587 
05588     case rm_nothing:
05589       return curr_cycle;
05590 
05591     default:
05592       gcc_unreachable ();
05593     }
05594 }
05595 
05596 /* This recursive function finishes forming ALT_STATE of AUTOMATON and
05597    inserts alt_state into the table.  */
05598 static void
05599 finish_forming_alt_state (alt_state_t alt_state,
05600         automaton_t automaton ATTRIBUTE_UNUSED)
05601 {
05602   state_t state_in_table;
05603   state_t corresponding_state;
05604 
05605   corresponding_state = alt_state->state;
05606   state_in_table = insert_state (corresponding_state);
05607   if (state_in_table != corresponding_state)
05608     {
05609       free_state (corresponding_state);
05610       alt_state->state = state_in_table;
05611     }
05612 }
05613 
05614 /* The following variable value is current automaton insn for whose
05615    reservation the alt states are created.  */
05616 static ainsn_t curr_ainsn;
05617 
05618 /* This recursive function processes `|' in reservation REGEXP for
05619    forming alt_states of AUTOMATON.  List of the alt states should
05620    have the same order as in the description.  */
05621 static void
05622 process_alts_for_forming_states (regexp_t regexp, automaton_t automaton,
05623          int inside_oneof_p)
05624 {
05625   int i;
05626 
05627   if (regexp->mode != rm_oneof)
05628     {
05629       alt_state_being_formed = get_free_alt_state ();
05630       state_being_formed = get_free_state (1, automaton);
05631       alt_state_being_formed->state = state_being_formed;
05632       /* We inserts in reverse order but we process alternatives also
05633          in reverse order.  So we have the same order of alternative
05634          as in the description.  */
05635       alt_state_being_formed->next_alt_state = curr_ainsn->alt_states;
05636       curr_ainsn->alt_states = alt_state_being_formed;
05637       (void) process_seq_for_forming_states (regexp, automaton, 0);
05638       finish_forming_alt_state (alt_state_being_formed, automaton);
05639     }
05640   else
05641     {
05642       gcc_assert (!inside_oneof_p);
05643       /* We processes it in reverse order to get list with the same
05644    order as in the description.  See also the previous
05645    commentary.  */
05646       for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
05647   process_alts_for_forming_states (REGEXP_ONEOF (regexp)->regexps [i],
05648            automaton, 1);
05649     }
05650 }
05651 
05652 /* Create nodes alt_state for all AUTOMATON insns.  */
05653 static void
05654 create_alt_states (automaton_t automaton)
05655 {
05656   struct insn_reserv_decl *reserv_decl;
05657 
05658   for (curr_ainsn = automaton->ainsn_list;
05659        curr_ainsn != NULL;
05660        curr_ainsn = curr_ainsn->next_ainsn)
05661     {
05662       reserv_decl = curr_ainsn->insn_reserv_decl;
05663       if (reserv_decl != DECL_INSN_RESERV (advance_cycle_insn_decl))
05664         {
05665           curr_ainsn->alt_states = NULL;
05666           process_alts_for_forming_states (reserv_decl->transformed_regexp,
05667              automaton, 0);
05668           curr_ainsn->sorted_alt_states
05669       = uniq_sort_alt_states (curr_ainsn->alt_states);
05670         }
05671     }
05672 }
05673 
05674 
05675 
05676 /* The page contains major code for building DFA(s) for fast pipeline
05677    hazards recognition.  */
05678 
05679 /* The function forms list of ainsns of AUTOMATON with the same
05680    reservation.  */
05681 static void
05682 form_ainsn_with_same_reservs (automaton_t automaton)
05683 {
05684   ainsn_t curr_ainsn;
05685   size_t i;
05686   vla_ptr_t first_insns;
05687   vla_ptr_t last_insns;
05688 
05689   VLA_PTR_CREATE (first_insns, 150, "first insns with the same reservs");
05690   VLA_PTR_CREATE (last_insns, 150, "last insns with the same reservs");
05691   for (curr_ainsn = automaton->ainsn_list;
05692        curr_ainsn != NULL;
05693        curr_ainsn = curr_ainsn->next_ainsn)
05694     if (curr_ainsn->insn_reserv_decl
05695   == DECL_INSN_RESERV (advance_cycle_insn_decl))
05696       {
05697         curr_ainsn->next_same_reservs_insn = NULL;
05698         curr_ainsn->first_insn_with_same_reservs = 1;
05699       }
05700     else
05701       {
05702         for (i = 0; i < VLA_PTR_LENGTH (first_insns); i++)
05703           if (alt_states_eq
05704               (curr_ainsn->sorted_alt_states,
05705                ((ainsn_t) VLA_PTR (first_insns, i))->sorted_alt_states))
05706             break;
05707         curr_ainsn->next_same_reservs_insn = NULL;
05708         if (i < VLA_PTR_LENGTH (first_insns))
05709           {
05710             curr_ainsn->first_insn_with_same_reservs = 0;
05711       ((ainsn_t) VLA_PTR (last_insns, i))->next_same_reservs_insn
05712         = curr_ainsn;
05713             VLA_PTR (last_insns, i) = curr_ainsn;
05714           }
05715         else
05716           {
05717             VLA_PTR_ADD (first_insns, curr_ainsn);
05718             VLA_PTR_ADD (last_insns, curr_ainsn);
05719             curr_ainsn->first_insn_with_same_reservs = 1;
05720           }
05721       }
05722   VLA_PTR_DELETE (first_insns);
05723   VLA_PTR_DELETE (last_insns);
05724 }
05725 
05726 /* Forming unit reservations which can affect creating the automaton
05727    states achieved from a given state.  It permits to build smaller
05728    automata in many cases.  We would have the same automata after
05729    the minimization without such optimization, but the automaton
05730    right after the building could be huge.  So in other words, usage
05731    of reservs_matter means some minimization during building the
05732    automaton.  */
05733 static reserv_sets_t
05734 form_reservs_matter (automaton_t automaton)
05735 {
05736   int cycle, unit;
05737   reserv_sets_t reservs_matter = alloc_empty_reserv_sets();
05738 
05739   for (cycle = 0; cycle < max_cycles_num; cycle++)
05740     for (unit = 0; unit < description->units_num; unit++)
05741       if (units_array [unit]->automaton_decl
05742     == automaton->corresponding_automaton_decl
05743     && (cycle >= units_array [unit]->min_occ_cycle_num
05744         /* We can not remove queried unit from reservations.  */
05745         || units_array [unit]->query_p
05746         /* We can not remove units which are used
05747      `exclusion_set', `presence_set',
05748      `final_presence_set', `absence_set', and
05749      `final_absence_set'.  */
05750         || units_array [unit]->in_set_p))
05751   set_unit_reserv (reservs_matter, cycle, unit);
05752   return reservs_matter;
05753 }
05754 
05755 /* The following function creates all states of nondeterministic (if
05756    NDFA_FLAG has nonzero value) or deterministic AUTOMATON.  */
05757 static void
05758 make_automaton (automaton_t automaton)
05759 {
05760   ainsn_t ainsn;
05761   struct insn_reserv_decl *insn_reserv_decl;
05762   alt_state_t alt_state;
05763   state_t state;
05764   state_t start_state;
05765   state_t state2;
05766   ainsn_t advance_cycle_ainsn;
05767   arc_t added_arc;
05768   vla_ptr_t state_stack;
05769   int states_n;
05770   reserv_sets_t reservs_matter = form_reservs_matter (automaton);
05771 
05772   VLA_PTR_CREATE (state_stack, 150, "state stack");
05773   /* Create the start state (empty state).  */
05774   start_state = insert_state (get_free_state (1, automaton));
05775   automaton->start_state = start_state;
05776   start_state->it_was_placed_in_stack_for_NDFA_forming = 1;
05777   VLA_PTR_ADD (state_stack, start_state);
05778   states_n = 1;
05779   while (VLA_PTR_LENGTH (state_stack) != 0)
05780     {
05781       state = VLA_PTR (state_stack, VLA_PTR_LENGTH (state_stack) - 1);
05782       VLA_PTR_SHORTEN (state_stack, 1);
05783       advance_cycle_ainsn = NULL;
05784       for (ainsn = automaton->ainsn_list;
05785      ainsn != NULL;
05786      ainsn = ainsn->next_ainsn)
05787         if (ainsn->first_insn_with_same_reservs)
05788           {
05789             insn_reserv_decl = ainsn->insn_reserv_decl;
05790             if (insn_reserv_decl != DECL_INSN_RESERV (advance_cycle_insn_decl))
05791               {
05792     /* We process alt_states in the same order as they are
05793                    present in the description.  */
05794     added_arc = NULL;
05795                 for (alt_state = ainsn->alt_states;
05796                      alt_state != NULL;
05797                      alt_state = alt_state->next_alt_state)
05798                   {
05799                     state2 = alt_state->state;
05800                     if (!intersected_state_reservs_p (state, state2))
05801                       {
05802                         state2 = states_union (state, state2, reservs_matter);
05803                         if (!state2->it_was_placed_in_stack_for_NDFA_forming)
05804                           {
05805                             state2->it_was_placed_in_stack_for_NDFA_forming
05806             = 1;
05807                             VLA_PTR_ADD (state_stack, state2);
05808           states_n++;
05809           if (progress_flag && states_n % 100 == 0)
05810             fprintf (stderr, ".");
05811                           }
05812       added_arc = add_arc (state, state2, ainsn, 1);
05813       if (!ndfa_flag)
05814         break;
05815                       }
05816                   }
05817     if (!ndfa_flag && added_arc != NULL)
05818       {
05819         added_arc->state_alts = 0;
05820         for (alt_state = ainsn->alt_states;
05821        alt_state != NULL;
05822        alt_state = alt_state->next_alt_state)
05823           {
05824       state2 = alt_state->state;
05825       if (!intersected_state_reservs_p (state, state2))
05826         added_arc->state_alts++;
05827           }
05828       }
05829               }
05830             else
05831               advance_cycle_ainsn = ainsn;
05832           }
05833       /* Add transition to advance cycle.  */
05834       state2 = state_shift (state, reservs_matter);
05835       if (!state2->it_was_placed_in_stack_for_NDFA_forming)
05836         {
05837           state2->it_was_placed_in_stack_for_NDFA_forming = 1;
05838           VLA_PTR_ADD (state_stack, state2);
05839     states_n++;
05840     if (progress_flag && states_n % 100 == 0)
05841       fprintf (stderr, ".");
05842         }
05843       gcc_assert (advance_cycle_ainsn);
05844       add_arc (state, state2, advance_cycle_ainsn, 1);
05845     }
05846   VLA_PTR_DELETE (state_stack);
05847 }
05848 
05849 /* Foms lists of all arcs of STATE marked by the same ainsn.  */
05850 static void
05851 form_arcs_marked_by_insn (state_t state)
05852 {
05853   decl_t decl;
05854   arc_t arc;
05855   int i;
05856 
05857   for (i = 0; i < description->decls_num; i++)
05858     {
05859       decl = description->decls [i];
05860       if (decl->mode == dm_insn_reserv)
05861   DECL_INSN_RESERV (decl)->arcs_marked_by_insn = NULL;
05862     }
05863   for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
05864     {
05865       gcc_assert (arc->insn);
05866       arc->next_arc_marked_by_insn
05867   = arc->insn->insn_reserv_decl->arcs_marked_by_insn;
05868       arc->insn->insn_reserv_decl->arcs_marked_by_insn = arc;
05869     }
05870 }
05871 
05872 /* The function creates composed state (see comments for IR) from
05873    ORIGINAL_STATE and list of arcs ARCS_MARKED_BY_INSN marked by the
05874    same insn.  If the composed state is not in STATE_STACK yet, it is
05875    pushed into STATE_STACK.  */
05876 static int
05877 create_composed_state (state_t original_state, arc_t arcs_marked_by_insn,
05878            vla_ptr_t *state_stack)
05879 {
05880   state_t state;
05881   alt_state_t alt_state, curr_alt_state;
05882   alt_state_t new_alt_state;
05883   arc_t curr_arc;
05884   arc_t next_arc;
05885   state_t state_in_table;
05886   state_t temp_state;
05887   alt_state_t canonical_alt_states_list;
05888   int alts_number;
05889   int new_state_p = 0;
05890 
05891   if (arcs_marked_by_insn == NULL)
05892     return new_state_p;
05893   if (arcs_marked_by_insn->next_arc_marked_by_insn == NULL)
05894     state = arcs_marked_by_insn->to_state;
05895   else
05896     {
05897       gcc_assert (ndfa_flag);
05898       /* Create composed state.  */
05899       state = get_free_state (0, arcs_marked_by_insn->to_state->automaton);
05900       curr_alt_state = NULL;
05901       for (curr_arc = arcs_marked_by_insn;
05902            curr_arc != NULL;
05903            curr_arc = curr_arc->next_arc_marked_by_insn)
05904   if (curr_arc->to_state->component_states == NULL)
05905     {
05906       new_alt_state = get_free_alt_state ();
05907       new_alt_state->next_alt_state = curr_alt_state;
05908       new_alt_state->state = curr_arc->to_state;
05909       curr_alt_state = new_alt_state;
05910     }
05911   else
05912     for (alt_state = curr_arc->to_state->component_states;
05913          alt_state != NULL;
05914          alt_state = alt_state->next_sorted_alt_state)
05915       {
05916         new_alt_state = get_free_alt_state ();
05917         new_alt_state->next_alt_state = curr_alt_state;
05918         new_alt_state->state = alt_state->state;
05919         gcc_assert (!alt_state->state->component_states);
05920         curr_alt_state = new_alt_state;
05921       }
05922       /* There are not identical sets in the alt state list.  */
05923       canonical_alt_states_list = uniq_sort_alt_states (curr_alt_state);
05924       if (canonical_alt_states_list->next_sorted_alt_state == NULL)
05925         {
05926           temp_state = state;
05927           state = canonical_alt_states_list->state;
05928           free_state (temp_state);
05929         }
05930       else
05931         {
05932           state->component_states = canonical_alt_states_list;
05933           state_in_table = insert_state (state);
05934           if (state_in_table != state)
05935             {
05936               gcc_assert
05937     (state_in_table->it_was_placed_in_stack_for_DFA_forming);
05938               free_state (state);
05939               state = state_in_table;
05940             }
05941           else
05942             {
05943               gcc_assert (!state->it_was_placed_in_stack_for_DFA_forming);
05944         new_state_p = 1;
05945               for (curr_alt_state = state->component_states;
05946                    curr_alt_state != NULL;
05947                    curr_alt_state = curr_alt_state->next_sorted_alt_state)
05948                 for (curr_arc = first_out_arc (curr_alt_state->state);
05949                      curr_arc != NULL;
05950                      curr_arc = next_out_arc (curr_arc))
05951       add_arc (state, curr_arc->to_state, curr_arc->insn, 1);
05952             }
05953           arcs_marked_by_insn->to_state = state;
05954           for (alts_number = 0,
05955          curr_arc = arcs_marked_by_insn->next_arc_marked_by_insn;
05956                curr_arc != NULL;
05957                curr_arc = next_arc)
05958             {
05959               next_arc = curr_arc->next_arc_marked_by_insn;
05960               remove_arc (original_state, curr_arc);
05961         alts_number++;
05962             }
05963     arcs_marked_by_insn->state_alts = alts_number;
05964         }
05965     }
05966   if (!state->it_was_placed_in_stack_for_DFA_forming)
05967     {
05968       state->it_was_placed_in_stack_for_DFA_forming = 1;
05969       VLA_PTR_ADD (*state_stack, state);
05970     }
05971   return new_state_p;
05972 }
05973 
05974 /* The function transforms nondeterministic AUTOMATON into
05975    deterministic.  */
05976 static void
05977 NDFA_to_DFA (automaton_t automaton)
05978 {
05979   state_t start_state;
05980   state_t state;
05981   decl_t decl;
05982   vla_ptr_t state_stack;
05983   int i;
05984   int states_n;
05985 
05986   VLA_PTR_CREATE (state_stack, 150, "state stack");
05987   /* Create the start state (empty state).  */
05988   start_state = automaton->start_state;
05989   start_state->it_was_placed_in_stack_for_DFA_forming = 1;
05990   VLA_PTR_ADD (state_stack, start_state);
05991   states_n = 1;
05992   while (VLA_PTR_LENGTH (state_stack) != 0)
05993     {
05994       state = VLA_PTR (state_stack, VLA_PTR_LENGTH (state_stack) - 1);
05995       VLA_PTR_SHORTEN (state_stack, 1);
05996       form_arcs_marked_by_insn (state);
05997       for (i = 0; i < description->decls_num; i++)
05998   {
05999     decl = description->decls [i];
06000     if (decl->mode == dm_insn_reserv
06001         && create_composed_state
06002            (state, DECL_INSN_RESERV (decl)->arcs_marked_by_insn,
06003       &state_stack))
06004       {
06005         states_n++;
06006         if (progress_flag && states_n % 100 == 0)
06007     fprintf (stderr, ".");
06008       }
06009   }
06010     }
06011   VLA_PTR_DELETE (state_stack);
06012 }
06013 
06014 /* The following variable value is current number (1, 2, ...) of passing
06015    graph of states.  */
06016 static int curr_state_graph_pass_num;
06017 
06018 /* This recursive function passes all states achieved from START_STATE
06019    and applies APPLIED_FUNC to them.  */
06020 static void
06021 pass_state_graph (state_t start_state, void (*applied_func) (state_t state))
06022 {
06023   arc_t arc;
06024 
06025   if (start_state->pass_num == curr_state_graph_pass_num)
06026     return;
06027   start_state->pass_num = curr_state_graph_pass_num;
06028   (*applied_func) (start_state);
06029   for (arc = first_out_arc (start_state);
06030        arc != NULL;
06031        arc = next_out_arc (arc))
06032     pass_state_graph (arc->to_state, applied_func);
06033 }
06034 
06035 /* This recursive function passes all states of AUTOMATON and applies
06036    APPLIED_FUNC to them.  */
06037 static void
06038 pass_states (automaton_t automaton, void (*applied_func) (state_t state))
06039 {
06040   curr_state_graph_pass_num++;
06041   pass_state_graph (automaton->start_state, applied_func);
06042 }
06043 
06044 /* The function initializes code for passing of all states.  */
06045 static void
06046 initiate_pass_states (void)
06047 {
06048   curr_state_graph_pass_num = 0;
06049 }
06050 
06051 /* The following vla is used for storing pointers to all achieved
06052    states.  */
06053 static vla_ptr_t all_achieved_states;
06054 
06055 /* This function is called by function pass_states to add an achieved
06056    STATE.  */
06057 static void
06058 add_achieved_state (state_t state)
06059 {
06060   VLA_PTR_ADD (all_achieved_states, state);
06061 }
06062 
06063 /* The function sets up equivalence numbers of insns which mark all
06064    out arcs of STATE by equiv_class_num_1 (if ODD_ITERATION_FLAG has
06065    nonzero value) or by equiv_class_num_2 of the destination state.
06066    The function returns number of out arcs of STATE.  */
06067 static int
06068 set_out_arc_insns_equiv_num (state_t state, int odd_iteration_flag)
06069 {
06070   int state_out_arcs_num;
06071   arc_t arc;
06072 
06073   state_out_arcs_num = 0;
06074   for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
06075     {
06076       gcc_assert (!arc->insn->insn_reserv_decl->equiv_class_num
06077       && !arc->insn->insn_reserv_decl->state_alts);
06078       state_out_arcs_num++;
06079       arc->insn->insn_reserv_decl->equiv_class_num
06080   = (odd_iteration_flag
06081            ? arc->to_state->equiv_class_num_1
06082      : arc->to_state->equiv_class_num_2);
06083       arc->insn->insn_reserv_decl->state_alts = arc->state_alts;
06084       gcc_assert (arc->insn->insn_reserv_decl->equiv_class_num
06085       && arc->insn->insn_reserv_decl->state_alts > 0);
06086     }
06087   return state_out_arcs_num;
06088 }
06089 
06090 /* The function clears equivalence numbers and alt_states in all insns
06091    which mark all out arcs of STATE.  */
06092 static void
06093 clear_arc_insns_equiv_num (state_t state)
06094 {
06095   arc_t arc;
06096 
06097   for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
06098     {
06099       arc->insn->insn_reserv_decl->equiv_class_num = 0;
06100       arc->insn->insn_reserv_decl->state_alts = 0;
06101     }
06102 }
06103 
06104 /* The function copies pointers to equivalent states from vla FROM
06105    into vla TO.  */
06106 static void
06107 copy_equiv_class (vla_ptr_t *to, const vla_ptr_t *from)
06108 {
06109   state_t *class_ptr;
06110 
06111   VLA_PTR_NULLIFY (*to);
06112   for (class_ptr = VLA_PTR_BEGIN (*from);
06113        class_ptr <= (state_t *) VLA_PTR_LAST (*from);
06114        class_ptr++)
06115     VLA_PTR_ADD (*to, *class_ptr);
06116 }
06117 
06118 /* The following function returns TRUE if STATE reserves the unit with
06119    UNIT_NUM on the first cycle.  */
06120 static int
06121 first_cycle_unit_presence (state_t state, int unit_num)
06122 {
06123   int presence_p;
06124 
06125   if (state->component_states == NULL)
06126     presence_p = test_unit_reserv (state->reservs, 0, unit_num);
06127   else
06128     presence_p
06129       = test_unit_reserv (state->component_states->state->reservs,
06130         0, unit_num);
06131   return presence_p;
06132 }
06133 
06134 /* The function returns nonzero value if STATE is not equivalent to
06135    ANOTHER_STATE from the same current partition on equivalence
06136    classes.  Another state has ANOTHER_STATE_OUT_ARCS_NUM number of
06137    output arcs.  Iteration of making equivalence partition is defined
06138    by ODD_ITERATION_FLAG.  */
06139 static int
06140 state_is_differed (state_t state, state_t another_state,
06141        int another_state_out_arcs_num, int odd_iteration_flag)
06142 {
06143   arc_t arc;
06144   int state_out_arcs_num;
06145   int i, presence1_p, presence2_p;
06146 
06147   state_out_arcs_num = 0;
06148   for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
06149     {
06150       state_out_arcs_num++;
06151       if ((odd_iteration_flag
06152            ? arc->to_state->equiv_class_num_1
06153      : arc->to_state->equiv_class_num_2)
06154           != arc->insn->insn_reserv_decl->equiv_class_num
06155     || (arc->insn->insn_reserv_decl->state_alts != arc->state_alts))
06156         return 1;
06157     }
06158   if (state_out_arcs_num != another_state_out_arcs_num)
06159     return 1;
06160   /* Now we are looking at the states with the point of view of query
06161      units.  */
06162   for (i = 0; i < description->units_num; i++)
06163     if (units_array [i]->query_p)
06164       {
06165   presence1_p = first_cycle_unit_presence (state, i);
06166   presence2_p = first_cycle_unit_presence (another_state, i);
06167   if ((presence1_p && !presence2_p) || (!presence1_p && presence2_p))
06168     return 1;
06169       }
06170   return 0;
06171 }
06172 
06173 /* The function makes initial partition of STATES on equivalent
06174    classes.  */
06175 static state_t
06176 init_equiv_class (state_t *states, int states_num)
06177 {
06178   state_t *state_ptr;
06179   state_t result_equiv_class;
06180 
06181   result_equiv_class = NULL;
06182   for (state_ptr = states; state_ptr < states + states_num; state_ptr++)
06183     {
06184       (*state_ptr)->equiv_class_num_1 = 1;
06185       (*state_ptr)->next_equiv_class_state = result_equiv_class;
06186       result_equiv_class = *state_ptr;
06187     }
06188   return result_equiv_class;
06189 }
06190 
06191 /* The function processes equivalence class given by its pointer
06192    EQUIV_CLASS_PTR on odd iteration if ODD_ITERATION_FLAG.  If there
06193    are not equivalent states, the function partitions the class
06194    removing nonequivalent states and placing them in
06195    *NEXT_ITERATION_CLASSES, increments *NEW_EQUIV_CLASS_NUM_PTR ans
06196    assigns it to the state equivalence number.  If the class has been
06197    partitioned, the function returns nonzero value.  */
06198 static int
06199 partition_equiv_class (state_t *equiv_class_ptr, int odd_iteration_flag,
06200            vla_ptr_t *next_iteration_classes,
06201            int *new_equiv_class_num_ptr)
06202 {
06203   state_t new_equiv_class;
06204   int partition_p;
06205   state_t first_state;
06206   state_t curr_state;
06207   state_t prev_state;
06208   state_t next_state;
06209   int out_arcs_num;
06210 
06211   partition_p = 0;
06212   gcc_assert (*equiv_class_ptr);
06213   for (first_state = *equiv_class_ptr;
06214        first_state != NULL;
06215        first_state = new_equiv_class)
06216     {
06217       new_equiv_class = NULL;
06218       if (first_state->next_equiv_class_state != NULL)
06219   {
06220     /* There are more one states in the class equivalence.  */
06221     out_arcs_num = set_out_arc_insns_equiv_num (first_state,
06222                   odd_iteration_flag);
06223     for (prev_state = first_state,
06224      curr_state = first_state->next_equiv_class_state;
06225          curr_state != NULL;
06226          curr_state = next_state)
06227       {
06228         next_state = curr_state->next_equiv_class_state;
06229         if (state_is_differed (curr_state, first_state, out_arcs_num,
06230              odd_iteration_flag))
06231     {
06232       /* Remove curr state from the class equivalence.  */
06233       prev_state->next_equiv_class_state = next_state;
06234       /* Add curr state to the new class equivalence.  */
06235       curr_state->next_equiv_class_state = new_equiv_class;
06236       if (new_equiv_class == NULL)
06237         (*new_equiv_class_num_ptr)++;
06238       if (odd_iteration_flag)
06239         curr_state->equiv_class_num_2 = *new_equiv_class_num_ptr;
06240       else
06241         curr_state->equiv_class_num_1 = *new_equiv_class_num_ptr;
06242       new_equiv_class = curr_state;
06243       partition_p = 1;
06244     }
06245         else
06246     prev_state = curr_state;
06247       }
06248     clear_arc_insns_equiv_num (first_state);
06249   }
06250       if (new_equiv_class != NULL)
06251   VLA_PTR_ADD  (*next_iteration_classes, new_equiv_class);
06252     }
06253   return partition_p;
06254 }
06255 
06256 /* The function finds equivalent states of AUTOMATON.  */
06257 static void
06258 evaluate_equiv_classes (automaton_t automaton, vla_ptr_t *equiv_classes)
06259 {
06260   state_t new_equiv_class;
06261   int new_equiv_class_num;
06262   int odd_iteration_flag;
06263   int finish_flag;
06264   vla_ptr_t next_iteration_classes;
06265   state_t *equiv_class_ptr;
06266   state_t *state_ptr;
06267 
06268   VLA_PTR_CREATE (all_achieved_states, 1500, "all achieved states");
06269   pass_states (automaton, add_achieved_state);
06270   new_equiv_class = init_equiv_class (VLA_PTR_BEGIN (all_achieved_states),
06271                                       VLA_PTR_LENGTH (all_achieved_states));
06272   odd_iteration_flag = 0;
06273   new_equiv_class_num = 1;
06274   VLA_PTR_CREATE (next_iteration_classes, 150, "next iteration classes");
06275   VLA_PTR_ADD (next_iteration_classes, new_equiv_class);
06276   do
06277     {
06278       odd_iteration_flag = !odd_iteration_flag;
06279       finish_flag = 1;
06280       copy_equiv_class (equiv_classes, &next_iteration_classes);
06281       /* Transfer equiv numbers for the next iteration.  */
06282       for (state_ptr = VLA_PTR_BEGIN (all_achieved_states);
06283      state_ptr <= (state_t *) VLA_PTR_LAST (all_achieved_states);
06284            state_ptr++)
06285   if (odd_iteration_flag)
06286     (*state_ptr)->equiv_class_num_2 = (*state_ptr)->equiv_class_num_1;
06287   else
06288     (*state_ptr)->equiv_class_num_1 = (*state_ptr)->equiv_class_num_2;
06289       for (equiv_class_ptr = VLA_PTR_BEGIN (*equiv_classes);
06290            equiv_class_ptr <= (state_t *) VLA_PTR_LAST (*equiv_classes);
06291            equiv_class_ptr++)
06292   if (partition_equiv_class (equiv_class_ptr, odd_iteration_flag,
06293            &next_iteration_classes,
06294            &new_equiv_class_num))
06295     finish_flag = 0;
06296     }
06297   while (!finish_flag);
06298   VLA_PTR_DELETE (next_iteration_classes);
06299   VLA_PTR_DELETE (all_achieved_states);
06300 }
06301 
06302 /* The function merges equivalent states of AUTOMATON.  */
06303 static void
06304 merge_states (automaton_t automaton, vla_ptr_t *equiv_classes)
06305 {
06306   state_t *equiv_class_ptr;
06307   state_t curr_state;
06308   state_t new_state;
06309   state_t first_class_state;
06310   alt_state_t alt_states;
06311   alt_state_t alt_state, new_alt_state;
06312   arc_t curr_arc;
06313   arc_t next_arc;
06314 
06315   /* Create states corresponding to equivalence classes containing two
06316      or more states.  */
06317   for (equiv_class_ptr = VLA_PTR_BEGIN (*equiv_classes);
06318        equiv_class_ptr <= (state_t *) VLA_PTR_LAST (*equiv_classes);
06319        equiv_class_ptr++)
06320     if ((*equiv_class_ptr)->next_equiv_class_state != NULL)
06321       {
06322         /* There are more one states in the class equivalence.  */
06323         /* Create new compound state.  */
06324         new_state = get_free_state (0, automaton);
06325         alt_states = NULL;
06326         first_class_state = *equiv_class_ptr;
06327         for (curr_state = first_class_state;
06328              curr_state != NULL;
06329              curr_state = curr_state->next_equiv_class_state)
06330           {
06331             curr_state->equiv_class_state = new_state;
06332       if (curr_state->component_states == NULL)
06333         {
06334     new_alt_state = get_free_alt_state ();
06335     new_alt_state->state = curr_state;
06336     new_alt_state->next_alt_state = alt_states;
06337     alt_states = new_alt_state;
06338         }
06339       else
06340         for (alt_state = curr_state->component_states;
06341        alt_state != NULL;
06342        alt_state = alt_state->next_sorted_alt_state)
06343     {
06344       new_alt_state = get_free_alt_state ();
06345       new_alt_state->state = alt_state->state;
06346       new_alt_state->next_alt_state = alt_states;
06347       alt_states = new_alt_state;
06348     }
06349           }
06350   /* Its is important that alt states were sorted before and
06351            after merging to have the same querying results.  */
06352         new_state->component_states = uniq_sort_alt_states (alt_states);
06353       }
06354     else
06355       (*equiv_class_ptr)->equiv_class_state = *equiv_class_ptr;
06356   for (equiv_class_ptr = VLA_PTR_BEGIN (*equiv_classes);
06357        equiv_class_ptr <= (state_t *) VLA_PTR_LAST (*equiv_classes);
06358        equiv_class_ptr++)
06359     if ((*equiv_class_ptr)->next_equiv_class_state != NULL)
06360       {
06361         first_class_state = *equiv_class_ptr;
06362         /* Create new arcs output from the state corresponding to
06363            equiv class.  */
06364         for (curr_arc = first_out_arc (first_class_state);
06365              curr_arc != NULL;
06366              curr_arc = next_out_arc (curr_arc))
06367           add_arc (first_class_state->equiv_class_state,
06368                    curr_arc->to_state->equiv_class_state,
06369        curr_arc->insn, curr_arc->state_alts);
06370         /* Delete output arcs from states of given class equivalence.  */
06371         for (curr_state = first_class_state;
06372              curr_state != NULL;
06373              curr_state = curr_state->next_equiv_class_state)
06374           {
06375             if (automaton->start_state == curr_state)
06376               automaton->start_state = curr_state->equiv_class_state;
06377             /* Delete the state and its output arcs.  */
06378             for (curr_arc = first_out_arc (curr_state);
06379                  curr_arc != NULL;
06380                  curr_arc = next_arc)
06381               {
06382                 next_arc = next_out_arc (curr_arc);
06383                 free_arc (curr_arc);
06384               }
06385           }
06386       }
06387     else
06388       {
06389         /* Change `to_state' of arcs output from the state of given
06390            equivalence class.  */
06391         for (curr_arc = first_out_arc (*equiv_class_ptr);
06392              curr_arc != NULL;
06393              curr_arc = next_out_arc (curr_arc))
06394           curr_arc->to_state = curr_arc->to_state->equiv_class_state;
06395       }
06396 }
06397 
06398 /* The function sets up new_cycle_p for states if there is arc to the
06399    state marked by advance_cycle_insn_decl.  */
06400 static void
06401 set_new_cycle_flags (state_t state)
06402 {
06403   arc_t arc;
06404 
06405   for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
06406     if (arc->insn->insn_reserv_decl
06407   == DECL_INSN_RESERV (advance_cycle_insn_decl))
06408       arc->to_state->new_cycle_p = 1;
06409 }
06410 
06411 /* The top level function for minimization of deterministic
06412    AUTOMATON.  */
06413 static void
06414 minimize_DFA (automaton_t automaton)
06415 {
06416   vla_ptr_t equiv_classes;
06417 
06418   VLA_PTR_CREATE (equiv_classes, 1500, "equivalence classes");
06419   evaluate_equiv_classes (automaton, &equiv_classes);
06420   merge_states (automaton, &equiv_classes);
06421   pass_states (automaton, set_new_cycle_flags);
06422   VLA_PTR_DELETE (equiv_classes);
06423 }
06424 
06425 /* Values of two variables are counted number of states and arcs in an
06426    automaton.  */
06427 static int curr_counted_states_num;
06428 static int curr_counted_arcs_num;
06429 
06430 /* The function is called by function `pass_states' to count states
06431    and arcs of an automaton.  */
06432 static void
06433 incr_states_and_arcs_nums (state_t state)
06434 {
06435   arc_t arc;
06436 
06437   curr_counted_states_num++;
06438   for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
06439     curr_counted_arcs_num++;
06440 }
06441 
06442 /* The function counts states and arcs of AUTOMATON.  */
06443 static void
06444 count_states_and_arcs (automaton_t automaton, int *states_num,
06445            int *arcs_num)
06446 {
06447   curr_counted_states_num = 0;
06448   curr_counted_arcs_num = 0;
06449   pass_states (automaton, incr_states_and_arcs_nums);
06450   *states_num = curr_counted_states_num;
06451   *arcs_num = curr_counted_arcs_num;
06452 }
06453 
06454 /* The function builds one DFA AUTOMATON for fast pipeline hazards
06455    recognition after checking and simplifying IR of the
06456    description.  */
06457 static void
06458 build_automaton (automaton_t automaton)
06459 {
06460   int states_num;
06461   int arcs_num;
06462 
06463   ticker_on (&NDFA_time);
06464   if (progress_flag)
06465     {
06466       if (automaton->corresponding_automaton_decl == NULL)
06467   fprintf (stderr, "Create anonymous automaton");
06468       else
06469   fprintf (stderr, "Create automaton `%s'",
06470      automaton->corresponding_automaton_decl->name);
06471       fprintf (stderr, " (1 dot is 100 new states):");
06472     }
06473   make_automaton (automaton);
06474   if (progress_flag)
06475     fprintf (stderr, " done\n");
06476   ticker_off (&NDFA_time);
06477   count_states_and_arcs (automaton, &states_num, &arcs_num);
06478   automaton->NDFA_states_num = states_num;
06479   automaton->NDFA_arcs_num = arcs_num;
06480   ticker_on (&NDFA_to_DFA_time);
06481   if (progress_flag)
06482     {
06483       if (automaton->corresponding_automaton_decl == NULL)
06484   fprintf (stderr, "Make anonymous DFA");
06485       else
06486   fprintf (stderr, "Make DFA `%s'",
06487      automaton->corresponding_automaton_decl->name);
06488       fprintf (stderr, " (1 dot is 100 new states):");
06489     }
06490   NDFA_to_DFA (automaton);
06491   if (progress_flag)
06492     fprintf (stderr, " done\n");
06493   ticker_off (&NDFA_to_DFA_time);
06494   count_states_and_arcs (automaton, &states_num, &arcs_num);
06495   automaton->DFA_states_num = states_num;
06496   automaton->DFA_arcs_num = arcs_num;
06497   if (!no_minimization_flag)
06498     {
06499       ticker_on (&minimize_time);
06500       if (progress_flag)
06501   {
06502     if (automaton->corresponding_automaton_decl == NULL)
06503       fprintf (stderr, "Minimize anonymous DFA...");
06504     else
06505       fprintf (stderr, "Minimize DFA `%s'...",
06506          automaton->corresponding_automaton_decl->name);
06507   }
06508       minimize_DFA (automaton);
06509       if (progress_flag)
06510   fprintf (stderr, "done\n");
06511       ticker_off (&minimize_time);
06512       count_states_and_arcs (automaton, &states_num, &arcs_num);
06513       automaton->minimal_DFA_states_num = states_num;
06514       automaton->minimal_DFA_arcs_num = arcs_num;
06515     }
06516 }
06517 
06518 
06519 
06520 /* The page contains code for enumeration  of all states of an automaton.  */
06521 
06522 /* Variable used for enumeration of all states of an automaton.  Its
06523    value is current number of automaton states.  */
06524 static int curr_state_order_num;
06525 
06526 /* The function is called by function `pass_states' for enumerating
06527    states.  */
06528 static void
06529 set_order_state_num (state_t state)
06530 {
06531   state->order_state_num = curr_state_order_num;
06532   curr_state_order_num++;
06533 }
06534 
06535 /* The function enumerates all states of AUTOMATON.  */
06536 static void
06537 enumerate_states (automaton_t automaton)
06538 {
06539   curr_state_order_num = 0;
06540   pass_states (automaton, set_order_state_num);
06541   automaton->achieved_states_num = curr_state_order_num;
06542 }
06543 
06544 
06545 
06546 /* The page contains code for finding equivalent automaton insns
06547    (ainsns).  */
06548 
06549 /* The function inserts AINSN into cyclic list
06550    CYCLIC_EQUIV_CLASS_INSN_LIST of ainsns.  */
06551 static ainsn_t
06552 insert_ainsn_into_equiv_class (ainsn_t ainsn,
06553              ainsn_t cyclic_equiv_class_insn_list)
06554 {
06555   if (cyclic_equiv_class_insn_list == NULL)
06556     ainsn->next_equiv_class_insn = ainsn;
06557   else
06558     {
06559       ainsn->next_equiv_class_insn
06560         = cyclic_equiv_class_insn_list->next_equiv_class_insn;
06561       cyclic_equiv_class_insn_list->next_equiv_class_insn = ainsn;
06562     }
06563   return ainsn;
06564 }
06565 
06566 /* The function deletes equiv_class_insn into cyclic list of
06567    equivalent ainsns.  */
06568 static void
06569 delete_ainsn_from_equiv_class (ainsn_t equiv_class_insn)
06570 {
06571   ainsn_t curr_equiv_class_insn;
06572   ainsn_t prev_equiv_class_insn;
06573 
06574   prev_equiv_class_insn = equiv_class_insn;
06575   for (curr_equiv_class_insn = equiv_class_insn->next_equiv_class_insn;
06576        curr_equiv_class_insn != equiv_class_insn;
06577        curr_equiv_class_insn = curr_equiv_class_insn->next_equiv_class_insn)
06578     prev_equiv_class_insn = curr_equiv_class_insn;
06579   if (prev_equiv_class_insn != equiv_class_insn)
06580     prev_equiv_class_insn->next_equiv_class_insn
06581       = equiv_class_insn->next_equiv_class_insn;
06582 }
06583 
06584 /* The function processes AINSN of a state in order to find equivalent
06585    ainsns.  INSN_ARCS_ARRAY is table: code of insn -> out arc of the
06586    state.  */
06587 static void
06588 process_insn_equiv_class (ainsn_t ainsn, arc_t *insn_arcs_array)
06589 {
06590   ainsn_t next_insn;
06591   ainsn_t curr_insn;
06592   ainsn_t cyclic_insn_list;
06593   arc_t arc;
06594 
06595   gcc_assert (insn_arcs_array [ainsn->insn_reserv_decl->insn_num]);
06596   curr_insn = ainsn;
06597   /* New class of ainsns which are not equivalent to given ainsn.  */
06598   cyclic_insn_list = NULL;
06599   do
06600     {
06601       next_insn = curr_insn->next_equiv_class_insn;
06602       arc = insn_arcs_array [curr_insn->insn_reserv_decl->insn_num];
06603       if (arc == NULL
06604           || (insn_arcs_array [ainsn->insn_reserv_decl->insn_num]->to_state
06605               != arc->to_state))
06606         {
06607           delete_ainsn_from_equiv_class (curr_insn);
06608           cyclic_insn_list = insert_ainsn_into_equiv_class (curr_insn,
06609                   cyclic_insn_list);
06610         }
06611       curr_insn = next_insn;
06612     }
06613   while (curr_insn != ainsn);
06614 }
06615 
06616 /* The function processes STATE in order to find equivalent ainsns.  */
06617 static void
06618 process_state_for_insn_equiv_partition (state_t state)
06619 {
06620   arc_t arc;
06621   arc_t *insn_arcs_array;
06622   int i;
06623   vla_ptr_t insn_arcs_vect;
06624 
06625   VLA_PTR_CREATE (insn_arcs_vect, 500, "insn arcs vector");
06626   VLA_PTR_EXPAND (insn_arcs_vect, description->insns_num);
06627   insn_arcs_array = VLA_PTR_BEGIN (insn_arcs_vect);
06628   /* Process insns of the arcs.  */
06629   for (i = 0; i < description->insns_num; i++)
06630     insn_arcs_array [i] = NULL;
06631   for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
06632     insn_arcs_array [arc->insn->insn_reserv_decl->insn_num] = arc;
06633   for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
06634     process_insn_equiv_class (arc->insn, insn_arcs_array);
06635   VLA_PTR_DELETE (insn_arcs_vect);
06636 }
06637 
06638 /* The function searches for equivalent ainsns of AUTOMATON.  */
06639 static void
06640 set_insn_equiv_classes (automaton_t automaton)
06641 {
06642   ainsn_t ainsn;
06643   ainsn_t first_insn;
06644   ainsn_t curr_insn;
06645   ainsn_t cyclic_insn_list;
06646   ainsn_t insn_with_same_reservs;
06647   int equiv_classes_num;
06648 
06649   /* All insns are included in one equivalence class.  */
06650   cyclic_insn_list = NULL;
06651   for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
06652     if (ainsn->first_insn_with_same_reservs)
06653       cyclic_insn_list = insert_ainsn_into_equiv_class (ainsn,
06654               cyclic_insn_list);
06655   /* Process insns in order to make equivalence partition.  */
06656   pass_states (automaton, process_state_for_insn_equiv_partition);
06657   /* Enumerate equiv classes.  */
06658   for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
06659     /* Set undefined value.  */
06660     ainsn->insn_equiv_class_num = -1;
06661   equiv_classes_num = 0;
06662   for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
06663     if (ainsn->insn_equiv_class_num < 0)
06664       {
06665         first_insn = ainsn;
06666         gcc_assert (first_insn->first_insn_with_same_reservs);
06667         first_insn->first_ainsn_with_given_equivalence_num = 1;
06668         curr_insn = first_insn;
06669         do
06670           {
06671             for (insn_with_same_reservs = curr_insn;
06672                  insn_with_same_reservs != NULL;
06673                  insn_with_same_reservs
06674        = insn_with_same_reservs->next_same_reservs_insn)
06675               insn_with_same_reservs->insn_equiv_class_num = equiv_classes_num;
06676             curr_insn = curr_insn->next_equiv_class_insn;
06677           }
06678         while (curr_insn != first_insn);
06679         equiv_classes_num++;
06680       }
06681   automaton->insn_equiv_classes_num = equiv_classes_num;
06682 }
06683 
06684 
06685 
06686 /* This page contains code for creating DFA(s) and calls functions
06687    building them.  */
06688 
06689 
06690 /* The following value is used to prevent floating point overflow for
06691    estimating an automaton bound.  The value should be less DBL_MAX on
06692    the host machine.  We use here approximate minimum of maximal
06693    double floating point value required by ANSI C standard.  It
06694    will work for non ANSI sun compiler too.  */
06695 
06696 #define MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND  1.0E37
06697 
06698 /* The function estimate size of the single DFA used by PHR (pipeline
06699    hazards recognizer).  */
06700 static double
06701 estimate_one_automaton_bound (void)
06702 {
06703   decl_t decl;
06704   double one_automaton_estimation_bound;
06705   double root_value;
06706   int i;
06707 
06708   one_automaton_estimation_bound = 1.0;
06709   for (i = 0; i < description->decls_num; i++)
06710     {
06711       decl = description->decls [i];
06712       if (decl->mode == dm_unit)
06713   {
06714     root_value = exp (log (DECL_UNIT (decl)->max_occ_cycle_num
06715          - DECL_UNIT (decl)->min_occ_cycle_num + 1.0)
06716                             / automata_num);
06717     if (MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND / root_value
06718         > one_automaton_estimation_bound)
06719       one_automaton_estimation_bound *= root_value;
06720   }
06721     }
06722   return one_automaton_estimation_bound;
06723 }
06724 
06725 /* The function compares unit declarations according to their maximal
06726    cycle in reservations.  */
06727 static int
06728 compare_max_occ_cycle_nums (const void *unit_decl_1,
06729           const void *unit_decl_2)
06730 {
06731   if ((DECL_UNIT (*(decl_t *) unit_decl_1)->max_occ_cycle_num)
06732       < (DECL_UNIT (*(decl_t *) unit_decl_2)->max_occ_cycle_num))
06733     return 1;
06734   else if ((DECL_UNIT (*(decl_t *) unit_decl_1)->max_occ_cycle_num)
06735      == (DECL_UNIT (*(decl_t *) unit_decl_2)->max_occ_cycle_num))
06736     return 0;
06737   else
06738     return -1;
06739 }
06740 
06741 /* The function makes heuristic assigning automata to units.  Actually
06742    efficacy of the algorithm has been checked yet??? */
06743 static void
06744 units_to_automata_heuristic_distr (void)
06745 {
06746   double estimation_bound;
06747   decl_t decl;
06748   decl_t *unit_decl_ptr;
06749   int automaton_num;
06750   int rest_units_num;
06751   double bound_value;
06752   vla_ptr_t unit_decls;
06753   int i;
06754 
06755   if (description->units_num == 0)
06756     return;
06757   estimation_bound = estimate_one_automaton_bound ();
06758   VLA_PTR_CREATE (unit_decls, 150, "unit decls");
06759   for (i = 0; i < description->decls_num; i++)
06760     {
06761       decl = description->decls [i];
06762       if (decl->mode == dm_unit)
06763   VLA_PTR_ADD (unit_decls, decl);
06764     }
06765   qsort (VLA_PTR_BEGIN (unit_decls), VLA_PTR_LENGTH (unit_decls),
06766          sizeof (decl_t), compare_max_occ_cycle_nums);
06767   automaton_num = 0;
06768   unit_decl_ptr = VLA_PTR_BEGIN (unit_decls);
06769   bound_value = DECL_UNIT (*unit_decl_ptr)->max_occ_cycle_num;
06770   DECL_UNIT (*unit_decl_ptr)->corresponding_automaton_num = automaton_num;
06771   for (unit_decl_ptr++;
06772        unit_decl_ptr <= (decl_t *) VLA_PTR_LAST (unit_decls);
06773        unit_decl_ptr++)
06774     {
06775       rest_units_num
06776   = ((decl_t *) VLA_PTR_LAST (unit_decls) - unit_decl_ptr + 1);
06777       gcc_assert (automata_num - automaton_num - 1 <= rest_units_num);
06778       if (automaton_num < automata_num - 1
06779           && ((automata_num - automaton_num - 1 == rest_units_num)
06780               || (bound_value
06781                   > (estimation_bound
06782          / (DECL_UNIT (*unit_decl_ptr)->max_occ_cycle_num)))))
06783         {
06784           bound_value = DECL_UNIT (*unit_decl_ptr)->max_occ_cycle_num;
06785           automaton_num++;
06786         }
06787       else
06788         bound_value *= DECL_UNIT (*unit_decl_ptr)->max_occ_cycle_num;
06789       DECL_UNIT (*unit_decl_ptr)->corresponding_automaton_num = automaton_num;
06790     }
06791   gcc_assert (automaton_num == automata_num - 1);
06792   VLA_PTR_DELETE (unit_decls);
06793 }
06794 
06795 /* The functions creates automaton insns for each automata.  Automaton
06796    insn is simply insn for given automaton which makes reservation
06797    only of units of the automaton.  */
06798 static ainsn_t
06799 create_ainsns (void)
06800 {
06801   decl_t decl;
06802   ainsn_t first_ainsn;
06803   ainsn_t curr_ainsn;
06804   ainsn_t prev_ainsn;
06805   int i;
06806 
06807   first_ainsn = NULL;
06808   prev_ainsn = NULL;
06809   for (i = 0; i < description->decls_num; i++)
06810     {
06811       decl = description->decls [i];
06812       if (decl->mode == dm_insn_reserv)
06813   {
06814     curr_ainsn = create_node (sizeof (struct ainsn));
06815     curr_ainsn->insn_reserv_decl = DECL_INSN_RESERV (decl);
06816     curr_ainsn->important_p = FALSE;
06817     curr_ainsn->next_ainsn = NULL;
06818     if (prev_ainsn == NULL)
06819       first_ainsn = curr_ainsn;
06820     else
06821       prev_ainsn->next_ainsn = curr_ainsn;
06822     prev_ainsn = curr_ainsn;
06823   }
06824     }
06825   return first_ainsn;
06826 }
06827 
06828 /* The function assigns automata to units according to constructions
06829    `define_automaton' in the description.  */
06830 static void
06831 units_to_automata_distr (void)
06832 {
06833   decl_t decl;
06834   int i;
06835 
06836   for (i = 0; i < description->decls_num; i++)
06837     {
06838       decl = description->decls [i];
06839       if (decl->mode == dm_unit)
06840   {
06841     if (DECL_UNIT (decl)->automaton_decl == NULL
06842         || (DECL_UNIT (decl)->automaton_decl->corresponding_automaton
06843       == NULL))
06844       /* Distribute to the first automaton.  */
06845       DECL_UNIT (decl)->corresponding_automaton_num = 0;
06846     else
06847       DECL_UNIT (decl)->corresponding_automaton_num
06848         = (DECL_UNIT (decl)->automaton_decl
06849                  ->corresponding_automaton->automaton_order_num);
06850   }
06851     }
06852 }
06853 
06854 /* The function creates DFA(s) for fast pipeline hazards recognition
06855    after checking and simplifying IR of the description.  */
06856 static void
06857 create_automata (void)
06858 {
06859   automaton_t curr_automaton;
06860   automaton_t prev_automaton;
06861   decl_t decl;
06862   int curr_automaton_num;
06863   int i;
06864 
06865   if (automata_num != 0)
06866     {
06867       units_to_automata_heuristic_distr ();
06868       for (prev_automaton = NULL, curr_automaton_num = 0;
06869            curr_automaton_num < automata_num;
06870            curr_automaton_num++, prev_automaton = curr_automaton)
06871         {
06872     curr_automaton = create_node (sizeof (struct automaton));
06873     curr_automaton->ainsn_list = create_ainsns ();
06874     curr_automaton->corresponding_automaton_decl = NULL;
06875     curr_automaton->next_automaton = NULL;
06876           curr_automaton->automaton_order_num = curr_automaton_num;
06877           if (prev_automaton == NULL)
06878             description->first_automaton = curr_automaton;
06879           else
06880             prev_automaton->next_automaton = curr_automaton;
06881         }
06882     }
06883   else
06884     {
06885       curr_automaton_num = 0;
06886       prev_automaton = NULL;
06887       for (i = 0; i < description->decls_num; i++)
06888   {
06889     decl = description->decls [i];
06890     if (decl->mode == dm_automaton
06891         && DECL_AUTOMATON (decl)->automaton_is_used)
06892       {
06893         curr_automaton = create_node (sizeof (struct automaton));
06894         curr_automaton->ainsn_list = create_ainsns ();
06895         curr_automaton->corresponding_automaton_decl
06896     = DECL_AUTOMATON (decl);
06897         curr_automaton->next_automaton = NULL;
06898         DECL_AUTOMATON (decl)->corresponding_automaton = curr_automaton;
06899         curr_automaton->automaton_order_num = curr_automaton_num;
06900         if (prev_automaton == NULL)
06901     description->first_automaton = curr_automaton;
06902         else
06903     prev_automaton->next_automaton = curr_automaton;
06904         curr_automaton_num++;
06905         prev_automaton = curr_automaton;
06906       }
06907   }
06908       if (curr_automaton_num == 0)
06909   {
06910     curr_automaton = create_node (sizeof (struct automaton));
06911     curr_automaton->ainsn_list = create_ainsns ();
06912     curr_automaton->corresponding_automaton_decl = NULL;
06913     curr_automaton->next_automaton = NULL;
06914     description->first_automaton = curr_automaton;
06915   }
06916       units_to_automata_distr ();
06917     }
06918   NDFA_time = create_ticker ();
06919   ticker_off (&NDFA_time);
06920   NDFA_to_DFA_time = create_ticker ();
06921   ticker_off (&NDFA_to_DFA_time);
06922   minimize_time = create_ticker ();
06923   ticker_off (&minimize_time);
06924   equiv_time = create_ticker ();
06925   ticker_off (&equiv_time);
06926   for (curr_automaton = description->first_automaton;
06927        curr_automaton != NULL;
06928        curr_automaton = curr_automaton->next_automaton)
06929     {
06930       if (progress_flag)
06931   {
06932     if (curr_automaton->corresponding_automaton_decl == NULL)
06933       fprintf (stderr, "Prepare anonymous automaton creation ... ");
06934     else
06935       fprintf (stderr, "Prepare automaton `%s' creation...",
06936          curr_automaton->corresponding_automaton_decl->name);
06937   }
06938       create_alt_states (curr_automaton);
06939       form_ainsn_with_same_reservs (curr_automaton);
06940       if (progress_flag)
06941   fprintf (stderr, "done\n");
06942       build_automaton (curr_automaton);
06943       enumerate_states (curr_automaton);
06944       ticker_on (&equiv_time);
06945       set_insn_equiv_classes (curr_automaton);
06946       ticker_off (&equiv_time);
06947     }
06948 }
06949 
06950 
06951 
06952 /* This page contains code for forming string representation of
06953    regexp.  The representation is formed on IR obstack.  So you should
06954    not work with IR obstack between regexp_representation and
06955    finish_regexp_representation calls.  */
06956 
06957 /* This recursive function forms string representation of regexp
06958    (without tailing '\0').  */
06959 static void
06960 form_regexp (regexp_t regexp)
06961 {
06962   int i;
06963 
06964   switch (regexp->mode)
06965     {
06966     case rm_unit: case rm_reserv:
06967       {
06968   const char *name = (regexp->mode == rm_unit
06969           ? REGEXP_UNIT (regexp)->name
06970           : REGEXP_RESERV (regexp)->name);
06971   
06972   obstack_grow (&irp, name, strlen (name));
06973   break;
06974       }
06975       
06976     case rm_sequence:
06977       for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
06978   {
06979     if (i != 0)
06980       obstack_1grow (&irp, ',');
06981     form_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
06982   }
06983       break;
06984 
06985     case rm_allof:
06986       obstack_1grow (&irp, '(');
06987       for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
06988   {
06989     if (i != 0)
06990             obstack_1grow (&irp, '+');
06991     if (REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_sequence
06992               || REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_oneof)
06993             obstack_1grow (&irp, '(');
06994     form_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
06995     if (REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_sequence
06996               || REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_oneof)
06997             obstack_1grow (&irp, ')');
06998         }
06999       obstack_1grow (&irp, ')');
07000       break;
07001       
07002     case rm_oneof:
07003       for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
07004   {
07005     if (i != 0)
07006       obstack_1grow (&irp, '|');
07007     if (REGEXP_ONEOF (regexp)->regexps[i]->mode == rm_sequence)
07008       obstack_1grow (&irp, '(');
07009     form_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
07010     if (REGEXP_ONEOF (regexp)->regexps[i]->mode == rm_sequence)
07011           obstack_1grow (&irp, ')');
07012   }
07013       break;
07014       
07015     case rm_repeat:
07016       {
07017   char digits [30];
07018   
07019   if (REGEXP_REPEAT (regexp)->regexp->mode == rm_sequence
07020       || REGEXP_REPEAT (regexp)->regexp->mode == rm_allof
07021       || REGEXP_REPEAT (regexp)->regexp->mode == rm_oneof)
07022     obstack_1grow (&irp, '(');
07023   form_regexp (REGEXP_REPEAT (regexp)->regexp);
07024   if (REGEXP_REPEAT (regexp)->regexp->mode == rm_sequence
07025       || REGEXP_REPEAT (regexp)->regexp->mode == rm_allof
07026       || REGEXP_REPEAT (regexp)->regexp->mode == rm_oneof)
07027     obstack_1grow (&irp, ')');
07028   sprintf (digits, "*%d", REGEXP_REPEAT (regexp)->repeat_num);
07029   obstack_grow (&irp, digits, strlen (digits));
07030   break;
07031       }
07032 
07033     case rm_nothing:
07034       obstack_grow (&irp, NOTHING_NAME, strlen (NOTHING_NAME));
07035       break;
07036 
07037     default:
07038       gcc_unreachable ();
07039     }
07040 }
07041 
07042 /* The function returns string representation of REGEXP on IR
07043    obstack.  */
07044 static const char *
07045 regexp_representation (regexp_t regexp)
07046 {
07047   form_regexp (regexp);
07048   obstack_1grow (&irp, '\0');
07049   return obstack_base (&irp);
07050 }
07051 
07052 /* The function frees memory allocated for last formed string
07053    representation of regexp.  */
07054 static void
07055 finish_regexp_representation (void)
07056 {
07057   int length = obstack_object_size (&irp);
07058 
07059   obstack_blank_fast (&irp, -length);
07060 }
07061 
07062 
07063 
07064 /* This page contains code for output PHR (pipeline hazards recognizer).  */
07065 
07066 /* The function outputs minimal C type which is sufficient for
07067    representation numbers in range min_range_value and
07068    max_range_value.  Because host machine and build machine may be
07069    different, we use here minimal values required by ANSI C standard
07070    instead of UCHAR_MAX, SHRT_MAX, SHRT_MIN, etc.  This is a good
07071    approximation.  */
07072 
07073 static void
07074 output_range_type (FILE *f, long int min_range_value,
07075        long int max_range_value)
07076 {
07077   if (min_range_value >= 0 && max_range_value <= 255)
07078     fprintf (f, "unsigned char");
07079   else if (min_range_value >= -127 && max_range_value <= 127)
07080     fprintf (f, "signed char");
07081   else if (min_range_value >= 0 && max_range_value <= 65535)
07082     fprintf (f, "unsigned short");
07083   else if (min_range_value >= -32767 && max_range_value <= 32767)
07084     fprintf (f, "short");
07085   else
07086     fprintf (f, "int");
07087 }
07088 
07089 /* The following macro value is used as value of member
07090    `longest_path_length' of state when we are processing path and the
07091    state on the path.  */
07092 
07093 #define ON_THE_PATH -2
07094 
07095 /* The following recursive function searches for the length of the
07096    longest path starting from STATE which does not contain cycles and
07097    `cycle advance' arcs.  */
07098 
07099 static int
07100 longest_path_length (state_t state)
07101 {
07102   arc_t arc;
07103   int length, result;
07104 
07105   if (state->longest_path_length != UNDEFINED_LONGEST_PATH_LENGTH)
07106     {
07107       /* We don't expect the path cycle here.  Our graph may contain
07108          only cycles with one state on the path not containing `cycle
07109          advance' arcs -- see comment below.  */
07110       gcc_assert (state->longest_path_length != ON_THE_PATH);
07111       
07112       /* We already visited the state.  */
07113       return state->longest_path_length;
07114     }
07115 
07116   result = 0;
07117   for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
07118     /* Ignore cycles containing one state and `cycle advance' arcs.  */
07119     if (arc->to_state != state
07120   && (arc->insn->insn_reserv_decl
07121       != DECL_INSN_RESERV (advance_cycle_insn_decl)))
07122     {
07123       length = longest_path_length (arc->to_state);
07124       if (length > result)
07125   result = length;
07126     }
07127   state->longest_path_length = result + 1;
07128   return result;
07129 }
07130 
07131 /* The following variable value is value of the corresponding global
07132    variable in the automaton based pipeline interface.  */
07133 
07134 static int max_dfa_issue_rate;
07135 
07136 /* The following function processes the longest path length staring
07137    from STATE to find MAX_DFA_ISSUE_RATE.  */
07138 
07139 static void
07140 process_state_longest_path_length (state_t state)
07141 {
07142   int value;
07143 
07144   value = longest_path_length (state);
07145   if (value > max_dfa_issue_rate)
07146     max_dfa_issue_rate = value;
07147 }
07148 
07149 /* The following macro value is name of the corresponding global
07150    variable in the automaton based pipeline interface.  */
07151 
07152 #define MAX_DFA_ISSUE_RATE_VAR_NAME "max_dfa_issue_rate"
07153 
07154 /* The following function calculates value of the corresponding
07155    global variable and outputs its declaration.  */
07156 
07157 static void
07158 output_dfa_max_issue_rate (void)
07159 {
07160   automaton_t automaton;
07161 
07162   gcc_assert (UNDEFINED_LONGEST_PATH_LENGTH != ON_THE_PATH && ON_THE_PATH < 0);
07163   max_dfa_issue_rate = 0;
07164   for (automaton = description->first_automaton;
07165        automaton != NULL;
07166        automaton = automaton->next_automaton)
07167     pass_states (automaton, process_state_longest_path_length);
07168   fprintf (output_file, "\nint %s = %d;\n",
07169      MAX_DFA_ISSUE_RATE_VAR_NAME, max_dfa_issue_rate);
07170 }
07171 
07172 /* The function outputs all initialization values of VECT with length
07173    vect_length.  */
07174 static void
07175 output_vect (vect_el_t *vect, int vect_length)
07176 {
07177   int els_on_line;
07178 
07179   els_on_line = 1;
07180   if (vect_length == 0)
07181     fprintf (output_file,
07182              "0 /* This is dummy el because the vect is empty */");
07183   else
07184     {
07185       do
07186         {
07187           fprintf (output_file, "%5ld", (long) *vect);
07188           vect_length--;
07189           if (els_on_line == 10)
07190       {
07191         els_on_line = 0;
07192         fprintf (output_file, ",\n");
07193       }
07194           else if (vect_length != 0)
07195             fprintf (output_file, ", ");
07196           els_on_line++;
07197           vect++;
07198         }
07199       while (vect_length != 0);
07200     }
07201 }
07202 
07203 /* The following is name of the structure which represents DFA(s) for
07204    PHR.  */
07205 #define CHIP_NAME "DFA_chip"
07206 
07207 /* The following is name of member which represents state of a DFA for
07208    PHR.  */
07209 static void
07210 output_chip_member_name (FILE *f, automaton_t automaton)
07211 {
07212   if (automaton->corresponding_automaton_decl == NULL)
07213     fprintf (f, "automaton_state_%d", automaton->automaton_order_num);
07214   else
07215     fprintf (f, "%s_automaton_state",
07216              automaton->corresponding_automaton_decl->name);
07217 }
07218 
07219 /* The following is name of temporary variable which stores state of a
07220    DFA for PHR.  */
07221 static void
07222 output_temp_chip_member_name (FILE *f, automaton_t automaton)
07223 {
07224   fprintf (f, "_");
07225   output_chip_member_name (f, automaton);
07226 }
07227 
07228 /* This is name of macro value which is code of pseudo_insn
07229    representing advancing cpu cycle.  Its value is used as internal
07230    code unknown insn.  */
07231 #define ADVANCE_CYCLE_VALUE_NAME "DFA__ADVANCE_CYCLE"
07232 
07233 /* Output name of translate vector for given automaton.  */
07234 static void
07235 output_translate_vect_name (FILE *f, automaton_t automaton)
07236 {
07237   if (automaton->corresponding_automaton_decl == NULL)
07238     fprintf (f, "translate_%d", automaton->automaton_order_num);
07239   else
07240     fprintf (f, "%s_translate", automaton->corresponding_automaton_decl->name);
07241 }
07242 
07243 /* Output name for simple transition table representation.  */
07244 static void
07245 output_trans_full_vect_name (FILE *f, automaton_t automaton)
07246 {
07247   if (automaton->corresponding_automaton_decl == NULL)
07248     fprintf (f, "transitions_%d", automaton->automaton_order_num);
07249   else
07250     fprintf (f, "%s_transitions",
07251        automaton->corresponding_automaton_decl->name);
07252 }
07253 
07254 /* Output name of comb vector of the transition table for given
07255    automaton.  */
07256 static void
07257 output_trans_comb_vect_name (FILE *f, automaton_t automaton)
07258 {
07259   if (automaton->corresponding_automaton_decl == NULL)
07260     fprintf (f, "transitions_%d", automaton->automaton_order_num);
07261   else
07262     fprintf (f, "%s_transitions",
07263              automaton->corresponding_automaton_decl->name);
07264 }
07265 
07266 /* Output name of check vector of the transition table for given
07267    automaton.  */
07268 static void
07269 output_trans_check_vect_name (FILE *f, automaton_t automaton)
07270 {
07271   if (automaton->corresponding_automaton_decl == NULL)
07272     fprintf (f, "check_%d", automaton->automaton_order_num);
07273   else
07274     fprintf (f, "%s_check", automaton->corresponding_automaton_decl->name);
07275 }
07276 
07277 /* Output name of base vector of the transition table for given
07278    automaton.  */
07279 static void
07280 output_trans_base_vect_name (FILE *f, automaton_t automaton)
07281 {
07282   if (automaton->corresponding_automaton_decl == NULL)
07283     fprintf (f, "base_%d", automaton->automaton_order_num);
07284   else
07285     fprintf (f, "%s_base", automaton->corresponding_automaton_decl->name);
07286 }
07287 
07288 /* Output name for simple alternatives number representation.  */
07289 static void
07290 output_state_alts_full_vect_name (FILE *f, automaton_t automaton)
07291 {
07292   if (automaton->corresponding_automaton_decl == NULL)
07293     fprintf (f, "state_alts_%d", automaton->automaton_order_num);
07294   else
07295     fprintf (f, "%s_state_alts",
07296              automaton->corresponding_automaton_decl->name);
07297 }
07298 
07299 /* Output name of comb vector of the alternatives number table for given
07300    automaton.  */
07301 static void
07302 output_state_alts_comb_vect_name (FILE *f, automaton_t automaton)
07303 {
07304   if (automaton->corresponding_automaton_decl == NULL)
07305     fprintf (f, "state_alts_%d", automaton->automaton_order_num);
07306   else
07307     fprintf (f, "%s_state_alts",
07308              automaton->corresponding_automaton_decl->name);
07309 }
07310 
07311 /* Output name of check vector of the alternatives number table for given
07312    automaton.  */
07313 static void
07314 output_state_alts_check_vect_name (FILE *f, automaton_t automaton)
07315 {
07316   if (automaton->corresponding_automaton_decl == NULL)
07317     fprintf (f, "check_state_alts_%d", automaton->automaton_order_num);
07318   else
07319     fprintf (f, "%s_check_state_alts",
07320        automaton->corresponding_automaton_decl->name);
07321 }
07322 
07323 /* Output name of base vector of the alternatives number table for given
07324    automaton.  */
07325 static void
07326 output_state_alts_base_vect_name (FILE *f, automaton_t automaton)
07327 {
07328   if (automaton->corresponding_automaton_decl == NULL)
07329     fprintf (f, "base_state_alts_%d", automaton->automaton_order_num);
07330   else
07331     fprintf (f, "%s_base_state_alts",
07332        automaton->corresponding_automaton_decl->name);
07333 }
07334 
07335 /* Output name of simple min issue delay table representation.  */
07336 static void
07337 output_min_issue_delay_vect_name (FILE *f, automaton_t automaton)
07338 {
07339   if (automaton->corresponding_automaton_decl == NULL)
07340     fprintf (f, "min_issue_delay_%d", automaton->automaton_order_num);
07341   else
07342     fprintf (f, "%s_min_issue_delay",
07343              automaton->corresponding_automaton_decl->name);
07344 }
07345 
07346 /* Output name of deadlock vector for given automaton.  */
07347 static void
07348 output_dead_lock_vect_name (FILE *f, automaton_t automaton)
07349 {
07350   if (automaton->corresponding_automaton_decl == NULL)
07351     fprintf (f, "dead_lock_%d", automaton->automaton_order_num);
07352   else
07353     fprintf (f, "%s_dead_lock", automaton->corresponding_automaton_decl->name);
07354 }
07355 
07356 /* Output name of reserved units table for AUTOMATON into file F.  */
07357 static void
07358 output_reserved_units_table_name (FILE *f, automaton_t automaton)
07359 {
07360   if (automaton->corresponding_automaton_decl == NULL)
07361     fprintf (f, "reserved_units_%d", automaton->automaton_order_num);
07362   else
07363     fprintf (f, "%s_reserved_units",
07364        automaton->corresponding_automaton_decl->name);
07365 }
07366 
07367 /* Name of the PHR interface macro.  */
07368 #define AUTOMATON_STATE_ALTS_MACRO_NAME "AUTOMATON_STATE_ALTS"
07369 
07370 /* Name of the PHR interface macro.  */
07371 #define CPU_UNITS_QUERY_MACRO_NAME "CPU_UNITS_QUERY"
07372 
07373 /* Names of an internal functions: */
07374 #define INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME "internal_min_issue_delay"
07375 
07376 /* This is external type of DFA(s) state.  */
07377 #define STATE_TYPE_NAME "state_t"
07378 
07379 #define INTERNAL_TRANSITION_FUNC_NAME "internal_state_transition"
07380 
07381 #define INTERNAL_STATE_ALTS_FUNC_NAME "internal_state_alts"
07382 
07383 #define INTERNAL_RESET_FUNC_NAME "internal_reset"
07384 
07385 #define INTERNAL_DEAD_LOCK_FUNC_NAME "internal_state_dead_lock_p"
07386 
07387 #define INTERNAL_INSN_LATENCY_FUNC_NAME "internal_insn_latency"
07388 
07389 /* Name of cache of insn dfa codes.  */
07390 #define DFA_INSN_CODES_VARIABLE_NAME "dfa_insn_codes"
07391 
07392 /* Name of length of cache of insn dfa codes.  */
07393 #define DFA_INSN_CODES_LENGTH_VARIABLE_NAME "dfa_insn_codes_length"
07394 
07395 /* Names of the PHR interface functions: */
07396 #define SIZE_FUNC_NAME "state_size"
07397 
07398 #define TRANSITION_FUNC_NAME "state_transition"
07399 
07400 #define STATE_ALTS_FUNC_NAME "state_alts"
07401 
07402 #define MIN_ISSUE_DELAY_FUNC_NAME "min_issue_delay"
07403 
07404 #define MIN_INSN_CONFLICT_DELAY_FUNC_NAME "min_insn_conflict_delay"
07405 
07406 #define DEAD_LOCK_FUNC_NAME "state_dead_lock_p"
07407 
07408 #define RESET_FUNC_NAME "state_reset"
07409 
07410 #define INSN_LATENCY_FUNC_NAME "insn_latency"
07411 
07412 #define PRINT_RESERVATION_FUNC_NAME "print_reservation"
07413 
07414 #define GET_CPU_UNIT_CODE_FUNC_NAME "get_cpu_unit_code"
07415 
07416 #define CPU_UNIT_RESERVATION_P_FUNC_NAME "cpu_unit_reservation_p"
07417 
07418 #define DFA_CLEAN_INSN_CACHE_FUNC_NAME  "dfa_clean_insn_cache"
07419 
07420 #define DFA_START_FUNC_NAME  "dfa_start"
07421 
07422 #define DFA_FINISH_FUNC_NAME "dfa_finish"
07423 
07424 /* Names of parameters of the PHR interface functions.  */
07425 #define STATE_NAME "state"
07426 
07427 #define INSN_PARAMETER_NAME "insn"
07428 
07429 #define INSN2_PARAMETER_NAME "insn2"
07430 
07431 #define CHIP_PARAMETER_NAME "chip"
07432 
07433 #define FILE_PARAMETER_NAME "f"
07434 
07435 #define CPU_UNIT_NAME_PARAMETER_NAME "cpu_unit_name"
07436 
07437 #define CPU_CODE_PARAMETER_NAME "cpu_unit_code"
07438 
07439 /* Names of the variables whose values are internal insn code of rtx
07440    insn.  */
07441 #define INTERNAL_INSN_CODE_NAME "insn_code"
07442 
07443 #define INTERNAL_INSN2_CODE_NAME "insn2_code"
07444 
07445 /* Names of temporary variables in some functions.  */
07446 #define TEMPORARY_VARIABLE_NAME "temp"
07447 
07448 #define I_VARIABLE_NAME "i"
07449 
07450 /* Name of result variable in some functions.  */
07451 #define RESULT_VARIABLE_NAME "res"
07452 
07453 /* Name of function (attribute) to translate insn into internal insn
07454    code.  */
07455 #define INTERNAL_DFA_INSN_CODE_FUNC_NAME "internal_dfa_insn_code"
07456 
07457 /* Name of function (attribute) to translate insn into internal insn
07458    code with caching.  */
07459 #define DFA_INSN_CODE_FUNC_NAME "dfa_insn_code"
07460 
07461 /* Name of function (attribute) to translate insn into internal insn
07462    code.  */
07463 #define INSN_DEFAULT_LATENCY_FUNC_NAME "insn_default_latency"
07464 
07465 /* Name of function (attribute) to translate insn into internal insn
07466    code.  */
07467 #define BYPASS_P_FUNC_NAME "bypass_p"
07468 
07469 /* Output C type which is used for representation of codes of states
07470    of AUTOMATON.  */
07471 static void
07472 output_state_member_type (FILE *f, automaton_t automaton)
07473 {
07474   output_range_type (f, 0, automaton->achieved_states_num);
07475 }
07476 
07477 /* Output definition of the structure representing current DFA(s)
07478    state(s).  */
07479 static void
07480 output_chip_definitions (void)
07481 {
07482   automaton_t automaton;
07483 
07484   fprintf (output_file, "struct %s\n{\n", CHIP_NAME);
07485   for (automaton = description->first_automaton;
07486        automaton != NULL;
07487        automaton = automaton->next_automaton)
07488     {
07489       fprintf (output_file, "  ");
07490       output_state_member_type (output_file, automaton);
07491       fprintf (output_file, " ");
07492       output_chip_member_name (output_file, automaton);
07493       fprintf (output_file, ";\n");
07494     }
07495   fprintf (output_file, "};\n\n");
07496 #if 0
07497   fprintf (output_file, "static struct %s %s;\n\n", CHIP_NAME, CHIP_NAME);
07498 #endif
07499 }
07500 
07501 
07502 /* The function outputs translate vector of internal insn code into
07503    insn equivalence class number.  The equivalence class number is
07504    used to access to table and vectors representing DFA(s).  */
07505 static void
07506 output_translate_vect (automaton_t automaton)
07507 {
07508   ainsn_t ainsn;
07509   int insn_value;
07510   vla_hwint_t translate_vect;
07511 
07512   VLA_HWINT_CREATE (translate_vect, 250, "translate vector");
07513   VLA_HWINT_EXPAND (translate_vect, description->insns_num);
07514   for (insn_value = 0; insn_value < description->insns_num; insn_value++)
07515     /* Undefined value */
07516     VLA_HWINT (translate_vect, insn_value) = automaton->insn_equiv_classes_num;
07517   for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
07518     VLA_HWINT (translate_vect, ainsn->insn_reserv_decl->insn_num)
07519       = ainsn->insn_equiv_class_num;
07520   fprintf (output_file,
07521            "/* Vector translating external insn codes to internal ones.*/\n");
07522   fprintf (output_file, "static const ");
07523   output_range_type (output_file, 0, automaton->insn_equiv_classes_num);
07524   fprintf (output_file, " ");
07525   output_translate_vect_name (output_file, automaton);
07526   fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
07527   output_vect (VLA_HWINT_BEGIN (translate_vect),
07528          VLA_HWINT_LENGTH (translate_vect));
07529   fprintf (output_file, "};\n\n");
07530   VLA_HWINT_DELETE (translate_vect);
07531 }
07532 
07533 /* The value in a table state x ainsn -> something which represents
07534    undefined value.  */
07535 static int undefined_vect_el_value;
07536 
07537 /* The following function returns nonzero value if the best
07538    representation of the table is comb vector.  */
07539 static int
07540 comb_vect_p (state_ainsn_table_t tab)
07541 {
07542   return  (2 * VLA_HWINT_LENGTH (tab->full_vect)
07543            > 5 * VLA_HWINT_LENGTH (tab->comb_vect));
07544 }
07545 
07546 /* The following function creates new table for AUTOMATON.  */
07547 static state_ainsn_table_t
07548 create_state_ainsn_table (automaton_t automaton)
07549 {
07550   state_ainsn_table_t tab;
07551   int full_vect_length;
07552   int i;
07553 
07554   tab = create_node (sizeof (struct state_ainsn_table));
07555   tab->automaton = automaton;
07556   VLA_HWINT_CREATE (tab->comb_vect, 10000, "comb vector");
07557   VLA_HWINT_CREATE (tab->check_vect, 10000, "check vector");
07558   VLA_HWINT_CREATE (tab->base_vect, 1000, "base vector");
07559   VLA_HWINT_EXPAND (tab->base_vect, automaton->achieved_states_num);
07560   VLA_HWINT_CREATE (tab->full_vect, 10000, "full vector");
07561   full_vect_length = (automaton->insn_equiv_classes_num
07562                       * automaton->achieved_states_num);
07563   VLA_HWINT_EXPAND (tab->full_vect, full_vect_length);
07564   for (i = 0; i < full_vect_length; i++)
07565     VLA_HWINT (tab->full_vect, i) = undefined_vect_el_value;
07566   tab->min_base_vect_el_value = 0;
07567   tab->max_base_vect_el_value = 0;
07568   tab->min_comb_vect_el_value = 0;
07569   tab->max_comb_vect_el_value = 0;
07570   return tab;
07571 }
07572 
07573 /* The following function outputs the best C representation of the
07574    table TAB of given TABLE_NAME.  */
07575 static void
07576 output_state_ainsn_table (state_ainsn_table_t tab, char *table_name,
07577         void (*output_full_vect_name_func) (FILE *, automaton_t),
07578         void (*output_comb_vect_name_func) (FILE *, automaton_t),
07579         void (*output_check_vect_name_func) (FILE *, automaton_t),
07580         void (*output_base_vect_name_func) (FILE *, automaton_t))
07581 {
07582   if (!comb_vect_p (tab))
07583     {
07584       fprintf (output_file, "/* Vector for %s.  */\n", table_name);
07585       fprintf (output_file, "static const ");
07586       output_range_type (output_file, tab->min_comb_vect_el_value,
07587                          tab->max_comb_vect_el_value);
07588       fprintf (output_file, " ");
07589       (*output_full_vect_name_func) (output_file, tab->automaton);
07590       fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
07591       output_vect (VLA_HWINT_BEGIN (tab->full_vect),
07592                    VLA_HWINT_LENGTH (tab->full_vect));
07593       fprintf (output_file, "};\n\n");
07594     }
07595   else
07596     {
07597       fprintf (output_file, "/* Comb vector for %s.  */\n", table_name);
07598       fprintf (output_file, "static const ");
07599       output_range_type (output_file, tab->min_comb_vect_el_value,
07600                          tab->max_comb_vect_el_value);
07601       fprintf (output_file, " ");
07602       (*output_comb_vect_name_func) (output_file, tab->automaton);
07603       fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
07604       output_vect (VLA_HWINT_BEGIN (tab->comb_vect),
07605                    VLA_HWINT_LENGTH (tab->comb_vect));
07606       fprintf (output_file, "};\n\n");
07607       fprintf (output_file, "/* Check vector for %s.  */\n", table_name);
07608       fprintf (output_file, "static const ");
07609       output_range_type (output_file, 0, tab->automaton->achieved_states_num);
07610       fprintf (output_file, " ");
07611       (*output_check_vect_name_func) (output_file, tab->automaton);
07612       fprintf (output_file, "[] = {\n");
07613       output_vect (VLA_HWINT_BEGIN (tab->check_vect),
07614                    VLA_HWINT_LENGTH (tab->check_vect));
07615       fprintf (output_file, "};\n\n");
07616       fprintf (output_file, "/* Base vector for %s.  */\n", table_name);
07617       fprintf (output_file, "static const ");
07618       output_range_type (output_file, tab->min_base_vect_el_value,
07619                          tab->max_base_vect_el_value);
07620       fprintf (output_file, " ");
07621       (*output_base_vect_name_func) (output_file, tab->automaton);
07622       fprintf (output_file, "[] = {\n");
07623       output_vect (VLA_HWINT_BEGIN (tab->base_vect),
07624                    VLA_HWINT_LENGTH (tab->base_vect));
07625       fprintf (output_file, "};\n\n");
07626     }
07627 }
07628 
07629 /* The following function adds vector with length VECT_LENGTH and
07630    elements pointed by VECT to table TAB as its line with number
07631    VECT_NUM.  */
07632 static void
07633 add_vect (state_ainsn_table_t tab, int vect_num, vect_el_t *vect,
07634     int vect_length)
07635 {
07636   int real_vect_length;
07637   vect_el_t *comb_vect_start;
07638   vect_el_t *check_vect_start;
07639   int comb_vect_index;
07640   int comb_vect_els_num;
07641   int vect_index;
07642   int first_unempty_vect_index;
07643   int additional_els_num;
07644   int no_state_value;
07645   vect_el_t vect_el;
07646   int i;
07647   unsigned long vect_mask, comb_vect_mask;