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