• Main Page
  • Modules
  • Data Types
  • Files

osprey-gcc-4.2.0/gcc/genautomata.c

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