configure.ac: Substitute `with_cpu'.
[official-gcc.git] / gcc / genautomata.c
blob8d93f0ee75127cc2d2ad2b5e370ebc3139234798
1 /* Pipeline hazard description translator.
2 Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010
3 Free Software Foundation, Inc.
5 Written by Vladimir Makarov <vmakarov@redhat.com>
7 This file is part of GCC.
9 GCC is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by the
11 Free Software Foundation; either version 3, or (at your option) any
12 later version.
14 GCC is distributed in the hope that it will be useful, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 for more details.
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING3. If not see
21 <http://www.gnu.org/licenses/>. */
23 /* References:
25 1. The finite state automaton based pipeline hazard recognizer and
26 instruction scheduler in GCC. V. Makarov. Proceedings of GCC
27 summit, 2003.
29 2. Detecting pipeline structural hazards quickly. T. Proebsting,
30 C. Fraser. Proceedings of ACM SIGPLAN-SIGACT Symposium on
31 Principles of Programming Languages, pages 280--286, 1994.
33 This article is a good start point to understand usage of finite
34 state automata for pipeline hazard recognizers. But I'd
35 recommend the 1st and 3rd article for more deep understanding.
37 3. Efficient Instruction Scheduling Using Finite State Automata:
38 V. Bala and N. Rubin, Proceedings of MICRO-28. This is the best
39 article about usage of finite state automata for pipeline hazard
40 recognizers.
42 The current implementation is described in the 1st article and it
43 is different from the 3rd article in the following:
45 1. New operator `|' (alternative) is permitted in functional unit
46 reservation which can be treated deterministically and
47 non-deterministically.
49 2. Possibility of usage of nondeterministic automata too.
51 3. Possibility to query functional unit reservations for given
52 automaton state.
54 4. Several constructions to describe impossible reservations
55 (`exclusion_set', `presence_set', `final_presence_set',
56 `absence_set', and `final_absence_set').
58 5. No reverse automata are generated. Trace instruction scheduling
59 requires this. It can be easily added in the future if we
60 really need this.
62 6. Union of automaton states are not generated yet. It is planned
63 to be implemented. Such feature is needed to make more accurate
64 interlock insn scheduling to get state describing functional
65 unit reservation in a joint CFG point. */
67 /* This file code processes constructions of machine description file
68 which describes automaton used for recognition of processor pipeline
69 hazards by insn scheduler and can be used for other tasks (such as
70 VLIW insn packing.
72 The translator functions `gen_cpu_unit', `gen_query_cpu_unit',
73 `gen_bypass', `gen_excl_set', `gen_presence_set',
74 `gen_final_presence_set', `gen_absence_set',
75 `gen_final_absence_set', `gen_automaton', `gen_automata_option',
76 `gen_reserv', `gen_insn_reserv' are called from file
77 `genattrtab.c'. They transform RTL constructions describing
78 automata in .md file into internal representation convenient for
79 further processing.
81 The translator major function `expand_automata' processes the
82 description internal representation into finite state automaton.
83 It can be divided on:
85 o checking correctness of the automaton pipeline description
86 (major function is `check_all_description').
88 o generating automaton (automata) from the description (major
89 function is `make_automaton').
91 o optional transformation of nondeterministic finite state
92 automata into deterministic ones if the alternative operator
93 `|' is treated nondeterministically in the description (major
94 function is NDFA_to_DFA).
96 o optional minimization of the finite state automata by merging
97 equivalent automaton states (major function is `minimize_DFA').
99 o forming tables (some as comb vectors) and attributes
100 representing the automata (functions output_..._table).
102 Function `write_automata' outputs the created finite state
103 automaton as different tables and functions which works with the
104 automata to inquire automaton state and to change its state. These
105 function are used by gcc instruction scheduler and may be some
106 other gcc code. */
108 #include "bconfig.h"
109 #include "system.h"
110 #include "coretypes.h"
111 #include "tm.h"
112 #include "rtl.h"
113 #include "obstack.h"
114 #include "errors.h"
115 #include "gensupport.h"
117 #include <math.h>
118 #include "hashtab.h"
119 #include "vec.h"
120 #include "fnmatch.h"
122 #ifndef CHAR_BIT
123 #define CHAR_BIT 8
124 #endif
126 /* Positions in machine description file. Now they are not used. But
127 they could be used in the future for better diagnostic messages. */
128 typedef int pos_t;
130 /* The following is element of vector of current (and planned in the
131 future) functional unit reservations. */
132 typedef unsigned HOST_WIDE_INT set_el_t;
134 /* Reservations of function units are represented by value of the following
135 type. */
136 typedef set_el_t *reserv_sets_t;
137 typedef const set_el_t *const_reserv_sets_t;
139 /* The following structure describes a ticker. */
140 struct ticker
142 /* The following member value is time of the ticker creation with
143 taking into account time when the ticker is off. Active time of
144 the ticker is current time minus the value. */
145 int modified_creation_time;
146 /* The following member value is time (incremented by one) when the
147 ticker was off. Zero value means that now the ticker is on. */
148 int incremented_off_time;
151 /* The ticker is represented by the following type. */
152 typedef struct ticker ticker_t;
154 /* The following type describes elements of output vectors. */
155 typedef HOST_WIDE_INT vect_el_t;
157 /* Forward declaration of structures of internal representation of
158 pipeline description based on NDFA. */
160 struct unit_decl;
161 struct bypass_decl;
162 struct result_decl;
163 struct automaton_decl;
164 struct unit_pattern_rel_decl;
165 struct reserv_decl;
166 struct insn_reserv_decl;
167 struct decl;
168 struct unit_regexp;
169 struct result_regexp;
170 struct reserv_regexp;
171 struct nothing_regexp;
172 struct sequence_regexp;
173 struct repeat_regexp;
174 struct allof_regexp;
175 struct oneof_regexp;
176 struct regexp;
177 struct description;
178 struct unit_set_el;
179 struct pattern_set_el;
180 struct pattern_reserv;
181 struct state;
182 struct alt_state;
183 struct arc;
184 struct ainsn;
185 struct automaton;
186 struct state_ainsn_table;
188 /* The following typedefs are for brevity. */
189 typedef struct unit_decl *unit_decl_t;
190 typedef const struct unit_decl *const_unit_decl_t;
191 typedef struct decl *decl_t;
192 typedef const struct decl *const_decl_t;
193 typedef struct regexp *regexp_t;
194 typedef struct unit_set_el *unit_set_el_t;
195 typedef struct pattern_set_el *pattern_set_el_t;
196 typedef struct pattern_reserv *pattern_reserv_t;
197 typedef struct alt_state *alt_state_t;
198 typedef struct state *state_t;
199 typedef const struct state *const_state_t;
200 typedef struct arc *arc_t;
201 typedef struct ainsn *ainsn_t;
202 typedef struct automaton *automaton_t;
203 typedef struct automata_list_el *automata_list_el_t;
204 typedef const struct automata_list_el *const_automata_list_el_t;
205 typedef struct state_ainsn_table *state_ainsn_table_t;
207 /* Undefined position. */
208 static pos_t no_pos = 0;
210 /* All IR is stored in the following obstack. */
211 static struct obstack irp;
214 /* Declare vector types for various data structures: */
217 typedef vec<vect_el_t> vla_hwint_t;
219 /* Forward declarations of functions used before their definitions, only. */
220 static regexp_t gen_regexp_sequence (const char *);
221 static void reserv_sets_or (reserv_sets_t, reserv_sets_t,
222 reserv_sets_t);
223 static reserv_sets_t get_excl_set (reserv_sets_t);
224 static int check_presence_pattern_sets (reserv_sets_t,
225 reserv_sets_t, int);
226 static int check_absence_pattern_sets (reserv_sets_t, reserv_sets_t,
227 int);
228 static arc_t first_out_arc (const_state_t);
229 static arc_t next_out_arc (arc_t);
233 /* Options with the following names can be set up in automata_option
234 construction. Because the strings occur more one time we use the
235 macros. */
237 #define NO_MINIMIZATION_OPTION "-no-minimization"
238 #define TIME_OPTION "-time"
239 #define STATS_OPTION "-stats"
240 #define V_OPTION "-v"
241 #define W_OPTION "-w"
242 #define NDFA_OPTION "-ndfa"
243 #define COLLAPSE_OPTION "-collapse-ndfa"
244 #define NO_COMB_OPTION "-no-comb-vect"
245 #define PROGRESS_OPTION "-progress"
247 /* The following flags are set up by function `initiate_automaton_gen'. */
249 /* Make automata with nondeterministic reservation by insns (`-ndfa'). */
250 static int ndfa_flag;
252 /* When making an NDFA, produce additional transitions that collapse
253 NDFA state into a deterministic one suitable for querying CPU units.
254 Provide avance-state transitions only for deterministic states. */
255 static int collapse_flag;
257 /* Do not make minimization of DFA (`-no-minimization'). */
258 static int no_minimization_flag;
260 /* Do not try to generate a comb vector (`-no-comb-vect'). */
261 static int no_comb_flag;
263 /* Value of this variable is number of automata being generated. The
264 actual number of automata may be less this value if there is not
265 sufficient number of units. This value is defined by argument of
266 option `-split' or by constructions automaton if the value is zero
267 (it is default value of the argument). */
268 static int split_argument;
270 /* Flag of output time statistics (`-time'). */
271 static int time_flag;
273 /* Flag of automata statistics (`-stats'). */
274 static int stats_flag;
276 /* Flag of creation of description file which contains description of
277 result automaton and statistics information (`-v'). */
278 static int v_flag;
280 /* Flag of output of a progress bar showing how many states were
281 generated so far for automaton being processed (`-progress'). */
282 static int progress_flag;
284 /* Flag of generating warning instead of error for non-critical errors
285 (`-w'). */
286 static int w_flag;
289 /* Output file for pipeline hazard recognizer (PHR) being generated.
290 The value is NULL if the file is not defined. */
291 static FILE *output_file;
293 /* Description file of PHR. The value is NULL if the file is not
294 created. */
295 static FILE *output_description_file;
297 /* PHR description file name. */
298 static char *output_description_file_name;
300 /* Value of the following variable is node representing description
301 being processed. This is start point of IR. */
302 static struct description *description;
306 /* This page contains description of IR structure (nodes). */
308 enum decl_mode
310 dm_unit,
311 dm_bypass,
312 dm_automaton,
313 dm_excl,
314 dm_presence,
315 dm_absence,
316 dm_reserv,
317 dm_insn_reserv
320 /* This describes define_cpu_unit and define_query_cpu_unit (see file
321 rtl.def). */
322 struct unit_decl
324 const char *name;
325 /* NULL if the automaton name is absent. */
326 const char *automaton_name;
327 /* If the following value is not zero, the cpu unit reservation is
328 described in define_query_cpu_unit. */
329 char query_p;
331 /* The following fields are defined by checker. */
333 /* The following field value is nonzero if the unit is used in an
334 regexp. */
335 char unit_is_used;
337 /* The following field value is order number (0, 1, ...) of given
338 unit. */
339 int unit_num;
340 /* The following field value is corresponding declaration of
341 automaton which was given in description. If the field value is
342 NULL then automaton in the unit declaration was absent. */
343 struct automaton_decl *automaton_decl;
344 /* The following field value is maximal cycle number (1, ...) on
345 which given unit occurs in insns. Zero value means that given
346 unit is not used in insns. */
347 int max_occ_cycle_num;
348 /* The following field value is minimal cycle number (0, ...) on
349 which given unit occurs in insns. -1 value means that given
350 unit is not used in insns. */
351 int min_occ_cycle_num;
352 /* The following list contains units which conflict with given
353 unit. */
354 unit_set_el_t excl_list;
355 /* The following list contains patterns which are required to
356 reservation of given unit. */
357 pattern_set_el_t presence_list;
358 pattern_set_el_t final_presence_list;
359 /* The following list contains patterns which should be not present
360 in reservation for given unit. */
361 pattern_set_el_t absence_list;
362 pattern_set_el_t final_absence_list;
363 /* The following is used only when `query_p' has nonzero value.
364 This is query number for the unit. */
365 int query_num;
366 /* The following is the last cycle on which the unit was checked for
367 correct distributions of units to automata in a regexp. */
368 int last_distribution_check_cycle;
370 /* The following fields are defined by automaton generator. */
372 /* The following field value is number of the automaton to which
373 given unit belongs. */
374 int corresponding_automaton_num;
375 /* If the following value is not zero, the cpu unit is present in a
376 `exclusion_set' or in right part of a `presence_set',
377 `final_presence_set', `absence_set', and
378 `final_absence_set'define_query_cpu_unit. */
379 char in_set_p;
382 /* This describes define_bypass (see file rtl.def). */
383 struct bypass_decl
385 int latency;
386 const char *out_pattern;
387 const char *in_pattern;
388 const char *bypass_guard_name;
390 /* The following fields are defined by checker. */
392 /* output and input insns of given bypass. */
393 struct insn_reserv_decl *out_insn_reserv;
394 struct insn_reserv_decl *in_insn_reserv;
395 /* The next bypass for given output insn. */
396 struct bypass_decl *next;
399 /* This describes define_automaton (see file rtl.def). */
400 struct automaton_decl
402 const char *name;
404 /* The following fields are defined by automaton generator. */
406 /* The following field value is nonzero if the automaton is used in
407 an regexp definition. */
408 char automaton_is_used;
410 /* The following fields are defined by checker. */
412 /* The following field value is the corresponding automaton. This
413 field is not NULL only if the automaton is present in unit
414 declarations and the automatic partition on automata is not
415 used. */
416 automaton_t corresponding_automaton;
419 /* This describes exclusion relations: exclusion_set (see file
420 rtl.def). */
421 struct excl_rel_decl
423 int all_names_num;
424 int first_list_length;
425 char *names [1];
428 /* This describes unit relations: [final_]presence_set or
429 [final_]absence_set (see file rtl.def). */
430 struct unit_pattern_rel_decl
432 int final_p;
433 int names_num;
434 int patterns_num;
435 char **names;
436 char ***patterns;
439 /* This describes define_reservation (see file rtl.def). */
440 struct reserv_decl
442 const char *name;
443 regexp_t regexp;
445 /* The following fields are defined by checker. */
447 /* The following field value is nonzero if the unit is used in an
448 regexp. */
449 char reserv_is_used;
450 /* The following field is used to check up cycle in expression
451 definition. */
452 int loop_pass_num;
455 /* This describes define_insn_reservation (see file rtl.def). */
456 struct insn_reserv_decl
458 rtx condexp;
459 int default_latency;
460 regexp_t regexp;
461 const char *name;
463 /* The following fields are defined by checker. */
465 /* The following field value is order number (0, 1, ...) of given
466 insn. */
467 int insn_num;
468 /* The following field value is list of bypasses in which given insn
469 is output insn. Bypasses with the same input insn stay one after
470 another in the list in the same order as their occurrences in the
471 description but the bypass without a guard stays always the last
472 in a row of bypasses with the same input insn. */
473 struct bypass_decl *bypass_list;
475 /* The following fields are defined by automaton generator. */
477 /* The following field is the insn regexp transformed that
478 the regexp has not optional regexp, repetition regexp, and an
479 reservation name (i.e. reservation identifiers are changed by the
480 corresponding regexp) and all alternations are the top level
481 of the regexp. The value can be NULL only if it is special
482 insn `cycle advancing'. */
483 regexp_t transformed_regexp;
484 /* The following field value is list of arcs marked given
485 insn. The field is used in transformation NDFA -> DFA. */
486 arc_t arcs_marked_by_insn;
487 /* The two following fields are used during minimization of a finite state
488 automaton. */
489 /* The field value is number of equivalence class of state into
490 which arc marked by given insn enters from a state (fixed during
491 an automaton minimization). */
492 int equiv_class_num;
493 /* The following member value is the list to automata which can be
494 changed by the insn issue. */
495 automata_list_el_t important_automata_list;
496 /* The following member is used to process insn once for output. */
497 int processed_p;
500 /* This contains a declaration mentioned above. */
501 struct decl
503 /* What node in the union? */
504 enum decl_mode mode;
505 pos_t pos;
506 union
508 struct unit_decl unit;
509 struct bypass_decl bypass;
510 struct automaton_decl automaton;
511 struct excl_rel_decl excl;
512 struct unit_pattern_rel_decl presence;
513 struct unit_pattern_rel_decl absence;
514 struct reserv_decl reserv;
515 struct insn_reserv_decl insn_reserv;
516 } decl;
519 /* The following structures represent parsed reservation strings. */
520 enum regexp_mode
522 rm_unit,
523 rm_reserv,
524 rm_nothing,
525 rm_sequence,
526 rm_repeat,
527 rm_allof,
528 rm_oneof
531 /* Cpu unit in reservation. */
532 struct unit_regexp
534 const char *name;
535 unit_decl_t unit_decl;
538 /* Define_reservation in a reservation. */
539 struct reserv_regexp
541 const char *name;
542 struct reserv_decl *reserv_decl;
545 /* Absence of reservation (represented by string `nothing'). */
546 struct nothing_regexp
548 /* This used to be empty but ISO C doesn't allow that. */
549 char unused;
552 /* Representation of reservations separated by ',' (see file
553 rtl.def). */
554 struct sequence_regexp
556 int regexps_num;
557 regexp_t regexps [1];
560 /* Representation of construction `repeat' (see file rtl.def). */
561 struct repeat_regexp
563 int repeat_num;
564 regexp_t regexp;
567 /* Representation of reservations separated by '+' (see file
568 rtl.def). */
569 struct allof_regexp
571 int regexps_num;
572 regexp_t regexps [1];
575 /* Representation of reservations separated by '|' (see file
576 rtl.def). */
577 struct oneof_regexp
579 int regexps_num;
580 regexp_t regexps [1];
583 /* Representation of a reservation string. */
584 struct regexp
586 /* What node in the union? */
587 enum regexp_mode mode;
588 pos_t pos;
589 union
591 struct unit_regexp unit;
592 struct reserv_regexp reserv;
593 struct nothing_regexp nothing;
594 struct sequence_regexp sequence;
595 struct repeat_regexp repeat;
596 struct allof_regexp allof;
597 struct oneof_regexp oneof;
598 } regexp;
601 /* Represents description of pipeline hazard description based on
602 NDFA. */
603 struct description
605 int decls_num, normal_decls_num;
607 /* The following fields are defined by checker. */
609 /* The following fields values are correspondingly number of all
610 units, query units, and insns in the description. */
611 int units_num;
612 int query_units_num;
613 int insns_num;
614 /* The following field value is max length (in cycles) of
615 reservations of insns. The field value is defined only for
616 correct programs. */
617 int max_insn_reserv_cycles;
619 /* The following fields are defined by automaton generator. */
621 /* The following field value is the first automaton. */
622 automaton_t first_automaton;
624 /* The following field is created by pipeline hazard parser and
625 contains all declarations. We allocate additional entries for
626 two special insns which are added by the automaton generator. */
627 decl_t decls [1];
631 /* The following nodes are created in automaton checker. */
633 /* The following nodes represent exclusion set for cpu units. Each
634 element is accessed through only one excl_list. */
635 struct unit_set_el
637 unit_decl_t unit_decl;
638 unit_set_el_t next_unit_set_el;
641 /* The following nodes represent presence or absence pattern for cpu
642 units. Each element is accessed through only one presence_list or
643 absence_list. */
644 struct pattern_set_el
646 /* The number of units in unit_decls. */
647 int units_num;
648 /* The units forming the pattern. */
649 struct unit_decl **unit_decls;
650 pattern_set_el_t next_pattern_set_el;
654 /* The following nodes are created in automaton generator. */
657 /* The following nodes represent presence or absence pattern for cpu
658 units. Each element is accessed through only one element of
659 unit_presence_set_table or unit_absence_set_table. */
660 struct pattern_reserv
662 reserv_sets_t reserv;
663 pattern_reserv_t next_pattern_reserv;
666 /* The following node type describes state automaton. The state may
667 be deterministic or non-deterministic. Non-deterministic state has
668 several component states which represent alternative cpu units
669 reservations. The state also is used for describing a
670 deterministic reservation of automaton insn. */
671 struct state
673 /* The following member value is nonzero if there is a transition by
674 cycle advancing. */
675 int new_cycle_p;
676 /* The following field is list of processor unit reservations on
677 each cycle. */
678 reserv_sets_t reservs;
679 /* The following field is unique number of given state between other
680 states. */
681 int unique_num;
682 /* The following field value is automaton to which given state
683 belongs. */
684 automaton_t automaton;
685 /* The following field value is the first arc output from given
686 state. */
687 arc_t first_out_arc;
688 unsigned int num_out_arcs;
689 /* The following field is used to form NDFA. */
690 char it_was_placed_in_stack_for_NDFA_forming;
691 /* The following field is used to form DFA. */
692 char it_was_placed_in_stack_for_DFA_forming;
693 /* The following field is used to transform NDFA to DFA and DFA
694 minimization. The field value is not NULL if the state is a
695 compound state. In this case the value of field `unit_sets_list'
696 is NULL. All states in the list are in the hash table. The list
697 is formed through field `next_sorted_alt_state'. We should
698 support only one level of nesting state. */
699 alt_state_t component_states;
700 /* The following field is used for passing graph of states. */
701 int pass_num;
702 /* The list of states belonging to one equivalence class is formed
703 with the aid of the following field. */
704 state_t next_equiv_class_state;
705 /* The two following fields are used during minimization of a finite
706 state automaton. */
707 int equiv_class_num_1, equiv_class_num_2;
708 /* The following field is used during minimization of a finite state
709 automaton. The field value is state corresponding to equivalence
710 class to which given state belongs. */
711 state_t equiv_class_state;
712 unsigned int *presence_signature;
713 /* The following field value is the order number of given state.
714 The states in final DFA is enumerated with the aid of the
715 following field. */
716 int order_state_num;
717 /* This member is used for passing states for searching minimal
718 delay time. */
719 int state_pass_num;
720 /* The following member is used to evaluate min issue delay of insn
721 for a state. */
722 int min_insn_issue_delay;
725 /* Automaton arc. */
726 struct arc
728 /* The following field refers for the state into which given arc
729 enters. */
730 state_t to_state;
731 /* The following field describes that the insn issue (with cycle
732 advancing for special insn `cycle advancing' and without cycle
733 advancing for others) makes transition from given state to
734 another given state. */
735 ainsn_t insn;
736 /* The following field value is the next arc output from the same
737 state. */
738 arc_t next_out_arc;
739 /* List of arcs marked given insn is formed with the following
740 field. The field is used in transformation NDFA -> DFA. */
741 arc_t next_arc_marked_by_insn;
744 /* The following node type describes a deterministic alternative in
745 non-deterministic state which characterizes cpu unit reservations
746 of automaton insn or which is part of NDFA. */
747 struct alt_state
749 /* The following field is a deterministic state which characterizes
750 unit reservations of the instruction. */
751 state_t state;
752 /* The following field refers to the next state which characterizes
753 unit reservations of the instruction. */
754 alt_state_t next_alt_state;
755 /* The following field refers to the next state in sorted list. */
756 alt_state_t next_sorted_alt_state;
759 /* The following node type describes insn of automaton. They are
760 labels of FA arcs. */
761 struct ainsn
763 /* The following field value is the corresponding insn declaration
764 of description. */
765 struct insn_reserv_decl *insn_reserv_decl;
766 /* The following field value is the next insn declaration for an
767 automaton. */
768 ainsn_t next_ainsn;
769 /* The following field is states which characterize automaton unit
770 reservations of the instruction. The value can be NULL only if it
771 is special insn `cycle advancing'. */
772 alt_state_t alt_states;
773 /* The following field is sorted list of states which characterize
774 automaton unit reservations of the instruction. The value can be
775 NULL only if it is special insn `cycle advancing'. */
776 alt_state_t sorted_alt_states;
777 /* The following field refers the next automaton insn with
778 the same reservations. */
779 ainsn_t next_same_reservs_insn;
780 /* The following field is flag of the first automaton insn with the
781 same reservations in the declaration list. Only arcs marked such
782 insn is present in the automaton. This significantly decreases
783 memory requirements especially when several automata are
784 formed. */
785 char first_insn_with_same_reservs;
786 /* The following member has nonzero value if there is arc from state of
787 the automaton marked by the ainsn. */
788 char arc_exists_p;
789 /* Cyclic list of insns of an equivalence class is formed with the
790 aid of the following field. */
791 ainsn_t next_equiv_class_insn;
792 /* The following field value is nonzero if the insn declaration is
793 the first insn declaration with given equivalence number. */
794 char first_ainsn_with_given_equivalence_num;
795 /* The following field is number of class of equivalence of insns.
796 It is necessary because many insns may be equivalent with the
797 point of view of pipeline hazards. */
798 int insn_equiv_class_num;
799 /* The following member value is TRUE if there is an arc in the
800 automaton marked by the insn into another state. In other
801 words, the insn can change the state of the automaton. */
802 int important_p;
805 /* The following describes an automaton for PHR. */
806 struct automaton
808 /* The following field value is the list of insn declarations for
809 given automaton. */
810 ainsn_t ainsn_list;
811 /* Pointers to the ainsns corresponding to the special reservations. */
812 ainsn_t advance_ainsn, collapse_ainsn;
814 /* The following field value is the corresponding automaton
815 declaration. This field is not NULL only if the automatic
816 partition on automata is not used. */
817 struct automaton_decl *corresponding_automaton_decl;
818 /* The following field value is the next automaton. */
819 automaton_t next_automaton;
820 /* The following field is start state of FA. There are not unit
821 reservations in the state. */
822 state_t start_state;
823 /* The following field value is number of equivalence classes of
824 insns (see field `insn_equiv_class_num' in
825 `insn_reserv_decl'). */
826 int insn_equiv_classes_num;
827 /* The following field value is number of states of final DFA. */
828 int achieved_states_num;
829 /* The following field value is the order number (0, 1, ...) of
830 given automaton. */
831 int automaton_order_num;
832 /* The following fields contain statistics information about
833 building automaton. */
834 int NDFA_states_num, DFA_states_num;
835 /* The following field value is defined only if minimization of DFA
836 is used. */
837 int minimal_DFA_states_num;
838 int NDFA_arcs_num, DFA_arcs_num;
839 /* The following field value is defined only if minimization of DFA
840 is used. */
841 int minimal_DFA_arcs_num;
842 /* The following member refers for two table state x ainsn -> int.
843 ??? Above sentence is incomprehensible. */
844 state_ainsn_table_t trans_table;
845 /* The following member value is maximal value of min issue delay
846 for insns of the automaton. */
847 int max_min_delay;
848 /* Usually min issue delay is small and we can place several (2, 4,
849 8) elements in one vector element. So the compression factor can
850 be 1 (no compression), 2, 4, 8. */
851 int min_issue_delay_table_compression_factor;
852 /* Total number of locked states in this automaton. */
853 int locked_states;
856 /* The following is the element of the list of automata. */
857 struct automata_list_el
859 /* The automaton itself. */
860 automaton_t automaton;
861 /* The next automata set element. */
862 automata_list_el_t next_automata_list_el;
865 /* The following structure describes a table state X ainsn -> int(>= 0). */
866 struct state_ainsn_table
868 /* Automaton to which given table belongs. */
869 automaton_t automaton;
870 /* The following tree vectors for comb vector implementation of the
871 table. */
872 vla_hwint_t comb_vect;
873 vla_hwint_t check_vect;
874 vla_hwint_t base_vect;
875 /* This is simple implementation of the table. */
876 vla_hwint_t full_vect;
877 /* Minimal and maximal values of the previous vectors. */
878 int min_comb_vect_el_value, max_comb_vect_el_value;
879 int min_base_vect_el_value, max_base_vect_el_value;
882 /* Macros to access members of unions. Use only them for access to
883 union members of declarations and regexps. */
885 #if defined ENABLE_CHECKING && (GCC_VERSION >= 2007)
887 #define DECL_UNIT(d) __extension__ \
888 (({ __typeof (d) const _decl = (d); \
889 if (_decl->mode != dm_unit) \
890 decl_mode_check_failed (_decl->mode, "dm_unit", \
891 __FILE__, __LINE__, __FUNCTION__); \
892 &(_decl)->decl.unit; }))
894 #define DECL_BYPASS(d) __extension__ \
895 (({ __typeof (d) const _decl = (d); \
896 if (_decl->mode != dm_bypass) \
897 decl_mode_check_failed (_decl->mode, "dm_bypass", \
898 __FILE__, __LINE__, __FUNCTION__); \
899 &(_decl)->decl.bypass; }))
901 #define DECL_AUTOMATON(d) __extension__ \
902 (({ __typeof (d) const _decl = (d); \
903 if (_decl->mode != dm_automaton) \
904 decl_mode_check_failed (_decl->mode, "dm_automaton", \
905 __FILE__, __LINE__, __FUNCTION__); \
906 &(_decl)->decl.automaton; }))
908 #define DECL_EXCL(d) __extension__ \
909 (({ __typeof (d) const _decl = (d); \
910 if (_decl->mode != dm_excl) \
911 decl_mode_check_failed (_decl->mode, "dm_excl", \
912 __FILE__, __LINE__, __FUNCTION__); \
913 &(_decl)->decl.excl; }))
915 #define DECL_PRESENCE(d) __extension__ \
916 (({ __typeof (d) const _decl = (d); \
917 if (_decl->mode != dm_presence) \
918 decl_mode_check_failed (_decl->mode, "dm_presence", \
919 __FILE__, __LINE__, __FUNCTION__); \
920 &(_decl)->decl.presence; }))
922 #define DECL_ABSENCE(d) __extension__ \
923 (({ __typeof (d) const _decl = (d); \
924 if (_decl->mode != dm_absence) \
925 decl_mode_check_failed (_decl->mode, "dm_absence", \
926 __FILE__, __LINE__, __FUNCTION__); \
927 &(_decl)->decl.absence; }))
929 #define DECL_RESERV(d) __extension__ \
930 (({ __typeof (d) const _decl = (d); \
931 if (_decl->mode != dm_reserv) \
932 decl_mode_check_failed (_decl->mode, "dm_reserv", \
933 __FILE__, __LINE__, __FUNCTION__); \
934 &(_decl)->decl.reserv; }))
936 #define DECL_INSN_RESERV(d) __extension__ \
937 (({ __typeof (d) const _decl = (d); \
938 if (_decl->mode != dm_insn_reserv) \
939 decl_mode_check_failed (_decl->mode, "dm_insn_reserv", \
940 __FILE__, __LINE__, __FUNCTION__); \
941 &(_decl)->decl.insn_reserv; }))
943 static const char *decl_name (enum decl_mode);
944 static void decl_mode_check_failed (enum decl_mode, const char *,
945 const char *, int, const char *)
946 ATTRIBUTE_NORETURN;
948 /* Return string representation of declaration mode MODE. */
949 static const char *
950 decl_name (enum decl_mode mode)
952 static char str [100];
954 if (mode == dm_unit)
955 return "dm_unit";
956 else if (mode == dm_bypass)
957 return "dm_bypass";
958 else if (mode == dm_automaton)
959 return "dm_automaton";
960 else if (mode == dm_excl)
961 return "dm_excl";
962 else if (mode == dm_presence)
963 return "dm_presence";
964 else if (mode == dm_absence)
965 return "dm_absence";
966 else if (mode == dm_reserv)
967 return "dm_reserv";
968 else if (mode == dm_insn_reserv)
969 return "dm_insn_reserv";
970 else
971 sprintf (str, "unknown (%d)", (int) mode);
972 return str;
975 /* The function prints message about unexpected declaration and finish
976 the program. */
977 static void
978 decl_mode_check_failed (enum decl_mode mode, const char *expected_mode_str,
979 const char *file, int line, const char *func)
981 fprintf
982 (stderr,
983 "\n%s: %d: error in %s: DECL check: expected decl %s, have %s\n",
984 file, line, func, expected_mode_str, decl_name (mode));
985 exit (1);
989 #define REGEXP_UNIT(r) __extension__ \
990 (({ struct regexp *const _regexp = (r); \
991 if (_regexp->mode != rm_unit) \
992 regexp_mode_check_failed (_regexp->mode, "rm_unit", \
993 __FILE__, __LINE__, __FUNCTION__); \
994 &(_regexp)->regexp.unit; }))
996 #define REGEXP_RESERV(r) __extension__ \
997 (({ struct regexp *const _regexp = (r); \
998 if (_regexp->mode != rm_reserv) \
999 regexp_mode_check_failed (_regexp->mode, "rm_reserv", \
1000 __FILE__, __LINE__, __FUNCTION__); \
1001 &(_regexp)->regexp.reserv; }))
1003 #define REGEXP_SEQUENCE(r) __extension__ \
1004 (({ struct regexp *const _regexp = (r); \
1005 if (_regexp->mode != rm_sequence) \
1006 regexp_mode_check_failed (_regexp->mode, "rm_sequence", \
1007 __FILE__, __LINE__, __FUNCTION__); \
1008 &(_regexp)->regexp.sequence; }))
1010 #define REGEXP_REPEAT(r) __extension__ \
1011 (({ struct regexp *const _regexp = (r); \
1012 if (_regexp->mode != rm_repeat) \
1013 regexp_mode_check_failed (_regexp->mode, "rm_repeat", \
1014 __FILE__, __LINE__, __FUNCTION__); \
1015 &(_regexp)->regexp.repeat; }))
1017 #define REGEXP_ALLOF(r) __extension__ \
1018 (({ struct regexp *const _regexp = (r); \
1019 if (_regexp->mode != rm_allof) \
1020 regexp_mode_check_failed (_regexp->mode, "rm_allof", \
1021 __FILE__, __LINE__, __FUNCTION__); \
1022 &(_regexp)->regexp.allof; }))
1024 #define REGEXP_ONEOF(r) __extension__ \
1025 (({ struct regexp *const _regexp = (r); \
1026 if (_regexp->mode != rm_oneof) \
1027 regexp_mode_check_failed (_regexp->mode, "rm_oneof", \
1028 __FILE__, __LINE__, __FUNCTION__); \
1029 &(_regexp)->regexp.oneof; }))
1031 static const char *regexp_name (enum regexp_mode);
1032 static void regexp_mode_check_failed (enum regexp_mode, const char *,
1033 const char *, int,
1034 const char *) ATTRIBUTE_NORETURN;
1037 /* Return string representation of regexp mode MODE. */
1038 static const char *
1039 regexp_name (enum regexp_mode mode)
1041 switch (mode)
1043 case rm_unit:
1044 return "rm_unit";
1045 case rm_reserv:
1046 return "rm_reserv";
1047 case rm_nothing:
1048 return "rm_nothing";
1049 case rm_sequence:
1050 return "rm_sequence";
1051 case rm_repeat:
1052 return "rm_repeat";
1053 case rm_allof:
1054 return "rm_allof";
1055 case rm_oneof:
1056 return "rm_oneof";
1057 default:
1058 gcc_unreachable ();
1062 /* The function prints message about unexpected regexp and finish the
1063 program. */
1064 static void
1065 regexp_mode_check_failed (enum regexp_mode mode,
1066 const char *expected_mode_str,
1067 const char *file, int line, const char *func)
1069 fprintf
1070 (stderr,
1071 "\n%s: %d: error in %s: REGEXP check: expected decl %s, have %s\n",
1072 file, line, func, expected_mode_str, regexp_name (mode));
1073 exit (1);
1076 #else /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */
1078 #define DECL_UNIT(d) (&(d)->decl.unit)
1079 #define DECL_BYPASS(d) (&(d)->decl.bypass)
1080 #define DECL_AUTOMATON(d) (&(d)->decl.automaton)
1081 #define DECL_EXCL(d) (&(d)->decl.excl)
1082 #define DECL_PRESENCE(d) (&(d)->decl.presence)
1083 #define DECL_ABSENCE(d) (&(d)->decl.absence)
1084 #define DECL_RESERV(d) (&(d)->decl.reserv)
1085 #define DECL_INSN_RESERV(d) (&(d)->decl.insn_reserv)
1087 #define REGEXP_UNIT(r) (&(r)->regexp.unit)
1088 #define REGEXP_RESERV(r) (&(r)->regexp.reserv)
1089 #define REGEXP_SEQUENCE(r) (&(r)->regexp.sequence)
1090 #define REGEXP_REPEAT(r) (&(r)->regexp.repeat)
1091 #define REGEXP_ALLOF(r) (&(r)->regexp.allof)
1092 #define REGEXP_ONEOF(r) (&(r)->regexp.oneof)
1094 #endif /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */
1096 #define XCREATENODE(T) ((T *) create_node (sizeof (T)))
1097 #define XCREATENODEVEC(T, N) ((T *) create_node (sizeof (T) * (N)))
1098 #define XCREATENODEVAR(T, S) ((T *) create_node ((S)))
1100 #define XCOPYNODE(T, P) ((T *) copy_node ((P), sizeof (T)))
1101 #define XCOPYNODEVEC(T, P, N) ((T *) copy_node ((P), sizeof (T) * (N)))
1102 #define XCOPYNODEVAR(T, P, S) ((T *) copy_node ((P), (S)))
1104 /* Create IR structure (node). */
1105 static void *
1106 create_node (size_t size)
1108 void *result;
1110 obstack_blank (&irp, size);
1111 result = obstack_base (&irp);
1112 obstack_finish (&irp);
1113 /* Default values of members are NULL and zero. */
1114 memset (result, 0, size);
1115 return result;
1118 /* Copy IR structure (node). */
1119 static void *
1120 copy_node (const void *from, size_t size)
1122 void *const result = create_node (size);
1123 memcpy (result, from, size);
1124 return result;
1127 /* The function checks that NAME does not contain quotes (`"'). */
1128 static const char *
1129 check_name (const char * name, pos_t pos ATTRIBUTE_UNUSED)
1131 const char *str;
1133 for (str = name; *str != '\0'; str++)
1134 if (*str == '\"')
1135 error ("Name `%s' contains quotes", name);
1136 return name;
1139 /* Pointers to all declarations during IR generation are stored in the
1140 following. */
1141 static vec<decl_t> decls;
1143 /* Given a pointer to a (char *) and a separator, return an alloc'ed
1144 string containing the next separated element, taking parentheses
1145 into account if PAR_FLAG has nonzero value. Advance the pointer to
1146 after the string scanned, or the end-of-string. Return NULL if at
1147 end of string. */
1148 static char *
1149 next_sep_el (const char **pstr, int sep, int par_flag)
1151 char *out_str;
1152 const char *p;
1153 int pars_num;
1154 int n_spaces;
1156 /* Remove leading whitespaces. */
1157 while (ISSPACE ((int) **pstr))
1158 (*pstr)++;
1160 if (**pstr == '\0')
1161 return NULL;
1163 n_spaces = 0;
1164 for (pars_num = 0, p = *pstr; *p != '\0'; p++)
1166 if (par_flag && *p == '(')
1167 pars_num++;
1168 else if (par_flag && *p == ')')
1169 pars_num--;
1170 else if (pars_num == 0 && *p == sep)
1171 break;
1172 if (pars_num == 0 && ISSPACE ((int) *p))
1173 n_spaces++;
1174 else
1176 for (; n_spaces != 0; n_spaces--)
1177 obstack_1grow (&irp, p [-n_spaces]);
1178 obstack_1grow (&irp, *p);
1181 obstack_1grow (&irp, '\0');
1182 out_str = obstack_base (&irp);
1183 obstack_finish (&irp);
1185 *pstr = p;
1186 if (**pstr == sep)
1187 (*pstr)++;
1189 return out_str;
1192 /* Given a string and a separator, return the number of separated
1193 elements in it, taking parentheses into account if PAR_FLAG has
1194 nonzero value. Return 0 for the null string, -1 if parentheses is
1195 not balanced. */
1196 static int
1197 n_sep_els (const char *s, int sep, int par_flag)
1199 int n;
1200 int pars_num;
1202 if (*s == '\0')
1203 return 0;
1205 for (pars_num = 0, n = 1; *s; s++)
1206 if (par_flag && *s == '(')
1207 pars_num++;
1208 else if (par_flag && *s == ')')
1209 pars_num--;
1210 else if (pars_num == 0 && *s == sep)
1211 n++;
1213 return (pars_num != 0 ? -1 : n);
1216 /* Given a string and a separator, return vector of strings which are
1217 elements in the string and number of elements through els_num.
1218 Take parentheses into account if PAREN_P has nonzero value. The
1219 function also inserts the end marker NULL at the end of vector.
1220 Return 0 for the null string, -1 if parentheses are not balanced. */
1221 static char **
1222 get_str_vect (const char *str, int *els_num, int sep, int paren_p)
1224 int i;
1225 char **vect;
1226 const char **pstr;
1227 char *trail;
1229 *els_num = n_sep_els (str, sep, paren_p);
1230 if (*els_num <= 0)
1231 return NULL;
1232 obstack_blank (&irp, sizeof (char *) * (*els_num + 1));
1233 vect = (char **) obstack_base (&irp);
1234 obstack_finish (&irp);
1235 pstr = &str;
1236 for (i = 0; i < *els_num; i++)
1237 vect [i] = next_sep_el (pstr, sep, paren_p);
1238 trail = next_sep_el (pstr, sep, paren_p);
1239 gcc_assert (!trail);
1240 vect [i] = NULL;
1241 return vect;
1244 /* Process a DEFINE_CPU_UNIT.
1246 This gives information about a unit contained in CPU. We fill a
1247 struct unit_decl with information used later by `expand_automata'. */
1248 static void
1249 gen_cpu_unit (rtx def)
1251 decl_t decl;
1252 char **str_cpu_units;
1253 int vect_length;
1254 int i;
1256 str_cpu_units = get_str_vect (XSTR (def, 0), &vect_length, ',', FALSE);
1257 if (str_cpu_units == NULL)
1258 fatal ("invalid string `%s' in define_cpu_unit", XSTR (def, 0));
1259 for (i = 0; i < vect_length; i++)
1261 decl = XCREATENODE (struct decl);
1262 decl->mode = dm_unit;
1263 decl->pos = 0;
1264 DECL_UNIT (decl)->name = check_name (str_cpu_units [i], decl->pos);
1265 DECL_UNIT (decl)->automaton_name = XSTR (def, 1);
1266 DECL_UNIT (decl)->query_p = 0;
1267 DECL_UNIT (decl)->min_occ_cycle_num = -1;
1268 DECL_UNIT (decl)->in_set_p = 0;
1269 decls.safe_push (decl);
1273 /* Process a DEFINE_QUERY_CPU_UNIT.
1275 This gives information about a unit contained in CPU. We fill a
1276 struct unit_decl with information used later by `expand_automata'. */
1277 static void
1278 gen_query_cpu_unit (rtx def)
1280 decl_t decl;
1281 char **str_cpu_units;
1282 int vect_length;
1283 int i;
1285 str_cpu_units = get_str_vect (XSTR (def, 0), &vect_length, ',',
1286 FALSE);
1287 if (str_cpu_units == NULL)
1288 fatal ("invalid string `%s' in define_query_cpu_unit", XSTR (def, 0));
1289 for (i = 0; i < vect_length; i++)
1291 decl = XCREATENODE (struct decl);
1292 decl->mode = dm_unit;
1293 decl->pos = 0;
1294 DECL_UNIT (decl)->name = check_name (str_cpu_units [i], decl->pos);
1295 DECL_UNIT (decl)->automaton_name = XSTR (def, 1);
1296 DECL_UNIT (decl)->query_p = 1;
1297 decls.safe_push (decl);
1301 /* Process a DEFINE_BYPASS.
1303 This gives information about a unit contained in the CPU. We fill
1304 in a struct bypass_decl with information used later by
1305 `expand_automata'. */
1306 static void
1307 gen_bypass (rtx def)
1309 decl_t decl;
1310 char **out_patterns;
1311 int out_length;
1312 char **in_patterns;
1313 int in_length;
1314 int i, j;
1316 out_patterns = get_str_vect (XSTR (def, 1), &out_length, ',', FALSE);
1317 if (out_patterns == NULL)
1318 fatal ("invalid string `%s' in define_bypass", XSTR (def, 1));
1319 in_patterns = get_str_vect (XSTR (def, 2), &in_length, ',', FALSE);
1320 if (in_patterns == NULL)
1321 fatal ("invalid string `%s' in define_bypass", XSTR (def, 2));
1322 for (i = 0; i < out_length; i++)
1323 for (j = 0; j < in_length; j++)
1325 decl = XCREATENODE (struct decl);
1326 decl->mode = dm_bypass;
1327 decl->pos = 0;
1328 DECL_BYPASS (decl)->latency = XINT (def, 0);
1329 DECL_BYPASS (decl)->out_pattern = out_patterns[i];
1330 DECL_BYPASS (decl)->in_pattern = in_patterns[j];
1331 DECL_BYPASS (decl)->bypass_guard_name = XSTR (def, 3);
1332 decls.safe_push (decl);
1336 /* Process an EXCLUSION_SET.
1338 This gives information about a cpu unit conflicts. We fill a
1339 struct excl_rel_decl (excl) with information used later by
1340 `expand_automata'. */
1341 static void
1342 gen_excl_set (rtx def)
1344 decl_t decl;
1345 char **first_str_cpu_units;
1346 char **second_str_cpu_units;
1347 int first_vect_length;
1348 int length;
1349 int i;
1351 first_str_cpu_units
1352 = get_str_vect (XSTR (def, 0), &first_vect_length, ',', FALSE);
1353 if (first_str_cpu_units == NULL)
1354 fatal ("invalid first string `%s' in exclusion_set", XSTR (def, 0));
1355 second_str_cpu_units = get_str_vect (XSTR (def, 1), &length, ',',
1356 FALSE);
1357 if (second_str_cpu_units == NULL)
1358 fatal ("invalid second string `%s' in exclusion_set", XSTR (def, 1));
1359 length += first_vect_length;
1360 decl = XCREATENODEVAR (struct decl, sizeof (struct decl) + (length - 1) * sizeof (char *));
1361 decl->mode = dm_excl;
1362 decl->pos = 0;
1363 DECL_EXCL (decl)->all_names_num = length;
1364 DECL_EXCL (decl)->first_list_length = first_vect_length;
1365 for (i = 0; i < length; i++)
1366 if (i < first_vect_length)
1367 DECL_EXCL (decl)->names [i] = first_str_cpu_units [i];
1368 else
1369 DECL_EXCL (decl)->names [i]
1370 = second_str_cpu_units [i - first_vect_length];
1371 decls.safe_push (decl);
1374 /* Process a PRESENCE_SET, a FINAL_PRESENCE_SET, an ABSENCE_SET,
1375 FINAL_ABSENCE_SET (it is depended on PRESENCE_P and FINAL_P).
1377 This gives information about a cpu unit reservation requirements.
1378 We fill a struct unit_pattern_rel_decl with information used later
1379 by `expand_automata'. */
1380 static void
1381 gen_presence_absence_set (rtx def, int presence_p, int final_p)
1383 decl_t decl;
1384 char **str_cpu_units;
1385 char **str_pattern_lists;
1386 char ***str_patterns;
1387 int cpu_units_length;
1388 int length;
1389 int patterns_length;
1390 int i;
1392 str_cpu_units = get_str_vect (XSTR (def, 0), &cpu_units_length, ',',
1393 FALSE);
1394 if (str_cpu_units == NULL)
1395 fatal ((presence_p
1396 ? (final_p
1397 ? "invalid first string `%s' in final_presence_set"
1398 : "invalid first string `%s' in presence_set")
1399 : (final_p
1400 ? "invalid first string `%s' in final_absence_set"
1401 : "invalid first string `%s' in absence_set")),
1402 XSTR (def, 0));
1403 str_pattern_lists = get_str_vect (XSTR (def, 1),
1404 &patterns_length, ',', FALSE);
1405 if (str_pattern_lists == NULL)
1406 fatal ((presence_p
1407 ? (final_p
1408 ? "invalid second string `%s' in final_presence_set"
1409 : "invalid second string `%s' in presence_set")
1410 : (final_p
1411 ? "invalid second string `%s' in final_absence_set"
1412 : "invalid second string `%s' in absence_set")), XSTR (def, 1));
1413 str_patterns = XOBNEWVEC (&irp, char **, patterns_length);
1414 for (i = 0; i < patterns_length; i++)
1416 str_patterns [i] = get_str_vect (str_pattern_lists [i],
1417 &length, ' ', FALSE);
1418 gcc_assert (str_patterns [i]);
1420 decl = XCREATENODE (struct decl);
1421 decl->pos = 0;
1422 if (presence_p)
1424 decl->mode = dm_presence;
1425 DECL_PRESENCE (decl)->names_num = cpu_units_length;
1426 DECL_PRESENCE (decl)->names = str_cpu_units;
1427 DECL_PRESENCE (decl)->patterns = str_patterns;
1428 DECL_PRESENCE (decl)->patterns_num = patterns_length;
1429 DECL_PRESENCE (decl)->final_p = final_p;
1431 else
1433 decl->mode = dm_absence;
1434 DECL_ABSENCE (decl)->names_num = cpu_units_length;
1435 DECL_ABSENCE (decl)->names = str_cpu_units;
1436 DECL_ABSENCE (decl)->patterns = str_patterns;
1437 DECL_ABSENCE (decl)->patterns_num = patterns_length;
1438 DECL_ABSENCE (decl)->final_p = final_p;
1440 decls.safe_push (decl);
1443 /* Process a PRESENCE_SET.
1445 This gives information about a cpu unit reservation requirements.
1446 We fill a struct unit_pattern_rel_decl (presence) with information
1447 used later by `expand_automata'. */
1448 static void
1449 gen_presence_set (rtx def)
1451 gen_presence_absence_set (def, TRUE, FALSE);
1454 /* Process a FINAL_PRESENCE_SET.
1456 This gives information about a cpu unit reservation requirements.
1457 We fill a struct unit_pattern_rel_decl (presence) with information
1458 used later by `expand_automata'. */
1459 static void
1460 gen_final_presence_set (rtx def)
1462 gen_presence_absence_set (def, TRUE, TRUE);
1465 /* Process an ABSENCE_SET.
1467 This gives information about a cpu unit reservation requirements.
1468 We fill a struct unit_pattern_rel_decl (absence) with information
1469 used later by `expand_automata'. */
1470 static void
1471 gen_absence_set (rtx def)
1473 gen_presence_absence_set (def, FALSE, FALSE);
1476 /* Process a FINAL_ABSENCE_SET.
1478 This gives information about a cpu unit reservation requirements.
1479 We fill a struct unit_pattern_rel_decl (absence) with information
1480 used later by `expand_automata'. */
1481 static void
1482 gen_final_absence_set (rtx def)
1484 gen_presence_absence_set (def, FALSE, TRUE);
1487 /* Process a DEFINE_AUTOMATON.
1489 This gives information about a finite state automaton used for
1490 recognizing pipeline hazards. We fill a struct automaton_decl
1491 with information used later by `expand_automata'. */
1492 static void
1493 gen_automaton (rtx def)
1495 decl_t decl;
1496 char **str_automata;
1497 int vect_length;
1498 int i;
1500 str_automata = get_str_vect (XSTR (def, 0), &vect_length, ',', FALSE);
1501 if (str_automata == NULL)
1502 fatal ("invalid string `%s' in define_automaton", XSTR (def, 0));
1503 for (i = 0; i < vect_length; i++)
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);
1513 /* Process an AUTOMATA_OPTION.
1515 This gives information how to generate finite state automaton used
1516 for recognizing pipeline hazards. */
1517 static void
1518 gen_automata_option (rtx def)
1520 if (strcmp (XSTR (def, 0), NO_MINIMIZATION_OPTION + 1) == 0)
1521 no_minimization_flag = 1;
1522 else if (strcmp (XSTR (def, 0), TIME_OPTION + 1) == 0)
1523 time_flag = 1;
1524 else if (strcmp (XSTR (def, 0), STATS_OPTION + 1) == 0)
1525 stats_flag = 1;
1526 else if (strcmp (XSTR (def, 0), V_OPTION + 1) == 0)
1527 v_flag = 1;
1528 else if (strcmp (XSTR (def, 0), W_OPTION + 1) == 0)
1529 w_flag = 1;
1530 else if (strcmp (XSTR (def, 0), NDFA_OPTION + 1) == 0)
1531 ndfa_flag = 1;
1532 else if (strcmp (XSTR (def, 0), COLLAPSE_OPTION + 1) == 0)
1533 collapse_flag = 1;
1534 else if (strcmp (XSTR (def, 0), NO_COMB_OPTION + 1) == 0)
1535 no_comb_flag = 1;
1536 else if (strcmp (XSTR (def, 0), PROGRESS_OPTION + 1) == 0)
1537 progress_flag = 1;
1538 else
1539 fatal ("invalid option `%s' in automata_option", XSTR (def, 0));
1542 /* Name in reservation to denote absence reservation. */
1543 #define NOTHING_NAME "nothing"
1545 /* The following string contains original reservation string being
1546 parsed. */
1547 static const char *reserv_str;
1549 /* Parse an element in STR. */
1550 static regexp_t
1551 gen_regexp_el (const char *str)
1553 regexp_t regexp;
1554 char *dstr;
1555 int len;
1557 if (*str == '(')
1559 len = strlen (str);
1560 if (str [len - 1] != ')')
1561 fatal ("garbage after ) in reservation `%s'", reserv_str);
1562 dstr = XALLOCAVAR (char, len - 1);
1563 memcpy (dstr, str + 1, len - 2);
1564 dstr [len-2] = '\0';
1565 regexp = gen_regexp_sequence (dstr);
1567 else if (strcmp (str, NOTHING_NAME) == 0)
1569 regexp = XCREATENODE (struct regexp);
1570 regexp->mode = rm_nothing;
1572 else
1574 regexp = XCREATENODE (struct regexp);
1575 regexp->mode = rm_unit;
1576 REGEXP_UNIT (regexp)->name = str;
1578 return regexp;
1581 /* Parse construction `repeat' in STR. */
1582 static regexp_t
1583 gen_regexp_repeat (const char *str)
1585 regexp_t regexp;
1586 regexp_t repeat;
1587 char **repeat_vect;
1588 int els_num;
1589 int i;
1591 repeat_vect = get_str_vect (str, &els_num, '*', TRUE);
1592 if (repeat_vect == NULL)
1593 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1594 if (els_num > 1)
1596 regexp = gen_regexp_el (repeat_vect [0]);
1597 for (i = 1; i < els_num; i++)
1599 repeat = XCREATENODE (struct regexp);
1600 repeat->mode = rm_repeat;
1601 REGEXP_REPEAT (repeat)->regexp = regexp;
1602 REGEXP_REPEAT (repeat)->repeat_num = atoi (repeat_vect [i]);
1603 if (REGEXP_REPEAT (repeat)->repeat_num <= 1)
1604 fatal ("repetition `%s' <= 1 in reservation `%s'",
1605 str, reserv_str);
1606 regexp = repeat;
1608 return regexp;
1610 else
1611 return gen_regexp_el (repeat_vect[0]);
1614 /* Parse reservation STR which possibly contains separator '+'. */
1615 static regexp_t
1616 gen_regexp_allof (const char *str)
1618 regexp_t allof;
1619 char **allof_vect;
1620 int els_num;
1621 int i;
1623 allof_vect = get_str_vect (str, &els_num, '+', TRUE);
1624 if (allof_vect == NULL)
1625 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1626 if (els_num > 1)
1628 allof = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
1629 + sizeof (regexp_t) * (els_num - 1));
1630 allof->mode = rm_allof;
1631 REGEXP_ALLOF (allof)->regexps_num = els_num;
1632 for (i = 0; i < els_num; i++)
1633 REGEXP_ALLOF (allof)->regexps [i] = gen_regexp_repeat (allof_vect [i]);
1634 return allof;
1636 else
1637 return gen_regexp_repeat (allof_vect[0]);
1640 /* Parse reservation STR which possibly contains separator '|'. */
1641 static regexp_t
1642 gen_regexp_oneof (const char *str)
1644 regexp_t oneof;
1645 char **oneof_vect;
1646 int els_num;
1647 int i;
1649 oneof_vect = get_str_vect (str, &els_num, '|', TRUE);
1650 if (oneof_vect == NULL)
1651 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1652 if (els_num > 1)
1654 oneof = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
1655 + sizeof (regexp_t) * (els_num - 1));
1656 oneof->mode = rm_oneof;
1657 REGEXP_ONEOF (oneof)->regexps_num = els_num;
1658 for (i = 0; i < els_num; i++)
1659 REGEXP_ONEOF (oneof)->regexps [i] = gen_regexp_allof (oneof_vect [i]);
1660 return oneof;
1662 else
1663 return gen_regexp_allof (oneof_vect[0]);
1666 /* Parse reservation STR which possibly contains separator ','. */
1667 static regexp_t
1668 gen_regexp_sequence (const char *str)
1670 regexp_t sequence;
1671 char **sequence_vect;
1672 int els_num;
1673 int i;
1675 sequence_vect = get_str_vect (str, &els_num, ',', TRUE);
1676 if (els_num > 1)
1678 sequence = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
1679 + sizeof (regexp_t) * (els_num - 1));
1680 sequence->mode = rm_sequence;
1681 REGEXP_SEQUENCE (sequence)->regexps_num = els_num;
1682 for (i = 0; i < els_num; i++)
1683 REGEXP_SEQUENCE (sequence)->regexps [i]
1684 = gen_regexp_oneof (sequence_vect [i]);
1685 return sequence;
1687 else
1688 return gen_regexp_oneof (sequence_vect[0]);
1691 /* Parse construction reservation STR. */
1692 static regexp_t
1693 gen_regexp (const char *str)
1695 reserv_str = str;
1696 return gen_regexp_sequence (str);
1699 /* Process a DEFINE_RESERVATION.
1701 This gives information about a reservation of cpu units. We fill
1702 in a struct reserv_decl with information used later by
1703 `expand_automata'. */
1704 static void
1705 gen_reserv (rtx def)
1707 decl_t decl;
1709 decl = XCREATENODE (struct decl);
1710 decl->mode = dm_reserv;
1711 decl->pos = 0;
1712 DECL_RESERV (decl)->name = check_name (XSTR (def, 0), decl->pos);
1713 DECL_RESERV (decl)->regexp = gen_regexp (XSTR (def, 1));
1714 decls.safe_push (decl);
1717 /* Process a DEFINE_INSN_RESERVATION.
1719 This gives information about the reservation of cpu units by an
1720 insn. We fill a struct insn_reserv_decl with information used
1721 later by `expand_automata'. */
1722 static void
1723 gen_insn_reserv (rtx def)
1725 decl_t decl;
1727 decl = XCREATENODE (struct decl);
1728 decl->mode = dm_insn_reserv;
1729 decl->pos = 0;
1730 DECL_INSN_RESERV (decl)->name
1731 = check_name (XSTR (def, 0), decl->pos);
1732 DECL_INSN_RESERV (decl)->default_latency = XINT (def, 1);
1733 DECL_INSN_RESERV (decl)->condexp = XEXP (def, 2);
1734 DECL_INSN_RESERV (decl)->regexp = gen_regexp (XSTR (def, 3));
1735 decls.safe_push (decl);
1740 /* The function evaluates hash value (0..UINT_MAX) of string. */
1741 static unsigned
1742 string_hash (const char *string)
1744 unsigned result, i;
1746 for (result = i = 0;*string++ != '\0'; i++)
1747 result += ((unsigned char) *string << (i % CHAR_BIT));
1748 return result;
1753 /* This page contains abstract data `table of automaton declarations'.
1754 Elements of the table is nodes representing automaton declarations.
1755 Key of the table elements is name of given automaton. Remember
1756 that automaton names have own space. */
1758 /* The function evaluates hash value of an automaton declaration. The
1759 function is used by abstract data `hashtab'. The function returns
1760 hash value (0..UINT_MAX) of given automaton declaration. */
1761 static hashval_t
1762 automaton_decl_hash (const void *automaton_decl)
1764 const_decl_t const decl = (const_decl_t) automaton_decl;
1766 gcc_assert (decl->mode != dm_automaton
1767 || DECL_AUTOMATON (decl)->name);
1768 return string_hash (DECL_AUTOMATON (decl)->name);
1771 /* The function tests automaton declarations on equality of their
1772 keys. The function is used by abstract data `hashtab'. The
1773 function returns 1 if the declarations have the same key, 0
1774 otherwise. */
1775 static int
1776 automaton_decl_eq_p (const void* automaton_decl_1,
1777 const void* automaton_decl_2)
1779 const_decl_t const decl1 = (const_decl_t) automaton_decl_1;
1780 const_decl_t const decl2 = (const_decl_t) automaton_decl_2;
1782 gcc_assert (decl1->mode == dm_automaton
1783 && DECL_AUTOMATON (decl1)->name
1784 && decl2->mode == dm_automaton
1785 && DECL_AUTOMATON (decl2)->name);
1786 return strcmp (DECL_AUTOMATON (decl1)->name,
1787 DECL_AUTOMATON (decl2)->name) == 0;
1790 /* The automaton declaration table itself is represented by the
1791 following variable. */
1792 static htab_t automaton_decl_table;
1794 /* The function inserts automaton declaration into the table. The
1795 function does nothing if an automaton declaration with the same key
1796 exists already in the table. The function returns automaton
1797 declaration node in the table with the same key as given automaton
1798 declaration node. */
1799 static decl_t
1800 insert_automaton_decl (decl_t automaton_decl)
1802 void **entry_ptr;
1804 entry_ptr = htab_find_slot (automaton_decl_table, automaton_decl, INSERT);
1805 if (*entry_ptr == NULL)
1806 *entry_ptr = (void *) automaton_decl;
1807 return (decl_t) *entry_ptr;
1810 /* The following variable value is node representing automaton
1811 declaration. The node used for searching automaton declaration
1812 with given name. */
1813 static struct decl work_automaton_decl;
1815 /* The function searches for automaton declaration in the table with
1816 the same key as node representing name of the automaton
1817 declaration. The function returns node found in the table, NULL if
1818 such node does not exist in the table. */
1819 static decl_t
1820 find_automaton_decl (const char *name)
1822 void *entry;
1824 work_automaton_decl.mode = dm_automaton;
1825 DECL_AUTOMATON (&work_automaton_decl)->name = name;
1826 entry = htab_find (automaton_decl_table, &work_automaton_decl);
1827 return (decl_t) entry;
1830 /* The function creates empty automaton declaration table and node
1831 representing automaton declaration and used for searching automaton
1832 declaration with given name. The function must be called only once
1833 before any work with the automaton declaration table. */
1834 static void
1835 initiate_automaton_decl_table (void)
1837 work_automaton_decl.mode = dm_automaton;
1838 automaton_decl_table = htab_create (10, automaton_decl_hash,
1839 automaton_decl_eq_p, (htab_del) 0);
1842 /* The function deletes the automaton declaration table. Only call of
1843 function `initiate_automaton_decl_table' is possible immediately
1844 after this function call. */
1845 static void
1846 finish_automaton_decl_table (void)
1848 htab_delete (automaton_decl_table);
1853 /* This page contains abstract data `table of insn declarations'.
1854 Elements of the table is nodes representing insn declarations. Key
1855 of the table elements is name of given insn (in corresponding
1856 define_insn_reservation). Remember that insn names have own
1857 space. */
1859 /* The function evaluates hash value of an insn declaration. The
1860 function is used by abstract data `hashtab'. The function returns
1861 hash value (0..UINT_MAX) of given insn declaration. */
1862 static hashval_t
1863 insn_decl_hash (const void *insn_decl)
1865 const_decl_t const decl = (const_decl_t) insn_decl;
1867 gcc_assert (decl->mode == dm_insn_reserv
1868 && DECL_INSN_RESERV (decl)->name);
1869 return string_hash (DECL_INSN_RESERV (decl)->name);
1872 /* The function tests insn declarations on equality of their keys.
1873 The function is used by abstract data `hashtab'. The function
1874 returns 1 if declarations have the same key, 0 otherwise. */
1875 static int
1876 insn_decl_eq_p (const void *insn_decl_1, const void *insn_decl_2)
1878 const_decl_t const decl1 = (const_decl_t) insn_decl_1;
1879 const_decl_t const decl2 = (const_decl_t) insn_decl_2;
1881 gcc_assert (decl1->mode == dm_insn_reserv
1882 && DECL_INSN_RESERV (decl1)->name
1883 && decl2->mode == dm_insn_reserv
1884 && DECL_INSN_RESERV (decl2)->name);
1885 return strcmp (DECL_INSN_RESERV (decl1)->name,
1886 DECL_INSN_RESERV (decl2)->name) == 0;
1889 /* The insn declaration table itself is represented by the following
1890 variable. The table does not contain insn reservation
1891 declarations. */
1892 static htab_t insn_decl_table;
1894 /* The function inserts insn declaration into the table. The function
1895 does nothing if an insn declaration with the same key exists
1896 already in the table. The function returns insn declaration node
1897 in the table with the same key as given insn declaration node. */
1898 static decl_t
1899 insert_insn_decl (decl_t insn_decl)
1901 void **entry_ptr;
1903 entry_ptr = htab_find_slot (insn_decl_table, insn_decl, INSERT);
1904 if (*entry_ptr == NULL)
1905 *entry_ptr = (void *) insn_decl;
1906 return (decl_t) *entry_ptr;
1909 /* The following variable value is node representing insn reservation
1910 declaration. The node used for searching insn reservation
1911 declaration with given name. */
1912 static struct decl work_insn_decl;
1914 /* The function searches for insn reservation declaration in the table
1915 with the same key as node representing name of the insn reservation
1916 declaration. The function returns node found in the table, NULL if
1917 such node does not exist in the table. */
1918 static decl_t
1919 find_insn_decl (const char *name)
1921 void *entry;
1923 work_insn_decl.mode = dm_insn_reserv;
1924 DECL_INSN_RESERV (&work_insn_decl)->name = name;
1925 entry = htab_find (insn_decl_table, &work_insn_decl);
1926 return (decl_t) entry;
1929 /* The function creates empty insn declaration table and node
1930 representing insn declaration and used for searching insn
1931 declaration with given name. The function must be called only once
1932 before any work with the insn declaration table. */
1933 static void
1934 initiate_insn_decl_table (void)
1936 work_insn_decl.mode = dm_insn_reserv;
1937 insn_decl_table = htab_create (10, insn_decl_hash, insn_decl_eq_p,
1938 (htab_del) 0);
1941 /* The function deletes the insn declaration table. Only call of
1942 function `initiate_insn_decl_table' is possible immediately after
1943 this function call. */
1944 static void
1945 finish_insn_decl_table (void)
1947 htab_delete (insn_decl_table);
1952 /* This page contains abstract data `table of declarations'. Elements
1953 of the table is nodes representing declarations (of units and
1954 reservations). Key of the table elements is names of given
1955 declarations. */
1957 /* The function evaluates hash value of a declaration. The function
1958 is used by abstract data `hashtab'. The function returns hash
1959 value (0..UINT_MAX) of given declaration. */
1960 static hashval_t
1961 decl_hash (const void *decl)
1963 const_decl_t const d = (const_decl_t) decl;
1965 gcc_assert ((d->mode == dm_unit && DECL_UNIT (d)->name)
1966 || (d->mode == dm_reserv && DECL_RESERV (d)->name));
1967 return string_hash (d->mode == dm_unit
1968 ? DECL_UNIT (d)->name : DECL_RESERV (d)->name);
1971 /* The function tests declarations on equality of their keys. The
1972 function is used by abstract data 'hashtab'. The function
1973 returns 1 if the declarations have the same key, 0 otherwise. */
1974 static int
1975 decl_eq_p (const void *decl_1, const void *decl_2)
1977 const_decl_t const d1 = (const_decl_t) decl_1;
1978 const_decl_t const d2 = (const_decl_t) decl_2;
1980 gcc_assert ((d1->mode == dm_unit && DECL_UNIT (d1)->name)
1981 || (d1->mode == dm_reserv && DECL_RESERV (d1)->name));
1982 gcc_assert ((d2->mode == dm_unit && DECL_UNIT (d2)->name)
1983 || (d2->mode == dm_reserv && DECL_RESERV (d2)->name));
1984 return strcmp ((d1->mode == dm_unit
1985 ? DECL_UNIT (d1)->name : DECL_RESERV (d1)->name),
1986 (d2->mode == dm_unit
1987 ? DECL_UNIT (d2)->name : DECL_RESERV (d2)->name)) == 0;
1990 /* The declaration table itself is represented by the following
1991 variable. */
1992 static htab_t decl_table;
1994 /* The function inserts declaration into the table. The function does
1995 nothing if a declaration with the same key exists already in the
1996 table. The function returns declaration node in the table with the
1997 same key as given declaration node. */
1999 static decl_t
2000 insert_decl (decl_t decl)
2002 void **entry_ptr;
2004 entry_ptr = htab_find_slot (decl_table, decl, INSERT);
2005 if (*entry_ptr == NULL)
2006 *entry_ptr = (void *) decl;
2007 return (decl_t) *entry_ptr;
2010 /* The following variable value is node representing declaration. The
2011 node used for searching declaration with given name. */
2012 static struct decl work_decl;
2014 /* The function searches for declaration in the table with the same
2015 key as node representing name of the declaration. The function
2016 returns node found in the table, NULL if such node does not exist
2017 in the table. */
2018 static decl_t
2019 find_decl (const char *name)
2021 void *entry;
2023 work_decl.mode = dm_unit;
2024 DECL_UNIT (&work_decl)->name = name;
2025 entry = htab_find (decl_table, &work_decl);
2026 return (decl_t) entry;
2029 /* The function creates empty declaration table and node representing
2030 declaration and used for searching declaration with given name.
2031 The function must be called only once before any work with the
2032 declaration table. */
2033 static void
2034 initiate_decl_table (void)
2036 work_decl.mode = dm_unit;
2037 decl_table = htab_create (10, decl_hash, decl_eq_p, (htab_del) 0);
2040 /* The function deletes the declaration table. Only call of function
2041 `initiate_declaration_table' is possible immediately after this
2042 function call. */
2043 static void
2044 finish_decl_table (void)
2046 htab_delete (decl_table);
2051 /* This page contains checker of pipeline hazard description. */
2053 /* Checking NAMES in an exclusion clause vector and returning formed
2054 unit_set_el_list. */
2055 static unit_set_el_t
2056 process_excls (char **names, int num, pos_t excl_pos ATTRIBUTE_UNUSED)
2058 unit_set_el_t el_list;
2059 unit_set_el_t last_el;
2060 unit_set_el_t new_el;
2061 decl_t decl_in_table;
2062 int i;
2064 el_list = NULL;
2065 last_el = NULL;
2066 for (i = 0; i < num; i++)
2068 decl_in_table = find_decl (names [i]);
2069 if (decl_in_table == NULL)
2070 error ("unit `%s' in exclusion is not declared", names [i]);
2071 else if (decl_in_table->mode != dm_unit)
2072 error ("`%s' in exclusion is not unit", names [i]);
2073 else
2075 new_el = XCREATENODE (struct unit_set_el);
2076 new_el->unit_decl = DECL_UNIT (decl_in_table);
2077 new_el->next_unit_set_el = NULL;
2078 if (last_el == NULL)
2079 el_list = last_el = new_el;
2080 else
2082 last_el->next_unit_set_el = new_el;
2083 last_el = last_el->next_unit_set_el;
2087 return el_list;
2090 /* The function adds each element from SOURCE_LIST to the exclusion
2091 list of the each element from DEST_LIST. Checking situation "unit
2092 excludes itself". */
2093 static void
2094 add_excls (unit_set_el_t dest_list, unit_set_el_t source_list,
2095 pos_t excl_pos ATTRIBUTE_UNUSED)
2097 unit_set_el_t dst;
2098 unit_set_el_t src;
2099 unit_set_el_t curr_el;
2100 unit_set_el_t prev_el;
2101 unit_set_el_t copy;
2103 for (dst = dest_list; dst != NULL; dst = dst->next_unit_set_el)
2104 for (src = source_list; src != NULL; src = src->next_unit_set_el)
2106 if (dst->unit_decl == src->unit_decl)
2108 error ("unit `%s' excludes itself", src->unit_decl->name);
2109 continue;
2111 if (dst->unit_decl->automaton_name != NULL
2112 && src->unit_decl->automaton_name != NULL
2113 && strcmp (dst->unit_decl->automaton_name,
2114 src->unit_decl->automaton_name) != 0)
2116 error ("units `%s' and `%s' in exclusion set belong to different automata",
2117 src->unit_decl->name, dst->unit_decl->name);
2118 continue;
2120 for (curr_el = dst->unit_decl->excl_list, prev_el = NULL;
2121 curr_el != NULL;
2122 prev_el = curr_el, curr_el = curr_el->next_unit_set_el)
2123 if (curr_el->unit_decl == src->unit_decl)
2124 break;
2125 if (curr_el == NULL)
2127 /* Element not found - insert. */
2128 copy = XCOPYNODE (struct unit_set_el, src);
2129 copy->next_unit_set_el = NULL;
2130 if (prev_el == NULL)
2131 dst->unit_decl->excl_list = copy;
2132 else
2133 prev_el->next_unit_set_el = copy;
2138 /* Checking NAMES in presence/absence clause and returning the
2139 formed unit_set_el_list. The function is called only after
2140 processing all exclusion sets. */
2141 static unit_set_el_t
2142 process_presence_absence_names (char **names, int num,
2143 pos_t req_pos ATTRIBUTE_UNUSED,
2144 int presence_p, int final_p)
2146 unit_set_el_t el_list;
2147 unit_set_el_t last_el;
2148 unit_set_el_t new_el;
2149 decl_t decl_in_table;
2150 int i;
2152 el_list = NULL;
2153 last_el = NULL;
2154 for (i = 0; i < num; i++)
2156 decl_in_table = find_decl (names [i]);
2157 if (decl_in_table == NULL)
2158 error ((presence_p
2159 ? (final_p
2160 ? "unit `%s' in final presence set is not declared"
2161 : "unit `%s' in presence set is not declared")
2162 : (final_p
2163 ? "unit `%s' in final absence set is not declared"
2164 : "unit `%s' in absence set is not declared")), names [i]);
2165 else if (decl_in_table->mode != dm_unit)
2166 error ((presence_p
2167 ? (final_p
2168 ? "`%s' in final presence set is not unit"
2169 : "`%s' in presence set is not unit")
2170 : (final_p
2171 ? "`%s' in final absence set is not unit"
2172 : "`%s' in absence set is not unit")), names [i]);
2173 else
2175 new_el = XCREATENODE (struct unit_set_el);
2176 new_el->unit_decl = DECL_UNIT (decl_in_table);
2177 new_el->next_unit_set_el = NULL;
2178 if (last_el == NULL)
2179 el_list = last_el = new_el;
2180 else
2182 last_el->next_unit_set_el = new_el;
2183 last_el = last_el->next_unit_set_el;
2187 return el_list;
2190 /* Checking NAMES in patterns of a presence/absence clause and
2191 returning the formed pattern_set_el_list. The function is called
2192 only after processing all exclusion sets. */
2193 static pattern_set_el_t
2194 process_presence_absence_patterns (char ***patterns, int num,
2195 pos_t req_pos ATTRIBUTE_UNUSED,
2196 int presence_p, int final_p)
2198 pattern_set_el_t el_list;
2199 pattern_set_el_t last_el;
2200 pattern_set_el_t new_el;
2201 decl_t decl_in_table;
2202 int i, j;
2204 el_list = NULL;
2205 last_el = NULL;
2206 for (i = 0; i < num; i++)
2208 for (j = 0; patterns [i] [j] != NULL; j++)
2210 new_el = XCREATENODEVAR (struct pattern_set_el,
2211 sizeof (struct pattern_set_el)
2212 + sizeof (struct unit_decl *) * j);
2213 new_el->unit_decls
2214 = (struct unit_decl **) ((char *) new_el
2215 + sizeof (struct pattern_set_el));
2216 new_el->next_pattern_set_el = NULL;
2217 if (last_el == NULL)
2218 el_list = last_el = new_el;
2219 else
2221 last_el->next_pattern_set_el = new_el;
2222 last_el = last_el->next_pattern_set_el;
2224 new_el->units_num = 0;
2225 for (j = 0; patterns [i] [j] != NULL; j++)
2227 decl_in_table = find_decl (patterns [i] [j]);
2228 if (decl_in_table == NULL)
2229 error ((presence_p
2230 ? (final_p
2231 ? "unit `%s' in final presence set is not declared"
2232 : "unit `%s' in presence set is not declared")
2233 : (final_p
2234 ? "unit `%s' in final absence set is not declared"
2235 : "unit `%s' in absence set is not declared")),
2236 patterns [i] [j]);
2237 else if (decl_in_table->mode != dm_unit)
2238 error ((presence_p
2239 ? (final_p
2240 ? "`%s' in final presence set is not unit"
2241 : "`%s' in presence set is not unit")
2242 : (final_p
2243 ? "`%s' in final absence set is not unit"
2244 : "`%s' in absence set is not unit")),
2245 patterns [i] [j]);
2246 else
2248 new_el->unit_decls [new_el->units_num]
2249 = DECL_UNIT (decl_in_table);
2250 new_el->units_num++;
2254 return el_list;
2257 /* The function adds each element from PATTERN_LIST to presence (if
2258 PRESENCE_P) or absence list of the each element from DEST_LIST.
2259 Checking situations "unit requires own absence", and "unit excludes
2260 and requires presence of ...", "unit requires absence and presence
2261 of ...", "units in (final) presence set belong to different
2262 automata", and "units in (final) absence set belong to different
2263 automata". Remember that we process absence sets only after all
2264 presence sets. */
2265 static void
2266 add_presence_absence (unit_set_el_t dest_list,
2267 pattern_set_el_t pattern_list,
2268 pos_t req_pos ATTRIBUTE_UNUSED,
2269 int presence_p, int final_p)
2271 unit_set_el_t dst;
2272 pattern_set_el_t pat;
2273 struct unit_decl *unit;
2274 unit_set_el_t curr_excl_el;
2275 pattern_set_el_t curr_pat_el;
2276 pattern_set_el_t prev_el;
2277 pattern_set_el_t copy;
2278 int i;
2279 int no_error_flag;
2281 for (dst = dest_list; dst != NULL; dst = dst->next_unit_set_el)
2282 for (pat = pattern_list; pat != NULL; pat = pat->next_pattern_set_el)
2284 for (i = 0; i < pat->units_num; i++)
2286 unit = pat->unit_decls [i];
2287 if (dst->unit_decl == unit && pat->units_num == 1 && !presence_p)
2289 error ("unit `%s' requires own absence", unit->name);
2290 continue;
2292 if (dst->unit_decl->automaton_name != NULL
2293 && unit->automaton_name != NULL
2294 && strcmp (dst->unit_decl->automaton_name,
2295 unit->automaton_name) != 0)
2297 error ((presence_p
2298 ? (final_p
2299 ? "units `%s' and `%s' in final presence set belong to different automata"
2300 : "units `%s' and `%s' in presence set belong to different automata")
2301 : (final_p
2302 ? "units `%s' and `%s' in final absence set belong to different automata"
2303 : "units `%s' and `%s' in absence set belong to different automata")),
2304 unit->name, dst->unit_decl->name);
2305 continue;
2307 no_error_flag = 1;
2308 if (presence_p)
2309 for (curr_excl_el = dst->unit_decl->excl_list;
2310 curr_excl_el != NULL;
2311 curr_excl_el = curr_excl_el->next_unit_set_el)
2313 if (unit == curr_excl_el->unit_decl && pat->units_num == 1)
2315 if (!w_flag)
2317 error ("unit `%s' excludes and requires presence of `%s'",
2318 dst->unit_decl->name, unit->name);
2319 no_error_flag = 0;
2321 else
2322 warning ("unit `%s' excludes and requires presence of `%s'",
2323 dst->unit_decl->name, unit->name);
2326 else if (pat->units_num == 1)
2327 for (curr_pat_el = dst->unit_decl->presence_list;
2328 curr_pat_el != NULL;
2329 curr_pat_el = curr_pat_el->next_pattern_set_el)
2330 if (curr_pat_el->units_num == 1
2331 && unit == curr_pat_el->unit_decls [0])
2333 if (!w_flag)
2335 error ("unit `%s' requires absence and presence of `%s'",
2336 dst->unit_decl->name, unit->name);
2337 no_error_flag = 0;
2339 else
2340 warning ("unit `%s' requires absence and presence of `%s'",
2341 dst->unit_decl->name, unit->name);
2343 if (no_error_flag)
2345 for (prev_el = (presence_p
2346 ? (final_p
2347 ? dst->unit_decl->final_presence_list
2348 : dst->unit_decl->final_presence_list)
2349 : (final_p
2350 ? dst->unit_decl->final_absence_list
2351 : dst->unit_decl->absence_list));
2352 prev_el != NULL && prev_el->next_pattern_set_el != NULL;
2353 prev_el = prev_el->next_pattern_set_el)
2355 copy = XCOPYNODE (struct pattern_set_el, pat);
2356 copy->next_pattern_set_el = NULL;
2357 if (prev_el == NULL)
2359 if (presence_p)
2361 if (final_p)
2362 dst->unit_decl->final_presence_list = copy;
2363 else
2364 dst->unit_decl->presence_list = copy;
2366 else if (final_p)
2367 dst->unit_decl->final_absence_list = copy;
2368 else
2369 dst->unit_decl->absence_list = copy;
2371 else
2372 prev_el->next_pattern_set_el = copy;
2379 /* The function inserts BYPASS in the list of bypasses of the
2380 corresponding output insn. The order of bypasses in the list is
2381 described in a comment for member `bypass_list' (see above). If
2382 there is already the same bypass in the list the function reports
2383 this and does nothing. */
2384 static void
2385 insert_bypass (struct bypass_decl *bypass)
2387 struct bypass_decl *curr, *last;
2388 struct insn_reserv_decl *out_insn_reserv = bypass->out_insn_reserv;
2389 struct insn_reserv_decl *in_insn_reserv = bypass->in_insn_reserv;
2391 for (curr = out_insn_reserv->bypass_list, last = NULL;
2392 curr != NULL;
2393 last = curr, curr = curr->next)
2394 if (curr->in_insn_reserv == in_insn_reserv)
2396 if ((bypass->bypass_guard_name != NULL
2397 && curr->bypass_guard_name != NULL
2398 && ! strcmp (bypass->bypass_guard_name, curr->bypass_guard_name))
2399 || bypass->bypass_guard_name == curr->bypass_guard_name)
2401 if (bypass->bypass_guard_name == NULL)
2403 if (!w_flag)
2404 error ("the same bypass `%s - %s' is already defined",
2405 bypass->out_pattern, bypass->in_pattern);
2406 else
2407 warning ("the same bypass `%s - %s' is already defined",
2408 bypass->out_pattern, bypass->in_pattern);
2410 else if (!w_flag)
2411 error ("the same bypass `%s - %s' (guard %s) is already defined",
2412 bypass->out_pattern, bypass->in_pattern,
2413 bypass->bypass_guard_name);
2414 else
2415 warning
2416 ("the same bypass `%s - %s' (guard %s) is already defined",
2417 bypass->out_pattern, bypass->in_pattern,
2418 bypass->bypass_guard_name);
2419 return;
2421 if (curr->bypass_guard_name == NULL)
2422 break;
2423 if (curr->next == NULL || curr->next->in_insn_reserv != in_insn_reserv)
2425 last = curr;
2426 break;
2430 if (last == NULL)
2432 bypass->next = out_insn_reserv->bypass_list;
2433 out_insn_reserv->bypass_list = bypass;
2435 else
2437 bypass->next = last->next;
2438 last->next = bypass;
2442 /* BYPASS is a define_bypass decl that includes glob pattern PATTERN.
2443 Call FN (BYPASS, INSN, DATA) for each matching instruction INSN. */
2445 static void
2446 for_each_matching_insn (decl_t bypass, const char *pattern,
2447 void (*fn) (decl_t, decl_t, void *), void *data)
2449 decl_t insn_reserv;
2450 bool matched_p;
2451 int i;
2453 matched_p = false;
2454 if (strpbrk (pattern, "*?["))
2455 for (i = 0; i < description->decls_num; i++)
2457 insn_reserv = description->decls[i];
2458 if (insn_reserv->mode == dm_insn_reserv
2459 && fnmatch (pattern, DECL_INSN_RESERV (insn_reserv)->name, 0) == 0)
2461 fn (bypass, insn_reserv, data);
2462 matched_p = true;
2465 else
2467 insn_reserv = find_insn_decl (pattern);
2468 if (insn_reserv)
2470 fn (bypass, insn_reserv, data);
2471 matched_p = true;
2474 if (!matched_p)
2475 error ("there is no insn reservation that matches `%s'", pattern);
2478 /* A subroutine of process_bypass that is called for each pair
2479 of matching instructions. OUT_INSN_RESERV is the output
2480 instruction and DATA is the input instruction. */
2482 static void
2483 process_bypass_2 (decl_t model, decl_t out_insn_reserv, void *data)
2485 struct bypass_decl *bypass;
2486 decl_t in_insn_reserv;
2488 in_insn_reserv = (decl_t) data;
2489 if (strcmp (DECL_INSN_RESERV (in_insn_reserv)->name,
2490 DECL_BYPASS (model)->in_pattern) == 0
2491 && strcmp (DECL_INSN_RESERV (out_insn_reserv)->name,
2492 DECL_BYPASS (model)->out_pattern) == 0)
2493 bypass = DECL_BYPASS (model);
2494 else
2496 bypass = XCNEW (struct bypass_decl);
2497 bypass->latency = DECL_BYPASS (model)->latency;
2498 bypass->out_pattern = DECL_INSN_RESERV (out_insn_reserv)->name;
2499 bypass->in_pattern = DECL_INSN_RESERV (in_insn_reserv)->name;
2500 bypass->bypass_guard_name = DECL_BYPASS (model)->bypass_guard_name;
2502 bypass->out_insn_reserv = DECL_INSN_RESERV (out_insn_reserv);
2503 bypass->in_insn_reserv = DECL_INSN_RESERV (in_insn_reserv);
2504 insert_bypass (bypass);
2507 /* A subroutine of process_bypass that is called for each input
2508 instruction IN_INSN_RESERV. */
2510 static void
2511 process_bypass_1 (decl_t bypass, decl_t in_insn_reserv,
2512 void *data ATTRIBUTE_UNUSED)
2514 for_each_matching_insn (bypass, DECL_BYPASS (bypass)->out_pattern,
2515 process_bypass_2, in_insn_reserv);
2518 /* Process define_bypass decl BYPASS, inserting a bypass for each specific
2519 pair of insn reservations. */
2521 static void
2522 process_bypass (decl_t bypass)
2524 for_each_matching_insn (bypass, DECL_BYPASS (bypass)->in_pattern,
2525 process_bypass_1, NULL);
2528 /* The function processes pipeline description declarations, checks
2529 their correctness, and forms exclusion/presence/absence sets. */
2530 static void
2531 process_decls (void)
2533 decl_t decl;
2534 decl_t automaton_decl;
2535 decl_t decl_in_table;
2536 int automaton_presence;
2537 int i;
2539 /* Checking repeated automata declarations. */
2540 automaton_presence = 0;
2541 for (i = 0; i < description->decls_num; i++)
2543 decl = description->decls [i];
2544 if (decl->mode == dm_automaton)
2546 automaton_presence = 1;
2547 decl_in_table = insert_automaton_decl (decl);
2548 if (decl_in_table != decl)
2550 if (!w_flag)
2551 error ("repeated declaration of automaton `%s'",
2552 DECL_AUTOMATON (decl)->name);
2553 else
2554 warning ("repeated declaration of automaton `%s'",
2555 DECL_AUTOMATON (decl)->name);
2559 /* Checking undeclared automata, repeated declarations (except for
2560 automata) and correctness of their attributes (insn latency times
2561 etc.). */
2562 for (i = 0; i < description->decls_num; i++)
2564 decl = description->decls [i];
2565 if (decl->mode == dm_insn_reserv)
2567 if (DECL_INSN_RESERV (decl)->default_latency < 0)
2568 error ("define_insn_reservation `%s' has negative latency time",
2569 DECL_INSN_RESERV (decl)->name);
2570 DECL_INSN_RESERV (decl)->insn_num = description->insns_num;
2571 description->insns_num++;
2572 decl_in_table = insert_insn_decl (decl);
2573 if (decl_in_table != decl)
2574 error ("`%s' is already used as insn reservation name",
2575 DECL_INSN_RESERV (decl)->name);
2577 else if (decl->mode == dm_bypass)
2579 if (DECL_BYPASS (decl)->latency < 0)
2580 error ("define_bypass `%s - %s' has negative latency time",
2581 DECL_BYPASS (decl)->out_pattern,
2582 DECL_BYPASS (decl)->in_pattern);
2584 else if (decl->mode == dm_unit || decl->mode == dm_reserv)
2586 if (decl->mode == dm_unit)
2588 DECL_UNIT (decl)->automaton_decl = NULL;
2589 if (DECL_UNIT (decl)->automaton_name != NULL)
2591 automaton_decl
2592 = find_automaton_decl (DECL_UNIT (decl)->automaton_name);
2593 if (automaton_decl == NULL)
2594 error ("automaton `%s' is not declared",
2595 DECL_UNIT (decl)->automaton_name);
2596 else
2598 DECL_AUTOMATON (automaton_decl)->automaton_is_used = 1;
2599 DECL_UNIT (decl)->automaton_decl
2600 = DECL_AUTOMATON (automaton_decl);
2603 else if (automaton_presence)
2604 error ("define_unit `%s' without automaton when one defined",
2605 DECL_UNIT (decl)->name);
2606 DECL_UNIT (decl)->unit_num = description->units_num;
2607 description->units_num++;
2608 if (strcmp (DECL_UNIT (decl)->name, NOTHING_NAME) == 0)
2610 error ("`%s' is declared as cpu unit", NOTHING_NAME);
2611 continue;
2613 decl_in_table = find_decl (DECL_UNIT (decl)->name);
2615 else
2617 if (strcmp (DECL_RESERV (decl)->name, NOTHING_NAME) == 0)
2619 error ("`%s' is declared as cpu reservation", NOTHING_NAME);
2620 continue;
2622 decl_in_table = find_decl (DECL_RESERV (decl)->name);
2624 if (decl_in_table == NULL)
2625 decl_in_table = insert_decl (decl);
2626 else
2628 if (decl->mode == dm_unit)
2629 error ("repeated declaration of unit `%s'",
2630 DECL_UNIT (decl)->name);
2631 else
2632 error ("repeated declaration of reservation `%s'",
2633 DECL_RESERV (decl)->name);
2637 /* Check bypasses and form list of bypasses for each (output)
2638 insn. */
2639 for (i = 0; i < description->decls_num; i++)
2641 decl = description->decls [i];
2642 if (decl->mode == dm_bypass)
2643 process_bypass (decl);
2646 /* Check exclusion set declarations and form exclusion sets. */
2647 for (i = 0; i < description->decls_num; i++)
2649 decl = description->decls [i];
2650 if (decl->mode == dm_excl)
2652 unit_set_el_t unit_set_el_list;
2653 unit_set_el_t unit_set_el_list_2;
2655 unit_set_el_list
2656 = process_excls (DECL_EXCL (decl)->names,
2657 DECL_EXCL (decl)->first_list_length, decl->pos);
2658 unit_set_el_list_2
2659 = process_excls (&DECL_EXCL (decl)->names
2660 [DECL_EXCL (decl)->first_list_length],
2661 DECL_EXCL (decl)->all_names_num
2662 - DECL_EXCL (decl)->first_list_length,
2663 decl->pos);
2664 add_excls (unit_set_el_list, unit_set_el_list_2, decl->pos);
2665 add_excls (unit_set_el_list_2, unit_set_el_list, decl->pos);
2669 /* Check presence set declarations and form presence sets. */
2670 for (i = 0; i < description->decls_num; i++)
2672 decl = description->decls [i];
2673 if (decl->mode == dm_presence)
2675 unit_set_el_t unit_set_el_list;
2676 pattern_set_el_t pattern_set_el_list;
2678 unit_set_el_list
2679 = process_presence_absence_names
2680 (DECL_PRESENCE (decl)->names, DECL_PRESENCE (decl)->names_num,
2681 decl->pos, TRUE, DECL_PRESENCE (decl)->final_p);
2682 pattern_set_el_list
2683 = process_presence_absence_patterns
2684 (DECL_PRESENCE (decl)->patterns,
2685 DECL_PRESENCE (decl)->patterns_num,
2686 decl->pos, TRUE, DECL_PRESENCE (decl)->final_p);
2687 add_presence_absence (unit_set_el_list, pattern_set_el_list,
2688 decl->pos, TRUE,
2689 DECL_PRESENCE (decl)->final_p);
2693 /* Check absence set declarations and form absence sets. */
2694 for (i = 0; i < description->decls_num; i++)
2696 decl = description->decls [i];
2697 if (decl->mode == dm_absence)
2699 unit_set_el_t unit_set_el_list;
2700 pattern_set_el_t pattern_set_el_list;
2702 unit_set_el_list
2703 = process_presence_absence_names
2704 (DECL_ABSENCE (decl)->names, DECL_ABSENCE (decl)->names_num,
2705 decl->pos, FALSE, DECL_ABSENCE (decl)->final_p);
2706 pattern_set_el_list
2707 = process_presence_absence_patterns
2708 (DECL_ABSENCE (decl)->patterns,
2709 DECL_ABSENCE (decl)->patterns_num,
2710 decl->pos, FALSE, DECL_ABSENCE (decl)->final_p);
2711 add_presence_absence (unit_set_el_list, pattern_set_el_list,
2712 decl->pos, FALSE,
2713 DECL_ABSENCE (decl)->final_p);
2718 /* The following function checks that declared automaton is used. If
2719 the automaton is not used, the function fixes error/warning. The
2720 following function must be called only after `process_decls'. */
2721 static void
2722 check_automaton_usage (void)
2724 decl_t decl;
2725 int i;
2727 for (i = 0; i < description->decls_num; i++)
2729 decl = description->decls [i];
2730 if (decl->mode == dm_automaton
2731 && !DECL_AUTOMATON (decl)->automaton_is_used)
2733 if (!w_flag)
2734 error ("automaton `%s' is not used", DECL_AUTOMATON (decl)->name);
2735 else
2736 warning ("automaton `%s' is not used",
2737 DECL_AUTOMATON (decl)->name);
2742 /* The following recursive function processes all regexp in order to
2743 fix usage of units or reservations and to fix errors of undeclared
2744 name. The function may change unit_regexp onto reserv_regexp.
2745 Remember that reserv_regexp does not exist before the function
2746 call. */
2747 static regexp_t
2748 process_regexp (regexp_t regexp)
2750 decl_t decl_in_table;
2751 regexp_t new_regexp;
2752 int i;
2754 switch (regexp->mode)
2756 case rm_unit:
2757 decl_in_table = find_decl (REGEXP_UNIT (regexp)->name);
2758 if (decl_in_table == NULL)
2759 error ("undeclared unit or reservation `%s'",
2760 REGEXP_UNIT (regexp)->name);
2761 else
2762 switch (decl_in_table->mode)
2764 case dm_unit:
2765 DECL_UNIT (decl_in_table)->unit_is_used = 1;
2766 REGEXP_UNIT (regexp)->unit_decl = DECL_UNIT (decl_in_table);
2767 break;
2769 case dm_reserv:
2770 DECL_RESERV (decl_in_table)->reserv_is_used = 1;
2771 new_regexp = XCREATENODE (struct regexp);
2772 new_regexp->mode = rm_reserv;
2773 new_regexp->pos = regexp->pos;
2774 REGEXP_RESERV (new_regexp)->name = REGEXP_UNIT (regexp)->name;
2775 REGEXP_RESERV (new_regexp)->reserv_decl
2776 = DECL_RESERV (decl_in_table);
2777 regexp = new_regexp;
2778 break;
2780 default:
2781 gcc_unreachable ();
2783 break;
2784 case rm_sequence:
2785 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
2786 REGEXP_SEQUENCE (regexp)->regexps [i]
2787 = process_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
2788 break;
2789 case rm_allof:
2790 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
2791 REGEXP_ALLOF (regexp)->regexps [i]
2792 = process_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
2793 break;
2794 case rm_oneof:
2795 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
2796 REGEXP_ONEOF (regexp)->regexps [i]
2797 = process_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
2798 break;
2799 case rm_repeat:
2800 REGEXP_REPEAT (regexp)->regexp
2801 = process_regexp (REGEXP_REPEAT (regexp)->regexp);
2802 break;
2803 case rm_nothing:
2804 break;
2805 default:
2806 gcc_unreachable ();
2808 return regexp;
2811 /* The following function processes regexp of define_reservation and
2812 define_insn_reservation with the aid of function
2813 `process_regexp'. */
2814 static void
2815 process_regexp_decls (void)
2817 decl_t decl;
2818 int i;
2820 for (i = 0; i < description->decls_num; i++)
2822 decl = description->decls [i];
2823 if (decl->mode == dm_reserv)
2824 DECL_RESERV (decl)->regexp
2825 = process_regexp (DECL_RESERV (decl)->regexp);
2826 else if (decl->mode == dm_insn_reserv)
2827 DECL_INSN_RESERV (decl)->regexp
2828 = process_regexp (DECL_INSN_RESERV (decl)->regexp);
2832 /* The following function checks that declared unit is used. If the
2833 unit is not used, the function fixes errors/warnings. The
2834 following function must be called only after `process_decls',
2835 `process_regexp_decls'. */
2836 static void
2837 check_usage (void)
2839 decl_t decl;
2840 int i;
2842 for (i = 0; i < description->decls_num; i++)
2844 decl = description->decls [i];
2845 if (decl->mode == dm_unit && !DECL_UNIT (decl)->unit_is_used)
2847 if (!w_flag)
2848 error ("unit `%s' is not used", DECL_UNIT (decl)->name);
2849 else
2850 warning ("unit `%s' is not used", DECL_UNIT (decl)->name);
2852 else if (decl->mode == dm_reserv && !DECL_RESERV (decl)->reserv_is_used)
2854 if (!w_flag)
2855 error ("reservation `%s' is not used", DECL_RESERV (decl)->name);
2856 else
2857 warning ("reservation `%s' is not used", DECL_RESERV (decl)->name);
2862 /* The following variable value is number of reservation being
2863 processed on loop recognition. */
2864 static int curr_loop_pass_num;
2866 /* The following recursive function returns nonzero value if REGEXP
2867 contains given decl or reservations in given regexp refers for
2868 given decl. */
2869 static int
2870 loop_in_regexp (regexp_t regexp, decl_t start_decl)
2872 int i;
2874 if (regexp == NULL)
2875 return 0;
2876 switch (regexp->mode)
2878 case rm_unit:
2879 return 0;
2881 case rm_reserv:
2882 if (start_decl->mode == dm_reserv
2883 && REGEXP_RESERV (regexp)->reserv_decl == DECL_RESERV (start_decl))
2884 return 1;
2885 else if (REGEXP_RESERV (regexp)->reserv_decl->loop_pass_num
2886 == curr_loop_pass_num)
2887 /* declaration has been processed. */
2888 return 0;
2889 else
2891 REGEXP_RESERV (regexp)->reserv_decl->loop_pass_num
2892 = curr_loop_pass_num;
2893 return loop_in_regexp (REGEXP_RESERV (regexp)->reserv_decl->regexp,
2894 start_decl);
2897 case rm_sequence:
2898 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
2899 if (loop_in_regexp (REGEXP_SEQUENCE (regexp)->regexps [i], start_decl))
2900 return 1;
2901 return 0;
2903 case rm_allof:
2904 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
2905 if (loop_in_regexp (REGEXP_ALLOF (regexp)->regexps [i], start_decl))
2906 return 1;
2907 return 0;
2909 case rm_oneof:
2910 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
2911 if (loop_in_regexp (REGEXP_ONEOF (regexp)->regexps [i], start_decl))
2912 return 1;
2913 return 0;
2915 case rm_repeat:
2916 return loop_in_regexp (REGEXP_REPEAT (regexp)->regexp, start_decl);
2918 case rm_nothing:
2919 return 0;
2921 default:
2922 gcc_unreachable ();
2926 /* The following function fixes errors "cycle in definition ...". The
2927 function uses function `loop_in_regexp' for that. */
2928 static void
2929 check_loops_in_regexps (void)
2931 decl_t decl;
2932 int i;
2934 for (i = 0; i < description->decls_num; i++)
2936 decl = description->decls [i];
2937 if (decl->mode == dm_reserv)
2938 DECL_RESERV (decl)->loop_pass_num = 0;
2940 for (i = 0; i < description->decls_num; i++)
2942 decl = description->decls [i];
2943 curr_loop_pass_num = i;
2945 if (decl->mode == dm_reserv)
2947 DECL_RESERV (decl)->loop_pass_num = curr_loop_pass_num;
2948 if (loop_in_regexp (DECL_RESERV (decl)->regexp, decl))
2950 gcc_assert (DECL_RESERV (decl)->regexp);
2951 error ("cycle in definition of reservation `%s'",
2952 DECL_RESERV (decl)->name);
2958 /* The function recursively processes IR of reservation and defines
2959 max and min cycle for reservation of unit. */
2960 static void
2961 process_regexp_cycles (regexp_t regexp, int max_start_cycle,
2962 int min_start_cycle, int *max_finish_cycle,
2963 int *min_finish_cycle)
2965 int i;
2967 switch (regexp->mode)
2969 case rm_unit:
2970 if (REGEXP_UNIT (regexp)->unit_decl->max_occ_cycle_num < max_start_cycle)
2971 REGEXP_UNIT (regexp)->unit_decl->max_occ_cycle_num = max_start_cycle;
2972 if (REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num > min_start_cycle
2973 || REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num == -1)
2974 REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num = min_start_cycle;
2975 *max_finish_cycle = max_start_cycle;
2976 *min_finish_cycle = min_start_cycle;
2977 break;
2979 case rm_reserv:
2980 process_regexp_cycles (REGEXP_RESERV (regexp)->reserv_decl->regexp,
2981 max_start_cycle, min_start_cycle,
2982 max_finish_cycle, min_finish_cycle);
2983 break;
2985 case rm_repeat:
2986 for (i = 0; i < REGEXP_REPEAT (regexp)->repeat_num; i++)
2988 process_regexp_cycles (REGEXP_REPEAT (regexp)->regexp,
2989 max_start_cycle, min_start_cycle,
2990 max_finish_cycle, min_finish_cycle);
2991 max_start_cycle = *max_finish_cycle + 1;
2992 min_start_cycle = *min_finish_cycle + 1;
2994 break;
2996 case rm_sequence:
2997 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
2999 process_regexp_cycles (REGEXP_SEQUENCE (regexp)->regexps [i],
3000 max_start_cycle, min_start_cycle,
3001 max_finish_cycle, min_finish_cycle);
3002 max_start_cycle = *max_finish_cycle + 1;
3003 min_start_cycle = *min_finish_cycle + 1;
3005 break;
3007 case rm_allof:
3009 int max_cycle = 0;
3010 int min_cycle = 0;
3012 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
3014 process_regexp_cycles (REGEXP_ALLOF (regexp)->regexps [i],
3015 max_start_cycle, min_start_cycle,
3016 max_finish_cycle, min_finish_cycle);
3017 if (max_cycle < *max_finish_cycle)
3018 max_cycle = *max_finish_cycle;
3019 if (i == 0 || min_cycle > *min_finish_cycle)
3020 min_cycle = *min_finish_cycle;
3022 *max_finish_cycle = max_cycle;
3023 *min_finish_cycle = min_cycle;
3025 break;
3027 case rm_oneof:
3029 int max_cycle = 0;
3030 int min_cycle = 0;
3032 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
3034 process_regexp_cycles (REGEXP_ONEOF (regexp)->regexps [i],
3035 max_start_cycle, min_start_cycle,
3036 max_finish_cycle, min_finish_cycle);
3037 if (max_cycle < *max_finish_cycle)
3038 max_cycle = *max_finish_cycle;
3039 if (i == 0 || min_cycle > *min_finish_cycle)
3040 min_cycle = *min_finish_cycle;
3042 *max_finish_cycle = max_cycle;
3043 *min_finish_cycle = min_cycle;
3045 break;
3047 case rm_nothing:
3048 *max_finish_cycle = max_start_cycle;
3049 *min_finish_cycle = min_start_cycle;
3050 break;
3052 default:
3053 gcc_unreachable ();
3057 /* The following function is called only for correct program. The
3058 function defines max reservation of insns in cycles. */
3059 static void
3060 evaluate_max_reserv_cycles (void)
3062 int max_insn_cycles_num;
3063 int min_insn_cycles_num;
3064 decl_t decl;
3065 int i;
3067 description->max_insn_reserv_cycles = 0;
3068 for (i = 0; i < description->decls_num; i++)
3070 decl = description->decls [i];
3071 if (decl->mode == dm_insn_reserv)
3073 process_regexp_cycles (DECL_INSN_RESERV (decl)->regexp, 0, 0,
3074 &max_insn_cycles_num, &min_insn_cycles_num);
3075 if (description->max_insn_reserv_cycles < max_insn_cycles_num)
3076 description->max_insn_reserv_cycles = max_insn_cycles_num;
3079 description->max_insn_reserv_cycles++;
3082 /* The following function calls functions for checking all
3083 description. */
3084 static void
3085 check_all_description (void)
3087 process_decls ();
3088 check_automaton_usage ();
3089 process_regexp_decls ();
3090 check_usage ();
3091 check_loops_in_regexps ();
3092 if (!have_error)
3093 evaluate_max_reserv_cycles ();
3098 /* The page contains abstract data `ticker'. This data is used to
3099 report time of different phases of building automata. It is
3100 possibly to write a description for which automata will be built
3101 during several minutes even on fast machine. */
3103 /* The following function creates ticker and makes it active. */
3104 static ticker_t
3105 create_ticker (void)
3107 ticker_t ticker;
3109 ticker.modified_creation_time = get_run_time ();
3110 ticker.incremented_off_time = 0;
3111 return ticker;
3114 /* The following function switches off given ticker. */
3115 static void
3116 ticker_off (ticker_t *ticker)
3118 if (ticker->incremented_off_time == 0)
3119 ticker->incremented_off_time = get_run_time () + 1;
3122 /* The following function switches on given ticker. */
3123 static void
3124 ticker_on (ticker_t *ticker)
3126 if (ticker->incremented_off_time != 0)
3128 ticker->modified_creation_time
3129 += get_run_time () - ticker->incremented_off_time + 1;
3130 ticker->incremented_off_time = 0;
3134 /* The following function returns current time in milliseconds since
3135 the moment when given ticker was created. */
3136 static int
3137 active_time (ticker_t ticker)
3139 if (ticker.incremented_off_time != 0)
3140 return ticker.incremented_off_time - 1 - ticker.modified_creation_time;
3141 else
3142 return get_run_time () - ticker.modified_creation_time;
3145 /* The following function returns string representation of active time
3146 of given ticker. The result is string representation of seconds
3147 with accuracy of 1/100 second. Only result of the last call of the
3148 function exists. Therefore the following code is not correct
3150 printf ("parser time: %s\ngeneration time: %s\n",
3151 active_time_string (parser_ticker),
3152 active_time_string (generation_ticker));
3154 Correct code has to be the following
3156 printf ("parser time: %s\n", active_time_string (parser_ticker));
3157 printf ("generation time: %s\n",
3158 active_time_string (generation_ticker));
3161 static void
3162 print_active_time (FILE *f, ticker_t ticker)
3164 int msecs;
3166 msecs = active_time (ticker);
3167 fprintf (f, "%d.%06d", msecs / 1000000, msecs % 1000000);
3172 /* The following variable value is number of automaton which are
3173 really being created. This value is defined on the base of
3174 argument of option `-split'. If the variable has zero value the
3175 number of automata is defined by the constructions `%automaton'.
3176 This case occurs when option `-split' is absent or has zero
3177 argument. If constructions `define_automaton' is absent only one
3178 automaton is created. */
3179 static int automata_num;
3181 /* The following variable values are times of
3182 o transformation of regular expressions
3183 o building NDFA (DFA if !ndfa_flag)
3184 o NDFA -> DFA (simply the same automaton if !ndfa_flag)
3185 o DFA minimization
3186 o building insn equivalence classes
3187 o all previous ones
3188 o code output */
3189 static ticker_t transform_time;
3190 static ticker_t NDFA_time;
3191 static ticker_t NDFA_to_DFA_time;
3192 static ticker_t minimize_time;
3193 static ticker_t equiv_time;
3194 static ticker_t automaton_generation_time;
3195 static ticker_t output_time;
3197 /* The following variable values are times of
3198 all checking
3199 all generation
3200 all pipeline hazard translator work */
3201 static ticker_t check_time;
3202 static ticker_t generation_time;
3203 static ticker_t all_time;
3207 /* Pseudo insn decl which denotes advancing cycle. */
3208 static decl_t advance_cycle_insn_decl;
3209 /* Pseudo insn decl which denotes collapsing the NDFA state. */
3210 static decl_t collapse_ndfa_insn_decl;
3212 /* Create and record a decl for the special advance-cycle transition. */
3213 static void
3214 add_advance_cycle_insn_decl (void)
3216 advance_cycle_insn_decl = XCREATENODE (struct decl);
3217 advance_cycle_insn_decl->mode = dm_insn_reserv;
3218 advance_cycle_insn_decl->pos = no_pos;
3219 DECL_INSN_RESERV (advance_cycle_insn_decl)->regexp = NULL;
3220 DECL_INSN_RESERV (advance_cycle_insn_decl)->name = "$advance_cycle";
3221 DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num
3222 = description->insns_num;
3223 description->decls [description->decls_num] = advance_cycle_insn_decl;
3224 description->decls_num++;
3225 description->insns_num++;
3228 /* Create and record a decl for the special collapse-NDFA transition. */
3229 static void
3230 add_collapse_ndfa_insn_decl (void)
3232 collapse_ndfa_insn_decl = XCREATENODE (struct decl);
3233 collapse_ndfa_insn_decl->mode = dm_insn_reserv;
3234 collapse_ndfa_insn_decl->pos = no_pos;
3235 DECL_INSN_RESERV (collapse_ndfa_insn_decl)->regexp = NULL;
3236 DECL_INSN_RESERV (collapse_ndfa_insn_decl)->name = "$collapse_ndfa";
3237 DECL_INSN_RESERV (collapse_ndfa_insn_decl)->insn_num
3238 = description->insns_num;
3239 description->decls [description->decls_num] = collapse_ndfa_insn_decl;
3240 description->decls_num++;
3241 description->insns_num++;
3244 /* True if DECL is either of the two special decls we created. */
3245 static bool
3246 special_decl_p (struct insn_reserv_decl *decl)
3248 return (decl == DECL_INSN_RESERV (advance_cycle_insn_decl)
3249 || (collapse_flag
3250 && decl == DECL_INSN_RESERV (collapse_ndfa_insn_decl)));
3254 /* Abstract data `alternative states' which represents
3255 nondeterministic nature of the description (see comments for
3256 structures alt_state and state). */
3258 /* List of free states. */
3259 static alt_state_t first_free_alt_state;
3261 #ifndef NDEBUG
3262 /* The following variables is maximal number of allocated nodes
3263 alt_state. */
3264 static int allocated_alt_states_num = 0;
3265 #endif
3267 /* The following function returns free node alt_state. It may be new
3268 allocated node or node freed earlier. */
3269 static alt_state_t
3270 get_free_alt_state (void)
3272 alt_state_t result;
3274 if (first_free_alt_state != NULL)
3276 result = first_free_alt_state;
3277 first_free_alt_state = first_free_alt_state->next_alt_state;
3279 else
3281 #ifndef NDEBUG
3282 allocated_alt_states_num++;
3283 #endif
3284 result = XCREATENODE (struct alt_state);
3286 result->state = NULL;
3287 result->next_alt_state = NULL;
3288 result->next_sorted_alt_state = NULL;
3289 return result;
3292 /* The function frees node ALT_STATE. */
3293 static void
3294 free_alt_state (alt_state_t alt_state)
3296 if (alt_state == NULL)
3297 return;
3298 alt_state->next_alt_state = first_free_alt_state;
3299 first_free_alt_state = alt_state;
3302 /* The function frees list started with node ALT_STATE_LIST. */
3303 static void
3304 free_alt_states (alt_state_t alt_states_list)
3306 alt_state_t curr_alt_state;
3307 alt_state_t next_alt_state;
3309 for (curr_alt_state = alt_states_list;
3310 curr_alt_state != NULL;
3311 curr_alt_state = next_alt_state)
3313 next_alt_state = curr_alt_state->next_alt_state;
3314 free_alt_state (curr_alt_state);
3318 /* The function compares unique numbers of alt states. */
3319 static int
3320 alt_state_cmp (const void *alt_state_ptr_1, const void *alt_state_ptr_2)
3322 if ((*(const alt_state_t *) alt_state_ptr_1)->state->unique_num
3323 == (*(const alt_state_t *) alt_state_ptr_2)->state->unique_num)
3324 return 0;
3325 else if ((*(const alt_state_t *) alt_state_ptr_1)->state->unique_num
3326 < (*(const alt_state_t *) alt_state_ptr_2)->state->unique_num)
3327 return -1;
3328 else
3329 return 1;
3332 /* The function sorts ALT_STATES_LIST and removes duplicated alt
3333 states from the list. The comparison key is alt state unique
3334 number. */
3336 static alt_state_t
3337 uniq_sort_alt_states (alt_state_t alt_states_list)
3339 alt_state_t curr_alt_state;
3340 vec<alt_state_t> alt_states;
3341 size_t i;
3342 size_t prev_unique_state_ind;
3343 alt_state_t result;
3345 if (alt_states_list == 0)
3346 return 0;
3347 if (alt_states_list->next_alt_state == 0)
3348 return alt_states_list;
3350 alt_states.create (150);
3351 for (curr_alt_state = alt_states_list;
3352 curr_alt_state != NULL;
3353 curr_alt_state = curr_alt_state->next_alt_state)
3354 alt_states.safe_push (curr_alt_state);
3356 alt_states.qsort (alt_state_cmp);
3358 prev_unique_state_ind = 0;
3359 for (i = 1; i < alt_states.length (); i++)
3360 if (alt_states[prev_unique_state_ind]->state != alt_states[i]->state)
3362 prev_unique_state_ind++;
3363 alt_states[prev_unique_state_ind] = alt_states[i];
3365 alt_states.truncate (prev_unique_state_ind + 1);
3367 for (i = 1; i < alt_states.length (); i++)
3368 alt_states[i-1]->next_sorted_alt_state
3369 = alt_states[i];
3370 alt_states.last ()->next_sorted_alt_state = 0;
3372 result = alt_states[0];
3374 alt_states.release ();
3375 return result;
3378 /* The function checks equality of alt state lists. Remember that the
3379 lists must be already sorted by the previous function. */
3380 static int
3381 alt_states_eq (alt_state_t alt_states_1, alt_state_t alt_states_2)
3383 while (alt_states_1 != NULL && alt_states_2 != NULL
3384 && alt_state_cmp (&alt_states_1, &alt_states_2) == 0)
3386 alt_states_1 = alt_states_1->next_sorted_alt_state;
3387 alt_states_2 = alt_states_2->next_sorted_alt_state;
3389 return alt_states_1 == alt_states_2;
3392 /* Initialization of the abstract data. */
3393 static void
3394 initiate_alt_states (void)
3396 first_free_alt_state = NULL;
3399 /* Finishing work with the abstract data. */
3400 static void
3401 finish_alt_states (void)
3407 /* The page contains macros for work with bits strings. We could use
3408 standard gcc bitmap or sbitmap but it would result in difficulties
3409 of building canadian cross. */
3411 /* Set bit number bitno in the bit string. The macro is not side
3412 effect proof. */
3413 #define bitmap_set_bit(bitstring, bitno) \
3414 ((bitstring)[(bitno) / (sizeof (*(bitstring)) * CHAR_BIT)] |= \
3415 (HOST_WIDE_INT)1 << (bitno) % (sizeof (*(bitstring)) * CHAR_BIT))
3417 #define CLEAR_BIT(bitstring, bitno) \
3418 ((bitstring)[(bitno) / (sizeof (*(bitstring)) * CHAR_BIT)] &= \
3419 ~((HOST_WIDE_INT)1 << (bitno) % (sizeof (*(bitstring)) * CHAR_BIT)))
3421 /* Test if bit number bitno in the bitstring is set. The macro is not
3422 side effect proof. */
3423 #define bitmap_bit_p(bitstring, bitno) \
3424 ((bitstring)[(bitno) / (sizeof (*(bitstring)) * CHAR_BIT)] >> \
3425 (bitno) % (sizeof (*(bitstring)) * CHAR_BIT) & 1)
3429 /* This page contains abstract data `state'. */
3431 /* Maximal length of reservations in cycles (>= 1). */
3432 static int max_cycles_num;
3434 /* Number of set elements (see type set_el_t) needed for
3435 representation of one cycle reservation. It is depended on units
3436 number. */
3437 static int els_in_cycle_reserv;
3439 /* Number of set elements (see type set_el_t) needed for
3440 representation of maximal length reservation. Deterministic
3441 reservation is stored as set (bit string) of length equal to the
3442 variable value * number of bits in set_el_t. */
3443 static int els_in_reservs;
3445 /* Array of pointers to unit declarations. */
3446 static unit_decl_t *units_array;
3448 /* Temporary reservation of maximal length. */
3449 static reserv_sets_t temp_reserv;
3451 /* The state table itself is represented by the following variable. */
3452 static htab_t state_table;
3454 /* Linked list of free 'state' structures to be recycled. The
3455 next_equiv_class_state pointer is borrowed for a free list. */
3456 static state_t first_free_state;
3458 static int curr_unique_state_num;
3460 #ifndef NDEBUG
3461 /* The following variables is maximal number of allocated nodes
3462 `state'. */
3463 static int allocated_states_num = 0;
3464 #endif
3466 /* Allocate new reservation set. */
3467 static reserv_sets_t
3468 alloc_empty_reserv_sets (void)
3470 reserv_sets_t result;
3472 obstack_blank (&irp, els_in_reservs * sizeof (set_el_t));
3473 result = (reserv_sets_t) obstack_base (&irp);
3474 obstack_finish (&irp);
3475 memset (result, 0, els_in_reservs * sizeof (set_el_t));
3476 return result;
3479 /* Hash value of reservation set. */
3480 static unsigned
3481 reserv_sets_hash_value (reserv_sets_t reservs)
3483 set_el_t hash_value;
3484 unsigned result;
3485 int reservs_num, i;
3486 set_el_t *reserv_ptr;
3488 hash_value = 0;
3489 reservs_num = els_in_reservs;
3490 reserv_ptr = reservs;
3491 i = 0;
3492 while (reservs_num != 0)
3494 reservs_num--;
3495 hash_value += ((*reserv_ptr >> i)
3496 | (*reserv_ptr << (sizeof (set_el_t) * CHAR_BIT - i)));
3497 i++;
3498 if (i == sizeof (set_el_t) * CHAR_BIT)
3499 i = 0;
3500 reserv_ptr++;
3502 if (sizeof (set_el_t) <= sizeof (unsigned))
3503 return hash_value;
3504 result = 0;
3505 for (i = sizeof (set_el_t); i > 0; i -= sizeof (unsigned) - 1)
3507 result += (unsigned) hash_value;
3508 hash_value >>= (sizeof (unsigned) - 1) * CHAR_BIT;
3510 return result;
3513 /* Comparison of given reservation sets. */
3514 static int
3515 reserv_sets_cmp (const_reserv_sets_t reservs_1, const_reserv_sets_t reservs_2)
3517 int reservs_num;
3518 const set_el_t *reserv_ptr_1;
3519 const set_el_t *reserv_ptr_2;
3521 gcc_assert (reservs_1 && reservs_2);
3522 reservs_num = els_in_reservs;
3523 reserv_ptr_1 = reservs_1;
3524 reserv_ptr_2 = reservs_2;
3525 while (reservs_num != 0 && *reserv_ptr_1 == *reserv_ptr_2)
3527 reservs_num--;
3528 reserv_ptr_1++;
3529 reserv_ptr_2++;
3531 if (reservs_num == 0)
3532 return 0;
3533 else if (*reserv_ptr_1 < *reserv_ptr_2)
3534 return -1;
3535 else
3536 return 1;
3539 /* The function checks equality of the reservation sets. */
3540 static int
3541 reserv_sets_eq (const_reserv_sets_t reservs_1, const_reserv_sets_t reservs_2)
3543 return reserv_sets_cmp (reservs_1, reservs_2) == 0;
3546 /* Set up in the reservation set that unit with UNIT_NUM is used on
3547 CYCLE_NUM. */
3548 static void
3549 set_unit_reserv (reserv_sets_t reservs, int cycle_num, int unit_num)
3551 gcc_assert (cycle_num < max_cycles_num);
3552 bitmap_set_bit (reservs, cycle_num * els_in_cycle_reserv
3553 * sizeof (set_el_t) * CHAR_BIT + unit_num);
3556 /* Set up in the reservation set RESERVS that unit with UNIT_NUM is
3557 used on CYCLE_NUM. */
3558 static int
3559 test_unit_reserv (reserv_sets_t reservs, int cycle_num, int unit_num)
3561 gcc_assert (cycle_num < max_cycles_num);
3562 return bitmap_bit_p (reservs, cycle_num * els_in_cycle_reserv
3563 * sizeof (set_el_t) * CHAR_BIT + unit_num);
3566 /* The function checks that the reservation sets are intersected,
3567 i.e. there is a unit reservation on a cycle in both reservation
3568 sets. */
3569 static int
3570 reserv_sets_are_intersected (reserv_sets_t operand_1,
3571 reserv_sets_t operand_2)
3573 set_el_t *el_ptr_1;
3574 set_el_t *el_ptr_2;
3575 set_el_t *cycle_ptr_1;
3576 set_el_t *cycle_ptr_2;
3578 gcc_assert (operand_1 && operand_2);
3579 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2;
3580 el_ptr_1 < operand_1 + els_in_reservs;
3581 el_ptr_1++, el_ptr_2++)
3582 if (*el_ptr_1 & *el_ptr_2)
3583 return 1;
3584 reserv_sets_or (temp_reserv, operand_1, operand_2);
3585 for (cycle_ptr_1 = operand_1, cycle_ptr_2 = operand_2;
3586 cycle_ptr_1 < operand_1 + els_in_reservs;
3587 cycle_ptr_1 += els_in_cycle_reserv, cycle_ptr_2 += els_in_cycle_reserv)
3589 for (el_ptr_1 = cycle_ptr_1, el_ptr_2 = get_excl_set (cycle_ptr_2);
3590 el_ptr_1 < cycle_ptr_1 + els_in_cycle_reserv;
3591 el_ptr_1++, el_ptr_2++)
3592 if (*el_ptr_1 & *el_ptr_2)
3593 return 1;
3594 if (!check_presence_pattern_sets (cycle_ptr_1, cycle_ptr_2, FALSE))
3595 return 1;
3596 if (!check_presence_pattern_sets (temp_reserv + (cycle_ptr_2
3597 - operand_2),
3598 cycle_ptr_2, TRUE))
3599 return 1;
3600 if (!check_absence_pattern_sets (cycle_ptr_1, cycle_ptr_2, FALSE))
3601 return 1;
3602 if (!check_absence_pattern_sets (temp_reserv + (cycle_ptr_2 - operand_2),
3603 cycle_ptr_2, TRUE))
3604 return 1;
3606 return 0;
3609 /* The function sets up RESULT bits by bits of OPERAND shifted on one
3610 cpu cycle. The remaining bits of OPERAND (representing the last
3611 cycle unit reservations) are not changed. */
3612 static void
3613 reserv_sets_shift (reserv_sets_t result, reserv_sets_t operand)
3615 int i;
3617 gcc_assert (result && operand && result != operand);
3618 for (i = els_in_cycle_reserv; i < els_in_reservs; i++)
3619 result [i - els_in_cycle_reserv] = operand [i];
3622 /* OR of the reservation sets. */
3623 static void
3624 reserv_sets_or (reserv_sets_t result, reserv_sets_t operand_1,
3625 reserv_sets_t operand_2)
3627 set_el_t *el_ptr_1;
3628 set_el_t *el_ptr_2;
3629 set_el_t *result_set_el_ptr;
3631 gcc_assert (result && operand_1 && operand_2);
3632 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2, result_set_el_ptr = result;
3633 el_ptr_1 < operand_1 + els_in_reservs;
3634 el_ptr_1++, el_ptr_2++, result_set_el_ptr++)
3635 *result_set_el_ptr = *el_ptr_1 | *el_ptr_2;
3638 /* AND of the reservation sets. */
3639 static void
3640 reserv_sets_and (reserv_sets_t result, reserv_sets_t operand_1,
3641 reserv_sets_t operand_2)
3643 set_el_t *el_ptr_1;
3644 set_el_t *el_ptr_2;
3645 set_el_t *result_set_el_ptr;
3647 gcc_assert (result && operand_1 && operand_2);
3648 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2, result_set_el_ptr = result;
3649 el_ptr_1 < operand_1 + els_in_reservs;
3650 el_ptr_1++, el_ptr_2++, result_set_el_ptr++)
3651 *result_set_el_ptr = *el_ptr_1 & *el_ptr_2;
3654 /* The function outputs string representation of units reservation on
3655 cycle START_CYCLE in the reservation set. The function uses repeat
3656 construction if REPETITION_NUM > 1. */
3657 static void
3658 output_cycle_reservs (FILE *f, reserv_sets_t reservs, int start_cycle,
3659 int repetition_num)
3661 int unit_num;
3662 int reserved_units_num;
3664 reserved_units_num = 0;
3665 for (unit_num = 0; unit_num < description->units_num; unit_num++)
3666 if (bitmap_bit_p (reservs, start_cycle * els_in_cycle_reserv
3667 * sizeof (set_el_t) * CHAR_BIT + unit_num))
3668 reserved_units_num++;
3669 gcc_assert (repetition_num > 0);
3670 if (repetition_num != 1 && reserved_units_num > 1)
3671 fprintf (f, "(");
3672 reserved_units_num = 0;
3673 for (unit_num = 0;
3674 unit_num < description->units_num;
3675 unit_num++)
3676 if (bitmap_bit_p (reservs, start_cycle * els_in_cycle_reserv
3677 * sizeof (set_el_t) * CHAR_BIT + unit_num))
3679 if (reserved_units_num != 0)
3680 fprintf (f, "+");
3681 reserved_units_num++;
3682 fprintf (f, "%s", units_array [unit_num]->name);
3684 if (reserved_units_num == 0)
3685 fprintf (f, NOTHING_NAME);
3686 gcc_assert (repetition_num > 0);
3687 if (repetition_num != 1 && reserved_units_num > 1)
3688 fprintf (f, ")");
3689 if (repetition_num != 1)
3690 fprintf (f, "*%d", repetition_num);
3693 /* The function outputs string representation of units reservation in
3694 the reservation set. */
3695 static void
3696 output_reserv_sets (FILE *f, reserv_sets_t reservs)
3698 int start_cycle = 0;
3699 int cycle;
3700 int repetition_num;
3702 repetition_num = 0;
3703 for (cycle = 0; cycle < max_cycles_num; cycle++)
3704 if (repetition_num == 0)
3706 repetition_num++;
3707 start_cycle = cycle;
3709 else if (memcmp
3710 ((char *) reservs + start_cycle * els_in_cycle_reserv
3711 * sizeof (set_el_t),
3712 (char *) reservs + cycle * els_in_cycle_reserv
3713 * sizeof (set_el_t),
3714 els_in_cycle_reserv * sizeof (set_el_t)) == 0)
3715 repetition_num++;
3716 else
3718 if (start_cycle != 0)
3719 fprintf (f, ", ");
3720 output_cycle_reservs (f, reservs, start_cycle, repetition_num);
3721 repetition_num = 1;
3722 start_cycle = cycle;
3724 if (start_cycle < max_cycles_num)
3726 if (start_cycle != 0)
3727 fprintf (f, ", ");
3728 output_cycle_reservs (f, reservs, start_cycle, repetition_num);
3732 /* The following function returns free node state for AUTOMATON. It
3733 may be new allocated node or node freed earlier. The function also
3734 allocates reservation set if WITH_RESERVS has nonzero value. */
3735 static state_t
3736 get_free_state (int with_reservs, automaton_t automaton)
3738 state_t result;
3740 gcc_assert (max_cycles_num > 0 && automaton);
3741 if (first_free_state)
3743 result = first_free_state;
3744 first_free_state = result->next_equiv_class_state;
3746 result->next_equiv_class_state = NULL;
3747 result->automaton = automaton;
3748 result->first_out_arc = NULL;
3749 result->it_was_placed_in_stack_for_NDFA_forming = 0;
3750 result->it_was_placed_in_stack_for_DFA_forming = 0;
3751 result->component_states = NULL;
3753 else
3755 #ifndef NDEBUG
3756 allocated_states_num++;
3757 #endif
3758 result = XCREATENODE (struct state);
3759 result->automaton = automaton;
3760 result->first_out_arc = NULL;
3761 result->unique_num = curr_unique_state_num;
3762 curr_unique_state_num++;
3764 if (with_reservs)
3766 if (result->reservs == NULL)
3767 result->reservs = alloc_empty_reserv_sets ();
3768 else
3769 memset (result->reservs, 0, els_in_reservs * sizeof (set_el_t));
3771 return result;
3774 /* The function frees node STATE. */
3775 static void
3776 free_state (state_t state)
3778 free_alt_states (state->component_states);
3779 state->next_equiv_class_state = first_free_state;
3780 first_free_state = state;
3783 /* Hash value of STATE. If STATE represents deterministic state it is
3784 simply hash value of the corresponding reservation set. Otherwise
3785 it is formed from hash values of the component deterministic
3786 states. One more key is order number of state automaton. */
3787 static hashval_t
3788 state_hash (const void *state)
3790 unsigned int hash_value;
3791 alt_state_t alt_state;
3793 if (((const_state_t) state)->component_states == NULL)
3794 hash_value = reserv_sets_hash_value (((const_state_t) state)->reservs);
3795 else
3797 hash_value = 0;
3798 for (alt_state = ((const_state_t) state)->component_states;
3799 alt_state != NULL;
3800 alt_state = alt_state->next_sorted_alt_state)
3801 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
3802 | (hash_value << CHAR_BIT))
3803 + alt_state->state->unique_num);
3805 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
3806 | (hash_value << CHAR_BIT))
3807 + ((const_state_t) state)->automaton->automaton_order_num);
3808 return hash_value;
3811 /* Return nonzero value if the states are the same. */
3812 static int
3813 state_eq_p (const void *state_1, const void *state_2)
3815 alt_state_t alt_state_1;
3816 alt_state_t alt_state_2;
3818 if (((const_state_t) state_1)->automaton != ((const_state_t) state_2)->automaton)
3819 return 0;
3820 else if (((const_state_t) state_1)->component_states == NULL
3821 && ((const_state_t) state_2)->component_states == NULL)
3822 return reserv_sets_eq (((const_state_t) state_1)->reservs,
3823 ((const_state_t) state_2)->reservs);
3824 else if (((const_state_t) state_1)->component_states != NULL
3825 && ((const_state_t) state_2)->component_states != NULL)
3827 for (alt_state_1 = ((const_state_t) state_1)->component_states,
3828 alt_state_2 = ((const_state_t) state_2)->component_states;
3829 alt_state_1 != NULL && alt_state_2 != NULL;
3830 alt_state_1 = alt_state_1->next_sorted_alt_state,
3831 alt_state_2 = alt_state_2->next_sorted_alt_state)
3832 /* All state in the list must be already in the hash table.
3833 Also the lists must be sorted. */
3834 if (alt_state_1->state != alt_state_2->state)
3835 return 0;
3836 return alt_state_1 == alt_state_2;
3838 else
3839 return 0;
3842 /* Insert STATE into the state table. */
3843 static state_t
3844 insert_state (state_t state)
3846 void **entry_ptr;
3848 entry_ptr = htab_find_slot (state_table, (void *) state, INSERT);
3849 if (*entry_ptr == NULL)
3850 *entry_ptr = (void *) state;
3851 return (state_t) *entry_ptr;
3854 /* Add reservation of unit with UNIT_NUM on cycle CYCLE_NUM to
3855 deterministic STATE. */
3856 static void
3857 set_state_reserv (state_t state, int cycle_num, int unit_num)
3859 set_unit_reserv (state->reservs, cycle_num, unit_num);
3862 /* Return nonzero value if the deterministic states contains a
3863 reservation of the same cpu unit on the same cpu cycle. */
3864 static int
3865 intersected_state_reservs_p (state_t state1, state_t state2)
3867 gcc_assert (state1->automaton == state2->automaton);
3868 return reserv_sets_are_intersected (state1->reservs, state2->reservs);
3871 /* Return deterministic state (inserted into the table) which
3872 representing the automaton state which is union of reservations of
3873 the deterministic states masked by RESERVS. */
3874 static state_t
3875 states_union (state_t state1, state_t state2, reserv_sets_t reservs)
3877 state_t result;
3878 state_t state_in_table;
3880 gcc_assert (state1->automaton == state2->automaton);
3881 result = get_free_state (1, state1->automaton);
3882 reserv_sets_or (result->reservs, state1->reservs, state2->reservs);
3883 reserv_sets_and (result->reservs, result->reservs, reservs);
3884 state_in_table = insert_state (result);
3885 if (result != state_in_table)
3887 free_state (result);
3888 result = state_in_table;
3890 return result;
3893 /* Return deterministic state (inserted into the table) which
3894 represent the automaton state is obtained from deterministic STATE
3895 by advancing cpu cycle and masking by RESERVS. */
3896 static state_t
3897 state_shift (state_t state, reserv_sets_t reservs)
3899 state_t result;
3900 state_t state_in_table;
3902 result = get_free_state (1, state->automaton);
3903 reserv_sets_shift (result->reservs, state->reservs);
3904 reserv_sets_and (result->reservs, result->reservs, reservs);
3905 state_in_table = insert_state (result);
3906 if (result != state_in_table)
3908 free_state (result);
3909 result = state_in_table;
3911 return result;
3914 /* Initialization of the abstract data. */
3915 static void
3916 initiate_states (void)
3918 decl_t decl;
3919 int i;
3921 if (description->units_num)
3922 units_array = XNEWVEC (unit_decl_t, description->units_num);
3923 else
3924 units_array = 0;
3926 for (i = 0; i < description->decls_num; i++)
3928 decl = description->decls [i];
3929 if (decl->mode == dm_unit)
3930 units_array [DECL_UNIT (decl)->unit_num] = DECL_UNIT (decl);
3932 max_cycles_num = description->max_insn_reserv_cycles;
3933 els_in_cycle_reserv
3934 = ((description->units_num + sizeof (set_el_t) * CHAR_BIT - 1)
3935 / (sizeof (set_el_t) * CHAR_BIT));
3936 els_in_reservs = els_in_cycle_reserv * max_cycles_num;
3937 curr_unique_state_num = 0;
3938 initiate_alt_states ();
3939 state_table = htab_create (1500, state_hash, state_eq_p, (htab_del) 0);
3940 temp_reserv = alloc_empty_reserv_sets ();
3943 /* Finishing work with the abstract data. */
3944 static void
3945 finish_states (void)
3947 free (units_array);
3948 units_array = 0;
3949 htab_delete (state_table);
3950 first_free_state = NULL;
3951 finish_alt_states ();
3956 /* Abstract data `arcs'. */
3958 /* List of free arcs. */
3959 static arc_t first_free_arc;
3961 #ifndef NDEBUG
3962 /* The following variables is maximal number of allocated nodes
3963 `arc'. */
3964 static int allocated_arcs_num = 0;
3965 #endif
3967 /* The function frees node ARC. */
3968 static void
3969 free_arc (arc_t arc)
3971 arc->next_out_arc = first_free_arc;
3972 first_free_arc = arc;
3975 /* The function removes and frees ARC staring from FROM_STATE. */
3976 static void
3977 remove_arc (state_t from_state, arc_t arc)
3979 arc_t prev_arc;
3980 arc_t curr_arc;
3982 gcc_assert (arc);
3983 for (prev_arc = NULL, curr_arc = from_state->first_out_arc;
3984 curr_arc != NULL;
3985 prev_arc = curr_arc, curr_arc = curr_arc->next_out_arc)
3986 if (curr_arc == arc)
3987 break;
3988 gcc_assert (curr_arc);
3989 if (prev_arc == NULL)
3990 from_state->first_out_arc = arc->next_out_arc;
3991 else
3992 prev_arc->next_out_arc = arc->next_out_arc;
3993 from_state->num_out_arcs--;
3994 free_arc (arc);
3997 /* The functions returns arc with given characteristics (or NULL if
3998 the arc does not exist). */
3999 static arc_t
4000 find_arc (state_t from_state, state_t to_state, ainsn_t insn)
4002 arc_t arc;
4004 for (arc = first_out_arc (from_state); arc != NULL; arc = next_out_arc (arc))
4005 if (arc->insn == insn
4006 && (arc->to_state == to_state
4007 || (collapse_flag
4008 /* Any arc is good enough for a collapse-ndfa transition. */
4009 && (insn->insn_reserv_decl
4010 == DECL_INSN_RESERV (collapse_ndfa_insn_decl)))))
4011 return arc;
4012 return NULL;
4015 /* The function adds arc from FROM_STATE to TO_STATE marked by AINSN,
4016 unless such an arc already exists. */
4017 static void
4018 add_arc (state_t from_state, state_t to_state, ainsn_t ainsn)
4020 arc_t new_arc;
4022 new_arc = find_arc (from_state, to_state, ainsn);
4023 if (new_arc != NULL)
4024 return;
4025 if (first_free_arc == NULL)
4027 #ifndef NDEBUG
4028 allocated_arcs_num++;
4029 #endif
4030 new_arc = XCREATENODE (struct arc);
4031 new_arc->to_state = NULL;
4032 new_arc->insn = NULL;
4033 new_arc->next_out_arc = NULL;
4035 else
4037 new_arc = first_free_arc;
4038 first_free_arc = first_free_arc->next_out_arc;
4040 new_arc->to_state = to_state;
4041 new_arc->insn = ainsn;
4042 ainsn->arc_exists_p = 1;
4043 new_arc->next_out_arc = from_state->first_out_arc;
4044 from_state->first_out_arc = new_arc;
4045 from_state->num_out_arcs++;
4046 new_arc->next_arc_marked_by_insn = NULL;
4049 /* The function returns the first arc starting from STATE. */
4050 static arc_t
4051 first_out_arc (const_state_t state)
4053 return state->first_out_arc;
4056 /* The function returns next out arc after ARC. */
4057 static arc_t
4058 next_out_arc (arc_t arc)
4060 return arc->next_out_arc;
4063 /* Initialization of the abstract data. */
4064 static void
4065 initiate_arcs (void)
4067 first_free_arc = NULL;
4070 /* Finishing work with the abstract data. */
4071 static void
4072 finish_arcs (void)
4078 /* Abstract data `automata lists'. */
4080 /* List of free states. */
4081 static automata_list_el_t first_free_automata_list_el;
4083 /* The list being formed. */
4084 static automata_list_el_t current_automata_list;
4086 /* Hash table of automata lists. */
4087 static htab_t automata_list_table;
4089 /* The following function returns free automata list el. It may be
4090 new allocated node or node freed earlier. */
4091 static automata_list_el_t
4092 get_free_automata_list_el (void)
4094 automata_list_el_t result;
4096 if (first_free_automata_list_el != NULL)
4098 result = first_free_automata_list_el;
4099 first_free_automata_list_el
4100 = first_free_automata_list_el->next_automata_list_el;
4102 else
4103 result = XCREATENODE (struct automata_list_el);
4104 result->automaton = NULL;
4105 result->next_automata_list_el = NULL;
4106 return result;
4109 /* The function frees node AUTOMATA_LIST_EL. */
4110 static void
4111 free_automata_list_el (automata_list_el_t automata_list_el)
4113 if (automata_list_el == NULL)
4114 return;
4115 automata_list_el->next_automata_list_el = first_free_automata_list_el;
4116 first_free_automata_list_el = automata_list_el;
4119 /* The function frees list AUTOMATA_LIST. */
4120 static void
4121 free_automata_list (automata_list_el_t automata_list)
4123 automata_list_el_t curr_automata_list_el;
4124 automata_list_el_t next_automata_list_el;
4126 for (curr_automata_list_el = automata_list;
4127 curr_automata_list_el != NULL;
4128 curr_automata_list_el = next_automata_list_el)
4130 next_automata_list_el = curr_automata_list_el->next_automata_list_el;
4131 free_automata_list_el (curr_automata_list_el);
4135 /* Hash value of AUTOMATA_LIST. */
4136 static hashval_t
4137 automata_list_hash (const void *automata_list)
4139 unsigned int hash_value;
4140 const_automata_list_el_t curr_automata_list_el;
4142 hash_value = 0;
4143 for (curr_automata_list_el = (const_automata_list_el_t) automata_list;
4144 curr_automata_list_el != NULL;
4145 curr_automata_list_el = curr_automata_list_el->next_automata_list_el)
4146 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
4147 | (hash_value << CHAR_BIT))
4148 + curr_automata_list_el->automaton->automaton_order_num);
4149 return hash_value;
4152 /* Return nonzero value if the automata_lists are the same. */
4153 static int
4154 automata_list_eq_p (const void *automata_list_1, const void *automata_list_2)
4156 const_automata_list_el_t automata_list_el_1;
4157 const_automata_list_el_t automata_list_el_2;
4159 for (automata_list_el_1 = (const_automata_list_el_t) automata_list_1,
4160 automata_list_el_2 = (const_automata_list_el_t) automata_list_2;
4161 automata_list_el_1 != NULL && automata_list_el_2 != NULL;
4162 automata_list_el_1 = automata_list_el_1->next_automata_list_el,
4163 automata_list_el_2 = automata_list_el_2->next_automata_list_el)
4164 if (automata_list_el_1->automaton != automata_list_el_2->automaton)
4165 return 0;
4166 return automata_list_el_1 == automata_list_el_2;
4169 /* Initialization of the abstract data. */
4170 static void
4171 initiate_automata_lists (void)
4173 first_free_automata_list_el = NULL;
4174 automata_list_table = htab_create (1500, automata_list_hash,
4175 automata_list_eq_p, (htab_del) 0);
4178 /* The following function starts new automata list and makes it the
4179 current one. */
4180 static void
4181 automata_list_start (void)
4183 current_automata_list = NULL;
4186 /* The following function adds AUTOMATON to the current list. */
4187 static void
4188 automata_list_add (automaton_t automaton)
4190 automata_list_el_t el;
4192 el = get_free_automata_list_el ();
4193 el->automaton = automaton;
4194 el->next_automata_list_el = current_automata_list;
4195 current_automata_list = el;
4198 /* The following function finishes forming the current list, inserts
4199 it into the table and returns it. */
4200 static automata_list_el_t
4201 automata_list_finish (void)
4203 void **entry_ptr;
4205 if (current_automata_list == NULL)
4206 return NULL;
4207 entry_ptr = htab_find_slot (automata_list_table,
4208 (void *) current_automata_list, INSERT);
4209 if (*entry_ptr == NULL)
4210 *entry_ptr = (void *) current_automata_list;
4211 else
4212 free_automata_list (current_automata_list);
4213 current_automata_list = NULL;
4214 return (automata_list_el_t) *entry_ptr;
4217 /* Finishing work with the abstract data. */
4218 static void
4219 finish_automata_lists (void)
4221 htab_delete (automata_list_table);
4226 /* The page contains abstract data for work with exclusion sets (see
4227 exclusion_set in file rtl.def). */
4229 /* The following variable refers to an exclusion set returned by
4230 get_excl_set. This is bit string of length equal to cpu units
4231 number. If exclusion set for given unit contains 1 for a unit,
4232 then simultaneous reservation of the units is prohibited. */
4233 static reserv_sets_t excl_set;
4235 /* The array contains exclusion sets for each unit. */
4236 static reserv_sets_t *unit_excl_set_table;
4238 /* The following function forms the array containing exclusion sets
4239 for each unit. */
4240 static void
4241 initiate_excl_sets (void)
4243 decl_t decl;
4244 reserv_sets_t unit_excl_set;
4245 unit_set_el_t el;
4246 int i;
4248 obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4249 excl_set = (reserv_sets_t) obstack_base (&irp);
4250 obstack_finish (&irp);
4251 obstack_blank (&irp, description->units_num * sizeof (reserv_sets_t));
4252 unit_excl_set_table = (reserv_sets_t *) obstack_base (&irp);
4253 obstack_finish (&irp);
4254 /* Evaluate unit exclusion sets. */
4255 for (i = 0; i < description->decls_num; i++)
4257 decl = description->decls [i];
4258 if (decl->mode == dm_unit)
4260 obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4261 unit_excl_set = (reserv_sets_t) obstack_base (&irp);
4262 obstack_finish (&irp);
4263 memset (unit_excl_set, 0, els_in_cycle_reserv * sizeof (set_el_t));
4264 for (el = DECL_UNIT (decl)->excl_list;
4265 el != NULL;
4266 el = el->next_unit_set_el)
4268 bitmap_set_bit (unit_excl_set, el->unit_decl->unit_num);
4269 el->unit_decl->in_set_p = TRUE;
4271 unit_excl_set_table [DECL_UNIT (decl)->unit_num] = unit_excl_set;
4276 /* The function sets up and return EXCL_SET which is union of
4277 exclusion sets for each unit in IN_SET. */
4278 static reserv_sets_t
4279 get_excl_set (reserv_sets_t in_set)
4281 int el;
4282 unsigned int i;
4283 int start_unit_num;
4284 int unit_num;
4286 memset (excl_set, 0, els_in_cycle_reserv * sizeof (set_el_t));
4287 for (el = 0; el < els_in_cycle_reserv; el++)
4288 if (in_set[el])
4289 for (i = 0; i < CHAR_BIT * sizeof (set_el_t); i++)
4290 if ((in_set[el] >> i) & 1)
4292 start_unit_num = el * CHAR_BIT * sizeof (set_el_t) + i;
4293 if (start_unit_num >= description->units_num)
4294 return excl_set;
4295 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4297 excl_set [unit_num]
4298 |= unit_excl_set_table [start_unit_num] [unit_num];
4301 return excl_set;
4306 /* The page contains abstract data for work with presence/absence
4307 pattern sets (see presence_set/absence_set in file rtl.def). */
4309 /* The following arrays contain correspondingly presence, final
4310 presence, absence, and final absence patterns for each unit. */
4311 static pattern_reserv_t *unit_presence_set_table;
4312 static pattern_reserv_t *unit_final_presence_set_table;
4313 static pattern_reserv_t *unit_absence_set_table;
4314 static pattern_reserv_t *unit_final_absence_set_table;
4316 /* The following function forms list of reservation sets for given
4317 PATTERN_LIST. */
4318 static pattern_reserv_t
4319 form_reserv_sets_list (pattern_set_el_t pattern_list)
4321 pattern_set_el_t el;
4322 pattern_reserv_t first, curr, prev;
4323 int i;
4325 prev = first = NULL;
4326 for (el = pattern_list; el != NULL; el = el->next_pattern_set_el)
4328 curr = XCREATENODE (struct pattern_reserv);
4329 curr->reserv = alloc_empty_reserv_sets ();
4330 curr->next_pattern_reserv = NULL;
4331 for (i = 0; i < el->units_num; i++)
4333 bitmap_set_bit (curr->reserv, el->unit_decls [i]->unit_num);
4334 el->unit_decls [i]->in_set_p = TRUE;
4336 if (prev != NULL)
4337 prev->next_pattern_reserv = curr;
4338 else
4339 first = curr;
4340 prev = curr;
4342 return first;
4345 /* The following function forms the array containing presence and
4346 absence pattern sets for each unit. */
4347 static void
4348 initiate_presence_absence_pattern_sets (void)
4350 decl_t decl;
4351 int i;
4353 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4354 unit_presence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4355 obstack_finish (&irp);
4356 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4357 unit_final_presence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4358 obstack_finish (&irp);
4359 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4360 unit_absence_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_absence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4364 obstack_finish (&irp);
4365 /* Evaluate unit presence/absence sets. */
4366 for (i = 0; i < description->decls_num; i++)
4368 decl = description->decls [i];
4369 if (decl->mode == dm_unit)
4371 unit_presence_set_table [DECL_UNIT (decl)->unit_num]
4372 = form_reserv_sets_list (DECL_UNIT (decl)->presence_list);
4373 unit_final_presence_set_table [DECL_UNIT (decl)->unit_num]
4374 = form_reserv_sets_list (DECL_UNIT (decl)->final_presence_list);
4375 unit_absence_set_table [DECL_UNIT (decl)->unit_num]
4376 = form_reserv_sets_list (DECL_UNIT (decl)->absence_list);
4377 unit_final_absence_set_table [DECL_UNIT (decl)->unit_num]
4378 = form_reserv_sets_list (DECL_UNIT (decl)->final_absence_list);
4383 /* The function checks that CHECKED_SET satisfies all presence pattern
4384 sets for units in ORIGINAL_SET. The function returns TRUE if it
4385 is ok. */
4386 static int
4387 check_presence_pattern_sets (reserv_sets_t checked_set,
4388 reserv_sets_t original_set,
4389 int final_p)
4391 int el;
4392 unsigned int i;
4393 int start_unit_num;
4394 int unit_num;
4395 int presence_p;
4396 pattern_reserv_t pat_reserv;
4398 for (el = 0; el < els_in_cycle_reserv; el++)
4399 if (original_set[el])
4400 for (i = 0; i < CHAR_BIT * sizeof (set_el_t); i++)
4401 if ((original_set[el] >> i) & 1)
4403 start_unit_num = el * CHAR_BIT * sizeof (set_el_t) + i;
4404 if (start_unit_num >= description->units_num)
4405 break;
4406 if ((final_p
4407 && unit_final_presence_set_table [start_unit_num] == NULL)
4408 || (!final_p
4409 && unit_presence_set_table [start_unit_num] == NULL))
4410 continue;
4411 presence_p = FALSE;
4412 for (pat_reserv = (final_p
4413 ? unit_final_presence_set_table [start_unit_num]
4414 : unit_presence_set_table [start_unit_num]);
4415 pat_reserv != NULL;
4416 pat_reserv = pat_reserv->next_pattern_reserv)
4418 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4419 if ((checked_set [unit_num] & pat_reserv->reserv [unit_num])
4420 != pat_reserv->reserv [unit_num])
4421 break;
4422 presence_p = presence_p || unit_num >= els_in_cycle_reserv;
4424 if (!presence_p)
4425 return FALSE;
4427 return TRUE;
4430 /* The function checks that CHECKED_SET satisfies all absence pattern
4431 sets for units in ORIGINAL_SET. The function returns TRUE if it
4432 is ok. */
4433 static int
4434 check_absence_pattern_sets (reserv_sets_t checked_set,
4435 reserv_sets_t original_set,
4436 int final_p)
4438 int el;
4439 unsigned int i;
4440 int start_unit_num;
4441 int unit_num;
4442 pattern_reserv_t pat_reserv;
4444 for (el = 0; el < els_in_cycle_reserv; el++)
4445 if (original_set[el])
4446 for (i = 0; i < CHAR_BIT * sizeof (set_el_t); i++)
4447 if ((original_set[el] >> i) & 1)
4449 start_unit_num = el * CHAR_BIT * sizeof (set_el_t) + i;
4450 if (start_unit_num >= description->units_num)
4451 break;
4452 for (pat_reserv = (final_p
4453 ? unit_final_absence_set_table [start_unit_num]
4454 : unit_absence_set_table [start_unit_num]);
4455 pat_reserv != NULL;
4456 pat_reserv = pat_reserv->next_pattern_reserv)
4458 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4459 if ((checked_set [unit_num] & pat_reserv->reserv [unit_num])
4460 != pat_reserv->reserv [unit_num]
4461 && pat_reserv->reserv [unit_num])
4462 break;
4463 if (unit_num >= els_in_cycle_reserv)
4464 return FALSE;
4467 return TRUE;
4472 /* This page contains code for transformation of original reservations
4473 described in .md file. The main goal of transformations is
4474 simplifying reservation and lifting up all `|' on the top of IR
4475 reservation representation. */
4478 /* The following function makes copy of IR representation of
4479 reservation. The function also substitutes all reservations
4480 defined by define_reservation by corresponding value during making
4481 the copy. */
4482 static regexp_t
4483 copy_insn_regexp (regexp_t regexp)
4485 regexp_t result;
4486 int i;
4488 switch (regexp->mode)
4490 case rm_reserv:
4491 result = copy_insn_regexp (REGEXP_RESERV (regexp)->reserv_decl->regexp);
4492 break;
4494 case rm_unit:
4495 result = XCOPYNODE (struct regexp, regexp);
4496 break;
4498 case rm_repeat:
4499 result = XCOPYNODE (struct regexp, regexp);
4500 REGEXP_REPEAT (result)->regexp
4501 = copy_insn_regexp (REGEXP_REPEAT (regexp)->regexp);
4502 break;
4504 case rm_sequence:
4505 result = XCOPYNODEVAR (struct regexp, regexp,
4506 sizeof (struct regexp) + sizeof (regexp_t)
4507 * (REGEXP_SEQUENCE (regexp)->regexps_num - 1));
4508 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4509 REGEXP_SEQUENCE (result)->regexps [i]
4510 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4511 break;
4513 case rm_allof:
4514 result = XCOPYNODEVAR (struct regexp, regexp,
4515 sizeof (struct regexp) + sizeof (regexp_t)
4516 * (REGEXP_ALLOF (regexp)->regexps_num - 1));
4517 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4518 REGEXP_ALLOF (result)->regexps [i]
4519 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4520 break;
4522 case rm_oneof:
4523 result = XCOPYNODEVAR (struct regexp, regexp,
4524 sizeof (struct regexp) + sizeof (regexp_t)
4525 * (REGEXP_ONEOF (regexp)->regexps_num - 1));
4526 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4527 REGEXP_ONEOF (result)->regexps [i]
4528 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4529 break;
4531 case rm_nothing:
4532 result = XCOPYNODE (struct regexp, regexp);
4533 break;
4535 default:
4536 gcc_unreachable ();
4538 return result;
4541 /* The following variable is set up 1 if a transformation has been
4542 applied. */
4543 static int regexp_transformed_p;
4545 /* The function makes transformation
4546 A*N -> A, A, ... */
4547 static regexp_t
4548 transform_1 (regexp_t regexp)
4550 int i;
4551 int repeat_num;
4552 regexp_t operand;
4553 pos_t pos;
4555 if (regexp->mode == rm_repeat)
4557 repeat_num = REGEXP_REPEAT (regexp)->repeat_num;
4558 gcc_assert (repeat_num > 1);
4559 operand = REGEXP_REPEAT (regexp)->regexp;
4560 pos = regexp->mode;
4561 regexp = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4562 + sizeof (regexp_t) * (repeat_num - 1));
4563 regexp->mode = rm_sequence;
4564 regexp->pos = pos;
4565 REGEXP_SEQUENCE (regexp)->regexps_num = repeat_num;
4566 for (i = 0; i < repeat_num; i++)
4567 REGEXP_SEQUENCE (regexp)->regexps [i] = copy_insn_regexp (operand);
4568 regexp_transformed_p = 1;
4570 return regexp;
4573 /* The function makes transformations
4574 ...,(A,B,...),C,... -> ...,A,B,...,C,...
4575 ...+(A+B+...)+C+... -> ...+A+B+...+C+...
4576 ...|(A|B|...)|C|... -> ...|A|B|...|C|... */
4577 static regexp_t
4578 transform_2 (regexp_t regexp)
4580 if (regexp->mode == rm_sequence)
4582 regexp_t sequence = NULL;
4583 regexp_t result;
4584 int sequence_index = 0;
4585 int i, j;
4587 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4588 if (REGEXP_SEQUENCE (regexp)->regexps [i]->mode == rm_sequence)
4590 sequence_index = i;
4591 sequence = REGEXP_SEQUENCE (regexp)->regexps [i];
4592 break;
4594 if (i < REGEXP_SEQUENCE (regexp)->regexps_num)
4596 gcc_assert (REGEXP_SEQUENCE (sequence)->regexps_num > 1
4597 && REGEXP_SEQUENCE (regexp)->regexps_num > 1);
4598 result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4599 + sizeof (regexp_t)
4600 * (REGEXP_SEQUENCE (regexp)->regexps_num
4601 + REGEXP_SEQUENCE (sequence)->regexps_num
4602 - 2));
4603 result->mode = rm_sequence;
4604 result->pos = regexp->pos;
4605 REGEXP_SEQUENCE (result)->regexps_num
4606 = (REGEXP_SEQUENCE (regexp)->regexps_num
4607 + REGEXP_SEQUENCE (sequence)->regexps_num - 1);
4608 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4609 if (i < sequence_index)
4610 REGEXP_SEQUENCE (result)->regexps [i]
4611 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4612 else if (i > sequence_index)
4613 REGEXP_SEQUENCE (result)->regexps
4614 [i + REGEXP_SEQUENCE (sequence)->regexps_num - 1]
4615 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4616 else
4617 for (j = 0; j < REGEXP_SEQUENCE (sequence)->regexps_num; j++)
4618 REGEXP_SEQUENCE (result)->regexps [i + j]
4619 = copy_insn_regexp (REGEXP_SEQUENCE (sequence)->regexps [j]);
4620 regexp_transformed_p = 1;
4621 regexp = result;
4624 else if (regexp->mode == rm_allof)
4626 regexp_t allof = NULL;
4627 regexp_t result;
4628 int allof_index = 0;
4629 int i, j;
4631 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4632 if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_allof)
4634 allof_index = i;
4635 allof = REGEXP_ALLOF (regexp)->regexps [i];
4636 break;
4638 if (i < REGEXP_ALLOF (regexp)->regexps_num)
4640 gcc_assert (REGEXP_ALLOF (allof)->regexps_num > 1
4641 && REGEXP_ALLOF (regexp)->regexps_num > 1);
4642 result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4643 + sizeof (regexp_t)
4644 * (REGEXP_ALLOF (regexp)->regexps_num
4645 + REGEXP_ALLOF (allof)->regexps_num - 2));
4646 result->mode = rm_allof;
4647 result->pos = regexp->pos;
4648 REGEXP_ALLOF (result)->regexps_num
4649 = (REGEXP_ALLOF (regexp)->regexps_num
4650 + REGEXP_ALLOF (allof)->regexps_num - 1);
4651 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4652 if (i < allof_index)
4653 REGEXP_ALLOF (result)->regexps [i]
4654 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4655 else if (i > allof_index)
4656 REGEXP_ALLOF (result)->regexps
4657 [i + REGEXP_ALLOF (allof)->regexps_num - 1]
4658 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4659 else
4660 for (j = 0; j < REGEXP_ALLOF (allof)->regexps_num; j++)
4661 REGEXP_ALLOF (result)->regexps [i + j]
4662 = copy_insn_regexp (REGEXP_ALLOF (allof)->regexps [j]);
4663 regexp_transformed_p = 1;
4664 regexp = result;
4667 else if (regexp->mode == rm_oneof)
4669 regexp_t oneof = NULL;
4670 regexp_t result;
4671 int oneof_index = 0;
4672 int i, j;
4674 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4675 if (REGEXP_ONEOF (regexp)->regexps [i]->mode == rm_oneof)
4677 oneof_index = i;
4678 oneof = REGEXP_ONEOF (regexp)->regexps [i];
4679 break;
4681 if (i < REGEXP_ONEOF (regexp)->regexps_num)
4683 gcc_assert (REGEXP_ONEOF (oneof)->regexps_num > 1
4684 && REGEXP_ONEOF (regexp)->regexps_num > 1);
4685 result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4686 + sizeof (regexp_t)
4687 * (REGEXP_ONEOF (regexp)->regexps_num
4688 + REGEXP_ONEOF (oneof)->regexps_num - 2));
4689 result->mode = rm_oneof;
4690 result->pos = regexp->pos;
4691 REGEXP_ONEOF (result)->regexps_num
4692 = (REGEXP_ONEOF (regexp)->regexps_num
4693 + REGEXP_ONEOF (oneof)->regexps_num - 1);
4694 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4695 if (i < oneof_index)
4696 REGEXP_ONEOF (result)->regexps [i]
4697 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4698 else if (i > oneof_index)
4699 REGEXP_ONEOF (result)->regexps
4700 [i + REGEXP_ONEOF (oneof)->regexps_num - 1]
4701 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4702 else
4703 for (j = 0; j < REGEXP_ONEOF (oneof)->regexps_num; j++)
4704 REGEXP_ONEOF (result)->regexps [i + j]
4705 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [j]);
4706 regexp_transformed_p = 1;
4707 regexp = result;
4710 return regexp;
4713 /* The function makes transformations
4714 ...,A|B|...,C,... -> (...,A,C,...)|(...,B,C,...)|...
4715 ...+(A|B|...)+C+... -> (...+A+C+...)|(...+B+C+...)|...
4716 ...+(A,B,...)+C+... -> (...+A+C+...),B,...
4717 ...+(A,B,...)+(C,D,...) -> (A+C),(B+D),... */
4718 static regexp_t
4719 transform_3 (regexp_t regexp)
4721 if (regexp->mode == rm_sequence)
4723 regexp_t oneof = NULL;
4724 int oneof_index = 0;
4725 regexp_t result;
4726 regexp_t sequence;
4727 int i, j;
4729 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4730 if (REGEXP_SEQUENCE (regexp)->regexps [i]->mode == rm_oneof)
4732 oneof_index = i;
4733 oneof = REGEXP_SEQUENCE (regexp)->regexps [i];
4734 break;
4736 if (i < REGEXP_SEQUENCE (regexp)->regexps_num)
4738 gcc_assert (REGEXP_ONEOF (oneof)->regexps_num > 1
4739 && REGEXP_SEQUENCE (regexp)->regexps_num > 1);
4740 result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4741 + sizeof (regexp_t)
4742 * (REGEXP_ONEOF (oneof)->regexps_num - 1));
4743 result->mode = rm_oneof;
4744 result->pos = regexp->pos;
4745 REGEXP_ONEOF (result)->regexps_num
4746 = REGEXP_ONEOF (oneof)->regexps_num;
4747 for (i = 0; i < REGEXP_ONEOF (result)->regexps_num; i++)
4749 sequence
4750 = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4751 + sizeof (regexp_t)
4752 * (REGEXP_SEQUENCE (regexp)->regexps_num - 1));
4753 sequence->mode = rm_sequence;
4754 sequence->pos = regexp->pos;
4755 REGEXP_SEQUENCE (sequence)->regexps_num
4756 = REGEXP_SEQUENCE (regexp)->regexps_num;
4757 REGEXP_ONEOF (result)->regexps [i] = sequence;
4758 for (j = 0; j < REGEXP_SEQUENCE (sequence)->regexps_num; j++)
4759 if (j != oneof_index)
4760 REGEXP_SEQUENCE (sequence)->regexps [j]
4761 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [j]);
4762 else
4763 REGEXP_SEQUENCE (sequence)->regexps [j]
4764 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [i]);
4766 regexp_transformed_p = 1;
4767 regexp = result;
4770 else if (regexp->mode == rm_allof)
4772 regexp_t oneof = NULL;
4773 regexp_t seq;
4774 int oneof_index = 0;
4775 int max_seq_length, allof_length;
4776 regexp_t result;
4777 regexp_t allof = NULL;
4778 regexp_t allof_op = NULL;
4779 int i, j;
4781 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4782 if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_oneof)
4784 oneof_index = i;
4785 oneof = REGEXP_ALLOF (regexp)->regexps [i];
4786 break;
4788 if (i < REGEXP_ALLOF (regexp)->regexps_num)
4790 gcc_assert (REGEXP_ONEOF (oneof)->regexps_num > 1
4791 && REGEXP_ALLOF (regexp)->regexps_num > 1);
4792 result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4793 + sizeof (regexp_t)
4794 * (REGEXP_ONEOF (oneof)->regexps_num - 1));
4795 result->mode = rm_oneof;
4796 result->pos = regexp->pos;
4797 REGEXP_ONEOF (result)->regexps_num
4798 = REGEXP_ONEOF (oneof)->regexps_num;
4799 for (i = 0; i < REGEXP_ONEOF (result)->regexps_num; i++)
4801 allof
4802 = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4803 + sizeof (regexp_t)
4804 * (REGEXP_ALLOF (regexp)->regexps_num - 1));
4805 allof->mode = rm_allof;
4806 allof->pos = regexp->pos;
4807 REGEXP_ALLOF (allof)->regexps_num
4808 = REGEXP_ALLOF (regexp)->regexps_num;
4809 REGEXP_ONEOF (result)->regexps [i] = allof;
4810 for (j = 0; j < REGEXP_ALLOF (allof)->regexps_num; j++)
4811 if (j != oneof_index)
4812 REGEXP_ALLOF (allof)->regexps [j]
4813 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [j]);
4814 else
4815 REGEXP_ALLOF (allof)->regexps [j]
4816 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [i]);
4818 regexp_transformed_p = 1;
4819 regexp = result;
4821 max_seq_length = 0;
4822 if (regexp->mode == rm_allof)
4823 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4825 switch (REGEXP_ALLOF (regexp)->regexps [i]->mode)
4827 case rm_sequence:
4828 seq = REGEXP_ALLOF (regexp)->regexps [i];
4829 if (max_seq_length < REGEXP_SEQUENCE (seq)->regexps_num)
4830 max_seq_length = REGEXP_SEQUENCE (seq)->regexps_num;
4831 break;
4833 case rm_unit:
4834 case rm_nothing:
4835 break;
4837 default:
4838 max_seq_length = 0;
4839 goto break_for;
4842 break_for:
4843 if (max_seq_length != 0)
4845 gcc_assert (max_seq_length != 1
4846 && REGEXP_ALLOF (regexp)->regexps_num > 1);
4847 result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4848 + sizeof (regexp_t) * (max_seq_length - 1));
4849 result->mode = rm_sequence;
4850 result->pos = regexp->pos;
4851 REGEXP_SEQUENCE (result)->regexps_num = max_seq_length;
4852 for (i = 0; i < max_seq_length; i++)
4854 allof_length = 0;
4855 for (j = 0; j < REGEXP_ALLOF (regexp)->regexps_num; j++)
4856 switch (REGEXP_ALLOF (regexp)->regexps [j]->mode)
4858 case rm_sequence:
4859 if (i < (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4860 ->regexps [j])->regexps_num))
4862 allof_op
4863 = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4864 ->regexps [j])
4865 ->regexps [i]);
4866 allof_length++;
4868 break;
4869 case rm_unit:
4870 case rm_nothing:
4871 if (i == 0)
4873 allof_op = REGEXP_ALLOF (regexp)->regexps [j];
4874 allof_length++;
4876 break;
4877 default:
4878 break;
4881 if (allof_length == 1)
4882 REGEXP_SEQUENCE (result)->regexps [i] = allof_op;
4883 else
4885 allof = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4886 + sizeof (regexp_t)
4887 * (allof_length - 1));
4888 allof->mode = rm_allof;
4889 allof->pos = regexp->pos;
4890 REGEXP_ALLOF (allof)->regexps_num = allof_length;
4891 REGEXP_SEQUENCE (result)->regexps [i] = allof;
4892 allof_length = 0;
4893 for (j = 0; j < REGEXP_ALLOF (regexp)->regexps_num; j++)
4894 if (REGEXP_ALLOF (regexp)->regexps [j]->mode == rm_sequence
4895 && (i <
4896 (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4897 ->regexps [j])->regexps_num)))
4899 allof_op = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4900 ->regexps [j])
4901 ->regexps [i]);
4902 REGEXP_ALLOF (allof)->regexps [allof_length]
4903 = allof_op;
4904 allof_length++;
4906 else if (i == 0
4907 && (REGEXP_ALLOF (regexp)->regexps [j]->mode
4908 == rm_unit
4909 || (REGEXP_ALLOF (regexp)->regexps [j]->mode
4910 == rm_nothing)))
4912 allof_op = REGEXP_ALLOF (regexp)->regexps [j];
4913 REGEXP_ALLOF (allof)->regexps [allof_length]
4914 = allof_op;
4915 allof_length++;
4919 regexp_transformed_p = 1;
4920 regexp = result;
4923 return regexp;
4926 /* The function traverses IR of reservation and applies transformations
4927 implemented by FUNC. */
4928 static regexp_t
4929 regexp_transform_func (regexp_t regexp, regexp_t (*func) (regexp_t regexp))
4931 int i;
4933 switch (regexp->mode)
4935 case rm_sequence:
4936 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4937 REGEXP_SEQUENCE (regexp)->regexps [i]
4938 = regexp_transform_func (REGEXP_SEQUENCE (regexp)->regexps [i],
4939 func);
4940 break;
4942 case rm_allof:
4943 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4944 REGEXP_ALLOF (regexp)->regexps [i]
4945 = regexp_transform_func (REGEXP_ALLOF (regexp)->regexps [i], func);
4946 break;
4948 case rm_oneof:
4949 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4950 REGEXP_ONEOF (regexp)->regexps [i]
4951 = regexp_transform_func (REGEXP_ONEOF (regexp)->regexps [i], func);
4952 break;
4954 case rm_repeat:
4955 REGEXP_REPEAT (regexp)->regexp
4956 = regexp_transform_func (REGEXP_REPEAT (regexp)->regexp, func);
4957 break;
4959 case rm_nothing:
4960 case rm_unit:
4961 break;
4963 default:
4964 gcc_unreachable ();
4966 return (*func) (regexp);
4969 /* The function applies all transformations for IR representation of
4970 reservation REGEXP. */
4971 static regexp_t
4972 transform_regexp (regexp_t regexp)
4974 regexp = regexp_transform_func (regexp, transform_1);
4977 regexp_transformed_p = 0;
4978 regexp = regexp_transform_func (regexp, transform_2);
4979 regexp = regexp_transform_func (regexp, transform_3);
4981 while (regexp_transformed_p);
4982 return regexp;
4985 /* The function applies all transformations for reservations of all
4986 insn declarations. */
4987 static void
4988 transform_insn_regexps (void)
4990 decl_t decl;
4991 int i;
4993 transform_time = create_ticker ();
4994 add_advance_cycle_insn_decl ();
4995 if (collapse_flag)
4996 add_collapse_ndfa_insn_decl ();
4997 if (progress_flag)
4998 fprintf (stderr, "Reservation transformation...");
4999 for (i = 0; i < description->normal_decls_num; i++)
5001 decl = description->decls [i];
5002 if (decl->mode == dm_insn_reserv)
5003 DECL_INSN_RESERV (decl)->transformed_regexp
5004 = transform_regexp (copy_insn_regexp
5005 (DECL_INSN_RESERV (decl)->regexp));
5007 if (progress_flag)
5008 fprintf (stderr, "done\n");
5009 ticker_off (&transform_time);
5014 /* The following variable value is TRUE if the first annotated message
5015 about units to automata distribution has been output. */
5016 static int annotation_message_reported_p;
5018 /* The vector contains all decls which are automata. */
5019 static vec<decl_t> automaton_decls;
5021 /* The following structure describes usage of a unit in a reservation. */
5022 struct unit_usage
5024 unit_decl_t unit_decl;
5025 /* The following forms a list of units used on the same cycle in the
5026 same alternative. The list is ordered by the correspdoning unit
5027 declarations and there is no unit declaration duplication in the
5028 list. */
5029 struct unit_usage *next;
5031 typedef struct unit_usage *unit_usage_t;
5034 /* Obstack for unit_usage structures. */
5035 static struct obstack unit_usages;
5037 /* VLA for representation of array of pointers to unit usage
5038 structures. There is an element for each combination of
5039 (alternative number, cycle). Unit usages on given cycle in
5040 alternative with given number are referred through element with
5041 index equals to the cycle * number of all alternatives in the
5042 regexp + the alternative number. */
5043 static vec<unit_usage_t> cycle_alt_unit_usages;
5045 /* The following function creates the structure unit_usage for UNIT on
5046 CYCLE in REGEXP alternative with ALT_NUM. The structure is made
5047 accessed through cycle_alt_unit_usages. */
5048 static void
5049 store_alt_unit_usage (regexp_t regexp, regexp_t unit, int cycle,
5050 int alt_num)
5052 size_t length;
5053 unit_decl_t unit_decl;
5054 unit_usage_t unit_usage_ptr, curr, prev;
5055 int index;
5057 gcc_assert (regexp && regexp->mode == rm_oneof
5058 && alt_num < REGEXP_ONEOF (regexp)->regexps_num);
5059 unit_decl = REGEXP_UNIT (unit)->unit_decl;
5061 length = (cycle + 1) * REGEXP_ONEOF (regexp)->regexps_num;
5062 while (cycle_alt_unit_usages.length () < length)
5063 cycle_alt_unit_usages.safe_push (NULL);
5065 index = cycle * REGEXP_ONEOF (regexp)->regexps_num + alt_num;
5066 prev = NULL;
5067 for (curr = cycle_alt_unit_usages[index];
5068 curr != NULL;
5069 prev = curr, curr = curr->next)
5070 if (curr->unit_decl >= unit_decl)
5071 break;
5072 if (curr != NULL && curr->unit_decl == unit_decl)
5073 return;
5074 obstack_blank (&unit_usages, sizeof (struct unit_usage));
5075 unit_usage_ptr = (struct unit_usage *) obstack_base (&unit_usages);
5076 obstack_finish (&unit_usages);
5077 unit_usage_ptr->unit_decl = unit_decl;
5078 unit_decl->last_distribution_check_cycle = -1; /* undefined */
5079 unit_usage_ptr->next = curr;
5080 if (prev == NULL)
5081 cycle_alt_unit_usages[index] = unit_usage_ptr;
5082 else
5083 prev->next = unit_usage_ptr;
5086 /* Return true if unit UNIT_DECL is present on the LIST. */
5087 static bool
5088 unit_present_on_list_p (unit_usage_t list, unit_decl_t unit_decl)
5090 while (list != NULL)
5092 if (list->unit_decl == unit_decl)
5093 return true;
5094 list = list->next;
5096 return false;
5099 /* The function returns true if reservations of alternatives ALT1 and
5100 ALT2 are equal after excluding reservations of units of
5101 EXCLUDED_AUTOMATON_DECL. */
5102 static bool
5103 equal_alternatives_p (int alt1, int alt2, int n_alts,
5104 struct automaton_decl *excluded_automaton_decl)
5106 int i;
5107 unit_usage_t list1, list2;
5109 for (i = 0;
5110 i < (int) cycle_alt_unit_usages.length ();
5111 i += n_alts)
5113 for (list1 = cycle_alt_unit_usages[i + alt1],
5114 list2 = cycle_alt_unit_usages[i + alt2];;
5115 list1 = list1->next, list2 = list2->next)
5117 while (list1 != NULL
5118 && list1->unit_decl->automaton_decl == excluded_automaton_decl)
5119 list1 = list1->next;
5120 while (list2 != NULL
5121 && list2->unit_decl->automaton_decl == excluded_automaton_decl)
5122 list2 = list2->next;
5123 if (list1 == NULL || list2 == NULL)
5125 if (list1 != list2)
5126 return false;
5127 else
5128 break;
5130 if (list1->unit_decl != list2->unit_decl)
5131 return false;
5134 return true;
5138 /* The function processes given REGEXP to find units with the wrong
5139 distribution. */
5140 static void
5141 check_regexp_units_distribution (const char *insn_reserv_name,
5142 regexp_t regexp)
5144 int i, j, k, cycle, start, n_alts, alt, alt2;
5145 bool annotation_reservation_message_reported_p;
5146 regexp_t seq, allof, unit;
5147 struct unit_usage *unit_usage_ptr;
5148 vec<int> marked;
5150 if (regexp == NULL || regexp->mode != rm_oneof)
5151 return;
5152 /* Store all unit usages in the regexp: */
5153 obstack_init (&unit_usages);
5154 cycle_alt_unit_usages.create (10);
5156 for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
5158 seq = REGEXP_ONEOF (regexp)->regexps [i];
5159 switch (seq->mode)
5161 case rm_sequence:
5162 for (j = 0; j < REGEXP_SEQUENCE (seq)->regexps_num; j++)
5164 allof = REGEXP_SEQUENCE (seq)->regexps [j];
5165 switch (allof->mode)
5167 case rm_allof:
5168 for (k = 0; k < REGEXP_ALLOF (allof)->regexps_num; k++)
5170 unit = REGEXP_ALLOF (allof)->regexps [k];
5171 if (unit->mode == rm_unit)
5172 store_alt_unit_usage (regexp, unit, j, i);
5173 else
5174 gcc_assert (unit->mode == rm_nothing);
5176 break;
5178 case rm_unit:
5179 store_alt_unit_usage (regexp, allof, j, i);
5180 break;
5182 case rm_nothing:
5183 break;
5185 default:
5186 gcc_unreachable ();
5189 break;
5191 case rm_allof:
5192 for (k = 0; k < REGEXP_ALLOF (seq)->regexps_num; k++)
5194 unit = REGEXP_ALLOF (seq)->regexps [k];
5195 switch (unit->mode)
5197 case rm_unit:
5198 store_alt_unit_usage (regexp, unit, 0, i);
5199 break;
5201 case rm_nothing:
5202 break;
5204 default:
5205 gcc_unreachable ();
5208 break;
5210 case rm_unit:
5211 store_alt_unit_usage (regexp, seq, 0, i);
5212 break;
5214 case rm_nothing:
5215 break;
5217 default:
5218 gcc_unreachable ();
5221 /* Check distribution: */
5222 for (i = 0; i < (int) cycle_alt_unit_usages.length (); i++)
5223 for (unit_usage_ptr = cycle_alt_unit_usages[i];
5224 unit_usage_ptr != NULL;
5225 unit_usage_ptr = unit_usage_ptr->next)
5226 unit_usage_ptr->unit_decl->last_distribution_check_cycle = -1;
5227 n_alts = REGEXP_ONEOF (regexp)->regexps_num;
5228 marked.create (n_alts);
5229 for (i = 0; i < n_alts; i++)
5230 marked.safe_push (0);
5231 annotation_reservation_message_reported_p = false;
5232 for (i = 0; i < (int) cycle_alt_unit_usages.length (); i++)
5234 cycle = i / n_alts;
5235 start = cycle * n_alts;
5236 for (unit_usage_ptr = cycle_alt_unit_usages[i];
5237 unit_usage_ptr != NULL;
5238 unit_usage_ptr = unit_usage_ptr->next)
5240 if (unit_usage_ptr->unit_decl->last_distribution_check_cycle == cycle)
5241 continue;
5242 unit_usage_ptr->unit_decl->last_distribution_check_cycle = cycle;
5243 for (alt = 0; alt < n_alts; alt++)
5244 if (! unit_present_on_list_p (cycle_alt_unit_usages[start + alt],
5245 unit_usage_ptr->unit_decl))
5246 break;
5247 if (alt >= n_alts)
5248 continue;
5249 memset (marked.address (), 0, n_alts * sizeof (int));
5250 for (alt = 0; alt < n_alts; alt++)
5252 if (! unit_present_on_list_p (cycle_alt_unit_usages[start + alt],
5253 unit_usage_ptr->unit_decl))
5254 continue;
5255 for (j = 0;
5256 j < (int) cycle_alt_unit_usages.length ();
5257 j++)
5259 alt2 = j % n_alts;
5260 if (! unit_present_on_list_p
5261 (cycle_alt_unit_usages[start + alt2],
5262 unit_usage_ptr->unit_decl)
5263 && equal_alternatives_p (alt, alt2, n_alts,
5264 unit_usage_ptr
5265 ->unit_decl->automaton_decl))
5267 marked[alt] = 1;
5268 marked[alt2] = 1;
5272 for (alt = 0; alt < n_alts && marked[alt]; alt++)
5274 if (alt < n_alts && 0)
5276 if (! annotation_message_reported_p)
5278 fprintf (stderr, "\n");
5279 error ("The following units do not satisfy units-automata distribution rule");
5280 error ("(Unit presence on one alt and its absence on other alt\n");
5281 error (" result in different other automata reservations)");
5282 annotation_message_reported_p = TRUE;
5284 if (! annotation_reservation_message_reported_p)
5286 error ("Reserv %s:", insn_reserv_name);
5287 annotation_reservation_message_reported_p = true;
5289 error (" Unit %s, cycle %d, alt %d, another alt %d",
5290 unit_usage_ptr->unit_decl->name, cycle, i % n_alts, alt);
5294 marked.release ();
5295 cycle_alt_unit_usages.release ();
5296 obstack_free (&unit_usages, NULL);
5299 /* The function finds units which violates units to automata
5300 distribution rule. If the units exist, report about them. */
5301 static void
5302 check_unit_distributions_to_automata (void)
5304 decl_t decl;
5305 int i;
5307 if (progress_flag)
5308 fprintf (stderr, "Check unit distributions to automata...");
5309 automaton_decls.create (0);
5310 for (i = 0; i < description->decls_num; i++)
5312 decl = description->decls [i];
5313 if (decl->mode == dm_automaton)
5314 automaton_decls.safe_push (decl);
5316 if (automaton_decls.length () > 1)
5318 annotation_message_reported_p = FALSE;
5319 for (i = 0; i < description->decls_num; i++)
5321 decl = description->decls [i];
5322 if (decl->mode == dm_insn_reserv)
5323 check_regexp_units_distribution
5324 (DECL_INSN_RESERV (decl)->name,
5325 DECL_INSN_RESERV (decl)->transformed_regexp);
5328 automaton_decls.release ();
5329 if (progress_flag)
5330 fprintf (stderr, "done\n");
5335 /* The page contains code for building alt_states (see comments for
5336 IR) describing all possible insns reservations of an automaton. */
5338 /* Current state being formed for which the current alt_state
5339 refers. */
5340 static state_t state_being_formed;
5342 /* Current alt_state being formed. */
5343 static alt_state_t alt_state_being_formed;
5345 /* This recursive function processes `,' and units in reservation
5346 REGEXP for forming alt_states of AUTOMATON. It is believed that
5347 CURR_CYCLE is start cycle of all reservation REGEXP. */
5348 static int
5349 process_seq_for_forming_states (regexp_t regexp, automaton_t automaton,
5350 int curr_cycle)
5352 int i;
5354 if (regexp == NULL)
5355 return curr_cycle;
5357 switch (regexp->mode)
5359 case rm_unit:
5360 if (REGEXP_UNIT (regexp)->unit_decl->corresponding_automaton_num
5361 == automaton->automaton_order_num)
5362 set_state_reserv (state_being_formed, curr_cycle,
5363 REGEXP_UNIT (regexp)->unit_decl->unit_num);
5364 return curr_cycle;
5366 case rm_sequence:
5367 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
5368 curr_cycle
5369 = process_seq_for_forming_states
5370 (REGEXP_SEQUENCE (regexp)->regexps [i], automaton, curr_cycle) + 1;
5371 return curr_cycle;
5373 case rm_allof:
5375 int finish_cycle = 0;
5376 int cycle;
5378 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
5380 cycle = process_seq_for_forming_states (REGEXP_ALLOF (regexp)
5381 ->regexps [i],
5382 automaton, curr_cycle);
5383 if (finish_cycle < cycle)
5384 finish_cycle = cycle;
5386 return finish_cycle;
5389 case rm_nothing:
5390 return curr_cycle;
5392 default:
5393 gcc_unreachable ();
5397 /* This recursive function finishes forming ALT_STATE of AUTOMATON and
5398 inserts alt_state into the table. */
5399 static void
5400 finish_forming_alt_state (alt_state_t alt_state,
5401 automaton_t automaton ATTRIBUTE_UNUSED)
5403 state_t state_in_table;
5404 state_t corresponding_state;
5406 corresponding_state = alt_state->state;
5407 state_in_table = insert_state (corresponding_state);
5408 if (state_in_table != corresponding_state)
5410 free_state (corresponding_state);
5411 alt_state->state = state_in_table;
5415 /* The following variable value is current automaton insn for whose
5416 reservation the alt states are created. */
5417 static ainsn_t curr_ainsn;
5419 /* This recursive function processes `|' in reservation REGEXP for
5420 forming alt_states of AUTOMATON. List of the alt states should
5421 have the same order as in the description. */
5422 static void
5423 process_alts_for_forming_states (regexp_t regexp, automaton_t automaton,
5424 int inside_oneof_p)
5426 int i;
5428 if (regexp->mode != rm_oneof)
5430 alt_state_being_formed = get_free_alt_state ();
5431 state_being_formed = get_free_state (1, automaton);
5432 alt_state_being_formed->state = state_being_formed;
5433 /* We inserts in reverse order but we process alternatives also
5434 in reverse order. So we have the same order of alternative
5435 as in the description. */
5436 alt_state_being_formed->next_alt_state = curr_ainsn->alt_states;
5437 curr_ainsn->alt_states = alt_state_being_formed;
5438 (void) process_seq_for_forming_states (regexp, automaton, 0);
5439 finish_forming_alt_state (alt_state_being_formed, automaton);
5441 else
5443 gcc_assert (!inside_oneof_p);
5444 /* We processes it in reverse order to get list with the same
5445 order as in the description. See also the previous
5446 commentary. */
5447 for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
5448 process_alts_for_forming_states (REGEXP_ONEOF (regexp)->regexps [i],
5449 automaton, 1);
5453 /* Create nodes alt_state for all AUTOMATON insns. */
5454 static void
5455 create_alt_states (automaton_t automaton)
5457 struct insn_reserv_decl *reserv_decl;
5459 for (curr_ainsn = automaton->ainsn_list;
5460 curr_ainsn != NULL;
5461 curr_ainsn = curr_ainsn->next_ainsn)
5463 reserv_decl = curr_ainsn->insn_reserv_decl;
5464 if (!special_decl_p (reserv_decl))
5466 curr_ainsn->alt_states = NULL;
5467 process_alts_for_forming_states (reserv_decl->transformed_regexp,
5468 automaton, 0);
5469 curr_ainsn->sorted_alt_states
5470 = uniq_sort_alt_states (curr_ainsn->alt_states);
5477 /* The page contains major code for building DFA(s) for fast pipeline
5478 hazards recognition. */
5480 /* The function forms list of ainsns of AUTOMATON with the same
5481 reservation. */
5483 static void
5484 form_ainsn_with_same_reservs (automaton_t automaton)
5486 ainsn_t curr_ainsn;
5487 size_t i;
5488 vec<ainsn_t> last_insns;
5489 last_insns.create (150);
5491 for (curr_ainsn = automaton->ainsn_list;
5492 curr_ainsn != NULL;
5493 curr_ainsn = curr_ainsn->next_ainsn)
5494 if (special_decl_p (curr_ainsn->insn_reserv_decl))
5496 curr_ainsn->next_same_reservs_insn = NULL;
5497 curr_ainsn->first_insn_with_same_reservs = 1;
5499 else
5501 for (i = 0; i < last_insns.length (); i++)
5502 if (alt_states_eq
5503 (curr_ainsn->sorted_alt_states,
5504 last_insns[i]->sorted_alt_states))
5505 break;
5506 curr_ainsn->next_same_reservs_insn = NULL;
5507 if (i < last_insns.length ())
5509 curr_ainsn->first_insn_with_same_reservs = 0;
5510 last_insns[i]->next_same_reservs_insn = curr_ainsn;
5511 last_insns[i] = curr_ainsn;
5513 else
5515 last_insns.safe_push (curr_ainsn);
5516 curr_ainsn->first_insn_with_same_reservs = 1;
5519 last_insns.release ();
5522 /* Forming unit reservations which can affect creating the automaton
5523 states achieved from a given state. It permits to build smaller
5524 automata in many cases. We would have the same automata after
5525 the minimization without such optimization, but the automaton
5526 right after the building could be huge. So in other words, usage
5527 of reservs_matter means some minimization during building the
5528 automaton. */
5529 static reserv_sets_t
5530 form_reservs_matter (automaton_t automaton)
5532 int cycle, unit;
5533 reserv_sets_t reservs_matter = alloc_empty_reserv_sets();
5535 for (cycle = 0; cycle < max_cycles_num; cycle++)
5536 for (unit = 0; unit < description->units_num; unit++)
5537 if (units_array [unit]->automaton_decl
5538 == automaton->corresponding_automaton_decl
5539 && (cycle >= units_array [unit]->min_occ_cycle_num
5540 /* We can not remove queried unit from reservations. */
5541 || units_array [unit]->query_p
5542 /* We can not remove units which are used
5543 `exclusion_set', `presence_set',
5544 `final_presence_set', `absence_set', and
5545 `final_absence_set'. */
5546 || units_array [unit]->in_set_p))
5547 set_unit_reserv (reservs_matter, cycle, unit);
5548 return reservs_matter;
5551 /* The following function creates all states of nondeterministic AUTOMATON. */
5552 static void
5553 make_automaton (automaton_t automaton)
5555 ainsn_t ainsn;
5556 struct insn_reserv_decl *insn_reserv_decl;
5557 alt_state_t alt_state;
5558 state_t state;
5559 state_t start_state;
5560 state_t state2;
5561 vec<state_t> state_stack;
5562 state_stack.create (150);
5563 int states_n;
5564 reserv_sets_t reservs_matter = form_reservs_matter (automaton);
5566 /* Create the start state (empty state). */
5567 start_state = insert_state (get_free_state (1, automaton));
5568 automaton->start_state = start_state;
5569 start_state->it_was_placed_in_stack_for_NDFA_forming = 1;
5570 state_stack.safe_push (start_state);
5571 states_n = 1;
5572 while (state_stack.length () != 0)
5574 state = state_stack.pop ();
5575 for (ainsn = automaton->ainsn_list;
5576 ainsn != NULL;
5577 ainsn = ainsn->next_ainsn)
5578 if (ainsn->first_insn_with_same_reservs)
5580 insn_reserv_decl = ainsn->insn_reserv_decl;
5581 if (!special_decl_p (insn_reserv_decl))
5583 /* We process alt_states in the same order as they are
5584 present in the description. */
5585 for (alt_state = ainsn->alt_states;
5586 alt_state != NULL;
5587 alt_state = alt_state->next_alt_state)
5589 state2 = alt_state->state;
5590 if (!intersected_state_reservs_p (state, state2))
5592 state2 = states_union (state, state2, reservs_matter);
5593 if (!state2->it_was_placed_in_stack_for_NDFA_forming)
5595 state2->it_was_placed_in_stack_for_NDFA_forming
5596 = 1;
5597 state_stack.safe_push (state2);
5598 states_n++;
5599 if (progress_flag && states_n % 100 == 0)
5600 fprintf (stderr, ".");
5602 add_arc (state, state2, ainsn);
5603 if (!ndfa_flag)
5604 break;
5609 /* Add transition to advance cycle. */
5610 state2 = state_shift (state, reservs_matter);
5611 if (!state2->it_was_placed_in_stack_for_NDFA_forming)
5613 state2->it_was_placed_in_stack_for_NDFA_forming = 1;
5614 state_stack.safe_push (state2);
5615 states_n++;
5616 if (progress_flag && states_n % 100 == 0)
5617 fprintf (stderr, ".");
5619 add_arc (state, state2, automaton->advance_ainsn);
5621 state_stack.release ();
5624 /* Form lists of all arcs of STATE marked by the same ainsn. */
5625 static void
5626 form_arcs_marked_by_insn (state_t state)
5628 decl_t decl;
5629 arc_t arc;
5630 int i;
5632 for (i = 0; i < description->decls_num; i++)
5634 decl = description->decls [i];
5635 if (decl->mode == dm_insn_reserv)
5636 DECL_INSN_RESERV (decl)->arcs_marked_by_insn = NULL;
5638 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
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;
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. */
5652 static int
5653 create_composed_state (state_t original_state, arc_t arcs_marked_by_insn,
5654 vec<state_t> *state_stack)
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;
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
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)
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;
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)
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;
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)
5702 temp_state = state;
5703 state = canonical_alt_states_list->state;
5704 free_state (temp_state);
5706 else
5708 state->component_states = canonical_alt_states_list;
5709 state_in_table = insert_state (state);
5710 if (state_in_table != state)
5712 gcc_assert
5713 (state_in_table->it_was_placed_in_stack_for_DFA_forming);
5714 free_state (state);
5715 state = state_in_table;
5717 else
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);
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)
5741 next_arc = curr_arc->next_arc_marked_by_insn;
5742 remove_arc (original_state, curr_arc);
5743 alts_number++;
5747 if (!state->it_was_placed_in_stack_for_DFA_forming)
5749 state->it_was_placed_in_stack_for_DFA_forming = 1;
5750 state_stack->safe_push (state);
5752 return new_state_p;
5755 /* The function transforms nondeterministic AUTOMATON into
5756 deterministic. */
5758 static void
5759 NDFA_to_DFA (automaton_t automaton)
5761 state_t start_state;
5762 state_t state;
5763 decl_t decl;
5764 vec<state_t> state_stack;
5765 int i;
5766 int states_n;
5768 state_stack.create (0);
5770 /* Create the start state (empty state). */
5771 start_state = automaton->start_state;
5772 start_state->it_was_placed_in_stack_for_DFA_forming = 1;
5773 state_stack.safe_push (start_state);
5774 states_n = 1;
5775 while (state_stack.length () != 0)
5777 state = state_stack.pop ();
5778 form_arcs_marked_by_insn (state);
5779 for (i = 0; i < description->decls_num; i++)
5781 decl = description->decls [i];
5782 if (decl->mode == dm_insn_reserv
5783 && decl != collapse_ndfa_insn_decl
5784 && create_composed_state
5785 (state, DECL_INSN_RESERV (decl)->arcs_marked_by_insn,
5786 &state_stack))
5788 states_n++;
5789 if (progress_flag && states_n % 100 == 0)
5790 fprintf (stderr, ".");
5793 /* Add a transition to collapse the NDFA. */
5794 if (collapse_flag)
5796 if (state->component_states != NULL)
5798 state_t state2 = state->component_states->state;
5799 if (!state2->it_was_placed_in_stack_for_DFA_forming)
5801 state2->it_was_placed_in_stack_for_DFA_forming = 1;
5802 state_stack.safe_push (state2);
5804 add_arc (state, state2, automaton->collapse_ainsn);
5806 else
5807 add_arc (state, state, automaton->collapse_ainsn);
5810 state_stack.release ();
5813 /* The following variable value is current number (1, 2, ...) of passing
5814 graph of states. */
5815 static int curr_state_graph_pass_num;
5817 /* This recursive function passes all states achieved from START_STATE
5818 and applies APPLIED_FUNC to them. */
5819 static void
5820 pass_state_graph (state_t start_state, void (*applied_func) (state_t state))
5822 arc_t arc;
5824 if (start_state->pass_num == curr_state_graph_pass_num)
5825 return;
5826 start_state->pass_num = curr_state_graph_pass_num;
5827 (*applied_func) (start_state);
5828 for (arc = first_out_arc (start_state);
5829 arc != NULL;
5830 arc = next_out_arc (arc))
5831 pass_state_graph (arc->to_state, applied_func);
5834 /* This recursive function passes all states of AUTOMATON and applies
5835 APPLIED_FUNC to them. */
5836 static void
5837 pass_states (automaton_t automaton, void (*applied_func) (state_t state))
5839 curr_state_graph_pass_num++;
5840 pass_state_graph (automaton->start_state, applied_func);
5843 /* The function initializes code for passing of all states. */
5844 static void
5845 initiate_pass_states (void)
5847 curr_state_graph_pass_num = 0;
5850 /* The following vla is used for storing pointers to all achieved
5851 states. */
5852 static vec<state_t> all_achieved_states;
5854 /* This function is called by function pass_states to add an achieved
5855 STATE. */
5856 static void
5857 add_achieved_state (state_t state)
5859 all_achieved_states.safe_push (state);
5862 /* The function sets up equivalence numbers of insns which mark all
5863 out arcs of STATE by equiv_class_num_1 (if ODD_ITERATION_FLAG has
5864 nonzero value) or by equiv_class_num_2 of the destination state. */
5865 static void
5866 set_out_arc_insns_equiv_num (state_t state, int odd_iteration_flag)
5868 arc_t arc;
5870 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5872 gcc_assert (!arc->insn->insn_reserv_decl->equiv_class_num);
5873 arc->insn->insn_reserv_decl->equiv_class_num
5874 = (odd_iteration_flag
5875 ? arc->to_state->equiv_class_num_1
5876 : arc->to_state->equiv_class_num_2);
5877 gcc_assert (arc->insn->insn_reserv_decl->equiv_class_num);
5881 /* The function clears equivalence numbers and alt_states in all insns
5882 which mark all out arcs of STATE. */
5883 static void
5884 clear_arc_insns_equiv_num (state_t state)
5886 arc_t arc;
5888 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5889 arc->insn->insn_reserv_decl->equiv_class_num = 0;
5893 /* The following function returns TRUE if STATE reserves the unit with
5894 UNIT_NUM on the first cycle. */
5895 static int
5896 first_cycle_unit_presence (state_t state, int unit_num)
5898 alt_state_t alt_state;
5900 if (state->component_states == NULL)
5901 return test_unit_reserv (state->reservs, 0, unit_num);
5902 else
5904 for (alt_state = state->component_states;
5905 alt_state != NULL;
5906 alt_state = alt_state->next_sorted_alt_state)
5907 if (test_unit_reserv (alt_state->state->reservs, 0, unit_num))
5908 return true;
5910 return false;
5913 /* This fills in the presence_signature[] member of STATE. */
5914 static void
5915 cache_presence (state_t state)
5917 int i, num = 0;
5918 unsigned int sz;
5919 sz = (description->query_units_num + sizeof (int) * CHAR_BIT - 1)
5920 / (sizeof (int) * CHAR_BIT);
5922 state->presence_signature = XCREATENODEVEC (unsigned int, sz);
5923 for (i = 0; i < description->units_num; i++)
5924 if (units_array [i]->query_p)
5926 int presence1_p = first_cycle_unit_presence (state, i);
5927 state->presence_signature[num / (sizeof (int) * CHAR_BIT)]
5928 |= (!!presence1_p) << (num % (sizeof (int) * CHAR_BIT));
5929 num++;
5933 /* The function returns nonzero value if STATE is not equivalent to
5934 ANOTHER_STATE from the same current partition on equivalence
5935 classes. Another state has ANOTHER_STATE_OUT_ARCS_NUM number of
5936 output arcs. Iteration of making equivalence partition is defined
5937 by ODD_ITERATION_FLAG. */
5938 static int
5939 state_is_differed (state_t state, state_t another_state,
5940 int odd_iteration_flag)
5942 arc_t arc;
5943 unsigned int sz, si;
5945 gcc_assert (state->num_out_arcs == another_state->num_out_arcs);
5947 sz = (description->query_units_num + sizeof (int) * CHAR_BIT - 1)
5948 / (sizeof (int) * CHAR_BIT);
5950 for (si = 0; si < sz; si++)
5951 gcc_assert (state->presence_signature[si]
5952 == another_state->presence_signature[si]);
5954 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5956 if ((odd_iteration_flag
5957 ? arc->to_state->equiv_class_num_1
5958 : arc->to_state->equiv_class_num_2)
5959 != arc->insn->insn_reserv_decl->equiv_class_num)
5960 return 1;
5963 return 0;
5966 /* Compares two states pointed to by STATE_PTR_1 and STATE_PTR_2
5967 and return -1, 0 or 1. This function can be used as predicate for
5968 qsort(). It requires the member presence_signature[] of both
5969 states be filled. */
5970 static int
5971 compare_states_for_equiv (const void *state_ptr_1,
5972 const void *state_ptr_2)
5974 const_state_t const s1 = *(const_state_t const*)state_ptr_1;
5975 const_state_t const s2 = *(const_state_t const*)state_ptr_2;
5976 unsigned int sz, si;
5977 if (s1->num_out_arcs < s2->num_out_arcs)
5978 return -1;
5979 else if (s1->num_out_arcs > s2->num_out_arcs)
5980 return 1;
5982 sz = (description->query_units_num + sizeof (int) * CHAR_BIT - 1)
5983 / (sizeof (int) * CHAR_BIT);
5985 for (si = 0; si < sz; si++)
5986 if (s1->presence_signature[si] < s2->presence_signature[si])
5987 return -1;
5988 else if (s1->presence_signature[si] > s2->presence_signature[si])
5989 return 1;
5990 return 0;
5993 /* The function makes initial partition of STATES on equivalent
5994 classes and saves it into CLASSES. This function requires the input
5995 to be sorted via compare_states_for_equiv(). */
5996 static int
5997 init_equiv_class (vec<state_t> states, vec<state_t> *classes)
5999 size_t i;
6000 state_t prev = 0;
6001 int class_num = 1;
6003 classes->create (150);
6004 for (i = 0; i < states.length (); i++)
6006 state_t state = states[i];
6007 if (prev)
6009 if (compare_states_for_equiv (&prev, &state) != 0)
6011 classes->safe_push (prev);
6012 class_num++;
6013 prev = NULL;
6016 state->equiv_class_num_1 = class_num;
6017 state->next_equiv_class_state = prev;
6018 prev = state;
6020 if (prev)
6021 classes->safe_push (prev);
6022 return class_num;
6025 /* The function copies pointers to equivalent states from vla FROM
6026 into vla TO. */
6027 static void
6028 copy_equiv_class (vec<state_t> *to, vec<state_t> from)
6030 to->release ();
6031 *to = from.copy ();
6034 /* The function processes equivalence class given by its first state,
6035 FIRST_STATE, on odd iteration if ODD_ITERATION_FLAG. If there
6036 are not equivalent states, the function partitions the class
6037 removing nonequivalent states and placing them in
6038 *NEXT_ITERATION_CLASSES, increments *NEW_EQUIV_CLASS_NUM_PTR ans
6039 assigns it to the state equivalence number. If the class has been
6040 partitioned, the function returns nonzero value. */
6041 static int
6042 partition_equiv_class (state_t first_state, int odd_iteration_flag,
6043 vec<state_t> *next_iteration_classes,
6044 int *new_equiv_class_num_ptr)
6046 state_t new_equiv_class;
6047 int partition_p;
6048 state_t curr_state;
6049 state_t prev_state;
6050 state_t next_state;
6052 partition_p = 0;
6054 while (first_state != NULL)
6056 new_equiv_class = NULL;
6057 if (first_state->next_equiv_class_state != NULL)
6059 /* There are more one states in the class equivalence. */
6060 set_out_arc_insns_equiv_num (first_state, odd_iteration_flag);
6061 for (prev_state = first_state,
6062 curr_state = first_state->next_equiv_class_state;
6063 curr_state != NULL;
6064 curr_state = next_state)
6066 next_state = curr_state->next_equiv_class_state;
6067 if (state_is_differed (curr_state, first_state,
6068 odd_iteration_flag))
6070 /* Remove curr state from the class equivalence. */
6071 prev_state->next_equiv_class_state = next_state;
6072 /* Add curr state to the new class equivalence. */
6073 curr_state->next_equiv_class_state = new_equiv_class;
6074 if (new_equiv_class == NULL)
6075 (*new_equiv_class_num_ptr)++;
6076 if (odd_iteration_flag)
6077 curr_state->equiv_class_num_2 = *new_equiv_class_num_ptr;
6078 else
6079 curr_state->equiv_class_num_1 = *new_equiv_class_num_ptr;
6080 new_equiv_class = curr_state;
6081 partition_p = 1;
6083 else
6084 prev_state = curr_state;
6086 clear_arc_insns_equiv_num (first_state);
6088 if (new_equiv_class != NULL)
6089 next_iteration_classes->safe_push (new_equiv_class);
6090 first_state = new_equiv_class;
6092 return partition_p;
6095 /* The function finds equivalent states of AUTOMATON. */
6096 static void
6097 evaluate_equiv_classes (automaton_t automaton, vec<state_t> *equiv_classes)
6099 int new_equiv_class_num;
6100 int odd_iteration_flag;
6101 int finish_flag;
6102 vec<state_t> next_iteration_classes;
6103 size_t i;
6105 all_achieved_states.create (1500);
6106 pass_states (automaton, add_achieved_state);
6107 pass_states (automaton, cache_presence);
6108 all_achieved_states.qsort (compare_states_for_equiv);
6110 odd_iteration_flag = 0;
6111 new_equiv_class_num = init_equiv_class (all_achieved_states,
6112 &next_iteration_classes);
6116 odd_iteration_flag = !odd_iteration_flag;
6117 finish_flag = 1;
6118 copy_equiv_class (equiv_classes, next_iteration_classes);
6120 /* Transfer equiv numbers for the next iteration. */
6121 for (i = 0; i < all_achieved_states.length (); i++)
6122 if (odd_iteration_flag)
6123 all_achieved_states[i]->equiv_class_num_2
6124 = all_achieved_states[i]->equiv_class_num_1;
6125 else
6126 all_achieved_states[i]->equiv_class_num_1
6127 = all_achieved_states[i]->equiv_class_num_2;
6129 for (i = 0; i < equiv_classes->length (); i++)
6130 if (partition_equiv_class ((*equiv_classes)[i],
6131 odd_iteration_flag,
6132 &next_iteration_classes,
6133 &new_equiv_class_num))
6134 finish_flag = 0;
6136 while (!finish_flag);
6137 next_iteration_classes.release ();
6138 all_achieved_states.release ();
6141 /* The function merges equivalent states of AUTOMATON. */
6142 static void
6143 merge_states (automaton_t automaton, vec<state_t> equiv_classes)
6145 state_t curr_state;
6146 state_t new_state;
6147 state_t first_class_state;
6148 alt_state_t alt_states;
6149 alt_state_t alt_state, new_alt_state;
6150 arc_t curr_arc;
6151 arc_t next_arc;
6152 size_t i;
6154 /* Create states corresponding to equivalence classes containing two
6155 or more states. */
6156 for (i = 0; i < equiv_classes.length (); i++)
6158 curr_state = equiv_classes[i];
6159 if (curr_state->next_equiv_class_state != NULL)
6161 /* There are more one states in the class equivalence. */
6162 /* Create new compound state. */
6163 new_state = get_free_state (0, automaton);
6164 alt_states = NULL;
6165 first_class_state = curr_state;
6166 for (curr_state = first_class_state;
6167 curr_state != NULL;
6168 curr_state = curr_state->next_equiv_class_state)
6170 curr_state->equiv_class_state = new_state;
6171 if (curr_state->component_states == NULL)
6173 new_alt_state = get_free_alt_state ();
6174 new_alt_state->state = curr_state;
6175 new_alt_state->next_alt_state = alt_states;
6176 alt_states = new_alt_state;
6178 else
6179 for (alt_state = curr_state->component_states;
6180 alt_state != NULL;
6181 alt_state = alt_state->next_sorted_alt_state)
6183 new_alt_state = get_free_alt_state ();
6184 new_alt_state->state = alt_state->state;
6185 new_alt_state->next_alt_state = alt_states;
6186 alt_states = new_alt_state;
6189 /* Its is important that alt states were sorted before and
6190 after merging to have the same querying results. */
6191 new_state->component_states = uniq_sort_alt_states (alt_states);
6193 else
6194 curr_state->equiv_class_state = curr_state;
6197 for (i = 0; i < equiv_classes.length (); i++)
6199 curr_state = equiv_classes[i];
6200 if (curr_state->next_equiv_class_state != NULL)
6202 first_class_state = curr_state;
6203 /* Create new arcs output from the state corresponding to
6204 equiv class. */
6205 for (curr_arc = first_out_arc (first_class_state);
6206 curr_arc != NULL;
6207 curr_arc = next_out_arc (curr_arc))
6208 add_arc (first_class_state->equiv_class_state,
6209 curr_arc->to_state->equiv_class_state,
6210 curr_arc->insn);
6211 /* Delete output arcs from states of given class equivalence. */
6212 for (curr_state = first_class_state;
6213 curr_state != NULL;
6214 curr_state = curr_state->next_equiv_class_state)
6216 if (automaton->start_state == curr_state)
6217 automaton->start_state = curr_state->equiv_class_state;
6218 /* Delete the state and its output arcs. */
6219 for (curr_arc = first_out_arc (curr_state);
6220 curr_arc != NULL;
6221 curr_arc = next_arc)
6223 next_arc = next_out_arc (curr_arc);
6224 free_arc (curr_arc);
6228 else
6230 /* Change `to_state' of arcs output from the state of given
6231 equivalence class. */
6232 for (curr_arc = first_out_arc (curr_state);
6233 curr_arc != NULL;
6234 curr_arc = next_out_arc (curr_arc))
6235 curr_arc->to_state = curr_arc->to_state->equiv_class_state;
6240 /* The function sets up new_cycle_p for states if there is arc to the
6241 state marked by advance_cycle_insn_decl. */
6242 static void
6243 set_new_cycle_flags (state_t state)
6245 arc_t arc;
6247 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6248 if (arc->insn->insn_reserv_decl
6249 == DECL_INSN_RESERV (advance_cycle_insn_decl))
6250 arc->to_state->new_cycle_p = 1;
6253 /* The top level function for minimization of deterministic
6254 AUTOMATON. */
6255 static void
6256 minimize_DFA (automaton_t automaton)
6258 vec<state_t> equiv_classes = vNULL;
6260 evaluate_equiv_classes (automaton, &equiv_classes);
6261 merge_states (automaton, equiv_classes);
6262 pass_states (automaton, set_new_cycle_flags);
6264 equiv_classes.release ();
6267 /* Values of two variables are counted number of states and arcs in an
6268 automaton. */
6269 static int curr_counted_states_num;
6270 static int curr_counted_arcs_num;
6272 /* The function is called by function `pass_states' to count states
6273 and arcs of an automaton. */
6274 static void
6275 incr_states_and_arcs_nums (state_t state)
6277 arc_t arc;
6279 curr_counted_states_num++;
6280 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6281 curr_counted_arcs_num++;
6284 /* The function counts states and arcs of AUTOMATON. */
6285 static void
6286 count_states_and_arcs (automaton_t automaton, int *states_num,
6287 int *arcs_num)
6289 curr_counted_states_num = 0;
6290 curr_counted_arcs_num = 0;
6291 pass_states (automaton, incr_states_and_arcs_nums);
6292 *states_num = curr_counted_states_num;
6293 *arcs_num = curr_counted_arcs_num;
6296 /* The function builds one DFA AUTOMATON for fast pipeline hazards
6297 recognition after checking and simplifying IR of the
6298 description. */
6299 static void
6300 build_automaton (automaton_t automaton)
6302 int states_num;
6303 int arcs_num;
6305 ticker_on (&NDFA_time);
6306 if (progress_flag)
6308 if (automaton->corresponding_automaton_decl == NULL)
6309 fprintf (stderr, "Create anonymous automaton");
6310 else
6311 fprintf (stderr, "Create automaton `%s'",
6312 automaton->corresponding_automaton_decl->name);
6313 fprintf (stderr, " (1 dot is 100 new states):");
6315 make_automaton (automaton);
6316 if (progress_flag)
6317 fprintf (stderr, " done\n");
6318 ticker_off (&NDFA_time);
6319 count_states_and_arcs (automaton, &states_num, &arcs_num);
6320 automaton->NDFA_states_num = states_num;
6321 automaton->NDFA_arcs_num = arcs_num;
6322 ticker_on (&NDFA_to_DFA_time);
6323 if (progress_flag)
6325 if (automaton->corresponding_automaton_decl == NULL)
6326 fprintf (stderr, "Make anonymous DFA");
6327 else
6328 fprintf (stderr, "Make DFA `%s'",
6329 automaton->corresponding_automaton_decl->name);
6330 fprintf (stderr, " (1 dot is 100 new states):");
6332 NDFA_to_DFA (automaton);
6333 if (progress_flag)
6334 fprintf (stderr, " done\n");
6335 ticker_off (&NDFA_to_DFA_time);
6336 count_states_and_arcs (automaton, &states_num, &arcs_num);
6337 automaton->DFA_states_num = states_num;
6338 automaton->DFA_arcs_num = arcs_num;
6339 if (!no_minimization_flag)
6341 ticker_on (&minimize_time);
6342 if (progress_flag)
6344 if (automaton->corresponding_automaton_decl == NULL)
6345 fprintf (stderr, "Minimize anonymous DFA...");
6346 else
6347 fprintf (stderr, "Minimize DFA `%s'...",
6348 automaton->corresponding_automaton_decl->name);
6350 minimize_DFA (automaton);
6351 if (progress_flag)
6352 fprintf (stderr, "done\n");
6353 ticker_off (&minimize_time);
6354 count_states_and_arcs (automaton, &states_num, &arcs_num);
6355 automaton->minimal_DFA_states_num = states_num;
6356 automaton->minimal_DFA_arcs_num = arcs_num;
6362 /* The page contains code for enumeration of all states of an automaton. */
6364 /* Variable used for enumeration of all states of an automaton. Its
6365 value is current number of automaton states. */
6366 static int curr_state_order_num;
6368 /* The function is called by function `pass_states' for enumerating
6369 states. */
6370 static void
6371 set_order_state_num (state_t state)
6373 state->order_state_num = curr_state_order_num;
6374 curr_state_order_num++;
6377 /* The function enumerates all states of AUTOMATON. */
6378 static void
6379 enumerate_states (automaton_t automaton)
6381 curr_state_order_num = 0;
6382 pass_states (automaton, set_order_state_num);
6383 automaton->achieved_states_num = curr_state_order_num;
6388 /* The page contains code for finding equivalent automaton insns
6389 (ainsns). */
6391 /* The function inserts AINSN into cyclic list
6392 CYCLIC_EQUIV_CLASS_INSN_LIST of ainsns. */
6393 static ainsn_t
6394 insert_ainsn_into_equiv_class (ainsn_t ainsn,
6395 ainsn_t cyclic_equiv_class_insn_list)
6397 if (cyclic_equiv_class_insn_list == NULL)
6398 ainsn->next_equiv_class_insn = ainsn;
6399 else
6401 ainsn->next_equiv_class_insn
6402 = cyclic_equiv_class_insn_list->next_equiv_class_insn;
6403 cyclic_equiv_class_insn_list->next_equiv_class_insn = ainsn;
6405 return ainsn;
6408 /* The function deletes equiv_class_insn into cyclic list of
6409 equivalent ainsns. */
6410 static void
6411 delete_ainsn_from_equiv_class (ainsn_t equiv_class_insn)
6413 ainsn_t curr_equiv_class_insn;
6414 ainsn_t prev_equiv_class_insn;
6416 prev_equiv_class_insn = equiv_class_insn;
6417 for (curr_equiv_class_insn = equiv_class_insn->next_equiv_class_insn;
6418 curr_equiv_class_insn != equiv_class_insn;
6419 curr_equiv_class_insn = curr_equiv_class_insn->next_equiv_class_insn)
6420 prev_equiv_class_insn = curr_equiv_class_insn;
6421 if (prev_equiv_class_insn != equiv_class_insn)
6422 prev_equiv_class_insn->next_equiv_class_insn
6423 = equiv_class_insn->next_equiv_class_insn;
6426 /* The function processes AINSN of a state in order to find equivalent
6427 ainsns. INSN_ARCS_ARRAY is table: code of insn -> out arc of the
6428 state. */
6429 static void
6430 process_insn_equiv_class (ainsn_t ainsn, arc_t *insn_arcs_array)
6432 ainsn_t next_insn;
6433 ainsn_t curr_insn;
6434 ainsn_t cyclic_insn_list;
6435 arc_t arc;
6437 gcc_assert (insn_arcs_array [ainsn->insn_reserv_decl->insn_num]);
6438 curr_insn = ainsn;
6439 /* New class of ainsns which are not equivalent to given ainsn. */
6440 cyclic_insn_list = NULL;
6443 next_insn = curr_insn->next_equiv_class_insn;
6444 arc = insn_arcs_array [curr_insn->insn_reserv_decl->insn_num];
6445 if (arc == NULL
6446 || (insn_arcs_array [ainsn->insn_reserv_decl->insn_num]->to_state
6447 != arc->to_state))
6449 delete_ainsn_from_equiv_class (curr_insn);
6450 cyclic_insn_list = insert_ainsn_into_equiv_class (curr_insn,
6451 cyclic_insn_list);
6453 curr_insn = next_insn;
6455 while (curr_insn != ainsn);
6458 /* The function processes STATE in order to find equivalent ainsns. */
6459 static void
6460 process_state_for_insn_equiv_partition (state_t state)
6462 arc_t arc;
6463 arc_t *insn_arcs_array = XCNEWVEC (arc_t, description->insns_num);
6465 /* Process insns of the arcs. */
6466 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6467 insn_arcs_array [arc->insn->insn_reserv_decl->insn_num] = arc;
6468 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6469 process_insn_equiv_class (arc->insn, insn_arcs_array);
6471 free (insn_arcs_array);
6474 /* The function searches for equivalent ainsns of AUTOMATON. */
6475 static void
6476 set_insn_equiv_classes (automaton_t automaton)
6478 ainsn_t ainsn;
6479 ainsn_t first_insn;
6480 ainsn_t curr_insn;
6481 ainsn_t cyclic_insn_list;
6482 ainsn_t insn_with_same_reservs;
6483 int equiv_classes_num;
6485 /* All insns are included in one equivalence class. */
6486 cyclic_insn_list = NULL;
6487 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6488 if (ainsn->first_insn_with_same_reservs)
6489 cyclic_insn_list = insert_ainsn_into_equiv_class (ainsn,
6490 cyclic_insn_list);
6491 /* Process insns in order to make equivalence partition. */
6492 pass_states (automaton, process_state_for_insn_equiv_partition);
6493 /* Enumerate equiv classes. */
6494 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6495 /* Set undefined value. */
6496 ainsn->insn_equiv_class_num = -1;
6497 equiv_classes_num = 0;
6498 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6499 if (ainsn->insn_equiv_class_num < 0)
6501 first_insn = ainsn;
6502 gcc_assert (first_insn->first_insn_with_same_reservs);
6503 first_insn->first_ainsn_with_given_equivalence_num = 1;
6504 curr_insn = first_insn;
6507 for (insn_with_same_reservs = curr_insn;
6508 insn_with_same_reservs != NULL;
6509 insn_with_same_reservs
6510 = insn_with_same_reservs->next_same_reservs_insn)
6511 insn_with_same_reservs->insn_equiv_class_num = equiv_classes_num;
6512 curr_insn = curr_insn->next_equiv_class_insn;
6514 while (curr_insn != first_insn);
6515 equiv_classes_num++;
6517 automaton->insn_equiv_classes_num = equiv_classes_num;
6522 /* This page contains code for creating DFA(s) and calls functions
6523 building them. */
6526 /* The following value is used to prevent floating point overflow for
6527 estimating an automaton bound. The value should be less DBL_MAX on
6528 the host machine. We use here approximate minimum of maximal
6529 double floating point value required by ANSI C standard. It
6530 will work for non ANSI sun compiler too. */
6532 #define MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND 1.0E37
6534 /* The function estimate size of the single DFA used by PHR (pipeline
6535 hazards recognizer). */
6536 static double
6537 estimate_one_automaton_bound (void)
6539 decl_t decl;
6540 double one_automaton_estimation_bound;
6541 double root_value;
6542 int i;
6544 one_automaton_estimation_bound = 1.0;
6545 for (i = 0; i < description->decls_num; i++)
6547 decl = description->decls [i];
6548 if (decl->mode == dm_unit)
6550 root_value = exp (log (DECL_UNIT (decl)->max_occ_cycle_num
6551 - DECL_UNIT (decl)->min_occ_cycle_num + 1.0)
6552 / automata_num);
6553 if (MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND / root_value
6554 > one_automaton_estimation_bound)
6555 one_automaton_estimation_bound *= root_value;
6558 return one_automaton_estimation_bound;
6561 /* The function compares unit declarations according to their maximal
6562 cycle in reservations. */
6563 static int
6564 compare_max_occ_cycle_nums (const void *unit_decl_1,
6565 const void *unit_decl_2)
6567 if ((DECL_UNIT (*(const_decl_t const*) unit_decl_1)->max_occ_cycle_num)
6568 < (DECL_UNIT (*(const_decl_t const*) unit_decl_2)->max_occ_cycle_num))
6569 return 1;
6570 else if ((DECL_UNIT (*(const_decl_t const*) unit_decl_1)->max_occ_cycle_num)
6571 == (DECL_UNIT (*(const_decl_t const*) unit_decl_2)->max_occ_cycle_num))
6572 return 0;
6573 else
6574 return -1;
6577 /* The function makes heuristic assigning automata to units. Actually
6578 efficacy of the algorithm has been checked yet??? */
6580 static void
6581 units_to_automata_heuristic_distr (void)
6583 double estimation_bound;
6584 int automaton_num;
6585 int rest_units_num;
6586 double bound_value;
6587 unit_decl_t *unit_decls;
6588 int i, j;
6590 if (description->units_num == 0)
6591 return;
6592 estimation_bound = estimate_one_automaton_bound ();
6593 unit_decls = XNEWVEC (unit_decl_t, description->units_num);
6595 for (i = 0, j = 0; i < description->decls_num; i++)
6596 if (description->decls[i]->mode == dm_unit)
6597 unit_decls[j++] = DECL_UNIT (description->decls[i]);
6598 gcc_assert (j == description->units_num);
6600 qsort (unit_decls, description->units_num,
6601 sizeof (unit_decl_t), compare_max_occ_cycle_nums);
6603 automaton_num = 0;
6604 bound_value = unit_decls[0]->max_occ_cycle_num;
6605 unit_decls[0]->corresponding_automaton_num = automaton_num;
6607 for (i = 1; i < description->units_num; i++)
6609 rest_units_num = description->units_num - i + 1;
6610 gcc_assert (automata_num - automaton_num - 1 <= rest_units_num);
6611 if (automaton_num < automata_num - 1
6612 && ((automata_num - automaton_num - 1 == rest_units_num)
6613 || (bound_value
6614 > (estimation_bound
6615 / unit_decls[i]->max_occ_cycle_num))))
6617 bound_value = unit_decls[i]->max_occ_cycle_num;
6618 automaton_num++;
6620 else
6621 bound_value *= unit_decls[i]->max_occ_cycle_num;
6622 unit_decls[i]->corresponding_automaton_num = automaton_num;
6624 gcc_assert (automaton_num == automata_num - 1);
6625 free (unit_decls);
6628 /* The functions creates automaton insns for each automata. Automaton
6629 insn is simply insn for given automaton which makes reservation
6630 only of units of the automaton. */
6631 static void
6632 create_ainsns (automaton_t automaton)
6634 decl_t decl;
6635 ainsn_t first_ainsn;
6636 ainsn_t curr_ainsn;
6637 ainsn_t prev_ainsn;
6638 int i;
6640 first_ainsn = NULL;
6641 prev_ainsn = NULL;
6642 for (i = 0; i < description->decls_num; i++)
6644 decl = description->decls [i];
6645 if (decl->mode == dm_insn_reserv)
6647 curr_ainsn = XCREATENODE (struct ainsn);
6648 curr_ainsn->insn_reserv_decl = DECL_INSN_RESERV (decl);
6649 curr_ainsn->important_p = FALSE;
6650 curr_ainsn->next_ainsn = NULL;
6651 if (prev_ainsn == NULL)
6652 first_ainsn = curr_ainsn;
6653 else
6654 prev_ainsn->next_ainsn = curr_ainsn;
6655 if (decl == advance_cycle_insn_decl)
6656 automaton->advance_ainsn = curr_ainsn;
6657 else if (decl == collapse_ndfa_insn_decl)
6658 automaton->collapse_ainsn = curr_ainsn;
6659 prev_ainsn = curr_ainsn;
6662 automaton->ainsn_list = first_ainsn;
6665 /* The function assigns automata to units according to constructions
6666 `define_automaton' in the description. */
6667 static void
6668 units_to_automata_distr (void)
6670 decl_t decl;
6671 int i;
6673 for (i = 0; i < description->decls_num; i++)
6675 decl = description->decls [i];
6676 if (decl->mode == dm_unit)
6678 if (DECL_UNIT (decl)->automaton_decl == NULL
6679 || (DECL_UNIT (decl)->automaton_decl->corresponding_automaton
6680 == NULL))
6681 /* Distribute to the first automaton. */
6682 DECL_UNIT (decl)->corresponding_automaton_num = 0;
6683 else
6684 DECL_UNIT (decl)->corresponding_automaton_num
6685 = (DECL_UNIT (decl)->automaton_decl
6686 ->corresponding_automaton->automaton_order_num);
6691 /* The function creates DFA(s) for fast pipeline hazards recognition
6692 after checking and simplifying IR of the description. */
6693 static void
6694 create_automata (void)
6696 automaton_t curr_automaton;
6697 automaton_t prev_automaton;
6698 decl_t decl;
6699 int curr_automaton_num;
6700 int i;
6702 if (automata_num != 0)
6704 units_to_automata_heuristic_distr ();
6705 for (prev_automaton = NULL, curr_automaton_num = 0;
6706 curr_automaton_num < automata_num;
6707 curr_automaton_num++, prev_automaton = curr_automaton)
6709 curr_automaton = XCREATENODE (struct automaton);
6710 create_ainsns (curr_automaton);
6711 curr_automaton->corresponding_automaton_decl = NULL;
6712 curr_automaton->next_automaton = NULL;
6713 curr_automaton->automaton_order_num = curr_automaton_num;
6714 if (prev_automaton == NULL)
6715 description->first_automaton = curr_automaton;
6716 else
6717 prev_automaton->next_automaton = curr_automaton;
6720 else
6722 curr_automaton_num = 0;
6723 prev_automaton = NULL;
6724 for (i = 0; i < description->decls_num; i++)
6726 decl = description->decls [i];
6727 if (decl->mode == dm_automaton
6728 && DECL_AUTOMATON (decl)->automaton_is_used)
6730 curr_automaton = XCREATENODE (struct automaton);
6731 create_ainsns (curr_automaton);
6732 curr_automaton->corresponding_automaton_decl
6733 = DECL_AUTOMATON (decl);
6734 curr_automaton->next_automaton = NULL;
6735 DECL_AUTOMATON (decl)->corresponding_automaton = curr_automaton;
6736 curr_automaton->automaton_order_num = curr_automaton_num;
6737 if (prev_automaton == NULL)
6738 description->first_automaton = curr_automaton;
6739 else
6740 prev_automaton->next_automaton = curr_automaton;
6741 curr_automaton_num++;
6742 prev_automaton = curr_automaton;
6745 if (curr_automaton_num == 0)
6747 curr_automaton = XCREATENODE (struct automaton);
6748 create_ainsns (curr_automaton);
6749 curr_automaton->corresponding_automaton_decl = NULL;
6750 curr_automaton->next_automaton = NULL;
6751 description->first_automaton = curr_automaton;
6753 units_to_automata_distr ();
6755 NDFA_time = create_ticker ();
6756 ticker_off (&NDFA_time);
6757 NDFA_to_DFA_time = create_ticker ();
6758 ticker_off (&NDFA_to_DFA_time);
6759 minimize_time = create_ticker ();
6760 ticker_off (&minimize_time);
6761 equiv_time = create_ticker ();
6762 ticker_off (&equiv_time);
6763 for (curr_automaton = description->first_automaton;
6764 curr_automaton != NULL;
6765 curr_automaton = curr_automaton->next_automaton)
6767 if (progress_flag)
6769 if (curr_automaton->corresponding_automaton_decl == NULL)
6770 fprintf (stderr, "Prepare anonymous automaton creation ... ");
6771 else
6772 fprintf (stderr, "Prepare automaton `%s' creation...",
6773 curr_automaton->corresponding_automaton_decl->name);
6775 create_alt_states (curr_automaton);
6776 form_ainsn_with_same_reservs (curr_automaton);
6777 if (progress_flag)
6778 fprintf (stderr, "done\n");
6779 build_automaton (curr_automaton);
6780 enumerate_states (curr_automaton);
6781 ticker_on (&equiv_time);
6782 set_insn_equiv_classes (curr_automaton);
6783 ticker_off (&equiv_time);
6789 /* This page contains code for forming string representation of
6790 regexp. The representation is formed on IR obstack. So you should
6791 not work with IR obstack between regexp_representation and
6792 finish_regexp_representation calls. */
6794 /* This recursive function forms string representation of regexp
6795 (without tailing '\0'). */
6796 static void
6797 form_regexp (regexp_t regexp)
6799 int i;
6801 switch (regexp->mode)
6803 case rm_unit: case rm_reserv:
6805 const char *name = (regexp->mode == rm_unit
6806 ? REGEXP_UNIT (regexp)->name
6807 : REGEXP_RESERV (regexp)->name);
6809 obstack_grow (&irp, name, strlen (name));
6810 break;
6813 case rm_sequence:
6814 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
6816 if (i != 0)
6817 obstack_1grow (&irp, ',');
6818 form_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
6820 break;
6822 case rm_allof:
6823 obstack_1grow (&irp, '(');
6824 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
6826 if (i != 0)
6827 obstack_1grow (&irp, '+');
6828 if (REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_sequence
6829 || REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_oneof)
6830 obstack_1grow (&irp, '(');
6831 form_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
6832 if (REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_sequence
6833 || REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_oneof)
6834 obstack_1grow (&irp, ')');
6836 obstack_1grow (&irp, ')');
6837 break;
6839 case rm_oneof:
6840 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
6842 if (i != 0)
6843 obstack_1grow (&irp, '|');
6844 if (REGEXP_ONEOF (regexp)->regexps[i]->mode == rm_sequence)
6845 obstack_1grow (&irp, '(');
6846 form_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
6847 if (REGEXP_ONEOF (regexp)->regexps[i]->mode == rm_sequence)
6848 obstack_1grow (&irp, ')');
6850 break;
6852 case rm_repeat:
6854 char digits [30];
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 form_regexp (REGEXP_REPEAT (regexp)->regexp);
6861 if (REGEXP_REPEAT (regexp)->regexp->mode == rm_sequence
6862 || REGEXP_REPEAT (regexp)->regexp->mode == rm_allof
6863 || REGEXP_REPEAT (regexp)->regexp->mode == rm_oneof)
6864 obstack_1grow (&irp, ')');
6865 sprintf (digits, "*%d", REGEXP_REPEAT (regexp)->repeat_num);
6866 obstack_grow (&irp, digits, strlen (digits));
6867 break;
6870 case rm_nothing:
6871 obstack_grow (&irp, NOTHING_NAME, strlen (NOTHING_NAME));
6872 break;
6874 default:
6875 gcc_unreachable ();
6879 /* The function returns string representation of REGEXP on IR
6880 obstack. */
6881 static const char *
6882 regexp_representation (regexp_t regexp)
6884 form_regexp (regexp);
6885 obstack_1grow (&irp, '\0');
6886 return obstack_base (&irp);
6889 /* The function frees memory allocated for last formed string
6890 representation of regexp. */
6891 static void
6892 finish_regexp_representation (void)
6894 int length = obstack_object_size (&irp);
6896 obstack_blank_fast (&irp, -length);
6901 /* This page contains code for output PHR (pipeline hazards recognizer). */
6903 /* The function outputs minimal C type which is sufficient for
6904 representation numbers in range min_range_value and
6905 max_range_value. Because host machine and build machine may be
6906 different, we use here minimal values required by ANSI C standard
6907 instead of UCHAR_MAX, SHRT_MAX, SHRT_MIN, etc. This is a good
6908 approximation. */
6910 static void
6911 output_range_type (FILE *f, long int min_range_value,
6912 long int max_range_value)
6914 if (min_range_value >= 0 && max_range_value <= 255)
6915 fprintf (f, "unsigned char");
6916 else if (min_range_value >= -127 && max_range_value <= 127)
6917 fprintf (f, "signed char");
6918 else if (min_range_value >= 0 && max_range_value <= 65535)
6919 fprintf (f, "unsigned short");
6920 else if (min_range_value >= -32767 && max_range_value <= 32767)
6921 fprintf (f, "short");
6922 else
6923 fprintf (f, "int");
6926 /* The function outputs all initialization values of VECT. */
6927 static void
6928 output_vect (vla_hwint_t vect)
6930 int els_on_line;
6931 size_t vect_length = vect.length ();
6932 size_t i;
6934 els_on_line = 1;
6935 if (vect_length == 0)
6936 fputs ("0 /* This is dummy el because the vect is empty */", output_file);
6937 else
6938 for (i = 0; i < vect_length; i++)
6940 fprintf (output_file, "%5ld", (long) vect[i]);
6941 if (els_on_line == 10)
6943 els_on_line = 0;
6944 fputs (",\n", output_file);
6946 else if (i < vect_length-1)
6947 fputs (", ", output_file);
6948 els_on_line++;
6952 /* The following is name of the structure which represents DFA(s) for
6953 PHR. */
6954 #define CHIP_NAME "DFA_chip"
6956 /* The following is name of member which represents state of a DFA for
6957 PHR. */
6958 static void
6959 output_chip_member_name (FILE *f, automaton_t automaton)
6961 if (automaton->corresponding_automaton_decl == NULL)
6962 fprintf (f, "automaton_state_%d", automaton->automaton_order_num);
6963 else
6964 fprintf (f, "%s_automaton_state",
6965 automaton->corresponding_automaton_decl->name);
6968 /* The following is name of temporary variable which stores state of a
6969 DFA for PHR. */
6970 static void
6971 output_temp_chip_member_name (FILE *f, automaton_t automaton)
6973 fprintf (f, "_");
6974 output_chip_member_name (f, automaton);
6977 /* This is name of macro value which is code of pseudo_insns
6978 representing advancing cpu cycle and collapsing the NDFA.
6979 Its value is used as internal code unknown insn. */
6980 #define ADVANCE_CYCLE_VALUE_NAME "DFA__ADVANCE_CYCLE"
6981 #define COLLAPSE_NDFA_VALUE_NAME "NDFA__COLLAPSE"
6983 /* Output name of translate vector for given automaton. */
6984 static void
6985 output_translate_vect_name (FILE *f, automaton_t automaton)
6987 if (automaton->corresponding_automaton_decl == NULL)
6988 fprintf (f, "translate_%d", automaton->automaton_order_num);
6989 else
6990 fprintf (f, "%s_translate", automaton->corresponding_automaton_decl->name);
6993 /* Output name for simple transition table representation. */
6994 static void
6995 output_trans_full_vect_name (FILE *f, automaton_t automaton)
6997 if (automaton->corresponding_automaton_decl == NULL)
6998 fprintf (f, "transitions_%d", automaton->automaton_order_num);
6999 else
7000 fprintf (f, "%s_transitions",
7001 automaton->corresponding_automaton_decl->name);
7004 /* Output name of comb vector of the transition table for given
7005 automaton. */
7006 static void
7007 output_trans_comb_vect_name (FILE *f, automaton_t automaton)
7009 if (automaton->corresponding_automaton_decl == NULL)
7010 fprintf (f, "transitions_%d", automaton->automaton_order_num);
7011 else
7012 fprintf (f, "%s_transitions",
7013 automaton->corresponding_automaton_decl->name);
7016 /* Output name of check vector of the transition table for given
7017 automaton. */
7018 static void
7019 output_trans_check_vect_name (FILE *f, automaton_t automaton)
7021 if (automaton->corresponding_automaton_decl == NULL)
7022 fprintf (f, "check_%d", automaton->automaton_order_num);
7023 else
7024 fprintf (f, "%s_check", automaton->corresponding_automaton_decl->name);
7027 /* Output name of base vector of the transition table for given
7028 automaton. */
7029 static void
7030 output_trans_base_vect_name (FILE *f, automaton_t automaton)
7032 if (automaton->corresponding_automaton_decl == NULL)
7033 fprintf (f, "base_%d", automaton->automaton_order_num);
7034 else
7035 fprintf (f, "%s_base", automaton->corresponding_automaton_decl->name);
7038 /* Output name of simple min issue delay table representation. */
7039 static void
7040 output_min_issue_delay_vect_name (FILE *f, automaton_t automaton)
7042 if (automaton->corresponding_automaton_decl == NULL)
7043 fprintf (f, "min_issue_delay_%d", automaton->automaton_order_num);
7044 else
7045 fprintf (f, "%s_min_issue_delay",
7046 automaton->corresponding_automaton_decl->name);
7049 /* Output name of deadlock vector for given automaton. */
7050 static void
7051 output_dead_lock_vect_name (FILE *f, automaton_t automaton)
7053 if (automaton->corresponding_automaton_decl == NULL)
7054 fprintf (f, "dead_lock_%d", automaton->automaton_order_num);
7055 else
7056 fprintf (f, "%s_dead_lock", automaton->corresponding_automaton_decl->name);
7059 /* Output name of reserved units table for AUTOMATON into file F. */
7060 static void
7061 output_reserved_units_table_name (FILE *f, automaton_t automaton)
7063 if (automaton->corresponding_automaton_decl == NULL)
7064 fprintf (f, "reserved_units_%d", automaton->automaton_order_num);
7065 else
7066 fprintf (f, "%s_reserved_units",
7067 automaton->corresponding_automaton_decl->name);
7070 /* Name of the PHR interface macro. */
7071 #define CPU_UNITS_QUERY_MACRO_NAME "CPU_UNITS_QUERY"
7073 /* Names of an internal functions: */
7074 #define INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME "internal_min_issue_delay"
7076 /* This is external type of DFA(s) state. */
7077 #define STATE_TYPE_NAME "state_t"
7079 #define INTERNAL_TRANSITION_FUNC_NAME "internal_state_transition"
7081 #define INTERNAL_RESET_FUNC_NAME "internal_reset"
7083 #define INTERNAL_DEAD_LOCK_FUNC_NAME "internal_state_dead_lock_p"
7085 #define INTERNAL_INSN_LATENCY_FUNC_NAME "internal_insn_latency"
7087 /* Name of cache of insn dfa codes. */
7088 #define DFA_INSN_CODES_VARIABLE_NAME "dfa_insn_codes"
7090 /* Name of length of cache of insn dfa codes. */
7091 #define DFA_INSN_CODES_LENGTH_VARIABLE_NAME "dfa_insn_codes_length"
7093 /* Names of the PHR interface functions: */
7094 #define SIZE_FUNC_NAME "state_size"
7096 #define TRANSITION_FUNC_NAME "state_transition"
7098 #define MIN_ISSUE_DELAY_FUNC_NAME "min_issue_delay"
7100 #define MIN_INSN_CONFLICT_DELAY_FUNC_NAME "min_insn_conflict_delay"
7102 #define DEAD_LOCK_FUNC_NAME "state_dead_lock_p"
7104 #define RESET_FUNC_NAME "state_reset"
7106 #define INSN_LATENCY_FUNC_NAME "insn_latency"
7108 #define PRINT_RESERVATION_FUNC_NAME "print_reservation"
7110 #define GET_CPU_UNIT_CODE_FUNC_NAME "get_cpu_unit_code"
7112 #define CPU_UNIT_RESERVATION_P_FUNC_NAME "cpu_unit_reservation_p"
7114 #define INSN_HAS_DFA_RESERVATION_P_FUNC_NAME "insn_has_dfa_reservation_p"
7116 #define DFA_CLEAN_INSN_CACHE_FUNC_NAME "dfa_clean_insn_cache"
7118 #define DFA_CLEAR_SINGLE_INSN_CACHE_FUNC_NAME "dfa_clear_single_insn_cache"
7120 #define DFA_START_FUNC_NAME "dfa_start"
7122 #define DFA_FINISH_FUNC_NAME "dfa_finish"
7124 /* Names of parameters of the PHR interface functions. */
7125 #define STATE_NAME "state"
7127 #define INSN_PARAMETER_NAME "insn"
7129 #define INSN2_PARAMETER_NAME "insn2"
7131 #define CHIP_PARAMETER_NAME "chip"
7133 #define FILE_PARAMETER_NAME "f"
7135 #define CPU_UNIT_NAME_PARAMETER_NAME "cpu_unit_name"
7137 #define CPU_CODE_PARAMETER_NAME "cpu_unit_code"
7139 /* Names of the variables whose values are internal insn code of rtx
7140 insn. */
7141 #define INTERNAL_INSN_CODE_NAME "insn_code"
7143 #define INTERNAL_INSN2_CODE_NAME "insn2_code"
7145 /* Names of temporary variables in some functions. */
7146 #define TEMPORARY_VARIABLE_NAME "temp"
7148 #define I_VARIABLE_NAME "i"
7150 /* Name of result variable in some functions. */
7151 #define RESULT_VARIABLE_NAME "res"
7153 /* Name of function (attribute) to translate insn into internal insn
7154 code. */
7155 #define INTERNAL_DFA_INSN_CODE_FUNC_NAME "internal_dfa_insn_code"
7157 /* Name of function (attribute) to translate insn into internal insn
7158 code with caching. */
7159 #define DFA_INSN_CODE_FUNC_NAME "dfa_insn_code"
7161 /* Output C type which is used for representation of codes of states
7162 of AUTOMATON. */
7163 static void
7164 output_state_member_type (FILE *f, automaton_t automaton)
7166 output_range_type (f, 0, automaton->achieved_states_num);
7169 /* Output definition of the structure representing current DFA(s)
7170 state(s). */
7171 static void
7172 output_chip_definitions (void)
7174 automaton_t automaton;
7176 fprintf (output_file, "struct %s\n{\n", CHIP_NAME);
7177 for (automaton = description->first_automaton;
7178 automaton != NULL;
7179 automaton = automaton->next_automaton)
7181 fprintf (output_file, " ");
7182 output_state_member_type (output_file, automaton);
7183 fprintf (output_file, " ");
7184 output_chip_member_name (output_file, automaton);
7185 fprintf (output_file, ";\n");
7187 fprintf (output_file, "};\n\n");
7188 #if 0
7189 fprintf (output_file, "static struct %s %s;\n\n", CHIP_NAME, CHIP_NAME);
7190 #endif
7194 /* The function outputs translate vector of internal insn code into
7195 insn equivalence class number. The equivalence class number is
7196 used to access to table and vectors representing DFA(s). */
7197 static void
7198 output_translate_vect (automaton_t automaton)
7200 ainsn_t ainsn;
7201 int insn_value;
7202 vla_hwint_t translate_vect;
7204 translate_vect.create (description->insns_num);
7206 for (insn_value = 0; insn_value < description->insns_num; insn_value++)
7207 /* Undefined value */
7208 translate_vect.quick_push (automaton->insn_equiv_classes_num);
7210 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
7211 translate_vect[ainsn->insn_reserv_decl->insn_num] =
7212 ainsn->insn_equiv_class_num;
7214 fprintf (output_file,
7215 "/* Vector translating external insn codes to internal ones.*/\n");
7216 fprintf (output_file, "static const ");
7217 output_range_type (output_file, 0, automaton->insn_equiv_classes_num);
7218 fprintf (output_file, " ");
7219 output_translate_vect_name (output_file, automaton);
7220 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7221 output_vect (translate_vect);
7222 fprintf (output_file, "};\n\n");
7223 translate_vect.release ();
7226 /* The value in a table state x ainsn -> something which represents
7227 undefined value. */
7228 static int undefined_vect_el_value;
7230 /* The following function returns nonzero value if the best
7231 representation of the table is comb vector. */
7232 static int
7233 comb_vect_p (state_ainsn_table_t tab)
7235 if (no_comb_flag)
7236 return false;
7237 return (2 * tab->full_vect.length () > 5 * tab->comb_vect.length ());
7240 /* The following function creates new table for AUTOMATON. */
7241 static state_ainsn_table_t
7242 create_state_ainsn_table (automaton_t automaton)
7244 state_ainsn_table_t tab;
7245 int full_vect_length;
7246 int i;
7248 tab = XCREATENODE (struct state_ainsn_table);
7249 tab->automaton = automaton;
7251 tab->comb_vect.create (10000);
7252 tab->check_vect.create (10000);
7254 tab->base_vect.create (0);
7255 tab->base_vect.safe_grow (automaton->achieved_states_num);
7257 full_vect_length = (automaton->insn_equiv_classes_num
7258 * automaton->achieved_states_num);
7259 tab->full_vect.create (full_vect_length);
7260 for (i = 0; i < full_vect_length; i++)
7261 tab->full_vect.quick_push (undefined_vect_el_value);
7263 tab->min_base_vect_el_value = 0;
7264 tab->max_base_vect_el_value = 0;
7265 tab->min_comb_vect_el_value = 0;
7266 tab->max_comb_vect_el_value = 0;
7267 return tab;
7270 /* The following function outputs the best C representation of the
7271 table TAB of given TABLE_NAME. */
7272 static void
7273 output_state_ainsn_table (state_ainsn_table_t tab, const char *table_name,
7274 void (*output_full_vect_name_func) (FILE *, automaton_t),
7275 void (*output_comb_vect_name_func) (FILE *, automaton_t),
7276 void (*output_check_vect_name_func) (FILE *, automaton_t),
7277 void (*output_base_vect_name_func) (FILE *, automaton_t))
7279 if (!comb_vect_p (tab))
7281 fprintf (output_file, "/* Vector for %s. */\n", table_name);
7282 fprintf (output_file, "static const ");
7283 output_range_type (output_file, tab->min_comb_vect_el_value,
7284 tab->max_comb_vect_el_value);
7285 fprintf (output_file, " ");
7286 (*output_full_vect_name_func) (output_file, tab->automaton);
7287 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7288 output_vect (tab->full_vect);
7289 fprintf (output_file, "};\n\n");
7291 else
7293 fprintf (output_file, "/* Comb vector for %s. */\n", table_name);
7294 fprintf (output_file, "static const ");
7295 output_range_type (output_file, tab->min_comb_vect_el_value,
7296 tab->max_comb_vect_el_value);
7297 fprintf (output_file, " ");
7298 (*output_comb_vect_name_func) (output_file, tab->automaton);
7299 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7300 output_vect (tab->comb_vect);
7301 fprintf (output_file, "};\n\n");
7302 fprintf (output_file, "/* Check vector for %s. */\n", table_name);
7303 fprintf (output_file, "static const ");
7304 output_range_type (output_file, 0, tab->automaton->achieved_states_num);
7305 fprintf (output_file, " ");
7306 (*output_check_vect_name_func) (output_file, tab->automaton);
7307 fprintf (output_file, "[] = {\n");
7308 output_vect (tab->check_vect);
7309 fprintf (output_file, "};\n\n");
7310 fprintf (output_file, "/* Base vector for %s. */\n", table_name);
7311 fprintf (output_file, "static const ");
7312 output_range_type (output_file, tab->min_base_vect_el_value,
7313 tab->max_base_vect_el_value);
7314 fprintf (output_file, " ");
7315 (*output_base_vect_name_func) (output_file, tab->automaton);
7316 fprintf (output_file, "[] = {\n");
7317 output_vect (tab->base_vect);
7318 fprintf (output_file, "};\n\n");
7322 /* The following function adds vector VECT to table TAB as its line
7323 with number VECT_NUM. */
7324 static void
7325 add_vect (state_ainsn_table_t tab, int vect_num, vla_hwint_t vect)
7327 int vect_length;
7328 size_t real_vect_length;
7329 int comb_vect_index;
7330 int comb_vect_els_num;
7331 int vect_index;
7332 int first_unempty_vect_index;
7333 int additional_els_num;
7334 int no_state_value;
7335 vect_el_t vect_el;
7336 int i;
7337 unsigned long vect_mask, comb_vect_mask;
7339 vect_length = vect.length ();
7340 gcc_assert (vect_length);
7341 gcc_assert (vect.last () != undefined_vect_el_value);
7342 real_vect_length = tab->automaton->insn_equiv_classes_num;
7343 /* Form full vector in the table: */
7345 size_t full_base = tab->automaton->insn_equiv_classes_num * vect_num;
7346 if (tab->full_vect.length () < full_base + vect_length)
7347 tab->full_vect.safe_grow (full_base + vect_length);
7348 for (i = 0; i < vect_length; i++)
7349 tab->full_vect[full_base + i] = vect[i];
7352 /* The comb_vect min/max values are also used for the full vector, so
7353 compute them now. */
7354 for (vect_index = 0; vect_index < vect_length; vect_index++)
7355 if (vect[vect_index] != undefined_vect_el_value)
7357 vect_el_t x = vect[vect_index];
7358 gcc_assert (x >= 0);
7359 if (tab->max_comb_vect_el_value < x)
7360 tab->max_comb_vect_el_value = x;
7361 if (tab->min_comb_vect_el_value > x)
7362 tab->min_comb_vect_el_value = x;
7364 if (no_comb_flag)
7365 return;
7367 /* Form comb vector in the table: */
7368 gcc_assert (tab->comb_vect.length () == tab->check_vect.length ());
7370 comb_vect_els_num = tab->comb_vect.length ();
7371 for (first_unempty_vect_index = 0;
7372 first_unempty_vect_index < vect_length;
7373 first_unempty_vect_index++)
7374 if (vect[first_unempty_vect_index]
7375 != undefined_vect_el_value)
7376 break;
7378 /* Search for the place in comb vect for the inserted vect. */
7380 /* Slow case. */
7381 if (vect_length - first_unempty_vect_index >= SIZEOF_LONG * CHAR_BIT)
7383 for (comb_vect_index = 0;
7384 comb_vect_index < comb_vect_els_num;
7385 comb_vect_index++)
7387 for (vect_index = first_unempty_vect_index;
7388 vect_index < vect_length
7389 && vect_index + comb_vect_index < comb_vect_els_num;
7390 vect_index++)
7391 if (vect[vect_index]
7392 != undefined_vect_el_value
7393 && (tab->comb_vect[vect_index + comb_vect_index]
7394 != undefined_vect_el_value))
7395 break;
7396 if (vect_index >= vect_length
7397 || vect_index + comb_vect_index >= comb_vect_els_num)
7398 break;
7400 goto found;
7403 /* Fast case. */
7404 vect_mask = 0;
7405 for (vect_index = first_unempty_vect_index;
7406 vect_index < vect_length;
7407 vect_index++)
7409 vect_mask = vect_mask << 1;
7410 if (vect[vect_index] != undefined_vect_el_value)
7411 vect_mask |= 1;
7414 /* Search for the place in comb vect for the inserted vect. */
7415 comb_vect_index = 0;
7416 if (comb_vect_els_num == 0)
7417 goto found;
7419 comb_vect_mask = 0;
7420 for (vect_index = first_unempty_vect_index;
7421 vect_index < vect_length && vect_index < comb_vect_els_num;
7422 vect_index++)
7424 comb_vect_mask <<= 1;
7425 if (vect_index + comb_vect_index < comb_vect_els_num
7426 && tab->comb_vect[vect_index + comb_vect_index]
7427 != undefined_vect_el_value)
7428 comb_vect_mask |= 1;
7430 if ((vect_mask & comb_vect_mask) == 0)
7431 goto found;
7433 for (comb_vect_index = 1, i = vect_length; i < comb_vect_els_num;
7434 comb_vect_index++, i++)
7436 comb_vect_mask = (comb_vect_mask << 1) | 1;
7437 comb_vect_mask ^= (tab->comb_vect[i]
7438 == undefined_vect_el_value);
7439 if ((vect_mask & comb_vect_mask) == 0)
7440 goto found;
7442 for ( ; comb_vect_index < comb_vect_els_num; comb_vect_index++)
7444 comb_vect_mask <<= 1;
7445 if ((vect_mask & comb_vect_mask) == 0)
7446 goto found;
7449 found:
7450 /* Slot was found. */
7451 additional_els_num = comb_vect_index + real_vect_length - comb_vect_els_num;
7452 if (additional_els_num < 0)
7453 additional_els_num = 0;
7454 /* Expand comb and check vectors. */
7455 vect_el = undefined_vect_el_value;
7456 no_state_value = tab->automaton->achieved_states_num;
7457 while (additional_els_num > 0)
7459 tab->comb_vect.safe_push (vect_el);
7460 tab->check_vect.safe_push (no_state_value);
7461 additional_els_num--;
7463 gcc_assert (tab->comb_vect.length ()
7464 >= comb_vect_index + real_vect_length);
7465 /* Fill comb and check vectors. */
7466 for (vect_index = 0; vect_index < vect_length; vect_index++)
7467 if (vect[vect_index] != undefined_vect_el_value)
7469 vect_el_t x = vect[vect_index];
7470 gcc_assert (tab->comb_vect[comb_vect_index + vect_index]
7471 == undefined_vect_el_value);
7472 gcc_assert (x >= 0);
7473 tab->comb_vect[comb_vect_index + vect_index] = x;
7474 tab->check_vect[comb_vect_index + vect_index] = vect_num;
7476 if (tab->max_comb_vect_el_value < undefined_vect_el_value)
7477 tab->max_comb_vect_el_value = undefined_vect_el_value;
7478 if (tab->min_comb_vect_el_value > undefined_vect_el_value)
7479 tab->min_comb_vect_el_value = undefined_vect_el_value;
7480 if (tab->max_base_vect_el_value < comb_vect_index)
7481 tab->max_base_vect_el_value = comb_vect_index;
7482 if (tab->min_base_vect_el_value > comb_vect_index)
7483 tab->min_base_vect_el_value = comb_vect_index;
7485 tab->base_vect[vect_num] = comb_vect_index;
7488 /* Return number of out arcs of STATE. */
7489 static int
7490 out_state_arcs_num (const_state_t state)
7492 int result;
7493 arc_t arc;
7495 result = 0;
7496 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
7498 gcc_assert (arc->insn);
7499 if (arc->insn->first_ainsn_with_given_equivalence_num)
7500 result++;
7502 return result;
7505 /* Compare number of possible transitions from the states. */
7506 static int
7507 compare_transition_els_num (const void *state_ptr_1,
7508 const void *state_ptr_2)
7510 const int transition_els_num_1
7511 = out_state_arcs_num (*(const_state_t const*) state_ptr_1);
7512 const int transition_els_num_2
7513 = out_state_arcs_num (*(const_state_t const*) state_ptr_2);
7515 if (transition_els_num_1 < transition_els_num_2)
7516 return 1;
7517 else if (transition_els_num_1 == transition_els_num_2)
7518 return 0;
7519 else
7520 return -1;
7523 /* The function adds element EL_VALUE to vector VECT for a table state
7524 x AINSN. */
7525 static void
7526 add_vect_el (vla_hwint_t &vect, ainsn_t ainsn, int el_value)
7528 int equiv_class_num;
7529 int vect_index;
7531 gcc_assert (ainsn);
7532 equiv_class_num = ainsn->insn_equiv_class_num;
7533 for (vect_index = vect.length ();
7534 vect_index <= equiv_class_num;
7535 vect_index++)
7536 vect.safe_push (undefined_vect_el_value);
7537 vect[equiv_class_num] = el_value;
7540 /* This is for forming vector of states of an automaton. */
7541 static vec<state_t> output_states_vect;
7543 /* The function is called by function pass_states. The function adds
7544 STATE to `output_states_vect'. */
7545 static void
7546 add_states_vect_el (state_t state)
7548 output_states_vect.safe_push (state);
7551 /* Form and output vectors (comb, check, base or full vector)
7552 representing transition table of AUTOMATON. */
7553 static void
7554 output_trans_table (automaton_t automaton)
7556 size_t i;
7557 arc_t arc;
7558 vla_hwint_t transition_vect = vla_hwint_t();
7560 undefined_vect_el_value = automaton->achieved_states_num;
7561 automaton->trans_table = create_state_ainsn_table (automaton);
7562 /* Create vect of pointers to states ordered by num of transitions
7563 from the state (state with the maximum num is the first). */
7564 output_states_vect.create (0);
7565 pass_states (automaton, add_states_vect_el);
7566 output_states_vect.qsort (compare_transition_els_num);
7568 for (i = 0; i < output_states_vect.length (); i++)
7570 transition_vect.truncate (0);
7571 for (arc = first_out_arc (output_states_vect[i]);
7572 arc != NULL;
7573 arc = next_out_arc (arc))
7575 gcc_assert (arc->insn);
7576 if (arc->insn->first_ainsn_with_given_equivalence_num)
7577 add_vect_el (transition_vect, arc->insn,
7578 arc->to_state->order_state_num);
7580 add_vect (automaton->trans_table,
7581 output_states_vect[i]->order_state_num,
7582 transition_vect);
7584 output_state_ainsn_table
7585 (automaton->trans_table, "state transitions",
7586 output_trans_full_vect_name, output_trans_comb_vect_name,
7587 output_trans_check_vect_name, output_trans_base_vect_name);
7589 output_states_vect.release ();
7590 transition_vect.release ();
7593 /* Form and output vectors representing minimal issue delay table of
7594 AUTOMATON. The table is state x ainsn -> minimal issue delay of
7595 the ainsn. */
7596 static void
7597 output_min_issue_delay_table (automaton_t automaton)
7599 vla_hwint_t min_issue_delay_vect;
7600 vla_hwint_t compressed_min_issue_delay_vect;
7601 ainsn_t ainsn;
7602 size_t i;
7603 size_t min_issue_delay_len, compressed_min_issue_delay_len;
7604 size_t cfactor;
7605 int changed;
7607 /* Create vect of pointers to states ordered by num of transitions
7608 from the state (state with the maximum num is the first). */
7609 output_states_vect.create (0);
7610 pass_states (automaton, add_states_vect_el);
7612 min_issue_delay_len = (output_states_vect.length ()
7613 * automaton->insn_equiv_classes_num);
7614 min_issue_delay_vect.create (min_issue_delay_len);
7615 for (i = 0; i < min_issue_delay_len; i++)
7616 min_issue_delay_vect.quick_push (-1);
7618 automaton->max_min_delay = 0;
7622 size_t state_no;
7624 changed = 0;
7626 for (state_no = 0; state_no < output_states_vect.length ();
7627 state_no++)
7629 state_t s = output_states_vect[state_no];
7630 arc_t arc;
7632 for (arc = first_out_arc (s); arc; arc = next_out_arc (arc))
7634 int k;
7636 size_t asn = s->order_state_num
7637 * automaton->insn_equiv_classes_num
7638 + arc->insn->insn_equiv_class_num;
7640 if (min_issue_delay_vect[asn])
7642 min_issue_delay_vect[asn] = (vect_el_t) 0;
7643 changed = 1;
7646 for (k = 0; k < automaton->insn_equiv_classes_num; k++)
7648 size_t n0, n1;
7649 vect_el_t delay0, delay1;
7651 n0 = s->order_state_num
7652 * automaton->insn_equiv_classes_num
7653 + k;
7654 n1 = arc->to_state->order_state_num
7655 * automaton->insn_equiv_classes_num
7656 + k;
7657 delay0 = min_issue_delay_vect[n0];
7658 delay1 = min_issue_delay_vect[n1];
7659 if (delay1 != -1)
7661 if (arc->insn->insn_reserv_decl
7662 == DECL_INSN_RESERV (advance_cycle_insn_decl))
7663 delay1++;
7664 if (delay1 < delay0 || delay0 == -1)
7666 min_issue_delay_vect[n0] = delay1;
7667 changed = 1;
7674 while (changed);
7676 automaton->max_min_delay = 0;
7678 for (ainsn = automaton->ainsn_list; ainsn; ainsn = ainsn->next_ainsn)
7679 if (ainsn->first_ainsn_with_given_equivalence_num)
7681 for (i = 0; i < output_states_vect.length (); i++)
7683 state_t s = output_states_vect[i];
7684 size_t np = s->order_state_num
7685 * automaton->insn_equiv_classes_num
7686 + ainsn->insn_equiv_class_num;
7687 vect_el_t x = min_issue_delay_vect[np];
7689 if (automaton->max_min_delay < x)
7690 automaton->max_min_delay = x;
7691 if (x == -1)
7692 min_issue_delay_vect[np] = (vect_el_t) 0;
7696 fprintf (output_file, "/* Vector of min issue delay of insns. */\n");
7697 fprintf (output_file, "static const ");
7698 output_range_type (output_file, 0, automaton->max_min_delay);
7699 fprintf (output_file, " ");
7700 output_min_issue_delay_vect_name (output_file, automaton);
7701 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7702 /* Compress the vector. */
7703 if (automaton->max_min_delay < 2)
7704 cfactor = 8;
7705 else if (automaton->max_min_delay < 4)
7706 cfactor = 4;
7707 else if (automaton->max_min_delay < 16)
7708 cfactor = 2;
7709 else
7710 cfactor = 1;
7711 automaton->min_issue_delay_table_compression_factor = cfactor;
7713 compressed_min_issue_delay_len = (min_issue_delay_len+cfactor-1) / cfactor;
7714 compressed_min_issue_delay_vect.create (compressed_min_issue_delay_len);
7716 for (i = 0; i < compressed_min_issue_delay_len; i++)
7717 compressed_min_issue_delay_vect.quick_push (0);
7719 for (i = 0; i < min_issue_delay_len; i++)
7721 size_t ci = i / cfactor;
7722 vect_el_t x = min_issue_delay_vect[i];
7723 vect_el_t cx = compressed_min_issue_delay_vect[ci];
7725 cx |= x << (8 - (i % cfactor + 1) * (8 / cfactor));
7726 compressed_min_issue_delay_vect[ci] = cx;
7728 output_vect (compressed_min_issue_delay_vect);
7729 fprintf (output_file, "};\n\n");
7730 output_states_vect.release ();
7731 min_issue_delay_vect.release ();
7732 compressed_min_issue_delay_vect.release ();
7735 /* Form and output vector representing the locked states of
7736 AUTOMATON. */
7737 static void
7738 output_dead_lock_vect (automaton_t automaton)
7740 size_t i;
7741 arc_t arc;
7742 vla_hwint_t dead_lock_vect = vla_hwint_t();
7744 /* Create vect of pointers to states ordered by num of
7745 transitions from the state (state with the maximum num is the
7746 first). */
7747 automaton->locked_states = 0;
7748 output_states_vect.create (0);
7749 pass_states (automaton, add_states_vect_el);
7751 dead_lock_vect.safe_grow (output_states_vect.length ());
7752 for (i = 0; i < output_states_vect.length (); i++)
7754 state_t s = output_states_vect[i];
7755 arc = first_out_arc (s);
7756 gcc_assert (arc);
7757 if (next_out_arc (arc) == NULL
7758 && (arc->insn->insn_reserv_decl
7759 == DECL_INSN_RESERV (advance_cycle_insn_decl)))
7761 dead_lock_vect[s->order_state_num] = 1;
7762 automaton->locked_states++;
7764 else
7765 dead_lock_vect[s->order_state_num] = (vect_el_t) 0;
7767 if (automaton->locked_states == 0)
7768 return;
7770 fprintf (output_file, "/* Vector for locked state flags. */\n");
7771 fprintf (output_file, "static const ");
7772 output_range_type (output_file, 0, 1);
7773 fprintf (output_file, " ");
7774 output_dead_lock_vect_name (output_file, automaton);
7775 fprintf (output_file, "[] = {\n");
7776 output_vect (dead_lock_vect);
7777 fprintf (output_file, "};\n\n");
7778 output_states_vect.release ();
7779 dead_lock_vect.release ();
7782 /* Form and output vector representing reserved units of the states of
7783 AUTOMATON. */
7784 static void
7785 output_reserved_units_table (automaton_t automaton)
7787 vla_hwint_t reserved_units_table = vla_hwint_t();
7788 int state_byte_size;
7789 int reserved_units_size;
7790 size_t n;
7791 int i;
7793 if (description->query_units_num == 0)
7794 return;
7796 /* Create vect of pointers to states. */
7797 output_states_vect.create (0);
7798 pass_states (automaton, add_states_vect_el);
7799 /* Create vector. */
7800 state_byte_size = (description->query_units_num + 7) / 8;
7801 reserved_units_size = (output_states_vect.length ()
7802 * state_byte_size);
7804 reserved_units_table.create (reserved_units_size);
7806 for (i = 0; i < reserved_units_size; i++)
7807 reserved_units_table.quick_push (0);
7808 for (n = 0; n < output_states_vect.length (); n++)
7810 state_t s = output_states_vect[n];
7811 for (i = 0; i < description->units_num; i++)
7812 if (units_array [i]->query_p
7813 && first_cycle_unit_presence (s, i))
7815 int ri = (s->order_state_num * state_byte_size
7816 + units_array [i]->query_num / 8);
7817 vect_el_t x = reserved_units_table[ri];
7819 x += 1 << (units_array [i]->query_num % 8);
7820 reserved_units_table[ri] = x;
7823 fprintf (output_file, "\n#if %s\n", CPU_UNITS_QUERY_MACRO_NAME);
7824 fprintf (output_file, "/* Vector for reserved units of states. */\n");
7825 fprintf (output_file, "static const ");
7826 output_range_type (output_file, 0, 255);
7827 fprintf (output_file, " ");
7828 output_reserved_units_table_name (output_file, automaton);
7829 fprintf (output_file, "[] = {\n");
7830 output_vect (reserved_units_table);
7831 fprintf (output_file, "};\n#endif /* #if %s */\n\n",
7832 CPU_UNITS_QUERY_MACRO_NAME);
7834 output_states_vect.release ();
7835 reserved_units_table.release ();
7838 /* The function outputs all tables representing DFA(s) used for fast
7839 pipeline hazards recognition. */
7840 static void
7841 output_tables (void)
7843 automaton_t automaton;
7845 for (automaton = description->first_automaton;
7846 automaton != NULL;
7847 automaton = automaton->next_automaton)
7849 output_translate_vect (automaton);
7850 output_trans_table (automaton);
7851 output_min_issue_delay_table (automaton);
7852 output_dead_lock_vect (automaton);
7853 output_reserved_units_table (automaton);
7855 fprintf (output_file, "\n#define %s %d\n\n", ADVANCE_CYCLE_VALUE_NAME,
7856 DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
7857 if (collapse_flag)
7858 fprintf (output_file, "\n#define %s %d\n\n", COLLAPSE_NDFA_VALUE_NAME,
7859 DECL_INSN_RESERV (collapse_ndfa_insn_decl)->insn_num);
7862 /* The function outputs definition and value of PHR interface variable
7863 `max_insn_queue_index'. Its value is not less than maximal queue
7864 length needed for the insn scheduler. */
7865 static void
7866 output_max_insn_queue_index_def (void)
7868 int i, max, latency;
7869 decl_t decl;
7871 max = description->max_insn_reserv_cycles;
7872 for (i = 0; i < description->decls_num; i++)
7874 decl = description->decls [i];
7875 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
7877 latency = DECL_INSN_RESERV (decl)->default_latency;
7878 if (latency > max)
7879 max = latency;
7881 else if (decl->mode == dm_bypass)
7883 latency = DECL_BYPASS (decl)->latency;
7884 if (latency > max)
7885 max = latency;
7888 for (i = 0; (1 << i) <= max; i++)
7890 gcc_assert (i >= 0);
7891 fprintf (output_file, "\nconst int max_insn_queue_index = %d;\n\n",
7892 (1 << i) - 1);
7895 /* The function outputs switch cases for insn reservations using
7896 function *output_automata_list_code. */
7897 static void
7898 output_insn_code_cases (void (*output_automata_list_code)
7899 (automata_list_el_t))
7901 decl_t decl, decl2;
7902 int i, j;
7904 for (i = 0; i < description->decls_num; i++)
7906 decl = description->decls [i];
7907 if (decl->mode == dm_insn_reserv)
7908 DECL_INSN_RESERV (decl)->processed_p = FALSE;
7910 for (i = 0; i < description->decls_num; i++)
7912 decl = description->decls [i];
7913 if (decl->mode == dm_insn_reserv
7914 && !DECL_INSN_RESERV (decl)->processed_p)
7916 for (j = i; j < description->decls_num; j++)
7918 decl2 = description->decls [j];
7919 if (decl2->mode == dm_insn_reserv
7920 && (DECL_INSN_RESERV (decl2)->important_automata_list
7921 == DECL_INSN_RESERV (decl)->important_automata_list))
7923 DECL_INSN_RESERV (decl2)->processed_p = TRUE;
7924 fprintf (output_file, " case %d: /* %s */\n",
7925 DECL_INSN_RESERV (decl2)->insn_num,
7926 DECL_INSN_RESERV (decl2)->name);
7929 (*output_automata_list_code)
7930 (DECL_INSN_RESERV (decl)->important_automata_list);
7936 /* The function outputs a code for evaluation of a minimal delay of
7937 issue of insns which have reservations in given AUTOMATA_LIST. */
7938 static void
7939 output_automata_list_min_issue_delay_code (automata_list_el_t automata_list)
7941 automata_list_el_t el;
7942 automaton_t automaton;
7944 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
7946 automaton = el->automaton;
7947 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
7948 output_min_issue_delay_vect_name (output_file, automaton);
7949 fprintf (output_file,
7950 (automaton->min_issue_delay_table_compression_factor != 1
7951 ? " [(" : " ["));
7952 output_translate_vect_name (output_file, automaton);
7953 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
7954 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7955 output_chip_member_name (output_file, automaton);
7956 fprintf (output_file, " * %d", automaton->insn_equiv_classes_num);
7957 if (automaton->min_issue_delay_table_compression_factor == 1)
7958 fprintf (output_file, "];\n");
7959 else
7961 fprintf (output_file, ") / %d];\n",
7962 automaton->min_issue_delay_table_compression_factor);
7963 fprintf (output_file, " %s = (%s >> (8 - ((",
7964 TEMPORARY_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
7965 output_translate_vect_name (output_file, automaton);
7966 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
7967 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7968 output_chip_member_name (output_file, automaton);
7969 fprintf (output_file, " * %d)", automaton->insn_equiv_classes_num);
7970 fprintf
7971 (output_file, " %% %d + 1) * %d)) & %d;\n",
7972 automaton->min_issue_delay_table_compression_factor,
7973 8 / automaton->min_issue_delay_table_compression_factor,
7974 (1 << (8 / automaton->min_issue_delay_table_compression_factor))
7975 - 1);
7977 if (el == automata_list)
7978 fprintf (output_file, " %s = %s;\n",
7979 RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
7980 else
7982 fprintf (output_file, " if (%s > %s)\n",
7983 TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
7984 fprintf (output_file, " %s = %s;\n",
7985 RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
7988 fprintf (output_file, " break;\n\n");
7991 /* Output function `internal_min_issue_delay'. */
7992 static void
7993 output_internal_min_issue_delay_func (void)
7995 fprintf (output_file,
7996 "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
7997 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7998 CHIP_NAME, CHIP_PARAMETER_NAME);
7999 fprintf (output_file, "{\n int %s ATTRIBUTE_UNUSED;\n int %s = -1;\n",
8000 TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
8001 fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8002 output_insn_code_cases (output_automata_list_min_issue_delay_code);
8003 fprintf (output_file,
8004 "\n default:\n %s = -1;\n break;\n }\n",
8005 RESULT_VARIABLE_NAME);
8006 fprintf (output_file, " return %s;\n", RESULT_VARIABLE_NAME);
8007 fprintf (output_file, "}\n\n");
8010 /* The function outputs a code changing state after issue of insns
8011 which have reservations in given AUTOMATA_LIST. */
8012 static void
8013 output_automata_list_transition_code (automata_list_el_t automata_list)
8015 automata_list_el_t el, next_el;
8017 fprintf (output_file, " {\n");
8018 if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
8019 for (el = automata_list;; el = next_el)
8021 next_el = el->next_automata_list_el;
8022 if (next_el == NULL)
8023 break;
8024 fprintf (output_file, " ");
8025 output_state_member_type (output_file, el->automaton);
8026 fprintf (output_file, " ");
8027 output_temp_chip_member_name (output_file, el->automaton);
8028 fprintf (output_file, ";\n");
8030 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
8031 if (comb_vect_p (el->automaton->trans_table))
8033 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
8034 output_trans_base_vect_name (output_file, el->automaton);
8035 fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
8036 output_chip_member_name (output_file, el->automaton);
8037 fprintf (output_file, "] + ");
8038 output_translate_vect_name (output_file, el->automaton);
8039 fprintf (output_file, " [%s];\n", INTERNAL_INSN_CODE_NAME);
8040 fprintf (output_file, " if (");
8041 output_trans_check_vect_name (output_file, el->automaton);
8042 fprintf (output_file, " [%s] != %s->",
8043 TEMPORARY_VARIABLE_NAME, CHIP_PARAMETER_NAME);
8044 output_chip_member_name (output_file, el->automaton);
8045 fprintf (output_file, ")\n");
8046 fprintf (output_file, " return %s (%s, %s);\n",
8047 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8048 CHIP_PARAMETER_NAME);
8049 fprintf (output_file, " else\n");
8050 fprintf (output_file, " ");
8051 if (el->next_automata_list_el != NULL)
8052 output_temp_chip_member_name (output_file, el->automaton);
8053 else
8055 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
8056 output_chip_member_name (output_file, el->automaton);
8058 fprintf (output_file, " = ");
8059 output_trans_comb_vect_name (output_file, el->automaton);
8060 fprintf (output_file, " [%s];\n", TEMPORARY_VARIABLE_NAME);
8062 else
8064 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
8065 output_trans_full_vect_name (output_file, el->automaton);
8066 fprintf (output_file, " [");
8067 output_translate_vect_name (output_file, el->automaton);
8068 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
8069 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
8070 output_chip_member_name (output_file, el->automaton);
8071 fprintf (output_file, " * %d];\n",
8072 el->automaton->insn_equiv_classes_num);
8073 fprintf (output_file, " if (%s >= %d)\n",
8074 TEMPORARY_VARIABLE_NAME, el->automaton->achieved_states_num);
8075 fprintf (output_file, " return %s (%s, %s);\n",
8076 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8077 CHIP_PARAMETER_NAME);
8078 fprintf (output_file, " else\n ");
8079 if (el->next_automata_list_el != NULL)
8080 output_temp_chip_member_name (output_file, el->automaton);
8081 else
8083 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
8084 output_chip_member_name (output_file, el->automaton);
8086 fprintf (output_file, " = %s;\n", TEMPORARY_VARIABLE_NAME);
8088 if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
8089 for (el = automata_list;; el = next_el)
8091 next_el = el->next_automata_list_el;
8092 if (next_el == NULL)
8093 break;
8094 fprintf (output_file, " %s->", CHIP_PARAMETER_NAME);
8095 output_chip_member_name (output_file, el->automaton);
8096 fprintf (output_file, " = ");
8097 output_temp_chip_member_name (output_file, el->automaton);
8098 fprintf (output_file, ";\n");
8100 fprintf (output_file, " return -1;\n");
8101 fprintf (output_file, " }\n");
8104 /* Output function `internal_state_transition'. */
8105 static void
8106 output_internal_trans_func (void)
8108 fprintf (output_file,
8109 "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
8110 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8111 CHIP_NAME, CHIP_PARAMETER_NAME);
8112 fprintf (output_file, "{\n int %s ATTRIBUTE_UNUSED;\n", TEMPORARY_VARIABLE_NAME);
8113 fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8114 output_insn_code_cases (output_automata_list_transition_code);
8115 fprintf (output_file, "\n default:\n return -1;\n }\n");
8116 fprintf (output_file, "}\n\n");
8119 /* Output code
8121 if (insn != 0)
8123 insn_code = dfa_insn_code (insn);
8124 if (insn_code > DFA__ADVANCE_CYCLE)
8125 return code;
8127 else
8128 insn_code = DFA__ADVANCE_CYCLE;
8130 where insn denotes INSN_NAME, insn_code denotes INSN_CODE_NAME, and
8131 code denotes CODE. */
8132 static void
8133 output_internal_insn_code_evaluation (const char *insn_name,
8134 const char *insn_code_name,
8135 int code)
8137 fprintf (output_file, "\n if (%s == 0)\n", insn_name);
8138 fprintf (output_file, " %s = %s;\n\n",
8139 insn_code_name, ADVANCE_CYCLE_VALUE_NAME);
8140 if (collapse_flag)
8142 fprintf (output_file, "\n else if (%s == const0_rtx)\n", insn_name);
8143 fprintf (output_file, " %s = %s;\n\n",
8144 insn_code_name, COLLAPSE_NDFA_VALUE_NAME);
8146 fprintf (output_file, "\n else\n {\n");
8147 fprintf (output_file, " %s = %s (%s);\n", insn_code_name,
8148 DFA_INSN_CODE_FUNC_NAME, insn_name);
8149 fprintf (output_file, " if (%s > %s)\n return %d;\n }\n",
8150 insn_code_name, ADVANCE_CYCLE_VALUE_NAME, code);
8154 /* This function outputs `dfa_insn_code' and its helper function
8155 `dfa_insn_code_enlarge'. */
8156 static void
8157 output_dfa_insn_code_func (void)
8159 /* Emacs c-mode gets really confused if there's a { or } in column 0
8160 inside a string, so don't do that. */
8161 fprintf (output_file, "\
8162 static void\n\
8163 dfa_insn_code_enlarge (int uid)\n\
8164 {\n\
8165 int i = %s;\n\
8166 %s = 2 * uid;\n\
8167 %s = XRESIZEVEC (int, %s,\n\
8168 %s);\n\
8169 for (; i < %s; i++)\n\
8170 %s[i] = -1;\n}\n\n",
8171 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8172 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8173 DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
8174 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8175 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8176 DFA_INSN_CODES_VARIABLE_NAME);
8177 fprintf (output_file, "\
8178 static inline int\n%s (rtx %s)\n\
8179 {\n\
8180 int uid = INSN_UID (%s);\n\
8181 int %s;\n\n",
8182 DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME,
8183 INSN_PARAMETER_NAME, INTERNAL_INSN_CODE_NAME);
8185 fprintf (output_file,
8186 " if (uid >= %s)\n dfa_insn_code_enlarge (uid);\n\n",
8187 DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8188 fprintf (output_file, " %s = %s[uid];\n",
8189 INTERNAL_INSN_CODE_NAME, DFA_INSN_CODES_VARIABLE_NAME);
8190 fprintf (output_file, "\
8191 if (%s < 0)\n\
8192 {\n\
8193 %s = %s (%s);\n\
8194 %s[uid] = %s;\n\
8195 }\n",
8196 INTERNAL_INSN_CODE_NAME,
8197 INTERNAL_INSN_CODE_NAME,
8198 INTERNAL_DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME,
8199 DFA_INSN_CODES_VARIABLE_NAME, INTERNAL_INSN_CODE_NAME);
8200 fprintf (output_file, " return %s;\n}\n\n", INTERNAL_INSN_CODE_NAME);
8203 /* The function outputs PHR interface function `state_transition'. */
8204 static void
8205 output_trans_func (void)
8207 fprintf (output_file, "int\n%s (%s %s, rtx %s)\n",
8208 TRANSITION_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME,
8209 INSN_PARAMETER_NAME);
8210 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
8211 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8212 INTERNAL_INSN_CODE_NAME, -1);
8213 fprintf (output_file, " return %s (%s, (struct %s *) %s);\n}\n\n",
8214 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME, STATE_NAME);
8217 /* Output function `min_issue_delay'. */
8218 static void
8219 output_min_issue_delay_func (void)
8221 fprintf (output_file, "int\n%s (%s %s, rtx %s)\n",
8222 MIN_ISSUE_DELAY_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME,
8223 INSN_PARAMETER_NAME);
8224 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
8225 fprintf (output_file, "\n if (%s != 0)\n {\n", INSN_PARAMETER_NAME);
8226 fprintf (output_file, " %s = %s (%s);\n", INTERNAL_INSN_CODE_NAME,
8227 DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME);
8228 fprintf (output_file, " if (%s > %s)\n return 0;\n",
8229 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8230 fprintf (output_file, " }\n else\n %s = %s;\n",
8231 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8232 fprintf (output_file, "\n return %s (%s, (struct %s *) %s);\n",
8233 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8234 CHIP_NAME, STATE_NAME);
8235 fprintf (output_file, "}\n\n");
8238 /* Output function `internal_dead_lock'. */
8239 static void
8240 output_internal_dead_lock_func (void)
8242 automaton_t automaton;
8244 fprintf (output_file, "static int\n%s (struct %s *ARG_UNUSED (%s))\n",
8245 INTERNAL_DEAD_LOCK_FUNC_NAME, CHIP_NAME, CHIP_PARAMETER_NAME);
8246 fprintf (output_file, "{\n");
8247 for (automaton = description->first_automaton;
8248 automaton != NULL;
8249 automaton = automaton->next_automaton)
8250 if (automaton->locked_states)
8252 fprintf (output_file, " if (");
8253 output_dead_lock_vect_name (output_file, automaton);
8254 fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
8255 output_chip_member_name (output_file, automaton);
8256 fprintf (output_file, "])\n return 1/* TRUE */;\n");
8258 fprintf (output_file, " return 0/* FALSE */;\n}\n\n");
8261 /* The function outputs PHR interface function `state_dead_lock_p'. */
8262 static void
8263 output_dead_lock_func (void)
8265 fprintf (output_file, "int\n%s (%s %s)\n",
8266 DEAD_LOCK_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME);
8267 fprintf (output_file, "{\n return %s ((struct %s *) %s);\n}\n\n",
8268 INTERNAL_DEAD_LOCK_FUNC_NAME, CHIP_NAME, STATE_NAME);
8271 /* Output function `internal_reset'. */
8272 static void
8273 output_internal_reset_func (void)
8275 fprintf (output_file, "static inline void\n%s (struct %s *%s)\n",
8276 INTERNAL_RESET_FUNC_NAME, CHIP_NAME, CHIP_PARAMETER_NAME);
8277 fprintf (output_file, "{\n memset (%s, 0, sizeof (struct %s));\n}\n\n",
8278 CHIP_PARAMETER_NAME, CHIP_NAME);
8281 /* The function outputs PHR interface function `state_size'. */
8282 static void
8283 output_size_func (void)
8285 fprintf (output_file, "int\n%s (void)\n", SIZE_FUNC_NAME);
8286 fprintf (output_file, "{\n return sizeof (struct %s);\n}\n\n", CHIP_NAME);
8289 /* The function outputs PHR interface function `state_reset'. */
8290 static void
8291 output_reset_func (void)
8293 fprintf (output_file, "void\n%s (%s %s)\n",
8294 RESET_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME);
8295 fprintf (output_file, "{\n %s ((struct %s *) %s);\n}\n\n", INTERNAL_RESET_FUNC_NAME,
8296 CHIP_NAME, STATE_NAME);
8299 /* Output function `min_insn_conflict_delay'. */
8300 static void
8301 output_min_insn_conflict_delay_func (void)
8303 fprintf (output_file,
8304 "int\n%s (%s %s, rtx %s, rtx %s)\n",
8305 MIN_INSN_CONFLICT_DELAY_FUNC_NAME, STATE_TYPE_NAME,
8306 STATE_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8307 fprintf (output_file, "{\n struct %s %s;\n int %s, %s, transition;\n",
8308 CHIP_NAME, CHIP_NAME, INTERNAL_INSN_CODE_NAME,
8309 INTERNAL_INSN2_CODE_NAME);
8310 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8311 INTERNAL_INSN_CODE_NAME, 0);
8312 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
8313 INTERNAL_INSN2_CODE_NAME, 0);
8314 fprintf (output_file, " memcpy (&%s, %s, sizeof (%s));\n",
8315 CHIP_NAME, STATE_NAME, CHIP_NAME);
8316 fprintf (output_file, " %s (&%s);\n", INTERNAL_RESET_FUNC_NAME, CHIP_NAME);
8317 fprintf (output_file, " transition = %s (%s, &%s);\n",
8318 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME);
8319 fprintf (output_file, " gcc_assert (transition <= 0);\n");
8320 fprintf (output_file, " return %s (%s, &%s);\n",
8321 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN2_CODE_NAME,
8322 CHIP_NAME);
8323 fprintf (output_file, "}\n\n");
8326 /* Output the array holding default latency values. These are used in
8327 insn_latency and maximal_insn_latency function implementations. */
8328 static void
8329 output_default_latencies (void)
8331 int i, j, col;
8332 decl_t decl;
8333 const char *tabletype = "unsigned char";
8335 /* Find the smallest integer type that can hold all the default
8336 latency values. */
8337 for (i = 0; i < description->decls_num; i++)
8338 if (description->decls[i]->mode == dm_insn_reserv)
8340 decl = description->decls[i];
8341 if (DECL_INSN_RESERV (decl)->default_latency > UCHAR_MAX
8342 && tabletype[0] != 'i') /* Don't shrink it. */
8343 tabletype = "unsigned short";
8344 if (DECL_INSN_RESERV (decl)->default_latency > USHRT_MAX)
8345 tabletype = "int";
8348 fprintf (output_file, " static const %s default_latencies[] =\n {",
8349 tabletype);
8351 for (i = 0, j = 0, col = 7; i < description->normal_decls_num; i++)
8352 if (description->decls[i]->mode == dm_insn_reserv)
8354 if ((col = (col+1) % 8) == 0)
8355 fputs ("\n ", output_file);
8356 decl = description->decls[i];
8357 gcc_assert (j++ == DECL_INSN_RESERV (decl)->insn_num);
8358 fprintf (output_file, "% 4d,",
8359 DECL_INSN_RESERV (decl)->default_latency);
8361 gcc_assert (j == description->insns_num - (collapse_flag ? 2 : 1));
8362 fputs ("\n };\n", output_file);
8365 /* Output function `internal_insn_latency'. */
8366 static void
8367 output_internal_insn_latency_func (void)
8369 int i;
8370 decl_t decl;
8371 struct bypass_decl *bypass;
8373 fprintf (output_file, "static int\n%s (int %s ATTRIBUTE_UNUSED,\n\tint %s ATTRIBUTE_UNUSED,\n\trtx %s ATTRIBUTE_UNUSED,\n\trtx %s ATTRIBUTE_UNUSED)\n",
8374 INTERNAL_INSN_LATENCY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8375 INTERNAL_INSN2_CODE_NAME, INSN_PARAMETER_NAME,
8376 INSN2_PARAMETER_NAME);
8377 fprintf (output_file, "{\n");
8379 if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8381 fputs (" return 0;\n}\n\n", output_file);
8382 return;
8385 fprintf (output_file, " if (%s >= %s || %s >= %s)\n return 0;\n",
8386 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8387 INTERNAL_INSN2_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8389 fprintf (output_file, " switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8390 for (i = 0; i < description->decls_num; i++)
8391 if (description->decls[i]->mode == dm_insn_reserv
8392 && DECL_INSN_RESERV (description->decls[i])->bypass_list)
8394 decl = description->decls [i];
8395 fprintf (output_file,
8396 " case %d:\n switch (%s)\n {\n",
8397 DECL_INSN_RESERV (decl)->insn_num,
8398 INTERNAL_INSN2_CODE_NAME);
8399 for (bypass = DECL_INSN_RESERV (decl)->bypass_list;
8400 bypass != NULL;
8401 bypass = bypass->next)
8403 gcc_assert (bypass->in_insn_reserv->insn_num
8404 != (DECL_INSN_RESERV
8405 (advance_cycle_insn_decl)->insn_num));
8406 fprintf (output_file, " case %d:\n",
8407 bypass->in_insn_reserv->insn_num);
8408 for (;;)
8410 if (bypass->bypass_guard_name == NULL)
8412 gcc_assert (bypass->next == NULL
8413 || (bypass->in_insn_reserv
8414 != bypass->next->in_insn_reserv));
8415 fprintf (output_file, " return %d;\n",
8416 bypass->latency);
8418 else
8420 fprintf (output_file,
8421 " if (%s (%s, %s))\n",
8422 bypass->bypass_guard_name, INSN_PARAMETER_NAME,
8423 INSN2_PARAMETER_NAME);
8424 fprintf (output_file, " return %d;\n",
8425 bypass->latency);
8427 if (bypass->next == NULL
8428 || bypass->in_insn_reserv != bypass->next->in_insn_reserv)
8429 break;
8430 bypass = bypass->next;
8432 if (bypass->bypass_guard_name != NULL)
8433 fprintf (output_file, " break;\n");
8435 fputs (" }\n break;\n", output_file);
8438 fprintf (output_file, " }\n return default_latencies[%s];\n}\n\n",
8439 INTERNAL_INSN_CODE_NAME);
8442 /* Output function `internal_maximum_insn_latency'. */
8443 static void
8444 output_internal_maximal_insn_latency_func (void)
8446 decl_t decl;
8447 struct bypass_decl *bypass;
8448 int i;
8449 int max;
8451 fprintf (output_file, "static int\n%s (int %s ATTRIBUTE_UNUSED,\n\trtx %s ATTRIBUTE_UNUSED)\n",
8452 "internal_maximal_insn_latency", INTERNAL_INSN_CODE_NAME,
8453 INSN_PARAMETER_NAME);
8454 fprintf (output_file, "{\n");
8456 if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8458 fputs (" return 0;\n}\n\n", output_file);
8459 return;
8462 fprintf (output_file, " switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8463 for (i = 0; i < description->decls_num; i++)
8464 if (description->decls[i]->mode == dm_insn_reserv
8465 && DECL_INSN_RESERV (description->decls[i])->bypass_list)
8467 decl = description->decls [i];
8468 max = DECL_INSN_RESERV (decl)->default_latency;
8469 fprintf (output_file,
8470 " case %d: {",
8471 DECL_INSN_RESERV (decl)->insn_num);
8472 for (bypass = DECL_INSN_RESERV (decl)->bypass_list;
8473 bypass != NULL;
8474 bypass = bypass->next)
8476 if (bypass->latency > max)
8477 max = bypass->latency;
8479 fprintf (output_file, " return %d; }\n break;\n", max);
8482 fprintf (output_file, " }\n return default_latencies[%s];\n}\n\n",
8483 INTERNAL_INSN_CODE_NAME);
8486 /* The function outputs PHR interface function `insn_latency'. */
8487 static void
8488 output_insn_latency_func (void)
8490 fprintf (output_file, "int\n%s (rtx %s, rtx %s)\n",
8491 INSN_LATENCY_FUNC_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8492 fprintf (output_file, "{\n int %s, %s;\n",
8493 INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME);
8494 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8495 INTERNAL_INSN_CODE_NAME, 0);
8496 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
8497 INTERNAL_INSN2_CODE_NAME, 0);
8498 fprintf (output_file, " return %s (%s, %s, %s, %s);\n}\n\n",
8499 INTERNAL_INSN_LATENCY_FUNC_NAME,
8500 INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME,
8501 INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8504 /* The function outputs PHR interface function `maximal_insn_latency'. */
8505 static void
8506 output_maximal_insn_latency_func (void)
8508 fprintf (output_file, "int\n%s (rtx %s)\n",
8509 "maximal_insn_latency", INSN_PARAMETER_NAME);
8510 fprintf (output_file, "{\n int %s;\n",
8511 INTERNAL_INSN_CODE_NAME);
8512 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8513 INTERNAL_INSN_CODE_NAME, 0);
8514 fprintf (output_file, " return %s (%s, %s);\n}\n\n",
8515 "internal_maximal_insn_latency",
8516 INTERNAL_INSN_CODE_NAME, INSN_PARAMETER_NAME);
8519 /* The function outputs PHR interface function `print_reservation'. */
8520 static void
8521 output_print_reservation_func (void)
8523 decl_t decl;
8524 int i, j;
8526 fprintf (output_file,
8527 "void\n%s (FILE *%s, rtx %s ATTRIBUTE_UNUSED)\n{\n",
8528 PRINT_RESERVATION_FUNC_NAME, FILE_PARAMETER_NAME,
8529 INSN_PARAMETER_NAME);
8531 if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8533 fprintf (output_file, " fputs (\"%s\", %s);\n}\n\n",
8534 NOTHING_NAME, FILE_PARAMETER_NAME);
8535 return;
8539 fputs (" static const char *const reservation_names[] =\n {",
8540 output_file);
8542 for (i = 0, j = 0; i < description->normal_decls_num; i++)
8544 decl = description->decls [i];
8545 if (decl->mode == dm_insn_reserv)
8547 gcc_assert (j == DECL_INSN_RESERV (decl)->insn_num);
8548 j++;
8550 fprintf (output_file, "\n \"%s\",",
8551 regexp_representation (DECL_INSN_RESERV (decl)->regexp));
8552 finish_regexp_representation ();
8555 gcc_assert (j == description->insns_num - (collapse_flag ? 2 : 1));
8557 fprintf (output_file, "\n \"%s\"\n };\n int %s;\n\n",
8558 NOTHING_NAME, INTERNAL_INSN_CODE_NAME);
8560 fprintf (output_file, " if (%s == 0)\n %s = %s;\n",
8561 INSN_PARAMETER_NAME,
8562 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8563 fprintf (output_file, " else\n\
8564 {\n\
8565 %s = %s (%s);\n\
8566 if (%s > %s)\n\
8567 %s = %s;\n\
8568 }\n",
8569 INTERNAL_INSN_CODE_NAME, DFA_INSN_CODE_FUNC_NAME,
8570 INSN_PARAMETER_NAME,
8571 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8572 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8574 fprintf (output_file, " fputs (reservation_names[%s], %s);\n}\n\n",
8575 INTERNAL_INSN_CODE_NAME, FILE_PARAMETER_NAME);
8578 /* The following function is used to sort unit declaration by their
8579 names. */
8580 static int
8581 units_cmp (const void *unit1, const void *unit2)
8583 const_unit_decl_t const u1 = *(const_unit_decl_t const*) unit1;
8584 const_unit_decl_t const u2 = *(const_unit_decl_t const*) unit2;
8586 return strcmp (u1->name, u2->name);
8589 /* The following macro value is name of struct containing unit name
8590 and unit code. */
8591 #define NAME_CODE_STRUCT_NAME "name_code"
8593 /* The following macro value is name of table of struct name_code. */
8594 #define NAME_CODE_TABLE_NAME "name_code_table"
8596 /* The following macro values are member names for struct name_code. */
8597 #define NAME_MEMBER_NAME "name"
8598 #define CODE_MEMBER_NAME "code"
8600 /* The following macro values are local variable names for function
8601 `get_cpu_unit_code'. */
8602 #define CMP_VARIABLE_NAME "cmp"
8603 #define LOW_VARIABLE_NAME "l"
8604 #define MIDDLE_VARIABLE_NAME "m"
8605 #define HIGH_VARIABLE_NAME "h"
8607 /* The following function outputs function to obtain internal cpu unit
8608 code by the cpu unit name. */
8609 static void
8610 output_get_cpu_unit_code_func (void)
8612 int i;
8613 unit_decl_t *units;
8615 fprintf (output_file, "int\n%s (const char *%s)\n",
8616 GET_CPU_UNIT_CODE_FUNC_NAME, CPU_UNIT_NAME_PARAMETER_NAME);
8617 fprintf (output_file, "{\n struct %s {const char *%s; int %s;};\n",
8618 NAME_CODE_STRUCT_NAME, NAME_MEMBER_NAME, CODE_MEMBER_NAME);
8619 fprintf (output_file, " int %s, %s, %s, %s;\n", CMP_VARIABLE_NAME,
8620 LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8621 fprintf (output_file, " static struct %s %s [] =\n {\n",
8622 NAME_CODE_STRUCT_NAME, NAME_CODE_TABLE_NAME);
8623 units = XNEWVEC (unit_decl_t, description->units_num);
8624 memcpy (units, units_array, sizeof (unit_decl_t) * description->units_num);
8625 qsort (units, description->units_num, sizeof (unit_decl_t), units_cmp);
8626 for (i = 0; i < description->units_num; i++)
8627 if (units [i]->query_p)
8628 fprintf (output_file, " {\"%s\", %d},\n",
8629 units[i]->name, units[i]->query_num);
8630 fprintf (output_file, " };\n\n");
8631 fprintf (output_file, " /* The following is binary search: */\n");
8632 fprintf (output_file, " %s = 0;\n", LOW_VARIABLE_NAME);
8633 fprintf (output_file, " %s = sizeof (%s) / sizeof (struct %s) - 1;\n",
8634 HIGH_VARIABLE_NAME, NAME_CODE_TABLE_NAME, NAME_CODE_STRUCT_NAME);
8635 fprintf (output_file, " while (%s <= %s)\n {\n",
8636 LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8637 fprintf (output_file, " %s = (%s + %s) / 2;\n",
8638 MIDDLE_VARIABLE_NAME, LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8639 fprintf (output_file, " %s = strcmp (%s, %s [%s].%s);\n",
8640 CMP_VARIABLE_NAME, CPU_UNIT_NAME_PARAMETER_NAME,
8641 NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, NAME_MEMBER_NAME);
8642 fprintf (output_file, " if (%s < 0)\n", CMP_VARIABLE_NAME);
8643 fprintf (output_file, " %s = %s - 1;\n",
8644 HIGH_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
8645 fprintf (output_file, " else if (%s > 0)\n", CMP_VARIABLE_NAME);
8646 fprintf (output_file, " %s = %s + 1;\n",
8647 LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
8648 fprintf (output_file, " else\n");
8649 fprintf (output_file, " return %s [%s].%s;\n }\n",
8650 NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, CODE_MEMBER_NAME);
8651 fprintf (output_file, " return -1;\n}\n\n");
8652 free (units);
8655 /* The following function outputs function to check reservation of cpu
8656 unit (its internal code will be passed as the function argument) in
8657 given cpu state. */
8658 static void
8659 output_cpu_unit_reservation_p (void)
8661 automaton_t automaton;
8663 fprintf (output_file, "int\n%s (%s %s, int %s)\n",
8664 CPU_UNIT_RESERVATION_P_FUNC_NAME,
8665 STATE_TYPE_NAME, STATE_NAME,
8666 CPU_CODE_PARAMETER_NAME);
8667 fprintf (output_file, "{\n gcc_assert (%s >= 0 && %s < %d);\n",
8668 CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME,
8669 description->query_units_num);
8670 if (description->query_units_num > 0)
8671 for (automaton = description->first_automaton;
8672 automaton != NULL;
8673 automaton = automaton->next_automaton)
8675 fprintf (output_file, " if ((");
8676 output_reserved_units_table_name (output_file, automaton);
8677 fprintf (output_file, " [((struct %s *) %s)->", CHIP_NAME, STATE_NAME);
8678 output_chip_member_name (output_file, automaton);
8679 fprintf (output_file, " * %d + %s / 8] >> (%s %% 8)) & 1)\n",
8680 (description->query_units_num + 7) / 8,
8681 CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME);
8682 fprintf (output_file, " return 1;\n");
8684 fprintf (output_file, " return 0;\n}\n\n");
8687 /* The following function outputs a function to check if insn
8688 has a dfa reservation. */
8689 static void
8690 output_insn_has_dfa_reservation_p (void)
8692 fprintf (output_file,
8693 "bool\n%s (rtx %s ATTRIBUTE_UNUSED)\n{\n",
8694 INSN_HAS_DFA_RESERVATION_P_FUNC_NAME,
8695 INSN_PARAMETER_NAME);
8697 if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8699 fprintf (output_file, " return false;\n}\n\n");
8700 return;
8703 fprintf (output_file, " int %s;\n\n", INTERNAL_INSN_CODE_NAME);
8705 fprintf (output_file, " if (%s == 0)\n %s = %s;\n",
8706 INSN_PARAMETER_NAME,
8707 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8708 fprintf (output_file, " else\n\
8709 {\n\
8710 %s = %s (%s);\n\
8711 if (%s > %s)\n\
8712 %s = %s;\n\
8713 }\n\n",
8714 INTERNAL_INSN_CODE_NAME, DFA_INSN_CODE_FUNC_NAME,
8715 INSN_PARAMETER_NAME,
8716 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8717 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8719 fprintf (output_file, " return %s != %s;\n}\n\n",
8720 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8723 /* The function outputs PHR interface functions `dfa_clean_insn_cache'
8724 and 'dfa_clear_single_insn_cache'. */
8725 static void
8726 output_dfa_clean_insn_cache_func (void)
8728 fprintf (output_file,
8729 "void\n%s (void)\n{\n int %s;\n\n",
8730 DFA_CLEAN_INSN_CACHE_FUNC_NAME, I_VARIABLE_NAME);
8731 fprintf (output_file,
8732 " for (%s = 0; %s < %s; %s++)\n %s [%s] = -1;\n}\n\n",
8733 I_VARIABLE_NAME, I_VARIABLE_NAME,
8734 DFA_INSN_CODES_LENGTH_VARIABLE_NAME, I_VARIABLE_NAME,
8735 DFA_INSN_CODES_VARIABLE_NAME, I_VARIABLE_NAME);
8737 fprintf (output_file,
8738 "void\n%s (rtx %s)\n{\n int %s;\n\n",
8739 DFA_CLEAR_SINGLE_INSN_CACHE_FUNC_NAME, INSN_PARAMETER_NAME,
8740 I_VARIABLE_NAME);
8741 fprintf (output_file,
8742 " %s = INSN_UID (%s);\n if (%s < %s)\n %s [%s] = -1;\n}\n\n",
8743 I_VARIABLE_NAME, INSN_PARAMETER_NAME, I_VARIABLE_NAME,
8744 DFA_INSN_CODES_LENGTH_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
8745 I_VARIABLE_NAME);
8748 /* The function outputs PHR interface function `dfa_start'. */
8749 static void
8750 output_dfa_start_func (void)
8752 fprintf (output_file,
8753 "void\n%s (void)\n{\n %s = get_max_uid ();\n",
8754 DFA_START_FUNC_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8755 fprintf (output_file, " %s = XNEWVEC (int, %s);\n",
8756 DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8757 fprintf (output_file, " %s ();\n}\n\n", DFA_CLEAN_INSN_CACHE_FUNC_NAME);
8760 /* The function outputs PHR interface function `dfa_finish'. */
8761 static void
8762 output_dfa_finish_func (void)
8764 fprintf (output_file, "void\n%s (void)\n{\n free (%s);\n}\n\n",
8765 DFA_FINISH_FUNC_NAME, DFA_INSN_CODES_VARIABLE_NAME);
8770 /* The page contains code for output description file (readable
8771 representation of original description and generated DFA(s). */
8773 /* The function outputs string representation of IR reservation. */
8774 static void
8775 output_regexp (regexp_t regexp)
8777 fprintf (output_description_file, "%s", regexp_representation (regexp));
8778 finish_regexp_representation ();
8781 /* Output names of units in LIST separated by comma. */
8782 static void
8783 output_unit_set_el_list (unit_set_el_t list)
8785 unit_set_el_t el;
8787 for (el = list; el != NULL; el = el->next_unit_set_el)
8789 if (el != list)
8790 fprintf (output_description_file, ", ");
8791 fprintf (output_description_file, "%s", el->unit_decl->name);
8795 /* Output patterns in LIST separated by comma. */
8796 static void
8797 output_pattern_set_el_list (pattern_set_el_t list)
8799 pattern_set_el_t el;
8800 int i;
8802 for (el = list; el != NULL; el = el->next_pattern_set_el)
8804 if (el != list)
8805 fprintf (output_description_file, ", ");
8806 for (i = 0; i < el->units_num; i++)
8807 fprintf (output_description_file, (i == 0 ? "%s" : " %s"),
8808 el->unit_decls [i]->name);
8812 /* The function outputs string representation of IR define_reservation
8813 and define_insn_reservation. */
8814 static void
8815 output_description (void)
8817 decl_t decl;
8818 int i;
8820 for (i = 0; i < description->decls_num; i++)
8822 decl = description->decls [i];
8823 if (decl->mode == dm_unit)
8825 if (DECL_UNIT (decl)->excl_list != NULL)
8827 fprintf (output_description_file, "unit %s exclusion_set: ",
8828 DECL_UNIT (decl)->name);
8829 output_unit_set_el_list (DECL_UNIT (decl)->excl_list);
8830 fprintf (output_description_file, "\n");
8832 if (DECL_UNIT (decl)->presence_list != NULL)
8834 fprintf (output_description_file, "unit %s presence_set: ",
8835 DECL_UNIT (decl)->name);
8836 output_pattern_set_el_list (DECL_UNIT (decl)->presence_list);
8837 fprintf (output_description_file, "\n");
8839 if (DECL_UNIT (decl)->final_presence_list != NULL)
8841 fprintf (output_description_file, "unit %s final_presence_set: ",
8842 DECL_UNIT (decl)->name);
8843 output_pattern_set_el_list
8844 (DECL_UNIT (decl)->final_presence_list);
8845 fprintf (output_description_file, "\n");
8847 if (DECL_UNIT (decl)->absence_list != NULL)
8849 fprintf (output_description_file, "unit %s absence_set: ",
8850 DECL_UNIT (decl)->name);
8851 output_pattern_set_el_list (DECL_UNIT (decl)->absence_list);
8852 fprintf (output_description_file, "\n");
8854 if (DECL_UNIT (decl)->final_absence_list != NULL)
8856 fprintf (output_description_file, "unit %s final_absence_set: ",
8857 DECL_UNIT (decl)->name);
8858 output_pattern_set_el_list
8859 (DECL_UNIT (decl)->final_absence_list);
8860 fprintf (output_description_file, "\n");
8864 fprintf (output_description_file, "\n");
8865 for (i = 0; i < description->normal_decls_num; i++)
8867 decl = description->decls [i];
8868 if (decl->mode == dm_reserv)
8870 fprintf (output_description_file, "reservation %s: ",
8871 DECL_RESERV (decl)->name);
8872 output_regexp (DECL_RESERV (decl)->regexp);
8873 fprintf (output_description_file, "\n");
8875 else if (decl->mode == dm_insn_reserv)
8877 fprintf (output_description_file, "insn reservation %s ",
8878 DECL_INSN_RESERV (decl)->name);
8879 print_rtl (output_description_file,
8880 DECL_INSN_RESERV (decl)->condexp);
8881 fprintf (output_description_file, ": ");
8882 output_regexp (DECL_INSN_RESERV (decl)->regexp);
8883 fprintf (output_description_file, "\n");
8885 else if (decl->mode == dm_bypass)
8886 fprintf (output_description_file, "bypass %d %s %s\n",
8887 DECL_BYPASS (decl)->latency,
8888 DECL_BYPASS (decl)->out_pattern,
8889 DECL_BYPASS (decl)->in_pattern);
8891 fprintf (output_description_file, "\n\f\n");
8894 /* The function outputs name of AUTOMATON. */
8895 static void
8896 output_automaton_name (FILE *f, automaton_t automaton)
8898 if (automaton->corresponding_automaton_decl == NULL)
8899 fprintf (f, "#%d", automaton->automaton_order_num);
8900 else
8901 fprintf (f, "`%s'", automaton->corresponding_automaton_decl->name);
8904 /* Maximal length of line for pretty printing into description
8905 file. */
8906 #define MAX_LINE_LENGTH 70
8908 /* The function outputs units name belonging to AUTOMATON. */
8909 static void
8910 output_automaton_units (automaton_t automaton)
8912 decl_t decl;
8913 const char *name;
8914 int curr_line_length;
8915 int there_is_an_automaton_unit;
8916 int i;
8918 fprintf (output_description_file, "\n Corresponding units:\n");
8919 fprintf (output_description_file, " ");
8920 curr_line_length = 4;
8921 there_is_an_automaton_unit = 0;
8922 for (i = 0; i < description->decls_num; i++)
8924 decl = description->decls [i];
8925 if (decl->mode == dm_unit
8926 && (DECL_UNIT (decl)->corresponding_automaton_num
8927 == automaton->automaton_order_num))
8929 there_is_an_automaton_unit = 1;
8930 name = DECL_UNIT (decl)->name;
8931 if (curr_line_length + strlen (name) + 1 > MAX_LINE_LENGTH )
8933 curr_line_length = strlen (name) + 4;
8934 fprintf (output_description_file, "\n ");
8936 else
8938 curr_line_length += strlen (name) + 1;
8939 fprintf (output_description_file, " ");
8941 fprintf (output_description_file, "%s", name);
8944 if (!there_is_an_automaton_unit)
8945 fprintf (output_description_file, "<None>");
8946 fprintf (output_description_file, "\n\n");
8949 /* The following variable is used for forming array of all possible cpu unit
8950 reservations described by the current DFA state. */
8951 static vec<reserv_sets_t> state_reservs;
8953 /* The function forms `state_reservs' for STATE. */
8954 static void
8955 add_state_reservs (state_t state)
8957 alt_state_t curr_alt_state;
8959 if (state->component_states != NULL)
8960 for (curr_alt_state = state->component_states;
8961 curr_alt_state != NULL;
8962 curr_alt_state = curr_alt_state->next_sorted_alt_state)
8963 add_state_reservs (curr_alt_state->state);
8964 else
8965 state_reservs.safe_push (state->reservs);
8968 /* The function outputs readable representation of all out arcs of
8969 STATE. */
8970 static void
8971 output_state_arcs (state_t state)
8973 arc_t arc;
8974 ainsn_t ainsn;
8975 const char *insn_name;
8976 int curr_line_length;
8978 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
8980 ainsn = arc->insn;
8981 gcc_assert (ainsn->first_insn_with_same_reservs);
8982 fprintf (output_description_file, " ");
8983 curr_line_length = 7;
8984 fprintf (output_description_file, "%2d: ", ainsn->insn_equiv_class_num);
8987 insn_name = ainsn->insn_reserv_decl->name;
8988 if (curr_line_length + strlen (insn_name) > MAX_LINE_LENGTH)
8990 if (ainsn != arc->insn)
8992 fprintf (output_description_file, ",\n ");
8993 curr_line_length = strlen (insn_name) + 6;
8995 else
8996 curr_line_length += strlen (insn_name);
8998 else
9000 curr_line_length += strlen (insn_name);
9001 if (ainsn != arc->insn)
9003 curr_line_length += 2;
9004 fprintf (output_description_file, ", ");
9007 fprintf (output_description_file, "%s", insn_name);
9008 ainsn = ainsn->next_same_reservs_insn;
9010 while (ainsn != NULL);
9011 fprintf (output_description_file, " %d \n",
9012 arc->to_state->order_state_num);
9014 fprintf (output_description_file, "\n");
9017 /* The following function is used for sorting possible cpu unit
9018 reservation of a DFA state. */
9019 static int
9020 state_reservs_cmp (const void *reservs_ptr_1, const void *reservs_ptr_2)
9022 return reserv_sets_cmp (*(const_reserv_sets_t const*) reservs_ptr_1,
9023 *(const_reserv_sets_t const*) reservs_ptr_2);
9026 /* The following function is used for sorting possible cpu unit
9027 reservation of a DFA state. */
9028 static void
9029 remove_state_duplicate_reservs (void)
9031 size_t i, j;
9033 for (i = 1, j = 0; i < state_reservs.length (); i++)
9034 if (reserv_sets_cmp (state_reservs[j], state_reservs[i]))
9036 j++;
9037 state_reservs[j] = state_reservs[i];
9039 state_reservs.truncate (j + 1);
9042 /* The following function output readable representation of DFA(s)
9043 state used for fast recognition of pipeline hazards. State is
9044 described by possible (current and scheduled) cpu unit
9045 reservations. */
9046 static void
9047 output_state (state_t state)
9049 size_t i;
9051 state_reservs.create (0);
9053 fprintf (output_description_file, " State #%d", state->order_state_num);
9054 fprintf (output_description_file,
9055 state->new_cycle_p ? " (new cycle)\n" : "\n");
9056 add_state_reservs (state);
9057 state_reservs.qsort (state_reservs_cmp);
9058 remove_state_duplicate_reservs ();
9059 for (i = 0; i < state_reservs.length (); i++)
9061 fprintf (output_description_file, " ");
9062 output_reserv_sets (output_description_file, state_reservs[i]);
9063 fprintf (output_description_file, "\n");
9065 fprintf (output_description_file, "\n");
9066 output_state_arcs (state);
9067 state_reservs.release ();
9070 /* The following function output readable representation of
9071 DFAs used for fast recognition of pipeline hazards. */
9072 static void
9073 output_automaton_descriptions (void)
9075 automaton_t automaton;
9077 for (automaton = description->first_automaton;
9078 automaton != NULL;
9079 automaton = automaton->next_automaton)
9081 fprintf (output_description_file, "\nAutomaton ");
9082 output_automaton_name (output_description_file, automaton);
9083 fprintf (output_description_file, "\n");
9084 output_automaton_units (automaton);
9085 pass_states (automaton, output_state);
9091 /* The page contains top level function for generation DFA(s) used for
9092 PHR. */
9094 /* The function outputs statistics about work of different phases of
9095 DFA generator. */
9096 static void
9097 output_statistics (FILE *f)
9099 automaton_t automaton;
9100 int states_num;
9101 #ifndef NDEBUG
9102 int transition_comb_vect_els = 0;
9103 int transition_full_vect_els = 0;
9104 int min_issue_delay_vect_els = 0;
9105 int locked_states = 0;
9106 #endif
9108 for (automaton = description->first_automaton;
9109 automaton != NULL;
9110 automaton = automaton->next_automaton)
9112 fprintf (f, "\nAutomaton ");
9113 output_automaton_name (f, automaton);
9114 fprintf (f, "\n %5d NDFA states, %5d NDFA arcs\n",
9115 automaton->NDFA_states_num, automaton->NDFA_arcs_num);
9116 fprintf (f, " %5d DFA states, %5d DFA arcs\n",
9117 automaton->DFA_states_num, automaton->DFA_arcs_num);
9118 states_num = automaton->DFA_states_num;
9119 if (!no_minimization_flag)
9121 fprintf (f, " %5d minimal DFA states, %5d minimal DFA arcs\n",
9122 automaton->minimal_DFA_states_num,
9123 automaton->minimal_DFA_arcs_num);
9124 states_num = automaton->minimal_DFA_states_num;
9126 fprintf (f, " %5d all insns %5d insn equivalence classes\n",
9127 description->insns_num, automaton->insn_equiv_classes_num);
9128 fprintf (f, " %d locked states\n", automaton->locked_states);
9129 #ifndef NDEBUG
9130 fprintf
9131 (f, "%5ld transition comb vector els, %5ld trans table els: %s\n",
9132 (long) automaton->trans_table->comb_vect.length (),
9133 (long) automaton->trans_table->full_vect.length (),
9134 (comb_vect_p (automaton->trans_table)
9135 ? "use comb vect" : "use simple vect"));
9136 fprintf
9137 (f, "%5ld min delay table els, compression factor %d\n",
9138 (long) states_num * automaton->insn_equiv_classes_num,
9139 automaton->min_issue_delay_table_compression_factor);
9140 transition_comb_vect_els
9141 += automaton->trans_table->comb_vect.length ();
9142 transition_full_vect_els
9143 += automaton->trans_table->full_vect.length ();
9144 min_issue_delay_vect_els
9145 += states_num * automaton->insn_equiv_classes_num;
9146 locked_states
9147 += automaton->locked_states;
9148 #endif
9150 #ifndef NDEBUG
9151 fprintf (f, "\n%5d all allocated states, %5d all allocated arcs\n",
9152 allocated_states_num, allocated_arcs_num);
9153 fprintf (f, "%5d all allocated alternative states\n",
9154 allocated_alt_states_num);
9155 fprintf (f, "%5d all transition comb vector els, %5d all trans table els\n",
9156 transition_comb_vect_els, transition_full_vect_els);
9157 fprintf (f, "%5d all min delay table els\n", min_issue_delay_vect_els);
9158 fprintf (f, "%5d all locked states\n", locked_states);
9159 #endif
9162 /* The function output times of work of different phases of DFA
9163 generator. */
9164 static void
9165 output_time_statistics (FILE *f)
9167 fprintf (f, "\n transformation: ");
9168 print_active_time (f, transform_time);
9169 fprintf (f, (!ndfa_flag ? ", building DFA: " : ", building NDFA: "));
9170 print_active_time (f, NDFA_time);
9171 if (ndfa_flag)
9173 fprintf (f, ", NDFA -> DFA: ");
9174 print_active_time (f, NDFA_to_DFA_time);
9176 fprintf (f, "\n DFA minimization: ");
9177 print_active_time (f, minimize_time);
9178 fprintf (f, ", making insn equivalence: ");
9179 print_active_time (f, equiv_time);
9180 fprintf (f, "\n all automaton generation: ");
9181 print_active_time (f, automaton_generation_time);
9182 fprintf (f, ", output: ");
9183 print_active_time (f, output_time);
9184 fprintf (f, "\n");
9187 /* The function generates DFA (deterministic finite state automaton)
9188 for fast recognition of pipeline hazards. No errors during
9189 checking must be fixed before this function call. */
9190 static void
9191 generate (void)
9193 automata_num = split_argument;
9194 if (description->units_num < automata_num)
9195 automata_num = description->units_num;
9196 initiate_states ();
9197 initiate_arcs ();
9198 initiate_automata_lists ();
9199 initiate_pass_states ();
9200 initiate_excl_sets ();
9201 initiate_presence_absence_pattern_sets ();
9202 automaton_generation_time = create_ticker ();
9203 create_automata ();
9204 ticker_off (&automaton_generation_time);
9209 /* This page mainly contains top level functions of pipeline hazards
9210 description translator. */
9212 /* The following macro value is suffix of name of description file of
9213 pipeline hazards description translator. */
9214 #define STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX ".dfa"
9216 /* The function returns suffix of given file name. The returned
9217 string can not be changed. */
9218 static const char *
9219 file_name_suffix (const char *file_name)
9221 const char *last_period;
9223 for (last_period = NULL; *file_name != '\0'; file_name++)
9224 if (*file_name == '.')
9225 last_period = file_name;
9226 return (last_period == NULL ? file_name : last_period);
9229 /* The function returns base name of given file name, i.e. pointer to
9230 first char after last `/' (or `\' for WIN32) in given file name,
9231 given file name itself if the directory name is absent. The
9232 returned string can not be changed. */
9233 static const char *
9234 base_file_name (const char *file_name)
9236 int directory_name_length;
9238 directory_name_length = strlen (file_name);
9239 #ifdef WIN32
9240 while (directory_name_length >= 0 && file_name[directory_name_length] != '/'
9241 && file_name[directory_name_length] != '\\')
9242 #else
9243 while (directory_name_length >= 0 && file_name[directory_name_length] != '/')
9244 #endif
9245 directory_name_length--;
9246 return file_name + directory_name_length + 1;
9249 /* A function passed as argument to init_rtx_reader_args_cb. It parses the
9250 options available for genautomata. Returns true if the option was
9251 recognized. */
9252 static bool
9253 parse_automata_opt (const char *str)
9255 if (strcmp (str, NO_MINIMIZATION_OPTION) == 0)
9256 no_minimization_flag = 1;
9257 else if (strcmp (str, TIME_OPTION) == 0)
9258 time_flag = 1;
9259 else if (strcmp (str, STATS_OPTION) == 0)
9260 stats_flag = 1;
9261 else if (strcmp (str, V_OPTION) == 0)
9262 v_flag = 1;
9263 else if (strcmp (str, W_OPTION) == 0)
9264 w_flag = 1;
9265 else if (strcmp (str, NDFA_OPTION) == 0)
9266 ndfa_flag = 1;
9267 else if (strcmp (str, COLLAPSE_OPTION) == 0)
9268 collapse_flag = 1;
9269 else if (strcmp (str, PROGRESS_OPTION) == 0)
9270 progress_flag = 1;
9271 else if (strcmp (str, "-split") == 0)
9273 fatal ("option `-split' has not been implemented yet\n");
9274 /* split_argument = atoi (argument_vect [i + 1]); */
9276 else
9277 return false;
9279 return true;
9282 /* The following is top level function to initialize the work of
9283 pipeline hazards description translator. */
9284 static void
9285 initiate_automaton_gen (char **argv)
9287 const char *base_name;
9289 /* Initialize IR storage. */
9290 obstack_init (&irp);
9291 initiate_automaton_decl_table ();
9292 initiate_insn_decl_table ();
9293 initiate_decl_table ();
9294 output_file = stdout;
9295 output_description_file = NULL;
9296 base_name = base_file_name (argv[1]);
9297 obstack_grow (&irp, base_name,
9298 strlen (base_name) - strlen (file_name_suffix (base_name)));
9299 obstack_grow (&irp, STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX,
9300 strlen (STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX) + 1);
9301 obstack_1grow (&irp, '\0');
9302 output_description_file_name = obstack_base (&irp);
9303 obstack_finish (&irp);
9306 /* The following function checks existence at least one arc marked by
9307 each insn. */
9308 static void
9309 check_automata_insn_issues (void)
9311 automaton_t automaton;
9312 ainsn_t ainsn, reserv_ainsn;
9314 for (automaton = description->first_automaton;
9315 automaton != NULL;
9316 automaton = automaton->next_automaton)
9318 for (ainsn = automaton->ainsn_list;
9319 ainsn != NULL;
9320 ainsn = ainsn->next_ainsn)
9321 if (ainsn->first_insn_with_same_reservs && !ainsn->arc_exists_p
9322 && ainsn != automaton->collapse_ainsn)
9324 for (reserv_ainsn = ainsn;
9325 reserv_ainsn != NULL;
9326 reserv_ainsn = reserv_ainsn->next_same_reservs_insn)
9327 if (automaton->corresponding_automaton_decl != NULL)
9329 if (!w_flag)
9330 error ("Automaton `%s': Insn `%s' will never be issued",
9331 automaton->corresponding_automaton_decl->name,
9332 reserv_ainsn->insn_reserv_decl->name);
9333 else
9334 warning ("Automaton `%s': Insn `%s' will never be issued",
9335 automaton->corresponding_automaton_decl->name,
9336 reserv_ainsn->insn_reserv_decl->name);
9338 else
9340 if (!w_flag)
9341 error ("Insn `%s' will never be issued",
9342 reserv_ainsn->insn_reserv_decl->name);
9343 else
9344 warning ("Insn `%s' will never be issued",
9345 reserv_ainsn->insn_reserv_decl->name);
9351 /* The following vla is used for storing pointers to all achieved
9352 states. */
9353 static vec<state_t> automaton_states;
9355 /* This function is called by function pass_states to add an achieved
9356 STATE. */
9357 static void
9358 add_automaton_state (state_t state)
9360 automaton_states.safe_push (state);
9363 /* The following function forms list of important automata (whose
9364 states may be changed after the insn issue) for each insn. */
9365 static void
9366 form_important_insn_automata_lists (void)
9368 automaton_t automaton;
9369 decl_t decl;
9370 ainsn_t ainsn;
9371 arc_t arc;
9372 int i;
9373 size_t n;
9375 automaton_states.create (0);
9376 /* Mark important ainsns. */
9377 for (automaton = description->first_automaton;
9378 automaton != NULL;
9379 automaton = automaton->next_automaton)
9381 automaton_states.truncate (0);
9382 pass_states (automaton, add_automaton_state);
9383 for (n = 0; n < automaton_states.length (); n++)
9385 state_t s = automaton_states[n];
9386 for (arc = first_out_arc (s);
9387 arc != NULL;
9388 arc = next_out_arc (arc))
9389 if (arc->to_state != s)
9391 gcc_assert (arc->insn->first_insn_with_same_reservs);
9392 for (ainsn = arc->insn;
9393 ainsn != NULL;
9394 ainsn = ainsn->next_same_reservs_insn)
9395 ainsn->important_p = TRUE;
9399 automaton_states.release ();
9401 /* Create automata sets for the insns. */
9402 for (i = 0; i < description->decls_num; i++)
9404 decl = description->decls [i];
9405 if (decl->mode == dm_insn_reserv)
9407 automata_list_start ();
9408 for (automaton = description->first_automaton;
9409 automaton != NULL;
9410 automaton = automaton->next_automaton)
9411 for (ainsn = automaton->ainsn_list;
9412 ainsn != NULL;
9413 ainsn = ainsn->next_ainsn)
9414 if (ainsn->important_p
9415 && ainsn->insn_reserv_decl == DECL_INSN_RESERV (decl))
9417 automata_list_add (automaton);
9418 break;
9420 DECL_INSN_RESERV (decl)->important_automata_list
9421 = automata_list_finish ();
9427 /* The following is top level function to generate automat(a,on) for
9428 fast recognition of pipeline hazards. */
9429 static void
9430 expand_automata (void)
9432 int i;
9434 description = XCREATENODEVAR (struct description,
9435 sizeof (struct description)
9436 /* Two entries for special insns. */
9437 + sizeof (decl_t) * (decls.length () + 1));
9438 description->decls_num = decls.length ();
9439 description->normal_decls_num = description->decls_num;
9440 description->query_units_num = 0;
9441 for (i = 0; i < description->decls_num; i++)
9443 description->decls [i] = decls[i];
9444 if (description->decls [i]->mode == dm_unit
9445 && DECL_UNIT (description->decls [i])->query_p)
9446 DECL_UNIT (description->decls [i])->query_num
9447 = description->query_units_num++;
9449 all_time = create_ticker ();
9450 check_time = create_ticker ();
9451 if (progress_flag)
9452 fprintf (stderr, "Check description...");
9453 check_all_description ();
9454 if (progress_flag)
9455 fprintf (stderr, "done\n");
9456 ticker_off (&check_time);
9457 generation_time = create_ticker ();
9458 if (!have_error)
9460 transform_insn_regexps ();
9461 check_unit_distributions_to_automata ();
9463 if (!have_error)
9465 generate ();
9466 check_automata_insn_issues ();
9468 if (!have_error)
9470 form_important_insn_automata_lists ();
9472 ticker_off (&generation_time);
9475 /* The following is top level function to output PHR and to finish
9476 work with pipeline description translator. */
9477 static void
9478 write_automata (void)
9480 output_time = create_ticker ();
9481 if (progress_flag)
9482 fprintf (stderr, "Forming and outputting automata tables...");
9483 output_tables ();
9484 if (progress_flag)
9486 fprintf (stderr, "done\n");
9487 fprintf (stderr, "Output functions to work with automata...");
9489 output_chip_definitions ();
9490 output_max_insn_queue_index_def ();
9491 output_internal_min_issue_delay_func ();
9492 output_internal_trans_func ();
9493 /* Cache of insn dfa codes: */
9494 fprintf (output_file, "\nstatic int *%s;\n", DFA_INSN_CODES_VARIABLE_NAME);
9495 fprintf (output_file, "\nstatic int %s;\n\n",
9496 DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
9497 output_dfa_insn_code_func ();
9498 output_trans_func ();
9499 output_min_issue_delay_func ();
9500 output_internal_dead_lock_func ();
9501 output_dead_lock_func ();
9502 output_size_func ();
9503 output_internal_reset_func ();
9504 output_reset_func ();
9505 output_min_insn_conflict_delay_func ();
9506 output_default_latencies ();
9507 output_internal_insn_latency_func ();
9508 output_insn_latency_func ();
9509 output_internal_maximal_insn_latency_func ();
9510 output_maximal_insn_latency_func ();
9511 output_print_reservation_func ();
9512 /* Output function get_cpu_unit_code. */
9513 fprintf (output_file, "\n#if %s\n\n", CPU_UNITS_QUERY_MACRO_NAME);
9514 output_get_cpu_unit_code_func ();
9515 output_cpu_unit_reservation_p ();
9516 output_insn_has_dfa_reservation_p ();
9517 fprintf (output_file, "\n#endif /* #if %s */\n\n",
9518 CPU_UNITS_QUERY_MACRO_NAME);
9519 output_dfa_clean_insn_cache_func ();
9520 output_dfa_start_func ();
9521 output_dfa_finish_func ();
9522 if (progress_flag)
9523 fprintf (stderr, "done\n");
9524 if (v_flag)
9526 output_description_file = fopen (output_description_file_name, "w");
9527 if (output_description_file == NULL)
9529 perror (output_description_file_name);
9530 exit (FATAL_EXIT_CODE);
9532 if (progress_flag)
9533 fprintf (stderr, "Output automata description...");
9534 output_description ();
9535 output_automaton_descriptions ();
9536 if (progress_flag)
9537 fprintf (stderr, "done\n");
9538 output_statistics (output_description_file);
9540 if (stats_flag)
9541 output_statistics (stderr);
9542 ticker_off (&output_time);
9543 if (time_flag)
9544 output_time_statistics (stderr);
9545 finish_states ();
9546 finish_arcs ();
9547 finish_automata_lists ();
9548 if (time_flag)
9550 fprintf (stderr, "Summary:\n");
9551 fprintf (stderr, " check time ");
9552 print_active_time (stderr, check_time);
9553 fprintf (stderr, ", generation time ");
9554 print_active_time (stderr, generation_time);
9555 fprintf (stderr, ", all time ");
9556 print_active_time (stderr, all_time);
9557 fprintf (stderr, "\n");
9559 /* Finish all work. */
9560 if (output_description_file != NULL)
9562 fflush (output_description_file);
9563 if (ferror (stdout) != 0)
9564 fatal ("Error in writing DFA description file %s: %s",
9565 output_description_file_name, xstrerror (errno));
9566 fclose (output_description_file);
9568 finish_automaton_decl_table ();
9569 finish_insn_decl_table ();
9570 finish_decl_table ();
9571 obstack_free (&irp, NULL);
9572 if (have_error && output_description_file != NULL)
9573 remove (output_description_file_name);
9577 main (int argc, char **argv)
9579 rtx desc;
9581 progname = "genautomata";
9583 if (!init_rtx_reader_args_cb (argc, argv, parse_automata_opt))
9584 return (FATAL_EXIT_CODE);
9586 initiate_automaton_gen (argv);
9587 while (1)
9589 int lineno;
9590 int insn_code_number;
9592 desc = read_md_rtx (&lineno, &insn_code_number);
9593 if (desc == NULL)
9594 break;
9596 switch (GET_CODE (desc))
9598 case DEFINE_CPU_UNIT:
9599 gen_cpu_unit (desc);
9600 break;
9602 case DEFINE_QUERY_CPU_UNIT:
9603 gen_query_cpu_unit (desc);
9604 break;
9606 case DEFINE_BYPASS:
9607 gen_bypass (desc);
9608 break;
9610 case EXCLUSION_SET:
9611 gen_excl_set (desc);
9612 break;
9614 case PRESENCE_SET:
9615 gen_presence_set (desc);
9616 break;
9618 case FINAL_PRESENCE_SET:
9619 gen_final_presence_set (desc);
9620 break;
9622 case ABSENCE_SET:
9623 gen_absence_set (desc);
9624 break;
9626 case FINAL_ABSENCE_SET:
9627 gen_final_absence_set (desc);
9628 break;
9630 case DEFINE_AUTOMATON:
9631 gen_automaton (desc);
9632 break;
9634 case AUTOMATA_OPTION:
9635 gen_automata_option (desc);
9636 break;
9638 case DEFINE_RESERVATION:
9639 gen_reserv (desc);
9640 break;
9642 case DEFINE_INSN_RESERVATION:
9643 gen_insn_reserv (desc);
9644 break;
9646 default:
9647 break;
9651 if (have_error)
9652 return FATAL_EXIT_CODE;
9654 if (decls.length () > 0)
9656 expand_automata ();
9657 if (!have_error)
9659 puts ("/* Generated automatically by the program `genautomata'\n"
9660 " from the machine description file `md'. */\n\n"
9661 "#include \"config.h\"\n"
9662 "#include \"system.h\"\n"
9663 "#include \"coretypes.h\"\n"
9664 "#include \"tm.h\"\n"
9665 "#include \"rtl.h\"\n"
9666 "#include \"tm_p.h\"\n"
9667 "#include \"insn-config.h\"\n"
9668 "#include \"recog.h\"\n"
9669 "#include \"regs.h\"\n"
9670 "#include \"output.h\"\n"
9671 "#include \"insn-attr.h\"\n"
9672 "#include \"diagnostic-core.h\"\n"
9673 "#include \"flags.h\"\n"
9674 "#include \"function.h\"\n"
9675 "#include \"emit-rtl.h\"\n");
9676 /* FIXME: emit-rtl.h can go away once crtl is in rtl.h. */
9678 write_automata ();
9681 else
9683 puts ("/* Generated automatically by the program `genautomata'\n"
9684 " from the machine description file `md'. */\n\n"
9685 "/* There is no automaton, but ISO C forbids empty\n"
9686 " translation units, so include a header file with some\n"
9687 " declarations, and its pre-requisite header file. */\n"
9688 "#include \"config.h\"\n"
9689 "#include \"system.h\"\n");
9692 fflush (stdout);
9693 return (ferror (stdout) != 0 || have_error
9694 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);