007-01-29 Manuel Lopez-Ibanez <manu@gcc.gnu.org>
[official-gcc.git] / gcc / genautomata.c
blobd4b94ca05c4dd05cbb467ffbe3739503548e3ea0
1 /* Pipeline hazard description translator.
2 Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007
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 2, 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 COPYING. If not, write to the Free
21 Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
22 02110-1301, USA. */
24 /* References:
26 1. Detecting pipeline structural hazards quickly. T. Proebsting,
27 C. Fraser. Proceedings of ACM SIGPLAN-SIGACT Symposium on
28 Principles of Programming Languages, pages 280--286, 1994.
30 This article is a good start point to understand usage of finite
31 state automata for pipeline hazard recognizers. But I'd
32 recommend the 2nd article for more deep understanding.
34 2. Efficient Instruction Scheduling Using Finite State Automata:
35 V. Bala and N. Rubin, Proceedings of MICRO-28. This is the best
36 article about usage of finite state automata for pipeline hazard
37 recognizers.
39 The current implementation is different from the 2nd article in the
40 following:
42 1. New operator `|' (alternative) is permitted in functional unit
43 reservation which can be treated deterministically and
44 non-deterministically.
46 2. Possibility of usage of nondeterministic automata too.
48 3. Possibility to query functional unit reservations for given
49 automaton state.
51 4. Several constructions to describe impossible reservations
52 (`exclusion_set', `presence_set', `final_presence_set',
53 `absence_set', and `final_absence_set').
55 5. No reverse automata are generated. Trace instruction scheduling
56 requires this. It can be easily added in the future if we
57 really need this.
59 6. Union of automaton states are not generated yet. It is planned
60 to be implemented. Such feature is needed to make more accurate
61 interlock insn scheduling to get state describing functional
62 unit reservation in a joint CFG point. */
64 /* This file code processes constructions of machine description file
65 which describes automaton used for recognition of processor pipeline
66 hazards by insn scheduler and can be used for other tasks (such as
67 VLIW insn packing.
69 The translator functions `gen_cpu_unit', `gen_query_cpu_unit',
70 `gen_bypass', `gen_excl_set', `gen_presence_set',
71 `gen_final_presence_set', `gen_absence_set',
72 `gen_final_absence_set', `gen_automaton', `gen_automata_option',
73 `gen_reserv', `gen_insn_reserv' are called from file
74 `genattrtab.c'. They transform RTL constructions describing
75 automata in .md file into internal representation convenient for
76 further processing.
78 The translator major function `expand_automata' processes the
79 description internal representation into finite state automaton.
80 It can be divided on:
82 o checking correctness of the automaton pipeline description
83 (major function is `check_all_description').
85 o generating automaton (automata) from the description (major
86 function is `make_automaton').
88 o optional transformation of nondeterministic finite state
89 automata into deterministic ones if the alternative operator
90 `|' is treated nondeterministically in the description (major
91 function is NDFA_to_DFA).
93 o optional minimization of the finite state automata by merging
94 equivalent automaton states (major function is `minimize_DFA').
96 o forming tables (some as comb vectors) and attributes
97 representing the automata (functions output_..._table).
99 Function `write_automata' outputs the created finite state
100 automaton as different tables and functions which works with the
101 automata to inquire automaton state and to change its state. These
102 function are used by gcc instruction scheduler and may be some
103 other gcc code. */
105 #include "bconfig.h"
106 #include "system.h"
107 #include "coretypes.h"
108 #include "tm.h"
109 #include "rtl.h"
110 #include "obstack.h"
111 #include "errors.h"
112 #include "gensupport.h"
114 #include <math.h>
115 #include "hashtab.h"
116 #include "vec.h"
118 #ifndef CHAR_BIT
119 #define CHAR_BIT 8
120 #endif
122 /* Positions in machine description file. Now they are not used. But
123 they could be used in the future for better diagnostic messages. */
124 typedef int pos_t;
126 /* The following is element of vector of current (and planned in the
127 future) functional unit reservations. */
128 typedef unsigned HOST_WIDE_INT set_el_t;
130 /* Reservations of function units are represented by value of the following
131 type. */
132 typedef set_el_t *reserv_sets_t;
134 /* The following structure describes a ticker. */
135 struct ticker
137 /* The following member value is time of the ticker creation with
138 taking into account time when the ticker is off. Active time of
139 the ticker is current time minus the value. */
140 int modified_creation_time;
141 /* The following member value is time (incremented by one) when the
142 ticker was off. Zero value means that now the ticker is on. */
143 int incremented_off_time;
146 /* The ticker is represented by the following type. */
147 typedef struct ticker ticker_t;
149 /* The following type describes elements of output vectors. */
150 typedef HOST_WIDE_INT vect_el_t;
152 /* Forward declaration of structures of internal representation of
153 pipeline description based on NDFA. */
155 struct unit_decl;
156 struct bypass_decl;
157 struct result_decl;
158 struct automaton_decl;
159 struct unit_pattern_rel_decl;
160 struct reserv_decl;
161 struct insn_reserv_decl;
162 struct decl;
163 struct unit_regexp;
164 struct result_regexp;
165 struct reserv_regexp;
166 struct nothing_regexp;
167 struct sequence_regexp;
168 struct repeat_regexp;
169 struct allof_regexp;
170 struct oneof_regexp;
171 struct regexp;
172 struct description;
173 struct unit_set_el;
174 struct pattern_set_el;
175 struct pattern_reserv;
176 struct state;
177 struct alt_state;
178 struct arc;
179 struct ainsn;
180 struct automaton;
181 struct state_ainsn_table;
183 /* The following typedefs are for brevity. */
184 typedef struct unit_decl *unit_decl_t;
185 typedef struct decl *decl_t;
186 typedef struct regexp *regexp_t;
187 typedef struct unit_set_el *unit_set_el_t;
188 typedef struct pattern_set_el *pattern_set_el_t;
189 typedef struct pattern_reserv *pattern_reserv_t;
190 typedef struct alt_state *alt_state_t;
191 typedef struct state *state_t;
192 typedef struct arc *arc_t;
193 typedef struct ainsn *ainsn_t;
194 typedef struct automaton *automaton_t;
195 typedef struct automata_list_el *automata_list_el_t;
196 typedef struct state_ainsn_table *state_ainsn_table_t;
198 /* Undefined position. */
199 static pos_t no_pos = 0;
201 /* All IR is stored in the following obstack. */
202 static struct obstack irp;
205 /* Declare vector types for various data structures: */
207 DEF_VEC_P(alt_state_t);
208 DEF_VEC_ALLOC_P(alt_state_t,heap);
209 DEF_VEC_P(ainsn_t);
210 DEF_VEC_ALLOC_P(ainsn_t,heap);
211 DEF_VEC_P(state_t);
212 DEF_VEC_ALLOC_P(state_t,heap);
213 DEF_VEC_P(decl_t);
214 DEF_VEC_ALLOC_P(decl_t,heap);
215 DEF_VEC_P(reserv_sets_t);
216 DEF_VEC_ALLOC_P(reserv_sets_t,heap);
218 DEF_VEC_I(vect_el_t);
219 DEF_VEC_ALLOC_I(vect_el_t, heap);
220 typedef VEC(vect_el_t,heap) *vla_hwint_t;
222 /* Forward declarations of functions used before their definitions, only. */
223 static regexp_t gen_regexp_sequence (const char *);
224 static void reserv_sets_or (reserv_sets_t, reserv_sets_t,
225 reserv_sets_t);
226 static reserv_sets_t get_excl_set (reserv_sets_t);
227 static int check_presence_pattern_sets (reserv_sets_t,
228 reserv_sets_t, int);
229 static int check_absence_pattern_sets (reserv_sets_t, reserv_sets_t,
230 int);
231 static arc_t first_out_arc (state_t);
232 static arc_t next_out_arc (arc_t);
236 /* Options with the following names can be set up in automata_option
237 construction. Because the strings occur more one time we use the
238 macros. */
240 #define NO_MINIMIZATION_OPTION "-no-minimization"
241 #define TIME_OPTION "-time"
242 #define STATS_OPTION "-stats"
243 #define V_OPTION "-v"
244 #define W_OPTION "-w"
245 #define NDFA_OPTION "-ndfa"
246 #define PROGRESS_OPTION "-progress"
248 /* The following flags are set up by function `initiate_automaton_gen'. */
250 /* Make automata with nondeterministic reservation by insns (`-ndfa'). */
251 static int ndfa_flag;
253 /* Do not make minimization of DFA (`-no-minimization'). */
254 static int no_minimization_flag;
256 /* Value of this variable is number of automata being generated. The
257 actual number of automata may be less this value if there is not
258 sufficient number of units. This value is defined by argument of
259 option `-split' or by constructions automaton if the value is zero
260 (it is default value of the argument). */
261 static int split_argument;
263 /* Flag of output time statistics (`-time'). */
264 static int time_flag;
266 /* Flag of automata statistics (`-stats'). */
267 static int stats_flag;
269 /* Flag of creation of description file which contains description of
270 result automaton and statistics information (`-v'). */
271 static int v_flag;
273 /* Flag of output of a progress bar showing how many states were
274 generated so far for automaton being processed (`-progress'). */
275 static int progress_flag;
277 /* Flag of generating warning instead of error for non-critical errors
278 (`-w'). */
279 static int w_flag;
282 /* Output file for pipeline hazard recognizer (PHR) being generated.
283 The value is NULL if the file is not defined. */
284 static FILE *output_file;
286 /* Description file of PHR. The value is NULL if the file is not
287 created. */
288 static FILE *output_description_file;
290 /* PHR description file name. */
291 static char *output_description_file_name;
293 /* Value of the following variable is node representing description
294 being processed. This is start point of IR. */
295 static struct description *description;
299 /* This page contains description of IR structure (nodes). */
301 enum decl_mode
303 dm_unit,
304 dm_bypass,
305 dm_automaton,
306 dm_excl,
307 dm_presence,
308 dm_absence,
309 dm_reserv,
310 dm_insn_reserv
313 /* This describes define_cpu_unit and define_query_cpu_unit (see file
314 rtl.def). */
315 struct unit_decl
317 const char *name;
318 /* NULL if the automaton name is absent. */
319 const char *automaton_name;
320 /* If the following value is not zero, the cpu unit reservation is
321 described in define_query_cpu_unit. */
322 char query_p;
324 /* The following fields are defined by checker. */
326 /* The following field value is nonzero if the unit is used in an
327 regexp. */
328 char unit_is_used;
330 /* The following field value is order number (0, 1, ...) of given
331 unit. */
332 int unit_num;
333 /* The following field value is corresponding declaration of
334 automaton which was given in description. If the field value is
335 NULL then automaton in the unit declaration was absent. */
336 struct automaton_decl *automaton_decl;
337 /* The following field value is maximal cycle number (1, ...) on
338 which given unit occurs in insns. Zero value means that given
339 unit is not used in insns. */
340 int max_occ_cycle_num;
341 /* The following field value is minimal cycle number (0, ...) on
342 which given unit occurs in insns. -1 value means that given
343 unit is not used in insns. */
344 int min_occ_cycle_num;
345 /* The following list contains units which conflict with given
346 unit. */
347 unit_set_el_t excl_list;
348 /* The following list contains patterns which are required to
349 reservation of given unit. */
350 pattern_set_el_t presence_list;
351 pattern_set_el_t final_presence_list;
352 /* The following list contains patterns which should be not present
353 in reservation for given unit. */
354 pattern_set_el_t absence_list;
355 pattern_set_el_t final_absence_list;
356 /* The following is used only when `query_p' has nonzero value.
357 This is query number for the unit. */
358 int query_num;
359 /* The following is the last cycle on which the unit was checked for
360 correct distributions of units to automata in a regexp. */
361 int last_distribution_check_cycle;
363 /* The following fields are defined by automaton generator. */
365 /* The following field value is number of the automaton to which
366 given unit belongs. */
367 int corresponding_automaton_num;
368 /* If the following value is not zero, the cpu unit is present in a
369 `exclusion_set' or in right part of a `presence_set',
370 `final_presence_set', `absence_set', and
371 `final_absence_set'define_query_cpu_unit. */
372 char in_set_p;
375 /* This describes define_bypass (see file rtl.def). */
376 struct bypass_decl
378 int latency;
379 const char *out_insn_name;
380 const char *in_insn_name;
381 const char *bypass_guard_name;
383 /* The following fields are defined by checker. */
385 /* output and input insns of given bypass. */
386 struct insn_reserv_decl *out_insn_reserv;
387 struct insn_reserv_decl *in_insn_reserv;
388 /* The next bypass for given output insn. */
389 struct bypass_decl *next;
392 /* This describes define_automaton (see file rtl.def). */
393 struct automaton_decl
395 const char *name;
397 /* The following fields are defined by automaton generator. */
399 /* The following field value is nonzero if the automaton is used in
400 an regexp definition. */
401 char automaton_is_used;
403 /* The following fields are defined by checker. */
405 /* The following field value is the corresponding automaton. This
406 field is not NULL only if the automaton is present in unit
407 declarations and the automatic partition on automata is not
408 used. */
409 automaton_t corresponding_automaton;
412 /* This describes exclusion relations: exclusion_set (see file
413 rtl.def). */
414 struct excl_rel_decl
416 int all_names_num;
417 int first_list_length;
418 char *names [1];
421 /* This describes unit relations: [final_]presence_set or
422 [final_]absence_set (see file rtl.def). */
423 struct unit_pattern_rel_decl
425 int final_p;
426 int names_num;
427 int patterns_num;
428 char **names;
429 char ***patterns;
432 /* This describes define_reservation (see file rtl.def). */
433 struct reserv_decl
435 const char *name;
436 regexp_t regexp;
438 /* The following fields are defined by checker. */
440 /* The following field value is nonzero if the unit is used in an
441 regexp. */
442 char reserv_is_used;
443 /* The following field is used to check up cycle in expression
444 definition. */
445 int loop_pass_num;
448 /* This describes define_insn_reservation (see file rtl.def). */
449 struct insn_reserv_decl
451 rtx condexp;
452 int default_latency;
453 regexp_t regexp;
454 const char *name;
456 /* The following fields are defined by checker. */
458 /* The following field value is order number (0, 1, ...) of given
459 insn. */
460 int insn_num;
461 /* The following field value is list of bypasses in which given insn
462 is output insn. */
463 struct bypass_decl *bypass_list;
465 /* The following fields are defined by automaton generator. */
467 /* The following field is the insn regexp transformed that
468 the regexp has not optional regexp, repetition regexp, and an
469 reservation name (i.e. reservation identifiers are changed by the
470 corresponding regexp) and all alternations are the topest level
471 of the regexp. The value can be NULL only if it is special
472 insn `cycle advancing'. */
473 regexp_t transformed_regexp;
474 /* The following field value is list of arcs marked given
475 insn. The field is used in transformation NDFA -> DFA. */
476 arc_t arcs_marked_by_insn;
477 /* The two following fields are used during minimization of a finite state
478 automaton. */
479 /* The field value is number of equivalence class of state into
480 which arc marked by given insn enters from a state (fixed during
481 an automaton minimization). */
482 int equiv_class_num;
483 /* The following member value is the list to automata which can be
484 changed by the insn issue. */
485 automata_list_el_t important_automata_list;
486 /* The following member is used to process insn once for output. */
487 int processed_p;
490 /* This contains a declaration mentioned above. */
491 struct decl
493 /* What node in the union? */
494 enum decl_mode mode;
495 pos_t pos;
496 union
498 struct unit_decl unit;
499 struct bypass_decl bypass;
500 struct automaton_decl automaton;
501 struct excl_rel_decl excl;
502 struct unit_pattern_rel_decl presence;
503 struct unit_pattern_rel_decl absence;
504 struct reserv_decl reserv;
505 struct insn_reserv_decl insn_reserv;
506 } decl;
509 /* The following structures represent parsed reservation strings. */
510 enum regexp_mode
512 rm_unit,
513 rm_reserv,
514 rm_nothing,
515 rm_sequence,
516 rm_repeat,
517 rm_allof,
518 rm_oneof
521 /* Cpu unit in reservation. */
522 struct unit_regexp
524 const char *name;
525 unit_decl_t unit_decl;
528 /* Define_reservation in a reservation. */
529 struct reserv_regexp
531 const char *name;
532 struct reserv_decl *reserv_decl;
535 /* Absence of reservation (represented by string `nothing'). */
536 struct nothing_regexp
538 /* This used to be empty but ISO C doesn't allow that. */
539 char unused;
542 /* Representation of reservations separated by ',' (see file
543 rtl.def). */
544 struct sequence_regexp
546 int regexps_num;
547 regexp_t regexps [1];
550 /* Representation of construction `repeat' (see file rtl.def). */
551 struct repeat_regexp
553 int repeat_num;
554 regexp_t regexp;
557 /* Representation of reservations separated by '+' (see file
558 rtl.def). */
559 struct allof_regexp
561 int regexps_num;
562 regexp_t regexps [1];
565 /* Representation of reservations separated by '|' (see file
566 rtl.def). */
567 struct oneof_regexp
569 int regexps_num;
570 regexp_t regexps [1];
573 /* Representation of a reservation string. */
574 struct regexp
576 /* What node in the union? */
577 enum regexp_mode mode;
578 pos_t pos;
579 union
581 struct unit_regexp unit;
582 struct reserv_regexp reserv;
583 struct nothing_regexp nothing;
584 struct sequence_regexp sequence;
585 struct repeat_regexp repeat;
586 struct allof_regexp allof;
587 struct oneof_regexp oneof;
588 } regexp;
591 /* Represents description of pipeline hazard description based on
592 NDFA. */
593 struct description
595 int decls_num;
597 /* The following fields are defined by checker. */
599 /* The following fields values are correspondingly number of all
600 units, query units, and insns in the description. */
601 int units_num;
602 int query_units_num;
603 int insns_num;
604 /* The following field value is max length (in cycles) of
605 reservations of insns. The field value is defined only for
606 correct programs. */
607 int max_insn_reserv_cycles;
609 /* The following fields are defined by automaton generator. */
611 /* The following field value is the first automaton. */
612 automaton_t first_automaton;
614 /* The following field is created by pipeline hazard parser and
615 contains all declarations. We allocate additional entry for
616 special insn "cycle advancing" which is added by the automaton
617 generator. */
618 decl_t decls [1];
622 /* The following nodes are created in automaton checker. */
624 /* The following nodes represent exclusion set for cpu units. Each
625 element is accessed through only one excl_list. */
626 struct unit_set_el
628 unit_decl_t unit_decl;
629 unit_set_el_t next_unit_set_el;
632 /* The following nodes represent presence or absence pattern for cpu
633 units. Each element is accessed through only one presence_list or
634 absence_list. */
635 struct pattern_set_el
637 /* The number of units in unit_decls. */
638 int units_num;
639 /* The units forming the pattern. */
640 struct unit_decl **unit_decls;
641 pattern_set_el_t next_pattern_set_el;
645 /* The following nodes are created in automaton generator. */
648 /* The following nodes represent presence or absence pattern for cpu
649 units. Each element is accessed through only one element of
650 unit_presence_set_table or unit_absence_set_table. */
651 struct pattern_reserv
653 reserv_sets_t reserv;
654 pattern_reserv_t next_pattern_reserv;
657 /* The following node type describes state automaton. The state may
658 be deterministic or non-deterministic. Non-deterministic state has
659 several component states which represent alternative cpu units
660 reservations. The state also is used for describing a
661 deterministic reservation of automaton insn. */
662 struct state
664 /* The following member value is nonzero if there is a transition by
665 cycle advancing. */
666 int new_cycle_p;
667 /* The following field is list of processor unit reservations on
668 each cycle. */
669 reserv_sets_t reservs;
670 /* The following field is unique number of given state between other
671 states. */
672 int unique_num;
673 /* The following field value is automaton to which given state
674 belongs. */
675 automaton_t automaton;
676 /* The following field value is the first arc output from given
677 state. */
678 arc_t first_out_arc;
679 unsigned int num_out_arcs;
680 /* The following field is used to form NDFA. */
681 char it_was_placed_in_stack_for_NDFA_forming;
682 /* The following field is used to form DFA. */
683 char it_was_placed_in_stack_for_DFA_forming;
684 /* The following field is used to transform NDFA to DFA and DFA
685 minimization. The field value is not NULL if the state is a
686 compound state. In this case the value of field `unit_sets_list'
687 is NULL. All states in the list are in the hash table. The list
688 is formed through field `next_sorted_alt_state'. We should
689 support only one level of nesting state. */
690 alt_state_t component_states;
691 /* The following field is used for passing graph of states. */
692 int pass_num;
693 /* The list of states belonging to one equivalence class is formed
694 with the aid of the following field. */
695 state_t next_equiv_class_state;
696 /* The two following fields are used during minimization of a finite
697 state automaton. */
698 int equiv_class_num_1, equiv_class_num_2;
699 /* The following field is used during minimization of a finite state
700 automaton. The field value is state corresponding to equivalence
701 class to which given state belongs. */
702 state_t equiv_class_state;
703 unsigned int *presence_signature;
704 /* The following field value is the order number of given state.
705 The states in final DFA is enumerated with the aid of the
706 following field. */
707 int order_state_num;
708 /* This member is used for passing states for searching minimal
709 delay time. */
710 int state_pass_num;
711 /* The following member is used to evaluate min issue delay of insn
712 for a state. */
713 int min_insn_issue_delay;
714 /* The following member is used to evaluate max issue rate of the
715 processor. The value of the member is maximal length of the path
716 from given state no containing arcs marked by special insn `cycle
717 advancing'. */
718 int longest_path_length;
721 /* The following macro is an initial value of member
722 `longest_path_length' of a state. */
723 #define UNDEFINED_LONGEST_PATH_LENGTH -1
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 /* The following field value is the corresponding automaton
812 declaration. This field is not NULL only if the automatic
813 partition on automata is not used. */
814 struct automaton_decl *corresponding_automaton_decl;
815 /* The following field value is the next automaton. */
816 automaton_t next_automaton;
817 /* The following field is start state of FA. There are not unit
818 reservations in the state. */
819 state_t start_state;
820 /* The following field value is number of equivalence classes of
821 insns (see field `insn_equiv_class_num' in
822 `insn_reserv_decl'). */
823 int insn_equiv_classes_num;
824 /* The following field value is number of states of final DFA. */
825 int achieved_states_num;
826 /* The following field value is the order number (0, 1, ...) of
827 given automaton. */
828 int automaton_order_num;
829 /* The following fields contain statistics information about
830 building automaton. */
831 int NDFA_states_num, DFA_states_num;
832 /* The following field value is defined only if minimization of DFA
833 is used. */
834 int minimal_DFA_states_num;
835 int NDFA_arcs_num, DFA_arcs_num;
836 /* The following field value is defined only if minimization of DFA
837 is used. */
838 int minimal_DFA_arcs_num;
839 /* The following member refers for two table state x ainsn -> int.
840 ??? Above sentence is incomprehensible. */
841 state_ainsn_table_t trans_table;
842 /* The following member value is maximal value of min issue delay
843 for insns of the automaton. */
844 int max_min_delay;
845 /* Usually min issue delay is small and we can place several (2, 4,
846 8) elements in one vector element. So the compression factor can
847 be 1 (no compression), 2, 4, 8. */
848 int min_issue_delay_table_compression_factor;
849 /* Total number of locked states in this automaton. */
850 int locked_states;
853 /* The following is the element of the list of automata. */
854 struct automata_list_el
856 /* The automaton itself. */
857 automaton_t automaton;
858 /* The next automata set element. */
859 automata_list_el_t next_automata_list_el;
862 /* The following structure describes a table state X ainsn -> int(>= 0). */
863 struct state_ainsn_table
865 /* Automaton to which given table belongs. */
866 automaton_t automaton;
867 /* The following tree vectors for comb vector implementation of the
868 table. */
869 vla_hwint_t comb_vect;
870 vla_hwint_t check_vect;
871 vla_hwint_t base_vect;
872 /* This is simple implementation of the table. */
873 vla_hwint_t full_vect;
874 /* Minimal and maximal values of the previous vectors. */
875 int min_comb_vect_el_value, max_comb_vect_el_value;
876 int min_base_vect_el_value, max_base_vect_el_value;
879 /* Macros to access members of unions. Use only them for access to
880 union members of declarations and regexps. */
882 #if defined ENABLE_CHECKING && (GCC_VERSION >= 2007)
884 #define DECL_UNIT(d) __extension__ \
885 (({ struct decl *const _decl = (d); \
886 if (_decl->mode != dm_unit) \
887 decl_mode_check_failed (_decl->mode, "dm_unit", \
888 __FILE__, __LINE__, __FUNCTION__); \
889 &(_decl)->decl.unit; }))
891 #define DECL_BYPASS(d) __extension__ \
892 (({ struct decl *const _decl = (d); \
893 if (_decl->mode != dm_bypass) \
894 decl_mode_check_failed (_decl->mode, "dm_bypass", \
895 __FILE__, __LINE__, __FUNCTION__); \
896 &(_decl)->decl.bypass; }))
898 #define DECL_AUTOMATON(d) __extension__ \
899 (({ struct decl *const _decl = (d); \
900 if (_decl->mode != dm_automaton) \
901 decl_mode_check_failed (_decl->mode, "dm_automaton", \
902 __FILE__, __LINE__, __FUNCTION__); \
903 &(_decl)->decl.automaton; }))
905 #define DECL_EXCL(d) __extension__ \
906 (({ struct decl *const _decl = (d); \
907 if (_decl->mode != dm_excl) \
908 decl_mode_check_failed (_decl->mode, "dm_excl", \
909 __FILE__, __LINE__, __FUNCTION__); \
910 &(_decl)->decl.excl; }))
912 #define DECL_PRESENCE(d) __extension__ \
913 (({ struct decl *const _decl = (d); \
914 if (_decl->mode != dm_presence) \
915 decl_mode_check_failed (_decl->mode, "dm_presence", \
916 __FILE__, __LINE__, __FUNCTION__); \
917 &(_decl)->decl.presence; }))
919 #define DECL_ABSENCE(d) __extension__ \
920 (({ struct decl *const _decl = (d); \
921 if (_decl->mode != dm_absence) \
922 decl_mode_check_failed (_decl->mode, "dm_absence", \
923 __FILE__, __LINE__, __FUNCTION__); \
924 &(_decl)->decl.absence; }))
926 #define DECL_RESERV(d) __extension__ \
927 (({ struct decl *const _decl = (d); \
928 if (_decl->mode != dm_reserv) \
929 decl_mode_check_failed (_decl->mode, "dm_reserv", \
930 __FILE__, __LINE__, __FUNCTION__); \
931 &(_decl)->decl.reserv; }))
933 #define DECL_INSN_RESERV(d) __extension__ \
934 (({ struct decl *const _decl = (d); \
935 if (_decl->mode != dm_insn_reserv) \
936 decl_mode_check_failed (_decl->mode, "dm_insn_reserv", \
937 __FILE__, __LINE__, __FUNCTION__); \
938 &(_decl)->decl.insn_reserv; }))
940 static const char *decl_name (enum decl_mode);
941 static void decl_mode_check_failed (enum decl_mode, const char *,
942 const char *, int, const char *)
943 ATTRIBUTE_NORETURN;
945 /* Return string representation of declaration mode MODE. */
946 static const char *
947 decl_name (enum decl_mode mode)
949 static char str [100];
951 if (mode == dm_unit)
952 return "dm_unit";
953 else if (mode == dm_bypass)
954 return "dm_bypass";
955 else if (mode == dm_automaton)
956 return "dm_automaton";
957 else if (mode == dm_excl)
958 return "dm_excl";
959 else if (mode == dm_presence)
960 return "dm_presence";
961 else if (mode == dm_absence)
962 return "dm_absence";
963 else if (mode == dm_reserv)
964 return "dm_reserv";
965 else if (mode == dm_insn_reserv)
966 return "dm_insn_reserv";
967 else
968 sprintf (str, "unknown (%d)", (int) mode);
969 return str;
972 /* The function prints message about unexpected declaration and finish
973 the program. */
974 static void
975 decl_mode_check_failed (enum decl_mode mode, const char *expected_mode_str,
976 const char *file, int line, const char *func)
978 fprintf
979 (stderr,
980 "\n%s: %d: error in %s: DECL check: expected decl %s, have %s\n",
981 file, line, func, expected_mode_str, decl_name (mode));
982 exit (1);
986 #define REGEXP_UNIT(r) __extension__ \
987 (({ struct regexp *const _regexp = (r); \
988 if (_regexp->mode != rm_unit) \
989 regexp_mode_check_failed (_regexp->mode, "rm_unit", \
990 __FILE__, __LINE__, __FUNCTION__); \
991 &(_regexp)->regexp.unit; }))
993 #define REGEXP_RESERV(r) __extension__ \
994 (({ struct regexp *const _regexp = (r); \
995 if (_regexp->mode != rm_reserv) \
996 regexp_mode_check_failed (_regexp->mode, "rm_reserv", \
997 __FILE__, __LINE__, __FUNCTION__); \
998 &(_regexp)->regexp.reserv; }))
1000 #define REGEXP_SEQUENCE(r) __extension__ \
1001 (({ struct regexp *const _regexp = (r); \
1002 if (_regexp->mode != rm_sequence) \
1003 regexp_mode_check_failed (_regexp->mode, "rm_sequence", \
1004 __FILE__, __LINE__, __FUNCTION__); \
1005 &(_regexp)->regexp.sequence; }))
1007 #define REGEXP_REPEAT(r) __extension__ \
1008 (({ struct regexp *const _regexp = (r); \
1009 if (_regexp->mode != rm_repeat) \
1010 regexp_mode_check_failed (_regexp->mode, "rm_repeat", \
1011 __FILE__, __LINE__, __FUNCTION__); \
1012 &(_regexp)->regexp.repeat; }))
1014 #define REGEXP_ALLOF(r) __extension__ \
1015 (({ struct regexp *const _regexp = (r); \
1016 if (_regexp->mode != rm_allof) \
1017 regexp_mode_check_failed (_regexp->mode, "rm_allof", \
1018 __FILE__, __LINE__, __FUNCTION__); \
1019 &(_regexp)->regexp.allof; }))
1021 #define REGEXP_ONEOF(r) __extension__ \
1022 (({ struct regexp *const _regexp = (r); \
1023 if (_regexp->mode != rm_oneof) \
1024 regexp_mode_check_failed (_regexp->mode, "rm_oneof", \
1025 __FILE__, __LINE__, __FUNCTION__); \
1026 &(_regexp)->regexp.oneof; }))
1028 static const char *regexp_name (enum regexp_mode);
1029 static void regexp_mode_check_failed (enum regexp_mode, const char *,
1030 const char *, int,
1031 const char *) ATTRIBUTE_NORETURN;
1034 /* Return string representation of regexp mode MODE. */
1035 static const char *
1036 regexp_name (enum regexp_mode mode)
1038 switch (mode)
1040 case rm_unit:
1041 return "rm_unit";
1042 case rm_reserv:
1043 return "rm_reserv";
1044 case rm_nothing:
1045 return "rm_nothing";
1046 case rm_sequence:
1047 return "rm_sequence";
1048 case rm_repeat:
1049 return "rm_repeat";
1050 case rm_allof:
1051 return "rm_allof";
1052 case rm_oneof:
1053 return "rm_oneof";
1054 default:
1055 gcc_unreachable ();
1059 /* The function prints message about unexpected regexp and finish the
1060 program. */
1061 static void
1062 regexp_mode_check_failed (enum regexp_mode mode,
1063 const char *expected_mode_str,
1064 const char *file, int line, const char *func)
1066 fprintf
1067 (stderr,
1068 "\n%s: %d: error in %s: REGEXP check: expected decl %s, have %s\n",
1069 file, line, func, expected_mode_str, regexp_name (mode));
1070 exit (1);
1073 #else /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */
1075 #define DECL_UNIT(d) (&(d)->decl.unit)
1076 #define DECL_BYPASS(d) (&(d)->decl.bypass)
1077 #define DECL_AUTOMATON(d) (&(d)->decl.automaton)
1078 #define DECL_EXCL(d) (&(d)->decl.excl)
1079 #define DECL_PRESENCE(d) (&(d)->decl.presence)
1080 #define DECL_ABSENCE(d) (&(d)->decl.absence)
1081 #define DECL_RESERV(d) (&(d)->decl.reserv)
1082 #define DECL_INSN_RESERV(d) (&(d)->decl.insn_reserv)
1084 #define REGEXP_UNIT(r) (&(r)->regexp.unit)
1085 #define REGEXP_RESERV(r) (&(r)->regexp.reserv)
1086 #define REGEXP_SEQUENCE(r) (&(r)->regexp.sequence)
1087 #define REGEXP_REPEAT(r) (&(r)->regexp.repeat)
1088 #define REGEXP_ALLOF(r) (&(r)->regexp.allof)
1089 #define REGEXP_ONEOF(r) (&(r)->regexp.oneof)
1091 #endif /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */
1093 /* Create IR structure (node). */
1094 static void *
1095 create_node (size_t size)
1097 void *result;
1099 obstack_blank (&irp, size);
1100 result = obstack_base (&irp);
1101 obstack_finish (&irp);
1102 /* Default values of members are NULL and zero. */
1103 memset (result, 0, size);
1104 return result;
1107 /* Copy IR structure (node). */
1108 static void *
1109 copy_node (const void *from, size_t size)
1111 void *const result = create_node (size);
1112 memcpy (result, from, size);
1113 return result;
1116 /* The function checks that NAME does not contain quotes (`"'). */
1117 static const char *
1118 check_name (const char * name, pos_t pos ATTRIBUTE_UNUSED)
1120 const char *str;
1122 for (str = name; *str != '\0'; str++)
1123 if (*str == '\"')
1124 error ("Name `%s' contains quotes", name);
1125 return name;
1128 /* Pointers to all declarations during IR generation are stored in the
1129 following. */
1130 static VEC(decl_t,heap) *decls;
1132 /* Given a pointer to a (char *) and a separator, return an alloc'ed
1133 string containing the next separated element, taking parentheses
1134 into account if PAR_FLAG has nonzero value. Advance the pointer to
1135 after the string scanned, or the end-of-string. Return NULL if at
1136 end of string. */
1137 static char *
1138 next_sep_el (const char **pstr, int sep, int par_flag)
1140 char *out_str;
1141 const char *p;
1142 int pars_num;
1143 int n_spaces;
1145 /* Remove leading whitespaces. */
1146 while (ISSPACE ((int) **pstr))
1147 (*pstr)++;
1149 if (**pstr == '\0')
1150 return NULL;
1152 n_spaces = 0;
1153 for (pars_num = 0, p = *pstr; *p != '\0'; p++)
1155 if (par_flag && *p == '(')
1156 pars_num++;
1157 else if (par_flag && *p == ')')
1158 pars_num--;
1159 else if (pars_num == 0 && *p == sep)
1160 break;
1161 if (pars_num == 0 && ISSPACE ((int) *p))
1162 n_spaces++;
1163 else
1165 for (; n_spaces != 0; n_spaces--)
1166 obstack_1grow (&irp, p [-n_spaces]);
1167 obstack_1grow (&irp, *p);
1170 obstack_1grow (&irp, '\0');
1171 out_str = obstack_base (&irp);
1172 obstack_finish (&irp);
1174 *pstr = p;
1175 if (**pstr == sep)
1176 (*pstr)++;
1178 return out_str;
1181 /* Given a string and a separator, return the number of separated
1182 elements in it, taking parentheses into account if PAR_FLAG has
1183 nonzero value. Return 0 for the null string, -1 if parentheses is
1184 not balanced. */
1185 static int
1186 n_sep_els (const char *s, int sep, int par_flag)
1188 int n;
1189 int pars_num;
1191 if (*s == '\0')
1192 return 0;
1194 for (pars_num = 0, n = 1; *s; s++)
1195 if (par_flag && *s == '(')
1196 pars_num++;
1197 else if (par_flag && *s == ')')
1198 pars_num--;
1199 else if (pars_num == 0 && *s == sep)
1200 n++;
1202 return (pars_num != 0 ? -1 : n);
1205 /* Given a string and a separator, return vector of strings which are
1206 elements in the string and number of elements through els_num.
1207 Take parentheses into account if PAREN_P has nonzero value. The
1208 function also inserts the end marker NULL at the end of vector.
1209 Return 0 for the null string, -1 if parentheses are not balanced. */
1210 static char **
1211 get_str_vect (const char *str, int *els_num, int sep, int paren_p)
1213 int i;
1214 char **vect;
1215 const char **pstr;
1216 char *trail;
1218 *els_num = n_sep_els (str, sep, paren_p);
1219 if (*els_num <= 0)
1220 return NULL;
1221 obstack_blank (&irp, sizeof (char *) * (*els_num + 1));
1222 vect = (char **) obstack_base (&irp);
1223 obstack_finish (&irp);
1224 pstr = &str;
1225 for (i = 0; i < *els_num; i++)
1226 vect [i] = next_sep_el (pstr, sep, paren_p);
1227 trail = next_sep_el (pstr, sep, paren_p);
1228 gcc_assert (!trail);
1229 vect [i] = NULL;
1230 return vect;
1233 /* Process a DEFINE_CPU_UNIT.
1235 This gives information about a unit contained in CPU. We fill a
1236 struct unit_decl with information used later by `expand_automata'. */
1237 static void
1238 gen_cpu_unit (rtx def)
1240 decl_t decl;
1241 char **str_cpu_units;
1242 int vect_length;
1243 int i;
1245 str_cpu_units = get_str_vect (XSTR (def, 0), &vect_length, ',', FALSE);
1246 if (str_cpu_units == NULL)
1247 fatal ("invalid string `%s' in define_cpu_unit", XSTR (def, 0));
1248 for (i = 0; i < vect_length; i++)
1250 decl = create_node (sizeof (struct decl));
1251 decl->mode = dm_unit;
1252 decl->pos = 0;
1253 DECL_UNIT (decl)->name = check_name (str_cpu_units [i], decl->pos);
1254 DECL_UNIT (decl)->automaton_name = XSTR (def, 1);
1255 DECL_UNIT (decl)->query_p = 0;
1256 DECL_UNIT (decl)->min_occ_cycle_num = -1;
1257 DECL_UNIT (decl)->in_set_p = 0;
1258 VEC_safe_push (decl_t,heap, decls, decl);
1262 /* Process a DEFINE_QUERY_CPU_UNIT.
1264 This gives information about a unit contained in CPU. We fill a
1265 struct unit_decl with information used later by `expand_automata'. */
1266 static void
1267 gen_query_cpu_unit (rtx def)
1269 decl_t decl;
1270 char **str_cpu_units;
1271 int vect_length;
1272 int i;
1274 str_cpu_units = get_str_vect (XSTR (def, 0), &vect_length, ',',
1275 FALSE);
1276 if (str_cpu_units == NULL)
1277 fatal ("invalid string `%s' in define_query_cpu_unit", XSTR (def, 0));
1278 for (i = 0; i < vect_length; i++)
1280 decl = create_node (sizeof (struct decl));
1281 decl->mode = dm_unit;
1282 decl->pos = 0;
1283 DECL_UNIT (decl)->name = check_name (str_cpu_units [i], decl->pos);
1284 DECL_UNIT (decl)->automaton_name = XSTR (def, 1);
1285 DECL_UNIT (decl)->query_p = 1;
1286 VEC_safe_push (decl_t,heap, decls, decl);
1290 /* Process a DEFINE_BYPASS.
1292 This gives information about a unit contained in the CPU. We fill
1293 in a struct bypass_decl with information used later by
1294 `expand_automata'. */
1295 static void
1296 gen_bypass (rtx def)
1298 decl_t decl;
1299 char **out_insns;
1300 int out_length;
1301 char **in_insns;
1302 int in_length;
1303 int i, j;
1305 out_insns = get_str_vect (XSTR (def, 1), &out_length, ',', FALSE);
1306 if (out_insns == NULL)
1307 fatal ("invalid string `%s' in define_bypass", XSTR (def, 1));
1308 in_insns = get_str_vect (XSTR (def, 2), &in_length, ',', FALSE);
1309 if (in_insns == NULL)
1310 fatal ("invalid string `%s' in define_bypass", XSTR (def, 2));
1311 for (i = 0; i < out_length; i++)
1312 for (j = 0; j < in_length; j++)
1314 decl = create_node (sizeof (struct decl));
1315 decl->mode = dm_bypass;
1316 decl->pos = 0;
1317 DECL_BYPASS (decl)->latency = XINT (def, 0);
1318 DECL_BYPASS (decl)->out_insn_name = out_insns [i];
1319 DECL_BYPASS (decl)->in_insn_name = in_insns [j];
1320 DECL_BYPASS (decl)->bypass_guard_name = XSTR (def, 3);
1321 VEC_safe_push (decl_t,heap, decls, decl);
1325 /* Process an EXCLUSION_SET.
1327 This gives information about a cpu unit conflicts. We fill a
1328 struct excl_rel_decl (excl) with information used later by
1329 `expand_automata'. */
1330 static void
1331 gen_excl_set (rtx def)
1333 decl_t decl;
1334 char **first_str_cpu_units;
1335 char **second_str_cpu_units;
1336 int first_vect_length;
1337 int length;
1338 int i;
1340 first_str_cpu_units
1341 = get_str_vect (XSTR (def, 0), &first_vect_length, ',', FALSE);
1342 if (first_str_cpu_units == NULL)
1343 fatal ("invalid first string `%s' in exclusion_set", XSTR (def, 0));
1344 second_str_cpu_units = get_str_vect (XSTR (def, 1), &length, ',',
1345 FALSE);
1346 if (second_str_cpu_units == NULL)
1347 fatal ("invalid second string `%s' in exclusion_set", XSTR (def, 1));
1348 length += first_vect_length;
1349 decl = create_node (sizeof (struct decl) + (length - 1) * sizeof (char *));
1350 decl->mode = dm_excl;
1351 decl->pos = 0;
1352 DECL_EXCL (decl)->all_names_num = length;
1353 DECL_EXCL (decl)->first_list_length = first_vect_length;
1354 for (i = 0; i < length; i++)
1355 if (i < first_vect_length)
1356 DECL_EXCL (decl)->names [i] = first_str_cpu_units [i];
1357 else
1358 DECL_EXCL (decl)->names [i]
1359 = second_str_cpu_units [i - first_vect_length];
1360 VEC_safe_push (decl_t,heap, decls, decl);
1363 /* Process a PRESENCE_SET, a FINAL_PRESENCE_SET, an ABSENCE_SET,
1364 FINAL_ABSENCE_SET (it is depended on PRESENCE_P and FINAL_P).
1366 This gives information about a cpu unit reservation requirements.
1367 We fill a struct unit_pattern_rel_decl with information used later
1368 by `expand_automata'. */
1369 static void
1370 gen_presence_absence_set (rtx def, int presence_p, int final_p)
1372 decl_t decl;
1373 char **str_cpu_units;
1374 char **str_pattern_lists;
1375 char ***str_patterns;
1376 int cpu_units_length;
1377 int length;
1378 int patterns_length;
1379 int i;
1381 str_cpu_units = get_str_vect (XSTR (def, 0), &cpu_units_length, ',',
1382 FALSE);
1383 if (str_cpu_units == NULL)
1384 fatal ((presence_p
1385 ? (final_p
1386 ? "invalid first string `%s' in final_presence_set"
1387 : "invalid first string `%s' in presence_set")
1388 : (final_p
1389 ? "invalid first string `%s' in final_absence_set"
1390 : "invalid first string `%s' in absence_set")),
1391 XSTR (def, 0));
1392 str_pattern_lists = get_str_vect (XSTR (def, 1),
1393 &patterns_length, ',', FALSE);
1394 if (str_pattern_lists == NULL)
1395 fatal ((presence_p
1396 ? (final_p
1397 ? "invalid second string `%s' in final_presence_set"
1398 : "invalid second string `%s' in presence_set")
1399 : (final_p
1400 ? "invalid second string `%s' in final_absence_set"
1401 : "invalid second string `%s' in absence_set")), XSTR (def, 1));
1402 str_patterns = obstack_alloc (&irp, patterns_length * sizeof (char **));
1403 for (i = 0; i < patterns_length; i++)
1405 str_patterns [i] = get_str_vect (str_pattern_lists [i],
1406 &length, ' ', FALSE);
1407 gcc_assert (str_patterns [i]);
1409 decl = create_node (sizeof (struct decl));
1410 decl->pos = 0;
1411 if (presence_p)
1413 decl->mode = dm_presence;
1414 DECL_PRESENCE (decl)->names_num = cpu_units_length;
1415 DECL_PRESENCE (decl)->names = str_cpu_units;
1416 DECL_PRESENCE (decl)->patterns = str_patterns;
1417 DECL_PRESENCE (decl)->patterns_num = patterns_length;
1418 DECL_PRESENCE (decl)->final_p = final_p;
1420 else
1422 decl->mode = dm_absence;
1423 DECL_ABSENCE (decl)->names_num = cpu_units_length;
1424 DECL_ABSENCE (decl)->names = str_cpu_units;
1425 DECL_ABSENCE (decl)->patterns = str_patterns;
1426 DECL_ABSENCE (decl)->patterns_num = patterns_length;
1427 DECL_ABSENCE (decl)->final_p = final_p;
1429 VEC_safe_push (decl_t,heap, decls, decl);
1432 /* Process a PRESENCE_SET.
1434 This gives information about a cpu unit reservation requirements.
1435 We fill a struct unit_pattern_rel_decl (presence) with information
1436 used later by `expand_automata'. */
1437 static void
1438 gen_presence_set (rtx def)
1440 gen_presence_absence_set (def, TRUE, FALSE);
1443 /* Process a FINAL_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_final_presence_set (rtx def)
1451 gen_presence_absence_set (def, TRUE, TRUE);
1454 /* Process an ABSENCE_SET.
1456 This gives information about a cpu unit reservation requirements.
1457 We fill a struct unit_pattern_rel_decl (absence) with information
1458 used later by `expand_automata'. */
1459 static void
1460 gen_absence_set (rtx def)
1462 gen_presence_absence_set (def, FALSE, FALSE);
1465 /* Process a FINAL_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_final_absence_set (rtx def)
1473 gen_presence_absence_set (def, FALSE, TRUE);
1476 /* Process a DEFINE_AUTOMATON.
1478 This gives information about a finite state automaton used for
1479 recognizing pipeline hazards. We fill a struct automaton_decl
1480 with information used later by `expand_automata'. */
1481 static void
1482 gen_automaton (rtx def)
1484 decl_t decl;
1485 char **str_automata;
1486 int vect_length;
1487 int i;
1489 str_automata = get_str_vect (XSTR (def, 0), &vect_length, ',', FALSE);
1490 if (str_automata == NULL)
1491 fatal ("invalid string `%s' in define_automaton", XSTR (def, 0));
1492 for (i = 0; i < vect_length; i++)
1494 decl = create_node (sizeof (struct decl));
1495 decl->mode = dm_automaton;
1496 decl->pos = 0;
1497 DECL_AUTOMATON (decl)->name = check_name (str_automata [i], decl->pos);
1498 VEC_safe_push (decl_t,heap, decls, decl);
1502 /* Process an AUTOMATA_OPTION.
1504 This gives information how to generate finite state automaton used
1505 for recognizing pipeline hazards. */
1506 static void
1507 gen_automata_option (rtx def)
1509 if (strcmp (XSTR (def, 0), NO_MINIMIZATION_OPTION + 1) == 0)
1510 no_minimization_flag = 1;
1511 else if (strcmp (XSTR (def, 0), TIME_OPTION + 1) == 0)
1512 time_flag = 1;
1513 else if (strcmp (XSTR (def, 0), STATS_OPTION + 1) == 0)
1514 stats_flag = 1;
1515 else if (strcmp (XSTR (def, 0), V_OPTION + 1) == 0)
1516 v_flag = 1;
1517 else if (strcmp (XSTR (def, 0), W_OPTION + 1) == 0)
1518 w_flag = 1;
1519 else if (strcmp (XSTR (def, 0), NDFA_OPTION + 1) == 0)
1520 ndfa_flag = 1;
1521 else if (strcmp (XSTR (def, 0), PROGRESS_OPTION + 1) == 0)
1522 progress_flag = 1;
1523 else
1524 fatal ("invalid option `%s' in automata_option", XSTR (def, 0));
1527 /* Name in reservation to denote absence reservation. */
1528 #define NOTHING_NAME "nothing"
1530 /* The following string contains original reservation string being
1531 parsed. */
1532 static const char *reserv_str;
1534 /* Parse an element in STR. */
1535 static regexp_t
1536 gen_regexp_el (const char *str)
1538 regexp_t regexp;
1539 char *dstr;
1540 int len;
1542 if (*str == '(')
1544 len = strlen (str);
1545 if (str [len - 1] != ')')
1546 fatal ("garbage after ) in reservation `%s'", reserv_str);
1547 dstr = alloca (len - 1);
1548 memcpy (dstr, str + 1, len - 2);
1549 dstr [len-2] = '\0';
1550 regexp = gen_regexp_sequence (dstr);
1552 else if (strcmp (str, NOTHING_NAME) == 0)
1554 regexp = create_node (sizeof (struct decl));
1555 regexp->mode = rm_nothing;
1557 else
1559 regexp = create_node (sizeof (struct decl));
1560 regexp->mode = rm_unit;
1561 REGEXP_UNIT (regexp)->name = str;
1563 return regexp;
1566 /* Parse construction `repeat' in STR. */
1567 static regexp_t
1568 gen_regexp_repeat (const char *str)
1570 regexp_t regexp;
1571 regexp_t repeat;
1572 char **repeat_vect;
1573 int els_num;
1574 int i;
1576 repeat_vect = get_str_vect (str, &els_num, '*', TRUE);
1577 if (repeat_vect == NULL)
1578 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1579 if (els_num > 1)
1581 regexp = gen_regexp_el (repeat_vect [0]);
1582 for (i = 1; i < els_num; i++)
1584 repeat = create_node (sizeof (struct regexp));
1585 repeat->mode = rm_repeat;
1586 REGEXP_REPEAT (repeat)->regexp = regexp;
1587 REGEXP_REPEAT (repeat)->repeat_num = atoi (repeat_vect [i]);
1588 if (REGEXP_REPEAT (repeat)->repeat_num <= 1)
1589 fatal ("repetition `%s' <= 1 in reservation `%s'",
1590 str, reserv_str);
1591 regexp = repeat;
1593 return regexp;
1595 else
1596 return gen_regexp_el (str);
1599 /* Parse reservation STR which possibly contains separator '+'. */
1600 static regexp_t
1601 gen_regexp_allof (const char *str)
1603 regexp_t allof;
1604 char **allof_vect;
1605 int els_num;
1606 int i;
1608 allof_vect = get_str_vect (str, &els_num, '+', TRUE);
1609 if (allof_vect == NULL)
1610 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1611 if (els_num > 1)
1613 allof = create_node (sizeof (struct regexp)
1614 + sizeof (regexp_t) * (els_num - 1));
1615 allof->mode = rm_allof;
1616 REGEXP_ALLOF (allof)->regexps_num = els_num;
1617 for (i = 0; i < els_num; i++)
1618 REGEXP_ALLOF (allof)->regexps [i] = gen_regexp_repeat (allof_vect [i]);
1619 return allof;
1621 else
1622 return gen_regexp_repeat (str);
1625 /* Parse reservation STR which possibly contains separator '|'. */
1626 static regexp_t
1627 gen_regexp_oneof (const char *str)
1629 regexp_t oneof;
1630 char **oneof_vect;
1631 int els_num;
1632 int i;
1634 oneof_vect = get_str_vect (str, &els_num, '|', TRUE);
1635 if (oneof_vect == NULL)
1636 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1637 if (els_num > 1)
1639 oneof = create_node (sizeof (struct regexp)
1640 + sizeof (regexp_t) * (els_num - 1));
1641 oneof->mode = rm_oneof;
1642 REGEXP_ONEOF (oneof)->regexps_num = els_num;
1643 for (i = 0; i < els_num; i++)
1644 REGEXP_ONEOF (oneof)->regexps [i] = gen_regexp_allof (oneof_vect [i]);
1645 return oneof;
1647 else
1648 return gen_regexp_allof (str);
1651 /* Parse reservation STR which possibly contains separator ','. */
1652 static regexp_t
1653 gen_regexp_sequence (const char *str)
1655 regexp_t sequence;
1656 char **sequence_vect;
1657 int els_num;
1658 int i;
1660 sequence_vect = get_str_vect (str, &els_num, ',', TRUE);
1661 if (els_num > 1)
1663 sequence = create_node (sizeof (struct regexp)
1664 + sizeof (regexp_t) * (els_num - 1));
1665 sequence->mode = rm_sequence;
1666 REGEXP_SEQUENCE (sequence)->regexps_num = els_num;
1667 for (i = 0; i < els_num; i++)
1668 REGEXP_SEQUENCE (sequence)->regexps [i]
1669 = gen_regexp_oneof (sequence_vect [i]);
1670 return sequence;
1672 else
1673 return gen_regexp_oneof (str);
1676 /* Parse construction reservation STR. */
1677 static regexp_t
1678 gen_regexp (const char *str)
1680 reserv_str = str;
1681 return gen_regexp_sequence (str);;
1684 /* Process a DEFINE_RESERVATION.
1686 This gives information about a reservation of cpu units. We fill
1687 in a struct reserv_decl with information used later by
1688 `expand_automata'. */
1689 static void
1690 gen_reserv (rtx def)
1692 decl_t decl;
1694 decl = create_node (sizeof (struct decl));
1695 decl->mode = dm_reserv;
1696 decl->pos = 0;
1697 DECL_RESERV (decl)->name = check_name (XSTR (def, 0), decl->pos);
1698 DECL_RESERV (decl)->regexp = gen_regexp (XSTR (def, 1));
1699 VEC_safe_push (decl_t,heap, decls, decl);
1702 /* Process a DEFINE_INSN_RESERVATION.
1704 This gives information about the reservation of cpu units by an
1705 insn. We fill a struct insn_reserv_decl with information used
1706 later by `expand_automata'. */
1707 static void
1708 gen_insn_reserv (rtx def)
1710 decl_t decl;
1712 decl = create_node (sizeof (struct decl));
1713 decl->mode = dm_insn_reserv;
1714 decl->pos = 0;
1715 DECL_INSN_RESERV (decl)->name
1716 = check_name (XSTR (def, 0), decl->pos);
1717 DECL_INSN_RESERV (decl)->default_latency = XINT (def, 1);
1718 DECL_INSN_RESERV (decl)->condexp = XEXP (def, 2);
1719 DECL_INSN_RESERV (decl)->regexp = gen_regexp (XSTR (def, 3));
1720 VEC_safe_push (decl_t,heap, decls, decl);
1725 /* The function evaluates hash value (0..UINT_MAX) of string. */
1726 static unsigned
1727 string_hash (const char *string)
1729 unsigned result, i;
1731 for (result = i = 0;*string++ != '\0'; i++)
1732 result += ((unsigned char) *string << (i % CHAR_BIT));
1733 return result;
1738 /* This page contains abstract data `table of automaton declarations'.
1739 Elements of the table is nodes representing automaton declarations.
1740 Key of the table elements is name of given automaton. Remember
1741 that automaton names have own space. */
1743 /* The function evaluates hash value of an automaton declaration. The
1744 function is used by abstract data `hashtab'. The function returns
1745 hash value (0..UINT_MAX) of given automaton declaration. */
1746 static hashval_t
1747 automaton_decl_hash (const void *automaton_decl)
1749 const decl_t decl = (decl_t) automaton_decl;
1751 gcc_assert (decl->mode != dm_automaton
1752 || DECL_AUTOMATON (decl)->name);
1753 return string_hash (DECL_AUTOMATON (decl)->name);
1756 /* The function tests automaton declarations on equality of their
1757 keys. The function is used by abstract data `hashtab'. The
1758 function returns 1 if the declarations have the same key, 0
1759 otherwise. */
1760 static int
1761 automaton_decl_eq_p (const void* automaton_decl_1,
1762 const void* automaton_decl_2)
1764 const decl_t decl1 = (decl_t) automaton_decl_1;
1765 const decl_t decl2 = (decl_t) automaton_decl_2;
1767 gcc_assert (decl1->mode == dm_automaton
1768 && DECL_AUTOMATON (decl1)->name
1769 && decl2->mode == dm_automaton
1770 && DECL_AUTOMATON (decl2)->name);
1771 return strcmp (DECL_AUTOMATON (decl1)->name,
1772 DECL_AUTOMATON (decl2)->name) == 0;
1775 /* The automaton declaration table itself is represented by the
1776 following variable. */
1777 static htab_t automaton_decl_table;
1779 /* The function inserts automaton declaration into the table. The
1780 function does nothing if an automaton declaration with the same key
1781 exists already in the table. The function returns automaton
1782 declaration node in the table with the same key as given automaton
1783 declaration node. */
1784 static decl_t
1785 insert_automaton_decl (decl_t automaton_decl)
1787 void **entry_ptr;
1789 entry_ptr = htab_find_slot (automaton_decl_table, automaton_decl, 1);
1790 if (*entry_ptr == NULL)
1791 *entry_ptr = (void *) automaton_decl;
1792 return (decl_t) *entry_ptr;
1795 /* The following variable value is node representing automaton
1796 declaration. The node used for searching automaton declaration
1797 with given name. */
1798 static struct decl work_automaton_decl;
1800 /* The function searches for automaton declaration in the table with
1801 the same key as node representing name of the automaton
1802 declaration. The function returns node found in the table, NULL if
1803 such node does not exist in the table. */
1804 static decl_t
1805 find_automaton_decl (const char *name)
1807 void *entry;
1809 work_automaton_decl.mode = dm_automaton;
1810 DECL_AUTOMATON (&work_automaton_decl)->name = name;
1811 entry = htab_find (automaton_decl_table, &work_automaton_decl);
1812 return (decl_t) entry;
1815 /* The function creates empty automaton declaration table and node
1816 representing automaton declaration and used for searching automaton
1817 declaration with given name. The function must be called only once
1818 before any work with the automaton declaration table. */
1819 static void
1820 initiate_automaton_decl_table (void)
1822 work_automaton_decl.mode = dm_automaton;
1823 automaton_decl_table = htab_create (10, automaton_decl_hash,
1824 automaton_decl_eq_p, (htab_del) 0);
1827 /* The function deletes the automaton declaration table. Only call of
1828 function `initiate_automaton_decl_table' is possible immediately
1829 after this function call. */
1830 static void
1831 finish_automaton_decl_table (void)
1833 htab_delete (automaton_decl_table);
1838 /* This page contains abstract data `table of insn declarations'.
1839 Elements of the table is nodes representing insn declarations. Key
1840 of the table elements is name of given insn (in corresponding
1841 define_insn_reservation). Remember that insn names have own
1842 space. */
1844 /* The function evaluates hash value of an insn declaration. The
1845 function is used by abstract data `hashtab'. The function returns
1846 hash value (0..UINT_MAX) of given insn declaration. */
1847 static hashval_t
1848 insn_decl_hash (const void *insn_decl)
1850 const decl_t decl = (decl_t) insn_decl;
1852 gcc_assert (decl->mode == dm_insn_reserv
1853 && DECL_INSN_RESERV (decl)->name);
1854 return string_hash (DECL_INSN_RESERV (decl)->name);
1857 /* The function tests insn declarations on equality of their keys.
1858 The function is used by abstract data `hashtab'. The function
1859 returns 1 if declarations have the same key, 0 otherwise. */
1860 static int
1861 insn_decl_eq_p (const void *insn_decl_1, const void *insn_decl_2)
1863 const decl_t decl1 = (decl_t) insn_decl_1;
1864 const decl_t decl2 = (decl_t) insn_decl_2;
1866 gcc_assert (decl1->mode == dm_insn_reserv
1867 && DECL_INSN_RESERV (decl1)->name
1868 && decl2->mode == dm_insn_reserv
1869 && DECL_INSN_RESERV (decl2)->name);
1870 return strcmp (DECL_INSN_RESERV (decl1)->name,
1871 DECL_INSN_RESERV (decl2)->name) == 0;
1874 /* The insn declaration table itself is represented by the following
1875 variable. The table does not contain insn reservation
1876 declarations. */
1877 static htab_t insn_decl_table;
1879 /* The function inserts insn declaration into the table. The function
1880 does nothing if an insn declaration with the same key exists
1881 already in the table. The function returns insn declaration node
1882 in the table with the same key as given insn declaration node. */
1883 static decl_t
1884 insert_insn_decl (decl_t insn_decl)
1886 void **entry_ptr;
1888 entry_ptr = htab_find_slot (insn_decl_table, insn_decl, 1);
1889 if (*entry_ptr == NULL)
1890 *entry_ptr = (void *) insn_decl;
1891 return (decl_t) *entry_ptr;
1894 /* The following variable value is node representing insn reservation
1895 declaration. The node used for searching insn reservation
1896 declaration with given name. */
1897 static struct decl work_insn_decl;
1899 /* The function searches for insn reservation declaration in the table
1900 with the same key as node representing name of the insn reservation
1901 declaration. The function returns node found in the table, NULL if
1902 such node does not exist in the table. */
1903 static decl_t
1904 find_insn_decl (const char *name)
1906 void *entry;
1908 work_insn_decl.mode = dm_insn_reserv;
1909 DECL_INSN_RESERV (&work_insn_decl)->name = name;
1910 entry = htab_find (insn_decl_table, &work_insn_decl);
1911 return (decl_t) entry;
1914 /* The function creates empty insn declaration table and node
1915 representing insn declaration and used for searching insn
1916 declaration with given name. The function must be called only once
1917 before any work with the insn declaration table. */
1918 static void
1919 initiate_insn_decl_table (void)
1921 work_insn_decl.mode = dm_insn_reserv;
1922 insn_decl_table = htab_create (10, insn_decl_hash, insn_decl_eq_p,
1923 (htab_del) 0);
1926 /* The function deletes the insn declaration table. Only call of
1927 function `initiate_insn_decl_table' is possible immediately after
1928 this function call. */
1929 static void
1930 finish_insn_decl_table (void)
1932 htab_delete (insn_decl_table);
1937 /* This page contains abstract data `table of declarations'. Elements
1938 of the table is nodes representing declarations (of units and
1939 reservations). Key of the table elements is names of given
1940 declarations. */
1942 /* The function evaluates hash value of a declaration. The function
1943 is used by abstract data `hashtab'. The function returns hash
1944 value (0..UINT_MAX) of given declaration. */
1945 static hashval_t
1946 decl_hash (const void *decl)
1948 const decl_t d = (const decl_t) decl;
1950 gcc_assert ((d->mode == dm_unit && DECL_UNIT (d)->name)
1951 || (d->mode == dm_reserv && DECL_RESERV (d)->name));
1952 return string_hash (d->mode == dm_unit
1953 ? DECL_UNIT (d)->name : DECL_RESERV (d)->name);
1956 /* The function tests declarations on equality of their keys. The
1957 function is used by abstract data 'hashtab'. The function
1958 returns 1 if the declarations have the same key, 0 otherwise. */
1959 static int
1960 decl_eq_p (const void *decl_1, const void *decl_2)
1962 const decl_t d1 = (const decl_t) decl_1;
1963 const decl_t d2 = (const decl_t) decl_2;
1965 gcc_assert ((d1->mode == dm_unit && DECL_UNIT (d1)->name)
1966 || (d1->mode == dm_reserv && DECL_RESERV (d1)->name));
1967 gcc_assert ((d2->mode == dm_unit && DECL_UNIT (d2)->name)
1968 || (d2->mode == dm_reserv && DECL_RESERV (d2)->name));
1969 return strcmp ((d1->mode == dm_unit
1970 ? DECL_UNIT (d1)->name : DECL_RESERV (d1)->name),
1971 (d2->mode == dm_unit
1972 ? DECL_UNIT (d2)->name : DECL_RESERV (d2)->name)) == 0;
1975 /* The declaration table itself is represented by the following
1976 variable. */
1977 static htab_t decl_table;
1979 /* The function inserts declaration into the table. The function does
1980 nothing if a declaration with the same key exists already in the
1981 table. The function returns declaration node in the table with the
1982 same key as given declaration node. */
1984 static decl_t
1985 insert_decl (decl_t decl)
1987 void **entry_ptr;
1989 entry_ptr = htab_find_slot (decl_table, decl, 1);
1990 if (*entry_ptr == NULL)
1991 *entry_ptr = (void *) decl;
1992 return (decl_t) *entry_ptr;
1995 /* The following variable value is node representing declaration. The
1996 node used for searching declaration with given name. */
1997 static struct decl work_decl;
1999 /* The function searches for declaration in the table with the same
2000 key as node representing name of the declaration. The function
2001 returns node found in the table, NULL if such node does not exist
2002 in the table. */
2003 static decl_t
2004 find_decl (const char *name)
2006 void *entry;
2008 work_decl.mode = dm_unit;
2009 DECL_UNIT (&work_decl)->name = name;
2010 entry = htab_find (decl_table, &work_decl);
2011 return (decl_t) entry;
2014 /* The function creates empty declaration table and node representing
2015 declaration and used for searching declaration with given name.
2016 The function must be called only once before any work with the
2017 declaration table. */
2018 static void
2019 initiate_decl_table (void)
2021 work_decl.mode = dm_unit;
2022 decl_table = htab_create (10, decl_hash, decl_eq_p, (htab_del) 0);
2025 /* The function deletes the declaration table. Only call of function
2026 `initiate_declaration_table' is possible immediately after this
2027 function call. */
2028 static void
2029 finish_decl_table (void)
2031 htab_delete (decl_table);
2036 /* This page contains checker of pipeline hazard description. */
2038 /* Checking NAMES in an exclusion clause vector and returning formed
2039 unit_set_el_list. */
2040 static unit_set_el_t
2041 process_excls (char **names, int num, pos_t excl_pos ATTRIBUTE_UNUSED)
2043 unit_set_el_t el_list;
2044 unit_set_el_t last_el;
2045 unit_set_el_t new_el;
2046 decl_t decl_in_table;
2047 int i;
2049 el_list = NULL;
2050 last_el = NULL;
2051 for (i = 0; i < num; i++)
2053 decl_in_table = find_decl (names [i]);
2054 if (decl_in_table == NULL)
2055 error ("unit `%s' in exclusion is not declared", names [i]);
2056 else if (decl_in_table->mode != dm_unit)
2057 error ("`%s' in exclusion is not unit", names [i]);
2058 else
2060 new_el = create_node (sizeof (struct unit_set_el));
2061 new_el->unit_decl = DECL_UNIT (decl_in_table);
2062 new_el->next_unit_set_el = NULL;
2063 if (last_el == NULL)
2064 el_list = last_el = new_el;
2065 else
2067 last_el->next_unit_set_el = new_el;
2068 last_el = last_el->next_unit_set_el;
2072 return el_list;
2075 /* The function adds each element from SOURCE_LIST to the exclusion
2076 list of the each element from DEST_LIST. Checking situation "unit
2077 excludes itself". */
2078 static void
2079 add_excls (unit_set_el_t dest_list, unit_set_el_t source_list,
2080 pos_t excl_pos ATTRIBUTE_UNUSED)
2082 unit_set_el_t dst;
2083 unit_set_el_t src;
2084 unit_set_el_t curr_el;
2085 unit_set_el_t prev_el;
2086 unit_set_el_t copy;
2088 for (dst = dest_list; dst != NULL; dst = dst->next_unit_set_el)
2089 for (src = source_list; src != NULL; src = src->next_unit_set_el)
2091 if (dst->unit_decl == src->unit_decl)
2093 error ("unit `%s' excludes itself", src->unit_decl->name);
2094 continue;
2096 if (dst->unit_decl->automaton_name != NULL
2097 && src->unit_decl->automaton_name != NULL
2098 && strcmp (dst->unit_decl->automaton_name,
2099 src->unit_decl->automaton_name) != 0)
2101 error ("units `%s' and `%s' in exclusion set belong to different automata",
2102 src->unit_decl->name, dst->unit_decl->name);
2103 continue;
2105 for (curr_el = dst->unit_decl->excl_list, prev_el = NULL;
2106 curr_el != NULL;
2107 prev_el = curr_el, curr_el = curr_el->next_unit_set_el)
2108 if (curr_el->unit_decl == src->unit_decl)
2109 break;
2110 if (curr_el == NULL)
2112 /* Element not found - insert. */
2113 copy = copy_node (src, sizeof (*src));
2114 copy->next_unit_set_el = NULL;
2115 if (prev_el == NULL)
2116 dst->unit_decl->excl_list = copy;
2117 else
2118 prev_el->next_unit_set_el = copy;
2123 /* Checking NAMES in presence/absence clause and returning the
2124 formed unit_set_el_list. The function is called only after
2125 processing all exclusion sets. */
2126 static unit_set_el_t
2127 process_presence_absence_names (char **names, int num,
2128 pos_t req_pos ATTRIBUTE_UNUSED,
2129 int presence_p, int final_p)
2131 unit_set_el_t el_list;
2132 unit_set_el_t last_el;
2133 unit_set_el_t new_el;
2134 decl_t decl_in_table;
2135 int i;
2137 el_list = NULL;
2138 last_el = NULL;
2139 for (i = 0; i < num; i++)
2141 decl_in_table = find_decl (names [i]);
2142 if (decl_in_table == NULL)
2143 error ((presence_p
2144 ? (final_p
2145 ? "unit `%s' in final presence set is not declared"
2146 : "unit `%s' in presence set is not declared")
2147 : (final_p
2148 ? "unit `%s' in final absence set is not declared"
2149 : "unit `%s' in absence set is not declared")), names [i]);
2150 else if (decl_in_table->mode != dm_unit)
2151 error ((presence_p
2152 ? (final_p
2153 ? "`%s' in final presence set is not unit"
2154 : "`%s' in presence set is not unit")
2155 : (final_p
2156 ? "`%s' in final absence set is not unit"
2157 : "`%s' in absence set is not unit")), names [i]);
2158 else
2160 new_el = create_node (sizeof (struct unit_set_el));
2161 new_el->unit_decl = DECL_UNIT (decl_in_table);
2162 new_el->next_unit_set_el = NULL;
2163 if (last_el == NULL)
2164 el_list = last_el = new_el;
2165 else
2167 last_el->next_unit_set_el = new_el;
2168 last_el = last_el->next_unit_set_el;
2172 return el_list;
2175 /* Checking NAMES in patterns of a presence/absence clause and
2176 returning the formed pattern_set_el_list. The function is called
2177 only after processing all exclusion sets. */
2178 static pattern_set_el_t
2179 process_presence_absence_patterns (char ***patterns, int num,
2180 pos_t req_pos ATTRIBUTE_UNUSED,
2181 int presence_p, int final_p)
2183 pattern_set_el_t el_list;
2184 pattern_set_el_t last_el;
2185 pattern_set_el_t new_el;
2186 decl_t decl_in_table;
2187 int i, j;
2189 el_list = NULL;
2190 last_el = NULL;
2191 for (i = 0; i < num; i++)
2193 for (j = 0; patterns [i] [j] != NULL; j++)
2195 new_el = create_node (sizeof (struct pattern_set_el)
2196 + sizeof (struct unit_decl *) * j);
2197 new_el->unit_decls
2198 = (struct unit_decl **) ((char *) new_el
2199 + sizeof (struct pattern_set_el));
2200 new_el->next_pattern_set_el = NULL;
2201 if (last_el == NULL)
2202 el_list = last_el = new_el;
2203 else
2205 last_el->next_pattern_set_el = new_el;
2206 last_el = last_el->next_pattern_set_el;
2208 new_el->units_num = 0;
2209 for (j = 0; patterns [i] [j] != NULL; j++)
2211 decl_in_table = find_decl (patterns [i] [j]);
2212 if (decl_in_table == NULL)
2213 error ((presence_p
2214 ? (final_p
2215 ? "unit `%s' in final presence set is not declared"
2216 : "unit `%s' in presence set is not declared")
2217 : (final_p
2218 ? "unit `%s' in final absence set is not declared"
2219 : "unit `%s' in absence set is not declared")),
2220 patterns [i] [j]);
2221 else if (decl_in_table->mode != dm_unit)
2222 error ((presence_p
2223 ? (final_p
2224 ? "`%s' in final presence set is not unit"
2225 : "`%s' in presence set is not unit")
2226 : (final_p
2227 ? "`%s' in final absence set is not unit"
2228 : "`%s' in absence set is not unit")),
2229 patterns [i] [j]);
2230 else
2232 new_el->unit_decls [new_el->units_num]
2233 = DECL_UNIT (decl_in_table);
2234 new_el->units_num++;
2238 return el_list;
2241 /* The function adds each element from PATTERN_LIST to presence (if
2242 PRESENCE_P) or absence list of the each element from DEST_LIST.
2243 Checking situations "unit requires own absence", and "unit excludes
2244 and requires presence of ...", "unit requires absence and presence
2245 of ...", "units in (final) presence set belong to different
2246 automata", and "units in (final) absence set belong to different
2247 automata". Remember that we process absence sets only after all
2248 presence sets. */
2249 static void
2250 add_presence_absence (unit_set_el_t dest_list,
2251 pattern_set_el_t pattern_list,
2252 pos_t req_pos ATTRIBUTE_UNUSED,
2253 int presence_p, int final_p)
2255 unit_set_el_t dst;
2256 pattern_set_el_t pat;
2257 struct unit_decl *unit;
2258 unit_set_el_t curr_excl_el;
2259 pattern_set_el_t curr_pat_el;
2260 pattern_set_el_t prev_el;
2261 pattern_set_el_t copy;
2262 int i;
2263 int no_error_flag;
2265 for (dst = dest_list; dst != NULL; dst = dst->next_unit_set_el)
2266 for (pat = pattern_list; pat != NULL; pat = pat->next_pattern_set_el)
2268 for (i = 0; i < pat->units_num; i++)
2270 unit = pat->unit_decls [i];
2271 if (dst->unit_decl == unit && pat->units_num == 1 && !presence_p)
2273 error ("unit `%s' requires own absence", unit->name);
2274 continue;
2276 if (dst->unit_decl->automaton_name != NULL
2277 && unit->automaton_name != NULL
2278 && strcmp (dst->unit_decl->automaton_name,
2279 unit->automaton_name) != 0)
2281 error ((presence_p
2282 ? (final_p
2283 ? "units `%s' and `%s' in final presence set belong to different automata"
2284 : "units `%s' and `%s' in presence set belong to different automata")
2285 : (final_p
2286 ? "units `%s' and `%s' in final absence set belong to different automata"
2287 : "units `%s' and `%s' in absence set belong to different automata")),
2288 unit->name, dst->unit_decl->name);
2289 continue;
2291 no_error_flag = 1;
2292 if (presence_p)
2293 for (curr_excl_el = dst->unit_decl->excl_list;
2294 curr_excl_el != NULL;
2295 curr_excl_el = curr_excl_el->next_unit_set_el)
2297 if (unit == curr_excl_el->unit_decl && pat->units_num == 1)
2299 if (!w_flag)
2301 error ("unit `%s' excludes and requires presence of `%s'",
2302 dst->unit_decl->name, unit->name);
2303 no_error_flag = 0;
2305 else
2306 warning
2307 (0, "unit `%s' excludes and requires presence of `%s'",
2308 dst->unit_decl->name, unit->name);
2311 else if (pat->units_num == 1)
2312 for (curr_pat_el = dst->unit_decl->presence_list;
2313 curr_pat_el != NULL;
2314 curr_pat_el = curr_pat_el->next_pattern_set_el)
2315 if (curr_pat_el->units_num == 1
2316 && unit == curr_pat_el->unit_decls [0])
2318 if (!w_flag)
2320 error
2321 ("unit `%s' requires absence and presence of `%s'",
2322 dst->unit_decl->name, unit->name);
2323 no_error_flag = 0;
2325 else
2326 warning
2327 (0, "unit `%s' requires absence and presence of `%s'",
2328 dst->unit_decl->name, unit->name);
2330 if (no_error_flag)
2332 for (prev_el = (presence_p
2333 ? (final_p
2334 ? dst->unit_decl->final_presence_list
2335 : dst->unit_decl->final_presence_list)
2336 : (final_p
2337 ? dst->unit_decl->final_absence_list
2338 : dst->unit_decl->absence_list));
2339 prev_el != NULL && prev_el->next_pattern_set_el != NULL;
2340 prev_el = prev_el->next_pattern_set_el)
2342 copy = copy_node (pat, sizeof (*pat));
2343 copy->next_pattern_set_el = NULL;
2344 if (prev_el == NULL)
2346 if (presence_p)
2348 if (final_p)
2349 dst->unit_decl->final_presence_list = copy;
2350 else
2351 dst->unit_decl->presence_list = copy;
2353 else if (final_p)
2354 dst->unit_decl->final_absence_list = copy;
2355 else
2356 dst->unit_decl->absence_list = copy;
2358 else
2359 prev_el->next_pattern_set_el = copy;
2366 /* The function searches for bypass with given IN_INSN_RESERV in given
2367 BYPASS_LIST. */
2368 static struct bypass_decl *
2369 find_bypass (struct bypass_decl *bypass_list,
2370 struct insn_reserv_decl *in_insn_reserv)
2372 struct bypass_decl *bypass;
2374 for (bypass = bypass_list; bypass != NULL; bypass = bypass->next)
2375 if (bypass->in_insn_reserv == in_insn_reserv)
2376 break;
2377 return bypass;
2380 /* The function processes pipeline description declarations, checks
2381 their correctness, and forms exclusion/presence/absence sets. */
2382 static void
2383 process_decls (void)
2385 decl_t decl;
2386 decl_t automaton_decl;
2387 decl_t decl_in_table;
2388 decl_t out_insn_reserv;
2389 decl_t in_insn_reserv;
2390 struct bypass_decl *bypass;
2391 int automaton_presence;
2392 int i;
2394 /* Checking repeated automata declarations. */
2395 automaton_presence = 0;
2396 for (i = 0; i < description->decls_num; i++)
2398 decl = description->decls [i];
2399 if (decl->mode == dm_automaton)
2401 automaton_presence = 1;
2402 decl_in_table = insert_automaton_decl (decl);
2403 if (decl_in_table != decl)
2405 if (!w_flag)
2406 error ("repeated declaration of automaton `%s'",
2407 DECL_AUTOMATON (decl)->name);
2408 else
2409 warning (0, "repeated declaration of automaton `%s'",
2410 DECL_AUTOMATON (decl)->name);
2414 /* Checking undeclared automata, repeated declarations (except for
2415 automata) and correctness of their attributes (insn latency times
2416 etc.). */
2417 for (i = 0; i < description->decls_num; i++)
2419 decl = description->decls [i];
2420 if (decl->mode == dm_insn_reserv)
2422 if (DECL_INSN_RESERV (decl)->default_latency < 0)
2423 error ("define_insn_reservation `%s' has negative latency time",
2424 DECL_INSN_RESERV (decl)->name);
2425 DECL_INSN_RESERV (decl)->insn_num = description->insns_num;
2426 description->insns_num++;
2427 decl_in_table = insert_insn_decl (decl);
2428 if (decl_in_table != decl)
2429 error ("`%s' is already used as insn reservation name",
2430 DECL_INSN_RESERV (decl)->name);
2432 else if (decl->mode == dm_bypass)
2434 if (DECL_BYPASS (decl)->latency < 0)
2435 error ("define_bypass `%s - %s' has negative latency time",
2436 DECL_BYPASS (decl)->out_insn_name,
2437 DECL_BYPASS (decl)->in_insn_name);
2439 else if (decl->mode == dm_unit || decl->mode == dm_reserv)
2441 if (decl->mode == dm_unit)
2443 DECL_UNIT (decl)->automaton_decl = NULL;
2444 if (DECL_UNIT (decl)->automaton_name != NULL)
2446 automaton_decl
2447 = find_automaton_decl (DECL_UNIT (decl)->automaton_name);
2448 if (automaton_decl == NULL)
2449 error ("automaton `%s' is not declared",
2450 DECL_UNIT (decl)->automaton_name);
2451 else
2453 DECL_AUTOMATON (automaton_decl)->automaton_is_used = 1;
2454 DECL_UNIT (decl)->automaton_decl
2455 = DECL_AUTOMATON (automaton_decl);
2458 else if (automaton_presence)
2459 error ("define_unit `%s' without automaton when one defined",
2460 DECL_UNIT (decl)->name);
2461 DECL_UNIT (decl)->unit_num = description->units_num;
2462 description->units_num++;
2463 if (strcmp (DECL_UNIT (decl)->name, NOTHING_NAME) == 0)
2465 error ("`%s' is declared as cpu unit", NOTHING_NAME);
2466 continue;
2468 decl_in_table = find_decl (DECL_UNIT (decl)->name);
2470 else
2472 if (strcmp (DECL_RESERV (decl)->name, NOTHING_NAME) == 0)
2474 error ("`%s' is declared as cpu reservation", NOTHING_NAME);
2475 continue;
2477 decl_in_table = find_decl (DECL_RESERV (decl)->name);
2479 if (decl_in_table == NULL)
2480 decl_in_table = insert_decl (decl);
2481 else
2483 if (decl->mode == dm_unit)
2484 error ("repeated declaration of unit `%s'",
2485 DECL_UNIT (decl)->name);
2486 else
2487 error ("repeated declaration of reservation `%s'",
2488 DECL_RESERV (decl)->name);
2492 /* Check bypasses and form list of bypasses for each (output)
2493 insn. */
2494 for (i = 0; i < description->decls_num; i++)
2496 decl = description->decls [i];
2497 if (decl->mode == dm_bypass)
2499 out_insn_reserv = find_insn_decl (DECL_BYPASS (decl)->out_insn_name);
2500 in_insn_reserv = find_insn_decl (DECL_BYPASS (decl)->in_insn_name);
2501 if (out_insn_reserv == NULL)
2502 error ("there is no insn reservation `%s'",
2503 DECL_BYPASS (decl)->out_insn_name);
2504 else if (in_insn_reserv == NULL)
2505 error ("there is no insn reservation `%s'",
2506 DECL_BYPASS (decl)->in_insn_name);
2507 else
2509 DECL_BYPASS (decl)->out_insn_reserv
2510 = DECL_INSN_RESERV (out_insn_reserv);
2511 DECL_BYPASS (decl)->in_insn_reserv
2512 = DECL_INSN_RESERV (in_insn_reserv);
2513 bypass
2514 = find_bypass (DECL_INSN_RESERV (out_insn_reserv)->bypass_list,
2515 DECL_BYPASS (decl)->in_insn_reserv);
2516 if (bypass != NULL)
2518 if (DECL_BYPASS (decl)->latency == bypass->latency)
2520 if (!w_flag)
2521 error
2522 ("the same bypass `%s - %s' is already defined",
2523 DECL_BYPASS (decl)->out_insn_name,
2524 DECL_BYPASS (decl)->in_insn_name);
2525 else
2526 warning
2527 (0, "the same bypass `%s - %s' is already defined",
2528 DECL_BYPASS (decl)->out_insn_name,
2529 DECL_BYPASS (decl)->in_insn_name);
2531 else
2532 error ("bypass `%s - %s' is already defined",
2533 DECL_BYPASS (decl)->out_insn_name,
2534 DECL_BYPASS (decl)->in_insn_name);
2536 else
2538 DECL_BYPASS (decl)->next
2539 = DECL_INSN_RESERV (out_insn_reserv)->bypass_list;
2540 DECL_INSN_RESERV (out_insn_reserv)->bypass_list
2541 = DECL_BYPASS (decl);
2547 /* Check exclusion set declarations and form exclusion sets. */
2548 for (i = 0; i < description->decls_num; i++)
2550 decl = description->decls [i];
2551 if (decl->mode == dm_excl)
2553 unit_set_el_t unit_set_el_list;
2554 unit_set_el_t unit_set_el_list_2;
2556 unit_set_el_list
2557 = process_excls (DECL_EXCL (decl)->names,
2558 DECL_EXCL (decl)->first_list_length, decl->pos);
2559 unit_set_el_list_2
2560 = process_excls (&DECL_EXCL (decl)->names
2561 [DECL_EXCL (decl)->first_list_length],
2562 DECL_EXCL (decl)->all_names_num
2563 - DECL_EXCL (decl)->first_list_length,
2564 decl->pos);
2565 add_excls (unit_set_el_list, unit_set_el_list_2, decl->pos);
2566 add_excls (unit_set_el_list_2, unit_set_el_list, decl->pos);
2570 /* Check presence set declarations and form presence sets. */
2571 for (i = 0; i < description->decls_num; i++)
2573 decl = description->decls [i];
2574 if (decl->mode == dm_presence)
2576 unit_set_el_t unit_set_el_list;
2577 pattern_set_el_t pattern_set_el_list;
2579 unit_set_el_list
2580 = process_presence_absence_names
2581 (DECL_PRESENCE (decl)->names, DECL_PRESENCE (decl)->names_num,
2582 decl->pos, TRUE, DECL_PRESENCE (decl)->final_p);
2583 pattern_set_el_list
2584 = process_presence_absence_patterns
2585 (DECL_PRESENCE (decl)->patterns,
2586 DECL_PRESENCE (decl)->patterns_num,
2587 decl->pos, TRUE, DECL_PRESENCE (decl)->final_p);
2588 add_presence_absence (unit_set_el_list, pattern_set_el_list,
2589 decl->pos, TRUE,
2590 DECL_PRESENCE (decl)->final_p);
2594 /* Check absence set declarations and form absence sets. */
2595 for (i = 0; i < description->decls_num; i++)
2597 decl = description->decls [i];
2598 if (decl->mode == dm_absence)
2600 unit_set_el_t unit_set_el_list;
2601 pattern_set_el_t pattern_set_el_list;
2603 unit_set_el_list
2604 = process_presence_absence_names
2605 (DECL_ABSENCE (decl)->names, DECL_ABSENCE (decl)->names_num,
2606 decl->pos, FALSE, DECL_ABSENCE (decl)->final_p);
2607 pattern_set_el_list
2608 = process_presence_absence_patterns
2609 (DECL_ABSENCE (decl)->patterns,
2610 DECL_ABSENCE (decl)->patterns_num,
2611 decl->pos, FALSE, DECL_ABSENCE (decl)->final_p);
2612 add_presence_absence (unit_set_el_list, pattern_set_el_list,
2613 decl->pos, FALSE,
2614 DECL_ABSENCE (decl)->final_p);
2619 /* The following function checks that declared automaton is used. If
2620 the automaton is not used, the function fixes error/warning. The
2621 following function must be called only after `process_decls'. */
2622 static void
2623 check_automaton_usage (void)
2625 decl_t decl;
2626 int i;
2628 for (i = 0; i < description->decls_num; i++)
2630 decl = description->decls [i];
2631 if (decl->mode == dm_automaton
2632 && !DECL_AUTOMATON (decl)->automaton_is_used)
2634 if (!w_flag)
2635 error ("automaton `%s' is not used", DECL_AUTOMATON (decl)->name);
2636 else
2637 warning (0, "automaton `%s' is not used",
2638 DECL_AUTOMATON (decl)->name);
2643 /* The following recursive function processes all regexp in order to
2644 fix usage of units or reservations and to fix errors of undeclared
2645 name. The function may change unit_regexp onto reserv_regexp.
2646 Remember that reserv_regexp does not exist before the function
2647 call. */
2648 static regexp_t
2649 process_regexp (regexp_t regexp)
2651 decl_t decl_in_table;
2652 regexp_t new_regexp;
2653 int i;
2655 switch (regexp->mode)
2657 case rm_unit:
2658 decl_in_table = find_decl (REGEXP_UNIT (regexp)->name);
2659 if (decl_in_table == NULL)
2660 error ("undeclared unit or reservation `%s'",
2661 REGEXP_UNIT (regexp)->name);
2662 else
2663 switch (decl_in_table->mode)
2665 case dm_unit:
2666 DECL_UNIT (decl_in_table)->unit_is_used = 1;
2667 REGEXP_UNIT (regexp)->unit_decl = DECL_UNIT (decl_in_table);
2668 break;
2670 case dm_reserv:
2671 DECL_RESERV (decl_in_table)->reserv_is_used = 1;
2672 new_regexp = create_node (sizeof (struct regexp));
2673 new_regexp->mode = rm_reserv;
2674 new_regexp->pos = regexp->pos;
2675 REGEXP_RESERV (new_regexp)->name = REGEXP_UNIT (regexp)->name;
2676 REGEXP_RESERV (new_regexp)->reserv_decl
2677 = DECL_RESERV (decl_in_table);
2678 regexp = new_regexp;
2679 break;
2681 default:
2682 gcc_unreachable ();
2684 break;
2685 case rm_sequence:
2686 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
2687 REGEXP_SEQUENCE (regexp)->regexps [i]
2688 = process_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
2689 break;
2690 case rm_allof:
2691 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
2692 REGEXP_ALLOF (regexp)->regexps [i]
2693 = process_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
2694 break;
2695 case rm_oneof:
2696 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
2697 REGEXP_ONEOF (regexp)->regexps [i]
2698 = process_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
2699 break;
2700 case rm_repeat:
2701 REGEXP_REPEAT (regexp)->regexp
2702 = process_regexp (REGEXP_REPEAT (regexp)->regexp);
2703 break;
2704 case rm_nothing:
2705 break;
2706 default:
2707 gcc_unreachable ();
2709 return regexp;
2712 /* The following function processes regexp of define_reservation and
2713 define_insn_reservation with the aid of function
2714 `process_regexp'. */
2715 static void
2716 process_regexp_decls (void)
2718 decl_t decl;
2719 int i;
2721 for (i = 0; i < description->decls_num; i++)
2723 decl = description->decls [i];
2724 if (decl->mode == dm_reserv)
2725 DECL_RESERV (decl)->regexp
2726 = process_regexp (DECL_RESERV (decl)->regexp);
2727 else if (decl->mode == dm_insn_reserv)
2728 DECL_INSN_RESERV (decl)->regexp
2729 = process_regexp (DECL_INSN_RESERV (decl)->regexp);
2733 /* The following function checks that declared unit is used. If the
2734 unit is not used, the function fixes errors/warnings. The
2735 following function must be called only after `process_decls',
2736 `process_regexp_decls'. */
2737 static void
2738 check_usage (void)
2740 decl_t decl;
2741 int i;
2743 for (i = 0; i < description->decls_num; i++)
2745 decl = description->decls [i];
2746 if (decl->mode == dm_unit && !DECL_UNIT (decl)->unit_is_used)
2748 if (!w_flag)
2749 error ("unit `%s' is not used", DECL_UNIT (decl)->name);
2750 else
2751 warning (0, "unit `%s' is not used", DECL_UNIT (decl)->name);
2753 else if (decl->mode == dm_reserv && !DECL_RESERV (decl)->reserv_is_used)
2755 if (!w_flag)
2756 error ("reservation `%s' is not used", DECL_RESERV (decl)->name);
2757 else
2758 warning (0, "reservation `%s' is not used", DECL_RESERV (decl)->name);
2763 /* The following variable value is number of reservation being
2764 processed on loop recognition. */
2765 static int curr_loop_pass_num;
2767 /* The following recursive function returns nonzero value if REGEXP
2768 contains given decl or reservations in given regexp refers for
2769 given decl. */
2770 static int
2771 loop_in_regexp (regexp_t regexp, decl_t start_decl)
2773 int i;
2775 if (regexp == NULL)
2776 return 0;
2777 switch (regexp->mode)
2779 case rm_unit:
2780 return 0;
2782 case rm_reserv:
2783 if (start_decl->mode == dm_reserv
2784 && REGEXP_RESERV (regexp)->reserv_decl == DECL_RESERV (start_decl))
2785 return 1;
2786 else if (REGEXP_RESERV (regexp)->reserv_decl->loop_pass_num
2787 == curr_loop_pass_num)
2788 /* declaration has been processed. */
2789 return 0;
2790 else
2792 REGEXP_RESERV (regexp)->reserv_decl->loop_pass_num
2793 = curr_loop_pass_num;
2794 return loop_in_regexp (REGEXP_RESERV (regexp)->reserv_decl->regexp,
2795 start_decl);
2798 case rm_sequence:
2799 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
2800 if (loop_in_regexp (REGEXP_SEQUENCE (regexp)->regexps [i], start_decl))
2801 return 1;
2802 return 0;
2804 case rm_allof:
2805 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
2806 if (loop_in_regexp (REGEXP_ALLOF (regexp)->regexps [i], start_decl))
2807 return 1;
2808 return 0;
2810 case rm_oneof:
2811 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
2812 if (loop_in_regexp (REGEXP_ONEOF (regexp)->regexps [i], start_decl))
2813 return 1;
2814 return 0;
2816 case rm_repeat:
2817 return loop_in_regexp (REGEXP_REPEAT (regexp)->regexp, start_decl);
2819 case rm_nothing:
2820 return 0;
2822 default:
2823 gcc_unreachable ();
2827 /* The following function fixes errors "cycle in definition ...". The
2828 function uses function `loop_in_regexp' for that. */
2829 static void
2830 check_loops_in_regexps (void)
2832 decl_t decl;
2833 int i;
2835 for (i = 0; i < description->decls_num; i++)
2837 decl = description->decls [i];
2838 if (decl->mode == dm_reserv)
2839 DECL_RESERV (decl)->loop_pass_num = 0;
2841 for (i = 0; i < description->decls_num; i++)
2843 decl = description->decls [i];
2844 curr_loop_pass_num = i;
2846 if (decl->mode == dm_reserv)
2848 DECL_RESERV (decl)->loop_pass_num = curr_loop_pass_num;
2849 if (loop_in_regexp (DECL_RESERV (decl)->regexp, decl))
2851 gcc_assert (DECL_RESERV (decl)->regexp);
2852 error ("cycle in definition of reservation `%s'",
2853 DECL_RESERV (decl)->name);
2859 /* The function recursively processes IR of reservation and defines
2860 max and min cycle for reservation of unit. */
2861 static void
2862 process_regexp_cycles (regexp_t regexp, int max_start_cycle,
2863 int min_start_cycle, int *max_finish_cycle,
2864 int *min_finish_cycle)
2866 int i;
2868 switch (regexp->mode)
2870 case rm_unit:
2871 if (REGEXP_UNIT (regexp)->unit_decl->max_occ_cycle_num < max_start_cycle)
2872 REGEXP_UNIT (regexp)->unit_decl->max_occ_cycle_num = max_start_cycle;
2873 if (REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num > min_start_cycle
2874 || REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num == -1)
2875 REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num = min_start_cycle;
2876 *max_finish_cycle = max_start_cycle;
2877 *min_finish_cycle = min_start_cycle;
2878 break;
2880 case rm_reserv:
2881 process_regexp_cycles (REGEXP_RESERV (regexp)->reserv_decl->regexp,
2882 max_start_cycle, min_start_cycle,
2883 max_finish_cycle, min_finish_cycle);
2884 break;
2886 case rm_repeat:
2887 for (i = 0; i < REGEXP_REPEAT (regexp)->repeat_num; i++)
2889 process_regexp_cycles (REGEXP_REPEAT (regexp)->regexp,
2890 max_start_cycle, min_start_cycle,
2891 max_finish_cycle, min_finish_cycle);
2892 max_start_cycle = *max_finish_cycle + 1;
2893 min_start_cycle = *min_finish_cycle + 1;
2895 break;
2897 case rm_sequence:
2898 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
2900 process_regexp_cycles (REGEXP_SEQUENCE (regexp)->regexps [i],
2901 max_start_cycle, min_start_cycle,
2902 max_finish_cycle, min_finish_cycle);
2903 max_start_cycle = *max_finish_cycle + 1;
2904 min_start_cycle = *min_finish_cycle + 1;
2906 break;
2908 case rm_allof:
2910 int max_cycle = 0;
2911 int min_cycle = 0;
2913 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
2915 process_regexp_cycles (REGEXP_ALLOF (regexp)->regexps [i],
2916 max_start_cycle, min_start_cycle,
2917 max_finish_cycle, min_finish_cycle);
2918 if (max_cycle < *max_finish_cycle)
2919 max_cycle = *max_finish_cycle;
2920 if (i == 0 || min_cycle > *min_finish_cycle)
2921 min_cycle = *min_finish_cycle;
2923 *max_finish_cycle = max_cycle;
2924 *min_finish_cycle = min_cycle;
2926 break;
2928 case rm_oneof:
2930 int max_cycle = 0;
2931 int min_cycle = 0;
2933 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
2935 process_regexp_cycles (REGEXP_ONEOF (regexp)->regexps [i],
2936 max_start_cycle, min_start_cycle,
2937 max_finish_cycle, min_finish_cycle);
2938 if (max_cycle < *max_finish_cycle)
2939 max_cycle = *max_finish_cycle;
2940 if (i == 0 || min_cycle > *min_finish_cycle)
2941 min_cycle = *min_finish_cycle;
2943 *max_finish_cycle = max_cycle;
2944 *min_finish_cycle = min_cycle;
2946 break;
2948 case rm_nothing:
2949 *max_finish_cycle = max_start_cycle;
2950 *min_finish_cycle = min_start_cycle;
2951 break;
2953 default:
2954 gcc_unreachable ();
2958 /* The following function is called only for correct program. The
2959 function defines max reservation of insns in cycles. */
2960 static void
2961 evaluate_max_reserv_cycles (void)
2963 int max_insn_cycles_num;
2964 int min_insn_cycles_num;
2965 decl_t decl;
2966 int i;
2968 description->max_insn_reserv_cycles = 0;
2969 for (i = 0; i < description->decls_num; i++)
2971 decl = description->decls [i];
2972 if (decl->mode == dm_insn_reserv)
2974 process_regexp_cycles (DECL_INSN_RESERV (decl)->regexp, 0, 0,
2975 &max_insn_cycles_num, &min_insn_cycles_num);
2976 if (description->max_insn_reserv_cycles < max_insn_cycles_num)
2977 description->max_insn_reserv_cycles = max_insn_cycles_num;
2980 description->max_insn_reserv_cycles++;
2983 /* The following function calls functions for checking all
2984 description. */
2985 static void
2986 check_all_description (void)
2988 process_decls ();
2989 check_automaton_usage ();
2990 process_regexp_decls ();
2991 check_usage ();
2992 check_loops_in_regexps ();
2993 if (!have_error)
2994 evaluate_max_reserv_cycles ();
2999 /* The page contains abstract data `ticker'. This data is used to
3000 report time of different phases of building automata. It is
3001 possibly to write a description for which automata will be built
3002 during several minutes even on fast machine. */
3004 /* The following function creates ticker and makes it active. */
3005 static ticker_t
3006 create_ticker (void)
3008 ticker_t ticker;
3010 ticker.modified_creation_time = get_run_time ();
3011 ticker.incremented_off_time = 0;
3012 return ticker;
3015 /* The following function switches off given ticker. */
3016 static void
3017 ticker_off (ticker_t *ticker)
3019 if (ticker->incremented_off_time == 0)
3020 ticker->incremented_off_time = get_run_time () + 1;
3023 /* The following function switches on given ticker. */
3024 static void
3025 ticker_on (ticker_t *ticker)
3027 if (ticker->incremented_off_time != 0)
3029 ticker->modified_creation_time
3030 += get_run_time () - ticker->incremented_off_time + 1;
3031 ticker->incremented_off_time = 0;
3035 /* The following function returns current time in milliseconds since
3036 the moment when given ticker was created. */
3037 static int
3038 active_time (ticker_t ticker)
3040 if (ticker.incremented_off_time != 0)
3041 return ticker.incremented_off_time - 1 - ticker.modified_creation_time;
3042 else
3043 return get_run_time () - ticker.modified_creation_time;
3046 /* The following function returns string representation of active time
3047 of given ticker. The result is string representation of seconds
3048 with accuracy of 1/100 second. Only result of the last call of the
3049 function exists. Therefore the following code is not correct
3051 printf ("parser time: %s\ngeneration time: %s\n",
3052 active_time_string (parser_ticker),
3053 active_time_string (generation_ticker));
3055 Correct code has to be the following
3057 printf ("parser time: %s\n", active_time_string (parser_ticker));
3058 printf ("generation time: %s\n",
3059 active_time_string (generation_ticker));
3062 static void
3063 print_active_time (FILE *f, ticker_t ticker)
3065 int msecs;
3067 msecs = active_time (ticker);
3068 fprintf (f, "%d.%06d", msecs / 1000000, msecs % 1000000);
3073 /* The following variable value is number of automaton which are
3074 really being created. This value is defined on the base of
3075 argument of option `-split'. If the variable has zero value the
3076 number of automata is defined by the constructions `%automaton'.
3077 This case occurs when option `-split' is absent or has zero
3078 argument. If constructions `define_automaton' is absent only one
3079 automaton is created. */
3080 static int automata_num;
3082 /* The following variable values are times of
3083 o transformation of regular expressions
3084 o building NDFA (DFA if !ndfa_flag)
3085 o NDFA -> DFA (simply the same automaton if !ndfa_flag)
3086 o DFA minimization
3087 o building insn equivalence classes
3088 o all previous ones
3089 o code output */
3090 static ticker_t transform_time;
3091 static ticker_t NDFA_time;
3092 static ticker_t NDFA_to_DFA_time;
3093 static ticker_t minimize_time;
3094 static ticker_t equiv_time;
3095 static ticker_t automaton_generation_time;
3096 static ticker_t output_time;
3098 /* The following variable values are times of
3099 all checking
3100 all generation
3101 all pipeline hazard translator work */
3102 static ticker_t check_time;
3103 static ticker_t generation_time;
3104 static ticker_t all_time;
3108 /* Pseudo insn decl which denotes advancing cycle. */
3109 static decl_t advance_cycle_insn_decl;
3110 static void
3111 add_advance_cycle_insn_decl (void)
3113 advance_cycle_insn_decl = create_node (sizeof (struct decl));
3114 advance_cycle_insn_decl->mode = dm_insn_reserv;
3115 advance_cycle_insn_decl->pos = no_pos;
3116 DECL_INSN_RESERV (advance_cycle_insn_decl)->regexp = NULL;
3117 DECL_INSN_RESERV (advance_cycle_insn_decl)->name = "$advance_cycle";
3118 DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num
3119 = description->insns_num;
3120 description->decls [description->decls_num] = advance_cycle_insn_decl;
3121 description->decls_num++;
3122 description->insns_num++;
3126 /* Abstract data `alternative states' which represents
3127 nondeterministic nature of the description (see comments for
3128 structures alt_state and state). */
3130 /* List of free states. */
3131 static alt_state_t first_free_alt_state;
3133 #ifndef NDEBUG
3134 /* The following variables is maximal number of allocated nodes
3135 alt_state. */
3136 static int allocated_alt_states_num = 0;
3137 #endif
3139 /* The following function returns free node alt_state. It may be new
3140 allocated node or node freed earlier. */
3141 static alt_state_t
3142 get_free_alt_state (void)
3144 alt_state_t result;
3146 if (first_free_alt_state != NULL)
3148 result = first_free_alt_state;
3149 first_free_alt_state = first_free_alt_state->next_alt_state;
3151 else
3153 #ifndef NDEBUG
3154 allocated_alt_states_num++;
3155 #endif
3156 result = create_node (sizeof (struct alt_state));
3158 result->state = NULL;
3159 result->next_alt_state = NULL;
3160 result->next_sorted_alt_state = NULL;
3161 return result;
3164 /* The function frees node ALT_STATE. */
3165 static void
3166 free_alt_state (alt_state_t alt_state)
3168 if (alt_state == NULL)
3169 return;
3170 alt_state->next_alt_state = first_free_alt_state;
3171 first_free_alt_state = alt_state;
3174 /* The function frees list started with node ALT_STATE_LIST. */
3175 static void
3176 free_alt_states (alt_state_t alt_states_list)
3178 alt_state_t curr_alt_state;
3179 alt_state_t next_alt_state;
3181 for (curr_alt_state = alt_states_list;
3182 curr_alt_state != NULL;
3183 curr_alt_state = next_alt_state)
3185 next_alt_state = curr_alt_state->next_alt_state;
3186 free_alt_state (curr_alt_state);
3190 /* The function compares unique numbers of alt states. */
3191 static int
3192 alt_state_cmp (const void *alt_state_ptr_1, const void *alt_state_ptr_2)
3194 if ((*(alt_state_t *) alt_state_ptr_1)->state->unique_num
3195 == (*(alt_state_t *) alt_state_ptr_2)->state->unique_num)
3196 return 0;
3197 else if ((*(alt_state_t *) alt_state_ptr_1)->state->unique_num
3198 < (*(alt_state_t *) alt_state_ptr_2)->state->unique_num)
3199 return -1;
3200 else
3201 return 1;
3204 /* The function sorts ALT_STATES_LIST and removes duplicated alt
3205 states from the list. The comparison key is alt state unique
3206 number. */
3208 static alt_state_t
3209 uniq_sort_alt_states (alt_state_t alt_states_list)
3211 alt_state_t curr_alt_state;
3212 VEC(alt_state_t,heap) *alt_states;
3213 size_t i;
3214 size_t prev_unique_state_ind;
3215 alt_state_t result;
3217 if (alt_states_list == 0)
3218 return 0;
3219 if (alt_states_list->next_alt_state == 0)
3220 return alt_states_list;
3222 alt_states = VEC_alloc (alt_state_t,heap, 150);
3223 for (curr_alt_state = alt_states_list;
3224 curr_alt_state != NULL;
3225 curr_alt_state = curr_alt_state->next_alt_state)
3226 VEC_safe_push (alt_state_t,heap, alt_states, curr_alt_state);
3228 qsort (VEC_address (alt_state_t, alt_states),
3229 VEC_length (alt_state_t, alt_states),
3230 sizeof (alt_state_t), alt_state_cmp);
3232 prev_unique_state_ind = 0;
3233 for (i = 1; i < VEC_length (alt_state_t, alt_states); i++)
3234 if (VEC_index (alt_state_t, alt_states, prev_unique_state_ind)->state
3235 != VEC_index (alt_state_t, alt_states, i)->state)
3237 prev_unique_state_ind++;
3238 VEC_replace (alt_state_t, alt_states, prev_unique_state_ind,
3239 VEC_index (alt_state_t, alt_states, i));
3241 VEC_truncate (alt_state_t, alt_states, prev_unique_state_ind + 1);
3243 for (i = 1; i < VEC_length (alt_state_t, alt_states); i++)
3244 VEC_index (alt_state_t, alt_states, i-1)->next_sorted_alt_state
3245 = VEC_index (alt_state_t, alt_states, i);
3246 VEC_last (alt_state_t, alt_states)->next_sorted_alt_state = 0;
3248 result = VEC_index (alt_state_t, alt_states, 0);
3250 VEC_free (alt_state_t,heap, alt_states);
3251 return result;
3254 /* The function checks equality of alt state lists. Remember that the
3255 lists must be already sorted by the previous function. */
3256 static int
3257 alt_states_eq (alt_state_t alt_states_1, alt_state_t alt_states_2)
3259 while (alt_states_1 != NULL && alt_states_2 != NULL
3260 && alt_state_cmp (&alt_states_1, &alt_states_2) == 0)
3262 alt_states_1 = alt_states_1->next_sorted_alt_state;
3263 alt_states_2 = alt_states_2->next_sorted_alt_state;
3265 return alt_states_1 == alt_states_2;
3268 /* Initialization of the abstract data. */
3269 static void
3270 initiate_alt_states (void)
3272 first_free_alt_state = NULL;
3275 /* Finishing work with the abstract data. */
3276 static void
3277 finish_alt_states (void)
3283 /* The page contains macros for work with bits strings. We could use
3284 standard gcc bitmap or sbitmap but it would result in difficulties
3285 of building canadian cross. */
3287 /* Set bit number bitno in the bit string. The macro is not side
3288 effect proof. */
3289 #define SET_BIT(bitstring, bitno) \
3290 (((char *) (bitstring)) [(bitno) / CHAR_BIT] |= 1 << (bitno) % CHAR_BIT)
3292 #define CLEAR_BIT(bitstring, bitno) \
3293 (((char *) (bitstring)) [(bitno) / CHAR_BIT] &= ~(1 << (bitno) % CHAR_BIT))
3295 /* Test if bit number bitno in the bitstring is set. The macro is not
3296 side effect proof. */
3297 #define TEST_BIT(bitstring, bitno) \
3298 (((char *) (bitstring)) [(bitno) / CHAR_BIT] >> (bitno) % CHAR_BIT & 1)
3302 /* This page contains abstract data `state'. */
3304 /* Maximal length of reservations in cycles (>= 1). */
3305 static int max_cycles_num;
3307 /* Number of set elements (see type set_el_t) needed for
3308 representation of one cycle reservation. It is depended on units
3309 number. */
3310 static int els_in_cycle_reserv;
3312 /* Number of set elements (see type set_el_t) needed for
3313 representation of maximal length reservation. Deterministic
3314 reservation is stored as set (bit string) of length equal to the
3315 variable value * number of bits in set_el_t. */
3316 static int els_in_reservs;
3318 /* Array of pointers to unit declarations. */
3319 static unit_decl_t *units_array;
3321 /* Temporary reservation of maximal length. */
3322 static reserv_sets_t temp_reserv;
3324 /* The state table itself is represented by the following variable. */
3325 static htab_t state_table;
3327 /* Linked list of free 'state' structures to be recycled. The
3328 next_equiv_class_state pointer is borrowed for a free list. */
3329 static state_t first_free_state;
3331 static int curr_unique_state_num;
3333 #ifndef NDEBUG
3334 /* The following variables is maximal number of allocated nodes
3335 `state'. */
3336 static int allocated_states_num = 0;
3337 #endif
3339 /* Allocate new reservation set. */
3340 static reserv_sets_t
3341 alloc_empty_reserv_sets (void)
3343 reserv_sets_t result;
3345 obstack_blank (&irp, els_in_reservs * sizeof (set_el_t));
3346 result = (reserv_sets_t) obstack_base (&irp);
3347 obstack_finish (&irp);
3348 memset (result, 0, els_in_reservs * sizeof (set_el_t));
3349 return result;
3352 /* Hash value of reservation set. */
3353 static unsigned
3354 reserv_sets_hash_value (reserv_sets_t reservs)
3356 set_el_t hash_value;
3357 unsigned result;
3358 int reservs_num, i;
3359 set_el_t *reserv_ptr;
3361 hash_value = 0;
3362 reservs_num = els_in_reservs;
3363 reserv_ptr = reservs;
3364 i = 0;
3365 while (reservs_num != 0)
3367 reservs_num--;
3368 hash_value += ((*reserv_ptr >> i)
3369 | (*reserv_ptr << (sizeof (set_el_t) * CHAR_BIT - i)));
3370 i++;
3371 if (i == sizeof (set_el_t) * CHAR_BIT)
3372 i = 0;
3373 reserv_ptr++;
3375 if (sizeof (set_el_t) <= sizeof (unsigned))
3376 return hash_value;
3377 result = 0;
3378 for (i = sizeof (set_el_t); i > 0; i -= sizeof (unsigned) - 1)
3380 result += (unsigned) hash_value;
3381 hash_value >>= (sizeof (unsigned) - 1) * CHAR_BIT;
3383 return result;
3386 /* Comparison of given reservation sets. */
3387 static int
3388 reserv_sets_cmp (reserv_sets_t reservs_1, reserv_sets_t reservs_2)
3390 int reservs_num;
3391 set_el_t *reserv_ptr_1;
3392 set_el_t *reserv_ptr_2;
3394 gcc_assert (reservs_1 && reservs_2);
3395 reservs_num = els_in_reservs;
3396 reserv_ptr_1 = reservs_1;
3397 reserv_ptr_2 = reservs_2;
3398 while (reservs_num != 0 && *reserv_ptr_1 == *reserv_ptr_2)
3400 reservs_num--;
3401 reserv_ptr_1++;
3402 reserv_ptr_2++;
3404 if (reservs_num == 0)
3405 return 0;
3406 else if (*reserv_ptr_1 < *reserv_ptr_2)
3407 return -1;
3408 else
3409 return 1;
3412 /* The function checks equality of the reservation sets. */
3413 static int
3414 reserv_sets_eq (reserv_sets_t reservs_1, reserv_sets_t reservs_2)
3416 return reserv_sets_cmp (reservs_1, reservs_2) == 0;
3419 /* Set up in the reservation set that unit with UNIT_NUM is used on
3420 CYCLE_NUM. */
3421 static void
3422 set_unit_reserv (reserv_sets_t reservs, int cycle_num, int unit_num)
3424 gcc_assert (cycle_num < max_cycles_num);
3425 SET_BIT (reservs, cycle_num * els_in_cycle_reserv
3426 * sizeof (set_el_t) * CHAR_BIT + unit_num);
3429 /* Set up in the reservation set RESERVS that unit with UNIT_NUM is
3430 used on CYCLE_NUM. */
3431 static int
3432 test_unit_reserv (reserv_sets_t reservs, int cycle_num, int unit_num)
3434 gcc_assert (cycle_num < max_cycles_num);
3435 return TEST_BIT (reservs, cycle_num * els_in_cycle_reserv
3436 * sizeof (set_el_t) * CHAR_BIT + unit_num);
3439 /* The function checks that the reservation sets are intersected,
3440 i.e. there is a unit reservation on a cycle in both reservation
3441 sets. */
3442 static int
3443 reserv_sets_are_intersected (reserv_sets_t operand_1,
3444 reserv_sets_t operand_2)
3446 set_el_t *el_ptr_1;
3447 set_el_t *el_ptr_2;
3448 set_el_t *cycle_ptr_1;
3449 set_el_t *cycle_ptr_2;
3451 gcc_assert (operand_1 && operand_2);
3452 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2;
3453 el_ptr_1 < operand_1 + els_in_reservs;
3454 el_ptr_1++, el_ptr_2++)
3455 if (*el_ptr_1 & *el_ptr_2)
3456 return 1;
3457 reserv_sets_or (temp_reserv, operand_1, operand_2);
3458 for (cycle_ptr_1 = operand_1, cycle_ptr_2 = operand_2;
3459 cycle_ptr_1 < operand_1 + els_in_reservs;
3460 cycle_ptr_1 += els_in_cycle_reserv, cycle_ptr_2 += els_in_cycle_reserv)
3462 for (el_ptr_1 = cycle_ptr_1, el_ptr_2 = get_excl_set (cycle_ptr_2);
3463 el_ptr_1 < cycle_ptr_1 + els_in_cycle_reserv;
3464 el_ptr_1++, el_ptr_2++)
3465 if (*el_ptr_1 & *el_ptr_2)
3466 return 1;
3467 if (!check_presence_pattern_sets (cycle_ptr_1, cycle_ptr_2, FALSE))
3468 return 1;
3469 if (!check_presence_pattern_sets (temp_reserv + (cycle_ptr_2
3470 - operand_2),
3471 cycle_ptr_2, TRUE))
3472 return 1;
3473 if (!check_absence_pattern_sets (cycle_ptr_1, cycle_ptr_2, FALSE))
3474 return 1;
3475 if (!check_absence_pattern_sets (temp_reserv + (cycle_ptr_2 - operand_2),
3476 cycle_ptr_2, TRUE))
3477 return 1;
3479 return 0;
3482 /* The function sets up RESULT bits by bits of OPERAND shifted on one
3483 cpu cycle. The remaining bits of OPERAND (representing the last
3484 cycle unit reservations) are not changed. */
3485 static void
3486 reserv_sets_shift (reserv_sets_t result, reserv_sets_t operand)
3488 int i;
3490 gcc_assert (result && operand && result != operand);
3491 for (i = els_in_cycle_reserv; i < els_in_reservs; i++)
3492 result [i - els_in_cycle_reserv] = operand [i];
3495 /* OR of the reservation sets. */
3496 static void
3497 reserv_sets_or (reserv_sets_t result, reserv_sets_t operand_1,
3498 reserv_sets_t operand_2)
3500 set_el_t *el_ptr_1;
3501 set_el_t *el_ptr_2;
3502 set_el_t *result_set_el_ptr;
3504 gcc_assert (result && operand_1 && operand_2);
3505 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2, result_set_el_ptr = result;
3506 el_ptr_1 < operand_1 + els_in_reservs;
3507 el_ptr_1++, el_ptr_2++, result_set_el_ptr++)
3508 *result_set_el_ptr = *el_ptr_1 | *el_ptr_2;
3511 /* AND of the reservation sets. */
3512 static void
3513 reserv_sets_and (reserv_sets_t result, reserv_sets_t operand_1,
3514 reserv_sets_t operand_2)
3516 set_el_t *el_ptr_1;
3517 set_el_t *el_ptr_2;
3518 set_el_t *result_set_el_ptr;
3520 gcc_assert (result && operand_1 && operand_2);
3521 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2, result_set_el_ptr = result;
3522 el_ptr_1 < operand_1 + els_in_reservs;
3523 el_ptr_1++, el_ptr_2++, result_set_el_ptr++)
3524 *result_set_el_ptr = *el_ptr_1 & *el_ptr_2;
3527 /* The function outputs string representation of units reservation on
3528 cycle START_CYCLE in the reservation set. The function uses repeat
3529 construction if REPETITION_NUM > 1. */
3530 static void
3531 output_cycle_reservs (FILE *f, reserv_sets_t reservs, int start_cycle,
3532 int repetition_num)
3534 int unit_num;
3535 int reserved_units_num;
3537 reserved_units_num = 0;
3538 for (unit_num = 0; unit_num < description->units_num; unit_num++)
3539 if (TEST_BIT (reservs, start_cycle * els_in_cycle_reserv
3540 * sizeof (set_el_t) * CHAR_BIT + unit_num))
3541 reserved_units_num++;
3542 gcc_assert (repetition_num > 0);
3543 if (repetition_num != 1 && reserved_units_num > 1)
3544 fprintf (f, "(");
3545 reserved_units_num = 0;
3546 for (unit_num = 0;
3547 unit_num < description->units_num;
3548 unit_num++)
3549 if (TEST_BIT (reservs, start_cycle * els_in_cycle_reserv
3550 * sizeof (set_el_t) * CHAR_BIT + unit_num))
3552 if (reserved_units_num != 0)
3553 fprintf (f, "+");
3554 reserved_units_num++;
3555 fprintf (f, "%s", units_array [unit_num]->name);
3557 if (reserved_units_num == 0)
3558 fprintf (f, NOTHING_NAME);
3559 gcc_assert (repetition_num > 0);
3560 if (repetition_num != 1 && reserved_units_num > 1)
3561 fprintf (f, ")");
3562 if (repetition_num != 1)
3563 fprintf (f, "*%d", repetition_num);
3566 /* The function outputs string representation of units reservation in
3567 the reservation set. */
3568 static void
3569 output_reserv_sets (FILE *f, reserv_sets_t reservs)
3571 int start_cycle = 0;
3572 int cycle;
3573 int repetition_num;
3575 repetition_num = 0;
3576 for (cycle = 0; cycle < max_cycles_num; cycle++)
3577 if (repetition_num == 0)
3579 repetition_num++;
3580 start_cycle = cycle;
3582 else if (memcmp
3583 ((char *) reservs + start_cycle * els_in_cycle_reserv
3584 * sizeof (set_el_t),
3585 (char *) reservs + cycle * els_in_cycle_reserv
3586 * sizeof (set_el_t),
3587 els_in_cycle_reserv * sizeof (set_el_t)) == 0)
3588 repetition_num++;
3589 else
3591 if (start_cycle != 0)
3592 fprintf (f, ", ");
3593 output_cycle_reservs (f, reservs, start_cycle, repetition_num);
3594 repetition_num = 1;
3595 start_cycle = cycle;
3597 if (start_cycle < max_cycles_num)
3599 if (start_cycle != 0)
3600 fprintf (f, ", ");
3601 output_cycle_reservs (f, reservs, start_cycle, repetition_num);
3605 /* The following function returns free node state for AUTOMATON. It
3606 may be new allocated node or node freed earlier. The function also
3607 allocates reservation set if WITH_RESERVS has nonzero value. */
3608 static state_t
3609 get_free_state (int with_reservs, automaton_t automaton)
3611 state_t result;
3613 gcc_assert (max_cycles_num > 0 && automaton);
3614 if (first_free_state)
3616 result = first_free_state;
3617 first_free_state = result->next_equiv_class_state;
3619 result->next_equiv_class_state = NULL;
3620 result->automaton = automaton;
3621 result->first_out_arc = NULL;
3622 result->it_was_placed_in_stack_for_NDFA_forming = 0;
3623 result->it_was_placed_in_stack_for_DFA_forming = 0;
3624 result->component_states = NULL;
3625 result->longest_path_length = UNDEFINED_LONGEST_PATH_LENGTH;
3627 else
3629 #ifndef NDEBUG
3630 allocated_states_num++;
3631 #endif
3632 result = create_node (sizeof (struct state));
3633 result->automaton = automaton;
3634 result->first_out_arc = NULL;
3635 result->unique_num = curr_unique_state_num;
3636 result->longest_path_length = UNDEFINED_LONGEST_PATH_LENGTH;
3637 curr_unique_state_num++;
3639 if (with_reservs)
3641 if (result->reservs == NULL)
3642 result->reservs = alloc_empty_reserv_sets ();
3643 else
3644 memset (result->reservs, 0, els_in_reservs * sizeof (set_el_t));
3646 return result;
3649 /* The function frees node STATE. */
3650 static void
3651 free_state (state_t state)
3653 free_alt_states (state->component_states);
3654 state->next_equiv_class_state = first_free_state;
3655 first_free_state = state;
3658 /* Hash value of STATE. If STATE represents deterministic state it is
3659 simply hash value of the corresponding reservation set. Otherwise
3660 it is formed from hash values of the component deterministic
3661 states. One more key is order number of state automaton. */
3662 static hashval_t
3663 state_hash (const void *state)
3665 unsigned int hash_value;
3666 alt_state_t alt_state;
3668 if (((state_t) state)->component_states == NULL)
3669 hash_value = reserv_sets_hash_value (((state_t) state)->reservs);
3670 else
3672 hash_value = 0;
3673 for (alt_state = ((state_t) state)->component_states;
3674 alt_state != NULL;
3675 alt_state = alt_state->next_sorted_alt_state)
3676 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
3677 | (hash_value << CHAR_BIT))
3678 + alt_state->state->unique_num);
3680 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
3681 | (hash_value << CHAR_BIT))
3682 + ((state_t) state)->automaton->automaton_order_num);
3683 return hash_value;
3686 /* Return nonzero value if the states are the same. */
3687 static int
3688 state_eq_p (const void *state_1, const void *state_2)
3690 alt_state_t alt_state_1;
3691 alt_state_t alt_state_2;
3693 if (((state_t) state_1)->automaton != ((state_t) state_2)->automaton)
3694 return 0;
3695 else if (((state_t) state_1)->component_states == NULL
3696 && ((state_t) state_2)->component_states == NULL)
3697 return reserv_sets_eq (((state_t) state_1)->reservs,
3698 ((state_t) state_2)->reservs);
3699 else if (((state_t) state_1)->component_states != NULL
3700 && ((state_t) state_2)->component_states != NULL)
3702 for (alt_state_1 = ((state_t) state_1)->component_states,
3703 alt_state_2 = ((state_t) state_2)->component_states;
3704 alt_state_1 != NULL && alt_state_2 != NULL;
3705 alt_state_1 = alt_state_1->next_sorted_alt_state,
3706 alt_state_2 = alt_state_2->next_sorted_alt_state)
3707 /* All state in the list must be already in the hash table.
3708 Also the lists must be sorted. */
3709 if (alt_state_1->state != alt_state_2->state)
3710 return 0;
3711 return alt_state_1 == alt_state_2;
3713 else
3714 return 0;
3717 /* Insert STATE into the state table. */
3718 static state_t
3719 insert_state (state_t state)
3721 void **entry_ptr;
3723 entry_ptr = htab_find_slot (state_table, (void *) state, 1);
3724 if (*entry_ptr == NULL)
3725 *entry_ptr = (void *) state;
3726 return (state_t) *entry_ptr;
3729 /* Add reservation of unit with UNIT_NUM on cycle CYCLE_NUM to
3730 deterministic STATE. */
3731 static void
3732 set_state_reserv (state_t state, int cycle_num, int unit_num)
3734 set_unit_reserv (state->reservs, cycle_num, unit_num);
3737 /* Return nonzero value if the deterministic states contains a
3738 reservation of the same cpu unit on the same cpu cycle. */
3739 static int
3740 intersected_state_reservs_p (state_t state1, state_t state2)
3742 gcc_assert (state1->automaton == state2->automaton);
3743 return reserv_sets_are_intersected (state1->reservs, state2->reservs);
3746 /* Return deterministic state (inserted into the table) which
3747 representing the automaton state which is union of reservations of
3748 the deterministic states masked by RESERVS. */
3749 static state_t
3750 states_union (state_t state1, state_t state2, reserv_sets_t reservs)
3752 state_t result;
3753 state_t state_in_table;
3755 gcc_assert (state1->automaton == state2->automaton);
3756 result = get_free_state (1, state1->automaton);
3757 reserv_sets_or (result->reservs, state1->reservs, state2->reservs);
3758 reserv_sets_and (result->reservs, result->reservs, reservs);
3759 state_in_table = insert_state (result);
3760 if (result != state_in_table)
3762 free_state (result);
3763 result = state_in_table;
3765 return result;
3768 /* Return deterministic state (inserted into the table) which
3769 represent the automaton state is obtained from deterministic STATE
3770 by advancing cpu cycle and masking by RESERVS. */
3771 static state_t
3772 state_shift (state_t state, reserv_sets_t reservs)
3774 state_t result;
3775 state_t state_in_table;
3777 result = get_free_state (1, state->automaton);
3778 reserv_sets_shift (result->reservs, state->reservs);
3779 reserv_sets_and (result->reservs, result->reservs, reservs);
3780 state_in_table = insert_state (result);
3781 if (result != state_in_table)
3783 free_state (result);
3784 result = state_in_table;
3786 return result;
3789 /* Initialization of the abstract data. */
3790 static void
3791 initiate_states (void)
3793 decl_t decl;
3794 int i;
3796 if (description->units_num)
3797 units_array = XNEWVEC (unit_decl_t, description->units_num);
3798 else
3799 units_array = 0;
3801 for (i = 0; i < description->decls_num; i++)
3803 decl = description->decls [i];
3804 if (decl->mode == dm_unit)
3805 units_array [DECL_UNIT (decl)->unit_num] = DECL_UNIT (decl);
3807 max_cycles_num = description->max_insn_reserv_cycles;
3808 els_in_cycle_reserv
3809 = ((description->units_num + sizeof (set_el_t) * CHAR_BIT - 1)
3810 / (sizeof (set_el_t) * CHAR_BIT));
3811 els_in_reservs = els_in_cycle_reserv * max_cycles_num;
3812 curr_unique_state_num = 0;
3813 initiate_alt_states ();
3814 state_table = htab_create (1500, state_hash, state_eq_p, (htab_del) 0);
3815 temp_reserv = alloc_empty_reserv_sets ();
3818 /* Finishing work with the abstract data. */
3819 static void
3820 finish_states (void)
3822 free (units_array);
3823 units_array = 0;
3824 htab_delete (state_table);
3825 first_free_state = NULL;
3826 finish_alt_states ();
3831 /* Abstract data `arcs'. */
3833 /* List of free arcs. */
3834 static arc_t first_free_arc;
3836 #ifndef NDEBUG
3837 /* The following variables is maximal number of allocated nodes
3838 `arc'. */
3839 static int allocated_arcs_num = 0;
3840 #endif
3842 /* The function frees node ARC. */
3843 static void
3844 free_arc (arc_t arc)
3846 arc->next_out_arc = first_free_arc;
3847 first_free_arc = arc;
3850 /* The function removes and frees ARC staring from FROM_STATE. */
3851 static void
3852 remove_arc (state_t from_state, arc_t arc)
3854 arc_t prev_arc;
3855 arc_t curr_arc;
3857 gcc_assert (arc);
3858 for (prev_arc = NULL, curr_arc = from_state->first_out_arc;
3859 curr_arc != NULL;
3860 prev_arc = curr_arc, curr_arc = curr_arc->next_out_arc)
3861 if (curr_arc == arc)
3862 break;
3863 gcc_assert (curr_arc);
3864 if (prev_arc == NULL)
3865 from_state->first_out_arc = arc->next_out_arc;
3866 else
3867 prev_arc->next_out_arc = arc->next_out_arc;
3868 from_state->num_out_arcs--;
3869 free_arc (arc);
3872 /* The functions returns arc with given characteristics (or NULL if
3873 the arc does not exist). */
3874 static arc_t
3875 find_arc (state_t from_state, state_t to_state, ainsn_t insn)
3877 arc_t arc;
3879 for (arc = first_out_arc (from_state); arc != NULL; arc = next_out_arc (arc))
3880 if (arc->to_state == to_state && arc->insn == insn)
3881 return arc;
3882 return NULL;
3885 /* The function adds arc from FROM_STATE to TO_STATE marked by AINSN.
3886 The function returns added arc (or already existing arc). */
3887 static arc_t
3888 add_arc (state_t from_state, state_t to_state, ainsn_t ainsn)
3890 arc_t new_arc;
3892 new_arc = find_arc (from_state, to_state, ainsn);
3893 if (new_arc != NULL)
3894 return new_arc;
3895 if (first_free_arc == NULL)
3897 #ifndef NDEBUG
3898 allocated_arcs_num++;
3899 #endif
3900 new_arc = create_node (sizeof (struct arc));
3901 new_arc->to_state = NULL;
3902 new_arc->insn = NULL;
3903 new_arc->next_out_arc = NULL;
3905 else
3907 new_arc = first_free_arc;
3908 first_free_arc = first_free_arc->next_out_arc;
3910 new_arc->to_state = to_state;
3911 new_arc->insn = ainsn;
3912 ainsn->arc_exists_p = 1;
3913 new_arc->next_out_arc = from_state->first_out_arc;
3914 from_state->first_out_arc = new_arc;
3915 from_state->num_out_arcs++;
3916 new_arc->next_arc_marked_by_insn = NULL;
3917 return new_arc;
3920 /* The function returns the first arc starting from STATE. */
3921 static arc_t
3922 first_out_arc (state_t state)
3924 return state->first_out_arc;
3927 /* The function returns next out arc after ARC. */
3928 static arc_t
3929 next_out_arc (arc_t arc)
3931 return arc->next_out_arc;
3934 /* Initialization of the abstract data. */
3935 static void
3936 initiate_arcs (void)
3938 first_free_arc = NULL;
3941 /* Finishing work with the abstract data. */
3942 static void
3943 finish_arcs (void)
3949 /* Abstract data `automata lists'. */
3951 /* List of free states. */
3952 static automata_list_el_t first_free_automata_list_el;
3954 /* The list being formed. */
3955 static automata_list_el_t current_automata_list;
3957 /* Hash table of automata lists. */
3958 static htab_t automata_list_table;
3960 /* The following function returns free automata list el. It may be
3961 new allocated node or node freed earlier. */
3962 static automata_list_el_t
3963 get_free_automata_list_el (void)
3965 automata_list_el_t result;
3967 if (first_free_automata_list_el != NULL)
3969 result = first_free_automata_list_el;
3970 first_free_automata_list_el
3971 = first_free_automata_list_el->next_automata_list_el;
3973 else
3974 result = create_node (sizeof (struct automata_list_el));
3975 result->automaton = NULL;
3976 result->next_automata_list_el = NULL;
3977 return result;
3980 /* The function frees node AUTOMATA_LIST_EL. */
3981 static void
3982 free_automata_list_el (automata_list_el_t automata_list_el)
3984 if (automata_list_el == NULL)
3985 return;
3986 automata_list_el->next_automata_list_el = first_free_automata_list_el;
3987 first_free_automata_list_el = automata_list_el;
3990 /* The function frees list AUTOMATA_LIST. */
3991 static void
3992 free_automata_list (automata_list_el_t automata_list)
3994 automata_list_el_t curr_automata_list_el;
3995 automata_list_el_t next_automata_list_el;
3997 for (curr_automata_list_el = automata_list;
3998 curr_automata_list_el != NULL;
3999 curr_automata_list_el = next_automata_list_el)
4001 next_automata_list_el = curr_automata_list_el->next_automata_list_el;
4002 free_automata_list_el (curr_automata_list_el);
4006 /* Hash value of AUTOMATA_LIST. */
4007 static hashval_t
4008 automata_list_hash (const void *automata_list)
4010 unsigned int hash_value;
4011 automata_list_el_t curr_automata_list_el;
4013 hash_value = 0;
4014 for (curr_automata_list_el = (automata_list_el_t) automata_list;
4015 curr_automata_list_el != NULL;
4016 curr_automata_list_el = curr_automata_list_el->next_automata_list_el)
4017 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
4018 | (hash_value << CHAR_BIT))
4019 + curr_automata_list_el->automaton->automaton_order_num);
4020 return hash_value;
4023 /* Return nonzero value if the automata_lists are the same. */
4024 static int
4025 automata_list_eq_p (const void *automata_list_1, const void *automata_list_2)
4027 automata_list_el_t automata_list_el_1;
4028 automata_list_el_t automata_list_el_2;
4030 for (automata_list_el_1 = (automata_list_el_t) automata_list_1,
4031 automata_list_el_2 = (automata_list_el_t) automata_list_2;
4032 automata_list_el_1 != NULL && automata_list_el_2 != NULL;
4033 automata_list_el_1 = automata_list_el_1->next_automata_list_el,
4034 automata_list_el_2 = automata_list_el_2->next_automata_list_el)
4035 if (automata_list_el_1->automaton != automata_list_el_2->automaton)
4036 return 0;
4037 return automata_list_el_1 == automata_list_el_2;
4040 /* Initialization of the abstract data. */
4041 static void
4042 initiate_automata_lists (void)
4044 first_free_automata_list_el = NULL;
4045 automata_list_table = htab_create (1500, automata_list_hash,
4046 automata_list_eq_p, (htab_del) 0);
4049 /* The following function starts new automata list and makes it the
4050 current one. */
4051 static void
4052 automata_list_start (void)
4054 current_automata_list = NULL;
4057 /* The following function adds AUTOMATON to the current list. */
4058 static void
4059 automata_list_add (automaton_t automaton)
4061 automata_list_el_t el;
4063 el = get_free_automata_list_el ();
4064 el->automaton = automaton;
4065 el->next_automata_list_el = current_automata_list;
4066 current_automata_list = el;
4069 /* The following function finishes forming the current list, inserts
4070 it into the table and returns it. */
4071 static automata_list_el_t
4072 automata_list_finish (void)
4074 void **entry_ptr;
4076 if (current_automata_list == NULL)
4077 return NULL;
4078 entry_ptr = htab_find_slot (automata_list_table,
4079 (void *) current_automata_list, 1);
4080 if (*entry_ptr == NULL)
4081 *entry_ptr = (void *) current_automata_list;
4082 else
4083 free_automata_list (current_automata_list);
4084 current_automata_list = NULL;
4085 return (automata_list_el_t) *entry_ptr;
4088 /* Finishing work with the abstract data. */
4089 static void
4090 finish_automata_lists (void)
4092 htab_delete (automata_list_table);
4097 /* The page contains abstract data for work with exclusion sets (see
4098 exclusion_set in file rtl.def). */
4100 /* The following variable refers to an exclusion set returned by
4101 get_excl_set. This is bit string of length equal to cpu units
4102 number. If exclusion set for given unit contains 1 for a unit,
4103 then simultaneous reservation of the units is prohibited. */
4104 static reserv_sets_t excl_set;
4106 /* The array contains exclusion sets for each unit. */
4107 static reserv_sets_t *unit_excl_set_table;
4109 /* The following function forms the array containing exclusion sets
4110 for each unit. */
4111 static void
4112 initiate_excl_sets (void)
4114 decl_t decl;
4115 reserv_sets_t unit_excl_set;
4116 unit_set_el_t el;
4117 int i;
4119 obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4120 excl_set = (reserv_sets_t) obstack_base (&irp);
4121 obstack_finish (&irp);
4122 obstack_blank (&irp, description->units_num * sizeof (reserv_sets_t));
4123 unit_excl_set_table = (reserv_sets_t *) obstack_base (&irp);
4124 obstack_finish (&irp);
4125 /* Evaluate unit exclusion sets. */
4126 for (i = 0; i < description->decls_num; i++)
4128 decl = description->decls [i];
4129 if (decl->mode == dm_unit)
4131 obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4132 unit_excl_set = (reserv_sets_t) obstack_base (&irp);
4133 obstack_finish (&irp);
4134 memset (unit_excl_set, 0, els_in_cycle_reserv * sizeof (set_el_t));
4135 for (el = DECL_UNIT (decl)->excl_list;
4136 el != NULL;
4137 el = el->next_unit_set_el)
4139 SET_BIT (unit_excl_set, el->unit_decl->unit_num);
4140 el->unit_decl->in_set_p = TRUE;
4142 unit_excl_set_table [DECL_UNIT (decl)->unit_num] = unit_excl_set;
4147 /* The function sets up and return EXCL_SET which is union of
4148 exclusion sets for each unit in IN_SET. */
4149 static reserv_sets_t
4150 get_excl_set (reserv_sets_t in_set)
4152 int excl_char_num;
4153 int chars_num;
4154 int i;
4155 int start_unit_num;
4156 int unit_num;
4158 chars_num = els_in_cycle_reserv * sizeof (set_el_t);
4159 memset (excl_set, 0, chars_num);
4160 for (excl_char_num = 0; excl_char_num < chars_num; excl_char_num++)
4161 if (((unsigned char *) in_set) [excl_char_num])
4162 for (i = CHAR_BIT - 1; i >= 0; i--)
4163 if ((((unsigned char *) in_set) [excl_char_num] >> i) & 1)
4165 start_unit_num = excl_char_num * CHAR_BIT + i;
4166 if (start_unit_num >= description->units_num)
4167 return excl_set;
4168 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4170 excl_set [unit_num]
4171 |= unit_excl_set_table [start_unit_num] [unit_num];
4174 return excl_set;
4179 /* The page contains abstract data for work with presence/absence
4180 pattern sets (see presence_set/absence_set in file rtl.def). */
4182 /* The following arrays contain correspondingly presence, final
4183 presence, absence, and final absence patterns for each unit. */
4184 static pattern_reserv_t *unit_presence_set_table;
4185 static pattern_reserv_t *unit_final_presence_set_table;
4186 static pattern_reserv_t *unit_absence_set_table;
4187 static pattern_reserv_t *unit_final_absence_set_table;
4189 /* The following function forms list of reservation sets for given
4190 PATTERN_LIST. */
4191 static pattern_reserv_t
4192 form_reserv_sets_list (pattern_set_el_t pattern_list)
4194 pattern_set_el_t el;
4195 pattern_reserv_t first, curr, prev;
4196 int i;
4198 prev = first = NULL;
4199 for (el = pattern_list; el != NULL; el = el->next_pattern_set_el)
4201 curr = create_node (sizeof (struct pattern_reserv));
4202 curr->reserv = alloc_empty_reserv_sets ();
4203 curr->next_pattern_reserv = NULL;
4204 for (i = 0; i < el->units_num; i++)
4206 SET_BIT (curr->reserv, el->unit_decls [i]->unit_num);
4207 el->unit_decls [i]->in_set_p = TRUE;
4209 if (prev != NULL)
4210 prev->next_pattern_reserv = curr;
4211 else
4212 first = curr;
4213 prev = curr;
4215 return first;
4218 /* The following function forms the array containing presence and
4219 absence pattern sets for each unit. */
4220 static void
4221 initiate_presence_absence_pattern_sets (void)
4223 decl_t decl;
4224 int i;
4226 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4227 unit_presence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4228 obstack_finish (&irp);
4229 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4230 unit_final_presence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4231 obstack_finish (&irp);
4232 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4233 unit_absence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4234 obstack_finish (&irp);
4235 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4236 unit_final_absence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4237 obstack_finish (&irp);
4238 /* Evaluate unit presence/absence sets. */
4239 for (i = 0; i < description->decls_num; i++)
4241 decl = description->decls [i];
4242 if (decl->mode == dm_unit)
4244 unit_presence_set_table [DECL_UNIT (decl)->unit_num]
4245 = form_reserv_sets_list (DECL_UNIT (decl)->presence_list);
4246 unit_final_presence_set_table [DECL_UNIT (decl)->unit_num]
4247 = form_reserv_sets_list (DECL_UNIT (decl)->final_presence_list);
4248 unit_absence_set_table [DECL_UNIT (decl)->unit_num]
4249 = form_reserv_sets_list (DECL_UNIT (decl)->absence_list);
4250 unit_final_absence_set_table [DECL_UNIT (decl)->unit_num]
4251 = form_reserv_sets_list (DECL_UNIT (decl)->final_absence_list);
4256 /* The function checks that CHECKED_SET satisfies all presence pattern
4257 sets for units in ORIGIONAL_SET. The function returns TRUE if it
4258 is ok. */
4259 static int
4260 check_presence_pattern_sets (reserv_sets_t checked_set,
4261 reserv_sets_t origional_set,
4262 int final_p)
4264 int char_num;
4265 int chars_num;
4266 int i;
4267 int start_unit_num;
4268 int unit_num;
4269 int presence_p;
4270 pattern_reserv_t pat_reserv;
4272 chars_num = els_in_cycle_reserv * sizeof (set_el_t);
4273 for (char_num = 0; char_num < chars_num; char_num++)
4274 if (((unsigned char *) origional_set) [char_num])
4275 for (i = CHAR_BIT - 1; i >= 0; i--)
4276 if ((((unsigned char *) origional_set) [char_num] >> i) & 1)
4278 start_unit_num = char_num * CHAR_BIT + i;
4279 if (start_unit_num >= description->units_num)
4280 break;
4281 if ((final_p
4282 && unit_final_presence_set_table [start_unit_num] == NULL)
4283 || (!final_p
4284 && unit_presence_set_table [start_unit_num] == NULL))
4285 continue;
4286 presence_p = FALSE;
4287 for (pat_reserv = (final_p
4288 ? unit_final_presence_set_table [start_unit_num]
4289 : unit_presence_set_table [start_unit_num]);
4290 pat_reserv != NULL;
4291 pat_reserv = pat_reserv->next_pattern_reserv)
4293 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4294 if ((checked_set [unit_num] & pat_reserv->reserv [unit_num])
4295 != pat_reserv->reserv [unit_num])
4296 break;
4297 presence_p = presence_p || unit_num >= els_in_cycle_reserv;
4299 if (!presence_p)
4300 return FALSE;
4302 return TRUE;
4305 /* The function checks that CHECKED_SET satisfies all absence pattern
4306 sets for units in ORIGIONAL_SET. The function returns TRUE if it
4307 is ok. */
4308 static int
4309 check_absence_pattern_sets (reserv_sets_t checked_set,
4310 reserv_sets_t origional_set,
4311 int final_p)
4313 int char_num;
4314 int chars_num;
4315 int i;
4316 int start_unit_num;
4317 int unit_num;
4318 pattern_reserv_t pat_reserv;
4320 chars_num = els_in_cycle_reserv * sizeof (set_el_t);
4321 for (char_num = 0; char_num < chars_num; char_num++)
4322 if (((unsigned char *) origional_set) [char_num])
4323 for (i = CHAR_BIT - 1; i >= 0; i--)
4324 if ((((unsigned char *) origional_set) [char_num] >> i) & 1)
4326 start_unit_num = char_num * CHAR_BIT + i;
4327 if (start_unit_num >= description->units_num)
4328 break;
4329 for (pat_reserv = (final_p
4330 ? unit_final_absence_set_table [start_unit_num]
4331 : unit_absence_set_table [start_unit_num]);
4332 pat_reserv != NULL;
4333 pat_reserv = pat_reserv->next_pattern_reserv)
4335 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4336 if ((checked_set [unit_num] & pat_reserv->reserv [unit_num])
4337 != pat_reserv->reserv [unit_num]
4338 && pat_reserv->reserv [unit_num])
4339 break;
4340 if (unit_num >= els_in_cycle_reserv)
4341 return FALSE;
4344 return TRUE;
4349 /* This page contains code for transformation of original reservations
4350 described in .md file. The main goal of transformations is
4351 simplifying reservation and lifting up all `|' on the top of IR
4352 reservation representation. */
4355 /* The following function makes copy of IR representation of
4356 reservation. The function also substitutes all reservations
4357 defined by define_reservation by corresponding value during making
4358 the copy. */
4359 static regexp_t
4360 copy_insn_regexp (regexp_t regexp)
4362 regexp_t result;
4363 int i;
4365 switch (regexp->mode)
4367 case rm_reserv:
4368 result = copy_insn_regexp (REGEXP_RESERV (regexp)->reserv_decl->regexp);
4369 break;
4371 case rm_unit:
4372 result = copy_node (regexp, sizeof (struct regexp));
4373 break;
4375 case rm_repeat:
4376 result = copy_node (regexp, sizeof (struct regexp));
4377 REGEXP_REPEAT (result)->regexp
4378 = copy_insn_regexp (REGEXP_REPEAT (regexp)->regexp);
4379 break;
4381 case rm_sequence:
4382 result = copy_node (regexp,
4383 sizeof (struct regexp) + sizeof (regexp_t)
4384 * (REGEXP_SEQUENCE (regexp)->regexps_num - 1));
4385 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4386 REGEXP_SEQUENCE (result)->regexps [i]
4387 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4388 break;
4390 case rm_allof:
4391 result = copy_node (regexp,
4392 sizeof (struct regexp) + sizeof (regexp_t)
4393 * (REGEXP_ALLOF (regexp)->regexps_num - 1));
4394 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4395 REGEXP_ALLOF (result)->regexps [i]
4396 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4397 break;
4399 case rm_oneof:
4400 result = copy_node (regexp,
4401 sizeof (struct regexp) + sizeof (regexp_t)
4402 * (REGEXP_ONEOF (regexp)->regexps_num - 1));
4403 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4404 REGEXP_ONEOF (result)->regexps [i]
4405 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4406 break;
4408 case rm_nothing:
4409 result = copy_node (regexp, sizeof (struct regexp));
4410 break;
4412 default:
4413 gcc_unreachable ();
4415 return result;
4418 /* The following variable is set up 1 if a transformation has been
4419 applied. */
4420 static int regexp_transformed_p;
4422 /* The function makes transformation
4423 A*N -> A, A, ... */
4424 static regexp_t
4425 transform_1 (regexp_t regexp)
4427 int i;
4428 int repeat_num;
4429 regexp_t operand;
4430 pos_t pos;
4432 if (regexp->mode == rm_repeat)
4434 repeat_num = REGEXP_REPEAT (regexp)->repeat_num;
4435 gcc_assert (repeat_num > 1);
4436 operand = REGEXP_REPEAT (regexp)->regexp;
4437 pos = regexp->mode;
4438 regexp = create_node (sizeof (struct regexp) + sizeof (regexp_t)
4439 * (repeat_num - 1));
4440 regexp->mode = rm_sequence;
4441 regexp->pos = pos;
4442 REGEXP_SEQUENCE (regexp)->regexps_num = repeat_num;
4443 for (i = 0; i < repeat_num; i++)
4444 REGEXP_SEQUENCE (regexp)->regexps [i] = copy_insn_regexp (operand);
4445 regexp_transformed_p = 1;
4447 return regexp;
4450 /* The function makes transformations
4451 ...,(A,B,...),C,... -> ...,A,B,...,C,...
4452 ...+(A+B+...)+C+... -> ...+A+B+...+C+...
4453 ...|(A|B|...)|C|... -> ...|A|B|...|C|... */
4454 static regexp_t
4455 transform_2 (regexp_t regexp)
4457 if (regexp->mode == rm_sequence)
4459 regexp_t sequence = NULL;
4460 regexp_t result;
4461 int sequence_index = 0;
4462 int i, j;
4464 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4465 if (REGEXP_SEQUENCE (regexp)->regexps [i]->mode == rm_sequence)
4467 sequence_index = i;
4468 sequence = REGEXP_SEQUENCE (regexp)->regexps [i];
4469 break;
4471 if (i < REGEXP_SEQUENCE (regexp)->regexps_num)
4473 gcc_assert (REGEXP_SEQUENCE (sequence)->regexps_num > 1
4474 && REGEXP_SEQUENCE (regexp)->regexps_num > 1);
4475 result = create_node (sizeof (struct regexp)
4476 + sizeof (regexp_t)
4477 * (REGEXP_SEQUENCE (regexp)->regexps_num
4478 + REGEXP_SEQUENCE (sequence)->regexps_num
4479 - 2));
4480 result->mode = rm_sequence;
4481 result->pos = regexp->pos;
4482 REGEXP_SEQUENCE (result)->regexps_num
4483 = (REGEXP_SEQUENCE (regexp)->regexps_num
4484 + REGEXP_SEQUENCE (sequence)->regexps_num - 1);
4485 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4486 if (i < sequence_index)
4487 REGEXP_SEQUENCE (result)->regexps [i]
4488 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4489 else if (i > sequence_index)
4490 REGEXP_SEQUENCE (result)->regexps
4491 [i + REGEXP_SEQUENCE (sequence)->regexps_num - 1]
4492 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4493 else
4494 for (j = 0; j < REGEXP_SEQUENCE (sequence)->regexps_num; j++)
4495 REGEXP_SEQUENCE (result)->regexps [i + j]
4496 = copy_insn_regexp (REGEXP_SEQUENCE (sequence)->regexps [j]);
4497 regexp_transformed_p = 1;
4498 regexp = result;
4501 else if (regexp->mode == rm_allof)
4503 regexp_t allof = NULL;
4504 regexp_t result;
4505 int allof_index = 0;
4506 int i, j;
4508 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4509 if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_allof)
4511 allof_index = i;
4512 allof = REGEXP_ALLOF (regexp)->regexps [i];
4513 break;
4515 if (i < REGEXP_ALLOF (regexp)->regexps_num)
4517 gcc_assert (REGEXP_ALLOF (allof)->regexps_num > 1
4518 && REGEXP_ALLOF (regexp)->regexps_num > 1);
4519 result = create_node (sizeof (struct regexp)
4520 + sizeof (regexp_t)
4521 * (REGEXP_ALLOF (regexp)->regexps_num
4522 + REGEXP_ALLOF (allof)->regexps_num - 2));
4523 result->mode = rm_allof;
4524 result->pos = regexp->pos;
4525 REGEXP_ALLOF (result)->regexps_num
4526 = (REGEXP_ALLOF (regexp)->regexps_num
4527 + REGEXP_ALLOF (allof)->regexps_num - 1);
4528 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4529 if (i < allof_index)
4530 REGEXP_ALLOF (result)->regexps [i]
4531 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4532 else if (i > allof_index)
4533 REGEXP_ALLOF (result)->regexps
4534 [i + REGEXP_ALLOF (allof)->regexps_num - 1]
4535 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4536 else
4537 for (j = 0; j < REGEXP_ALLOF (allof)->regexps_num; j++)
4538 REGEXP_ALLOF (result)->regexps [i + j]
4539 = copy_insn_regexp (REGEXP_ALLOF (allof)->regexps [j]);
4540 regexp_transformed_p = 1;
4541 regexp = result;
4544 else if (regexp->mode == rm_oneof)
4546 regexp_t oneof = NULL;
4547 regexp_t result;
4548 int oneof_index = 0;
4549 int i, j;
4551 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4552 if (REGEXP_ONEOF (regexp)->regexps [i]->mode == rm_oneof)
4554 oneof_index = i;
4555 oneof = REGEXP_ONEOF (regexp)->regexps [i];
4556 break;
4558 if (i < REGEXP_ONEOF (regexp)->regexps_num)
4560 gcc_assert (REGEXP_ONEOF (oneof)->regexps_num > 1
4561 && REGEXP_ONEOF (regexp)->regexps_num > 1);
4562 result = create_node (sizeof (struct regexp)
4563 + sizeof (regexp_t)
4564 * (REGEXP_ONEOF (regexp)->regexps_num
4565 + REGEXP_ONEOF (oneof)->regexps_num - 2));
4566 result->mode = rm_oneof;
4567 result->pos = regexp->pos;
4568 REGEXP_ONEOF (result)->regexps_num
4569 = (REGEXP_ONEOF (regexp)->regexps_num
4570 + REGEXP_ONEOF (oneof)->regexps_num - 1);
4571 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4572 if (i < oneof_index)
4573 REGEXP_ONEOF (result)->regexps [i]
4574 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4575 else if (i > oneof_index)
4576 REGEXP_ONEOF (result)->regexps
4577 [i + REGEXP_ONEOF (oneof)->regexps_num - 1]
4578 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4579 else
4580 for (j = 0; j < REGEXP_ONEOF (oneof)->regexps_num; j++)
4581 REGEXP_ONEOF (result)->regexps [i + j]
4582 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [j]);
4583 regexp_transformed_p = 1;
4584 regexp = result;
4587 return regexp;
4590 /* The function makes transformations
4591 ...,A|B|...,C,... -> (...,A,C,...)|(...,B,C,...)|...
4592 ...+(A|B|...)+C+... -> (...+A+C+...)|(...+B+C+...)|...
4593 ...+(A,B,...)+C+... -> (...+A+C+...),B,...
4594 ...+(A,B,...)+(C,D,...) -> (A+C),(B+D),... */
4595 static regexp_t
4596 transform_3 (regexp_t regexp)
4598 if (regexp->mode == rm_sequence)
4600 regexp_t oneof = NULL;
4601 int oneof_index = 0;
4602 regexp_t result;
4603 regexp_t sequence;
4604 int i, j;
4606 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4607 if (REGEXP_SEQUENCE (regexp)->regexps [i]->mode == rm_oneof)
4609 oneof_index = i;
4610 oneof = REGEXP_SEQUENCE (regexp)->regexps [i];
4611 break;
4613 if (i < REGEXP_SEQUENCE (regexp)->regexps_num)
4615 gcc_assert (REGEXP_ONEOF (oneof)->regexps_num > 1
4616 && REGEXP_SEQUENCE (regexp)->regexps_num > 1);
4617 result = create_node (sizeof (struct regexp)
4618 + sizeof (regexp_t)
4619 * (REGEXP_ONEOF (oneof)->regexps_num - 1));
4620 result->mode = rm_oneof;
4621 result->pos = regexp->pos;
4622 REGEXP_ONEOF (result)->regexps_num
4623 = REGEXP_ONEOF (oneof)->regexps_num;
4624 for (i = 0; i < REGEXP_ONEOF (result)->regexps_num; i++)
4626 sequence
4627 = create_node (sizeof (struct regexp)
4628 + sizeof (regexp_t)
4629 * (REGEXP_SEQUENCE (regexp)->regexps_num - 1));
4630 sequence->mode = rm_sequence;
4631 sequence->pos = regexp->pos;
4632 REGEXP_SEQUENCE (sequence)->regexps_num
4633 = REGEXP_SEQUENCE (regexp)->regexps_num;
4634 REGEXP_ONEOF (result)->regexps [i] = sequence;
4635 for (j = 0; j < REGEXP_SEQUENCE (sequence)->regexps_num; j++)
4636 if (j != oneof_index)
4637 REGEXP_SEQUENCE (sequence)->regexps [j]
4638 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [j]);
4639 else
4640 REGEXP_SEQUENCE (sequence)->regexps [j]
4641 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [i]);
4643 regexp_transformed_p = 1;
4644 regexp = result;
4647 else if (regexp->mode == rm_allof)
4649 regexp_t oneof = NULL;
4650 regexp_t seq;
4651 int oneof_index = 0;
4652 int max_seq_length, allof_length;
4653 regexp_t result;
4654 regexp_t allof = NULL;
4655 regexp_t allof_op = NULL;
4656 int i, j;
4658 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4659 if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_oneof)
4661 oneof_index = i;
4662 oneof = REGEXP_ALLOF (regexp)->regexps [i];
4663 break;
4665 if (i < REGEXP_ALLOF (regexp)->regexps_num)
4667 gcc_assert (REGEXP_ONEOF (oneof)->regexps_num > 1
4668 && REGEXP_ALLOF (regexp)->regexps_num > 1);
4669 result = create_node (sizeof (struct regexp)
4670 + sizeof (regexp_t)
4671 * (REGEXP_ONEOF (oneof)->regexps_num - 1));
4672 result->mode = rm_oneof;
4673 result->pos = regexp->pos;
4674 REGEXP_ONEOF (result)->regexps_num
4675 = REGEXP_ONEOF (oneof)->regexps_num;
4676 for (i = 0; i < REGEXP_ONEOF (result)->regexps_num; i++)
4678 allof
4679 = create_node (sizeof (struct regexp)
4680 + sizeof (regexp_t)
4681 * (REGEXP_ALLOF (regexp)->regexps_num - 1));
4682 allof->mode = rm_allof;
4683 allof->pos = regexp->pos;
4684 REGEXP_ALLOF (allof)->regexps_num
4685 = REGEXP_ALLOF (regexp)->regexps_num;
4686 REGEXP_ONEOF (result)->regexps [i] = allof;
4687 for (j = 0; j < REGEXP_ALLOF (allof)->regexps_num; j++)
4688 if (j != oneof_index)
4689 REGEXP_ALLOF (allof)->regexps [j]
4690 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [j]);
4691 else
4692 REGEXP_ALLOF (allof)->regexps [j]
4693 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [i]);
4695 regexp_transformed_p = 1;
4696 regexp = result;
4698 max_seq_length = 0;
4699 if (regexp->mode == rm_allof)
4700 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4702 switch (REGEXP_ALLOF (regexp)->regexps [i]->mode)
4704 case rm_sequence:
4705 seq = REGEXP_ALLOF (regexp)->regexps [i];
4706 if (max_seq_length < REGEXP_SEQUENCE (seq)->regexps_num)
4707 max_seq_length = REGEXP_SEQUENCE (seq)->regexps_num;
4708 break;
4710 case rm_unit:
4711 case rm_nothing:
4712 break;
4714 default:
4715 max_seq_length = 0;
4716 goto break_for;
4719 break_for:
4720 if (max_seq_length != 0)
4722 gcc_assert (max_seq_length != 1
4723 && REGEXP_ALLOF (regexp)->regexps_num > 1);
4724 result = create_node (sizeof (struct regexp)
4725 + sizeof (regexp_t) * (max_seq_length - 1));
4726 result->mode = rm_sequence;
4727 result->pos = regexp->pos;
4728 REGEXP_SEQUENCE (result)->regexps_num = max_seq_length;
4729 for (i = 0; i < max_seq_length; i++)
4731 allof_length = 0;
4732 for (j = 0; j < REGEXP_ALLOF (regexp)->regexps_num; j++)
4733 switch (REGEXP_ALLOF (regexp)->regexps [j]->mode)
4735 case rm_sequence:
4736 if (i < (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4737 ->regexps [j])->regexps_num))
4739 allof_op
4740 = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4741 ->regexps [j])
4742 ->regexps [i]);
4743 allof_length++;
4745 break;
4746 case rm_unit:
4747 case rm_nothing:
4748 if (i == 0)
4750 allof_op = REGEXP_ALLOF (regexp)->regexps [j];
4751 allof_length++;
4753 break;
4754 default:
4755 break;
4758 if (allof_length == 1)
4759 REGEXP_SEQUENCE (result)->regexps [i] = allof_op;
4760 else
4762 allof = create_node (sizeof (struct regexp)
4763 + sizeof (regexp_t)
4764 * (allof_length - 1));
4765 allof->mode = rm_allof;
4766 allof->pos = regexp->pos;
4767 REGEXP_ALLOF (allof)->regexps_num = allof_length;
4768 REGEXP_SEQUENCE (result)->regexps [i] = allof;
4769 allof_length = 0;
4770 for (j = 0; j < REGEXP_ALLOF (regexp)->regexps_num; j++)
4771 if (REGEXP_ALLOF (regexp)->regexps [j]->mode == rm_sequence
4772 && (i <
4773 (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4774 ->regexps [j])->regexps_num)))
4776 allof_op = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4777 ->regexps [j])
4778 ->regexps [i]);
4779 REGEXP_ALLOF (allof)->regexps [allof_length]
4780 = allof_op;
4781 allof_length++;
4783 else if (i == 0
4784 && (REGEXP_ALLOF (regexp)->regexps [j]->mode
4785 == rm_unit
4786 || (REGEXP_ALLOF (regexp)->regexps [j]->mode
4787 == rm_nothing)))
4789 allof_op = REGEXP_ALLOF (regexp)->regexps [j];
4790 REGEXP_ALLOF (allof)->regexps [allof_length]
4791 = allof_op;
4792 allof_length++;
4796 regexp_transformed_p = 1;
4797 regexp = result;
4800 return regexp;
4803 /* The function traverses IR of reservation and applies transformations
4804 implemented by FUNC. */
4805 static regexp_t
4806 regexp_transform_func (regexp_t regexp, regexp_t (*func) (regexp_t regexp))
4808 int i;
4810 switch (regexp->mode)
4812 case rm_sequence:
4813 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4814 REGEXP_SEQUENCE (regexp)->regexps [i]
4815 = regexp_transform_func (REGEXP_SEQUENCE (regexp)->regexps [i],
4816 func);
4817 break;
4819 case rm_allof:
4820 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4821 REGEXP_ALLOF (regexp)->regexps [i]
4822 = regexp_transform_func (REGEXP_ALLOF (regexp)->regexps [i], func);
4823 break;
4825 case rm_oneof:
4826 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4827 REGEXP_ONEOF (regexp)->regexps [i]
4828 = regexp_transform_func (REGEXP_ONEOF (regexp)->regexps [i], func);
4829 break;
4831 case rm_repeat:
4832 REGEXP_REPEAT (regexp)->regexp
4833 = regexp_transform_func (REGEXP_REPEAT (regexp)->regexp, func);
4834 break;
4836 case rm_nothing:
4837 case rm_unit:
4838 break;
4840 default:
4841 gcc_unreachable ();
4843 return (*func) (regexp);
4846 /* The function applies all transformations for IR representation of
4847 reservation REGEXP. */
4848 static regexp_t
4849 transform_regexp (regexp_t regexp)
4851 regexp = regexp_transform_func (regexp, transform_1);
4854 regexp_transformed_p = 0;
4855 regexp = regexp_transform_func (regexp, transform_2);
4856 regexp = regexp_transform_func (regexp, transform_3);
4858 while (regexp_transformed_p);
4859 return regexp;
4862 /* The function applies all transformations for reservations of all
4863 insn declarations. */
4864 static void
4865 transform_insn_regexps (void)
4867 decl_t decl;
4868 int i;
4870 transform_time = create_ticker ();
4871 add_advance_cycle_insn_decl ();
4872 if (progress_flag)
4873 fprintf (stderr, "Reservation transformation...");
4874 for (i = 0; i < description->decls_num; i++)
4876 decl = description->decls [i];
4877 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
4878 DECL_INSN_RESERV (decl)->transformed_regexp
4879 = transform_regexp (copy_insn_regexp
4880 (DECL_INSN_RESERV (decl)->regexp));
4882 if (progress_flag)
4883 fprintf (stderr, "done\n");
4884 ticker_off (&transform_time);
4889 /* The following variable value is TRUE if the first annotated message
4890 about units to automata distribution has been output. */
4891 static int annotation_message_reported_p;
4893 /* The following structure describes usage of a unit in a reservation. */
4894 struct unit_usage
4896 unit_decl_t unit_decl;
4897 /* The following forms a list of units used on the same cycle in the
4898 same alternative. */
4899 struct unit_usage *next;
4901 typedef struct unit_usage *unit_usage_t;
4903 DEF_VEC_P(unit_usage_t);
4904 DEF_VEC_ALLOC_P(unit_usage_t,heap);
4906 /* Obstack for unit_usage structures. */
4907 static struct obstack unit_usages;
4909 /* VLA for representation of array of pointers to unit usage
4910 structures. There is an element for each combination of
4911 (alternative number, cycle). Unit usages on given cycle in
4912 alternative with given number are referred through element with
4913 index equals to the cycle * number of all alternatives in the regexp
4914 + the alternative number. */
4915 static VEC(unit_usage_t,heap) *cycle_alt_unit_usages;
4917 /* The following function creates the structure unit_usage for UNIT on
4918 CYCLE in REGEXP alternative with ALT_NUM. The structure is made
4919 accessed through cycle_alt_unit_usages. */
4920 static void
4921 store_alt_unit_usage (regexp_t regexp, regexp_t unit, int cycle,
4922 int alt_num)
4924 size_t length;
4925 unit_decl_t unit_decl;
4926 unit_usage_t unit_usage_ptr;
4927 int index;
4929 gcc_assert (regexp && regexp->mode == rm_oneof
4930 && alt_num < REGEXP_ONEOF (regexp)->regexps_num);
4931 unit_decl = REGEXP_UNIT (unit)->unit_decl;
4933 length = (cycle + 1) * REGEXP_ONEOF (regexp)->regexps_num;
4934 while (VEC_length (unit_usage_t, cycle_alt_unit_usages) < length)
4935 VEC_safe_push (unit_usage_t,heap, cycle_alt_unit_usages, 0);
4937 obstack_blank (&unit_usages, sizeof (struct unit_usage));
4938 unit_usage_ptr = (struct unit_usage *) obstack_base (&unit_usages);
4939 obstack_finish (&unit_usages);
4940 unit_usage_ptr->unit_decl = unit_decl;
4941 index = cycle * REGEXP_ONEOF (regexp)->regexps_num + alt_num;
4942 unit_usage_ptr->next = VEC_index (unit_usage_t, cycle_alt_unit_usages, index);
4943 VEC_replace (unit_usage_t, cycle_alt_unit_usages, index, unit_usage_ptr);
4944 unit_decl->last_distribution_check_cycle = -1; /* undefined */
4947 /* The function processes given REGEXP to find units with the wrong
4948 distribution. */
4949 static void
4950 check_regexp_units_distribution (const char *insn_reserv_name,
4951 regexp_t regexp)
4953 int i, j, k, cycle;
4954 regexp_t seq, allof, unit;
4955 struct unit_usage *unit_usage_ptr, *other_unit_usage_ptr;
4957 if (regexp == NULL || regexp->mode != rm_oneof)
4958 return;
4959 /* Store all unit usages in the regexp: */
4960 obstack_init (&unit_usages);
4961 cycle_alt_unit_usages = 0;
4963 for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
4965 seq = REGEXP_ONEOF (regexp)->regexps [i];
4966 switch (seq->mode)
4968 case rm_sequence:
4969 for (j = 0; j < REGEXP_SEQUENCE (seq)->regexps_num; j++)
4971 allof = REGEXP_SEQUENCE (seq)->regexps [j];
4972 switch (allof->mode)
4974 case rm_allof:
4975 for (k = 0; k < REGEXP_ALLOF (allof)->regexps_num; k++)
4977 unit = REGEXP_ALLOF (allof)->regexps [k];
4978 if (unit->mode == rm_unit)
4979 store_alt_unit_usage (regexp, unit, j, i);
4980 else
4981 gcc_assert (unit->mode == rm_nothing);
4983 break;
4985 case rm_unit:
4986 store_alt_unit_usage (regexp, allof, j, i);
4987 break;
4989 case rm_nothing:
4990 break;
4992 default:
4993 gcc_unreachable ();
4996 break;
4998 case rm_allof:
4999 for (k = 0; k < REGEXP_ALLOF (seq)->regexps_num; k++)
5001 unit = REGEXP_ALLOF (seq)->regexps [k];
5002 switch (unit->mode)
5004 case rm_unit:
5005 store_alt_unit_usage (regexp, unit, 0, i);
5006 break;
5008 case rm_nothing:
5009 break;
5011 default:
5012 gcc_unreachable ();
5015 break;
5017 case rm_unit:
5018 store_alt_unit_usage (regexp, seq, 0, i);
5019 break;
5021 case rm_nothing:
5022 break;
5024 default:
5025 gcc_unreachable ();
5028 /* Check distribution: */
5029 for (i = 0; i < (int) VEC_length (unit_usage_t, cycle_alt_unit_usages); i++)
5031 cycle = i / REGEXP_ONEOF (regexp)->regexps_num;
5032 for (unit_usage_ptr = VEC_index (unit_usage_t, cycle_alt_unit_usages, i);
5033 unit_usage_ptr != NULL;
5034 unit_usage_ptr = unit_usage_ptr->next)
5035 if (cycle != unit_usage_ptr->unit_decl->last_distribution_check_cycle)
5037 unit_usage_ptr->unit_decl->last_distribution_check_cycle = cycle;
5038 for (k = cycle * REGEXP_ONEOF (regexp)->regexps_num;
5039 k < (int) VEC_length (unit_usage_t, cycle_alt_unit_usages)
5040 && k == cycle * REGEXP_ONEOF (regexp)->regexps_num;
5041 k++)
5043 for (other_unit_usage_ptr
5044 = VEC_index (unit_usage_t, cycle_alt_unit_usages, k);
5045 other_unit_usage_ptr != NULL;
5046 other_unit_usage_ptr = other_unit_usage_ptr->next)
5047 if (unit_usage_ptr->unit_decl->automaton_decl
5048 == other_unit_usage_ptr->unit_decl->automaton_decl)
5049 break;
5050 if (other_unit_usage_ptr == NULL
5051 && (VEC_index (unit_usage_t, cycle_alt_unit_usages, k)
5052 != NULL))
5053 break;
5055 if (k < (int) VEC_length (unit_usage_t, cycle_alt_unit_usages)
5056 && k == cycle * REGEXP_ONEOF (regexp)->regexps_num)
5058 if (!annotation_message_reported_p)
5060 fprintf (stderr, "\n");
5061 error ("The following units do not satisfy units-automata distribution rule");
5062 error (" (A unit of given unit automaton should be on each reserv. altern.)");
5063 annotation_message_reported_p = TRUE;
5065 error ("Unit %s, reserv. %s, cycle %d",
5066 unit_usage_ptr->unit_decl->name, insn_reserv_name,
5067 cycle);
5071 VEC_free (unit_usage_t,heap, cycle_alt_unit_usages);
5072 obstack_free (&unit_usages, NULL);
5075 /* The function finds units which violates units to automata
5076 distribution rule. If the units exist, report about them. */
5077 static void
5078 check_unit_distributions_to_automata (void)
5080 decl_t decl;
5081 int i;
5083 if (progress_flag)
5084 fprintf (stderr, "Check unit distributions to automata...");
5085 annotation_message_reported_p = FALSE;
5086 for (i = 0; i < description->decls_num; i++)
5088 decl = description->decls [i];
5089 if (decl->mode == dm_insn_reserv)
5090 check_regexp_units_distribution
5091 (DECL_INSN_RESERV (decl)->name,
5092 DECL_INSN_RESERV (decl)->transformed_regexp);
5094 if (progress_flag)
5095 fprintf (stderr, "done\n");
5100 /* The page contains code for building alt_states (see comments for
5101 IR) describing all possible insns reservations of an automaton. */
5103 /* Current state being formed for which the current alt_state
5104 refers. */
5105 static state_t state_being_formed;
5107 /* Current alt_state being formed. */
5108 static alt_state_t alt_state_being_formed;
5110 /* This recursive function processes `,' and units in reservation
5111 REGEXP for forming alt_states of AUTOMATON. It is believed that
5112 CURR_CYCLE is start cycle of all reservation REGEXP. */
5113 static int
5114 process_seq_for_forming_states (regexp_t regexp, automaton_t automaton,
5115 int curr_cycle)
5117 int i;
5119 if (regexp == NULL)
5120 return curr_cycle;
5122 switch (regexp->mode)
5124 case rm_unit:
5125 if (REGEXP_UNIT (regexp)->unit_decl->corresponding_automaton_num
5126 == automaton->automaton_order_num)
5127 set_state_reserv (state_being_formed, curr_cycle,
5128 REGEXP_UNIT (regexp)->unit_decl->unit_num);
5129 return curr_cycle;
5131 case rm_sequence:
5132 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
5133 curr_cycle
5134 = process_seq_for_forming_states
5135 (REGEXP_SEQUENCE (regexp)->regexps [i], automaton, curr_cycle) + 1;
5136 return curr_cycle;
5138 case rm_allof:
5140 int finish_cycle = 0;
5141 int cycle;
5143 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
5145 cycle = process_seq_for_forming_states (REGEXP_ALLOF (regexp)
5146 ->regexps [i],
5147 automaton, curr_cycle);
5148 if (finish_cycle < cycle)
5149 finish_cycle = cycle;
5151 return finish_cycle;
5154 case rm_nothing:
5155 return curr_cycle;
5157 default:
5158 gcc_unreachable ();
5162 /* This recursive function finishes forming ALT_STATE of AUTOMATON and
5163 inserts alt_state into the table. */
5164 static void
5165 finish_forming_alt_state (alt_state_t alt_state,
5166 automaton_t automaton ATTRIBUTE_UNUSED)
5168 state_t state_in_table;
5169 state_t corresponding_state;
5171 corresponding_state = alt_state->state;
5172 state_in_table = insert_state (corresponding_state);
5173 if (state_in_table != corresponding_state)
5175 free_state (corresponding_state);
5176 alt_state->state = state_in_table;
5180 /* The following variable value is current automaton insn for whose
5181 reservation the alt states are created. */
5182 static ainsn_t curr_ainsn;
5184 /* This recursive function processes `|' in reservation REGEXP for
5185 forming alt_states of AUTOMATON. List of the alt states should
5186 have the same order as in the description. */
5187 static void
5188 process_alts_for_forming_states (regexp_t regexp, automaton_t automaton,
5189 int inside_oneof_p)
5191 int i;
5193 if (regexp->mode != rm_oneof)
5195 alt_state_being_formed = get_free_alt_state ();
5196 state_being_formed = get_free_state (1, automaton);
5197 alt_state_being_formed->state = state_being_formed;
5198 /* We inserts in reverse order but we process alternatives also
5199 in reverse order. So we have the same order of alternative
5200 as in the description. */
5201 alt_state_being_formed->next_alt_state = curr_ainsn->alt_states;
5202 curr_ainsn->alt_states = alt_state_being_formed;
5203 (void) process_seq_for_forming_states (regexp, automaton, 0);
5204 finish_forming_alt_state (alt_state_being_formed, automaton);
5206 else
5208 gcc_assert (!inside_oneof_p);
5209 /* We processes it in reverse order to get list with the same
5210 order as in the description. See also the previous
5211 commentary. */
5212 for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
5213 process_alts_for_forming_states (REGEXP_ONEOF (regexp)->regexps [i],
5214 automaton, 1);
5218 /* Create nodes alt_state for all AUTOMATON insns. */
5219 static void
5220 create_alt_states (automaton_t automaton)
5222 struct insn_reserv_decl *reserv_decl;
5224 for (curr_ainsn = automaton->ainsn_list;
5225 curr_ainsn != NULL;
5226 curr_ainsn = curr_ainsn->next_ainsn)
5228 reserv_decl = curr_ainsn->insn_reserv_decl;
5229 if (reserv_decl != DECL_INSN_RESERV (advance_cycle_insn_decl))
5231 curr_ainsn->alt_states = NULL;
5232 process_alts_for_forming_states (reserv_decl->transformed_regexp,
5233 automaton, 0);
5234 curr_ainsn->sorted_alt_states
5235 = uniq_sort_alt_states (curr_ainsn->alt_states);
5242 /* The page contains major code for building DFA(s) for fast pipeline
5243 hazards recognition. */
5245 /* The function forms list of ainsns of AUTOMATON with the same
5246 reservation. */
5248 static void
5249 form_ainsn_with_same_reservs (automaton_t automaton)
5251 ainsn_t curr_ainsn;
5252 size_t i;
5253 VEC(ainsn_t,heap) *last_insns = VEC_alloc (ainsn_t,heap, 150);
5255 for (curr_ainsn = automaton->ainsn_list;
5256 curr_ainsn != NULL;
5257 curr_ainsn = curr_ainsn->next_ainsn)
5258 if (curr_ainsn->insn_reserv_decl
5259 == DECL_INSN_RESERV (advance_cycle_insn_decl))
5261 curr_ainsn->next_same_reservs_insn = NULL;
5262 curr_ainsn->first_insn_with_same_reservs = 1;
5264 else
5266 for (i = 0; i < VEC_length (ainsn_t, last_insns); i++)
5267 if (alt_states_eq
5268 (curr_ainsn->sorted_alt_states,
5269 VEC_index (ainsn_t, last_insns, i)->sorted_alt_states))
5270 break;
5271 curr_ainsn->next_same_reservs_insn = NULL;
5272 if (i < VEC_length (ainsn_t, last_insns))
5274 curr_ainsn->first_insn_with_same_reservs = 0;
5275 VEC_index (ainsn_t, last_insns, i)->next_same_reservs_insn
5276 = curr_ainsn;
5277 VEC_replace (ainsn_t, last_insns, i, curr_ainsn);
5279 else
5281 VEC_safe_push (ainsn_t, heap, last_insns, curr_ainsn);
5282 curr_ainsn->first_insn_with_same_reservs = 1;
5285 VEC_free (ainsn_t,heap, last_insns);
5288 /* Forming unit reservations which can affect creating the automaton
5289 states achieved from a given state. It permits to build smaller
5290 automata in many cases. We would have the same automata after
5291 the minimization without such optimization, but the automaton
5292 right after the building could be huge. So in other words, usage
5293 of reservs_matter means some minimization during building the
5294 automaton. */
5295 static reserv_sets_t
5296 form_reservs_matter (automaton_t automaton)
5298 int cycle, unit;
5299 reserv_sets_t reservs_matter = alloc_empty_reserv_sets();
5301 for (cycle = 0; cycle < max_cycles_num; cycle++)
5302 for (unit = 0; unit < description->units_num; unit++)
5303 if (units_array [unit]->automaton_decl
5304 == automaton->corresponding_automaton_decl
5305 && (cycle >= units_array [unit]->min_occ_cycle_num
5306 /* We can not remove queried unit from reservations. */
5307 || units_array [unit]->query_p
5308 /* We can not remove units which are used
5309 `exclusion_set', `presence_set',
5310 `final_presence_set', `absence_set', and
5311 `final_absence_set'. */
5312 || units_array [unit]->in_set_p))
5313 set_unit_reserv (reservs_matter, cycle, unit);
5314 return reservs_matter;
5317 /* The following function creates all states of nondeterministic AUTOMATON. */
5318 static void
5319 make_automaton (automaton_t automaton)
5321 ainsn_t ainsn;
5322 struct insn_reserv_decl *insn_reserv_decl;
5323 alt_state_t alt_state;
5324 state_t state;
5325 state_t start_state;
5326 state_t state2;
5327 ainsn_t advance_cycle_ainsn;
5328 arc_t added_arc;
5329 VEC(state_t,heap) *state_stack = VEC_alloc(state_t,heap, 150);
5330 int states_n;
5331 reserv_sets_t reservs_matter = form_reservs_matter (automaton);
5333 /* Create the start state (empty state). */
5334 start_state = insert_state (get_free_state (1, automaton));
5335 automaton->start_state = start_state;
5336 start_state->it_was_placed_in_stack_for_NDFA_forming = 1;
5337 VEC_safe_push (state_t,heap, state_stack, start_state);
5338 states_n = 1;
5339 while (VEC_length (state_t, state_stack) != 0)
5341 state = VEC_pop (state_t, state_stack);
5342 advance_cycle_ainsn = NULL;
5343 for (ainsn = automaton->ainsn_list;
5344 ainsn != NULL;
5345 ainsn = ainsn->next_ainsn)
5346 if (ainsn->first_insn_with_same_reservs)
5348 insn_reserv_decl = ainsn->insn_reserv_decl;
5349 if (insn_reserv_decl != DECL_INSN_RESERV (advance_cycle_insn_decl))
5351 /* We process alt_states in the same order as they are
5352 present in the description. */
5353 added_arc = NULL;
5354 for (alt_state = ainsn->alt_states;
5355 alt_state != NULL;
5356 alt_state = alt_state->next_alt_state)
5358 state2 = alt_state->state;
5359 if (!intersected_state_reservs_p (state, state2))
5361 state2 = states_union (state, state2, reservs_matter);
5362 if (!state2->it_was_placed_in_stack_for_NDFA_forming)
5364 state2->it_was_placed_in_stack_for_NDFA_forming
5365 = 1;
5366 VEC_safe_push (state_t,heap, state_stack, state2);
5367 states_n++;
5368 if (progress_flag && states_n % 100 == 0)
5369 fprintf (stderr, ".");
5371 added_arc = add_arc (state, state2, ainsn);
5372 if (!ndfa_flag)
5373 break;
5376 if (!ndfa_flag && added_arc != NULL)
5378 for (alt_state = ainsn->alt_states;
5379 alt_state != NULL;
5380 alt_state = alt_state->next_alt_state)
5381 state2 = alt_state->state;
5384 else
5385 advance_cycle_ainsn = ainsn;
5387 /* Add transition to advance cycle. */
5388 state2 = state_shift (state, reservs_matter);
5389 if (!state2->it_was_placed_in_stack_for_NDFA_forming)
5391 state2->it_was_placed_in_stack_for_NDFA_forming = 1;
5392 VEC_safe_push (state_t,heap, state_stack, state2);
5393 states_n++;
5394 if (progress_flag && states_n % 100 == 0)
5395 fprintf (stderr, ".");
5397 gcc_assert (advance_cycle_ainsn);
5398 add_arc (state, state2, advance_cycle_ainsn);
5400 VEC_free (state_t,heap, state_stack);
5403 /* Foms lists of all arcs of STATE marked by the same ainsn. */
5404 static void
5405 form_arcs_marked_by_insn (state_t state)
5407 decl_t decl;
5408 arc_t arc;
5409 int i;
5411 for (i = 0; i < description->decls_num; i++)
5413 decl = description->decls [i];
5414 if (decl->mode == dm_insn_reserv)
5415 DECL_INSN_RESERV (decl)->arcs_marked_by_insn = NULL;
5417 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5419 gcc_assert (arc->insn);
5420 arc->next_arc_marked_by_insn
5421 = arc->insn->insn_reserv_decl->arcs_marked_by_insn;
5422 arc->insn->insn_reserv_decl->arcs_marked_by_insn = arc;
5426 /* The function creates composed state (see comments for IR) from
5427 ORIGINAL_STATE and list of arcs ARCS_MARKED_BY_INSN marked by the
5428 same insn. If the composed state is not in STATE_STACK yet, it is
5429 pushed into STATE_STACK. */
5431 static int
5432 create_composed_state (state_t original_state, arc_t arcs_marked_by_insn,
5433 VEC(state_t,heap) **state_stack)
5435 state_t state;
5436 alt_state_t alt_state, curr_alt_state;
5437 alt_state_t new_alt_state;
5438 arc_t curr_arc;
5439 arc_t next_arc;
5440 state_t state_in_table;
5441 state_t temp_state;
5442 alt_state_t canonical_alt_states_list;
5443 int alts_number;
5444 int new_state_p = 0;
5446 if (arcs_marked_by_insn == NULL)
5447 return new_state_p;
5448 if (arcs_marked_by_insn->next_arc_marked_by_insn == NULL)
5449 state = arcs_marked_by_insn->to_state;
5450 else
5452 gcc_assert (ndfa_flag);
5453 /* Create composed state. */
5454 state = get_free_state (0, arcs_marked_by_insn->to_state->automaton);
5455 curr_alt_state = NULL;
5456 for (curr_arc = arcs_marked_by_insn;
5457 curr_arc != NULL;
5458 curr_arc = curr_arc->next_arc_marked_by_insn)
5459 if (curr_arc->to_state->component_states == NULL)
5461 new_alt_state = get_free_alt_state ();
5462 new_alt_state->next_alt_state = curr_alt_state;
5463 new_alt_state->state = curr_arc->to_state;
5464 curr_alt_state = new_alt_state;
5466 else
5467 for (alt_state = curr_arc->to_state->component_states;
5468 alt_state != NULL;
5469 alt_state = alt_state->next_sorted_alt_state)
5471 new_alt_state = get_free_alt_state ();
5472 new_alt_state->next_alt_state = curr_alt_state;
5473 new_alt_state->state = alt_state->state;
5474 gcc_assert (!alt_state->state->component_states);
5475 curr_alt_state = new_alt_state;
5477 /* There are not identical sets in the alt state list. */
5478 canonical_alt_states_list = uniq_sort_alt_states (curr_alt_state);
5479 if (canonical_alt_states_list->next_sorted_alt_state == NULL)
5481 temp_state = state;
5482 state = canonical_alt_states_list->state;
5483 free_state (temp_state);
5485 else
5487 state->component_states = canonical_alt_states_list;
5488 state_in_table = insert_state (state);
5489 if (state_in_table != state)
5491 gcc_assert
5492 (state_in_table->it_was_placed_in_stack_for_DFA_forming);
5493 free_state (state);
5494 state = state_in_table;
5496 else
5498 gcc_assert (!state->it_was_placed_in_stack_for_DFA_forming);
5499 new_state_p = 1;
5500 for (curr_alt_state = state->component_states;
5501 curr_alt_state != NULL;
5502 curr_alt_state = curr_alt_state->next_sorted_alt_state)
5503 for (curr_arc = first_out_arc (curr_alt_state->state);
5504 curr_arc != NULL;
5505 curr_arc = next_out_arc (curr_arc))
5506 add_arc (state, curr_arc->to_state, curr_arc->insn);
5508 arcs_marked_by_insn->to_state = state;
5509 for (alts_number = 0,
5510 curr_arc = arcs_marked_by_insn->next_arc_marked_by_insn;
5511 curr_arc != NULL;
5512 curr_arc = next_arc)
5514 next_arc = curr_arc->next_arc_marked_by_insn;
5515 remove_arc (original_state, curr_arc);
5516 alts_number++;
5520 if (!state->it_was_placed_in_stack_for_DFA_forming)
5522 state->it_was_placed_in_stack_for_DFA_forming = 1;
5523 VEC_safe_push (state_t,heap, *state_stack, state);
5525 return new_state_p;
5528 /* The function transforms nondeterministic AUTOMATON into
5529 deterministic. */
5531 static void
5532 NDFA_to_DFA (automaton_t automaton)
5534 state_t start_state;
5535 state_t state;
5536 decl_t decl;
5537 VEC(state_t,heap) *state_stack;
5538 int i;
5539 int states_n;
5541 state_stack = VEC_alloc (state_t,heap, 0);
5543 /* Create the start state (empty state). */
5544 start_state = automaton->start_state;
5545 start_state->it_was_placed_in_stack_for_DFA_forming = 1;
5546 VEC_safe_push (state_t,heap, state_stack, start_state);
5547 states_n = 1;
5548 while (VEC_length (state_t, state_stack) != 0)
5550 state = VEC_pop (state_t, state_stack);
5551 form_arcs_marked_by_insn (state);
5552 for (i = 0; i < description->decls_num; i++)
5554 decl = description->decls [i];
5555 if (decl->mode == dm_insn_reserv
5556 && create_composed_state
5557 (state, DECL_INSN_RESERV (decl)->arcs_marked_by_insn,
5558 &state_stack))
5560 states_n++;
5561 if (progress_flag && states_n % 100 == 0)
5562 fprintf (stderr, ".");
5566 VEC_free (state_t,heap, state_stack);
5569 /* The following variable value is current number (1, 2, ...) of passing
5570 graph of states. */
5571 static int curr_state_graph_pass_num;
5573 /* This recursive function passes all states achieved from START_STATE
5574 and applies APPLIED_FUNC to them. */
5575 static void
5576 pass_state_graph (state_t start_state, void (*applied_func) (state_t state))
5578 arc_t arc;
5580 if (start_state->pass_num == curr_state_graph_pass_num)
5581 return;
5582 start_state->pass_num = curr_state_graph_pass_num;
5583 (*applied_func) (start_state);
5584 for (arc = first_out_arc (start_state);
5585 arc != NULL;
5586 arc = next_out_arc (arc))
5587 pass_state_graph (arc->to_state, applied_func);
5590 /* This recursive function passes all states of AUTOMATON and applies
5591 APPLIED_FUNC to them. */
5592 static void
5593 pass_states (automaton_t automaton, void (*applied_func) (state_t state))
5595 curr_state_graph_pass_num++;
5596 pass_state_graph (automaton->start_state, applied_func);
5599 /* The function initializes code for passing of all states. */
5600 static void
5601 initiate_pass_states (void)
5603 curr_state_graph_pass_num = 0;
5606 /* The following vla is used for storing pointers to all achieved
5607 states. */
5608 static VEC(state_t,heap) *all_achieved_states;
5610 /* This function is called by function pass_states to add an achieved
5611 STATE. */
5612 static void
5613 add_achieved_state (state_t state)
5615 VEC_safe_push (state_t,heap, all_achieved_states, state);
5618 /* The function sets up equivalence numbers of insns which mark all
5619 out arcs of STATE by equiv_class_num_1 (if ODD_ITERATION_FLAG has
5620 nonzero value) or by equiv_class_num_2 of the destination state.
5621 The function returns number of out arcs of STATE. */
5622 static void
5623 set_out_arc_insns_equiv_num (state_t state, int odd_iteration_flag)
5625 arc_t arc;
5627 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5629 gcc_assert (!arc->insn->insn_reserv_decl->equiv_class_num);
5630 arc->insn->insn_reserv_decl->equiv_class_num
5631 = (odd_iteration_flag
5632 ? arc->to_state->equiv_class_num_1
5633 : arc->to_state->equiv_class_num_2);
5634 gcc_assert (arc->insn->insn_reserv_decl->equiv_class_num);
5638 /* The function clears equivalence numbers and alt_states in all insns
5639 which mark all out arcs of STATE. */
5640 static void
5641 clear_arc_insns_equiv_num (state_t state)
5643 arc_t arc;
5645 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5646 arc->insn->insn_reserv_decl->equiv_class_num = 0;
5650 /* The following function returns TRUE if STATE reserves the unit with
5651 UNIT_NUM on the first cycle. */
5652 static int
5653 first_cycle_unit_presence (state_t state, int unit_num)
5655 alt_state_t alt_state;
5657 if (state->component_states == NULL)
5658 return test_unit_reserv (state->reservs, 0, unit_num);
5659 else
5661 for (alt_state = state->component_states;
5662 alt_state != NULL;
5663 alt_state = alt_state->next_sorted_alt_state)
5664 if (test_unit_reserv (alt_state->state->reservs, 0, unit_num))
5665 return true;
5667 return false;
5670 /* This fills in the presence_signature[] member of STATE. */
5671 static void
5672 cache_presence (state_t state)
5674 int i, num = 0;
5675 unsigned int sz;
5676 sz = (description->query_units_num + sizeof (int) * CHAR_BIT - 1)
5677 / (sizeof (int) * CHAR_BIT);
5679 state->presence_signature = create_node (sz * sizeof (int));
5680 for (i = 0; i < description->units_num; i++)
5681 if (units_array [i]->query_p)
5683 int presence1_p = first_cycle_unit_presence (state, i);
5684 state->presence_signature[num / (sizeof (int) * CHAR_BIT)]
5685 |= (!!presence1_p) << (num % (sizeof (int) * CHAR_BIT));
5686 num++;
5690 /* The function returns nonzero value if STATE is not equivalent to
5691 ANOTHER_STATE from the same current partition on equivalence
5692 classes. Another state has ANOTHER_STATE_OUT_ARCS_NUM number of
5693 output arcs. Iteration of making equivalence partition is defined
5694 by ODD_ITERATION_FLAG. */
5695 static int
5696 state_is_differed (state_t state, state_t another_state,
5697 int odd_iteration_flag)
5699 arc_t arc;
5700 unsigned int sz, si;
5702 gcc_assert (state->num_out_arcs == another_state->num_out_arcs);
5704 sz = (description->query_units_num + sizeof (int) * CHAR_BIT - 1)
5705 / (sizeof (int) * CHAR_BIT);
5707 for (si = 0; si < sz; si++)
5708 gcc_assert (state->presence_signature[si]
5709 == another_state->presence_signature[si]);
5711 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5713 if ((odd_iteration_flag
5714 ? arc->to_state->equiv_class_num_1
5715 : arc->to_state->equiv_class_num_2)
5716 != arc->insn->insn_reserv_decl->equiv_class_num)
5717 return 1;
5720 return 0;
5723 /* Compares two states pointed to by STATE_PTR_1 and STATE_PTR_2
5724 and return -1, 0 or 1. This function can be used as predicate for
5725 qsort(). It requires the member presence_signature[] of both
5726 states be filled. */
5727 static int
5728 compare_states_for_equiv (const void *state_ptr_1,
5729 const void *state_ptr_2)
5731 state_t s1 = *(state_t *)state_ptr_1;
5732 state_t s2 = *(state_t *)state_ptr_2;
5733 unsigned int sz, si;
5734 if (s1->num_out_arcs < s2->num_out_arcs)
5735 return -1;
5736 else if (s1->num_out_arcs > s2->num_out_arcs)
5737 return 1;
5739 sz = (description->query_units_num + sizeof (int) * CHAR_BIT - 1)
5740 / (sizeof (int) * CHAR_BIT);
5742 for (si = 0; si < sz; si++)
5743 if (s1->presence_signature[si] < s2->presence_signature[si])
5744 return -1;
5745 else if (s1->presence_signature[si] > s2->presence_signature[si])
5746 return 1;
5747 return 0;
5750 /* The function makes initial partition of STATES on equivalent
5751 classes and saves it into *CLASSES. This function requires the input
5752 to be sorted via compare_states_for_equiv(). */
5753 static int
5754 init_equiv_class (VEC(state_t,heap) *states, VEC (state_t,heap) **classes)
5756 size_t i;
5757 state_t prev = 0;
5758 int class_num = 1;
5760 *classes = VEC_alloc (state_t,heap, 150);
5761 for (i = 0; i < VEC_length (state_t, states); i++)
5763 state_t state = VEC_index (state_t, states, i);
5764 if (prev)
5766 if (compare_states_for_equiv (&prev, &state) != 0)
5768 VEC_safe_push (state_t,heap, *classes, prev);
5769 class_num++;
5770 prev = NULL;
5773 state->equiv_class_num_1 = class_num;
5774 state->next_equiv_class_state = prev;
5775 prev = state;
5777 if (prev)
5778 VEC_safe_push (state_t,heap, *classes, prev);
5779 return class_num;
5782 /* The function copies pointers to equivalent states from vla FROM
5783 into vla TO. */
5784 static void
5785 copy_equiv_class (VEC(state_t,heap) **to, VEC(state_t,heap) *from)
5787 VEC_free (state_t,heap, *to);
5788 *to = VEC_copy (state_t,heap, from);
5791 /* The function processes equivalence class given by its first state,
5792 FIRST_STATE, on odd iteration if ODD_ITERATION_FLAG. If there
5793 are not equivalent states, the function partitions the class
5794 removing nonequivalent states and placing them in
5795 *NEXT_ITERATION_CLASSES, increments *NEW_EQUIV_CLASS_NUM_PTR ans
5796 assigns it to the state equivalence number. If the class has been
5797 partitioned, the function returns nonzero value. */
5798 static int
5799 partition_equiv_class (state_t first_state, int odd_iteration_flag,
5800 VEC(state_t,heap) **next_iteration_classes,
5801 int *new_equiv_class_num_ptr)
5803 state_t new_equiv_class;
5804 int partition_p;
5805 state_t curr_state;
5806 state_t prev_state;
5807 state_t next_state;
5809 partition_p = 0;
5811 while (first_state != NULL)
5813 new_equiv_class = NULL;
5814 if (first_state->next_equiv_class_state != NULL)
5816 /* There are more one states in the class equivalence. */
5817 set_out_arc_insns_equiv_num (first_state, odd_iteration_flag);
5818 for (prev_state = first_state,
5819 curr_state = first_state->next_equiv_class_state;
5820 curr_state != NULL;
5821 curr_state = next_state)
5823 next_state = curr_state->next_equiv_class_state;
5824 if (state_is_differed (curr_state, first_state,
5825 odd_iteration_flag))
5827 /* Remove curr state from the class equivalence. */
5828 prev_state->next_equiv_class_state = next_state;
5829 /* Add curr state to the new class equivalence. */
5830 curr_state->next_equiv_class_state = new_equiv_class;
5831 if (new_equiv_class == NULL)
5832 (*new_equiv_class_num_ptr)++;
5833 if (odd_iteration_flag)
5834 curr_state->equiv_class_num_2 = *new_equiv_class_num_ptr;
5835 else
5836 curr_state->equiv_class_num_1 = *new_equiv_class_num_ptr;
5837 new_equiv_class = curr_state;
5838 partition_p = 1;
5840 else
5841 prev_state = curr_state;
5843 clear_arc_insns_equiv_num (first_state);
5845 if (new_equiv_class != NULL)
5846 VEC_safe_push (state_t,heap, *next_iteration_classes, new_equiv_class);
5847 first_state = new_equiv_class;
5849 return partition_p;
5852 /* The function finds equivalent states of AUTOMATON. */
5853 static void
5854 evaluate_equiv_classes (automaton_t automaton,
5855 VEC(state_t,heap) **equiv_classes)
5857 int new_equiv_class_num;
5858 int odd_iteration_flag;
5859 int finish_flag;
5860 VEC (state_t,heap) *next_iteration_classes;
5861 size_t i;
5863 all_achieved_states = VEC_alloc (state_t,heap, 1500);
5864 pass_states (automaton, add_achieved_state);
5865 pass_states (automaton, cache_presence);
5866 qsort (VEC_address (state_t, all_achieved_states),
5867 VEC_length (state_t, all_achieved_states),
5868 sizeof (state_t), compare_states_for_equiv);
5870 odd_iteration_flag = 0;
5871 new_equiv_class_num = init_equiv_class (all_achieved_states,
5872 &next_iteration_classes);
5876 odd_iteration_flag = !odd_iteration_flag;
5877 finish_flag = 1;
5878 copy_equiv_class (equiv_classes, next_iteration_classes);
5880 /* Transfer equiv numbers for the next iteration. */
5881 for (i = 0; i < VEC_length (state_t, all_achieved_states); i++)
5882 if (odd_iteration_flag)
5883 VEC_index (state_t, all_achieved_states, i)->equiv_class_num_2
5884 = VEC_index (state_t, all_achieved_states, i)->equiv_class_num_1;
5885 else
5886 VEC_index (state_t, all_achieved_states, i)->equiv_class_num_1
5887 = VEC_index (state_t, all_achieved_states, i)->equiv_class_num_2;
5889 for (i = 0; i < VEC_length (state_t, *equiv_classes); i++)
5890 if (partition_equiv_class (VEC_index (state_t, *equiv_classes, i),
5891 odd_iteration_flag,
5892 &next_iteration_classes,
5893 &new_equiv_class_num))
5894 finish_flag = 0;
5896 while (!finish_flag);
5897 VEC_free (state_t,heap, next_iteration_classes);
5898 VEC_free (state_t,heap, all_achieved_states);
5901 /* The function merges equivalent states of AUTOMATON. */
5902 static void
5903 merge_states (automaton_t automaton, VEC(state_t,heap) *equiv_classes)
5905 state_t curr_state;
5906 state_t new_state;
5907 state_t first_class_state;
5908 alt_state_t alt_states;
5909 alt_state_t alt_state, new_alt_state;
5910 arc_t curr_arc;
5911 arc_t next_arc;
5912 size_t i;
5914 /* Create states corresponding to equivalence classes containing two
5915 or more states. */
5916 for (i = 0; i < VEC_length (state_t, equiv_classes); i++)
5918 curr_state = VEC_index (state_t, equiv_classes, i);
5919 if (curr_state->next_equiv_class_state != NULL)
5921 /* There are more one states in the class equivalence. */
5922 /* Create new compound state. */
5923 new_state = get_free_state (0, automaton);
5924 alt_states = NULL;
5925 first_class_state = curr_state;
5926 for (curr_state = first_class_state;
5927 curr_state != NULL;
5928 curr_state = curr_state->next_equiv_class_state)
5930 curr_state->equiv_class_state = new_state;
5931 if (curr_state->component_states == NULL)
5933 new_alt_state = get_free_alt_state ();
5934 new_alt_state->state = curr_state;
5935 new_alt_state->next_alt_state = alt_states;
5936 alt_states = new_alt_state;
5938 else
5939 for (alt_state = curr_state->component_states;
5940 alt_state != NULL;
5941 alt_state = alt_state->next_sorted_alt_state)
5943 new_alt_state = get_free_alt_state ();
5944 new_alt_state->state = alt_state->state;
5945 new_alt_state->next_alt_state = alt_states;
5946 alt_states = new_alt_state;
5949 /* Its is important that alt states were sorted before and
5950 after merging to have the same querying results. */
5951 new_state->component_states = uniq_sort_alt_states (alt_states);
5953 else
5954 curr_state->equiv_class_state = curr_state;
5957 for (i = 0; i < VEC_length (state_t, equiv_classes); i++)
5959 curr_state = VEC_index (state_t, equiv_classes, i);
5960 if (curr_state->next_equiv_class_state != NULL)
5962 first_class_state = curr_state;
5963 /* Create new arcs output from the state corresponding to
5964 equiv class. */
5965 for (curr_arc = first_out_arc (first_class_state);
5966 curr_arc != NULL;
5967 curr_arc = next_out_arc (curr_arc))
5968 add_arc (first_class_state->equiv_class_state,
5969 curr_arc->to_state->equiv_class_state,
5970 curr_arc->insn);
5971 /* Delete output arcs from states of given class equivalence. */
5972 for (curr_state = first_class_state;
5973 curr_state != NULL;
5974 curr_state = curr_state->next_equiv_class_state)
5976 if (automaton->start_state == curr_state)
5977 automaton->start_state = curr_state->equiv_class_state;
5978 /* Delete the state and its output arcs. */
5979 for (curr_arc = first_out_arc (curr_state);
5980 curr_arc != NULL;
5981 curr_arc = next_arc)
5983 next_arc = next_out_arc (curr_arc);
5984 free_arc (curr_arc);
5988 else
5990 /* Change `to_state' of arcs output from the state of given
5991 equivalence class. */
5992 for (curr_arc = first_out_arc (curr_state);
5993 curr_arc != NULL;
5994 curr_arc = next_out_arc (curr_arc))
5995 curr_arc->to_state = curr_arc->to_state->equiv_class_state;
6000 /* The function sets up new_cycle_p for states if there is arc to the
6001 state marked by advance_cycle_insn_decl. */
6002 static void
6003 set_new_cycle_flags (state_t state)
6005 arc_t arc;
6007 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6008 if (arc->insn->insn_reserv_decl
6009 == DECL_INSN_RESERV (advance_cycle_insn_decl))
6010 arc->to_state->new_cycle_p = 1;
6013 /* The top level function for minimization of deterministic
6014 AUTOMATON. */
6015 static void
6016 minimize_DFA (automaton_t automaton)
6018 VEC(state_t,heap) *equiv_classes = 0;
6020 evaluate_equiv_classes (automaton, &equiv_classes);
6021 merge_states (automaton, equiv_classes);
6022 pass_states (automaton, set_new_cycle_flags);
6024 VEC_free (state_t,heap, equiv_classes);
6027 /* Values of two variables are counted number of states and arcs in an
6028 automaton. */
6029 static int curr_counted_states_num;
6030 static int curr_counted_arcs_num;
6032 /* The function is called by function `pass_states' to count states
6033 and arcs of an automaton. */
6034 static void
6035 incr_states_and_arcs_nums (state_t state)
6037 arc_t arc;
6039 curr_counted_states_num++;
6040 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6041 curr_counted_arcs_num++;
6044 /* The function counts states and arcs of AUTOMATON. */
6045 static void
6046 count_states_and_arcs (automaton_t automaton, int *states_num,
6047 int *arcs_num)
6049 curr_counted_states_num = 0;
6050 curr_counted_arcs_num = 0;
6051 pass_states (automaton, incr_states_and_arcs_nums);
6052 *states_num = curr_counted_states_num;
6053 *arcs_num = curr_counted_arcs_num;
6056 /* The function builds one DFA AUTOMATON for fast pipeline hazards
6057 recognition after checking and simplifying IR of the
6058 description. */
6059 static void
6060 build_automaton (automaton_t automaton)
6062 int states_num;
6063 int arcs_num;
6065 ticker_on (&NDFA_time);
6066 if (progress_flag)
6068 if (automaton->corresponding_automaton_decl == NULL)
6069 fprintf (stderr, "Create anonymous automaton");
6070 else
6071 fprintf (stderr, "Create automaton `%s'",
6072 automaton->corresponding_automaton_decl->name);
6073 fprintf (stderr, " (1 dot is 100 new states):");
6075 make_automaton (automaton);
6076 if (progress_flag)
6077 fprintf (stderr, " done\n");
6078 ticker_off (&NDFA_time);
6079 count_states_and_arcs (automaton, &states_num, &arcs_num);
6080 automaton->NDFA_states_num = states_num;
6081 automaton->NDFA_arcs_num = arcs_num;
6082 ticker_on (&NDFA_to_DFA_time);
6083 if (progress_flag)
6085 if (automaton->corresponding_automaton_decl == NULL)
6086 fprintf (stderr, "Make anonymous DFA");
6087 else
6088 fprintf (stderr, "Make DFA `%s'",
6089 automaton->corresponding_automaton_decl->name);
6090 fprintf (stderr, " (1 dot is 100 new states):");
6092 NDFA_to_DFA (automaton);
6093 if (progress_flag)
6094 fprintf (stderr, " done\n");
6095 ticker_off (&NDFA_to_DFA_time);
6096 count_states_and_arcs (automaton, &states_num, &arcs_num);
6097 automaton->DFA_states_num = states_num;
6098 automaton->DFA_arcs_num = arcs_num;
6099 if (!no_minimization_flag)
6101 ticker_on (&minimize_time);
6102 if (progress_flag)
6104 if (automaton->corresponding_automaton_decl == NULL)
6105 fprintf (stderr, "Minimize anonymous DFA...");
6106 else
6107 fprintf (stderr, "Minimize DFA `%s'...",
6108 automaton->corresponding_automaton_decl->name);
6110 minimize_DFA (automaton);
6111 if (progress_flag)
6112 fprintf (stderr, "done\n");
6113 ticker_off (&minimize_time);
6114 count_states_and_arcs (automaton, &states_num, &arcs_num);
6115 automaton->minimal_DFA_states_num = states_num;
6116 automaton->minimal_DFA_arcs_num = arcs_num;
6122 /* The page contains code for enumeration of all states of an automaton. */
6124 /* Variable used for enumeration of all states of an automaton. Its
6125 value is current number of automaton states. */
6126 static int curr_state_order_num;
6128 /* The function is called by function `pass_states' for enumerating
6129 states. */
6130 static void
6131 set_order_state_num (state_t state)
6133 state->order_state_num = curr_state_order_num;
6134 curr_state_order_num++;
6137 /* The function enumerates all states of AUTOMATON. */
6138 static void
6139 enumerate_states (automaton_t automaton)
6141 curr_state_order_num = 0;
6142 pass_states (automaton, set_order_state_num);
6143 automaton->achieved_states_num = curr_state_order_num;
6148 /* The page contains code for finding equivalent automaton insns
6149 (ainsns). */
6151 /* The function inserts AINSN into cyclic list
6152 CYCLIC_EQUIV_CLASS_INSN_LIST of ainsns. */
6153 static ainsn_t
6154 insert_ainsn_into_equiv_class (ainsn_t ainsn,
6155 ainsn_t cyclic_equiv_class_insn_list)
6157 if (cyclic_equiv_class_insn_list == NULL)
6158 ainsn->next_equiv_class_insn = ainsn;
6159 else
6161 ainsn->next_equiv_class_insn
6162 = cyclic_equiv_class_insn_list->next_equiv_class_insn;
6163 cyclic_equiv_class_insn_list->next_equiv_class_insn = ainsn;
6165 return ainsn;
6168 /* The function deletes equiv_class_insn into cyclic list of
6169 equivalent ainsns. */
6170 static void
6171 delete_ainsn_from_equiv_class (ainsn_t equiv_class_insn)
6173 ainsn_t curr_equiv_class_insn;
6174 ainsn_t prev_equiv_class_insn;
6176 prev_equiv_class_insn = equiv_class_insn;
6177 for (curr_equiv_class_insn = equiv_class_insn->next_equiv_class_insn;
6178 curr_equiv_class_insn != equiv_class_insn;
6179 curr_equiv_class_insn = curr_equiv_class_insn->next_equiv_class_insn)
6180 prev_equiv_class_insn = curr_equiv_class_insn;
6181 if (prev_equiv_class_insn != equiv_class_insn)
6182 prev_equiv_class_insn->next_equiv_class_insn
6183 = equiv_class_insn->next_equiv_class_insn;
6186 /* The function processes AINSN of a state in order to find equivalent
6187 ainsns. INSN_ARCS_ARRAY is table: code of insn -> out arc of the
6188 state. */
6189 static void
6190 process_insn_equiv_class (ainsn_t ainsn, arc_t *insn_arcs_array)
6192 ainsn_t next_insn;
6193 ainsn_t curr_insn;
6194 ainsn_t cyclic_insn_list;
6195 arc_t arc;
6197 gcc_assert (insn_arcs_array [ainsn->insn_reserv_decl->insn_num]);
6198 curr_insn = ainsn;
6199 /* New class of ainsns which are not equivalent to given ainsn. */
6200 cyclic_insn_list = NULL;
6203 next_insn = curr_insn->next_equiv_class_insn;
6204 arc = insn_arcs_array [curr_insn->insn_reserv_decl->insn_num];
6205 if (arc == NULL
6206 || (insn_arcs_array [ainsn->insn_reserv_decl->insn_num]->to_state
6207 != arc->to_state))
6209 delete_ainsn_from_equiv_class (curr_insn);
6210 cyclic_insn_list = insert_ainsn_into_equiv_class (curr_insn,
6211 cyclic_insn_list);
6213 curr_insn = next_insn;
6215 while (curr_insn != ainsn);
6218 /* The function processes STATE in order to find equivalent ainsns. */
6219 static void
6220 process_state_for_insn_equiv_partition (state_t state)
6222 arc_t arc;
6223 arc_t *insn_arcs_array = XCNEWVEC (arc_t, description->insns_num);
6225 /* Process insns of the arcs. */
6226 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6227 insn_arcs_array [arc->insn->insn_reserv_decl->insn_num] = arc;
6228 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6229 process_insn_equiv_class (arc->insn, insn_arcs_array);
6231 free (insn_arcs_array);
6234 /* The function searches for equivalent ainsns of AUTOMATON. */
6235 static void
6236 set_insn_equiv_classes (automaton_t automaton)
6238 ainsn_t ainsn;
6239 ainsn_t first_insn;
6240 ainsn_t curr_insn;
6241 ainsn_t cyclic_insn_list;
6242 ainsn_t insn_with_same_reservs;
6243 int equiv_classes_num;
6245 /* All insns are included in one equivalence class. */
6246 cyclic_insn_list = NULL;
6247 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6248 if (ainsn->first_insn_with_same_reservs)
6249 cyclic_insn_list = insert_ainsn_into_equiv_class (ainsn,
6250 cyclic_insn_list);
6251 /* Process insns in order to make equivalence partition. */
6252 pass_states (automaton, process_state_for_insn_equiv_partition);
6253 /* Enumerate equiv classes. */
6254 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6255 /* Set undefined value. */
6256 ainsn->insn_equiv_class_num = -1;
6257 equiv_classes_num = 0;
6258 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6259 if (ainsn->insn_equiv_class_num < 0)
6261 first_insn = ainsn;
6262 gcc_assert (first_insn->first_insn_with_same_reservs);
6263 first_insn->first_ainsn_with_given_equivalence_num = 1;
6264 curr_insn = first_insn;
6267 for (insn_with_same_reservs = curr_insn;
6268 insn_with_same_reservs != NULL;
6269 insn_with_same_reservs
6270 = insn_with_same_reservs->next_same_reservs_insn)
6271 insn_with_same_reservs->insn_equiv_class_num = equiv_classes_num;
6272 curr_insn = curr_insn->next_equiv_class_insn;
6274 while (curr_insn != first_insn);
6275 equiv_classes_num++;
6277 automaton->insn_equiv_classes_num = equiv_classes_num;
6282 /* This page contains code for creating DFA(s) and calls functions
6283 building them. */
6286 /* The following value is used to prevent floating point overflow for
6287 estimating an automaton bound. The value should be less DBL_MAX on
6288 the host machine. We use here approximate minimum of maximal
6289 double floating point value required by ANSI C standard. It
6290 will work for non ANSI sun compiler too. */
6292 #define MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND 1.0E37
6294 /* The function estimate size of the single DFA used by PHR (pipeline
6295 hazards recognizer). */
6296 static double
6297 estimate_one_automaton_bound (void)
6299 decl_t decl;
6300 double one_automaton_estimation_bound;
6301 double root_value;
6302 int i;
6304 one_automaton_estimation_bound = 1.0;
6305 for (i = 0; i < description->decls_num; i++)
6307 decl = description->decls [i];
6308 if (decl->mode == dm_unit)
6310 root_value = exp (log (DECL_UNIT (decl)->max_occ_cycle_num
6311 - DECL_UNIT (decl)->min_occ_cycle_num + 1.0)
6312 / automata_num);
6313 if (MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND / root_value
6314 > one_automaton_estimation_bound)
6315 one_automaton_estimation_bound *= root_value;
6318 return one_automaton_estimation_bound;
6321 /* The function compares unit declarations according to their maximal
6322 cycle in reservations. */
6323 static int
6324 compare_max_occ_cycle_nums (const void *unit_decl_1,
6325 const void *unit_decl_2)
6327 if ((DECL_UNIT (*(decl_t *) unit_decl_1)->max_occ_cycle_num)
6328 < (DECL_UNIT (*(decl_t *) unit_decl_2)->max_occ_cycle_num))
6329 return 1;
6330 else if ((DECL_UNIT (*(decl_t *) unit_decl_1)->max_occ_cycle_num)
6331 == (DECL_UNIT (*(decl_t *) unit_decl_2)->max_occ_cycle_num))
6332 return 0;
6333 else
6334 return -1;
6337 /* The function makes heuristic assigning automata to units. Actually
6338 efficacy of the algorithm has been checked yet??? */
6340 static void
6341 units_to_automata_heuristic_distr (void)
6343 double estimation_bound;
6344 int automaton_num;
6345 int rest_units_num;
6346 double bound_value;
6347 unit_decl_t *unit_decls;
6348 int i, j;
6350 if (description->units_num == 0)
6351 return;
6352 estimation_bound = estimate_one_automaton_bound ();
6353 unit_decls = XNEWVEC (unit_decl_t, description->units_num);
6355 for (i = 0, j = 0; i < description->decls_num; i++)
6356 if (description->decls[i]->mode == dm_unit)
6357 unit_decls[j++] = DECL_UNIT (description->decls[i]);
6358 gcc_assert (j == description->units_num);
6360 qsort (unit_decls, description->units_num,
6361 sizeof (unit_decl_t), compare_max_occ_cycle_nums);
6363 automaton_num = 0;
6364 bound_value = unit_decls[0]->max_occ_cycle_num;
6365 unit_decls[0]->corresponding_automaton_num = automaton_num;
6367 for (i = 1; i < description->units_num; i++)
6369 rest_units_num = description->units_num - i + 1;
6370 gcc_assert (automata_num - automaton_num - 1 <= rest_units_num);
6371 if (automaton_num < automata_num - 1
6372 && ((automata_num - automaton_num - 1 == rest_units_num)
6373 || (bound_value
6374 > (estimation_bound
6375 / unit_decls[i]->max_occ_cycle_num))))
6377 bound_value = unit_decls[i]->max_occ_cycle_num;
6378 automaton_num++;
6380 else
6381 bound_value *= unit_decls[i]->max_occ_cycle_num;
6382 unit_decls[i]->corresponding_automaton_num = automaton_num;
6384 gcc_assert (automaton_num == automata_num - 1);
6385 free (unit_decls);
6388 /* The functions creates automaton insns for each automata. Automaton
6389 insn is simply insn for given automaton which makes reservation
6390 only of units of the automaton. */
6391 static ainsn_t
6392 create_ainsns (void)
6394 decl_t decl;
6395 ainsn_t first_ainsn;
6396 ainsn_t curr_ainsn;
6397 ainsn_t prev_ainsn;
6398 int i;
6400 first_ainsn = NULL;
6401 prev_ainsn = NULL;
6402 for (i = 0; i < description->decls_num; i++)
6404 decl = description->decls [i];
6405 if (decl->mode == dm_insn_reserv)
6407 curr_ainsn = create_node (sizeof (struct ainsn));
6408 curr_ainsn->insn_reserv_decl = DECL_INSN_RESERV (decl);
6409 curr_ainsn->important_p = FALSE;
6410 curr_ainsn->next_ainsn = NULL;
6411 if (prev_ainsn == NULL)
6412 first_ainsn = curr_ainsn;
6413 else
6414 prev_ainsn->next_ainsn = curr_ainsn;
6415 prev_ainsn = curr_ainsn;
6418 return first_ainsn;
6421 /* The function assigns automata to units according to constructions
6422 `define_automaton' in the description. */
6423 static void
6424 units_to_automata_distr (void)
6426 decl_t decl;
6427 int i;
6429 for (i = 0; i < description->decls_num; i++)
6431 decl = description->decls [i];
6432 if (decl->mode == dm_unit)
6434 if (DECL_UNIT (decl)->automaton_decl == NULL
6435 || (DECL_UNIT (decl)->automaton_decl->corresponding_automaton
6436 == NULL))
6437 /* Distribute to the first automaton. */
6438 DECL_UNIT (decl)->corresponding_automaton_num = 0;
6439 else
6440 DECL_UNIT (decl)->corresponding_automaton_num
6441 = (DECL_UNIT (decl)->automaton_decl
6442 ->corresponding_automaton->automaton_order_num);
6447 /* The function creates DFA(s) for fast pipeline hazards recognition
6448 after checking and simplifying IR of the description. */
6449 static void
6450 create_automata (void)
6452 automaton_t curr_automaton;
6453 automaton_t prev_automaton;
6454 decl_t decl;
6455 int curr_automaton_num;
6456 int i;
6458 if (automata_num != 0)
6460 units_to_automata_heuristic_distr ();
6461 for (prev_automaton = NULL, curr_automaton_num = 0;
6462 curr_automaton_num < automata_num;
6463 curr_automaton_num++, prev_automaton = curr_automaton)
6465 curr_automaton = create_node (sizeof (struct automaton));
6466 curr_automaton->ainsn_list = create_ainsns ();
6467 curr_automaton->corresponding_automaton_decl = NULL;
6468 curr_automaton->next_automaton = NULL;
6469 curr_automaton->automaton_order_num = curr_automaton_num;
6470 if (prev_automaton == NULL)
6471 description->first_automaton = curr_automaton;
6472 else
6473 prev_automaton->next_automaton = curr_automaton;
6476 else
6478 curr_automaton_num = 0;
6479 prev_automaton = NULL;
6480 for (i = 0; i < description->decls_num; i++)
6482 decl = description->decls [i];
6483 if (decl->mode == dm_automaton
6484 && DECL_AUTOMATON (decl)->automaton_is_used)
6486 curr_automaton = create_node (sizeof (struct automaton));
6487 curr_automaton->ainsn_list = create_ainsns ();
6488 curr_automaton->corresponding_automaton_decl
6489 = DECL_AUTOMATON (decl);
6490 curr_automaton->next_automaton = NULL;
6491 DECL_AUTOMATON (decl)->corresponding_automaton = curr_automaton;
6492 curr_automaton->automaton_order_num = curr_automaton_num;
6493 if (prev_automaton == NULL)
6494 description->first_automaton = curr_automaton;
6495 else
6496 prev_automaton->next_automaton = curr_automaton;
6497 curr_automaton_num++;
6498 prev_automaton = curr_automaton;
6501 if (curr_automaton_num == 0)
6503 curr_automaton = create_node (sizeof (struct automaton));
6504 curr_automaton->ainsn_list = create_ainsns ();
6505 curr_automaton->corresponding_automaton_decl = NULL;
6506 curr_automaton->next_automaton = NULL;
6507 description->first_automaton = curr_automaton;
6509 units_to_automata_distr ();
6511 NDFA_time = create_ticker ();
6512 ticker_off (&NDFA_time);
6513 NDFA_to_DFA_time = create_ticker ();
6514 ticker_off (&NDFA_to_DFA_time);
6515 minimize_time = create_ticker ();
6516 ticker_off (&minimize_time);
6517 equiv_time = create_ticker ();
6518 ticker_off (&equiv_time);
6519 for (curr_automaton = description->first_automaton;
6520 curr_automaton != NULL;
6521 curr_automaton = curr_automaton->next_automaton)
6523 if (progress_flag)
6525 if (curr_automaton->corresponding_automaton_decl == NULL)
6526 fprintf (stderr, "Prepare anonymous automaton creation ... ");
6527 else
6528 fprintf (stderr, "Prepare automaton `%s' creation...",
6529 curr_automaton->corresponding_automaton_decl->name);
6531 create_alt_states (curr_automaton);
6532 form_ainsn_with_same_reservs (curr_automaton);
6533 if (progress_flag)
6534 fprintf (stderr, "done\n");
6535 build_automaton (curr_automaton);
6536 enumerate_states (curr_automaton);
6537 ticker_on (&equiv_time);
6538 set_insn_equiv_classes (curr_automaton);
6539 ticker_off (&equiv_time);
6545 /* This page contains code for forming string representation of
6546 regexp. The representation is formed on IR obstack. So you should
6547 not work with IR obstack between regexp_representation and
6548 finish_regexp_representation calls. */
6550 /* This recursive function forms string representation of regexp
6551 (without tailing '\0'). */
6552 static void
6553 form_regexp (regexp_t regexp)
6555 int i;
6557 switch (regexp->mode)
6559 case rm_unit: case rm_reserv:
6561 const char *name = (regexp->mode == rm_unit
6562 ? REGEXP_UNIT (regexp)->name
6563 : REGEXP_RESERV (regexp)->name);
6565 obstack_grow (&irp, name, strlen (name));
6566 break;
6569 case rm_sequence:
6570 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
6572 if (i != 0)
6573 obstack_1grow (&irp, ',');
6574 form_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
6576 break;
6578 case rm_allof:
6579 obstack_1grow (&irp, '(');
6580 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
6582 if (i != 0)
6583 obstack_1grow (&irp, '+');
6584 if (REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_sequence
6585 || REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_oneof)
6586 obstack_1grow (&irp, '(');
6587 form_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
6588 if (REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_sequence
6589 || REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_oneof)
6590 obstack_1grow (&irp, ')');
6592 obstack_1grow (&irp, ')');
6593 break;
6595 case rm_oneof:
6596 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
6598 if (i != 0)
6599 obstack_1grow (&irp, '|');
6600 if (REGEXP_ONEOF (regexp)->regexps[i]->mode == rm_sequence)
6601 obstack_1grow (&irp, '(');
6602 form_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
6603 if (REGEXP_ONEOF (regexp)->regexps[i]->mode == rm_sequence)
6604 obstack_1grow (&irp, ')');
6606 break;
6608 case rm_repeat:
6610 char digits [30];
6612 if (REGEXP_REPEAT (regexp)->regexp->mode == rm_sequence
6613 || REGEXP_REPEAT (regexp)->regexp->mode == rm_allof
6614 || REGEXP_REPEAT (regexp)->regexp->mode == rm_oneof)
6615 obstack_1grow (&irp, '(');
6616 form_regexp (REGEXP_REPEAT (regexp)->regexp);
6617 if (REGEXP_REPEAT (regexp)->regexp->mode == rm_sequence
6618 || REGEXP_REPEAT (regexp)->regexp->mode == rm_allof
6619 || REGEXP_REPEAT (regexp)->regexp->mode == rm_oneof)
6620 obstack_1grow (&irp, ')');
6621 sprintf (digits, "*%d", REGEXP_REPEAT (regexp)->repeat_num);
6622 obstack_grow (&irp, digits, strlen (digits));
6623 break;
6626 case rm_nothing:
6627 obstack_grow (&irp, NOTHING_NAME, strlen (NOTHING_NAME));
6628 break;
6630 default:
6631 gcc_unreachable ();
6635 /* The function returns string representation of REGEXP on IR
6636 obstack. */
6637 static const char *
6638 regexp_representation (regexp_t regexp)
6640 form_regexp (regexp);
6641 obstack_1grow (&irp, '\0');
6642 return obstack_base (&irp);
6645 /* The function frees memory allocated for last formed string
6646 representation of regexp. */
6647 static void
6648 finish_regexp_representation (void)
6650 int length = obstack_object_size (&irp);
6652 obstack_blank_fast (&irp, -length);
6657 /* This page contains code for output PHR (pipeline hazards recognizer). */
6659 /* The function outputs minimal C type which is sufficient for
6660 representation numbers in range min_range_value and
6661 max_range_value. Because host machine and build machine may be
6662 different, we use here minimal values required by ANSI C standard
6663 instead of UCHAR_MAX, SHRT_MAX, SHRT_MIN, etc. This is a good
6664 approximation. */
6666 static void
6667 output_range_type (FILE *f, long int min_range_value,
6668 long int max_range_value)
6670 if (min_range_value >= 0 && max_range_value <= 255)
6671 fprintf (f, "unsigned char");
6672 else if (min_range_value >= -127 && max_range_value <= 127)
6673 fprintf (f, "signed char");
6674 else if (min_range_value >= 0 && max_range_value <= 65535)
6675 fprintf (f, "unsigned short");
6676 else if (min_range_value >= -32767 && max_range_value <= 32767)
6677 fprintf (f, "short");
6678 else
6679 fprintf (f, "int");
6682 /* The following macro value is used as value of member
6683 `longest_path_length' of state when we are processing path and the
6684 state on the path. */
6686 #define ON_THE_PATH -2
6688 /* The following recursive function searches for the length of the
6689 longest path starting from STATE which does not contain cycles and
6690 `cycle advance' arcs. */
6692 static int
6693 longest_path_length (state_t state)
6695 arc_t arc;
6696 int length, result;
6698 if (state->longest_path_length != UNDEFINED_LONGEST_PATH_LENGTH)
6700 /* We don't expect the path cycle here. Our graph may contain
6701 only cycles with one state on the path not containing `cycle
6702 advance' arcs -- see comment below. */
6703 gcc_assert (state->longest_path_length != ON_THE_PATH);
6705 /* We already visited the state. */
6706 return state->longest_path_length;
6709 result = 0;
6710 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6711 /* Ignore cycles containing one state and `cycle advance' arcs. */
6712 if (arc->to_state != state
6713 && (arc->insn->insn_reserv_decl
6714 != DECL_INSN_RESERV (advance_cycle_insn_decl)))
6716 length = longest_path_length (arc->to_state);
6717 if (length > result)
6718 result = length;
6720 state->longest_path_length = result + 1;
6721 return result;
6724 /* The function outputs all initialization values of VECT. */
6725 static void
6726 output_vect (vla_hwint_t vect)
6728 int els_on_line;
6729 size_t vect_length = VEC_length (vect_el_t, vect);
6730 size_t i;
6732 els_on_line = 1;
6733 if (vect_length == 0)
6734 fputs ("0 /* This is dummy el because the vect is empty */", output_file);
6735 else
6736 for (i = 0; i < vect_length; i++)
6738 fprintf (output_file, "%5ld", (long) VEC_index (vect_el_t, vect, i));
6739 if (els_on_line == 10)
6741 els_on_line = 0;
6742 fputs (",\n", output_file);
6744 else if (i < vect_length-1)
6745 fputs (", ", output_file);
6746 els_on_line++;
6750 /* The following is name of the structure which represents DFA(s) for
6751 PHR. */
6752 #define CHIP_NAME "DFA_chip"
6754 /* The following is name of member which represents state of a DFA for
6755 PHR. */
6756 static void
6757 output_chip_member_name (FILE *f, automaton_t automaton)
6759 if (automaton->corresponding_automaton_decl == NULL)
6760 fprintf (f, "automaton_state_%d", automaton->automaton_order_num);
6761 else
6762 fprintf (f, "%s_automaton_state",
6763 automaton->corresponding_automaton_decl->name);
6766 /* The following is name of temporary variable which stores state of a
6767 DFA for PHR. */
6768 static void
6769 output_temp_chip_member_name (FILE *f, automaton_t automaton)
6771 fprintf (f, "_");
6772 output_chip_member_name (f, automaton);
6775 /* This is name of macro value which is code of pseudo_insn
6776 representing advancing cpu cycle. Its value is used as internal
6777 code unknown insn. */
6778 #define ADVANCE_CYCLE_VALUE_NAME "DFA__ADVANCE_CYCLE"
6780 /* Output name of translate vector for given automaton. */
6781 static void
6782 output_translate_vect_name (FILE *f, automaton_t automaton)
6784 if (automaton->corresponding_automaton_decl == NULL)
6785 fprintf (f, "translate_%d", automaton->automaton_order_num);
6786 else
6787 fprintf (f, "%s_translate", automaton->corresponding_automaton_decl->name);
6790 /* Output name for simple transition table representation. */
6791 static void
6792 output_trans_full_vect_name (FILE *f, automaton_t automaton)
6794 if (automaton->corresponding_automaton_decl == NULL)
6795 fprintf (f, "transitions_%d", automaton->automaton_order_num);
6796 else
6797 fprintf (f, "%s_transitions",
6798 automaton->corresponding_automaton_decl->name);
6801 /* Output name of comb vector of the transition table for given
6802 automaton. */
6803 static void
6804 output_trans_comb_vect_name (FILE *f, automaton_t automaton)
6806 if (automaton->corresponding_automaton_decl == NULL)
6807 fprintf (f, "transitions_%d", automaton->automaton_order_num);
6808 else
6809 fprintf (f, "%s_transitions",
6810 automaton->corresponding_automaton_decl->name);
6813 /* Output name of check vector of the transition table for given
6814 automaton. */
6815 static void
6816 output_trans_check_vect_name (FILE *f, automaton_t automaton)
6818 if (automaton->corresponding_automaton_decl == NULL)
6819 fprintf (f, "check_%d", automaton->automaton_order_num);
6820 else
6821 fprintf (f, "%s_check", automaton->corresponding_automaton_decl->name);
6824 /* Output name of base vector of the transition table for given
6825 automaton. */
6826 static void
6827 output_trans_base_vect_name (FILE *f, automaton_t automaton)
6829 if (automaton->corresponding_automaton_decl == NULL)
6830 fprintf (f, "base_%d", automaton->automaton_order_num);
6831 else
6832 fprintf (f, "%s_base", automaton->corresponding_automaton_decl->name);
6835 /* Output name of simple min issue delay table representation. */
6836 static void
6837 output_min_issue_delay_vect_name (FILE *f, automaton_t automaton)
6839 if (automaton->corresponding_automaton_decl == NULL)
6840 fprintf (f, "min_issue_delay_%d", automaton->automaton_order_num);
6841 else
6842 fprintf (f, "%s_min_issue_delay",
6843 automaton->corresponding_automaton_decl->name);
6846 /* Output name of deadlock vector for given automaton. */
6847 static void
6848 output_dead_lock_vect_name (FILE *f, automaton_t automaton)
6850 if (automaton->corresponding_automaton_decl == NULL)
6851 fprintf (f, "dead_lock_%d", automaton->automaton_order_num);
6852 else
6853 fprintf (f, "%s_dead_lock", automaton->corresponding_automaton_decl->name);
6856 /* Output name of reserved units table for AUTOMATON into file F. */
6857 static void
6858 output_reserved_units_table_name (FILE *f, automaton_t automaton)
6860 if (automaton->corresponding_automaton_decl == NULL)
6861 fprintf (f, "reserved_units_%d", automaton->automaton_order_num);
6862 else
6863 fprintf (f, "%s_reserved_units",
6864 automaton->corresponding_automaton_decl->name);
6867 /* Name of the PHR interface macro. */
6868 #define CPU_UNITS_QUERY_MACRO_NAME "CPU_UNITS_QUERY"
6870 /* Names of an internal functions: */
6871 #define INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME "internal_min_issue_delay"
6873 /* This is external type of DFA(s) state. */
6874 #define STATE_TYPE_NAME "state_t"
6876 #define INTERNAL_TRANSITION_FUNC_NAME "internal_state_transition"
6878 #define INTERNAL_RESET_FUNC_NAME "internal_reset"
6880 #define INTERNAL_DEAD_LOCK_FUNC_NAME "internal_state_dead_lock_p"
6882 #define INTERNAL_INSN_LATENCY_FUNC_NAME "internal_insn_latency"
6884 /* Name of cache of insn dfa codes. */
6885 #define DFA_INSN_CODES_VARIABLE_NAME "dfa_insn_codes"
6887 /* Name of length of cache of insn dfa codes. */
6888 #define DFA_INSN_CODES_LENGTH_VARIABLE_NAME "dfa_insn_codes_length"
6890 /* Names of the PHR interface functions: */
6891 #define SIZE_FUNC_NAME "state_size"
6893 #define TRANSITION_FUNC_NAME "state_transition"
6895 #define MIN_ISSUE_DELAY_FUNC_NAME "min_issue_delay"
6897 #define MIN_INSN_CONFLICT_DELAY_FUNC_NAME "min_insn_conflict_delay"
6899 #define DEAD_LOCK_FUNC_NAME "state_dead_lock_p"
6901 #define RESET_FUNC_NAME "state_reset"
6903 #define INSN_LATENCY_FUNC_NAME "insn_latency"
6905 #define PRINT_RESERVATION_FUNC_NAME "print_reservation"
6907 #define GET_CPU_UNIT_CODE_FUNC_NAME "get_cpu_unit_code"
6909 #define CPU_UNIT_RESERVATION_P_FUNC_NAME "cpu_unit_reservation_p"
6911 #define DFA_CLEAN_INSN_CACHE_FUNC_NAME "dfa_clean_insn_cache"
6913 #define DFA_CLEAR_SINGLE_INSN_CACHE_FUNC_NAME "dfa_clear_single_insn_cache"
6915 #define DFA_START_FUNC_NAME "dfa_start"
6917 #define DFA_FINISH_FUNC_NAME "dfa_finish"
6919 /* Names of parameters of the PHR interface functions. */
6920 #define STATE_NAME "state"
6922 #define INSN_PARAMETER_NAME "insn"
6924 #define INSN2_PARAMETER_NAME "insn2"
6926 #define CHIP_PARAMETER_NAME "chip"
6928 #define FILE_PARAMETER_NAME "f"
6930 #define CPU_UNIT_NAME_PARAMETER_NAME "cpu_unit_name"
6932 #define CPU_CODE_PARAMETER_NAME "cpu_unit_code"
6934 /* Names of the variables whose values are internal insn code of rtx
6935 insn. */
6936 #define INTERNAL_INSN_CODE_NAME "insn_code"
6938 #define INTERNAL_INSN2_CODE_NAME "insn2_code"
6940 /* Names of temporary variables in some functions. */
6941 #define TEMPORARY_VARIABLE_NAME "temp"
6943 #define I_VARIABLE_NAME "i"
6945 /* Name of result variable in some functions. */
6946 #define RESULT_VARIABLE_NAME "res"
6948 /* Name of function (attribute) to translate insn into internal insn
6949 code. */
6950 #define INTERNAL_DFA_INSN_CODE_FUNC_NAME "internal_dfa_insn_code"
6952 /* Name of function (attribute) to translate insn into internal insn
6953 code with caching. */
6954 #define DFA_INSN_CODE_FUNC_NAME "dfa_insn_code"
6956 /* Output C type which is used for representation of codes of states
6957 of AUTOMATON. */
6958 static void
6959 output_state_member_type (FILE *f, automaton_t automaton)
6961 output_range_type (f, 0, automaton->achieved_states_num);
6964 /* Output definition of the structure representing current DFA(s)
6965 state(s). */
6966 static void
6967 output_chip_definitions (void)
6969 automaton_t automaton;
6971 fprintf (output_file, "struct %s\n{\n", CHIP_NAME);
6972 for (automaton = description->first_automaton;
6973 automaton != NULL;
6974 automaton = automaton->next_automaton)
6976 fprintf (output_file, " ");
6977 output_state_member_type (output_file, automaton);
6978 fprintf (output_file, " ");
6979 output_chip_member_name (output_file, automaton);
6980 fprintf (output_file, ";\n");
6982 fprintf (output_file, "};\n\n");
6983 #if 0
6984 fprintf (output_file, "static struct %s %s;\n\n", CHIP_NAME, CHIP_NAME);
6985 #endif
6989 /* The function outputs translate vector of internal insn code into
6990 insn equivalence class number. The equivalence class number is
6991 used to access to table and vectors representing DFA(s). */
6992 static void
6993 output_translate_vect (automaton_t automaton)
6995 ainsn_t ainsn;
6996 int insn_value;
6997 vla_hwint_t translate_vect;
6999 translate_vect = VEC_alloc (vect_el_t,heap, description->insns_num);
7001 for (insn_value = 0; insn_value < description->insns_num; insn_value++)
7002 /* Undefined value */
7003 VEC_quick_push (vect_el_t, translate_vect,
7004 automaton->insn_equiv_classes_num);
7006 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
7007 VEC_replace (vect_el_t, translate_vect,
7008 ainsn->insn_reserv_decl->insn_num,
7009 ainsn->insn_equiv_class_num);
7011 fprintf (output_file,
7012 "/* Vector translating external insn codes to internal ones.*/\n");
7013 fprintf (output_file, "static const ");
7014 output_range_type (output_file, 0, automaton->insn_equiv_classes_num);
7015 fprintf (output_file, " ");
7016 output_translate_vect_name (output_file, automaton);
7017 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7018 output_vect (translate_vect);
7019 fprintf (output_file, "};\n\n");
7020 VEC_free (vect_el_t,heap, translate_vect);
7023 /* The value in a table state x ainsn -> something which represents
7024 undefined value. */
7025 static int undefined_vect_el_value;
7027 /* The following function returns nonzero value if the best
7028 representation of the table is comb vector. */
7029 static int
7030 comb_vect_p (state_ainsn_table_t tab)
7032 return (2 * VEC_length (vect_el_t, tab->full_vect)
7033 > 5 * VEC_length (vect_el_t, tab->comb_vect));
7036 /* The following function creates new table for AUTOMATON. */
7037 static state_ainsn_table_t
7038 create_state_ainsn_table (automaton_t automaton)
7040 state_ainsn_table_t tab;
7041 int full_vect_length;
7042 int i;
7044 tab = create_node (sizeof (struct state_ainsn_table));
7045 tab->automaton = automaton;
7047 tab->comb_vect = VEC_alloc (vect_el_t,heap, 10000);
7048 tab->check_vect = VEC_alloc (vect_el_t,heap, 10000);
7050 tab->base_vect = 0;
7051 VEC_safe_grow (vect_el_t,heap, tab->base_vect,
7052 automaton->achieved_states_num);
7054 full_vect_length = (automaton->insn_equiv_classes_num
7055 * automaton->achieved_states_num);
7056 tab->full_vect = VEC_alloc (vect_el_t,heap, full_vect_length);
7057 for (i = 0; i < full_vect_length; i++)
7058 VEC_quick_push (vect_el_t, tab->full_vect, undefined_vect_el_value);
7060 tab->min_base_vect_el_value = 0;
7061 tab->max_base_vect_el_value = 0;
7062 tab->min_comb_vect_el_value = 0;
7063 tab->max_comb_vect_el_value = 0;
7064 return tab;
7067 /* The following function outputs the best C representation of the
7068 table TAB of given TABLE_NAME. */
7069 static void
7070 output_state_ainsn_table (state_ainsn_table_t tab, const char *table_name,
7071 void (*output_full_vect_name_func) (FILE *, automaton_t),
7072 void (*output_comb_vect_name_func) (FILE *, automaton_t),
7073 void (*output_check_vect_name_func) (FILE *, automaton_t),
7074 void (*output_base_vect_name_func) (FILE *, automaton_t))
7076 if (!comb_vect_p (tab))
7078 fprintf (output_file, "/* Vector for %s. */\n", table_name);
7079 fprintf (output_file, "static const ");
7080 output_range_type (output_file, tab->min_comb_vect_el_value,
7081 tab->max_comb_vect_el_value);
7082 fprintf (output_file, " ");
7083 (*output_full_vect_name_func) (output_file, tab->automaton);
7084 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7085 output_vect (tab->full_vect);
7086 fprintf (output_file, "};\n\n");
7088 else
7090 fprintf (output_file, "/* Comb vector for %s. */\n", table_name);
7091 fprintf (output_file, "static const ");
7092 output_range_type (output_file, tab->min_comb_vect_el_value,
7093 tab->max_comb_vect_el_value);
7094 fprintf (output_file, " ");
7095 (*output_comb_vect_name_func) (output_file, tab->automaton);
7096 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7097 output_vect (tab->comb_vect);
7098 fprintf (output_file, "};\n\n");
7099 fprintf (output_file, "/* Check vector for %s. */\n", table_name);
7100 fprintf (output_file, "static const ");
7101 output_range_type (output_file, 0, tab->automaton->achieved_states_num);
7102 fprintf (output_file, " ");
7103 (*output_check_vect_name_func) (output_file, tab->automaton);
7104 fprintf (output_file, "[] = {\n");
7105 output_vect (tab->check_vect);
7106 fprintf (output_file, "};\n\n");
7107 fprintf (output_file, "/* Base vector for %s. */\n", table_name);
7108 fprintf (output_file, "static const ");
7109 output_range_type (output_file, tab->min_base_vect_el_value,
7110 tab->max_base_vect_el_value);
7111 fprintf (output_file, " ");
7112 (*output_base_vect_name_func) (output_file, tab->automaton);
7113 fprintf (output_file, "[] = {\n");
7114 output_vect (tab->base_vect);
7115 fprintf (output_file, "};\n\n");
7119 /* The following function adds vector VECT to table TAB as its line
7120 with number VECT_NUM. */
7121 static void
7122 add_vect (state_ainsn_table_t tab, int vect_num, vla_hwint_t vect)
7124 int vect_length;
7125 size_t real_vect_length;
7126 int comb_vect_index;
7127 int comb_vect_els_num;
7128 int vect_index;
7129 int first_unempty_vect_index;
7130 int additional_els_num;
7131 int no_state_value;
7132 vect_el_t vect_el;
7133 int i;
7134 unsigned long vect_mask, comb_vect_mask;
7136 vect_length = VEC_length (vect_el_t, vect);
7137 gcc_assert (vect_length);
7138 gcc_assert (VEC_last (vect_el_t, vect) != undefined_vect_el_value);
7139 real_vect_length = tab->automaton->insn_equiv_classes_num;
7140 /* Form full vector in the table: */
7142 size_t full_base = tab->automaton->insn_equiv_classes_num * vect_num;
7143 if (VEC_length (vect_el_t, tab->full_vect) < full_base + vect_length)
7144 VEC_safe_grow (vect_el_t,heap, tab->full_vect,
7145 full_base + vect_length);
7146 for (i = 0; i < vect_length; i++)
7147 VEC_replace (vect_el_t, tab->full_vect, full_base + i,
7148 VEC_index (vect_el_t, vect, i));
7150 /* Form comb vector in the table: */
7151 gcc_assert (VEC_length (vect_el_t, tab->comb_vect)
7152 == VEC_length (vect_el_t, tab->check_vect));
7154 comb_vect_els_num = VEC_length (vect_el_t, tab->comb_vect);
7155 for (first_unempty_vect_index = 0;
7156 first_unempty_vect_index < vect_length;
7157 first_unempty_vect_index++)
7158 if (VEC_index (vect_el_t, vect, first_unempty_vect_index)
7159 != undefined_vect_el_value)
7160 break;
7162 /* Search for the place in comb vect for the inserted vect. */
7164 /* Slow case. */
7165 if (vect_length - first_unempty_vect_index >= SIZEOF_LONG * CHAR_BIT)
7167 for (comb_vect_index = 0;
7168 comb_vect_index < comb_vect_els_num;
7169 comb_vect_index++)
7171 for (vect_index = first_unempty_vect_index;
7172 vect_index < vect_length
7173 && vect_index + comb_vect_index < comb_vect_els_num;
7174 vect_index++)
7175 if (VEC_index (vect_el_t, vect, vect_index)
7176 != undefined_vect_el_value
7177 && (VEC_index (vect_el_t, tab->comb_vect,
7178 vect_index + comb_vect_index)
7179 != undefined_vect_el_value))
7180 break;
7181 if (vect_index >= vect_length
7182 || vect_index + comb_vect_index >= comb_vect_els_num)
7183 break;
7185 goto found;
7188 /* Fast case. */
7189 vect_mask = 0;
7190 for (vect_index = first_unempty_vect_index;
7191 vect_index < vect_length;
7192 vect_index++)
7194 vect_mask = vect_mask << 1;
7195 if (VEC_index (vect_el_t, vect, vect_index) != undefined_vect_el_value)
7196 vect_mask |= 1;
7199 /* Search for the place in comb vect for the inserted vect. */
7200 comb_vect_index = 0;
7201 if (comb_vect_els_num == 0)
7202 goto found;
7204 comb_vect_mask = 0;
7205 for (vect_index = first_unempty_vect_index;
7206 vect_index < vect_length && vect_index < comb_vect_els_num;
7207 vect_index++)
7209 comb_vect_mask <<= 1;
7210 if (vect_index + comb_vect_index < comb_vect_els_num
7211 && VEC_index (vect_el_t, tab->comb_vect, vect_index + comb_vect_index)
7212 != undefined_vect_el_value)
7213 comb_vect_mask |= 1;
7215 if ((vect_mask & comb_vect_mask) == 0)
7216 goto found;
7218 for (comb_vect_index = 1, i = vect_length; i < comb_vect_els_num;
7219 comb_vect_index++, i++)
7221 comb_vect_mask = (comb_vect_mask << 1) | 1;
7222 comb_vect_mask ^= (VEC_index (vect_el_t, tab->comb_vect, i)
7223 == undefined_vect_el_value);
7224 if ((vect_mask & comb_vect_mask) == 0)
7225 goto found;
7227 for ( ; comb_vect_index < comb_vect_els_num; comb_vect_index++)
7229 comb_vect_mask <<= 1;
7230 if ((vect_mask & comb_vect_mask) == 0)
7231 goto found;
7234 found:
7235 /* Slot was found. */
7236 additional_els_num = comb_vect_index + real_vect_length - comb_vect_els_num;
7237 if (additional_els_num < 0)
7238 additional_els_num = 0;
7239 /* Expand comb and check vectors. */
7240 vect_el = undefined_vect_el_value;
7241 no_state_value = tab->automaton->achieved_states_num;
7242 while (additional_els_num > 0)
7244 VEC_safe_push (vect_el_t,heap, tab->comb_vect, vect_el);
7245 VEC_safe_push (vect_el_t,heap, tab->check_vect, no_state_value);
7246 additional_els_num--;
7248 gcc_assert (VEC_length (vect_el_t, tab->comb_vect)
7249 >= comb_vect_index + real_vect_length);
7250 /* Fill comb and check vectors. */
7251 for (vect_index = 0; vect_index < vect_length; vect_index++)
7252 if (VEC_index (vect_el_t, vect, vect_index) != undefined_vect_el_value)
7254 vect_el_t x = VEC_index (vect_el_t, vect, vect_index);
7255 gcc_assert (VEC_index (vect_el_t, tab->comb_vect,
7256 comb_vect_index + vect_index)
7257 == undefined_vect_el_value);
7258 gcc_assert (x >= 0);
7259 if (tab->max_comb_vect_el_value < x)
7260 tab->max_comb_vect_el_value = x;
7261 if (tab->min_comb_vect_el_value > x)
7262 tab->min_comb_vect_el_value = x;
7263 VEC_replace (vect_el_t, tab->comb_vect,
7264 comb_vect_index + vect_index, x);
7265 VEC_replace (vect_el_t, tab->check_vect,
7266 comb_vect_index + vect_index, vect_num);
7268 if (tab->max_comb_vect_el_value < undefined_vect_el_value)
7269 tab->max_comb_vect_el_value = undefined_vect_el_value;
7270 if (tab->min_comb_vect_el_value > undefined_vect_el_value)
7271 tab->min_comb_vect_el_value = undefined_vect_el_value;
7272 if (tab->max_base_vect_el_value < comb_vect_index)
7273 tab->max_base_vect_el_value = comb_vect_index;
7274 if (tab->min_base_vect_el_value > comb_vect_index)
7275 tab->min_base_vect_el_value = comb_vect_index;
7277 VEC_replace (vect_el_t, tab->base_vect, vect_num, comb_vect_index);
7280 /* Return number of out arcs of STATE. */
7281 static int
7282 out_state_arcs_num (state_t state)
7284 int result;
7285 arc_t arc;
7287 result = 0;
7288 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
7290 gcc_assert (arc->insn);
7291 if (arc->insn->first_ainsn_with_given_equivalence_num)
7292 result++;
7294 return result;
7297 /* Compare number of possible transitions from the states. */
7298 static int
7299 compare_transition_els_num (const void *state_ptr_1,
7300 const void *state_ptr_2)
7302 int transition_els_num_1;
7303 int transition_els_num_2;
7305 transition_els_num_1 = out_state_arcs_num (*(state_t *) state_ptr_1);
7306 transition_els_num_2 = out_state_arcs_num (*(state_t *) state_ptr_2);
7307 if (transition_els_num_1 < transition_els_num_2)
7308 return 1;
7309 else if (transition_els_num_1 == transition_els_num_2)
7310 return 0;
7311 else
7312 return -1;
7315 /* The function adds element EL_VALUE to vector VECT for a table state
7316 x AINSN. */
7317 static void
7318 add_vect_el (vla_hwint_t *vect, ainsn_t ainsn, int el_value)
7320 int equiv_class_num;
7321 int vect_index;
7323 gcc_assert (ainsn);
7324 equiv_class_num = ainsn->insn_equiv_class_num;
7325 for (vect_index = VEC_length (vect_el_t, *vect);
7326 vect_index <= equiv_class_num;
7327 vect_index++)
7328 VEC_safe_push (vect_el_t,heap, *vect, undefined_vect_el_value);
7329 VEC_replace (vect_el_t, *vect, equiv_class_num, el_value);
7332 /* This is for forming vector of states of an automaton. */
7333 static VEC(state_t,heap) *output_states_vect;
7335 /* The function is called by function pass_states. The function adds
7336 STATE to `output_states_vect'. */
7337 static void
7338 add_states_vect_el (state_t state)
7340 VEC_safe_push (state_t,heap, output_states_vect, state);
7343 /* Form and output vectors (comb, check, base or full vector)
7344 representing transition table of AUTOMATON. */
7345 static void
7346 output_trans_table (automaton_t automaton)
7348 size_t i;
7349 arc_t arc;
7350 vla_hwint_t transition_vect = 0;
7352 undefined_vect_el_value = automaton->achieved_states_num;
7353 automaton->trans_table = create_state_ainsn_table (automaton);
7354 /* Create vect of pointers to states ordered by num of transitions
7355 from the state (state with the maximum num is the first). */
7356 output_states_vect = 0;
7357 pass_states (automaton, add_states_vect_el);
7358 qsort (VEC_address (state_t, output_states_vect),
7359 VEC_length (state_t, output_states_vect),
7360 sizeof (state_t), compare_transition_els_num);
7362 for (i = 0; i < VEC_length (state_t, output_states_vect); i++)
7364 VEC_truncate (vect_el_t, transition_vect, 0);
7365 for (arc = first_out_arc (VEC_index (state_t, output_states_vect, i));
7366 arc != NULL;
7367 arc = next_out_arc (arc))
7369 gcc_assert (arc->insn);
7370 if (arc->insn->first_ainsn_with_given_equivalence_num)
7371 add_vect_el (&transition_vect, arc->insn,
7372 arc->to_state->order_state_num);
7374 add_vect (automaton->trans_table,
7375 VEC_index (state_t, output_states_vect, i)->order_state_num,
7376 transition_vect);
7378 output_state_ainsn_table
7379 (automaton->trans_table, "state transitions",
7380 output_trans_full_vect_name, output_trans_comb_vect_name,
7381 output_trans_check_vect_name, output_trans_base_vect_name);
7383 VEC_free (state_t,heap, output_states_vect);
7384 VEC_free (vect_el_t,heap, transition_vect);
7387 /* The current number of passing states to find minimal issue delay
7388 value for an ainsn and state. */
7389 static int curr_state_pass_num;
7391 /* This recursive function passes states to find minimal issue delay
7392 value for AINSN. The state being visited is STATE. The function
7393 returns minimal issue delay value for AINSN in STATE or -1 if we
7394 enter into a loop. */
7395 static int
7396 min_issue_delay_pass_states (state_t state, ainsn_t ainsn)
7398 arc_t arc;
7399 int min_insn_issue_delay, insn_issue_delay;
7401 if (state->state_pass_num == curr_state_pass_num
7402 || state->min_insn_issue_delay != -1)
7403 /* We've entered into a loop or already have the correct value for
7404 given state and ainsn. */
7405 return state->min_insn_issue_delay;
7406 state->state_pass_num = curr_state_pass_num;
7407 min_insn_issue_delay = -1;
7408 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
7409 if (arc->insn == ainsn)
7411 min_insn_issue_delay = 0;
7412 break;
7414 else
7416 insn_issue_delay = min_issue_delay_pass_states (arc->to_state, ainsn);
7417 if (insn_issue_delay != -1)
7419 if (arc->insn->insn_reserv_decl
7420 == DECL_INSN_RESERV (advance_cycle_insn_decl))
7421 insn_issue_delay++;
7422 if (min_insn_issue_delay == -1
7423 || min_insn_issue_delay > insn_issue_delay)
7425 min_insn_issue_delay = insn_issue_delay;
7426 if (insn_issue_delay == 0)
7427 break;
7431 return min_insn_issue_delay;
7434 /* The function searches minimal issue delay value for AINSN in STATE.
7435 The function can return negative value if we can not issue AINSN. We
7436 will report about it later. */
7437 static int
7438 min_issue_delay (state_t state, ainsn_t ainsn)
7440 curr_state_pass_num++;
7441 state->min_insn_issue_delay = min_issue_delay_pass_states (state, ainsn);
7442 return state->min_insn_issue_delay;
7445 /* The function initiates code for finding minimal issue delay values.
7446 It should be called only once. */
7447 static void
7448 initiate_min_issue_delay_pass_states (void)
7450 curr_state_pass_num = 0;
7453 /* Form and output vectors representing minimal issue delay table of
7454 AUTOMATON. The table is state x ainsn -> minimal issue delay of
7455 the ainsn. */
7456 static void
7457 output_min_issue_delay_table (automaton_t automaton)
7459 vla_hwint_t min_issue_delay_vect;
7460 vla_hwint_t compressed_min_issue_delay_vect;
7461 vect_el_t min_delay;
7462 ainsn_t ainsn;
7463 size_t i, min_issue_delay_len;
7464 size_t compressed_min_issue_delay_len;
7465 size_t cfactor;
7467 /* Create vect of pointers to states ordered by num of transitions
7468 from the state (state with the maximum num is the first). */
7469 output_states_vect = 0;
7470 pass_states (automaton, add_states_vect_el);
7472 min_issue_delay_len = (VEC_length (state_t, output_states_vect)
7473 * automaton->insn_equiv_classes_num);
7474 min_issue_delay_vect = VEC_alloc (vect_el_t,heap, min_issue_delay_len);
7475 for (i = 0; i < min_issue_delay_len; i++)
7476 VEC_quick_push (vect_el_t, min_issue_delay_vect, 0);
7478 automaton->max_min_delay = 0;
7479 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
7480 if (ainsn->first_ainsn_with_given_equivalence_num)
7482 for (i = 0; i < VEC_length (state_t, output_states_vect); i++)
7483 VEC_index (state_t, output_states_vect, i)->min_insn_issue_delay = -1;
7484 for (i = 0; i < VEC_length (state_t, output_states_vect); i++)
7486 state_t s = VEC_index (state_t, output_states_vect, i);
7487 min_delay = min_issue_delay (s, ainsn);
7488 if (automaton->max_min_delay < min_delay)
7489 automaton->max_min_delay = min_delay;
7490 VEC_replace (vect_el_t, min_issue_delay_vect,
7491 s->order_state_num
7492 * automaton->insn_equiv_classes_num
7493 + ainsn->insn_equiv_class_num,
7494 min_delay);
7497 fprintf (output_file, "/* Vector of min issue delay of insns. */\n");
7498 fprintf (output_file, "static const ");
7499 output_range_type (output_file, 0, automaton->max_min_delay);
7500 fprintf (output_file, " ");
7501 output_min_issue_delay_vect_name (output_file, automaton);
7502 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7503 /* Compress the vector. */
7504 if (automaton->max_min_delay < 2)
7505 cfactor = 8;
7506 else if (automaton->max_min_delay < 4)
7507 cfactor = 4;
7508 else if (automaton->max_min_delay < 16)
7509 cfactor = 2;
7510 else
7511 cfactor = 1;
7512 automaton->min_issue_delay_table_compression_factor = cfactor;
7514 compressed_min_issue_delay_len = (min_issue_delay_len+cfactor-1) / cfactor;
7515 compressed_min_issue_delay_vect
7516 = VEC_alloc (vect_el_t,heap, compressed_min_issue_delay_len);
7518 for (i = 0; i < compressed_min_issue_delay_len; i++)
7519 VEC_quick_push (vect_el_t, compressed_min_issue_delay_vect, 0);
7521 for (i = 0; i < min_issue_delay_len; i++)
7523 size_t ci = i / cfactor;
7524 vect_el_t x = VEC_index (vect_el_t, min_issue_delay_vect, i);
7525 vect_el_t cx = VEC_index (vect_el_t, compressed_min_issue_delay_vect, ci);
7527 cx |= x << (8 - (i % cfactor + 1) * (8 / cfactor));
7528 VEC_replace (vect_el_t, compressed_min_issue_delay_vect, ci, cx);
7530 output_vect (compressed_min_issue_delay_vect);
7531 fprintf (output_file, "};\n\n");
7532 VEC_free (state_t,heap, output_states_vect);
7533 VEC_free (vect_el_t,heap, min_issue_delay_vect);
7534 VEC_free (vect_el_t,heap, compressed_min_issue_delay_vect);
7537 /* Form and output vector representing the locked states of
7538 AUTOMATON. */
7539 static void
7540 output_dead_lock_vect (automaton_t automaton)
7542 size_t i;
7543 arc_t arc;
7544 vla_hwint_t dead_lock_vect = 0;
7546 /* Create vect of pointers to states ordered by num of
7547 transitions from the state (state with the maximum num is the
7548 first). */
7549 automaton->locked_states = 0;
7550 output_states_vect = 0;
7551 pass_states (automaton, add_states_vect_el);
7553 VEC_safe_grow (vect_el_t,heap, dead_lock_vect,
7554 VEC_length (state_t, output_states_vect));
7555 for (i = 0; i < VEC_length (state_t, output_states_vect); i++)
7557 state_t s = VEC_index (state_t, output_states_vect, i);
7558 arc = first_out_arc (s);
7559 gcc_assert (arc);
7560 if (next_out_arc (arc) == NULL
7561 && (arc->insn->insn_reserv_decl
7562 == DECL_INSN_RESERV (advance_cycle_insn_decl)))
7564 VEC_replace (vect_el_t, dead_lock_vect, s->order_state_num, 1);
7565 automaton->locked_states++;
7567 else
7568 VEC_replace (vect_el_t, dead_lock_vect, s->order_state_num, 0);
7570 if (automaton->locked_states == 0)
7571 return;
7573 fprintf (output_file, "/* Vector for locked state flags. */\n");
7574 fprintf (output_file, "static const ");
7575 output_range_type (output_file, 0, 1);
7576 fprintf (output_file, " ");
7577 output_dead_lock_vect_name (output_file, automaton);
7578 fprintf (output_file, "[] = {\n");
7579 output_vect (dead_lock_vect);
7580 fprintf (output_file, "};\n\n");
7581 VEC_free (state_t,heap, output_states_vect);
7582 VEC_free (vect_el_t,heap, dead_lock_vect);
7585 /* Form and output vector representing reserved units of the states of
7586 AUTOMATON. */
7587 static void
7588 output_reserved_units_table (automaton_t automaton)
7590 vla_hwint_t reserved_units_table = 0;
7591 int state_byte_size;
7592 int reserved_units_size;
7593 size_t n;
7594 int i;
7596 if (description->query_units_num == 0)
7597 return;
7599 /* Create vect of pointers to states. */
7600 output_states_vect = 0;
7601 pass_states (automaton, add_states_vect_el);
7602 /* Create vector. */
7603 state_byte_size = (description->query_units_num + 7) / 8;
7604 reserved_units_size = (VEC_length (state_t, output_states_vect)
7605 * state_byte_size);
7607 reserved_units_table = VEC_alloc (vect_el_t,heap, reserved_units_size);
7609 for (i = 0; i < reserved_units_size; i++)
7610 VEC_quick_push (vect_el_t, reserved_units_table, 0);
7611 for (n = 0; n < VEC_length (state_t, output_states_vect); n++)
7613 state_t s = VEC_index (state_t, output_states_vect, n);
7614 for (i = 0; i < description->units_num; i++)
7615 if (units_array [i]->query_p
7616 && first_cycle_unit_presence (s, i))
7618 int ri = (s->order_state_num * state_byte_size
7619 + units_array [i]->query_num / 8);
7620 vect_el_t x = VEC_index (vect_el_t, reserved_units_table, ri);
7622 x += 1 << (units_array [i]->query_num % 8);
7623 VEC_replace (vect_el_t, reserved_units_table, ri, x);
7626 fprintf (output_file, "\n#if %s\n", CPU_UNITS_QUERY_MACRO_NAME);
7627 fprintf (output_file, "/* Vector for reserved units of states. */\n");
7628 fprintf (output_file, "static const ");
7629 output_range_type (output_file, 0, 255);
7630 fprintf (output_file, " ");
7631 output_reserved_units_table_name (output_file, automaton);
7632 fprintf (output_file, "[] = {\n");
7633 output_vect (reserved_units_table);
7634 fprintf (output_file, "};\n#endif /* #if %s */\n\n",
7635 CPU_UNITS_QUERY_MACRO_NAME);
7637 VEC_free (state_t,heap, output_states_vect);
7638 VEC_free (vect_el_t,heap, reserved_units_table);
7641 /* The function outputs all tables representing DFA(s) used for fast
7642 pipeline hazards recognition. */
7643 static void
7644 output_tables (void)
7646 automaton_t automaton;
7648 initiate_min_issue_delay_pass_states ();
7649 for (automaton = description->first_automaton;
7650 automaton != NULL;
7651 automaton = automaton->next_automaton)
7653 output_translate_vect (automaton);
7654 output_trans_table (automaton);
7655 output_min_issue_delay_table (automaton);
7656 output_dead_lock_vect (automaton);
7657 output_reserved_units_table (automaton);
7659 fprintf (output_file, "\n#define %s %d\n\n", ADVANCE_CYCLE_VALUE_NAME,
7660 DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
7663 /* The function outputs definition and value of PHR interface variable
7664 `max_insn_queue_index'. Its value is not less than maximal queue
7665 length needed for the insn scheduler. */
7666 static void
7667 output_max_insn_queue_index_def (void)
7669 int i, max, latency;
7670 decl_t decl;
7672 max = description->max_insn_reserv_cycles;
7673 for (i = 0; i < description->decls_num; i++)
7675 decl = description->decls [i];
7676 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
7678 latency = DECL_INSN_RESERV (decl)->default_latency;
7679 if (latency > max)
7680 max = latency;
7682 else if (decl->mode == dm_bypass)
7684 latency = DECL_BYPASS (decl)->latency;
7685 if (latency > max)
7686 max = latency;
7689 for (i = 0; (1 << i) <= max; i++)
7691 gcc_assert (i >= 0);
7692 fprintf (output_file, "\nconst int max_insn_queue_index = %d;\n\n",
7693 (1 << i) - 1);
7696 /* The function outputs switch cases for insn reservations using
7697 function *output_automata_list_code. */
7698 static void
7699 output_insn_code_cases (void (*output_automata_list_code)
7700 (automata_list_el_t))
7702 decl_t decl, decl2;
7703 int i, j;
7705 for (i = 0; i < description->decls_num; i++)
7707 decl = description->decls [i];
7708 if (decl->mode == dm_insn_reserv)
7709 DECL_INSN_RESERV (decl)->processed_p = FALSE;
7711 for (i = 0; i < description->decls_num; i++)
7713 decl = description->decls [i];
7714 if (decl->mode == dm_insn_reserv
7715 && !DECL_INSN_RESERV (decl)->processed_p)
7717 for (j = i; j < description->decls_num; j++)
7719 decl2 = description->decls [j];
7720 if (decl2->mode == dm_insn_reserv
7721 && (DECL_INSN_RESERV (decl2)->important_automata_list
7722 == DECL_INSN_RESERV (decl)->important_automata_list))
7724 DECL_INSN_RESERV (decl2)->processed_p = TRUE;
7725 fprintf (output_file, " case %d: /* %s */\n",
7726 DECL_INSN_RESERV (decl2)->insn_num,
7727 DECL_INSN_RESERV (decl2)->name);
7730 (*output_automata_list_code)
7731 (DECL_INSN_RESERV (decl)->important_automata_list);
7737 /* The function outputs a code for evaluation of a minimal delay of
7738 issue of insns which have reservations in given AUTOMATA_LIST. */
7739 static void
7740 output_automata_list_min_issue_delay_code (automata_list_el_t automata_list)
7742 automata_list_el_t el;
7743 automaton_t automaton;
7745 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
7747 automaton = el->automaton;
7748 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
7749 output_min_issue_delay_vect_name (output_file, automaton);
7750 fprintf (output_file,
7751 (automaton->min_issue_delay_table_compression_factor != 1
7752 ? " [(" : " ["));
7753 output_translate_vect_name (output_file, automaton);
7754 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
7755 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7756 output_chip_member_name (output_file, automaton);
7757 fprintf (output_file, " * %d", automaton->insn_equiv_classes_num);
7758 if (automaton->min_issue_delay_table_compression_factor == 1)
7759 fprintf (output_file, "];\n");
7760 else
7762 fprintf (output_file, ") / %d];\n",
7763 automaton->min_issue_delay_table_compression_factor);
7764 fprintf (output_file, " %s = (%s >> (8 - (",
7765 TEMPORARY_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
7766 output_translate_vect_name (output_file, automaton);
7767 fprintf
7768 (output_file, " [%s] %% %d + 1) * %d)) & %d;\n",
7769 INTERNAL_INSN_CODE_NAME,
7770 automaton->min_issue_delay_table_compression_factor,
7771 8 / automaton->min_issue_delay_table_compression_factor,
7772 (1 << (8 / automaton->min_issue_delay_table_compression_factor))
7773 - 1);
7775 if (el == automata_list)
7776 fprintf (output_file, " %s = %s;\n",
7777 RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
7778 else
7780 fprintf (output_file, " if (%s > %s)\n",
7781 TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
7782 fprintf (output_file, " %s = %s;\n",
7783 RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
7786 fprintf (output_file, " break;\n\n");
7789 /* Output function `internal_min_issue_delay'. */
7790 static void
7791 output_internal_min_issue_delay_func (void)
7793 fprintf (output_file,
7794 "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
7795 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7796 CHIP_NAME, CHIP_PARAMETER_NAME);
7797 fprintf (output_file, "{\n int %s ATTRIBUTE_UNUSED;\n int %s = -1;\n",
7798 TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
7799 fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
7800 output_insn_code_cases (output_automata_list_min_issue_delay_code);
7801 fprintf (output_file,
7802 "\n default:\n %s = -1;\n break;\n }\n",
7803 RESULT_VARIABLE_NAME);
7804 fprintf (output_file, " return %s;\n", RESULT_VARIABLE_NAME);
7805 fprintf (output_file, "}\n\n");
7808 /* The function outputs a code changing state after issue of insns
7809 which have reservations in given AUTOMATA_LIST. */
7810 static void
7811 output_automata_list_transition_code (automata_list_el_t automata_list)
7813 automata_list_el_t el, next_el;
7815 fprintf (output_file, " {\n");
7816 if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
7817 for (el = automata_list;; el = next_el)
7819 next_el = el->next_automata_list_el;
7820 if (next_el == NULL)
7821 break;
7822 fprintf (output_file, " ");
7823 output_state_member_type (output_file, el->automaton);
7824 fprintf (output_file, " ");
7825 output_temp_chip_member_name (output_file, el->automaton);
7826 fprintf (output_file, ";\n");
7828 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
7829 if (comb_vect_p (el->automaton->trans_table))
7831 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
7832 output_trans_base_vect_name (output_file, el->automaton);
7833 fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
7834 output_chip_member_name (output_file, el->automaton);
7835 fprintf (output_file, "] + ");
7836 output_translate_vect_name (output_file, el->automaton);
7837 fprintf (output_file, " [%s];\n", INTERNAL_INSN_CODE_NAME);
7838 fprintf (output_file, " if (");
7839 output_trans_check_vect_name (output_file, el->automaton);
7840 fprintf (output_file, " [%s] != %s->",
7841 TEMPORARY_VARIABLE_NAME, CHIP_PARAMETER_NAME);
7842 output_chip_member_name (output_file, el->automaton);
7843 fprintf (output_file, ")\n");
7844 fprintf (output_file, " return %s (%s, %s);\n",
7845 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7846 CHIP_PARAMETER_NAME);
7847 fprintf (output_file, " else\n");
7848 fprintf (output_file, " ");
7849 if (el->next_automata_list_el != NULL)
7850 output_temp_chip_member_name (output_file, el->automaton);
7851 else
7853 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7854 output_chip_member_name (output_file, el->automaton);
7856 fprintf (output_file, " = ");
7857 output_trans_comb_vect_name (output_file, el->automaton);
7858 fprintf (output_file, " [%s];\n", TEMPORARY_VARIABLE_NAME);
7860 else
7862 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
7863 output_trans_full_vect_name (output_file, el->automaton);
7864 fprintf (output_file, " [");
7865 output_translate_vect_name (output_file, el->automaton);
7866 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
7867 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7868 output_chip_member_name (output_file, el->automaton);
7869 fprintf (output_file, " * %d];\n",
7870 el->automaton->insn_equiv_classes_num);
7871 fprintf (output_file, " if (%s >= %d)\n",
7872 TEMPORARY_VARIABLE_NAME, el->automaton->achieved_states_num);
7873 fprintf (output_file, " return %s (%s, %s);\n",
7874 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7875 CHIP_PARAMETER_NAME);
7876 fprintf (output_file, " else\n ");
7877 if (el->next_automata_list_el != NULL)
7878 output_temp_chip_member_name (output_file, el->automaton);
7879 else
7881 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7882 output_chip_member_name (output_file, el->automaton);
7884 fprintf (output_file, " = %s;\n", TEMPORARY_VARIABLE_NAME);
7886 if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
7887 for (el = automata_list;; el = next_el)
7889 next_el = el->next_automata_list_el;
7890 if (next_el == NULL)
7891 break;
7892 fprintf (output_file, " %s->", CHIP_PARAMETER_NAME);
7893 output_chip_member_name (output_file, el->automaton);
7894 fprintf (output_file, " = ");
7895 output_temp_chip_member_name (output_file, el->automaton);
7896 fprintf (output_file, ";\n");
7898 fprintf (output_file, " return -1;\n");
7899 fprintf (output_file, " }\n");
7902 /* Output function `internal_state_transition'. */
7903 static void
7904 output_internal_trans_func (void)
7906 fprintf (output_file,
7907 "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
7908 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7909 CHIP_NAME, CHIP_PARAMETER_NAME);
7910 fprintf (output_file, "{\n int %s ATTRIBUTE_UNUSED;\n", TEMPORARY_VARIABLE_NAME);
7911 fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
7912 output_insn_code_cases (output_automata_list_transition_code);
7913 fprintf (output_file, "\n default:\n return -1;\n }\n");
7914 fprintf (output_file, "}\n\n");
7917 /* Output code
7919 if (insn != 0)
7921 insn_code = dfa_insn_code (insn);
7922 if (insn_code > DFA__ADVANCE_CYCLE)
7923 return code;
7925 else
7926 insn_code = DFA__ADVANCE_CYCLE;
7928 where insn denotes INSN_NAME, insn_code denotes INSN_CODE_NAME, and
7929 code denotes CODE. */
7930 static void
7931 output_internal_insn_code_evaluation (const char *insn_name,
7932 const char *insn_code_name,
7933 int code)
7935 fprintf (output_file, "\n if (%s != 0)\n {\n", insn_name);
7936 fprintf (output_file, " %s = %s (%s);\n", insn_code_name,
7937 DFA_INSN_CODE_FUNC_NAME, insn_name);
7938 fprintf (output_file, " if (%s > %s)\n return %d;\n",
7939 insn_code_name, ADVANCE_CYCLE_VALUE_NAME, code);
7940 fprintf (output_file, " }\n else\n %s = %s;\n\n",
7941 insn_code_name, ADVANCE_CYCLE_VALUE_NAME);
7945 /* This function outputs `dfa_insn_code' and its helper function
7946 `dfa_insn_code_enlarge'. */
7947 static void
7948 output_dfa_insn_code_func (void)
7950 /* Emacs c-mode gets really confused if there's a { or } in column 0
7951 inside a string, so don't do that. */
7952 fprintf (output_file, "\
7953 static void\n\
7954 dfa_insn_code_enlarge (int uid)\n\
7955 {\n\
7956 int i = %s;\n\
7957 %s = 2 * uid;\n\
7958 %s = xrealloc (%s,\n\
7959 %s * sizeof(int));\n\
7960 for (; i < %s; i++)\n\
7961 %s[i] = -1;\n}\n\n",
7962 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
7963 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
7964 DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
7965 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
7966 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
7967 DFA_INSN_CODES_VARIABLE_NAME);
7968 fprintf (output_file, "\
7969 static inline int\n%s (rtx %s)\n\
7970 {\n\
7971 int uid = INSN_UID (%s);\n\
7972 int %s;\n\n",
7973 DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME,
7974 INSN_PARAMETER_NAME, INTERNAL_INSN_CODE_NAME);
7976 fprintf (output_file,
7977 " if (uid >= %s)\n dfa_insn_code_enlarge (uid);\n\n",
7978 DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
7979 fprintf (output_file, " %s = %s[uid];\n",
7980 INTERNAL_INSN_CODE_NAME, DFA_INSN_CODES_VARIABLE_NAME);
7981 fprintf (output_file, "\
7982 if (%s < 0)\n\
7983 {\n\
7984 %s = %s (%s);\n\
7985 %s[uid] = %s;\n\
7986 }\n",
7987 INTERNAL_INSN_CODE_NAME,
7988 INTERNAL_INSN_CODE_NAME,
7989 INTERNAL_DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME,
7990 DFA_INSN_CODES_VARIABLE_NAME, INTERNAL_INSN_CODE_NAME);
7991 fprintf (output_file, " return %s;\n}\n\n", INTERNAL_INSN_CODE_NAME);
7994 /* The function outputs PHR interface function `state_transition'. */
7995 static void
7996 output_trans_func (void)
7998 fprintf (output_file, "int\n%s (%s %s, rtx %s)\n",
7999 TRANSITION_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME,
8000 INSN_PARAMETER_NAME);
8001 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
8002 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8003 INTERNAL_INSN_CODE_NAME, -1);
8004 fprintf (output_file, " return %s (%s, %s);\n}\n\n",
8005 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, STATE_NAME);
8008 /* Output function `min_issue_delay'. */
8009 static void
8010 output_min_issue_delay_func (void)
8012 fprintf (output_file, "int\n%s (%s %s, rtx %s)\n",
8013 MIN_ISSUE_DELAY_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME,
8014 INSN_PARAMETER_NAME);
8015 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
8016 fprintf (output_file, "\n if (%s != 0)\n {\n", INSN_PARAMETER_NAME);
8017 fprintf (output_file, " %s = %s (%s);\n", INTERNAL_INSN_CODE_NAME,
8018 DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME);
8019 fprintf (output_file, " if (%s > %s)\n return 0;\n",
8020 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8021 fprintf (output_file, " }\n else\n %s = %s;\n",
8022 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8023 fprintf (output_file, "\n return %s (%s, %s);\n",
8024 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8025 STATE_NAME);
8026 fprintf (output_file, "}\n\n");
8029 /* Output function `internal_dead_lock'. */
8030 static void
8031 output_internal_dead_lock_func (void)
8033 automaton_t automaton;
8035 fprintf (output_file, "static int\n%s (struct %s *ARG_UNUSED (%s))\n",
8036 INTERNAL_DEAD_LOCK_FUNC_NAME, CHIP_NAME, CHIP_PARAMETER_NAME);
8037 fprintf (output_file, "{\n");
8038 for (automaton = description->first_automaton;
8039 automaton != NULL;
8040 automaton = automaton->next_automaton)
8041 if (automaton->locked_states)
8043 fprintf (output_file, " if (");
8044 output_dead_lock_vect_name (output_file, automaton);
8045 fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
8046 output_chip_member_name (output_file, automaton);
8047 fprintf (output_file, "])\n return 1/* TRUE */;\n");
8049 fprintf (output_file, " return 0/* FALSE */;\n}\n\n");
8052 /* The function outputs PHR interface function `state_dead_lock_p'. */
8053 static void
8054 output_dead_lock_func (void)
8056 fprintf (output_file, "int\n%s (%s %s)\n",
8057 DEAD_LOCK_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME);
8058 fprintf (output_file, "{\n return %s (%s);\n}\n\n",
8059 INTERNAL_DEAD_LOCK_FUNC_NAME, STATE_NAME);
8062 /* Output function `internal_reset'. */
8063 static void
8064 output_internal_reset_func (void)
8066 fprintf (output_file, "static inline void\n%s (struct %s *%s)\n",
8067 INTERNAL_RESET_FUNC_NAME, CHIP_NAME, CHIP_PARAMETER_NAME);
8068 fprintf (output_file, "{\n memset (%s, 0, sizeof (struct %s));\n}\n\n",
8069 CHIP_PARAMETER_NAME, CHIP_NAME);
8072 /* The function outputs PHR interface function `state_size'. */
8073 static void
8074 output_size_func (void)
8076 fprintf (output_file, "int\n%s (void)\n", SIZE_FUNC_NAME);
8077 fprintf (output_file, "{\n return sizeof (struct %s);\n}\n\n", CHIP_NAME);
8080 /* The function outputs PHR interface function `state_reset'. */
8081 static void
8082 output_reset_func (void)
8084 fprintf (output_file, "void\n%s (%s %s)\n",
8085 RESET_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME);
8086 fprintf (output_file, "{\n %s (%s);\n}\n\n", INTERNAL_RESET_FUNC_NAME,
8087 STATE_NAME);
8090 /* Output function `min_insn_conflict_delay'. */
8091 static void
8092 output_min_insn_conflict_delay_func (void)
8094 fprintf (output_file,
8095 "int\n%s (%s %s, rtx %s, rtx %s)\n",
8096 MIN_INSN_CONFLICT_DELAY_FUNC_NAME, STATE_TYPE_NAME,
8097 STATE_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8098 fprintf (output_file, "{\n struct %s %s;\n int %s, %s, transition;\n",
8099 CHIP_NAME, CHIP_NAME, INTERNAL_INSN_CODE_NAME,
8100 INTERNAL_INSN2_CODE_NAME);
8101 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8102 INTERNAL_INSN_CODE_NAME, 0);
8103 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
8104 INTERNAL_INSN2_CODE_NAME, 0);
8105 fprintf (output_file, " memcpy (&%s, %s, sizeof (%s));\n",
8106 CHIP_NAME, STATE_NAME, CHIP_NAME);
8107 fprintf (output_file, " %s (&%s);\n", INTERNAL_RESET_FUNC_NAME, CHIP_NAME);
8108 fprintf (output_file, " transition = %s (%s, &%s);\n",
8109 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME);
8110 fprintf (output_file, " gcc_assert (transition <= 0);\n");
8111 fprintf (output_file, " return %s (%s, &%s);\n",
8112 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN2_CODE_NAME,
8113 CHIP_NAME);
8114 fprintf (output_file, "}\n\n");
8117 /* Output function `internal_insn_latency'. */
8118 static void
8119 output_internal_insn_latency_func (void)
8121 decl_t decl;
8122 struct bypass_decl *bypass;
8123 int i, j, col;
8124 const char *tabletype = "unsigned char";
8126 /* Find the smallest integer type that can hold all the default
8127 latency values. */
8128 for (i = 0; i < description->decls_num; i++)
8129 if (description->decls[i]->mode == dm_insn_reserv)
8131 decl = description->decls[i];
8132 if (DECL_INSN_RESERV (decl)->default_latency > UCHAR_MAX
8133 && tabletype[0] != 'i') /* Don't shrink it. */
8134 tabletype = "unsigned short";
8135 if (DECL_INSN_RESERV (decl)->default_latency > USHRT_MAX)
8136 tabletype = "int";
8139 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",
8140 INTERNAL_INSN_LATENCY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8141 INTERNAL_INSN2_CODE_NAME, INSN_PARAMETER_NAME,
8142 INSN2_PARAMETER_NAME);
8143 fprintf (output_file, "{\n");
8145 if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8147 fputs (" return 0;\n}\n\n", output_file);
8148 return;
8151 fprintf (output_file, " static const %s default_latencies[] =\n {",
8152 tabletype);
8154 for (i = 0, j = 0, col = 7; i < description->decls_num; i++)
8155 if (description->decls[i]->mode == dm_insn_reserv
8156 && description->decls[i] != advance_cycle_insn_decl)
8158 if ((col = (col+1) % 8) == 0)
8159 fputs ("\n ", output_file);
8160 decl = description->decls[i];
8161 gcc_assert (j++ == DECL_INSN_RESERV (decl)->insn_num);
8162 fprintf (output_file, "% 4d,",
8163 DECL_INSN_RESERV (decl)->default_latency);
8165 gcc_assert (j == DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
8166 fputs ("\n };\n", output_file);
8168 fprintf (output_file, " if (%s >= %s || %s >= %s)\n return 0;\n",
8169 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8170 INTERNAL_INSN2_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8172 fprintf (output_file, " switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8173 for (i = 0; i < description->decls_num; i++)
8174 if (description->decls[i]->mode == dm_insn_reserv
8175 && DECL_INSN_RESERV (description->decls[i])->bypass_list)
8177 decl = description->decls [i];
8178 fprintf (output_file,
8179 " case %d:\n switch (%s)\n {\n",
8180 DECL_INSN_RESERV (decl)->insn_num,
8181 INTERNAL_INSN2_CODE_NAME);
8182 for (bypass = DECL_INSN_RESERV (decl)->bypass_list;
8183 bypass != NULL;
8184 bypass = bypass->next)
8186 gcc_assert (bypass->in_insn_reserv->insn_num
8187 != (DECL_INSN_RESERV
8188 (advance_cycle_insn_decl)->insn_num));
8189 fprintf (output_file, " case %d:\n",
8190 bypass->in_insn_reserv->insn_num);
8191 if (bypass->bypass_guard_name == NULL)
8192 fprintf (output_file, " return %d;\n",
8193 bypass->latency);
8194 else
8196 fprintf (output_file,
8197 " if (%s (%s, %s))\n",
8198 bypass->bypass_guard_name, INSN_PARAMETER_NAME,
8199 INSN2_PARAMETER_NAME);
8200 fprintf (output_file,
8201 " return %d;\n break;\n",
8202 bypass->latency);
8205 fputs (" }\n break;\n", output_file);
8208 fprintf (output_file, " }\n return default_latencies[%s];\n}\n\n",
8209 INTERNAL_INSN_CODE_NAME);
8212 /* The function outputs PHR interface function `insn_latency'. */
8213 static void
8214 output_insn_latency_func (void)
8216 fprintf (output_file, "int\n%s (rtx %s, rtx %s)\n",
8217 INSN_LATENCY_FUNC_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8218 fprintf (output_file, "{\n int %s, %s;\n",
8219 INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME);
8220 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8221 INTERNAL_INSN_CODE_NAME, 0);
8222 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
8223 INTERNAL_INSN2_CODE_NAME, 0);
8224 fprintf (output_file, " return %s (%s, %s, %s, %s);\n}\n\n",
8225 INTERNAL_INSN_LATENCY_FUNC_NAME,
8226 INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME,
8227 INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8230 /* The function outputs PHR interface function `print_reservation'. */
8231 static void
8232 output_print_reservation_func (void)
8234 decl_t decl;
8235 int i, j;
8237 fprintf (output_file,
8238 "void\n%s (FILE *%s, rtx %s ATTRIBUTE_UNUSED)\n{\n",
8239 PRINT_RESERVATION_FUNC_NAME, FILE_PARAMETER_NAME,
8240 INSN_PARAMETER_NAME);
8242 if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8244 fprintf (output_file, " fputs (\"%s\", %s);\n}\n\n",
8245 NOTHING_NAME, FILE_PARAMETER_NAME);
8246 return;
8250 fputs (" static const char *const reservation_names[] =\n {",
8251 output_file);
8253 for (i = 0, j = 0; i < description->decls_num; i++)
8255 decl = description->decls [i];
8256 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
8258 gcc_assert (j == DECL_INSN_RESERV (decl)->insn_num);
8259 j++;
8261 fprintf (output_file, "\n \"%s\",",
8262 regexp_representation (DECL_INSN_RESERV (decl)->regexp));
8263 finish_regexp_representation ();
8266 gcc_assert (j == DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
8268 fprintf (output_file, "\n \"%s\"\n };\n int %s;\n\n",
8269 NOTHING_NAME, INTERNAL_INSN_CODE_NAME);
8271 fprintf (output_file, " if (%s == 0)\n %s = %s;\n",
8272 INSN_PARAMETER_NAME,
8273 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8274 fprintf (output_file, " else\n\
8275 {\n\
8276 %s = %s (%s);\n\
8277 if (%s > %s)\n\
8278 %s = %s;\n\
8279 }\n",
8280 INTERNAL_INSN_CODE_NAME, DFA_INSN_CODE_FUNC_NAME,
8281 INSN_PARAMETER_NAME,
8282 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8283 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8285 fprintf (output_file, " fputs (reservation_names[%s], %s);\n}\n\n",
8286 INTERNAL_INSN_CODE_NAME, FILE_PARAMETER_NAME);
8289 /* The following function is used to sort unit declaration by their
8290 names. */
8291 static int
8292 units_cmp (const void *unit1, const void *unit2)
8294 const unit_decl_t u1 = *(unit_decl_t *) unit1;
8295 const unit_decl_t u2 = *(unit_decl_t *) unit2;
8297 return strcmp (u1->name, u2->name);
8300 /* The following macro value is name of struct containing unit name
8301 and unit code. */
8302 #define NAME_CODE_STRUCT_NAME "name_code"
8304 /* The following macro value is name of table of struct name_code. */
8305 #define NAME_CODE_TABLE_NAME "name_code_table"
8307 /* The following macro values are member names for struct name_code. */
8308 #define NAME_MEMBER_NAME "name"
8309 #define CODE_MEMBER_NAME "code"
8311 /* The following macro values are local variable names for function
8312 `get_cpu_unit_code'. */
8313 #define CMP_VARIABLE_NAME "cmp"
8314 #define LOW_VARIABLE_NAME "l"
8315 #define MIDDLE_VARIABLE_NAME "m"
8316 #define HIGH_VARIABLE_NAME "h"
8318 /* The following function outputs function to obtain internal cpu unit
8319 code by the cpu unit name. */
8320 static void
8321 output_get_cpu_unit_code_func (void)
8323 int i;
8324 unit_decl_t *units;
8326 fprintf (output_file, "int\n%s (const char *%s)\n",
8327 GET_CPU_UNIT_CODE_FUNC_NAME, CPU_UNIT_NAME_PARAMETER_NAME);
8328 fprintf (output_file, "{\n struct %s {const char *%s; int %s;};\n",
8329 NAME_CODE_STRUCT_NAME, NAME_MEMBER_NAME, CODE_MEMBER_NAME);
8330 fprintf (output_file, " int %s, %s, %s, %s;\n", CMP_VARIABLE_NAME,
8331 LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8332 fprintf (output_file, " static struct %s %s [] =\n {\n",
8333 NAME_CODE_STRUCT_NAME, NAME_CODE_TABLE_NAME);
8334 units = xmalloc (sizeof (unit_decl_t) * description->units_num);
8335 memcpy (units, units_array, sizeof (unit_decl_t) * description->units_num);
8336 qsort (units, description->units_num, sizeof (unit_decl_t), units_cmp);
8337 for (i = 0; i < description->units_num; i++)
8338 if (units [i]->query_p)
8339 fprintf (output_file, " {\"%s\", %d},\n",
8340 units[i]->name, units[i]->query_num);
8341 fprintf (output_file, " };\n\n");
8342 fprintf (output_file, " /* The following is binary search: */\n");
8343 fprintf (output_file, " %s = 0;\n", LOW_VARIABLE_NAME);
8344 fprintf (output_file, " %s = sizeof (%s) / sizeof (struct %s) - 1;\n",
8345 HIGH_VARIABLE_NAME, NAME_CODE_TABLE_NAME, NAME_CODE_STRUCT_NAME);
8346 fprintf (output_file, " while (%s <= %s)\n {\n",
8347 LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8348 fprintf (output_file, " %s = (%s + %s) / 2;\n",
8349 MIDDLE_VARIABLE_NAME, LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8350 fprintf (output_file, " %s = strcmp (%s, %s [%s].%s);\n",
8351 CMP_VARIABLE_NAME, CPU_UNIT_NAME_PARAMETER_NAME,
8352 NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, NAME_MEMBER_NAME);
8353 fprintf (output_file, " if (%s < 0)\n", CMP_VARIABLE_NAME);
8354 fprintf (output_file, " %s = %s - 1;\n",
8355 HIGH_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
8356 fprintf (output_file, " else if (%s > 0)\n", CMP_VARIABLE_NAME);
8357 fprintf (output_file, " %s = %s + 1;\n",
8358 LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
8359 fprintf (output_file, " else\n");
8360 fprintf (output_file, " return %s [%s].%s;\n }\n",
8361 NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, CODE_MEMBER_NAME);
8362 fprintf (output_file, " return -1;\n}\n\n");
8363 free (units);
8366 /* The following function outputs function to check reservation of cpu
8367 unit (its internal code will be passed as the function argument) in
8368 given cpu state. */
8369 static void
8370 output_cpu_unit_reservation_p (void)
8372 automaton_t automaton;
8374 fprintf (output_file, "int\n%s (%s %s, int %s)\n",
8375 CPU_UNIT_RESERVATION_P_FUNC_NAME,
8376 STATE_TYPE_NAME, STATE_NAME,
8377 CPU_CODE_PARAMETER_NAME);
8378 fprintf (output_file, "{\n gcc_assert (%s >= 0 && %s < %d);\n",
8379 CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME,
8380 description->query_units_num);
8381 if (description->query_units_num > 0)
8382 for (automaton = description->first_automaton;
8383 automaton != NULL;
8384 automaton = automaton->next_automaton)
8386 fprintf (output_file, " if ((");
8387 output_reserved_units_table_name (output_file, automaton);
8388 fprintf (output_file, " [((struct %s *) %s)->", CHIP_NAME, STATE_NAME);
8389 output_chip_member_name (output_file, automaton);
8390 fprintf (output_file, " * %d + %s / 8] >> (%s %% 8)) & 1)\n",
8391 (description->query_units_num + 7) / 8,
8392 CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME);
8393 fprintf (output_file, " return 1;\n");
8395 fprintf (output_file, " return 0;\n}\n\n");
8398 /* The function outputs PHR interface functions `dfa_clean_insn_cache'
8399 and 'dfa_clear_single_insn_cache'. */
8400 static void
8401 output_dfa_clean_insn_cache_func (void)
8403 fprintf (output_file,
8404 "void\n%s (void)\n{\n int %s;\n\n",
8405 DFA_CLEAN_INSN_CACHE_FUNC_NAME, I_VARIABLE_NAME);
8406 fprintf (output_file,
8407 " for (%s = 0; %s < %s; %s++)\n %s [%s] = -1;\n}\n\n",
8408 I_VARIABLE_NAME, I_VARIABLE_NAME,
8409 DFA_INSN_CODES_LENGTH_VARIABLE_NAME, I_VARIABLE_NAME,
8410 DFA_INSN_CODES_VARIABLE_NAME, I_VARIABLE_NAME);
8412 fprintf (output_file,
8413 "void\n%s (rtx %s)\n{\n int %s;\n\n",
8414 DFA_CLEAR_SINGLE_INSN_CACHE_FUNC_NAME, INSN_PARAMETER_NAME,
8415 I_VARIABLE_NAME);
8416 fprintf (output_file,
8417 " %s = INSN_UID (%s);\n if (%s < %s)\n %s [%s] = -1;\n}\n\n",
8418 I_VARIABLE_NAME, INSN_PARAMETER_NAME, I_VARIABLE_NAME,
8419 DFA_INSN_CODES_LENGTH_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
8420 I_VARIABLE_NAME);
8423 /* The function outputs PHR interface function `dfa_start'. */
8424 static void
8425 output_dfa_start_func (void)
8427 fprintf (output_file,
8428 "void\n%s (void)\n{\n %s = get_max_uid ();\n",
8429 DFA_START_FUNC_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8430 fprintf (output_file, " %s = xmalloc (%s * sizeof (int));\n",
8431 DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8432 fprintf (output_file, " %s ();\n}\n\n", DFA_CLEAN_INSN_CACHE_FUNC_NAME);
8435 /* The function outputs PHR interface function `dfa_finish'. */
8436 static void
8437 output_dfa_finish_func (void)
8439 fprintf (output_file, "void\n%s (void)\n{\n free (%s);\n}\n\n",
8440 DFA_FINISH_FUNC_NAME, DFA_INSN_CODES_VARIABLE_NAME);
8445 /* The page contains code for output description file (readable
8446 representation of original description and generated DFA(s). */
8448 /* The function outputs string representation of IR reservation. */
8449 static void
8450 output_regexp (regexp_t regexp)
8452 fprintf (output_description_file, "%s", regexp_representation (regexp));
8453 finish_regexp_representation ();
8456 /* Output names of units in LIST separated by comma. */
8457 static void
8458 output_unit_set_el_list (unit_set_el_t list)
8460 unit_set_el_t el;
8462 for (el = list; el != NULL; el = el->next_unit_set_el)
8464 if (el != list)
8465 fprintf (output_description_file, ", ");
8466 fprintf (output_description_file, "%s", el->unit_decl->name);
8470 /* Output patterns in LIST separated by comma. */
8471 static void
8472 output_pattern_set_el_list (pattern_set_el_t list)
8474 pattern_set_el_t el;
8475 int i;
8477 for (el = list; el != NULL; el = el->next_pattern_set_el)
8479 if (el != list)
8480 fprintf (output_description_file, ", ");
8481 for (i = 0; i < el->units_num; i++)
8482 fprintf (output_description_file, (i == 0 ? "%s" : " %s"),
8483 el->unit_decls [i]->name);
8487 /* The function outputs string representation of IR define_reservation
8488 and define_insn_reservation. */
8489 static void
8490 output_description (void)
8492 decl_t decl;
8493 int i;
8495 for (i = 0; i < description->decls_num; i++)
8497 decl = description->decls [i];
8498 if (decl->mode == dm_unit)
8500 if (DECL_UNIT (decl)->excl_list != NULL)
8502 fprintf (output_description_file, "unit %s exlusion_set: ",
8503 DECL_UNIT (decl)->name);
8504 output_unit_set_el_list (DECL_UNIT (decl)->excl_list);
8505 fprintf (output_description_file, "\n");
8507 if (DECL_UNIT (decl)->presence_list != NULL)
8509 fprintf (output_description_file, "unit %s presence_set: ",
8510 DECL_UNIT (decl)->name);
8511 output_pattern_set_el_list (DECL_UNIT (decl)->presence_list);
8512 fprintf (output_description_file, "\n");
8514 if (DECL_UNIT (decl)->final_presence_list != NULL)
8516 fprintf (output_description_file, "unit %s final_presence_set: ",
8517 DECL_UNIT (decl)->name);
8518 output_pattern_set_el_list
8519 (DECL_UNIT (decl)->final_presence_list);
8520 fprintf (output_description_file, "\n");
8522 if (DECL_UNIT (decl)->absence_list != NULL)
8524 fprintf (output_description_file, "unit %s absence_set: ",
8525 DECL_UNIT (decl)->name);
8526 output_pattern_set_el_list (DECL_UNIT (decl)->absence_list);
8527 fprintf (output_description_file, "\n");
8529 if (DECL_UNIT (decl)->final_absence_list != NULL)
8531 fprintf (output_description_file, "unit %s final_absence_set: ",
8532 DECL_UNIT (decl)->name);
8533 output_pattern_set_el_list
8534 (DECL_UNIT (decl)->final_absence_list);
8535 fprintf (output_description_file, "\n");
8539 fprintf (output_description_file, "\n");
8540 for (i = 0; i < description->decls_num; i++)
8542 decl = description->decls [i];
8543 if (decl->mode == dm_reserv)
8545 fprintf (output_description_file, "reservation %s: ",
8546 DECL_RESERV (decl)->name);
8547 output_regexp (DECL_RESERV (decl)->regexp);
8548 fprintf (output_description_file, "\n");
8550 else if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
8552 fprintf (output_description_file, "insn reservation %s ",
8553 DECL_INSN_RESERV (decl)->name);
8554 print_rtl (output_description_file,
8555 DECL_INSN_RESERV (decl)->condexp);
8556 fprintf (output_description_file, ": ");
8557 output_regexp (DECL_INSN_RESERV (decl)->regexp);
8558 fprintf (output_description_file, "\n");
8560 else if (decl->mode == dm_bypass)
8561 fprintf (output_description_file, "bypass %d %s %s\n",
8562 DECL_BYPASS (decl)->latency,
8563 DECL_BYPASS (decl)->out_insn_name,
8564 DECL_BYPASS (decl)->in_insn_name);
8566 fprintf (output_description_file, "\n\f\n");
8569 /* The function outputs name of AUTOMATON. */
8570 static void
8571 output_automaton_name (FILE *f, automaton_t automaton)
8573 if (automaton->corresponding_automaton_decl == NULL)
8574 fprintf (f, "#%d", automaton->automaton_order_num);
8575 else
8576 fprintf (f, "`%s'", automaton->corresponding_automaton_decl->name);
8579 /* Maximal length of line for pretty printing into description
8580 file. */
8581 #define MAX_LINE_LENGTH 70
8583 /* The function outputs units name belonging to AUTOMATON. */
8584 static void
8585 output_automaton_units (automaton_t automaton)
8587 decl_t decl;
8588 const char *name;
8589 int curr_line_length;
8590 int there_is_an_automaton_unit;
8591 int i;
8593 fprintf (output_description_file, "\n Corresponding units:\n");
8594 fprintf (output_description_file, " ");
8595 curr_line_length = 4;
8596 there_is_an_automaton_unit = 0;
8597 for (i = 0; i < description->decls_num; i++)
8599 decl = description->decls [i];
8600 if (decl->mode == dm_unit
8601 && (DECL_UNIT (decl)->corresponding_automaton_num
8602 == automaton->automaton_order_num))
8604 there_is_an_automaton_unit = 1;
8605 name = DECL_UNIT (decl)->name;
8606 if (curr_line_length + strlen (name) + 1 > MAX_LINE_LENGTH )
8608 curr_line_length = strlen (name) + 4;
8609 fprintf (output_description_file, "\n ");
8611 else
8613 curr_line_length += strlen (name) + 1;
8614 fprintf (output_description_file, " ");
8616 fprintf (output_description_file, "%s", name);
8619 if (!there_is_an_automaton_unit)
8620 fprintf (output_description_file, "<None>");
8621 fprintf (output_description_file, "\n\n");
8624 /* The following variable is used for forming array of all possible cpu unit
8625 reservations described by the current DFA state. */
8626 static VEC(reserv_sets_t,heap) *state_reservs;
8628 /* The function forms `state_reservs' for STATE. */
8629 static void
8630 add_state_reservs (state_t state)
8632 alt_state_t curr_alt_state;
8634 if (state->component_states != NULL)
8635 for (curr_alt_state = state->component_states;
8636 curr_alt_state != NULL;
8637 curr_alt_state = curr_alt_state->next_sorted_alt_state)
8638 add_state_reservs (curr_alt_state->state);
8639 else
8640 VEC_safe_push (reserv_sets_t,heap, state_reservs, state->reservs);
8643 /* The function outputs readable representation of all out arcs of
8644 STATE. */
8645 static void
8646 output_state_arcs (state_t state)
8648 arc_t arc;
8649 ainsn_t ainsn;
8650 const char *insn_name;
8651 int curr_line_length;
8653 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
8655 ainsn = arc->insn;
8656 gcc_assert (ainsn->first_insn_with_same_reservs);
8657 fprintf (output_description_file, " ");
8658 curr_line_length = 7;
8659 fprintf (output_description_file, "%2d: ", ainsn->insn_equiv_class_num);
8662 insn_name = ainsn->insn_reserv_decl->name;
8663 if (curr_line_length + strlen (insn_name) > MAX_LINE_LENGTH)
8665 if (ainsn != arc->insn)
8667 fprintf (output_description_file, ",\n ");
8668 curr_line_length = strlen (insn_name) + 6;
8670 else
8671 curr_line_length += strlen (insn_name);
8673 else
8675 curr_line_length += strlen (insn_name);
8676 if (ainsn != arc->insn)
8678 curr_line_length += 2;
8679 fprintf (output_description_file, ", ");
8682 fprintf (output_description_file, "%s", insn_name);
8683 ainsn = ainsn->next_same_reservs_insn;
8685 while (ainsn != NULL);
8686 fprintf (output_description_file, " %d \n",
8687 arc->to_state->order_state_num);
8689 fprintf (output_description_file, "\n");
8692 /* The following function is used for sorting possible cpu unit
8693 reservation of a DFA state. */
8694 static int
8695 state_reservs_cmp (const void *reservs_ptr_1, const void *reservs_ptr_2)
8697 return reserv_sets_cmp (*(reserv_sets_t *) reservs_ptr_1,
8698 *(reserv_sets_t *) reservs_ptr_2);
8701 /* The following function is used for sorting possible cpu unit
8702 reservation of a DFA state. */
8703 static void
8704 remove_state_duplicate_reservs (void)
8706 size_t i, j;
8708 for (i = 1, j = 0; i < VEC_length (reserv_sets_t, state_reservs); i++)
8709 if (reserv_sets_cmp (VEC_index (reserv_sets_t, state_reservs, j),
8710 VEC_index (reserv_sets_t, state_reservs, i)))
8712 j++;
8713 VEC_replace (reserv_sets_t, state_reservs, j,
8714 VEC_index (reserv_sets_t, state_reservs, i));
8716 VEC_truncate (reserv_sets_t, state_reservs, j + 1);
8719 /* The following function output readable representation of DFA(s)
8720 state used for fast recognition of pipeline hazards. State is
8721 described by possible (current and scheduled) cpu unit
8722 reservations. */
8723 static void
8724 output_state (state_t state)
8726 size_t i;
8728 state_reservs = 0;
8730 fprintf (output_description_file, " State #%d", state->order_state_num);
8731 fprintf (output_description_file,
8732 state->new_cycle_p ? " (new cycle)\n" : "\n");
8733 add_state_reservs (state);
8734 qsort (VEC_address (reserv_sets_t, state_reservs),
8735 VEC_length (reserv_sets_t, state_reservs),
8736 sizeof (reserv_sets_t), state_reservs_cmp);
8737 remove_state_duplicate_reservs ();
8738 for (i = 1; i < VEC_length (reserv_sets_t, state_reservs); i++)
8740 fprintf (output_description_file, " ");
8741 output_reserv_sets (output_description_file,
8742 VEC_index (reserv_sets_t, state_reservs, i));
8743 fprintf (output_description_file, "\n");
8745 fprintf (output_description_file, "\n");
8746 output_state_arcs (state);
8747 VEC_free (reserv_sets_t,heap, state_reservs);
8750 /* The following function output readable representation of
8751 DFAs used for fast recognition of pipeline hazards. */
8752 static void
8753 output_automaton_descriptions (void)
8755 automaton_t automaton;
8757 for (automaton = description->first_automaton;
8758 automaton != NULL;
8759 automaton = automaton->next_automaton)
8761 fprintf (output_description_file, "\nAutomaton ");
8762 output_automaton_name (output_description_file, automaton);
8763 fprintf (output_description_file, "\n");
8764 output_automaton_units (automaton);
8765 pass_states (automaton, output_state);
8771 /* The page contains top level function for generation DFA(s) used for
8772 PHR. */
8774 /* The function outputs statistics about work of different phases of
8775 DFA generator. */
8776 static void
8777 output_statistics (FILE *f)
8779 automaton_t automaton;
8780 int states_num;
8781 #ifndef NDEBUG
8782 int transition_comb_vect_els = 0;
8783 int transition_full_vect_els = 0;
8784 int min_issue_delay_vect_els = 0;
8785 int locked_states = 0;
8786 #endif
8788 for (automaton = description->first_automaton;
8789 automaton != NULL;
8790 automaton = automaton->next_automaton)
8792 fprintf (f, "\nAutomaton ");
8793 output_automaton_name (f, automaton);
8794 fprintf (f, "\n %5d NDFA states, %5d NDFA arcs\n",
8795 automaton->NDFA_states_num, automaton->NDFA_arcs_num);
8796 fprintf (f, " %5d DFA states, %5d DFA arcs\n",
8797 automaton->DFA_states_num, automaton->DFA_arcs_num);
8798 states_num = automaton->DFA_states_num;
8799 if (!no_minimization_flag)
8801 fprintf (f, " %5d minimal DFA states, %5d minimal DFA arcs\n",
8802 automaton->minimal_DFA_states_num,
8803 automaton->minimal_DFA_arcs_num);
8804 states_num = automaton->minimal_DFA_states_num;
8806 fprintf (f, " %5d all insns %5d insn equivalence classes\n",
8807 description->insns_num, automaton->insn_equiv_classes_num);
8808 fprintf (f, " %d locked states\n", automaton->locked_states);
8809 #ifndef NDEBUG
8810 fprintf
8811 (f, "%5ld transition comb vector els, %5ld trans table els: %s\n",
8812 (long) VEC_length (vect_el_t, automaton->trans_table->comb_vect),
8813 (long) VEC_length (vect_el_t, automaton->trans_table->full_vect),
8814 (comb_vect_p (automaton->trans_table)
8815 ? "use comb vect" : "use simple vect"));
8816 fprintf
8817 (f, "%5ld min delay table els, compression factor %d\n",
8818 (long) states_num * automaton->insn_equiv_classes_num,
8819 automaton->min_issue_delay_table_compression_factor);
8820 transition_comb_vect_els
8821 += VEC_length (vect_el_t, automaton->trans_table->comb_vect);
8822 transition_full_vect_els
8823 += VEC_length (vect_el_t, automaton->trans_table->full_vect);
8824 min_issue_delay_vect_els
8825 += states_num * automaton->insn_equiv_classes_num;
8826 locked_states
8827 += automaton->locked_states;
8828 #endif
8830 #ifndef NDEBUG
8831 fprintf (f, "\n%5d all allocated states, %5d all allocated arcs\n",
8832 allocated_states_num, allocated_arcs_num);
8833 fprintf (f, "%5d all allocated alternative states\n",
8834 allocated_alt_states_num);
8835 fprintf (f, "%5d all transition comb vector els, %5d all trans table els\n",
8836 transition_comb_vect_els, transition_full_vect_els);
8837 fprintf (f, "%5d all min delay table els\n", min_issue_delay_vect_els);
8838 fprintf (f, "%5d all locked states\n", locked_states);
8839 #endif
8842 /* The function output times of work of different phases of DFA
8843 generator. */
8844 static void
8845 output_time_statistics (FILE *f)
8847 fprintf (f, "\n transformation: ");
8848 print_active_time (f, transform_time);
8849 fprintf (f, (!ndfa_flag ? ", building DFA: " : ", building NDFA: "));
8850 print_active_time (f, NDFA_time);
8851 if (ndfa_flag)
8853 fprintf (f, ", NDFA -> DFA: ");
8854 print_active_time (f, NDFA_to_DFA_time);
8856 fprintf (f, "\n DFA minimization: ");
8857 print_active_time (f, minimize_time);
8858 fprintf (f, ", making insn equivalence: ");
8859 print_active_time (f, equiv_time);
8860 fprintf (f, "\n all automaton generation: ");
8861 print_active_time (f, automaton_generation_time);
8862 fprintf (f, ", output: ");
8863 print_active_time (f, output_time);
8864 fprintf (f, "\n");
8867 /* The function generates DFA (deterministic finite state automaton)
8868 for fast recognition of pipeline hazards. No errors during
8869 checking must be fixed before this function call. */
8870 static void
8871 generate (void)
8873 automata_num = split_argument;
8874 if (description->units_num < automata_num)
8875 automata_num = description->units_num;
8876 initiate_states ();
8877 initiate_arcs ();
8878 initiate_automata_lists ();
8879 initiate_pass_states ();
8880 initiate_excl_sets ();
8881 initiate_presence_absence_pattern_sets ();
8882 automaton_generation_time = create_ticker ();
8883 create_automata ();
8884 ticker_off (&automaton_generation_time);
8889 /* This page mainly contains top level functions of pipeline hazards
8890 description translator. */
8892 /* The following macro value is suffix of name of description file of
8893 pipeline hazards description translator. */
8894 #define STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX ".dfa"
8896 /* The function returns suffix of given file name. The returned
8897 string can not be changed. */
8898 static const char *
8899 file_name_suffix (const char *file_name)
8901 const char *last_period;
8903 for (last_period = NULL; *file_name != '\0'; file_name++)
8904 if (*file_name == '.')
8905 last_period = file_name;
8906 return (last_period == NULL ? file_name : last_period);
8909 /* The function returns base name of given file name, i.e. pointer to
8910 first char after last `/' (or `\' for WIN32) in given file name,
8911 given file name itself if the directory name is absent. The
8912 returned string can not be changed. */
8913 static const char *
8914 base_file_name (const char *file_name)
8916 int directory_name_length;
8918 directory_name_length = strlen (file_name);
8919 #ifdef WIN32
8920 while (directory_name_length >= 0 && file_name[directory_name_length] != '/'
8921 && file_name[directory_name_length] != '\\')
8922 #else
8923 while (directory_name_length >= 0 && file_name[directory_name_length] != '/')
8924 #endif
8925 directory_name_length--;
8926 return file_name + directory_name_length + 1;
8929 /* The following is top level function to initialize the work of
8930 pipeline hazards description translator. */
8931 static void
8932 initiate_automaton_gen (int argc, char **argv)
8934 const char *base_name;
8935 int i;
8937 ndfa_flag = 0;
8938 split_argument = 0; /* default value */
8939 no_minimization_flag = 0;
8940 time_flag = 0;
8941 stats_flag = 0;
8942 v_flag = 0;
8943 w_flag = 0;
8944 progress_flag = 0;
8945 for (i = 2; i < argc; i++)
8946 if (strcmp (argv [i], NO_MINIMIZATION_OPTION) == 0)
8947 no_minimization_flag = 1;
8948 else if (strcmp (argv [i], TIME_OPTION) == 0)
8949 time_flag = 1;
8950 else if (strcmp (argv [i], STATS_OPTION) == 0)
8951 stats_flag = 1;
8952 else if (strcmp (argv [i], V_OPTION) == 0)
8953 v_flag = 1;
8954 else if (strcmp (argv [i], W_OPTION) == 0)
8955 w_flag = 1;
8956 else if (strcmp (argv [i], NDFA_OPTION) == 0)
8957 ndfa_flag = 1;
8958 else if (strcmp (argv [i], PROGRESS_OPTION) == 0)
8959 progress_flag = 1;
8960 else if (strcmp (argv [i], "-split") == 0)
8962 if (i + 1 >= argc)
8963 fatal ("-split has no argument.");
8964 fatal ("option `-split' has not been implemented yet\n");
8965 /* split_argument = atoi (argument_vect [i + 1]); */
8968 /* Initialize IR storage. */
8969 obstack_init (&irp);
8970 initiate_automaton_decl_table ();
8971 initiate_insn_decl_table ();
8972 initiate_decl_table ();
8973 output_file = stdout;
8974 output_description_file = NULL;
8975 base_name = base_file_name (argv[1]);
8976 obstack_grow (&irp, base_name,
8977 strlen (base_name) - strlen (file_name_suffix (base_name)));
8978 obstack_grow (&irp, STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX,
8979 strlen (STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX) + 1);
8980 obstack_1grow (&irp, '\0');
8981 output_description_file_name = obstack_base (&irp);
8982 obstack_finish (&irp);
8985 /* The following function checks existence at least one arc marked by
8986 each insn. */
8987 static void
8988 check_automata_insn_issues (void)
8990 automaton_t automaton;
8991 ainsn_t ainsn, reserv_ainsn;
8993 for (automaton = description->first_automaton;
8994 automaton != NULL;
8995 automaton = automaton->next_automaton)
8997 for (ainsn = automaton->ainsn_list;
8998 ainsn != NULL;
8999 ainsn = ainsn->next_ainsn)
9000 if (ainsn->first_insn_with_same_reservs && !ainsn->arc_exists_p)
9002 for (reserv_ainsn = ainsn;
9003 reserv_ainsn != NULL;
9004 reserv_ainsn = reserv_ainsn->next_same_reservs_insn)
9005 if (automaton->corresponding_automaton_decl != NULL)
9007 if (!w_flag)
9008 error ("Automaton `%s': Insn `%s' will never be issued",
9009 automaton->corresponding_automaton_decl->name,
9010 reserv_ainsn->insn_reserv_decl->name);
9011 else
9012 warning
9013 (0, "Automaton `%s': Insn `%s' will never be issued",
9014 automaton->corresponding_automaton_decl->name,
9015 reserv_ainsn->insn_reserv_decl->name);
9017 else
9019 if (!w_flag)
9020 error ("Insn `%s' will never be issued",
9021 reserv_ainsn->insn_reserv_decl->name);
9022 else
9023 warning (0, "Insn `%s' will never be issued",
9024 reserv_ainsn->insn_reserv_decl->name);
9030 /* The following vla is used for storing pointers to all achieved
9031 states. */
9032 static VEC(state_t,heap) *automaton_states;
9034 /* This function is called by function pass_states to add an achieved
9035 STATE. */
9036 static void
9037 add_automaton_state (state_t state)
9039 VEC_safe_push (state_t,heap, automaton_states, state);
9042 /* The following function forms list of important automata (whose
9043 states may be changed after the insn issue) for each insn. */
9044 static void
9045 form_important_insn_automata_lists (void)
9047 automaton_t automaton;
9048 decl_t decl;
9049 ainsn_t ainsn;
9050 arc_t arc;
9051 int i;
9052 size_t n;
9054 automaton_states = 0;
9055 /* Mark important ainsns. */
9056 for (automaton = description->first_automaton;
9057 automaton != NULL;
9058 automaton = automaton->next_automaton)
9060 VEC_truncate (state_t, automaton_states, 0);
9061 pass_states (automaton, add_automaton_state);
9062 for (n = 0; n < VEC_length (state_t, automaton_states); n++)
9064 state_t s = VEC_index (state_t, automaton_states, n);
9065 for (arc = first_out_arc (s);
9066 arc != NULL;
9067 arc = next_out_arc (arc))
9068 if (arc->to_state != s)
9070 gcc_assert (arc->insn->first_insn_with_same_reservs);
9071 for (ainsn = arc->insn;
9072 ainsn != NULL;
9073 ainsn = ainsn->next_same_reservs_insn)
9074 ainsn->important_p = TRUE;
9078 VEC_free (state_t,heap, automaton_states);
9080 /* Create automata sets for the insns. */
9081 for (i = 0; i < description->decls_num; i++)
9083 decl = description->decls [i];
9084 if (decl->mode == dm_insn_reserv)
9086 automata_list_start ();
9087 for (automaton = description->first_automaton;
9088 automaton != NULL;
9089 automaton = automaton->next_automaton)
9090 for (ainsn = automaton->ainsn_list;
9091 ainsn != NULL;
9092 ainsn = ainsn->next_ainsn)
9093 if (ainsn->important_p
9094 && ainsn->insn_reserv_decl == DECL_INSN_RESERV (decl))
9096 automata_list_add (automaton);
9097 break;
9099 DECL_INSN_RESERV (decl)->important_automata_list
9100 = automata_list_finish ();
9106 /* The following is top level function to generate automat(a,on) for
9107 fast recognition of pipeline hazards. */
9108 static void
9109 expand_automata (void)
9111 int i;
9113 description = create_node (sizeof (struct description)
9114 /* One entry for cycle advancing insn. */
9115 + sizeof (decl_t) * VEC_length (decl_t, decls));
9116 description->decls_num = VEC_length (decl_t, decls);
9117 description->query_units_num = 0;
9118 for (i = 0; i < description->decls_num; i++)
9120 description->decls [i] = VEC_index (decl_t, decls, i);
9121 if (description->decls [i]->mode == dm_unit
9122 && DECL_UNIT (description->decls [i])->query_p)
9123 DECL_UNIT (description->decls [i])->query_num
9124 = description->query_units_num++;
9126 all_time = create_ticker ();
9127 check_time = create_ticker ();
9128 if (progress_flag)
9129 fprintf (stderr, "Check description...");
9130 check_all_description ();
9131 if (progress_flag)
9132 fprintf (stderr, "done\n");
9133 ticker_off (&check_time);
9134 generation_time = create_ticker ();
9135 if (!have_error)
9137 transform_insn_regexps ();
9138 check_unit_distributions_to_automata ();
9140 if (!have_error)
9142 generate ();
9143 check_automata_insn_issues ();
9145 if (!have_error)
9147 form_important_insn_automata_lists ();
9149 ticker_off (&generation_time);
9152 /* The following is top level function to output PHR and to finish
9153 work with pipeline description translator. */
9154 static void
9155 write_automata (void)
9157 output_time = create_ticker ();
9158 if (progress_flag)
9159 fprintf (stderr, "Forming and outputting automata tables...");
9160 output_tables ();
9161 if (progress_flag)
9163 fprintf (stderr, "done\n");
9164 fprintf (stderr, "Output functions to work with automata...");
9166 output_chip_definitions ();
9167 output_max_insn_queue_index_def ();
9168 output_internal_min_issue_delay_func ();
9169 output_internal_trans_func ();
9170 /* Cache of insn dfa codes: */
9171 fprintf (output_file, "\nstatic int *%s;\n", DFA_INSN_CODES_VARIABLE_NAME);
9172 fprintf (output_file, "\nstatic int %s;\n\n",
9173 DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
9174 output_dfa_insn_code_func ();
9175 output_trans_func ();
9176 output_min_issue_delay_func ();
9177 output_internal_dead_lock_func ();
9178 output_dead_lock_func ();
9179 output_size_func ();
9180 output_internal_reset_func ();
9181 output_reset_func ();
9182 output_min_insn_conflict_delay_func ();
9183 output_internal_insn_latency_func ();
9184 output_insn_latency_func ();
9185 output_print_reservation_func ();
9186 /* Output function get_cpu_unit_code. */
9187 fprintf (output_file, "\n#if %s\n\n", CPU_UNITS_QUERY_MACRO_NAME);
9188 output_get_cpu_unit_code_func ();
9189 output_cpu_unit_reservation_p ();
9190 fprintf (output_file, "\n#endif /* #if %s */\n\n",
9191 CPU_UNITS_QUERY_MACRO_NAME);
9192 output_dfa_clean_insn_cache_func ();
9193 output_dfa_start_func ();
9194 output_dfa_finish_func ();
9195 if (progress_flag)
9196 fprintf (stderr, "done\n");
9197 if (v_flag)
9199 output_description_file = fopen (output_description_file_name, "w");
9200 if (output_description_file == NULL)
9202 perror (output_description_file_name);
9203 exit (FATAL_EXIT_CODE);
9205 if (progress_flag)
9206 fprintf (stderr, "Output automata description...");
9207 output_description ();
9208 output_automaton_descriptions ();
9209 if (progress_flag)
9210 fprintf (stderr, "done\n");
9211 output_statistics (output_description_file);
9213 if (stats_flag)
9214 output_statistics (stderr);
9215 ticker_off (&output_time);
9216 if (time_flag)
9217 output_time_statistics (stderr);
9218 finish_states ();
9219 finish_arcs ();
9220 finish_automata_lists ();
9221 if (time_flag)
9223 fprintf (stderr, "Summary:\n");
9224 fprintf (stderr, " check time ");
9225 print_active_time (stderr, check_time);
9226 fprintf (stderr, ", generation time ");
9227 print_active_time (stderr, generation_time);
9228 fprintf (stderr, ", all time ");
9229 print_active_time (stderr, all_time);
9230 fprintf (stderr, "\n");
9232 /* Finish all work. */
9233 if (output_description_file != NULL)
9235 fflush (output_description_file);
9236 if (ferror (stdout) != 0)
9237 fatal ("Error in writing DFA description file %s: %s",
9238 output_description_file_name, xstrerror (errno));
9239 fclose (output_description_file);
9241 finish_automaton_decl_table ();
9242 finish_insn_decl_table ();
9243 finish_decl_table ();
9244 obstack_free (&irp, NULL);
9245 if (have_error && output_description_file != NULL)
9246 remove (output_description_file_name);
9250 main (int argc, char **argv)
9252 rtx desc;
9254 progname = "genautomata";
9256 if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
9257 return (FATAL_EXIT_CODE);
9259 initiate_automaton_gen (argc, argv);
9260 while (1)
9262 int lineno;
9263 int insn_code_number;
9265 desc = read_md_rtx (&lineno, &insn_code_number);
9266 if (desc == NULL)
9267 break;
9269 switch (GET_CODE (desc))
9271 case DEFINE_CPU_UNIT:
9272 gen_cpu_unit (desc);
9273 break;
9275 case DEFINE_QUERY_CPU_UNIT:
9276 gen_query_cpu_unit (desc);
9277 break;
9279 case DEFINE_BYPASS:
9280 gen_bypass (desc);
9281 break;
9283 case EXCLUSION_SET:
9284 gen_excl_set (desc);
9285 break;
9287 case PRESENCE_SET:
9288 gen_presence_set (desc);
9289 break;
9291 case FINAL_PRESENCE_SET:
9292 gen_final_presence_set (desc);
9293 break;
9295 case ABSENCE_SET:
9296 gen_absence_set (desc);
9297 break;
9299 case FINAL_ABSENCE_SET:
9300 gen_final_absence_set (desc);
9301 break;
9303 case DEFINE_AUTOMATON:
9304 gen_automaton (desc);
9305 break;
9307 case AUTOMATA_OPTION:
9308 gen_automata_option (desc);
9309 break;
9311 case DEFINE_RESERVATION:
9312 gen_reserv (desc);
9313 break;
9315 case DEFINE_INSN_RESERVATION:
9316 gen_insn_reserv (desc);
9317 break;
9319 default:
9320 break;
9324 if (have_error)
9325 return FATAL_EXIT_CODE;
9327 puts ("/* Generated automatically by the program `genautomata'\n"
9328 " from the machine description file `md'. */\n\n"
9329 "#include \"config.h\"\n"
9330 "#include \"system.h\"\n"
9331 "#include \"coretypes.h\"\n"
9332 "#include \"tm.h\"\n"
9333 "#include \"rtl.h\"\n"
9334 "#include \"tm_p.h\"\n"
9335 "#include \"insn-config.h\"\n"
9336 "#include \"recog.h\"\n"
9337 "#include \"regs.h\"\n"
9338 "#include \"real.h\"\n"
9339 "#include \"output.h\"\n"
9340 "#include \"insn-attr.h\"\n"
9341 "#include \"toplev.h\"\n"
9342 "#include \"flags.h\"\n"
9343 "#include \"function.h\"\n");
9345 if (VEC_length (decl_t, decls) > 0)
9347 expand_automata ();
9348 write_automata ();
9351 fflush (stdout);
9352 return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);