1 /* Pipeline hazard description translator.
2 Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007
3 Free Software Foundation, Inc.
5 Written by Vladimir Makarov <vmakarov@redhat.com>
7 This file is part of GCC.
9 GCC is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by the
11 Free Software Foundation; either version 3, or (at your option) any
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
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING3. If not see
21 <http://www.gnu.org/licenses/>. */
25 1. Detecting pipeline structural hazards quickly. T. Proebsting,
26 C. Fraser. Proceedings of ACM SIGPLAN-SIGACT Symposium on
27 Principles of Programming Languages, pages 280--286, 1994.
29 This article is a good start point to understand usage of finite
30 state automata for pipeline hazard recognizers. But I'd
31 recommend the 2nd article for more deep understanding.
33 2. Efficient Instruction Scheduling Using Finite State Automata:
34 V. Bala and N. Rubin, Proceedings of MICRO-28. This is the best
35 article about usage of finite state automata for pipeline hazard
38 The current implementation is different from the 2nd article in the
41 1. New operator `|' (alternative) is permitted in functional unit
42 reservation which can be treated deterministically and
43 non-deterministically.
45 2. Possibility of usage of nondeterministic automata too.
47 3. Possibility to query functional unit reservations for given
50 4. Several constructions to describe impossible reservations
51 (`exclusion_set', `presence_set', `final_presence_set',
52 `absence_set', and `final_absence_set').
54 5. No reverse automata are generated. Trace instruction scheduling
55 requires this. It can be easily added in the future if we
58 6. Union of automaton states are not generated yet. It is planned
59 to be implemented. Such feature is needed to make more accurate
60 interlock insn scheduling to get state describing functional
61 unit reservation in a joint CFG point. */
63 /* This file code processes constructions of machine description file
64 which describes automaton used for recognition of processor pipeline
65 hazards by insn scheduler and can be used for other tasks (such as
68 The translator functions `gen_cpu_unit', `gen_query_cpu_unit',
69 `gen_bypass', `gen_excl_set', `gen_presence_set',
70 `gen_final_presence_set', `gen_absence_set',
71 `gen_final_absence_set', `gen_automaton', `gen_automata_option',
72 `gen_reserv', `gen_insn_reserv' are called from file
73 `genattrtab.c'. They transform RTL constructions describing
74 automata in .md file into internal representation convenient for
77 The translator major function `expand_automata' processes the
78 description internal representation into finite state automaton.
81 o checking correctness of the automaton pipeline description
82 (major function is `check_all_description').
84 o generating automaton (automata) from the description (major
85 function is `make_automaton').
87 o optional transformation of nondeterministic finite state
88 automata into deterministic ones if the alternative operator
89 `|' is treated nondeterministically in the description (major
90 function is NDFA_to_DFA).
92 o optional minimization of the finite state automata by merging
93 equivalent automaton states (major function is `minimize_DFA').
95 o forming tables (some as comb vectors) and attributes
96 representing the automata (functions output_..._table).
98 Function `write_automata' outputs the created finite state
99 automaton as different tables and functions which works with the
100 automata to inquire automaton state and to change its state. These
101 function are used by gcc instruction scheduler and may be some
106 #include "coretypes.h"
111 #include "gensupport.h"
121 /* Positions in machine description file. Now they are not used. But
122 they could be used in the future for better diagnostic messages. */
125 /* The following is element of vector of current (and planned in the
126 future) functional unit reservations. */
127 typedef unsigned HOST_WIDE_INT set_el_t;
129 /* Reservations of function units are represented by value of the following
131 typedef set_el_t *reserv_sets_t;
132 typedef const set_el_t *const_reserv_sets_t;
134 /* The following structure describes a 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. */
158 struct automaton_decl;
159 struct unit_pattern_rel_decl;
161 struct insn_reserv_decl;
164 struct result_regexp;
165 struct reserv_regexp;
166 struct nothing_regexp;
167 struct sequence_regexp;
168 struct repeat_regexp;
174 struct pattern_set_el;
175 struct pattern_reserv;
181 struct state_ainsn_table;
183 /* The following typedefs are for brevity. */
184 typedef struct unit_decl *unit_decl_t;
185 typedef const struct unit_decl *const_unit_decl_t;
186 typedef struct decl *decl_t;
187 typedef const struct decl *const_decl_t;
188 typedef struct regexp *regexp_t;
189 typedef struct unit_set_el *unit_set_el_t;
190 typedef struct pattern_set_el *pattern_set_el_t;
191 typedef struct pattern_reserv *pattern_reserv_t;
192 typedef struct alt_state *alt_state_t;
193 typedef struct state *state_t;
194 typedef const struct state *const_state_t;
195 typedef struct arc *arc_t;
196 typedef struct ainsn *ainsn_t;
197 typedef struct automaton *automaton_t;
198 typedef struct automata_list_el *automata_list_el_t;
199 typedef const struct automata_list_el *const_automata_list_el_t;
200 typedef struct state_ainsn_table *state_ainsn_table_t;
202 /* Undefined position. */
203 static pos_t no_pos = 0;
205 /* All IR is stored in the following obstack. */
206 static struct obstack irp;
209 /* Declare vector types for various data structures: */
211 DEF_VEC_P(alt_state_t);
212 DEF_VEC_ALLOC_P(alt_state_t,heap);
214 DEF_VEC_ALLOC_P(ainsn_t,heap);
216 DEF_VEC_ALLOC_P(state_t,heap);
218 DEF_VEC_ALLOC_P(decl_t,heap);
219 DEF_VEC_P(reserv_sets_t);
220 DEF_VEC_ALLOC_P(reserv_sets_t,heap);
222 DEF_VEC_I(vect_el_t);
223 DEF_VEC_ALLOC_I(vect_el_t, heap);
224 typedef VEC(vect_el_t,heap) *vla_hwint_t;
226 /* Forward declarations of functions used before their definitions, only. */
227 static regexp_t gen_regexp_sequence (const char *);
228 static void reserv_sets_or (reserv_sets_t, reserv_sets_t,
230 static reserv_sets_t get_excl_set (reserv_sets_t);
231 static int check_presence_pattern_sets (reserv_sets_t,
233 static int check_absence_pattern_sets (reserv_sets_t, reserv_sets_t,
235 static arc_t first_out_arc (const_state_t);
236 static arc_t next_out_arc (arc_t);
240 /* Options with the following names can be set up in automata_option
241 construction. Because the strings occur more one time we use the
244 #define NO_MINIMIZATION_OPTION "-no-minimization"
245 #define TIME_OPTION "-time"
246 #define STATS_OPTION "-stats"
247 #define V_OPTION "-v"
248 #define W_OPTION "-w"
249 #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 automata statistics (`-stats'). */
271 static int stats_flag;
273 /* Flag of creation of description file which contains description of
274 result automaton and statistics information (`-v'). */
277 /* Flag of output of a progress bar showing how many states were
278 generated so far for automaton being processed (`-progress'). */
279 static int progress_flag;
281 /* Flag of generating warning instead of error for non-critical errors
286 /* Output file for pipeline hazard recognizer (PHR) being generated.
287 The value is NULL if the file is not defined. */
288 static FILE *output_file;
290 /* Description file of PHR. The value is NULL if the file is not
292 static FILE *output_description_file;
294 /* PHR description file name. */
295 static char *output_description_file_name;
297 /* Value of the following variable is node representing description
298 being processed. This is start point of IR. */
299 static struct description *description;
303 /* This page contains description of IR structure (nodes). */
317 /* This describes define_cpu_unit and define_query_cpu_unit (see file
322 /* NULL if the automaton name is absent. */
323 const char *automaton_name;
324 /* If the following value is not zero, the cpu unit reservation is
325 described in define_query_cpu_unit. */
328 /* The following fields are defined by checker. */
330 /* The following field value is nonzero if the unit is used in an
334 /* The following field value is order number (0, 1, ...) of given
337 /* The following field value is corresponding declaration of
338 automaton which was given in description. If the field value is
339 NULL then automaton in the unit declaration was absent. */
340 struct automaton_decl *automaton_decl;
341 /* The following field value is maximal cycle number (1, ...) on
342 which given unit occurs in insns. Zero value means that given
343 unit is not used in insns. */
344 int max_occ_cycle_num;
345 /* The following field value is minimal cycle number (0, ...) on
346 which given unit occurs in insns. -1 value means that given
347 unit is not used in insns. */
348 int min_occ_cycle_num;
349 /* The following list contains units which conflict with given
351 unit_set_el_t excl_list;
352 /* The following list contains patterns which are required to
353 reservation of given unit. */
354 pattern_set_el_t presence_list;
355 pattern_set_el_t final_presence_list;
356 /* The following list contains patterns which should be not present
357 in reservation for given unit. */
358 pattern_set_el_t absence_list;
359 pattern_set_el_t final_absence_list;
360 /* The following is used only when `query_p' has nonzero value.
361 This is query number for the unit. */
363 /* The following is the last cycle on which the unit was checked for
364 correct distributions of units to automata in a regexp. */
365 int last_distribution_check_cycle;
367 /* The following fields are defined by automaton generator. */
369 /* The following field value is number of the automaton to which
370 given unit belongs. */
371 int corresponding_automaton_num;
372 /* If the following value is not zero, the cpu unit is present in a
373 `exclusion_set' or in right part of a `presence_set',
374 `final_presence_set', `absence_set', and
375 `final_absence_set'define_query_cpu_unit. */
379 /* This describes define_bypass (see file rtl.def). */
383 const char *out_insn_name;
384 const char *in_insn_name;
385 const char *bypass_guard_name;
387 /* The following fields are defined by checker. */
389 /* output and input insns of given bypass. */
390 struct insn_reserv_decl *out_insn_reserv;
391 struct insn_reserv_decl *in_insn_reserv;
392 /* The next bypass for given output insn. */
393 struct bypass_decl *next;
396 /* This describes define_automaton (see file rtl.def). */
397 struct automaton_decl
401 /* The following fields are defined by automaton generator. */
403 /* The following field value is nonzero if the automaton is used in
404 an regexp definition. */
405 char automaton_is_used;
407 /* The following fields are defined by checker. */
409 /* The following field value is the corresponding automaton. This
410 field is not NULL only if the automaton is present in unit
411 declarations and the automatic partition on automata is not
413 automaton_t corresponding_automaton;
416 /* This describes exclusion relations: exclusion_set (see file
421 int first_list_length;
425 /* This describes unit relations: [final_]presence_set or
426 [final_]absence_set (see file rtl.def). */
427 struct unit_pattern_rel_decl
436 /* This describes define_reservation (see file rtl.def). */
442 /* The following fields are defined by checker. */
444 /* The following field value is nonzero if the unit is used in an
447 /* The following field is used to check up cycle in expression
452 /* This describes define_insn_reservation (see file rtl.def). */
453 struct insn_reserv_decl
460 /* The following fields are defined by checker. */
462 /* The following field value is order number (0, 1, ...) of given
465 /* The following field value is list of bypasses in which given insn
467 struct bypass_decl *bypass_list;
469 /* The following fields are defined by automaton generator. */
471 /* The following field is the insn regexp transformed that
472 the regexp has not optional regexp, repetition regexp, and an
473 reservation name (i.e. reservation identifiers are changed by the
474 corresponding regexp) and all alternations are the topest level
475 of the regexp. The value can be NULL only if it is special
476 insn `cycle advancing'. */
477 regexp_t transformed_regexp;
478 /* The following field value is list of arcs marked given
479 insn. The field is used in transformation NDFA -> DFA. */
480 arc_t arcs_marked_by_insn;
481 /* The two following fields are used during minimization of a finite state
483 /* The field value is number of equivalence class of state into
484 which arc marked by given insn enters from a state (fixed during
485 an automaton minimization). */
487 /* The following member value is the list to automata which can be
488 changed by the insn issue. */
489 automata_list_el_t important_automata_list;
490 /* The following member is used to process insn once for output. */
494 /* This contains a declaration mentioned above. */
497 /* What node in the union? */
502 struct unit_decl unit;
503 struct bypass_decl bypass;
504 struct automaton_decl automaton;
505 struct excl_rel_decl excl;
506 struct unit_pattern_rel_decl presence;
507 struct unit_pattern_rel_decl absence;
508 struct reserv_decl reserv;
509 struct insn_reserv_decl insn_reserv;
513 /* The following structures represent parsed reservation strings. */
525 /* Cpu unit in reservation. */
529 unit_decl_t unit_decl;
532 /* Define_reservation in a reservation. */
536 struct reserv_decl *reserv_decl;
539 /* Absence of reservation (represented by string `nothing'). */
540 struct nothing_regexp
542 /* This used to be empty but ISO C doesn't allow that. */
546 /* Representation of reservations separated by ',' (see file
548 struct sequence_regexp
551 regexp_t regexps [1];
554 /* Representation of construction `repeat' (see file rtl.def). */
561 /* Representation of reservations separated by '+' (see file
566 regexp_t regexps [1];
569 /* Representation of reservations separated by '|' (see file
574 regexp_t regexps [1];
577 /* Representation of a reservation string. */
580 /* What node in the union? */
581 enum regexp_mode mode;
585 struct unit_regexp unit;
586 struct reserv_regexp reserv;
587 struct nothing_regexp nothing;
588 struct sequence_regexp sequence;
589 struct repeat_regexp repeat;
590 struct allof_regexp allof;
591 struct oneof_regexp oneof;
595 /* Represents description of pipeline hazard description based on
601 /* The following fields are defined by checker. */
603 /* The following fields values are correspondingly number of all
604 units, query units, and insns in the description. */
608 /* The following field value is max length (in cycles) of
609 reservations of insns. The field value is defined only for
611 int max_insn_reserv_cycles;
613 /* The following fields are defined by automaton generator. */
615 /* The following field value is the first automaton. */
616 automaton_t first_automaton;
618 /* The following field is created by pipeline hazard parser and
619 contains all declarations. We allocate additional entry for
620 special insn "cycle advancing" which is added by the automaton
626 /* The following nodes are created in automaton checker. */
628 /* The following nodes represent exclusion set for cpu units. Each
629 element is accessed through only one excl_list. */
632 unit_decl_t unit_decl;
633 unit_set_el_t next_unit_set_el;
636 /* The following nodes represent presence or absence pattern for cpu
637 units. Each element is accessed through only one presence_list or
639 struct pattern_set_el
641 /* The number of units in unit_decls. */
643 /* The units forming the pattern. */
644 struct unit_decl **unit_decls;
645 pattern_set_el_t next_pattern_set_el;
649 /* The following nodes are created in automaton generator. */
652 /* The following nodes represent presence or absence pattern for cpu
653 units. Each element is accessed through only one element of
654 unit_presence_set_table or unit_absence_set_table. */
655 struct pattern_reserv
657 reserv_sets_t reserv;
658 pattern_reserv_t next_pattern_reserv;
661 /* The following node type describes state automaton. The state may
662 be deterministic or non-deterministic. Non-deterministic state has
663 several component states which represent alternative cpu units
664 reservations. The state also is used for describing a
665 deterministic reservation of automaton insn. */
668 /* The following member value is nonzero if there is a transition by
671 /* The following field is list of processor unit reservations on
673 reserv_sets_t reservs;
674 /* The following field is unique number of given state between other
677 /* The following field value is automaton to which given state
679 automaton_t automaton;
680 /* The following field value is the first arc output from given
683 unsigned int num_out_arcs;
684 /* The following field is used to form NDFA. */
685 char it_was_placed_in_stack_for_NDFA_forming;
686 /* The following field is used to form DFA. */
687 char it_was_placed_in_stack_for_DFA_forming;
688 /* The following field is used to transform NDFA to DFA and DFA
689 minimization. The field value is not NULL if the state is a
690 compound state. In this case the value of field `unit_sets_list'
691 is NULL. All states in the list are in the hash table. The list
692 is formed through field `next_sorted_alt_state'. We should
693 support only one level of nesting state. */
694 alt_state_t component_states;
695 /* The following field is used for passing graph of states. */
697 /* The list of states belonging to one equivalence class is formed
698 with the aid of the following field. */
699 state_t next_equiv_class_state;
700 /* The two following fields are used during minimization of a finite
702 int equiv_class_num_1, equiv_class_num_2;
703 /* The following field is used during minimization of a finite state
704 automaton. The field value is state corresponding to equivalence
705 class to which given state belongs. */
706 state_t equiv_class_state;
707 unsigned int *presence_signature;
708 /* The following field value is the order number of given state.
709 The states in final DFA is enumerated with the aid of the
712 /* This member is used for passing states for searching minimal
715 /* The following member is used to evaluate min issue delay of insn
717 int min_insn_issue_delay;
723 /* The following field refers for the state into which given arc
726 /* The following field describes that the insn issue (with cycle
727 advancing for special insn `cycle advancing' and without cycle
728 advancing for others) makes transition from given state to
729 another given state. */
731 /* The following field value is the next arc output from the same
734 /* List of arcs marked given insn is formed with the following
735 field. The field is used in transformation NDFA -> DFA. */
736 arc_t next_arc_marked_by_insn;
739 /* The following node type describes a deterministic alternative in
740 non-deterministic state which characterizes cpu unit reservations
741 of automaton insn or which is part of NDFA. */
744 /* The following field is a deterministic state which characterizes
745 unit reservations of the instruction. */
747 /* The following field refers to the next state which characterizes
748 unit reservations of the instruction. */
749 alt_state_t next_alt_state;
750 /* The following field refers to the next state in sorted list. */
751 alt_state_t next_sorted_alt_state;
754 /* The following node type describes insn of automaton. They are
755 labels of FA arcs. */
758 /* The following field value is the corresponding insn declaration
760 struct insn_reserv_decl *insn_reserv_decl;
761 /* The following field value is the next insn declaration for an
764 /* The following field is states which characterize automaton unit
765 reservations of the instruction. The value can be NULL only if it
766 is special insn `cycle advancing'. */
767 alt_state_t alt_states;
768 /* The following field is sorted list of states which characterize
769 automaton unit reservations of the instruction. The value can be
770 NULL only if it is special insn `cycle advancing'. */
771 alt_state_t sorted_alt_states;
772 /* The following field refers the next automaton insn with
773 the same reservations. */
774 ainsn_t next_same_reservs_insn;
775 /* The following field is flag of the first automaton insn with the
776 same reservations in the declaration list. Only arcs marked such
777 insn is present in the automaton. This significantly decreases
778 memory requirements especially when several automata are
780 char first_insn_with_same_reservs;
781 /* The following member has nonzero value if there is arc from state of
782 the automaton marked by the ainsn. */
784 /* Cyclic list of insns of an equivalence class is formed with the
785 aid of the following field. */
786 ainsn_t next_equiv_class_insn;
787 /* The following field value is nonzero if the insn declaration is
788 the first insn declaration with given equivalence number. */
789 char first_ainsn_with_given_equivalence_num;
790 /* The following field is number of class of equivalence of insns.
791 It is necessary because many insns may be equivalent with the
792 point of view of pipeline hazards. */
793 int insn_equiv_class_num;
794 /* The following member value is TRUE if there is an arc in the
795 automaton marked by the insn into another state. In other
796 words, the insn can change the state of the automaton. */
800 /* The following describes an automaton for PHR. */
803 /* The following field value is the list of insn declarations for
806 /* The following field value is the corresponding automaton
807 declaration. This field is not NULL only if the automatic
808 partition on automata is not used. */
809 struct automaton_decl *corresponding_automaton_decl;
810 /* The following field value is the next automaton. */
811 automaton_t next_automaton;
812 /* The following field is start state of FA. There are not unit
813 reservations in the state. */
815 /* The following field value is number of equivalence classes of
816 insns (see field `insn_equiv_class_num' in
817 `insn_reserv_decl'). */
818 int insn_equiv_classes_num;
819 /* The following field value is number of states of final DFA. */
820 int achieved_states_num;
821 /* The following field value is the order number (0, 1, ...) of
823 int automaton_order_num;
824 /* The following fields contain statistics information about
825 building automaton. */
826 int NDFA_states_num, DFA_states_num;
827 /* The following field value is defined only if minimization of DFA
829 int minimal_DFA_states_num;
830 int NDFA_arcs_num, DFA_arcs_num;
831 /* The following field value is defined only if minimization of DFA
833 int minimal_DFA_arcs_num;
834 /* The following member refers for two table state x ainsn -> int.
835 ??? Above sentence is incomprehensible. */
836 state_ainsn_table_t trans_table;
837 /* The following member value is maximal value of min issue delay
838 for insns of the automaton. */
840 /* Usually min issue delay is small and we can place several (2, 4,
841 8) elements in one vector element. So the compression factor can
842 be 1 (no compression), 2, 4, 8. */
843 int min_issue_delay_table_compression_factor;
844 /* Total number of locked states in this automaton. */
848 /* The following is the element of the list of automata. */
849 struct automata_list_el
851 /* The automaton itself. */
852 automaton_t automaton;
853 /* The next automata set element. */
854 automata_list_el_t next_automata_list_el;
857 /* The following structure describes a table state X ainsn -> int(>= 0). */
858 struct state_ainsn_table
860 /* Automaton to which given table belongs. */
861 automaton_t automaton;
862 /* The following tree vectors for comb vector implementation of the
864 vla_hwint_t comb_vect;
865 vla_hwint_t check_vect;
866 vla_hwint_t base_vect;
867 /* This is simple implementation of the table. */
868 vla_hwint_t full_vect;
869 /* Minimal and maximal values of the previous vectors. */
870 int min_comb_vect_el_value, max_comb_vect_el_value;
871 int min_base_vect_el_value, max_base_vect_el_value;
874 /* Macros to access members of unions. Use only them for access to
875 union members of declarations and regexps. */
877 #if defined ENABLE_CHECKING && (GCC_VERSION >= 2007)
879 #define DECL_UNIT(d) __extension__ \
880 (({ __typeof (d) const _decl = (d); \
881 if (_decl->mode != dm_unit) \
882 decl_mode_check_failed (_decl->mode, "dm_unit", \
883 __FILE__, __LINE__, __FUNCTION__); \
884 &(_decl)->decl.unit; }))
886 #define DECL_BYPASS(d) __extension__ \
887 (({ __typeof (d) const _decl = (d); \
888 if (_decl->mode != dm_bypass) \
889 decl_mode_check_failed (_decl->mode, "dm_bypass", \
890 __FILE__, __LINE__, __FUNCTION__); \
891 &(_decl)->decl.bypass; }))
893 #define DECL_AUTOMATON(d) __extension__ \
894 (({ __typeof (d) const _decl = (d); \
895 if (_decl->mode != dm_automaton) \
896 decl_mode_check_failed (_decl->mode, "dm_automaton", \
897 __FILE__, __LINE__, __FUNCTION__); \
898 &(_decl)->decl.automaton; }))
900 #define DECL_EXCL(d) __extension__ \
901 (({ __typeof (d) const _decl = (d); \
902 if (_decl->mode != dm_excl) \
903 decl_mode_check_failed (_decl->mode, "dm_excl", \
904 __FILE__, __LINE__, __FUNCTION__); \
905 &(_decl)->decl.excl; }))
907 #define DECL_PRESENCE(d) __extension__ \
908 (({ __typeof (d) const _decl = (d); \
909 if (_decl->mode != dm_presence) \
910 decl_mode_check_failed (_decl->mode, "dm_presence", \
911 __FILE__, __LINE__, __FUNCTION__); \
912 &(_decl)->decl.presence; }))
914 #define DECL_ABSENCE(d) __extension__ \
915 (({ __typeof (d) const _decl = (d); \
916 if (_decl->mode != dm_absence) \
917 decl_mode_check_failed (_decl->mode, "dm_absence", \
918 __FILE__, __LINE__, __FUNCTION__); \
919 &(_decl)->decl.absence; }))
921 #define DECL_RESERV(d) __extension__ \
922 (({ __typeof (d) const _decl = (d); \
923 if (_decl->mode != dm_reserv) \
924 decl_mode_check_failed (_decl->mode, "dm_reserv", \
925 __FILE__, __LINE__, __FUNCTION__); \
926 &(_decl)->decl.reserv; }))
928 #define DECL_INSN_RESERV(d) __extension__ \
929 (({ __typeof (d) const _decl = (d); \
930 if (_decl->mode != dm_insn_reserv) \
931 decl_mode_check_failed (_decl->mode, "dm_insn_reserv", \
932 __FILE__, __LINE__, __FUNCTION__); \
933 &(_decl)->decl.insn_reserv; }))
935 static const char *decl_name (enum decl_mode);
936 static void decl_mode_check_failed (enum decl_mode, const char *,
937 const char *, int, const char *)
940 /* Return string representation of declaration mode MODE. */
942 decl_name (enum decl_mode mode)
944 static char str [100];
948 else if (mode == dm_bypass)
950 else if (mode == dm_automaton)
951 return "dm_automaton";
952 else if (mode == dm_excl)
954 else if (mode == dm_presence)
955 return "dm_presence";
956 else if (mode == dm_absence)
958 else if (mode == dm_reserv)
960 else if (mode == dm_insn_reserv)
961 return "dm_insn_reserv";
963 sprintf (str, "unknown (%d)", (int) mode);
967 /* The function prints message about unexpected declaration and finish
970 decl_mode_check_failed (enum decl_mode mode, const char *expected_mode_str,
971 const char *file, int line, const char *func)
975 "\n%s: %d: error in %s: DECL check: expected decl %s, have %s\n",
976 file, line, func, expected_mode_str, decl_name (mode));
981 #define REGEXP_UNIT(r) __extension__ \
982 (({ struct regexp *const _regexp = (r); \
983 if (_regexp->mode != rm_unit) \
984 regexp_mode_check_failed (_regexp->mode, "rm_unit", \
985 __FILE__, __LINE__, __FUNCTION__); \
986 &(_regexp)->regexp.unit; }))
988 #define REGEXP_RESERV(r) __extension__ \
989 (({ struct regexp *const _regexp = (r); \
990 if (_regexp->mode != rm_reserv) \
991 regexp_mode_check_failed (_regexp->mode, "rm_reserv", \
992 __FILE__, __LINE__, __FUNCTION__); \
993 &(_regexp)->regexp.reserv; }))
995 #define REGEXP_SEQUENCE(r) __extension__ \
996 (({ struct regexp *const _regexp = (r); \
997 if (_regexp->mode != rm_sequence) \
998 regexp_mode_check_failed (_regexp->mode, "rm_sequence", \
999 __FILE__, __LINE__, __FUNCTION__); \
1000 &(_regexp)->regexp.sequence; }))
1002 #define REGEXP_REPEAT(r) __extension__ \
1003 (({ struct regexp *const _regexp = (r); \
1004 if (_regexp->mode != rm_repeat) \
1005 regexp_mode_check_failed (_regexp->mode, "rm_repeat", \
1006 __FILE__, __LINE__, __FUNCTION__); \
1007 &(_regexp)->regexp.repeat; }))
1009 #define REGEXP_ALLOF(r) __extension__ \
1010 (({ struct regexp *const _regexp = (r); \
1011 if (_regexp->mode != rm_allof) \
1012 regexp_mode_check_failed (_regexp->mode, "rm_allof", \
1013 __FILE__, __LINE__, __FUNCTION__); \
1014 &(_regexp)->regexp.allof; }))
1016 #define REGEXP_ONEOF(r) __extension__ \
1017 (({ struct regexp *const _regexp = (r); \
1018 if (_regexp->mode != rm_oneof) \
1019 regexp_mode_check_failed (_regexp->mode, "rm_oneof", \
1020 __FILE__, __LINE__, __FUNCTION__); \
1021 &(_regexp)->regexp.oneof; }))
1023 static const char *regexp_name (enum regexp_mode);
1024 static void regexp_mode_check_failed (enum regexp_mode, const char *,
1026 const char *) ATTRIBUTE_NORETURN;
1029 /* Return string representation of regexp mode MODE. */
1031 regexp_name (enum regexp_mode mode)
1040 return "rm_nothing";
1042 return "rm_sequence";
1054 /* The function prints message about unexpected regexp and finish the
1057 regexp_mode_check_failed (enum regexp_mode mode,
1058 const char *expected_mode_str,
1059 const char *file, int line, const char *func)
1063 "\n%s: %d: error in %s: REGEXP check: expected decl %s, have %s\n",
1064 file, line, func, expected_mode_str, regexp_name (mode));
1068 #else /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */
1070 #define DECL_UNIT(d) (&(d)->decl.unit)
1071 #define DECL_BYPASS(d) (&(d)->decl.bypass)
1072 #define DECL_AUTOMATON(d) (&(d)->decl.automaton)
1073 #define DECL_EXCL(d) (&(d)->decl.excl)
1074 #define DECL_PRESENCE(d) (&(d)->decl.presence)
1075 #define DECL_ABSENCE(d) (&(d)->decl.absence)
1076 #define DECL_RESERV(d) (&(d)->decl.reserv)
1077 #define DECL_INSN_RESERV(d) (&(d)->decl.insn_reserv)
1079 #define REGEXP_UNIT(r) (&(r)->regexp.unit)
1080 #define REGEXP_RESERV(r) (&(r)->regexp.reserv)
1081 #define REGEXP_SEQUENCE(r) (&(r)->regexp.sequence)
1082 #define REGEXP_REPEAT(r) (&(r)->regexp.repeat)
1083 #define REGEXP_ALLOF(r) (&(r)->regexp.allof)
1084 #define REGEXP_ONEOF(r) (&(r)->regexp.oneof)
1086 #endif /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */
1088 /* Create IR structure (node). */
1090 create_node (size_t size)
1094 obstack_blank (&irp, size);
1095 result = obstack_base (&irp);
1096 obstack_finish (&irp);
1097 /* Default values of members are NULL and zero. */
1098 memset (result, 0, size);
1102 /* Copy IR structure (node). */
1104 copy_node (const void *from, size_t size)
1106 void *const result = create_node (size);
1107 memcpy (result, from, size);
1111 /* The function checks that NAME does not contain quotes (`"'). */
1113 check_name (const char * name, pos_t pos ATTRIBUTE_UNUSED)
1117 for (str = name; *str != '\0'; str++)
1119 error ("Name `%s' contains quotes", name);
1123 /* Pointers to all declarations during IR generation are stored in the
1125 static VEC(decl_t,heap) *decls;
1127 /* Given a pointer to a (char *) and a separator, return an alloc'ed
1128 string containing the next separated element, taking parentheses
1129 into account if PAR_FLAG has nonzero value. Advance the pointer to
1130 after the string scanned, or the end-of-string. Return NULL if at
1133 next_sep_el (const char **pstr, int sep, int par_flag)
1140 /* Remove leading whitespaces. */
1141 while (ISSPACE ((int) **pstr))
1148 for (pars_num = 0, p = *pstr; *p != '\0'; p++)
1150 if (par_flag && *p == '(')
1152 else if (par_flag && *p == ')')
1154 else if (pars_num == 0 && *p == sep)
1156 if (pars_num == 0 && ISSPACE ((int) *p))
1160 for (; n_spaces != 0; n_spaces--)
1161 obstack_1grow (&irp, p [-n_spaces]);
1162 obstack_1grow (&irp, *p);
1165 obstack_1grow (&irp, '\0');
1166 out_str = obstack_base (&irp);
1167 obstack_finish (&irp);
1176 /* Given a string and a separator, return the number of separated
1177 elements in it, taking parentheses into account if PAR_FLAG has
1178 nonzero value. Return 0 for the null string, -1 if parentheses is
1181 n_sep_els (const char *s, int sep, int par_flag)
1189 for (pars_num = 0, n = 1; *s; s++)
1190 if (par_flag && *s == '(')
1192 else if (par_flag && *s == ')')
1194 else if (pars_num == 0 && *s == sep)
1197 return (pars_num != 0 ? -1 : n);
1200 /* Given a string and a separator, return vector of strings which are
1201 elements in the string and number of elements through els_num.
1202 Take parentheses into account if PAREN_P has nonzero value. The
1203 function also inserts the end marker NULL at the end of vector.
1204 Return 0 for the null string, -1 if parentheses are not balanced. */
1206 get_str_vect (const char *str, int *els_num, int sep, int paren_p)
1213 *els_num = n_sep_els (str, sep, paren_p);
1216 obstack_blank (&irp, sizeof (char *) * (*els_num + 1));
1217 vect = (char **) obstack_base (&irp);
1218 obstack_finish (&irp);
1220 for (i = 0; i < *els_num; i++)
1221 vect [i] = next_sep_el (pstr, sep, paren_p);
1222 trail = next_sep_el (pstr, sep, paren_p);
1223 gcc_assert (!trail);
1228 /* Process a DEFINE_CPU_UNIT.
1230 This gives information about a unit contained in CPU. We fill a
1231 struct unit_decl with information used later by `expand_automata'. */
1233 gen_cpu_unit (rtx def)
1236 char **str_cpu_units;
1240 str_cpu_units = get_str_vect (XSTR (def, 0), &vect_length, ',', FALSE);
1241 if (str_cpu_units == NULL)
1242 fatal ("invalid string `%s' in define_cpu_unit", XSTR (def, 0));
1243 for (i = 0; i < vect_length; i++)
1245 decl = create_node (sizeof (struct decl));
1246 decl->mode = dm_unit;
1248 DECL_UNIT (decl)->name = check_name (str_cpu_units [i], decl->pos);
1249 DECL_UNIT (decl)->automaton_name = XSTR (def, 1);
1250 DECL_UNIT (decl)->query_p = 0;
1251 DECL_UNIT (decl)->min_occ_cycle_num = -1;
1252 DECL_UNIT (decl)->in_set_p = 0;
1253 VEC_safe_push (decl_t,heap, decls, decl);
1257 /* Process a DEFINE_QUERY_CPU_UNIT.
1259 This gives information about a unit contained in CPU. We fill a
1260 struct unit_decl with information used later by `expand_automata'. */
1262 gen_query_cpu_unit (rtx def)
1265 char **str_cpu_units;
1269 str_cpu_units = get_str_vect (XSTR (def, 0), &vect_length, ',',
1271 if (str_cpu_units == NULL)
1272 fatal ("invalid string `%s' in define_query_cpu_unit", XSTR (def, 0));
1273 for (i = 0; i < vect_length; i++)
1275 decl = create_node (sizeof (struct decl));
1276 decl->mode = dm_unit;
1278 DECL_UNIT (decl)->name = check_name (str_cpu_units [i], decl->pos);
1279 DECL_UNIT (decl)->automaton_name = XSTR (def, 1);
1280 DECL_UNIT (decl)->query_p = 1;
1281 VEC_safe_push (decl_t,heap, decls, decl);
1285 /* Process a DEFINE_BYPASS.
1287 This gives information about a unit contained in the CPU. We fill
1288 in a struct bypass_decl with information used later by
1289 `expand_automata'. */
1291 gen_bypass (rtx def)
1300 out_insns = get_str_vect (XSTR (def, 1), &out_length, ',', FALSE);
1301 if (out_insns == NULL)
1302 fatal ("invalid string `%s' in define_bypass", XSTR (def, 1));
1303 in_insns = get_str_vect (XSTR (def, 2), &in_length, ',', FALSE);
1304 if (in_insns == NULL)
1305 fatal ("invalid string `%s' in define_bypass", XSTR (def, 2));
1306 for (i = 0; i < out_length; i++)
1307 for (j = 0; j < in_length; j++)
1309 decl = create_node (sizeof (struct decl));
1310 decl->mode = dm_bypass;
1312 DECL_BYPASS (decl)->latency = XINT (def, 0);
1313 DECL_BYPASS (decl)->out_insn_name = out_insns [i];
1314 DECL_BYPASS (decl)->in_insn_name = in_insns [j];
1315 DECL_BYPASS (decl)->bypass_guard_name = XSTR (def, 3);
1316 VEC_safe_push (decl_t,heap, decls, decl);
1320 /* Process an EXCLUSION_SET.
1322 This gives information about a cpu unit conflicts. We fill a
1323 struct excl_rel_decl (excl) with information used later by
1324 `expand_automata'. */
1326 gen_excl_set (rtx def)
1329 char **first_str_cpu_units;
1330 char **second_str_cpu_units;
1331 int first_vect_length;
1336 = get_str_vect (XSTR (def, 0), &first_vect_length, ',', FALSE);
1337 if (first_str_cpu_units == NULL)
1338 fatal ("invalid first string `%s' in exclusion_set", XSTR (def, 0));
1339 second_str_cpu_units = get_str_vect (XSTR (def, 1), &length, ',',
1341 if (second_str_cpu_units == NULL)
1342 fatal ("invalid second string `%s' in exclusion_set", XSTR (def, 1));
1343 length += first_vect_length;
1344 decl = create_node (sizeof (struct decl) + (length - 1) * sizeof (char *));
1345 decl->mode = dm_excl;
1347 DECL_EXCL (decl)->all_names_num = length;
1348 DECL_EXCL (decl)->first_list_length = first_vect_length;
1349 for (i = 0; i < length; i++)
1350 if (i < first_vect_length)
1351 DECL_EXCL (decl)->names [i] = first_str_cpu_units [i];
1353 DECL_EXCL (decl)->names [i]
1354 = second_str_cpu_units [i - first_vect_length];
1355 VEC_safe_push (decl_t,heap, decls, decl);
1358 /* Process a PRESENCE_SET, a FINAL_PRESENCE_SET, an ABSENCE_SET,
1359 FINAL_ABSENCE_SET (it is depended on PRESENCE_P and FINAL_P).
1361 This gives information about a cpu unit reservation requirements.
1362 We fill a struct unit_pattern_rel_decl with information used later
1363 by `expand_automata'. */
1365 gen_presence_absence_set (rtx def, int presence_p, int final_p)
1368 char **str_cpu_units;
1369 char **str_pattern_lists;
1370 char ***str_patterns;
1371 int cpu_units_length;
1373 int patterns_length;
1376 str_cpu_units = get_str_vect (XSTR (def, 0), &cpu_units_length, ',',
1378 if (str_cpu_units == NULL)
1381 ? "invalid first string `%s' in final_presence_set"
1382 : "invalid first string `%s' in presence_set")
1384 ? "invalid first string `%s' in final_absence_set"
1385 : "invalid first string `%s' in absence_set")),
1387 str_pattern_lists = get_str_vect (XSTR (def, 1),
1388 &patterns_length, ',', FALSE);
1389 if (str_pattern_lists == NULL)
1392 ? "invalid second string `%s' in final_presence_set"
1393 : "invalid second string `%s' in presence_set")
1395 ? "invalid second string `%s' in final_absence_set"
1396 : "invalid second string `%s' in absence_set")), XSTR (def, 1));
1397 str_patterns = obstack_alloc (&irp, patterns_length * sizeof (char **));
1398 for (i = 0; i < patterns_length; i++)
1400 str_patterns [i] = get_str_vect (str_pattern_lists [i],
1401 &length, ' ', FALSE);
1402 gcc_assert (str_patterns [i]);
1404 decl = create_node (sizeof (struct decl));
1408 decl->mode = dm_presence;
1409 DECL_PRESENCE (decl)->names_num = cpu_units_length;
1410 DECL_PRESENCE (decl)->names = str_cpu_units;
1411 DECL_PRESENCE (decl)->patterns = str_patterns;
1412 DECL_PRESENCE (decl)->patterns_num = patterns_length;
1413 DECL_PRESENCE (decl)->final_p = final_p;
1417 decl->mode = dm_absence;
1418 DECL_ABSENCE (decl)->names_num = cpu_units_length;
1419 DECL_ABSENCE (decl)->names = str_cpu_units;
1420 DECL_ABSENCE (decl)->patterns = str_patterns;
1421 DECL_ABSENCE (decl)->patterns_num = patterns_length;
1422 DECL_ABSENCE (decl)->final_p = final_p;
1424 VEC_safe_push (decl_t,heap, decls, decl);
1427 /* Process a PRESENCE_SET.
1429 This gives information about a cpu unit reservation requirements.
1430 We fill a struct unit_pattern_rel_decl (presence) with information
1431 used later by `expand_automata'. */
1433 gen_presence_set (rtx def)
1435 gen_presence_absence_set (def, TRUE, FALSE);
1438 /* Process a FINAL_PRESENCE_SET.
1440 This gives information about a cpu unit reservation requirements.
1441 We fill a struct unit_pattern_rel_decl (presence) with information
1442 used later by `expand_automata'. */
1444 gen_final_presence_set (rtx def)
1446 gen_presence_absence_set (def, TRUE, TRUE);
1449 /* Process an ABSENCE_SET.
1451 This gives information about a cpu unit reservation requirements.
1452 We fill a struct unit_pattern_rel_decl (absence) with information
1453 used later by `expand_automata'. */
1455 gen_absence_set (rtx def)
1457 gen_presence_absence_set (def, FALSE, FALSE);
1460 /* Process a FINAL_ABSENCE_SET.
1462 This gives information about a cpu unit reservation requirements.
1463 We fill a struct unit_pattern_rel_decl (absence) with information
1464 used later by `expand_automata'. */
1466 gen_final_absence_set (rtx def)
1468 gen_presence_absence_set (def, FALSE, TRUE);
1471 /* Process a DEFINE_AUTOMATON.
1473 This gives information about a finite state automaton used for
1474 recognizing pipeline hazards. We fill a struct automaton_decl
1475 with information used later by `expand_automata'. */
1477 gen_automaton (rtx def)
1480 char **str_automata;
1484 str_automata = get_str_vect (XSTR (def, 0), &vect_length, ',', FALSE);
1485 if (str_automata == NULL)
1486 fatal ("invalid string `%s' in define_automaton", XSTR (def, 0));
1487 for (i = 0; i < vect_length; i++)
1489 decl = create_node (sizeof (struct decl));
1490 decl->mode = dm_automaton;
1492 DECL_AUTOMATON (decl)->name = check_name (str_automata [i], decl->pos);
1493 VEC_safe_push (decl_t,heap, decls, decl);
1497 /* Process an AUTOMATA_OPTION.
1499 This gives information how to generate finite state automaton used
1500 for recognizing pipeline hazards. */
1502 gen_automata_option (rtx def)
1504 if (strcmp (XSTR (def, 0), NO_MINIMIZATION_OPTION + 1) == 0)
1505 no_minimization_flag = 1;
1506 else if (strcmp (XSTR (def, 0), TIME_OPTION + 1) == 0)
1508 else if (strcmp (XSTR (def, 0), STATS_OPTION + 1) == 0)
1510 else if (strcmp (XSTR (def, 0), V_OPTION + 1) == 0)
1512 else if (strcmp (XSTR (def, 0), W_OPTION + 1) == 0)
1514 else if (strcmp (XSTR (def, 0), NDFA_OPTION + 1) == 0)
1516 else if (strcmp (XSTR (def, 0), PROGRESS_OPTION + 1) == 0)
1519 fatal ("invalid option `%s' in automata_option", XSTR (def, 0));
1522 /* Name in reservation to denote absence reservation. */
1523 #define NOTHING_NAME "nothing"
1525 /* The following string contains original reservation string being
1527 static const char *reserv_str;
1529 /* Parse an element in STR. */
1531 gen_regexp_el (const char *str)
1540 if (str [len - 1] != ')')
1541 fatal ("garbage after ) in reservation `%s'", reserv_str);
1542 dstr = alloca (len - 1);
1543 memcpy (dstr, str + 1, len - 2);
1544 dstr [len-2] = '\0';
1545 regexp = gen_regexp_sequence (dstr);
1547 else if (strcmp (str, NOTHING_NAME) == 0)
1549 regexp = create_node (sizeof *regexp);
1550 regexp->mode = rm_nothing;
1554 regexp = create_node (sizeof *regexp);
1555 regexp->mode = rm_unit;
1556 REGEXP_UNIT (regexp)->name = str;
1561 /* Parse construction `repeat' in STR. */
1563 gen_regexp_repeat (const char *str)
1571 repeat_vect = get_str_vect (str, &els_num, '*', TRUE);
1572 if (repeat_vect == NULL)
1573 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1576 regexp = gen_regexp_el (repeat_vect [0]);
1577 for (i = 1; i < els_num; i++)
1579 repeat = create_node (sizeof (struct regexp));
1580 repeat->mode = rm_repeat;
1581 REGEXP_REPEAT (repeat)->regexp = regexp;
1582 REGEXP_REPEAT (repeat)->repeat_num = atoi (repeat_vect [i]);
1583 if (REGEXP_REPEAT (repeat)->repeat_num <= 1)
1584 fatal ("repetition `%s' <= 1 in reservation `%s'",
1591 return gen_regexp_el (str);
1594 /* Parse reservation STR which possibly contains separator '+'. */
1596 gen_regexp_allof (const char *str)
1603 allof_vect = get_str_vect (str, &els_num, '+', TRUE);
1604 if (allof_vect == NULL)
1605 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1608 allof = create_node (sizeof (struct regexp)
1609 + sizeof (regexp_t) * (els_num - 1));
1610 allof->mode = rm_allof;
1611 REGEXP_ALLOF (allof)->regexps_num = els_num;
1612 for (i = 0; i < els_num; i++)
1613 REGEXP_ALLOF (allof)->regexps [i] = gen_regexp_repeat (allof_vect [i]);
1617 return gen_regexp_repeat (str);
1620 /* Parse reservation STR which possibly contains separator '|'. */
1622 gen_regexp_oneof (const char *str)
1629 oneof_vect = get_str_vect (str, &els_num, '|', TRUE);
1630 if (oneof_vect == NULL)
1631 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1634 oneof = create_node (sizeof (struct regexp)
1635 + sizeof (regexp_t) * (els_num - 1));
1636 oneof->mode = rm_oneof;
1637 REGEXP_ONEOF (oneof)->regexps_num = els_num;
1638 for (i = 0; i < els_num; i++)
1639 REGEXP_ONEOF (oneof)->regexps [i] = gen_regexp_allof (oneof_vect [i]);
1643 return gen_regexp_allof (str);
1646 /* Parse reservation STR which possibly contains separator ','. */
1648 gen_regexp_sequence (const char *str)
1651 char **sequence_vect;
1655 sequence_vect = get_str_vect (str, &els_num, ',', TRUE);
1658 sequence = create_node (sizeof (struct regexp)
1659 + sizeof (regexp_t) * (els_num - 1));
1660 sequence->mode = rm_sequence;
1661 REGEXP_SEQUENCE (sequence)->regexps_num = els_num;
1662 for (i = 0; i < els_num; i++)
1663 REGEXP_SEQUENCE (sequence)->regexps [i]
1664 = gen_regexp_oneof (sequence_vect [i]);
1668 return gen_regexp_oneof (str);
1671 /* Parse construction reservation STR. */
1673 gen_regexp (const char *str)
1676 return gen_regexp_sequence (str);;
1679 /* Process a DEFINE_RESERVATION.
1681 This gives information about a reservation of cpu units. We fill
1682 in a struct reserv_decl with information used later by
1683 `expand_automata'. */
1685 gen_reserv (rtx def)
1689 decl = create_node (sizeof (struct decl));
1690 decl->mode = dm_reserv;
1692 DECL_RESERV (decl)->name = check_name (XSTR (def, 0), decl->pos);
1693 DECL_RESERV (decl)->regexp = gen_regexp (XSTR (def, 1));
1694 VEC_safe_push (decl_t,heap, decls, decl);
1697 /* Process a DEFINE_INSN_RESERVATION.
1699 This gives information about the reservation of cpu units by an
1700 insn. We fill a struct insn_reserv_decl with information used
1701 later by `expand_automata'. */
1703 gen_insn_reserv (rtx def)
1707 decl = create_node (sizeof (struct decl));
1708 decl->mode = dm_insn_reserv;
1710 DECL_INSN_RESERV (decl)->name
1711 = check_name (XSTR (def, 0), decl->pos);
1712 DECL_INSN_RESERV (decl)->default_latency = XINT (def, 1);
1713 DECL_INSN_RESERV (decl)->condexp = XEXP (def, 2);
1714 DECL_INSN_RESERV (decl)->regexp = gen_regexp (XSTR (def, 3));
1715 VEC_safe_push (decl_t,heap, decls, decl);
1720 /* The function evaluates hash value (0..UINT_MAX) of string. */
1722 string_hash (const char *string)
1726 for (result = i = 0;*string++ != '\0'; i++)
1727 result += ((unsigned char) *string << (i % CHAR_BIT));
1733 /* This page contains abstract data `table of automaton declarations'.
1734 Elements of the table is nodes representing automaton declarations.
1735 Key of the table elements is name of given automaton. Remember
1736 that automaton names have own space. */
1738 /* The function evaluates hash value of an automaton declaration. The
1739 function is used by abstract data `hashtab'. The function returns
1740 hash value (0..UINT_MAX) of given automaton declaration. */
1742 automaton_decl_hash (const void *automaton_decl)
1744 const_decl_t const decl = (const_decl_t) automaton_decl;
1746 gcc_assert (decl->mode != dm_automaton
1747 || DECL_AUTOMATON (decl)->name);
1748 return string_hash (DECL_AUTOMATON (decl)->name);
1751 /* The function tests automaton declarations on equality of their
1752 keys. The function is used by abstract data `hashtab'. The
1753 function returns 1 if the declarations have the same key, 0
1756 automaton_decl_eq_p (const void* automaton_decl_1,
1757 const void* automaton_decl_2)
1759 const_decl_t const decl1 = (const_decl_t) automaton_decl_1;
1760 const_decl_t const decl2 = (const_decl_t) automaton_decl_2;
1762 gcc_assert (decl1->mode == dm_automaton
1763 && DECL_AUTOMATON (decl1)->name
1764 && decl2->mode == dm_automaton
1765 && DECL_AUTOMATON (decl2)->name);
1766 return strcmp (DECL_AUTOMATON (decl1)->name,
1767 DECL_AUTOMATON (decl2)->name) == 0;
1770 /* The automaton declaration table itself is represented by the
1771 following variable. */
1772 static htab_t automaton_decl_table;
1774 /* The function inserts automaton declaration into the table. The
1775 function does nothing if an automaton declaration with the same key
1776 exists already in the table. The function returns automaton
1777 declaration node in the table with the same key as given automaton
1778 declaration node. */
1780 insert_automaton_decl (decl_t automaton_decl)
1784 entry_ptr = htab_find_slot (automaton_decl_table, automaton_decl, 1);
1785 if (*entry_ptr == NULL)
1786 *entry_ptr = (void *) automaton_decl;
1787 return (decl_t) *entry_ptr;
1790 /* The following variable value is node representing automaton
1791 declaration. The node used for searching automaton declaration
1793 static struct decl work_automaton_decl;
1795 /* The function searches for automaton declaration in the table with
1796 the same key as node representing name of the automaton
1797 declaration. The function returns node found in the table, NULL if
1798 such node does not exist in the table. */
1800 find_automaton_decl (const char *name)
1804 work_automaton_decl.mode = dm_automaton;
1805 DECL_AUTOMATON (&work_automaton_decl)->name = name;
1806 entry = htab_find (automaton_decl_table, &work_automaton_decl);
1807 return (decl_t) entry;
1810 /* The function creates empty automaton declaration table and node
1811 representing automaton declaration and used for searching automaton
1812 declaration with given name. The function must be called only once
1813 before any work with the automaton declaration table. */
1815 initiate_automaton_decl_table (void)
1817 work_automaton_decl.mode = dm_automaton;
1818 automaton_decl_table = htab_create (10, automaton_decl_hash,
1819 automaton_decl_eq_p, (htab_del) 0);
1822 /* The function deletes the automaton declaration table. Only call of
1823 function `initiate_automaton_decl_table' is possible immediately
1824 after this function call. */
1826 finish_automaton_decl_table (void)
1828 htab_delete (automaton_decl_table);
1833 /* This page contains abstract data `table of insn declarations'.
1834 Elements of the table is nodes representing insn declarations. Key
1835 of the table elements is name of given insn (in corresponding
1836 define_insn_reservation). Remember that insn names have own
1839 /* The function evaluates hash value of an insn declaration. The
1840 function is used by abstract data `hashtab'. The function returns
1841 hash value (0..UINT_MAX) of given insn declaration. */
1843 insn_decl_hash (const void *insn_decl)
1845 const_decl_t const decl = (const_decl_t) insn_decl;
1847 gcc_assert (decl->mode == dm_insn_reserv
1848 && DECL_INSN_RESERV (decl)->name);
1849 return string_hash (DECL_INSN_RESERV (decl)->name);
1852 /* The function tests insn declarations on equality of their keys.
1853 The function is used by abstract data `hashtab'. The function
1854 returns 1 if declarations have the same key, 0 otherwise. */
1856 insn_decl_eq_p (const void *insn_decl_1, const void *insn_decl_2)
1858 const_decl_t const decl1 = (const_decl_t) insn_decl_1;
1859 const_decl_t const decl2 = (const_decl_t) insn_decl_2;
1861 gcc_assert (decl1->mode == dm_insn_reserv
1862 && DECL_INSN_RESERV (decl1)->name
1863 && decl2->mode == dm_insn_reserv
1864 && DECL_INSN_RESERV (decl2)->name);
1865 return strcmp (DECL_INSN_RESERV (decl1)->name,
1866 DECL_INSN_RESERV (decl2)->name) == 0;
1869 /* The insn declaration table itself is represented by the following
1870 variable. The table does not contain insn reservation
1872 static htab_t insn_decl_table;
1874 /* The function inserts insn declaration into the table. The function
1875 does nothing if an insn declaration with the same key exists
1876 already in the table. The function returns insn declaration node
1877 in the table with the same key as given insn declaration node. */
1879 insert_insn_decl (decl_t insn_decl)
1883 entry_ptr = htab_find_slot (insn_decl_table, insn_decl, 1);
1884 if (*entry_ptr == NULL)
1885 *entry_ptr = (void *) insn_decl;
1886 return (decl_t) *entry_ptr;
1889 /* The following variable value is node representing insn reservation
1890 declaration. The node used for searching insn reservation
1891 declaration with given name. */
1892 static struct decl work_insn_decl;
1894 /* The function searches for insn reservation declaration in the table
1895 with the same key as node representing name of the insn reservation
1896 declaration. The function returns node found in the table, NULL if
1897 such node does not exist in the table. */
1899 find_insn_decl (const char *name)
1903 work_insn_decl.mode = dm_insn_reserv;
1904 DECL_INSN_RESERV (&work_insn_decl)->name = name;
1905 entry = htab_find (insn_decl_table, &work_insn_decl);
1906 return (decl_t) entry;
1909 /* The function creates empty insn declaration table and node
1910 representing insn declaration and used for searching insn
1911 declaration with given name. The function must be called only once
1912 before any work with the insn declaration table. */
1914 initiate_insn_decl_table (void)
1916 work_insn_decl.mode = dm_insn_reserv;
1917 insn_decl_table = htab_create (10, insn_decl_hash, insn_decl_eq_p,
1921 /* The function deletes the insn declaration table. Only call of
1922 function `initiate_insn_decl_table' is possible immediately after
1923 this function call. */
1925 finish_insn_decl_table (void)
1927 htab_delete (insn_decl_table);
1932 /* This page contains abstract data `table of declarations'. Elements
1933 of the table is nodes representing declarations (of units and
1934 reservations). Key of the table elements is names of given
1937 /* The function evaluates hash value of a declaration. The function
1938 is used by abstract data `hashtab'. The function returns hash
1939 value (0..UINT_MAX) of given declaration. */
1941 decl_hash (const void *decl)
1943 const_decl_t const d = (const_decl_t) decl;
1945 gcc_assert ((d->mode == dm_unit && DECL_UNIT (d)->name)
1946 || (d->mode == dm_reserv && DECL_RESERV (d)->name));
1947 return string_hash (d->mode == dm_unit
1948 ? DECL_UNIT (d)->name : DECL_RESERV (d)->name);
1951 /* The function tests declarations on equality of their keys. The
1952 function is used by abstract data 'hashtab'. The function
1953 returns 1 if the declarations have the same key, 0 otherwise. */
1955 decl_eq_p (const void *decl_1, const void *decl_2)
1957 const_decl_t const d1 = (const_decl_t) decl_1;
1958 const_decl_t const d2 = (const_decl_t) decl_2;
1960 gcc_assert ((d1->mode == dm_unit && DECL_UNIT (d1)->name)
1961 || (d1->mode == dm_reserv && DECL_RESERV (d1)->name));
1962 gcc_assert ((d2->mode == dm_unit && DECL_UNIT (d2)->name)
1963 || (d2->mode == dm_reserv && DECL_RESERV (d2)->name));
1964 return strcmp ((d1->mode == dm_unit
1965 ? DECL_UNIT (d1)->name : DECL_RESERV (d1)->name),
1966 (d2->mode == dm_unit
1967 ? DECL_UNIT (d2)->name : DECL_RESERV (d2)->name)) == 0;
1970 /* The declaration table itself is represented by the following
1972 static htab_t decl_table;
1974 /* The function inserts declaration into the table. The function does
1975 nothing if a declaration with the same key exists already in the
1976 table. The function returns declaration node in the table with the
1977 same key as given declaration node. */
1980 insert_decl (decl_t decl)
1984 entry_ptr = htab_find_slot (decl_table, decl, 1);
1985 if (*entry_ptr == NULL)
1986 *entry_ptr = (void *) decl;
1987 return (decl_t) *entry_ptr;
1990 /* The following variable value is node representing declaration. The
1991 node used for searching declaration with given name. */
1992 static struct decl work_decl;
1994 /* The function searches for declaration in the table with the same
1995 key as node representing name of the declaration. The function
1996 returns node found in the table, NULL if such node does not exist
1999 find_decl (const char *name)
2003 work_decl.mode = dm_unit;
2004 DECL_UNIT (&work_decl)->name = name;
2005 entry = htab_find (decl_table, &work_decl);
2006 return (decl_t) entry;
2009 /* The function creates empty declaration table and node representing
2010 declaration and used for searching declaration with given name.
2011 The function must be called only once before any work with the
2012 declaration table. */
2014 initiate_decl_table (void)
2016 work_decl.mode = dm_unit;
2017 decl_table = htab_create (10, decl_hash, decl_eq_p, (htab_del) 0);
2020 /* The function deletes the declaration table. Only call of function
2021 `initiate_declaration_table' is possible immediately after this
2024 finish_decl_table (void)
2026 htab_delete (decl_table);
2031 /* This page contains checker of pipeline hazard description. */
2033 /* Checking NAMES in an exclusion clause vector and returning formed
2034 unit_set_el_list. */
2035 static unit_set_el_t
2036 process_excls (char **names, int num, pos_t excl_pos ATTRIBUTE_UNUSED)
2038 unit_set_el_t el_list;
2039 unit_set_el_t last_el;
2040 unit_set_el_t new_el;
2041 decl_t decl_in_table;
2046 for (i = 0; i < num; i++)
2048 decl_in_table = find_decl (names [i]);
2049 if (decl_in_table == NULL)
2050 error ("unit `%s' in exclusion is not declared", names [i]);
2051 else if (decl_in_table->mode != dm_unit)
2052 error ("`%s' in exclusion is not unit", names [i]);
2055 new_el = create_node (sizeof (struct unit_set_el));
2056 new_el->unit_decl = DECL_UNIT (decl_in_table);
2057 new_el->next_unit_set_el = NULL;
2058 if (last_el == NULL)
2059 el_list = last_el = new_el;
2062 last_el->next_unit_set_el = new_el;
2063 last_el = last_el->next_unit_set_el;
2070 /* The function adds each element from SOURCE_LIST to the exclusion
2071 list of the each element from DEST_LIST. Checking situation "unit
2072 excludes itself". */
2074 add_excls (unit_set_el_t dest_list, unit_set_el_t source_list,
2075 pos_t excl_pos ATTRIBUTE_UNUSED)
2079 unit_set_el_t curr_el;
2080 unit_set_el_t prev_el;
2083 for (dst = dest_list; dst != NULL; dst = dst->next_unit_set_el)
2084 for (src = source_list; src != NULL; src = src->next_unit_set_el)
2086 if (dst->unit_decl == src->unit_decl)
2088 error ("unit `%s' excludes itself", src->unit_decl->name);
2091 if (dst->unit_decl->automaton_name != NULL
2092 && src->unit_decl->automaton_name != NULL
2093 && strcmp (dst->unit_decl->automaton_name,
2094 src->unit_decl->automaton_name) != 0)
2096 error ("units `%s' and `%s' in exclusion set belong to different automata",
2097 src->unit_decl->name, dst->unit_decl->name);
2100 for (curr_el = dst->unit_decl->excl_list, prev_el = NULL;
2102 prev_el = curr_el, curr_el = curr_el->next_unit_set_el)
2103 if (curr_el->unit_decl == src->unit_decl)
2105 if (curr_el == NULL)
2107 /* Element not found - insert. */
2108 copy = copy_node (src, sizeof (*src));
2109 copy->next_unit_set_el = NULL;
2110 if (prev_el == NULL)
2111 dst->unit_decl->excl_list = copy;
2113 prev_el->next_unit_set_el = copy;
2118 /* Checking NAMES in presence/absence clause and returning the
2119 formed unit_set_el_list. The function is called only after
2120 processing all exclusion sets. */
2121 static unit_set_el_t
2122 process_presence_absence_names (char **names, int num,
2123 pos_t req_pos ATTRIBUTE_UNUSED,
2124 int presence_p, int final_p)
2126 unit_set_el_t el_list;
2127 unit_set_el_t last_el;
2128 unit_set_el_t new_el;
2129 decl_t decl_in_table;
2134 for (i = 0; i < num; i++)
2136 decl_in_table = find_decl (names [i]);
2137 if (decl_in_table == NULL)
2140 ? "unit `%s' in final presence set is not declared"
2141 : "unit `%s' in presence set is not declared")
2143 ? "unit `%s' in final absence set is not declared"
2144 : "unit `%s' in absence set is not declared")), names [i]);
2145 else if (decl_in_table->mode != dm_unit)
2148 ? "`%s' in final presence set is not unit"
2149 : "`%s' in presence set is not unit")
2151 ? "`%s' in final absence set is not unit"
2152 : "`%s' in absence set is not unit")), names [i]);
2155 new_el = create_node (sizeof (struct unit_set_el));
2156 new_el->unit_decl = DECL_UNIT (decl_in_table);
2157 new_el->next_unit_set_el = NULL;
2158 if (last_el == NULL)
2159 el_list = last_el = new_el;
2162 last_el->next_unit_set_el = new_el;
2163 last_el = last_el->next_unit_set_el;
2170 /* Checking NAMES in patterns of a presence/absence clause and
2171 returning the formed pattern_set_el_list. The function is called
2172 only after processing all exclusion sets. */
2173 static pattern_set_el_t
2174 process_presence_absence_patterns (char ***patterns, int num,
2175 pos_t req_pos ATTRIBUTE_UNUSED,
2176 int presence_p, int final_p)
2178 pattern_set_el_t el_list;
2179 pattern_set_el_t last_el;
2180 pattern_set_el_t new_el;
2181 decl_t decl_in_table;
2186 for (i = 0; i < num; i++)
2188 for (j = 0; patterns [i] [j] != NULL; j++)
2190 new_el = create_node (sizeof (struct pattern_set_el)
2191 + sizeof (struct unit_decl *) * j);
2193 = (struct unit_decl **) ((char *) new_el
2194 + sizeof (struct pattern_set_el));
2195 new_el->next_pattern_set_el = NULL;
2196 if (last_el == NULL)
2197 el_list = last_el = new_el;
2200 last_el->next_pattern_set_el = new_el;
2201 last_el = last_el->next_pattern_set_el;
2203 new_el->units_num = 0;
2204 for (j = 0; patterns [i] [j] != NULL; j++)
2206 decl_in_table = find_decl (patterns [i] [j]);
2207 if (decl_in_table == NULL)
2210 ? "unit `%s' in final presence set is not declared"
2211 : "unit `%s' in presence set is not declared")
2213 ? "unit `%s' in final absence set is not declared"
2214 : "unit `%s' in absence set is not declared")),
2216 else if (decl_in_table->mode != dm_unit)
2219 ? "`%s' in final presence set is not unit"
2220 : "`%s' in presence set is not unit")
2222 ? "`%s' in final absence set is not unit"
2223 : "`%s' in absence set is not unit")),
2227 new_el->unit_decls [new_el->units_num]
2228 = DECL_UNIT (decl_in_table);
2229 new_el->units_num++;
2236 /* The function adds each element from PATTERN_LIST to presence (if
2237 PRESENCE_P) or absence list of the each element from DEST_LIST.
2238 Checking situations "unit requires own absence", and "unit excludes
2239 and requires presence of ...", "unit requires absence and presence
2240 of ...", "units in (final) presence set belong to different
2241 automata", and "units in (final) absence set belong to different
2242 automata". Remember that we process absence sets only after all
2245 add_presence_absence (unit_set_el_t dest_list,
2246 pattern_set_el_t pattern_list,
2247 pos_t req_pos ATTRIBUTE_UNUSED,
2248 int presence_p, int final_p)
2251 pattern_set_el_t pat;
2252 struct unit_decl *unit;
2253 unit_set_el_t curr_excl_el;
2254 pattern_set_el_t curr_pat_el;
2255 pattern_set_el_t prev_el;
2256 pattern_set_el_t copy;
2260 for (dst = dest_list; dst != NULL; dst = dst->next_unit_set_el)
2261 for (pat = pattern_list; pat != NULL; pat = pat->next_pattern_set_el)
2263 for (i = 0; i < pat->units_num; i++)
2265 unit = pat->unit_decls [i];
2266 if (dst->unit_decl == unit && pat->units_num == 1 && !presence_p)
2268 error ("unit `%s' requires own absence", unit->name);
2271 if (dst->unit_decl->automaton_name != NULL
2272 && unit->automaton_name != NULL
2273 && strcmp (dst->unit_decl->automaton_name,
2274 unit->automaton_name) != 0)
2278 ? "units `%s' and `%s' in final presence set belong to different automata"
2279 : "units `%s' and `%s' in presence set belong to different automata")
2281 ? "units `%s' and `%s' in final absence set belong to different automata"
2282 : "units `%s' and `%s' in absence set belong to different automata")),
2283 unit->name, dst->unit_decl->name);
2288 for (curr_excl_el = dst->unit_decl->excl_list;
2289 curr_excl_el != NULL;
2290 curr_excl_el = curr_excl_el->next_unit_set_el)
2292 if (unit == curr_excl_el->unit_decl && pat->units_num == 1)
2296 error ("unit `%s' excludes and requires presence of `%s'",
2297 dst->unit_decl->name, unit->name);
2302 (0, "unit `%s' excludes and requires presence of `%s'",
2303 dst->unit_decl->name, unit->name);
2306 else if (pat->units_num == 1)
2307 for (curr_pat_el = dst->unit_decl->presence_list;
2308 curr_pat_el != NULL;
2309 curr_pat_el = curr_pat_el->next_pattern_set_el)
2310 if (curr_pat_el->units_num == 1
2311 && unit == curr_pat_el->unit_decls [0])
2316 ("unit `%s' requires absence and presence of `%s'",
2317 dst->unit_decl->name, unit->name);
2322 (0, "unit `%s' requires absence and presence of `%s'",
2323 dst->unit_decl->name, unit->name);
2327 for (prev_el = (presence_p
2329 ? dst->unit_decl->final_presence_list
2330 : dst->unit_decl->final_presence_list)
2332 ? dst->unit_decl->final_absence_list
2333 : dst->unit_decl->absence_list));
2334 prev_el != NULL && prev_el->next_pattern_set_el != NULL;
2335 prev_el = prev_el->next_pattern_set_el)
2337 copy = copy_node (pat, sizeof (*pat));
2338 copy->next_pattern_set_el = NULL;
2339 if (prev_el == NULL)
2344 dst->unit_decl->final_presence_list = copy;
2346 dst->unit_decl->presence_list = copy;
2349 dst->unit_decl->final_absence_list = copy;
2351 dst->unit_decl->absence_list = copy;
2354 prev_el->next_pattern_set_el = copy;
2361 /* The function searches for bypass with given IN_INSN_RESERV in given
2363 static struct bypass_decl *
2364 find_bypass (struct bypass_decl *bypass_list,
2365 struct insn_reserv_decl *in_insn_reserv)
2367 struct bypass_decl *bypass;
2369 for (bypass = bypass_list; bypass != NULL; bypass = bypass->next)
2370 if (bypass->in_insn_reserv == in_insn_reserv)
2375 /* The function processes pipeline description declarations, checks
2376 their correctness, and forms exclusion/presence/absence sets. */
2378 process_decls (void)
2381 decl_t automaton_decl;
2382 decl_t decl_in_table;
2383 decl_t out_insn_reserv;
2384 decl_t in_insn_reserv;
2385 struct bypass_decl *bypass;
2386 int automaton_presence;
2389 /* Checking repeated automata declarations. */
2390 automaton_presence = 0;
2391 for (i = 0; i < description->decls_num; i++)
2393 decl = description->decls [i];
2394 if (decl->mode == dm_automaton)
2396 automaton_presence = 1;
2397 decl_in_table = insert_automaton_decl (decl);
2398 if (decl_in_table != decl)
2401 error ("repeated declaration of automaton `%s'",
2402 DECL_AUTOMATON (decl)->name);
2404 warning (0, "repeated declaration of automaton `%s'",
2405 DECL_AUTOMATON (decl)->name);
2409 /* Checking undeclared automata, repeated declarations (except for
2410 automata) and correctness of their attributes (insn latency times
2412 for (i = 0; i < description->decls_num; i++)
2414 decl = description->decls [i];
2415 if (decl->mode == dm_insn_reserv)
2417 if (DECL_INSN_RESERV (decl)->default_latency < 0)
2418 error ("define_insn_reservation `%s' has negative latency time",
2419 DECL_INSN_RESERV (decl)->name);
2420 DECL_INSN_RESERV (decl)->insn_num = description->insns_num;
2421 description->insns_num++;
2422 decl_in_table = insert_insn_decl (decl);
2423 if (decl_in_table != decl)
2424 error ("`%s' is already used as insn reservation name",
2425 DECL_INSN_RESERV (decl)->name);
2427 else if (decl->mode == dm_bypass)
2429 if (DECL_BYPASS (decl)->latency < 0)
2430 error ("define_bypass `%s - %s' has negative latency time",
2431 DECL_BYPASS (decl)->out_insn_name,
2432 DECL_BYPASS (decl)->in_insn_name);
2434 else if (decl->mode == dm_unit || decl->mode == dm_reserv)
2436 if (decl->mode == dm_unit)
2438 DECL_UNIT (decl)->automaton_decl = NULL;
2439 if (DECL_UNIT (decl)->automaton_name != NULL)
2442 = find_automaton_decl (DECL_UNIT (decl)->automaton_name);
2443 if (automaton_decl == NULL)
2444 error ("automaton `%s' is not declared",
2445 DECL_UNIT (decl)->automaton_name);
2448 DECL_AUTOMATON (automaton_decl)->automaton_is_used = 1;
2449 DECL_UNIT (decl)->automaton_decl
2450 = DECL_AUTOMATON (automaton_decl);
2453 else if (automaton_presence)
2454 error ("define_unit `%s' without automaton when one defined",
2455 DECL_UNIT (decl)->name);
2456 DECL_UNIT (decl)->unit_num = description->units_num;
2457 description->units_num++;
2458 if (strcmp (DECL_UNIT (decl)->name, NOTHING_NAME) == 0)
2460 error ("`%s' is declared as cpu unit", NOTHING_NAME);
2463 decl_in_table = find_decl (DECL_UNIT (decl)->name);
2467 if (strcmp (DECL_RESERV (decl)->name, NOTHING_NAME) == 0)
2469 error ("`%s' is declared as cpu reservation", NOTHING_NAME);
2472 decl_in_table = find_decl (DECL_RESERV (decl)->name);
2474 if (decl_in_table == NULL)
2475 decl_in_table = insert_decl (decl);
2478 if (decl->mode == dm_unit)
2479 error ("repeated declaration of unit `%s'",
2480 DECL_UNIT (decl)->name);
2482 error ("repeated declaration of reservation `%s'",
2483 DECL_RESERV (decl)->name);
2487 /* Check bypasses and form list of bypasses for each (output)
2489 for (i = 0; i < description->decls_num; i++)
2491 decl = description->decls [i];
2492 if (decl->mode == dm_bypass)
2494 out_insn_reserv = find_insn_decl (DECL_BYPASS (decl)->out_insn_name);
2495 in_insn_reserv = find_insn_decl (DECL_BYPASS (decl)->in_insn_name);
2496 if (out_insn_reserv == NULL)
2497 error ("there is no insn reservation `%s'",
2498 DECL_BYPASS (decl)->out_insn_name);
2499 else if (in_insn_reserv == NULL)
2500 error ("there is no insn reservation `%s'",
2501 DECL_BYPASS (decl)->in_insn_name);
2504 DECL_BYPASS (decl)->out_insn_reserv
2505 = DECL_INSN_RESERV (out_insn_reserv);
2506 DECL_BYPASS (decl)->in_insn_reserv
2507 = DECL_INSN_RESERV (in_insn_reserv);
2509 = find_bypass (DECL_INSN_RESERV (out_insn_reserv)->bypass_list,
2510 DECL_BYPASS (decl)->in_insn_reserv);
2513 if (DECL_BYPASS (decl)->latency == bypass->latency)
2517 ("the same bypass `%s - %s' is already defined",
2518 DECL_BYPASS (decl)->out_insn_name,
2519 DECL_BYPASS (decl)->in_insn_name);
2522 (0, "the same bypass `%s - %s' is already defined",
2523 DECL_BYPASS (decl)->out_insn_name,
2524 DECL_BYPASS (decl)->in_insn_name);
2527 error ("bypass `%s - %s' is already defined",
2528 DECL_BYPASS (decl)->out_insn_name,
2529 DECL_BYPASS (decl)->in_insn_name);
2533 DECL_BYPASS (decl)->next
2534 = DECL_INSN_RESERV (out_insn_reserv)->bypass_list;
2535 DECL_INSN_RESERV (out_insn_reserv)->bypass_list
2536 = DECL_BYPASS (decl);
2542 /* Check exclusion set declarations and form exclusion sets. */
2543 for (i = 0; i < description->decls_num; i++)
2545 decl = description->decls [i];
2546 if (decl->mode == dm_excl)
2548 unit_set_el_t unit_set_el_list;
2549 unit_set_el_t unit_set_el_list_2;
2552 = process_excls (DECL_EXCL (decl)->names,
2553 DECL_EXCL (decl)->first_list_length, decl->pos);
2555 = process_excls (&DECL_EXCL (decl)->names
2556 [DECL_EXCL (decl)->first_list_length],
2557 DECL_EXCL (decl)->all_names_num
2558 - DECL_EXCL (decl)->first_list_length,
2560 add_excls (unit_set_el_list, unit_set_el_list_2, decl->pos);
2561 add_excls (unit_set_el_list_2, unit_set_el_list, decl->pos);
2565 /* Check presence set declarations and form presence sets. */
2566 for (i = 0; i < description->decls_num; i++)
2568 decl = description->decls [i];
2569 if (decl->mode == dm_presence)
2571 unit_set_el_t unit_set_el_list;
2572 pattern_set_el_t pattern_set_el_list;
2575 = process_presence_absence_names
2576 (DECL_PRESENCE (decl)->names, DECL_PRESENCE (decl)->names_num,
2577 decl->pos, TRUE, DECL_PRESENCE (decl)->final_p);
2579 = process_presence_absence_patterns
2580 (DECL_PRESENCE (decl)->patterns,
2581 DECL_PRESENCE (decl)->patterns_num,
2582 decl->pos, TRUE, DECL_PRESENCE (decl)->final_p);
2583 add_presence_absence (unit_set_el_list, pattern_set_el_list,
2585 DECL_PRESENCE (decl)->final_p);
2589 /* Check absence set declarations and form absence sets. */
2590 for (i = 0; i < description->decls_num; i++)
2592 decl = description->decls [i];
2593 if (decl->mode == dm_absence)
2595 unit_set_el_t unit_set_el_list;
2596 pattern_set_el_t pattern_set_el_list;
2599 = process_presence_absence_names
2600 (DECL_ABSENCE (decl)->names, DECL_ABSENCE (decl)->names_num,
2601 decl->pos, FALSE, DECL_ABSENCE (decl)->final_p);
2603 = process_presence_absence_patterns
2604 (DECL_ABSENCE (decl)->patterns,
2605 DECL_ABSENCE (decl)->patterns_num,
2606 decl->pos, FALSE, DECL_ABSENCE (decl)->final_p);
2607 add_presence_absence (unit_set_el_list, pattern_set_el_list,
2609 DECL_ABSENCE (decl)->final_p);
2614 /* The following function checks that declared automaton is used. If
2615 the automaton is not used, the function fixes error/warning. The
2616 following function must be called only after `process_decls'. */
2618 check_automaton_usage (void)
2623 for (i = 0; i < description->decls_num; i++)
2625 decl = description->decls [i];
2626 if (decl->mode == dm_automaton
2627 && !DECL_AUTOMATON (decl)->automaton_is_used)
2630 error ("automaton `%s' is not used", DECL_AUTOMATON (decl)->name);
2632 warning (0, "automaton `%s' is not used",
2633 DECL_AUTOMATON (decl)->name);
2638 /* The following recursive function processes all regexp in order to
2639 fix usage of units or reservations and to fix errors of undeclared
2640 name. The function may change unit_regexp onto reserv_regexp.
2641 Remember that reserv_regexp does not exist before the function
2644 process_regexp (regexp_t regexp)
2646 decl_t decl_in_table;
2647 regexp_t new_regexp;
2650 switch (regexp->mode)
2653 decl_in_table = find_decl (REGEXP_UNIT (regexp)->name);
2654 if (decl_in_table == NULL)
2655 error ("undeclared unit or reservation `%s'",
2656 REGEXP_UNIT (regexp)->name);
2658 switch (decl_in_table->mode)
2661 DECL_UNIT (decl_in_table)->unit_is_used = 1;
2662 REGEXP_UNIT (regexp)->unit_decl = DECL_UNIT (decl_in_table);
2666 DECL_RESERV (decl_in_table)->reserv_is_used = 1;
2667 new_regexp = create_node (sizeof (struct regexp));
2668 new_regexp->mode = rm_reserv;
2669 new_regexp->pos = regexp->pos;
2670 REGEXP_RESERV (new_regexp)->name = REGEXP_UNIT (regexp)->name;
2671 REGEXP_RESERV (new_regexp)->reserv_decl
2672 = DECL_RESERV (decl_in_table);
2673 regexp = new_regexp;
2681 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
2682 REGEXP_SEQUENCE (regexp)->regexps [i]
2683 = process_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
2686 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
2687 REGEXP_ALLOF (regexp)->regexps [i]
2688 = process_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
2691 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
2692 REGEXP_ONEOF (regexp)->regexps [i]
2693 = process_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
2696 REGEXP_REPEAT (regexp)->regexp
2697 = process_regexp (REGEXP_REPEAT (regexp)->regexp);
2707 /* The following function processes regexp of define_reservation and
2708 define_insn_reservation with the aid of function
2709 `process_regexp'. */
2711 process_regexp_decls (void)
2716 for (i = 0; i < description->decls_num; i++)
2718 decl = description->decls [i];
2719 if (decl->mode == dm_reserv)
2720 DECL_RESERV (decl)->regexp
2721 = process_regexp (DECL_RESERV (decl)->regexp);
2722 else if (decl->mode == dm_insn_reserv)
2723 DECL_INSN_RESERV (decl)->regexp
2724 = process_regexp (DECL_INSN_RESERV (decl)->regexp);
2728 /* The following function checks that declared unit is used. If the
2729 unit is not used, the function fixes errors/warnings. The
2730 following function must be called only after `process_decls',
2731 `process_regexp_decls'. */
2738 for (i = 0; i < description->decls_num; i++)
2740 decl = description->decls [i];
2741 if (decl->mode == dm_unit && !DECL_UNIT (decl)->unit_is_used)
2744 error ("unit `%s' is not used", DECL_UNIT (decl)->name);
2746 warning (0, "unit `%s' is not used", DECL_UNIT (decl)->name);
2748 else if (decl->mode == dm_reserv && !DECL_RESERV (decl)->reserv_is_used)
2751 error ("reservation `%s' is not used", DECL_RESERV (decl)->name);
2753 warning (0, "reservation `%s' is not used", DECL_RESERV (decl)->name);
2758 /* The following variable value is number of reservation being
2759 processed on loop recognition. */
2760 static int curr_loop_pass_num;
2762 /* The following recursive function returns nonzero value if REGEXP
2763 contains given decl or reservations in given regexp refers for
2766 loop_in_regexp (regexp_t regexp, decl_t start_decl)
2772 switch (regexp->mode)
2778 if (start_decl->mode == dm_reserv
2779 && REGEXP_RESERV (regexp)->reserv_decl == DECL_RESERV (start_decl))
2781 else if (REGEXP_RESERV (regexp)->reserv_decl->loop_pass_num
2782 == curr_loop_pass_num)
2783 /* declaration has been processed. */
2787 REGEXP_RESERV (regexp)->reserv_decl->loop_pass_num
2788 = curr_loop_pass_num;
2789 return loop_in_regexp (REGEXP_RESERV (regexp)->reserv_decl->regexp,
2794 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
2795 if (loop_in_regexp (REGEXP_SEQUENCE (regexp)->regexps [i], start_decl))
2800 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
2801 if (loop_in_regexp (REGEXP_ALLOF (regexp)->regexps [i], start_decl))
2806 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
2807 if (loop_in_regexp (REGEXP_ONEOF (regexp)->regexps [i], start_decl))
2812 return loop_in_regexp (REGEXP_REPEAT (regexp)->regexp, start_decl);
2822 /* The following function fixes errors "cycle in definition ...". The
2823 function uses function `loop_in_regexp' for that. */
2825 check_loops_in_regexps (void)
2830 for (i = 0; i < description->decls_num; i++)
2832 decl = description->decls [i];
2833 if (decl->mode == dm_reserv)
2834 DECL_RESERV (decl)->loop_pass_num = 0;
2836 for (i = 0; i < description->decls_num; i++)
2838 decl = description->decls [i];
2839 curr_loop_pass_num = i;
2841 if (decl->mode == dm_reserv)
2843 DECL_RESERV (decl)->loop_pass_num = curr_loop_pass_num;
2844 if (loop_in_regexp (DECL_RESERV (decl)->regexp, decl))
2846 gcc_assert (DECL_RESERV (decl)->regexp);
2847 error ("cycle in definition of reservation `%s'",
2848 DECL_RESERV (decl)->name);
2854 /* The function recursively processes IR of reservation and defines
2855 max and min cycle for reservation of unit. */
2857 process_regexp_cycles (regexp_t regexp, int max_start_cycle,
2858 int min_start_cycle, int *max_finish_cycle,
2859 int *min_finish_cycle)
2863 switch (regexp->mode)
2866 if (REGEXP_UNIT (regexp)->unit_decl->max_occ_cycle_num < max_start_cycle)
2867 REGEXP_UNIT (regexp)->unit_decl->max_occ_cycle_num = max_start_cycle;
2868 if (REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num > min_start_cycle
2869 || REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num == -1)
2870 REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num = min_start_cycle;
2871 *max_finish_cycle = max_start_cycle;
2872 *min_finish_cycle = min_start_cycle;
2876 process_regexp_cycles (REGEXP_RESERV (regexp)->reserv_decl->regexp,
2877 max_start_cycle, min_start_cycle,
2878 max_finish_cycle, min_finish_cycle);
2882 for (i = 0; i < REGEXP_REPEAT (regexp)->repeat_num; i++)
2884 process_regexp_cycles (REGEXP_REPEAT (regexp)->regexp,
2885 max_start_cycle, min_start_cycle,
2886 max_finish_cycle, min_finish_cycle);
2887 max_start_cycle = *max_finish_cycle + 1;
2888 min_start_cycle = *min_finish_cycle + 1;
2893 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
2895 process_regexp_cycles (REGEXP_SEQUENCE (regexp)->regexps [i],
2896 max_start_cycle, min_start_cycle,
2897 max_finish_cycle, min_finish_cycle);
2898 max_start_cycle = *max_finish_cycle + 1;
2899 min_start_cycle = *min_finish_cycle + 1;
2908 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
2910 process_regexp_cycles (REGEXP_ALLOF (regexp)->regexps [i],
2911 max_start_cycle, min_start_cycle,
2912 max_finish_cycle, min_finish_cycle);
2913 if (max_cycle < *max_finish_cycle)
2914 max_cycle = *max_finish_cycle;
2915 if (i == 0 || min_cycle > *min_finish_cycle)
2916 min_cycle = *min_finish_cycle;
2918 *max_finish_cycle = max_cycle;
2919 *min_finish_cycle = min_cycle;
2928 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
2930 process_regexp_cycles (REGEXP_ONEOF (regexp)->regexps [i],
2931 max_start_cycle, min_start_cycle,
2932 max_finish_cycle, min_finish_cycle);
2933 if (max_cycle < *max_finish_cycle)
2934 max_cycle = *max_finish_cycle;
2935 if (i == 0 || min_cycle > *min_finish_cycle)
2936 min_cycle = *min_finish_cycle;
2938 *max_finish_cycle = max_cycle;
2939 *min_finish_cycle = min_cycle;
2944 *max_finish_cycle = max_start_cycle;
2945 *min_finish_cycle = min_start_cycle;
2953 /* The following function is called only for correct program. The
2954 function defines max reservation of insns in cycles. */
2956 evaluate_max_reserv_cycles (void)
2958 int max_insn_cycles_num;
2959 int min_insn_cycles_num;
2963 description->max_insn_reserv_cycles = 0;
2964 for (i = 0; i < description->decls_num; i++)
2966 decl = description->decls [i];
2967 if (decl->mode == dm_insn_reserv)
2969 process_regexp_cycles (DECL_INSN_RESERV (decl)->regexp, 0, 0,
2970 &max_insn_cycles_num, &min_insn_cycles_num);
2971 if (description->max_insn_reserv_cycles < max_insn_cycles_num)
2972 description->max_insn_reserv_cycles = max_insn_cycles_num;
2975 description->max_insn_reserv_cycles++;
2978 /* The following function calls functions for checking all
2981 check_all_description (void)
2984 check_automaton_usage ();
2985 process_regexp_decls ();
2987 check_loops_in_regexps ();
2989 evaluate_max_reserv_cycles ();
2994 /* The page contains abstract data `ticker'. This data is used to
2995 report time of different phases of building automata. It is
2996 possibly to write a description for which automata will be built
2997 during several minutes even on fast machine. */
2999 /* The following function creates ticker and makes it active. */
3001 create_ticker (void)
3005 ticker.modified_creation_time = get_run_time ();
3006 ticker.incremented_off_time = 0;
3010 /* The following function switches off given ticker. */
3012 ticker_off (ticker_t *ticker)
3014 if (ticker->incremented_off_time == 0)
3015 ticker->incremented_off_time = get_run_time () + 1;
3018 /* The following function switches on given ticker. */
3020 ticker_on (ticker_t *ticker)
3022 if (ticker->incremented_off_time != 0)
3024 ticker->modified_creation_time
3025 += get_run_time () - ticker->incremented_off_time + 1;
3026 ticker->incremented_off_time = 0;
3030 /* The following function returns current time in milliseconds since
3031 the moment when given ticker was created. */
3033 active_time (ticker_t ticker)
3035 if (ticker.incremented_off_time != 0)
3036 return ticker.incremented_off_time - 1 - ticker.modified_creation_time;
3038 return get_run_time () - ticker.modified_creation_time;
3041 /* The following function returns string representation of active time
3042 of given ticker. The result is string representation of seconds
3043 with accuracy of 1/100 second. Only result of the last call of the
3044 function exists. Therefore the following code is not correct
3046 printf ("parser time: %s\ngeneration time: %s\n",
3047 active_time_string (parser_ticker),
3048 active_time_string (generation_ticker));
3050 Correct code has to be the following
3052 printf ("parser time: %s\n", active_time_string (parser_ticker));
3053 printf ("generation time: %s\n",
3054 active_time_string (generation_ticker));
3058 print_active_time (FILE *f, ticker_t ticker)
3062 msecs = active_time (ticker);
3063 fprintf (f, "%d.%06d", msecs / 1000000, msecs % 1000000);
3068 /* The following variable value is number of automaton which are
3069 really being created. This value is defined on the base of
3070 argument of option `-split'. If the variable has zero value the
3071 number of automata is defined by the constructions `%automaton'.
3072 This case occurs when option `-split' is absent or has zero
3073 argument. If constructions `define_automaton' is absent only one
3074 automaton is created. */
3075 static int automata_num;
3077 /* The following variable values are times of
3078 o transformation of regular expressions
3079 o building NDFA (DFA if !ndfa_flag)
3080 o NDFA -> DFA (simply the same automaton if !ndfa_flag)
3082 o building insn equivalence classes
3085 static ticker_t transform_time;
3086 static ticker_t NDFA_time;
3087 static ticker_t NDFA_to_DFA_time;
3088 static ticker_t minimize_time;
3089 static ticker_t equiv_time;
3090 static ticker_t automaton_generation_time;
3091 static ticker_t output_time;
3093 /* The following variable values are times of
3096 all pipeline hazard translator work */
3097 static ticker_t check_time;
3098 static ticker_t generation_time;
3099 static ticker_t all_time;
3103 /* Pseudo insn decl which denotes advancing cycle. */
3104 static decl_t advance_cycle_insn_decl;
3106 add_advance_cycle_insn_decl (void)
3108 advance_cycle_insn_decl = create_node (sizeof (struct decl));
3109 advance_cycle_insn_decl->mode = dm_insn_reserv;
3110 advance_cycle_insn_decl->pos = no_pos;
3111 DECL_INSN_RESERV (advance_cycle_insn_decl)->regexp = NULL;
3112 DECL_INSN_RESERV (advance_cycle_insn_decl)->name = "$advance_cycle";
3113 DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num
3114 = description->insns_num;
3115 description->decls [description->decls_num] = advance_cycle_insn_decl;
3116 description->decls_num++;
3117 description->insns_num++;
3121 /* Abstract data `alternative states' which represents
3122 nondeterministic nature of the description (see comments for
3123 structures alt_state and state). */
3125 /* List of free states. */
3126 static alt_state_t first_free_alt_state;
3129 /* The following variables is maximal number of allocated nodes
3131 static int allocated_alt_states_num = 0;
3134 /* The following function returns free node alt_state. It may be new
3135 allocated node or node freed earlier. */
3137 get_free_alt_state (void)
3141 if (first_free_alt_state != NULL)
3143 result = first_free_alt_state;
3144 first_free_alt_state = first_free_alt_state->next_alt_state;
3149 allocated_alt_states_num++;
3151 result = create_node (sizeof (struct alt_state));
3153 result->state = NULL;
3154 result->next_alt_state = NULL;
3155 result->next_sorted_alt_state = NULL;
3159 /* The function frees node ALT_STATE. */
3161 free_alt_state (alt_state_t alt_state)
3163 if (alt_state == NULL)
3165 alt_state->next_alt_state = first_free_alt_state;
3166 first_free_alt_state = alt_state;
3169 /* The function frees list started with node ALT_STATE_LIST. */
3171 free_alt_states (alt_state_t alt_states_list)
3173 alt_state_t curr_alt_state;
3174 alt_state_t next_alt_state;
3176 for (curr_alt_state = alt_states_list;
3177 curr_alt_state != NULL;
3178 curr_alt_state = next_alt_state)
3180 next_alt_state = curr_alt_state->next_alt_state;
3181 free_alt_state (curr_alt_state);
3185 /* The function compares unique numbers of alt states. */
3187 alt_state_cmp (const void *alt_state_ptr_1, const void *alt_state_ptr_2)
3189 if ((*(const alt_state_t *) alt_state_ptr_1)->state->unique_num
3190 == (*(const alt_state_t *) alt_state_ptr_2)->state->unique_num)
3192 else if ((*(const alt_state_t *) alt_state_ptr_1)->state->unique_num
3193 < (*(const alt_state_t *) alt_state_ptr_2)->state->unique_num)
3199 /* The function sorts ALT_STATES_LIST and removes duplicated alt
3200 states from the list. The comparison key is alt state unique
3204 uniq_sort_alt_states (alt_state_t alt_states_list)
3206 alt_state_t curr_alt_state;
3207 VEC(alt_state_t,heap) *alt_states;
3209 size_t prev_unique_state_ind;
3212 if (alt_states_list == 0)
3214 if (alt_states_list->next_alt_state == 0)
3215 return alt_states_list;
3217 alt_states = VEC_alloc (alt_state_t,heap, 150);
3218 for (curr_alt_state = alt_states_list;
3219 curr_alt_state != NULL;
3220 curr_alt_state = curr_alt_state->next_alt_state)
3221 VEC_safe_push (alt_state_t,heap, alt_states, curr_alt_state);
3223 qsort (VEC_address (alt_state_t, alt_states),
3224 VEC_length (alt_state_t, alt_states),
3225 sizeof (alt_state_t), alt_state_cmp);
3227 prev_unique_state_ind = 0;
3228 for (i = 1; i < VEC_length (alt_state_t, alt_states); i++)
3229 if (VEC_index (alt_state_t, alt_states, prev_unique_state_ind)->state
3230 != VEC_index (alt_state_t, alt_states, i)->state)
3232 prev_unique_state_ind++;
3233 VEC_replace (alt_state_t, alt_states, prev_unique_state_ind,
3234 VEC_index (alt_state_t, alt_states, i));
3236 VEC_truncate (alt_state_t, alt_states, prev_unique_state_ind + 1);
3238 for (i = 1; i < VEC_length (alt_state_t, alt_states); i++)
3239 VEC_index (alt_state_t, alt_states, i-1)->next_sorted_alt_state
3240 = VEC_index (alt_state_t, alt_states, i);
3241 VEC_last (alt_state_t, alt_states)->next_sorted_alt_state = 0;
3243 result = VEC_index (alt_state_t, alt_states, 0);
3245 VEC_free (alt_state_t,heap, alt_states);
3249 /* The function checks equality of alt state lists. Remember that the
3250 lists must be already sorted by the previous function. */
3252 alt_states_eq (alt_state_t alt_states_1, alt_state_t alt_states_2)
3254 while (alt_states_1 != NULL && alt_states_2 != NULL
3255 && alt_state_cmp (&alt_states_1, &alt_states_2) == 0)
3257 alt_states_1 = alt_states_1->next_sorted_alt_state;
3258 alt_states_2 = alt_states_2->next_sorted_alt_state;
3260 return alt_states_1 == alt_states_2;
3263 /* Initialization of the abstract data. */
3265 initiate_alt_states (void)
3267 first_free_alt_state = NULL;
3270 /* Finishing work with the abstract data. */
3272 finish_alt_states (void)
3278 /* The page contains macros for work with bits strings. We could use
3279 standard gcc bitmap or sbitmap but it would result in difficulties
3280 of building canadian cross. */
3282 /* Set bit number bitno in the bit string. The macro is not side
3284 #define SET_BIT(bitstring, bitno) \
3285 (((char *) (bitstring)) [(bitno) / CHAR_BIT] |= 1 << (bitno) % CHAR_BIT)
3287 #define CLEAR_BIT(bitstring, bitno) \
3288 (((char *) (bitstring)) [(bitno) / CHAR_BIT] &= ~(1 << (bitno) % CHAR_BIT))
3290 /* Test if bit number bitno in the bitstring is set. The macro is not
3291 side effect proof. */
3292 #define TEST_BIT(bitstring, bitno) \
3293 (((char *) (bitstring)) [(bitno) / CHAR_BIT] >> (bitno) % CHAR_BIT & 1)
3297 /* This page contains abstract data `state'. */
3299 /* Maximal length of reservations in cycles (>= 1). */
3300 static int max_cycles_num;
3302 /* Number of set elements (see type set_el_t) needed for
3303 representation of one cycle reservation. It is depended on units
3305 static int els_in_cycle_reserv;
3307 /* Number of set elements (see type set_el_t) needed for
3308 representation of maximal length reservation. Deterministic
3309 reservation is stored as set (bit string) of length equal to the
3310 variable value * number of bits in set_el_t. */
3311 static int els_in_reservs;
3313 /* Array of pointers to unit declarations. */
3314 static unit_decl_t *units_array;
3316 /* Temporary reservation of maximal length. */
3317 static reserv_sets_t temp_reserv;
3319 /* The state table itself is represented by the following variable. */
3320 static htab_t state_table;
3322 /* Linked list of free 'state' structures to be recycled. The
3323 next_equiv_class_state pointer is borrowed for a free list. */
3324 static state_t first_free_state;
3326 static int curr_unique_state_num;
3329 /* The following variables is maximal number of allocated nodes
3331 static int allocated_states_num = 0;
3334 /* Allocate new reservation set. */
3335 static reserv_sets_t
3336 alloc_empty_reserv_sets (void)
3338 reserv_sets_t result;
3340 obstack_blank (&irp, els_in_reservs * sizeof (set_el_t));
3341 result = (reserv_sets_t) obstack_base (&irp);
3342 obstack_finish (&irp);
3343 memset (result, 0, els_in_reservs * sizeof (set_el_t));
3347 /* Hash value of reservation set. */
3349 reserv_sets_hash_value (reserv_sets_t reservs)
3351 set_el_t hash_value;
3354 set_el_t *reserv_ptr;
3357 reservs_num = els_in_reservs;
3358 reserv_ptr = reservs;
3360 while (reservs_num != 0)
3363 hash_value += ((*reserv_ptr >> i)
3364 | (*reserv_ptr << (sizeof (set_el_t) * CHAR_BIT - i)));
3366 if (i == sizeof (set_el_t) * CHAR_BIT)
3370 if (sizeof (set_el_t) <= sizeof (unsigned))
3373 for (i = sizeof (set_el_t); i > 0; i -= sizeof (unsigned) - 1)
3375 result += (unsigned) hash_value;
3376 hash_value >>= (sizeof (unsigned) - 1) * CHAR_BIT;
3381 /* Comparison of given reservation sets. */
3383 reserv_sets_cmp (const_reserv_sets_t reservs_1, const_reserv_sets_t reservs_2)
3386 const set_el_t *reserv_ptr_1;
3387 const set_el_t *reserv_ptr_2;
3389 gcc_assert (reservs_1 && reservs_2);
3390 reservs_num = els_in_reservs;
3391 reserv_ptr_1 = reservs_1;
3392 reserv_ptr_2 = reservs_2;
3393 while (reservs_num != 0 && *reserv_ptr_1 == *reserv_ptr_2)
3399 if (reservs_num == 0)
3401 else if (*reserv_ptr_1 < *reserv_ptr_2)
3407 /* The function checks equality of the reservation sets. */
3409 reserv_sets_eq (const_reserv_sets_t reservs_1, const_reserv_sets_t reservs_2)
3411 return reserv_sets_cmp (reservs_1, reservs_2) == 0;
3414 /* Set up in the reservation set that unit with UNIT_NUM is used on
3417 set_unit_reserv (reserv_sets_t reservs, int cycle_num, int unit_num)
3419 gcc_assert (cycle_num < max_cycles_num);
3420 SET_BIT (reservs, cycle_num * els_in_cycle_reserv
3421 * sizeof (set_el_t) * CHAR_BIT + unit_num);
3424 /* Set up in the reservation set RESERVS that unit with UNIT_NUM is
3425 used on CYCLE_NUM. */
3427 test_unit_reserv (reserv_sets_t reservs, int cycle_num, int unit_num)
3429 gcc_assert (cycle_num < max_cycles_num);
3430 return TEST_BIT (reservs, cycle_num * els_in_cycle_reserv
3431 * sizeof (set_el_t) * CHAR_BIT + unit_num);
3434 /* The function checks that the reservation sets are intersected,
3435 i.e. there is a unit reservation on a cycle in both reservation
3438 reserv_sets_are_intersected (reserv_sets_t operand_1,
3439 reserv_sets_t operand_2)
3443 set_el_t *cycle_ptr_1;
3444 set_el_t *cycle_ptr_2;
3446 gcc_assert (operand_1 && operand_2);
3447 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2;
3448 el_ptr_1 < operand_1 + els_in_reservs;
3449 el_ptr_1++, el_ptr_2++)
3450 if (*el_ptr_1 & *el_ptr_2)
3452 reserv_sets_or (temp_reserv, operand_1, operand_2);
3453 for (cycle_ptr_1 = operand_1, cycle_ptr_2 = operand_2;
3454 cycle_ptr_1 < operand_1 + els_in_reservs;
3455 cycle_ptr_1 += els_in_cycle_reserv, cycle_ptr_2 += els_in_cycle_reserv)
3457 for (el_ptr_1 = cycle_ptr_1, el_ptr_2 = get_excl_set (cycle_ptr_2);
3458 el_ptr_1 < cycle_ptr_1 + els_in_cycle_reserv;
3459 el_ptr_1++, el_ptr_2++)
3460 if (*el_ptr_1 & *el_ptr_2)
3462 if (!check_presence_pattern_sets (cycle_ptr_1, cycle_ptr_2, FALSE))
3464 if (!check_presence_pattern_sets (temp_reserv + (cycle_ptr_2
3468 if (!check_absence_pattern_sets (cycle_ptr_1, cycle_ptr_2, FALSE))
3470 if (!check_absence_pattern_sets (temp_reserv + (cycle_ptr_2 - operand_2),
3477 /* The function sets up RESULT bits by bits of OPERAND shifted on one
3478 cpu cycle. The remaining bits of OPERAND (representing the last
3479 cycle unit reservations) are not changed. */
3481 reserv_sets_shift (reserv_sets_t result, reserv_sets_t operand)
3485 gcc_assert (result && operand && result != operand);
3486 for (i = els_in_cycle_reserv; i < els_in_reservs; i++)
3487 result [i - els_in_cycle_reserv] = operand [i];
3490 /* OR of the reservation sets. */
3492 reserv_sets_or (reserv_sets_t result, reserv_sets_t operand_1,
3493 reserv_sets_t operand_2)
3497 set_el_t *result_set_el_ptr;
3499 gcc_assert (result && operand_1 && operand_2);
3500 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2, result_set_el_ptr = result;
3501 el_ptr_1 < operand_1 + els_in_reservs;
3502 el_ptr_1++, el_ptr_2++, result_set_el_ptr++)
3503 *result_set_el_ptr = *el_ptr_1 | *el_ptr_2;
3506 /* AND of the reservation sets. */
3508 reserv_sets_and (reserv_sets_t result, reserv_sets_t operand_1,
3509 reserv_sets_t operand_2)
3513 set_el_t *result_set_el_ptr;
3515 gcc_assert (result && operand_1 && operand_2);
3516 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2, result_set_el_ptr = result;
3517 el_ptr_1 < operand_1 + els_in_reservs;
3518 el_ptr_1++, el_ptr_2++, result_set_el_ptr++)
3519 *result_set_el_ptr = *el_ptr_1 & *el_ptr_2;
3522 /* The function outputs string representation of units reservation on
3523 cycle START_CYCLE in the reservation set. The function uses repeat
3524 construction if REPETITION_NUM > 1. */
3526 output_cycle_reservs (FILE *f, reserv_sets_t reservs, int start_cycle,
3530 int reserved_units_num;
3532 reserved_units_num = 0;
3533 for (unit_num = 0; unit_num < description->units_num; unit_num++)
3534 if (TEST_BIT (reservs, start_cycle * els_in_cycle_reserv
3535 * sizeof (set_el_t) * CHAR_BIT + unit_num))
3536 reserved_units_num++;
3537 gcc_assert (repetition_num > 0);
3538 if (repetition_num != 1 && reserved_units_num > 1)
3540 reserved_units_num = 0;
3542 unit_num < description->units_num;
3544 if (TEST_BIT (reservs, start_cycle * els_in_cycle_reserv
3545 * sizeof (set_el_t) * CHAR_BIT + unit_num))
3547 if (reserved_units_num != 0)
3549 reserved_units_num++;
3550 fprintf (f, "%s", units_array [unit_num]->name);
3552 if (reserved_units_num == 0)
3553 fprintf (f, NOTHING_NAME);
3554 gcc_assert (repetition_num > 0);
3555 if (repetition_num != 1 && reserved_units_num > 1)
3557 if (repetition_num != 1)
3558 fprintf (f, "*%d", repetition_num);
3561 /* The function outputs string representation of units reservation in
3562 the reservation set. */
3564 output_reserv_sets (FILE *f, reserv_sets_t reservs)
3566 int start_cycle = 0;
3571 for (cycle = 0; cycle < max_cycles_num; cycle++)
3572 if (repetition_num == 0)
3575 start_cycle = cycle;
3578 ((char *) reservs + start_cycle * els_in_cycle_reserv
3579 * sizeof (set_el_t),
3580 (char *) reservs + cycle * els_in_cycle_reserv
3581 * sizeof (set_el_t),
3582 els_in_cycle_reserv * sizeof (set_el_t)) == 0)
3586 if (start_cycle != 0)
3588 output_cycle_reservs (f, reservs, start_cycle, repetition_num);
3590 start_cycle = cycle;
3592 if (start_cycle < max_cycles_num)
3594 if (start_cycle != 0)
3596 output_cycle_reservs (f, reservs, start_cycle, repetition_num);
3600 /* The following function returns free node state for AUTOMATON. It
3601 may be new allocated node or node freed earlier. The function also
3602 allocates reservation set if WITH_RESERVS has nonzero value. */
3604 get_free_state (int with_reservs, automaton_t automaton)
3608 gcc_assert (max_cycles_num > 0 && automaton);
3609 if (first_free_state)
3611 result = first_free_state;
3612 first_free_state = result->next_equiv_class_state;
3614 result->next_equiv_class_state = NULL;
3615 result->automaton = automaton;
3616 result->first_out_arc = NULL;
3617 result->it_was_placed_in_stack_for_NDFA_forming = 0;
3618 result->it_was_placed_in_stack_for_DFA_forming = 0;
3619 result->component_states = NULL;
3624 allocated_states_num++;
3626 result = create_node (sizeof (struct state));
3627 result->automaton = automaton;
3628 result->first_out_arc = NULL;
3629 result->unique_num = curr_unique_state_num;
3630 curr_unique_state_num++;
3634 if (result->reservs == NULL)
3635 result->reservs = alloc_empty_reserv_sets ();
3637 memset (result->reservs, 0, els_in_reservs * sizeof (set_el_t));
3642 /* The function frees node STATE. */
3644 free_state (state_t state)
3646 free_alt_states (state->component_states);
3647 state->next_equiv_class_state = first_free_state;
3648 first_free_state = state;
3651 /* Hash value of STATE. If STATE represents deterministic state it is
3652 simply hash value of the corresponding reservation set. Otherwise
3653 it is formed from hash values of the component deterministic
3654 states. One more key is order number of state automaton. */
3656 state_hash (const void *state)
3658 unsigned int hash_value;
3659 alt_state_t alt_state;
3661 if (((const_state_t) state)->component_states == NULL)
3662 hash_value = reserv_sets_hash_value (((const_state_t) state)->reservs);
3666 for (alt_state = ((const_state_t) state)->component_states;
3668 alt_state = alt_state->next_sorted_alt_state)
3669 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
3670 | (hash_value << CHAR_BIT))
3671 + alt_state->state->unique_num);
3673 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
3674 | (hash_value << CHAR_BIT))
3675 + ((const_state_t) state)->automaton->automaton_order_num);
3679 /* Return nonzero value if the states are the same. */
3681 state_eq_p (const void *state_1, const void *state_2)
3683 alt_state_t alt_state_1;
3684 alt_state_t alt_state_2;
3686 if (((const_state_t) state_1)->automaton != ((const_state_t) state_2)->automaton)
3688 else if (((const_state_t) state_1)->component_states == NULL
3689 && ((const_state_t) state_2)->component_states == NULL)
3690 return reserv_sets_eq (((const_state_t) state_1)->reservs,
3691 ((const_state_t) state_2)->reservs);
3692 else if (((const_state_t) state_1)->component_states != NULL
3693 && ((const_state_t) state_2)->component_states != NULL)
3695 for (alt_state_1 = ((const_state_t) state_1)->component_states,
3696 alt_state_2 = ((const_state_t) state_2)->component_states;
3697 alt_state_1 != NULL && alt_state_2 != NULL;
3698 alt_state_1 = alt_state_1->next_sorted_alt_state,
3699 alt_state_2 = alt_state_2->next_sorted_alt_state)
3700 /* All state in the list must be already in the hash table.
3701 Also the lists must be sorted. */
3702 if (alt_state_1->state != alt_state_2->state)
3704 return alt_state_1 == alt_state_2;
3710 /* Insert STATE into the state table. */
3712 insert_state (state_t state)
3716 entry_ptr = htab_find_slot (state_table, (void *) state, 1);
3717 if (*entry_ptr == NULL)
3718 *entry_ptr = (void *) state;
3719 return (state_t) *entry_ptr;
3722 /* Add reservation of unit with UNIT_NUM on cycle CYCLE_NUM to
3723 deterministic STATE. */
3725 set_state_reserv (state_t state, int cycle_num, int unit_num)
3727 set_unit_reserv (state->reservs, cycle_num, unit_num);
3730 /* Return nonzero value if the deterministic states contains a
3731 reservation of the same cpu unit on the same cpu cycle. */
3733 intersected_state_reservs_p (state_t state1, state_t state2)
3735 gcc_assert (state1->automaton == state2->automaton);
3736 return reserv_sets_are_intersected (state1->reservs, state2->reservs);
3739 /* Return deterministic state (inserted into the table) which
3740 representing the automaton state which is union of reservations of
3741 the deterministic states masked by RESERVS. */
3743 states_union (state_t state1, state_t state2, reserv_sets_t reservs)
3746 state_t state_in_table;
3748 gcc_assert (state1->automaton == state2->automaton);
3749 result = get_free_state (1, state1->automaton);
3750 reserv_sets_or (result->reservs, state1->reservs, state2->reservs);
3751 reserv_sets_and (result->reservs, result->reservs, reservs);
3752 state_in_table = insert_state (result);
3753 if (result != state_in_table)
3755 free_state (result);
3756 result = state_in_table;
3761 /* Return deterministic state (inserted into the table) which
3762 represent the automaton state is obtained from deterministic STATE
3763 by advancing cpu cycle and masking by RESERVS. */
3765 state_shift (state_t state, reserv_sets_t reservs)
3768 state_t state_in_table;
3770 result = get_free_state (1, state->automaton);
3771 reserv_sets_shift (result->reservs, state->reservs);
3772 reserv_sets_and (result->reservs, result->reservs, reservs);
3773 state_in_table = insert_state (result);
3774 if (result != state_in_table)
3776 free_state (result);
3777 result = state_in_table;
3782 /* Initialization of the abstract data. */
3784 initiate_states (void)
3789 if (description->units_num)
3790 units_array = XNEWVEC (unit_decl_t, description->units_num);
3794 for (i = 0; i < description->decls_num; i++)
3796 decl = description->decls [i];
3797 if (decl->mode == dm_unit)
3798 units_array [DECL_UNIT (decl)->unit_num] = DECL_UNIT (decl);
3800 max_cycles_num = description->max_insn_reserv_cycles;
3802 = ((description->units_num + sizeof (set_el_t) * CHAR_BIT - 1)
3803 / (sizeof (set_el_t) * CHAR_BIT));
3804 els_in_reservs = els_in_cycle_reserv * max_cycles_num;
3805 curr_unique_state_num = 0;
3806 initiate_alt_states ();
3807 state_table = htab_create (1500, state_hash, state_eq_p, (htab_del) 0);
3808 temp_reserv = alloc_empty_reserv_sets ();
3811 /* Finishing work with the abstract data. */
3813 finish_states (void)
3817 htab_delete (state_table);
3818 first_free_state = NULL;
3819 finish_alt_states ();
3824 /* Abstract data `arcs'. */
3826 /* List of free arcs. */
3827 static arc_t first_free_arc;
3830 /* The following variables is maximal number of allocated nodes
3832 static int allocated_arcs_num = 0;
3835 /* The function frees node ARC. */
3837 free_arc (arc_t arc)
3839 arc->next_out_arc = first_free_arc;
3840 first_free_arc = arc;
3843 /* The function removes and frees ARC staring from FROM_STATE. */
3845 remove_arc (state_t from_state, arc_t arc)
3851 for (prev_arc = NULL, curr_arc = from_state->first_out_arc;
3853 prev_arc = curr_arc, curr_arc = curr_arc->next_out_arc)
3854 if (curr_arc == arc)
3856 gcc_assert (curr_arc);
3857 if (prev_arc == NULL)
3858 from_state->first_out_arc = arc->next_out_arc;
3860 prev_arc->next_out_arc = arc->next_out_arc;
3861 from_state->num_out_arcs--;
3865 /* The functions returns arc with given characteristics (or NULL if
3866 the arc does not exist). */
3868 find_arc (state_t from_state, state_t to_state, ainsn_t insn)
3872 for (arc = first_out_arc (from_state); arc != NULL; arc = next_out_arc (arc))
3873 if (arc->to_state == to_state && arc->insn == insn)
3878 /* The function adds arc from FROM_STATE to TO_STATE marked by AINSN.
3879 The function returns added arc (or already existing arc). */
3881 add_arc (state_t from_state, state_t to_state, ainsn_t ainsn)
3885 new_arc = find_arc (from_state, to_state, ainsn);
3886 if (new_arc != NULL)
3888 if (first_free_arc == NULL)
3891 allocated_arcs_num++;
3893 new_arc = create_node (sizeof (struct arc));
3894 new_arc->to_state = NULL;
3895 new_arc->insn = NULL;
3896 new_arc->next_out_arc = NULL;
3900 new_arc = first_free_arc;
3901 first_free_arc = first_free_arc->next_out_arc;
3903 new_arc->to_state = to_state;
3904 new_arc->insn = ainsn;
3905 ainsn->arc_exists_p = 1;
3906 new_arc->next_out_arc = from_state->first_out_arc;
3907 from_state->first_out_arc = new_arc;
3908 from_state->num_out_arcs++;
3909 new_arc->next_arc_marked_by_insn = NULL;
3913 /* The function returns the first arc starting from STATE. */
3915 first_out_arc (const_state_t state)
3917 return state->first_out_arc;
3920 /* The function returns next out arc after ARC. */
3922 next_out_arc (arc_t arc)
3924 return arc->next_out_arc;
3927 /* Initialization of the abstract data. */
3929 initiate_arcs (void)
3931 first_free_arc = NULL;
3934 /* Finishing work with the abstract data. */
3942 /* Abstract data `automata lists'. */
3944 /* List of free states. */
3945 static automata_list_el_t first_free_automata_list_el;
3947 /* The list being formed. */
3948 static automata_list_el_t current_automata_list;
3950 /* Hash table of automata lists. */
3951 static htab_t automata_list_table;
3953 /* The following function returns free automata list el. It may be
3954 new allocated node or node freed earlier. */
3955 static automata_list_el_t
3956 get_free_automata_list_el (void)
3958 automata_list_el_t result;
3960 if (first_free_automata_list_el != NULL)
3962 result = first_free_automata_list_el;
3963 first_free_automata_list_el
3964 = first_free_automata_list_el->next_automata_list_el;
3967 result = create_node (sizeof (struct automata_list_el));
3968 result->automaton = NULL;
3969 result->next_automata_list_el = NULL;
3973 /* The function frees node AUTOMATA_LIST_EL. */
3975 free_automata_list_el (automata_list_el_t automata_list_el)
3977 if (automata_list_el == NULL)
3979 automata_list_el->next_automata_list_el = first_free_automata_list_el;
3980 first_free_automata_list_el = automata_list_el;
3983 /* The function frees list AUTOMATA_LIST. */
3985 free_automata_list (automata_list_el_t automata_list)
3987 automata_list_el_t curr_automata_list_el;
3988 automata_list_el_t next_automata_list_el;
3990 for (curr_automata_list_el = automata_list;
3991 curr_automata_list_el != NULL;
3992 curr_automata_list_el = next_automata_list_el)
3994 next_automata_list_el = curr_automata_list_el->next_automata_list_el;
3995 free_automata_list_el (curr_automata_list_el);
3999 /* Hash value of AUTOMATA_LIST. */
4001 automata_list_hash (const void *automata_list)
4003 unsigned int hash_value;
4004 const_automata_list_el_t curr_automata_list_el;
4007 for (curr_automata_list_el = (const_automata_list_el_t) automata_list;
4008 curr_automata_list_el != NULL;
4009 curr_automata_list_el = curr_automata_list_el->next_automata_list_el)
4010 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
4011 | (hash_value << CHAR_BIT))
4012 + curr_automata_list_el->automaton->automaton_order_num);
4016 /* Return nonzero value if the automata_lists are the same. */
4018 automata_list_eq_p (const void *automata_list_1, const void *automata_list_2)
4020 const_automata_list_el_t automata_list_el_1;
4021 const_automata_list_el_t automata_list_el_2;
4023 for (automata_list_el_1 = (const_automata_list_el_t) automata_list_1,
4024 automata_list_el_2 = (const_automata_list_el_t) automata_list_2;
4025 automata_list_el_1 != NULL && automata_list_el_2 != NULL;
4026 automata_list_el_1 = automata_list_el_1->next_automata_list_el,
4027 automata_list_el_2 = automata_list_el_2->next_automata_list_el)
4028 if (automata_list_el_1->automaton != automata_list_el_2->automaton)
4030 return automata_list_el_1 == automata_list_el_2;
4033 /* Initialization of the abstract data. */
4035 initiate_automata_lists (void)
4037 first_free_automata_list_el = NULL;
4038 automata_list_table = htab_create (1500, automata_list_hash,
4039 automata_list_eq_p, (htab_del) 0);
4042 /* The following function starts new automata list and makes it the
4045 automata_list_start (void)
4047 current_automata_list = NULL;
4050 /* The following function adds AUTOMATON to the current list. */
4052 automata_list_add (automaton_t automaton)
4054 automata_list_el_t el;
4056 el = get_free_automata_list_el ();
4057 el->automaton = automaton;
4058 el->next_automata_list_el = current_automata_list;
4059 current_automata_list = el;
4062 /* The following function finishes forming the current list, inserts
4063 it into the table and returns it. */
4064 static automata_list_el_t
4065 automata_list_finish (void)
4069 if (current_automata_list == NULL)
4071 entry_ptr = htab_find_slot (automata_list_table,
4072 (void *) current_automata_list, 1);
4073 if (*entry_ptr == NULL)
4074 *entry_ptr = (void *) current_automata_list;
4076 free_automata_list (current_automata_list);
4077 current_automata_list = NULL;
4078 return (automata_list_el_t) *entry_ptr;
4081 /* Finishing work with the abstract data. */
4083 finish_automata_lists (void)
4085 htab_delete (automata_list_table);
4090 /* The page contains abstract data for work with exclusion sets (see
4091 exclusion_set in file rtl.def). */
4093 /* The following variable refers to an exclusion set returned by
4094 get_excl_set. This is bit string of length equal to cpu units
4095 number. If exclusion set for given unit contains 1 for a unit,
4096 then simultaneous reservation of the units is prohibited. */
4097 static reserv_sets_t excl_set;
4099 /* The array contains exclusion sets for each unit. */
4100 static reserv_sets_t *unit_excl_set_table;
4102 /* The following function forms the array containing exclusion sets
4105 initiate_excl_sets (void)
4108 reserv_sets_t unit_excl_set;
4112 obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4113 excl_set = (reserv_sets_t) obstack_base (&irp);
4114 obstack_finish (&irp);
4115 obstack_blank (&irp, description->units_num * sizeof (reserv_sets_t));
4116 unit_excl_set_table = (reserv_sets_t *) obstack_base (&irp);
4117 obstack_finish (&irp);
4118 /* Evaluate unit exclusion sets. */
4119 for (i = 0; i < description->decls_num; i++)
4121 decl = description->decls [i];
4122 if (decl->mode == dm_unit)
4124 obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4125 unit_excl_set = (reserv_sets_t) obstack_base (&irp);
4126 obstack_finish (&irp);
4127 memset (unit_excl_set, 0, els_in_cycle_reserv * sizeof (set_el_t));
4128 for (el = DECL_UNIT (decl)->excl_list;
4130 el = el->next_unit_set_el)
4132 SET_BIT (unit_excl_set, el->unit_decl->unit_num);
4133 el->unit_decl->in_set_p = TRUE;
4135 unit_excl_set_table [DECL_UNIT (decl)->unit_num] = unit_excl_set;
4140 /* The function sets up and return EXCL_SET which is union of
4141 exclusion sets for each unit in IN_SET. */
4142 static reserv_sets_t
4143 get_excl_set (reserv_sets_t in_set)
4151 chars_num = els_in_cycle_reserv * sizeof (set_el_t);
4152 memset (excl_set, 0, chars_num);
4153 for (excl_char_num = 0; excl_char_num < chars_num; excl_char_num++)
4154 if (((unsigned char *) in_set) [excl_char_num])
4155 for (i = CHAR_BIT - 1; i >= 0; i--)
4156 if ((((unsigned char *) in_set) [excl_char_num] >> i) & 1)
4158 start_unit_num = excl_char_num * CHAR_BIT + i;
4159 if (start_unit_num >= description->units_num)
4161 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4164 |= unit_excl_set_table [start_unit_num] [unit_num];
4172 /* The page contains abstract data for work with presence/absence
4173 pattern sets (see presence_set/absence_set in file rtl.def). */
4175 /* The following arrays contain correspondingly presence, final
4176 presence, absence, and final absence patterns for each unit. */
4177 static pattern_reserv_t *unit_presence_set_table;
4178 static pattern_reserv_t *unit_final_presence_set_table;
4179 static pattern_reserv_t *unit_absence_set_table;
4180 static pattern_reserv_t *unit_final_absence_set_table;
4182 /* The following function forms list of reservation sets for given
4184 static pattern_reserv_t
4185 form_reserv_sets_list (pattern_set_el_t pattern_list)
4187 pattern_set_el_t el;
4188 pattern_reserv_t first, curr, prev;
4191 prev = first = NULL;
4192 for (el = pattern_list; el != NULL; el = el->next_pattern_set_el)
4194 curr = create_node (sizeof (struct pattern_reserv));
4195 curr->reserv = alloc_empty_reserv_sets ();
4196 curr->next_pattern_reserv = NULL;
4197 for (i = 0; i < el->units_num; i++)
4199 SET_BIT (curr->reserv, el->unit_decls [i]->unit_num);
4200 el->unit_decls [i]->in_set_p = TRUE;
4203 prev->next_pattern_reserv = curr;
4211 /* The following function forms the array containing presence and
4212 absence pattern sets for each unit. */
4214 initiate_presence_absence_pattern_sets (void)
4219 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4220 unit_presence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4221 obstack_finish (&irp);
4222 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4223 unit_final_presence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4224 obstack_finish (&irp);
4225 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4226 unit_absence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4227 obstack_finish (&irp);
4228 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4229 unit_final_absence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4230 obstack_finish (&irp);
4231 /* Evaluate unit presence/absence sets. */
4232 for (i = 0; i < description->decls_num; i++)
4234 decl = description->decls [i];
4235 if (decl->mode == dm_unit)
4237 unit_presence_set_table [DECL_UNIT (decl)->unit_num]
4238 = form_reserv_sets_list (DECL_UNIT (decl)->presence_list);
4239 unit_final_presence_set_table [DECL_UNIT (decl)->unit_num]
4240 = form_reserv_sets_list (DECL_UNIT (decl)->final_presence_list);
4241 unit_absence_set_table [DECL_UNIT (decl)->unit_num]
4242 = form_reserv_sets_list (DECL_UNIT (decl)->absence_list);
4243 unit_final_absence_set_table [DECL_UNIT (decl)->unit_num]
4244 = form_reserv_sets_list (DECL_UNIT (decl)->final_absence_list);
4249 /* The function checks that CHECKED_SET satisfies all presence pattern
4250 sets for units in ORIGIONAL_SET. The function returns TRUE if it
4253 check_presence_pattern_sets (reserv_sets_t checked_set,
4254 reserv_sets_t origional_set,
4263 pattern_reserv_t pat_reserv;
4265 chars_num = els_in_cycle_reserv * sizeof (set_el_t);
4266 for (char_num = 0; char_num < chars_num; char_num++)
4267 if (((unsigned char *) origional_set) [char_num])
4268 for (i = CHAR_BIT - 1; i >= 0; i--)
4269 if ((((unsigned char *) origional_set) [char_num] >> i) & 1)
4271 start_unit_num = char_num * CHAR_BIT + i;
4272 if (start_unit_num >= description->units_num)
4275 && unit_final_presence_set_table [start_unit_num] == NULL)
4277 && unit_presence_set_table [start_unit_num] == NULL))
4280 for (pat_reserv = (final_p
4281 ? unit_final_presence_set_table [start_unit_num]
4282 : unit_presence_set_table [start_unit_num]);
4284 pat_reserv = pat_reserv->next_pattern_reserv)
4286 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4287 if ((checked_set [unit_num] & pat_reserv->reserv [unit_num])
4288 != pat_reserv->reserv [unit_num])
4290 presence_p = presence_p || unit_num >= els_in_cycle_reserv;
4298 /* The function checks that CHECKED_SET satisfies all absence pattern
4299 sets for units in ORIGIONAL_SET. The function returns TRUE if it
4302 check_absence_pattern_sets (reserv_sets_t checked_set,
4303 reserv_sets_t origional_set,
4311 pattern_reserv_t pat_reserv;
4313 chars_num = els_in_cycle_reserv * sizeof (set_el_t);
4314 for (char_num = 0; char_num < chars_num; char_num++)
4315 if (((unsigned char *) origional_set) [char_num])
4316 for (i = CHAR_BIT - 1; i >= 0; i--)
4317 if ((((unsigned char *) origional_set) [char_num] >> i) & 1)
4319 start_unit_num = char_num * CHAR_BIT + i;
4320 if (start_unit_num >= description->units_num)
4322 for (pat_reserv = (final_p
4323 ? unit_final_absence_set_table [start_unit_num]
4324 : unit_absence_set_table [start_unit_num]);
4326 pat_reserv = pat_reserv->next_pattern_reserv)
4328 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4329 if ((checked_set [unit_num] & pat_reserv->reserv [unit_num])
4330 != pat_reserv->reserv [unit_num]
4331 && pat_reserv->reserv [unit_num])
4333 if (unit_num >= els_in_cycle_reserv)
4342 /* This page contains code for transformation of original reservations
4343 described in .md file. The main goal of transformations is
4344 simplifying reservation and lifting up all `|' on the top of IR
4345 reservation representation. */
4348 /* The following function makes copy of IR representation of
4349 reservation. The function also substitutes all reservations
4350 defined by define_reservation by corresponding value during making
4353 copy_insn_regexp (regexp_t regexp)
4358 switch (regexp->mode)
4361 result = copy_insn_regexp (REGEXP_RESERV (regexp)->reserv_decl->regexp);
4365 result = copy_node (regexp, sizeof (struct regexp));
4369 result = copy_node (regexp, sizeof (struct regexp));
4370 REGEXP_REPEAT (result)->regexp
4371 = copy_insn_regexp (REGEXP_REPEAT (regexp)->regexp);
4375 result = copy_node (regexp,
4376 sizeof (struct regexp) + sizeof (regexp_t)
4377 * (REGEXP_SEQUENCE (regexp)->regexps_num - 1));
4378 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4379 REGEXP_SEQUENCE (result)->regexps [i]
4380 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4384 result = copy_node (regexp,
4385 sizeof (struct regexp) + sizeof (regexp_t)
4386 * (REGEXP_ALLOF (regexp)->regexps_num - 1));
4387 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4388 REGEXP_ALLOF (result)->regexps [i]
4389 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4393 result = copy_node (regexp,
4394 sizeof (struct regexp) + sizeof (regexp_t)
4395 * (REGEXP_ONEOF (regexp)->regexps_num - 1));
4396 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4397 REGEXP_ONEOF (result)->regexps [i]
4398 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4402 result = copy_node (regexp, sizeof (struct regexp));
4411 /* The following variable is set up 1 if a transformation has been
4413 static int regexp_transformed_p;
4415 /* The function makes transformation
4418 transform_1 (regexp_t regexp)
4425 if (regexp->mode == rm_repeat)
4427 repeat_num = REGEXP_REPEAT (regexp)->repeat_num;
4428 gcc_assert (repeat_num > 1);
4429 operand = REGEXP_REPEAT (regexp)->regexp;
4431 regexp = create_node (sizeof (struct regexp) + sizeof (regexp_t)
4432 * (repeat_num - 1));
4433 regexp->mode = rm_sequence;
4435 REGEXP_SEQUENCE (regexp)->regexps_num = repeat_num;
4436 for (i = 0; i < repeat_num; i++)
4437 REGEXP_SEQUENCE (regexp)->regexps [i] = copy_insn_regexp (operand);
4438 regexp_transformed_p = 1;
4443 /* The function makes transformations
4444 ...,(A,B,...),C,... -> ...,A,B,...,C,...
4445 ...+(A+B+...)+C+... -> ...+A+B+...+C+...
4446 ...|(A|B|...)|C|... -> ...|A|B|...|C|... */
4448 transform_2 (regexp_t regexp)
4450 if (regexp->mode == rm_sequence)
4452 regexp_t sequence = NULL;
4454 int sequence_index = 0;
4457 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4458 if (REGEXP_SEQUENCE (regexp)->regexps [i]->mode == rm_sequence)
4461 sequence = REGEXP_SEQUENCE (regexp)->regexps [i];
4464 if (i < REGEXP_SEQUENCE (regexp)->regexps_num)
4466 gcc_assert (REGEXP_SEQUENCE (sequence)->regexps_num > 1
4467 && REGEXP_SEQUENCE (regexp)->regexps_num > 1);
4468 result = create_node (sizeof (struct regexp)
4470 * (REGEXP_SEQUENCE (regexp)->regexps_num
4471 + REGEXP_SEQUENCE (sequence)->regexps_num
4473 result->mode = rm_sequence;
4474 result->pos = regexp->pos;
4475 REGEXP_SEQUENCE (result)->regexps_num
4476 = (REGEXP_SEQUENCE (regexp)->regexps_num
4477 + REGEXP_SEQUENCE (sequence)->regexps_num - 1);
4478 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4479 if (i < sequence_index)
4480 REGEXP_SEQUENCE (result)->regexps [i]
4481 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4482 else if (i > sequence_index)
4483 REGEXP_SEQUENCE (result)->regexps
4484 [i + REGEXP_SEQUENCE (sequence)->regexps_num - 1]
4485 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4487 for (j = 0; j < REGEXP_SEQUENCE (sequence)->regexps_num; j++)
4488 REGEXP_SEQUENCE (result)->regexps [i + j]
4489 = copy_insn_regexp (REGEXP_SEQUENCE (sequence)->regexps [j]);
4490 regexp_transformed_p = 1;
4494 else if (regexp->mode == rm_allof)
4496 regexp_t allof = NULL;
4498 int allof_index = 0;
4501 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4502 if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_allof)
4505 allof = REGEXP_ALLOF (regexp)->regexps [i];
4508 if (i < REGEXP_ALLOF (regexp)->regexps_num)
4510 gcc_assert (REGEXP_ALLOF (allof)->regexps_num > 1
4511 && REGEXP_ALLOF (regexp)->regexps_num > 1);
4512 result = create_node (sizeof (struct regexp)
4514 * (REGEXP_ALLOF (regexp)->regexps_num
4515 + REGEXP_ALLOF (allof)->regexps_num - 2));
4516 result->mode = rm_allof;
4517 result->pos = regexp->pos;
4518 REGEXP_ALLOF (result)->regexps_num
4519 = (REGEXP_ALLOF (regexp)->regexps_num
4520 + REGEXP_ALLOF (allof)->regexps_num - 1);
4521 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4522 if (i < allof_index)
4523 REGEXP_ALLOF (result)->regexps [i]
4524 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4525 else if (i > allof_index)
4526 REGEXP_ALLOF (result)->regexps
4527 [i + REGEXP_ALLOF (allof)->regexps_num - 1]
4528 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4530 for (j = 0; j < REGEXP_ALLOF (allof)->regexps_num; j++)
4531 REGEXP_ALLOF (result)->regexps [i + j]
4532 = copy_insn_regexp (REGEXP_ALLOF (allof)->regexps [j]);
4533 regexp_transformed_p = 1;
4537 else if (regexp->mode == rm_oneof)
4539 regexp_t oneof = NULL;
4541 int oneof_index = 0;
4544 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4545 if (REGEXP_ONEOF (regexp)->regexps [i]->mode == rm_oneof)
4548 oneof = REGEXP_ONEOF (regexp)->regexps [i];
4551 if (i < REGEXP_ONEOF (regexp)->regexps_num)
4553 gcc_assert (REGEXP_ONEOF (oneof)->regexps_num > 1
4554 && REGEXP_ONEOF (regexp)->regexps_num > 1);
4555 result = create_node (sizeof (struct regexp)
4557 * (REGEXP_ONEOF (regexp)->regexps_num
4558 + REGEXP_ONEOF (oneof)->regexps_num - 2));
4559 result->mode = rm_oneof;
4560 result->pos = regexp->pos;
4561 REGEXP_ONEOF (result)->regexps_num
4562 = (REGEXP_ONEOF (regexp)->regexps_num
4563 + REGEXP_ONEOF (oneof)->regexps_num - 1);
4564 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4565 if (i < oneof_index)
4566 REGEXP_ONEOF (result)->regexps [i]
4567 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4568 else if (i > oneof_index)
4569 REGEXP_ONEOF (result)->regexps
4570 [i + REGEXP_ONEOF (oneof)->regexps_num - 1]
4571 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4573 for (j = 0; j < REGEXP_ONEOF (oneof)->regexps_num; j++)
4574 REGEXP_ONEOF (result)->regexps [i + j]
4575 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [j]);
4576 regexp_transformed_p = 1;
4583 /* The function makes transformations
4584 ...,A|B|...,C,... -> (...,A,C,...)|(...,B,C,...)|...
4585 ...+(A|B|...)+C+... -> (...+A+C+...)|(...+B+C+...)|...
4586 ...+(A,B,...)+C+... -> (...+A+C+...),B,...
4587 ...+(A,B,...)+(C,D,...) -> (A+C),(B+D),... */
4589 transform_3 (regexp_t regexp)
4591 if (regexp->mode == rm_sequence)
4593 regexp_t oneof = NULL;
4594 int oneof_index = 0;
4599 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4600 if (REGEXP_SEQUENCE (regexp)->regexps [i]->mode == rm_oneof)
4603 oneof = REGEXP_SEQUENCE (regexp)->regexps [i];
4606 if (i < REGEXP_SEQUENCE (regexp)->regexps_num)
4608 gcc_assert (REGEXP_ONEOF (oneof)->regexps_num > 1
4609 && REGEXP_SEQUENCE (regexp)->regexps_num > 1);
4610 result = create_node (sizeof (struct regexp)
4612 * (REGEXP_ONEOF (oneof)->regexps_num - 1));
4613 result->mode = rm_oneof;
4614 result->pos = regexp->pos;
4615 REGEXP_ONEOF (result)->regexps_num
4616 = REGEXP_ONEOF (oneof)->regexps_num;
4617 for (i = 0; i < REGEXP_ONEOF (result)->regexps_num; i++)
4620 = create_node (sizeof (struct regexp)
4622 * (REGEXP_SEQUENCE (regexp)->regexps_num - 1));
4623 sequence->mode = rm_sequence;
4624 sequence->pos = regexp->pos;
4625 REGEXP_SEQUENCE (sequence)->regexps_num
4626 = REGEXP_SEQUENCE (regexp)->regexps_num;
4627 REGEXP_ONEOF (result)->regexps [i] = sequence;
4628 for (j = 0; j < REGEXP_SEQUENCE (sequence)->regexps_num; j++)
4629 if (j != oneof_index)
4630 REGEXP_SEQUENCE (sequence)->regexps [j]
4631 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [j]);
4633 REGEXP_SEQUENCE (sequence)->regexps [j]
4634 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [i]);
4636 regexp_transformed_p = 1;
4640 else if (regexp->mode == rm_allof)
4642 regexp_t oneof = NULL;
4644 int oneof_index = 0;
4645 int max_seq_length, allof_length;
4647 regexp_t allof = NULL;
4648 regexp_t allof_op = NULL;
4651 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4652 if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_oneof)
4655 oneof = REGEXP_ALLOF (regexp)->regexps [i];
4658 if (i < REGEXP_ALLOF (regexp)->regexps_num)
4660 gcc_assert (REGEXP_ONEOF (oneof)->regexps_num > 1
4661 && REGEXP_ALLOF (regexp)->regexps_num > 1);
4662 result = create_node (sizeof (struct regexp)
4664 * (REGEXP_ONEOF (oneof)->regexps_num - 1));
4665 result->mode = rm_oneof;
4666 result->pos = regexp->pos;
4667 REGEXP_ONEOF (result)->regexps_num
4668 = REGEXP_ONEOF (oneof)->regexps_num;
4669 for (i = 0; i < REGEXP_ONEOF (result)->regexps_num; i++)
4672 = create_node (sizeof (struct regexp)
4674 * (REGEXP_ALLOF (regexp)->regexps_num - 1));
4675 allof->mode = rm_allof;
4676 allof->pos = regexp->pos;
4677 REGEXP_ALLOF (allof)->regexps_num
4678 = REGEXP_ALLOF (regexp)->regexps_num;
4679 REGEXP_ONEOF (result)->regexps [i] = allof;
4680 for (j = 0; j < REGEXP_ALLOF (allof)->regexps_num; j++)
4681 if (j != oneof_index)
4682 REGEXP_ALLOF (allof)->regexps [j]
4683 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [j]);
4685 REGEXP_ALLOF (allof)->regexps [j]
4686 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [i]);
4688 regexp_transformed_p = 1;
4692 if (regexp->mode == rm_allof)
4693 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4695 switch (REGEXP_ALLOF (regexp)->regexps [i]->mode)
4698 seq = REGEXP_ALLOF (regexp)->regexps [i];
4699 if (max_seq_length < REGEXP_SEQUENCE (seq)->regexps_num)
4700 max_seq_length = REGEXP_SEQUENCE (seq)->regexps_num;
4713 if (max_seq_length != 0)
4715 gcc_assert (max_seq_length != 1
4716 && REGEXP_ALLOF (regexp)->regexps_num > 1);
4717 result = create_node (sizeof (struct regexp)
4718 + sizeof (regexp_t) * (max_seq_length - 1));
4719 result->mode = rm_sequence;
4720 result->pos = regexp->pos;
4721 REGEXP_SEQUENCE (result)->regexps_num = max_seq_length;
4722 for (i = 0; i < max_seq_length; i++)
4725 for (j = 0; j < REGEXP_ALLOF (regexp)->regexps_num; j++)
4726 switch (REGEXP_ALLOF (regexp)->regexps [j]->mode)
4729 if (i < (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4730 ->regexps [j])->regexps_num))
4733 = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4743 allof_op = REGEXP_ALLOF (regexp)->regexps [j];
4751 if (allof_length == 1)
4752 REGEXP_SEQUENCE (result)->regexps [i] = allof_op;
4755 allof = create_node (sizeof (struct regexp)
4757 * (allof_length - 1));
4758 allof->mode = rm_allof;
4759 allof->pos = regexp->pos;
4760 REGEXP_ALLOF (allof)->regexps_num = allof_length;
4761 REGEXP_SEQUENCE (result)->regexps [i] = allof;
4763 for (j = 0; j < REGEXP_ALLOF (regexp)->regexps_num; j++)
4764 if (REGEXP_ALLOF (regexp)->regexps [j]->mode == rm_sequence
4766 (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4767 ->regexps [j])->regexps_num)))
4769 allof_op = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4772 REGEXP_ALLOF (allof)->regexps [allof_length]
4777 && (REGEXP_ALLOF (regexp)->regexps [j]->mode
4779 || (REGEXP_ALLOF (regexp)->regexps [j]->mode
4782 allof_op = REGEXP_ALLOF (regexp)->regexps [j];
4783 REGEXP_ALLOF (allof)->regexps [allof_length]
4789 regexp_transformed_p = 1;
4796 /* The function traverses IR of reservation and applies transformations
4797 implemented by FUNC. */
4799 regexp_transform_func (regexp_t regexp, regexp_t (*func) (regexp_t regexp))
4803 switch (regexp->mode)
4806 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4807 REGEXP_SEQUENCE (regexp)->regexps [i]
4808 = regexp_transform_func (REGEXP_SEQUENCE (regexp)->regexps [i],
4813 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4814 REGEXP_ALLOF (regexp)->regexps [i]
4815 = regexp_transform_func (REGEXP_ALLOF (regexp)->regexps [i], func);
4819 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4820 REGEXP_ONEOF (regexp)->regexps [i]
4821 = regexp_transform_func (REGEXP_ONEOF (regexp)->regexps [i], func);
4825 REGEXP_REPEAT (regexp)->regexp
4826 = regexp_transform_func (REGEXP_REPEAT (regexp)->regexp, func);
4836 return (*func) (regexp);
4839 /* The function applies all transformations for IR representation of
4840 reservation REGEXP. */
4842 transform_regexp (regexp_t regexp)
4844 regexp = regexp_transform_func (regexp, transform_1);
4847 regexp_transformed_p = 0;
4848 regexp = regexp_transform_func (regexp, transform_2);
4849 regexp = regexp_transform_func (regexp, transform_3);
4851 while (regexp_transformed_p);
4855 /* The function applies all transformations for reservations of all
4856 insn declarations. */
4858 transform_insn_regexps (void)
4863 transform_time = create_ticker ();
4864 add_advance_cycle_insn_decl ();
4866 fprintf (stderr, "Reservation transformation...");
4867 for (i = 0; i < description->decls_num; i++)
4869 decl = description->decls [i];
4870 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
4871 DECL_INSN_RESERV (decl)->transformed_regexp
4872 = transform_regexp (copy_insn_regexp
4873 (DECL_INSN_RESERV (decl)->regexp));
4876 fprintf (stderr, "done\n");
4877 ticker_off (&transform_time);
4882 /* The following variable value is TRUE if the first annotated message
4883 about units to automata distribution has been output. */
4884 static int annotation_message_reported_p;
4886 /* The following structure describes usage of a unit in a reservation. */
4889 unit_decl_t unit_decl;
4890 /* The following forms a list of units used on the same cycle in the
4891 same alternative. */
4892 struct unit_usage *next;
4894 typedef struct unit_usage *unit_usage_t;
4896 DEF_VEC_P(unit_usage_t);
4897 DEF_VEC_ALLOC_P(unit_usage_t,heap);
4899 /* Obstack for unit_usage structures. */
4900 static struct obstack unit_usages;
4902 /* VLA for representation of array of pointers to unit usage
4903 structures. There is an element for each combination of
4904 (alternative number, cycle). Unit usages on given cycle in
4905 alternative with given number are referred through element with
4906 index equals to the cycle * number of all alternatives in the regexp
4907 + the alternative number. */
4908 static VEC(unit_usage_t,heap) *cycle_alt_unit_usages;
4910 /* The following function creates the structure unit_usage for UNIT on
4911 CYCLE in REGEXP alternative with ALT_NUM. The structure is made
4912 accessed through cycle_alt_unit_usages. */
4914 store_alt_unit_usage (regexp_t regexp, regexp_t unit, int cycle,
4918 unit_decl_t unit_decl;
4919 unit_usage_t unit_usage_ptr;
4922 gcc_assert (regexp && regexp->mode == rm_oneof
4923 && alt_num < REGEXP_ONEOF (regexp)->regexps_num);
4924 unit_decl = REGEXP_UNIT (unit)->unit_decl;
4926 length = (cycle + 1) * REGEXP_ONEOF (regexp)->regexps_num;
4927 while (VEC_length (unit_usage_t, cycle_alt_unit_usages) < length)
4928 VEC_safe_push (unit_usage_t,heap, cycle_alt_unit_usages, 0);
4930 obstack_blank (&unit_usages, sizeof (struct unit_usage));
4931 unit_usage_ptr = (struct unit_usage *) obstack_base (&unit_usages);
4932 obstack_finish (&unit_usages);
4933 unit_usage_ptr->unit_decl = unit_decl;
4934 index = cycle * REGEXP_ONEOF (regexp)->regexps_num + alt_num;
4935 unit_usage_ptr->next = VEC_index (unit_usage_t, cycle_alt_unit_usages, index);
4936 VEC_replace (unit_usage_t, cycle_alt_unit_usages, index, unit_usage_ptr);
4937 unit_decl->last_distribution_check_cycle = -1; /* undefined */
4940 /* The function processes given REGEXP to find units with the wrong
4943 check_regexp_units_distribution (const char *insn_reserv_name,
4947 regexp_t seq, allof, unit;
4948 struct unit_usage *unit_usage_ptr, *other_unit_usage_ptr;
4950 if (regexp == NULL || regexp->mode != rm_oneof)
4952 /* Store all unit usages in the regexp: */
4953 obstack_init (&unit_usages);
4954 cycle_alt_unit_usages = 0;
4956 for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
4958 seq = REGEXP_ONEOF (regexp)->regexps [i];
4962 for (j = 0; j < REGEXP_SEQUENCE (seq)->regexps_num; j++)
4964 allof = REGEXP_SEQUENCE (seq)->regexps [j];
4965 switch (allof->mode)
4968 for (k = 0; k < REGEXP_ALLOF (allof)->regexps_num; k++)
4970 unit = REGEXP_ALLOF (allof)->regexps [k];
4971 if (unit->mode == rm_unit)
4972 store_alt_unit_usage (regexp, unit, j, i);
4974 gcc_assert (unit->mode == rm_nothing);
4979 store_alt_unit_usage (regexp, allof, j, i);
4992 for (k = 0; k < REGEXP_ALLOF (seq)->regexps_num; k++)
4994 unit = REGEXP_ALLOF (seq)->regexps [k];
4998 store_alt_unit_usage (regexp, unit, 0, i);
5011 store_alt_unit_usage (regexp, seq, 0, i);
5021 /* Check distribution: */
5022 for (i = 0; i < (int) VEC_length (unit_usage_t, cycle_alt_unit_usages); i++)
5024 cycle = i / REGEXP_ONEOF (regexp)->regexps_num;
5025 for (unit_usage_ptr = VEC_index (unit_usage_t, cycle_alt_unit_usages, i);
5026 unit_usage_ptr != NULL;
5027 unit_usage_ptr = unit_usage_ptr->next)
5028 if (cycle != unit_usage_ptr->unit_decl->last_distribution_check_cycle)
5030 unit_usage_ptr->unit_decl->last_distribution_check_cycle = cycle;
5031 for (k = cycle * REGEXP_ONEOF (regexp)->regexps_num;
5032 k < (int) VEC_length (unit_usage_t, cycle_alt_unit_usages)
5033 && k == cycle * REGEXP_ONEOF (regexp)->regexps_num;
5036 for (other_unit_usage_ptr
5037 = VEC_index (unit_usage_t, cycle_alt_unit_usages, k);
5038 other_unit_usage_ptr != NULL;
5039 other_unit_usage_ptr = other_unit_usage_ptr->next)
5040 if (unit_usage_ptr->unit_decl->automaton_decl
5041 == other_unit_usage_ptr->unit_decl->automaton_decl)
5043 if (other_unit_usage_ptr == NULL
5044 && (VEC_index (unit_usage_t, cycle_alt_unit_usages, k)
5048 if (k < (int) VEC_length (unit_usage_t, cycle_alt_unit_usages)
5049 && k == cycle * REGEXP_ONEOF (regexp)->regexps_num)
5051 if (!annotation_message_reported_p)
5053 fprintf (stderr, "\n");
5054 error ("The following units do not satisfy units-automata distribution rule");
5055 error (" (A unit of given unit automaton should be on each reserv. altern.)");
5056 annotation_message_reported_p = TRUE;
5058 error ("Unit %s, reserv. %s, cycle %d",
5059 unit_usage_ptr->unit_decl->name, insn_reserv_name,
5064 VEC_free (unit_usage_t,heap, cycle_alt_unit_usages);
5065 obstack_free (&unit_usages, NULL);
5068 /* The function finds units which violates units to automata
5069 distribution rule. If the units exist, report about them. */
5071 check_unit_distributions_to_automata (void)
5077 fprintf (stderr, "Check unit distributions to automata...");
5078 annotation_message_reported_p = FALSE;
5079 for (i = 0; i < description->decls_num; i++)
5081 decl = description->decls [i];
5082 if (decl->mode == dm_insn_reserv)
5083 check_regexp_units_distribution
5084 (DECL_INSN_RESERV (decl)->name,
5085 DECL_INSN_RESERV (decl)->transformed_regexp);
5088 fprintf (stderr, "done\n");
5093 /* The page contains code for building alt_states (see comments for
5094 IR) describing all possible insns reservations of an automaton. */
5096 /* Current state being formed for which the current alt_state
5098 static state_t state_being_formed;
5100 /* Current alt_state being formed. */
5101 static alt_state_t alt_state_being_formed;
5103 /* This recursive function processes `,' and units in reservation
5104 REGEXP for forming alt_states of AUTOMATON. It is believed that
5105 CURR_CYCLE is start cycle of all reservation REGEXP. */
5107 process_seq_for_forming_states (regexp_t regexp, automaton_t automaton,
5115 switch (regexp->mode)
5118 if (REGEXP_UNIT (regexp)->unit_decl->corresponding_automaton_num
5119 == automaton->automaton_order_num)
5120 set_state_reserv (state_being_formed, curr_cycle,
5121 REGEXP_UNIT (regexp)->unit_decl->unit_num);
5125 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
5127 = process_seq_for_forming_states
5128 (REGEXP_SEQUENCE (regexp)->regexps [i], automaton, curr_cycle) + 1;
5133 int finish_cycle = 0;
5136 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
5138 cycle = process_seq_for_forming_states (REGEXP_ALLOF (regexp)
5140 automaton, curr_cycle);
5141 if (finish_cycle < cycle)
5142 finish_cycle = cycle;
5144 return finish_cycle;
5155 /* This recursive function finishes forming ALT_STATE of AUTOMATON and
5156 inserts alt_state into the table. */
5158 finish_forming_alt_state (alt_state_t alt_state,
5159 automaton_t automaton ATTRIBUTE_UNUSED)
5161 state_t state_in_table;
5162 state_t corresponding_state;
5164 corresponding_state = alt_state->state;
5165 state_in_table = insert_state (corresponding_state);
5166 if (state_in_table != corresponding_state)
5168 free_state (corresponding_state);
5169 alt_state->state = state_in_table;
5173 /* The following variable value is current automaton insn for whose
5174 reservation the alt states are created. */
5175 static ainsn_t curr_ainsn;
5177 /* This recursive function processes `|' in reservation REGEXP for
5178 forming alt_states of AUTOMATON. List of the alt states should
5179 have the same order as in the description. */
5181 process_alts_for_forming_states (regexp_t regexp, automaton_t automaton,
5186 if (regexp->mode != rm_oneof)
5188 alt_state_being_formed = get_free_alt_state ();
5189 state_being_formed = get_free_state (1, automaton);
5190 alt_state_being_formed->state = state_being_formed;
5191 /* We inserts in reverse order but we process alternatives also
5192 in reverse order. So we have the same order of alternative
5193 as in the description. */
5194 alt_state_being_formed->next_alt_state = curr_ainsn->alt_states;
5195 curr_ainsn->alt_states = alt_state_being_formed;
5196 (void) process_seq_for_forming_states (regexp, automaton, 0);
5197 finish_forming_alt_state (alt_state_being_formed, automaton);
5201 gcc_assert (!inside_oneof_p);
5202 /* We processes it in reverse order to get list with the same
5203 order as in the description. See also the previous
5205 for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
5206 process_alts_for_forming_states (REGEXP_ONEOF (regexp)->regexps [i],
5211 /* Create nodes alt_state for all AUTOMATON insns. */
5213 create_alt_states (automaton_t automaton)
5215 struct insn_reserv_decl *reserv_decl;
5217 for (curr_ainsn = automaton->ainsn_list;
5219 curr_ainsn = curr_ainsn->next_ainsn)
5221 reserv_decl = curr_ainsn->insn_reserv_decl;
5222 if (reserv_decl != DECL_INSN_RESERV (advance_cycle_insn_decl))
5224 curr_ainsn->alt_states = NULL;
5225 process_alts_for_forming_states (reserv_decl->transformed_regexp,
5227 curr_ainsn->sorted_alt_states
5228 = uniq_sort_alt_states (curr_ainsn->alt_states);
5235 /* The page contains major code for building DFA(s) for fast pipeline
5236 hazards recognition. */
5238 /* The function forms list of ainsns of AUTOMATON with the same
5242 form_ainsn_with_same_reservs (automaton_t automaton)
5246 VEC(ainsn_t,heap) *last_insns = VEC_alloc (ainsn_t,heap, 150);
5248 for (curr_ainsn = automaton->ainsn_list;
5250 curr_ainsn = curr_ainsn->next_ainsn)
5251 if (curr_ainsn->insn_reserv_decl
5252 == DECL_INSN_RESERV (advance_cycle_insn_decl))
5254 curr_ainsn->next_same_reservs_insn = NULL;
5255 curr_ainsn->first_insn_with_same_reservs = 1;
5259 for (i = 0; i < VEC_length (ainsn_t, last_insns); i++)
5261 (curr_ainsn->sorted_alt_states,
5262 VEC_index (ainsn_t, last_insns, i)->sorted_alt_states))
5264 curr_ainsn->next_same_reservs_insn = NULL;
5265 if (i < VEC_length (ainsn_t, last_insns))
5267 curr_ainsn->first_insn_with_same_reservs = 0;
5268 VEC_index (ainsn_t, last_insns, i)->next_same_reservs_insn
5270 VEC_replace (ainsn_t, last_insns, i, curr_ainsn);
5274 VEC_safe_push (ainsn_t, heap, last_insns, curr_ainsn);
5275 curr_ainsn->first_insn_with_same_reservs = 1;
5278 VEC_free (ainsn_t,heap, last_insns);
5281 /* Forming unit reservations which can affect creating the automaton
5282 states achieved from a given state. It permits to build smaller
5283 automata in many cases. We would have the same automata after
5284 the minimization without such optimization, but the automaton
5285 right after the building could be huge. So in other words, usage
5286 of reservs_matter means some minimization during building the
5288 static reserv_sets_t
5289 form_reservs_matter (automaton_t automaton)
5292 reserv_sets_t reservs_matter = alloc_empty_reserv_sets();
5294 for (cycle = 0; cycle < max_cycles_num; cycle++)
5295 for (unit = 0; unit < description->units_num; unit++)
5296 if (units_array [unit]->automaton_decl
5297 == automaton->corresponding_automaton_decl
5298 && (cycle >= units_array [unit]->min_occ_cycle_num
5299 /* We can not remove queried unit from reservations. */
5300 || units_array [unit]->query_p
5301 /* We can not remove units which are used
5302 `exclusion_set', `presence_set',
5303 `final_presence_set', `absence_set', and
5304 `final_absence_set'. */
5305 || units_array [unit]->in_set_p))
5306 set_unit_reserv (reservs_matter, cycle, unit);
5307 return reservs_matter;
5310 /* The following function creates all states of nondeterministic AUTOMATON. */
5312 make_automaton (automaton_t automaton)
5315 struct insn_reserv_decl *insn_reserv_decl;
5316 alt_state_t alt_state;
5318 state_t start_state;
5320 ainsn_t advance_cycle_ainsn;
5322 VEC(state_t,heap) *state_stack = VEC_alloc(state_t,heap, 150);
5324 reserv_sets_t reservs_matter = form_reservs_matter (automaton);
5326 /* Create the start state (empty state). */
5327 start_state = insert_state (get_free_state (1, automaton));
5328 automaton->start_state = start_state;
5329 start_state->it_was_placed_in_stack_for_NDFA_forming = 1;
5330 VEC_safe_push (state_t,heap, state_stack, start_state);
5332 while (VEC_length (state_t, state_stack) != 0)
5334 state = VEC_pop (state_t, state_stack);
5335 advance_cycle_ainsn = NULL;
5336 for (ainsn = automaton->ainsn_list;
5338 ainsn = ainsn->next_ainsn)
5339 if (ainsn->first_insn_with_same_reservs)
5341 insn_reserv_decl = ainsn->insn_reserv_decl;
5342 if (insn_reserv_decl != DECL_INSN_RESERV (advance_cycle_insn_decl))
5344 /* We process alt_states in the same order as they are
5345 present in the description. */
5347 for (alt_state = ainsn->alt_states;
5349 alt_state = alt_state->next_alt_state)
5351 state2 = alt_state->state;
5352 if (!intersected_state_reservs_p (state, state2))
5354 state2 = states_union (state, state2, reservs_matter);
5355 if (!state2->it_was_placed_in_stack_for_NDFA_forming)
5357 state2->it_was_placed_in_stack_for_NDFA_forming
5359 VEC_safe_push (state_t,heap, state_stack, state2);
5361 if (progress_flag && states_n % 100 == 0)
5362 fprintf (stderr, ".");
5364 added_arc = add_arc (state, state2, ainsn);
5369 if (!ndfa_flag && added_arc != NULL)
5371 for (alt_state = ainsn->alt_states;
5373 alt_state = alt_state->next_alt_state)
5374 state2 = alt_state->state;
5378 advance_cycle_ainsn = ainsn;
5380 /* Add transition to advance cycle. */
5381 state2 = state_shift (state, reservs_matter);
5382 if (!state2->it_was_placed_in_stack_for_NDFA_forming)
5384 state2->it_was_placed_in_stack_for_NDFA_forming = 1;
5385 VEC_safe_push (state_t,heap, state_stack, state2);
5387 if (progress_flag && states_n % 100 == 0)
5388 fprintf (stderr, ".");
5390 gcc_assert (advance_cycle_ainsn);
5391 add_arc (state, state2, advance_cycle_ainsn);
5393 VEC_free (state_t,heap, state_stack);
5396 /* Foms lists of all arcs of STATE marked by the same ainsn. */
5398 form_arcs_marked_by_insn (state_t state)
5404 for (i = 0; i < description->decls_num; i++)
5406 decl = description->decls [i];
5407 if (decl->mode == dm_insn_reserv)
5408 DECL_INSN_RESERV (decl)->arcs_marked_by_insn = NULL;
5410 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5412 gcc_assert (arc->insn);
5413 arc->next_arc_marked_by_insn
5414 = arc->insn->insn_reserv_decl->arcs_marked_by_insn;
5415 arc->insn->insn_reserv_decl->arcs_marked_by_insn = arc;
5419 /* The function creates composed state (see comments for IR) from
5420 ORIGINAL_STATE and list of arcs ARCS_MARKED_BY_INSN marked by the
5421 same insn. If the composed state is not in STATE_STACK yet, it is
5422 pushed into STATE_STACK. */
5425 create_composed_state (state_t original_state, arc_t arcs_marked_by_insn,
5426 VEC(state_t,heap) **state_stack)
5429 alt_state_t alt_state, curr_alt_state;
5430 alt_state_t new_alt_state;
5433 state_t state_in_table;
5435 alt_state_t canonical_alt_states_list;
5437 int new_state_p = 0;
5439 if (arcs_marked_by_insn == NULL)
5441 if (arcs_marked_by_insn->next_arc_marked_by_insn == NULL)
5442 state = arcs_marked_by_insn->to_state;
5445 gcc_assert (ndfa_flag);
5446 /* Create composed state. */
5447 state = get_free_state (0, arcs_marked_by_insn->to_state->automaton);
5448 curr_alt_state = NULL;
5449 for (curr_arc = arcs_marked_by_insn;
5451 curr_arc = curr_arc->next_arc_marked_by_insn)
5452 if (curr_arc->to_state->component_states == NULL)
5454 new_alt_state = get_free_alt_state ();
5455 new_alt_state->next_alt_state = curr_alt_state;
5456 new_alt_state->state = curr_arc->to_state;
5457 curr_alt_state = new_alt_state;
5460 for (alt_state = curr_arc->to_state->component_states;
5462 alt_state = alt_state->next_sorted_alt_state)
5464 new_alt_state = get_free_alt_state ();
5465 new_alt_state->next_alt_state = curr_alt_state;
5466 new_alt_state->state = alt_state->state;
5467 gcc_assert (!alt_state->state->component_states);
5468 curr_alt_state = new_alt_state;
5470 /* There are not identical sets in the alt state list. */
5471 canonical_alt_states_list = uniq_sort_alt_states (curr_alt_state);
5472 if (canonical_alt_states_list->next_sorted_alt_state == NULL)
5475 state = canonical_alt_states_list->state;
5476 free_state (temp_state);
5480 state->component_states = canonical_alt_states_list;
5481 state_in_table = insert_state (state);
5482 if (state_in_table != state)
5485 (state_in_table->it_was_placed_in_stack_for_DFA_forming);
5487 state = state_in_table;
5491 gcc_assert (!state->it_was_placed_in_stack_for_DFA_forming);
5493 for (curr_alt_state = state->component_states;
5494 curr_alt_state != NULL;
5495 curr_alt_state = curr_alt_state->next_sorted_alt_state)
5496 for (curr_arc = first_out_arc (curr_alt_state->state);
5498 curr_arc = next_out_arc (curr_arc))
5499 add_arc (state, curr_arc->to_state, curr_arc->insn);
5501 arcs_marked_by_insn->to_state = state;
5502 for (alts_number = 0,
5503 curr_arc = arcs_marked_by_insn->next_arc_marked_by_insn;
5505 curr_arc = next_arc)
5507 next_arc = curr_arc->next_arc_marked_by_insn;
5508 remove_arc (original_state, curr_arc);
5513 if (!state->it_was_placed_in_stack_for_DFA_forming)
5515 state->it_was_placed_in_stack_for_DFA_forming = 1;
5516 VEC_safe_push (state_t,heap, *state_stack, state);
5521 /* The function transforms nondeterministic AUTOMATON into
5525 NDFA_to_DFA (automaton_t automaton)
5527 state_t start_state;
5530 VEC(state_t,heap) *state_stack;
5534 state_stack = VEC_alloc (state_t,heap, 0);
5536 /* Create the start state (empty state). */
5537 start_state = automaton->start_state;
5538 start_state->it_was_placed_in_stack_for_DFA_forming = 1;
5539 VEC_safe_push (state_t,heap, state_stack, start_state);
5541 while (VEC_length (state_t, state_stack) != 0)
5543 state = VEC_pop (state_t, state_stack);
5544 form_arcs_marked_by_insn (state);
5545 for (i = 0; i < description->decls_num; i++)
5547 decl = description->decls [i];
5548 if (decl->mode == dm_insn_reserv
5549 && create_composed_state
5550 (state, DECL_INSN_RESERV (decl)->arcs_marked_by_insn,
5554 if (progress_flag && states_n % 100 == 0)
5555 fprintf (stderr, ".");
5559 VEC_free (state_t,heap, state_stack);
5562 /* The following variable value is current number (1, 2, ...) of passing
5564 static int curr_state_graph_pass_num;
5566 /* This recursive function passes all states achieved from START_STATE
5567 and applies APPLIED_FUNC to them. */
5569 pass_state_graph (state_t start_state, void (*applied_func) (state_t state))
5573 if (start_state->pass_num == curr_state_graph_pass_num)
5575 start_state->pass_num = curr_state_graph_pass_num;
5576 (*applied_func) (start_state);
5577 for (arc = first_out_arc (start_state);
5579 arc = next_out_arc (arc))
5580 pass_state_graph (arc->to_state, applied_func);
5583 /* This recursive function passes all states of AUTOMATON and applies
5584 APPLIED_FUNC to them. */
5586 pass_states (automaton_t automaton, void (*applied_func) (state_t state))
5588 curr_state_graph_pass_num++;
5589 pass_state_graph (automaton->start_state, applied_func);
5592 /* The function initializes code for passing of all states. */
5594 initiate_pass_states (void)
5596 curr_state_graph_pass_num = 0;
5599 /* The following vla is used for storing pointers to all achieved
5601 static VEC(state_t,heap) *all_achieved_states;
5603 /* This function is called by function pass_states to add an achieved
5606 add_achieved_state (state_t state)
5608 VEC_safe_push (state_t,heap, all_achieved_states, state);
5611 /* The function sets up equivalence numbers of insns which mark all
5612 out arcs of STATE by equiv_class_num_1 (if ODD_ITERATION_FLAG has
5613 nonzero value) or by equiv_class_num_2 of the destination state.
5614 The function returns number of out arcs of STATE. */
5616 set_out_arc_insns_equiv_num (state_t state, int odd_iteration_flag)
5620 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5622 gcc_assert (!arc->insn->insn_reserv_decl->equiv_class_num);
5623 arc->insn->insn_reserv_decl->equiv_class_num
5624 = (odd_iteration_flag
5625 ? arc->to_state->equiv_class_num_1
5626 : arc->to_state->equiv_class_num_2);
5627 gcc_assert (arc->insn->insn_reserv_decl->equiv_class_num);
5631 /* The function clears equivalence numbers and alt_states in all insns
5632 which mark all out arcs of STATE. */
5634 clear_arc_insns_equiv_num (state_t state)
5638 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5639 arc->insn->insn_reserv_decl->equiv_class_num = 0;
5643 /* The following function returns TRUE if STATE reserves the unit with
5644 UNIT_NUM on the first cycle. */
5646 first_cycle_unit_presence (state_t state, int unit_num)
5648 alt_state_t alt_state;
5650 if (state->component_states == NULL)
5651 return test_unit_reserv (state->reservs, 0, unit_num);
5654 for (alt_state = state->component_states;
5656 alt_state = alt_state->next_sorted_alt_state)
5657 if (test_unit_reserv (alt_state->state->reservs, 0, unit_num))
5663 /* This fills in the presence_signature[] member of STATE. */
5665 cache_presence (state_t state)
5669 sz = (description->query_units_num + sizeof (int) * CHAR_BIT - 1)
5670 / (sizeof (int) * CHAR_BIT);
5672 state->presence_signature = create_node (sz * sizeof (int));
5673 for (i = 0; i < description->units_num; i++)
5674 if (units_array [i]->query_p)
5676 int presence1_p = first_cycle_unit_presence (state, i);
5677 state->presence_signature[num / (sizeof (int) * CHAR_BIT)]
5678 |= (!!presence1_p) << (num % (sizeof (int) * CHAR_BIT));
5683 /* The function returns nonzero value if STATE is not equivalent to
5684 ANOTHER_STATE from the same current partition on equivalence
5685 classes. Another state has ANOTHER_STATE_OUT_ARCS_NUM number of
5686 output arcs. Iteration of making equivalence partition is defined
5687 by ODD_ITERATION_FLAG. */
5689 state_is_differed (state_t state, state_t another_state,
5690 int odd_iteration_flag)
5693 unsigned int sz, si;
5695 gcc_assert (state->num_out_arcs == another_state->num_out_arcs);
5697 sz = (description->query_units_num + sizeof (int) * CHAR_BIT - 1)
5698 / (sizeof (int) * CHAR_BIT);
5700 for (si = 0; si < sz; si++)
5701 gcc_assert (state->presence_signature[si]
5702 == another_state->presence_signature[si]);
5704 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5706 if ((odd_iteration_flag
5707 ? arc->to_state->equiv_class_num_1
5708 : arc->to_state->equiv_class_num_2)
5709 != arc->insn->insn_reserv_decl->equiv_class_num)
5716 /* Compares two states pointed to by STATE_PTR_1 and STATE_PTR_2
5717 and return -1, 0 or 1. This function can be used as predicate for
5718 qsort(). It requires the member presence_signature[] of both
5719 states be filled. */
5721 compare_states_for_equiv (const void *state_ptr_1,
5722 const void *state_ptr_2)
5724 const_state_t const s1 = *(const_state_t const*)state_ptr_1;
5725 const_state_t const s2 = *(const_state_t const*)state_ptr_2;
5726 unsigned int sz, si;
5727 if (s1->num_out_arcs < s2->num_out_arcs)
5729 else if (s1->num_out_arcs > s2->num_out_arcs)
5732 sz = (description->query_units_num + sizeof (int) * CHAR_BIT - 1)
5733 / (sizeof (int) * CHAR_BIT);
5735 for (si = 0; si < sz; si++)
5736 if (s1->presence_signature[si] < s2->presence_signature[si])
5738 else if (s1->presence_signature[si] > s2->presence_signature[si])
5743 /* The function makes initial partition of STATES on equivalent
5744 classes and saves it into *CLASSES. This function requires the input
5745 to be sorted via compare_states_for_equiv(). */
5747 init_equiv_class (VEC(state_t,heap) *states, VEC (state_t,heap) **classes)
5753 *classes = VEC_alloc (state_t,heap, 150);
5754 for (i = 0; i < VEC_length (state_t, states); i++)
5756 state_t state = VEC_index (state_t, states, i);
5759 if (compare_states_for_equiv (&prev, &state) != 0)
5761 VEC_safe_push (state_t,heap, *classes, prev);
5766 state->equiv_class_num_1 = class_num;
5767 state->next_equiv_class_state = prev;
5771 VEC_safe_push (state_t,heap, *classes, prev);
5775 /* The function copies pointers to equivalent states from vla FROM
5778 copy_equiv_class (VEC(state_t,heap) **to, VEC(state_t,heap) *from)
5780 VEC_free (state_t,heap, *to);
5781 *to = VEC_copy (state_t,heap, from);
5784 /* The function processes equivalence class given by its first state,
5785 FIRST_STATE, on odd iteration if ODD_ITERATION_FLAG. If there
5786 are not equivalent states, the function partitions the class
5787 removing nonequivalent states and placing them in
5788 *NEXT_ITERATION_CLASSES, increments *NEW_EQUIV_CLASS_NUM_PTR ans
5789 assigns it to the state equivalence number. If the class has been
5790 partitioned, the function returns nonzero value. */
5792 partition_equiv_class (state_t first_state, int odd_iteration_flag,
5793 VEC(state_t,heap) **next_iteration_classes,
5794 int *new_equiv_class_num_ptr)
5796 state_t new_equiv_class;
5804 while (first_state != NULL)
5806 new_equiv_class = NULL;
5807 if (first_state->next_equiv_class_state != NULL)
5809 /* There are more one states in the class equivalence. */
5810 set_out_arc_insns_equiv_num (first_state, odd_iteration_flag);
5811 for (prev_state = first_state,
5812 curr_state = first_state->next_equiv_class_state;
5814 curr_state = next_state)
5816 next_state = curr_state->next_equiv_class_state;
5817 if (state_is_differed (curr_state, first_state,
5818 odd_iteration_flag))
5820 /* Remove curr state from the class equivalence. */
5821 prev_state->next_equiv_class_state = next_state;
5822 /* Add curr state to the new class equivalence. */
5823 curr_state->next_equiv_class_state = new_equiv_class;
5824 if (new_equiv_class == NULL)
5825 (*new_equiv_class_num_ptr)++;
5826 if (odd_iteration_flag)
5827 curr_state->equiv_class_num_2 = *new_equiv_class_num_ptr;
5829 curr_state->equiv_class_num_1 = *new_equiv_class_num_ptr;
5830 new_equiv_class = curr_state;
5834 prev_state = curr_state;
5836 clear_arc_insns_equiv_num (first_state);
5838 if (new_equiv_class != NULL)
5839 VEC_safe_push (state_t,heap, *next_iteration_classes, new_equiv_class);
5840 first_state = new_equiv_class;
5845 /* The function finds equivalent states of AUTOMATON. */
5847 evaluate_equiv_classes (automaton_t automaton,
5848 VEC(state_t,heap) **equiv_classes)
5850 int new_equiv_class_num;
5851 int odd_iteration_flag;
5853 VEC (state_t,heap) *next_iteration_classes;
5856 all_achieved_states = VEC_alloc (state_t,heap, 1500);
5857 pass_states (automaton, add_achieved_state);
5858 pass_states (automaton, cache_presence);
5859 qsort (VEC_address (state_t, all_achieved_states),
5860 VEC_length (state_t, all_achieved_states),
5861 sizeof (state_t), compare_states_for_equiv);
5863 odd_iteration_flag = 0;
5864 new_equiv_class_num = init_equiv_class (all_achieved_states,
5865 &next_iteration_classes);
5869 odd_iteration_flag = !odd_iteration_flag;
5871 copy_equiv_class (equiv_classes, next_iteration_classes);
5873 /* Transfer equiv numbers for the next iteration. */
5874 for (i = 0; i < VEC_length (state_t, all_achieved_states); i++)
5875 if (odd_iteration_flag)
5876 VEC_index (state_t, all_achieved_states, i)->equiv_class_num_2
5877 = VEC_index (state_t, all_achieved_states, i)->equiv_class_num_1;
5879 VEC_index (state_t, all_achieved_states, i)->equiv_class_num_1
5880 = VEC_index (state_t, all_achieved_states, i)->equiv_class_num_2;
5882 for (i = 0; i < VEC_length (state_t, *equiv_classes); i++)
5883 if (partition_equiv_class (VEC_index (state_t, *equiv_classes, i),
5885 &next_iteration_classes,
5886 &new_equiv_class_num))
5889 while (!finish_flag);
5890 VEC_free (state_t,heap, next_iteration_classes);
5891 VEC_free (state_t,heap, all_achieved_states);
5894 /* The function merges equivalent states of AUTOMATON. */
5896 merge_states (automaton_t automaton, VEC(state_t,heap) *equiv_classes)
5900 state_t first_class_state;
5901 alt_state_t alt_states;
5902 alt_state_t alt_state, new_alt_state;
5907 /* Create states corresponding to equivalence classes containing two
5909 for (i = 0; i < VEC_length (state_t, equiv_classes); i++)
5911 curr_state = VEC_index (state_t, equiv_classes, i);
5912 if (curr_state->next_equiv_class_state != NULL)
5914 /* There are more one states in the class equivalence. */
5915 /* Create new compound state. */
5916 new_state = get_free_state (0, automaton);
5918 first_class_state = curr_state;
5919 for (curr_state = first_class_state;
5921 curr_state = curr_state->next_equiv_class_state)
5923 curr_state->equiv_class_state = new_state;
5924 if (curr_state->component_states == NULL)
5926 new_alt_state = get_free_alt_state ();
5927 new_alt_state->state = curr_state;
5928 new_alt_state->next_alt_state = alt_states;
5929 alt_states = new_alt_state;
5932 for (alt_state = curr_state->component_states;
5934 alt_state = alt_state->next_sorted_alt_state)
5936 new_alt_state = get_free_alt_state ();
5937 new_alt_state->state = alt_state->state;
5938 new_alt_state->next_alt_state = alt_states;
5939 alt_states = new_alt_state;
5942 /* Its is important that alt states were sorted before and
5943 after merging to have the same querying results. */
5944 new_state->component_states = uniq_sort_alt_states (alt_states);
5947 curr_state->equiv_class_state = curr_state;
5950 for (i = 0; i < VEC_length (state_t, equiv_classes); i++)
5952 curr_state = VEC_index (state_t, equiv_classes, i);
5953 if (curr_state->next_equiv_class_state != NULL)
5955 first_class_state = curr_state;
5956 /* Create new arcs output from the state corresponding to
5958 for (curr_arc = first_out_arc (first_class_state);
5960 curr_arc = next_out_arc (curr_arc))
5961 add_arc (first_class_state->equiv_class_state,
5962 curr_arc->to_state->equiv_class_state,
5964 /* Delete output arcs from states of given class equivalence. */
5965 for (curr_state = first_class_state;
5967 curr_state = curr_state->next_equiv_class_state)
5969 if (automaton->start_state == curr_state)
5970 automaton->start_state = curr_state->equiv_class_state;
5971 /* Delete the state and its output arcs. */
5972 for (curr_arc = first_out_arc (curr_state);
5974 curr_arc = next_arc)
5976 next_arc = next_out_arc (curr_arc);
5977 free_arc (curr_arc);
5983 /* Change `to_state' of arcs output from the state of given
5984 equivalence class. */
5985 for (curr_arc = first_out_arc (curr_state);
5987 curr_arc = next_out_arc (curr_arc))
5988 curr_arc->to_state = curr_arc->to_state->equiv_class_state;
5993 /* The function sets up new_cycle_p for states if there is arc to the
5994 state marked by advance_cycle_insn_decl. */
5996 set_new_cycle_flags (state_t state)
6000 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6001 if (arc->insn->insn_reserv_decl
6002 == DECL_INSN_RESERV (advance_cycle_insn_decl))
6003 arc->to_state->new_cycle_p = 1;
6006 /* The top level function for minimization of deterministic
6009 minimize_DFA (automaton_t automaton)
6011 VEC(state_t,heap) *equiv_classes = 0;
6013 evaluate_equiv_classes (automaton, &equiv_classes);
6014 merge_states (automaton, equiv_classes);
6015 pass_states (automaton, set_new_cycle_flags);
6017 VEC_free (state_t,heap, equiv_classes);
6020 /* Values of two variables are counted number of states and arcs in an
6022 static int curr_counted_states_num;
6023 static int curr_counted_arcs_num;
6025 /* The function is called by function `pass_states' to count states
6026 and arcs of an automaton. */
6028 incr_states_and_arcs_nums (state_t state)
6032 curr_counted_states_num++;
6033 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6034 curr_counted_arcs_num++;
6037 /* The function counts states and arcs of AUTOMATON. */
6039 count_states_and_arcs (automaton_t automaton, int *states_num,
6042 curr_counted_states_num = 0;
6043 curr_counted_arcs_num = 0;
6044 pass_states (automaton, incr_states_and_arcs_nums);
6045 *states_num = curr_counted_states_num;
6046 *arcs_num = curr_counted_arcs_num;
6049 /* The function builds one DFA AUTOMATON for fast pipeline hazards
6050 recognition after checking and simplifying IR of the
6053 build_automaton (automaton_t automaton)
6058 ticker_on (&NDFA_time);
6061 if (automaton->corresponding_automaton_decl == NULL)
6062 fprintf (stderr, "Create anonymous automaton");
6064 fprintf (stderr, "Create automaton `%s'",
6065 automaton->corresponding_automaton_decl->name);
6066 fprintf (stderr, " (1 dot is 100 new states):");
6068 make_automaton (automaton);
6070 fprintf (stderr, " done\n");
6071 ticker_off (&NDFA_time);
6072 count_states_and_arcs (automaton, &states_num, &arcs_num);
6073 automaton->NDFA_states_num = states_num;
6074 automaton->NDFA_arcs_num = arcs_num;
6075 ticker_on (&NDFA_to_DFA_time);
6078 if (automaton->corresponding_automaton_decl == NULL)
6079 fprintf (stderr, "Make anonymous DFA");
6081 fprintf (stderr, "Make DFA `%s'",
6082 automaton->corresponding_automaton_decl->name);
6083 fprintf (stderr, " (1 dot is 100 new states):");
6085 NDFA_to_DFA (automaton);
6087 fprintf (stderr, " done\n");
6088 ticker_off (&NDFA_to_DFA_time);
6089 count_states_and_arcs (automaton, &states_num, &arcs_num);
6090 automaton->DFA_states_num = states_num;
6091 automaton->DFA_arcs_num = arcs_num;
6092 if (!no_minimization_flag)
6094 ticker_on (&minimize_time);
6097 if (automaton->corresponding_automaton_decl == NULL)
6098 fprintf (stderr, "Minimize anonymous DFA...");
6100 fprintf (stderr, "Minimize DFA `%s'...",
6101 automaton->corresponding_automaton_decl->name);
6103 minimize_DFA (automaton);
6105 fprintf (stderr, "done\n");
6106 ticker_off (&minimize_time);
6107 count_states_and_arcs (automaton, &states_num, &arcs_num);
6108 automaton->minimal_DFA_states_num = states_num;
6109 automaton->minimal_DFA_arcs_num = arcs_num;
6115 /* The page contains code for enumeration of all states of an automaton. */
6117 /* Variable used for enumeration of all states of an automaton. Its
6118 value is current number of automaton states. */
6119 static int curr_state_order_num;
6121 /* The function is called by function `pass_states' for enumerating
6124 set_order_state_num (state_t state)
6126 state->order_state_num = curr_state_order_num;
6127 curr_state_order_num++;
6130 /* The function enumerates all states of AUTOMATON. */
6132 enumerate_states (automaton_t automaton)
6134 curr_state_order_num = 0;
6135 pass_states (automaton, set_order_state_num);
6136 automaton->achieved_states_num = curr_state_order_num;
6141 /* The page contains code for finding equivalent automaton insns
6144 /* The function inserts AINSN into cyclic list
6145 CYCLIC_EQUIV_CLASS_INSN_LIST of ainsns. */
6147 insert_ainsn_into_equiv_class (ainsn_t ainsn,
6148 ainsn_t cyclic_equiv_class_insn_list)
6150 if (cyclic_equiv_class_insn_list == NULL)
6151 ainsn->next_equiv_class_insn = ainsn;
6154 ainsn->next_equiv_class_insn
6155 = cyclic_equiv_class_insn_list->next_equiv_class_insn;
6156 cyclic_equiv_class_insn_list->next_equiv_class_insn = ainsn;
6161 /* The function deletes equiv_class_insn into cyclic list of
6162 equivalent ainsns. */
6164 delete_ainsn_from_equiv_class (ainsn_t equiv_class_insn)
6166 ainsn_t curr_equiv_class_insn;
6167 ainsn_t prev_equiv_class_insn;
6169 prev_equiv_class_insn = equiv_class_insn;
6170 for (curr_equiv_class_insn = equiv_class_insn->next_equiv_class_insn;
6171 curr_equiv_class_insn != equiv_class_insn;
6172 curr_equiv_class_insn = curr_equiv_class_insn->next_equiv_class_insn)
6173 prev_equiv_class_insn = curr_equiv_class_insn;
6174 if (prev_equiv_class_insn != equiv_class_insn)
6175 prev_equiv_class_insn->next_equiv_class_insn
6176 = equiv_class_insn->next_equiv_class_insn;
6179 /* The function processes AINSN of a state in order to find equivalent
6180 ainsns. INSN_ARCS_ARRAY is table: code of insn -> out arc of the
6183 process_insn_equiv_class (ainsn_t ainsn, arc_t *insn_arcs_array)
6187 ainsn_t cyclic_insn_list;
6190 gcc_assert (insn_arcs_array [ainsn->insn_reserv_decl->insn_num]);
6192 /* New class of ainsns which are not equivalent to given ainsn. */
6193 cyclic_insn_list = NULL;
6196 next_insn = curr_insn->next_equiv_class_insn;
6197 arc = insn_arcs_array [curr_insn->insn_reserv_decl->insn_num];
6199 || (insn_arcs_array [ainsn->insn_reserv_decl->insn_num]->to_state
6202 delete_ainsn_from_equiv_class (curr_insn);
6203 cyclic_insn_list = insert_ainsn_into_equiv_class (curr_insn,
6206 curr_insn = next_insn;
6208 while (curr_insn != ainsn);
6211 /* The function processes STATE in order to find equivalent ainsns. */
6213 process_state_for_insn_equiv_partition (state_t state)
6216 arc_t *insn_arcs_array = XCNEWVEC (arc_t, description->insns_num);
6218 /* Process insns of the arcs. */
6219 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6220 insn_arcs_array [arc->insn->insn_reserv_decl->insn_num] = arc;
6221 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6222 process_insn_equiv_class (arc->insn, insn_arcs_array);
6224 free (insn_arcs_array);
6227 /* The function searches for equivalent ainsns of AUTOMATON. */
6229 set_insn_equiv_classes (automaton_t automaton)
6234 ainsn_t cyclic_insn_list;
6235 ainsn_t insn_with_same_reservs;
6236 int equiv_classes_num;
6238 /* All insns are included in one equivalence class. */
6239 cyclic_insn_list = NULL;
6240 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6241 if (ainsn->first_insn_with_same_reservs)
6242 cyclic_insn_list = insert_ainsn_into_equiv_class (ainsn,
6244 /* Process insns in order to make equivalence partition. */
6245 pass_states (automaton, process_state_for_insn_equiv_partition);
6246 /* Enumerate equiv classes. */
6247 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6248 /* Set undefined value. */
6249 ainsn->insn_equiv_class_num = -1;
6250 equiv_classes_num = 0;
6251 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6252 if (ainsn->insn_equiv_class_num < 0)
6255 gcc_assert (first_insn->first_insn_with_same_reservs);
6256 first_insn->first_ainsn_with_given_equivalence_num = 1;
6257 curr_insn = first_insn;
6260 for (insn_with_same_reservs = curr_insn;
6261 insn_with_same_reservs != NULL;
6262 insn_with_same_reservs
6263 = insn_with_same_reservs->next_same_reservs_insn)
6264 insn_with_same_reservs->insn_equiv_class_num = equiv_classes_num;
6265 curr_insn = curr_insn->next_equiv_class_insn;
6267 while (curr_insn != first_insn);
6268 equiv_classes_num++;
6270 automaton->insn_equiv_classes_num = equiv_classes_num;
6275 /* This page contains code for creating DFA(s) and calls functions
6279 /* The following value is used to prevent floating point overflow for
6280 estimating an automaton bound. The value should be less DBL_MAX on
6281 the host machine. We use here approximate minimum of maximal
6282 double floating point value required by ANSI C standard. It
6283 will work for non ANSI sun compiler too. */
6285 #define MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND 1.0E37
6287 /* The function estimate size of the single DFA used by PHR (pipeline
6288 hazards recognizer). */
6290 estimate_one_automaton_bound (void)
6293 double one_automaton_estimation_bound;
6297 one_automaton_estimation_bound = 1.0;
6298 for (i = 0; i < description->decls_num; i++)
6300 decl = description->decls [i];
6301 if (decl->mode == dm_unit)
6303 root_value = exp (log (DECL_UNIT (decl)->max_occ_cycle_num
6304 - DECL_UNIT (decl)->min_occ_cycle_num + 1.0)
6306 if (MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND / root_value
6307 > one_automaton_estimation_bound)
6308 one_automaton_estimation_bound *= root_value;
6311 return one_automaton_estimation_bound;
6314 /* The function compares unit declarations according to their maximal
6315 cycle in reservations. */
6317 compare_max_occ_cycle_nums (const void *unit_decl_1,
6318 const void *unit_decl_2)
6320 if ((DECL_UNIT (*(const_decl_t const*) unit_decl_1)->max_occ_cycle_num)
6321 < (DECL_UNIT (*(const_decl_t const*) unit_decl_2)->max_occ_cycle_num))
6323 else if ((DECL_UNIT (*(const_decl_t const*) unit_decl_1)->max_occ_cycle_num)
6324 == (DECL_UNIT (*(const_decl_t const*) unit_decl_2)->max_occ_cycle_num))
6330 /* The function makes heuristic assigning automata to units. Actually
6331 efficacy of the algorithm has been checked yet??? */
6334 units_to_automata_heuristic_distr (void)
6336 double estimation_bound;
6340 unit_decl_t *unit_decls;
6343 if (description->units_num == 0)
6345 estimation_bound = estimate_one_automaton_bound ();
6346 unit_decls = XNEWVEC (unit_decl_t, description->units_num);
6348 for (i = 0, j = 0; i < description->decls_num; i++)
6349 if (description->decls[i]->mode == dm_unit)
6350 unit_decls[j++] = DECL_UNIT (description->decls[i]);
6351 gcc_assert (j == description->units_num);
6353 qsort (unit_decls, description->units_num,
6354 sizeof (unit_decl_t), compare_max_occ_cycle_nums);
6357 bound_value = unit_decls[0]->max_occ_cycle_num;
6358 unit_decls[0]->corresponding_automaton_num = automaton_num;
6360 for (i = 1; i < description->units_num; i++)
6362 rest_units_num = description->units_num - i + 1;
6363 gcc_assert (automata_num - automaton_num - 1 <= rest_units_num);
6364 if (automaton_num < automata_num - 1
6365 && ((automata_num - automaton_num - 1 == rest_units_num)
6368 / unit_decls[i]->max_occ_cycle_num))))
6370 bound_value = unit_decls[i]->max_occ_cycle_num;
6374 bound_value *= unit_decls[i]->max_occ_cycle_num;
6375 unit_decls[i]->corresponding_automaton_num = automaton_num;
6377 gcc_assert (automaton_num == automata_num - 1);
6381 /* The functions creates automaton insns for each automata. Automaton
6382 insn is simply insn for given automaton which makes reservation
6383 only of units of the automaton. */
6385 create_ainsns (void)
6388 ainsn_t first_ainsn;
6395 for (i = 0; i < description->decls_num; i++)
6397 decl = description->decls [i];
6398 if (decl->mode == dm_insn_reserv)
6400 curr_ainsn = create_node (sizeof (struct ainsn));
6401 curr_ainsn->insn_reserv_decl = DECL_INSN_RESERV (decl);
6402 curr_ainsn->important_p = FALSE;
6403 curr_ainsn->next_ainsn = NULL;
6404 if (prev_ainsn == NULL)
6405 first_ainsn = curr_ainsn;
6407 prev_ainsn->next_ainsn = curr_ainsn;
6408 prev_ainsn = curr_ainsn;
6414 /* The function assigns automata to units according to constructions
6415 `define_automaton' in the description. */
6417 units_to_automata_distr (void)
6422 for (i = 0; i < description->decls_num; i++)
6424 decl = description->decls [i];
6425 if (decl->mode == dm_unit)
6427 if (DECL_UNIT (decl)->automaton_decl == NULL
6428 || (DECL_UNIT (decl)->automaton_decl->corresponding_automaton
6430 /* Distribute to the first automaton. */
6431 DECL_UNIT (decl)->corresponding_automaton_num = 0;
6433 DECL_UNIT (decl)->corresponding_automaton_num
6434 = (DECL_UNIT (decl)->automaton_decl
6435 ->corresponding_automaton->automaton_order_num);
6440 /* The function creates DFA(s) for fast pipeline hazards recognition
6441 after checking and simplifying IR of the description. */
6443 create_automata (void)
6445 automaton_t curr_automaton;
6446 automaton_t prev_automaton;
6448 int curr_automaton_num;
6451 if (automata_num != 0)
6453 units_to_automata_heuristic_distr ();
6454 for (prev_automaton = NULL, curr_automaton_num = 0;
6455 curr_automaton_num < automata_num;
6456 curr_automaton_num++, prev_automaton = curr_automaton)
6458 curr_automaton = create_node (sizeof (struct automaton));
6459 curr_automaton->ainsn_list = create_ainsns ();
6460 curr_automaton->corresponding_automaton_decl = NULL;
6461 curr_automaton->next_automaton = NULL;
6462 curr_automaton->automaton_order_num = curr_automaton_num;
6463 if (prev_automaton == NULL)
6464 description->first_automaton = curr_automaton;
6466 prev_automaton->next_automaton = curr_automaton;
6471 curr_automaton_num = 0;
6472 prev_automaton = NULL;
6473 for (i = 0; i < description->decls_num; i++)
6475 decl = description->decls [i];
6476 if (decl->mode == dm_automaton
6477 && DECL_AUTOMATON (decl)->automaton_is_used)
6479 curr_automaton = create_node (sizeof (struct automaton));
6480 curr_automaton->ainsn_list = create_ainsns ();
6481 curr_automaton->corresponding_automaton_decl
6482 = DECL_AUTOMATON (decl);
6483 curr_automaton->next_automaton = NULL;
6484 DECL_AUTOMATON (decl)->corresponding_automaton = curr_automaton;
6485 curr_automaton->automaton_order_num = curr_automaton_num;
6486 if (prev_automaton == NULL)
6487 description->first_automaton = curr_automaton;
6489 prev_automaton->next_automaton = curr_automaton;
6490 curr_automaton_num++;
6491 prev_automaton = curr_automaton;
6494 if (curr_automaton_num == 0)
6496 curr_automaton = create_node (sizeof (struct automaton));
6497 curr_automaton->ainsn_list = create_ainsns ();
6498 curr_automaton->corresponding_automaton_decl = NULL;
6499 curr_automaton->next_automaton = NULL;
6500 description->first_automaton = curr_automaton;
6502 units_to_automata_distr ();
6504 NDFA_time = create_ticker ();
6505 ticker_off (&NDFA_time);
6506 NDFA_to_DFA_time = create_ticker ();
6507 ticker_off (&NDFA_to_DFA_time);
6508 minimize_time = create_ticker ();
6509 ticker_off (&minimize_time);
6510 equiv_time = create_ticker ();
6511 ticker_off (&equiv_time);
6512 for (curr_automaton = description->first_automaton;
6513 curr_automaton != NULL;
6514 curr_automaton = curr_automaton->next_automaton)
6518 if (curr_automaton->corresponding_automaton_decl == NULL)
6519 fprintf (stderr, "Prepare anonymous automaton creation ... ");
6521 fprintf (stderr, "Prepare automaton `%s' creation...",
6522 curr_automaton->corresponding_automaton_decl->name);
6524 create_alt_states (curr_automaton);
6525 form_ainsn_with_same_reservs (curr_automaton);
6527 fprintf (stderr, "done\n");
6528 build_automaton (curr_automaton);
6529 enumerate_states (curr_automaton);
6530 ticker_on (&equiv_time);
6531 set_insn_equiv_classes (curr_automaton);
6532 ticker_off (&equiv_time);
6538 /* This page contains code for forming string representation of
6539 regexp. The representation is formed on IR obstack. So you should
6540 not work with IR obstack between regexp_representation and
6541 finish_regexp_representation calls. */
6543 /* This recursive function forms string representation of regexp
6544 (without tailing '\0'). */
6546 form_regexp (regexp_t regexp)
6550 switch (regexp->mode)
6552 case rm_unit: case rm_reserv:
6554 const char *name = (regexp->mode == rm_unit
6555 ? REGEXP_UNIT (regexp)->name
6556 : REGEXP_RESERV (regexp)->name);
6558 obstack_grow (&irp, name, strlen (name));
6563 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
6566 obstack_1grow (&irp, ',');
6567 form_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
6572 obstack_1grow (&irp, '(');
6573 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
6576 obstack_1grow (&irp, '+');
6577 if (REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_sequence
6578 || REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_oneof)
6579 obstack_1grow (&irp, '(');
6580 form_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
6581 if (REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_sequence
6582 || REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_oneof)
6583 obstack_1grow (&irp, ')');
6585 obstack_1grow (&irp, ')');
6589 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
6592 obstack_1grow (&irp, '|');
6593 if (REGEXP_ONEOF (regexp)->regexps[i]->mode == rm_sequence)
6594 obstack_1grow (&irp, '(');
6595 form_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
6596 if (REGEXP_ONEOF (regexp)->regexps[i]->mode == rm_sequence)
6597 obstack_1grow (&irp, ')');
6605 if (REGEXP_REPEAT (regexp)->regexp->mode == rm_sequence
6606 || REGEXP_REPEAT (regexp)->regexp->mode == rm_allof
6607 || REGEXP_REPEAT (regexp)->regexp->mode == rm_oneof)
6608 obstack_1grow (&irp, '(');
6609 form_regexp (REGEXP_REPEAT (regexp)->regexp);
6610 if (REGEXP_REPEAT (regexp)->regexp->mode == rm_sequence
6611 || REGEXP_REPEAT (regexp)->regexp->mode == rm_allof
6612 || REGEXP_REPEAT (regexp)->regexp->mode == rm_oneof)
6613 obstack_1grow (&irp, ')');
6614 sprintf (digits, "*%d", REGEXP_REPEAT (regexp)->repeat_num);
6615 obstack_grow (&irp, digits, strlen (digits));
6620 obstack_grow (&irp, NOTHING_NAME, strlen (NOTHING_NAME));
6628 /* The function returns string representation of REGEXP on IR
6631 regexp_representation (regexp_t regexp)
6633 form_regexp (regexp);
6634 obstack_1grow (&irp, '\0');
6635 return obstack_base (&irp);
6638 /* The function frees memory allocated for last formed string
6639 representation of regexp. */
6641 finish_regexp_representation (void)
6643 int length = obstack_object_size (&irp);
6645 obstack_blank_fast (&irp, -length);
6650 /* This page contains code for output PHR (pipeline hazards recognizer). */
6652 /* The function outputs minimal C type which is sufficient for
6653 representation numbers in range min_range_value and
6654 max_range_value. Because host machine and build machine may be
6655 different, we use here minimal values required by ANSI C standard
6656 instead of UCHAR_MAX, SHRT_MAX, SHRT_MIN, etc. This is a good
6660 output_range_type (FILE *f, long int min_range_value,
6661 long int max_range_value)
6663 if (min_range_value >= 0 && max_range_value <= 255)
6664 fprintf (f, "unsigned char");
6665 else if (min_range_value >= -127 && max_range_value <= 127)
6666 fprintf (f, "signed char");
6667 else if (min_range_value >= 0 && max_range_value <= 65535)
6668 fprintf (f, "unsigned short");
6669 else if (min_range_value >= -32767 && max_range_value <= 32767)
6670 fprintf (f, "short");
6675 /* The function outputs all initialization values of VECT. */
6677 output_vect (vla_hwint_t vect)
6680 size_t vect_length = VEC_length (vect_el_t, vect);
6684 if (vect_length == 0)
6685 fputs ("0 /* This is dummy el because the vect is empty */", output_file);
6687 for (i = 0; i < vect_length; i++)
6689 fprintf (output_file, "%5ld", (long) VEC_index (vect_el_t, vect, i));
6690 if (els_on_line == 10)
6693 fputs (",\n", output_file);
6695 else if (i < vect_length-1)
6696 fputs (", ", output_file);
6701 /* The following is name of the structure which represents DFA(s) for
6703 #define CHIP_NAME "DFA_chip"
6705 /* The following is name of member which represents state of a DFA for
6708 output_chip_member_name (FILE *f, automaton_t automaton)
6710 if (automaton->corresponding_automaton_decl == NULL)
6711 fprintf (f, "automaton_state_%d", automaton->automaton_order_num);
6713 fprintf (f, "%s_automaton_state",
6714 automaton->corresponding_automaton_decl->name);
6717 /* The following is name of temporary variable which stores state of a
6720 output_temp_chip_member_name (FILE *f, automaton_t automaton)
6723 output_chip_member_name (f, automaton);
6726 /* This is name of macro value which is code of pseudo_insn
6727 representing advancing cpu cycle. Its value is used as internal
6728 code unknown insn. */
6729 #define ADVANCE_CYCLE_VALUE_NAME "DFA__ADVANCE_CYCLE"
6731 /* Output name of translate vector for given automaton. */
6733 output_translate_vect_name (FILE *f, automaton_t automaton)
6735 if (automaton->corresponding_automaton_decl == NULL)
6736 fprintf (f, "translate_%d", automaton->automaton_order_num);
6738 fprintf (f, "%s_translate", automaton->corresponding_automaton_decl->name);
6741 /* Output name for simple transition table representation. */
6743 output_trans_full_vect_name (FILE *f, automaton_t automaton)
6745 if (automaton->corresponding_automaton_decl == NULL)
6746 fprintf (f, "transitions_%d", automaton->automaton_order_num);
6748 fprintf (f, "%s_transitions",
6749 automaton->corresponding_automaton_decl->name);
6752 /* Output name of comb vector of the transition table for given
6755 output_trans_comb_vect_name (FILE *f, automaton_t automaton)
6757 if (automaton->corresponding_automaton_decl == NULL)
6758 fprintf (f, "transitions_%d", automaton->automaton_order_num);
6760 fprintf (f, "%s_transitions",
6761 automaton->corresponding_automaton_decl->name);
6764 /* Output name of check vector of the transition table for given
6767 output_trans_check_vect_name (FILE *f, automaton_t automaton)
6769 if (automaton->corresponding_automaton_decl == NULL)
6770 fprintf (f, "check_%d", automaton->automaton_order_num);
6772 fprintf (f, "%s_check", automaton->corresponding_automaton_decl->name);
6775 /* Output name of base vector of the transition table for given
6778 output_trans_base_vect_name (FILE *f, automaton_t automaton)
6780 if (automaton->corresponding_automaton_decl == NULL)
6781 fprintf (f, "base_%d", automaton->automaton_order_num);
6783 fprintf (f, "%s_base", automaton->corresponding_automaton_decl->name);
6786 /* Output name of simple min issue delay table representation. */
6788 output_min_issue_delay_vect_name (FILE *f, automaton_t automaton)
6790 if (automaton->corresponding_automaton_decl == NULL)
6791 fprintf (f, "min_issue_delay_%d", automaton->automaton_order_num);
6793 fprintf (f, "%s_min_issue_delay",
6794 automaton->corresponding_automaton_decl->name);
6797 /* Output name of deadlock vector for given automaton. */
6799 output_dead_lock_vect_name (FILE *f, automaton_t automaton)
6801 if (automaton->corresponding_automaton_decl == NULL)
6802 fprintf (f, "dead_lock_%d", automaton->automaton_order_num);
6804 fprintf (f, "%s_dead_lock", automaton->corresponding_automaton_decl->name);
6807 /* Output name of reserved units table for AUTOMATON into file F. */
6809 output_reserved_units_table_name (FILE *f, automaton_t automaton)
6811 if (automaton->corresponding_automaton_decl == NULL)
6812 fprintf (f, "reserved_units_%d", automaton->automaton_order_num);
6814 fprintf (f, "%s_reserved_units",
6815 automaton->corresponding_automaton_decl->name);
6818 /* Name of the PHR interface macro. */
6819 #define CPU_UNITS_QUERY_MACRO_NAME "CPU_UNITS_QUERY"
6821 /* Names of an internal functions: */
6822 #define INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME "internal_min_issue_delay"
6824 /* This is external type of DFA(s) state. */
6825 #define STATE_TYPE_NAME "state_t"
6827 #define INTERNAL_TRANSITION_FUNC_NAME "internal_state_transition"
6829 #define INTERNAL_RESET_FUNC_NAME "internal_reset"
6831 #define INTERNAL_DEAD_LOCK_FUNC_NAME "internal_state_dead_lock_p"
6833 #define INTERNAL_INSN_LATENCY_FUNC_NAME "internal_insn_latency"
6835 /* Name of cache of insn dfa codes. */
6836 #define DFA_INSN_CODES_VARIABLE_NAME "dfa_insn_codes"
6838 /* Name of length of cache of insn dfa codes. */
6839 #define DFA_INSN_CODES_LENGTH_VARIABLE_NAME "dfa_insn_codes_length"
6841 /* Names of the PHR interface functions: */
6842 #define SIZE_FUNC_NAME "state_size"
6844 #define TRANSITION_FUNC_NAME "state_transition"
6846 #define MIN_ISSUE_DELAY_FUNC_NAME "min_issue_delay"
6848 #define MIN_INSN_CONFLICT_DELAY_FUNC_NAME "min_insn_conflict_delay"
6850 #define DEAD_LOCK_FUNC_NAME "state_dead_lock_p"
6852 #define RESET_FUNC_NAME "state_reset"
6854 #define INSN_LATENCY_FUNC_NAME "insn_latency"
6856 #define PRINT_RESERVATION_FUNC_NAME "print_reservation"
6858 #define GET_CPU_UNIT_CODE_FUNC_NAME "get_cpu_unit_code"
6860 #define CPU_UNIT_RESERVATION_P_FUNC_NAME "cpu_unit_reservation_p"
6862 #define DFA_CLEAN_INSN_CACHE_FUNC_NAME "dfa_clean_insn_cache"
6864 #define DFA_CLEAR_SINGLE_INSN_CACHE_FUNC_NAME "dfa_clear_single_insn_cache"
6866 #define DFA_START_FUNC_NAME "dfa_start"
6868 #define DFA_FINISH_FUNC_NAME "dfa_finish"
6870 /* Names of parameters of the PHR interface functions. */
6871 #define STATE_NAME "state"
6873 #define INSN_PARAMETER_NAME "insn"
6875 #define INSN2_PARAMETER_NAME "insn2"
6877 #define CHIP_PARAMETER_NAME "chip"
6879 #define FILE_PARAMETER_NAME "f"
6881 #define CPU_UNIT_NAME_PARAMETER_NAME "cpu_unit_name"
6883 #define CPU_CODE_PARAMETER_NAME "cpu_unit_code"
6885 /* Names of the variables whose values are internal insn code of rtx
6887 #define INTERNAL_INSN_CODE_NAME "insn_code"
6889 #define INTERNAL_INSN2_CODE_NAME "insn2_code"
6891 /* Names of temporary variables in some functions. */
6892 #define TEMPORARY_VARIABLE_NAME "temp"
6894 #define I_VARIABLE_NAME "i"
6896 /* Name of result variable in some functions. */
6897 #define RESULT_VARIABLE_NAME "res"
6899 /* Name of function (attribute) to translate insn into internal insn
6901 #define INTERNAL_DFA_INSN_CODE_FUNC_NAME "internal_dfa_insn_code"
6903 /* Name of function (attribute) to translate insn into internal insn
6904 code with caching. */
6905 #define DFA_INSN_CODE_FUNC_NAME "dfa_insn_code"
6907 /* Output C type which is used for representation of codes of states
6910 output_state_member_type (FILE *f, automaton_t automaton)
6912 output_range_type (f, 0, automaton->achieved_states_num);
6915 /* Output definition of the structure representing current DFA(s)
6918 output_chip_definitions (void)
6920 automaton_t automaton;
6922 fprintf (output_file, "struct %s\n{\n", CHIP_NAME);
6923 for (automaton = description->first_automaton;
6925 automaton = automaton->next_automaton)
6927 fprintf (output_file, " ");
6928 output_state_member_type (output_file, automaton);
6929 fprintf (output_file, " ");
6930 output_chip_member_name (output_file, automaton);
6931 fprintf (output_file, ";\n");
6933 fprintf (output_file, "};\n\n");
6935 fprintf (output_file, "static struct %s %s;\n\n", CHIP_NAME, CHIP_NAME);
6940 /* The function outputs translate vector of internal insn code into
6941 insn equivalence class number. The equivalence class number is
6942 used to access to table and vectors representing DFA(s). */
6944 output_translate_vect (automaton_t automaton)
6948 vla_hwint_t translate_vect;
6950 translate_vect = VEC_alloc (vect_el_t,heap, description->insns_num);
6952 for (insn_value = 0; insn_value < description->insns_num; insn_value++)
6953 /* Undefined value */
6954 VEC_quick_push (vect_el_t, translate_vect,
6955 automaton->insn_equiv_classes_num);
6957 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6958 VEC_replace (vect_el_t, translate_vect,
6959 ainsn->insn_reserv_decl->insn_num,
6960 ainsn->insn_equiv_class_num);
6962 fprintf (output_file,
6963 "/* Vector translating external insn codes to internal ones.*/\n");
6964 fprintf (output_file, "static const ");
6965 output_range_type (output_file, 0, automaton->insn_equiv_classes_num);
6966 fprintf (output_file, " ");
6967 output_translate_vect_name (output_file, automaton);
6968 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
6969 output_vect (translate_vect);
6970 fprintf (output_file, "};\n\n");
6971 VEC_free (vect_el_t,heap, translate_vect);
6974 /* The value in a table state x ainsn -> something which represents
6976 static int undefined_vect_el_value;
6978 /* The following function returns nonzero value if the best
6979 representation of the table is comb vector. */
6981 comb_vect_p (state_ainsn_table_t tab)
6983 return (2 * VEC_length (vect_el_t, tab->full_vect)
6984 > 5 * VEC_length (vect_el_t, tab->comb_vect));
6987 /* The following function creates new table for AUTOMATON. */
6988 static state_ainsn_table_t
6989 create_state_ainsn_table (automaton_t automaton)
6991 state_ainsn_table_t tab;
6992 int full_vect_length;
6995 tab = create_node (sizeof (struct state_ainsn_table));
6996 tab->automaton = automaton;
6998 tab->comb_vect = VEC_alloc (vect_el_t,heap, 10000);
6999 tab->check_vect = VEC_alloc (vect_el_t,heap, 10000);
7002 VEC_safe_grow (vect_el_t,heap, tab->base_vect,
7003 automaton->achieved_states_num);
7005 full_vect_length = (automaton->insn_equiv_classes_num
7006 * automaton->achieved_states_num);
7007 tab->full_vect = VEC_alloc (vect_el_t,heap, full_vect_length);
7008 for (i = 0; i < full_vect_length; i++)
7009 VEC_quick_push (vect_el_t, tab->full_vect, undefined_vect_el_value);
7011 tab->min_base_vect_el_value = 0;
7012 tab->max_base_vect_el_value = 0;
7013 tab->min_comb_vect_el_value = 0;
7014 tab->max_comb_vect_el_value = 0;
7018 /* The following function outputs the best C representation of the
7019 table TAB of given TABLE_NAME. */
7021 output_state_ainsn_table (state_ainsn_table_t tab, const char *table_name,
7022 void (*output_full_vect_name_func) (FILE *, automaton_t),
7023 void (*output_comb_vect_name_func) (FILE *, automaton_t),
7024 void (*output_check_vect_name_func) (FILE *, automaton_t),
7025 void (*output_base_vect_name_func) (FILE *, automaton_t))
7027 if (!comb_vect_p (tab))
7029 fprintf (output_file, "/* Vector for %s. */\n", table_name);
7030 fprintf (output_file, "static const ");
7031 output_range_type (output_file, tab->min_comb_vect_el_value,
7032 tab->max_comb_vect_el_value);
7033 fprintf (output_file, " ");
7034 (*output_full_vect_name_func) (output_file, tab->automaton);
7035 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7036 output_vect (tab->full_vect);
7037 fprintf (output_file, "};\n\n");
7041 fprintf (output_file, "/* Comb vector for %s. */\n", table_name);
7042 fprintf (output_file, "static const ");
7043 output_range_type (output_file, tab->min_comb_vect_el_value,
7044 tab->max_comb_vect_el_value);
7045 fprintf (output_file, " ");
7046 (*output_comb_vect_name_func) (output_file, tab->automaton);
7047 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7048 output_vect (tab->comb_vect);
7049 fprintf (output_file, "};\n\n");
7050 fprintf (output_file, "/* Check vector for %s. */\n", table_name);
7051 fprintf (output_file, "static const ");
7052 output_range_type (output_file, 0, tab->automaton->achieved_states_num);
7053 fprintf (output_file, " ");
7054 (*output_check_vect_name_func) (output_file, tab->automaton);
7055 fprintf (output_file, "[] = {\n");
7056 output_vect (tab->check_vect);
7057 fprintf (output_file, "};\n\n");
7058 fprintf (output_file, "/* Base vector for %s. */\n", table_name);
7059 fprintf (output_file, "static const ");
7060 output_range_type (output_file, tab->min_base_vect_el_value,
7061 tab->max_base_vect_el_value);
7062 fprintf (output_file, " ");
7063 (*output_base_vect_name_func) (output_file, tab->automaton);
7064 fprintf (output_file, "[] = {\n");
7065 output_vect (tab->base_vect);
7066 fprintf (output_file, "};\n\n");
7070 /* The following function adds vector VECT to table TAB as its line
7071 with number VECT_NUM. */
7073 add_vect (state_ainsn_table_t tab, int vect_num, vla_hwint_t vect)
7076 size_t real_vect_length;
7077 int comb_vect_index;
7078 int comb_vect_els_num;
7080 int first_unempty_vect_index;
7081 int additional_els_num;
7085 unsigned long vect_mask, comb_vect_mask;
7087 vect_length = VEC_length (vect_el_t, vect);
7088 gcc_assert (vect_length);
7089 gcc_assert (VEC_last (vect_el_t, vect) != undefined_vect_el_value);
7090 real_vect_length = tab->automaton->insn_equiv_classes_num;
7091 /* Form full vector in the table: */
7093 size_t full_base = tab->automaton->insn_equiv_classes_num * vect_num;
7094 if (VEC_length (vect_el_t, tab->full_vect) < full_base + vect_length)
7095 VEC_safe_grow (vect_el_t,heap, tab->full_vect,
7096 full_base + vect_length);
7097 for (i = 0; i < vect_length; i++)
7098 VEC_replace (vect_el_t, tab->full_vect, full_base + i,
7099 VEC_index (vect_el_t, vect, i));
7101 /* Form comb vector in the table: */
7102 gcc_assert (VEC_length (vect_el_t, tab->comb_vect)
7103 == VEC_length (vect_el_t, tab->check_vect));
7105 comb_vect_els_num = VEC_length (vect_el_t, tab->comb_vect);
7106 for (first_unempty_vect_index = 0;
7107 first_unempty_vect_index < vect_length;
7108 first_unempty_vect_index++)
7109 if (VEC_index (vect_el_t, vect, first_unempty_vect_index)
7110 != undefined_vect_el_value)
7113 /* Search for the place in comb vect for the inserted vect. */
7116 if (vect_length - first_unempty_vect_index >= SIZEOF_LONG * CHAR_BIT)
7118 for (comb_vect_index = 0;
7119 comb_vect_index < comb_vect_els_num;
7122 for (vect_index = first_unempty_vect_index;
7123 vect_index < vect_length
7124 && vect_index + comb_vect_index < comb_vect_els_num;
7126 if (VEC_index (vect_el_t, vect, vect_index)
7127 != undefined_vect_el_value
7128 && (VEC_index (vect_el_t, tab->comb_vect,
7129 vect_index + comb_vect_index)
7130 != undefined_vect_el_value))
7132 if (vect_index >= vect_length
7133 || vect_index + comb_vect_index >= comb_vect_els_num)
7141 for (vect_index = first_unempty_vect_index;
7142 vect_index < vect_length;
7145 vect_mask = vect_mask << 1;
7146 if (VEC_index (vect_el_t, vect, vect_index) != undefined_vect_el_value)
7150 /* Search for the place in comb vect for the inserted vect. */
7151 comb_vect_index = 0;
7152 if (comb_vect_els_num == 0)
7156 for (vect_index = first_unempty_vect_index;
7157 vect_index < vect_length && vect_index < comb_vect_els_num;
7160 comb_vect_mask <<= 1;
7161 if (vect_index + comb_vect_index < comb_vect_els_num
7162 && VEC_index (vect_el_t, tab->comb_vect, vect_index + comb_vect_index)
7163 != undefined_vect_el_value)
7164 comb_vect_mask |= 1;
7166 if ((vect_mask & comb_vect_mask) == 0)
7169 for (comb_vect_index = 1, i = vect_length; i < comb_vect_els_num;
7170 comb_vect_index++, i++)
7172 comb_vect_mask = (comb_vect_mask << 1) | 1;
7173 comb_vect_mask ^= (VEC_index (vect_el_t, tab->comb_vect, i)
7174 == undefined_vect_el_value);
7175 if ((vect_mask & comb_vect_mask) == 0)
7178 for ( ; comb_vect_index < comb_vect_els_num; comb_vect_index++)
7180 comb_vect_mask <<= 1;
7181 if ((vect_mask & comb_vect_mask) == 0)
7186 /* Slot was found. */
7187 additional_els_num = comb_vect_index + real_vect_length - comb_vect_els_num;
7188 if (additional_els_num < 0)
7189 additional_els_num = 0;
7190 /* Expand comb and check vectors. */
7191 vect_el = undefined_vect_el_value;
7192 no_state_value = tab->automaton->achieved_states_num;
7193 while (additional_els_num > 0)
7195 VEC_safe_push (vect_el_t,heap, tab->comb_vect, vect_el);
7196 VEC_safe_push (vect_el_t,heap, tab->check_vect, no_state_value);
7197 additional_els_num--;
7199 gcc_assert (VEC_length (vect_el_t, tab->comb_vect)
7200 >= comb_vect_index + real_vect_length);
7201 /* Fill comb and check vectors. */
7202 for (vect_index = 0; vect_index < vect_length; vect_index++)
7203 if (VEC_index (vect_el_t, vect, vect_index) != undefined_vect_el_value)
7205 vect_el_t x = VEC_index (vect_el_t, vect, vect_index);
7206 gcc_assert (VEC_index (vect_el_t, tab->comb_vect,
7207 comb_vect_index + vect_index)
7208 == undefined_vect_el_value);
7209 gcc_assert (x >= 0);
7210 if (tab->max_comb_vect_el_value < x)
7211 tab->max_comb_vect_el_value = x;
7212 if (tab->min_comb_vect_el_value > x)
7213 tab->min_comb_vect_el_value = x;
7214 VEC_replace (vect_el_t, tab->comb_vect,
7215 comb_vect_index + vect_index, x);
7216 VEC_replace (vect_el_t, tab->check_vect,
7217 comb_vect_index + vect_index, vect_num);
7219 if (tab->max_comb_vect_el_value < undefined_vect_el_value)
7220 tab->max_comb_vect_el_value = undefined_vect_el_value;
7221 if (tab->min_comb_vect_el_value > undefined_vect_el_value)
7222 tab->min_comb_vect_el_value = undefined_vect_el_value;
7223 if (tab->max_base_vect_el_value < comb_vect_index)
7224 tab->max_base_vect_el_value = comb_vect_index;
7225 if (tab->min_base_vect_el_value > comb_vect_index)
7226 tab->min_base_vect_el_value = comb_vect_index;
7228 VEC_replace (vect_el_t, tab->base_vect, vect_num, comb_vect_index);
7231 /* Return number of out arcs of STATE. */
7233 out_state_arcs_num (const_state_t state)
7239 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
7241 gcc_assert (arc->insn);
7242 if (arc->insn->first_ainsn_with_given_equivalence_num)
7248 /* Compare number of possible transitions from the states. */
7250 compare_transition_els_num (const void *state_ptr_1,
7251 const void *state_ptr_2)
7253 const int transition_els_num_1
7254 = out_state_arcs_num (*(const_state_t const*) state_ptr_1);
7255 const int transition_els_num_2
7256 = out_state_arcs_num (*(const_state_t const*) state_ptr_2);
7258 if (transition_els_num_1 < transition_els_num_2)
7260 else if (transition_els_num_1 == transition_els_num_2)
7266 /* The function adds element EL_VALUE to vector VECT for a table state
7269 add_vect_el (vla_hwint_t *vect, ainsn_t ainsn, int el_value)
7271 int equiv_class_num;
7275 equiv_class_num = ainsn->insn_equiv_class_num;
7276 for (vect_index = VEC_length (vect_el_t, *vect);
7277 vect_index <= equiv_class_num;
7279 VEC_safe_push (vect_el_t,heap, *vect, undefined_vect_el_value);
7280 VEC_replace (vect_el_t, *vect, equiv_class_num, el_value);
7283 /* This is for forming vector of states of an automaton. */
7284 static VEC(state_t,heap) *output_states_vect;
7286 /* The function is called by function pass_states. The function adds
7287 STATE to `output_states_vect'. */
7289 add_states_vect_el (state_t state)
7291 VEC_safe_push (state_t,heap, output_states_vect, state);
7294 /* Form and output vectors (comb, check, base or full vector)
7295 representing transition table of AUTOMATON. */
7297 output_trans_table (automaton_t automaton)
7301 vla_hwint_t transition_vect = 0;
7303 undefined_vect_el_value = automaton->achieved_states_num;
7304 automaton->trans_table = create_state_ainsn_table (automaton);
7305 /* Create vect of pointers to states ordered by num of transitions
7306 from the state (state with the maximum num is the first). */
7307 output_states_vect = 0;
7308 pass_states (automaton, add_states_vect_el);
7309 qsort (VEC_address (state_t, output_states_vect),
7310 VEC_length (state_t, output_states_vect),
7311 sizeof (state_t), compare_transition_els_num);
7313 for (i = 0; i < VEC_length (state_t, output_states_vect); i++)
7315 VEC_truncate (vect_el_t, transition_vect, 0);
7316 for (arc = first_out_arc (VEC_index (state_t, output_states_vect, i));
7318 arc = next_out_arc (arc))
7320 gcc_assert (arc->insn);
7321 if (arc->insn->first_ainsn_with_given_equivalence_num)
7322 add_vect_el (&transition_vect, arc->insn,
7323 arc->to_state->order_state_num);
7325 add_vect (automaton->trans_table,
7326 VEC_index (state_t, output_states_vect, i)->order_state_num,
7329 output_state_ainsn_table
7330 (automaton->trans_table, "state transitions",
7331 output_trans_full_vect_name, output_trans_comb_vect_name,
7332 output_trans_check_vect_name, output_trans_base_vect_name);
7334 VEC_free (state_t,heap, output_states_vect);
7335 VEC_free (vect_el_t,heap, transition_vect);
7338 /* The current number of passing states to find minimal issue delay
7339 value for an ainsn and state. */
7340 static int curr_state_pass_num;
7342 /* This recursive function passes states to find minimal issue delay
7343 value for AINSN. The state being visited is STATE. The function
7344 returns minimal issue delay value for AINSN in STATE or -1 if we
7345 enter into a loop. */
7347 min_issue_delay_pass_states (state_t state, ainsn_t ainsn)
7350 int min_insn_issue_delay, insn_issue_delay;
7352 if (state->state_pass_num == curr_state_pass_num
7353 || state->min_insn_issue_delay != -1)
7354 /* We've entered into a loop or already have the correct value for
7355 given state and ainsn. */
7356 return state->min_insn_issue_delay;
7357 state->state_pass_num = curr_state_pass_num;
7358 min_insn_issue_delay = -1;
7359 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
7360 if (arc->insn == ainsn)
7362 min_insn_issue_delay = 0;
7367 insn_issue_delay = min_issue_delay_pass_states (arc->to_state, ainsn);
7368 if (insn_issue_delay != -1)
7370 if (arc->insn->insn_reserv_decl
7371 == DECL_INSN_RESERV (advance_cycle_insn_decl))
7373 if (min_insn_issue_delay == -1
7374 || min_insn_issue_delay > insn_issue_delay)
7376 min_insn_issue_delay = insn_issue_delay;
7377 if (insn_issue_delay == 0)
7382 return min_insn_issue_delay;
7385 /* The function searches minimal issue delay value for AINSN in STATE.
7386 The function can return negative value if we can not issue AINSN. We
7387 will report about it later. */
7389 min_issue_delay (state_t state, ainsn_t ainsn)
7391 curr_state_pass_num++;
7392 state->min_insn_issue_delay = min_issue_delay_pass_states (state, ainsn);
7393 return state->min_insn_issue_delay;
7396 /* The function initiates code for finding minimal issue delay values.
7397 It should be called only once. */
7399 initiate_min_issue_delay_pass_states (void)
7401 curr_state_pass_num = 0;
7404 /* Form and output vectors representing minimal issue delay table of
7405 AUTOMATON. The table is state x ainsn -> minimal issue delay of
7408 output_min_issue_delay_table (automaton_t automaton)
7410 vla_hwint_t min_issue_delay_vect;
7411 vla_hwint_t compressed_min_issue_delay_vect;
7412 vect_el_t min_delay;
7414 size_t i, min_issue_delay_len;
7415 size_t compressed_min_issue_delay_len;
7418 /* Create vect of pointers to states ordered by num of transitions
7419 from the state (state with the maximum num is the first). */
7420 output_states_vect = 0;
7421 pass_states (automaton, add_states_vect_el);
7423 min_issue_delay_len = (VEC_length (state_t, output_states_vect)
7424 * automaton->insn_equiv_classes_num);
7425 min_issue_delay_vect = VEC_alloc (vect_el_t,heap, min_issue_delay_len);
7426 for (i = 0; i < min_issue_delay_len; i++)
7427 VEC_quick_push (vect_el_t, min_issue_delay_vect, 0);
7429 automaton->max_min_delay = 0;
7430 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
7431 if (ainsn->first_ainsn_with_given_equivalence_num)
7433 for (i = 0; i < VEC_length (state_t, output_states_vect); i++)
7434 VEC_index (state_t, output_states_vect, i)->min_insn_issue_delay = -1;
7435 for (i = 0; i < VEC_length (state_t, output_states_vect); i++)
7437 state_t s = VEC_index (state_t, output_states_vect, i);
7438 min_delay = min_issue_delay (s, ainsn);
7439 if (automaton->max_min_delay < min_delay)
7440 automaton->max_min_delay = min_delay;
7441 VEC_replace (vect_el_t, min_issue_delay_vect,
7443 * automaton->insn_equiv_classes_num
7444 + ainsn->insn_equiv_class_num,
7448 fprintf (output_file, "/* Vector of min issue delay of insns. */\n");
7449 fprintf (output_file, "static const ");
7450 output_range_type (output_file, 0, automaton->max_min_delay);
7451 fprintf (output_file, " ");
7452 output_min_issue_delay_vect_name (output_file, automaton);
7453 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7454 /* Compress the vector. */
7455 if (automaton->max_min_delay < 2)
7457 else if (automaton->max_min_delay < 4)
7459 else if (automaton->max_min_delay < 16)
7463 automaton->min_issue_delay_table_compression_factor = cfactor;
7465 compressed_min_issue_delay_len = (min_issue_delay_len+cfactor-1) / cfactor;
7466 compressed_min_issue_delay_vect
7467 = VEC_alloc (vect_el_t,heap, compressed_min_issue_delay_len);
7469 for (i = 0; i < compressed_min_issue_delay_len; i++)
7470 VEC_quick_push (vect_el_t, compressed_min_issue_delay_vect, 0);
7472 for (i = 0; i < min_issue_delay_len; i++)
7474 size_t ci = i / cfactor;
7475 vect_el_t x = VEC_index (vect_el_t, min_issue_delay_vect, i);
7476 vect_el_t cx = VEC_index (vect_el_t, compressed_min_issue_delay_vect, ci);
7478 cx |= x << (8 - (i % cfactor + 1) * (8 / cfactor));
7479 VEC_replace (vect_el_t, compressed_min_issue_delay_vect, ci, cx);
7481 output_vect (compressed_min_issue_delay_vect);
7482 fprintf (output_file, "};\n\n");
7483 VEC_free (state_t,heap, output_states_vect);
7484 VEC_free (vect_el_t,heap, min_issue_delay_vect);
7485 VEC_free (vect_el_t,heap, compressed_min_issue_delay_vect);
7488 /* Form and output vector representing the locked states of
7491 output_dead_lock_vect (automaton_t automaton)
7495 vla_hwint_t dead_lock_vect = 0;
7497 /* Create vect of pointers to states ordered by num of
7498 transitions from the state (state with the maximum num is the
7500 automaton->locked_states = 0;
7501 output_states_vect = 0;
7502 pass_states (automaton, add_states_vect_el);
7504 VEC_safe_grow (vect_el_t,heap, dead_lock_vect,
7505 VEC_length (state_t, output_states_vect));
7506 for (i = 0; i < VEC_length (state_t, output_states_vect); i++)
7508 state_t s = VEC_index (state_t, output_states_vect, i);
7509 arc = first_out_arc (s);
7511 if (next_out_arc (arc) == NULL
7512 && (arc->insn->insn_reserv_decl
7513 == DECL_INSN_RESERV (advance_cycle_insn_decl)))
7515 VEC_replace (vect_el_t, dead_lock_vect, s->order_state_num, 1);
7516 automaton->locked_states++;
7519 VEC_replace (vect_el_t, dead_lock_vect, s->order_state_num, 0);
7521 if (automaton->locked_states == 0)
7524 fprintf (output_file, "/* Vector for locked state flags. */\n");
7525 fprintf (output_file, "static const ");
7526 output_range_type (output_file, 0, 1);
7527 fprintf (output_file, " ");
7528 output_dead_lock_vect_name (output_file, automaton);
7529 fprintf (output_file, "[] = {\n");
7530 output_vect (dead_lock_vect);
7531 fprintf (output_file, "};\n\n");
7532 VEC_free (state_t,heap, output_states_vect);
7533 VEC_free (vect_el_t,heap, dead_lock_vect);
7536 /* Form and output vector representing reserved units of the states of
7539 output_reserved_units_table (automaton_t automaton)
7541 vla_hwint_t reserved_units_table = 0;
7542 int state_byte_size;
7543 int reserved_units_size;
7547 if (description->query_units_num == 0)
7550 /* Create vect of pointers to states. */
7551 output_states_vect = 0;
7552 pass_states (automaton, add_states_vect_el);
7553 /* Create vector. */
7554 state_byte_size = (description->query_units_num + 7) / 8;
7555 reserved_units_size = (VEC_length (state_t, output_states_vect)
7558 reserved_units_table = VEC_alloc (vect_el_t,heap, reserved_units_size);
7560 for (i = 0; i < reserved_units_size; i++)
7561 VEC_quick_push (vect_el_t, reserved_units_table, 0);
7562 for (n = 0; n < VEC_length (state_t, output_states_vect); n++)
7564 state_t s = VEC_index (state_t, output_states_vect, n);
7565 for (i = 0; i < description->units_num; i++)
7566 if (units_array [i]->query_p
7567 && first_cycle_unit_presence (s, i))
7569 int ri = (s->order_state_num * state_byte_size
7570 + units_array [i]->query_num / 8);
7571 vect_el_t x = VEC_index (vect_el_t, reserved_units_table, ri);
7573 x += 1 << (units_array [i]->query_num % 8);
7574 VEC_replace (vect_el_t, reserved_units_table, ri, x);
7577 fprintf (output_file, "\n#if %s\n", CPU_UNITS_QUERY_MACRO_NAME);
7578 fprintf (output_file, "/* Vector for reserved units of states. */\n");
7579 fprintf (output_file, "static const ");
7580 output_range_type (output_file, 0, 255);
7581 fprintf (output_file, " ");
7582 output_reserved_units_table_name (output_file, automaton);
7583 fprintf (output_file, "[] = {\n");
7584 output_vect (reserved_units_table);
7585 fprintf (output_file, "};\n#endif /* #if %s */\n\n",
7586 CPU_UNITS_QUERY_MACRO_NAME);
7588 VEC_free (state_t,heap, output_states_vect);
7589 VEC_free (vect_el_t,heap, reserved_units_table);
7592 /* The function outputs all tables representing DFA(s) used for fast
7593 pipeline hazards recognition. */
7595 output_tables (void)
7597 automaton_t automaton;
7599 initiate_min_issue_delay_pass_states ();
7600 for (automaton = description->first_automaton;
7602 automaton = automaton->next_automaton)
7604 output_translate_vect (automaton);
7605 output_trans_table (automaton);
7606 output_min_issue_delay_table (automaton);
7607 output_dead_lock_vect (automaton);
7608 output_reserved_units_table (automaton);
7610 fprintf (output_file, "\n#define %s %d\n\n", ADVANCE_CYCLE_VALUE_NAME,
7611 DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
7614 /* The function outputs definition and value of PHR interface variable
7615 `max_insn_queue_index'. Its value is not less than maximal queue
7616 length needed for the insn scheduler. */
7618 output_max_insn_queue_index_def (void)
7620 int i, max, latency;
7623 max = description->max_insn_reserv_cycles;
7624 for (i = 0; i < description->decls_num; i++)
7626 decl = description->decls [i];
7627 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
7629 latency = DECL_INSN_RESERV (decl)->default_latency;
7633 else if (decl->mode == dm_bypass)
7635 latency = DECL_BYPASS (decl)->latency;
7640 for (i = 0; (1 << i) <= max; i++)
7642 gcc_assert (i >= 0);
7643 fprintf (output_file, "\nconst int max_insn_queue_index = %d;\n\n",
7647 /* The function outputs switch cases for insn reservations using
7648 function *output_automata_list_code. */
7650 output_insn_code_cases (void (*output_automata_list_code)
7651 (automata_list_el_t))
7656 for (i = 0; i < description->decls_num; i++)
7658 decl = description->decls [i];
7659 if (decl->mode == dm_insn_reserv)
7660 DECL_INSN_RESERV (decl)->processed_p = FALSE;
7662 for (i = 0; i < description->decls_num; i++)
7664 decl = description->decls [i];
7665 if (decl->mode == dm_insn_reserv
7666 && !DECL_INSN_RESERV (decl)->processed_p)
7668 for (j = i; j < description->decls_num; j++)
7670 decl2 = description->decls [j];
7671 if (decl2->mode == dm_insn_reserv
7672 && (DECL_INSN_RESERV (decl2)->important_automata_list
7673 == DECL_INSN_RESERV (decl)->important_automata_list))
7675 DECL_INSN_RESERV (decl2)->processed_p = TRUE;
7676 fprintf (output_file, " case %d: /* %s */\n",
7677 DECL_INSN_RESERV (decl2)->insn_num,
7678 DECL_INSN_RESERV (decl2)->name);
7681 (*output_automata_list_code)
7682 (DECL_INSN_RESERV (decl)->important_automata_list);
7688 /* The function outputs a code for evaluation of a minimal delay of
7689 issue of insns which have reservations in given AUTOMATA_LIST. */
7691 output_automata_list_min_issue_delay_code (automata_list_el_t automata_list)
7693 automata_list_el_t el;
7694 automaton_t automaton;
7696 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
7698 automaton = el->automaton;
7699 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
7700 output_min_issue_delay_vect_name (output_file, automaton);
7701 fprintf (output_file,
7702 (automaton->min_issue_delay_table_compression_factor != 1
7704 output_translate_vect_name (output_file, automaton);
7705 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
7706 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7707 output_chip_member_name (output_file, automaton);
7708 fprintf (output_file, " * %d", automaton->insn_equiv_classes_num);
7709 if (automaton->min_issue_delay_table_compression_factor == 1)
7710 fprintf (output_file, "];\n");
7713 fprintf (output_file, ") / %d];\n",
7714 automaton->min_issue_delay_table_compression_factor);
7715 fprintf (output_file, " %s = (%s >> (8 - (",
7716 TEMPORARY_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
7717 output_translate_vect_name (output_file, automaton);
7719 (output_file, " [%s] %% %d + 1) * %d)) & %d;\n",
7720 INTERNAL_INSN_CODE_NAME,
7721 automaton->min_issue_delay_table_compression_factor,
7722 8 / automaton->min_issue_delay_table_compression_factor,
7723 (1 << (8 / automaton->min_issue_delay_table_compression_factor))
7726 if (el == automata_list)
7727 fprintf (output_file, " %s = %s;\n",
7728 RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
7731 fprintf (output_file, " if (%s > %s)\n",
7732 TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
7733 fprintf (output_file, " %s = %s;\n",
7734 RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
7737 fprintf (output_file, " break;\n\n");
7740 /* Output function `internal_min_issue_delay'. */
7742 output_internal_min_issue_delay_func (void)
7744 fprintf (output_file,
7745 "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
7746 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7747 CHIP_NAME, CHIP_PARAMETER_NAME);
7748 fprintf (output_file, "{\n int %s ATTRIBUTE_UNUSED;\n int %s = -1;\n",
7749 TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
7750 fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
7751 output_insn_code_cases (output_automata_list_min_issue_delay_code);
7752 fprintf (output_file,
7753 "\n default:\n %s = -1;\n break;\n }\n",
7754 RESULT_VARIABLE_NAME);
7755 fprintf (output_file, " return %s;\n", RESULT_VARIABLE_NAME);
7756 fprintf (output_file, "}\n\n");
7759 /* The function outputs a code changing state after issue of insns
7760 which have reservations in given AUTOMATA_LIST. */
7762 output_automata_list_transition_code (automata_list_el_t automata_list)
7764 automata_list_el_t el, next_el;
7766 fprintf (output_file, " {\n");
7767 if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
7768 for (el = automata_list;; el = next_el)
7770 next_el = el->next_automata_list_el;
7771 if (next_el == NULL)
7773 fprintf (output_file, " ");
7774 output_state_member_type (output_file, el->automaton);
7775 fprintf (output_file, " ");
7776 output_temp_chip_member_name (output_file, el->automaton);
7777 fprintf (output_file, ";\n");
7779 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
7780 if (comb_vect_p (el->automaton->trans_table))
7782 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
7783 output_trans_base_vect_name (output_file, el->automaton);
7784 fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
7785 output_chip_member_name (output_file, el->automaton);
7786 fprintf (output_file, "] + ");
7787 output_translate_vect_name (output_file, el->automaton);
7788 fprintf (output_file, " [%s];\n", INTERNAL_INSN_CODE_NAME);
7789 fprintf (output_file, " if (");
7790 output_trans_check_vect_name (output_file, el->automaton);
7791 fprintf (output_file, " [%s] != %s->",
7792 TEMPORARY_VARIABLE_NAME, CHIP_PARAMETER_NAME);
7793 output_chip_member_name (output_file, el->automaton);
7794 fprintf (output_file, ")\n");
7795 fprintf (output_file, " return %s (%s, %s);\n",
7796 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7797 CHIP_PARAMETER_NAME);
7798 fprintf (output_file, " else\n");
7799 fprintf (output_file, " ");
7800 if (el->next_automata_list_el != NULL)
7801 output_temp_chip_member_name (output_file, el->automaton);
7804 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7805 output_chip_member_name (output_file, el->automaton);
7807 fprintf (output_file, " = ");
7808 output_trans_comb_vect_name (output_file, el->automaton);
7809 fprintf (output_file, " [%s];\n", TEMPORARY_VARIABLE_NAME);
7813 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
7814 output_trans_full_vect_name (output_file, el->automaton);
7815 fprintf (output_file, " [");
7816 output_translate_vect_name (output_file, el->automaton);
7817 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
7818 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7819 output_chip_member_name (output_file, el->automaton);
7820 fprintf (output_file, " * %d];\n",
7821 el->automaton->insn_equiv_classes_num);
7822 fprintf (output_file, " if (%s >= %d)\n",
7823 TEMPORARY_VARIABLE_NAME, el->automaton->achieved_states_num);
7824 fprintf (output_file, " return %s (%s, %s);\n",
7825 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7826 CHIP_PARAMETER_NAME);
7827 fprintf (output_file, " else\n ");
7828 if (el->next_automata_list_el != NULL)
7829 output_temp_chip_member_name (output_file, el->automaton);
7832 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7833 output_chip_member_name (output_file, el->automaton);
7835 fprintf (output_file, " = %s;\n", TEMPORARY_VARIABLE_NAME);
7837 if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
7838 for (el = automata_list;; el = next_el)
7840 next_el = el->next_automata_list_el;
7841 if (next_el == NULL)
7843 fprintf (output_file, " %s->", CHIP_PARAMETER_NAME);
7844 output_chip_member_name (output_file, el->automaton);
7845 fprintf (output_file, " = ");
7846 output_temp_chip_member_name (output_file, el->automaton);
7847 fprintf (output_file, ";\n");
7849 fprintf (output_file, " return -1;\n");
7850 fprintf (output_file, " }\n");
7853 /* Output function `internal_state_transition'. */
7855 output_internal_trans_func (void)
7857 fprintf (output_file,
7858 "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
7859 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7860 CHIP_NAME, CHIP_PARAMETER_NAME);
7861 fprintf (output_file, "{\n int %s ATTRIBUTE_UNUSED;\n", TEMPORARY_VARIABLE_NAME);
7862 fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
7863 output_insn_code_cases (output_automata_list_transition_code);
7864 fprintf (output_file, "\n default:\n return -1;\n }\n");
7865 fprintf (output_file, "}\n\n");
7872 insn_code = dfa_insn_code (insn);
7873 if (insn_code > DFA__ADVANCE_CYCLE)
7877 insn_code = DFA__ADVANCE_CYCLE;
7879 where insn denotes INSN_NAME, insn_code denotes INSN_CODE_NAME, and
7880 code denotes CODE. */
7882 output_internal_insn_code_evaluation (const char *insn_name,
7883 const char *insn_code_name,
7886 fprintf (output_file, "\n if (%s != 0)\n {\n", insn_name);
7887 fprintf (output_file, " %s = %s (%s);\n", insn_code_name,
7888 DFA_INSN_CODE_FUNC_NAME, insn_name);
7889 fprintf (output_file, " if (%s > %s)\n return %d;\n",
7890 insn_code_name, ADVANCE_CYCLE_VALUE_NAME, code);
7891 fprintf (output_file, " }\n else\n %s = %s;\n\n",
7892 insn_code_name, ADVANCE_CYCLE_VALUE_NAME);
7896 /* This function outputs `dfa_insn_code' and its helper function
7897 `dfa_insn_code_enlarge'. */
7899 output_dfa_insn_code_func (void)
7901 /* Emacs c-mode gets really confused if there's a { or } in column 0
7902 inside a string, so don't do that. */
7903 fprintf (output_file, "\
7905 dfa_insn_code_enlarge (int uid)\n\
7909 %s = xrealloc (%s,\n\
7910 %s * sizeof(int));\n\
7911 for (; i < %s; i++)\n\
7912 %s[i] = -1;\n}\n\n",
7913 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
7914 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
7915 DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
7916 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
7917 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
7918 DFA_INSN_CODES_VARIABLE_NAME);
7919 fprintf (output_file, "\
7920 static inline int\n%s (rtx %s)\n\
7922 int uid = INSN_UID (%s);\n\
7924 DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME,
7925 INSN_PARAMETER_NAME, INTERNAL_INSN_CODE_NAME);
7927 fprintf (output_file,
7928 " if (uid >= %s)\n dfa_insn_code_enlarge (uid);\n\n",
7929 DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
7930 fprintf (output_file, " %s = %s[uid];\n",
7931 INTERNAL_INSN_CODE_NAME, DFA_INSN_CODES_VARIABLE_NAME);
7932 fprintf (output_file, "\
7938 INTERNAL_INSN_CODE_NAME,
7939 INTERNAL_INSN_CODE_NAME,
7940 INTERNAL_DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME,
7941 DFA_INSN_CODES_VARIABLE_NAME, INTERNAL_INSN_CODE_NAME);
7942 fprintf (output_file, " return %s;\n}\n\n", INTERNAL_INSN_CODE_NAME);
7945 /* The function outputs PHR interface function `state_transition'. */
7947 output_trans_func (void)
7949 fprintf (output_file, "int\n%s (%s %s, rtx %s)\n",
7950 TRANSITION_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME,
7951 INSN_PARAMETER_NAME);
7952 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
7953 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
7954 INTERNAL_INSN_CODE_NAME, -1);
7955 fprintf (output_file, " return %s (%s, %s);\n}\n\n",
7956 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, STATE_NAME);
7959 /* Output function `min_issue_delay'. */
7961 output_min_issue_delay_func (void)
7963 fprintf (output_file, "int\n%s (%s %s, rtx %s)\n",
7964 MIN_ISSUE_DELAY_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME,
7965 INSN_PARAMETER_NAME);
7966 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
7967 fprintf (output_file, "\n if (%s != 0)\n {\n", INSN_PARAMETER_NAME);
7968 fprintf (output_file, " %s = %s (%s);\n", INTERNAL_INSN_CODE_NAME,
7969 DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME);
7970 fprintf (output_file, " if (%s > %s)\n return 0;\n",
7971 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
7972 fprintf (output_file, " }\n else\n %s = %s;\n",
7973 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
7974 fprintf (output_file, "\n return %s (%s, %s);\n",
7975 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7977 fprintf (output_file, "}\n\n");
7980 /* Output function `internal_dead_lock'. */
7982 output_internal_dead_lock_func (void)
7984 automaton_t automaton;
7986 fprintf (output_file, "static int\n%s (struct %s *ARG_UNUSED (%s))\n",
7987 INTERNAL_DEAD_LOCK_FUNC_NAME, CHIP_NAME, CHIP_PARAMETER_NAME);
7988 fprintf (output_file, "{\n");
7989 for (automaton = description->first_automaton;
7991 automaton = automaton->next_automaton)
7992 if (automaton->locked_states)
7994 fprintf (output_file, " if (");
7995 output_dead_lock_vect_name (output_file, automaton);
7996 fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
7997 output_chip_member_name (output_file, automaton);
7998 fprintf (output_file, "])\n return 1/* TRUE */;\n");
8000 fprintf (output_file, " return 0/* FALSE */;\n}\n\n");
8003 /* The function outputs PHR interface function `state_dead_lock_p'. */
8005 output_dead_lock_func (void)
8007 fprintf (output_file, "int\n%s (%s %s)\n",
8008 DEAD_LOCK_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME);
8009 fprintf (output_file, "{\n return %s (%s);\n}\n\n",
8010 INTERNAL_DEAD_LOCK_FUNC_NAME, STATE_NAME);
8013 /* Output function `internal_reset'. */
8015 output_internal_reset_func (void)
8017 fprintf (output_file, "static inline void\n%s (struct %s *%s)\n",
8018 INTERNAL_RESET_FUNC_NAME, CHIP_NAME, CHIP_PARAMETER_NAME);
8019 fprintf (output_file, "{\n memset (%s, 0, sizeof (struct %s));\n}\n\n",
8020 CHIP_PARAMETER_NAME, CHIP_NAME);
8023 /* The function outputs PHR interface function `state_size'. */
8025 output_size_func (void)
8027 fprintf (output_file, "int\n%s (void)\n", SIZE_FUNC_NAME);
8028 fprintf (output_file, "{\n return sizeof (struct %s);\n}\n\n", CHIP_NAME);
8031 /* The function outputs PHR interface function `state_reset'. */
8033 output_reset_func (void)
8035 fprintf (output_file, "void\n%s (%s %s)\n",
8036 RESET_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME);
8037 fprintf (output_file, "{\n %s (%s);\n}\n\n", INTERNAL_RESET_FUNC_NAME,
8041 /* Output function `min_insn_conflict_delay'. */
8043 output_min_insn_conflict_delay_func (void)
8045 fprintf (output_file,
8046 "int\n%s (%s %s, rtx %s, rtx %s)\n",
8047 MIN_INSN_CONFLICT_DELAY_FUNC_NAME, STATE_TYPE_NAME,
8048 STATE_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8049 fprintf (output_file, "{\n struct %s %s;\n int %s, %s, transition;\n",
8050 CHIP_NAME, CHIP_NAME, INTERNAL_INSN_CODE_NAME,
8051 INTERNAL_INSN2_CODE_NAME);
8052 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8053 INTERNAL_INSN_CODE_NAME, 0);
8054 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
8055 INTERNAL_INSN2_CODE_NAME, 0);
8056 fprintf (output_file, " memcpy (&%s, %s, sizeof (%s));\n",
8057 CHIP_NAME, STATE_NAME, CHIP_NAME);
8058 fprintf (output_file, " %s (&%s);\n", INTERNAL_RESET_FUNC_NAME, CHIP_NAME);
8059 fprintf (output_file, " transition = %s (%s, &%s);\n",
8060 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME);
8061 fprintf (output_file, " gcc_assert (transition <= 0);\n");
8062 fprintf (output_file, " return %s (%s, &%s);\n",
8063 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN2_CODE_NAME,
8065 fprintf (output_file, "}\n\n");
8068 /* Output function `internal_insn_latency'. */
8070 output_internal_insn_latency_func (void)
8073 struct bypass_decl *bypass;
8075 const char *tabletype = "unsigned char";
8077 /* Find the smallest integer type that can hold all the default
8079 for (i = 0; i < description->decls_num; i++)
8080 if (description->decls[i]->mode == dm_insn_reserv)
8082 decl = description->decls[i];
8083 if (DECL_INSN_RESERV (decl)->default_latency > UCHAR_MAX
8084 && tabletype[0] != 'i') /* Don't shrink it. */
8085 tabletype = "unsigned short";
8086 if (DECL_INSN_RESERV (decl)->default_latency > USHRT_MAX)
8090 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",
8091 INTERNAL_INSN_LATENCY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8092 INTERNAL_INSN2_CODE_NAME, INSN_PARAMETER_NAME,
8093 INSN2_PARAMETER_NAME);
8094 fprintf (output_file, "{\n");
8096 if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8098 fputs (" return 0;\n}\n\n", output_file);
8102 fprintf (output_file, " static const %s default_latencies[] =\n {",
8105 for (i = 0, j = 0, col = 7; i < description->decls_num; i++)
8106 if (description->decls[i]->mode == dm_insn_reserv
8107 && description->decls[i] != advance_cycle_insn_decl)
8109 if ((col = (col+1) % 8) == 0)
8110 fputs ("\n ", output_file);
8111 decl = description->decls[i];
8112 gcc_assert (j++ == DECL_INSN_RESERV (decl)->insn_num);
8113 fprintf (output_file, "% 4d,",
8114 DECL_INSN_RESERV (decl)->default_latency);
8116 gcc_assert (j == DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
8117 fputs ("\n };\n", output_file);
8119 fprintf (output_file, " if (%s >= %s || %s >= %s)\n return 0;\n",
8120 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8121 INTERNAL_INSN2_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8123 fprintf (output_file, " switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8124 for (i = 0; i < description->decls_num; i++)
8125 if (description->decls[i]->mode == dm_insn_reserv
8126 && DECL_INSN_RESERV (description->decls[i])->bypass_list)
8128 decl = description->decls [i];
8129 fprintf (output_file,
8130 " case %d:\n switch (%s)\n {\n",
8131 DECL_INSN_RESERV (decl)->insn_num,
8132 INTERNAL_INSN2_CODE_NAME);
8133 for (bypass = DECL_INSN_RESERV (decl)->bypass_list;
8135 bypass = bypass->next)
8137 gcc_assert (bypass->in_insn_reserv->insn_num
8138 != (DECL_INSN_RESERV
8139 (advance_cycle_insn_decl)->insn_num));
8140 fprintf (output_file, " case %d:\n",
8141 bypass->in_insn_reserv->insn_num);
8142 if (bypass->bypass_guard_name == NULL)
8143 fprintf (output_file, " return %d;\n",
8147 fprintf (output_file,
8148 " if (%s (%s, %s))\n",
8149 bypass->bypass_guard_name, INSN_PARAMETER_NAME,
8150 INSN2_PARAMETER_NAME);
8151 fprintf (output_file,
8152 " return %d;\n break;\n",
8156 fputs (" }\n break;\n", output_file);
8159 fprintf (output_file, " }\n return default_latencies[%s];\n}\n\n",
8160 INTERNAL_INSN_CODE_NAME);
8163 /* The function outputs PHR interface function `insn_latency'. */
8165 output_insn_latency_func (void)
8167 fprintf (output_file, "int\n%s (rtx %s, rtx %s)\n",
8168 INSN_LATENCY_FUNC_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8169 fprintf (output_file, "{\n int %s, %s;\n",
8170 INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME);
8171 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8172 INTERNAL_INSN_CODE_NAME, 0);
8173 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
8174 INTERNAL_INSN2_CODE_NAME, 0);
8175 fprintf (output_file, " return %s (%s, %s, %s, %s);\n}\n\n",
8176 INTERNAL_INSN_LATENCY_FUNC_NAME,
8177 INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME,
8178 INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8181 /* The function outputs PHR interface function `print_reservation'. */
8183 output_print_reservation_func (void)
8188 fprintf (output_file,
8189 "void\n%s (FILE *%s, rtx %s ATTRIBUTE_UNUSED)\n{\n",
8190 PRINT_RESERVATION_FUNC_NAME, FILE_PARAMETER_NAME,
8191 INSN_PARAMETER_NAME);
8193 if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8195 fprintf (output_file, " fputs (\"%s\", %s);\n}\n\n",
8196 NOTHING_NAME, FILE_PARAMETER_NAME);
8201 fputs (" static const char *const reservation_names[] =\n {",
8204 for (i = 0, j = 0; i < description->decls_num; i++)
8206 decl = description->decls [i];
8207 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
8209 gcc_assert (j == DECL_INSN_RESERV (decl)->insn_num);
8212 fprintf (output_file, "\n \"%s\",",
8213 regexp_representation (DECL_INSN_RESERV (decl)->regexp));
8214 finish_regexp_representation ();
8217 gcc_assert (j == DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
8219 fprintf (output_file, "\n \"%s\"\n };\n int %s;\n\n",
8220 NOTHING_NAME, INTERNAL_INSN_CODE_NAME);
8222 fprintf (output_file, " if (%s == 0)\n %s = %s;\n",
8223 INSN_PARAMETER_NAME,
8224 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8225 fprintf (output_file, " else\n\
8231 INTERNAL_INSN_CODE_NAME, DFA_INSN_CODE_FUNC_NAME,
8232 INSN_PARAMETER_NAME,
8233 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8234 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8236 fprintf (output_file, " fputs (reservation_names[%s], %s);\n}\n\n",
8237 INTERNAL_INSN_CODE_NAME, FILE_PARAMETER_NAME);
8240 /* The following function is used to sort unit declaration by their
8243 units_cmp (const void *unit1, const void *unit2)
8245 const_unit_decl_t const u1 = *(const_unit_decl_t const*) unit1;
8246 const_unit_decl_t const u2 = *(const_unit_decl_t const*) unit2;
8248 return strcmp (u1->name, u2->name);
8251 /* The following macro value is name of struct containing unit name
8253 #define NAME_CODE_STRUCT_NAME "name_code"
8255 /* The following macro value is name of table of struct name_code. */
8256 #define NAME_CODE_TABLE_NAME "name_code_table"
8258 /* The following macro values are member names for struct name_code. */
8259 #define NAME_MEMBER_NAME "name"
8260 #define CODE_MEMBER_NAME "code"
8262 /* The following macro values are local variable names for function
8263 `get_cpu_unit_code'. */
8264 #define CMP_VARIABLE_NAME "cmp"
8265 #define LOW_VARIABLE_NAME "l"
8266 #define MIDDLE_VARIABLE_NAME "m"
8267 #define HIGH_VARIABLE_NAME "h"
8269 /* The following function outputs function to obtain internal cpu unit
8270 code by the cpu unit name. */
8272 output_get_cpu_unit_code_func (void)
8277 fprintf (output_file, "int\n%s (const char *%s)\n",
8278 GET_CPU_UNIT_CODE_FUNC_NAME, CPU_UNIT_NAME_PARAMETER_NAME);
8279 fprintf (output_file, "{\n struct %s {const char *%s; int %s;};\n",
8280 NAME_CODE_STRUCT_NAME, NAME_MEMBER_NAME, CODE_MEMBER_NAME);
8281 fprintf (output_file, " int %s, %s, %s, %s;\n", CMP_VARIABLE_NAME,
8282 LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8283 fprintf (output_file, " static struct %s %s [] =\n {\n",
8284 NAME_CODE_STRUCT_NAME, NAME_CODE_TABLE_NAME);
8285 units = xmalloc (sizeof (unit_decl_t) * description->units_num);
8286 memcpy (units, units_array, sizeof (unit_decl_t) * description->units_num);
8287 qsort (units, description->units_num, sizeof (unit_decl_t), units_cmp);
8288 for (i = 0; i < description->units_num; i++)
8289 if (units [i]->query_p)
8290 fprintf (output_file, " {\"%s\", %d},\n",
8291 units[i]->name, units[i]->query_num);
8292 fprintf (output_file, " };\n\n");
8293 fprintf (output_file, " /* The following is binary search: */\n");
8294 fprintf (output_file, " %s = 0;\n", LOW_VARIABLE_NAME);
8295 fprintf (output_file, " %s = sizeof (%s) / sizeof (struct %s) - 1;\n",
8296 HIGH_VARIABLE_NAME, NAME_CODE_TABLE_NAME, NAME_CODE_STRUCT_NAME);
8297 fprintf (output_file, " while (%s <= %s)\n {\n",
8298 LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8299 fprintf (output_file, " %s = (%s + %s) / 2;\n",
8300 MIDDLE_VARIABLE_NAME, LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8301 fprintf (output_file, " %s = strcmp (%s, %s [%s].%s);\n",
8302 CMP_VARIABLE_NAME, CPU_UNIT_NAME_PARAMETER_NAME,
8303 NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, NAME_MEMBER_NAME);
8304 fprintf (output_file, " if (%s < 0)\n", CMP_VARIABLE_NAME);
8305 fprintf (output_file, " %s = %s - 1;\n",
8306 HIGH_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
8307 fprintf (output_file, " else if (%s > 0)\n", CMP_VARIABLE_NAME);
8308 fprintf (output_file, " %s = %s + 1;\n",
8309 LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
8310 fprintf (output_file, " else\n");
8311 fprintf (output_file, " return %s [%s].%s;\n }\n",
8312 NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, CODE_MEMBER_NAME);
8313 fprintf (output_file, " return -1;\n}\n\n");
8317 /* The following function outputs function to check reservation of cpu
8318 unit (its internal code will be passed as the function argument) in
8321 output_cpu_unit_reservation_p (void)
8323 automaton_t automaton;
8325 fprintf (output_file, "int\n%s (%s %s, int %s)\n",
8326 CPU_UNIT_RESERVATION_P_FUNC_NAME,
8327 STATE_TYPE_NAME, STATE_NAME,
8328 CPU_CODE_PARAMETER_NAME);
8329 fprintf (output_file, "{\n gcc_assert (%s >= 0 && %s < %d);\n",
8330 CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME,
8331 description->query_units_num);
8332 if (description->query_units_num > 0)
8333 for (automaton = description->first_automaton;
8335 automaton = automaton->next_automaton)
8337 fprintf (output_file, " if ((");
8338 output_reserved_units_table_name (output_file, automaton);
8339 fprintf (output_file, " [((struct %s *) %s)->", CHIP_NAME, STATE_NAME);
8340 output_chip_member_name (output_file, automaton);
8341 fprintf (output_file, " * %d + %s / 8] >> (%s %% 8)) & 1)\n",
8342 (description->query_units_num + 7) / 8,
8343 CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME);
8344 fprintf (output_file, " return 1;\n");
8346 fprintf (output_file, " return 0;\n}\n\n");
8349 /* The function outputs PHR interface functions `dfa_clean_insn_cache'
8350 and 'dfa_clear_single_insn_cache'. */
8352 output_dfa_clean_insn_cache_func (void)
8354 fprintf (output_file,
8355 "void\n%s (void)\n{\n int %s;\n\n",
8356 DFA_CLEAN_INSN_CACHE_FUNC_NAME, I_VARIABLE_NAME);
8357 fprintf (output_file,
8358 " for (%s = 0; %s < %s; %s++)\n %s [%s] = -1;\n}\n\n",
8359 I_VARIABLE_NAME, I_VARIABLE_NAME,
8360 DFA_INSN_CODES_LENGTH_VARIABLE_NAME, I_VARIABLE_NAME,
8361 DFA_INSN_CODES_VARIABLE_NAME, I_VARIABLE_NAME);
8363 fprintf (output_file,
8364 "void\n%s (rtx %s)\n{\n int %s;\n\n",
8365 DFA_CLEAR_SINGLE_INSN_CACHE_FUNC_NAME, INSN_PARAMETER_NAME,
8367 fprintf (output_file,
8368 " %s = INSN_UID (%s);\n if (%s < %s)\n %s [%s] = -1;\n}\n\n",
8369 I_VARIABLE_NAME, INSN_PARAMETER_NAME, I_VARIABLE_NAME,
8370 DFA_INSN_CODES_LENGTH_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
8374 /* The function outputs PHR interface function `dfa_start'. */
8376 output_dfa_start_func (void)
8378 fprintf (output_file,
8379 "void\n%s (void)\n{\n %s = get_max_uid ();\n",
8380 DFA_START_FUNC_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8381 fprintf (output_file, " %s = xmalloc (%s * sizeof (int));\n",
8382 DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8383 fprintf (output_file, " %s ();\n}\n\n", DFA_CLEAN_INSN_CACHE_FUNC_NAME);
8386 /* The function outputs PHR interface function `dfa_finish'. */
8388 output_dfa_finish_func (void)
8390 fprintf (output_file, "void\n%s (void)\n{\n free (%s);\n}\n\n",
8391 DFA_FINISH_FUNC_NAME, DFA_INSN_CODES_VARIABLE_NAME);
8396 /* The page contains code for output description file (readable
8397 representation of original description and generated DFA(s). */
8399 /* The function outputs string representation of IR reservation. */
8401 output_regexp (regexp_t regexp)
8403 fprintf (output_description_file, "%s", regexp_representation (regexp));
8404 finish_regexp_representation ();
8407 /* Output names of units in LIST separated by comma. */
8409 output_unit_set_el_list (unit_set_el_t list)
8413 for (el = list; el != NULL; el = el->next_unit_set_el)
8416 fprintf (output_description_file, ", ");
8417 fprintf (output_description_file, "%s", el->unit_decl->name);
8421 /* Output patterns in LIST separated by comma. */
8423 output_pattern_set_el_list (pattern_set_el_t list)
8425 pattern_set_el_t el;
8428 for (el = list; el != NULL; el = el->next_pattern_set_el)
8431 fprintf (output_description_file, ", ");
8432 for (i = 0; i < el->units_num; i++)
8433 fprintf (output_description_file, (i == 0 ? "%s" : " %s"),
8434 el->unit_decls [i]->name);
8438 /* The function outputs string representation of IR define_reservation
8439 and define_insn_reservation. */
8441 output_description (void)
8446 for (i = 0; i < description->decls_num; i++)
8448 decl = description->decls [i];
8449 if (decl->mode == dm_unit)
8451 if (DECL_UNIT (decl)->excl_list != NULL)
8453 fprintf (output_description_file, "unit %s exlusion_set: ",
8454 DECL_UNIT (decl)->name);
8455 output_unit_set_el_list (DECL_UNIT (decl)->excl_list);
8456 fprintf (output_description_file, "\n");
8458 if (DECL_UNIT (decl)->presence_list != NULL)
8460 fprintf (output_description_file, "unit %s presence_set: ",
8461 DECL_UNIT (decl)->name);
8462 output_pattern_set_el_list (DECL_UNIT (decl)->presence_list);
8463 fprintf (output_description_file, "\n");
8465 if (DECL_UNIT (decl)->final_presence_list != NULL)
8467 fprintf (output_description_file, "unit %s final_presence_set: ",
8468 DECL_UNIT (decl)->name);
8469 output_pattern_set_el_list
8470 (DECL_UNIT (decl)->final_presence_list);
8471 fprintf (output_description_file, "\n");
8473 if (DECL_UNIT (decl)->absence_list != NULL)
8475 fprintf (output_description_file, "unit %s absence_set: ",
8476 DECL_UNIT (decl)->name);
8477 output_pattern_set_el_list (DECL_UNIT (decl)->absence_list);
8478 fprintf (output_description_file, "\n");
8480 if (DECL_UNIT (decl)->final_absence_list != NULL)
8482 fprintf (output_description_file, "unit %s final_absence_set: ",
8483 DECL_UNIT (decl)->name);
8484 output_pattern_set_el_list
8485 (DECL_UNIT (decl)->final_absence_list);
8486 fprintf (output_description_file, "\n");
8490 fprintf (output_description_file, "\n");
8491 for (i = 0; i < description->decls_num; i++)
8493 decl = description->decls [i];
8494 if (decl->mode == dm_reserv)
8496 fprintf (output_description_file, "reservation %s: ",
8497 DECL_RESERV (decl)->name);
8498 output_regexp (DECL_RESERV (decl)->regexp);
8499 fprintf (output_description_file, "\n");
8501 else if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
8503 fprintf (output_description_file, "insn reservation %s ",
8504 DECL_INSN_RESERV (decl)->name);
8505 print_rtl (output_description_file,
8506 DECL_INSN_RESERV (decl)->condexp);
8507 fprintf (output_description_file, ": ");
8508 output_regexp (DECL_INSN_RESERV (decl)->regexp);
8509 fprintf (output_description_file, "\n");
8511 else if (decl->mode == dm_bypass)
8512 fprintf (output_description_file, "bypass %d %s %s\n",
8513 DECL_BYPASS (decl)->latency,
8514 DECL_BYPASS (decl)->out_insn_name,
8515 DECL_BYPASS (decl)->in_insn_name);
8517 fprintf (output_description_file, "\n\f\n");
8520 /* The function outputs name of AUTOMATON. */
8522 output_automaton_name (FILE *f, automaton_t automaton)
8524 if (automaton->corresponding_automaton_decl == NULL)
8525 fprintf (f, "#%d", automaton->automaton_order_num);
8527 fprintf (f, "`%s'", automaton->corresponding_automaton_decl->name);
8530 /* Maximal length of line for pretty printing into description
8532 #define MAX_LINE_LENGTH 70
8534 /* The function outputs units name belonging to AUTOMATON. */
8536 output_automaton_units (automaton_t automaton)
8540 int curr_line_length;
8541 int there_is_an_automaton_unit;
8544 fprintf (output_description_file, "\n Corresponding units:\n");
8545 fprintf (output_description_file, " ");
8546 curr_line_length = 4;
8547 there_is_an_automaton_unit = 0;
8548 for (i = 0; i < description->decls_num; i++)
8550 decl = description->decls [i];
8551 if (decl->mode == dm_unit
8552 && (DECL_UNIT (decl)->corresponding_automaton_num
8553 == automaton->automaton_order_num))
8555 there_is_an_automaton_unit = 1;
8556 name = DECL_UNIT (decl)->name;
8557 if (curr_line_length + strlen (name) + 1 > MAX_LINE_LENGTH )
8559 curr_line_length = strlen (name) + 4;
8560 fprintf (output_description_file, "\n ");
8564 curr_line_length += strlen (name) + 1;
8565 fprintf (output_description_file, " ");
8567 fprintf (output_description_file, "%s", name);
8570 if (!there_is_an_automaton_unit)
8571 fprintf (output_description_file, "<None>");
8572 fprintf (output_description_file, "\n\n");
8575 /* The following variable is used for forming array of all possible cpu unit
8576 reservations described by the current DFA state. */
8577 static VEC(reserv_sets_t,heap) *state_reservs;
8579 /* The function forms `state_reservs' for STATE. */
8581 add_state_reservs (state_t state)
8583 alt_state_t curr_alt_state;
8585 if (state->component_states != NULL)
8586 for (curr_alt_state = state->component_states;
8587 curr_alt_state != NULL;
8588 curr_alt_state = curr_alt_state->next_sorted_alt_state)
8589 add_state_reservs (curr_alt_state->state);
8591 VEC_safe_push (reserv_sets_t,heap, state_reservs, state->reservs);
8594 /* The function outputs readable representation of all out arcs of
8597 output_state_arcs (state_t state)
8601 const char *insn_name;
8602 int curr_line_length;
8604 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
8607 gcc_assert (ainsn->first_insn_with_same_reservs);
8608 fprintf (output_description_file, " ");
8609 curr_line_length = 7;
8610 fprintf (output_description_file, "%2d: ", ainsn->insn_equiv_class_num);
8613 insn_name = ainsn->insn_reserv_decl->name;
8614 if (curr_line_length + strlen (insn_name) > MAX_LINE_LENGTH)
8616 if (ainsn != arc->insn)
8618 fprintf (output_description_file, ",\n ");
8619 curr_line_length = strlen (insn_name) + 6;
8622 curr_line_length += strlen (insn_name);
8626 curr_line_length += strlen (insn_name);
8627 if (ainsn != arc->insn)
8629 curr_line_length += 2;
8630 fprintf (output_description_file, ", ");
8633 fprintf (output_description_file, "%s", insn_name);
8634 ainsn = ainsn->next_same_reservs_insn;
8636 while (ainsn != NULL);
8637 fprintf (output_description_file, " %d \n",
8638 arc->to_state->order_state_num);
8640 fprintf (output_description_file, "\n");
8643 /* The following function is used for sorting possible cpu unit
8644 reservation of a DFA state. */
8646 state_reservs_cmp (const void *reservs_ptr_1, const void *reservs_ptr_2)
8648 return reserv_sets_cmp (*(const_reserv_sets_t const*) reservs_ptr_1,
8649 *(const_reserv_sets_t const*) reservs_ptr_2);
8652 /* The following function is used for sorting possible cpu unit
8653 reservation of a DFA state. */
8655 remove_state_duplicate_reservs (void)
8659 for (i = 1, j = 0; i < VEC_length (reserv_sets_t, state_reservs); i++)
8660 if (reserv_sets_cmp (VEC_index (reserv_sets_t, state_reservs, j),
8661 VEC_index (reserv_sets_t, state_reservs, i)))
8664 VEC_replace (reserv_sets_t, state_reservs, j,
8665 VEC_index (reserv_sets_t, state_reservs, i));
8667 VEC_truncate (reserv_sets_t, state_reservs, j + 1);
8670 /* The following function output readable representation of DFA(s)
8671 state used for fast recognition of pipeline hazards. State is
8672 described by possible (current and scheduled) cpu unit
8675 output_state (state_t state)
8681 fprintf (output_description_file, " State #%d", state->order_state_num);
8682 fprintf (output_description_file,
8683 state->new_cycle_p ? " (new cycle)\n" : "\n");
8684 add_state_reservs (state);
8685 qsort (VEC_address (reserv_sets_t, state_reservs),
8686 VEC_length (reserv_sets_t, state_reservs),
8687 sizeof (reserv_sets_t), state_reservs_cmp);
8688 remove_state_duplicate_reservs ();
8689 for (i = 1; i < VEC_length (reserv_sets_t, state_reservs); i++)
8691 fprintf (output_description_file, " ");
8692 output_reserv_sets (output_description_file,
8693 VEC_index (reserv_sets_t, state_reservs, i));
8694 fprintf (output_description_file, "\n");
8696 fprintf (output_description_file, "\n");
8697 output_state_arcs (state);
8698 VEC_free (reserv_sets_t,heap, state_reservs);
8701 /* The following function output readable representation of
8702 DFAs used for fast recognition of pipeline hazards. */
8704 output_automaton_descriptions (void)
8706 automaton_t automaton;
8708 for (automaton = description->first_automaton;
8710 automaton = automaton->next_automaton)
8712 fprintf (output_description_file, "\nAutomaton ");
8713 output_automaton_name (output_description_file, automaton);
8714 fprintf (output_description_file, "\n");
8715 output_automaton_units (automaton);
8716 pass_states (automaton, output_state);
8722 /* The page contains top level function for generation DFA(s) used for
8725 /* The function outputs statistics about work of different phases of
8728 output_statistics (FILE *f)
8730 automaton_t automaton;
8733 int transition_comb_vect_els = 0;
8734 int transition_full_vect_els = 0;
8735 int min_issue_delay_vect_els = 0;
8736 int locked_states = 0;
8739 for (automaton = description->first_automaton;
8741 automaton = automaton->next_automaton)
8743 fprintf (f, "\nAutomaton ");
8744 output_automaton_name (f, automaton);
8745 fprintf (f, "\n %5d NDFA states, %5d NDFA arcs\n",
8746 automaton->NDFA_states_num, automaton->NDFA_arcs_num);
8747 fprintf (f, " %5d DFA states, %5d DFA arcs\n",
8748 automaton->DFA_states_num, automaton->DFA_arcs_num);
8749 states_num = automaton->DFA_states_num;
8750 if (!no_minimization_flag)
8752 fprintf (f, " %5d minimal DFA states, %5d minimal DFA arcs\n",
8753 automaton->minimal_DFA_states_num,
8754 automaton->minimal_DFA_arcs_num);
8755 states_num = automaton->minimal_DFA_states_num;
8757 fprintf (f, " %5d all insns %5d insn equivalence classes\n",
8758 description->insns_num, automaton->insn_equiv_classes_num);
8759 fprintf (f, " %d locked states\n", automaton->locked_states);
8762 (f, "%5ld transition comb vector els, %5ld trans table els: %s\n",
8763 (long) VEC_length (vect_el_t, automaton->trans_table->comb_vect),
8764 (long) VEC_length (vect_el_t, automaton->trans_table->full_vect),
8765 (comb_vect_p (automaton->trans_table)
8766 ? "use comb vect" : "use simple vect"));
8768 (f, "%5ld min delay table els, compression factor %d\n",
8769 (long) states_num * automaton->insn_equiv_classes_num,
8770 automaton->min_issue_delay_table_compression_factor);
8771 transition_comb_vect_els
8772 += VEC_length (vect_el_t, automaton->trans_table->comb_vect);
8773 transition_full_vect_els
8774 += VEC_length (vect_el_t, automaton->trans_table->full_vect);
8775 min_issue_delay_vect_els
8776 += states_num * automaton->insn_equiv_classes_num;
8778 += automaton->locked_states;
8782 fprintf (f, "\n%5d all allocated states, %5d all allocated arcs\n",
8783 allocated_states_num, allocated_arcs_num);
8784 fprintf (f, "%5d all allocated alternative states\n",
8785 allocated_alt_states_num);
8786 fprintf (f, "%5d all transition comb vector els, %5d all trans table els\n",
8787 transition_comb_vect_els, transition_full_vect_els);
8788 fprintf (f, "%5d all min delay table els\n", min_issue_delay_vect_els);
8789 fprintf (f, "%5d all locked states\n", locked_states);
8793 /* The function output times of work of different phases of DFA
8796 output_time_statistics (FILE *f)
8798 fprintf (f, "\n transformation: ");
8799 print_active_time (f, transform_time);
8800 fprintf (f, (!ndfa_flag ? ", building DFA: " : ", building NDFA: "));
8801 print_active_time (f, NDFA_time);
8804 fprintf (f, ", NDFA -> DFA: ");
8805 print_active_time (f, NDFA_to_DFA_time);
8807 fprintf (f, "\n DFA minimization: ");
8808 print_active_time (f, minimize_time);
8809 fprintf (f, ", making insn equivalence: ");
8810 print_active_time (f, equiv_time);
8811 fprintf (f, "\n all automaton generation: ");
8812 print_active_time (f, automaton_generation_time);
8813 fprintf (f, ", output: ");
8814 print_active_time (f, output_time);
8818 /* The function generates DFA (deterministic finite state automaton)
8819 for fast recognition of pipeline hazards. No errors during
8820 checking must be fixed before this function call. */
8824 automata_num = split_argument;
8825 if (description->units_num < automata_num)
8826 automata_num = description->units_num;
8829 initiate_automata_lists ();
8830 initiate_pass_states ();
8831 initiate_excl_sets ();
8832 initiate_presence_absence_pattern_sets ();
8833 automaton_generation_time = create_ticker ();
8835 ticker_off (&automaton_generation_time);
8840 /* This page mainly contains top level functions of pipeline hazards
8841 description translator. */
8843 /* The following macro value is suffix of name of description file of
8844 pipeline hazards description translator. */
8845 #define STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX ".dfa"
8847 /* The function returns suffix of given file name. The returned
8848 string can not be changed. */
8850 file_name_suffix (const char *file_name)
8852 const char *last_period;
8854 for (last_period = NULL; *file_name != '\0'; file_name++)
8855 if (*file_name == '.')
8856 last_period = file_name;
8857 return (last_period == NULL ? file_name : last_period);
8860 /* The function returns base name of given file name, i.e. pointer to
8861 first char after last `/' (or `\' for WIN32) in given file name,
8862 given file name itself if the directory name is absent. The
8863 returned string can not be changed. */
8865 base_file_name (const char *file_name)
8867 int directory_name_length;
8869 directory_name_length = strlen (file_name);
8871 while (directory_name_length >= 0 && file_name[directory_name_length] != '/'
8872 && file_name[directory_name_length] != '\\')
8874 while (directory_name_length >= 0 && file_name[directory_name_length] != '/')
8876 directory_name_length--;
8877 return file_name + directory_name_length + 1;
8880 /* The following is top level function to initialize the work of
8881 pipeline hazards description translator. */
8883 initiate_automaton_gen (int argc, char **argv)
8885 const char *base_name;
8889 split_argument = 0; /* default value */
8890 no_minimization_flag = 0;
8896 for (i = 2; i < argc; i++)
8897 if (strcmp (argv [i], NO_MINIMIZATION_OPTION) == 0)
8898 no_minimization_flag = 1;
8899 else if (strcmp (argv [i], TIME_OPTION) == 0)
8901 else if (strcmp (argv [i], STATS_OPTION) == 0)
8903 else if (strcmp (argv [i], V_OPTION) == 0)
8905 else if (strcmp (argv [i], W_OPTION) == 0)
8907 else if (strcmp (argv [i], NDFA_OPTION) == 0)
8909 else if (strcmp (argv [i], PROGRESS_OPTION) == 0)
8911 else if (strcmp (argv [i], "-split") == 0)
8914 fatal ("-split has no argument.");
8915 fatal ("option `-split' has not been implemented yet\n");
8916 /* split_argument = atoi (argument_vect [i + 1]); */
8919 /* Initialize IR storage. */
8920 obstack_init (&irp);
8921 initiate_automaton_decl_table ();
8922 initiate_insn_decl_table ();
8923 initiate_decl_table ();
8924 output_file = stdout;
8925 output_description_file = NULL;
8926 base_name = base_file_name (argv[1]);
8927 obstack_grow (&irp, base_name,
8928 strlen (base_name) - strlen (file_name_suffix (base_name)));
8929 obstack_grow (&irp, STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX,
8930 strlen (STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX) + 1);
8931 obstack_1grow (&irp, '\0');
8932 output_description_file_name = obstack_base (&irp);
8933 obstack_finish (&irp);
8936 /* The following function checks existence at least one arc marked by
8939 check_automata_insn_issues (void)
8941 automaton_t automaton;
8942 ainsn_t ainsn, reserv_ainsn;
8944 for (automaton = description->first_automaton;
8946 automaton = automaton->next_automaton)
8948 for (ainsn = automaton->ainsn_list;
8950 ainsn = ainsn->next_ainsn)
8951 if (ainsn->first_insn_with_same_reservs && !ainsn->arc_exists_p)
8953 for (reserv_ainsn = ainsn;
8954 reserv_ainsn != NULL;
8955 reserv_ainsn = reserv_ainsn->next_same_reservs_insn)
8956 if (automaton->corresponding_automaton_decl != NULL)
8959 error ("Automaton `%s': Insn `%s' will never be issued",
8960 automaton->corresponding_automaton_decl->name,
8961 reserv_ainsn->insn_reserv_decl->name);
8964 (0, "Automaton `%s': Insn `%s' will never be issued",
8965 automaton->corresponding_automaton_decl->name,
8966 reserv_ainsn->insn_reserv_decl->name);
8971 error ("Insn `%s' will never be issued",
8972 reserv_ainsn->insn_reserv_decl->name);
8974 warning (0, "Insn `%s' will never be issued",
8975 reserv_ainsn->insn_reserv_decl->name);
8981 /* The following vla is used for storing pointers to all achieved
8983 static VEC(state_t,heap) *automaton_states;
8985 /* This function is called by function pass_states to add an achieved
8988 add_automaton_state (state_t state)
8990 VEC_safe_push (state_t,heap, automaton_states, state);
8993 /* The following function forms list of important automata (whose
8994 states may be changed after the insn issue) for each insn. */
8996 form_important_insn_automata_lists (void)
8998 automaton_t automaton;
9005 automaton_states = 0;
9006 /* Mark important ainsns. */
9007 for (automaton = description->first_automaton;
9009 automaton = automaton->next_automaton)
9011 VEC_truncate (state_t, automaton_states, 0);
9012 pass_states (automaton, add_automaton_state);
9013 for (n = 0; n < VEC_length (state_t, automaton_states); n++)
9015 state_t s = VEC_index (state_t, automaton_states, n);
9016 for (arc = first_out_arc (s);
9018 arc = next_out_arc (arc))
9019 if (arc->to_state != s)
9021 gcc_assert (arc->insn->first_insn_with_same_reservs);
9022 for (ainsn = arc->insn;
9024 ainsn = ainsn->next_same_reservs_insn)
9025 ainsn->important_p = TRUE;
9029 VEC_free (state_t,heap, automaton_states);
9031 /* Create automata sets for the insns. */
9032 for (i = 0; i < description->decls_num; i++)
9034 decl = description->decls [i];
9035 if (decl->mode == dm_insn_reserv)
9037 automata_list_start ();
9038 for (automaton = description->first_automaton;
9040 automaton = automaton->next_automaton)
9041 for (ainsn = automaton->ainsn_list;
9043 ainsn = ainsn->next_ainsn)
9044 if (ainsn->important_p
9045 && ainsn->insn_reserv_decl == DECL_INSN_RESERV (decl))
9047 automata_list_add (automaton);
9050 DECL_INSN_RESERV (decl)->important_automata_list
9051 = automata_list_finish ();
9057 /* The following is top level function to generate automat(a,on) for
9058 fast recognition of pipeline hazards. */
9060 expand_automata (void)
9064 description = create_node (sizeof (struct description)
9065 /* One entry for cycle advancing insn. */
9066 + sizeof (decl_t) * VEC_length (decl_t, decls));
9067 description->decls_num = VEC_length (decl_t, decls);
9068 description->query_units_num = 0;
9069 for (i = 0; i < description->decls_num; i++)
9071 description->decls [i] = VEC_index (decl_t, decls, i);
9072 if (description->decls [i]->mode == dm_unit
9073 && DECL_UNIT (description->decls [i])->query_p)
9074 DECL_UNIT (description->decls [i])->query_num
9075 = description->query_units_num++;
9077 all_time = create_ticker ();
9078 check_time = create_ticker ();
9080 fprintf (stderr, "Check description...");
9081 check_all_description ();
9083 fprintf (stderr, "done\n");
9084 ticker_off (&check_time);
9085 generation_time = create_ticker ();
9088 transform_insn_regexps ();
9089 check_unit_distributions_to_automata ();
9094 check_automata_insn_issues ();
9098 form_important_insn_automata_lists ();
9100 ticker_off (&generation_time);
9103 /* The following is top level function to output PHR and to finish
9104 work with pipeline description translator. */
9106 write_automata (void)
9108 output_time = create_ticker ();
9110 fprintf (stderr, "Forming and outputting automata tables...");
9114 fprintf (stderr, "done\n");
9115 fprintf (stderr, "Output functions to work with automata...");
9117 output_chip_definitions ();
9118 output_max_insn_queue_index_def ();
9119 output_internal_min_issue_delay_func ();
9120 output_internal_trans_func ();
9121 /* Cache of insn dfa codes: */
9122 fprintf (output_file, "\nstatic int *%s;\n", DFA_INSN_CODES_VARIABLE_NAME);
9123 fprintf (output_file, "\nstatic int %s;\n\n",
9124 DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
9125 output_dfa_insn_code_func ();
9126 output_trans_func ();
9127 output_min_issue_delay_func ();
9128 output_internal_dead_lock_func ();
9129 output_dead_lock_func ();
9130 output_size_func ();
9131 output_internal_reset_func ();
9132 output_reset_func ();
9133 output_min_insn_conflict_delay_func ();
9134 output_internal_insn_latency_func ();
9135 output_insn_latency_func ();
9136 output_print_reservation_func ();
9137 /* Output function get_cpu_unit_code. */
9138 fprintf (output_file, "\n#if %s\n\n", CPU_UNITS_QUERY_MACRO_NAME);
9139 output_get_cpu_unit_code_func ();
9140 output_cpu_unit_reservation_p ();
9141 fprintf (output_file, "\n#endif /* #if %s */\n\n",
9142 CPU_UNITS_QUERY_MACRO_NAME);
9143 output_dfa_clean_insn_cache_func ();
9144 output_dfa_start_func ();
9145 output_dfa_finish_func ();
9147 fprintf (stderr, "done\n");
9150 output_description_file = fopen (output_description_file_name, "w");
9151 if (output_description_file == NULL)
9153 perror (output_description_file_name);
9154 exit (FATAL_EXIT_CODE);
9157 fprintf (stderr, "Output automata description...");
9158 output_description ();
9159 output_automaton_descriptions ();
9161 fprintf (stderr, "done\n");
9162 output_statistics (output_description_file);
9165 output_statistics (stderr);
9166 ticker_off (&output_time);
9168 output_time_statistics (stderr);
9171 finish_automata_lists ();
9174 fprintf (stderr, "Summary:\n");
9175 fprintf (stderr, " check time ");
9176 print_active_time (stderr, check_time);
9177 fprintf (stderr, ", generation time ");
9178 print_active_time (stderr, generation_time);
9179 fprintf (stderr, ", all time ");
9180 print_active_time (stderr, all_time);
9181 fprintf (stderr, "\n");
9183 /* Finish all work. */
9184 if (output_description_file != NULL)
9186 fflush (output_description_file);
9187 if (ferror (stdout) != 0)
9188 fatal ("Error in writing DFA description file %s: %s",
9189 output_description_file_name, xstrerror (errno));
9190 fclose (output_description_file);
9192 finish_automaton_decl_table ();
9193 finish_insn_decl_table ();
9194 finish_decl_table ();
9195 obstack_free (&irp, NULL);
9196 if (have_error && output_description_file != NULL)
9197 remove (output_description_file_name);
9201 main (int argc, char **argv)
9205 progname = "genautomata";
9207 if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
9208 return (FATAL_EXIT_CODE);
9210 initiate_automaton_gen (argc, argv);
9214 int insn_code_number;
9216 desc = read_md_rtx (&lineno, &insn_code_number);
9220 switch (GET_CODE (desc))
9222 case DEFINE_CPU_UNIT:
9223 gen_cpu_unit (desc);
9226 case DEFINE_QUERY_CPU_UNIT:
9227 gen_query_cpu_unit (desc);
9235 gen_excl_set (desc);
9239 gen_presence_set (desc);
9242 case FINAL_PRESENCE_SET:
9243 gen_final_presence_set (desc);
9247 gen_absence_set (desc);
9250 case FINAL_ABSENCE_SET:
9251 gen_final_absence_set (desc);
9254 case DEFINE_AUTOMATON:
9255 gen_automaton (desc);
9258 case AUTOMATA_OPTION:
9259 gen_automata_option (desc);
9262 case DEFINE_RESERVATION:
9266 case DEFINE_INSN_RESERVATION:
9267 gen_insn_reserv (desc);
9276 return FATAL_EXIT_CODE;
9278 puts ("/* Generated automatically by the program `genautomata'\n"
9279 " from the machine description file `md'. */\n\n"
9280 "#include \"config.h\"\n"
9281 "#include \"system.h\"\n"
9282 "#include \"coretypes.h\"\n"
9283 "#include \"tm.h\"\n"
9284 "#include \"rtl.h\"\n"
9285 "#include \"tm_p.h\"\n"
9286 "#include \"insn-config.h\"\n"
9287 "#include \"recog.h\"\n"
9288 "#include \"regs.h\"\n"
9289 "#include \"real.h\"\n"
9290 "#include \"output.h\"\n"
9291 "#include \"insn-attr.h\"\n"
9292 "#include \"toplev.h\"\n"
9293 "#include \"flags.h\"\n"
9294 "#include \"function.h\"\n");
9296 if (VEC_length (decl_t, decls) > 0)
9303 return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);