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