• Main Page
  • Modules
  • Data Types
  • Files

osprey/kgccfe/gnu/genautomata.c

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