Merge from mainline
[official-gcc.git] / gcc / genautomata.c
blob2c17ee4b4469e67adda567e99bb263f88cb73539
1 /* Pipeline hazard description translator.
2 Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005
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"
242 #define TIME_OPTION "-time"
244 #define V_OPTION "-v"
246 #define W_OPTION "-w"
248 #define NDFA_OPTION "-ndfa"
250 #define PROGRESS_OPTION "-progress"
252 /* The following flags are set up by function `initiate_automaton_gen'. */
254 /* Make automata with nondeterministic reservation by insns (`-ndfa'). */
255 static int ndfa_flag;
257 /* Do not make minimization of DFA (`-no-minimization'). */
258 static int no_minimization_flag;
260 /* Value of this variable is number of automata being generated. The
261 actual number of automata may be less this value if there is not
262 sufficient number of units. This value is defined by argument of
263 option `-split' or by constructions automaton if the value is zero
264 (it is default value of the argument). */
265 static int split_argument;
267 /* Flag of output time statistics (`-time'). */
268 static int time_flag;
270 /* Flag of creation of description file which contains description of
271 result automaton and statistics information (`-v'). */
272 static int v_flag;
274 /* Flag of output of a progress bar showing how many states were
275 generated so far for automaton being processed (`-progress'). */
276 static int progress_flag;
278 /* Flag of generating warning instead of error for non-critical errors
279 (`-w'). */
280 static int w_flag;
283 /* Output file for pipeline hazard recognizer (PHR) being generated.
284 The value is NULL if the file is not defined. */
285 static FILE *output_file;
287 /* Description file of PHR. The value is NULL if the file is not
288 created. */
289 static FILE *output_description_file;
291 /* PHR description file name. */
292 static char *output_description_file_name;
294 /* Value of the following variable is node representing description
295 being processed. This is start point of IR. */
296 static struct description *description;
300 /* This page contains description of IR structure (nodes). */
302 enum decl_mode
304 dm_unit,
305 dm_bypass,
306 dm_automaton,
307 dm_excl,
308 dm_presence,
309 dm_absence,
310 dm_reserv,
311 dm_insn_reserv
314 /* This describes define_cpu_unit and define_query_cpu_unit (see file
315 rtl.def). */
316 struct unit_decl
318 const char *name;
319 /* NULL if the automaton name is absent. */
320 const char *automaton_name;
321 /* If the following value is not zero, the cpu unit reservation is
322 described in define_query_cpu_unit. */
323 char query_p;
325 /* The following fields are defined by checker. */
327 /* The following field value is nonzero if the unit is used in an
328 regexp. */
329 char unit_is_used;
331 /* The following field value is order number (0, 1, ...) of given
332 unit. */
333 int unit_num;
334 /* The following field value is corresponding declaration of
335 automaton which was given in description. If the field value is
336 NULL then automaton in the unit declaration was absent. */
337 struct automaton_decl *automaton_decl;
338 /* The following field value is maximal cycle number (1, ...) on
339 which given unit occurs in insns. Zero value means that given
340 unit is not used in insns. */
341 int max_occ_cycle_num;
342 /* The following field value is minimal cycle number (0, ...) on
343 which given unit occurs in insns. -1 value means that given
344 unit is not used in insns. */
345 int min_occ_cycle_num;
346 /* The following list contains units which conflict with given
347 unit. */
348 unit_set_el_t excl_list;
349 /* The following list contains patterns which are required to
350 reservation of given unit. */
351 pattern_set_el_t presence_list;
352 pattern_set_el_t final_presence_list;
353 /* The following list contains patterns which should be not present
354 in reservation for given unit. */
355 pattern_set_el_t absence_list;
356 pattern_set_el_t final_absence_list;
357 /* The following is used only when `query_p' has nonzero value.
358 This is query number for the unit. */
359 int query_num;
360 /* The following is the last cycle on which the unit was checked for
361 correct distributions of units to automata in a regexp. */
362 int last_distribution_check_cycle;
364 /* The following fields are defined by automaton generator. */
366 /* The following field value is number of the automaton to which
367 given unit belongs. */
368 int corresponding_automaton_num;
369 /* If the following value is not zero, the cpu unit is present in a
370 `exclusion_set' or in right part of a `presence_set',
371 `final_presence_set', `absence_set', and
372 `final_absence_set'define_query_cpu_unit. */
373 char in_set_p;
376 /* This describes define_bypass (see file rtl.def). */
377 struct bypass_decl
379 int latency;
380 const char *out_insn_name;
381 const char *in_insn_name;
382 const char *bypass_guard_name;
384 /* The following fields are defined by checker. */
386 /* output and input insns of given bypass. */
387 struct insn_reserv_decl *out_insn_reserv;
388 struct insn_reserv_decl *in_insn_reserv;
389 /* The next bypass for given output insn. */
390 struct bypass_decl *next;
393 /* This describes define_automaton (see file rtl.def). */
394 struct automaton_decl
396 const char *name;
398 /* The following fields are defined by automaton generator. */
400 /* The following field value is nonzero if the automaton is used in
401 an regexp definition. */
402 char automaton_is_used;
404 /* The following fields are defined by checker. */
406 /* The following field value is the corresponding automaton. This
407 field is not NULL only if the automaton is present in unit
408 declarations and the automatic partition on automata is not
409 used. */
410 automaton_t corresponding_automaton;
413 /* This describes exclusion relations: exclusion_set (see file
414 rtl.def). */
415 struct excl_rel_decl
417 int all_names_num;
418 int first_list_length;
419 char *names [1];
422 /* This describes unit relations: [final_]presence_set or
423 [final_]absence_set (see file rtl.def). */
424 struct unit_pattern_rel_decl
426 int final_p;
427 int names_num;
428 int patterns_num;
429 char **names;
430 char ***patterns;
433 /* This describes define_reservation (see file rtl.def). */
434 struct reserv_decl
436 const char *name;
437 regexp_t regexp;
439 /* The following fields are defined by checker. */
441 /* The following field value is nonzero if the unit is used in an
442 regexp. */
443 char reserv_is_used;
444 /* The following field is used to check up cycle in expression
445 definition. */
446 int loop_pass_num;
449 /* This describes define_insn_reservation (see file rtl.def). */
450 struct insn_reserv_decl
452 rtx condexp;
453 int default_latency;
454 regexp_t regexp;
455 const char *name;
457 /* The following fields are defined by checker. */
459 /* The following field value is order number (0, 1, ...) of given
460 insn. */
461 int insn_num;
462 /* The following field value is list of bypasses in which given insn
463 is output insn. */
464 struct bypass_decl *bypass_list;
466 /* The following fields are defined by automaton generator. */
468 /* The following field is the insn regexp transformed that
469 the regexp has not optional regexp, repetition regexp, and an
470 reservation name (i.e. reservation identifiers are changed by the
471 corresponding regexp) and all alternations are the topest level
472 of the regexp. The value can be NULL only if it is special
473 insn `cycle advancing'. */
474 regexp_t transformed_regexp;
475 /* The following field value is list of arcs marked given
476 insn. The field is used in transformation NDFA -> DFA. */
477 arc_t arcs_marked_by_insn;
478 /* The two following fields are used during minimization of a finite state
479 automaton. */
480 /* The field value is number of equivalence class of state into
481 which arc marked by given insn enters from a state (fixed during
482 an automaton minimization). */
483 int equiv_class_num;
484 /* The following member value is the list to automata which can be
485 changed by the insn issue. */
486 automata_list_el_t important_automata_list;
487 /* The following member is used to process insn once for output. */
488 int processed_p;
491 /* This contains a declaration mentioned above. */
492 struct decl
494 /* What node in the union? */
495 enum decl_mode mode;
496 pos_t pos;
497 union
499 struct unit_decl unit;
500 struct bypass_decl bypass;
501 struct automaton_decl automaton;
502 struct excl_rel_decl excl;
503 struct unit_pattern_rel_decl presence;
504 struct unit_pattern_rel_decl absence;
505 struct reserv_decl reserv;
506 struct insn_reserv_decl insn_reserv;
507 } decl;
510 /* The following structures represent parsed reservation strings. */
511 enum regexp_mode
513 rm_unit,
514 rm_reserv,
515 rm_nothing,
516 rm_sequence,
517 rm_repeat,
518 rm_allof,
519 rm_oneof
522 /* Cpu unit in reservation. */
523 struct unit_regexp
525 const char *name;
526 unit_decl_t unit_decl;
529 /* Define_reservation in a reservation. */
530 struct reserv_regexp
532 const char *name;
533 struct reserv_decl *reserv_decl;
536 /* Absence of reservation (represented by string `nothing'). */
537 struct nothing_regexp
539 /* This used to be empty but ISO C doesn't allow that. */
540 char unused;
543 /* Representation of reservations separated by ',' (see file
544 rtl.def). */
545 struct sequence_regexp
547 int regexps_num;
548 regexp_t regexps [1];
551 /* Representation of construction `repeat' (see file rtl.def). */
552 struct repeat_regexp
554 int repeat_num;
555 regexp_t regexp;
558 /* Representation of reservations separated by '+' (see file
559 rtl.def). */
560 struct allof_regexp
562 int regexps_num;
563 regexp_t regexps [1];
566 /* Representation of reservations separated by '|' (see file
567 rtl.def). */
568 struct oneof_regexp
570 int regexps_num;
571 regexp_t regexps [1];
574 /* Representation of a reservation string. */
575 struct regexp
577 /* What node in the union? */
578 enum regexp_mode mode;
579 pos_t pos;
580 union
582 struct unit_regexp unit;
583 struct reserv_regexp reserv;
584 struct nothing_regexp nothing;
585 struct sequence_regexp sequence;
586 struct repeat_regexp repeat;
587 struct allof_regexp allof;
588 struct oneof_regexp oneof;
589 } regexp;
592 /* Represents description of pipeline hazard description based on
593 NDFA. */
594 struct description
596 int decls_num;
598 /* The following fields are defined by checker. */
600 /* The following fields values are correspondingly number of all
601 units, query units, and insns in the description. */
602 int units_num;
603 int query_units_num;
604 int insns_num;
605 /* The following field value is max length (in cycles) of
606 reservations of insns. The field value is defined only for
607 correct programs. */
608 int max_insn_reserv_cycles;
610 /* The following fields are defined by automaton generator. */
612 /* The following field value is the first automaton. */
613 automaton_t first_automaton;
615 /* The following field is created by pipeline hazard parser and
616 contains all declarations. We allocate additional entry for
617 special insn "cycle advancing" which is added by the automaton
618 generator. */
619 decl_t decls [1];
623 /* The following nodes are created in automaton checker. */
625 /* The following nodes represent exclusion set for cpu units. Each
626 element is accessed through only one excl_list. */
627 struct unit_set_el
629 unit_decl_t unit_decl;
630 unit_set_el_t next_unit_set_el;
633 /* The following nodes represent presence or absence pattern for cpu
634 units. Each element is accessed through only one presence_list or
635 absence_list. */
636 struct pattern_set_el
638 /* The number of units in unit_decls. */
639 int units_num;
640 /* The units forming the pattern. */
641 struct unit_decl **unit_decls;
642 pattern_set_el_t next_pattern_set_el;
646 /* The following nodes are created in automaton generator. */
649 /* The following nodes represent presence or absence pattern for cpu
650 units. Each element is accessed through only one element of
651 unit_presence_set_table or unit_absence_set_table. */
652 struct pattern_reserv
654 reserv_sets_t reserv;
655 pattern_reserv_t next_pattern_reserv;
658 /* The following node type describes state automaton. The state may
659 be deterministic or non-deterministic. Non-deterministic state has
660 several component states which represent alternative cpu units
661 reservations. The state also is used for describing a
662 deterministic reservation of automaton insn. */
663 struct state
665 /* The following member value is nonzero if there is a transition by
666 cycle advancing. */
667 int new_cycle_p;
668 /* The following field is list of processor unit reservations on
669 each cycle. */
670 reserv_sets_t reservs;
671 /* The following field is unique number of given state between other
672 states. */
673 int unique_num;
674 /* The following field value is automaton to which given state
675 belongs. */
676 automaton_t automaton;
677 /* The following field value is the first arc output from given
678 state. */
679 arc_t first_out_arc;
680 /* 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 /* The following field value is the order number of given state.
704 The states in final DFA is enumerated with the aid of the
705 following field. */
706 int order_state_num;
707 /* This member is used for passing states for searching minimal
708 delay time. */
709 int state_pass_num;
710 /* The following member is used to evaluate min issue delay of insn
711 for a state. */
712 int min_insn_issue_delay;
713 /* The following member is used to evaluate max issue rate of the
714 processor. The value of the member is maximal length of the path
715 from given state no containing arcs marked by special insn `cycle
716 advancing'. */
717 int longest_path_length;
720 /* The following macro is an initial value of member
721 `longest_path_length' of a state. */
722 #define UNDEFINED_LONGEST_PATH_LENGTH -1
724 /* Automaton arc. */
725 struct arc
727 /* The following field refers for the state into which given arc
728 enters. */
729 state_t to_state;
730 /* The following field describes that the insn issue (with cycle
731 advancing for special insn `cycle advancing' and without cycle
732 advancing for others) makes transition from given state to
733 another given state. */
734 ainsn_t insn;
735 /* The following field value is the next arc output from the same
736 state. */
737 arc_t next_out_arc;
738 /* List of arcs marked given insn is formed with the following
739 field. The field is used in transformation NDFA -> DFA. */
740 arc_t next_arc_marked_by_insn;
743 /* The following node type describes a deterministic alternative in
744 non-deterministic state which characterizes cpu unit reservations
745 of automaton insn or which is part of NDFA. */
746 struct alt_state
748 /* The following field is a deterministic state which characterizes
749 unit reservations of the instruction. */
750 state_t state;
751 /* The following field refers to the next state which characterizes
752 unit reservations of the instruction. */
753 alt_state_t next_alt_state;
754 /* The following field refers to the next state in sorted list. */
755 alt_state_t next_sorted_alt_state;
758 /* The following node type describes insn of automaton. They are
759 labels of FA arcs. */
760 struct ainsn
762 /* The following field value is the corresponding insn declaration
763 of description. */
764 struct insn_reserv_decl *insn_reserv_decl;
765 /* The following field value is the next insn declaration for an
766 automaton. */
767 ainsn_t next_ainsn;
768 /* The following field is states which characterize automaton unit
769 reservations of the instruction. The value can be NULL only if it
770 is special insn `cycle advancing'. */
771 alt_state_t alt_states;
772 /* The following field is sorted list of states which characterize
773 automaton unit reservations of the instruction. The value can be
774 NULL only if it is special insn `cycle advancing'. */
775 alt_state_t sorted_alt_states;
776 /* The following field refers the next automaton insn with
777 the same reservations. */
778 ainsn_t next_same_reservs_insn;
779 /* The following field is flag of the first automaton insn with the
780 same reservations in the declaration list. Only arcs marked such
781 insn is present in the automaton. This significantly decreases
782 memory requirements especially when several automata are
783 formed. */
784 char first_insn_with_same_reservs;
785 /* The following member has nonzero value if there is arc from state of
786 the automaton marked by the ainsn. */
787 char arc_exists_p;
788 /* Cyclic list of insns of an equivalence class is formed with the
789 aid of the following field. */
790 ainsn_t next_equiv_class_insn;
791 /* The following field value is nonzero if the insn declaration is
792 the first insn declaration with given equivalence number. */
793 char first_ainsn_with_given_equivalence_num;
794 /* The following field is number of class of equivalence of insns.
795 It is necessary because many insns may be equivalent with the
796 point of view of pipeline hazards. */
797 int insn_equiv_class_num;
798 /* The following member value is TRUE if there is an arc in the
799 automaton marked by the insn into another state. In other
800 words, the insn can change the state of the automaton. */
801 int important_p;
804 /* The following describes an automaton for PHR. */
805 struct automaton
807 /* The following field value is the list of insn declarations for
808 given automaton. */
809 ainsn_t ainsn_list;
810 /* The following field value is the corresponding automaton
811 declaration. This field is not NULL only if the automatic
812 partition on automata is not used. */
813 struct automaton_decl *corresponding_automaton_decl;
814 /* The following field value is the next automaton. */
815 automaton_t next_automaton;
816 /* The following field is start state of FA. There are not unit
817 reservations in the state. */
818 state_t start_state;
819 /* The following field value is number of equivalence classes of
820 insns (see field `insn_equiv_class_num' in
821 `insn_reserv_decl'). */
822 int insn_equiv_classes_num;
823 /* The following field value is number of states of final DFA. */
824 int achieved_states_num;
825 /* The following field value is the order number (0, 1, ...) of
826 given automaton. */
827 int automaton_order_num;
828 /* The following fields contain statistics information about
829 building automaton. */
830 int NDFA_states_num, DFA_states_num;
831 /* The following field value is defined only if minimization of DFA
832 is used. */
833 int minimal_DFA_states_num;
834 int NDFA_arcs_num, DFA_arcs_num;
835 /* The following field value is defined only if minimization of DFA
836 is used. */
837 int minimal_DFA_arcs_num;
838 /* The following member refers for two table state x ainsn -> int.
839 ??? Above sentence is incomprehensible. */
840 state_ainsn_table_t trans_table;
841 /* The following member value is maximal value of min issue delay
842 for insns of the automaton. */
843 int max_min_delay;
844 /* Usually min issue delay is small and we can place several (2, 4,
845 8) elements in one vector element. So the compression factor can
846 be 1 (no compression), 2, 4, 8. */
847 int min_issue_delay_table_compression_factor;
848 /* Total number of locked states in this automaton. */
849 int locked_states;
852 /* The following is the element of the list of automata. */
853 struct automata_list_el
855 /* The automaton itself. */
856 automaton_t automaton;
857 /* The next automata set element. */
858 automata_list_el_t next_automata_list_el;
861 /* The following structure describes a table state X ainsn -> int(>= 0). */
862 struct state_ainsn_table
864 /* Automaton to which given table belongs. */
865 automaton_t automaton;
866 /* The following tree vectors for comb vector implementation of the
867 table. */
868 vla_hwint_t comb_vect;
869 vla_hwint_t check_vect;
870 vla_hwint_t base_vect;
871 /* This is simple implementation of the table. */
872 vla_hwint_t full_vect;
873 /* Minimal and maximal values of the previous vectors. */
874 int min_comb_vect_el_value, max_comb_vect_el_value;
875 int min_base_vect_el_value, max_base_vect_el_value;
878 /* Macros to access members of unions. Use only them for access to
879 union members of declarations and regexps. */
881 #if defined ENABLE_CHECKING && (GCC_VERSION >= 2007)
883 #define DECL_UNIT(d) __extension__ \
884 (({ struct decl *const _decl = (d); \
885 if (_decl->mode != dm_unit) \
886 decl_mode_check_failed (_decl->mode, "dm_unit", \
887 __FILE__, __LINE__, __FUNCTION__); \
888 &(_decl)->decl.unit; }))
890 #define DECL_BYPASS(d) __extension__ \
891 (({ struct decl *const _decl = (d); \
892 if (_decl->mode != dm_bypass) \
893 decl_mode_check_failed (_decl->mode, "dm_bypass", \
894 __FILE__, __LINE__, __FUNCTION__); \
895 &(_decl)->decl.bypass; }))
897 #define DECL_AUTOMATON(d) __extension__ \
898 (({ struct decl *const _decl = (d); \
899 if (_decl->mode != dm_automaton) \
900 decl_mode_check_failed (_decl->mode, "dm_automaton", \
901 __FILE__, __LINE__, __FUNCTION__); \
902 &(_decl)->decl.automaton; }))
904 #define DECL_EXCL(d) __extension__ \
905 (({ struct decl *const _decl = (d); \
906 if (_decl->mode != dm_excl) \
907 decl_mode_check_failed (_decl->mode, "dm_excl", \
908 __FILE__, __LINE__, __FUNCTION__); \
909 &(_decl)->decl.excl; }))
911 #define DECL_PRESENCE(d) __extension__ \
912 (({ struct decl *const _decl = (d); \
913 if (_decl->mode != dm_presence) \
914 decl_mode_check_failed (_decl->mode, "dm_presence", \
915 __FILE__, __LINE__, __FUNCTION__); \
916 &(_decl)->decl.presence; }))
918 #define DECL_ABSENCE(d) __extension__ \
919 (({ struct decl *const _decl = (d); \
920 if (_decl->mode != dm_absence) \
921 decl_mode_check_failed (_decl->mode, "dm_absence", \
922 __FILE__, __LINE__, __FUNCTION__); \
923 &(_decl)->decl.absence; }))
925 #define DECL_RESERV(d) __extension__ \
926 (({ struct decl *const _decl = (d); \
927 if (_decl->mode != dm_reserv) \
928 decl_mode_check_failed (_decl->mode, "dm_reserv", \
929 __FILE__, __LINE__, __FUNCTION__); \
930 &(_decl)->decl.reserv; }))
932 #define DECL_INSN_RESERV(d) __extension__ \
933 (({ struct decl *const _decl = (d); \
934 if (_decl->mode != dm_insn_reserv) \
935 decl_mode_check_failed (_decl->mode, "dm_insn_reserv", \
936 __FILE__, __LINE__, __FUNCTION__); \
937 &(_decl)->decl.insn_reserv; }))
939 static const char *decl_name (enum decl_mode);
940 static void decl_mode_check_failed (enum decl_mode, const char *,
941 const char *, int, const char *)
942 ATTRIBUTE_NORETURN;
944 /* Return string representation of declaration mode MODE. */
945 static const char *
946 decl_name (enum decl_mode mode)
948 static char str [100];
950 if (mode == dm_unit)
951 return "dm_unit";
952 else if (mode == dm_bypass)
953 return "dm_bypass";
954 else if (mode == dm_automaton)
955 return "dm_automaton";
956 else if (mode == dm_excl)
957 return "dm_excl";
958 else if (mode == dm_presence)
959 return "dm_presence";
960 else if (mode == dm_absence)
961 return "dm_absence";
962 else if (mode == dm_reserv)
963 return "dm_reserv";
964 else if (mode == dm_insn_reserv)
965 return "dm_insn_reserv";
966 else
967 sprintf (str, "unknown (%d)", (int) mode);
968 return str;
971 /* The function prints message about unexpected declaration and finish
972 the program. */
973 static void
974 decl_mode_check_failed (enum decl_mode mode, const char *expected_mode_str,
975 const char *file, int line, const char *func)
977 fprintf
978 (stderr,
979 "\n%s: %d: error in %s: DECL check: expected decl %s, have %s\n",
980 file, line, func, expected_mode_str, decl_name (mode));
981 exit (1);
985 #define REGEXP_UNIT(r) __extension__ \
986 (({ struct regexp *const _regexp = (r); \
987 if (_regexp->mode != rm_unit) \
988 regexp_mode_check_failed (_regexp->mode, "rm_unit", \
989 __FILE__, __LINE__, __FUNCTION__); \
990 &(_regexp)->regexp.unit; }))
992 #define REGEXP_RESERV(r) __extension__ \
993 (({ struct regexp *const _regexp = (r); \
994 if (_regexp->mode != rm_reserv) \
995 regexp_mode_check_failed (_regexp->mode, "rm_reserv", \
996 __FILE__, __LINE__, __FUNCTION__); \
997 &(_regexp)->regexp.reserv; }))
999 #define REGEXP_SEQUENCE(r) __extension__ \
1000 (({ struct regexp *const _regexp = (r); \
1001 if (_regexp->mode != rm_sequence) \
1002 regexp_mode_check_failed (_regexp->mode, "rm_sequence", \
1003 __FILE__, __LINE__, __FUNCTION__); \
1004 &(_regexp)->regexp.sequence; }))
1006 #define REGEXP_REPEAT(r) __extension__ \
1007 (({ struct regexp *const _regexp = (r); \
1008 if (_regexp->mode != rm_repeat) \
1009 regexp_mode_check_failed (_regexp->mode, "rm_repeat", \
1010 __FILE__, __LINE__, __FUNCTION__); \
1011 &(_regexp)->regexp.repeat; }))
1013 #define REGEXP_ALLOF(r) __extension__ \
1014 (({ struct regexp *const _regexp = (r); \
1015 if (_regexp->mode != rm_allof) \
1016 regexp_mode_check_failed (_regexp->mode, "rm_allof", \
1017 __FILE__, __LINE__, __FUNCTION__); \
1018 &(_regexp)->regexp.allof; }))
1020 #define REGEXP_ONEOF(r) __extension__ \
1021 (({ struct regexp *const _regexp = (r); \
1022 if (_regexp->mode != rm_oneof) \
1023 regexp_mode_check_failed (_regexp->mode, "rm_oneof", \
1024 __FILE__, __LINE__, __FUNCTION__); \
1025 &(_regexp)->regexp.oneof; }))
1027 static const char *regexp_name (enum regexp_mode);
1028 static void regexp_mode_check_failed (enum regexp_mode, const char *,
1029 const char *, int,
1030 const char *) ATTRIBUTE_NORETURN;
1033 /* Return string representation of regexp mode MODE. */
1034 static const char *
1035 regexp_name (enum regexp_mode mode)
1037 switch (mode)
1039 case rm_unit:
1040 return "rm_unit";
1041 case rm_reserv:
1042 return "rm_reserv";
1043 case rm_nothing:
1044 return "rm_nothing";
1045 case rm_sequence:
1046 return "rm_sequence";
1047 case rm_repeat:
1048 return "rm_repeat";
1049 case rm_allof:
1050 return "rm_allof";
1051 case rm_oneof:
1052 return "rm_oneof";
1053 default:
1054 gcc_unreachable ();
1058 /* The function prints message about unexpected regexp and finish the
1059 program. */
1060 static void
1061 regexp_mode_check_failed (enum regexp_mode mode,
1062 const char *expected_mode_str,
1063 const char *file, int line, const char *func)
1065 fprintf
1066 (stderr,
1067 "\n%s: %d: error in %s: REGEXP check: expected decl %s, have %s\n",
1068 file, line, func, expected_mode_str, regexp_name (mode));
1069 exit (1);
1072 #else /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */
1074 #define DECL_UNIT(d) (&(d)->decl.unit)
1075 #define DECL_BYPASS(d) (&(d)->decl.bypass)
1076 #define DECL_AUTOMATON(d) (&(d)->decl.automaton)
1077 #define DECL_EXCL(d) (&(d)->decl.excl)
1078 #define DECL_PRESENCE(d) (&(d)->decl.presence)
1079 #define DECL_ABSENCE(d) (&(d)->decl.absence)
1080 #define DECL_RESERV(d) (&(d)->decl.reserv)
1081 #define DECL_INSN_RESERV(d) (&(d)->decl.insn_reserv)
1083 #define REGEXP_UNIT(r) (&(r)->regexp.unit)
1084 #define REGEXP_RESERV(r) (&(r)->regexp.reserv)
1085 #define REGEXP_SEQUENCE(r) (&(r)->regexp.sequence)
1086 #define REGEXP_REPEAT(r) (&(r)->regexp.repeat)
1087 #define REGEXP_ALLOF(r) (&(r)->regexp.allof)
1088 #define REGEXP_ONEOF(r) (&(r)->regexp.oneof)
1090 #endif /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */
1092 /* Create IR structure (node). */
1093 static void *
1094 create_node (size_t size)
1096 void *result;
1098 obstack_blank (&irp, size);
1099 result = obstack_base (&irp);
1100 obstack_finish (&irp);
1101 /* Default values of members are NULL and zero. */
1102 memset (result, 0, size);
1103 return result;
1106 /* Copy IR structure (node). */
1107 static void *
1108 copy_node (const void *from, size_t size)
1110 void *const result = create_node (size);
1111 memcpy (result, from, size);
1112 return result;
1115 /* The function checks that NAME does not contain quotes (`"'). */
1116 static const char *
1117 check_name (const char * name, pos_t pos ATTRIBUTE_UNUSED)
1119 const char *str;
1121 for (str = name; *str != '\0'; str++)
1122 if (*str == '\"')
1123 error ("Name `%s' contains quotes", name);
1124 return name;
1127 /* Pointers to all declarations during IR generation are stored in the
1128 following. */
1129 static VEC(decl_t,heap) *decls;
1131 /* Given a pointer to a (char *) and a separator, return an alloc'ed
1132 string containing the next separated element, taking parentheses
1133 into account if PAR_FLAG has nonzero value. Advance the pointer to
1134 after the string scanned, or the end-of-string. Return NULL if at
1135 end of string. */
1136 static char *
1137 next_sep_el (const char **pstr, int sep, int par_flag)
1139 char *out_str;
1140 const char *p;
1141 int pars_num;
1142 int n_spaces;
1144 /* Remove leading whitespaces. */
1145 while (ISSPACE ((int) **pstr))
1146 (*pstr)++;
1148 if (**pstr == '\0')
1149 return NULL;
1151 n_spaces = 0;
1152 for (pars_num = 0, p = *pstr; *p != '\0'; p++)
1154 if (par_flag && *p == '(')
1155 pars_num++;
1156 else if (par_flag && *p == ')')
1157 pars_num--;
1158 else if (pars_num == 0 && *p == sep)
1159 break;
1160 if (pars_num == 0 && ISSPACE ((int) *p))
1161 n_spaces++;
1162 else
1164 for (; n_spaces != 0; n_spaces--)
1165 obstack_1grow (&irp, p [-n_spaces]);
1166 obstack_1grow (&irp, *p);
1169 obstack_1grow (&irp, '\0');
1170 out_str = obstack_base (&irp);
1171 obstack_finish (&irp);
1173 *pstr = p;
1174 if (**pstr == sep)
1175 (*pstr)++;
1177 return out_str;
1180 /* Given a string and a separator, return the number of separated
1181 elements in it, taking parentheses into account if PAR_FLAG has
1182 nonzero value. Return 0 for the null string, -1 if parentheses is
1183 not balanced. */
1184 static int
1185 n_sep_els (const char *s, int sep, int par_flag)
1187 int n;
1188 int pars_num;
1190 if (*s == '\0')
1191 return 0;
1193 for (pars_num = 0, n = 1; *s; s++)
1194 if (par_flag && *s == '(')
1195 pars_num++;
1196 else if (par_flag && *s == ')')
1197 pars_num--;
1198 else if (pars_num == 0 && *s == sep)
1199 n++;
1201 return (pars_num != 0 ? -1 : n);
1204 /* Given a string and a separator, return vector of strings which are
1205 elements in the string and number of elements through els_num.
1206 Take parentheses into account if PAREN_P has nonzero value. The
1207 function also inserts the end marker NULL at the end of vector.
1208 Return 0 for the null string, -1 if parentheses are not balanced. */
1209 static char **
1210 get_str_vect (const char *str, int *els_num, int sep, int paren_p)
1212 int i;
1213 char **vect;
1214 const char **pstr;
1215 char *trail;
1217 *els_num = n_sep_els (str, sep, paren_p);
1218 if (*els_num <= 0)
1219 return NULL;
1220 obstack_blank (&irp, sizeof (char *) * (*els_num + 1));
1221 vect = (char **) obstack_base (&irp);
1222 obstack_finish (&irp);
1223 pstr = &str;
1224 for (i = 0; i < *els_num; i++)
1225 vect [i] = next_sep_el (pstr, sep, paren_p);
1226 trail = next_sep_el (pstr, sep, paren_p);
1227 gcc_assert (!trail);
1228 vect [i] = NULL;
1229 return vect;
1232 /* Process a DEFINE_CPU_UNIT.
1234 This gives information about a unit contained in CPU. We fill a
1235 struct unit_decl with information used later by `expand_automata'. */
1236 static void
1237 gen_cpu_unit (rtx def)
1239 decl_t decl;
1240 char **str_cpu_units;
1241 int vect_length;
1242 int i;
1244 str_cpu_units = get_str_vect (XSTR (def, 0), &vect_length, ',', FALSE);
1245 if (str_cpu_units == NULL)
1246 fatal ("invalid string `%s' in define_cpu_unit", XSTR (def, 0));
1247 for (i = 0; i < vect_length; i++)
1249 decl = create_node (sizeof (struct decl));
1250 decl->mode = dm_unit;
1251 decl->pos = 0;
1252 DECL_UNIT (decl)->name = check_name (str_cpu_units [i], decl->pos);
1253 DECL_UNIT (decl)->automaton_name = XSTR (def, 1);
1254 DECL_UNIT (decl)->query_p = 0;
1255 DECL_UNIT (decl)->min_occ_cycle_num = -1;
1256 DECL_UNIT (decl)->in_set_p = 0;
1257 VEC_safe_push (decl_t,heap, decls, decl);
1261 /* Process a DEFINE_QUERY_CPU_UNIT.
1263 This gives information about a unit contained in CPU. We fill a
1264 struct unit_decl with information used later by `expand_automata'. */
1265 static void
1266 gen_query_cpu_unit (rtx def)
1268 decl_t decl;
1269 char **str_cpu_units;
1270 int vect_length;
1271 int i;
1273 str_cpu_units = get_str_vect (XSTR (def, 0), &vect_length, ',',
1274 FALSE);
1275 if (str_cpu_units == NULL)
1276 fatal ("invalid string `%s' in define_query_cpu_unit", XSTR (def, 0));
1277 for (i = 0; i < vect_length; i++)
1279 decl = create_node (sizeof (struct decl));
1280 decl->mode = dm_unit;
1281 decl->pos = 0;
1282 DECL_UNIT (decl)->name = check_name (str_cpu_units [i], decl->pos);
1283 DECL_UNIT (decl)->automaton_name = XSTR (def, 1);
1284 DECL_UNIT (decl)->query_p = 1;
1285 VEC_safe_push (decl_t,heap, decls, decl);
1289 /* Process a DEFINE_BYPASS.
1291 This gives information about a unit contained in the CPU. We fill
1292 in a struct bypass_decl with information used later by
1293 `expand_automata'. */
1294 static void
1295 gen_bypass (rtx def)
1297 decl_t decl;
1298 char **out_insns;
1299 int out_length;
1300 char **in_insns;
1301 int in_length;
1302 int i, j;
1304 out_insns = get_str_vect (XSTR (def, 1), &out_length, ',', FALSE);
1305 if (out_insns == NULL)
1306 fatal ("invalid string `%s' in define_bypass", XSTR (def, 1));
1307 in_insns = get_str_vect (XSTR (def, 2), &in_length, ',', FALSE);
1308 if (in_insns == NULL)
1309 fatal ("invalid string `%s' in define_bypass", XSTR (def, 2));
1310 for (i = 0; i < out_length; i++)
1311 for (j = 0; j < in_length; j++)
1313 decl = create_node (sizeof (struct decl));
1314 decl->mode = dm_bypass;
1315 decl->pos = 0;
1316 DECL_BYPASS (decl)->latency = XINT (def, 0);
1317 DECL_BYPASS (decl)->out_insn_name = out_insns [i];
1318 DECL_BYPASS (decl)->in_insn_name = in_insns [j];
1319 DECL_BYPASS (decl)->bypass_guard_name = XSTR (def, 3);
1320 VEC_safe_push (decl_t,heap, decls, decl);
1324 /* Process an EXCLUSION_SET.
1326 This gives information about a cpu unit conflicts. We fill a
1327 struct excl_rel_decl (excl) with information used later by
1328 `expand_automata'. */
1329 static void
1330 gen_excl_set (rtx def)
1332 decl_t decl;
1333 char **first_str_cpu_units;
1334 char **second_str_cpu_units;
1335 int first_vect_length;
1336 int length;
1337 int i;
1339 first_str_cpu_units
1340 = get_str_vect (XSTR (def, 0), &first_vect_length, ',', FALSE);
1341 if (first_str_cpu_units == NULL)
1342 fatal ("invalid first string `%s' in exclusion_set", XSTR (def, 0));
1343 second_str_cpu_units = get_str_vect (XSTR (def, 1), &length, ',',
1344 FALSE);
1345 if (second_str_cpu_units == NULL)
1346 fatal ("invalid second string `%s' in exclusion_set", XSTR (def, 1));
1347 length += first_vect_length;
1348 decl = create_node (sizeof (struct decl) + (length - 1) * sizeof (char *));
1349 decl->mode = dm_excl;
1350 decl->pos = 0;
1351 DECL_EXCL (decl)->all_names_num = length;
1352 DECL_EXCL (decl)->first_list_length = first_vect_length;
1353 for (i = 0; i < length; i++)
1354 if (i < first_vect_length)
1355 DECL_EXCL (decl)->names [i] = first_str_cpu_units [i];
1356 else
1357 DECL_EXCL (decl)->names [i]
1358 = second_str_cpu_units [i - first_vect_length];
1359 VEC_safe_push (decl_t,heap, decls, decl);
1362 /* Process a PRESENCE_SET, a FINAL_PRESENCE_SET, an ABSENCE_SET,
1363 FINAL_ABSENCE_SET (it is depended on PRESENCE_P and FINAL_P).
1365 This gives information about a cpu unit reservation requirements.
1366 We fill a struct unit_pattern_rel_decl with information used later
1367 by `expand_automata'. */
1368 static void
1369 gen_presence_absence_set (rtx def, int presence_p, int final_p)
1371 decl_t decl;
1372 char **str_cpu_units;
1373 char **str_pattern_lists;
1374 char ***str_patterns;
1375 int cpu_units_length;
1376 int length;
1377 int patterns_length;
1378 int i;
1380 str_cpu_units = get_str_vect (XSTR (def, 0), &cpu_units_length, ',',
1381 FALSE);
1382 if (str_cpu_units == NULL)
1383 fatal ((presence_p
1384 ? (final_p
1385 ? "invalid first string `%s' in final_presence_set"
1386 : "invalid first string `%s' in presence_set")
1387 : (final_p
1388 ? "invalid first string `%s' in final_absence_set"
1389 : "invalid first string `%s' in absence_set")),
1390 XSTR (def, 0));
1391 str_pattern_lists = get_str_vect (XSTR (def, 1),
1392 &patterns_length, ',', FALSE);
1393 if (str_pattern_lists == NULL)
1394 fatal ((presence_p
1395 ? (final_p
1396 ? "invalid second string `%s' in final_presence_set"
1397 : "invalid second string `%s' in presence_set")
1398 : (final_p
1399 ? "invalid second string `%s' in final_absence_set"
1400 : "invalid second string `%s' in absence_set")), XSTR (def, 1));
1401 str_patterns = obstack_alloc (&irp, patterns_length * sizeof (char **));
1402 for (i = 0; i < patterns_length; i++)
1404 str_patterns [i] = get_str_vect (str_pattern_lists [i],
1405 &length, ' ', FALSE);
1406 gcc_assert (str_patterns [i]);
1408 decl = create_node (sizeof (struct decl));
1409 decl->pos = 0;
1410 if (presence_p)
1412 decl->mode = dm_presence;
1413 DECL_PRESENCE (decl)->names_num = cpu_units_length;
1414 DECL_PRESENCE (decl)->names = str_cpu_units;
1415 DECL_PRESENCE (decl)->patterns = str_patterns;
1416 DECL_PRESENCE (decl)->patterns_num = patterns_length;
1417 DECL_PRESENCE (decl)->final_p = final_p;
1419 else
1421 decl->mode = dm_absence;
1422 DECL_ABSENCE (decl)->names_num = cpu_units_length;
1423 DECL_ABSENCE (decl)->names = str_cpu_units;
1424 DECL_ABSENCE (decl)->patterns = str_patterns;
1425 DECL_ABSENCE (decl)->patterns_num = patterns_length;
1426 DECL_ABSENCE (decl)->final_p = final_p;
1428 VEC_safe_push (decl_t,heap, decls, decl);
1431 /* Process a PRESENCE_SET.
1433 This gives information about a cpu unit reservation requirements.
1434 We fill a struct unit_pattern_rel_decl (presence) with information
1435 used later by `expand_automata'. */
1436 static void
1437 gen_presence_set (rtx def)
1439 gen_presence_absence_set (def, TRUE, FALSE);
1442 /* Process a FINAL_PRESENCE_SET.
1444 This gives information about a cpu unit reservation requirements.
1445 We fill a struct unit_pattern_rel_decl (presence) with information
1446 used later by `expand_automata'. */
1447 static void
1448 gen_final_presence_set (rtx def)
1450 gen_presence_absence_set (def, TRUE, TRUE);
1453 /* Process an ABSENCE_SET.
1455 This gives information about a cpu unit reservation requirements.
1456 We fill a struct unit_pattern_rel_decl (absence) with information
1457 used later by `expand_automata'. */
1458 static void
1459 gen_absence_set (rtx def)
1461 gen_presence_absence_set (def, FALSE, FALSE);
1464 /* Process a FINAL_ABSENCE_SET.
1466 This gives information about a cpu unit reservation requirements.
1467 We fill a struct unit_pattern_rel_decl (absence) with information
1468 used later by `expand_automata'. */
1469 static void
1470 gen_final_absence_set (rtx def)
1472 gen_presence_absence_set (def, FALSE, TRUE);
1475 /* Process a DEFINE_AUTOMATON.
1477 This gives information about a finite state automaton used for
1478 recognizing pipeline hazards. We fill a struct automaton_decl
1479 with information used later by `expand_automata'. */
1480 static void
1481 gen_automaton (rtx def)
1483 decl_t decl;
1484 char **str_automata;
1485 int vect_length;
1486 int i;
1488 str_automata = get_str_vect (XSTR (def, 0), &vect_length, ',', FALSE);
1489 if (str_automata == NULL)
1490 fatal ("invalid string `%s' in define_automaton", XSTR (def, 0));
1491 for (i = 0; i < vect_length; i++)
1493 decl = create_node (sizeof (struct decl));
1494 decl->mode = dm_automaton;
1495 decl->pos = 0;
1496 DECL_AUTOMATON (decl)->name = check_name (str_automata [i], decl->pos);
1497 VEC_safe_push (decl_t,heap, decls, decl);
1501 /* Process an AUTOMATA_OPTION.
1503 This gives information how to generate finite state automaton used
1504 for recognizing pipeline hazards. */
1505 static void
1506 gen_automata_option (rtx def)
1508 if (strcmp (XSTR (def, 0), NO_MINIMIZATION_OPTION + 1) == 0)
1509 no_minimization_flag = 1;
1510 else if (strcmp (XSTR (def, 0), TIME_OPTION + 1) == 0)
1511 time_flag = 1;
1512 else if (strcmp (XSTR (def, 0), V_OPTION + 1) == 0)
1513 v_flag = 1;
1514 else if (strcmp (XSTR (def, 0), W_OPTION + 1) == 0)
1515 w_flag = 1;
1516 else if (strcmp (XSTR (def, 0), NDFA_OPTION + 1) == 0)
1517 ndfa_flag = 1;
1518 else if (strcmp (XSTR (def, 0), PROGRESS_OPTION + 1) == 0)
1519 progress_flag = 1;
1520 else
1521 fatal ("invalid option `%s' in automata_option", XSTR (def, 0));
1524 /* Name in reservation to denote absence reservation. */
1525 #define NOTHING_NAME "nothing"
1527 /* The following string contains original reservation string being
1528 parsed. */
1529 static const char *reserv_str;
1531 /* Parse an element in STR. */
1532 static regexp_t
1533 gen_regexp_el (const char *str)
1535 regexp_t regexp;
1536 char *dstr;
1537 int len;
1539 if (*str == '(')
1541 len = strlen (str);
1542 if (str [len - 1] != ')')
1543 fatal ("garbage after ) in reservation `%s'", reserv_str);
1544 dstr = alloca (len - 1);
1545 memcpy (dstr, str + 1, len - 2);
1546 dstr [len-2] = '\0';
1547 regexp = gen_regexp_sequence (dstr);
1549 else if (strcmp (str, NOTHING_NAME) == 0)
1551 regexp = create_node (sizeof (struct decl));
1552 regexp->mode = rm_nothing;
1554 else
1556 regexp = create_node (sizeof (struct decl));
1557 regexp->mode = rm_unit;
1558 REGEXP_UNIT (regexp)->name = str;
1560 return regexp;
1563 /* Parse construction `repeat' in STR. */
1564 static regexp_t
1565 gen_regexp_repeat (const char *str)
1567 regexp_t regexp;
1568 regexp_t repeat;
1569 char **repeat_vect;
1570 int els_num;
1571 int i;
1573 repeat_vect = get_str_vect (str, &els_num, '*', TRUE);
1574 if (repeat_vect == NULL)
1575 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1576 if (els_num > 1)
1578 regexp = gen_regexp_el (repeat_vect [0]);
1579 for (i = 1; i < els_num; i++)
1581 repeat = create_node (sizeof (struct regexp));
1582 repeat->mode = rm_repeat;
1583 REGEXP_REPEAT (repeat)->regexp = regexp;
1584 REGEXP_REPEAT (repeat)->repeat_num = atoi (repeat_vect [i]);
1585 if (REGEXP_REPEAT (repeat)->repeat_num <= 1)
1586 fatal ("repetition `%s' <= 1 in reservation `%s'",
1587 str, reserv_str);
1588 regexp = repeat;
1590 return regexp;
1592 else
1593 return gen_regexp_el (str);
1596 /* Parse reservation STR which possibly contains separator '+'. */
1597 static regexp_t
1598 gen_regexp_allof (const char *str)
1600 regexp_t allof;
1601 char **allof_vect;
1602 int els_num;
1603 int i;
1605 allof_vect = get_str_vect (str, &els_num, '+', TRUE);
1606 if (allof_vect == NULL)
1607 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1608 if (els_num > 1)
1610 allof = create_node (sizeof (struct regexp)
1611 + sizeof (regexp_t) * (els_num - 1));
1612 allof->mode = rm_allof;
1613 REGEXP_ALLOF (allof)->regexps_num = els_num;
1614 for (i = 0; i < els_num; i++)
1615 REGEXP_ALLOF (allof)->regexps [i] = gen_regexp_repeat (allof_vect [i]);
1616 return allof;
1618 else
1619 return gen_regexp_repeat (str);
1622 /* Parse reservation STR which possibly contains separator '|'. */
1623 static regexp_t
1624 gen_regexp_oneof (const char *str)
1626 regexp_t oneof;
1627 char **oneof_vect;
1628 int els_num;
1629 int i;
1631 oneof_vect = get_str_vect (str, &els_num, '|', TRUE);
1632 if (oneof_vect == NULL)
1633 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1634 if (els_num > 1)
1636 oneof = create_node (sizeof (struct regexp)
1637 + sizeof (regexp_t) * (els_num - 1));
1638 oneof->mode = rm_oneof;
1639 REGEXP_ONEOF (oneof)->regexps_num = els_num;
1640 for (i = 0; i < els_num; i++)
1641 REGEXP_ONEOF (oneof)->regexps [i] = gen_regexp_allof (oneof_vect [i]);
1642 return oneof;
1644 else
1645 return gen_regexp_allof (str);
1648 /* Parse reservation STR which possibly contains separator ','. */
1649 static regexp_t
1650 gen_regexp_sequence (const char *str)
1652 regexp_t sequence;
1653 char **sequence_vect;
1654 int els_num;
1655 int i;
1657 sequence_vect = get_str_vect (str, &els_num, ',', TRUE);
1658 if (els_num > 1)
1660 sequence = create_node (sizeof (struct regexp)
1661 + sizeof (regexp_t) * (els_num - 1));
1662 sequence->mode = rm_sequence;
1663 REGEXP_SEQUENCE (sequence)->regexps_num = els_num;
1664 for (i = 0; i < els_num; i++)
1665 REGEXP_SEQUENCE (sequence)->regexps [i]
1666 = gen_regexp_oneof (sequence_vect [i]);
1667 return sequence;
1669 else
1670 return gen_regexp_oneof (str);
1673 /* Parse construction reservation STR. */
1674 static regexp_t
1675 gen_regexp (const char *str)
1677 reserv_str = str;
1678 return gen_regexp_sequence (str);;
1681 /* Process a DEFINE_RESERVATION.
1683 This gives information about a reservation of cpu units. We fill
1684 in a struct reserv_decl with information used later by
1685 `expand_automata'. */
1686 static void
1687 gen_reserv (rtx def)
1689 decl_t decl;
1691 decl = create_node (sizeof (struct decl));
1692 decl->mode = dm_reserv;
1693 decl->pos = 0;
1694 DECL_RESERV (decl)->name = check_name (XSTR (def, 0), decl->pos);
1695 DECL_RESERV (decl)->regexp = gen_regexp (XSTR (def, 1));
1696 VEC_safe_push (decl_t,heap, decls, decl);
1699 /* Process a DEFINE_INSN_RESERVATION.
1701 This gives information about the reservation of cpu units by an
1702 insn. We fill a struct insn_reserv_decl with information used
1703 later by `expand_automata'. */
1704 static void
1705 gen_insn_reserv (rtx def)
1707 decl_t decl;
1709 decl = create_node (sizeof (struct decl));
1710 decl->mode = dm_insn_reserv;
1711 decl->pos = 0;
1712 DECL_INSN_RESERV (decl)->name
1713 = check_name (XSTR (def, 0), decl->pos);
1714 DECL_INSN_RESERV (decl)->default_latency = XINT (def, 1);
1715 DECL_INSN_RESERV (decl)->condexp = XEXP (def, 2);
1716 DECL_INSN_RESERV (decl)->regexp = gen_regexp (XSTR (def, 3));
1717 VEC_safe_push (decl_t,heap, decls, decl);
1722 /* The function evaluates hash value (0..UINT_MAX) of string. */
1723 static unsigned
1724 string_hash (const char *string)
1726 unsigned result, i;
1728 for (result = i = 0;*string++ != '\0'; i++)
1729 result += ((unsigned char) *string << (i % CHAR_BIT));
1730 return result;
1735 /* This page contains abstract data `table of automaton declarations'.
1736 Elements of the table is nodes representing automaton declarations.
1737 Key of the table elements is name of given automaton. Remember
1738 that automaton names have own space. */
1740 /* The function evaluates hash value of an automaton declaration. The
1741 function is used by abstract data `hashtab'. The function returns
1742 hash value (0..UINT_MAX) of given automaton declaration. */
1743 static hashval_t
1744 automaton_decl_hash (const void *automaton_decl)
1746 const decl_t decl = (decl_t) automaton_decl;
1748 gcc_assert (decl->mode != dm_automaton
1749 || DECL_AUTOMATON (decl)->name);
1750 return string_hash (DECL_AUTOMATON (decl)->name);
1753 /* The function tests automaton declarations on equality of their
1754 keys. The function is used by abstract data `hashtab'. The
1755 function returns 1 if the declarations have the same key, 0
1756 otherwise. */
1757 static int
1758 automaton_decl_eq_p (const void* automaton_decl_1,
1759 const void* automaton_decl_2)
1761 const decl_t decl1 = (decl_t) automaton_decl_1;
1762 const decl_t decl2 = (decl_t) automaton_decl_2;
1764 gcc_assert (decl1->mode == dm_automaton
1765 && DECL_AUTOMATON (decl1)->name
1766 && decl2->mode == dm_automaton
1767 && DECL_AUTOMATON (decl2)->name);
1768 return strcmp (DECL_AUTOMATON (decl1)->name,
1769 DECL_AUTOMATON (decl2)->name) == 0;
1772 /* The automaton declaration table itself is represented by the
1773 following variable. */
1774 static htab_t automaton_decl_table;
1776 /* The function inserts automaton declaration into the table. The
1777 function does nothing if an automaton declaration with the same key
1778 exists already in the table. The function returns automaton
1779 declaration node in the table with the same key as given automaton
1780 declaration node. */
1781 static decl_t
1782 insert_automaton_decl (decl_t automaton_decl)
1784 void **entry_ptr;
1786 entry_ptr = htab_find_slot (automaton_decl_table, automaton_decl, 1);
1787 if (*entry_ptr == NULL)
1788 *entry_ptr = (void *) automaton_decl;
1789 return (decl_t) *entry_ptr;
1792 /* The following variable value is node representing automaton
1793 declaration. The node used for searching automaton declaration
1794 with given name. */
1795 static struct decl work_automaton_decl;
1797 /* The function searches for automaton declaration in the table with
1798 the same key as node representing name of the automaton
1799 declaration. The function returns node found in the table, NULL if
1800 such node does not exist in the table. */
1801 static decl_t
1802 find_automaton_decl (const char *name)
1804 void *entry;
1806 work_automaton_decl.mode = dm_automaton;
1807 DECL_AUTOMATON (&work_automaton_decl)->name = name;
1808 entry = htab_find (automaton_decl_table, &work_automaton_decl);
1809 return (decl_t) entry;
1812 /* The function creates empty automaton declaration table and node
1813 representing automaton declaration and used for searching automaton
1814 declaration with given name. The function must be called only once
1815 before any work with the automaton declaration table. */
1816 static void
1817 initiate_automaton_decl_table (void)
1819 work_automaton_decl.mode = dm_automaton;
1820 automaton_decl_table = htab_create (10, automaton_decl_hash,
1821 automaton_decl_eq_p, (htab_del) 0);
1824 /* The function deletes the automaton declaration table. Only call of
1825 function `initiate_automaton_decl_table' is possible immediately
1826 after this function call. */
1827 static void
1828 finish_automaton_decl_table (void)
1830 htab_delete (automaton_decl_table);
1835 /* This page contains abstract data `table of insn declarations'.
1836 Elements of the table is nodes representing insn declarations. Key
1837 of the table elements is name of given insn (in corresponding
1838 define_insn_reservation). Remember that insn names have own
1839 space. */
1841 /* The function evaluates hash value of an insn declaration. The
1842 function is used by abstract data `hashtab'. The function returns
1843 hash value (0..UINT_MAX) of given insn declaration. */
1844 static hashval_t
1845 insn_decl_hash (const void *insn_decl)
1847 const decl_t decl = (decl_t) insn_decl;
1849 gcc_assert (decl->mode == dm_insn_reserv
1850 && DECL_INSN_RESERV (decl)->name);
1851 return string_hash (DECL_INSN_RESERV (decl)->name);
1854 /* The function tests insn declarations on equality of their keys.
1855 The function is used by abstract data `hashtab'. The function
1856 returns 1 if declarations have the same key, 0 otherwise. */
1857 static int
1858 insn_decl_eq_p (const void *insn_decl_1, const void *insn_decl_2)
1860 const decl_t decl1 = (decl_t) insn_decl_1;
1861 const decl_t decl2 = (decl_t) insn_decl_2;
1863 gcc_assert (decl1->mode == dm_insn_reserv
1864 && DECL_INSN_RESERV (decl1)->name
1865 && decl2->mode == dm_insn_reserv
1866 && DECL_INSN_RESERV (decl2)->name);
1867 return strcmp (DECL_INSN_RESERV (decl1)->name,
1868 DECL_INSN_RESERV (decl2)->name) == 0;
1871 /* The insn declaration table itself is represented by the following
1872 variable. The table does not contain insn reservation
1873 declarations. */
1874 static htab_t insn_decl_table;
1876 /* The function inserts insn declaration into the table. The function
1877 does nothing if an insn declaration with the same key exists
1878 already in the table. The function returns insn declaration node
1879 in the table with the same key as given insn declaration node. */
1880 static decl_t
1881 insert_insn_decl (decl_t insn_decl)
1883 void **entry_ptr;
1885 entry_ptr = htab_find_slot (insn_decl_table, insn_decl, 1);
1886 if (*entry_ptr == NULL)
1887 *entry_ptr = (void *) insn_decl;
1888 return (decl_t) *entry_ptr;
1891 /* The following variable value is node representing insn reservation
1892 declaration. The node used for searching insn reservation
1893 declaration with given name. */
1894 static struct decl work_insn_decl;
1896 /* The function searches for insn reservation declaration in the table
1897 with the same key as node representing name of the insn reservation
1898 declaration. The function returns node found in the table, NULL if
1899 such node does not exist in the table. */
1900 static decl_t
1901 find_insn_decl (const char *name)
1903 void *entry;
1905 work_insn_decl.mode = dm_insn_reserv;
1906 DECL_INSN_RESERV (&work_insn_decl)->name = name;
1907 entry = htab_find (insn_decl_table, &work_insn_decl);
1908 return (decl_t) entry;
1911 /* The function creates empty insn declaration table and node
1912 representing insn declaration and used for searching insn
1913 declaration with given name. The function must be called only once
1914 before any work with the insn declaration table. */
1915 static void
1916 initiate_insn_decl_table (void)
1918 work_insn_decl.mode = dm_insn_reserv;
1919 insn_decl_table = htab_create (10, insn_decl_hash, insn_decl_eq_p,
1920 (htab_del) 0);
1923 /* The function deletes the insn declaration table. Only call of
1924 function `initiate_insn_decl_table' is possible immediately after
1925 this function call. */
1926 static void
1927 finish_insn_decl_table (void)
1929 htab_delete (insn_decl_table);
1934 /* This page contains abstract data `table of declarations'. Elements
1935 of the table is nodes representing declarations (of units and
1936 reservations). Key of the table elements is names of given
1937 declarations. */
1939 /* The function evaluates hash value of a declaration. The function
1940 is used by abstract data `hashtab'. The function returns hash
1941 value (0..UINT_MAX) of given declaration. */
1942 static hashval_t
1943 decl_hash (const void *decl)
1945 const decl_t d = (const decl_t) decl;
1947 gcc_assert ((d->mode == dm_unit && DECL_UNIT (d)->name)
1948 || (d->mode == dm_reserv && DECL_RESERV (d)->name));
1949 return string_hash (d->mode == dm_unit
1950 ? DECL_UNIT (d)->name : DECL_RESERV (d)->name);
1953 /* The function tests declarations on equality of their keys. The
1954 function is used by abstract data 'hashtab'. The function
1955 returns 1 if the declarations have the same key, 0 otherwise. */
1956 static int
1957 decl_eq_p (const void *decl_1, const void *decl_2)
1959 const decl_t d1 = (const decl_t) decl_1;
1960 const decl_t d2 = (const decl_t) decl_2;
1962 gcc_assert ((d1->mode == dm_unit && DECL_UNIT (d1)->name)
1963 || (d1->mode == dm_reserv && DECL_RESERV (d1)->name));
1964 gcc_assert ((d2->mode == dm_unit && DECL_UNIT (d2)->name)
1965 || (d2->mode == dm_reserv && DECL_RESERV (d2)->name));
1966 return strcmp ((d1->mode == dm_unit
1967 ? DECL_UNIT (d1)->name : DECL_RESERV (d1)->name),
1968 (d2->mode == dm_unit
1969 ? DECL_UNIT (d2)->name : DECL_RESERV (d2)->name)) == 0;
1972 /* The declaration table itself is represented by the following
1973 variable. */
1974 static htab_t decl_table;
1976 /* The function inserts declaration into the table. The function does
1977 nothing if a declaration with the same key exists already in the
1978 table. The function returns declaration node in the table with the
1979 same key as given declaration node. */
1981 static decl_t
1982 insert_decl (decl_t decl)
1984 void **entry_ptr;
1986 entry_ptr = htab_find_slot (decl_table, decl, 1);
1987 if (*entry_ptr == NULL)
1988 *entry_ptr = (void *) decl;
1989 return (decl_t) *entry_ptr;
1992 /* The following variable value is node representing declaration. The
1993 node used for searching declaration with given name. */
1994 static struct decl work_decl;
1996 /* The function searches for declaration in the table with the same
1997 key as node representing name of the declaration. The function
1998 returns node found in the table, NULL if such node does not exist
1999 in the table. */
2000 static decl_t
2001 find_decl (const char *name)
2003 void *entry;
2005 work_decl.mode = dm_unit;
2006 DECL_UNIT (&work_decl)->name = name;
2007 entry = htab_find (decl_table, &work_decl);
2008 return (decl_t) entry;
2011 /* The function creates empty declaration table and node representing
2012 declaration and used for searching declaration with given name.
2013 The function must be called only once before any work with the
2014 declaration table. */
2015 static void
2016 initiate_decl_table (void)
2018 work_decl.mode = dm_unit;
2019 decl_table = htab_create (10, decl_hash, decl_eq_p, (htab_del) 0);
2022 /* The function deletes the declaration table. Only call of function
2023 `initiate_declaration_table' is possible immediately after this
2024 function call. */
2025 static void
2026 finish_decl_table (void)
2028 htab_delete (decl_table);
2033 /* This page contains checker of pipeline hazard description. */
2035 /* Checking NAMES in an exclusion clause vector and returning formed
2036 unit_set_el_list. */
2037 static unit_set_el_t
2038 process_excls (char **names, int num, pos_t excl_pos ATTRIBUTE_UNUSED)
2040 unit_set_el_t el_list;
2041 unit_set_el_t last_el;
2042 unit_set_el_t new_el;
2043 decl_t decl_in_table;
2044 int i;
2046 el_list = NULL;
2047 last_el = NULL;
2048 for (i = 0; i < num; i++)
2050 decl_in_table = find_decl (names [i]);
2051 if (decl_in_table == NULL)
2052 error ("unit `%s' in exclusion is not declared", names [i]);
2053 else if (decl_in_table->mode != dm_unit)
2054 error ("`%s' in exclusion is not unit", names [i]);
2055 else
2057 new_el = create_node (sizeof (struct unit_set_el));
2058 new_el->unit_decl = DECL_UNIT (decl_in_table);
2059 new_el->next_unit_set_el = NULL;
2060 if (last_el == NULL)
2061 el_list = last_el = new_el;
2062 else
2064 last_el->next_unit_set_el = new_el;
2065 last_el = last_el->next_unit_set_el;
2069 return el_list;
2072 /* The function adds each element from SOURCE_LIST to the exclusion
2073 list of the each element from DEST_LIST. Checking situation "unit
2074 excludes itself". */
2075 static void
2076 add_excls (unit_set_el_t dest_list, unit_set_el_t source_list,
2077 pos_t excl_pos ATTRIBUTE_UNUSED)
2079 unit_set_el_t dst;
2080 unit_set_el_t src;
2081 unit_set_el_t curr_el;
2082 unit_set_el_t prev_el;
2083 unit_set_el_t copy;
2085 for (dst = dest_list; dst != NULL; dst = dst->next_unit_set_el)
2086 for (src = source_list; src != NULL; src = src->next_unit_set_el)
2088 if (dst->unit_decl == src->unit_decl)
2090 error ("unit `%s' excludes itself", src->unit_decl->name);
2091 continue;
2093 if (dst->unit_decl->automaton_name != NULL
2094 && src->unit_decl->automaton_name != NULL
2095 && strcmp (dst->unit_decl->automaton_name,
2096 src->unit_decl->automaton_name) != 0)
2098 error ("units `%s' and `%s' in exclusion set belong to different automata",
2099 src->unit_decl->name, dst->unit_decl->name);
2100 continue;
2102 for (curr_el = dst->unit_decl->excl_list, prev_el = NULL;
2103 curr_el != NULL;
2104 prev_el = curr_el, curr_el = curr_el->next_unit_set_el)
2105 if (curr_el->unit_decl == src->unit_decl)
2106 break;
2107 if (curr_el == NULL)
2109 /* Element not found - insert. */
2110 copy = copy_node (src, sizeof (*src));
2111 copy->next_unit_set_el = NULL;
2112 if (prev_el == NULL)
2113 dst->unit_decl->excl_list = copy;
2114 else
2115 prev_el->next_unit_set_el = copy;
2120 /* Checking NAMES in presence/absence clause and returning the
2121 formed unit_set_el_list. The function is called only after
2122 processing all exclusion sets. */
2123 static unit_set_el_t
2124 process_presence_absence_names (char **names, int num,
2125 pos_t req_pos ATTRIBUTE_UNUSED,
2126 int presence_p, int final_p)
2128 unit_set_el_t el_list;
2129 unit_set_el_t last_el;
2130 unit_set_el_t new_el;
2131 decl_t decl_in_table;
2132 int i;
2134 el_list = NULL;
2135 last_el = NULL;
2136 for (i = 0; i < num; i++)
2138 decl_in_table = find_decl (names [i]);
2139 if (decl_in_table == NULL)
2140 error ((presence_p
2141 ? (final_p
2142 ? "unit `%s' in final presence set is not declared"
2143 : "unit `%s' in presence set is not declared")
2144 : (final_p
2145 ? "unit `%s' in final absence set is not declared"
2146 : "unit `%s' in absence set is not declared")), names [i]);
2147 else if (decl_in_table->mode != dm_unit)
2148 error ((presence_p
2149 ? (final_p
2150 ? "`%s' in final presence set is not unit"
2151 : "`%s' in presence set is not unit")
2152 : (final_p
2153 ? "`%s' in final absence set is not unit"
2154 : "`%s' in absence set is not unit")), names [i]);
2155 else
2157 new_el = create_node (sizeof (struct unit_set_el));
2158 new_el->unit_decl = DECL_UNIT (decl_in_table);
2159 new_el->next_unit_set_el = NULL;
2160 if (last_el == NULL)
2161 el_list = last_el = new_el;
2162 else
2164 last_el->next_unit_set_el = new_el;
2165 last_el = last_el->next_unit_set_el;
2169 return el_list;
2172 /* Checking NAMES in patterns of a presence/absence clause and
2173 returning the formed pattern_set_el_list. The function is called
2174 only after processing all exclusion sets. */
2175 static pattern_set_el_t
2176 process_presence_absence_patterns (char ***patterns, int num,
2177 pos_t req_pos ATTRIBUTE_UNUSED,
2178 int presence_p, int final_p)
2180 pattern_set_el_t el_list;
2181 pattern_set_el_t last_el;
2182 pattern_set_el_t new_el;
2183 decl_t decl_in_table;
2184 int i, j;
2186 el_list = NULL;
2187 last_el = NULL;
2188 for (i = 0; i < num; i++)
2190 for (j = 0; patterns [i] [j] != NULL; j++)
2192 new_el = create_node (sizeof (struct pattern_set_el)
2193 + sizeof (struct unit_decl *) * j);
2194 new_el->unit_decls
2195 = (struct unit_decl **) ((char *) new_el
2196 + sizeof (struct pattern_set_el));
2197 new_el->next_pattern_set_el = NULL;
2198 if (last_el == NULL)
2199 el_list = last_el = new_el;
2200 else
2202 last_el->next_pattern_set_el = new_el;
2203 last_el = last_el->next_pattern_set_el;
2205 new_el->units_num = 0;
2206 for (j = 0; patterns [i] [j] != NULL; j++)
2208 decl_in_table = find_decl (patterns [i] [j]);
2209 if (decl_in_table == NULL)
2210 error ((presence_p
2211 ? (final_p
2212 ? "unit `%s' in final presence set is not declared"
2213 : "unit `%s' in presence set is not declared")
2214 : (final_p
2215 ? "unit `%s' in final absence set is not declared"
2216 : "unit `%s' in absence set is not declared")),
2217 patterns [i] [j]);
2218 else if (decl_in_table->mode != dm_unit)
2219 error ((presence_p
2220 ? (final_p
2221 ? "`%s' in final presence set is not unit"
2222 : "`%s' in presence set is not unit")
2223 : (final_p
2224 ? "`%s' in final absence set is not unit"
2225 : "`%s' in absence set is not unit")),
2226 patterns [i] [j]);
2227 else
2229 new_el->unit_decls [new_el->units_num]
2230 = DECL_UNIT (decl_in_table);
2231 new_el->units_num++;
2235 return el_list;
2238 /* The function adds each element from PATTERN_LIST to presence (if
2239 PRESENCE_P) or absence list of the each element from DEST_LIST.
2240 Checking situations "unit requires own absence", and "unit excludes
2241 and requires presence of ...", "unit requires absence and presence
2242 of ...", "units in (final) presence set belong to different
2243 automata", and "units in (final) absence set belong to different
2244 automata". Remember that we process absence sets only after all
2245 presence sets. */
2246 static void
2247 add_presence_absence (unit_set_el_t dest_list,
2248 pattern_set_el_t pattern_list,
2249 pos_t req_pos ATTRIBUTE_UNUSED,
2250 int presence_p, int final_p)
2252 unit_set_el_t dst;
2253 pattern_set_el_t pat;
2254 struct unit_decl *unit;
2255 unit_set_el_t curr_excl_el;
2256 pattern_set_el_t curr_pat_el;
2257 pattern_set_el_t prev_el;
2258 pattern_set_el_t copy;
2259 int i;
2260 int no_error_flag;
2262 for (dst = dest_list; dst != NULL; dst = dst->next_unit_set_el)
2263 for (pat = pattern_list; pat != NULL; pat = pat->next_pattern_set_el)
2265 for (i = 0; i < pat->units_num; i++)
2267 unit = pat->unit_decls [i];
2268 if (dst->unit_decl == unit && pat->units_num == 1 && !presence_p)
2270 error ("unit `%s' requires own absence", unit->name);
2271 continue;
2273 if (dst->unit_decl->automaton_name != NULL
2274 && unit->automaton_name != NULL
2275 && strcmp (dst->unit_decl->automaton_name,
2276 unit->automaton_name) != 0)
2278 error ((presence_p
2279 ? (final_p
2280 ? "units `%s' and `%s' in final presence set belong to different automata"
2281 : "units `%s' and `%s' in presence set belong to different automata")
2282 : (final_p
2283 ? "units `%s' and `%s' in final absence set belong to different automata"
2284 : "units `%s' and `%s' in absence set belong to different automata")),
2285 unit->name, dst->unit_decl->name);
2286 continue;
2288 no_error_flag = 1;
2289 if (presence_p)
2290 for (curr_excl_el = dst->unit_decl->excl_list;
2291 curr_excl_el != NULL;
2292 curr_excl_el = curr_excl_el->next_unit_set_el)
2294 if (unit == curr_excl_el->unit_decl && pat->units_num == 1)
2296 if (!w_flag)
2298 error ("unit `%s' excludes and requires presence of `%s'",
2299 dst->unit_decl->name, unit->name);
2300 no_error_flag = 0;
2302 else
2303 warning
2304 (0, "unit `%s' excludes and requires presence of `%s'",
2305 dst->unit_decl->name, unit->name);
2308 else if (pat->units_num == 1)
2309 for (curr_pat_el = dst->unit_decl->presence_list;
2310 curr_pat_el != NULL;
2311 curr_pat_el = curr_pat_el->next_pattern_set_el)
2312 if (curr_pat_el->units_num == 1
2313 && unit == curr_pat_el->unit_decls [0])
2315 if (!w_flag)
2317 error
2318 ("unit `%s' requires absence and presence of `%s'",
2319 dst->unit_decl->name, unit->name);
2320 no_error_flag = 0;
2322 else
2323 warning
2324 (0, "unit `%s' requires absence and presence of `%s'",
2325 dst->unit_decl->name, unit->name);
2327 if (no_error_flag)
2329 for (prev_el = (presence_p
2330 ? (final_p
2331 ? dst->unit_decl->final_presence_list
2332 : dst->unit_decl->final_presence_list)
2333 : (final_p
2334 ? dst->unit_decl->final_absence_list
2335 : dst->unit_decl->absence_list));
2336 prev_el != NULL && prev_el->next_pattern_set_el != NULL;
2337 prev_el = prev_el->next_pattern_set_el)
2339 copy = copy_node (pat, sizeof (*pat));
2340 copy->next_pattern_set_el = NULL;
2341 if (prev_el == NULL)
2343 if (presence_p)
2345 if (final_p)
2346 dst->unit_decl->final_presence_list = copy;
2347 else
2348 dst->unit_decl->presence_list = copy;
2350 else if (final_p)
2351 dst->unit_decl->final_absence_list = copy;
2352 else
2353 dst->unit_decl->absence_list = copy;
2355 else
2356 prev_el->next_pattern_set_el = copy;
2363 /* The function searches for bypass with given IN_INSN_RESERV in given
2364 BYPASS_LIST. */
2365 static struct bypass_decl *
2366 find_bypass (struct bypass_decl *bypass_list,
2367 struct insn_reserv_decl *in_insn_reserv)
2369 struct bypass_decl *bypass;
2371 for (bypass = bypass_list; bypass != NULL; bypass = bypass->next)
2372 if (bypass->in_insn_reserv == in_insn_reserv)
2373 break;
2374 return bypass;
2377 /* The function processes pipeline description declarations, checks
2378 their correctness, and forms exclusion/presence/absence sets. */
2379 static void
2380 process_decls (void)
2382 decl_t decl;
2383 decl_t automaton_decl;
2384 decl_t decl_in_table;
2385 decl_t out_insn_reserv;
2386 decl_t in_insn_reserv;
2387 struct bypass_decl *bypass;
2388 int automaton_presence;
2389 int i;
2391 /* Checking repeated automata declarations. */
2392 automaton_presence = 0;
2393 for (i = 0; i < description->decls_num; i++)
2395 decl = description->decls [i];
2396 if (decl->mode == dm_automaton)
2398 automaton_presence = 1;
2399 decl_in_table = insert_automaton_decl (decl);
2400 if (decl_in_table != decl)
2402 if (!w_flag)
2403 error ("repeated declaration of automaton `%s'",
2404 DECL_AUTOMATON (decl)->name);
2405 else
2406 warning (0, "repeated declaration of automaton `%s'",
2407 DECL_AUTOMATON (decl)->name);
2411 /* Checking undeclared automata, repeated declarations (except for
2412 automata) and correctness of their attributes (insn latency times
2413 etc.). */
2414 for (i = 0; i < description->decls_num; i++)
2416 decl = description->decls [i];
2417 if (decl->mode == dm_insn_reserv)
2419 if (DECL_INSN_RESERV (decl)->default_latency < 0)
2420 error ("define_insn_reservation `%s' has negative latency time",
2421 DECL_INSN_RESERV (decl)->name);
2422 DECL_INSN_RESERV (decl)->insn_num = description->insns_num;
2423 description->insns_num++;
2424 decl_in_table = insert_insn_decl (decl);
2425 if (decl_in_table != decl)
2426 error ("`%s' is already used as insn reservation name",
2427 DECL_INSN_RESERV (decl)->name);
2429 else if (decl->mode == dm_bypass)
2431 if (DECL_BYPASS (decl)->latency < 0)
2432 error ("define_bypass `%s - %s' has negative latency time",
2433 DECL_BYPASS (decl)->out_insn_name,
2434 DECL_BYPASS (decl)->in_insn_name);
2436 else if (decl->mode == dm_unit || decl->mode == dm_reserv)
2438 if (decl->mode == dm_unit)
2440 DECL_UNIT (decl)->automaton_decl = NULL;
2441 if (DECL_UNIT (decl)->automaton_name != NULL)
2443 automaton_decl
2444 = find_automaton_decl (DECL_UNIT (decl)->automaton_name);
2445 if (automaton_decl == NULL)
2446 error ("automaton `%s' is not declared",
2447 DECL_UNIT (decl)->automaton_name);
2448 else
2450 DECL_AUTOMATON (automaton_decl)->automaton_is_used = 1;
2451 DECL_UNIT (decl)->automaton_decl
2452 = DECL_AUTOMATON (automaton_decl);
2455 else if (automaton_presence)
2456 error ("define_unit `%s' without automaton when one defined",
2457 DECL_UNIT (decl)->name);
2458 DECL_UNIT (decl)->unit_num = description->units_num;
2459 description->units_num++;
2460 if (strcmp (DECL_UNIT (decl)->name, NOTHING_NAME) == 0)
2462 error ("`%s' is declared as cpu unit", NOTHING_NAME);
2463 continue;
2465 decl_in_table = find_decl (DECL_UNIT (decl)->name);
2467 else
2469 if (strcmp (DECL_RESERV (decl)->name, NOTHING_NAME) == 0)
2471 error ("`%s' is declared as cpu reservation", NOTHING_NAME);
2472 continue;
2474 decl_in_table = find_decl (DECL_RESERV (decl)->name);
2476 if (decl_in_table == NULL)
2477 decl_in_table = insert_decl (decl);
2478 else
2480 if (decl->mode == dm_unit)
2481 error ("repeated declaration of unit `%s'",
2482 DECL_UNIT (decl)->name);
2483 else
2484 error ("repeated declaration of reservation `%s'",
2485 DECL_RESERV (decl)->name);
2489 /* Check bypasses and form list of bypasses for each (output)
2490 insn. */
2491 for (i = 0; i < description->decls_num; i++)
2493 decl = description->decls [i];
2494 if (decl->mode == dm_bypass)
2496 out_insn_reserv = find_insn_decl (DECL_BYPASS (decl)->out_insn_name);
2497 in_insn_reserv = find_insn_decl (DECL_BYPASS (decl)->in_insn_name);
2498 if (out_insn_reserv == NULL)
2499 error ("there is no insn reservation `%s'",
2500 DECL_BYPASS (decl)->out_insn_name);
2501 else if (in_insn_reserv == NULL)
2502 error ("there is no insn reservation `%s'",
2503 DECL_BYPASS (decl)->in_insn_name);
2504 else
2506 DECL_BYPASS (decl)->out_insn_reserv
2507 = DECL_INSN_RESERV (out_insn_reserv);
2508 DECL_BYPASS (decl)->in_insn_reserv
2509 = DECL_INSN_RESERV (in_insn_reserv);
2510 bypass
2511 = find_bypass (DECL_INSN_RESERV (out_insn_reserv)->bypass_list,
2512 DECL_BYPASS (decl)->in_insn_reserv);
2513 if (bypass != NULL)
2515 if (DECL_BYPASS (decl)->latency == bypass->latency)
2517 if (!w_flag)
2518 error
2519 ("the same bypass `%s - %s' is already defined",
2520 DECL_BYPASS (decl)->out_insn_name,
2521 DECL_BYPASS (decl)->in_insn_name);
2522 else
2523 warning
2524 (0, "the same bypass `%s - %s' is already defined",
2525 DECL_BYPASS (decl)->out_insn_name,
2526 DECL_BYPASS (decl)->in_insn_name);
2528 else
2529 error ("bypass `%s - %s' is already defined",
2530 DECL_BYPASS (decl)->out_insn_name,
2531 DECL_BYPASS (decl)->in_insn_name);
2533 else
2535 DECL_BYPASS (decl)->next
2536 = DECL_INSN_RESERV (out_insn_reserv)->bypass_list;
2537 DECL_INSN_RESERV (out_insn_reserv)->bypass_list
2538 = DECL_BYPASS (decl);
2544 /* Check exclusion set declarations and form exclusion sets. */
2545 for (i = 0; i < description->decls_num; i++)
2547 decl = description->decls [i];
2548 if (decl->mode == dm_excl)
2550 unit_set_el_t unit_set_el_list;
2551 unit_set_el_t unit_set_el_list_2;
2553 unit_set_el_list
2554 = process_excls (DECL_EXCL (decl)->names,
2555 DECL_EXCL (decl)->first_list_length, decl->pos);
2556 unit_set_el_list_2
2557 = process_excls (&DECL_EXCL (decl)->names
2558 [DECL_EXCL (decl)->first_list_length],
2559 DECL_EXCL (decl)->all_names_num
2560 - DECL_EXCL (decl)->first_list_length,
2561 decl->pos);
2562 add_excls (unit_set_el_list, unit_set_el_list_2, decl->pos);
2563 add_excls (unit_set_el_list_2, unit_set_el_list, decl->pos);
2567 /* Check presence set declarations and form presence sets. */
2568 for (i = 0; i < description->decls_num; i++)
2570 decl = description->decls [i];
2571 if (decl->mode == dm_presence)
2573 unit_set_el_t unit_set_el_list;
2574 pattern_set_el_t pattern_set_el_list;
2576 unit_set_el_list
2577 = process_presence_absence_names
2578 (DECL_PRESENCE (decl)->names, DECL_PRESENCE (decl)->names_num,
2579 decl->pos, TRUE, DECL_PRESENCE (decl)->final_p);
2580 pattern_set_el_list
2581 = process_presence_absence_patterns
2582 (DECL_PRESENCE (decl)->patterns,
2583 DECL_PRESENCE (decl)->patterns_num,
2584 decl->pos, TRUE, DECL_PRESENCE (decl)->final_p);
2585 add_presence_absence (unit_set_el_list, pattern_set_el_list,
2586 decl->pos, TRUE,
2587 DECL_PRESENCE (decl)->final_p);
2591 /* Check absence set declarations and form absence sets. */
2592 for (i = 0; i < description->decls_num; i++)
2594 decl = description->decls [i];
2595 if (decl->mode == dm_absence)
2597 unit_set_el_t unit_set_el_list;
2598 pattern_set_el_t pattern_set_el_list;
2600 unit_set_el_list
2601 = process_presence_absence_names
2602 (DECL_ABSENCE (decl)->names, DECL_ABSENCE (decl)->names_num,
2603 decl->pos, FALSE, DECL_ABSENCE (decl)->final_p);
2604 pattern_set_el_list
2605 = process_presence_absence_patterns
2606 (DECL_ABSENCE (decl)->patterns,
2607 DECL_ABSENCE (decl)->patterns_num,
2608 decl->pos, FALSE, DECL_ABSENCE (decl)->final_p);
2609 add_presence_absence (unit_set_el_list, pattern_set_el_list,
2610 decl->pos, FALSE,
2611 DECL_ABSENCE (decl)->final_p);
2616 /* The following function checks that declared automaton is used. If
2617 the automaton is not used, the function fixes error/warning. The
2618 following function must be called only after `process_decls'. */
2619 static void
2620 check_automaton_usage (void)
2622 decl_t decl;
2623 int i;
2625 for (i = 0; i < description->decls_num; i++)
2627 decl = description->decls [i];
2628 if (decl->mode == dm_automaton
2629 && !DECL_AUTOMATON (decl)->automaton_is_used)
2631 if (!w_flag)
2632 error ("automaton `%s' is not used", DECL_AUTOMATON (decl)->name);
2633 else
2634 warning (0, "automaton `%s' is not used",
2635 DECL_AUTOMATON (decl)->name);
2640 /* The following recursive function processes all regexp in order to
2641 fix usage of units or reservations and to fix errors of undeclared
2642 name. The function may change unit_regexp onto reserv_regexp.
2643 Remember that reserv_regexp does not exist before the function
2644 call. */
2645 static regexp_t
2646 process_regexp (regexp_t regexp)
2648 decl_t decl_in_table;
2649 regexp_t new_regexp;
2650 int i;
2652 switch (regexp->mode)
2654 case rm_unit:
2655 decl_in_table = find_decl (REGEXP_UNIT (regexp)->name);
2656 if (decl_in_table == NULL)
2657 error ("undeclared unit or reservation `%s'",
2658 REGEXP_UNIT (regexp)->name);
2659 else
2660 switch (decl_in_table->mode)
2662 case dm_unit:
2663 DECL_UNIT (decl_in_table)->unit_is_used = 1;
2664 REGEXP_UNIT (regexp)->unit_decl = DECL_UNIT (decl_in_table);
2665 break;
2667 case dm_reserv:
2668 DECL_RESERV (decl_in_table)->reserv_is_used = 1;
2669 new_regexp = create_node (sizeof (struct regexp));
2670 new_regexp->mode = rm_reserv;
2671 new_regexp->pos = regexp->pos;
2672 REGEXP_RESERV (new_regexp)->name = REGEXP_UNIT (regexp)->name;
2673 REGEXP_RESERV (new_regexp)->reserv_decl
2674 = DECL_RESERV (decl_in_table);
2675 regexp = new_regexp;
2676 break;
2678 default:
2679 gcc_unreachable ();
2681 break;
2682 case rm_sequence:
2683 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
2684 REGEXP_SEQUENCE (regexp)->regexps [i]
2685 = process_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
2686 break;
2687 case rm_allof:
2688 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
2689 REGEXP_ALLOF (regexp)->regexps [i]
2690 = process_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
2691 break;
2692 case rm_oneof:
2693 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
2694 REGEXP_ONEOF (regexp)->regexps [i]
2695 = process_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
2696 break;
2697 case rm_repeat:
2698 REGEXP_REPEAT (regexp)->regexp
2699 = process_regexp (REGEXP_REPEAT (regexp)->regexp);
2700 break;
2701 case rm_nothing:
2702 break;
2703 default:
2704 gcc_unreachable ();
2706 return regexp;
2709 /* The following function processes regexp of define_reservation and
2710 define_insn_reservation with the aid of function
2711 `process_regexp'. */
2712 static void
2713 process_regexp_decls (void)
2715 decl_t decl;
2716 int i;
2718 for (i = 0; i < description->decls_num; i++)
2720 decl = description->decls [i];
2721 if (decl->mode == dm_reserv)
2722 DECL_RESERV (decl)->regexp
2723 = process_regexp (DECL_RESERV (decl)->regexp);
2724 else if (decl->mode == dm_insn_reserv)
2725 DECL_INSN_RESERV (decl)->regexp
2726 = process_regexp (DECL_INSN_RESERV (decl)->regexp);
2730 /* The following function checks that declared unit is used. If the
2731 unit is not used, the function fixes errors/warnings. The
2732 following function must be called only after `process_decls',
2733 `process_regexp_decls'. */
2734 static void
2735 check_usage (void)
2737 decl_t decl;
2738 int i;
2740 for (i = 0; i < description->decls_num; i++)
2742 decl = description->decls [i];
2743 if (decl->mode == dm_unit && !DECL_UNIT (decl)->unit_is_used)
2745 if (!w_flag)
2746 error ("unit `%s' is not used", DECL_UNIT (decl)->name);
2747 else
2748 warning (0, "unit `%s' is not used", DECL_UNIT (decl)->name);
2750 else if (decl->mode == dm_reserv && !DECL_RESERV (decl)->reserv_is_used)
2752 if (!w_flag)
2753 error ("reservation `%s' is not used", DECL_RESERV (decl)->name);
2754 else
2755 warning (0, "reservation `%s' is not used", DECL_RESERV (decl)->name);
2760 /* The following variable value is number of reservation being
2761 processed on loop recognition. */
2762 static int curr_loop_pass_num;
2764 /* The following recursive function returns nonzero value if REGEXP
2765 contains given decl or reservations in given regexp refers for
2766 given decl. */
2767 static int
2768 loop_in_regexp (regexp_t regexp, decl_t start_decl)
2770 int i;
2772 if (regexp == NULL)
2773 return 0;
2774 switch (regexp->mode)
2776 case rm_unit:
2777 return 0;
2779 case rm_reserv:
2780 if (start_decl->mode == dm_reserv
2781 && REGEXP_RESERV (regexp)->reserv_decl == DECL_RESERV (start_decl))
2782 return 1;
2783 else if (REGEXP_RESERV (regexp)->reserv_decl->loop_pass_num
2784 == curr_loop_pass_num)
2785 /* declaration has been processed. */
2786 return 0;
2787 else
2789 REGEXP_RESERV (regexp)->reserv_decl->loop_pass_num
2790 = curr_loop_pass_num;
2791 return loop_in_regexp (REGEXP_RESERV (regexp)->reserv_decl->regexp,
2792 start_decl);
2795 case rm_sequence:
2796 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
2797 if (loop_in_regexp (REGEXP_SEQUENCE (regexp)->regexps [i], start_decl))
2798 return 1;
2799 return 0;
2801 case rm_allof:
2802 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
2803 if (loop_in_regexp (REGEXP_ALLOF (regexp)->regexps [i], start_decl))
2804 return 1;
2805 return 0;
2807 case rm_oneof:
2808 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
2809 if (loop_in_regexp (REGEXP_ONEOF (regexp)->regexps [i], start_decl))
2810 return 1;
2811 return 0;
2813 case rm_repeat:
2814 return loop_in_regexp (REGEXP_REPEAT (regexp)->regexp, start_decl);
2816 case rm_nothing:
2817 return 0;
2819 default:
2820 gcc_unreachable ();
2824 /* The following function fixes errors "cycle in definition ...". The
2825 function uses function `loop_in_regexp' for that. */
2826 static void
2827 check_loops_in_regexps (void)
2829 decl_t decl;
2830 int i;
2832 for (i = 0; i < description->decls_num; i++)
2834 decl = description->decls [i];
2835 if (decl->mode == dm_reserv)
2836 DECL_RESERV (decl)->loop_pass_num = 0;
2838 for (i = 0; i < description->decls_num; i++)
2840 decl = description->decls [i];
2841 curr_loop_pass_num = i;
2843 if (decl->mode == dm_reserv)
2845 DECL_RESERV (decl)->loop_pass_num = curr_loop_pass_num;
2846 if (loop_in_regexp (DECL_RESERV (decl)->regexp, decl))
2848 gcc_assert (DECL_RESERV (decl)->regexp);
2849 error ("cycle in definition of reservation `%s'",
2850 DECL_RESERV (decl)->name);
2856 /* The function recursively processes IR of reservation and defines
2857 max and min cycle for reservation of unit. */
2858 static void
2859 process_regexp_cycles (regexp_t regexp, int max_start_cycle,
2860 int min_start_cycle, int *max_finish_cycle,
2861 int *min_finish_cycle)
2863 int i;
2865 switch (regexp->mode)
2867 case rm_unit:
2868 if (REGEXP_UNIT (regexp)->unit_decl->max_occ_cycle_num < max_start_cycle)
2869 REGEXP_UNIT (regexp)->unit_decl->max_occ_cycle_num = max_start_cycle;
2870 if (REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num > min_start_cycle
2871 || REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num == -1)
2872 REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num = min_start_cycle;
2873 *max_finish_cycle = max_start_cycle;
2874 *min_finish_cycle = min_start_cycle;
2875 break;
2877 case rm_reserv:
2878 process_regexp_cycles (REGEXP_RESERV (regexp)->reserv_decl->regexp,
2879 max_start_cycle, min_start_cycle,
2880 max_finish_cycle, min_finish_cycle);
2881 break;
2883 case rm_repeat:
2884 for (i = 0; i < REGEXP_REPEAT (regexp)->repeat_num; i++)
2886 process_regexp_cycles (REGEXP_REPEAT (regexp)->regexp,
2887 max_start_cycle, min_start_cycle,
2888 max_finish_cycle, min_finish_cycle);
2889 max_start_cycle = *max_finish_cycle + 1;
2890 min_start_cycle = *min_finish_cycle + 1;
2892 break;
2894 case rm_sequence:
2895 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
2897 process_regexp_cycles (REGEXP_SEQUENCE (regexp)->regexps [i],
2898 max_start_cycle, min_start_cycle,
2899 max_finish_cycle, min_finish_cycle);
2900 max_start_cycle = *max_finish_cycle + 1;
2901 min_start_cycle = *min_finish_cycle + 1;
2903 break;
2905 case rm_allof:
2907 int max_cycle = 0;
2908 int min_cycle = 0;
2910 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
2912 process_regexp_cycles (REGEXP_ALLOF (regexp)->regexps [i],
2913 max_start_cycle, min_start_cycle,
2914 max_finish_cycle, min_finish_cycle);
2915 if (max_cycle < *max_finish_cycle)
2916 max_cycle = *max_finish_cycle;
2917 if (i == 0 || min_cycle > *min_finish_cycle)
2918 min_cycle = *min_finish_cycle;
2920 *max_finish_cycle = max_cycle;
2921 *min_finish_cycle = min_cycle;
2923 break;
2925 case rm_oneof:
2927 int max_cycle = 0;
2928 int min_cycle = 0;
2930 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
2932 process_regexp_cycles (REGEXP_ONEOF (regexp)->regexps [i],
2933 max_start_cycle, min_start_cycle,
2934 max_finish_cycle, min_finish_cycle);
2935 if (max_cycle < *max_finish_cycle)
2936 max_cycle = *max_finish_cycle;
2937 if (i == 0 || min_cycle > *min_finish_cycle)
2938 min_cycle = *min_finish_cycle;
2940 *max_finish_cycle = max_cycle;
2941 *min_finish_cycle = min_cycle;
2943 break;
2945 case rm_nothing:
2946 *max_finish_cycle = max_start_cycle;
2947 *min_finish_cycle = min_start_cycle;
2948 break;
2950 default:
2951 gcc_unreachable ();
2955 /* The following function is called only for correct program. The
2956 function defines max reservation of insns in cycles. */
2957 static void
2958 evaluate_max_reserv_cycles (void)
2960 int max_insn_cycles_num;
2961 int min_insn_cycles_num;
2962 decl_t decl;
2963 int i;
2965 description->max_insn_reserv_cycles = 0;
2966 for (i = 0; i < description->decls_num; i++)
2968 decl = description->decls [i];
2969 if (decl->mode == dm_insn_reserv)
2971 process_regexp_cycles (DECL_INSN_RESERV (decl)->regexp, 0, 0,
2972 &max_insn_cycles_num, &min_insn_cycles_num);
2973 if (description->max_insn_reserv_cycles < max_insn_cycles_num)
2974 description->max_insn_reserv_cycles = max_insn_cycles_num;
2977 description->max_insn_reserv_cycles++;
2980 /* The following function calls functions for checking all
2981 description. */
2982 static void
2983 check_all_description (void)
2985 process_decls ();
2986 check_automaton_usage ();
2987 process_regexp_decls ();
2988 check_usage ();
2989 check_loops_in_regexps ();
2990 if (!have_error)
2991 evaluate_max_reserv_cycles ();
2996 /* The page contains abstract data `ticker'. This data is used to
2997 report time of different phases of building automata. It is
2998 possibly to write a description for which automata will be built
2999 during several minutes even on fast machine. */
3001 /* The following function creates ticker and makes it active. */
3002 static ticker_t
3003 create_ticker (void)
3005 ticker_t ticker;
3007 ticker.modified_creation_time = get_run_time ();
3008 ticker.incremented_off_time = 0;
3009 return ticker;
3012 /* The following function switches off given ticker. */
3013 static void
3014 ticker_off (ticker_t *ticker)
3016 if (ticker->incremented_off_time == 0)
3017 ticker->incremented_off_time = get_run_time () + 1;
3020 /* The following function switches on given ticker. */
3021 static void
3022 ticker_on (ticker_t *ticker)
3024 if (ticker->incremented_off_time != 0)
3026 ticker->modified_creation_time
3027 += get_run_time () - ticker->incremented_off_time + 1;
3028 ticker->incremented_off_time = 0;
3032 /* The following function returns current time in milliseconds since
3033 the moment when given ticker was created. */
3034 static int
3035 active_time (ticker_t ticker)
3037 if (ticker.incremented_off_time != 0)
3038 return ticker.incremented_off_time - 1 - ticker.modified_creation_time;
3039 else
3040 return get_run_time () - ticker.modified_creation_time;
3043 /* The following function returns string representation of active time
3044 of given ticker. The result is string representation of seconds
3045 with accuracy of 1/100 second. Only result of the last call of the
3046 function exists. Therefore the following code is not correct
3048 printf ("parser time: %s\ngeneration time: %s\n",
3049 active_time_string (parser_ticker),
3050 active_time_string (generation_ticker));
3052 Correct code has to be the following
3054 printf ("parser time: %s\n", active_time_string (parser_ticker));
3055 printf ("generation time: %s\n",
3056 active_time_string (generation_ticker));
3059 static void
3060 print_active_time (FILE *f, ticker_t ticker)
3062 int msecs;
3064 msecs = active_time (ticker);
3065 fprintf (f, "%d.%06d", msecs / 1000000, msecs % 1000000);
3070 /* The following variable value is number of automaton which are
3071 really being created. This value is defined on the base of
3072 argument of option `-split'. If the variable has zero value the
3073 number of automata is defined by the constructions `%automaton'.
3074 This case occurs when option `-split' is absent or has zero
3075 argument. If constructions `define_automaton' is absent only one
3076 automaton is created. */
3077 static int automata_num;
3079 /* The following variable values are times of
3080 o transformation of regular expressions
3081 o building NDFA (DFA if !ndfa_flag)
3082 o NDFA -> DFA (simply the same automaton if !ndfa_flag)
3083 o DFA minimization
3084 o building insn equivalence classes
3085 o all previous ones
3086 o code output */
3087 static ticker_t transform_time;
3088 static ticker_t NDFA_time;
3089 static ticker_t NDFA_to_DFA_time;
3090 static ticker_t minimize_time;
3091 static ticker_t equiv_time;
3092 static ticker_t automaton_generation_time;
3093 static ticker_t output_time;
3095 /* The following variable values are times of
3096 all checking
3097 all generation
3098 all pipeline hazard translator work */
3099 static ticker_t check_time;
3100 static ticker_t generation_time;
3101 static ticker_t all_time;
3105 /* Pseudo insn decl which denotes advancing cycle. */
3106 static decl_t advance_cycle_insn_decl;
3107 static void
3108 add_advance_cycle_insn_decl (void)
3110 advance_cycle_insn_decl = create_node (sizeof (struct decl));
3111 advance_cycle_insn_decl->mode = dm_insn_reserv;
3112 advance_cycle_insn_decl->pos = no_pos;
3113 DECL_INSN_RESERV (advance_cycle_insn_decl)->regexp = NULL;
3114 DECL_INSN_RESERV (advance_cycle_insn_decl)->name = "$advance_cycle";
3115 DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num
3116 = description->insns_num;
3117 description->decls [description->decls_num] = advance_cycle_insn_decl;
3118 description->decls_num++;
3119 description->insns_num++;
3123 /* Abstract data `alternative states' which represents
3124 nondeterministic nature of the description (see comments for
3125 structures alt_state and state). */
3127 /* List of free states. */
3128 static alt_state_t first_free_alt_state;
3130 #ifndef NDEBUG
3131 /* The following variables is maximal number of allocated nodes
3132 alt_state. */
3133 static int allocated_alt_states_num = 0;
3134 #endif
3136 /* The following function returns free node alt_state. It may be new
3137 allocated node or node freed earlier. */
3138 static alt_state_t
3139 get_free_alt_state (void)
3141 alt_state_t result;
3143 if (first_free_alt_state != NULL)
3145 result = first_free_alt_state;
3146 first_free_alt_state = first_free_alt_state->next_alt_state;
3148 else
3150 #ifndef NDEBUG
3151 allocated_alt_states_num++;
3152 #endif
3153 result = create_node (sizeof (struct alt_state));
3155 result->state = NULL;
3156 result->next_alt_state = NULL;
3157 result->next_sorted_alt_state = NULL;
3158 return result;
3161 /* The function frees node ALT_STATE. */
3162 static void
3163 free_alt_state (alt_state_t alt_state)
3165 if (alt_state == NULL)
3166 return;
3167 alt_state->next_alt_state = first_free_alt_state;
3168 first_free_alt_state = alt_state;
3171 /* The function frees list started with node ALT_STATE_LIST. */
3172 static void
3173 free_alt_states (alt_state_t alt_states_list)
3175 alt_state_t curr_alt_state;
3176 alt_state_t next_alt_state;
3178 for (curr_alt_state = alt_states_list;
3179 curr_alt_state != NULL;
3180 curr_alt_state = next_alt_state)
3182 next_alt_state = curr_alt_state->next_alt_state;
3183 free_alt_state (curr_alt_state);
3187 /* The function compares unique numbers of alt states. */
3188 static int
3189 alt_state_cmp (const void *alt_state_ptr_1, const void *alt_state_ptr_2)
3191 if ((*(alt_state_t *) alt_state_ptr_1)->state->unique_num
3192 == (*(alt_state_t *) alt_state_ptr_2)->state->unique_num)
3193 return 0;
3194 else if ((*(alt_state_t *) alt_state_ptr_1)->state->unique_num
3195 < (*(alt_state_t *) alt_state_ptr_2)->state->unique_num)
3196 return -1;
3197 else
3198 return 1;
3201 /* The function sorts ALT_STATES_LIST and removes duplicated alt
3202 states from the list. The comparison key is alt state unique
3203 number. */
3205 static alt_state_t
3206 uniq_sort_alt_states (alt_state_t alt_states_list)
3208 alt_state_t curr_alt_state;
3209 VEC(alt_state_t,heap) *alt_states;
3210 size_t i;
3211 size_t prev_unique_state_ind;
3212 alt_state_t result;
3214 if (alt_states_list == 0)
3215 return 0;
3216 if (alt_states_list->next_alt_state == 0)
3217 return alt_states_list;
3219 alt_states = VEC_alloc (alt_state_t,heap, 150);
3220 for (curr_alt_state = alt_states_list;
3221 curr_alt_state != NULL;
3222 curr_alt_state = curr_alt_state->next_alt_state)
3223 VEC_safe_push (alt_state_t,heap, alt_states, curr_alt_state);
3225 qsort (VEC_address (alt_state_t, alt_states),
3226 VEC_length (alt_state_t, alt_states),
3227 sizeof (alt_state_t), alt_state_cmp);
3229 prev_unique_state_ind = 0;
3230 for (i = 1; i < VEC_length (alt_state_t, alt_states); i++)
3231 if (VEC_index (alt_state_t, alt_states, prev_unique_state_ind)->state
3232 != VEC_index (alt_state_t, alt_states, i)->state)
3234 prev_unique_state_ind++;
3235 VEC_replace (alt_state_t, alt_states, prev_unique_state_ind,
3236 VEC_index (alt_state_t, alt_states, i));
3238 VEC_truncate (alt_state_t, alt_states, prev_unique_state_ind + 1);
3240 for (i = 1; i < VEC_length (alt_state_t, alt_states); i++)
3241 VEC_index (alt_state_t, alt_states, i-1)->next_sorted_alt_state
3242 = VEC_index (alt_state_t, alt_states, i);
3243 VEC_last (alt_state_t, alt_states)->next_sorted_alt_state = 0;
3245 result = VEC_index (alt_state_t, alt_states, 0);
3247 VEC_free (alt_state_t,heap, alt_states);
3248 return result;
3251 /* The function checks equality of alt state lists. Remember that the
3252 lists must be already sorted by the previous function. */
3253 static int
3254 alt_states_eq (alt_state_t alt_states_1, alt_state_t alt_states_2)
3256 while (alt_states_1 != NULL && alt_states_2 != NULL
3257 && alt_state_cmp (&alt_states_1, &alt_states_2) == 0)
3259 alt_states_1 = alt_states_1->next_sorted_alt_state;
3260 alt_states_2 = alt_states_2->next_sorted_alt_state;
3262 return alt_states_1 == alt_states_2;
3265 /* Initialization of the abstract data. */
3266 static void
3267 initiate_alt_states (void)
3269 first_free_alt_state = NULL;
3272 /* Finishing work with the abstract data. */
3273 static void
3274 finish_alt_states (void)
3280 /* The page contains macros for work with bits strings. We could use
3281 standard gcc bitmap or sbitmap but it would result in difficulties
3282 of building canadian cross. */
3284 /* Set bit number bitno in the bit string. The macro is not side
3285 effect proof. */
3286 #define SET_BIT(bitstring, bitno) \
3287 (((char *) (bitstring)) [(bitno) / CHAR_BIT] |= 1 << (bitno) % CHAR_BIT)
3289 #define CLEAR_BIT(bitstring, bitno) \
3290 (((char *) (bitstring)) [(bitno) / CHAR_BIT] &= ~(1 << (bitno) % CHAR_BIT))
3292 /* Test if bit number bitno in the bitstring is set. The macro is not
3293 side effect proof. */
3294 #define TEST_BIT(bitstring, bitno) \
3295 (((char *) (bitstring)) [(bitno) / CHAR_BIT] >> (bitno) % CHAR_BIT & 1)
3299 /* This page contains abstract data `state'. */
3301 /* Maximal length of reservations in cycles (>= 1). */
3302 static int max_cycles_num;
3304 /* Number of set elements (see type set_el_t) needed for
3305 representation of one cycle reservation. It is depended on units
3306 number. */
3307 static int els_in_cycle_reserv;
3309 /* Number of set elements (see type set_el_t) needed for
3310 representation of maximal length reservation. Deterministic
3311 reservation is stored as set (bit string) of length equal to the
3312 variable value * number of bits in set_el_t. */
3313 static int els_in_reservs;
3315 /* Array of pointers to unit declarations. */
3316 static unit_decl_t *units_array;
3318 /* Temporary reservation of maximal length. */
3319 static reserv_sets_t temp_reserv;
3321 /* The state table itself is represented by the following variable. */
3322 static htab_t state_table;
3324 /* Linked list of free 'state' structures to be recycled. The
3325 next_equiv_class_state pointer is borrowed for a free list. */
3326 static state_t first_free_state;
3328 static int curr_unique_state_num;
3330 #ifndef NDEBUG
3331 /* The following variables is maximal number of allocated nodes
3332 `state'. */
3333 static int allocated_states_num = 0;
3334 #endif
3336 /* Allocate new reservation set. */
3337 static reserv_sets_t
3338 alloc_empty_reserv_sets (void)
3340 reserv_sets_t result;
3342 obstack_blank (&irp, els_in_reservs * sizeof (set_el_t));
3343 result = (reserv_sets_t) obstack_base (&irp);
3344 obstack_finish (&irp);
3345 memset (result, 0, els_in_reservs * sizeof (set_el_t));
3346 return result;
3349 /* Hash value of reservation set. */
3350 static unsigned
3351 reserv_sets_hash_value (reserv_sets_t reservs)
3353 set_el_t hash_value;
3354 unsigned result;
3355 int reservs_num, i;
3356 set_el_t *reserv_ptr;
3358 hash_value = 0;
3359 reservs_num = els_in_reservs;
3360 reserv_ptr = reservs;
3361 i = 0;
3362 while (reservs_num != 0)
3364 reservs_num--;
3365 hash_value += ((*reserv_ptr >> i)
3366 | (*reserv_ptr << (sizeof (set_el_t) * CHAR_BIT - i)));
3367 i++;
3368 if (i == sizeof (set_el_t) * CHAR_BIT)
3369 i = 0;
3370 reserv_ptr++;
3372 if (sizeof (set_el_t) <= sizeof (unsigned))
3373 return hash_value;
3374 result = 0;
3375 for (i = sizeof (set_el_t); i > 0; i -= sizeof (unsigned) - 1)
3377 result += (unsigned) hash_value;
3378 hash_value >>= (sizeof (unsigned) - 1) * CHAR_BIT;
3380 return result;
3383 /* Comparison of given reservation sets. */
3384 static int
3385 reserv_sets_cmp (reserv_sets_t reservs_1, reserv_sets_t reservs_2)
3387 int reservs_num;
3388 set_el_t *reserv_ptr_1;
3389 set_el_t *reserv_ptr_2;
3391 gcc_assert (reservs_1 && reservs_2);
3392 reservs_num = els_in_reservs;
3393 reserv_ptr_1 = reservs_1;
3394 reserv_ptr_2 = reservs_2;
3395 while (reservs_num != 0 && *reserv_ptr_1 == *reserv_ptr_2)
3397 reservs_num--;
3398 reserv_ptr_1++;
3399 reserv_ptr_2++;
3401 if (reservs_num == 0)
3402 return 0;
3403 else if (*reserv_ptr_1 < *reserv_ptr_2)
3404 return -1;
3405 else
3406 return 1;
3409 /* The function checks equality of the reservation sets. */
3410 static int
3411 reserv_sets_eq (reserv_sets_t reservs_1, reserv_sets_t reservs_2)
3413 return reserv_sets_cmp (reservs_1, reservs_2) == 0;
3416 /* Set up in the reservation set that unit with UNIT_NUM is used on
3417 CYCLE_NUM. */
3418 static void
3419 set_unit_reserv (reserv_sets_t reservs, int cycle_num, int unit_num)
3421 gcc_assert (cycle_num < max_cycles_num);
3422 SET_BIT (reservs, cycle_num * els_in_cycle_reserv
3423 * sizeof (set_el_t) * CHAR_BIT + unit_num);
3426 /* Set up in the reservation set RESERVS that unit with UNIT_NUM is
3427 used on CYCLE_NUM. */
3428 static int
3429 test_unit_reserv (reserv_sets_t reservs, int cycle_num, int unit_num)
3431 gcc_assert (cycle_num < max_cycles_num);
3432 return TEST_BIT (reservs, cycle_num * els_in_cycle_reserv
3433 * sizeof (set_el_t) * CHAR_BIT + unit_num);
3436 /* The function checks that the reservation sets are intersected,
3437 i.e. there is a unit reservation on a cycle in both reservation
3438 sets. */
3439 static int
3440 reserv_sets_are_intersected (reserv_sets_t operand_1,
3441 reserv_sets_t operand_2)
3443 set_el_t *el_ptr_1;
3444 set_el_t *el_ptr_2;
3445 set_el_t *cycle_ptr_1;
3446 set_el_t *cycle_ptr_2;
3448 gcc_assert (operand_1 && operand_2);
3449 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2;
3450 el_ptr_1 < operand_1 + els_in_reservs;
3451 el_ptr_1++, el_ptr_2++)
3452 if (*el_ptr_1 & *el_ptr_2)
3453 return 1;
3454 reserv_sets_or (temp_reserv, operand_1, operand_2);
3455 for (cycle_ptr_1 = operand_1, cycle_ptr_2 = operand_2;
3456 cycle_ptr_1 < operand_1 + els_in_reservs;
3457 cycle_ptr_1 += els_in_cycle_reserv, cycle_ptr_2 += els_in_cycle_reserv)
3459 for (el_ptr_1 = cycle_ptr_1, el_ptr_2 = get_excl_set (cycle_ptr_2);
3460 el_ptr_1 < cycle_ptr_1 + els_in_cycle_reserv;
3461 el_ptr_1++, el_ptr_2++)
3462 if (*el_ptr_1 & *el_ptr_2)
3463 return 1;
3464 if (!check_presence_pattern_sets (cycle_ptr_1, cycle_ptr_2, FALSE))
3465 return 1;
3466 if (!check_presence_pattern_sets (temp_reserv + (cycle_ptr_2
3467 - operand_2),
3468 cycle_ptr_2, TRUE))
3469 return 1;
3470 if (!check_absence_pattern_sets (cycle_ptr_1, cycle_ptr_2, FALSE))
3471 return 1;
3472 if (!check_absence_pattern_sets (temp_reserv + (cycle_ptr_2 - operand_2),
3473 cycle_ptr_2, TRUE))
3474 return 1;
3476 return 0;
3479 /* The function sets up RESULT bits by bits of OPERAND shifted on one
3480 cpu cycle. The remaining bits of OPERAND (representing the last
3481 cycle unit reservations) are not changed. */
3482 static void
3483 reserv_sets_shift (reserv_sets_t result, reserv_sets_t operand)
3485 int i;
3487 gcc_assert (result && operand && result != operand);
3488 for (i = els_in_cycle_reserv; i < els_in_reservs; i++)
3489 result [i - els_in_cycle_reserv] = operand [i];
3492 /* OR of the reservation sets. */
3493 static void
3494 reserv_sets_or (reserv_sets_t result, reserv_sets_t operand_1,
3495 reserv_sets_t operand_2)
3497 set_el_t *el_ptr_1;
3498 set_el_t *el_ptr_2;
3499 set_el_t *result_set_el_ptr;
3501 gcc_assert (result && operand_1 && operand_2);
3502 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2, result_set_el_ptr = result;
3503 el_ptr_1 < operand_1 + els_in_reservs;
3504 el_ptr_1++, el_ptr_2++, result_set_el_ptr++)
3505 *result_set_el_ptr = *el_ptr_1 | *el_ptr_2;
3508 /* AND of the reservation sets. */
3509 static void
3510 reserv_sets_and (reserv_sets_t result, reserv_sets_t operand_1,
3511 reserv_sets_t operand_2)
3513 set_el_t *el_ptr_1;
3514 set_el_t *el_ptr_2;
3515 set_el_t *result_set_el_ptr;
3517 gcc_assert (result && operand_1 && operand_2);
3518 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2, result_set_el_ptr = result;
3519 el_ptr_1 < operand_1 + els_in_reservs;
3520 el_ptr_1++, el_ptr_2++, result_set_el_ptr++)
3521 *result_set_el_ptr = *el_ptr_1 & *el_ptr_2;
3524 /* The function outputs string representation of units reservation on
3525 cycle START_CYCLE in the reservation set. The function uses repeat
3526 construction if REPETITION_NUM > 1. */
3527 static void
3528 output_cycle_reservs (FILE *f, reserv_sets_t reservs, int start_cycle,
3529 int repetition_num)
3531 int unit_num;
3532 int reserved_units_num;
3534 reserved_units_num = 0;
3535 for (unit_num = 0; unit_num < description->units_num; unit_num++)
3536 if (TEST_BIT (reservs, start_cycle * els_in_cycle_reserv
3537 * sizeof (set_el_t) * CHAR_BIT + unit_num))
3538 reserved_units_num++;
3539 gcc_assert (repetition_num > 0);
3540 if (repetition_num != 1 && reserved_units_num > 1)
3541 fprintf (f, "(");
3542 reserved_units_num = 0;
3543 for (unit_num = 0;
3544 unit_num < description->units_num;
3545 unit_num++)
3546 if (TEST_BIT (reservs, start_cycle * els_in_cycle_reserv
3547 * sizeof (set_el_t) * CHAR_BIT + unit_num))
3549 if (reserved_units_num != 0)
3550 fprintf (f, "+");
3551 reserved_units_num++;
3552 fprintf (f, "%s", units_array [unit_num]->name);
3554 if (reserved_units_num == 0)
3555 fprintf (f, NOTHING_NAME);
3556 gcc_assert (repetition_num > 0);
3557 if (repetition_num != 1 && reserved_units_num > 1)
3558 fprintf (f, ")");
3559 if (repetition_num != 1)
3560 fprintf (f, "*%d", repetition_num);
3563 /* The function outputs string representation of units reservation in
3564 the reservation set. */
3565 static void
3566 output_reserv_sets (FILE *f, reserv_sets_t reservs)
3568 int start_cycle = 0;
3569 int cycle;
3570 int repetition_num;
3572 repetition_num = 0;
3573 for (cycle = 0; cycle < max_cycles_num; cycle++)
3574 if (repetition_num == 0)
3576 repetition_num++;
3577 start_cycle = cycle;
3579 else if (memcmp
3580 ((char *) reservs + start_cycle * els_in_cycle_reserv
3581 * sizeof (set_el_t),
3582 (char *) reservs + cycle * els_in_cycle_reserv
3583 * sizeof (set_el_t),
3584 els_in_cycle_reserv * sizeof (set_el_t)) == 0)
3585 repetition_num++;
3586 else
3588 if (start_cycle != 0)
3589 fprintf (f, ", ");
3590 output_cycle_reservs (f, reservs, start_cycle, repetition_num);
3591 repetition_num = 1;
3592 start_cycle = cycle;
3594 if (start_cycle < max_cycles_num)
3596 if (start_cycle != 0)
3597 fprintf (f, ", ");
3598 output_cycle_reservs (f, reservs, start_cycle, repetition_num);
3602 /* The following function returns free node state for AUTOMATON. It
3603 may be new allocated node or node freed earlier. The function also
3604 allocates reservation set if WITH_RESERVS has nonzero value. */
3605 static state_t
3606 get_free_state (int with_reservs, automaton_t automaton)
3608 state_t result;
3610 gcc_assert (max_cycles_num > 0 && automaton);
3611 if (first_free_state)
3613 result = first_free_state;
3614 first_free_state = result->next_equiv_class_state;
3616 result->next_equiv_class_state = NULL;
3617 result->automaton = automaton;
3618 result->first_out_arc = NULL;
3619 result->it_was_placed_in_stack_for_NDFA_forming = 0;
3620 result->it_was_placed_in_stack_for_DFA_forming = 0;
3621 result->component_states = NULL;
3622 result->longest_path_length = UNDEFINED_LONGEST_PATH_LENGTH;
3624 else
3626 #ifndef NDEBUG
3627 allocated_states_num++;
3628 #endif
3629 result = create_node (sizeof (struct state));
3630 result->automaton = automaton;
3631 result->first_out_arc = NULL;
3632 result->unique_num = curr_unique_state_num;
3633 result->longest_path_length = UNDEFINED_LONGEST_PATH_LENGTH;
3634 curr_unique_state_num++;
3636 if (with_reservs)
3638 if (result->reservs == NULL)
3639 result->reservs = alloc_empty_reserv_sets ();
3640 else
3641 memset (result->reservs, 0, els_in_reservs * sizeof (set_el_t));
3643 return result;
3646 /* The function frees node STATE. */
3647 static void
3648 free_state (state_t state)
3650 free_alt_states (state->component_states);
3651 state->next_equiv_class_state = first_free_state;
3652 first_free_state = state;
3655 /* Hash value of STATE. If STATE represents deterministic state it is
3656 simply hash value of the corresponding reservation set. Otherwise
3657 it is formed from hash values of the component deterministic
3658 states. One more key is order number of state automaton. */
3659 static hashval_t
3660 state_hash (const void *state)
3662 unsigned int hash_value;
3663 alt_state_t alt_state;
3665 if (((state_t) state)->component_states == NULL)
3666 hash_value = reserv_sets_hash_value (((state_t) state)->reservs);
3667 else
3669 hash_value = 0;
3670 for (alt_state = ((state_t) state)->component_states;
3671 alt_state != NULL;
3672 alt_state = alt_state->next_sorted_alt_state)
3673 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
3674 | (hash_value << CHAR_BIT))
3675 + alt_state->state->unique_num);
3677 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
3678 | (hash_value << CHAR_BIT))
3679 + ((state_t) state)->automaton->automaton_order_num);
3680 return hash_value;
3683 /* Return nonzero value if the states are the same. */
3684 static int
3685 state_eq_p (const void *state_1, const void *state_2)
3687 alt_state_t alt_state_1;
3688 alt_state_t alt_state_2;
3690 if (((state_t) state_1)->automaton != ((state_t) state_2)->automaton)
3691 return 0;
3692 else if (((state_t) state_1)->component_states == NULL
3693 && ((state_t) state_2)->component_states == NULL)
3694 return reserv_sets_eq (((state_t) state_1)->reservs,
3695 ((state_t) state_2)->reservs);
3696 else if (((state_t) state_1)->component_states != NULL
3697 && ((state_t) state_2)->component_states != NULL)
3699 for (alt_state_1 = ((state_t) state_1)->component_states,
3700 alt_state_2 = ((state_t) state_2)->component_states;
3701 alt_state_1 != NULL && alt_state_2 != NULL;
3702 alt_state_1 = alt_state_1->next_sorted_alt_state,
3703 alt_state_2 = alt_state_2->next_sorted_alt_state)
3704 /* All state in the list must be already in the hash table.
3705 Also the lists must be sorted. */
3706 if (alt_state_1->state != alt_state_2->state)
3707 return 0;
3708 return alt_state_1 == alt_state_2;
3710 else
3711 return 0;
3714 /* Insert STATE into the state table. */
3715 static state_t
3716 insert_state (state_t state)
3718 void **entry_ptr;
3720 entry_ptr = htab_find_slot (state_table, (void *) state, 1);
3721 if (*entry_ptr == NULL)
3722 *entry_ptr = (void *) state;
3723 return (state_t) *entry_ptr;
3726 /* Add reservation of unit with UNIT_NUM on cycle CYCLE_NUM to
3727 deterministic STATE. */
3728 static void
3729 set_state_reserv (state_t state, int cycle_num, int unit_num)
3731 set_unit_reserv (state->reservs, cycle_num, unit_num);
3734 /* Return nonzero value if the deterministic states contains a
3735 reservation of the same cpu unit on the same cpu cycle. */
3736 static int
3737 intersected_state_reservs_p (state_t state1, state_t state2)
3739 gcc_assert (state1->automaton == state2->automaton);
3740 return reserv_sets_are_intersected (state1->reservs, state2->reservs);
3743 /* Return deterministic state (inserted into the table) which
3744 representing the automaton state which is union of reservations of
3745 the deterministic states masked by RESERVS. */
3746 static state_t
3747 states_union (state_t state1, state_t state2, reserv_sets_t reservs)
3749 state_t result;
3750 state_t state_in_table;
3752 gcc_assert (state1->automaton == state2->automaton);
3753 result = get_free_state (1, state1->automaton);
3754 reserv_sets_or (result->reservs, state1->reservs, state2->reservs);
3755 reserv_sets_and (result->reservs, result->reservs, reservs);
3756 state_in_table = insert_state (result);
3757 if (result != state_in_table)
3759 free_state (result);
3760 result = state_in_table;
3762 return result;
3765 /* Return deterministic state (inserted into the table) which
3766 represent the automaton state is obtained from deterministic STATE
3767 by advancing cpu cycle and masking by RESERVS. */
3768 static state_t
3769 state_shift (state_t state, reserv_sets_t reservs)
3771 state_t result;
3772 state_t state_in_table;
3774 result = get_free_state (1, state->automaton);
3775 reserv_sets_shift (result->reservs, state->reservs);
3776 reserv_sets_and (result->reservs, result->reservs, reservs);
3777 state_in_table = insert_state (result);
3778 if (result != state_in_table)
3780 free_state (result);
3781 result = state_in_table;
3783 return result;
3786 /* Initialization of the abstract data. */
3787 static void
3788 initiate_states (void)
3790 decl_t decl;
3791 int i;
3793 if (description->units_num)
3794 units_array = XNEWVEC (unit_decl_t, description->units_num);
3795 else
3796 units_array = 0;
3798 for (i = 0; i < description->decls_num; i++)
3800 decl = description->decls [i];
3801 if (decl->mode == dm_unit)
3802 units_array [DECL_UNIT (decl)->unit_num] = DECL_UNIT (decl);
3804 max_cycles_num = description->max_insn_reserv_cycles;
3805 els_in_cycle_reserv
3806 = ((description->units_num + sizeof (set_el_t) * CHAR_BIT - 1)
3807 / (sizeof (set_el_t) * CHAR_BIT));
3808 els_in_reservs = els_in_cycle_reserv * max_cycles_num;
3809 curr_unique_state_num = 0;
3810 initiate_alt_states ();
3811 state_table = htab_create (1500, state_hash, state_eq_p, (htab_del) 0);
3812 temp_reserv = alloc_empty_reserv_sets ();
3815 /* Finishing work with the abstract data. */
3816 static void
3817 finish_states (void)
3819 free (units_array);
3820 units_array = 0;
3821 htab_delete (state_table);
3822 first_free_state = NULL;
3823 finish_alt_states ();
3828 /* Abstract data `arcs'. */
3830 /* List of free arcs. */
3831 static arc_t first_free_arc;
3833 #ifndef NDEBUG
3834 /* The following variables is maximal number of allocated nodes
3835 `arc'. */
3836 static int allocated_arcs_num = 0;
3837 #endif
3839 /* The function frees node ARC. */
3840 static void
3841 free_arc (arc_t arc)
3843 arc->next_out_arc = first_free_arc;
3844 first_free_arc = arc;
3847 /* The function removes and frees ARC staring from FROM_STATE. */
3848 static void
3849 remove_arc (state_t from_state, arc_t arc)
3851 arc_t prev_arc;
3852 arc_t curr_arc;
3854 gcc_assert (arc);
3855 for (prev_arc = NULL, curr_arc = from_state->first_out_arc;
3856 curr_arc != NULL;
3857 prev_arc = curr_arc, curr_arc = curr_arc->next_out_arc)
3858 if (curr_arc == arc)
3859 break;
3860 gcc_assert (curr_arc);
3861 if (prev_arc == NULL)
3862 from_state->first_out_arc = arc->next_out_arc;
3863 else
3864 prev_arc->next_out_arc = arc->next_out_arc;
3865 free_arc (arc);
3868 /* The functions returns arc with given characteristics (or NULL if
3869 the arc does not exist). */
3870 static arc_t
3871 find_arc (state_t from_state, state_t to_state, ainsn_t insn)
3873 arc_t arc;
3875 for (arc = first_out_arc (from_state); arc != NULL; arc = next_out_arc (arc))
3876 if (arc->to_state == to_state && arc->insn == insn)
3877 return arc;
3878 return NULL;
3881 /* The function adds arc from FROM_STATE to TO_STATE marked by AINSN.
3882 The function returns added arc (or already existing arc). */
3883 static arc_t
3884 add_arc (state_t from_state, state_t to_state, ainsn_t ainsn)
3886 arc_t new_arc;
3888 new_arc = find_arc (from_state, to_state, ainsn);
3889 if (new_arc != NULL)
3890 return new_arc;
3891 if (first_free_arc == NULL)
3893 #ifndef NDEBUG
3894 allocated_arcs_num++;
3895 #endif
3896 new_arc = create_node (sizeof (struct arc));
3897 new_arc->to_state = NULL;
3898 new_arc->insn = NULL;
3899 new_arc->next_out_arc = NULL;
3901 else
3903 new_arc = first_free_arc;
3904 first_free_arc = first_free_arc->next_out_arc;
3906 new_arc->to_state = to_state;
3907 new_arc->insn = ainsn;
3908 ainsn->arc_exists_p = 1;
3909 new_arc->next_out_arc = from_state->first_out_arc;
3910 from_state->first_out_arc = new_arc;
3911 new_arc->next_arc_marked_by_insn = NULL;
3912 return new_arc;
3915 /* The function returns the first arc starting from STATE. */
3916 static arc_t
3917 first_out_arc (state_t state)
3919 return state->first_out_arc;
3922 /* The function returns next out arc after ARC. */
3923 static arc_t
3924 next_out_arc (arc_t arc)
3926 return arc->next_out_arc;
3929 /* Initialization of the abstract data. */
3930 static void
3931 initiate_arcs (void)
3933 first_free_arc = NULL;
3936 /* Finishing work with the abstract data. */
3937 static void
3938 finish_arcs (void)
3944 /* Abstract data `automata lists'. */
3946 /* List of free states. */
3947 static automata_list_el_t first_free_automata_list_el;
3949 /* The list being formed. */
3950 static automata_list_el_t current_automata_list;
3952 /* Hash table of automata lists. */
3953 static htab_t automata_list_table;
3955 /* The following function returns free automata list el. It may be
3956 new allocated node or node freed earlier. */
3957 static automata_list_el_t
3958 get_free_automata_list_el (void)
3960 automata_list_el_t result;
3962 if (first_free_automata_list_el != NULL)
3964 result = first_free_automata_list_el;
3965 first_free_automata_list_el
3966 = first_free_automata_list_el->next_automata_list_el;
3968 else
3969 result = create_node (sizeof (struct automata_list_el));
3970 result->automaton = NULL;
3971 result->next_automata_list_el = NULL;
3972 return result;
3975 /* The function frees node AUTOMATA_LIST_EL. */
3976 static void
3977 free_automata_list_el (automata_list_el_t automata_list_el)
3979 if (automata_list_el == NULL)
3980 return;
3981 automata_list_el->next_automata_list_el = first_free_automata_list_el;
3982 first_free_automata_list_el = automata_list_el;
3985 /* The function frees list AUTOMATA_LIST. */
3986 static void
3987 free_automata_list (automata_list_el_t automata_list)
3989 automata_list_el_t curr_automata_list_el;
3990 automata_list_el_t next_automata_list_el;
3992 for (curr_automata_list_el = automata_list;
3993 curr_automata_list_el != NULL;
3994 curr_automata_list_el = next_automata_list_el)
3996 next_automata_list_el = curr_automata_list_el->next_automata_list_el;
3997 free_automata_list_el (curr_automata_list_el);
4001 /* Hash value of AUTOMATA_LIST. */
4002 static hashval_t
4003 automata_list_hash (const void *automata_list)
4005 unsigned int hash_value;
4006 automata_list_el_t curr_automata_list_el;
4008 hash_value = 0;
4009 for (curr_automata_list_el = (automata_list_el_t) automata_list;
4010 curr_automata_list_el != NULL;
4011 curr_automata_list_el = curr_automata_list_el->next_automata_list_el)
4012 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
4013 | (hash_value << CHAR_BIT))
4014 + curr_automata_list_el->automaton->automaton_order_num);
4015 return hash_value;
4018 /* Return nonzero value if the automata_lists are the same. */
4019 static int
4020 automata_list_eq_p (const void *automata_list_1, const void *automata_list_2)
4022 automata_list_el_t automata_list_el_1;
4023 automata_list_el_t automata_list_el_2;
4025 for (automata_list_el_1 = (automata_list_el_t) automata_list_1,
4026 automata_list_el_2 = (automata_list_el_t) automata_list_2;
4027 automata_list_el_1 != NULL && automata_list_el_2 != NULL;
4028 automata_list_el_1 = automata_list_el_1->next_automata_list_el,
4029 automata_list_el_2 = automata_list_el_2->next_automata_list_el)
4030 if (automata_list_el_1->automaton != automata_list_el_2->automaton)
4031 return 0;
4032 return automata_list_el_1 == automata_list_el_2;
4035 /* Initialization of the abstract data. */
4036 static void
4037 initiate_automata_lists (void)
4039 first_free_automata_list_el = NULL;
4040 automata_list_table = htab_create (1500, automata_list_hash,
4041 automata_list_eq_p, (htab_del) 0);
4044 /* The following function starts new automata list and makes it the
4045 current one. */
4046 static void
4047 automata_list_start (void)
4049 current_automata_list = NULL;
4052 /* The following function adds AUTOMATON to the current list. */
4053 static void
4054 automata_list_add (automaton_t automaton)
4056 automata_list_el_t el;
4058 el = get_free_automata_list_el ();
4059 el->automaton = automaton;
4060 el->next_automata_list_el = current_automata_list;
4061 current_automata_list = el;
4064 /* The following function finishes forming the current list, inserts
4065 it into the table and returns it. */
4066 static automata_list_el_t
4067 automata_list_finish (void)
4069 void **entry_ptr;
4071 if (current_automata_list == NULL)
4072 return NULL;
4073 entry_ptr = htab_find_slot (automata_list_table,
4074 (void *) current_automata_list, 1);
4075 if (*entry_ptr == NULL)
4076 *entry_ptr = (void *) current_automata_list;
4077 else
4078 free_automata_list (current_automata_list);
4079 current_automata_list = NULL;
4080 return (automata_list_el_t) *entry_ptr;
4083 /* Finishing work with the abstract data. */
4084 static void
4085 finish_automata_lists (void)
4087 htab_delete (automata_list_table);
4092 /* The page contains abstract data for work with exclusion sets (see
4093 exclusion_set in file rtl.def). */
4095 /* The following variable refers to an exclusion set returned by
4096 get_excl_set. This is bit string of length equal to cpu units
4097 number. If exclusion set for given unit contains 1 for a unit,
4098 then simultaneous reservation of the units is prohibited. */
4099 static reserv_sets_t excl_set;
4101 /* The array contains exclusion sets for each unit. */
4102 static reserv_sets_t *unit_excl_set_table;
4104 /* The following function forms the array containing exclusion sets
4105 for each unit. */
4106 static void
4107 initiate_excl_sets (void)
4109 decl_t decl;
4110 reserv_sets_t unit_excl_set;
4111 unit_set_el_t el;
4112 int i;
4114 obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4115 excl_set = (reserv_sets_t) obstack_base (&irp);
4116 obstack_finish (&irp);
4117 obstack_blank (&irp, description->units_num * sizeof (reserv_sets_t));
4118 unit_excl_set_table = (reserv_sets_t *) obstack_base (&irp);
4119 obstack_finish (&irp);
4120 /* Evaluate unit exclusion sets. */
4121 for (i = 0; i < description->decls_num; i++)
4123 decl = description->decls [i];
4124 if (decl->mode == dm_unit)
4126 obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4127 unit_excl_set = (reserv_sets_t) obstack_base (&irp);
4128 obstack_finish (&irp);
4129 memset (unit_excl_set, 0, els_in_cycle_reserv * sizeof (set_el_t));
4130 for (el = DECL_UNIT (decl)->excl_list;
4131 el != NULL;
4132 el = el->next_unit_set_el)
4134 SET_BIT (unit_excl_set, el->unit_decl->unit_num);
4135 el->unit_decl->in_set_p = TRUE;
4137 unit_excl_set_table [DECL_UNIT (decl)->unit_num] = unit_excl_set;
4142 /* The function sets up and return EXCL_SET which is union of
4143 exclusion sets for each unit in IN_SET. */
4144 static reserv_sets_t
4145 get_excl_set (reserv_sets_t in_set)
4147 int excl_char_num;
4148 int chars_num;
4149 int i;
4150 int start_unit_num;
4151 int unit_num;
4153 chars_num = els_in_cycle_reserv * sizeof (set_el_t);
4154 memset (excl_set, 0, chars_num);
4155 for (excl_char_num = 0; excl_char_num < chars_num; excl_char_num++)
4156 if (((unsigned char *) in_set) [excl_char_num])
4157 for (i = CHAR_BIT - 1; i >= 0; i--)
4158 if ((((unsigned char *) in_set) [excl_char_num] >> i) & 1)
4160 start_unit_num = excl_char_num * CHAR_BIT + i;
4161 if (start_unit_num >= description->units_num)
4162 return excl_set;
4163 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4165 excl_set [unit_num]
4166 |= unit_excl_set_table [start_unit_num] [unit_num];
4169 return excl_set;
4174 /* The page contains abstract data for work with presence/absence
4175 pattern sets (see presence_set/absence_set in file rtl.def). */
4177 /* The following arrays contain correspondingly presence, final
4178 presence, absence, and final absence patterns for each unit. */
4179 static pattern_reserv_t *unit_presence_set_table;
4180 static pattern_reserv_t *unit_final_presence_set_table;
4181 static pattern_reserv_t *unit_absence_set_table;
4182 static pattern_reserv_t *unit_final_absence_set_table;
4184 /* The following function forms list of reservation sets for given
4185 PATTERN_LIST. */
4186 static pattern_reserv_t
4187 form_reserv_sets_list (pattern_set_el_t pattern_list)
4189 pattern_set_el_t el;
4190 pattern_reserv_t first, curr, prev;
4191 int i;
4193 prev = first = NULL;
4194 for (el = pattern_list; el != NULL; el = el->next_pattern_set_el)
4196 curr = create_node (sizeof (struct pattern_reserv));
4197 curr->reserv = alloc_empty_reserv_sets ();
4198 curr->next_pattern_reserv = NULL;
4199 for (i = 0; i < el->units_num; i++)
4201 SET_BIT (curr->reserv, el->unit_decls [i]->unit_num);
4202 el->unit_decls [i]->in_set_p = TRUE;
4204 if (prev != NULL)
4205 prev->next_pattern_reserv = curr;
4206 else
4207 first = curr;
4208 prev = curr;
4210 return first;
4213 /* The following function forms the array containing presence and
4214 absence pattern sets for each unit. */
4215 static void
4216 initiate_presence_absence_pattern_sets (void)
4218 decl_t decl;
4219 int i;
4221 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4222 unit_presence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4223 obstack_finish (&irp);
4224 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4225 unit_final_presence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4226 obstack_finish (&irp);
4227 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4228 unit_absence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4229 obstack_finish (&irp);
4230 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4231 unit_final_absence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4232 obstack_finish (&irp);
4233 /* Evaluate unit presence/absence sets. */
4234 for (i = 0; i < description->decls_num; i++)
4236 decl = description->decls [i];
4237 if (decl->mode == dm_unit)
4239 unit_presence_set_table [DECL_UNIT (decl)->unit_num]
4240 = form_reserv_sets_list (DECL_UNIT (decl)->presence_list);
4241 unit_final_presence_set_table [DECL_UNIT (decl)->unit_num]
4242 = form_reserv_sets_list (DECL_UNIT (decl)->final_presence_list);
4243 unit_absence_set_table [DECL_UNIT (decl)->unit_num]
4244 = form_reserv_sets_list (DECL_UNIT (decl)->absence_list);
4245 unit_final_absence_set_table [DECL_UNIT (decl)->unit_num]
4246 = form_reserv_sets_list (DECL_UNIT (decl)->final_absence_list);
4251 /* The function checks that CHECKED_SET satisfies all presence pattern
4252 sets for units in ORIGIONAL_SET. The function returns TRUE if it
4253 is ok. */
4254 static int
4255 check_presence_pattern_sets (reserv_sets_t checked_set,
4256 reserv_sets_t origional_set,
4257 int final_p)
4259 int char_num;
4260 int chars_num;
4261 int i;
4262 int start_unit_num;
4263 int unit_num;
4264 int presence_p;
4265 pattern_reserv_t pat_reserv;
4267 chars_num = els_in_cycle_reserv * sizeof (set_el_t);
4268 for (char_num = 0; char_num < chars_num; char_num++)
4269 if (((unsigned char *) origional_set) [char_num])
4270 for (i = CHAR_BIT - 1; i >= 0; i--)
4271 if ((((unsigned char *) origional_set) [char_num] >> i) & 1)
4273 start_unit_num = char_num * CHAR_BIT + i;
4274 if (start_unit_num >= description->units_num)
4275 break;
4276 if ((final_p
4277 && unit_final_presence_set_table [start_unit_num] == NULL)
4278 || (!final_p
4279 && unit_presence_set_table [start_unit_num] == NULL))
4280 continue;
4281 presence_p = FALSE;
4282 for (pat_reserv = (final_p
4283 ? unit_final_presence_set_table [start_unit_num]
4284 : unit_presence_set_table [start_unit_num]);
4285 pat_reserv != NULL;
4286 pat_reserv = pat_reserv->next_pattern_reserv)
4288 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4289 if ((checked_set [unit_num] & pat_reserv->reserv [unit_num])
4290 != pat_reserv->reserv [unit_num])
4291 break;
4292 presence_p = presence_p || unit_num >= els_in_cycle_reserv;
4294 if (!presence_p)
4295 return FALSE;
4297 return TRUE;
4300 /* The function checks that CHECKED_SET satisfies all absence pattern
4301 sets for units in ORIGIONAL_SET. The function returns TRUE if it
4302 is ok. */
4303 static int
4304 check_absence_pattern_sets (reserv_sets_t checked_set,
4305 reserv_sets_t origional_set,
4306 int final_p)
4308 int char_num;
4309 int chars_num;
4310 int i;
4311 int start_unit_num;
4312 int unit_num;
4313 pattern_reserv_t pat_reserv;
4315 chars_num = els_in_cycle_reserv * sizeof (set_el_t);
4316 for (char_num = 0; char_num < chars_num; char_num++)
4317 if (((unsigned char *) origional_set) [char_num])
4318 for (i = CHAR_BIT - 1; i >= 0; i--)
4319 if ((((unsigned char *) origional_set) [char_num] >> i) & 1)
4321 start_unit_num = char_num * CHAR_BIT + i;
4322 if (start_unit_num >= description->units_num)
4323 break;
4324 for (pat_reserv = (final_p
4325 ? unit_final_absence_set_table [start_unit_num]
4326 : unit_absence_set_table [start_unit_num]);
4327 pat_reserv != NULL;
4328 pat_reserv = pat_reserv->next_pattern_reserv)
4330 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4331 if ((checked_set [unit_num] & pat_reserv->reserv [unit_num])
4332 != pat_reserv->reserv [unit_num]
4333 && pat_reserv->reserv [unit_num])
4334 break;
4335 if (unit_num >= els_in_cycle_reserv)
4336 return FALSE;
4339 return TRUE;
4344 /* This page contains code for transformation of original reservations
4345 described in .md file. The main goal of transformations is
4346 simplifying reservation and lifting up all `|' on the top of IR
4347 reservation representation. */
4350 /* The following function makes copy of IR representation of
4351 reservation. The function also substitutes all reservations
4352 defined by define_reservation by corresponding value during making
4353 the copy. */
4354 static regexp_t
4355 copy_insn_regexp (regexp_t regexp)
4357 regexp_t result;
4358 int i;
4360 switch (regexp->mode)
4362 case rm_reserv:
4363 result = copy_insn_regexp (REGEXP_RESERV (regexp)->reserv_decl->regexp);
4364 break;
4366 case rm_unit:
4367 result = copy_node (regexp, sizeof (struct regexp));
4368 break;
4370 case rm_repeat:
4371 result = copy_node (regexp, sizeof (struct regexp));
4372 REGEXP_REPEAT (result)->regexp
4373 = copy_insn_regexp (REGEXP_REPEAT (regexp)->regexp);
4374 break;
4376 case rm_sequence:
4377 result = copy_node (regexp,
4378 sizeof (struct regexp) + sizeof (regexp_t)
4379 * (REGEXP_SEQUENCE (regexp)->regexps_num - 1));
4380 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4381 REGEXP_SEQUENCE (result)->regexps [i]
4382 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4383 break;
4385 case rm_allof:
4386 result = copy_node (regexp,
4387 sizeof (struct regexp) + sizeof (regexp_t)
4388 * (REGEXP_ALLOF (regexp)->regexps_num - 1));
4389 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4390 REGEXP_ALLOF (result)->regexps [i]
4391 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4392 break;
4394 case rm_oneof:
4395 result = copy_node (regexp,
4396 sizeof (struct regexp) + sizeof (regexp_t)
4397 * (REGEXP_ONEOF (regexp)->regexps_num - 1));
4398 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4399 REGEXP_ONEOF (result)->regexps [i]
4400 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4401 break;
4403 case rm_nothing:
4404 result = copy_node (regexp, sizeof (struct regexp));
4405 break;
4407 default:
4408 gcc_unreachable ();
4410 return result;
4413 /* The following variable is set up 1 if a transformation has been
4414 applied. */
4415 static int regexp_transformed_p;
4417 /* The function makes transformation
4418 A*N -> A, A, ... */
4419 static regexp_t
4420 transform_1 (regexp_t regexp)
4422 int i;
4423 int repeat_num;
4424 regexp_t operand;
4425 pos_t pos;
4427 if (regexp->mode == rm_repeat)
4429 repeat_num = REGEXP_REPEAT (regexp)->repeat_num;
4430 gcc_assert (repeat_num > 1);
4431 operand = REGEXP_REPEAT (regexp)->regexp;
4432 pos = regexp->mode;
4433 regexp = create_node (sizeof (struct regexp) + sizeof (regexp_t)
4434 * (repeat_num - 1));
4435 regexp->mode = rm_sequence;
4436 regexp->pos = pos;
4437 REGEXP_SEQUENCE (regexp)->regexps_num = repeat_num;
4438 for (i = 0; i < repeat_num; i++)
4439 REGEXP_SEQUENCE (regexp)->regexps [i] = copy_insn_regexp (operand);
4440 regexp_transformed_p = 1;
4442 return regexp;
4445 /* The function makes transformations
4446 ...,(A,B,...),C,... -> ...,A,B,...,C,...
4447 ...+(A+B+...)+C+... -> ...+A+B+...+C+...
4448 ...|(A|B|...)|C|... -> ...|A|B|...|C|... */
4449 static regexp_t
4450 transform_2 (regexp_t regexp)
4452 if (regexp->mode == rm_sequence)
4454 regexp_t sequence = NULL;
4455 regexp_t result;
4456 int sequence_index = 0;
4457 int i, j;
4459 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4460 if (REGEXP_SEQUENCE (regexp)->regexps [i]->mode == rm_sequence)
4462 sequence_index = i;
4463 sequence = REGEXP_SEQUENCE (regexp)->regexps [i];
4464 break;
4466 if (i < REGEXP_SEQUENCE (regexp)->regexps_num)
4468 gcc_assert (REGEXP_SEQUENCE (sequence)->regexps_num > 1
4469 && REGEXP_SEQUENCE (regexp)->regexps_num > 1);
4470 result = create_node (sizeof (struct regexp)
4471 + sizeof (regexp_t)
4472 * (REGEXP_SEQUENCE (regexp)->regexps_num
4473 + REGEXP_SEQUENCE (sequence)->regexps_num
4474 - 2));
4475 result->mode = rm_sequence;
4476 result->pos = regexp->pos;
4477 REGEXP_SEQUENCE (result)->regexps_num
4478 = (REGEXP_SEQUENCE (regexp)->regexps_num
4479 + REGEXP_SEQUENCE (sequence)->regexps_num - 1);
4480 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4481 if (i < sequence_index)
4482 REGEXP_SEQUENCE (result)->regexps [i]
4483 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4484 else if (i > sequence_index)
4485 REGEXP_SEQUENCE (result)->regexps
4486 [i + REGEXP_SEQUENCE (sequence)->regexps_num - 1]
4487 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4488 else
4489 for (j = 0; j < REGEXP_SEQUENCE (sequence)->regexps_num; j++)
4490 REGEXP_SEQUENCE (result)->regexps [i + j]
4491 = copy_insn_regexp (REGEXP_SEQUENCE (sequence)->regexps [j]);
4492 regexp_transformed_p = 1;
4493 regexp = result;
4496 else if (regexp->mode == rm_allof)
4498 regexp_t allof = NULL;
4499 regexp_t result;
4500 int allof_index = 0;
4501 int i, j;
4503 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4504 if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_allof)
4506 allof_index = i;
4507 allof = REGEXP_ALLOF (regexp)->regexps [i];
4508 break;
4510 if (i < REGEXP_ALLOF (regexp)->regexps_num)
4512 gcc_assert (REGEXP_ALLOF (allof)->regexps_num > 1
4513 && REGEXP_ALLOF (regexp)->regexps_num > 1);
4514 result = create_node (sizeof (struct regexp)
4515 + sizeof (regexp_t)
4516 * (REGEXP_ALLOF (regexp)->regexps_num
4517 + REGEXP_ALLOF (allof)->regexps_num - 2));
4518 result->mode = rm_allof;
4519 result->pos = regexp->pos;
4520 REGEXP_ALLOF (result)->regexps_num
4521 = (REGEXP_ALLOF (regexp)->regexps_num
4522 + REGEXP_ALLOF (allof)->regexps_num - 1);
4523 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4524 if (i < allof_index)
4525 REGEXP_ALLOF (result)->regexps [i]
4526 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4527 else if (i > allof_index)
4528 REGEXP_ALLOF (result)->regexps
4529 [i + REGEXP_ALLOF (allof)->regexps_num - 1]
4530 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4531 else
4532 for (j = 0; j < REGEXP_ALLOF (allof)->regexps_num; j++)
4533 REGEXP_ALLOF (result)->regexps [i + j]
4534 = copy_insn_regexp (REGEXP_ALLOF (allof)->regexps [j]);
4535 regexp_transformed_p = 1;
4536 regexp = result;
4539 else if (regexp->mode == rm_oneof)
4541 regexp_t oneof = NULL;
4542 regexp_t result;
4543 int oneof_index = 0;
4544 int i, j;
4546 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4547 if (REGEXP_ONEOF (regexp)->regexps [i]->mode == rm_oneof)
4549 oneof_index = i;
4550 oneof = REGEXP_ONEOF (regexp)->regexps [i];
4551 break;
4553 if (i < REGEXP_ONEOF (regexp)->regexps_num)
4555 gcc_assert (REGEXP_ONEOF (oneof)->regexps_num > 1
4556 && REGEXP_ONEOF (regexp)->regexps_num > 1);
4557 result = create_node (sizeof (struct regexp)
4558 + sizeof (regexp_t)
4559 * (REGEXP_ONEOF (regexp)->regexps_num
4560 + REGEXP_ONEOF (oneof)->regexps_num - 2));
4561 result->mode = rm_oneof;
4562 result->pos = regexp->pos;
4563 REGEXP_ONEOF (result)->regexps_num
4564 = (REGEXP_ONEOF (regexp)->regexps_num
4565 + REGEXP_ONEOF (oneof)->regexps_num - 1);
4566 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4567 if (i < oneof_index)
4568 REGEXP_ONEOF (result)->regexps [i]
4569 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4570 else if (i > oneof_index)
4571 REGEXP_ONEOF (result)->regexps
4572 [i + REGEXP_ONEOF (oneof)->regexps_num - 1]
4573 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4574 else
4575 for (j = 0; j < REGEXP_ONEOF (oneof)->regexps_num; j++)
4576 REGEXP_ONEOF (result)->regexps [i + j]
4577 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [j]);
4578 regexp_transformed_p = 1;
4579 regexp = result;
4582 return regexp;
4585 /* The function makes transformations
4586 ...,A|B|...,C,... -> (...,A,C,...)|(...,B,C,...)|...
4587 ...+(A|B|...)+C+... -> (...+A+C+...)|(...+B+C+...)|...
4588 ...+(A,B,...)+C+... -> (...+A+C+...),B,...
4589 ...+(A,B,...)+(C,D,...) -> (A+C),(B+D),... */
4590 static regexp_t
4591 transform_3 (regexp_t regexp)
4593 if (regexp->mode == rm_sequence)
4595 regexp_t oneof = NULL;
4596 int oneof_index = 0;
4597 regexp_t result;
4598 regexp_t sequence;
4599 int i, j;
4601 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4602 if (REGEXP_SEQUENCE (regexp)->regexps [i]->mode == rm_oneof)
4604 oneof_index = i;
4605 oneof = REGEXP_SEQUENCE (regexp)->regexps [i];
4606 break;
4608 if (i < REGEXP_SEQUENCE (regexp)->regexps_num)
4610 gcc_assert (REGEXP_ONEOF (oneof)->regexps_num > 1
4611 && REGEXP_SEQUENCE (regexp)->regexps_num > 1);
4612 result = create_node (sizeof (struct regexp)
4613 + sizeof (regexp_t)
4614 * (REGEXP_ONEOF (oneof)->regexps_num - 1));
4615 result->mode = rm_oneof;
4616 result->pos = regexp->pos;
4617 REGEXP_ONEOF (result)->regexps_num
4618 = REGEXP_ONEOF (oneof)->regexps_num;
4619 for (i = 0; i < REGEXP_ONEOF (result)->regexps_num; i++)
4621 sequence
4622 = create_node (sizeof (struct regexp)
4623 + sizeof (regexp_t)
4624 * (REGEXP_SEQUENCE (regexp)->regexps_num - 1));
4625 sequence->mode = rm_sequence;
4626 sequence->pos = regexp->pos;
4627 REGEXP_SEQUENCE (sequence)->regexps_num
4628 = REGEXP_SEQUENCE (regexp)->regexps_num;
4629 REGEXP_ONEOF (result)->regexps [i] = sequence;
4630 for (j = 0; j < REGEXP_SEQUENCE (sequence)->regexps_num; j++)
4631 if (j != oneof_index)
4632 REGEXP_SEQUENCE (sequence)->regexps [j]
4633 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [j]);
4634 else
4635 REGEXP_SEQUENCE (sequence)->regexps [j]
4636 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [i]);
4638 regexp_transformed_p = 1;
4639 regexp = result;
4642 else if (regexp->mode == rm_allof)
4644 regexp_t oneof = NULL;
4645 regexp_t seq;
4646 int oneof_index = 0;
4647 int max_seq_length, allof_length;
4648 regexp_t result;
4649 regexp_t allof = NULL;
4650 regexp_t allof_op = NULL;
4651 int i, j;
4653 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4654 if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_oneof)
4656 oneof_index = i;
4657 oneof = REGEXP_ALLOF (regexp)->regexps [i];
4658 break;
4660 if (i < REGEXP_ALLOF (regexp)->regexps_num)
4662 gcc_assert (REGEXP_ONEOF (oneof)->regexps_num > 1
4663 && REGEXP_ALLOF (regexp)->regexps_num > 1);
4664 result = create_node (sizeof (struct regexp)
4665 + sizeof (regexp_t)
4666 * (REGEXP_ONEOF (oneof)->regexps_num - 1));
4667 result->mode = rm_oneof;
4668 result->pos = regexp->pos;
4669 REGEXP_ONEOF (result)->regexps_num
4670 = REGEXP_ONEOF (oneof)->regexps_num;
4671 for (i = 0; i < REGEXP_ONEOF (result)->regexps_num; i++)
4673 allof
4674 = create_node (sizeof (struct regexp)
4675 + sizeof (regexp_t)
4676 * (REGEXP_ALLOF (regexp)->regexps_num - 1));
4677 allof->mode = rm_allof;
4678 allof->pos = regexp->pos;
4679 REGEXP_ALLOF (allof)->regexps_num
4680 = REGEXP_ALLOF (regexp)->regexps_num;
4681 REGEXP_ONEOF (result)->regexps [i] = allof;
4682 for (j = 0; j < REGEXP_ALLOF (allof)->regexps_num; j++)
4683 if (j != oneof_index)
4684 REGEXP_ALLOF (allof)->regexps [j]
4685 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [j]);
4686 else
4687 REGEXP_ALLOF (allof)->regexps [j]
4688 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [i]);
4690 regexp_transformed_p = 1;
4691 regexp = result;
4693 max_seq_length = 0;
4694 if (regexp->mode == rm_allof)
4695 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4697 switch (REGEXP_ALLOF (regexp)->regexps [i]->mode)
4699 case rm_sequence:
4700 seq = REGEXP_ALLOF (regexp)->regexps [i];
4701 if (max_seq_length < REGEXP_SEQUENCE (seq)->regexps_num)
4702 max_seq_length = REGEXP_SEQUENCE (seq)->regexps_num;
4703 break;
4705 case rm_unit:
4706 case rm_nothing:
4707 break;
4709 default:
4710 max_seq_length = 0;
4711 goto break_for;
4714 break_for:
4715 if (max_seq_length != 0)
4717 gcc_assert (max_seq_length != 1
4718 && REGEXP_ALLOF (regexp)->regexps_num > 1);
4719 result = create_node (sizeof (struct regexp)
4720 + sizeof (regexp_t) * (max_seq_length - 1));
4721 result->mode = rm_sequence;
4722 result->pos = regexp->pos;
4723 REGEXP_SEQUENCE (result)->regexps_num = max_seq_length;
4724 for (i = 0; i < max_seq_length; i++)
4726 allof_length = 0;
4727 for (j = 0; j < REGEXP_ALLOF (regexp)->regexps_num; j++)
4728 switch (REGEXP_ALLOF (regexp)->regexps [j]->mode)
4730 case rm_sequence:
4731 if (i < (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4732 ->regexps [j])->regexps_num))
4734 allof_op
4735 = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4736 ->regexps [j])
4737 ->regexps [i]);
4738 allof_length++;
4740 break;
4741 case rm_unit:
4742 case rm_nothing:
4743 if (i == 0)
4745 allof_op = REGEXP_ALLOF (regexp)->regexps [j];
4746 allof_length++;
4748 break;
4749 default:
4750 break;
4753 if (allof_length == 1)
4754 REGEXP_SEQUENCE (result)->regexps [i] = allof_op;
4755 else
4757 allof = create_node (sizeof (struct regexp)
4758 + sizeof (regexp_t)
4759 * (allof_length - 1));
4760 allof->mode = rm_allof;
4761 allof->pos = regexp->pos;
4762 REGEXP_ALLOF (allof)->regexps_num = allof_length;
4763 REGEXP_SEQUENCE (result)->regexps [i] = allof;
4764 allof_length = 0;
4765 for (j = 0; j < REGEXP_ALLOF (regexp)->regexps_num; j++)
4766 if (REGEXP_ALLOF (regexp)->regexps [j]->mode == rm_sequence
4767 && (i <
4768 (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4769 ->regexps [j])->regexps_num)))
4771 allof_op = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4772 ->regexps [j])
4773 ->regexps [i]);
4774 REGEXP_ALLOF (allof)->regexps [allof_length]
4775 = allof_op;
4776 allof_length++;
4778 else if (i == 0
4779 && (REGEXP_ALLOF (regexp)->regexps [j]->mode
4780 == rm_unit
4781 || (REGEXP_ALLOF (regexp)->regexps [j]->mode
4782 == rm_nothing)))
4784 allof_op = REGEXP_ALLOF (regexp)->regexps [j];
4785 REGEXP_ALLOF (allof)->regexps [allof_length]
4786 = allof_op;
4787 allof_length++;
4791 regexp_transformed_p = 1;
4792 regexp = result;
4795 return regexp;
4798 /* The function traverses IR of reservation and applies transformations
4799 implemented by FUNC. */
4800 static regexp_t
4801 regexp_transform_func (regexp_t regexp, regexp_t (*func) (regexp_t regexp))
4803 int i;
4805 switch (regexp->mode)
4807 case rm_sequence:
4808 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4809 REGEXP_SEQUENCE (regexp)->regexps [i]
4810 = regexp_transform_func (REGEXP_SEQUENCE (regexp)->regexps [i],
4811 func);
4812 break;
4814 case rm_allof:
4815 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4816 REGEXP_ALLOF (regexp)->regexps [i]
4817 = regexp_transform_func (REGEXP_ALLOF (regexp)->regexps [i], func);
4818 break;
4820 case rm_oneof:
4821 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4822 REGEXP_ONEOF (regexp)->regexps [i]
4823 = regexp_transform_func (REGEXP_ONEOF (regexp)->regexps [i], func);
4824 break;
4826 case rm_repeat:
4827 REGEXP_REPEAT (regexp)->regexp
4828 = regexp_transform_func (REGEXP_REPEAT (regexp)->regexp, func);
4829 break;
4831 case rm_nothing:
4832 case rm_unit:
4833 break;
4835 default:
4836 gcc_unreachable ();
4838 return (*func) (regexp);
4841 /* The function applies all transformations for IR representation of
4842 reservation REGEXP. */
4843 static regexp_t
4844 transform_regexp (regexp_t regexp)
4846 regexp = regexp_transform_func (regexp, transform_1);
4849 regexp_transformed_p = 0;
4850 regexp = regexp_transform_func (regexp, transform_2);
4851 regexp = regexp_transform_func (regexp, transform_3);
4853 while (regexp_transformed_p);
4854 return regexp;
4857 /* The function applies all transformations for reservations of all
4858 insn declarations. */
4859 static void
4860 transform_insn_regexps (void)
4862 decl_t decl;
4863 int i;
4865 transform_time = create_ticker ();
4866 add_advance_cycle_insn_decl ();
4867 if (progress_flag)
4868 fprintf (stderr, "Reservation transformation...");
4869 for (i = 0; i < description->decls_num; i++)
4871 decl = description->decls [i];
4872 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
4873 DECL_INSN_RESERV (decl)->transformed_regexp
4874 = transform_regexp (copy_insn_regexp
4875 (DECL_INSN_RESERV (decl)->regexp));
4877 if (progress_flag)
4878 fprintf (stderr, "done\n");
4879 ticker_off (&transform_time);
4884 /* The following variable value is TRUE if the first annotated message
4885 about units to automata distribution has been output. */
4886 static int annotation_message_reported_p;
4888 /* The following structure describes usage of a unit in a reservation. */
4889 struct unit_usage
4891 unit_decl_t unit_decl;
4892 /* The following forms a list of units used on the same cycle in the
4893 same alternative. */
4894 struct unit_usage *next;
4896 typedef struct unit_usage *unit_usage_t;
4898 DEF_VEC_P(unit_usage_t);
4899 DEF_VEC_ALLOC_P(unit_usage_t,heap);
4901 /* Obstack for unit_usage structures. */
4902 static struct obstack unit_usages;
4904 /* VLA for representation of array of pointers to unit usage
4905 structures. There is an element for each combination of
4906 (alternative number, cycle). Unit usages on given cycle in
4907 alternative with given number are referred through element with
4908 index equals to the cycle * number of all alternatives in the regexp
4909 + the alternative number. */
4910 static VEC(unit_usage_t,heap) *cycle_alt_unit_usages;
4912 /* The following function creates the structure unit_usage for UNIT on
4913 CYCLE in REGEXP alternative with ALT_NUM. The structure is made
4914 accessed through cycle_alt_unit_usages. */
4915 static void
4916 store_alt_unit_usage (regexp_t regexp, regexp_t unit, int cycle,
4917 int alt_num)
4919 size_t length;
4920 unit_decl_t unit_decl;
4921 unit_usage_t unit_usage_ptr;
4922 int index;
4924 gcc_assert (regexp && regexp->mode == rm_oneof
4925 && alt_num < REGEXP_ONEOF (regexp)->regexps_num);
4926 unit_decl = REGEXP_UNIT (unit)->unit_decl;
4928 length = (cycle + 1) * REGEXP_ONEOF (regexp)->regexps_num;
4929 while (VEC_length (unit_usage_t, cycle_alt_unit_usages) < length)
4930 VEC_safe_push (unit_usage_t,heap, cycle_alt_unit_usages, 0);
4932 obstack_blank (&unit_usages, sizeof (struct unit_usage));
4933 unit_usage_ptr = (struct unit_usage *) obstack_base (&unit_usages);
4934 obstack_finish (&unit_usages);
4935 unit_usage_ptr->unit_decl = unit_decl;
4936 index = cycle * REGEXP_ONEOF (regexp)->regexps_num + alt_num;
4937 unit_usage_ptr->next = VEC_index (unit_usage_t, cycle_alt_unit_usages, index);
4938 VEC_replace (unit_usage_t, cycle_alt_unit_usages, index, unit_usage_ptr);
4939 unit_decl->last_distribution_check_cycle = -1; /* undefined */
4942 /* The function processes given REGEXP to find units with the wrong
4943 distribution. */
4944 static void
4945 check_regexp_units_distribution (const char *insn_reserv_name,
4946 regexp_t regexp)
4948 int i, j, k, cycle;
4949 regexp_t seq, allof, unit;
4950 struct unit_usage *unit_usage_ptr, *other_unit_usage_ptr;
4952 if (regexp == NULL || regexp->mode != rm_oneof)
4953 return;
4954 /* Store all unit usages in the regexp: */
4955 obstack_init (&unit_usages);
4956 cycle_alt_unit_usages = 0;
4958 for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
4960 seq = REGEXP_ONEOF (regexp)->regexps [i];
4961 switch (seq->mode)
4963 case rm_sequence:
4964 for (j = 0; j < REGEXP_SEQUENCE (seq)->regexps_num; j++)
4966 allof = REGEXP_SEQUENCE (seq)->regexps [j];
4967 switch (allof->mode)
4969 case rm_allof:
4970 for (k = 0; k < REGEXP_ALLOF (allof)->regexps_num; k++)
4972 unit = REGEXP_ALLOF (allof)->regexps [k];
4973 if (unit->mode == rm_unit)
4974 store_alt_unit_usage (regexp, unit, j, i);
4975 else
4976 gcc_assert (unit->mode == rm_nothing);
4978 break;
4980 case rm_unit:
4981 store_alt_unit_usage (regexp, allof, j, i);
4982 break;
4984 case rm_nothing:
4985 break;
4987 default:
4988 gcc_unreachable ();
4991 break;
4993 case rm_allof:
4994 for (k = 0; k < REGEXP_ALLOF (seq)->regexps_num; k++)
4996 unit = REGEXP_ALLOF (seq)->regexps [k];
4997 switch (unit->mode)
4999 case rm_unit:
5000 store_alt_unit_usage (regexp, unit, 0, i);
5001 break;
5003 case rm_nothing:
5004 break;
5006 default:
5007 gcc_unreachable ();
5010 break;
5012 case rm_unit:
5013 store_alt_unit_usage (regexp, seq, 0, i);
5014 break;
5016 case rm_nothing:
5017 break;
5019 default:
5020 gcc_unreachable ();
5023 /* Check distribution: */
5024 for (i = 0; i < (int) VEC_length (unit_usage_t, cycle_alt_unit_usages); i++)
5026 cycle = i / REGEXP_ONEOF (regexp)->regexps_num;
5027 for (unit_usage_ptr = VEC_index (unit_usage_t, cycle_alt_unit_usages, i);
5028 unit_usage_ptr != NULL;
5029 unit_usage_ptr = unit_usage_ptr->next)
5030 if (cycle != unit_usage_ptr->unit_decl->last_distribution_check_cycle)
5032 unit_usage_ptr->unit_decl->last_distribution_check_cycle = cycle;
5033 for (k = cycle * REGEXP_ONEOF (regexp)->regexps_num;
5034 k < (int) VEC_length (unit_usage_t, cycle_alt_unit_usages)
5035 && k == cycle * REGEXP_ONEOF (regexp)->regexps_num;
5036 k++)
5038 for (other_unit_usage_ptr
5039 = VEC_index (unit_usage_t, cycle_alt_unit_usages, k);
5040 other_unit_usage_ptr != NULL;
5041 other_unit_usage_ptr = other_unit_usage_ptr->next)
5042 if (unit_usage_ptr->unit_decl->automaton_decl
5043 == other_unit_usage_ptr->unit_decl->automaton_decl)
5044 break;
5045 if (other_unit_usage_ptr == NULL
5046 && (VEC_index (unit_usage_t, cycle_alt_unit_usages, k)
5047 != NULL))
5048 break;
5050 if (k < (int) VEC_length (unit_usage_t, cycle_alt_unit_usages)
5051 && k == cycle * REGEXP_ONEOF (regexp)->regexps_num)
5053 if (!annotation_message_reported_p)
5055 fprintf (stderr, "\n");
5056 error ("The following units do not satisfy units-automata distribution rule");
5057 error (" (A unit of given unit automaton should be on each reserv. altern.)");
5058 annotation_message_reported_p = TRUE;
5060 error ("Unit %s, reserv. %s, cycle %d",
5061 unit_usage_ptr->unit_decl->name, insn_reserv_name,
5062 cycle);
5066 VEC_free (unit_usage_t,heap, cycle_alt_unit_usages);
5067 obstack_free (&unit_usages, NULL);
5070 /* The function finds units which violates units to automata
5071 distribution rule. If the units exist, report about them. */
5072 static void
5073 check_unit_distributions_to_automata (void)
5075 decl_t decl;
5076 int i;
5078 if (progress_flag)
5079 fprintf (stderr, "Check unit distributions to automata...");
5080 annotation_message_reported_p = FALSE;
5081 for (i = 0; i < description->decls_num; i++)
5083 decl = description->decls [i];
5084 if (decl->mode == dm_insn_reserv)
5085 check_regexp_units_distribution
5086 (DECL_INSN_RESERV (decl)->name,
5087 DECL_INSN_RESERV (decl)->transformed_regexp);
5089 if (progress_flag)
5090 fprintf (stderr, "done\n");
5095 /* The page contains code for building alt_states (see comments for
5096 IR) describing all possible insns reservations of an automaton. */
5098 /* Current state being formed for which the current alt_state
5099 refers. */
5100 static state_t state_being_formed;
5102 /* Current alt_state being formed. */
5103 static alt_state_t alt_state_being_formed;
5105 /* This recursive function processes `,' and units in reservation
5106 REGEXP for forming alt_states of AUTOMATON. It is believed that
5107 CURR_CYCLE is start cycle of all reservation REGEXP. */
5108 static int
5109 process_seq_for_forming_states (regexp_t regexp, automaton_t automaton,
5110 int curr_cycle)
5112 int i;
5114 if (regexp == NULL)
5115 return curr_cycle;
5117 switch (regexp->mode)
5119 case rm_unit:
5120 if (REGEXP_UNIT (regexp)->unit_decl->corresponding_automaton_num
5121 == automaton->automaton_order_num)
5122 set_state_reserv (state_being_formed, curr_cycle,
5123 REGEXP_UNIT (regexp)->unit_decl->unit_num);
5124 return curr_cycle;
5126 case rm_sequence:
5127 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
5128 curr_cycle
5129 = process_seq_for_forming_states
5130 (REGEXP_SEQUENCE (regexp)->regexps [i], automaton, curr_cycle) + 1;
5131 return curr_cycle;
5133 case rm_allof:
5135 int finish_cycle = 0;
5136 int cycle;
5138 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
5140 cycle = process_seq_for_forming_states (REGEXP_ALLOF (regexp)
5141 ->regexps [i],
5142 automaton, curr_cycle);
5143 if (finish_cycle < cycle)
5144 finish_cycle = cycle;
5146 return finish_cycle;
5149 case rm_nothing:
5150 return curr_cycle;
5152 default:
5153 gcc_unreachable ();
5157 /* This recursive function finishes forming ALT_STATE of AUTOMATON and
5158 inserts alt_state into the table. */
5159 static void
5160 finish_forming_alt_state (alt_state_t alt_state,
5161 automaton_t automaton ATTRIBUTE_UNUSED)
5163 state_t state_in_table;
5164 state_t corresponding_state;
5166 corresponding_state = alt_state->state;
5167 state_in_table = insert_state (corresponding_state);
5168 if (state_in_table != corresponding_state)
5170 free_state (corresponding_state);
5171 alt_state->state = state_in_table;
5175 /* The following variable value is current automaton insn for whose
5176 reservation the alt states are created. */
5177 static ainsn_t curr_ainsn;
5179 /* This recursive function processes `|' in reservation REGEXP for
5180 forming alt_states of AUTOMATON. List of the alt states should
5181 have the same order as in the description. */
5182 static void
5183 process_alts_for_forming_states (regexp_t regexp, automaton_t automaton,
5184 int inside_oneof_p)
5186 int i;
5188 if (regexp->mode != rm_oneof)
5190 alt_state_being_formed = get_free_alt_state ();
5191 state_being_formed = get_free_state (1, automaton);
5192 alt_state_being_formed->state = state_being_formed;
5193 /* We inserts in reverse order but we process alternatives also
5194 in reverse order. So we have the same order of alternative
5195 as in the description. */
5196 alt_state_being_formed->next_alt_state = curr_ainsn->alt_states;
5197 curr_ainsn->alt_states = alt_state_being_formed;
5198 (void) process_seq_for_forming_states (regexp, automaton, 0);
5199 finish_forming_alt_state (alt_state_being_formed, automaton);
5201 else
5203 gcc_assert (!inside_oneof_p);
5204 /* We processes it in reverse order to get list with the same
5205 order as in the description. See also the previous
5206 commentary. */
5207 for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
5208 process_alts_for_forming_states (REGEXP_ONEOF (regexp)->regexps [i],
5209 automaton, 1);
5213 /* Create nodes alt_state for all AUTOMATON insns. */
5214 static void
5215 create_alt_states (automaton_t automaton)
5217 struct insn_reserv_decl *reserv_decl;
5219 for (curr_ainsn = automaton->ainsn_list;
5220 curr_ainsn != NULL;
5221 curr_ainsn = curr_ainsn->next_ainsn)
5223 reserv_decl = curr_ainsn->insn_reserv_decl;
5224 if (reserv_decl != DECL_INSN_RESERV (advance_cycle_insn_decl))
5226 curr_ainsn->alt_states = NULL;
5227 process_alts_for_forming_states (reserv_decl->transformed_regexp,
5228 automaton, 0);
5229 curr_ainsn->sorted_alt_states
5230 = uniq_sort_alt_states (curr_ainsn->alt_states);
5237 /* The page contains major code for building DFA(s) for fast pipeline
5238 hazards recognition. */
5240 /* The function forms list of ainsns of AUTOMATON with the same
5241 reservation. */
5243 static void
5244 form_ainsn_with_same_reservs (automaton_t automaton)
5246 ainsn_t curr_ainsn;
5247 size_t i;
5248 VEC(ainsn_t,heap) *last_insns = VEC_alloc (ainsn_t,heap, 150);
5250 for (curr_ainsn = automaton->ainsn_list;
5251 curr_ainsn != NULL;
5252 curr_ainsn = curr_ainsn->next_ainsn)
5253 if (curr_ainsn->insn_reserv_decl
5254 == DECL_INSN_RESERV (advance_cycle_insn_decl))
5256 curr_ainsn->next_same_reservs_insn = NULL;
5257 curr_ainsn->first_insn_with_same_reservs = 1;
5259 else
5261 for (i = 0; i < VEC_length (ainsn_t, last_insns); i++)
5262 if (alt_states_eq
5263 (curr_ainsn->sorted_alt_states,
5264 VEC_index (ainsn_t, last_insns, i)->sorted_alt_states))
5265 break;
5266 curr_ainsn->next_same_reservs_insn = NULL;
5267 if (i < VEC_length (ainsn_t, last_insns))
5269 curr_ainsn->first_insn_with_same_reservs = 0;
5270 VEC_index (ainsn_t, last_insns, i)->next_same_reservs_insn
5271 = curr_ainsn;
5272 VEC_replace (ainsn_t, last_insns, i, curr_ainsn);
5274 else
5276 VEC_safe_push (ainsn_t, heap, last_insns, curr_ainsn);
5277 curr_ainsn->first_insn_with_same_reservs = 1;
5280 VEC_free (ainsn_t,heap, last_insns);
5283 /* Forming unit reservations which can affect creating the automaton
5284 states achieved from a given state. It permits to build smaller
5285 automata in many cases. We would have the same automata after
5286 the minimization without such optimization, but the automaton
5287 right after the building could be huge. So in other words, usage
5288 of reservs_matter means some minimization during building the
5289 automaton. */
5290 static reserv_sets_t
5291 form_reservs_matter (automaton_t automaton)
5293 int cycle, unit;
5294 reserv_sets_t reservs_matter = alloc_empty_reserv_sets();
5296 for (cycle = 0; cycle < max_cycles_num; cycle++)
5297 for (unit = 0; unit < description->units_num; unit++)
5298 if (units_array [unit]->automaton_decl
5299 == automaton->corresponding_automaton_decl
5300 && (cycle >= units_array [unit]->min_occ_cycle_num
5301 /* We can not remove queried unit from reservations. */
5302 || units_array [unit]->query_p
5303 /* We can not remove units which are used
5304 `exclusion_set', `presence_set',
5305 `final_presence_set', `absence_set', and
5306 `final_absence_set'. */
5307 || units_array [unit]->in_set_p))
5308 set_unit_reserv (reservs_matter, cycle, unit);
5309 return reservs_matter;
5312 /* The following function creates all states of nondeterministic AUTOMATON. */
5313 static void
5314 make_automaton (automaton_t automaton)
5316 ainsn_t ainsn;
5317 struct insn_reserv_decl *insn_reserv_decl;
5318 alt_state_t alt_state;
5319 state_t state;
5320 state_t start_state;
5321 state_t state2;
5322 ainsn_t advance_cycle_ainsn;
5323 arc_t added_arc;
5324 VEC(state_t,heap) *state_stack = VEC_alloc(state_t,heap, 150);
5325 int states_n;
5326 reserv_sets_t reservs_matter = form_reservs_matter (automaton);
5328 /* Create the start state (empty state). */
5329 start_state = insert_state (get_free_state (1, automaton));
5330 automaton->start_state = start_state;
5331 start_state->it_was_placed_in_stack_for_NDFA_forming = 1;
5332 VEC_safe_push (state_t,heap, state_stack, start_state);
5333 states_n = 1;
5334 while (VEC_length (state_t, state_stack) != 0)
5336 state = VEC_pop (state_t, state_stack);
5337 advance_cycle_ainsn = NULL;
5338 for (ainsn = automaton->ainsn_list;
5339 ainsn != NULL;
5340 ainsn = ainsn->next_ainsn)
5341 if (ainsn->first_insn_with_same_reservs)
5343 insn_reserv_decl = ainsn->insn_reserv_decl;
5344 if (insn_reserv_decl != DECL_INSN_RESERV (advance_cycle_insn_decl))
5346 /* We process alt_states in the same order as they are
5347 present in the description. */
5348 added_arc = NULL;
5349 for (alt_state = ainsn->alt_states;
5350 alt_state != NULL;
5351 alt_state = alt_state->next_alt_state)
5353 state2 = alt_state->state;
5354 if (!intersected_state_reservs_p (state, state2))
5356 state2 = states_union (state, state2, reservs_matter);
5357 if (!state2->it_was_placed_in_stack_for_NDFA_forming)
5359 state2->it_was_placed_in_stack_for_NDFA_forming
5360 = 1;
5361 VEC_safe_push (state_t,heap, state_stack, state2);
5362 states_n++;
5363 if (progress_flag && states_n % 100 == 0)
5364 fprintf (stderr, ".");
5366 added_arc = add_arc (state, state2, ainsn);
5367 if (!ndfa_flag)
5368 break;
5371 if (!ndfa_flag && added_arc != NULL)
5373 for (alt_state = ainsn->alt_states;
5374 alt_state != NULL;
5375 alt_state = alt_state->next_alt_state)
5376 state2 = alt_state->state;
5379 else
5380 advance_cycle_ainsn = ainsn;
5382 /* Add transition to advance cycle. */
5383 state2 = state_shift (state, reservs_matter);
5384 if (!state2->it_was_placed_in_stack_for_NDFA_forming)
5386 state2->it_was_placed_in_stack_for_NDFA_forming = 1;
5387 VEC_safe_push (state_t,heap, state_stack, state2);
5388 states_n++;
5389 if (progress_flag && states_n % 100 == 0)
5390 fprintf (stderr, ".");
5392 gcc_assert (advance_cycle_ainsn);
5393 add_arc (state, state2, advance_cycle_ainsn);
5395 VEC_free (state_t,heap, state_stack);
5398 /* Foms lists of all arcs of STATE marked by the same ainsn. */
5399 static void
5400 form_arcs_marked_by_insn (state_t state)
5402 decl_t decl;
5403 arc_t arc;
5404 int i;
5406 for (i = 0; i < description->decls_num; i++)
5408 decl = description->decls [i];
5409 if (decl->mode == dm_insn_reserv)
5410 DECL_INSN_RESERV (decl)->arcs_marked_by_insn = NULL;
5412 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5414 gcc_assert (arc->insn);
5415 arc->next_arc_marked_by_insn
5416 = arc->insn->insn_reserv_decl->arcs_marked_by_insn;
5417 arc->insn->insn_reserv_decl->arcs_marked_by_insn = arc;
5421 /* The function creates composed state (see comments for IR) from
5422 ORIGINAL_STATE and list of arcs ARCS_MARKED_BY_INSN marked by the
5423 same insn. If the composed state is not in STATE_STACK yet, it is
5424 pushed into STATE_STACK. */
5426 static int
5427 create_composed_state (state_t original_state, arc_t arcs_marked_by_insn,
5428 VEC(state_t,heap) **state_stack)
5430 state_t state;
5431 alt_state_t alt_state, curr_alt_state;
5432 alt_state_t new_alt_state;
5433 arc_t curr_arc;
5434 arc_t next_arc;
5435 state_t state_in_table;
5436 state_t temp_state;
5437 alt_state_t canonical_alt_states_list;
5438 int alts_number;
5439 int new_state_p = 0;
5441 if (arcs_marked_by_insn == NULL)
5442 return new_state_p;
5443 if (arcs_marked_by_insn->next_arc_marked_by_insn == NULL)
5444 state = arcs_marked_by_insn->to_state;
5445 else
5447 gcc_assert (ndfa_flag);
5448 /* Create composed state. */
5449 state = get_free_state (0, arcs_marked_by_insn->to_state->automaton);
5450 curr_alt_state = NULL;
5451 for (curr_arc = arcs_marked_by_insn;
5452 curr_arc != NULL;
5453 curr_arc = curr_arc->next_arc_marked_by_insn)
5454 if (curr_arc->to_state->component_states == NULL)
5456 new_alt_state = get_free_alt_state ();
5457 new_alt_state->next_alt_state = curr_alt_state;
5458 new_alt_state->state = curr_arc->to_state;
5459 curr_alt_state = new_alt_state;
5461 else
5462 for (alt_state = curr_arc->to_state->component_states;
5463 alt_state != NULL;
5464 alt_state = alt_state->next_sorted_alt_state)
5466 new_alt_state = get_free_alt_state ();
5467 new_alt_state->next_alt_state = curr_alt_state;
5468 new_alt_state->state = alt_state->state;
5469 gcc_assert (!alt_state->state->component_states);
5470 curr_alt_state = new_alt_state;
5472 /* There are not identical sets in the alt state list. */
5473 canonical_alt_states_list = uniq_sort_alt_states (curr_alt_state);
5474 if (canonical_alt_states_list->next_sorted_alt_state == NULL)
5476 temp_state = state;
5477 state = canonical_alt_states_list->state;
5478 free_state (temp_state);
5480 else
5482 state->component_states = canonical_alt_states_list;
5483 state_in_table = insert_state (state);
5484 if (state_in_table != state)
5486 gcc_assert
5487 (state_in_table->it_was_placed_in_stack_for_DFA_forming);
5488 free_state (state);
5489 state = state_in_table;
5491 else
5493 gcc_assert (!state->it_was_placed_in_stack_for_DFA_forming);
5494 new_state_p = 1;
5495 for (curr_alt_state = state->component_states;
5496 curr_alt_state != NULL;
5497 curr_alt_state = curr_alt_state->next_sorted_alt_state)
5498 for (curr_arc = first_out_arc (curr_alt_state->state);
5499 curr_arc != NULL;
5500 curr_arc = next_out_arc (curr_arc))
5501 add_arc (state, curr_arc->to_state, curr_arc->insn);
5503 arcs_marked_by_insn->to_state = state;
5504 for (alts_number = 0,
5505 curr_arc = arcs_marked_by_insn->next_arc_marked_by_insn;
5506 curr_arc != NULL;
5507 curr_arc = next_arc)
5509 next_arc = curr_arc->next_arc_marked_by_insn;
5510 remove_arc (original_state, curr_arc);
5511 alts_number++;
5515 if (!state->it_was_placed_in_stack_for_DFA_forming)
5517 state->it_was_placed_in_stack_for_DFA_forming = 1;
5518 VEC_safe_push (state_t,heap, *state_stack, state);
5520 return new_state_p;
5523 /* The function transforms nondeterministic AUTOMATON into
5524 deterministic. */
5526 static void
5527 NDFA_to_DFA (automaton_t automaton)
5529 state_t start_state;
5530 state_t state;
5531 decl_t decl;
5532 VEC(state_t,heap) *state_stack;
5533 int i;
5534 int states_n;
5536 state_stack = VEC_alloc (state_t,heap, 0);
5538 /* Create the start state (empty state). */
5539 start_state = automaton->start_state;
5540 start_state->it_was_placed_in_stack_for_DFA_forming = 1;
5541 VEC_safe_push (state_t,heap, state_stack, start_state);
5542 states_n = 1;
5543 while (VEC_length (state_t, state_stack) != 0)
5545 state = VEC_pop (state_t, state_stack);
5546 form_arcs_marked_by_insn (state);
5547 for (i = 0; i < description->decls_num; i++)
5549 decl = description->decls [i];
5550 if (decl->mode == dm_insn_reserv
5551 && create_composed_state
5552 (state, DECL_INSN_RESERV (decl)->arcs_marked_by_insn,
5553 &state_stack))
5555 states_n++;
5556 if (progress_flag && states_n % 100 == 0)
5557 fprintf (stderr, ".");
5561 VEC_free (state_t,heap, state_stack);
5564 /* The following variable value is current number (1, 2, ...) of passing
5565 graph of states. */
5566 static int curr_state_graph_pass_num;
5568 /* This recursive function passes all states achieved from START_STATE
5569 and applies APPLIED_FUNC to them. */
5570 static void
5571 pass_state_graph (state_t start_state, void (*applied_func) (state_t state))
5573 arc_t arc;
5575 if (start_state->pass_num == curr_state_graph_pass_num)
5576 return;
5577 start_state->pass_num = curr_state_graph_pass_num;
5578 (*applied_func) (start_state);
5579 for (arc = first_out_arc (start_state);
5580 arc != NULL;
5581 arc = next_out_arc (arc))
5582 pass_state_graph (arc->to_state, applied_func);
5585 /* This recursive function passes all states of AUTOMATON and applies
5586 APPLIED_FUNC to them. */
5587 static void
5588 pass_states (automaton_t automaton, void (*applied_func) (state_t state))
5590 curr_state_graph_pass_num++;
5591 pass_state_graph (automaton->start_state, applied_func);
5594 /* The function initializes code for passing of all states. */
5595 static void
5596 initiate_pass_states (void)
5598 curr_state_graph_pass_num = 0;
5601 /* The following vla is used for storing pointers to all achieved
5602 states. */
5603 static VEC(state_t,heap) *all_achieved_states;
5605 /* This function is called by function pass_states to add an achieved
5606 STATE. */
5607 static void
5608 add_achieved_state (state_t state)
5610 VEC_safe_push (state_t,heap, all_achieved_states, state);
5613 /* The function sets up equivalence numbers of insns which mark all
5614 out arcs of STATE by equiv_class_num_1 (if ODD_ITERATION_FLAG has
5615 nonzero value) or by equiv_class_num_2 of the destination state.
5616 The function returns number of out arcs of STATE. */
5617 static int
5618 set_out_arc_insns_equiv_num (state_t state, int odd_iteration_flag)
5620 int state_out_arcs_num;
5621 arc_t arc;
5623 state_out_arcs_num = 0;
5624 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5626 gcc_assert (!arc->insn->insn_reserv_decl->equiv_class_num);
5627 state_out_arcs_num++;
5628 arc->insn->insn_reserv_decl->equiv_class_num
5629 = (odd_iteration_flag
5630 ? arc->to_state->equiv_class_num_1
5631 : arc->to_state->equiv_class_num_2);
5632 gcc_assert (arc->insn->insn_reserv_decl->equiv_class_num);
5634 return state_out_arcs_num;
5637 /* The function clears equivalence numbers and alt_states in all insns
5638 which mark all out arcs of STATE. */
5639 static void
5640 clear_arc_insns_equiv_num (state_t state)
5642 arc_t arc;
5644 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5645 arc->insn->insn_reserv_decl->equiv_class_num = 0;
5649 /* The following function returns TRUE if STATE reserves the unit with
5650 UNIT_NUM on the first cycle. */
5651 static int
5652 first_cycle_unit_presence (state_t state, int unit_num)
5654 alt_state_t alt_state;
5656 if (state->component_states == NULL)
5657 return test_unit_reserv (state->reservs, 0, unit_num);
5658 else
5660 for (alt_state = state->component_states;
5661 alt_state != NULL;
5662 alt_state = alt_state->next_sorted_alt_state)
5663 if (test_unit_reserv (alt_state->state->reservs, 0, unit_num))
5664 return true;
5666 return false;
5669 /* The function returns nonzero value if STATE is not equivalent to
5670 ANOTHER_STATE from the same current partition on equivalence
5671 classes. Another state has ANOTHER_STATE_OUT_ARCS_NUM number of
5672 output arcs. Iteration of making equivalence partition is defined
5673 by ODD_ITERATION_FLAG. */
5674 static int
5675 state_is_differed (state_t state, state_t another_state,
5676 int another_state_out_arcs_num, int odd_iteration_flag)
5678 arc_t arc;
5679 int state_out_arcs_num;
5680 int i, presence1_p, presence2_p;
5682 state_out_arcs_num = 0;
5683 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5685 state_out_arcs_num++;
5686 if ((odd_iteration_flag
5687 ? arc->to_state->equiv_class_num_1
5688 : arc->to_state->equiv_class_num_2)
5689 != arc->insn->insn_reserv_decl->equiv_class_num)
5690 return 1;
5692 if (state_out_arcs_num != another_state_out_arcs_num)
5693 return 1;
5694 /* Now we are looking at the states with the point of view of query
5695 units. */
5696 for (i = 0; i < description->units_num; i++)
5697 if (units_array [i]->query_p)
5699 presence1_p = first_cycle_unit_presence (state, i);
5700 presence2_p = first_cycle_unit_presence (another_state, i);
5701 if ((presence1_p && !presence2_p) || (!presence1_p && presence2_p))
5702 return 1;
5704 return 0;
5707 /* The function makes initial partition of STATES on equivalent
5708 classes. */
5709 static state_t
5710 init_equiv_class (VEC(state_t,heap) *states)
5712 size_t i;
5713 state_t prev = 0;
5715 for (i = 0; i < VEC_length (state_t, states); i++)
5717 VEC_index (state_t, states, i)->equiv_class_num_1 = 1;
5718 VEC_index (state_t, states, i)->next_equiv_class_state = prev;
5719 prev = VEC_index (state_t, states, i);
5721 return prev;
5724 /* The function copies pointers to equivalent states from vla FROM
5725 into vla TO. */
5726 static void
5727 copy_equiv_class (VEC(state_t,heap) **to, VEC(state_t,heap) *from)
5729 VEC_free (state_t,heap, *to);
5730 *to = VEC_copy (state_t,heap, from);
5732 /* The function processes equivalence class given by its first state,
5733 FIRST_STATE, on odd iteration if ODD_ITERATION_FLAG. If there
5734 are not equivalent states, the function partitions the class
5735 removing nonequivalent states and placing them in
5736 *NEXT_ITERATION_CLASSES, increments *NEW_EQUIV_CLASS_NUM_PTR ans
5737 assigns it to the state equivalence number. If the class has been
5738 partitioned, the function returns nonzero value. */
5739 static int
5740 partition_equiv_class (state_t first_state, int odd_iteration_flag,
5741 VEC(state_t,heap) **next_iteration_classes,
5742 int *new_equiv_class_num_ptr)
5744 state_t new_equiv_class;
5745 int partition_p;
5746 state_t curr_state;
5747 state_t prev_state;
5748 state_t next_state;
5749 int out_arcs_num;
5751 partition_p = 0;
5753 while (first_state != NULL)
5755 new_equiv_class = NULL;
5756 if (first_state->next_equiv_class_state != NULL)
5758 /* There are more one states in the class equivalence. */
5759 out_arcs_num = set_out_arc_insns_equiv_num (first_state,
5760 odd_iteration_flag);
5761 for (prev_state = first_state,
5762 curr_state = first_state->next_equiv_class_state;
5763 curr_state != NULL;
5764 curr_state = next_state)
5766 next_state = curr_state->next_equiv_class_state;
5767 if (state_is_differed (curr_state, first_state, out_arcs_num,
5768 odd_iteration_flag))
5770 /* Remove curr state from the class equivalence. */
5771 prev_state->next_equiv_class_state = next_state;
5772 /* Add curr state to the new class equivalence. */
5773 curr_state->next_equiv_class_state = new_equiv_class;
5774 if (new_equiv_class == NULL)
5775 (*new_equiv_class_num_ptr)++;
5776 if (odd_iteration_flag)
5777 curr_state->equiv_class_num_2 = *new_equiv_class_num_ptr;
5778 else
5779 curr_state->equiv_class_num_1 = *new_equiv_class_num_ptr;
5780 new_equiv_class = curr_state;
5781 partition_p = 1;
5783 else
5784 prev_state = curr_state;
5786 clear_arc_insns_equiv_num (first_state);
5788 if (new_equiv_class != NULL)
5789 VEC_safe_push (state_t,heap, *next_iteration_classes, new_equiv_class);
5790 first_state = new_equiv_class;
5792 return partition_p;
5795 /* The function finds equivalent states of AUTOMATON. */
5796 static void
5797 evaluate_equiv_classes (automaton_t automaton,
5798 VEC(state_t,heap) **equiv_classes)
5800 state_t new_equiv_class;
5801 int new_equiv_class_num;
5802 int odd_iteration_flag;
5803 int finish_flag;
5804 VEC (state_t,heap) *next_iteration_classes;
5805 size_t i;
5807 all_achieved_states = VEC_alloc (state_t,heap, 1500);
5808 pass_states (automaton, add_achieved_state);
5809 new_equiv_class = init_equiv_class (all_achieved_states);
5810 odd_iteration_flag = 0;
5811 new_equiv_class_num = 1;
5813 next_iteration_classes = VEC_alloc (state_t,heap, 150);
5814 VEC_quick_push (state_t, next_iteration_classes, new_equiv_class);
5818 odd_iteration_flag = !odd_iteration_flag;
5819 finish_flag = 1;
5820 copy_equiv_class (equiv_classes, next_iteration_classes);
5822 /* Transfer equiv numbers for the next iteration. */
5823 for (i = 0; i < VEC_length (state_t, all_achieved_states); i++)
5824 if (odd_iteration_flag)
5825 VEC_index (state_t, all_achieved_states, i)->equiv_class_num_2
5826 = VEC_index (state_t, all_achieved_states, i)->equiv_class_num_1;
5827 else
5828 VEC_index (state_t, all_achieved_states, i)->equiv_class_num_1
5829 = VEC_index (state_t, all_achieved_states, i)->equiv_class_num_2;
5831 for (i = 0; i < VEC_length (state_t, *equiv_classes); i++)
5832 if (partition_equiv_class (VEC_index (state_t, *equiv_classes, i),
5833 odd_iteration_flag,
5834 &next_iteration_classes,
5835 &new_equiv_class_num))
5836 finish_flag = 0;
5838 while (!finish_flag);
5839 VEC_free (state_t,heap, next_iteration_classes);
5840 VEC_free (state_t,heap, all_achieved_states);
5843 /* The function merges equivalent states of AUTOMATON. */
5844 static void
5845 merge_states (automaton_t automaton, VEC(state_t,heap) *equiv_classes)
5847 state_t curr_state;
5848 state_t new_state;
5849 state_t first_class_state;
5850 alt_state_t alt_states;
5851 alt_state_t alt_state, new_alt_state;
5852 arc_t curr_arc;
5853 arc_t next_arc;
5854 size_t i;
5856 /* Create states corresponding to equivalence classes containing two
5857 or more states. */
5858 for (i = 0; i < VEC_length (state_t, equiv_classes); i++)
5860 curr_state = VEC_index (state_t, equiv_classes, i);
5861 if (curr_state->next_equiv_class_state != NULL)
5863 /* There are more one states in the class equivalence. */
5864 /* Create new compound state. */
5865 new_state = get_free_state (0, automaton);
5866 alt_states = NULL;
5867 first_class_state = curr_state;
5868 for (curr_state = first_class_state;
5869 curr_state != NULL;
5870 curr_state = curr_state->next_equiv_class_state)
5872 curr_state->equiv_class_state = new_state;
5873 if (curr_state->component_states == NULL)
5875 new_alt_state = get_free_alt_state ();
5876 new_alt_state->state = curr_state;
5877 new_alt_state->next_alt_state = alt_states;
5878 alt_states = new_alt_state;
5880 else
5881 for (alt_state = curr_state->component_states;
5882 alt_state != NULL;
5883 alt_state = alt_state->next_sorted_alt_state)
5885 new_alt_state = get_free_alt_state ();
5886 new_alt_state->state = alt_state->state;
5887 new_alt_state->next_alt_state = alt_states;
5888 alt_states = new_alt_state;
5891 /* Its is important that alt states were sorted before and
5892 after merging to have the same querying results. */
5893 new_state->component_states = uniq_sort_alt_states (alt_states);
5895 else
5896 curr_state->equiv_class_state = curr_state;
5899 for (i = 0; i < VEC_length (state_t, equiv_classes); i++)
5901 curr_state = VEC_index (state_t, equiv_classes, i);
5902 if (curr_state->next_equiv_class_state != NULL)
5904 first_class_state = curr_state;
5905 /* Create new arcs output from the state corresponding to
5906 equiv class. */
5907 for (curr_arc = first_out_arc (first_class_state);
5908 curr_arc != NULL;
5909 curr_arc = next_out_arc (curr_arc))
5910 add_arc (first_class_state->equiv_class_state,
5911 curr_arc->to_state->equiv_class_state,
5912 curr_arc->insn);
5913 /* Delete output arcs from states of given class equivalence. */
5914 for (curr_state = first_class_state;
5915 curr_state != NULL;
5916 curr_state = curr_state->next_equiv_class_state)
5918 if (automaton->start_state == curr_state)
5919 automaton->start_state = curr_state->equiv_class_state;
5920 /* Delete the state and its output arcs. */
5921 for (curr_arc = first_out_arc (curr_state);
5922 curr_arc != NULL;
5923 curr_arc = next_arc)
5925 next_arc = next_out_arc (curr_arc);
5926 free_arc (curr_arc);
5930 else
5932 /* Change `to_state' of arcs output from the state of given
5933 equivalence class. */
5934 for (curr_arc = first_out_arc (curr_state);
5935 curr_arc != NULL;
5936 curr_arc = next_out_arc (curr_arc))
5937 curr_arc->to_state = curr_arc->to_state->equiv_class_state;
5942 /* The function sets up new_cycle_p for states if there is arc to the
5943 state marked by advance_cycle_insn_decl. */
5944 static void
5945 set_new_cycle_flags (state_t state)
5947 arc_t arc;
5949 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5950 if (arc->insn->insn_reserv_decl
5951 == DECL_INSN_RESERV (advance_cycle_insn_decl))
5952 arc->to_state->new_cycle_p = 1;
5955 /* The top level function for minimization of deterministic
5956 AUTOMATON. */
5957 static void
5958 minimize_DFA (automaton_t automaton)
5960 VEC(state_t,heap) *equiv_classes = 0;
5962 evaluate_equiv_classes (automaton, &equiv_classes);
5963 merge_states (automaton, equiv_classes);
5964 pass_states (automaton, set_new_cycle_flags);
5966 VEC_free (state_t,heap, equiv_classes);
5969 /* Values of two variables are counted number of states and arcs in an
5970 automaton. */
5971 static int curr_counted_states_num;
5972 static int curr_counted_arcs_num;
5974 /* The function is called by function `pass_states' to count states
5975 and arcs of an automaton. */
5976 static void
5977 incr_states_and_arcs_nums (state_t state)
5979 arc_t arc;
5981 curr_counted_states_num++;
5982 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5983 curr_counted_arcs_num++;
5986 /* The function counts states and arcs of AUTOMATON. */
5987 static void
5988 count_states_and_arcs (automaton_t automaton, int *states_num,
5989 int *arcs_num)
5991 curr_counted_states_num = 0;
5992 curr_counted_arcs_num = 0;
5993 pass_states (automaton, incr_states_and_arcs_nums);
5994 *states_num = curr_counted_states_num;
5995 *arcs_num = curr_counted_arcs_num;
5998 /* The function builds one DFA AUTOMATON for fast pipeline hazards
5999 recognition after checking and simplifying IR of the
6000 description. */
6001 static void
6002 build_automaton (automaton_t automaton)
6004 int states_num;
6005 int arcs_num;
6007 ticker_on (&NDFA_time);
6008 if (progress_flag)
6010 if (automaton->corresponding_automaton_decl == NULL)
6011 fprintf (stderr, "Create anonymous automaton");
6012 else
6013 fprintf (stderr, "Create automaton `%s'",
6014 automaton->corresponding_automaton_decl->name);
6015 fprintf (stderr, " (1 dot is 100 new states):");
6017 make_automaton (automaton);
6018 if (progress_flag)
6019 fprintf (stderr, " done\n");
6020 ticker_off (&NDFA_time);
6021 count_states_and_arcs (automaton, &states_num, &arcs_num);
6022 automaton->NDFA_states_num = states_num;
6023 automaton->NDFA_arcs_num = arcs_num;
6024 ticker_on (&NDFA_to_DFA_time);
6025 if (progress_flag)
6027 if (automaton->corresponding_automaton_decl == NULL)
6028 fprintf (stderr, "Make anonymous DFA");
6029 else
6030 fprintf (stderr, "Make DFA `%s'",
6031 automaton->corresponding_automaton_decl->name);
6032 fprintf (stderr, " (1 dot is 100 new states):");
6034 NDFA_to_DFA (automaton);
6035 if (progress_flag)
6036 fprintf (stderr, " done\n");
6037 ticker_off (&NDFA_to_DFA_time);
6038 count_states_and_arcs (automaton, &states_num, &arcs_num);
6039 automaton->DFA_states_num = states_num;
6040 automaton->DFA_arcs_num = arcs_num;
6041 if (!no_minimization_flag)
6043 ticker_on (&minimize_time);
6044 if (progress_flag)
6046 if (automaton->corresponding_automaton_decl == NULL)
6047 fprintf (stderr, "Minimize anonymous DFA...");
6048 else
6049 fprintf (stderr, "Minimize DFA `%s'...",
6050 automaton->corresponding_automaton_decl->name);
6052 minimize_DFA (automaton);
6053 if (progress_flag)
6054 fprintf (stderr, "done\n");
6055 ticker_off (&minimize_time);
6056 count_states_and_arcs (automaton, &states_num, &arcs_num);
6057 automaton->minimal_DFA_states_num = states_num;
6058 automaton->minimal_DFA_arcs_num = arcs_num;
6064 /* The page contains code for enumeration of all states of an automaton. */
6066 /* Variable used for enumeration of all states of an automaton. Its
6067 value is current number of automaton states. */
6068 static int curr_state_order_num;
6070 /* The function is called by function `pass_states' for enumerating
6071 states. */
6072 static void
6073 set_order_state_num (state_t state)
6075 state->order_state_num = curr_state_order_num;
6076 curr_state_order_num++;
6079 /* The function enumerates all states of AUTOMATON. */
6080 static void
6081 enumerate_states (automaton_t automaton)
6083 curr_state_order_num = 0;
6084 pass_states (automaton, set_order_state_num);
6085 automaton->achieved_states_num = curr_state_order_num;
6090 /* The page contains code for finding equivalent automaton insns
6091 (ainsns). */
6093 /* The function inserts AINSN into cyclic list
6094 CYCLIC_EQUIV_CLASS_INSN_LIST of ainsns. */
6095 static ainsn_t
6096 insert_ainsn_into_equiv_class (ainsn_t ainsn,
6097 ainsn_t cyclic_equiv_class_insn_list)
6099 if (cyclic_equiv_class_insn_list == NULL)
6100 ainsn->next_equiv_class_insn = ainsn;
6101 else
6103 ainsn->next_equiv_class_insn
6104 = cyclic_equiv_class_insn_list->next_equiv_class_insn;
6105 cyclic_equiv_class_insn_list->next_equiv_class_insn = ainsn;
6107 return ainsn;
6110 /* The function deletes equiv_class_insn into cyclic list of
6111 equivalent ainsns. */
6112 static void
6113 delete_ainsn_from_equiv_class (ainsn_t equiv_class_insn)
6115 ainsn_t curr_equiv_class_insn;
6116 ainsn_t prev_equiv_class_insn;
6118 prev_equiv_class_insn = equiv_class_insn;
6119 for (curr_equiv_class_insn = equiv_class_insn->next_equiv_class_insn;
6120 curr_equiv_class_insn != equiv_class_insn;
6121 curr_equiv_class_insn = curr_equiv_class_insn->next_equiv_class_insn)
6122 prev_equiv_class_insn = curr_equiv_class_insn;
6123 if (prev_equiv_class_insn != equiv_class_insn)
6124 prev_equiv_class_insn->next_equiv_class_insn
6125 = equiv_class_insn->next_equiv_class_insn;
6128 /* The function processes AINSN of a state in order to find equivalent
6129 ainsns. INSN_ARCS_ARRAY is table: code of insn -> out arc of the
6130 state. */
6131 static void
6132 process_insn_equiv_class (ainsn_t ainsn, arc_t *insn_arcs_array)
6134 ainsn_t next_insn;
6135 ainsn_t curr_insn;
6136 ainsn_t cyclic_insn_list;
6137 arc_t arc;
6139 gcc_assert (insn_arcs_array [ainsn->insn_reserv_decl->insn_num]);
6140 curr_insn = ainsn;
6141 /* New class of ainsns which are not equivalent to given ainsn. */
6142 cyclic_insn_list = NULL;
6145 next_insn = curr_insn->next_equiv_class_insn;
6146 arc = insn_arcs_array [curr_insn->insn_reserv_decl->insn_num];
6147 if (arc == NULL
6148 || (insn_arcs_array [ainsn->insn_reserv_decl->insn_num]->to_state
6149 != arc->to_state))
6151 delete_ainsn_from_equiv_class (curr_insn);
6152 cyclic_insn_list = insert_ainsn_into_equiv_class (curr_insn,
6153 cyclic_insn_list);
6155 curr_insn = next_insn;
6157 while (curr_insn != ainsn);
6160 /* The function processes STATE in order to find equivalent ainsns. */
6161 static void
6162 process_state_for_insn_equiv_partition (state_t state)
6164 arc_t arc;
6165 arc_t *insn_arcs_array = XCNEWVEC (arc_t, description->insns_num);
6167 /* Process insns of the arcs. */
6168 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6169 insn_arcs_array [arc->insn->insn_reserv_decl->insn_num] = arc;
6170 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6171 process_insn_equiv_class (arc->insn, insn_arcs_array);
6173 free (insn_arcs_array);
6176 /* The function searches for equivalent ainsns of AUTOMATON. */
6177 static void
6178 set_insn_equiv_classes (automaton_t automaton)
6180 ainsn_t ainsn;
6181 ainsn_t first_insn;
6182 ainsn_t curr_insn;
6183 ainsn_t cyclic_insn_list;
6184 ainsn_t insn_with_same_reservs;
6185 int equiv_classes_num;
6187 /* All insns are included in one equivalence class. */
6188 cyclic_insn_list = NULL;
6189 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6190 if (ainsn->first_insn_with_same_reservs)
6191 cyclic_insn_list = insert_ainsn_into_equiv_class (ainsn,
6192 cyclic_insn_list);
6193 /* Process insns in order to make equivalence partition. */
6194 pass_states (automaton, process_state_for_insn_equiv_partition);
6195 /* Enumerate equiv classes. */
6196 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6197 /* Set undefined value. */
6198 ainsn->insn_equiv_class_num = -1;
6199 equiv_classes_num = 0;
6200 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6201 if (ainsn->insn_equiv_class_num < 0)
6203 first_insn = ainsn;
6204 gcc_assert (first_insn->first_insn_with_same_reservs);
6205 first_insn->first_ainsn_with_given_equivalence_num = 1;
6206 curr_insn = first_insn;
6209 for (insn_with_same_reservs = curr_insn;
6210 insn_with_same_reservs != NULL;
6211 insn_with_same_reservs
6212 = insn_with_same_reservs->next_same_reservs_insn)
6213 insn_with_same_reservs->insn_equiv_class_num = equiv_classes_num;
6214 curr_insn = curr_insn->next_equiv_class_insn;
6216 while (curr_insn != first_insn);
6217 equiv_classes_num++;
6219 automaton->insn_equiv_classes_num = equiv_classes_num;
6224 /* This page contains code for creating DFA(s) and calls functions
6225 building them. */
6228 /* The following value is used to prevent floating point overflow for
6229 estimating an automaton bound. The value should be less DBL_MAX on
6230 the host machine. We use here approximate minimum of maximal
6231 double floating point value required by ANSI C standard. It
6232 will work for non ANSI sun compiler too. */
6234 #define MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND 1.0E37
6236 /* The function estimate size of the single DFA used by PHR (pipeline
6237 hazards recognizer). */
6238 static double
6239 estimate_one_automaton_bound (void)
6241 decl_t decl;
6242 double one_automaton_estimation_bound;
6243 double root_value;
6244 int i;
6246 one_automaton_estimation_bound = 1.0;
6247 for (i = 0; i < description->decls_num; i++)
6249 decl = description->decls [i];
6250 if (decl->mode == dm_unit)
6252 root_value = exp (log (DECL_UNIT (decl)->max_occ_cycle_num
6253 - DECL_UNIT (decl)->min_occ_cycle_num + 1.0)
6254 / automata_num);
6255 if (MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND / root_value
6256 > one_automaton_estimation_bound)
6257 one_automaton_estimation_bound *= root_value;
6260 return one_automaton_estimation_bound;
6263 /* The function compares unit declarations according to their maximal
6264 cycle in reservations. */
6265 static int
6266 compare_max_occ_cycle_nums (const void *unit_decl_1,
6267 const void *unit_decl_2)
6269 if ((DECL_UNIT (*(decl_t *) unit_decl_1)->max_occ_cycle_num)
6270 < (DECL_UNIT (*(decl_t *) unit_decl_2)->max_occ_cycle_num))
6271 return 1;
6272 else if ((DECL_UNIT (*(decl_t *) unit_decl_1)->max_occ_cycle_num)
6273 == (DECL_UNIT (*(decl_t *) unit_decl_2)->max_occ_cycle_num))
6274 return 0;
6275 else
6276 return -1;
6279 /* The function makes heuristic assigning automata to units. Actually
6280 efficacy of the algorithm has been checked yet??? */
6282 static void
6283 units_to_automata_heuristic_distr (void)
6285 double estimation_bound;
6286 int automaton_num;
6287 int rest_units_num;
6288 double bound_value;
6289 unit_decl_t *unit_decls;
6290 int i, j;
6292 if (description->units_num == 0)
6293 return;
6294 estimation_bound = estimate_one_automaton_bound ();
6295 unit_decls = XNEWVEC (unit_decl_t, description->units_num);
6297 for (i = 0, j = 0; i < description->decls_num; i++)
6298 if (description->decls[i]->mode == dm_unit)
6299 unit_decls[j++] = DECL_UNIT (description->decls[i]);
6300 gcc_assert (j == description->units_num);
6302 qsort (unit_decls, description->units_num,
6303 sizeof (unit_decl_t), compare_max_occ_cycle_nums);
6305 automaton_num = 0;
6306 bound_value = unit_decls[0]->max_occ_cycle_num;
6307 unit_decls[0]->corresponding_automaton_num = automaton_num;
6309 for (i = 1; i < description->units_num; i++)
6311 rest_units_num = description->units_num - i + 1;
6312 gcc_assert (automata_num - automaton_num - 1 <= rest_units_num);
6313 if (automaton_num < automata_num - 1
6314 && ((automata_num - automaton_num - 1 == rest_units_num)
6315 || (bound_value
6316 > (estimation_bound
6317 / unit_decls[i]->max_occ_cycle_num))))
6319 bound_value = unit_decls[i]->max_occ_cycle_num;
6320 automaton_num++;
6322 else
6323 bound_value *= unit_decls[i]->max_occ_cycle_num;
6324 unit_decls[i]->corresponding_automaton_num = automaton_num;
6326 gcc_assert (automaton_num == automata_num - 1);
6327 free (unit_decls);
6330 /* The functions creates automaton insns for each automata. Automaton
6331 insn is simply insn for given automaton which makes reservation
6332 only of units of the automaton. */
6333 static ainsn_t
6334 create_ainsns (void)
6336 decl_t decl;
6337 ainsn_t first_ainsn;
6338 ainsn_t curr_ainsn;
6339 ainsn_t prev_ainsn;
6340 int i;
6342 first_ainsn = NULL;
6343 prev_ainsn = NULL;
6344 for (i = 0; i < description->decls_num; i++)
6346 decl = description->decls [i];
6347 if (decl->mode == dm_insn_reserv)
6349 curr_ainsn = create_node (sizeof (struct ainsn));
6350 curr_ainsn->insn_reserv_decl = DECL_INSN_RESERV (decl);
6351 curr_ainsn->important_p = FALSE;
6352 curr_ainsn->next_ainsn = NULL;
6353 if (prev_ainsn == NULL)
6354 first_ainsn = curr_ainsn;
6355 else
6356 prev_ainsn->next_ainsn = curr_ainsn;
6357 prev_ainsn = curr_ainsn;
6360 return first_ainsn;
6363 /* The function assigns automata to units according to constructions
6364 `define_automaton' in the description. */
6365 static void
6366 units_to_automata_distr (void)
6368 decl_t decl;
6369 int i;
6371 for (i = 0; i < description->decls_num; i++)
6373 decl = description->decls [i];
6374 if (decl->mode == dm_unit)
6376 if (DECL_UNIT (decl)->automaton_decl == NULL
6377 || (DECL_UNIT (decl)->automaton_decl->corresponding_automaton
6378 == NULL))
6379 /* Distribute to the first automaton. */
6380 DECL_UNIT (decl)->corresponding_automaton_num = 0;
6381 else
6382 DECL_UNIT (decl)->corresponding_automaton_num
6383 = (DECL_UNIT (decl)->automaton_decl
6384 ->corresponding_automaton->automaton_order_num);
6389 /* The function creates DFA(s) for fast pipeline hazards recognition
6390 after checking and simplifying IR of the description. */
6391 static void
6392 create_automata (void)
6394 automaton_t curr_automaton;
6395 automaton_t prev_automaton;
6396 decl_t decl;
6397 int curr_automaton_num;
6398 int i;
6400 if (automata_num != 0)
6402 units_to_automata_heuristic_distr ();
6403 for (prev_automaton = NULL, curr_automaton_num = 0;
6404 curr_automaton_num < automata_num;
6405 curr_automaton_num++, prev_automaton = curr_automaton)
6407 curr_automaton = create_node (sizeof (struct automaton));
6408 curr_automaton->ainsn_list = create_ainsns ();
6409 curr_automaton->corresponding_automaton_decl = NULL;
6410 curr_automaton->next_automaton = NULL;
6411 curr_automaton->automaton_order_num = curr_automaton_num;
6412 if (prev_automaton == NULL)
6413 description->first_automaton = curr_automaton;
6414 else
6415 prev_automaton->next_automaton = curr_automaton;
6418 else
6420 curr_automaton_num = 0;
6421 prev_automaton = NULL;
6422 for (i = 0; i < description->decls_num; i++)
6424 decl = description->decls [i];
6425 if (decl->mode == dm_automaton
6426 && DECL_AUTOMATON (decl)->automaton_is_used)
6428 curr_automaton = create_node (sizeof (struct automaton));
6429 curr_automaton->ainsn_list = create_ainsns ();
6430 curr_automaton->corresponding_automaton_decl
6431 = DECL_AUTOMATON (decl);
6432 curr_automaton->next_automaton = NULL;
6433 DECL_AUTOMATON (decl)->corresponding_automaton = curr_automaton;
6434 curr_automaton->automaton_order_num = curr_automaton_num;
6435 if (prev_automaton == NULL)
6436 description->first_automaton = curr_automaton;
6437 else
6438 prev_automaton->next_automaton = curr_automaton;
6439 curr_automaton_num++;
6440 prev_automaton = curr_automaton;
6443 if (curr_automaton_num == 0)
6445 curr_automaton = create_node (sizeof (struct automaton));
6446 curr_automaton->ainsn_list = create_ainsns ();
6447 curr_automaton->corresponding_automaton_decl = NULL;
6448 curr_automaton->next_automaton = NULL;
6449 description->first_automaton = curr_automaton;
6451 units_to_automata_distr ();
6453 NDFA_time = create_ticker ();
6454 ticker_off (&NDFA_time);
6455 NDFA_to_DFA_time = create_ticker ();
6456 ticker_off (&NDFA_to_DFA_time);
6457 minimize_time = create_ticker ();
6458 ticker_off (&minimize_time);
6459 equiv_time = create_ticker ();
6460 ticker_off (&equiv_time);
6461 for (curr_automaton = description->first_automaton;
6462 curr_automaton != NULL;
6463 curr_automaton = curr_automaton->next_automaton)
6465 if (progress_flag)
6467 if (curr_automaton->corresponding_automaton_decl == NULL)
6468 fprintf (stderr, "Prepare anonymous automaton creation ... ");
6469 else
6470 fprintf (stderr, "Prepare automaton `%s' creation...",
6471 curr_automaton->corresponding_automaton_decl->name);
6473 create_alt_states (curr_automaton);
6474 form_ainsn_with_same_reservs (curr_automaton);
6475 if (progress_flag)
6476 fprintf (stderr, "done\n");
6477 build_automaton (curr_automaton);
6478 enumerate_states (curr_automaton);
6479 ticker_on (&equiv_time);
6480 set_insn_equiv_classes (curr_automaton);
6481 ticker_off (&equiv_time);
6487 /* This page contains code for forming string representation of
6488 regexp. The representation is formed on IR obstack. So you should
6489 not work with IR obstack between regexp_representation and
6490 finish_regexp_representation calls. */
6492 /* This recursive function forms string representation of regexp
6493 (without tailing '\0'). */
6494 static void
6495 form_regexp (regexp_t regexp)
6497 int i;
6499 switch (regexp->mode)
6501 case rm_unit: case rm_reserv:
6503 const char *name = (regexp->mode == rm_unit
6504 ? REGEXP_UNIT (regexp)->name
6505 : REGEXP_RESERV (regexp)->name);
6507 obstack_grow (&irp, name, strlen (name));
6508 break;
6511 case rm_sequence:
6512 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
6514 if (i != 0)
6515 obstack_1grow (&irp, ',');
6516 form_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
6518 break;
6520 case rm_allof:
6521 obstack_1grow (&irp, '(');
6522 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
6524 if (i != 0)
6525 obstack_1grow (&irp, '+');
6526 if (REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_sequence
6527 || REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_oneof)
6528 obstack_1grow (&irp, '(');
6529 form_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
6530 if (REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_sequence
6531 || REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_oneof)
6532 obstack_1grow (&irp, ')');
6534 obstack_1grow (&irp, ')');
6535 break;
6537 case rm_oneof:
6538 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
6540 if (i != 0)
6541 obstack_1grow (&irp, '|');
6542 if (REGEXP_ONEOF (regexp)->regexps[i]->mode == rm_sequence)
6543 obstack_1grow (&irp, '(');
6544 form_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
6545 if (REGEXP_ONEOF (regexp)->regexps[i]->mode == rm_sequence)
6546 obstack_1grow (&irp, ')');
6548 break;
6550 case rm_repeat:
6552 char digits [30];
6554 if (REGEXP_REPEAT (regexp)->regexp->mode == rm_sequence
6555 || REGEXP_REPEAT (regexp)->regexp->mode == rm_allof
6556 || REGEXP_REPEAT (regexp)->regexp->mode == rm_oneof)
6557 obstack_1grow (&irp, '(');
6558 form_regexp (REGEXP_REPEAT (regexp)->regexp);
6559 if (REGEXP_REPEAT (regexp)->regexp->mode == rm_sequence
6560 || REGEXP_REPEAT (regexp)->regexp->mode == rm_allof
6561 || REGEXP_REPEAT (regexp)->regexp->mode == rm_oneof)
6562 obstack_1grow (&irp, ')');
6563 sprintf (digits, "*%d", REGEXP_REPEAT (regexp)->repeat_num);
6564 obstack_grow (&irp, digits, strlen (digits));
6565 break;
6568 case rm_nothing:
6569 obstack_grow (&irp, NOTHING_NAME, strlen (NOTHING_NAME));
6570 break;
6572 default:
6573 gcc_unreachable ();
6577 /* The function returns string representation of REGEXP on IR
6578 obstack. */
6579 static const char *
6580 regexp_representation (regexp_t regexp)
6582 form_regexp (regexp);
6583 obstack_1grow (&irp, '\0');
6584 return obstack_base (&irp);
6587 /* The function frees memory allocated for last formed string
6588 representation of regexp. */
6589 static void
6590 finish_regexp_representation (void)
6592 int length = obstack_object_size (&irp);
6594 obstack_blank_fast (&irp, -length);
6599 /* This page contains code for output PHR (pipeline hazards recognizer). */
6601 /* The function outputs minimal C type which is sufficient for
6602 representation numbers in range min_range_value and
6603 max_range_value. Because host machine and build machine may be
6604 different, we use here minimal values required by ANSI C standard
6605 instead of UCHAR_MAX, SHRT_MAX, SHRT_MIN, etc. This is a good
6606 approximation. */
6608 static void
6609 output_range_type (FILE *f, long int min_range_value,
6610 long int max_range_value)
6612 if (min_range_value >= 0 && max_range_value <= 255)
6613 fprintf (f, "unsigned char");
6614 else if (min_range_value >= -127 && max_range_value <= 127)
6615 fprintf (f, "signed char");
6616 else if (min_range_value >= 0 && max_range_value <= 65535)
6617 fprintf (f, "unsigned short");
6618 else if (min_range_value >= -32767 && max_range_value <= 32767)
6619 fprintf (f, "short");
6620 else
6621 fprintf (f, "int");
6624 /* The following macro value is used as value of member
6625 `longest_path_length' of state when we are processing path and the
6626 state on the path. */
6628 #define ON_THE_PATH -2
6630 /* The following recursive function searches for the length of the
6631 longest path starting from STATE which does not contain cycles and
6632 `cycle advance' arcs. */
6634 static int
6635 longest_path_length (state_t state)
6637 arc_t arc;
6638 int length, result;
6640 if (state->longest_path_length != UNDEFINED_LONGEST_PATH_LENGTH)
6642 /* We don't expect the path cycle here. Our graph may contain
6643 only cycles with one state on the path not containing `cycle
6644 advance' arcs -- see comment below. */
6645 gcc_assert (state->longest_path_length != ON_THE_PATH);
6647 /* We already visited the state. */
6648 return state->longest_path_length;
6651 result = 0;
6652 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6653 /* Ignore cycles containing one state and `cycle advance' arcs. */
6654 if (arc->to_state != state
6655 && (arc->insn->insn_reserv_decl
6656 != DECL_INSN_RESERV (advance_cycle_insn_decl)))
6658 length = longest_path_length (arc->to_state);
6659 if (length > result)
6660 result = length;
6662 state->longest_path_length = result + 1;
6663 return result;
6666 /* The function outputs all initialization values of VECT. */
6667 static void
6668 output_vect (vla_hwint_t vect)
6670 int els_on_line;
6671 size_t vect_length = VEC_length (vect_el_t, vect);
6672 size_t i;
6674 els_on_line = 1;
6675 if (vect_length == 0)
6676 fputs ("0 /* This is dummy el because the vect is empty */", output_file);
6677 else
6678 for (i = 0; i < vect_length; i++)
6680 fprintf (output_file, "%5ld", (long) VEC_index (vect_el_t, vect, i));
6681 if (els_on_line == 10)
6683 els_on_line = 0;
6684 fputs (",\n", output_file);
6686 else if (i < vect_length-1)
6687 fputs (", ", output_file);
6688 els_on_line++;
6692 /* The following is name of the structure which represents DFA(s) for
6693 PHR. */
6694 #define CHIP_NAME "DFA_chip"
6696 /* The following is name of member which represents state of a DFA for
6697 PHR. */
6698 static void
6699 output_chip_member_name (FILE *f, automaton_t automaton)
6701 if (automaton->corresponding_automaton_decl == NULL)
6702 fprintf (f, "automaton_state_%d", automaton->automaton_order_num);
6703 else
6704 fprintf (f, "%s_automaton_state",
6705 automaton->corresponding_automaton_decl->name);
6708 /* The following is name of temporary variable which stores state of a
6709 DFA for PHR. */
6710 static void
6711 output_temp_chip_member_name (FILE *f, automaton_t automaton)
6713 fprintf (f, "_");
6714 output_chip_member_name (f, automaton);
6717 /* This is name of macro value which is code of pseudo_insn
6718 representing advancing cpu cycle. Its value is used as internal
6719 code unknown insn. */
6720 #define ADVANCE_CYCLE_VALUE_NAME "DFA__ADVANCE_CYCLE"
6722 /* Output name of translate vector for given automaton. */
6723 static void
6724 output_translate_vect_name (FILE *f, automaton_t automaton)
6726 if (automaton->corresponding_automaton_decl == NULL)
6727 fprintf (f, "translate_%d", automaton->automaton_order_num);
6728 else
6729 fprintf (f, "%s_translate", automaton->corresponding_automaton_decl->name);
6732 /* Output name for simple transition table representation. */
6733 static void
6734 output_trans_full_vect_name (FILE *f, automaton_t automaton)
6736 if (automaton->corresponding_automaton_decl == NULL)
6737 fprintf (f, "transitions_%d", automaton->automaton_order_num);
6738 else
6739 fprintf (f, "%s_transitions",
6740 automaton->corresponding_automaton_decl->name);
6743 /* Output name of comb vector of the transition table for given
6744 automaton. */
6745 static void
6746 output_trans_comb_vect_name (FILE *f, automaton_t automaton)
6748 if (automaton->corresponding_automaton_decl == NULL)
6749 fprintf (f, "transitions_%d", automaton->automaton_order_num);
6750 else
6751 fprintf (f, "%s_transitions",
6752 automaton->corresponding_automaton_decl->name);
6755 /* Output name of check vector of the transition table for given
6756 automaton. */
6757 static void
6758 output_trans_check_vect_name (FILE *f, automaton_t automaton)
6760 if (automaton->corresponding_automaton_decl == NULL)
6761 fprintf (f, "check_%d", automaton->automaton_order_num);
6762 else
6763 fprintf (f, "%s_check", automaton->corresponding_automaton_decl->name);
6766 /* Output name of base vector of the transition table for given
6767 automaton. */
6768 static void
6769 output_trans_base_vect_name (FILE *f, automaton_t automaton)
6771 if (automaton->corresponding_automaton_decl == NULL)
6772 fprintf (f, "base_%d", automaton->automaton_order_num);
6773 else
6774 fprintf (f, "%s_base", automaton->corresponding_automaton_decl->name);
6777 /* Output name of simple min issue delay table representation. */
6778 static void
6779 output_min_issue_delay_vect_name (FILE *f, automaton_t automaton)
6781 if (automaton->corresponding_automaton_decl == NULL)
6782 fprintf (f, "min_issue_delay_%d", automaton->automaton_order_num);
6783 else
6784 fprintf (f, "%s_min_issue_delay",
6785 automaton->corresponding_automaton_decl->name);
6788 /* Output name of deadlock vector for given automaton. */
6789 static void
6790 output_dead_lock_vect_name (FILE *f, automaton_t automaton)
6792 if (automaton->corresponding_automaton_decl == NULL)
6793 fprintf (f, "dead_lock_%d", automaton->automaton_order_num);
6794 else
6795 fprintf (f, "%s_dead_lock", automaton->corresponding_automaton_decl->name);
6798 /* Output name of reserved units table for AUTOMATON into file F. */
6799 static void
6800 output_reserved_units_table_name (FILE *f, automaton_t automaton)
6802 if (automaton->corresponding_automaton_decl == NULL)
6803 fprintf (f, "reserved_units_%d", automaton->automaton_order_num);
6804 else
6805 fprintf (f, "%s_reserved_units",
6806 automaton->corresponding_automaton_decl->name);
6809 /* Name of the PHR interface macro. */
6810 #define CPU_UNITS_QUERY_MACRO_NAME "CPU_UNITS_QUERY"
6812 /* Names of an internal functions: */
6813 #define INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME "internal_min_issue_delay"
6815 /* This is external type of DFA(s) state. */
6816 #define STATE_TYPE_NAME "state_t"
6818 #define INTERNAL_TRANSITION_FUNC_NAME "internal_state_transition"
6820 #define INTERNAL_RESET_FUNC_NAME "internal_reset"
6822 #define INTERNAL_DEAD_LOCK_FUNC_NAME "internal_state_dead_lock_p"
6824 #define INTERNAL_INSN_LATENCY_FUNC_NAME "internal_insn_latency"
6826 /* Name of cache of insn dfa codes. */
6827 #define DFA_INSN_CODES_VARIABLE_NAME "dfa_insn_codes"
6829 /* Name of length of cache of insn dfa codes. */
6830 #define DFA_INSN_CODES_LENGTH_VARIABLE_NAME "dfa_insn_codes_length"
6832 /* Names of the PHR interface functions: */
6833 #define SIZE_FUNC_NAME "state_size"
6835 #define TRANSITION_FUNC_NAME "state_transition"
6837 #define MIN_ISSUE_DELAY_FUNC_NAME "min_issue_delay"
6839 #define MIN_INSN_CONFLICT_DELAY_FUNC_NAME "min_insn_conflict_delay"
6841 #define DEAD_LOCK_FUNC_NAME "state_dead_lock_p"
6843 #define RESET_FUNC_NAME "state_reset"
6845 #define INSN_LATENCY_FUNC_NAME "insn_latency"
6847 #define PRINT_RESERVATION_FUNC_NAME "print_reservation"
6849 #define GET_CPU_UNIT_CODE_FUNC_NAME "get_cpu_unit_code"
6851 #define CPU_UNIT_RESERVATION_P_FUNC_NAME "cpu_unit_reservation_p"
6853 #define DFA_CLEAN_INSN_CACHE_FUNC_NAME "dfa_clean_insn_cache"
6855 #define DFA_START_FUNC_NAME "dfa_start"
6857 #define DFA_FINISH_FUNC_NAME "dfa_finish"
6859 /* Names of parameters of the PHR interface functions. */
6860 #define STATE_NAME "state"
6862 #define INSN_PARAMETER_NAME "insn"
6864 #define INSN2_PARAMETER_NAME "insn2"
6866 #define CHIP_PARAMETER_NAME "chip"
6868 #define FILE_PARAMETER_NAME "f"
6870 #define CPU_UNIT_NAME_PARAMETER_NAME "cpu_unit_name"
6872 #define CPU_CODE_PARAMETER_NAME "cpu_unit_code"
6874 /* Names of the variables whose values are internal insn code of rtx
6875 insn. */
6876 #define INTERNAL_INSN_CODE_NAME "insn_code"
6878 #define INTERNAL_INSN2_CODE_NAME "insn2_code"
6880 /* Names of temporary variables in some functions. */
6881 #define TEMPORARY_VARIABLE_NAME "temp"
6883 #define I_VARIABLE_NAME "i"
6885 /* Name of result variable in some functions. */
6886 #define RESULT_VARIABLE_NAME "res"
6888 /* Name of function (attribute) to translate insn into internal insn
6889 code. */
6890 #define INTERNAL_DFA_INSN_CODE_FUNC_NAME "internal_dfa_insn_code"
6892 /* Name of function (attribute) to translate insn into internal insn
6893 code with caching. */
6894 #define DFA_INSN_CODE_FUNC_NAME "dfa_insn_code"
6896 /* Output C type which is used for representation of codes of states
6897 of AUTOMATON. */
6898 static void
6899 output_state_member_type (FILE *f, automaton_t automaton)
6901 output_range_type (f, 0, automaton->achieved_states_num);
6904 /* Output definition of the structure representing current DFA(s)
6905 state(s). */
6906 static void
6907 output_chip_definitions (void)
6909 automaton_t automaton;
6911 fprintf (output_file, "struct %s\n{\n", CHIP_NAME);
6912 for (automaton = description->first_automaton;
6913 automaton != NULL;
6914 automaton = automaton->next_automaton)
6916 fprintf (output_file, " ");
6917 output_state_member_type (output_file, automaton);
6918 fprintf (output_file, " ");
6919 output_chip_member_name (output_file, automaton);
6920 fprintf (output_file, ";\n");
6922 fprintf (output_file, "};\n\n");
6923 #if 0
6924 fprintf (output_file, "static struct %s %s;\n\n", CHIP_NAME, CHIP_NAME);
6925 #endif
6929 /* The function outputs translate vector of internal insn code into
6930 insn equivalence class number. The equivalence class number is
6931 used to access to table and vectors representing DFA(s). */
6932 static void
6933 output_translate_vect (automaton_t automaton)
6935 ainsn_t ainsn;
6936 int insn_value;
6937 vla_hwint_t translate_vect;
6939 translate_vect = VEC_alloc (vect_el_t,heap, description->insns_num);
6941 for (insn_value = 0; insn_value < description->insns_num; insn_value++)
6942 /* Undefined value */
6943 VEC_quick_push (vect_el_t, translate_vect,
6944 automaton->insn_equiv_classes_num);
6946 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6947 VEC_replace (vect_el_t, translate_vect,
6948 ainsn->insn_reserv_decl->insn_num,
6949 ainsn->insn_equiv_class_num);
6951 fprintf (output_file,
6952 "/* Vector translating external insn codes to internal ones.*/\n");
6953 fprintf (output_file, "static const ");
6954 output_range_type (output_file, 0, automaton->insn_equiv_classes_num);
6955 fprintf (output_file, " ");
6956 output_translate_vect_name (output_file, automaton);
6957 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
6958 output_vect (translate_vect);
6959 fprintf (output_file, "};\n\n");
6960 VEC_free (vect_el_t,heap, translate_vect);
6963 /* The value in a table state x ainsn -> something which represents
6964 undefined value. */
6965 static int undefined_vect_el_value;
6967 /* The following function returns nonzero value if the best
6968 representation of the table is comb vector. */
6969 static int
6970 comb_vect_p (state_ainsn_table_t tab)
6972 return (2 * VEC_length (vect_el_t, tab->full_vect)
6973 > 5 * VEC_length (vect_el_t, tab->comb_vect));
6976 /* The following function creates new table for AUTOMATON. */
6977 static state_ainsn_table_t
6978 create_state_ainsn_table (automaton_t automaton)
6980 state_ainsn_table_t tab;
6981 int full_vect_length;
6982 int i;
6984 tab = create_node (sizeof (struct state_ainsn_table));
6985 tab->automaton = automaton;
6987 tab->comb_vect = VEC_alloc (vect_el_t,heap, 10000);
6988 tab->check_vect = VEC_alloc (vect_el_t,heap, 10000);
6990 tab->base_vect = 0;
6991 VEC_safe_grow (vect_el_t,heap, tab->base_vect,
6992 automaton->achieved_states_num);
6994 full_vect_length = (automaton->insn_equiv_classes_num
6995 * automaton->achieved_states_num);
6996 tab->full_vect = VEC_alloc (vect_el_t,heap, full_vect_length);
6997 for (i = 0; i < full_vect_length; i++)
6998 VEC_quick_push (vect_el_t, tab->full_vect, undefined_vect_el_value);
7000 tab->min_base_vect_el_value = 0;
7001 tab->max_base_vect_el_value = 0;
7002 tab->min_comb_vect_el_value = 0;
7003 tab->max_comb_vect_el_value = 0;
7004 return tab;
7007 /* The following function outputs the best C representation of the
7008 table TAB of given TABLE_NAME. */
7009 static void
7010 output_state_ainsn_table (state_ainsn_table_t tab, const char *table_name,
7011 void (*output_full_vect_name_func) (FILE *, automaton_t),
7012 void (*output_comb_vect_name_func) (FILE *, automaton_t),
7013 void (*output_check_vect_name_func) (FILE *, automaton_t),
7014 void (*output_base_vect_name_func) (FILE *, automaton_t))
7016 if (!comb_vect_p (tab))
7018 fprintf (output_file, "/* Vector for %s. */\n", table_name);
7019 fprintf (output_file, "static const ");
7020 output_range_type (output_file, tab->min_comb_vect_el_value,
7021 tab->max_comb_vect_el_value);
7022 fprintf (output_file, " ");
7023 (*output_full_vect_name_func) (output_file, tab->automaton);
7024 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7025 output_vect (tab->full_vect);
7026 fprintf (output_file, "};\n\n");
7028 else
7030 fprintf (output_file, "/* Comb vector for %s. */\n", table_name);
7031 fprintf (output_file, "static const ");
7032 output_range_type (output_file, tab->min_comb_vect_el_value,
7033 tab->max_comb_vect_el_value);
7034 fprintf (output_file, " ");
7035 (*output_comb_vect_name_func) (output_file, tab->automaton);
7036 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7037 output_vect (tab->comb_vect);
7038 fprintf (output_file, "};\n\n");
7039 fprintf (output_file, "/* Check vector for %s. */\n", table_name);
7040 fprintf (output_file, "static const ");
7041 output_range_type (output_file, 0, tab->automaton->achieved_states_num);
7042 fprintf (output_file, " ");
7043 (*output_check_vect_name_func) (output_file, tab->automaton);
7044 fprintf (output_file, "[] = {\n");
7045 output_vect (tab->check_vect);
7046 fprintf (output_file, "};\n\n");
7047 fprintf (output_file, "/* Base vector for %s. */\n", table_name);
7048 fprintf (output_file, "static const ");
7049 output_range_type (output_file, tab->min_base_vect_el_value,
7050 tab->max_base_vect_el_value);
7051 fprintf (output_file, " ");
7052 (*output_base_vect_name_func) (output_file, tab->automaton);
7053 fprintf (output_file, "[] = {\n");
7054 output_vect (tab->base_vect);
7055 fprintf (output_file, "};\n\n");
7059 /* The following function adds vector VECT to table TAB as its line
7060 with number VECT_NUM. */
7061 static void
7062 add_vect (state_ainsn_table_t tab, int vect_num, vla_hwint_t vect)
7064 int vect_length;
7065 size_t real_vect_length;
7066 int comb_vect_index;
7067 int comb_vect_els_num;
7068 int vect_index;
7069 int first_unempty_vect_index;
7070 int additional_els_num;
7071 int no_state_value;
7072 vect_el_t vect_el;
7073 int i;
7074 unsigned long vect_mask, comb_vect_mask;
7076 vect_length = VEC_length (vect_el_t, vect);
7077 gcc_assert (vect_length);
7078 gcc_assert (VEC_last (vect_el_t, vect) != undefined_vect_el_value);
7079 real_vect_length = tab->automaton->insn_equiv_classes_num;
7080 /* Form full vector in the table: */
7082 size_t full_base = tab->automaton->insn_equiv_classes_num * vect_num;
7083 if (VEC_length (vect_el_t, tab->full_vect) < full_base + vect_length)
7084 VEC_safe_grow (vect_el_t,heap, tab->full_vect,
7085 full_base + vect_length);
7086 for (i = 0; i < vect_length; i++)
7087 VEC_replace (vect_el_t, tab->full_vect, full_base + i,
7088 VEC_index (vect_el_t, vect, i));
7090 /* Form comb vector in the table: */
7091 gcc_assert (VEC_length (vect_el_t, tab->comb_vect)
7092 == VEC_length (vect_el_t, tab->check_vect));
7094 comb_vect_els_num = VEC_length (vect_el_t, tab->comb_vect);
7095 for (first_unempty_vect_index = 0;
7096 first_unempty_vect_index < vect_length;
7097 first_unempty_vect_index++)
7098 if (VEC_index (vect_el_t, vect, first_unempty_vect_index)
7099 != undefined_vect_el_value)
7100 break;
7102 /* Search for the place in comb vect for the inserted vect. */
7104 /* Slow case. */
7105 if (vect_length - first_unempty_vect_index >= SIZEOF_LONG * CHAR_BIT)
7107 for (comb_vect_index = 0;
7108 comb_vect_index < comb_vect_els_num;
7109 comb_vect_index++)
7111 for (vect_index = first_unempty_vect_index;
7112 vect_index < vect_length
7113 && vect_index + comb_vect_index < comb_vect_els_num;
7114 vect_index++)
7115 if (VEC_index (vect_el_t, vect, vect_index)
7116 != undefined_vect_el_value
7117 && (VEC_index (vect_el_t, tab->comb_vect,
7118 vect_index + comb_vect_index)
7119 != undefined_vect_el_value))
7120 break;
7121 if (vect_index >= vect_length
7122 || vect_index + comb_vect_index >= comb_vect_els_num)
7123 break;
7125 goto found;
7128 /* Fast case. */
7129 vect_mask = 0;
7130 for (vect_index = first_unempty_vect_index;
7131 vect_index < vect_length;
7132 vect_index++)
7134 vect_mask = vect_mask << 1;
7135 if (VEC_index (vect_el_t, vect, vect_index) != undefined_vect_el_value)
7136 vect_mask |= 1;
7139 /* Search for the place in comb vect for the inserted vect. */
7140 comb_vect_index = 0;
7141 if (comb_vect_els_num == 0)
7142 goto found;
7144 comb_vect_mask = 0;
7145 for (vect_index = first_unempty_vect_index;
7146 vect_index < vect_length && vect_index < comb_vect_els_num;
7147 vect_index++)
7149 comb_vect_mask <<= 1;
7150 if (vect_index + comb_vect_index < comb_vect_els_num
7151 && VEC_index (vect_el_t, tab->comb_vect, vect_index + comb_vect_index)
7152 != undefined_vect_el_value)
7153 comb_vect_mask |= 1;
7155 if ((vect_mask & comb_vect_mask) == 0)
7156 goto found;
7158 for (comb_vect_index = 1, i = vect_length; i < comb_vect_els_num;
7159 comb_vect_index++, i++)
7161 comb_vect_mask = (comb_vect_mask << 1) | 1;
7162 comb_vect_mask ^= (VEC_index (vect_el_t, tab->comb_vect, i)
7163 == undefined_vect_el_value);
7164 if ((vect_mask & comb_vect_mask) == 0)
7165 goto found;
7167 for ( ; comb_vect_index < comb_vect_els_num; comb_vect_index++)
7169 comb_vect_mask <<= 1;
7170 if ((vect_mask & comb_vect_mask) == 0)
7171 goto found;
7174 found:
7175 /* Slot was found. */
7176 additional_els_num = comb_vect_index + real_vect_length - comb_vect_els_num;
7177 if (additional_els_num < 0)
7178 additional_els_num = 0;
7179 /* Expand comb and check vectors. */
7180 vect_el = undefined_vect_el_value;
7181 no_state_value = tab->automaton->achieved_states_num;
7182 while (additional_els_num > 0)
7184 VEC_safe_push (vect_el_t,heap, tab->comb_vect, vect_el);
7185 VEC_safe_push (vect_el_t,heap, tab->check_vect, no_state_value);
7186 additional_els_num--;
7188 gcc_assert (VEC_length (vect_el_t, tab->comb_vect)
7189 >= comb_vect_index + real_vect_length);
7190 /* Fill comb and check vectors. */
7191 for (vect_index = 0; vect_index < vect_length; vect_index++)
7192 if (VEC_index (vect_el_t, vect, vect_index) != undefined_vect_el_value)
7194 vect_el_t x = VEC_index (vect_el_t, vect, vect_index);
7195 gcc_assert (VEC_index (vect_el_t, tab->comb_vect,
7196 comb_vect_index + vect_index)
7197 == undefined_vect_el_value);
7198 gcc_assert (x >= 0);
7199 if (tab->max_comb_vect_el_value < x)
7200 tab->max_comb_vect_el_value = x;
7201 if (tab->min_comb_vect_el_value > x)
7202 tab->min_comb_vect_el_value = x;
7203 VEC_replace (vect_el_t, tab->comb_vect,
7204 comb_vect_index + vect_index, x);
7205 VEC_replace (vect_el_t, tab->check_vect,
7206 comb_vect_index + vect_index, vect_num);
7208 if (tab->max_comb_vect_el_value < undefined_vect_el_value)
7209 tab->max_comb_vect_el_value = undefined_vect_el_value;
7210 if (tab->min_comb_vect_el_value > undefined_vect_el_value)
7211 tab->min_comb_vect_el_value = undefined_vect_el_value;
7212 if (tab->max_base_vect_el_value < comb_vect_index)
7213 tab->max_base_vect_el_value = comb_vect_index;
7214 if (tab->min_base_vect_el_value > comb_vect_index)
7215 tab->min_base_vect_el_value = comb_vect_index;
7217 VEC_replace (vect_el_t, tab->base_vect, vect_num, comb_vect_index);
7220 /* Return number of out arcs of STATE. */
7221 static int
7222 out_state_arcs_num (state_t state)
7224 int result;
7225 arc_t arc;
7227 result = 0;
7228 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
7230 gcc_assert (arc->insn);
7231 if (arc->insn->first_ainsn_with_given_equivalence_num)
7232 result++;
7234 return result;
7237 /* Compare number of possible transitions from the states. */
7238 static int
7239 compare_transition_els_num (const void *state_ptr_1,
7240 const void *state_ptr_2)
7242 int transition_els_num_1;
7243 int transition_els_num_2;
7245 transition_els_num_1 = out_state_arcs_num (*(state_t *) state_ptr_1);
7246 transition_els_num_2 = out_state_arcs_num (*(state_t *) state_ptr_2);
7247 if (transition_els_num_1 < transition_els_num_2)
7248 return 1;
7249 else if (transition_els_num_1 == transition_els_num_2)
7250 return 0;
7251 else
7252 return -1;
7255 /* The function adds element EL_VALUE to vector VECT for a table state
7256 x AINSN. */
7257 static void
7258 add_vect_el (vla_hwint_t *vect, ainsn_t ainsn, int el_value)
7260 int equiv_class_num;
7261 int vect_index;
7263 gcc_assert (ainsn);
7264 equiv_class_num = ainsn->insn_equiv_class_num;
7265 for (vect_index = VEC_length (vect_el_t, *vect);
7266 vect_index <= equiv_class_num;
7267 vect_index++)
7268 VEC_safe_push (vect_el_t,heap, *vect, undefined_vect_el_value);
7269 VEC_replace (vect_el_t, *vect, equiv_class_num, el_value);
7272 /* This is for forming vector of states of an automaton. */
7273 static VEC(state_t,heap) *output_states_vect;
7275 /* The function is called by function pass_states. The function adds
7276 STATE to `output_states_vect'. */
7277 static void
7278 add_states_vect_el (state_t state)
7280 VEC_safe_push (state_t,heap, output_states_vect, state);
7283 /* Form and output vectors (comb, check, base or full vector)
7284 representing transition table of AUTOMATON. */
7285 static void
7286 output_trans_table (automaton_t automaton)
7288 size_t i;
7289 arc_t arc;
7290 vla_hwint_t transition_vect = 0;
7292 undefined_vect_el_value = automaton->achieved_states_num;
7293 automaton->trans_table = create_state_ainsn_table (automaton);
7294 /* Create vect of pointers to states ordered by num of transitions
7295 from the state (state with the maximum num is the first). */
7296 output_states_vect = 0;
7297 pass_states (automaton, add_states_vect_el);
7298 qsort (VEC_address (state_t, output_states_vect),
7299 VEC_length (state_t, output_states_vect),
7300 sizeof (state_t), compare_transition_els_num);
7302 for (i = 0; i < VEC_length (state_t, output_states_vect); i++)
7304 VEC_truncate (vect_el_t, transition_vect, 0);
7305 for (arc = first_out_arc (VEC_index (state_t, output_states_vect, i));
7306 arc != NULL;
7307 arc = next_out_arc (arc))
7309 gcc_assert (arc->insn);
7310 if (arc->insn->first_ainsn_with_given_equivalence_num)
7311 add_vect_el (&transition_vect, arc->insn,
7312 arc->to_state->order_state_num);
7314 add_vect (automaton->trans_table,
7315 VEC_index (state_t, output_states_vect, i)->order_state_num,
7316 transition_vect);
7318 output_state_ainsn_table
7319 (automaton->trans_table, "state transitions",
7320 output_trans_full_vect_name, output_trans_comb_vect_name,
7321 output_trans_check_vect_name, output_trans_base_vect_name);
7323 VEC_free (state_t,heap, output_states_vect);
7324 VEC_free (vect_el_t,heap, transition_vect);
7327 /* The current number of passing states to find minimal issue delay
7328 value for an ainsn and state. */
7329 static int curr_state_pass_num;
7331 /* This recursive function passes states to find minimal issue delay
7332 value for AINSN. The state being visited is STATE. The function
7333 returns minimal issue delay value for AINSN in STATE or -1 if we
7334 enter into a loop. */
7335 static int
7336 min_issue_delay_pass_states (state_t state, ainsn_t ainsn)
7338 arc_t arc;
7339 int min_insn_issue_delay, insn_issue_delay;
7341 if (state->state_pass_num == curr_state_pass_num
7342 || state->min_insn_issue_delay != -1)
7343 /* We've entered into a loop or already have the correct value for
7344 given state and ainsn. */
7345 return state->min_insn_issue_delay;
7346 state->state_pass_num = curr_state_pass_num;
7347 min_insn_issue_delay = -1;
7348 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
7349 if (arc->insn == ainsn)
7351 min_insn_issue_delay = 0;
7352 break;
7354 else
7356 insn_issue_delay = min_issue_delay_pass_states (arc->to_state, ainsn);
7357 if (insn_issue_delay != -1)
7359 if (arc->insn->insn_reserv_decl
7360 == DECL_INSN_RESERV (advance_cycle_insn_decl))
7361 insn_issue_delay++;
7362 if (min_insn_issue_delay == -1
7363 || min_insn_issue_delay > insn_issue_delay)
7365 min_insn_issue_delay = insn_issue_delay;
7366 if (insn_issue_delay == 0)
7367 break;
7371 return min_insn_issue_delay;
7374 /* The function searches minimal issue delay value for AINSN in STATE.
7375 The function can return negative value if we can not issue AINSN. We
7376 will report about it later. */
7377 static int
7378 min_issue_delay (state_t state, ainsn_t ainsn)
7380 curr_state_pass_num++;
7381 state->min_insn_issue_delay = min_issue_delay_pass_states (state, ainsn);
7382 return state->min_insn_issue_delay;
7385 /* The function initiates code for finding minimal issue delay values.
7386 It should be called only once. */
7387 static void
7388 initiate_min_issue_delay_pass_states (void)
7390 curr_state_pass_num = 0;
7393 /* Form and output vectors representing minimal issue delay table of
7394 AUTOMATON. The table is state x ainsn -> minimal issue delay of
7395 the ainsn. */
7396 static void
7397 output_min_issue_delay_table (automaton_t automaton)
7399 vla_hwint_t min_issue_delay_vect;
7400 vla_hwint_t compressed_min_issue_delay_vect;
7401 vect_el_t min_delay;
7402 ainsn_t ainsn;
7403 size_t i, min_issue_delay_len;
7404 size_t compressed_min_issue_delay_len;
7405 size_t cfactor;
7407 /* Create vect of pointers to states ordered by num of transitions
7408 from the state (state with the maximum num is the first). */
7409 output_states_vect = 0;
7410 pass_states (automaton, add_states_vect_el);
7412 min_issue_delay_len = (VEC_length (state_t, output_states_vect)
7413 * automaton->insn_equiv_classes_num);
7414 min_issue_delay_vect = VEC_alloc (vect_el_t,heap, min_issue_delay_len);
7415 for (i = 0; i < min_issue_delay_len; i++)
7416 VEC_quick_push (vect_el_t, min_issue_delay_vect, 0);
7418 automaton->max_min_delay = 0;
7419 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
7420 if (ainsn->first_ainsn_with_given_equivalence_num)
7422 for (i = 0; i < VEC_length (state_t, output_states_vect); i++)
7423 VEC_index (state_t, output_states_vect, i)->min_insn_issue_delay = -1;
7424 for (i = 0; i < VEC_length (state_t, output_states_vect); i++)
7426 state_t s = VEC_index (state_t, output_states_vect, i);
7427 min_delay = min_issue_delay (s, ainsn);
7428 if (automaton->max_min_delay < min_delay)
7429 automaton->max_min_delay = min_delay;
7430 VEC_replace (vect_el_t, min_issue_delay_vect,
7431 s->order_state_num
7432 * automaton->insn_equiv_classes_num
7433 + ainsn->insn_equiv_class_num,
7434 min_delay);
7437 fprintf (output_file, "/* Vector of min issue delay of insns. */\n");
7438 fprintf (output_file, "static const ");
7439 output_range_type (output_file, 0, automaton->max_min_delay);
7440 fprintf (output_file, " ");
7441 output_min_issue_delay_vect_name (output_file, automaton);
7442 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7443 /* Compress the vector. */
7444 if (automaton->max_min_delay < 2)
7445 cfactor = 8;
7446 else if (automaton->max_min_delay < 4)
7447 cfactor = 4;
7448 else if (automaton->max_min_delay < 16)
7449 cfactor = 2;
7450 else
7451 cfactor = 1;
7452 automaton->min_issue_delay_table_compression_factor = cfactor;
7454 compressed_min_issue_delay_len = (min_issue_delay_len+cfactor-1) / cfactor;
7455 compressed_min_issue_delay_vect
7456 = VEC_alloc (vect_el_t,heap, compressed_min_issue_delay_len);
7458 for (i = 0; i < compressed_min_issue_delay_len; i++)
7459 VEC_quick_push (vect_el_t, compressed_min_issue_delay_vect, 0);
7461 for (i = 0; i < min_issue_delay_len; i++)
7463 size_t ci = i / cfactor;
7464 vect_el_t x = VEC_index (vect_el_t, min_issue_delay_vect, i);
7465 vect_el_t cx = VEC_index (vect_el_t, compressed_min_issue_delay_vect, ci);
7467 cx |= x << (8 - (i % cfactor + 1) * (8 / cfactor));
7468 VEC_replace (vect_el_t, compressed_min_issue_delay_vect, ci, cx);
7470 output_vect (compressed_min_issue_delay_vect);
7471 fprintf (output_file, "};\n\n");
7472 VEC_free (state_t,heap, output_states_vect);
7473 VEC_free (vect_el_t,heap, min_issue_delay_vect);
7474 VEC_free (vect_el_t,heap, compressed_min_issue_delay_vect);
7477 /* Form and output vector representing the locked states of
7478 AUTOMATON. */
7479 static void
7480 output_dead_lock_vect (automaton_t automaton)
7482 size_t i;
7483 arc_t arc;
7484 vla_hwint_t dead_lock_vect = 0;
7486 /* Create vect of pointers to states ordered by num of
7487 transitions from the state (state with the maximum num is the
7488 first). */
7489 automaton->locked_states = 0;
7490 output_states_vect = 0;
7491 pass_states (automaton, add_states_vect_el);
7493 VEC_safe_grow (vect_el_t,heap, dead_lock_vect,
7494 VEC_length (state_t, output_states_vect));
7495 for (i = 0; i < VEC_length (state_t, output_states_vect); i++)
7497 state_t s = VEC_index (state_t, output_states_vect, i);
7498 arc = first_out_arc (s);
7499 gcc_assert (arc);
7500 if (next_out_arc (arc) == NULL
7501 && (arc->insn->insn_reserv_decl
7502 == DECL_INSN_RESERV (advance_cycle_insn_decl)))
7504 VEC_replace (vect_el_t, dead_lock_vect, s->order_state_num, 1);
7505 automaton->locked_states++;
7507 else
7508 VEC_replace (vect_el_t, dead_lock_vect, s->order_state_num, 0);
7510 if (automaton->locked_states == 0)
7511 return;
7513 fprintf (output_file, "/* Vector for locked state flags. */\n");
7514 fprintf (output_file, "static const ");
7515 output_range_type (output_file, 0, 1);
7516 fprintf (output_file, " ");
7517 output_dead_lock_vect_name (output_file, automaton);
7518 fprintf (output_file, "[] = {\n");
7519 output_vect (dead_lock_vect);
7520 fprintf (output_file, "};\n\n");
7521 VEC_free (state_t,heap, output_states_vect);
7522 VEC_free (vect_el_t,heap, dead_lock_vect);
7525 /* Form and output vector representing reserved units of the states of
7526 AUTOMATON. */
7527 static void
7528 output_reserved_units_table (automaton_t automaton)
7530 vla_hwint_t reserved_units_table = 0;
7531 int state_byte_size;
7532 int reserved_units_size;
7533 size_t n;
7534 int i;
7536 if (description->query_units_num == 0)
7537 return;
7539 /* Create vect of pointers to states. */
7540 output_states_vect = 0;
7541 pass_states (automaton, add_states_vect_el);
7542 /* Create vector. */
7543 state_byte_size = (description->query_units_num + 7) / 8;
7544 reserved_units_size = (VEC_length (state_t, output_states_vect)
7545 * state_byte_size);
7547 reserved_units_table = VEC_alloc (vect_el_t,heap, reserved_units_size);
7549 for (i = 0; i < reserved_units_size; i++)
7550 VEC_quick_push (vect_el_t, reserved_units_table, 0);
7551 for (n = 0; n < VEC_length (state_t, output_states_vect); n++)
7553 state_t s = VEC_index (state_t, output_states_vect, n);
7554 for (i = 0; i < description->units_num; i++)
7555 if (units_array [i]->query_p
7556 && first_cycle_unit_presence (s, i))
7558 int ri = (s->order_state_num * state_byte_size
7559 + units_array [i]->query_num / 8);
7560 vect_el_t x = VEC_index (vect_el_t, reserved_units_table, ri);
7562 x += 1 << (units_array [i]->query_num % 8);
7563 VEC_replace (vect_el_t, reserved_units_table, ri, x);
7566 fprintf (output_file, "\n#if %s\n", CPU_UNITS_QUERY_MACRO_NAME);
7567 fprintf (output_file, "/* Vector for reserved units of states. */\n");
7568 fprintf (output_file, "static const ");
7569 output_range_type (output_file, 0, 255);
7570 fprintf (output_file, " ");
7571 output_reserved_units_table_name (output_file, automaton);
7572 fprintf (output_file, "[] = {\n");
7573 output_vect (reserved_units_table);
7574 fprintf (output_file, "};\n#endif /* #if %s */\n\n",
7575 CPU_UNITS_QUERY_MACRO_NAME);
7577 VEC_free (state_t,heap, output_states_vect);
7578 VEC_free (vect_el_t,heap, reserved_units_table);
7581 /* The function outputs all tables representing DFA(s) used for fast
7582 pipeline hazards recognition. */
7583 static void
7584 output_tables (void)
7586 automaton_t automaton;
7588 initiate_min_issue_delay_pass_states ();
7589 for (automaton = description->first_automaton;
7590 automaton != NULL;
7591 automaton = automaton->next_automaton)
7593 output_translate_vect (automaton);
7594 output_trans_table (automaton);
7595 output_min_issue_delay_table (automaton);
7596 output_dead_lock_vect (automaton);
7597 output_reserved_units_table (automaton);
7599 fprintf (output_file, "\n#define %s %d\n\n", ADVANCE_CYCLE_VALUE_NAME,
7600 DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
7603 /* The function outputs definition and value of PHR interface variable
7604 `max_insn_queue_index'. Its value is not less than maximal queue
7605 length needed for the insn scheduler. */
7606 static void
7607 output_max_insn_queue_index_def (void)
7609 int i, max, latency;
7610 decl_t decl;
7612 max = description->max_insn_reserv_cycles;
7613 for (i = 0; i < description->decls_num; i++)
7615 decl = description->decls [i];
7616 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
7618 latency = DECL_INSN_RESERV (decl)->default_latency;
7619 if (latency > max)
7620 max = latency;
7622 else if (decl->mode == dm_bypass)
7624 latency = DECL_BYPASS (decl)->latency;
7625 if (latency > max)
7626 max = latency;
7629 for (i = 0; (1 << i) <= max; i++)
7631 gcc_assert (i >= 0);
7632 fprintf (output_file, "\nconst int max_insn_queue_index = %d;\n\n",
7633 (1 << i) - 1);
7636 /* The function outputs switch cases for insn reservations using
7637 function *output_automata_list_code. */
7638 static void
7639 output_insn_code_cases (void (*output_automata_list_code)
7640 (automata_list_el_t))
7642 decl_t decl, decl2;
7643 int i, j;
7645 for (i = 0; i < description->decls_num; i++)
7647 decl = description->decls [i];
7648 if (decl->mode == dm_insn_reserv)
7649 DECL_INSN_RESERV (decl)->processed_p = FALSE;
7651 for (i = 0; i < description->decls_num; i++)
7653 decl = description->decls [i];
7654 if (decl->mode == dm_insn_reserv
7655 && !DECL_INSN_RESERV (decl)->processed_p)
7657 for (j = i; j < description->decls_num; j++)
7659 decl2 = description->decls [j];
7660 if (decl2->mode == dm_insn_reserv
7661 && (DECL_INSN_RESERV (decl2)->important_automata_list
7662 == DECL_INSN_RESERV (decl)->important_automata_list))
7664 DECL_INSN_RESERV (decl2)->processed_p = TRUE;
7665 fprintf (output_file, " case %d: /* %s */\n",
7666 DECL_INSN_RESERV (decl2)->insn_num,
7667 DECL_INSN_RESERV (decl2)->name);
7670 (*output_automata_list_code)
7671 (DECL_INSN_RESERV (decl)->important_automata_list);
7677 /* The function outputs a code for evaluation of a minimal delay of
7678 issue of insns which have reservations in given AUTOMATA_LIST. */
7679 static void
7680 output_automata_list_min_issue_delay_code (automata_list_el_t automata_list)
7682 automata_list_el_t el;
7683 automaton_t automaton;
7685 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
7687 automaton = el->automaton;
7688 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
7689 output_min_issue_delay_vect_name (output_file, automaton);
7690 fprintf (output_file,
7691 (automaton->min_issue_delay_table_compression_factor != 1
7692 ? " [(" : " ["));
7693 output_translate_vect_name (output_file, automaton);
7694 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
7695 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7696 output_chip_member_name (output_file, automaton);
7697 fprintf (output_file, " * %d", automaton->insn_equiv_classes_num);
7698 if (automaton->min_issue_delay_table_compression_factor == 1)
7699 fprintf (output_file, "];\n");
7700 else
7702 fprintf (output_file, ") / %d];\n",
7703 automaton->min_issue_delay_table_compression_factor);
7704 fprintf (output_file, " %s = (%s >> (8 - (",
7705 TEMPORARY_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
7706 output_translate_vect_name (output_file, automaton);
7707 fprintf
7708 (output_file, " [%s] %% %d + 1) * %d)) & %d;\n",
7709 INTERNAL_INSN_CODE_NAME,
7710 automaton->min_issue_delay_table_compression_factor,
7711 8 / automaton->min_issue_delay_table_compression_factor,
7712 (1 << (8 / automaton->min_issue_delay_table_compression_factor))
7713 - 1);
7715 if (el == automata_list)
7716 fprintf (output_file, " %s = %s;\n",
7717 RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
7718 else
7720 fprintf (output_file, " if (%s > %s)\n",
7721 TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
7722 fprintf (output_file, " %s = %s;\n",
7723 RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
7726 fprintf (output_file, " break;\n\n");
7729 /* Output function `internal_min_issue_delay'. */
7730 static void
7731 output_internal_min_issue_delay_func (void)
7733 fprintf (output_file,
7734 "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
7735 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7736 CHIP_NAME, CHIP_PARAMETER_NAME);
7737 fprintf (output_file, "{\n int %s ATTRIBUTE_UNUSED;\n int %s = -1;\n",
7738 TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
7739 fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
7740 output_insn_code_cases (output_automata_list_min_issue_delay_code);
7741 fprintf (output_file,
7742 "\n default:\n %s = -1;\n break;\n }\n",
7743 RESULT_VARIABLE_NAME);
7744 fprintf (output_file, " return %s;\n", RESULT_VARIABLE_NAME);
7745 fprintf (output_file, "}\n\n");
7748 /* The function outputs a code changing state after issue of insns
7749 which have reservations in given AUTOMATA_LIST. */
7750 static void
7751 output_automata_list_transition_code (automata_list_el_t automata_list)
7753 automata_list_el_t el, next_el;
7755 fprintf (output_file, " {\n");
7756 if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
7757 for (el = automata_list;; el = next_el)
7759 next_el = el->next_automata_list_el;
7760 if (next_el == NULL)
7761 break;
7762 fprintf (output_file, " ");
7763 output_state_member_type (output_file, el->automaton);
7764 fprintf (output_file, " ");
7765 output_temp_chip_member_name (output_file, el->automaton);
7766 fprintf (output_file, ";\n");
7768 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
7769 if (comb_vect_p (el->automaton->trans_table))
7771 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
7772 output_trans_base_vect_name (output_file, el->automaton);
7773 fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
7774 output_chip_member_name (output_file, el->automaton);
7775 fprintf (output_file, "] + ");
7776 output_translate_vect_name (output_file, el->automaton);
7777 fprintf (output_file, " [%s];\n", INTERNAL_INSN_CODE_NAME);
7778 fprintf (output_file, " if (");
7779 output_trans_check_vect_name (output_file, el->automaton);
7780 fprintf (output_file, " [%s] != %s->",
7781 TEMPORARY_VARIABLE_NAME, CHIP_PARAMETER_NAME);
7782 output_chip_member_name (output_file, el->automaton);
7783 fprintf (output_file, ")\n");
7784 fprintf (output_file, " return %s (%s, %s);\n",
7785 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7786 CHIP_PARAMETER_NAME);
7787 fprintf (output_file, " else\n");
7788 fprintf (output_file, " ");
7789 if (el->next_automata_list_el != NULL)
7790 output_temp_chip_member_name (output_file, el->automaton);
7791 else
7793 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7794 output_chip_member_name (output_file, el->automaton);
7796 fprintf (output_file, " = ");
7797 output_trans_comb_vect_name (output_file, el->automaton);
7798 fprintf (output_file, " [%s];\n", TEMPORARY_VARIABLE_NAME);
7800 else
7802 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
7803 output_trans_full_vect_name (output_file, el->automaton);
7804 fprintf (output_file, " [");
7805 output_translate_vect_name (output_file, el->automaton);
7806 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
7807 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7808 output_chip_member_name (output_file, el->automaton);
7809 fprintf (output_file, " * %d];\n",
7810 el->automaton->insn_equiv_classes_num);
7811 fprintf (output_file, " if (%s >= %d)\n",
7812 TEMPORARY_VARIABLE_NAME, el->automaton->achieved_states_num);
7813 fprintf (output_file, " return %s (%s, %s);\n",
7814 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7815 CHIP_PARAMETER_NAME);
7816 fprintf (output_file, " else\n ");
7817 if (el->next_automata_list_el != NULL)
7818 output_temp_chip_member_name (output_file, el->automaton);
7819 else
7821 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7822 output_chip_member_name (output_file, el->automaton);
7824 fprintf (output_file, " = %s;\n", TEMPORARY_VARIABLE_NAME);
7826 if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
7827 for (el = automata_list;; el = next_el)
7829 next_el = el->next_automata_list_el;
7830 if (next_el == NULL)
7831 break;
7832 fprintf (output_file, " %s->", CHIP_PARAMETER_NAME);
7833 output_chip_member_name (output_file, el->automaton);
7834 fprintf (output_file, " = ");
7835 output_temp_chip_member_name (output_file, el->automaton);
7836 fprintf (output_file, ";\n");
7838 fprintf (output_file, " return -1;\n");
7839 fprintf (output_file, " }\n");
7842 /* Output function `internal_state_transition'. */
7843 static void
7844 output_internal_trans_func (void)
7846 fprintf (output_file,
7847 "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
7848 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7849 CHIP_NAME, CHIP_PARAMETER_NAME);
7850 fprintf (output_file, "{\n int %s ATTRIBUTE_UNUSED;\n", TEMPORARY_VARIABLE_NAME);
7851 fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
7852 output_insn_code_cases (output_automata_list_transition_code);
7853 fprintf (output_file, "\n default:\n return -1;\n }\n");
7854 fprintf (output_file, "}\n\n");
7857 /* Output code
7859 if (insn != 0)
7861 insn_code = dfa_insn_code (insn);
7862 if (insn_code > DFA__ADVANCE_CYCLE)
7863 return code;
7865 else
7866 insn_code = DFA__ADVANCE_CYCLE;
7868 where insn denotes INSN_NAME, insn_code denotes INSN_CODE_NAME, and
7869 code denotes CODE. */
7870 static void
7871 output_internal_insn_code_evaluation (const char *insn_name,
7872 const char *insn_code_name,
7873 int code)
7875 fprintf (output_file, "\n if (%s != 0)\n {\n", insn_name);
7876 fprintf (output_file, " %s = %s (%s);\n", insn_code_name,
7877 DFA_INSN_CODE_FUNC_NAME, insn_name);
7878 fprintf (output_file, " if (%s > %s)\n return %d;\n",
7879 insn_code_name, ADVANCE_CYCLE_VALUE_NAME, code);
7880 fprintf (output_file, " }\n else\n %s = %s;\n\n",
7881 insn_code_name, ADVANCE_CYCLE_VALUE_NAME);
7885 /* This function outputs `dfa_insn_code' and its helper function
7886 `dfa_insn_code_enlarge'. */
7887 static void
7888 output_dfa_insn_code_func (void)
7890 /* Emacs c-mode gets really confused if there's a { or } in column 0
7891 inside a string, so don't do that. */
7892 fprintf (output_file, "\
7893 static void\n\
7894 dfa_insn_code_enlarge (int uid)\n\
7895 {\n\
7896 int i = %s;\n\
7897 %s = 2 * uid;\n\
7898 %s = xrealloc (%s,\n\
7899 %s * sizeof(int));\n\
7900 for (; i < %s; i++)\n\
7901 %s[i] = -1;\n}\n\n",
7902 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
7903 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
7904 DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
7905 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
7906 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
7907 DFA_INSN_CODES_VARIABLE_NAME);
7908 fprintf (output_file, "\
7909 static inline int\n%s (rtx %s)\n\
7910 {\n\
7911 int uid = INSN_UID (%s);\n\
7912 int %s;\n\n",
7913 DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME,
7914 INSN_PARAMETER_NAME, INTERNAL_INSN_CODE_NAME);
7916 fprintf (output_file,
7917 " if (uid >= %s)\n dfa_insn_code_enlarge (uid);\n\n",
7918 DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
7919 fprintf (output_file, " %s = %s[uid];\n",
7920 INTERNAL_INSN_CODE_NAME, DFA_INSN_CODES_VARIABLE_NAME);
7921 fprintf (output_file, "\
7922 if (%s < 0)\n\
7923 {\n\
7924 %s = %s (%s);\n\
7925 %s[uid] = %s;\n\
7926 }\n",
7927 INTERNAL_INSN_CODE_NAME,
7928 INTERNAL_INSN_CODE_NAME,
7929 INTERNAL_DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME,
7930 DFA_INSN_CODES_VARIABLE_NAME, INTERNAL_INSN_CODE_NAME);
7931 fprintf (output_file, " return %s;\n}\n\n", INTERNAL_INSN_CODE_NAME);
7934 /* The function outputs PHR interface function `state_transition'. */
7935 static void
7936 output_trans_func (void)
7938 fprintf (output_file, "int\n%s (%s %s, rtx %s)\n",
7939 TRANSITION_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME,
7940 INSN_PARAMETER_NAME);
7941 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
7942 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
7943 INTERNAL_INSN_CODE_NAME, -1);
7944 fprintf (output_file, " return %s (%s, %s);\n}\n\n",
7945 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, STATE_NAME);
7948 /* Output function `min_issue_delay'. */
7949 static void
7950 output_min_issue_delay_func (void)
7952 fprintf (output_file, "int\n%s (%s %s, rtx %s)\n",
7953 MIN_ISSUE_DELAY_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME,
7954 INSN_PARAMETER_NAME);
7955 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
7956 fprintf (output_file, "\n if (%s != 0)\n {\n", INSN_PARAMETER_NAME);
7957 fprintf (output_file, " %s = %s (%s);\n", INTERNAL_INSN_CODE_NAME,
7958 DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME);
7959 fprintf (output_file, " if (%s > %s)\n return 0;\n",
7960 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
7961 fprintf (output_file, " }\n else\n %s = %s;\n",
7962 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
7963 fprintf (output_file, "\n return %s (%s, %s);\n",
7964 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7965 STATE_NAME);
7966 fprintf (output_file, "}\n\n");
7969 /* Output function `internal_dead_lock'. */
7970 static void
7971 output_internal_dead_lock_func (void)
7973 automaton_t automaton;
7975 fprintf (output_file, "static int\n%s (struct %s *ARG_UNUSED (%s))\n",
7976 INTERNAL_DEAD_LOCK_FUNC_NAME, CHIP_NAME, CHIP_PARAMETER_NAME);
7977 fprintf (output_file, "{\n");
7978 for (automaton = description->first_automaton;
7979 automaton != NULL;
7980 automaton = automaton->next_automaton)
7981 if (automaton->locked_states)
7983 fprintf (output_file, " if (");
7984 output_dead_lock_vect_name (output_file, automaton);
7985 fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
7986 output_chip_member_name (output_file, automaton);
7987 fprintf (output_file, "])\n return 1/* TRUE */;\n");
7989 fprintf (output_file, " return 0/* FALSE */;\n}\n\n");
7992 /* The function outputs PHR interface function `state_dead_lock_p'. */
7993 static void
7994 output_dead_lock_func (void)
7996 fprintf (output_file, "int\n%s (%s %s)\n",
7997 DEAD_LOCK_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME);
7998 fprintf (output_file, "{\n return %s (%s);\n}\n\n",
7999 INTERNAL_DEAD_LOCK_FUNC_NAME, STATE_NAME);
8002 /* Output function `internal_reset'. */
8003 static void
8004 output_internal_reset_func (void)
8006 fprintf (output_file, "static inline void\n%s (struct %s *%s)\n",
8007 INTERNAL_RESET_FUNC_NAME, CHIP_NAME, CHIP_PARAMETER_NAME);
8008 fprintf (output_file, "{\n memset (%s, 0, sizeof (struct %s));\n}\n\n",
8009 CHIP_PARAMETER_NAME, CHIP_NAME);
8012 /* The function outputs PHR interface function `state_size'. */
8013 static void
8014 output_size_func (void)
8016 fprintf (output_file, "int\n%s (void)\n", SIZE_FUNC_NAME);
8017 fprintf (output_file, "{\n return sizeof (struct %s);\n}\n\n", CHIP_NAME);
8020 /* The function outputs PHR interface function `state_reset'. */
8021 static void
8022 output_reset_func (void)
8024 fprintf (output_file, "void\n%s (%s %s)\n",
8025 RESET_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME);
8026 fprintf (output_file, "{\n %s (%s);\n}\n\n", INTERNAL_RESET_FUNC_NAME,
8027 STATE_NAME);
8030 /* Output function `min_insn_conflict_delay'. */
8031 static void
8032 output_min_insn_conflict_delay_func (void)
8034 fprintf (output_file,
8035 "int\n%s (%s %s, rtx %s, rtx %s)\n",
8036 MIN_INSN_CONFLICT_DELAY_FUNC_NAME, STATE_TYPE_NAME,
8037 STATE_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8038 fprintf (output_file, "{\n struct %s %s;\n int %s, %s, transition;\n",
8039 CHIP_NAME, CHIP_NAME, INTERNAL_INSN_CODE_NAME,
8040 INTERNAL_INSN2_CODE_NAME);
8041 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8042 INTERNAL_INSN_CODE_NAME, 0);
8043 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
8044 INTERNAL_INSN2_CODE_NAME, 0);
8045 fprintf (output_file, " memcpy (&%s, %s, sizeof (%s));\n",
8046 CHIP_NAME, STATE_NAME, CHIP_NAME);
8047 fprintf (output_file, " %s (&%s);\n", INTERNAL_RESET_FUNC_NAME, CHIP_NAME);
8048 fprintf (output_file, " transition = %s (%s, &%s);\n",
8049 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME);
8050 fprintf (output_file, " gcc_assert (transition <= 0);\n");
8051 fprintf (output_file, " return %s (%s, &%s);\n",
8052 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN2_CODE_NAME,
8053 CHIP_NAME);
8054 fprintf (output_file, "}\n\n");
8057 /* Output function `internal_insn_latency'. */
8058 static void
8059 output_internal_insn_latency_func (void)
8061 decl_t decl;
8062 struct bypass_decl *bypass;
8063 int i, j, col;
8064 const char *tabletype = "unsigned char";
8066 /* Find the smallest integer type that can hold all the default
8067 latency values. */
8068 for (i = 0; i < description->decls_num; i++)
8069 if (description->decls[i]->mode == dm_insn_reserv)
8071 decl = description->decls[i];
8072 if (DECL_INSN_RESERV (decl)->default_latency > UCHAR_MAX
8073 && tabletype[0] != 'i') /* Don't shrink it. */
8074 tabletype = "unsigned short";
8075 if (DECL_INSN_RESERV (decl)->default_latency > USHRT_MAX)
8076 tabletype = "int";
8079 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",
8080 INTERNAL_INSN_LATENCY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8081 INTERNAL_INSN2_CODE_NAME, INSN_PARAMETER_NAME,
8082 INSN2_PARAMETER_NAME);
8083 fprintf (output_file, "{\n");
8085 if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8087 fputs (" return 0;\n}\n\n", output_file);
8088 return;
8091 fprintf (output_file, " static const %s default_latencies[] =\n {",
8092 tabletype);
8094 for (i = 0, j = 0, col = 7; i < description->decls_num; i++)
8095 if (description->decls[i]->mode == dm_insn_reserv
8096 && description->decls[i] != advance_cycle_insn_decl)
8098 if ((col = (col+1) % 8) == 0)
8099 fputs ("\n ", output_file);
8100 decl = description->decls[i];
8101 gcc_assert (j++ == DECL_INSN_RESERV (decl)->insn_num);
8102 fprintf (output_file, "% 4d,",
8103 DECL_INSN_RESERV (decl)->default_latency);
8105 gcc_assert (j == DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
8106 fputs ("\n };\n", output_file);
8108 fprintf (output_file, " if (%s >= %s || %s >= %s)\n return 0;\n",
8109 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8110 INTERNAL_INSN2_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8112 fprintf (output_file, " switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8113 for (i = 0; i < description->decls_num; i++)
8114 if (description->decls[i]->mode == dm_insn_reserv
8115 && DECL_INSN_RESERV (description->decls[i])->bypass_list)
8117 decl = description->decls [i];
8118 fprintf (output_file,
8119 " case %d:\n switch (%s)\n {\n",
8120 DECL_INSN_RESERV (decl)->insn_num,
8121 INTERNAL_INSN2_CODE_NAME);
8122 for (bypass = DECL_INSN_RESERV (decl)->bypass_list;
8123 bypass != NULL;
8124 bypass = bypass->next)
8126 gcc_assert (bypass->in_insn_reserv->insn_num
8127 != (DECL_INSN_RESERV
8128 (advance_cycle_insn_decl)->insn_num));
8129 fprintf (output_file, " case %d:\n",
8130 bypass->in_insn_reserv->insn_num);
8131 if (bypass->bypass_guard_name == NULL)
8132 fprintf (output_file, " return %d;\n",
8133 bypass->latency);
8134 else
8136 fprintf (output_file,
8137 " if (%s (%s, %s))\n",
8138 bypass->bypass_guard_name, INSN_PARAMETER_NAME,
8139 INSN2_PARAMETER_NAME);
8140 fprintf (output_file,
8141 " return %d;\n break;\n",
8142 bypass->latency);
8145 fputs (" }\n break;\n", output_file);
8148 fprintf (output_file, " }\n return default_latencies[%s];\n}\n\n",
8149 INTERNAL_INSN_CODE_NAME);
8152 /* The function outputs PHR interface function `insn_latency'. */
8153 static void
8154 output_insn_latency_func (void)
8156 fprintf (output_file, "int\n%s (rtx %s, rtx %s)\n",
8157 INSN_LATENCY_FUNC_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8158 fprintf (output_file, "{\n int %s, %s;\n",
8159 INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME);
8160 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8161 INTERNAL_INSN_CODE_NAME, 0);
8162 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
8163 INTERNAL_INSN2_CODE_NAME, 0);
8164 fprintf (output_file, " return %s (%s, %s, %s, %s);\n}\n\n",
8165 INTERNAL_INSN_LATENCY_FUNC_NAME,
8166 INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME,
8167 INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8170 /* The function outputs PHR interface function `print_reservation'. */
8171 static void
8172 output_print_reservation_func (void)
8174 decl_t decl;
8175 int i, j;
8177 fprintf (output_file,
8178 "void\n%s (FILE *%s, rtx %s ATTRIBUTE_UNUSED)\n{\n",
8179 PRINT_RESERVATION_FUNC_NAME, FILE_PARAMETER_NAME,
8180 INSN_PARAMETER_NAME);
8182 if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8184 fprintf (output_file, " fputs (\"%s\", %s);\n}\n\n",
8185 NOTHING_NAME, FILE_PARAMETER_NAME);
8186 return;
8190 fputs (" static const char *const reservation_names[] =\n {",
8191 output_file);
8193 for (i = 0, j = 0; i < description->decls_num; i++)
8195 decl = description->decls [i];
8196 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
8198 gcc_assert (j == DECL_INSN_RESERV (decl)->insn_num);
8199 j++;
8201 fprintf (output_file, "\n \"%s\",",
8202 regexp_representation (DECL_INSN_RESERV (decl)->regexp));
8203 finish_regexp_representation ();
8206 gcc_assert (j == DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
8208 fprintf (output_file, "\n \"%s\"\n };\n int %s;\n\n",
8209 NOTHING_NAME, INTERNAL_INSN_CODE_NAME);
8211 fprintf (output_file, " if (%s == 0)\n %s = %s;\n",
8212 INSN_PARAMETER_NAME,
8213 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8214 fprintf (output_file, " else\n\
8215 {\n\
8216 %s = %s (%s);\n\
8217 if (%s > %s)\n\
8218 %s = %s;\n\
8219 }\n",
8220 INTERNAL_INSN_CODE_NAME, DFA_INSN_CODE_FUNC_NAME,
8221 INSN_PARAMETER_NAME,
8222 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8223 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8225 fprintf (output_file, " fputs (reservation_names[%s], %s);\n}\n\n",
8226 INTERNAL_INSN_CODE_NAME, FILE_PARAMETER_NAME);
8229 /* The following function is used to sort unit declaration by their
8230 names. */
8231 static int
8232 units_cmp (const void *unit1, const void *unit2)
8234 const unit_decl_t u1 = *(unit_decl_t *) unit1;
8235 const unit_decl_t u2 = *(unit_decl_t *) unit2;
8237 return strcmp (u1->name, u2->name);
8240 /* The following macro value is name of struct containing unit name
8241 and unit code. */
8242 #define NAME_CODE_STRUCT_NAME "name_code"
8244 /* The following macro value is name of table of struct name_code. */
8245 #define NAME_CODE_TABLE_NAME "name_code_table"
8247 /* The following macro values are member names for struct name_code. */
8248 #define NAME_MEMBER_NAME "name"
8249 #define CODE_MEMBER_NAME "code"
8251 /* The following macro values are local variable names for function
8252 `get_cpu_unit_code'. */
8253 #define CMP_VARIABLE_NAME "cmp"
8254 #define LOW_VARIABLE_NAME "l"
8255 #define MIDDLE_VARIABLE_NAME "m"
8256 #define HIGH_VARIABLE_NAME "h"
8258 /* The following function outputs function to obtain internal cpu unit
8259 code by the cpu unit name. */
8260 static void
8261 output_get_cpu_unit_code_func (void)
8263 int i;
8264 unit_decl_t *units;
8266 fprintf (output_file, "int\n%s (const char *%s)\n",
8267 GET_CPU_UNIT_CODE_FUNC_NAME, CPU_UNIT_NAME_PARAMETER_NAME);
8268 fprintf (output_file, "{\n struct %s {const char *%s; int %s;};\n",
8269 NAME_CODE_STRUCT_NAME, NAME_MEMBER_NAME, CODE_MEMBER_NAME);
8270 fprintf (output_file, " int %s, %s, %s, %s;\n", CMP_VARIABLE_NAME,
8271 LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8272 fprintf (output_file, " static struct %s %s [] =\n {\n",
8273 NAME_CODE_STRUCT_NAME, NAME_CODE_TABLE_NAME);
8274 units = xmalloc (sizeof (unit_decl_t) * description->units_num);
8275 memcpy (units, units_array, sizeof (unit_decl_t) * description->units_num);
8276 qsort (units, description->units_num, sizeof (unit_decl_t), units_cmp);
8277 for (i = 0; i < description->units_num; i++)
8278 if (units [i]->query_p)
8279 fprintf (output_file, " {\"%s\", %d},\n",
8280 units[i]->name, units[i]->query_num);
8281 fprintf (output_file, " };\n\n");
8282 fprintf (output_file, " /* The following is binary search: */\n");
8283 fprintf (output_file, " %s = 0;\n", LOW_VARIABLE_NAME);
8284 fprintf (output_file, " %s = sizeof (%s) / sizeof (struct %s) - 1;\n",
8285 HIGH_VARIABLE_NAME, NAME_CODE_TABLE_NAME, NAME_CODE_STRUCT_NAME);
8286 fprintf (output_file, " while (%s <= %s)\n {\n",
8287 LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8288 fprintf (output_file, " %s = (%s + %s) / 2;\n",
8289 MIDDLE_VARIABLE_NAME, LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8290 fprintf (output_file, " %s = strcmp (%s, %s [%s].%s);\n",
8291 CMP_VARIABLE_NAME, CPU_UNIT_NAME_PARAMETER_NAME,
8292 NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, NAME_MEMBER_NAME);
8293 fprintf (output_file, " if (%s < 0)\n", CMP_VARIABLE_NAME);
8294 fprintf (output_file, " %s = %s - 1;\n",
8295 HIGH_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
8296 fprintf (output_file, " else if (%s > 0)\n", CMP_VARIABLE_NAME);
8297 fprintf (output_file, " %s = %s + 1;\n",
8298 LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
8299 fprintf (output_file, " else\n");
8300 fprintf (output_file, " return %s [%s].%s;\n }\n",
8301 NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, CODE_MEMBER_NAME);
8302 fprintf (output_file, " return -1;\n}\n\n");
8303 free (units);
8306 /* The following function outputs function to check reservation of cpu
8307 unit (its internal code will be passed as the function argument) in
8308 given cpu state. */
8309 static void
8310 output_cpu_unit_reservation_p (void)
8312 automaton_t automaton;
8314 fprintf (output_file, "int\n%s (%s %s, int %s)\n",
8315 CPU_UNIT_RESERVATION_P_FUNC_NAME,
8316 STATE_TYPE_NAME, STATE_NAME,
8317 CPU_CODE_PARAMETER_NAME);
8318 fprintf (output_file, "{\n gcc_assert (%s >= 0 && %s < %d);\n",
8319 CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME,
8320 description->query_units_num);
8321 if (description->query_units_num > 0)
8322 for (automaton = description->first_automaton;
8323 automaton != NULL;
8324 automaton = automaton->next_automaton)
8326 fprintf (output_file, " if ((");
8327 output_reserved_units_table_name (output_file, automaton);
8328 fprintf (output_file, " [((struct %s *) %s)->", CHIP_NAME, STATE_NAME);
8329 output_chip_member_name (output_file, automaton);
8330 fprintf (output_file, " * %d + %s / 8] >> (%s %% 8)) & 1)\n",
8331 (description->query_units_num + 7) / 8,
8332 CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME);
8333 fprintf (output_file, " return 1;\n");
8335 fprintf (output_file, " return 0;\n}\n\n");
8338 /* The function outputs PHR interface function `dfa_clean_insn_cache'. */
8339 static void
8340 output_dfa_clean_insn_cache_func (void)
8342 fprintf (output_file,
8343 "void\n%s (void)\n{\n int %s;\n\n",
8344 DFA_CLEAN_INSN_CACHE_FUNC_NAME, I_VARIABLE_NAME);
8345 fprintf (output_file,
8346 " for (%s = 0; %s < %s; %s++)\n %s [%s] = -1;\n}\n\n",
8347 I_VARIABLE_NAME, I_VARIABLE_NAME,
8348 DFA_INSN_CODES_LENGTH_VARIABLE_NAME, I_VARIABLE_NAME,
8349 DFA_INSN_CODES_VARIABLE_NAME, I_VARIABLE_NAME);
8352 /* The function outputs PHR interface function `dfa_start'. */
8353 static void
8354 output_dfa_start_func (void)
8356 fprintf (output_file,
8357 "void\n%s (void)\n{\n %s = get_max_uid ();\n",
8358 DFA_START_FUNC_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8359 fprintf (output_file, " %s = xmalloc (%s * sizeof (int));\n",
8360 DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8361 fprintf (output_file, " %s ();\n}\n\n", DFA_CLEAN_INSN_CACHE_FUNC_NAME);
8364 /* The function outputs PHR interface function `dfa_finish'. */
8365 static void
8366 output_dfa_finish_func (void)
8368 fprintf (output_file, "void\n%s (void)\n{\n free (%s);\n}\n\n",
8369 DFA_FINISH_FUNC_NAME, DFA_INSN_CODES_VARIABLE_NAME);
8374 /* The page contains code for output description file (readable
8375 representation of original description and generated DFA(s). */
8377 /* The function outputs string representation of IR reservation. */
8378 static void
8379 output_regexp (regexp_t regexp)
8381 fprintf (output_description_file, "%s", regexp_representation (regexp));
8382 finish_regexp_representation ();
8385 /* Output names of units in LIST separated by comma. */
8386 static void
8387 output_unit_set_el_list (unit_set_el_t list)
8389 unit_set_el_t el;
8391 for (el = list; el != NULL; el = el->next_unit_set_el)
8393 if (el != list)
8394 fprintf (output_description_file, ", ");
8395 fprintf (output_description_file, "%s", el->unit_decl->name);
8399 /* Output patterns in LIST separated by comma. */
8400 static void
8401 output_pattern_set_el_list (pattern_set_el_t list)
8403 pattern_set_el_t el;
8404 int i;
8406 for (el = list; el != NULL; el = el->next_pattern_set_el)
8408 if (el != list)
8409 fprintf (output_description_file, ", ");
8410 for (i = 0; i < el->units_num; i++)
8411 fprintf (output_description_file, (i == 0 ? "%s" : " %s"),
8412 el->unit_decls [i]->name);
8416 /* The function outputs string representation of IR define_reservation
8417 and define_insn_reservation. */
8418 static void
8419 output_description (void)
8421 decl_t decl;
8422 int i;
8424 for (i = 0; i < description->decls_num; i++)
8426 decl = description->decls [i];
8427 if (decl->mode == dm_unit)
8429 if (DECL_UNIT (decl)->excl_list != NULL)
8431 fprintf (output_description_file, "unit %s exlusion_set: ",
8432 DECL_UNIT (decl)->name);
8433 output_unit_set_el_list (DECL_UNIT (decl)->excl_list);
8434 fprintf (output_description_file, "\n");
8436 if (DECL_UNIT (decl)->presence_list != NULL)
8438 fprintf (output_description_file, "unit %s presence_set: ",
8439 DECL_UNIT (decl)->name);
8440 output_pattern_set_el_list (DECL_UNIT (decl)->presence_list);
8441 fprintf (output_description_file, "\n");
8443 if (DECL_UNIT (decl)->final_presence_list != NULL)
8445 fprintf (output_description_file, "unit %s final_presence_set: ",
8446 DECL_UNIT (decl)->name);
8447 output_pattern_set_el_list
8448 (DECL_UNIT (decl)->final_presence_list);
8449 fprintf (output_description_file, "\n");
8451 if (DECL_UNIT (decl)->absence_list != NULL)
8453 fprintf (output_description_file, "unit %s absence_set: ",
8454 DECL_UNIT (decl)->name);
8455 output_pattern_set_el_list (DECL_UNIT (decl)->absence_list);
8456 fprintf (output_description_file, "\n");
8458 if (DECL_UNIT (decl)->final_absence_list != NULL)
8460 fprintf (output_description_file, "unit %s final_absence_set: ",
8461 DECL_UNIT (decl)->name);
8462 output_pattern_set_el_list
8463 (DECL_UNIT (decl)->final_absence_list);
8464 fprintf (output_description_file, "\n");
8468 fprintf (output_description_file, "\n");
8469 for (i = 0; i < description->decls_num; i++)
8471 decl = description->decls [i];
8472 if (decl->mode == dm_reserv)
8474 fprintf (output_description_file, "reservation %s: ",
8475 DECL_RESERV (decl)->name);
8476 output_regexp (DECL_RESERV (decl)->regexp);
8477 fprintf (output_description_file, "\n");
8479 else if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
8481 fprintf (output_description_file, "insn reservation %s ",
8482 DECL_INSN_RESERV (decl)->name);
8483 print_rtl (output_description_file,
8484 DECL_INSN_RESERV (decl)->condexp);
8485 fprintf (output_description_file, ": ");
8486 output_regexp (DECL_INSN_RESERV (decl)->regexp);
8487 fprintf (output_description_file, "\n");
8489 else if (decl->mode == dm_bypass)
8490 fprintf (output_description_file, "bypass %d %s %s\n",
8491 DECL_BYPASS (decl)->latency,
8492 DECL_BYPASS (decl)->out_insn_name,
8493 DECL_BYPASS (decl)->in_insn_name);
8495 fprintf (output_description_file, "\n\f\n");
8498 /* The function outputs name of AUTOMATON. */
8499 static void
8500 output_automaton_name (FILE *f, automaton_t automaton)
8502 if (automaton->corresponding_automaton_decl == NULL)
8503 fprintf (f, "#%d", automaton->automaton_order_num);
8504 else
8505 fprintf (f, "`%s'", automaton->corresponding_automaton_decl->name);
8508 /* Maximal length of line for pretty printing into description
8509 file. */
8510 #define MAX_LINE_LENGTH 70
8512 /* The function outputs units name belonging to AUTOMATON. */
8513 static void
8514 output_automaton_units (automaton_t automaton)
8516 decl_t decl;
8517 const char *name;
8518 int curr_line_length;
8519 int there_is_an_automaton_unit;
8520 int i;
8522 fprintf (output_description_file, "\n Corresponding units:\n");
8523 fprintf (output_description_file, " ");
8524 curr_line_length = 4;
8525 there_is_an_automaton_unit = 0;
8526 for (i = 0; i < description->decls_num; i++)
8528 decl = description->decls [i];
8529 if (decl->mode == dm_unit
8530 && (DECL_UNIT (decl)->corresponding_automaton_num
8531 == automaton->automaton_order_num))
8533 there_is_an_automaton_unit = 1;
8534 name = DECL_UNIT (decl)->name;
8535 if (curr_line_length + strlen (name) + 1 > MAX_LINE_LENGTH )
8537 curr_line_length = strlen (name) + 4;
8538 fprintf (output_description_file, "\n ");
8540 else
8542 curr_line_length += strlen (name) + 1;
8543 fprintf (output_description_file, " ");
8545 fprintf (output_description_file, "%s", name);
8548 if (!there_is_an_automaton_unit)
8549 fprintf (output_description_file, "<None>");
8550 fprintf (output_description_file, "\n\n");
8553 /* The following variable is used for forming array of all possible cpu unit
8554 reservations described by the current DFA state. */
8555 static VEC(reserv_sets_t,heap) *state_reservs;
8557 /* The function forms `state_reservs' for STATE. */
8558 static void
8559 add_state_reservs (state_t state)
8561 alt_state_t curr_alt_state;
8563 if (state->component_states != NULL)
8564 for (curr_alt_state = state->component_states;
8565 curr_alt_state != NULL;
8566 curr_alt_state = curr_alt_state->next_sorted_alt_state)
8567 add_state_reservs (curr_alt_state->state);
8568 else
8569 VEC_safe_push (reserv_sets_t,heap, state_reservs, state->reservs);
8572 /* The function outputs readable representation of all out arcs of
8573 STATE. */
8574 static void
8575 output_state_arcs (state_t state)
8577 arc_t arc;
8578 ainsn_t ainsn;
8579 const char *insn_name;
8580 int curr_line_length;
8582 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
8584 ainsn = arc->insn;
8585 gcc_assert (ainsn->first_insn_with_same_reservs);
8586 fprintf (output_description_file, " ");
8587 curr_line_length = 7;
8588 fprintf (output_description_file, "%2d: ", ainsn->insn_equiv_class_num);
8591 insn_name = ainsn->insn_reserv_decl->name;
8592 if (curr_line_length + strlen (insn_name) > MAX_LINE_LENGTH)
8594 if (ainsn != arc->insn)
8596 fprintf (output_description_file, ",\n ");
8597 curr_line_length = strlen (insn_name) + 6;
8599 else
8600 curr_line_length += strlen (insn_name);
8602 else
8604 curr_line_length += strlen (insn_name);
8605 if (ainsn != arc->insn)
8607 curr_line_length += 2;
8608 fprintf (output_description_file, ", ");
8611 fprintf (output_description_file, "%s", insn_name);
8612 ainsn = ainsn->next_same_reservs_insn;
8614 while (ainsn != NULL);
8615 fprintf (output_description_file, " %d \n",
8616 arc->to_state->order_state_num);
8618 fprintf (output_description_file, "\n");
8621 /* The following function is used for sorting possible cpu unit
8622 reservation of a DFA state. */
8623 static int
8624 state_reservs_cmp (const void *reservs_ptr_1, const void *reservs_ptr_2)
8626 return reserv_sets_cmp (*(reserv_sets_t *) reservs_ptr_1,
8627 *(reserv_sets_t *) reservs_ptr_2);
8630 /* The following function is used for sorting possible cpu unit
8631 reservation of a DFA state. */
8632 static void
8633 remove_state_duplicate_reservs (void)
8635 size_t i, j;
8637 for (i = 1, j = 0; i < VEC_length (reserv_sets_t, state_reservs); i++)
8638 if (reserv_sets_cmp (VEC_index (reserv_sets_t, state_reservs, j),
8639 VEC_index (reserv_sets_t, state_reservs, i)))
8641 j++;
8642 VEC_replace (reserv_sets_t, state_reservs, j,
8643 VEC_index (reserv_sets_t, state_reservs, i));
8645 VEC_truncate (reserv_sets_t, state_reservs, j + 1);
8648 /* The following function output readable representation of DFA(s)
8649 state used for fast recognition of pipeline hazards. State is
8650 described by possible (current and scheduled) cpu unit
8651 reservations. */
8652 static void
8653 output_state (state_t state)
8655 size_t i;
8657 state_reservs = 0;
8659 fprintf (output_description_file, " State #%d", state->order_state_num);
8660 fprintf (output_description_file,
8661 state->new_cycle_p ? " (new cycle)\n" : "\n");
8662 add_state_reservs (state);
8663 qsort (VEC_address (reserv_sets_t, state_reservs),
8664 VEC_length (reserv_sets_t, state_reservs),
8665 sizeof (reserv_sets_t), state_reservs_cmp);
8666 remove_state_duplicate_reservs ();
8667 for (i = 1; i < VEC_length (reserv_sets_t, state_reservs); i++)
8669 fprintf (output_description_file, " ");
8670 output_reserv_sets (output_description_file,
8671 VEC_index (reserv_sets_t, state_reservs, i));
8672 fprintf (output_description_file, "\n");
8674 fprintf (output_description_file, "\n");
8675 output_state_arcs (state);
8676 VEC_free (reserv_sets_t,heap, state_reservs);
8679 /* The following function output readable representation of
8680 DFAs used for fast recognition of pipeline hazards. */
8681 static void
8682 output_automaton_descriptions (void)
8684 automaton_t automaton;
8686 for (automaton = description->first_automaton;
8687 automaton != NULL;
8688 automaton = automaton->next_automaton)
8690 fprintf (output_description_file, "\nAutomaton ");
8691 output_automaton_name (output_description_file, automaton);
8692 fprintf (output_description_file, "\n");
8693 output_automaton_units (automaton);
8694 pass_states (automaton, output_state);
8700 /* The page contains top level function for generation DFA(s) used for
8701 PHR. */
8703 /* The function outputs statistics about work of different phases of
8704 DFA generator. */
8705 static void
8706 output_statistics (FILE *f)
8708 automaton_t automaton;
8709 int states_num;
8710 #ifndef NDEBUG
8711 int transition_comb_vect_els = 0;
8712 int transition_full_vect_els = 0;
8713 int min_issue_delay_vect_els = 0;
8714 int locked_states = 0;
8715 #endif
8717 for (automaton = description->first_automaton;
8718 automaton != NULL;
8719 automaton = automaton->next_automaton)
8721 fprintf (f, "\nAutomaton ");
8722 output_automaton_name (f, automaton);
8723 fprintf (f, "\n %5d NDFA states, %5d NDFA arcs\n",
8724 automaton->NDFA_states_num, automaton->NDFA_arcs_num);
8725 fprintf (f, " %5d DFA states, %5d DFA arcs\n",
8726 automaton->DFA_states_num, automaton->DFA_arcs_num);
8727 states_num = automaton->DFA_states_num;
8728 if (!no_minimization_flag)
8730 fprintf (f, " %5d minimal DFA states, %5d minimal DFA arcs\n",
8731 automaton->minimal_DFA_states_num,
8732 automaton->minimal_DFA_arcs_num);
8733 states_num = automaton->minimal_DFA_states_num;
8735 fprintf (f, " %5d all insns %5d insn equivalence classes\n",
8736 description->insns_num, automaton->insn_equiv_classes_num);
8737 fprintf (f, " %d locked states\n", automaton->locked_states);
8738 #ifndef NDEBUG
8739 fprintf
8740 (f, "%5ld transition comb vector els, %5ld trans table els: %s\n",
8741 (long) VEC_length (vect_el_t, automaton->trans_table->comb_vect),
8742 (long) VEC_length (vect_el_t, automaton->trans_table->full_vect),
8743 (comb_vect_p (automaton->trans_table)
8744 ? "use comb vect" : "use simple vect"));
8745 fprintf
8746 (f, "%5ld min delay table els, compression factor %d\n",
8747 (long) states_num * automaton->insn_equiv_classes_num,
8748 automaton->min_issue_delay_table_compression_factor);
8749 transition_comb_vect_els
8750 += VEC_length (vect_el_t, automaton->trans_table->comb_vect);
8751 transition_full_vect_els
8752 += VEC_length (vect_el_t, automaton->trans_table->full_vect);
8753 min_issue_delay_vect_els
8754 += states_num * automaton->insn_equiv_classes_num;
8755 locked_states
8756 += automaton->locked_states;
8757 #endif
8759 #ifndef NDEBUG
8760 fprintf (f, "\n%5d all allocated states, %5d all allocated arcs\n",
8761 allocated_states_num, allocated_arcs_num);
8762 fprintf (f, "%5d all allocated alternative states\n",
8763 allocated_alt_states_num);
8764 fprintf (f, "%5d all transition comb vector els, %5d all trans table els\n",
8765 transition_comb_vect_els, transition_full_vect_els);
8766 fprintf (f, "%5d all min delay table els\n", min_issue_delay_vect_els);
8767 fprintf (f, "%5d all locked states\n", locked_states);
8768 #endif
8771 /* The function output times of work of different phases of DFA
8772 generator. */
8773 static void
8774 output_time_statistics (FILE *f)
8776 fprintf (f, "\n transformation: ");
8777 print_active_time (f, transform_time);
8778 fprintf (f, (!ndfa_flag ? ", building DFA: " : ", building NDFA: "));
8779 print_active_time (f, NDFA_time);
8780 if (ndfa_flag)
8782 fprintf (f, ", NDFA -> DFA: ");
8783 print_active_time (f, NDFA_to_DFA_time);
8785 fprintf (f, "\n DFA minimization: ");
8786 print_active_time (f, minimize_time);
8787 fprintf (f, ", making insn equivalence: ");
8788 print_active_time (f, equiv_time);
8789 fprintf (f, "\n all automaton generation: ");
8790 print_active_time (f, automaton_generation_time);
8791 fprintf (f, ", output: ");
8792 print_active_time (f, output_time);
8793 fprintf (f, "\n");
8796 /* The function generates DFA (deterministic finite state automaton)
8797 for fast recognition of pipeline hazards. No errors during
8798 checking must be fixed before this function call. */
8799 static void
8800 generate (void)
8802 automata_num = split_argument;
8803 if (description->units_num < automata_num)
8804 automata_num = description->units_num;
8805 initiate_states ();
8806 initiate_arcs ();
8807 initiate_automata_lists ();
8808 initiate_pass_states ();
8809 initiate_excl_sets ();
8810 initiate_presence_absence_pattern_sets ();
8811 automaton_generation_time = create_ticker ();
8812 create_automata ();
8813 ticker_off (&automaton_generation_time);
8818 /* This page mainly contains top level functions of pipeline hazards
8819 description translator. */
8821 /* The following macro value is suffix of name of description file of
8822 pipeline hazards description translator. */
8823 #define STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX ".dfa"
8825 /* The function returns suffix of given file name. The returned
8826 string can not be changed. */
8827 static const char *
8828 file_name_suffix (const char *file_name)
8830 const char *last_period;
8832 for (last_period = NULL; *file_name != '\0'; file_name++)
8833 if (*file_name == '.')
8834 last_period = file_name;
8835 return (last_period == NULL ? file_name : last_period);
8838 /* The function returns base name of given file name, i.e. pointer to
8839 first char after last `/' (or `\' for WIN32) in given file name,
8840 given file name itself if the directory name is absent. The
8841 returned string can not be changed. */
8842 static const char *
8843 base_file_name (const char *file_name)
8845 int directory_name_length;
8847 directory_name_length = strlen (file_name);
8848 #ifdef WIN32
8849 while (directory_name_length >= 0 && file_name[directory_name_length] != '/'
8850 && file_name[directory_name_length] != '\\')
8851 #else
8852 while (directory_name_length >= 0 && file_name[directory_name_length] != '/')
8853 #endif
8854 directory_name_length--;
8855 return file_name + directory_name_length + 1;
8858 /* The following is top level function to initialize the work of
8859 pipeline hazards description translator. */
8860 static void
8861 initiate_automaton_gen (int argc, char **argv)
8863 const char *base_name;
8864 int i;
8866 ndfa_flag = 0;
8867 split_argument = 0; /* default value */
8868 no_minimization_flag = 0;
8869 time_flag = 0;
8870 v_flag = 0;
8871 w_flag = 0;
8872 progress_flag = 0;
8873 for (i = 2; i < argc; i++)
8874 if (strcmp (argv [i], NO_MINIMIZATION_OPTION) == 0)
8875 no_minimization_flag = 1;
8876 else if (strcmp (argv [i], TIME_OPTION) == 0)
8877 time_flag = 1;
8878 else if (strcmp (argv [i], V_OPTION) == 0)
8879 v_flag = 1;
8880 else if (strcmp (argv [i], W_OPTION) == 0)
8881 w_flag = 1;
8882 else if (strcmp (argv [i], NDFA_OPTION) == 0)
8883 ndfa_flag = 1;
8884 else if (strcmp (argv [i], PROGRESS_OPTION) == 0)
8885 progress_flag = 1;
8886 else if (strcmp (argv [i], "-split") == 0)
8888 if (i + 1 >= argc)
8889 fatal ("-split has no argument.");
8890 fatal ("option `-split' has not been implemented yet\n");
8891 /* split_argument = atoi (argument_vect [i + 1]); */
8894 /* Initialize IR storage. */
8895 obstack_init (&irp);
8896 initiate_automaton_decl_table ();
8897 initiate_insn_decl_table ();
8898 initiate_decl_table ();
8899 output_file = stdout;
8900 output_description_file = NULL;
8901 base_name = base_file_name (argv[1]);
8902 obstack_grow (&irp, base_name,
8903 strlen (base_name) - strlen (file_name_suffix (base_name)));
8904 obstack_grow (&irp, STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX,
8905 strlen (STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX) + 1);
8906 obstack_1grow (&irp, '\0');
8907 output_description_file_name = obstack_base (&irp);
8908 obstack_finish (&irp);
8911 /* The following function checks existence at least one arc marked by
8912 each insn. */
8913 static void
8914 check_automata_insn_issues (void)
8916 automaton_t automaton;
8917 ainsn_t ainsn, reserv_ainsn;
8919 for (automaton = description->first_automaton;
8920 automaton != NULL;
8921 automaton = automaton->next_automaton)
8923 for (ainsn = automaton->ainsn_list;
8924 ainsn != NULL;
8925 ainsn = ainsn->next_ainsn)
8926 if (ainsn->first_insn_with_same_reservs && !ainsn->arc_exists_p)
8928 for (reserv_ainsn = ainsn;
8929 reserv_ainsn != NULL;
8930 reserv_ainsn = reserv_ainsn->next_same_reservs_insn)
8931 if (automaton->corresponding_automaton_decl != NULL)
8933 if (!w_flag)
8934 error ("Automaton `%s': Insn `%s' will never be issued",
8935 automaton->corresponding_automaton_decl->name,
8936 reserv_ainsn->insn_reserv_decl->name);
8937 else
8938 warning
8939 (0, "Automaton `%s': Insn `%s' will never be issued",
8940 automaton->corresponding_automaton_decl->name,
8941 reserv_ainsn->insn_reserv_decl->name);
8943 else
8945 if (!w_flag)
8946 error ("Insn `%s' will never be issued",
8947 reserv_ainsn->insn_reserv_decl->name);
8948 else
8949 warning (0, "Insn `%s' will never be issued",
8950 reserv_ainsn->insn_reserv_decl->name);
8956 /* The following vla is used for storing pointers to all achieved
8957 states. */
8958 static VEC(state_t,heap) *automaton_states;
8960 /* This function is called by function pass_states to add an achieved
8961 STATE. */
8962 static void
8963 add_automaton_state (state_t state)
8965 VEC_safe_push (state_t,heap, automaton_states, state);
8968 /* The following function forms list of important automata (whose
8969 states may be changed after the insn issue) for each insn. */
8970 static void
8971 form_important_insn_automata_lists (void)
8973 automaton_t automaton;
8974 decl_t decl;
8975 ainsn_t ainsn;
8976 arc_t arc;
8977 int i;
8978 size_t n;
8980 automaton_states = 0;
8981 /* Mark important ainsns. */
8982 for (automaton = description->first_automaton;
8983 automaton != NULL;
8984 automaton = automaton->next_automaton)
8986 VEC_truncate (state_t, automaton_states, 0);
8987 pass_states (automaton, add_automaton_state);
8988 for (n = 0; n < VEC_length (state_t, automaton_states); n++)
8990 state_t s = VEC_index (state_t, automaton_states, n);
8991 for (arc = first_out_arc (s);
8992 arc != NULL;
8993 arc = next_out_arc (arc))
8994 if (arc->to_state != s)
8996 gcc_assert (arc->insn->first_insn_with_same_reservs);
8997 for (ainsn = arc->insn;
8998 ainsn != NULL;
8999 ainsn = ainsn->next_same_reservs_insn)
9000 ainsn->important_p = TRUE;
9004 VEC_free (state_t,heap, automaton_states);
9006 /* Create automata sets for the insns. */
9007 for (i = 0; i < description->decls_num; i++)
9009 decl = description->decls [i];
9010 if (decl->mode == dm_insn_reserv)
9012 automata_list_start ();
9013 for (automaton = description->first_automaton;
9014 automaton != NULL;
9015 automaton = automaton->next_automaton)
9016 for (ainsn = automaton->ainsn_list;
9017 ainsn != NULL;
9018 ainsn = ainsn->next_ainsn)
9019 if (ainsn->important_p
9020 && ainsn->insn_reserv_decl == DECL_INSN_RESERV (decl))
9022 automata_list_add (automaton);
9023 break;
9025 DECL_INSN_RESERV (decl)->important_automata_list
9026 = automata_list_finish ();
9032 /* The following is top level function to generate automat(a,on) for
9033 fast recognition of pipeline hazards. */
9034 static void
9035 expand_automata (void)
9037 int i;
9039 description = create_node (sizeof (struct description)
9040 /* One entry for cycle advancing insn. */
9041 + sizeof (decl_t) * VEC_length (decl_t, decls));
9042 description->decls_num = VEC_length (decl_t, decls);
9043 description->query_units_num = 0;
9044 for (i = 0; i < description->decls_num; i++)
9046 description->decls [i] = VEC_index (decl_t, decls, i);
9047 if (description->decls [i]->mode == dm_unit
9048 && DECL_UNIT (description->decls [i])->query_p)
9049 DECL_UNIT (description->decls [i])->query_num
9050 = description->query_units_num++;
9052 all_time = create_ticker ();
9053 check_time = create_ticker ();
9054 if (progress_flag)
9055 fprintf (stderr, "Check description...");
9056 check_all_description ();
9057 if (progress_flag)
9058 fprintf (stderr, "done\n");
9059 ticker_off (&check_time);
9060 generation_time = create_ticker ();
9061 if (!have_error)
9063 transform_insn_regexps ();
9064 check_unit_distributions_to_automata ();
9066 if (!have_error)
9068 generate ();
9069 check_automata_insn_issues ();
9071 if (!have_error)
9073 form_important_insn_automata_lists ();
9075 ticker_off (&generation_time);
9078 /* The following is top level function to output PHR and to finish
9079 work with pipeline description translator. */
9080 static void
9081 write_automata (void)
9083 output_time = create_ticker ();
9084 if (progress_flag)
9085 fprintf (stderr, "Forming and outputting automata tables...");
9086 output_tables ();
9087 if (progress_flag)
9089 fprintf (stderr, "done\n");
9090 fprintf (stderr, "Output functions to work with automata...");
9092 output_chip_definitions ();
9093 output_max_insn_queue_index_def ();
9094 output_internal_min_issue_delay_func ();
9095 output_internal_trans_func ();
9096 /* Cache of insn dfa codes: */
9097 fprintf (output_file, "\nstatic int *%s;\n", DFA_INSN_CODES_VARIABLE_NAME);
9098 fprintf (output_file, "\nstatic int %s;\n\n",
9099 DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
9100 output_dfa_insn_code_func ();
9101 output_trans_func ();
9102 output_min_issue_delay_func ();
9103 output_internal_dead_lock_func ();
9104 output_dead_lock_func ();
9105 output_size_func ();
9106 output_internal_reset_func ();
9107 output_reset_func ();
9108 output_min_insn_conflict_delay_func ();
9109 output_internal_insn_latency_func ();
9110 output_insn_latency_func ();
9111 output_print_reservation_func ();
9112 /* Output function get_cpu_unit_code. */
9113 fprintf (output_file, "\n#if %s\n\n", CPU_UNITS_QUERY_MACRO_NAME);
9114 output_get_cpu_unit_code_func ();
9115 output_cpu_unit_reservation_p ();
9116 fprintf (output_file, "\n#endif /* #if %s */\n\n",
9117 CPU_UNITS_QUERY_MACRO_NAME);
9118 output_dfa_clean_insn_cache_func ();
9119 output_dfa_start_func ();
9120 output_dfa_finish_func ();
9121 if (progress_flag)
9122 fprintf (stderr, "done\n");
9123 if (v_flag)
9125 output_description_file = fopen (output_description_file_name, "w");
9126 if (output_description_file == NULL)
9128 perror (output_description_file_name);
9129 exit (FATAL_EXIT_CODE);
9131 if (progress_flag)
9132 fprintf (stderr, "Output automata description...");
9133 output_description ();
9134 output_automaton_descriptions ();
9135 if (progress_flag)
9136 fprintf (stderr, "done\n");
9137 output_statistics (output_description_file);
9139 output_statistics (stderr);
9140 ticker_off (&output_time);
9141 output_time_statistics (stderr);
9142 finish_states ();
9143 finish_arcs ();
9144 finish_automata_lists ();
9145 if (time_flag)
9147 fprintf (stderr, "Summary:\n");
9148 fprintf (stderr, " check time ");
9149 print_active_time (stderr, check_time);
9150 fprintf (stderr, ", generation time ");
9151 print_active_time (stderr, generation_time);
9152 fprintf (stderr, ", all time ");
9153 print_active_time (stderr, all_time);
9154 fprintf (stderr, "\n");
9156 /* Finish all work. */
9157 if (output_description_file != NULL)
9159 fflush (output_description_file);
9160 if (ferror (stdout) != 0)
9161 fatal ("Error in writing DFA description file %s",
9162 output_description_file_name);
9163 fclose (output_description_file);
9165 finish_automaton_decl_table ();
9166 finish_insn_decl_table ();
9167 finish_decl_table ();
9168 obstack_free (&irp, NULL);
9169 if (have_error && output_description_file != NULL)
9170 remove (output_description_file_name);
9174 main (int argc, char **argv)
9176 rtx desc;
9178 progname = "genautomata";
9180 if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
9181 return (FATAL_EXIT_CODE);
9183 initiate_automaton_gen (argc, argv);
9184 while (1)
9186 int lineno;
9187 int insn_code_number;
9189 desc = read_md_rtx (&lineno, &insn_code_number);
9190 if (desc == NULL)
9191 break;
9193 switch (GET_CODE (desc))
9195 case DEFINE_CPU_UNIT:
9196 gen_cpu_unit (desc);
9197 break;
9199 case DEFINE_QUERY_CPU_UNIT:
9200 gen_query_cpu_unit (desc);
9201 break;
9203 case DEFINE_BYPASS:
9204 gen_bypass (desc);
9205 break;
9207 case EXCLUSION_SET:
9208 gen_excl_set (desc);
9209 break;
9211 case PRESENCE_SET:
9212 gen_presence_set (desc);
9213 break;
9215 case FINAL_PRESENCE_SET:
9216 gen_final_presence_set (desc);
9217 break;
9219 case ABSENCE_SET:
9220 gen_absence_set (desc);
9221 break;
9223 case FINAL_ABSENCE_SET:
9224 gen_final_absence_set (desc);
9225 break;
9227 case DEFINE_AUTOMATON:
9228 gen_automaton (desc);
9229 break;
9231 case AUTOMATA_OPTION:
9232 gen_automata_option (desc);
9233 break;
9235 case DEFINE_RESERVATION:
9236 gen_reserv (desc);
9237 break;
9239 case DEFINE_INSN_RESERVATION:
9240 gen_insn_reserv (desc);
9241 break;
9243 default:
9244 break;
9248 if (have_error)
9249 return FATAL_EXIT_CODE;
9251 puts ("/* Generated automatically by the program `genautomata'\n"
9252 " from the machine description file `md'. */\n\n"
9253 "#include \"config.h\"\n"
9254 "#include \"system.h\"\n"
9255 "#include \"coretypes.h\"\n"
9256 "#include \"tm.h\"\n"
9257 "#include \"rtl.h\"\n"
9258 "#include \"tm_p.h\"\n"
9259 "#include \"insn-config.h\"\n"
9260 "#include \"recog.h\"\n"
9261 "#include \"regs.h\"\n"
9262 "#include \"real.h\"\n"
9263 "#include \"output.h\"\n"
9264 "#include \"insn-attr.h\"\n"
9265 "#include \"toplev.h\"\n"
9266 "#include \"flags.h\"\n"
9267 "#include \"function.h\"\n");
9269 if (VEC_length (decl_t, decls) > 0)
9271 expand_automata ();
9272 write_automata ();
9275 fflush (stdout);
9276 return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);