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