1 /* Pipeline hazard description translator.
2 Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009
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. The finite state automaton based pipeline hazard recognizer and
26 instruction scheduler in GCC. V. Makarov. Proceedings of GCC
29 2. Detecting pipeline structural hazards quickly. T. Proebsting,
30 C. Fraser. Proceedings of ACM SIGPLAN-SIGACT Symposium on
31 Principles of Programming Languages, pages 280--286, 1994.
33 This article is a good start point to understand usage of finite
34 state automata for pipeline hazard recognizers. But I'd
35 recommend the 1st and 3rd article for more deep understanding.
37 3. Efficient Instruction Scheduling Using Finite State Automata:
38 V. Bala and N. Rubin, Proceedings of MICRO-28. This is the best
39 article about usage of finite state automata for pipeline hazard
42 The current implementation is described in the 1st article and it
43 is different from the 3rd article in the following:
45 1. New operator `|' (alternative) is permitted in functional unit
46 reservation which can be treated deterministically and
47 non-deterministically.
49 2. Possibility of usage of nondeterministic automata too.
51 3. Possibility to query functional unit reservations for given
54 4. Several constructions to describe impossible reservations
55 (`exclusion_set', `presence_set', `final_presence_set',
56 `absence_set', and `final_absence_set').
58 5. No reverse automata are generated. Trace instruction scheduling
59 requires this. It can be easily added in the future if we
62 6. Union of automaton states are not generated yet. It is planned
63 to be implemented. Such feature is needed to make more accurate
64 interlock insn scheduling to get state describing functional
65 unit reservation in a joint CFG point. */
67 /* This file code processes constructions of machine description file
68 which describes automaton used for recognition of processor pipeline
69 hazards by insn scheduler and can be used for other tasks (such as
72 The translator functions `gen_cpu_unit', `gen_query_cpu_unit',
73 `gen_bypass', `gen_excl_set', `gen_presence_set',
74 `gen_final_presence_set', `gen_absence_set',
75 `gen_final_absence_set', `gen_automaton', `gen_automata_option',
76 `gen_reserv', `gen_insn_reserv' are called from file
77 `genattrtab.c'. They transform RTL constructions describing
78 automata in .md file into internal representation convenient for
81 The translator major function `expand_automata' processes the
82 description internal representation into finite state automaton.
85 o checking correctness of the automaton pipeline description
86 (major function is `check_all_description').
88 o generating automaton (automata) from the description (major
89 function is `make_automaton').
91 o optional transformation of nondeterministic finite state
92 automata into deterministic ones if the alternative operator
93 `|' is treated nondeterministically in the description (major
94 function is NDFA_to_DFA).
96 o optional minimization of the finite state automata by merging
97 equivalent automaton states (major function is `minimize_DFA').
99 o forming tables (some as comb vectors) and attributes
100 representing the automata (functions output_..._table).
102 Function `write_automata' outputs the created finite state
103 automaton as different tables and functions which works with the
104 automata to inquire automaton state and to change its state. These
105 function are used by gcc instruction scheduler and may be some
110 #include "coretypes.h"
115 #include "gensupport.h"
125 /* Positions in machine description file. Now they are not used. But
126 they could be used in the future for better diagnostic messages. */
129 /* The following is element of vector of current (and planned in the
130 future) functional unit reservations. */
131 typedef unsigned HOST_WIDE_INT set_el_t;
133 /* Reservations of function units are represented by value of the following
135 typedef set_el_t *reserv_sets_t;
136 typedef const set_el_t *const_reserv_sets_t;
138 /* The following structure describes a ticker. */
141 /* The following member value is time of the ticker creation with
142 taking into account time when the ticker is off. Active time of
143 the ticker is current time minus the value. */
144 int modified_creation_time;
145 /* The following member value is time (incremented by one) when the
146 ticker was off. Zero value means that now the ticker is on. */
147 int incremented_off_time;
150 /* The ticker is represented by the following type. */
151 typedef struct ticker ticker_t;
153 /* The following type describes elements of output vectors. */
154 typedef HOST_WIDE_INT vect_el_t;
156 /* Forward declaration of structures of internal representation of
157 pipeline description based on NDFA. */
162 struct automaton_decl;
163 struct unit_pattern_rel_decl;
165 struct insn_reserv_decl;
168 struct result_regexp;
169 struct reserv_regexp;
170 struct nothing_regexp;
171 struct sequence_regexp;
172 struct repeat_regexp;
178 struct pattern_set_el;
179 struct pattern_reserv;
185 struct state_ainsn_table;
187 /* The following typedefs are for brevity. */
188 typedef struct unit_decl *unit_decl_t;
189 typedef const struct unit_decl *const_unit_decl_t;
190 typedef struct decl *decl_t;
191 typedef const struct decl *const_decl_t;
192 typedef struct regexp *regexp_t;
193 typedef struct unit_set_el *unit_set_el_t;
194 typedef struct pattern_set_el *pattern_set_el_t;
195 typedef struct pattern_reserv *pattern_reserv_t;
196 typedef struct alt_state *alt_state_t;
197 typedef struct state *state_t;
198 typedef const struct state *const_state_t;
199 typedef struct arc *arc_t;
200 typedef struct ainsn *ainsn_t;
201 typedef struct automaton *automaton_t;
202 typedef struct automata_list_el *automata_list_el_t;
203 typedef const struct automata_list_el *const_automata_list_el_t;
204 typedef struct state_ainsn_table *state_ainsn_table_t;
206 /* Undefined position. */
207 static pos_t no_pos = 0;
209 /* All IR is stored in the following obstack. */
210 static struct obstack irp;
213 /* Declare vector types for various data structures: */
215 DEF_VEC_P(alt_state_t);
216 DEF_VEC_ALLOC_P(alt_state_t, heap);
218 DEF_VEC_ALLOC_P(ainsn_t, heap);
220 DEF_VEC_ALLOC_P(state_t, heap);
222 DEF_VEC_ALLOC_P(decl_t, heap);
223 DEF_VEC_P(reserv_sets_t);
224 DEF_VEC_ALLOC_P(reserv_sets_t, heap);
226 DEF_VEC_I(vect_el_t);
227 DEF_VEC_ALLOC_I(vect_el_t, heap);
228 typedef VEC(vect_el_t, heap) *vla_hwint_t;
230 /* Forward declarations of functions used before their definitions, only. */
231 static regexp_t gen_regexp_sequence (const char *);
232 static void reserv_sets_or (reserv_sets_t, reserv_sets_t,
234 static reserv_sets_t get_excl_set (reserv_sets_t);
235 static int check_presence_pattern_sets (reserv_sets_t,
237 static int check_absence_pattern_sets (reserv_sets_t, reserv_sets_t,
239 static arc_t first_out_arc (const_state_t);
240 static arc_t next_out_arc (arc_t);
244 /* Options with the following names can be set up in automata_option
245 construction. Because the strings occur more one time we use the
248 #define NO_MINIMIZATION_OPTION "-no-minimization"
249 #define TIME_OPTION "-time"
250 #define STATS_OPTION "-stats"
251 #define V_OPTION "-v"
252 #define W_OPTION "-w"
253 #define NDFA_OPTION "-ndfa"
254 #define PROGRESS_OPTION "-progress"
256 /* The following flags are set up by function `initiate_automaton_gen'. */
258 /* Make automata with nondeterministic reservation by insns (`-ndfa'). */
259 static int ndfa_flag;
261 /* Do not make minimization of DFA (`-no-minimization'). */
262 static int no_minimization_flag;
264 /* Value of this variable is number of automata being generated. The
265 actual number of automata may be less this value if there is not
266 sufficient number of units. This value is defined by argument of
267 option `-split' or by constructions automaton if the value is zero
268 (it is default value of the argument). */
269 static int split_argument;
271 /* Flag of output time statistics (`-time'). */
272 static int time_flag;
274 /* Flag of automata statistics (`-stats'). */
275 static int stats_flag;
277 /* Flag of creation of description file which contains description of
278 result automaton and statistics information (`-v'). */
281 /* Flag of output of a progress bar showing how many states were
282 generated so far for automaton being processed (`-progress'). */
283 static int progress_flag;
285 /* Flag of generating warning instead of error for non-critical errors
290 /* Output file for pipeline hazard recognizer (PHR) being generated.
291 The value is NULL if the file is not defined. */
292 static FILE *output_file;
294 /* Description file of PHR. The value is NULL if the file is not
296 static FILE *output_description_file;
298 /* PHR description file name. */
299 static char *output_description_file_name;
301 /* Value of the following variable is node representing description
302 being processed. This is start point of IR. */
303 static struct description *description;
307 /* This page contains description of IR structure (nodes). */
321 /* This describes define_cpu_unit and define_query_cpu_unit (see file
326 /* NULL if the automaton name is absent. */
327 const char *automaton_name;
328 /* If the following value is not zero, the cpu unit reservation is
329 described in define_query_cpu_unit. */
332 /* The following fields are defined by checker. */
334 /* The following field value is nonzero if the unit is used in an
338 /* The following field value is order number (0, 1, ...) of given
341 /* The following field value is corresponding declaration of
342 automaton which was given in description. If the field value is
343 NULL then automaton in the unit declaration was absent. */
344 struct automaton_decl *automaton_decl;
345 /* The following field value is maximal cycle number (1, ...) on
346 which given unit occurs in insns. Zero value means that given
347 unit is not used in insns. */
348 int max_occ_cycle_num;
349 /* The following field value is minimal cycle number (0, ...) on
350 which given unit occurs in insns. -1 value means that given
351 unit is not used in insns. */
352 int min_occ_cycle_num;
353 /* The following list contains units which conflict with given
355 unit_set_el_t excl_list;
356 /* The following list contains patterns which are required to
357 reservation of given unit. */
358 pattern_set_el_t presence_list;
359 pattern_set_el_t final_presence_list;
360 /* The following list contains patterns which should be not present
361 in reservation for given unit. */
362 pattern_set_el_t absence_list;
363 pattern_set_el_t final_absence_list;
364 /* The following is used only when `query_p' has nonzero value.
365 This is query number for the unit. */
367 /* The following is the last cycle on which the unit was checked for
368 correct distributions of units to automata in a regexp. */
369 int last_distribution_check_cycle;
371 /* The following fields are defined by automaton generator. */
373 /* The following field value is number of the automaton to which
374 given unit belongs. */
375 int corresponding_automaton_num;
376 /* If the following value is not zero, the cpu unit is present in a
377 `exclusion_set' or in right part of a `presence_set',
378 `final_presence_set', `absence_set', and
379 `final_absence_set'define_query_cpu_unit. */
383 /* This describes define_bypass (see file rtl.def). */
387 const char *out_insn_name;
388 const char *in_insn_name;
389 const char *bypass_guard_name;
391 /* The following fields are defined by checker. */
393 /* output and input insns of given bypass. */
394 struct insn_reserv_decl *out_insn_reserv;
395 struct insn_reserv_decl *in_insn_reserv;
396 /* The next bypass for given output insn. */
397 struct bypass_decl *next;
400 /* This describes define_automaton (see file rtl.def). */
401 struct automaton_decl
405 /* The following fields are defined by automaton generator. */
407 /* The following field value is nonzero if the automaton is used in
408 an regexp definition. */
409 char automaton_is_used;
411 /* The following fields are defined by checker. */
413 /* The following field value is the corresponding automaton. This
414 field is not NULL only if the automaton is present in unit
415 declarations and the automatic partition on automata is not
417 automaton_t corresponding_automaton;
420 /* This describes exclusion relations: exclusion_set (see file
425 int first_list_length;
429 /* This describes unit relations: [final_]presence_set or
430 [final_]absence_set (see file rtl.def). */
431 struct unit_pattern_rel_decl
440 /* This describes define_reservation (see file rtl.def). */
446 /* The following fields are defined by checker. */
448 /* The following field value is nonzero if the unit is used in an
451 /* The following field is used to check up cycle in expression
456 /* This describes define_insn_reservation (see file rtl.def). */
457 struct insn_reserv_decl
464 /* The following fields are defined by checker. */
466 /* The following field value is order number (0, 1, ...) of given
469 /* The following field value is list of bypasses in which given insn
470 is output insn. Bypasses with the same input insn stay one after
471 another in the list in the same order as their occurrences in the
472 description but the bypass without a guard stays always the last
473 in a row of bypasses with the same input insn. */
474 struct bypass_decl *bypass_list;
476 /* The following fields are defined by automaton generator. */
478 /* The following field is the insn regexp transformed that
479 the regexp has not optional regexp, repetition regexp, and an
480 reservation name (i.e. reservation identifiers are changed by the
481 corresponding regexp) and all alternations are the top level
482 of the regexp. The value can be NULL only if it is special
483 insn `cycle advancing'. */
484 regexp_t transformed_regexp;
485 /* The following field value is list of arcs marked given
486 insn. The field is used in transformation NDFA -> DFA. */
487 arc_t arcs_marked_by_insn;
488 /* The two following fields are used during minimization of a finite state
490 /* The field value is number of equivalence class of state into
491 which arc marked by given insn enters from a state (fixed during
492 an automaton minimization). */
494 /* The following member value is the list to automata which can be
495 changed by the insn issue. */
496 automata_list_el_t important_automata_list;
497 /* The following member is used to process insn once for output. */
501 /* This contains a declaration mentioned above. */
504 /* What node in the union? */
509 struct unit_decl unit;
510 struct bypass_decl bypass;
511 struct automaton_decl automaton;
512 struct excl_rel_decl excl;
513 struct unit_pattern_rel_decl presence;
514 struct unit_pattern_rel_decl absence;
515 struct reserv_decl reserv;
516 struct insn_reserv_decl insn_reserv;
520 /* The following structures represent parsed reservation strings. */
532 /* Cpu unit in reservation. */
536 unit_decl_t unit_decl;
539 /* Define_reservation in a reservation. */
543 struct reserv_decl *reserv_decl;
546 /* Absence of reservation (represented by string `nothing'). */
547 struct nothing_regexp
549 /* This used to be empty but ISO C doesn't allow that. */
553 /* Representation of reservations separated by ',' (see file
555 struct sequence_regexp
558 regexp_t regexps [1];
561 /* Representation of construction `repeat' (see file rtl.def). */
568 /* Representation of reservations separated by '+' (see file
573 regexp_t regexps [1];
576 /* Representation of reservations separated by '|' (see file
581 regexp_t regexps [1];
584 /* Representation of a reservation string. */
587 /* What node in the union? */
588 enum regexp_mode mode;
592 struct unit_regexp unit;
593 struct reserv_regexp reserv;
594 struct nothing_regexp nothing;
595 struct sequence_regexp sequence;
596 struct repeat_regexp repeat;
597 struct allof_regexp allof;
598 struct oneof_regexp oneof;
602 /* Represents description of pipeline hazard description based on
608 /* The following fields are defined by checker. */
610 /* The following fields values are correspondingly number of all
611 units, query units, and insns in the description. */
615 /* The following field value is max length (in cycles) of
616 reservations of insns. The field value is defined only for
618 int max_insn_reserv_cycles;
620 /* The following fields are defined by automaton generator. */
622 /* The following field value is the first automaton. */
623 automaton_t first_automaton;
625 /* The following field is created by pipeline hazard parser and
626 contains all declarations. We allocate additional entry for
627 special insn "cycle advancing" which is added by the automaton
633 /* The following nodes are created in automaton checker. */
635 /* The following nodes represent exclusion set for cpu units. Each
636 element is accessed through only one excl_list. */
639 unit_decl_t unit_decl;
640 unit_set_el_t next_unit_set_el;
643 /* The following nodes represent presence or absence pattern for cpu
644 units. Each element is accessed through only one presence_list or
646 struct pattern_set_el
648 /* The number of units in unit_decls. */
650 /* The units forming the pattern. */
651 struct unit_decl **unit_decls;
652 pattern_set_el_t next_pattern_set_el;
656 /* The following nodes are created in automaton generator. */
659 /* The following nodes represent presence or absence pattern for cpu
660 units. Each element is accessed through only one element of
661 unit_presence_set_table or unit_absence_set_table. */
662 struct pattern_reserv
664 reserv_sets_t reserv;
665 pattern_reserv_t next_pattern_reserv;
668 /* The following node type describes state automaton. The state may
669 be deterministic or non-deterministic. Non-deterministic state has
670 several component states which represent alternative cpu units
671 reservations. The state also is used for describing a
672 deterministic reservation of automaton insn. */
675 /* The following member value is nonzero if there is a transition by
678 /* The following field is list of processor unit reservations on
680 reserv_sets_t reservs;
681 /* The following field is unique number of given state between other
684 /* The following field value is automaton to which given state
686 automaton_t automaton;
687 /* The following field value is the first arc output from given
690 unsigned int num_out_arcs;
691 /* The following field is used to form NDFA. */
692 char it_was_placed_in_stack_for_NDFA_forming;
693 /* The following field is used to form DFA. */
694 char it_was_placed_in_stack_for_DFA_forming;
695 /* The following field is used to transform NDFA to DFA and DFA
696 minimization. The field value is not NULL if the state is a
697 compound state. In this case the value of field `unit_sets_list'
698 is NULL. All states in the list are in the hash table. The list
699 is formed through field `next_sorted_alt_state'. We should
700 support only one level of nesting state. */
701 alt_state_t component_states;
702 /* The following field is used for passing graph of states. */
704 /* The list of states belonging to one equivalence class is formed
705 with the aid of the following field. */
706 state_t next_equiv_class_state;
707 /* The two following fields are used during minimization of a finite
709 int equiv_class_num_1, equiv_class_num_2;
710 /* The following field is used during minimization of a finite state
711 automaton. The field value is state corresponding to equivalence
712 class to which given state belongs. */
713 state_t equiv_class_state;
714 unsigned int *presence_signature;
715 /* The following field value is the order number of given state.
716 The states in final DFA is enumerated with the aid of the
719 /* This member is used for passing states for searching minimal
722 /* The following member is used to evaluate min issue delay of insn
724 int min_insn_issue_delay;
730 /* The following field refers for the state into which given arc
733 /* The following field describes that the insn issue (with cycle
734 advancing for special insn `cycle advancing' and without cycle
735 advancing for others) makes transition from given state to
736 another given state. */
738 /* The following field value is the next arc output from the same
741 /* List of arcs marked given insn is formed with the following
742 field. The field is used in transformation NDFA -> DFA. */
743 arc_t next_arc_marked_by_insn;
746 /* The following node type describes a deterministic alternative in
747 non-deterministic state which characterizes cpu unit reservations
748 of automaton insn or which is part of NDFA. */
751 /* The following field is a deterministic state which characterizes
752 unit reservations of the instruction. */
754 /* The following field refers to the next state which characterizes
755 unit reservations of the instruction. */
756 alt_state_t next_alt_state;
757 /* The following field refers to the next state in sorted list. */
758 alt_state_t next_sorted_alt_state;
761 /* The following node type describes insn of automaton. They are
762 labels of FA arcs. */
765 /* The following field value is the corresponding insn declaration
767 struct insn_reserv_decl *insn_reserv_decl;
768 /* The following field value is the next insn declaration for an
771 /* The following field is states which characterize automaton unit
772 reservations of the instruction. The value can be NULL only if it
773 is special insn `cycle advancing'. */
774 alt_state_t alt_states;
775 /* The following field is sorted list of states which characterize
776 automaton unit reservations of the instruction. The value can be
777 NULL only if it is special insn `cycle advancing'. */
778 alt_state_t sorted_alt_states;
779 /* The following field refers the next automaton insn with
780 the same reservations. */
781 ainsn_t next_same_reservs_insn;
782 /* The following field is flag of the first automaton insn with the
783 same reservations in the declaration list. Only arcs marked such
784 insn is present in the automaton. This significantly decreases
785 memory requirements especially when several automata are
787 char first_insn_with_same_reservs;
788 /* The following member has nonzero value if there is arc from state of
789 the automaton marked by the ainsn. */
791 /* Cyclic list of insns of an equivalence class is formed with the
792 aid of the following field. */
793 ainsn_t next_equiv_class_insn;
794 /* The following field value is nonzero if the insn declaration is
795 the first insn declaration with given equivalence number. */
796 char first_ainsn_with_given_equivalence_num;
797 /* The following field is number of class of equivalence of insns.
798 It is necessary because many insns may be equivalent with the
799 point of view of pipeline hazards. */
800 int insn_equiv_class_num;
801 /* The following member value is TRUE if there is an arc in the
802 automaton marked by the insn into another state. In other
803 words, the insn can change the state of the automaton. */
807 /* The following describes an automaton for PHR. */
810 /* The following field value is the list of insn declarations for
813 /* The following field value is the corresponding automaton
814 declaration. This field is not NULL only if the automatic
815 partition on automata is not used. */
816 struct automaton_decl *corresponding_automaton_decl;
817 /* The following field value is the next automaton. */
818 automaton_t next_automaton;
819 /* The following field is start state of FA. There are not unit
820 reservations in the state. */
822 /* The following field value is number of equivalence classes of
823 insns (see field `insn_equiv_class_num' in
824 `insn_reserv_decl'). */
825 int insn_equiv_classes_num;
826 /* The following field value is number of states of final DFA. */
827 int achieved_states_num;
828 /* The following field value is the order number (0, 1, ...) of
830 int automaton_order_num;
831 /* The following fields contain statistics information about
832 building automaton. */
833 int NDFA_states_num, DFA_states_num;
834 /* The following field value is defined only if minimization of DFA
836 int minimal_DFA_states_num;
837 int NDFA_arcs_num, DFA_arcs_num;
838 /* The following field value is defined only if minimization of DFA
840 int minimal_DFA_arcs_num;
841 /* The following member refers for two table state x ainsn -> int.
842 ??? Above sentence is incomprehensible. */
843 state_ainsn_table_t trans_table;
844 /* The following member value is maximal value of min issue delay
845 for insns of the automaton. */
847 /* Usually min issue delay is small and we can place several (2, 4,
848 8) elements in one vector element. So the compression factor can
849 be 1 (no compression), 2, 4, 8. */
850 int min_issue_delay_table_compression_factor;
851 /* Total number of locked states in this automaton. */
855 /* The following is the element of the list of automata. */
856 struct automata_list_el
858 /* The automaton itself. */
859 automaton_t automaton;
860 /* The next automata set element. */
861 automata_list_el_t next_automata_list_el;
864 /* The following structure describes a table state X ainsn -> int(>= 0). */
865 struct state_ainsn_table
867 /* Automaton to which given table belongs. */
868 automaton_t automaton;
869 /* The following tree vectors for comb vector implementation of the
871 vla_hwint_t comb_vect;
872 vla_hwint_t check_vect;
873 vla_hwint_t base_vect;
874 /* This is simple implementation of the table. */
875 vla_hwint_t full_vect;
876 /* Minimal and maximal values of the previous vectors. */
877 int min_comb_vect_el_value, max_comb_vect_el_value;
878 int min_base_vect_el_value, max_base_vect_el_value;
881 /* Macros to access members of unions. Use only them for access to
882 union members of declarations and regexps. */
884 #if defined ENABLE_CHECKING && (GCC_VERSION >= 2007)
886 #define DECL_UNIT(d) __extension__ \
887 (({ __typeof (d) const _decl = (d); \
888 if (_decl->mode != dm_unit) \
889 decl_mode_check_failed (_decl->mode, "dm_unit", \
890 __FILE__, __LINE__, __FUNCTION__); \
891 &(_decl)->decl.unit; }))
893 #define DECL_BYPASS(d) __extension__ \
894 (({ __typeof (d) const _decl = (d); \
895 if (_decl->mode != dm_bypass) \
896 decl_mode_check_failed (_decl->mode, "dm_bypass", \
897 __FILE__, __LINE__, __FUNCTION__); \
898 &(_decl)->decl.bypass; }))
900 #define DECL_AUTOMATON(d) __extension__ \
901 (({ __typeof (d) const _decl = (d); \
902 if (_decl->mode != dm_automaton) \
903 decl_mode_check_failed (_decl->mode, "dm_automaton", \
904 __FILE__, __LINE__, __FUNCTION__); \
905 &(_decl)->decl.automaton; }))
907 #define DECL_EXCL(d) __extension__ \
908 (({ __typeof (d) const _decl = (d); \
909 if (_decl->mode != dm_excl) \
910 decl_mode_check_failed (_decl->mode, "dm_excl", \
911 __FILE__, __LINE__, __FUNCTION__); \
912 &(_decl)->decl.excl; }))
914 #define DECL_PRESENCE(d) __extension__ \
915 (({ __typeof (d) const _decl = (d); \
916 if (_decl->mode != dm_presence) \
917 decl_mode_check_failed (_decl->mode, "dm_presence", \
918 __FILE__, __LINE__, __FUNCTION__); \
919 &(_decl)->decl.presence; }))
921 #define DECL_ABSENCE(d) __extension__ \
922 (({ __typeof (d) const _decl = (d); \
923 if (_decl->mode != dm_absence) \
924 decl_mode_check_failed (_decl->mode, "dm_absence", \
925 __FILE__, __LINE__, __FUNCTION__); \
926 &(_decl)->decl.absence; }))
928 #define DECL_RESERV(d) __extension__ \
929 (({ __typeof (d) const _decl = (d); \
930 if (_decl->mode != dm_reserv) \
931 decl_mode_check_failed (_decl->mode, "dm_reserv", \
932 __FILE__, __LINE__, __FUNCTION__); \
933 &(_decl)->decl.reserv; }))
935 #define DECL_INSN_RESERV(d) __extension__ \
936 (({ __typeof (d) const _decl = (d); \
937 if (_decl->mode != dm_insn_reserv) \
938 decl_mode_check_failed (_decl->mode, "dm_insn_reserv", \
939 __FILE__, __LINE__, __FUNCTION__); \
940 &(_decl)->decl.insn_reserv; }))
942 static const char *decl_name (enum decl_mode);
943 static void decl_mode_check_failed (enum decl_mode, const char *,
944 const char *, int, const char *)
947 /* Return string representation of declaration mode MODE. */
949 decl_name (enum decl_mode mode)
951 static char str [100];
955 else if (mode == dm_bypass)
957 else if (mode == dm_automaton)
958 return "dm_automaton";
959 else if (mode == dm_excl)
961 else if (mode == dm_presence)
962 return "dm_presence";
963 else if (mode == dm_absence)
965 else if (mode == dm_reserv)
967 else if (mode == dm_insn_reserv)
968 return "dm_insn_reserv";
970 sprintf (str, "unknown (%d)", (int) mode);
974 /* The function prints message about unexpected declaration and finish
977 decl_mode_check_failed (enum decl_mode mode, const char *expected_mode_str,
978 const char *file, int line, const char *func)
982 "\n%s: %d: error in %s: DECL check: expected decl %s, have %s\n",
983 file, line, func, expected_mode_str, decl_name (mode));
988 #define REGEXP_UNIT(r) __extension__ \
989 (({ struct regexp *const _regexp = (r); \
990 if (_regexp->mode != rm_unit) \
991 regexp_mode_check_failed (_regexp->mode, "rm_unit", \
992 __FILE__, __LINE__, __FUNCTION__); \
993 &(_regexp)->regexp.unit; }))
995 #define REGEXP_RESERV(r) __extension__ \
996 (({ struct regexp *const _regexp = (r); \
997 if (_regexp->mode != rm_reserv) \
998 regexp_mode_check_failed (_regexp->mode, "rm_reserv", \
999 __FILE__, __LINE__, __FUNCTION__); \
1000 &(_regexp)->regexp.reserv; }))
1002 #define REGEXP_SEQUENCE(r) __extension__ \
1003 (({ struct regexp *const _regexp = (r); \
1004 if (_regexp->mode != rm_sequence) \
1005 regexp_mode_check_failed (_regexp->mode, "rm_sequence", \
1006 __FILE__, __LINE__, __FUNCTION__); \
1007 &(_regexp)->regexp.sequence; }))
1009 #define REGEXP_REPEAT(r) __extension__ \
1010 (({ struct regexp *const _regexp = (r); \
1011 if (_regexp->mode != rm_repeat) \
1012 regexp_mode_check_failed (_regexp->mode, "rm_repeat", \
1013 __FILE__, __LINE__, __FUNCTION__); \
1014 &(_regexp)->regexp.repeat; }))
1016 #define REGEXP_ALLOF(r) __extension__ \
1017 (({ struct regexp *const _regexp = (r); \
1018 if (_regexp->mode != rm_allof) \
1019 regexp_mode_check_failed (_regexp->mode, "rm_allof", \
1020 __FILE__, __LINE__, __FUNCTION__); \
1021 &(_regexp)->regexp.allof; }))
1023 #define REGEXP_ONEOF(r) __extension__ \
1024 (({ struct regexp *const _regexp = (r); \
1025 if (_regexp->mode != rm_oneof) \
1026 regexp_mode_check_failed (_regexp->mode, "rm_oneof", \
1027 __FILE__, __LINE__, __FUNCTION__); \
1028 &(_regexp)->regexp.oneof; }))
1030 static const char *regexp_name (enum regexp_mode);
1031 static void regexp_mode_check_failed (enum regexp_mode, const char *,
1033 const char *) ATTRIBUTE_NORETURN;
1036 /* Return string representation of regexp mode MODE. */
1038 regexp_name (enum regexp_mode mode)
1047 return "rm_nothing";
1049 return "rm_sequence";
1061 /* The function prints message about unexpected regexp and finish the
1064 regexp_mode_check_failed (enum regexp_mode mode,
1065 const char *expected_mode_str,
1066 const char *file, int line, const char *func)
1070 "\n%s: %d: error in %s: REGEXP check: expected decl %s, have %s\n",
1071 file, line, func, expected_mode_str, regexp_name (mode));
1075 #else /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */
1077 #define DECL_UNIT(d) (&(d)->decl.unit)
1078 #define DECL_BYPASS(d) (&(d)->decl.bypass)
1079 #define DECL_AUTOMATON(d) (&(d)->decl.automaton)
1080 #define DECL_EXCL(d) (&(d)->decl.excl)
1081 #define DECL_PRESENCE(d) (&(d)->decl.presence)
1082 #define DECL_ABSENCE(d) (&(d)->decl.absence)
1083 #define DECL_RESERV(d) (&(d)->decl.reserv)
1084 #define DECL_INSN_RESERV(d) (&(d)->decl.insn_reserv)
1086 #define REGEXP_UNIT(r) (&(r)->regexp.unit)
1087 #define REGEXP_RESERV(r) (&(r)->regexp.reserv)
1088 #define REGEXP_SEQUENCE(r) (&(r)->regexp.sequence)
1089 #define REGEXP_REPEAT(r) (&(r)->regexp.repeat)
1090 #define REGEXP_ALLOF(r) (&(r)->regexp.allof)
1091 #define REGEXP_ONEOF(r) (&(r)->regexp.oneof)
1093 #endif /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */
1095 #define XCREATENODE(T) ((T *) create_node (sizeof (T)))
1096 #define XCREATENODEVEC(T, N) ((T *) create_node (sizeof (T) * (N)))
1097 #define XCREATENODEVAR(T, S) ((T *) create_node ((S)))
1099 #define XCOPYNODE(T, P) ((T *) copy_node ((P), sizeof (T)))
1100 #define XCOPYNODEVEC(T, P, N) ((T *) copy_node ((P), sizeof (T) * (N)))
1101 #define XCOPYNODEVAR(T, P, S) ((T *) copy_node ((P), (S)))
1103 /* Create IR structure (node). */
1105 create_node (size_t size)
1109 obstack_blank (&irp, size);
1110 result = obstack_base (&irp);
1111 obstack_finish (&irp);
1112 /* Default values of members are NULL and zero. */
1113 memset (result, 0, size);
1117 /* Copy IR structure (node). */
1119 copy_node (const void *from, size_t size)
1121 void *const result = create_node (size);
1122 memcpy (result, from, size);
1126 /* The function checks that NAME does not contain quotes (`"'). */
1128 check_name (const char * name, pos_t pos ATTRIBUTE_UNUSED)
1132 for (str = name; *str != '\0'; str++)
1134 error ("Name `%s' contains quotes", name);
1138 /* Pointers to all declarations during IR generation are stored in the
1140 static VEC(decl_t, heap) *decls;
1142 /* Given a pointer to a (char *) and a separator, return an alloc'ed
1143 string containing the next separated element, taking parentheses
1144 into account if PAR_FLAG has nonzero value. Advance the pointer to
1145 after the string scanned, or the end-of-string. Return NULL if at
1148 next_sep_el (const char **pstr, int sep, int par_flag)
1155 /* Remove leading whitespaces. */
1156 while (ISSPACE ((int) **pstr))
1163 for (pars_num = 0, p = *pstr; *p != '\0'; p++)
1165 if (par_flag && *p == '(')
1167 else if (par_flag && *p == ')')
1169 else if (pars_num == 0 && *p == sep)
1171 if (pars_num == 0 && ISSPACE ((int) *p))
1175 for (; n_spaces != 0; n_spaces--)
1176 obstack_1grow (&irp, p [-n_spaces]);
1177 obstack_1grow (&irp, *p);
1180 obstack_1grow (&irp, '\0');
1181 out_str = obstack_base (&irp);
1182 obstack_finish (&irp);
1191 /* Given a string and a separator, return the number of separated
1192 elements in it, taking parentheses into account if PAR_FLAG has
1193 nonzero value. Return 0 for the null string, -1 if parentheses is
1196 n_sep_els (const char *s, int sep, int par_flag)
1204 for (pars_num = 0, n = 1; *s; s++)
1205 if (par_flag && *s == '(')
1207 else if (par_flag && *s == ')')
1209 else if (pars_num == 0 && *s == sep)
1212 return (pars_num != 0 ? -1 : n);
1215 /* Given a string and a separator, return vector of strings which are
1216 elements in the string and number of elements through els_num.
1217 Take parentheses into account if PAREN_P has nonzero value. The
1218 function also inserts the end marker NULL at the end of vector.
1219 Return 0 for the null string, -1 if parentheses are not balanced. */
1221 get_str_vect (const char *str, int *els_num, int sep, int paren_p)
1228 *els_num = n_sep_els (str, sep, paren_p);
1231 obstack_blank (&irp, sizeof (char *) * (*els_num + 1));
1232 vect = (char **) obstack_base (&irp);
1233 obstack_finish (&irp);
1235 for (i = 0; i < *els_num; i++)
1236 vect [i] = next_sep_el (pstr, sep, paren_p);
1237 trail = next_sep_el (pstr, sep, paren_p);
1238 gcc_assert (!trail);
1243 /* Process a DEFINE_CPU_UNIT.
1245 This gives information about a unit contained in CPU. We fill a
1246 struct unit_decl with information used later by `expand_automata'. */
1248 gen_cpu_unit (rtx def)
1251 char **str_cpu_units;
1255 str_cpu_units = get_str_vect (XSTR (def, 0), &vect_length, ',', FALSE);
1256 if (str_cpu_units == NULL)
1257 fatal ("invalid string `%s' in define_cpu_unit", XSTR (def, 0));
1258 for (i = 0; i < vect_length; i++)
1260 decl = XCREATENODE (struct decl);
1261 decl->mode = dm_unit;
1263 DECL_UNIT (decl)->name = check_name (str_cpu_units [i], decl->pos);
1264 DECL_UNIT (decl)->automaton_name = XSTR (def, 1);
1265 DECL_UNIT (decl)->query_p = 0;
1266 DECL_UNIT (decl)->min_occ_cycle_num = -1;
1267 DECL_UNIT (decl)->in_set_p = 0;
1268 VEC_safe_push (decl_t, heap, decls, decl);
1272 /* Process a DEFINE_QUERY_CPU_UNIT.
1274 This gives information about a unit contained in CPU. We fill a
1275 struct unit_decl with information used later by `expand_automata'. */
1277 gen_query_cpu_unit (rtx def)
1280 char **str_cpu_units;
1284 str_cpu_units = get_str_vect (XSTR (def, 0), &vect_length, ',',
1286 if (str_cpu_units == NULL)
1287 fatal ("invalid string `%s' in define_query_cpu_unit", XSTR (def, 0));
1288 for (i = 0; i < vect_length; i++)
1290 decl = XCREATENODE (struct decl);
1291 decl->mode = dm_unit;
1293 DECL_UNIT (decl)->name = check_name (str_cpu_units [i], decl->pos);
1294 DECL_UNIT (decl)->automaton_name = XSTR (def, 1);
1295 DECL_UNIT (decl)->query_p = 1;
1296 VEC_safe_push (decl_t, heap, decls, decl);
1300 /* Process a DEFINE_BYPASS.
1302 This gives information about a unit contained in the CPU. We fill
1303 in a struct bypass_decl with information used later by
1304 `expand_automata'. */
1306 gen_bypass (rtx def)
1315 out_insns = get_str_vect (XSTR (def, 1), &out_length, ',', FALSE);
1316 if (out_insns == NULL)
1317 fatal ("invalid string `%s' in define_bypass", XSTR (def, 1));
1318 in_insns = get_str_vect (XSTR (def, 2), &in_length, ',', FALSE);
1319 if (in_insns == NULL)
1320 fatal ("invalid string `%s' in define_bypass", XSTR (def, 2));
1321 for (i = 0; i < out_length; i++)
1322 for (j = 0; j < in_length; j++)
1324 decl = XCREATENODE (struct decl);
1325 decl->mode = dm_bypass;
1327 DECL_BYPASS (decl)->latency = XINT (def, 0);
1328 DECL_BYPASS (decl)->out_insn_name = out_insns [i];
1329 DECL_BYPASS (decl)->in_insn_name = in_insns [j];
1330 DECL_BYPASS (decl)->bypass_guard_name = XSTR (def, 3);
1331 VEC_safe_push (decl_t, heap, decls, decl);
1335 /* Process an EXCLUSION_SET.
1337 This gives information about a cpu unit conflicts. We fill a
1338 struct excl_rel_decl (excl) with information used later by
1339 `expand_automata'. */
1341 gen_excl_set (rtx def)
1344 char **first_str_cpu_units;
1345 char **second_str_cpu_units;
1346 int first_vect_length;
1351 = get_str_vect (XSTR (def, 0), &first_vect_length, ',', FALSE);
1352 if (first_str_cpu_units == NULL)
1353 fatal ("invalid first string `%s' in exclusion_set", XSTR (def, 0));
1354 second_str_cpu_units = get_str_vect (XSTR (def, 1), &length, ',',
1356 if (second_str_cpu_units == NULL)
1357 fatal ("invalid second string `%s' in exclusion_set", XSTR (def, 1));
1358 length += first_vect_length;
1359 decl = XCREATENODEVAR (struct decl, sizeof (struct decl) + (length - 1) * sizeof (char *));
1360 decl->mode = dm_excl;
1362 DECL_EXCL (decl)->all_names_num = length;
1363 DECL_EXCL (decl)->first_list_length = first_vect_length;
1364 for (i = 0; i < length; i++)
1365 if (i < first_vect_length)
1366 DECL_EXCL (decl)->names [i] = first_str_cpu_units [i];
1368 DECL_EXCL (decl)->names [i]
1369 = second_str_cpu_units [i - first_vect_length];
1370 VEC_safe_push (decl_t, heap, decls, decl);
1373 /* Process a PRESENCE_SET, a FINAL_PRESENCE_SET, an ABSENCE_SET,
1374 FINAL_ABSENCE_SET (it is depended on PRESENCE_P and FINAL_P).
1376 This gives information about a cpu unit reservation requirements.
1377 We fill a struct unit_pattern_rel_decl with information used later
1378 by `expand_automata'. */
1380 gen_presence_absence_set (rtx def, int presence_p, int final_p)
1383 char **str_cpu_units;
1384 char **str_pattern_lists;
1385 char ***str_patterns;
1386 int cpu_units_length;
1388 int patterns_length;
1391 str_cpu_units = get_str_vect (XSTR (def, 0), &cpu_units_length, ',',
1393 if (str_cpu_units == NULL)
1396 ? "invalid first string `%s' in final_presence_set"
1397 : "invalid first string `%s' in presence_set")
1399 ? "invalid first string `%s' in final_absence_set"
1400 : "invalid first string `%s' in absence_set")),
1402 str_pattern_lists = get_str_vect (XSTR (def, 1),
1403 &patterns_length, ',', FALSE);
1404 if (str_pattern_lists == NULL)
1407 ? "invalid second string `%s' in final_presence_set"
1408 : "invalid second string `%s' in presence_set")
1410 ? "invalid second string `%s' in final_absence_set"
1411 : "invalid second string `%s' in absence_set")), XSTR (def, 1));
1412 str_patterns = XOBNEWVEC (&irp, char **, patterns_length);
1413 for (i = 0; i < patterns_length; i++)
1415 str_patterns [i] = get_str_vect (str_pattern_lists [i],
1416 &length, ' ', FALSE);
1417 gcc_assert (str_patterns [i]);
1419 decl = XCREATENODE (struct decl);
1423 decl->mode = dm_presence;
1424 DECL_PRESENCE (decl)->names_num = cpu_units_length;
1425 DECL_PRESENCE (decl)->names = str_cpu_units;
1426 DECL_PRESENCE (decl)->patterns = str_patterns;
1427 DECL_PRESENCE (decl)->patterns_num = patterns_length;
1428 DECL_PRESENCE (decl)->final_p = final_p;
1432 decl->mode = dm_absence;
1433 DECL_ABSENCE (decl)->names_num = cpu_units_length;
1434 DECL_ABSENCE (decl)->names = str_cpu_units;
1435 DECL_ABSENCE (decl)->patterns = str_patterns;
1436 DECL_ABSENCE (decl)->patterns_num = patterns_length;
1437 DECL_ABSENCE (decl)->final_p = final_p;
1439 VEC_safe_push (decl_t, heap, decls, decl);
1442 /* Process a PRESENCE_SET.
1444 This gives information about a cpu unit reservation requirements.
1445 We fill a struct unit_pattern_rel_decl (presence) with information
1446 used later by `expand_automata'. */
1448 gen_presence_set (rtx def)
1450 gen_presence_absence_set (def, TRUE, FALSE);
1453 /* Process a FINAL_PRESENCE_SET.
1455 This gives information about a cpu unit reservation requirements.
1456 We fill a struct unit_pattern_rel_decl (presence) with information
1457 used later by `expand_automata'. */
1459 gen_final_presence_set (rtx def)
1461 gen_presence_absence_set (def, TRUE, TRUE);
1464 /* Process an ABSENCE_SET.
1466 This gives information about a cpu unit reservation requirements.
1467 We fill a struct unit_pattern_rel_decl (absence) with information
1468 used later by `expand_automata'. */
1470 gen_absence_set (rtx def)
1472 gen_presence_absence_set (def, FALSE, FALSE);
1475 /* Process a FINAL_ABSENCE_SET.
1477 This gives information about a cpu unit reservation requirements.
1478 We fill a struct unit_pattern_rel_decl (absence) with information
1479 used later by `expand_automata'. */
1481 gen_final_absence_set (rtx def)
1483 gen_presence_absence_set (def, FALSE, TRUE);
1486 /* Process a DEFINE_AUTOMATON.
1488 This gives information about a finite state automaton used for
1489 recognizing pipeline hazards. We fill a struct automaton_decl
1490 with information used later by `expand_automata'. */
1492 gen_automaton (rtx def)
1495 char **str_automata;
1499 str_automata = get_str_vect (XSTR (def, 0), &vect_length, ',', FALSE);
1500 if (str_automata == NULL)
1501 fatal ("invalid string `%s' in define_automaton", XSTR (def, 0));
1502 for (i = 0; i < vect_length; i++)
1504 decl = XCREATENODE (struct decl);
1505 decl->mode = dm_automaton;
1507 DECL_AUTOMATON (decl)->name = check_name (str_automata [i], decl->pos);
1508 VEC_safe_push (decl_t, heap, decls, decl);
1512 /* Process an AUTOMATA_OPTION.
1514 This gives information how to generate finite state automaton used
1515 for recognizing pipeline hazards. */
1517 gen_automata_option (rtx def)
1519 if (strcmp (XSTR (def, 0), NO_MINIMIZATION_OPTION + 1) == 0)
1520 no_minimization_flag = 1;
1521 else if (strcmp (XSTR (def, 0), TIME_OPTION + 1) == 0)
1523 else if (strcmp (XSTR (def, 0), STATS_OPTION + 1) == 0)
1525 else if (strcmp (XSTR (def, 0), V_OPTION + 1) == 0)
1527 else if (strcmp (XSTR (def, 0), W_OPTION + 1) == 0)
1529 else if (strcmp (XSTR (def, 0), NDFA_OPTION + 1) == 0)
1531 else if (strcmp (XSTR (def, 0), PROGRESS_OPTION + 1) == 0)
1534 fatal ("invalid option `%s' in automata_option", XSTR (def, 0));
1537 /* Name in reservation to denote absence reservation. */
1538 #define NOTHING_NAME "nothing"
1540 /* The following string contains original reservation string being
1542 static const char *reserv_str;
1544 /* Parse an element in STR. */
1546 gen_regexp_el (const char *str)
1555 if (str [len - 1] != ')')
1556 fatal ("garbage after ) in reservation `%s'", reserv_str);
1557 dstr = XALLOCAVAR (char, len - 1);
1558 memcpy (dstr, str + 1, len - 2);
1559 dstr [len-2] = '\0';
1560 regexp = gen_regexp_sequence (dstr);
1562 else if (strcmp (str, NOTHING_NAME) == 0)
1564 regexp = XCREATENODE (struct regexp);
1565 regexp->mode = rm_nothing;
1569 regexp = XCREATENODE (struct regexp);
1570 regexp->mode = rm_unit;
1571 REGEXP_UNIT (regexp)->name = str;
1576 /* Parse construction `repeat' in STR. */
1578 gen_regexp_repeat (const char *str)
1586 repeat_vect = get_str_vect (str, &els_num, '*', TRUE);
1587 if (repeat_vect == NULL)
1588 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1591 regexp = gen_regexp_el (repeat_vect [0]);
1592 for (i = 1; i < els_num; i++)
1594 repeat = XCREATENODE (struct regexp);
1595 repeat->mode = rm_repeat;
1596 REGEXP_REPEAT (repeat)->regexp = regexp;
1597 REGEXP_REPEAT (repeat)->repeat_num = atoi (repeat_vect [i]);
1598 if (REGEXP_REPEAT (repeat)->repeat_num <= 1)
1599 fatal ("repetition `%s' <= 1 in reservation `%s'",
1606 return gen_regexp_el (str);
1609 /* Parse reservation STR which possibly contains separator '+'. */
1611 gen_regexp_allof (const char *str)
1618 allof_vect = get_str_vect (str, &els_num, '+', TRUE);
1619 if (allof_vect == NULL)
1620 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1623 allof = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
1624 + sizeof (regexp_t) * (els_num - 1));
1625 allof->mode = rm_allof;
1626 REGEXP_ALLOF (allof)->regexps_num = els_num;
1627 for (i = 0; i < els_num; i++)
1628 REGEXP_ALLOF (allof)->regexps [i] = gen_regexp_repeat (allof_vect [i]);
1632 return gen_regexp_repeat (str);
1635 /* Parse reservation STR which possibly contains separator '|'. */
1637 gen_regexp_oneof (const char *str)
1644 oneof_vect = get_str_vect (str, &els_num, '|', TRUE);
1645 if (oneof_vect == NULL)
1646 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1649 oneof = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
1650 + sizeof (regexp_t) * (els_num - 1));
1651 oneof->mode = rm_oneof;
1652 REGEXP_ONEOF (oneof)->regexps_num = els_num;
1653 for (i = 0; i < els_num; i++)
1654 REGEXP_ONEOF (oneof)->regexps [i] = gen_regexp_allof (oneof_vect [i]);
1658 return gen_regexp_allof (str);
1661 /* Parse reservation STR which possibly contains separator ','. */
1663 gen_regexp_sequence (const char *str)
1666 char **sequence_vect;
1670 sequence_vect = get_str_vect (str, &els_num, ',', TRUE);
1673 sequence = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
1674 + sizeof (regexp_t) * (els_num - 1));
1675 sequence->mode = rm_sequence;
1676 REGEXP_SEQUENCE (sequence)->regexps_num = els_num;
1677 for (i = 0; i < els_num; i++)
1678 REGEXP_SEQUENCE (sequence)->regexps [i]
1679 = gen_regexp_oneof (sequence_vect [i]);
1683 return gen_regexp_oneof (str);
1686 /* Parse construction reservation STR. */
1688 gen_regexp (const char *str)
1691 return gen_regexp_sequence (str);;
1694 /* Process a DEFINE_RESERVATION.
1696 This gives information about a reservation of cpu units. We fill
1697 in a struct reserv_decl with information used later by
1698 `expand_automata'. */
1700 gen_reserv (rtx def)
1704 decl = XCREATENODE (struct decl);
1705 decl->mode = dm_reserv;
1707 DECL_RESERV (decl)->name = check_name (XSTR (def, 0), decl->pos);
1708 DECL_RESERV (decl)->regexp = gen_regexp (XSTR (def, 1));
1709 VEC_safe_push (decl_t, heap, decls, decl);
1712 /* Process a DEFINE_INSN_RESERVATION.
1714 This gives information about the reservation of cpu units by an
1715 insn. We fill a struct insn_reserv_decl with information used
1716 later by `expand_automata'. */
1718 gen_insn_reserv (rtx def)
1722 decl = XCREATENODE (struct decl);
1723 decl->mode = dm_insn_reserv;
1725 DECL_INSN_RESERV (decl)->name
1726 = check_name (XSTR (def, 0), decl->pos);
1727 DECL_INSN_RESERV (decl)->default_latency = XINT (def, 1);
1728 DECL_INSN_RESERV (decl)->condexp = XEXP (def, 2);
1729 DECL_INSN_RESERV (decl)->regexp = gen_regexp (XSTR (def, 3));
1730 VEC_safe_push (decl_t, heap, decls, decl);
1735 /* The function evaluates hash value (0..UINT_MAX) of string. */
1737 string_hash (const char *string)
1741 for (result = i = 0;*string++ != '\0'; i++)
1742 result += ((unsigned char) *string << (i % CHAR_BIT));
1748 /* This page contains abstract data `table of automaton declarations'.
1749 Elements of the table is nodes representing automaton declarations.
1750 Key of the table elements is name of given automaton. Remember
1751 that automaton names have own space. */
1753 /* The function evaluates hash value of an automaton declaration. The
1754 function is used by abstract data `hashtab'. The function returns
1755 hash value (0..UINT_MAX) of given automaton declaration. */
1757 automaton_decl_hash (const void *automaton_decl)
1759 const_decl_t const decl = (const_decl_t) automaton_decl;
1761 gcc_assert (decl->mode != dm_automaton
1762 || DECL_AUTOMATON (decl)->name);
1763 return string_hash (DECL_AUTOMATON (decl)->name);
1766 /* The function tests automaton declarations on equality of their
1767 keys. The function is used by abstract data `hashtab'. The
1768 function returns 1 if the declarations have the same key, 0
1771 automaton_decl_eq_p (const void* automaton_decl_1,
1772 const void* automaton_decl_2)
1774 const_decl_t const decl1 = (const_decl_t) automaton_decl_1;
1775 const_decl_t const decl2 = (const_decl_t) automaton_decl_2;
1777 gcc_assert (decl1->mode == dm_automaton
1778 && DECL_AUTOMATON (decl1)->name
1779 && decl2->mode == dm_automaton
1780 && DECL_AUTOMATON (decl2)->name);
1781 return strcmp (DECL_AUTOMATON (decl1)->name,
1782 DECL_AUTOMATON (decl2)->name) == 0;
1785 /* The automaton declaration table itself is represented by the
1786 following variable. */
1787 static htab_t automaton_decl_table;
1789 /* The function inserts automaton declaration into the table. The
1790 function does nothing if an automaton declaration with the same key
1791 exists already in the table. The function returns automaton
1792 declaration node in the table with the same key as given automaton
1793 declaration node. */
1795 insert_automaton_decl (decl_t automaton_decl)
1799 entry_ptr = htab_find_slot (automaton_decl_table, automaton_decl, INSERT);
1800 if (*entry_ptr == NULL)
1801 *entry_ptr = (void *) automaton_decl;
1802 return (decl_t) *entry_ptr;
1805 /* The following variable value is node representing automaton
1806 declaration. The node used for searching automaton declaration
1808 static struct decl work_automaton_decl;
1810 /* The function searches for automaton declaration in the table with
1811 the same key as node representing name of the automaton
1812 declaration. The function returns node found in the table, NULL if
1813 such node does not exist in the table. */
1815 find_automaton_decl (const char *name)
1819 work_automaton_decl.mode = dm_automaton;
1820 DECL_AUTOMATON (&work_automaton_decl)->name = name;
1821 entry = htab_find (automaton_decl_table, &work_automaton_decl);
1822 return (decl_t) entry;
1825 /* The function creates empty automaton declaration table and node
1826 representing automaton declaration and used for searching automaton
1827 declaration with given name. The function must be called only once
1828 before any work with the automaton declaration table. */
1830 initiate_automaton_decl_table (void)
1832 work_automaton_decl.mode = dm_automaton;
1833 automaton_decl_table = htab_create (10, automaton_decl_hash,
1834 automaton_decl_eq_p, (htab_del) 0);
1837 /* The function deletes the automaton declaration table. Only call of
1838 function `initiate_automaton_decl_table' is possible immediately
1839 after this function call. */
1841 finish_automaton_decl_table (void)
1843 htab_delete (automaton_decl_table);
1848 /* This page contains abstract data `table of insn declarations'.
1849 Elements of the table is nodes representing insn declarations. Key
1850 of the table elements is name of given insn (in corresponding
1851 define_insn_reservation). Remember that insn names have own
1854 /* The function evaluates hash value of an insn declaration. The
1855 function is used by abstract data `hashtab'. The function returns
1856 hash value (0..UINT_MAX) of given insn declaration. */
1858 insn_decl_hash (const void *insn_decl)
1860 const_decl_t const decl = (const_decl_t) insn_decl;
1862 gcc_assert (decl->mode == dm_insn_reserv
1863 && DECL_INSN_RESERV (decl)->name);
1864 return string_hash (DECL_INSN_RESERV (decl)->name);
1867 /* The function tests insn declarations on equality of their keys.
1868 The function is used by abstract data `hashtab'. The function
1869 returns 1 if declarations have the same key, 0 otherwise. */
1871 insn_decl_eq_p (const void *insn_decl_1, const void *insn_decl_2)
1873 const_decl_t const decl1 = (const_decl_t) insn_decl_1;
1874 const_decl_t const decl2 = (const_decl_t) insn_decl_2;
1876 gcc_assert (decl1->mode == dm_insn_reserv
1877 && DECL_INSN_RESERV (decl1)->name
1878 && decl2->mode == dm_insn_reserv
1879 && DECL_INSN_RESERV (decl2)->name);
1880 return strcmp (DECL_INSN_RESERV (decl1)->name,
1881 DECL_INSN_RESERV (decl2)->name) == 0;
1884 /* The insn declaration table itself is represented by the following
1885 variable. The table does not contain insn reservation
1887 static htab_t insn_decl_table;
1889 /* The function inserts insn declaration into the table. The function
1890 does nothing if an insn declaration with the same key exists
1891 already in the table. The function returns insn declaration node
1892 in the table with the same key as given insn declaration node. */
1894 insert_insn_decl (decl_t insn_decl)
1898 entry_ptr = htab_find_slot (insn_decl_table, insn_decl, INSERT);
1899 if (*entry_ptr == NULL)
1900 *entry_ptr = (void *) insn_decl;
1901 return (decl_t) *entry_ptr;
1904 /* The following variable value is node representing insn reservation
1905 declaration. The node used for searching insn reservation
1906 declaration with given name. */
1907 static struct decl work_insn_decl;
1909 /* The function searches for insn reservation declaration in the table
1910 with the same key as node representing name of the insn reservation
1911 declaration. The function returns node found in the table, NULL if
1912 such node does not exist in the table. */
1914 find_insn_decl (const char *name)
1918 work_insn_decl.mode = dm_insn_reserv;
1919 DECL_INSN_RESERV (&work_insn_decl)->name = name;
1920 entry = htab_find (insn_decl_table, &work_insn_decl);
1921 return (decl_t) entry;
1924 /* The function creates empty insn declaration table and node
1925 representing insn declaration and used for searching insn
1926 declaration with given name. The function must be called only once
1927 before any work with the insn declaration table. */
1929 initiate_insn_decl_table (void)
1931 work_insn_decl.mode = dm_insn_reserv;
1932 insn_decl_table = htab_create (10, insn_decl_hash, insn_decl_eq_p,
1936 /* The function deletes the insn declaration table. Only call of
1937 function `initiate_insn_decl_table' is possible immediately after
1938 this function call. */
1940 finish_insn_decl_table (void)
1942 htab_delete (insn_decl_table);
1947 /* This page contains abstract data `table of declarations'. Elements
1948 of the table is nodes representing declarations (of units and
1949 reservations). Key of the table elements is names of given
1952 /* The function evaluates hash value of a declaration. The function
1953 is used by abstract data `hashtab'. The function returns hash
1954 value (0..UINT_MAX) of given declaration. */
1956 decl_hash (const void *decl)
1958 const_decl_t const d = (const_decl_t) decl;
1960 gcc_assert ((d->mode == dm_unit && DECL_UNIT (d)->name)
1961 || (d->mode == dm_reserv && DECL_RESERV (d)->name));
1962 return string_hash (d->mode == dm_unit
1963 ? DECL_UNIT (d)->name : DECL_RESERV (d)->name);
1966 /* The function tests declarations on equality of their keys. The
1967 function is used by abstract data 'hashtab'. The function
1968 returns 1 if the declarations have the same key, 0 otherwise. */
1970 decl_eq_p (const void *decl_1, const void *decl_2)
1972 const_decl_t const d1 = (const_decl_t) decl_1;
1973 const_decl_t const d2 = (const_decl_t) decl_2;
1975 gcc_assert ((d1->mode == dm_unit && DECL_UNIT (d1)->name)
1976 || (d1->mode == dm_reserv && DECL_RESERV (d1)->name));
1977 gcc_assert ((d2->mode == dm_unit && DECL_UNIT (d2)->name)
1978 || (d2->mode == dm_reserv && DECL_RESERV (d2)->name));
1979 return strcmp ((d1->mode == dm_unit
1980 ? DECL_UNIT (d1)->name : DECL_RESERV (d1)->name),
1981 (d2->mode == dm_unit
1982 ? DECL_UNIT (d2)->name : DECL_RESERV (d2)->name)) == 0;
1985 /* The declaration table itself is represented by the following
1987 static htab_t decl_table;
1989 /* The function inserts declaration into the table. The function does
1990 nothing if a declaration with the same key exists already in the
1991 table. The function returns declaration node in the table with the
1992 same key as given declaration node. */
1995 insert_decl (decl_t decl)
1999 entry_ptr = htab_find_slot (decl_table, decl, INSERT);
2000 if (*entry_ptr == NULL)
2001 *entry_ptr = (void *) decl;
2002 return (decl_t) *entry_ptr;
2005 /* The following variable value is node representing declaration. The
2006 node used for searching declaration with given name. */
2007 static struct decl work_decl;
2009 /* The function searches for declaration in the table with the same
2010 key as node representing name of the declaration. The function
2011 returns node found in the table, NULL if such node does not exist
2014 find_decl (const char *name)
2018 work_decl.mode = dm_unit;
2019 DECL_UNIT (&work_decl)->name = name;
2020 entry = htab_find (decl_table, &work_decl);
2021 return (decl_t) entry;
2024 /* The function creates empty declaration table and node representing
2025 declaration and used for searching declaration with given name.
2026 The function must be called only once before any work with the
2027 declaration table. */
2029 initiate_decl_table (void)
2031 work_decl.mode = dm_unit;
2032 decl_table = htab_create (10, decl_hash, decl_eq_p, (htab_del) 0);
2035 /* The function deletes the declaration table. Only call of function
2036 `initiate_declaration_table' is possible immediately after this
2039 finish_decl_table (void)
2041 htab_delete (decl_table);
2046 /* This page contains checker of pipeline hazard description. */
2048 /* Checking NAMES in an exclusion clause vector and returning formed
2049 unit_set_el_list. */
2050 static unit_set_el_t
2051 process_excls (char **names, int num, pos_t excl_pos ATTRIBUTE_UNUSED)
2053 unit_set_el_t el_list;
2054 unit_set_el_t last_el;
2055 unit_set_el_t new_el;
2056 decl_t decl_in_table;
2061 for (i = 0; i < num; i++)
2063 decl_in_table = find_decl (names [i]);
2064 if (decl_in_table == NULL)
2065 error ("unit `%s' in exclusion is not declared", names [i]);
2066 else if (decl_in_table->mode != dm_unit)
2067 error ("`%s' in exclusion is not unit", names [i]);
2070 new_el = XCREATENODE (struct unit_set_el);
2071 new_el->unit_decl = DECL_UNIT (decl_in_table);
2072 new_el->next_unit_set_el = NULL;
2073 if (last_el == NULL)
2074 el_list = last_el = new_el;
2077 last_el->next_unit_set_el = new_el;
2078 last_el = last_el->next_unit_set_el;
2085 /* The function adds each element from SOURCE_LIST to the exclusion
2086 list of the each element from DEST_LIST. Checking situation "unit
2087 excludes itself". */
2089 add_excls (unit_set_el_t dest_list, unit_set_el_t source_list,
2090 pos_t excl_pos ATTRIBUTE_UNUSED)
2094 unit_set_el_t curr_el;
2095 unit_set_el_t prev_el;
2098 for (dst = dest_list; dst != NULL; dst = dst->next_unit_set_el)
2099 for (src = source_list; src != NULL; src = src->next_unit_set_el)
2101 if (dst->unit_decl == src->unit_decl)
2103 error ("unit `%s' excludes itself", src->unit_decl->name);
2106 if (dst->unit_decl->automaton_name != NULL
2107 && src->unit_decl->automaton_name != NULL
2108 && strcmp (dst->unit_decl->automaton_name,
2109 src->unit_decl->automaton_name) != 0)
2111 error ("units `%s' and `%s' in exclusion set belong to different automata",
2112 src->unit_decl->name, dst->unit_decl->name);
2115 for (curr_el = dst->unit_decl->excl_list, prev_el = NULL;
2117 prev_el = curr_el, curr_el = curr_el->next_unit_set_el)
2118 if (curr_el->unit_decl == src->unit_decl)
2120 if (curr_el == NULL)
2122 /* Element not found - insert. */
2123 copy = XCOPYNODE (struct unit_set_el, src);
2124 copy->next_unit_set_el = NULL;
2125 if (prev_el == NULL)
2126 dst->unit_decl->excl_list = copy;
2128 prev_el->next_unit_set_el = copy;
2133 /* Checking NAMES in presence/absence clause and returning the
2134 formed unit_set_el_list. The function is called only after
2135 processing all exclusion sets. */
2136 static unit_set_el_t
2137 process_presence_absence_names (char **names, int num,
2138 pos_t req_pos ATTRIBUTE_UNUSED,
2139 int presence_p, int final_p)
2141 unit_set_el_t el_list;
2142 unit_set_el_t last_el;
2143 unit_set_el_t new_el;
2144 decl_t decl_in_table;
2149 for (i = 0; i < num; i++)
2151 decl_in_table = find_decl (names [i]);
2152 if (decl_in_table == NULL)
2155 ? "unit `%s' in final presence set is not declared"
2156 : "unit `%s' in presence set is not declared")
2158 ? "unit `%s' in final absence set is not declared"
2159 : "unit `%s' in absence set is not declared")), names [i]);
2160 else if (decl_in_table->mode != dm_unit)
2163 ? "`%s' in final presence set is not unit"
2164 : "`%s' in presence set is not unit")
2166 ? "`%s' in final absence set is not unit"
2167 : "`%s' in absence set is not unit")), names [i]);
2170 new_el = XCREATENODE (struct unit_set_el);
2171 new_el->unit_decl = DECL_UNIT (decl_in_table);
2172 new_el->next_unit_set_el = NULL;
2173 if (last_el == NULL)
2174 el_list = last_el = new_el;
2177 last_el->next_unit_set_el = new_el;
2178 last_el = last_el->next_unit_set_el;
2185 /* Checking NAMES in patterns of a presence/absence clause and
2186 returning the formed pattern_set_el_list. The function is called
2187 only after processing all exclusion sets. */
2188 static pattern_set_el_t
2189 process_presence_absence_patterns (char ***patterns, int num,
2190 pos_t req_pos ATTRIBUTE_UNUSED,
2191 int presence_p, int final_p)
2193 pattern_set_el_t el_list;
2194 pattern_set_el_t last_el;
2195 pattern_set_el_t new_el;
2196 decl_t decl_in_table;
2201 for (i = 0; i < num; i++)
2203 for (j = 0; patterns [i] [j] != NULL; j++)
2205 new_el = XCREATENODEVAR (struct pattern_set_el,
2206 sizeof (struct pattern_set_el)
2207 + sizeof (struct unit_decl *) * j);
2209 = (struct unit_decl **) ((char *) new_el
2210 + sizeof (struct pattern_set_el));
2211 new_el->next_pattern_set_el = NULL;
2212 if (last_el == NULL)
2213 el_list = last_el = new_el;
2216 last_el->next_pattern_set_el = new_el;
2217 last_el = last_el->next_pattern_set_el;
2219 new_el->units_num = 0;
2220 for (j = 0; patterns [i] [j] != NULL; j++)
2222 decl_in_table = find_decl (patterns [i] [j]);
2223 if (decl_in_table == NULL)
2226 ? "unit `%s' in final presence set is not declared"
2227 : "unit `%s' in presence set is not declared")
2229 ? "unit `%s' in final absence set is not declared"
2230 : "unit `%s' in absence set is not declared")),
2232 else if (decl_in_table->mode != dm_unit)
2235 ? "`%s' in final presence set is not unit"
2236 : "`%s' in presence set is not unit")
2238 ? "`%s' in final absence set is not unit"
2239 : "`%s' in absence set is not unit")),
2243 new_el->unit_decls [new_el->units_num]
2244 = DECL_UNIT (decl_in_table);
2245 new_el->units_num++;
2252 /* The function adds each element from PATTERN_LIST to presence (if
2253 PRESENCE_P) or absence list of the each element from DEST_LIST.
2254 Checking situations "unit requires own absence", and "unit excludes
2255 and requires presence of ...", "unit requires absence and presence
2256 of ...", "units in (final) presence set belong to different
2257 automata", and "units in (final) absence set belong to different
2258 automata". Remember that we process absence sets only after all
2261 add_presence_absence (unit_set_el_t dest_list,
2262 pattern_set_el_t pattern_list,
2263 pos_t req_pos ATTRIBUTE_UNUSED,
2264 int presence_p, int final_p)
2267 pattern_set_el_t pat;
2268 struct unit_decl *unit;
2269 unit_set_el_t curr_excl_el;
2270 pattern_set_el_t curr_pat_el;
2271 pattern_set_el_t prev_el;
2272 pattern_set_el_t copy;
2276 for (dst = dest_list; dst != NULL; dst = dst->next_unit_set_el)
2277 for (pat = pattern_list; pat != NULL; pat = pat->next_pattern_set_el)
2279 for (i = 0; i < pat->units_num; i++)
2281 unit = pat->unit_decls [i];
2282 if (dst->unit_decl == unit && pat->units_num == 1 && !presence_p)
2284 error ("unit `%s' requires own absence", unit->name);
2287 if (dst->unit_decl->automaton_name != NULL
2288 && unit->automaton_name != NULL
2289 && strcmp (dst->unit_decl->automaton_name,
2290 unit->automaton_name) != 0)
2294 ? "units `%s' and `%s' in final presence set belong to different automata"
2295 : "units `%s' and `%s' in presence set belong to different automata")
2297 ? "units `%s' and `%s' in final absence set belong to different automata"
2298 : "units `%s' and `%s' in absence set belong to different automata")),
2299 unit->name, dst->unit_decl->name);
2304 for (curr_excl_el = dst->unit_decl->excl_list;
2305 curr_excl_el != NULL;
2306 curr_excl_el = curr_excl_el->next_unit_set_el)
2308 if (unit == curr_excl_el->unit_decl && pat->units_num == 1)
2312 error ("unit `%s' excludes and requires presence of `%s'",
2313 dst->unit_decl->name, unit->name);
2317 warning ("unit `%s' excludes and requires presence of `%s'",
2318 dst->unit_decl->name, unit->name);
2321 else if (pat->units_num == 1)
2322 for (curr_pat_el = dst->unit_decl->presence_list;
2323 curr_pat_el != NULL;
2324 curr_pat_el = curr_pat_el->next_pattern_set_el)
2325 if (curr_pat_el->units_num == 1
2326 && unit == curr_pat_el->unit_decls [0])
2330 error ("unit `%s' requires absence and presence of `%s'",
2331 dst->unit_decl->name, unit->name);
2335 warning ("unit `%s' requires absence and presence of `%s'",
2336 dst->unit_decl->name, unit->name);
2340 for (prev_el = (presence_p
2342 ? dst->unit_decl->final_presence_list
2343 : dst->unit_decl->final_presence_list)
2345 ? dst->unit_decl->final_absence_list
2346 : dst->unit_decl->absence_list));
2347 prev_el != NULL && prev_el->next_pattern_set_el != NULL;
2348 prev_el = prev_el->next_pattern_set_el)
2350 copy = XCOPYNODE (struct pattern_set_el, pat);
2351 copy->next_pattern_set_el = NULL;
2352 if (prev_el == NULL)
2357 dst->unit_decl->final_presence_list = copy;
2359 dst->unit_decl->presence_list = copy;
2362 dst->unit_decl->final_absence_list = copy;
2364 dst->unit_decl->absence_list = copy;
2367 prev_el->next_pattern_set_el = copy;
2374 /* The function inserts BYPASS in the list of bypasses of the
2375 corresponding output insn. The order of bypasses in the list is
2376 decribed in a comment for member `bypass_list' (see above). If
2377 there is already the same bypass in the list the function reports
2378 this and does nothing. */
2380 insert_bypass (struct bypass_decl *bypass)
2382 struct bypass_decl *curr, *last;
2383 struct insn_reserv_decl *out_insn_reserv = bypass->out_insn_reserv;
2384 struct insn_reserv_decl *in_insn_reserv = bypass->in_insn_reserv;
2386 for (curr = out_insn_reserv->bypass_list, last = NULL;
2388 last = curr, curr = curr->next)
2389 if (curr->in_insn_reserv == in_insn_reserv)
2391 if ((bypass->bypass_guard_name != NULL
2392 && curr->bypass_guard_name != NULL
2393 && ! strcmp (bypass->bypass_guard_name, curr->bypass_guard_name))
2394 || bypass->bypass_guard_name == curr->bypass_guard_name)
2396 if (bypass->bypass_guard_name == NULL)
2399 error ("the same bypass `%s - %s' is already defined",
2400 bypass->out_insn_name, bypass->in_insn_name);
2402 warning ("the same bypass `%s - %s' is already defined",
2403 bypass->out_insn_name, bypass->in_insn_name);
2406 error ("the same bypass `%s - %s' (guard %s) is already defined",
2407 bypass->out_insn_name, bypass->in_insn_name,
2408 bypass->bypass_guard_name);
2411 ("the same bypass `%s - %s' (guard %s) is already defined",
2412 bypass->out_insn_name, bypass->in_insn_name,
2413 bypass->bypass_guard_name);
2416 if (curr->bypass_guard_name == NULL)
2418 if (curr->next == NULL || curr->next->in_insn_reserv != in_insn_reserv)
2427 bypass->next = out_insn_reserv->bypass_list;
2428 out_insn_reserv->bypass_list = bypass;
2432 bypass->next = last->next;
2433 last->next = bypass;
2437 /* The function processes pipeline description declarations, checks
2438 their correctness, and forms exclusion/presence/absence sets. */
2440 process_decls (void)
2443 decl_t automaton_decl;
2444 decl_t decl_in_table;
2445 decl_t out_insn_reserv;
2446 decl_t in_insn_reserv;
2447 int automaton_presence;
2450 /* Checking repeated automata declarations. */
2451 automaton_presence = 0;
2452 for (i = 0; i < description->decls_num; i++)
2454 decl = description->decls [i];
2455 if (decl->mode == dm_automaton)
2457 automaton_presence = 1;
2458 decl_in_table = insert_automaton_decl (decl);
2459 if (decl_in_table != decl)
2462 error ("repeated declaration of automaton `%s'",
2463 DECL_AUTOMATON (decl)->name);
2465 warning ("repeated declaration of automaton `%s'",
2466 DECL_AUTOMATON (decl)->name);
2470 /* Checking undeclared automata, repeated declarations (except for
2471 automata) and correctness of their attributes (insn latency times
2473 for (i = 0; i < description->decls_num; i++)
2475 decl = description->decls [i];
2476 if (decl->mode == dm_insn_reserv)
2478 if (DECL_INSN_RESERV (decl)->default_latency < 0)
2479 error ("define_insn_reservation `%s' has negative latency time",
2480 DECL_INSN_RESERV (decl)->name);
2481 DECL_INSN_RESERV (decl)->insn_num = description->insns_num;
2482 description->insns_num++;
2483 decl_in_table = insert_insn_decl (decl);
2484 if (decl_in_table != decl)
2485 error ("`%s' is already used as insn reservation name",
2486 DECL_INSN_RESERV (decl)->name);
2488 else if (decl->mode == dm_bypass)
2490 if (DECL_BYPASS (decl)->latency < 0)
2491 error ("define_bypass `%s - %s' has negative latency time",
2492 DECL_BYPASS (decl)->out_insn_name,
2493 DECL_BYPASS (decl)->in_insn_name);
2495 else if (decl->mode == dm_unit || decl->mode == dm_reserv)
2497 if (decl->mode == dm_unit)
2499 DECL_UNIT (decl)->automaton_decl = NULL;
2500 if (DECL_UNIT (decl)->automaton_name != NULL)
2503 = find_automaton_decl (DECL_UNIT (decl)->automaton_name);
2504 if (automaton_decl == NULL)
2505 error ("automaton `%s' is not declared",
2506 DECL_UNIT (decl)->automaton_name);
2509 DECL_AUTOMATON (automaton_decl)->automaton_is_used = 1;
2510 DECL_UNIT (decl)->automaton_decl
2511 = DECL_AUTOMATON (automaton_decl);
2514 else if (automaton_presence)
2515 error ("define_unit `%s' without automaton when one defined",
2516 DECL_UNIT (decl)->name);
2517 DECL_UNIT (decl)->unit_num = description->units_num;
2518 description->units_num++;
2519 if (strcmp (DECL_UNIT (decl)->name, NOTHING_NAME) == 0)
2521 error ("`%s' is declared as cpu unit", NOTHING_NAME);
2524 decl_in_table = find_decl (DECL_UNIT (decl)->name);
2528 if (strcmp (DECL_RESERV (decl)->name, NOTHING_NAME) == 0)
2530 error ("`%s' is declared as cpu reservation", NOTHING_NAME);
2533 decl_in_table = find_decl (DECL_RESERV (decl)->name);
2535 if (decl_in_table == NULL)
2536 decl_in_table = insert_decl (decl);
2539 if (decl->mode == dm_unit)
2540 error ("repeated declaration of unit `%s'",
2541 DECL_UNIT (decl)->name);
2543 error ("repeated declaration of reservation `%s'",
2544 DECL_RESERV (decl)->name);
2548 /* Check bypasses and form list of bypasses for each (output)
2550 for (i = 0; i < description->decls_num; i++)
2552 decl = description->decls [i];
2553 if (decl->mode == dm_bypass)
2555 out_insn_reserv = find_insn_decl (DECL_BYPASS (decl)->out_insn_name);
2556 in_insn_reserv = find_insn_decl (DECL_BYPASS (decl)->in_insn_name);
2557 if (out_insn_reserv == NULL)
2558 error ("there is no insn reservation `%s'",
2559 DECL_BYPASS (decl)->out_insn_name);
2560 else if (in_insn_reserv == NULL)
2561 error ("there is no insn reservation `%s'",
2562 DECL_BYPASS (decl)->in_insn_name);
2565 DECL_BYPASS (decl)->out_insn_reserv
2566 = DECL_INSN_RESERV (out_insn_reserv);
2567 DECL_BYPASS (decl)->in_insn_reserv
2568 = DECL_INSN_RESERV (in_insn_reserv);
2569 insert_bypass (DECL_BYPASS (decl));
2574 /* Check exclusion set declarations and form exclusion sets. */
2575 for (i = 0; i < description->decls_num; i++)
2577 decl = description->decls [i];
2578 if (decl->mode == dm_excl)
2580 unit_set_el_t unit_set_el_list;
2581 unit_set_el_t unit_set_el_list_2;
2584 = process_excls (DECL_EXCL (decl)->names,
2585 DECL_EXCL (decl)->first_list_length, decl->pos);
2587 = process_excls (&DECL_EXCL (decl)->names
2588 [DECL_EXCL (decl)->first_list_length],
2589 DECL_EXCL (decl)->all_names_num
2590 - DECL_EXCL (decl)->first_list_length,
2592 add_excls (unit_set_el_list, unit_set_el_list_2, decl->pos);
2593 add_excls (unit_set_el_list_2, unit_set_el_list, decl->pos);
2597 /* Check presence set declarations and form presence sets. */
2598 for (i = 0; i < description->decls_num; i++)
2600 decl = description->decls [i];
2601 if (decl->mode == dm_presence)
2603 unit_set_el_t unit_set_el_list;
2604 pattern_set_el_t pattern_set_el_list;
2607 = process_presence_absence_names
2608 (DECL_PRESENCE (decl)->names, DECL_PRESENCE (decl)->names_num,
2609 decl->pos, TRUE, DECL_PRESENCE (decl)->final_p);
2611 = process_presence_absence_patterns
2612 (DECL_PRESENCE (decl)->patterns,
2613 DECL_PRESENCE (decl)->patterns_num,
2614 decl->pos, TRUE, DECL_PRESENCE (decl)->final_p);
2615 add_presence_absence (unit_set_el_list, pattern_set_el_list,
2617 DECL_PRESENCE (decl)->final_p);
2621 /* Check absence set declarations and form absence sets. */
2622 for (i = 0; i < description->decls_num; i++)
2624 decl = description->decls [i];
2625 if (decl->mode == dm_absence)
2627 unit_set_el_t unit_set_el_list;
2628 pattern_set_el_t pattern_set_el_list;
2631 = process_presence_absence_names
2632 (DECL_ABSENCE (decl)->names, DECL_ABSENCE (decl)->names_num,
2633 decl->pos, FALSE, DECL_ABSENCE (decl)->final_p);
2635 = process_presence_absence_patterns
2636 (DECL_ABSENCE (decl)->patterns,
2637 DECL_ABSENCE (decl)->patterns_num,
2638 decl->pos, FALSE, DECL_ABSENCE (decl)->final_p);
2639 add_presence_absence (unit_set_el_list, pattern_set_el_list,
2641 DECL_ABSENCE (decl)->final_p);
2646 /* The following function checks that declared automaton is used. If
2647 the automaton is not used, the function fixes error/warning. The
2648 following function must be called only after `process_decls'. */
2650 check_automaton_usage (void)
2655 for (i = 0; i < description->decls_num; i++)
2657 decl = description->decls [i];
2658 if (decl->mode == dm_automaton
2659 && !DECL_AUTOMATON (decl)->automaton_is_used)
2662 error ("automaton `%s' is not used", DECL_AUTOMATON (decl)->name);
2664 warning ("automaton `%s' is not used",
2665 DECL_AUTOMATON (decl)->name);
2670 /* The following recursive function processes all regexp in order to
2671 fix usage of units or reservations and to fix errors of undeclared
2672 name. The function may change unit_regexp onto reserv_regexp.
2673 Remember that reserv_regexp does not exist before the function
2676 process_regexp (regexp_t regexp)
2678 decl_t decl_in_table;
2679 regexp_t new_regexp;
2682 switch (regexp->mode)
2685 decl_in_table = find_decl (REGEXP_UNIT (regexp)->name);
2686 if (decl_in_table == NULL)
2687 error ("undeclared unit or reservation `%s'",
2688 REGEXP_UNIT (regexp)->name);
2690 switch (decl_in_table->mode)
2693 DECL_UNIT (decl_in_table)->unit_is_used = 1;
2694 REGEXP_UNIT (regexp)->unit_decl = DECL_UNIT (decl_in_table);
2698 DECL_RESERV (decl_in_table)->reserv_is_used = 1;
2699 new_regexp = XCREATENODE (struct regexp);
2700 new_regexp->mode = rm_reserv;
2701 new_regexp->pos = regexp->pos;
2702 REGEXP_RESERV (new_regexp)->name = REGEXP_UNIT (regexp)->name;
2703 REGEXP_RESERV (new_regexp)->reserv_decl
2704 = DECL_RESERV (decl_in_table);
2705 regexp = new_regexp;
2713 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
2714 REGEXP_SEQUENCE (regexp)->regexps [i]
2715 = process_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
2718 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
2719 REGEXP_ALLOF (regexp)->regexps [i]
2720 = process_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
2723 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
2724 REGEXP_ONEOF (regexp)->regexps [i]
2725 = process_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
2728 REGEXP_REPEAT (regexp)->regexp
2729 = process_regexp (REGEXP_REPEAT (regexp)->regexp);
2739 /* The following function processes regexp of define_reservation and
2740 define_insn_reservation with the aid of function
2741 `process_regexp'. */
2743 process_regexp_decls (void)
2748 for (i = 0; i < description->decls_num; i++)
2750 decl = description->decls [i];
2751 if (decl->mode == dm_reserv)
2752 DECL_RESERV (decl)->regexp
2753 = process_regexp (DECL_RESERV (decl)->regexp);
2754 else if (decl->mode == dm_insn_reserv)
2755 DECL_INSN_RESERV (decl)->regexp
2756 = process_regexp (DECL_INSN_RESERV (decl)->regexp);
2760 /* The following function checks that declared unit is used. If the
2761 unit is not used, the function fixes errors/warnings. The
2762 following function must be called only after `process_decls',
2763 `process_regexp_decls'. */
2770 for (i = 0; i < description->decls_num; i++)
2772 decl = description->decls [i];
2773 if (decl->mode == dm_unit && !DECL_UNIT (decl)->unit_is_used)
2776 error ("unit `%s' is not used", DECL_UNIT (decl)->name);
2778 warning ("unit `%s' is not used", DECL_UNIT (decl)->name);
2780 else if (decl->mode == dm_reserv && !DECL_RESERV (decl)->reserv_is_used)
2783 error ("reservation `%s' is not used", DECL_RESERV (decl)->name);
2785 warning ("reservation `%s' is not used", DECL_RESERV (decl)->name);
2790 /* The following variable value is number of reservation being
2791 processed on loop recognition. */
2792 static int curr_loop_pass_num;
2794 /* The following recursive function returns nonzero value if REGEXP
2795 contains given decl or reservations in given regexp refers for
2798 loop_in_regexp (regexp_t regexp, decl_t start_decl)
2804 switch (regexp->mode)
2810 if (start_decl->mode == dm_reserv
2811 && REGEXP_RESERV (regexp)->reserv_decl == DECL_RESERV (start_decl))
2813 else if (REGEXP_RESERV (regexp)->reserv_decl->loop_pass_num
2814 == curr_loop_pass_num)
2815 /* declaration has been processed. */
2819 REGEXP_RESERV (regexp)->reserv_decl->loop_pass_num
2820 = curr_loop_pass_num;
2821 return loop_in_regexp (REGEXP_RESERV (regexp)->reserv_decl->regexp,
2826 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
2827 if (loop_in_regexp (REGEXP_SEQUENCE (regexp)->regexps [i], start_decl))
2832 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
2833 if (loop_in_regexp (REGEXP_ALLOF (regexp)->regexps [i], start_decl))
2838 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
2839 if (loop_in_regexp (REGEXP_ONEOF (regexp)->regexps [i], start_decl))
2844 return loop_in_regexp (REGEXP_REPEAT (regexp)->regexp, start_decl);
2854 /* The following function fixes errors "cycle in definition ...". The
2855 function uses function `loop_in_regexp' for that. */
2857 check_loops_in_regexps (void)
2862 for (i = 0; i < description->decls_num; i++)
2864 decl = description->decls [i];
2865 if (decl->mode == dm_reserv)
2866 DECL_RESERV (decl)->loop_pass_num = 0;
2868 for (i = 0; i < description->decls_num; i++)
2870 decl = description->decls [i];
2871 curr_loop_pass_num = i;
2873 if (decl->mode == dm_reserv)
2875 DECL_RESERV (decl)->loop_pass_num = curr_loop_pass_num;
2876 if (loop_in_regexp (DECL_RESERV (decl)->regexp, decl))
2878 gcc_assert (DECL_RESERV (decl)->regexp);
2879 error ("cycle in definition of reservation `%s'",
2880 DECL_RESERV (decl)->name);
2886 /* The function recursively processes IR of reservation and defines
2887 max and min cycle for reservation of unit. */
2889 process_regexp_cycles (regexp_t regexp, int max_start_cycle,
2890 int min_start_cycle, int *max_finish_cycle,
2891 int *min_finish_cycle)
2895 switch (regexp->mode)
2898 if (REGEXP_UNIT (regexp)->unit_decl->max_occ_cycle_num < max_start_cycle)
2899 REGEXP_UNIT (regexp)->unit_decl->max_occ_cycle_num = max_start_cycle;
2900 if (REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num > min_start_cycle
2901 || REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num == -1)
2902 REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num = min_start_cycle;
2903 *max_finish_cycle = max_start_cycle;
2904 *min_finish_cycle = min_start_cycle;
2908 process_regexp_cycles (REGEXP_RESERV (regexp)->reserv_decl->regexp,
2909 max_start_cycle, min_start_cycle,
2910 max_finish_cycle, min_finish_cycle);
2914 for (i = 0; i < REGEXP_REPEAT (regexp)->repeat_num; i++)
2916 process_regexp_cycles (REGEXP_REPEAT (regexp)->regexp,
2917 max_start_cycle, min_start_cycle,
2918 max_finish_cycle, min_finish_cycle);
2919 max_start_cycle = *max_finish_cycle + 1;
2920 min_start_cycle = *min_finish_cycle + 1;
2925 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
2927 process_regexp_cycles (REGEXP_SEQUENCE (regexp)->regexps [i],
2928 max_start_cycle, min_start_cycle,
2929 max_finish_cycle, min_finish_cycle);
2930 max_start_cycle = *max_finish_cycle + 1;
2931 min_start_cycle = *min_finish_cycle + 1;
2940 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
2942 process_regexp_cycles (REGEXP_ALLOF (regexp)->regexps [i],
2943 max_start_cycle, min_start_cycle,
2944 max_finish_cycle, min_finish_cycle);
2945 if (max_cycle < *max_finish_cycle)
2946 max_cycle = *max_finish_cycle;
2947 if (i == 0 || min_cycle > *min_finish_cycle)
2948 min_cycle = *min_finish_cycle;
2950 *max_finish_cycle = max_cycle;
2951 *min_finish_cycle = min_cycle;
2960 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
2962 process_regexp_cycles (REGEXP_ONEOF (regexp)->regexps [i],
2963 max_start_cycle, min_start_cycle,
2964 max_finish_cycle, min_finish_cycle);
2965 if (max_cycle < *max_finish_cycle)
2966 max_cycle = *max_finish_cycle;
2967 if (i == 0 || min_cycle > *min_finish_cycle)
2968 min_cycle = *min_finish_cycle;
2970 *max_finish_cycle = max_cycle;
2971 *min_finish_cycle = min_cycle;
2976 *max_finish_cycle = max_start_cycle;
2977 *min_finish_cycle = min_start_cycle;
2985 /* The following function is called only for correct program. The
2986 function defines max reservation of insns in cycles. */
2988 evaluate_max_reserv_cycles (void)
2990 int max_insn_cycles_num;
2991 int min_insn_cycles_num;
2995 description->max_insn_reserv_cycles = 0;
2996 for (i = 0; i < description->decls_num; i++)
2998 decl = description->decls [i];
2999 if (decl->mode == dm_insn_reserv)
3001 process_regexp_cycles (DECL_INSN_RESERV (decl)->regexp, 0, 0,
3002 &max_insn_cycles_num, &min_insn_cycles_num);
3003 if (description->max_insn_reserv_cycles < max_insn_cycles_num)
3004 description->max_insn_reserv_cycles = max_insn_cycles_num;
3007 description->max_insn_reserv_cycles++;
3010 /* The following function calls functions for checking all
3013 check_all_description (void)
3016 check_automaton_usage ();
3017 process_regexp_decls ();
3019 check_loops_in_regexps ();
3021 evaluate_max_reserv_cycles ();
3026 /* The page contains abstract data `ticker'. This data is used to
3027 report time of different phases of building automata. It is
3028 possibly to write a description for which automata will be built
3029 during several minutes even on fast machine. */
3031 /* The following function creates ticker and makes it active. */
3033 create_ticker (void)
3037 ticker.modified_creation_time = get_run_time ();
3038 ticker.incremented_off_time = 0;
3042 /* The following function switches off given ticker. */
3044 ticker_off (ticker_t *ticker)
3046 if (ticker->incremented_off_time == 0)
3047 ticker->incremented_off_time = get_run_time () + 1;
3050 /* The following function switches on given ticker. */
3052 ticker_on (ticker_t *ticker)
3054 if (ticker->incremented_off_time != 0)
3056 ticker->modified_creation_time
3057 += get_run_time () - ticker->incremented_off_time + 1;
3058 ticker->incremented_off_time = 0;
3062 /* The following function returns current time in milliseconds since
3063 the moment when given ticker was created. */
3065 active_time (ticker_t ticker)
3067 if (ticker.incremented_off_time != 0)
3068 return ticker.incremented_off_time - 1 - ticker.modified_creation_time;
3070 return get_run_time () - ticker.modified_creation_time;
3073 /* The following function returns string representation of active time
3074 of given ticker. The result is string representation of seconds
3075 with accuracy of 1/100 second. Only result of the last call of the
3076 function exists. Therefore the following code is not correct
3078 printf ("parser time: %s\ngeneration time: %s\n",
3079 active_time_string (parser_ticker),
3080 active_time_string (generation_ticker));
3082 Correct code has to be the following
3084 printf ("parser time: %s\n", active_time_string (parser_ticker));
3085 printf ("generation time: %s\n",
3086 active_time_string (generation_ticker));
3090 print_active_time (FILE *f, ticker_t ticker)
3094 msecs = active_time (ticker);
3095 fprintf (f, "%d.%06d", msecs / 1000000, msecs % 1000000);
3100 /* The following variable value is number of automaton which are
3101 really being created. This value is defined on the base of
3102 argument of option `-split'. If the variable has zero value the
3103 number of automata is defined by the constructions `%automaton'.
3104 This case occurs when option `-split' is absent or has zero
3105 argument. If constructions `define_automaton' is absent only one
3106 automaton is created. */
3107 static int automata_num;
3109 /* The following variable values are times of
3110 o transformation of regular expressions
3111 o building NDFA (DFA if !ndfa_flag)
3112 o NDFA -> DFA (simply the same automaton if !ndfa_flag)
3114 o building insn equivalence classes
3117 static ticker_t transform_time;
3118 static ticker_t NDFA_time;
3119 static ticker_t NDFA_to_DFA_time;
3120 static ticker_t minimize_time;
3121 static ticker_t equiv_time;
3122 static ticker_t automaton_generation_time;
3123 static ticker_t output_time;
3125 /* The following variable values are times of
3128 all pipeline hazard translator work */
3129 static ticker_t check_time;
3130 static ticker_t generation_time;
3131 static ticker_t all_time;
3135 /* Pseudo insn decl which denotes advancing cycle. */
3136 static decl_t advance_cycle_insn_decl;
3138 add_advance_cycle_insn_decl (void)
3140 advance_cycle_insn_decl = XCREATENODE (struct decl);
3141 advance_cycle_insn_decl->mode = dm_insn_reserv;
3142 advance_cycle_insn_decl->pos = no_pos;
3143 DECL_INSN_RESERV (advance_cycle_insn_decl)->regexp = NULL;
3144 DECL_INSN_RESERV (advance_cycle_insn_decl)->name = "$advance_cycle";
3145 DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num
3146 = description->insns_num;
3147 description->decls [description->decls_num] = advance_cycle_insn_decl;
3148 description->decls_num++;
3149 description->insns_num++;
3153 /* Abstract data `alternative states' which represents
3154 nondeterministic nature of the description (see comments for
3155 structures alt_state and state). */
3157 /* List of free states. */
3158 static alt_state_t first_free_alt_state;
3161 /* The following variables is maximal number of allocated nodes
3163 static int allocated_alt_states_num = 0;
3166 /* The following function returns free node alt_state. It may be new
3167 allocated node or node freed earlier. */
3169 get_free_alt_state (void)
3173 if (first_free_alt_state != NULL)
3175 result = first_free_alt_state;
3176 first_free_alt_state = first_free_alt_state->next_alt_state;
3181 allocated_alt_states_num++;
3183 result = XCREATENODE (struct alt_state);
3185 result->state = NULL;
3186 result->next_alt_state = NULL;
3187 result->next_sorted_alt_state = NULL;
3191 /* The function frees node ALT_STATE. */
3193 free_alt_state (alt_state_t alt_state)
3195 if (alt_state == NULL)
3197 alt_state->next_alt_state = first_free_alt_state;
3198 first_free_alt_state = alt_state;
3201 /* The function frees list started with node ALT_STATE_LIST. */
3203 free_alt_states (alt_state_t alt_states_list)
3205 alt_state_t curr_alt_state;
3206 alt_state_t next_alt_state;
3208 for (curr_alt_state = alt_states_list;
3209 curr_alt_state != NULL;
3210 curr_alt_state = next_alt_state)
3212 next_alt_state = curr_alt_state->next_alt_state;
3213 free_alt_state (curr_alt_state);
3217 /* The function compares unique numbers of alt states. */
3219 alt_state_cmp (const void *alt_state_ptr_1, const void *alt_state_ptr_2)
3221 if ((*(const alt_state_t *) alt_state_ptr_1)->state->unique_num
3222 == (*(const alt_state_t *) alt_state_ptr_2)->state->unique_num)
3224 else if ((*(const alt_state_t *) alt_state_ptr_1)->state->unique_num
3225 < (*(const alt_state_t *) alt_state_ptr_2)->state->unique_num)
3231 /* The function sorts ALT_STATES_LIST and removes duplicated alt
3232 states from the list. The comparison key is alt state unique
3236 uniq_sort_alt_states (alt_state_t alt_states_list)
3238 alt_state_t curr_alt_state;
3239 VEC(alt_state_t, heap) *alt_states;
3241 size_t prev_unique_state_ind;
3244 if (alt_states_list == 0)
3246 if (alt_states_list->next_alt_state == 0)
3247 return alt_states_list;
3249 alt_states = VEC_alloc (alt_state_t, heap, 150);
3250 for (curr_alt_state = alt_states_list;
3251 curr_alt_state != NULL;
3252 curr_alt_state = curr_alt_state->next_alt_state)
3253 VEC_safe_push (alt_state_t, heap, alt_states, curr_alt_state);
3255 qsort (VEC_address (alt_state_t, alt_states),
3256 VEC_length (alt_state_t, alt_states),
3257 sizeof (alt_state_t), alt_state_cmp);
3259 prev_unique_state_ind = 0;
3260 for (i = 1; i < VEC_length (alt_state_t, alt_states); i++)
3261 if (VEC_index (alt_state_t, alt_states, prev_unique_state_ind)->state
3262 != VEC_index (alt_state_t, alt_states, i)->state)
3264 prev_unique_state_ind++;
3265 VEC_replace (alt_state_t, alt_states, prev_unique_state_ind,
3266 VEC_index (alt_state_t, alt_states, i));
3268 VEC_truncate (alt_state_t, alt_states, prev_unique_state_ind + 1);
3270 for (i = 1; i < VEC_length (alt_state_t, alt_states); i++)
3271 VEC_index (alt_state_t, alt_states, i-1)->next_sorted_alt_state
3272 = VEC_index (alt_state_t, alt_states, i);
3273 VEC_last (alt_state_t, alt_states)->next_sorted_alt_state = 0;
3275 result = VEC_index (alt_state_t, alt_states, 0);
3277 VEC_free (alt_state_t, heap, alt_states);
3281 /* The function checks equality of alt state lists. Remember that the
3282 lists must be already sorted by the previous function. */
3284 alt_states_eq (alt_state_t alt_states_1, alt_state_t alt_states_2)
3286 while (alt_states_1 != NULL && alt_states_2 != NULL
3287 && alt_state_cmp (&alt_states_1, &alt_states_2) == 0)
3289 alt_states_1 = alt_states_1->next_sorted_alt_state;
3290 alt_states_2 = alt_states_2->next_sorted_alt_state;
3292 return alt_states_1 == alt_states_2;
3295 /* Initialization of the abstract data. */
3297 initiate_alt_states (void)
3299 first_free_alt_state = NULL;
3302 /* Finishing work with the abstract data. */
3304 finish_alt_states (void)
3310 /* The page contains macros for work with bits strings. We could use
3311 standard gcc bitmap or sbitmap but it would result in difficulties
3312 of building canadian cross. */
3314 /* Set bit number bitno in the bit string. The macro is not side
3316 #define SET_BIT(bitstring, bitno) \
3317 (((char *) (bitstring)) [(bitno) / CHAR_BIT] |= 1 << (bitno) % CHAR_BIT)
3319 #define CLEAR_BIT(bitstring, bitno) \
3320 (((char *) (bitstring)) [(bitno) / CHAR_BIT] &= ~(1 << (bitno) % CHAR_BIT))
3322 /* Test if bit number bitno in the bitstring is set. The macro is not
3323 side effect proof. */
3324 #define TEST_BIT(bitstring, bitno) \
3325 (((char *) (bitstring)) [(bitno) / CHAR_BIT] >> (bitno) % CHAR_BIT & 1)
3329 /* This page contains abstract data `state'. */
3331 /* Maximal length of reservations in cycles (>= 1). */
3332 static int max_cycles_num;
3334 /* Number of set elements (see type set_el_t) needed for
3335 representation of one cycle reservation. It is depended on units
3337 static int els_in_cycle_reserv;
3339 /* Number of set elements (see type set_el_t) needed for
3340 representation of maximal length reservation. Deterministic
3341 reservation is stored as set (bit string) of length equal to the
3342 variable value * number of bits in set_el_t. */
3343 static int els_in_reservs;
3345 /* Array of pointers to unit declarations. */
3346 static unit_decl_t *units_array;
3348 /* Temporary reservation of maximal length. */
3349 static reserv_sets_t temp_reserv;
3351 /* The state table itself is represented by the following variable. */
3352 static htab_t state_table;
3354 /* Linked list of free 'state' structures to be recycled. The
3355 next_equiv_class_state pointer is borrowed for a free list. */
3356 static state_t first_free_state;
3358 static int curr_unique_state_num;
3361 /* The following variables is maximal number of allocated nodes
3363 static int allocated_states_num = 0;
3366 /* Allocate new reservation set. */
3367 static reserv_sets_t
3368 alloc_empty_reserv_sets (void)
3370 reserv_sets_t result;
3372 obstack_blank (&irp, els_in_reservs * sizeof (set_el_t));
3373 result = (reserv_sets_t) obstack_base (&irp);
3374 obstack_finish (&irp);
3375 memset (result, 0, els_in_reservs * sizeof (set_el_t));
3379 /* Hash value of reservation set. */
3381 reserv_sets_hash_value (reserv_sets_t reservs)
3383 set_el_t hash_value;
3386 set_el_t *reserv_ptr;
3389 reservs_num = els_in_reservs;
3390 reserv_ptr = reservs;
3392 while (reservs_num != 0)
3395 hash_value += ((*reserv_ptr >> i)
3396 | (*reserv_ptr << (sizeof (set_el_t) * CHAR_BIT - i)));
3398 if (i == sizeof (set_el_t) * CHAR_BIT)
3402 if (sizeof (set_el_t) <= sizeof (unsigned))
3405 for (i = sizeof (set_el_t); i > 0; i -= sizeof (unsigned) - 1)
3407 result += (unsigned) hash_value;
3408 hash_value >>= (sizeof (unsigned) - 1) * CHAR_BIT;
3413 /* Comparison of given reservation sets. */
3415 reserv_sets_cmp (const_reserv_sets_t reservs_1, const_reserv_sets_t reservs_2)
3418 const set_el_t *reserv_ptr_1;
3419 const set_el_t *reserv_ptr_2;
3421 gcc_assert (reservs_1 && reservs_2);
3422 reservs_num = els_in_reservs;
3423 reserv_ptr_1 = reservs_1;
3424 reserv_ptr_2 = reservs_2;
3425 while (reservs_num != 0 && *reserv_ptr_1 == *reserv_ptr_2)
3431 if (reservs_num == 0)
3433 else if (*reserv_ptr_1 < *reserv_ptr_2)
3439 /* The function checks equality of the reservation sets. */
3441 reserv_sets_eq (const_reserv_sets_t reservs_1, const_reserv_sets_t reservs_2)
3443 return reserv_sets_cmp (reservs_1, reservs_2) == 0;
3446 /* Set up in the reservation set that unit with UNIT_NUM is used on
3449 set_unit_reserv (reserv_sets_t reservs, int cycle_num, int unit_num)
3451 gcc_assert (cycle_num < max_cycles_num);
3452 SET_BIT (reservs, cycle_num * els_in_cycle_reserv
3453 * sizeof (set_el_t) * CHAR_BIT + unit_num);
3456 /* Set up in the reservation set RESERVS that unit with UNIT_NUM is
3457 used on CYCLE_NUM. */
3459 test_unit_reserv (reserv_sets_t reservs, int cycle_num, int unit_num)
3461 gcc_assert (cycle_num < max_cycles_num);
3462 return TEST_BIT (reservs, cycle_num * els_in_cycle_reserv
3463 * sizeof (set_el_t) * CHAR_BIT + unit_num);
3466 /* The function checks that the reservation sets are intersected,
3467 i.e. there is a unit reservation on a cycle in both reservation
3470 reserv_sets_are_intersected (reserv_sets_t operand_1,
3471 reserv_sets_t operand_2)
3475 set_el_t *cycle_ptr_1;
3476 set_el_t *cycle_ptr_2;
3478 gcc_assert (operand_1 && operand_2);
3479 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2;
3480 el_ptr_1 < operand_1 + els_in_reservs;
3481 el_ptr_1++, el_ptr_2++)
3482 if (*el_ptr_1 & *el_ptr_2)
3484 reserv_sets_or (temp_reserv, operand_1, operand_2);
3485 for (cycle_ptr_1 = operand_1, cycle_ptr_2 = operand_2;
3486 cycle_ptr_1 < operand_1 + els_in_reservs;
3487 cycle_ptr_1 += els_in_cycle_reserv, cycle_ptr_2 += els_in_cycle_reserv)
3489 for (el_ptr_1 = cycle_ptr_1, el_ptr_2 = get_excl_set (cycle_ptr_2);
3490 el_ptr_1 < cycle_ptr_1 + els_in_cycle_reserv;
3491 el_ptr_1++, el_ptr_2++)
3492 if (*el_ptr_1 & *el_ptr_2)
3494 if (!check_presence_pattern_sets (cycle_ptr_1, cycle_ptr_2, FALSE))
3496 if (!check_presence_pattern_sets (temp_reserv + (cycle_ptr_2
3500 if (!check_absence_pattern_sets (cycle_ptr_1, cycle_ptr_2, FALSE))
3502 if (!check_absence_pattern_sets (temp_reserv + (cycle_ptr_2 - operand_2),
3509 /* The function sets up RESULT bits by bits of OPERAND shifted on one
3510 cpu cycle. The remaining bits of OPERAND (representing the last
3511 cycle unit reservations) are not changed. */
3513 reserv_sets_shift (reserv_sets_t result, reserv_sets_t operand)
3517 gcc_assert (result && operand && result != operand);
3518 for (i = els_in_cycle_reserv; i < els_in_reservs; i++)
3519 result [i - els_in_cycle_reserv] = operand [i];
3522 /* OR of the reservation sets. */
3524 reserv_sets_or (reserv_sets_t result, reserv_sets_t operand_1,
3525 reserv_sets_t operand_2)
3529 set_el_t *result_set_el_ptr;
3531 gcc_assert (result && operand_1 && operand_2);
3532 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2, result_set_el_ptr = result;
3533 el_ptr_1 < operand_1 + els_in_reservs;
3534 el_ptr_1++, el_ptr_2++, result_set_el_ptr++)
3535 *result_set_el_ptr = *el_ptr_1 | *el_ptr_2;
3538 /* AND of the reservation sets. */
3540 reserv_sets_and (reserv_sets_t result, reserv_sets_t operand_1,
3541 reserv_sets_t operand_2)
3545 set_el_t *result_set_el_ptr;
3547 gcc_assert (result && operand_1 && operand_2);
3548 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2, result_set_el_ptr = result;
3549 el_ptr_1 < operand_1 + els_in_reservs;
3550 el_ptr_1++, el_ptr_2++, result_set_el_ptr++)
3551 *result_set_el_ptr = *el_ptr_1 & *el_ptr_2;
3554 /* The function outputs string representation of units reservation on
3555 cycle START_CYCLE in the reservation set. The function uses repeat
3556 construction if REPETITION_NUM > 1. */
3558 output_cycle_reservs (FILE *f, reserv_sets_t reservs, int start_cycle,
3562 int reserved_units_num;
3564 reserved_units_num = 0;
3565 for (unit_num = 0; unit_num < description->units_num; unit_num++)
3566 if (TEST_BIT (reservs, start_cycle * els_in_cycle_reserv
3567 * sizeof (set_el_t) * CHAR_BIT + unit_num))
3568 reserved_units_num++;
3569 gcc_assert (repetition_num > 0);
3570 if (repetition_num != 1 && reserved_units_num > 1)
3572 reserved_units_num = 0;
3574 unit_num < description->units_num;
3576 if (TEST_BIT (reservs, start_cycle * els_in_cycle_reserv
3577 * sizeof (set_el_t) * CHAR_BIT + unit_num))
3579 if (reserved_units_num != 0)
3581 reserved_units_num++;
3582 fprintf (f, "%s", units_array [unit_num]->name);
3584 if (reserved_units_num == 0)
3585 fprintf (f, NOTHING_NAME);
3586 gcc_assert (repetition_num > 0);
3587 if (repetition_num != 1 && reserved_units_num > 1)
3589 if (repetition_num != 1)
3590 fprintf (f, "*%d", repetition_num);
3593 /* The function outputs string representation of units reservation in
3594 the reservation set. */
3596 output_reserv_sets (FILE *f, reserv_sets_t reservs)
3598 int start_cycle = 0;
3603 for (cycle = 0; cycle < max_cycles_num; cycle++)
3604 if (repetition_num == 0)
3607 start_cycle = cycle;
3610 ((char *) reservs + start_cycle * els_in_cycle_reserv
3611 * sizeof (set_el_t),
3612 (char *) reservs + cycle * els_in_cycle_reserv
3613 * sizeof (set_el_t),
3614 els_in_cycle_reserv * sizeof (set_el_t)) == 0)
3618 if (start_cycle != 0)
3620 output_cycle_reservs (f, reservs, start_cycle, repetition_num);
3622 start_cycle = cycle;
3624 if (start_cycle < max_cycles_num)
3626 if (start_cycle != 0)
3628 output_cycle_reservs (f, reservs, start_cycle, repetition_num);
3632 /* The following function returns free node state for AUTOMATON. It
3633 may be new allocated node or node freed earlier. The function also
3634 allocates reservation set if WITH_RESERVS has nonzero value. */
3636 get_free_state (int with_reservs, automaton_t automaton)
3640 gcc_assert (max_cycles_num > 0 && automaton);
3641 if (first_free_state)
3643 result = first_free_state;
3644 first_free_state = result->next_equiv_class_state;
3646 result->next_equiv_class_state = NULL;
3647 result->automaton = automaton;
3648 result->first_out_arc = NULL;
3649 result->it_was_placed_in_stack_for_NDFA_forming = 0;
3650 result->it_was_placed_in_stack_for_DFA_forming = 0;
3651 result->component_states = NULL;
3656 allocated_states_num++;
3658 result = XCREATENODE (struct state);
3659 result->automaton = automaton;
3660 result->first_out_arc = NULL;
3661 result->unique_num = curr_unique_state_num;
3662 curr_unique_state_num++;
3666 if (result->reservs == NULL)
3667 result->reservs = alloc_empty_reserv_sets ();
3669 memset (result->reservs, 0, els_in_reservs * sizeof (set_el_t));
3674 /* The function frees node STATE. */
3676 free_state (state_t state)
3678 free_alt_states (state->component_states);
3679 state->next_equiv_class_state = first_free_state;
3680 first_free_state = state;
3683 /* Hash value of STATE. If STATE represents deterministic state it is
3684 simply hash value of the corresponding reservation set. Otherwise
3685 it is formed from hash values of the component deterministic
3686 states. One more key is order number of state automaton. */
3688 state_hash (const void *state)
3690 unsigned int hash_value;
3691 alt_state_t alt_state;
3693 if (((const_state_t) state)->component_states == NULL)
3694 hash_value = reserv_sets_hash_value (((const_state_t) state)->reservs);
3698 for (alt_state = ((const_state_t) state)->component_states;
3700 alt_state = alt_state->next_sorted_alt_state)
3701 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
3702 | (hash_value << CHAR_BIT))
3703 + alt_state->state->unique_num);
3705 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
3706 | (hash_value << CHAR_BIT))
3707 + ((const_state_t) state)->automaton->automaton_order_num);
3711 /* Return nonzero value if the states are the same. */
3713 state_eq_p (const void *state_1, const void *state_2)
3715 alt_state_t alt_state_1;
3716 alt_state_t alt_state_2;
3718 if (((const_state_t) state_1)->automaton != ((const_state_t) state_2)->automaton)
3720 else if (((const_state_t) state_1)->component_states == NULL
3721 && ((const_state_t) state_2)->component_states == NULL)
3722 return reserv_sets_eq (((const_state_t) state_1)->reservs,
3723 ((const_state_t) state_2)->reservs);
3724 else if (((const_state_t) state_1)->component_states != NULL
3725 && ((const_state_t) state_2)->component_states != NULL)
3727 for (alt_state_1 = ((const_state_t) state_1)->component_states,
3728 alt_state_2 = ((const_state_t) state_2)->component_states;
3729 alt_state_1 != NULL && alt_state_2 != NULL;
3730 alt_state_1 = alt_state_1->next_sorted_alt_state,
3731 alt_state_2 = alt_state_2->next_sorted_alt_state)
3732 /* All state in the list must be already in the hash table.
3733 Also the lists must be sorted. */
3734 if (alt_state_1->state != alt_state_2->state)
3736 return alt_state_1 == alt_state_2;
3742 /* Insert STATE into the state table. */
3744 insert_state (state_t state)
3748 entry_ptr = htab_find_slot (state_table, (void *) state, INSERT);
3749 if (*entry_ptr == NULL)
3750 *entry_ptr = (void *) state;
3751 return (state_t) *entry_ptr;
3754 /* Add reservation of unit with UNIT_NUM on cycle CYCLE_NUM to
3755 deterministic STATE. */
3757 set_state_reserv (state_t state, int cycle_num, int unit_num)
3759 set_unit_reserv (state->reservs, cycle_num, unit_num);
3762 /* Return nonzero value if the deterministic states contains a
3763 reservation of the same cpu unit on the same cpu cycle. */
3765 intersected_state_reservs_p (state_t state1, state_t state2)
3767 gcc_assert (state1->automaton == state2->automaton);
3768 return reserv_sets_are_intersected (state1->reservs, state2->reservs);
3771 /* Return deterministic state (inserted into the table) which
3772 representing the automaton state which is union of reservations of
3773 the deterministic states masked by RESERVS. */
3775 states_union (state_t state1, state_t state2, reserv_sets_t reservs)
3778 state_t state_in_table;
3780 gcc_assert (state1->automaton == state2->automaton);
3781 result = get_free_state (1, state1->automaton);
3782 reserv_sets_or (result->reservs, state1->reservs, state2->reservs);
3783 reserv_sets_and (result->reservs, result->reservs, reservs);
3784 state_in_table = insert_state (result);
3785 if (result != state_in_table)
3787 free_state (result);
3788 result = state_in_table;
3793 /* Return deterministic state (inserted into the table) which
3794 represent the automaton state is obtained from deterministic STATE
3795 by advancing cpu cycle and masking by RESERVS. */
3797 state_shift (state_t state, reserv_sets_t reservs)
3800 state_t state_in_table;
3802 result = get_free_state (1, state->automaton);
3803 reserv_sets_shift (result->reservs, state->reservs);
3804 reserv_sets_and (result->reservs, result->reservs, reservs);
3805 state_in_table = insert_state (result);
3806 if (result != state_in_table)
3808 free_state (result);
3809 result = state_in_table;
3814 /* Initialization of the abstract data. */
3816 initiate_states (void)
3821 if (description->units_num)
3822 units_array = XNEWVEC (unit_decl_t, description->units_num);
3826 for (i = 0; i < description->decls_num; i++)
3828 decl = description->decls [i];
3829 if (decl->mode == dm_unit)
3830 units_array [DECL_UNIT (decl)->unit_num] = DECL_UNIT (decl);
3832 max_cycles_num = description->max_insn_reserv_cycles;
3834 = ((description->units_num + sizeof (set_el_t) * CHAR_BIT - 1)
3835 / (sizeof (set_el_t) * CHAR_BIT));
3836 els_in_reservs = els_in_cycle_reserv * max_cycles_num;
3837 curr_unique_state_num = 0;
3838 initiate_alt_states ();
3839 state_table = htab_create (1500, state_hash, state_eq_p, (htab_del) 0);
3840 temp_reserv = alloc_empty_reserv_sets ();
3843 /* Finishing work with the abstract data. */
3845 finish_states (void)
3849 htab_delete (state_table);
3850 first_free_state = NULL;
3851 finish_alt_states ();
3856 /* Abstract data `arcs'. */
3858 /* List of free arcs. */
3859 static arc_t first_free_arc;
3862 /* The following variables is maximal number of allocated nodes
3864 static int allocated_arcs_num = 0;
3867 /* The function frees node ARC. */
3869 free_arc (arc_t arc)
3871 arc->next_out_arc = first_free_arc;
3872 first_free_arc = arc;
3875 /* The function removes and frees ARC staring from FROM_STATE. */
3877 remove_arc (state_t from_state, arc_t arc)
3883 for (prev_arc = NULL, curr_arc = from_state->first_out_arc;
3885 prev_arc = curr_arc, curr_arc = curr_arc->next_out_arc)
3886 if (curr_arc == arc)
3888 gcc_assert (curr_arc);
3889 if (prev_arc == NULL)
3890 from_state->first_out_arc = arc->next_out_arc;
3892 prev_arc->next_out_arc = arc->next_out_arc;
3893 from_state->num_out_arcs--;
3897 /* The functions returns arc with given characteristics (or NULL if
3898 the arc does not exist). */
3900 find_arc (state_t from_state, state_t to_state, ainsn_t insn)
3904 for (arc = first_out_arc (from_state); arc != NULL; arc = next_out_arc (arc))
3905 if (arc->to_state == to_state && arc->insn == insn)
3910 /* The function adds arc from FROM_STATE to TO_STATE marked by AINSN.
3911 The function returns added arc (or already existing arc). */
3913 add_arc (state_t from_state, state_t to_state, ainsn_t ainsn)
3917 new_arc = find_arc (from_state, to_state, ainsn);
3918 if (new_arc != NULL)
3920 if (first_free_arc == NULL)
3923 allocated_arcs_num++;
3925 new_arc = XCREATENODE (struct arc);
3926 new_arc->to_state = NULL;
3927 new_arc->insn = NULL;
3928 new_arc->next_out_arc = NULL;
3932 new_arc = first_free_arc;
3933 first_free_arc = first_free_arc->next_out_arc;
3935 new_arc->to_state = to_state;
3936 new_arc->insn = ainsn;
3937 ainsn->arc_exists_p = 1;
3938 new_arc->next_out_arc = from_state->first_out_arc;
3939 from_state->first_out_arc = new_arc;
3940 from_state->num_out_arcs++;
3941 new_arc->next_arc_marked_by_insn = NULL;
3945 /* The function returns the first arc starting from STATE. */
3947 first_out_arc (const_state_t state)
3949 return state->first_out_arc;
3952 /* The function returns next out arc after ARC. */
3954 next_out_arc (arc_t arc)
3956 return arc->next_out_arc;
3959 /* Initialization of the abstract data. */
3961 initiate_arcs (void)
3963 first_free_arc = NULL;
3966 /* Finishing work with the abstract data. */
3974 /* Abstract data `automata lists'. */
3976 /* List of free states. */
3977 static automata_list_el_t first_free_automata_list_el;
3979 /* The list being formed. */
3980 static automata_list_el_t current_automata_list;
3982 /* Hash table of automata lists. */
3983 static htab_t automata_list_table;
3985 /* The following function returns free automata list el. It may be
3986 new allocated node or node freed earlier. */
3987 static automata_list_el_t
3988 get_free_automata_list_el (void)
3990 automata_list_el_t result;
3992 if (first_free_automata_list_el != NULL)
3994 result = first_free_automata_list_el;
3995 first_free_automata_list_el
3996 = first_free_automata_list_el->next_automata_list_el;
3999 result = XCREATENODE (struct automata_list_el);
4000 result->automaton = NULL;
4001 result->next_automata_list_el = NULL;
4005 /* The function frees node AUTOMATA_LIST_EL. */
4007 free_automata_list_el (automata_list_el_t automata_list_el)
4009 if (automata_list_el == NULL)
4011 automata_list_el->next_automata_list_el = first_free_automata_list_el;
4012 first_free_automata_list_el = automata_list_el;
4015 /* The function frees list AUTOMATA_LIST. */
4017 free_automata_list (automata_list_el_t automata_list)
4019 automata_list_el_t curr_automata_list_el;
4020 automata_list_el_t next_automata_list_el;
4022 for (curr_automata_list_el = automata_list;
4023 curr_automata_list_el != NULL;
4024 curr_automata_list_el = next_automata_list_el)
4026 next_automata_list_el = curr_automata_list_el->next_automata_list_el;
4027 free_automata_list_el (curr_automata_list_el);
4031 /* Hash value of AUTOMATA_LIST. */
4033 automata_list_hash (const void *automata_list)
4035 unsigned int hash_value;
4036 const_automata_list_el_t curr_automata_list_el;
4039 for (curr_automata_list_el = (const_automata_list_el_t) automata_list;
4040 curr_automata_list_el != NULL;
4041 curr_automata_list_el = curr_automata_list_el->next_automata_list_el)
4042 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
4043 | (hash_value << CHAR_BIT))
4044 + curr_automata_list_el->automaton->automaton_order_num);
4048 /* Return nonzero value if the automata_lists are the same. */
4050 automata_list_eq_p (const void *automata_list_1, const void *automata_list_2)
4052 const_automata_list_el_t automata_list_el_1;
4053 const_automata_list_el_t automata_list_el_2;
4055 for (automata_list_el_1 = (const_automata_list_el_t) automata_list_1,
4056 automata_list_el_2 = (const_automata_list_el_t) automata_list_2;
4057 automata_list_el_1 != NULL && automata_list_el_2 != NULL;
4058 automata_list_el_1 = automata_list_el_1->next_automata_list_el,
4059 automata_list_el_2 = automata_list_el_2->next_automata_list_el)
4060 if (automata_list_el_1->automaton != automata_list_el_2->automaton)
4062 return automata_list_el_1 == automata_list_el_2;
4065 /* Initialization of the abstract data. */
4067 initiate_automata_lists (void)
4069 first_free_automata_list_el = NULL;
4070 automata_list_table = htab_create (1500, automata_list_hash,
4071 automata_list_eq_p, (htab_del) 0);
4074 /* The following function starts new automata list and makes it the
4077 automata_list_start (void)
4079 current_automata_list = NULL;
4082 /* The following function adds AUTOMATON to the current list. */
4084 automata_list_add (automaton_t automaton)
4086 automata_list_el_t el;
4088 el = get_free_automata_list_el ();
4089 el->automaton = automaton;
4090 el->next_automata_list_el = current_automata_list;
4091 current_automata_list = el;
4094 /* The following function finishes forming the current list, inserts
4095 it into the table and returns it. */
4096 static automata_list_el_t
4097 automata_list_finish (void)
4101 if (current_automata_list == NULL)
4103 entry_ptr = htab_find_slot (automata_list_table,
4104 (void *) current_automata_list, INSERT);
4105 if (*entry_ptr == NULL)
4106 *entry_ptr = (void *) current_automata_list;
4108 free_automata_list (current_automata_list);
4109 current_automata_list = NULL;
4110 return (automata_list_el_t) *entry_ptr;
4113 /* Finishing work with the abstract data. */
4115 finish_automata_lists (void)
4117 htab_delete (automata_list_table);
4122 /* The page contains abstract data for work with exclusion sets (see
4123 exclusion_set in file rtl.def). */
4125 /* The following variable refers to an exclusion set returned by
4126 get_excl_set. This is bit string of length equal to cpu units
4127 number. If exclusion set for given unit contains 1 for a unit,
4128 then simultaneous reservation of the units is prohibited. */
4129 static reserv_sets_t excl_set;
4131 /* The array contains exclusion sets for each unit. */
4132 static reserv_sets_t *unit_excl_set_table;
4134 /* The following function forms the array containing exclusion sets
4137 initiate_excl_sets (void)
4140 reserv_sets_t unit_excl_set;
4144 obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4145 excl_set = (reserv_sets_t) obstack_base (&irp);
4146 obstack_finish (&irp);
4147 obstack_blank (&irp, description->units_num * sizeof (reserv_sets_t));
4148 unit_excl_set_table = (reserv_sets_t *) obstack_base (&irp);
4149 obstack_finish (&irp);
4150 /* Evaluate unit exclusion sets. */
4151 for (i = 0; i < description->decls_num; i++)
4153 decl = description->decls [i];
4154 if (decl->mode == dm_unit)
4156 obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4157 unit_excl_set = (reserv_sets_t) obstack_base (&irp);
4158 obstack_finish (&irp);
4159 memset (unit_excl_set, 0, els_in_cycle_reserv * sizeof (set_el_t));
4160 for (el = DECL_UNIT (decl)->excl_list;
4162 el = el->next_unit_set_el)
4164 SET_BIT (unit_excl_set, el->unit_decl->unit_num);
4165 el->unit_decl->in_set_p = TRUE;
4167 unit_excl_set_table [DECL_UNIT (decl)->unit_num] = unit_excl_set;
4172 /* The function sets up and return EXCL_SET which is union of
4173 exclusion sets for each unit in IN_SET. */
4174 static reserv_sets_t
4175 get_excl_set (reserv_sets_t in_set)
4182 memset (excl_set, 0, els_in_cycle_reserv * sizeof (set_el_t));
4183 for (el = 0; el < els_in_cycle_reserv; el++)
4185 for (i = 0; i < CHAR_BIT * sizeof (set_el_t); i++)
4186 if ((in_set[el] >> i) & 1)
4188 start_unit_num = el * CHAR_BIT * sizeof (set_el_t) + i;
4189 if (start_unit_num >= description->units_num)
4191 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4194 |= unit_excl_set_table [start_unit_num] [unit_num];
4202 /* The page contains abstract data for work with presence/absence
4203 pattern sets (see presence_set/absence_set in file rtl.def). */
4205 /* The following arrays contain correspondingly presence, final
4206 presence, absence, and final absence patterns for each unit. */
4207 static pattern_reserv_t *unit_presence_set_table;
4208 static pattern_reserv_t *unit_final_presence_set_table;
4209 static pattern_reserv_t *unit_absence_set_table;
4210 static pattern_reserv_t *unit_final_absence_set_table;
4212 /* The following function forms list of reservation sets for given
4214 static pattern_reserv_t
4215 form_reserv_sets_list (pattern_set_el_t pattern_list)
4217 pattern_set_el_t el;
4218 pattern_reserv_t first, curr, prev;
4221 prev = first = NULL;
4222 for (el = pattern_list; el != NULL; el = el->next_pattern_set_el)
4224 curr = XCREATENODE (struct pattern_reserv);
4225 curr->reserv = alloc_empty_reserv_sets ();
4226 curr->next_pattern_reserv = NULL;
4227 for (i = 0; i < el->units_num; i++)
4229 SET_BIT (curr->reserv, el->unit_decls [i]->unit_num);
4230 el->unit_decls [i]->in_set_p = TRUE;
4233 prev->next_pattern_reserv = curr;
4241 /* The following function forms the array containing presence and
4242 absence pattern sets for each unit. */
4244 initiate_presence_absence_pattern_sets (void)
4249 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4250 unit_presence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4251 obstack_finish (&irp);
4252 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4253 unit_final_presence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4254 obstack_finish (&irp);
4255 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4256 unit_absence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4257 obstack_finish (&irp);
4258 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4259 unit_final_absence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4260 obstack_finish (&irp);
4261 /* Evaluate unit presence/absence sets. */
4262 for (i = 0; i < description->decls_num; i++)
4264 decl = description->decls [i];
4265 if (decl->mode == dm_unit)
4267 unit_presence_set_table [DECL_UNIT (decl)->unit_num]
4268 = form_reserv_sets_list (DECL_UNIT (decl)->presence_list);
4269 unit_final_presence_set_table [DECL_UNIT (decl)->unit_num]
4270 = form_reserv_sets_list (DECL_UNIT (decl)->final_presence_list);
4271 unit_absence_set_table [DECL_UNIT (decl)->unit_num]
4272 = form_reserv_sets_list (DECL_UNIT (decl)->absence_list);
4273 unit_final_absence_set_table [DECL_UNIT (decl)->unit_num]
4274 = form_reserv_sets_list (DECL_UNIT (decl)->final_absence_list);
4279 /* The function checks that CHECKED_SET satisfies all presence pattern
4280 sets for units in ORIGINAL_SET. The function returns TRUE if it
4283 check_presence_pattern_sets (reserv_sets_t checked_set,
4284 reserv_sets_t original_set,
4292 pattern_reserv_t pat_reserv;
4294 for (el = 0; el < els_in_cycle_reserv; el++)
4295 if (original_set[el])
4296 for (i = 0; i < CHAR_BIT * sizeof (set_el_t); i++)
4297 if ((original_set[el] >> i) & 1)
4299 start_unit_num = el * CHAR_BIT * sizeof (set_el_t) + i;
4300 if (start_unit_num >= description->units_num)
4303 && unit_final_presence_set_table [start_unit_num] == NULL)
4305 && unit_presence_set_table [start_unit_num] == NULL))
4308 for (pat_reserv = (final_p
4309 ? unit_final_presence_set_table [start_unit_num]
4310 : unit_presence_set_table [start_unit_num]);
4312 pat_reserv = pat_reserv->next_pattern_reserv)
4314 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4315 if ((checked_set [unit_num] & pat_reserv->reserv [unit_num])
4316 != pat_reserv->reserv [unit_num])
4318 presence_p = presence_p || unit_num >= els_in_cycle_reserv;
4326 /* The function checks that CHECKED_SET satisfies all absence pattern
4327 sets for units in ORIGINAL_SET. The function returns TRUE if it
4330 check_absence_pattern_sets (reserv_sets_t checked_set,
4331 reserv_sets_t original_set,
4338 pattern_reserv_t pat_reserv;
4340 for (el = 0; el < els_in_cycle_reserv; el++)
4341 if (original_set[el])
4342 for (i = 0; i < CHAR_BIT * sizeof (set_el_t); i++)
4343 if ((original_set[el] >> i) & 1)
4345 start_unit_num = el * CHAR_BIT * sizeof (set_el_t) + i;
4346 if (start_unit_num >= description->units_num)
4348 for (pat_reserv = (final_p
4349 ? unit_final_absence_set_table [start_unit_num]
4350 : unit_absence_set_table [start_unit_num]);
4352 pat_reserv = pat_reserv->next_pattern_reserv)
4354 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4355 if ((checked_set [unit_num] & pat_reserv->reserv [unit_num])
4356 != pat_reserv->reserv [unit_num]
4357 && pat_reserv->reserv [unit_num])
4359 if (unit_num >= els_in_cycle_reserv)
4368 /* This page contains code for transformation of original reservations
4369 described in .md file. The main goal of transformations is
4370 simplifying reservation and lifting up all `|' on the top of IR
4371 reservation representation. */
4374 /* The following function makes copy of IR representation of
4375 reservation. The function also substitutes all reservations
4376 defined by define_reservation by corresponding value during making
4379 copy_insn_regexp (regexp_t regexp)
4384 switch (regexp->mode)
4387 result = copy_insn_regexp (REGEXP_RESERV (regexp)->reserv_decl->regexp);
4391 result = XCOPYNODE (struct regexp, regexp);
4395 result = XCOPYNODE (struct regexp, regexp);
4396 REGEXP_REPEAT (result)->regexp
4397 = copy_insn_regexp (REGEXP_REPEAT (regexp)->regexp);
4401 result = XCOPYNODEVAR (struct regexp, regexp,
4402 sizeof (struct regexp) + sizeof (regexp_t)
4403 * (REGEXP_SEQUENCE (regexp)->regexps_num - 1));
4404 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4405 REGEXP_SEQUENCE (result)->regexps [i]
4406 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4410 result = XCOPYNODEVAR (struct regexp, regexp,
4411 sizeof (struct regexp) + sizeof (regexp_t)
4412 * (REGEXP_ALLOF (regexp)->regexps_num - 1));
4413 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4414 REGEXP_ALLOF (result)->regexps [i]
4415 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4419 result = XCOPYNODEVAR (struct regexp, regexp,
4420 sizeof (struct regexp) + sizeof (regexp_t)
4421 * (REGEXP_ONEOF (regexp)->regexps_num - 1));
4422 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4423 REGEXP_ONEOF (result)->regexps [i]
4424 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4428 result = XCOPYNODE (struct regexp, regexp);
4437 /* The following variable is set up 1 if a transformation has been
4439 static int regexp_transformed_p;
4441 /* The function makes transformation
4444 transform_1 (regexp_t regexp)
4451 if (regexp->mode == rm_repeat)
4453 repeat_num = REGEXP_REPEAT (regexp)->repeat_num;
4454 gcc_assert (repeat_num > 1);
4455 operand = REGEXP_REPEAT (regexp)->regexp;
4457 regexp = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4458 + sizeof (regexp_t) * (repeat_num - 1));
4459 regexp->mode = rm_sequence;
4461 REGEXP_SEQUENCE (regexp)->regexps_num = repeat_num;
4462 for (i = 0; i < repeat_num; i++)
4463 REGEXP_SEQUENCE (regexp)->regexps [i] = copy_insn_regexp (operand);
4464 regexp_transformed_p = 1;
4469 /* The function makes transformations
4470 ...,(A,B,...),C,... -> ...,A,B,...,C,...
4471 ...+(A+B+...)+C+... -> ...+A+B+...+C+...
4472 ...|(A|B|...)|C|... -> ...|A|B|...|C|... */
4474 transform_2 (regexp_t regexp)
4476 if (regexp->mode == rm_sequence)
4478 regexp_t sequence = NULL;
4480 int sequence_index = 0;
4483 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4484 if (REGEXP_SEQUENCE (regexp)->regexps [i]->mode == rm_sequence)
4487 sequence = REGEXP_SEQUENCE (regexp)->regexps [i];
4490 if (i < REGEXP_SEQUENCE (regexp)->regexps_num)
4492 gcc_assert (REGEXP_SEQUENCE (sequence)->regexps_num > 1
4493 && REGEXP_SEQUENCE (regexp)->regexps_num > 1);
4494 result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4496 * (REGEXP_SEQUENCE (regexp)->regexps_num
4497 + REGEXP_SEQUENCE (sequence)->regexps_num
4499 result->mode = rm_sequence;
4500 result->pos = regexp->pos;
4501 REGEXP_SEQUENCE (result)->regexps_num
4502 = (REGEXP_SEQUENCE (regexp)->regexps_num
4503 + REGEXP_SEQUENCE (sequence)->regexps_num - 1);
4504 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4505 if (i < sequence_index)
4506 REGEXP_SEQUENCE (result)->regexps [i]
4507 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4508 else if (i > sequence_index)
4509 REGEXP_SEQUENCE (result)->regexps
4510 [i + REGEXP_SEQUENCE (sequence)->regexps_num - 1]
4511 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4513 for (j = 0; j < REGEXP_SEQUENCE (sequence)->regexps_num; j++)
4514 REGEXP_SEQUENCE (result)->regexps [i + j]
4515 = copy_insn_regexp (REGEXP_SEQUENCE (sequence)->regexps [j]);
4516 regexp_transformed_p = 1;
4520 else if (regexp->mode == rm_allof)
4522 regexp_t allof = NULL;
4524 int allof_index = 0;
4527 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4528 if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_allof)
4531 allof = REGEXP_ALLOF (regexp)->regexps [i];
4534 if (i < REGEXP_ALLOF (regexp)->regexps_num)
4536 gcc_assert (REGEXP_ALLOF (allof)->regexps_num > 1
4537 && REGEXP_ALLOF (regexp)->regexps_num > 1);
4538 result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4540 * (REGEXP_ALLOF (regexp)->regexps_num
4541 + REGEXP_ALLOF (allof)->regexps_num - 2));
4542 result->mode = rm_allof;
4543 result->pos = regexp->pos;
4544 REGEXP_ALLOF (result)->regexps_num
4545 = (REGEXP_ALLOF (regexp)->regexps_num
4546 + REGEXP_ALLOF (allof)->regexps_num - 1);
4547 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4548 if (i < allof_index)
4549 REGEXP_ALLOF (result)->regexps [i]
4550 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4551 else if (i > allof_index)
4552 REGEXP_ALLOF (result)->regexps
4553 [i + REGEXP_ALLOF (allof)->regexps_num - 1]
4554 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4556 for (j = 0; j < REGEXP_ALLOF (allof)->regexps_num; j++)
4557 REGEXP_ALLOF (result)->regexps [i + j]
4558 = copy_insn_regexp (REGEXP_ALLOF (allof)->regexps [j]);
4559 regexp_transformed_p = 1;
4563 else if (regexp->mode == rm_oneof)
4565 regexp_t oneof = NULL;
4567 int oneof_index = 0;
4570 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4571 if (REGEXP_ONEOF (regexp)->regexps [i]->mode == rm_oneof)
4574 oneof = REGEXP_ONEOF (regexp)->regexps [i];
4577 if (i < REGEXP_ONEOF (regexp)->regexps_num)
4579 gcc_assert (REGEXP_ONEOF (oneof)->regexps_num > 1
4580 && REGEXP_ONEOF (regexp)->regexps_num > 1);
4581 result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4583 * (REGEXP_ONEOF (regexp)->regexps_num
4584 + REGEXP_ONEOF (oneof)->regexps_num - 2));
4585 result->mode = rm_oneof;
4586 result->pos = regexp->pos;
4587 REGEXP_ONEOF (result)->regexps_num
4588 = (REGEXP_ONEOF (regexp)->regexps_num
4589 + REGEXP_ONEOF (oneof)->regexps_num - 1);
4590 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4591 if (i < oneof_index)
4592 REGEXP_ONEOF (result)->regexps [i]
4593 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4594 else if (i > oneof_index)
4595 REGEXP_ONEOF (result)->regexps
4596 [i + REGEXP_ONEOF (oneof)->regexps_num - 1]
4597 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4599 for (j = 0; j < REGEXP_ONEOF (oneof)->regexps_num; j++)
4600 REGEXP_ONEOF (result)->regexps [i + j]
4601 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [j]);
4602 regexp_transformed_p = 1;
4609 /* The function makes transformations
4610 ...,A|B|...,C,... -> (...,A,C,...)|(...,B,C,...)|...
4611 ...+(A|B|...)+C+... -> (...+A+C+...)|(...+B+C+...)|...
4612 ...+(A,B,...)+C+... -> (...+A+C+...),B,...
4613 ...+(A,B,...)+(C,D,...) -> (A+C),(B+D),... */
4615 transform_3 (regexp_t regexp)
4617 if (regexp->mode == rm_sequence)
4619 regexp_t oneof = NULL;
4620 int oneof_index = 0;
4625 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4626 if (REGEXP_SEQUENCE (regexp)->regexps [i]->mode == rm_oneof)
4629 oneof = REGEXP_SEQUENCE (regexp)->regexps [i];
4632 if (i < REGEXP_SEQUENCE (regexp)->regexps_num)
4634 gcc_assert (REGEXP_ONEOF (oneof)->regexps_num > 1
4635 && REGEXP_SEQUENCE (regexp)->regexps_num > 1);
4636 result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4638 * (REGEXP_ONEOF (oneof)->regexps_num - 1));
4639 result->mode = rm_oneof;
4640 result->pos = regexp->pos;
4641 REGEXP_ONEOF (result)->regexps_num
4642 = REGEXP_ONEOF (oneof)->regexps_num;
4643 for (i = 0; i < REGEXP_ONEOF (result)->regexps_num; i++)
4646 = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4648 * (REGEXP_SEQUENCE (regexp)->regexps_num - 1));
4649 sequence->mode = rm_sequence;
4650 sequence->pos = regexp->pos;
4651 REGEXP_SEQUENCE (sequence)->regexps_num
4652 = REGEXP_SEQUENCE (regexp)->regexps_num;
4653 REGEXP_ONEOF (result)->regexps [i] = sequence;
4654 for (j = 0; j < REGEXP_SEQUENCE (sequence)->regexps_num; j++)
4655 if (j != oneof_index)
4656 REGEXP_SEQUENCE (sequence)->regexps [j]
4657 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [j]);
4659 REGEXP_SEQUENCE (sequence)->regexps [j]
4660 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [i]);
4662 regexp_transformed_p = 1;
4666 else if (regexp->mode == rm_allof)
4668 regexp_t oneof = NULL;
4670 int oneof_index = 0;
4671 int max_seq_length, allof_length;
4673 regexp_t allof = NULL;
4674 regexp_t allof_op = NULL;
4677 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4678 if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_oneof)
4681 oneof = REGEXP_ALLOF (regexp)->regexps [i];
4684 if (i < REGEXP_ALLOF (regexp)->regexps_num)
4686 gcc_assert (REGEXP_ONEOF (oneof)->regexps_num > 1
4687 && REGEXP_ALLOF (regexp)->regexps_num > 1);
4688 result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4690 * (REGEXP_ONEOF (oneof)->regexps_num - 1));
4691 result->mode = rm_oneof;
4692 result->pos = regexp->pos;
4693 REGEXP_ONEOF (result)->regexps_num
4694 = REGEXP_ONEOF (oneof)->regexps_num;
4695 for (i = 0; i < REGEXP_ONEOF (result)->regexps_num; i++)
4698 = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4700 * (REGEXP_ALLOF (regexp)->regexps_num - 1));
4701 allof->mode = rm_allof;
4702 allof->pos = regexp->pos;
4703 REGEXP_ALLOF (allof)->regexps_num
4704 = REGEXP_ALLOF (regexp)->regexps_num;
4705 REGEXP_ONEOF (result)->regexps [i] = allof;
4706 for (j = 0; j < REGEXP_ALLOF (allof)->regexps_num; j++)
4707 if (j != oneof_index)
4708 REGEXP_ALLOF (allof)->regexps [j]
4709 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [j]);
4711 REGEXP_ALLOF (allof)->regexps [j]
4712 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [i]);
4714 regexp_transformed_p = 1;
4718 if (regexp->mode == rm_allof)
4719 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4721 switch (REGEXP_ALLOF (regexp)->regexps [i]->mode)
4724 seq = REGEXP_ALLOF (regexp)->regexps [i];
4725 if (max_seq_length < REGEXP_SEQUENCE (seq)->regexps_num)
4726 max_seq_length = REGEXP_SEQUENCE (seq)->regexps_num;
4739 if (max_seq_length != 0)
4741 gcc_assert (max_seq_length != 1
4742 && REGEXP_ALLOF (regexp)->regexps_num > 1);
4743 result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4744 + sizeof (regexp_t) * (max_seq_length - 1));
4745 result->mode = rm_sequence;
4746 result->pos = regexp->pos;
4747 REGEXP_SEQUENCE (result)->regexps_num = max_seq_length;
4748 for (i = 0; i < max_seq_length; i++)
4751 for (j = 0; j < REGEXP_ALLOF (regexp)->regexps_num; j++)
4752 switch (REGEXP_ALLOF (regexp)->regexps [j]->mode)
4755 if (i < (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4756 ->regexps [j])->regexps_num))
4759 = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4769 allof_op = REGEXP_ALLOF (regexp)->regexps [j];
4777 if (allof_length == 1)
4778 REGEXP_SEQUENCE (result)->regexps [i] = allof_op;
4781 allof = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4783 * (allof_length - 1));
4784 allof->mode = rm_allof;
4785 allof->pos = regexp->pos;
4786 REGEXP_ALLOF (allof)->regexps_num = allof_length;
4787 REGEXP_SEQUENCE (result)->regexps [i] = allof;
4789 for (j = 0; j < REGEXP_ALLOF (regexp)->regexps_num; j++)
4790 if (REGEXP_ALLOF (regexp)->regexps [j]->mode == rm_sequence
4792 (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4793 ->regexps [j])->regexps_num)))
4795 allof_op = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4798 REGEXP_ALLOF (allof)->regexps [allof_length]
4803 && (REGEXP_ALLOF (regexp)->regexps [j]->mode
4805 || (REGEXP_ALLOF (regexp)->regexps [j]->mode
4808 allof_op = REGEXP_ALLOF (regexp)->regexps [j];
4809 REGEXP_ALLOF (allof)->regexps [allof_length]
4815 regexp_transformed_p = 1;
4822 /* The function traverses IR of reservation and applies transformations
4823 implemented by FUNC. */
4825 regexp_transform_func (regexp_t regexp, regexp_t (*func) (regexp_t regexp))
4829 switch (regexp->mode)
4832 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4833 REGEXP_SEQUENCE (regexp)->regexps [i]
4834 = regexp_transform_func (REGEXP_SEQUENCE (regexp)->regexps [i],
4839 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4840 REGEXP_ALLOF (regexp)->regexps [i]
4841 = regexp_transform_func (REGEXP_ALLOF (regexp)->regexps [i], func);
4845 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4846 REGEXP_ONEOF (regexp)->regexps [i]
4847 = regexp_transform_func (REGEXP_ONEOF (regexp)->regexps [i], func);
4851 REGEXP_REPEAT (regexp)->regexp
4852 = regexp_transform_func (REGEXP_REPEAT (regexp)->regexp, func);
4862 return (*func) (regexp);
4865 /* The function applies all transformations for IR representation of
4866 reservation REGEXP. */
4868 transform_regexp (regexp_t regexp)
4870 regexp = regexp_transform_func (regexp, transform_1);
4873 regexp_transformed_p = 0;
4874 regexp = regexp_transform_func (regexp, transform_2);
4875 regexp = regexp_transform_func (regexp, transform_3);
4877 while (regexp_transformed_p);
4881 /* The function applies all transformations for reservations of all
4882 insn declarations. */
4884 transform_insn_regexps (void)
4889 transform_time = create_ticker ();
4890 add_advance_cycle_insn_decl ();
4892 fprintf (stderr, "Reservation transformation...");
4893 for (i = 0; i < description->decls_num; i++)
4895 decl = description->decls [i];
4896 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
4897 DECL_INSN_RESERV (decl)->transformed_regexp
4898 = transform_regexp (copy_insn_regexp
4899 (DECL_INSN_RESERV (decl)->regexp));
4902 fprintf (stderr, "done\n");
4903 ticker_off (&transform_time);
4908 /* The following variable value is TRUE if the first annotated message
4909 about units to automata distribution has been output. */
4910 static int annotation_message_reported_p;
4912 /* The vector contains all decls which are automata. */
4913 static VEC(decl_t, heap) *automaton_decls;
4915 /* The following structure describes usage of a unit in a reservation. */
4918 unit_decl_t unit_decl;
4919 /* The following forms a list of units used on the same cycle in the
4920 same alternative. The list is ordered by the correspdoning unit
4921 declarations and there is no unit declaration duplication in the
4923 struct unit_usage *next;
4925 typedef struct unit_usage *unit_usage_t;
4927 DEF_VEC_P(unit_usage_t);
4928 DEF_VEC_ALLOC_P(unit_usage_t, heap);
4930 /* Obstack for unit_usage structures. */
4931 static struct obstack unit_usages;
4933 /* VLA for representation of array of pointers to unit usage
4934 structures. There is an element for each combination of
4935 (alternative number, cycle). Unit usages on given cycle in
4936 alternative with given number are referred through element with
4937 index equals to the cycle * number of all alternatives in the
4938 regexp + the alternative number. */
4939 static VEC(unit_usage_t, heap) *cycle_alt_unit_usages;
4941 /* The following function creates the structure unit_usage for UNIT on
4942 CYCLE in REGEXP alternative with ALT_NUM. The structure is made
4943 accessed through cycle_alt_unit_usages. */
4945 store_alt_unit_usage (regexp_t regexp, regexp_t unit, int cycle,
4949 unit_decl_t unit_decl;
4950 unit_usage_t unit_usage_ptr, curr, prev;
4953 gcc_assert (regexp && regexp->mode == rm_oneof
4954 && alt_num < REGEXP_ONEOF (regexp)->regexps_num);
4955 unit_decl = REGEXP_UNIT (unit)->unit_decl;
4957 length = (cycle + 1) * REGEXP_ONEOF (regexp)->regexps_num;
4958 while (VEC_length (unit_usage_t, cycle_alt_unit_usages) < length)
4959 VEC_safe_push (unit_usage_t, heap, cycle_alt_unit_usages, 0);
4961 index = cycle * REGEXP_ONEOF (regexp)->regexps_num + alt_num;
4963 for (curr = VEC_index (unit_usage_t, cycle_alt_unit_usages, index);
4965 prev = curr, curr = curr->next)
4966 if (curr->unit_decl >= unit_decl)
4968 if (curr != NULL && curr->unit_decl == unit_decl)
4970 obstack_blank (&unit_usages, sizeof (struct unit_usage));
4971 unit_usage_ptr = (struct unit_usage *) obstack_base (&unit_usages);
4972 obstack_finish (&unit_usages);
4973 unit_usage_ptr->unit_decl = unit_decl;
4974 unit_decl->last_distribution_check_cycle = -1; /* undefined */
4975 unit_usage_ptr->next = curr;
4977 VEC_replace (unit_usage_t, cycle_alt_unit_usages, index, unit_usage_ptr);
4979 prev->next = unit_usage_ptr;
4982 /* Return true if unit UNIT_DECL is present on the LIST. */
4984 unit_present_on_list_p (unit_usage_t list, unit_decl_t unit_decl)
4986 while (list != NULL)
4988 if (list->unit_decl == unit_decl)
4995 /* The function returns true if reservations of alternatives ALT1 and
4996 ALT2 are equal after excluding reservations of units of
4997 EXCLUDED_AUTOMATON_DECL. */
4999 equal_alternatives_p (int alt1, int alt2, int n_alts,
5000 struct automaton_decl *excluded_automaton_decl)
5003 unit_usage_t list1, list2;
5006 i < (int) VEC_length (unit_usage_t, cycle_alt_unit_usages);
5009 for (list1 = VEC_index (unit_usage_t, cycle_alt_unit_usages, i + alt1),
5010 list2 = VEC_index (unit_usage_t, cycle_alt_unit_usages, i + alt2);;
5011 list1 = list1->next, list2 = list2->next)
5013 while (list1 != NULL
5014 && list1->unit_decl->automaton_decl == excluded_automaton_decl)
5015 list1 = list1->next;
5016 while (list2 != NULL
5017 && list2->unit_decl->automaton_decl == excluded_automaton_decl)
5018 list2 = list2->next;
5019 if (list1 == NULL || list2 == NULL)
5026 if (list1->unit_decl != list2->unit_decl)
5034 DEF_VEC_ALLOC_I(int, heap);
5036 /* The function processes given REGEXP to find units with the wrong
5039 check_regexp_units_distribution (const char *insn_reserv_name,
5042 int i, j, k, cycle, start, n_alts, alt, alt2;
5043 bool annotation_reservation_message_reported_p;
5044 regexp_t seq, allof, unit;
5045 struct unit_usage *unit_usage_ptr;
5046 VEC(int, heap) *marked;
5048 if (regexp == NULL || regexp->mode != rm_oneof)
5050 /* Store all unit usages in the regexp: */
5051 obstack_init (&unit_usages);
5052 cycle_alt_unit_usages = VEC_alloc (unit_usage_t, heap, 10);
5054 for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
5056 seq = REGEXP_ONEOF (regexp)->regexps [i];
5060 for (j = 0; j < REGEXP_SEQUENCE (seq)->regexps_num; j++)
5062 allof = REGEXP_SEQUENCE (seq)->regexps [j];
5063 switch (allof->mode)
5066 for (k = 0; k < REGEXP_ALLOF (allof)->regexps_num; k++)
5068 unit = REGEXP_ALLOF (allof)->regexps [k];
5069 if (unit->mode == rm_unit)
5070 store_alt_unit_usage (regexp, unit, j, i);
5072 gcc_assert (unit->mode == rm_nothing);
5077 store_alt_unit_usage (regexp, allof, j, i);
5090 for (k = 0; k < REGEXP_ALLOF (seq)->regexps_num; k++)
5092 unit = REGEXP_ALLOF (seq)->regexps [k];
5096 store_alt_unit_usage (regexp, unit, 0, i);
5109 store_alt_unit_usage (regexp, seq, 0, i);
5119 /* Check distribution: */
5120 for (i = 0; i < (int) VEC_length (unit_usage_t, cycle_alt_unit_usages); i++)
5121 for (unit_usage_ptr = VEC_index (unit_usage_t, cycle_alt_unit_usages, i);
5122 unit_usage_ptr != NULL;
5123 unit_usage_ptr = unit_usage_ptr->next)
5124 unit_usage_ptr->unit_decl->last_distribution_check_cycle = -1;
5125 n_alts = REGEXP_ONEOF (regexp)->regexps_num;
5126 marked = VEC_alloc (int, heap, n_alts);
5127 for (i = 0; i < n_alts; i++)
5128 VEC_safe_push (int, heap, marked, 0);
5129 annotation_reservation_message_reported_p = false;
5130 for (i = 0; i < (int) VEC_length (unit_usage_t, cycle_alt_unit_usages); i++)
5133 start = cycle * n_alts;
5134 for (unit_usage_ptr = VEC_index (unit_usage_t, cycle_alt_unit_usages, i);
5135 unit_usage_ptr != NULL;
5136 unit_usage_ptr = unit_usage_ptr->next)
5138 if (unit_usage_ptr->unit_decl->last_distribution_check_cycle == cycle)
5140 unit_usage_ptr->unit_decl->last_distribution_check_cycle = cycle;
5141 for (alt = 0; alt < n_alts; alt++)
5142 if (! unit_present_on_list_p (VEC_index (unit_usage_t,
5143 cycle_alt_unit_usages,
5145 unit_usage_ptr->unit_decl))
5149 memset (VEC_address (int, marked), 0, n_alts * sizeof (int));
5150 for (alt = 0; alt < n_alts; alt++)
5152 if (! unit_present_on_list_p (VEC_index (unit_usage_t,
5153 cycle_alt_unit_usages,
5155 unit_usage_ptr->unit_decl))
5158 j < (int) VEC_length (unit_usage_t, cycle_alt_unit_usages);
5162 if (! unit_present_on_list_p
5163 (VEC_index (unit_usage_t, cycle_alt_unit_usages,
5165 unit_usage_ptr->unit_decl)
5166 && equal_alternatives_p (alt, alt2, n_alts,
5168 ->unit_decl->automaton_decl))
5170 VEC_replace (int, marked, alt, 1);
5171 VEC_replace (int, marked, alt2, 1);
5175 for (alt = 0; alt < n_alts && VEC_index (int, marked, alt); alt++)
5177 if (alt < n_alts && 0)
5179 if (! annotation_message_reported_p)
5181 fprintf (stderr, "\n");
5182 error ("The following units do not satisfy units-automata distribution rule");
5183 error ("(Unit presence on one alt and its absence on other alt\n");
5184 error (" result in different other automata reservations)");
5185 annotation_message_reported_p = TRUE;
5187 if (! annotation_reservation_message_reported_p)
5189 error ("Reserv %s:", insn_reserv_name);
5190 annotation_reservation_message_reported_p = true;
5192 error (" Unit %s, cycle %d, alt %d, another alt %d",
5193 unit_usage_ptr->unit_decl->name, cycle, i % n_alts, alt);
5197 VEC_free (int, heap, marked);
5198 VEC_free (unit_usage_t, heap, cycle_alt_unit_usages);
5199 obstack_free (&unit_usages, NULL);
5202 /* The function finds units which violates units to automata
5203 distribution rule. If the units exist, report about them. */
5205 check_unit_distributions_to_automata (void)
5211 fprintf (stderr, "Check unit distributions to automata...");
5212 automaton_decls = NULL;
5213 for (i = 0; i < description->decls_num; i++)
5215 decl = description->decls [i];
5216 if (decl->mode == dm_automaton)
5217 VEC_safe_push (decl_t, heap, automaton_decls, decl);
5219 if (VEC_length (decl_t, automaton_decls) > 1)
5221 annotation_message_reported_p = FALSE;
5222 for (i = 0; i < description->decls_num; i++)
5224 decl = description->decls [i];
5225 if (decl->mode == dm_insn_reserv)
5226 check_regexp_units_distribution
5227 (DECL_INSN_RESERV (decl)->name,
5228 DECL_INSN_RESERV (decl)->transformed_regexp);
5231 VEC_free (decl_t, heap, automaton_decls);
5233 fprintf (stderr, "done\n");
5238 /* The page contains code for building alt_states (see comments for
5239 IR) describing all possible insns reservations of an automaton. */
5241 /* Current state being formed for which the current alt_state
5243 static state_t state_being_formed;
5245 /* Current alt_state being formed. */
5246 static alt_state_t alt_state_being_formed;
5248 /* This recursive function processes `,' and units in reservation
5249 REGEXP for forming alt_states of AUTOMATON. It is believed that
5250 CURR_CYCLE is start cycle of all reservation REGEXP. */
5252 process_seq_for_forming_states (regexp_t regexp, automaton_t automaton,
5260 switch (regexp->mode)
5263 if (REGEXP_UNIT (regexp)->unit_decl->corresponding_automaton_num
5264 == automaton->automaton_order_num)
5265 set_state_reserv (state_being_formed, curr_cycle,
5266 REGEXP_UNIT (regexp)->unit_decl->unit_num);
5270 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
5272 = process_seq_for_forming_states
5273 (REGEXP_SEQUENCE (regexp)->regexps [i], automaton, curr_cycle) + 1;
5278 int finish_cycle = 0;
5281 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
5283 cycle = process_seq_for_forming_states (REGEXP_ALLOF (regexp)
5285 automaton, curr_cycle);
5286 if (finish_cycle < cycle)
5287 finish_cycle = cycle;
5289 return finish_cycle;
5300 /* This recursive function finishes forming ALT_STATE of AUTOMATON and
5301 inserts alt_state into the table. */
5303 finish_forming_alt_state (alt_state_t alt_state,
5304 automaton_t automaton ATTRIBUTE_UNUSED)
5306 state_t state_in_table;
5307 state_t corresponding_state;
5309 corresponding_state = alt_state->state;
5310 state_in_table = insert_state (corresponding_state);
5311 if (state_in_table != corresponding_state)
5313 free_state (corresponding_state);
5314 alt_state->state = state_in_table;
5318 /* The following variable value is current automaton insn for whose
5319 reservation the alt states are created. */
5320 static ainsn_t curr_ainsn;
5322 /* This recursive function processes `|' in reservation REGEXP for
5323 forming alt_states of AUTOMATON. List of the alt states should
5324 have the same order as in the description. */
5326 process_alts_for_forming_states (regexp_t regexp, automaton_t automaton,
5331 if (regexp->mode != rm_oneof)
5333 alt_state_being_formed = get_free_alt_state ();
5334 state_being_formed = get_free_state (1, automaton);
5335 alt_state_being_formed->state = state_being_formed;
5336 /* We inserts in reverse order but we process alternatives also
5337 in reverse order. So we have the same order of alternative
5338 as in the description. */
5339 alt_state_being_formed->next_alt_state = curr_ainsn->alt_states;
5340 curr_ainsn->alt_states = alt_state_being_formed;
5341 (void) process_seq_for_forming_states (regexp, automaton, 0);
5342 finish_forming_alt_state (alt_state_being_formed, automaton);
5346 gcc_assert (!inside_oneof_p);
5347 /* We processes it in reverse order to get list with the same
5348 order as in the description. See also the previous
5350 for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
5351 process_alts_for_forming_states (REGEXP_ONEOF (regexp)->regexps [i],
5356 /* Create nodes alt_state for all AUTOMATON insns. */
5358 create_alt_states (automaton_t automaton)
5360 struct insn_reserv_decl *reserv_decl;
5362 for (curr_ainsn = automaton->ainsn_list;
5364 curr_ainsn = curr_ainsn->next_ainsn)
5366 reserv_decl = curr_ainsn->insn_reserv_decl;
5367 if (reserv_decl != DECL_INSN_RESERV (advance_cycle_insn_decl))
5369 curr_ainsn->alt_states = NULL;
5370 process_alts_for_forming_states (reserv_decl->transformed_regexp,
5372 curr_ainsn->sorted_alt_states
5373 = uniq_sort_alt_states (curr_ainsn->alt_states);
5380 /* The page contains major code for building DFA(s) for fast pipeline
5381 hazards recognition. */
5383 /* The function forms list of ainsns of AUTOMATON with the same
5387 form_ainsn_with_same_reservs (automaton_t automaton)
5391 VEC(ainsn_t, heap) *last_insns = VEC_alloc (ainsn_t, heap, 150);
5393 for (curr_ainsn = automaton->ainsn_list;
5395 curr_ainsn = curr_ainsn->next_ainsn)
5396 if (curr_ainsn->insn_reserv_decl
5397 == DECL_INSN_RESERV (advance_cycle_insn_decl))
5399 curr_ainsn->next_same_reservs_insn = NULL;
5400 curr_ainsn->first_insn_with_same_reservs = 1;
5404 for (i = 0; i < VEC_length (ainsn_t, last_insns); i++)
5406 (curr_ainsn->sorted_alt_states,
5407 VEC_index (ainsn_t, last_insns, i)->sorted_alt_states))
5409 curr_ainsn->next_same_reservs_insn = NULL;
5410 if (i < VEC_length (ainsn_t, last_insns))
5412 curr_ainsn->first_insn_with_same_reservs = 0;
5413 VEC_index (ainsn_t, last_insns, i)->next_same_reservs_insn
5415 VEC_replace (ainsn_t, last_insns, i, curr_ainsn);
5419 VEC_safe_push (ainsn_t, heap, last_insns, curr_ainsn);
5420 curr_ainsn->first_insn_with_same_reservs = 1;
5423 VEC_free (ainsn_t, heap, last_insns);
5426 /* Forming unit reservations which can affect creating the automaton
5427 states achieved from a given state. It permits to build smaller
5428 automata in many cases. We would have the same automata after
5429 the minimization without such optimization, but the automaton
5430 right after the building could be huge. So in other words, usage
5431 of reservs_matter means some minimization during building the
5433 static reserv_sets_t
5434 form_reservs_matter (automaton_t automaton)
5437 reserv_sets_t reservs_matter = alloc_empty_reserv_sets();
5439 for (cycle = 0; cycle < max_cycles_num; cycle++)
5440 for (unit = 0; unit < description->units_num; unit++)
5441 if (units_array [unit]->automaton_decl
5442 == automaton->corresponding_automaton_decl
5443 && (cycle >= units_array [unit]->min_occ_cycle_num
5444 /* We can not remove queried unit from reservations. */
5445 || units_array [unit]->query_p
5446 /* We can not remove units which are used
5447 `exclusion_set', `presence_set',
5448 `final_presence_set', `absence_set', and
5449 `final_absence_set'. */
5450 || units_array [unit]->in_set_p))
5451 set_unit_reserv (reservs_matter, cycle, unit);
5452 return reservs_matter;
5455 /* The following function creates all states of nondeterministic AUTOMATON. */
5457 make_automaton (automaton_t automaton)
5460 struct insn_reserv_decl *insn_reserv_decl;
5461 alt_state_t alt_state;
5463 state_t start_state;
5465 ainsn_t advance_cycle_ainsn;
5467 VEC(state_t, heap) *state_stack = VEC_alloc(state_t, heap, 150);
5469 reserv_sets_t reservs_matter = form_reservs_matter (automaton);
5471 /* Create the start state (empty state). */
5472 start_state = insert_state (get_free_state (1, automaton));
5473 automaton->start_state = start_state;
5474 start_state->it_was_placed_in_stack_for_NDFA_forming = 1;
5475 VEC_safe_push (state_t, heap, state_stack, start_state);
5477 while (VEC_length (state_t, state_stack) != 0)
5479 state = VEC_pop (state_t, state_stack);
5480 advance_cycle_ainsn = NULL;
5481 for (ainsn = automaton->ainsn_list;
5483 ainsn = ainsn->next_ainsn)
5484 if (ainsn->first_insn_with_same_reservs)
5486 insn_reserv_decl = ainsn->insn_reserv_decl;
5487 if (insn_reserv_decl != DECL_INSN_RESERV (advance_cycle_insn_decl))
5489 /* We process alt_states in the same order as they are
5490 present in the description. */
5492 for (alt_state = ainsn->alt_states;
5494 alt_state = alt_state->next_alt_state)
5496 state2 = alt_state->state;
5497 if (!intersected_state_reservs_p (state, state2))
5499 state2 = states_union (state, state2, reservs_matter);
5500 if (!state2->it_was_placed_in_stack_for_NDFA_forming)
5502 state2->it_was_placed_in_stack_for_NDFA_forming
5504 VEC_safe_push (state_t, heap, state_stack, state2);
5506 if (progress_flag && states_n % 100 == 0)
5507 fprintf (stderr, ".");
5509 added_arc = add_arc (state, state2, ainsn);
5514 if (!ndfa_flag && added_arc != NULL)
5516 for (alt_state = ainsn->alt_states;
5518 alt_state = alt_state->next_alt_state)
5519 state2 = alt_state->state;
5523 advance_cycle_ainsn = ainsn;
5525 /* Add transition to advance cycle. */
5526 state2 = state_shift (state, reservs_matter);
5527 if (!state2->it_was_placed_in_stack_for_NDFA_forming)
5529 state2->it_was_placed_in_stack_for_NDFA_forming = 1;
5530 VEC_safe_push (state_t, heap, state_stack, state2);
5532 if (progress_flag && states_n % 100 == 0)
5533 fprintf (stderr, ".");
5535 gcc_assert (advance_cycle_ainsn);
5536 add_arc (state, state2, advance_cycle_ainsn);
5538 VEC_free (state_t, heap, state_stack);
5541 /* Form lists of all arcs of STATE marked by the same ainsn. */
5543 form_arcs_marked_by_insn (state_t state)
5549 for (i = 0; i < description->decls_num; i++)
5551 decl = description->decls [i];
5552 if (decl->mode == dm_insn_reserv)
5553 DECL_INSN_RESERV (decl)->arcs_marked_by_insn = NULL;
5555 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5557 gcc_assert (arc->insn);
5558 arc->next_arc_marked_by_insn
5559 = arc->insn->insn_reserv_decl->arcs_marked_by_insn;
5560 arc->insn->insn_reserv_decl->arcs_marked_by_insn = arc;
5564 /* The function creates composed state (see comments for IR) from
5565 ORIGINAL_STATE and list of arcs ARCS_MARKED_BY_INSN marked by the
5566 same insn. If the composed state is not in STATE_STACK yet, it is
5567 pushed into STATE_STACK. */
5570 create_composed_state (state_t original_state, arc_t arcs_marked_by_insn,
5571 VEC(state_t, heap) **state_stack)
5574 alt_state_t alt_state, curr_alt_state;
5575 alt_state_t new_alt_state;
5578 state_t state_in_table;
5580 alt_state_t canonical_alt_states_list;
5582 int new_state_p = 0;
5584 if (arcs_marked_by_insn == NULL)
5586 if (arcs_marked_by_insn->next_arc_marked_by_insn == NULL)
5587 state = arcs_marked_by_insn->to_state;
5590 gcc_assert (ndfa_flag);
5591 /* Create composed state. */
5592 state = get_free_state (0, arcs_marked_by_insn->to_state->automaton);
5593 curr_alt_state = NULL;
5594 for (curr_arc = arcs_marked_by_insn;
5596 curr_arc = curr_arc->next_arc_marked_by_insn)
5597 if (curr_arc->to_state->component_states == NULL)
5599 new_alt_state = get_free_alt_state ();
5600 new_alt_state->next_alt_state = curr_alt_state;
5601 new_alt_state->state = curr_arc->to_state;
5602 curr_alt_state = new_alt_state;
5605 for (alt_state = curr_arc->to_state->component_states;
5607 alt_state = alt_state->next_sorted_alt_state)
5609 new_alt_state = get_free_alt_state ();
5610 new_alt_state->next_alt_state = curr_alt_state;
5611 new_alt_state->state = alt_state->state;
5612 gcc_assert (!alt_state->state->component_states);
5613 curr_alt_state = new_alt_state;
5615 /* There are not identical sets in the alt state list. */
5616 canonical_alt_states_list = uniq_sort_alt_states (curr_alt_state);
5617 if (canonical_alt_states_list->next_sorted_alt_state == NULL)
5620 state = canonical_alt_states_list->state;
5621 free_state (temp_state);
5625 state->component_states = canonical_alt_states_list;
5626 state_in_table = insert_state (state);
5627 if (state_in_table != state)
5630 (state_in_table->it_was_placed_in_stack_for_DFA_forming);
5632 state = state_in_table;
5636 gcc_assert (!state->it_was_placed_in_stack_for_DFA_forming);
5638 for (curr_alt_state = state->component_states;
5639 curr_alt_state != NULL;
5640 curr_alt_state = curr_alt_state->next_sorted_alt_state)
5641 for (curr_arc = first_out_arc (curr_alt_state->state);
5643 curr_arc = next_out_arc (curr_arc))
5644 add_arc (state, curr_arc->to_state, curr_arc->insn);
5646 arcs_marked_by_insn->to_state = state;
5647 for (alts_number = 0,
5648 curr_arc = arcs_marked_by_insn->next_arc_marked_by_insn;
5650 curr_arc = next_arc)
5652 next_arc = curr_arc->next_arc_marked_by_insn;
5653 remove_arc (original_state, curr_arc);
5658 if (!state->it_was_placed_in_stack_for_DFA_forming)
5660 state->it_was_placed_in_stack_for_DFA_forming = 1;
5661 VEC_safe_push (state_t, heap, *state_stack, state);
5666 /* The function transforms nondeterministic AUTOMATON into
5670 NDFA_to_DFA (automaton_t automaton)
5672 state_t start_state;
5675 VEC(state_t, heap) *state_stack;
5679 state_stack = VEC_alloc (state_t, heap, 0);
5681 /* Create the start state (empty state). */
5682 start_state = automaton->start_state;
5683 start_state->it_was_placed_in_stack_for_DFA_forming = 1;
5684 VEC_safe_push (state_t, heap, state_stack, start_state);
5686 while (VEC_length (state_t, state_stack) != 0)
5688 state = VEC_pop (state_t, state_stack);
5689 form_arcs_marked_by_insn (state);
5690 for (i = 0; i < description->decls_num; i++)
5692 decl = description->decls [i];
5693 if (decl->mode == dm_insn_reserv
5694 && create_composed_state
5695 (state, DECL_INSN_RESERV (decl)->arcs_marked_by_insn,
5699 if (progress_flag && states_n % 100 == 0)
5700 fprintf (stderr, ".");
5704 VEC_free (state_t, heap, state_stack);
5707 /* The following variable value is current number (1, 2, ...) of passing
5709 static int curr_state_graph_pass_num;
5711 /* This recursive function passes all states achieved from START_STATE
5712 and applies APPLIED_FUNC to them. */
5714 pass_state_graph (state_t start_state, void (*applied_func) (state_t state))
5718 if (start_state->pass_num == curr_state_graph_pass_num)
5720 start_state->pass_num = curr_state_graph_pass_num;
5721 (*applied_func) (start_state);
5722 for (arc = first_out_arc (start_state);
5724 arc = next_out_arc (arc))
5725 pass_state_graph (arc->to_state, applied_func);
5728 /* This recursive function passes all states of AUTOMATON and applies
5729 APPLIED_FUNC to them. */
5731 pass_states (automaton_t automaton, void (*applied_func) (state_t state))
5733 curr_state_graph_pass_num++;
5734 pass_state_graph (automaton->start_state, applied_func);
5737 /* The function initializes code for passing of all states. */
5739 initiate_pass_states (void)
5741 curr_state_graph_pass_num = 0;
5744 /* The following vla is used for storing pointers to all achieved
5746 static VEC(state_t, heap) *all_achieved_states;
5748 /* This function is called by function pass_states to add an achieved
5751 add_achieved_state (state_t state)
5753 VEC_safe_push (state_t, heap, all_achieved_states, state);
5756 /* The function sets up equivalence numbers of insns which mark all
5757 out arcs of STATE by equiv_class_num_1 (if ODD_ITERATION_FLAG has
5758 nonzero value) or by equiv_class_num_2 of the destination state.
5759 The function returns number of out arcs of STATE. */
5761 set_out_arc_insns_equiv_num (state_t state, int odd_iteration_flag)
5765 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5767 gcc_assert (!arc->insn->insn_reserv_decl->equiv_class_num);
5768 arc->insn->insn_reserv_decl->equiv_class_num
5769 = (odd_iteration_flag
5770 ? arc->to_state->equiv_class_num_1
5771 : arc->to_state->equiv_class_num_2);
5772 gcc_assert (arc->insn->insn_reserv_decl->equiv_class_num);
5776 /* The function clears equivalence numbers and alt_states in all insns
5777 which mark all out arcs of STATE. */
5779 clear_arc_insns_equiv_num (state_t state)
5783 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5784 arc->insn->insn_reserv_decl->equiv_class_num = 0;
5788 /* The following function returns TRUE if STATE reserves the unit with
5789 UNIT_NUM on the first cycle. */
5791 first_cycle_unit_presence (state_t state, int unit_num)
5793 alt_state_t alt_state;
5795 if (state->component_states == NULL)
5796 return test_unit_reserv (state->reservs, 0, unit_num);
5799 for (alt_state = state->component_states;
5801 alt_state = alt_state->next_sorted_alt_state)
5802 if (test_unit_reserv (alt_state->state->reservs, 0, unit_num))
5808 /* This fills in the presence_signature[] member of STATE. */
5810 cache_presence (state_t state)
5814 sz = (description->query_units_num + sizeof (int) * CHAR_BIT - 1)
5815 / (sizeof (int) * CHAR_BIT);
5817 state->presence_signature = XCREATENODEVEC (unsigned int, sz);
5818 for (i = 0; i < description->units_num; i++)
5819 if (units_array [i]->query_p)
5821 int presence1_p = first_cycle_unit_presence (state, i);
5822 state->presence_signature[num / (sizeof (int) * CHAR_BIT)]
5823 |= (!!presence1_p) << (num % (sizeof (int) * CHAR_BIT));
5828 /* The function returns nonzero value if STATE is not equivalent to
5829 ANOTHER_STATE from the same current partition on equivalence
5830 classes. Another state has ANOTHER_STATE_OUT_ARCS_NUM number of
5831 output arcs. Iteration of making equivalence partition is defined
5832 by ODD_ITERATION_FLAG. */
5834 state_is_differed (state_t state, state_t another_state,
5835 int odd_iteration_flag)
5838 unsigned int sz, si;
5840 gcc_assert (state->num_out_arcs == another_state->num_out_arcs);
5842 sz = (description->query_units_num + sizeof (int) * CHAR_BIT - 1)
5843 / (sizeof (int) * CHAR_BIT);
5845 for (si = 0; si < sz; si++)
5846 gcc_assert (state->presence_signature[si]
5847 == another_state->presence_signature[si]);
5849 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5851 if ((odd_iteration_flag
5852 ? arc->to_state->equiv_class_num_1
5853 : arc->to_state->equiv_class_num_2)
5854 != arc->insn->insn_reserv_decl->equiv_class_num)
5861 /* Compares two states pointed to by STATE_PTR_1 and STATE_PTR_2
5862 and return -1, 0 or 1. This function can be used as predicate for
5863 qsort(). It requires the member presence_signature[] of both
5864 states be filled. */
5866 compare_states_for_equiv (const void *state_ptr_1,
5867 const void *state_ptr_2)
5869 const_state_t const s1 = *(const_state_t const*)state_ptr_1;
5870 const_state_t const s2 = *(const_state_t const*)state_ptr_2;
5871 unsigned int sz, si;
5872 if (s1->num_out_arcs < s2->num_out_arcs)
5874 else if (s1->num_out_arcs > s2->num_out_arcs)
5877 sz = (description->query_units_num + sizeof (int) * CHAR_BIT - 1)
5878 / (sizeof (int) * CHAR_BIT);
5880 for (si = 0; si < sz; si++)
5881 if (s1->presence_signature[si] < s2->presence_signature[si])
5883 else if (s1->presence_signature[si] > s2->presence_signature[si])
5888 /* The function makes initial partition of STATES on equivalent
5889 classes and saves it into *CLASSES. This function requires the input
5890 to be sorted via compare_states_for_equiv(). */
5892 init_equiv_class (VEC(state_t, heap) *states, VEC (state_t, heap) **classes)
5898 *classes = VEC_alloc (state_t, heap, 150);
5899 for (i = 0; i < VEC_length (state_t, states); i++)
5901 state_t state = VEC_index (state_t, states, i);
5904 if (compare_states_for_equiv (&prev, &state) != 0)
5906 VEC_safe_push (state_t, heap, *classes, prev);
5911 state->equiv_class_num_1 = class_num;
5912 state->next_equiv_class_state = prev;
5916 VEC_safe_push (state_t, heap, *classes, prev);
5920 /* The function copies pointers to equivalent states from vla FROM
5923 copy_equiv_class (VEC(state_t, heap) **to, VEC(state_t, heap) *from)
5925 VEC_free (state_t, heap, *to);
5926 *to = VEC_copy (state_t, heap, from);
5929 /* The function processes equivalence class given by its first state,
5930 FIRST_STATE, on odd iteration if ODD_ITERATION_FLAG. If there
5931 are not equivalent states, the function partitions the class
5932 removing nonequivalent states and placing them in
5933 *NEXT_ITERATION_CLASSES, increments *NEW_EQUIV_CLASS_NUM_PTR ans
5934 assigns it to the state equivalence number. If the class has been
5935 partitioned, the function returns nonzero value. */
5937 partition_equiv_class (state_t first_state, int odd_iteration_flag,
5938 VEC(state_t, heap) **next_iteration_classes,
5939 int *new_equiv_class_num_ptr)
5941 state_t new_equiv_class;
5949 while (first_state != NULL)
5951 new_equiv_class = NULL;
5952 if (first_state->next_equiv_class_state != NULL)
5954 /* There are more one states in the class equivalence. */
5955 set_out_arc_insns_equiv_num (first_state, odd_iteration_flag);
5956 for (prev_state = first_state,
5957 curr_state = first_state->next_equiv_class_state;
5959 curr_state = next_state)
5961 next_state = curr_state->next_equiv_class_state;
5962 if (state_is_differed (curr_state, first_state,
5963 odd_iteration_flag))
5965 /* Remove curr state from the class equivalence. */
5966 prev_state->next_equiv_class_state = next_state;
5967 /* Add curr state to the new class equivalence. */
5968 curr_state->next_equiv_class_state = new_equiv_class;
5969 if (new_equiv_class == NULL)
5970 (*new_equiv_class_num_ptr)++;
5971 if (odd_iteration_flag)
5972 curr_state->equiv_class_num_2 = *new_equiv_class_num_ptr;
5974 curr_state->equiv_class_num_1 = *new_equiv_class_num_ptr;
5975 new_equiv_class = curr_state;
5979 prev_state = curr_state;
5981 clear_arc_insns_equiv_num (first_state);
5983 if (new_equiv_class != NULL)
5984 VEC_safe_push (state_t, heap, *next_iteration_classes, new_equiv_class);
5985 first_state = new_equiv_class;
5990 /* The function finds equivalent states of AUTOMATON. */
5992 evaluate_equiv_classes (automaton_t automaton,
5993 VEC(state_t, heap) **equiv_classes)
5995 int new_equiv_class_num;
5996 int odd_iteration_flag;
5998 VEC (state_t, heap) *next_iteration_classes;
6001 all_achieved_states = VEC_alloc (state_t, heap, 1500);
6002 pass_states (automaton, add_achieved_state);
6003 pass_states (automaton, cache_presence);
6004 qsort (VEC_address (state_t, all_achieved_states),
6005 VEC_length (state_t, all_achieved_states),
6006 sizeof (state_t), compare_states_for_equiv);
6008 odd_iteration_flag = 0;
6009 new_equiv_class_num = init_equiv_class (all_achieved_states,
6010 &next_iteration_classes);
6014 odd_iteration_flag = !odd_iteration_flag;
6016 copy_equiv_class (equiv_classes, next_iteration_classes);
6018 /* Transfer equiv numbers for the next iteration. */
6019 for (i = 0; i < VEC_length (state_t, all_achieved_states); i++)
6020 if (odd_iteration_flag)
6021 VEC_index (state_t, all_achieved_states, i)->equiv_class_num_2
6022 = VEC_index (state_t, all_achieved_states, i)->equiv_class_num_1;
6024 VEC_index (state_t, all_achieved_states, i)->equiv_class_num_1
6025 = VEC_index (state_t, all_achieved_states, i)->equiv_class_num_2;
6027 for (i = 0; i < VEC_length (state_t, *equiv_classes); i++)
6028 if (partition_equiv_class (VEC_index (state_t, *equiv_classes, i),
6030 &next_iteration_classes,
6031 &new_equiv_class_num))
6034 while (!finish_flag);
6035 VEC_free (state_t, heap, next_iteration_classes);
6036 VEC_free (state_t, heap, all_achieved_states);
6039 /* The function merges equivalent states of AUTOMATON. */
6041 merge_states (automaton_t automaton, VEC(state_t, heap) *equiv_classes)
6045 state_t first_class_state;
6046 alt_state_t alt_states;
6047 alt_state_t alt_state, new_alt_state;
6052 /* Create states corresponding to equivalence classes containing two
6054 for (i = 0; i < VEC_length (state_t, equiv_classes); i++)
6056 curr_state = VEC_index (state_t, equiv_classes, i);
6057 if (curr_state->next_equiv_class_state != NULL)
6059 /* There are more one states in the class equivalence. */
6060 /* Create new compound state. */
6061 new_state = get_free_state (0, automaton);
6063 first_class_state = curr_state;
6064 for (curr_state = first_class_state;
6066 curr_state = curr_state->next_equiv_class_state)
6068 curr_state->equiv_class_state = new_state;
6069 if (curr_state->component_states == NULL)
6071 new_alt_state = get_free_alt_state ();
6072 new_alt_state->state = curr_state;
6073 new_alt_state->next_alt_state = alt_states;
6074 alt_states = new_alt_state;
6077 for (alt_state = curr_state->component_states;
6079 alt_state = alt_state->next_sorted_alt_state)
6081 new_alt_state = get_free_alt_state ();
6082 new_alt_state->state = alt_state->state;
6083 new_alt_state->next_alt_state = alt_states;
6084 alt_states = new_alt_state;
6087 /* Its is important that alt states were sorted before and
6088 after merging to have the same querying results. */
6089 new_state->component_states = uniq_sort_alt_states (alt_states);
6092 curr_state->equiv_class_state = curr_state;
6095 for (i = 0; i < VEC_length (state_t, equiv_classes); i++)
6097 curr_state = VEC_index (state_t, equiv_classes, i);
6098 if (curr_state->next_equiv_class_state != NULL)
6100 first_class_state = curr_state;
6101 /* Create new arcs output from the state corresponding to
6103 for (curr_arc = first_out_arc (first_class_state);
6105 curr_arc = next_out_arc (curr_arc))
6106 add_arc (first_class_state->equiv_class_state,
6107 curr_arc->to_state->equiv_class_state,
6109 /* Delete output arcs from states of given class equivalence. */
6110 for (curr_state = first_class_state;
6112 curr_state = curr_state->next_equiv_class_state)
6114 if (automaton->start_state == curr_state)
6115 automaton->start_state = curr_state->equiv_class_state;
6116 /* Delete the state and its output arcs. */
6117 for (curr_arc = first_out_arc (curr_state);
6119 curr_arc = next_arc)
6121 next_arc = next_out_arc (curr_arc);
6122 free_arc (curr_arc);
6128 /* Change `to_state' of arcs output from the state of given
6129 equivalence class. */
6130 for (curr_arc = first_out_arc (curr_state);
6132 curr_arc = next_out_arc (curr_arc))
6133 curr_arc->to_state = curr_arc->to_state->equiv_class_state;
6138 /* The function sets up new_cycle_p for states if there is arc to the
6139 state marked by advance_cycle_insn_decl. */
6141 set_new_cycle_flags (state_t state)
6145 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6146 if (arc->insn->insn_reserv_decl
6147 == DECL_INSN_RESERV (advance_cycle_insn_decl))
6148 arc->to_state->new_cycle_p = 1;
6151 /* The top level function for minimization of deterministic
6154 minimize_DFA (automaton_t automaton)
6156 VEC(state_t, heap) *equiv_classes = 0;
6158 evaluate_equiv_classes (automaton, &equiv_classes);
6159 merge_states (automaton, equiv_classes);
6160 pass_states (automaton, set_new_cycle_flags);
6162 VEC_free (state_t, heap, equiv_classes);
6165 /* Values of two variables are counted number of states and arcs in an
6167 static int curr_counted_states_num;
6168 static int curr_counted_arcs_num;
6170 /* The function is called by function `pass_states' to count states
6171 and arcs of an automaton. */
6173 incr_states_and_arcs_nums (state_t state)
6177 curr_counted_states_num++;
6178 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6179 curr_counted_arcs_num++;
6182 /* The function counts states and arcs of AUTOMATON. */
6184 count_states_and_arcs (automaton_t automaton, int *states_num,
6187 curr_counted_states_num = 0;
6188 curr_counted_arcs_num = 0;
6189 pass_states (automaton, incr_states_and_arcs_nums);
6190 *states_num = curr_counted_states_num;
6191 *arcs_num = curr_counted_arcs_num;
6194 /* The function builds one DFA AUTOMATON for fast pipeline hazards
6195 recognition after checking and simplifying IR of the
6198 build_automaton (automaton_t automaton)
6203 ticker_on (&NDFA_time);
6206 if (automaton->corresponding_automaton_decl == NULL)
6207 fprintf (stderr, "Create anonymous automaton");
6209 fprintf (stderr, "Create automaton `%s'",
6210 automaton->corresponding_automaton_decl->name);
6211 fprintf (stderr, " (1 dot is 100 new states):");
6213 make_automaton (automaton);
6215 fprintf (stderr, " done\n");
6216 ticker_off (&NDFA_time);
6217 count_states_and_arcs (automaton, &states_num, &arcs_num);
6218 automaton->NDFA_states_num = states_num;
6219 automaton->NDFA_arcs_num = arcs_num;
6220 ticker_on (&NDFA_to_DFA_time);
6223 if (automaton->corresponding_automaton_decl == NULL)
6224 fprintf (stderr, "Make anonymous DFA");
6226 fprintf (stderr, "Make DFA `%s'",
6227 automaton->corresponding_automaton_decl->name);
6228 fprintf (stderr, " (1 dot is 100 new states):");
6230 NDFA_to_DFA (automaton);
6232 fprintf (stderr, " done\n");
6233 ticker_off (&NDFA_to_DFA_time);
6234 count_states_and_arcs (automaton, &states_num, &arcs_num);
6235 automaton->DFA_states_num = states_num;
6236 automaton->DFA_arcs_num = arcs_num;
6237 if (!no_minimization_flag)
6239 ticker_on (&minimize_time);
6242 if (automaton->corresponding_automaton_decl == NULL)
6243 fprintf (stderr, "Minimize anonymous DFA...");
6245 fprintf (stderr, "Minimize DFA `%s'...",
6246 automaton->corresponding_automaton_decl->name);
6248 minimize_DFA (automaton);
6250 fprintf (stderr, "done\n");
6251 ticker_off (&minimize_time);
6252 count_states_and_arcs (automaton, &states_num, &arcs_num);
6253 automaton->minimal_DFA_states_num = states_num;
6254 automaton->minimal_DFA_arcs_num = arcs_num;
6260 /* The page contains code for enumeration of all states of an automaton. */
6262 /* Variable used for enumeration of all states of an automaton. Its
6263 value is current number of automaton states. */
6264 static int curr_state_order_num;
6266 /* The function is called by function `pass_states' for enumerating
6269 set_order_state_num (state_t state)
6271 state->order_state_num = curr_state_order_num;
6272 curr_state_order_num++;
6275 /* The function enumerates all states of AUTOMATON. */
6277 enumerate_states (automaton_t automaton)
6279 curr_state_order_num = 0;
6280 pass_states (automaton, set_order_state_num);
6281 automaton->achieved_states_num = curr_state_order_num;
6286 /* The page contains code for finding equivalent automaton insns
6289 /* The function inserts AINSN into cyclic list
6290 CYCLIC_EQUIV_CLASS_INSN_LIST of ainsns. */
6292 insert_ainsn_into_equiv_class (ainsn_t ainsn,
6293 ainsn_t cyclic_equiv_class_insn_list)
6295 if (cyclic_equiv_class_insn_list == NULL)
6296 ainsn->next_equiv_class_insn = ainsn;
6299 ainsn->next_equiv_class_insn
6300 = cyclic_equiv_class_insn_list->next_equiv_class_insn;
6301 cyclic_equiv_class_insn_list->next_equiv_class_insn = ainsn;
6306 /* The function deletes equiv_class_insn into cyclic list of
6307 equivalent ainsns. */
6309 delete_ainsn_from_equiv_class (ainsn_t equiv_class_insn)
6311 ainsn_t curr_equiv_class_insn;
6312 ainsn_t prev_equiv_class_insn;
6314 prev_equiv_class_insn = equiv_class_insn;
6315 for (curr_equiv_class_insn = equiv_class_insn->next_equiv_class_insn;
6316 curr_equiv_class_insn != equiv_class_insn;
6317 curr_equiv_class_insn = curr_equiv_class_insn->next_equiv_class_insn)
6318 prev_equiv_class_insn = curr_equiv_class_insn;
6319 if (prev_equiv_class_insn != equiv_class_insn)
6320 prev_equiv_class_insn->next_equiv_class_insn
6321 = equiv_class_insn->next_equiv_class_insn;
6324 /* The function processes AINSN of a state in order to find equivalent
6325 ainsns. INSN_ARCS_ARRAY is table: code of insn -> out arc of the
6328 process_insn_equiv_class (ainsn_t ainsn, arc_t *insn_arcs_array)
6332 ainsn_t cyclic_insn_list;
6335 gcc_assert (insn_arcs_array [ainsn->insn_reserv_decl->insn_num]);
6337 /* New class of ainsns which are not equivalent to given ainsn. */
6338 cyclic_insn_list = NULL;
6341 next_insn = curr_insn->next_equiv_class_insn;
6342 arc = insn_arcs_array [curr_insn->insn_reserv_decl->insn_num];
6344 || (insn_arcs_array [ainsn->insn_reserv_decl->insn_num]->to_state
6347 delete_ainsn_from_equiv_class (curr_insn);
6348 cyclic_insn_list = insert_ainsn_into_equiv_class (curr_insn,
6351 curr_insn = next_insn;
6353 while (curr_insn != ainsn);
6356 /* The function processes STATE in order to find equivalent ainsns. */
6358 process_state_for_insn_equiv_partition (state_t state)
6361 arc_t *insn_arcs_array = XCNEWVEC (arc_t, description->insns_num);
6363 /* Process insns of the arcs. */
6364 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6365 insn_arcs_array [arc->insn->insn_reserv_decl->insn_num] = arc;
6366 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6367 process_insn_equiv_class (arc->insn, insn_arcs_array);
6369 free (insn_arcs_array);
6372 /* The function searches for equivalent ainsns of AUTOMATON. */
6374 set_insn_equiv_classes (automaton_t automaton)
6379 ainsn_t cyclic_insn_list;
6380 ainsn_t insn_with_same_reservs;
6381 int equiv_classes_num;
6383 /* All insns are included in one equivalence class. */
6384 cyclic_insn_list = NULL;
6385 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6386 if (ainsn->first_insn_with_same_reservs)
6387 cyclic_insn_list = insert_ainsn_into_equiv_class (ainsn,
6389 /* Process insns in order to make equivalence partition. */
6390 pass_states (automaton, process_state_for_insn_equiv_partition);
6391 /* Enumerate equiv classes. */
6392 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6393 /* Set undefined value. */
6394 ainsn->insn_equiv_class_num = -1;
6395 equiv_classes_num = 0;
6396 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6397 if (ainsn->insn_equiv_class_num < 0)
6400 gcc_assert (first_insn->first_insn_with_same_reservs);
6401 first_insn->first_ainsn_with_given_equivalence_num = 1;
6402 curr_insn = first_insn;
6405 for (insn_with_same_reservs = curr_insn;
6406 insn_with_same_reservs != NULL;
6407 insn_with_same_reservs
6408 = insn_with_same_reservs->next_same_reservs_insn)
6409 insn_with_same_reservs->insn_equiv_class_num = equiv_classes_num;
6410 curr_insn = curr_insn->next_equiv_class_insn;
6412 while (curr_insn != first_insn);
6413 equiv_classes_num++;
6415 automaton->insn_equiv_classes_num = equiv_classes_num;
6420 /* This page contains code for creating DFA(s) and calls functions
6424 /* The following value is used to prevent floating point overflow for
6425 estimating an automaton bound. The value should be less DBL_MAX on
6426 the host machine. We use here approximate minimum of maximal
6427 double floating point value required by ANSI C standard. It
6428 will work for non ANSI sun compiler too. */
6430 #define MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND 1.0E37
6432 /* The function estimate size of the single DFA used by PHR (pipeline
6433 hazards recognizer). */
6435 estimate_one_automaton_bound (void)
6438 double one_automaton_estimation_bound;
6442 one_automaton_estimation_bound = 1.0;
6443 for (i = 0; i < description->decls_num; i++)
6445 decl = description->decls [i];
6446 if (decl->mode == dm_unit)
6448 root_value = exp (log (DECL_UNIT (decl)->max_occ_cycle_num
6449 - DECL_UNIT (decl)->min_occ_cycle_num + 1.0)
6451 if (MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND / root_value
6452 > one_automaton_estimation_bound)
6453 one_automaton_estimation_bound *= root_value;
6456 return one_automaton_estimation_bound;
6459 /* The function compares unit declarations according to their maximal
6460 cycle in reservations. */
6462 compare_max_occ_cycle_nums (const void *unit_decl_1,
6463 const void *unit_decl_2)
6465 if ((DECL_UNIT (*(const_decl_t const*) unit_decl_1)->max_occ_cycle_num)
6466 < (DECL_UNIT (*(const_decl_t const*) unit_decl_2)->max_occ_cycle_num))
6468 else if ((DECL_UNIT (*(const_decl_t const*) unit_decl_1)->max_occ_cycle_num)
6469 == (DECL_UNIT (*(const_decl_t const*) unit_decl_2)->max_occ_cycle_num))
6475 /* The function makes heuristic assigning automata to units. Actually
6476 efficacy of the algorithm has been checked yet??? */
6479 units_to_automata_heuristic_distr (void)
6481 double estimation_bound;
6485 unit_decl_t *unit_decls;
6488 if (description->units_num == 0)
6490 estimation_bound = estimate_one_automaton_bound ();
6491 unit_decls = XNEWVEC (unit_decl_t, description->units_num);
6493 for (i = 0, j = 0; i < description->decls_num; i++)
6494 if (description->decls[i]->mode == dm_unit)
6495 unit_decls[j++] = DECL_UNIT (description->decls[i]);
6496 gcc_assert (j == description->units_num);
6498 qsort (unit_decls, description->units_num,
6499 sizeof (unit_decl_t), compare_max_occ_cycle_nums);
6502 bound_value = unit_decls[0]->max_occ_cycle_num;
6503 unit_decls[0]->corresponding_automaton_num = automaton_num;
6505 for (i = 1; i < description->units_num; i++)
6507 rest_units_num = description->units_num - i + 1;
6508 gcc_assert (automata_num - automaton_num - 1 <= rest_units_num);
6509 if (automaton_num < automata_num - 1
6510 && ((automata_num - automaton_num - 1 == rest_units_num)
6513 / unit_decls[i]->max_occ_cycle_num))))
6515 bound_value = unit_decls[i]->max_occ_cycle_num;
6519 bound_value *= unit_decls[i]->max_occ_cycle_num;
6520 unit_decls[i]->corresponding_automaton_num = automaton_num;
6522 gcc_assert (automaton_num == automata_num - 1);
6526 /* The functions creates automaton insns for each automata. Automaton
6527 insn is simply insn for given automaton which makes reservation
6528 only of units of the automaton. */
6530 create_ainsns (void)
6533 ainsn_t first_ainsn;
6540 for (i = 0; i < description->decls_num; i++)
6542 decl = description->decls [i];
6543 if (decl->mode == dm_insn_reserv)
6545 curr_ainsn = XCREATENODE (struct ainsn);
6546 curr_ainsn->insn_reserv_decl = DECL_INSN_RESERV (decl);
6547 curr_ainsn->important_p = FALSE;
6548 curr_ainsn->next_ainsn = NULL;
6549 if (prev_ainsn == NULL)
6550 first_ainsn = curr_ainsn;
6552 prev_ainsn->next_ainsn = curr_ainsn;
6553 prev_ainsn = curr_ainsn;
6559 /* The function assigns automata to units according to constructions
6560 `define_automaton' in the description. */
6562 units_to_automata_distr (void)
6567 for (i = 0; i < description->decls_num; i++)
6569 decl = description->decls [i];
6570 if (decl->mode == dm_unit)
6572 if (DECL_UNIT (decl)->automaton_decl == NULL
6573 || (DECL_UNIT (decl)->automaton_decl->corresponding_automaton
6575 /* Distribute to the first automaton. */
6576 DECL_UNIT (decl)->corresponding_automaton_num = 0;
6578 DECL_UNIT (decl)->corresponding_automaton_num
6579 = (DECL_UNIT (decl)->automaton_decl
6580 ->corresponding_automaton->automaton_order_num);
6585 /* The function creates DFA(s) for fast pipeline hazards recognition
6586 after checking and simplifying IR of the description. */
6588 create_automata (void)
6590 automaton_t curr_automaton;
6591 automaton_t prev_automaton;
6593 int curr_automaton_num;
6596 if (automata_num != 0)
6598 units_to_automata_heuristic_distr ();
6599 for (prev_automaton = NULL, curr_automaton_num = 0;
6600 curr_automaton_num < automata_num;
6601 curr_automaton_num++, prev_automaton = curr_automaton)
6603 curr_automaton = XCREATENODE (struct automaton);
6604 curr_automaton->ainsn_list = create_ainsns ();
6605 curr_automaton->corresponding_automaton_decl = NULL;
6606 curr_automaton->next_automaton = NULL;
6607 curr_automaton->automaton_order_num = curr_automaton_num;
6608 if (prev_automaton == NULL)
6609 description->first_automaton = curr_automaton;
6611 prev_automaton->next_automaton = curr_automaton;
6616 curr_automaton_num = 0;
6617 prev_automaton = NULL;
6618 for (i = 0; i < description->decls_num; i++)
6620 decl = description->decls [i];
6621 if (decl->mode == dm_automaton
6622 && DECL_AUTOMATON (decl)->automaton_is_used)
6624 curr_automaton = XCREATENODE (struct automaton);
6625 curr_automaton->ainsn_list = create_ainsns ();
6626 curr_automaton->corresponding_automaton_decl
6627 = DECL_AUTOMATON (decl);
6628 curr_automaton->next_automaton = NULL;
6629 DECL_AUTOMATON (decl)->corresponding_automaton = curr_automaton;
6630 curr_automaton->automaton_order_num = curr_automaton_num;
6631 if (prev_automaton == NULL)
6632 description->first_automaton = curr_automaton;
6634 prev_automaton->next_automaton = curr_automaton;
6635 curr_automaton_num++;
6636 prev_automaton = curr_automaton;
6639 if (curr_automaton_num == 0)
6641 curr_automaton = XCREATENODE (struct automaton);
6642 curr_automaton->ainsn_list = create_ainsns ();
6643 curr_automaton->corresponding_automaton_decl = NULL;
6644 curr_automaton->next_automaton = NULL;
6645 description->first_automaton = curr_automaton;
6647 units_to_automata_distr ();
6649 NDFA_time = create_ticker ();
6650 ticker_off (&NDFA_time);
6651 NDFA_to_DFA_time = create_ticker ();
6652 ticker_off (&NDFA_to_DFA_time);
6653 minimize_time = create_ticker ();
6654 ticker_off (&minimize_time);
6655 equiv_time = create_ticker ();
6656 ticker_off (&equiv_time);
6657 for (curr_automaton = description->first_automaton;
6658 curr_automaton != NULL;
6659 curr_automaton = curr_automaton->next_automaton)
6663 if (curr_automaton->corresponding_automaton_decl == NULL)
6664 fprintf (stderr, "Prepare anonymous automaton creation ... ");
6666 fprintf (stderr, "Prepare automaton `%s' creation...",
6667 curr_automaton->corresponding_automaton_decl->name);
6669 create_alt_states (curr_automaton);
6670 form_ainsn_with_same_reservs (curr_automaton);
6672 fprintf (stderr, "done\n");
6673 build_automaton (curr_automaton);
6674 enumerate_states (curr_automaton);
6675 ticker_on (&equiv_time);
6676 set_insn_equiv_classes (curr_automaton);
6677 ticker_off (&equiv_time);
6683 /* This page contains code for forming string representation of
6684 regexp. The representation is formed on IR obstack. So you should
6685 not work with IR obstack between regexp_representation and
6686 finish_regexp_representation calls. */
6688 /* This recursive function forms string representation of regexp
6689 (without tailing '\0'). */
6691 form_regexp (regexp_t regexp)
6695 switch (regexp->mode)
6697 case rm_unit: case rm_reserv:
6699 const char *name = (regexp->mode == rm_unit
6700 ? REGEXP_UNIT (regexp)->name
6701 : REGEXP_RESERV (regexp)->name);
6703 obstack_grow (&irp, name, strlen (name));
6708 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
6711 obstack_1grow (&irp, ',');
6712 form_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
6717 obstack_1grow (&irp, '(');
6718 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
6721 obstack_1grow (&irp, '+');
6722 if (REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_sequence
6723 || REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_oneof)
6724 obstack_1grow (&irp, '(');
6725 form_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
6726 if (REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_sequence
6727 || REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_oneof)
6728 obstack_1grow (&irp, ')');
6730 obstack_1grow (&irp, ')');
6734 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
6737 obstack_1grow (&irp, '|');
6738 if (REGEXP_ONEOF (regexp)->regexps[i]->mode == rm_sequence)
6739 obstack_1grow (&irp, '(');
6740 form_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
6741 if (REGEXP_ONEOF (regexp)->regexps[i]->mode == rm_sequence)
6742 obstack_1grow (&irp, ')');
6750 if (REGEXP_REPEAT (regexp)->regexp->mode == rm_sequence
6751 || REGEXP_REPEAT (regexp)->regexp->mode == rm_allof
6752 || REGEXP_REPEAT (regexp)->regexp->mode == rm_oneof)
6753 obstack_1grow (&irp, '(');
6754 form_regexp (REGEXP_REPEAT (regexp)->regexp);
6755 if (REGEXP_REPEAT (regexp)->regexp->mode == rm_sequence
6756 || REGEXP_REPEAT (regexp)->regexp->mode == rm_allof
6757 || REGEXP_REPEAT (regexp)->regexp->mode == rm_oneof)
6758 obstack_1grow (&irp, ')');
6759 sprintf (digits, "*%d", REGEXP_REPEAT (regexp)->repeat_num);
6760 obstack_grow (&irp, digits, strlen (digits));
6765 obstack_grow (&irp, NOTHING_NAME, strlen (NOTHING_NAME));
6773 /* The function returns string representation of REGEXP on IR
6776 regexp_representation (regexp_t regexp)
6778 form_regexp (regexp);
6779 obstack_1grow (&irp, '\0');
6780 return obstack_base (&irp);
6783 /* The function frees memory allocated for last formed string
6784 representation of regexp. */
6786 finish_regexp_representation (void)
6788 int length = obstack_object_size (&irp);
6790 obstack_blank_fast (&irp, -length);
6795 /* This page contains code for output PHR (pipeline hazards recognizer). */
6797 /* The function outputs minimal C type which is sufficient for
6798 representation numbers in range min_range_value and
6799 max_range_value. Because host machine and build machine may be
6800 different, we use here minimal values required by ANSI C standard
6801 instead of UCHAR_MAX, SHRT_MAX, SHRT_MIN, etc. This is a good
6805 output_range_type (FILE *f, long int min_range_value,
6806 long int max_range_value)
6808 if (min_range_value >= 0 && max_range_value <= 255)
6809 fprintf (f, "unsigned char");
6810 else if (min_range_value >= -127 && max_range_value <= 127)
6811 fprintf (f, "signed char");
6812 else if (min_range_value >= 0 && max_range_value <= 65535)
6813 fprintf (f, "unsigned short");
6814 else if (min_range_value >= -32767 && max_range_value <= 32767)
6815 fprintf (f, "short");
6820 /* The function outputs all initialization values of VECT. */
6822 output_vect (vla_hwint_t vect)
6825 size_t vect_length = VEC_length (vect_el_t, vect);
6829 if (vect_length == 0)
6830 fputs ("0 /* This is dummy el because the vect is empty */", output_file);
6832 for (i = 0; i < vect_length; i++)
6834 fprintf (output_file, "%5ld", (long) VEC_index (vect_el_t, vect, i));
6835 if (els_on_line == 10)
6838 fputs (",\n", output_file);
6840 else if (i < vect_length-1)
6841 fputs (", ", output_file);
6846 /* The following is name of the structure which represents DFA(s) for
6848 #define CHIP_NAME "DFA_chip"
6850 /* The following is name of member which represents state of a DFA for
6853 output_chip_member_name (FILE *f, automaton_t automaton)
6855 if (automaton->corresponding_automaton_decl == NULL)
6856 fprintf (f, "automaton_state_%d", automaton->automaton_order_num);
6858 fprintf (f, "%s_automaton_state",
6859 automaton->corresponding_automaton_decl->name);
6862 /* The following is name of temporary variable which stores state of a
6865 output_temp_chip_member_name (FILE *f, automaton_t automaton)
6868 output_chip_member_name (f, automaton);
6871 /* This is name of macro value which is code of pseudo_insn
6872 representing advancing cpu cycle. Its value is used as internal
6873 code unknown insn. */
6874 #define ADVANCE_CYCLE_VALUE_NAME "DFA__ADVANCE_CYCLE"
6876 /* Output name of translate vector for given automaton. */
6878 output_translate_vect_name (FILE *f, automaton_t automaton)
6880 if (automaton->corresponding_automaton_decl == NULL)
6881 fprintf (f, "translate_%d", automaton->automaton_order_num);
6883 fprintf (f, "%s_translate", automaton->corresponding_automaton_decl->name);
6886 /* Output name for simple transition table representation. */
6888 output_trans_full_vect_name (FILE *f, automaton_t automaton)
6890 if (automaton->corresponding_automaton_decl == NULL)
6891 fprintf (f, "transitions_%d", automaton->automaton_order_num);
6893 fprintf (f, "%s_transitions",
6894 automaton->corresponding_automaton_decl->name);
6897 /* Output name of comb vector of the transition table for given
6900 output_trans_comb_vect_name (FILE *f, automaton_t automaton)
6902 if (automaton->corresponding_automaton_decl == NULL)
6903 fprintf (f, "transitions_%d", automaton->automaton_order_num);
6905 fprintf (f, "%s_transitions",
6906 automaton->corresponding_automaton_decl->name);
6909 /* Output name of check vector of the transition table for given
6912 output_trans_check_vect_name (FILE *f, automaton_t automaton)
6914 if (automaton->corresponding_automaton_decl == NULL)
6915 fprintf (f, "check_%d", automaton->automaton_order_num);
6917 fprintf (f, "%s_check", automaton->corresponding_automaton_decl->name);
6920 /* Output name of base vector of the transition table for given
6923 output_trans_base_vect_name (FILE *f, automaton_t automaton)
6925 if (automaton->corresponding_automaton_decl == NULL)
6926 fprintf (f, "base_%d", automaton->automaton_order_num);
6928 fprintf (f, "%s_base", automaton->corresponding_automaton_decl->name);
6931 /* Output name of simple min issue delay table representation. */
6933 output_min_issue_delay_vect_name (FILE *f, automaton_t automaton)
6935 if (automaton->corresponding_automaton_decl == NULL)
6936 fprintf (f, "min_issue_delay_%d", automaton->automaton_order_num);
6938 fprintf (f, "%s_min_issue_delay",
6939 automaton->corresponding_automaton_decl->name);
6942 /* Output name of deadlock vector for given automaton. */
6944 output_dead_lock_vect_name (FILE *f, automaton_t automaton)
6946 if (automaton->corresponding_automaton_decl == NULL)
6947 fprintf (f, "dead_lock_%d", automaton->automaton_order_num);
6949 fprintf (f, "%s_dead_lock", automaton->corresponding_automaton_decl->name);
6952 /* Output name of reserved units table for AUTOMATON into file F. */
6954 output_reserved_units_table_name (FILE *f, automaton_t automaton)
6956 if (automaton->corresponding_automaton_decl == NULL)
6957 fprintf (f, "reserved_units_%d", automaton->automaton_order_num);
6959 fprintf (f, "%s_reserved_units",
6960 automaton->corresponding_automaton_decl->name);
6963 /* Name of the PHR interface macro. */
6964 #define CPU_UNITS_QUERY_MACRO_NAME "CPU_UNITS_QUERY"
6966 /* Names of an internal functions: */
6967 #define INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME "internal_min_issue_delay"
6969 /* This is external type of DFA(s) state. */
6970 #define STATE_TYPE_NAME "state_t"
6972 #define INTERNAL_TRANSITION_FUNC_NAME "internal_state_transition"
6974 #define INTERNAL_RESET_FUNC_NAME "internal_reset"
6976 #define INTERNAL_DEAD_LOCK_FUNC_NAME "internal_state_dead_lock_p"
6978 #define INTERNAL_INSN_LATENCY_FUNC_NAME "internal_insn_latency"
6980 /* Name of cache of insn dfa codes. */
6981 #define DFA_INSN_CODES_VARIABLE_NAME "dfa_insn_codes"
6983 /* Name of length of cache of insn dfa codes. */
6984 #define DFA_INSN_CODES_LENGTH_VARIABLE_NAME "dfa_insn_codes_length"
6986 /* Names of the PHR interface functions: */
6987 #define SIZE_FUNC_NAME "state_size"
6989 #define TRANSITION_FUNC_NAME "state_transition"
6991 #define MIN_ISSUE_DELAY_FUNC_NAME "min_issue_delay"
6993 #define MIN_INSN_CONFLICT_DELAY_FUNC_NAME "min_insn_conflict_delay"
6995 #define DEAD_LOCK_FUNC_NAME "state_dead_lock_p"
6997 #define RESET_FUNC_NAME "state_reset"
6999 #define INSN_LATENCY_FUNC_NAME "insn_latency"
7001 #define PRINT_RESERVATION_FUNC_NAME "print_reservation"
7003 #define GET_CPU_UNIT_CODE_FUNC_NAME "get_cpu_unit_code"
7005 #define CPU_UNIT_RESERVATION_P_FUNC_NAME "cpu_unit_reservation_p"
7007 #define INSN_HAS_DFA_RESERVATION_P_FUNC_NAME "insn_has_dfa_reservation_p"
7009 #define DFA_CLEAN_INSN_CACHE_FUNC_NAME "dfa_clean_insn_cache"
7011 #define DFA_CLEAR_SINGLE_INSN_CACHE_FUNC_NAME "dfa_clear_single_insn_cache"
7013 #define DFA_START_FUNC_NAME "dfa_start"
7015 #define DFA_FINISH_FUNC_NAME "dfa_finish"
7017 /* Names of parameters of the PHR interface functions. */
7018 #define STATE_NAME "state"
7020 #define INSN_PARAMETER_NAME "insn"
7022 #define INSN2_PARAMETER_NAME "insn2"
7024 #define CHIP_PARAMETER_NAME "chip"
7026 #define FILE_PARAMETER_NAME "f"
7028 #define CPU_UNIT_NAME_PARAMETER_NAME "cpu_unit_name"
7030 #define CPU_CODE_PARAMETER_NAME "cpu_unit_code"
7032 /* Names of the variables whose values are internal insn code of rtx
7034 #define INTERNAL_INSN_CODE_NAME "insn_code"
7036 #define INTERNAL_INSN2_CODE_NAME "insn2_code"
7038 /* Names of temporary variables in some functions. */
7039 #define TEMPORARY_VARIABLE_NAME "temp"
7041 #define I_VARIABLE_NAME "i"
7043 /* Name of result variable in some functions. */
7044 #define RESULT_VARIABLE_NAME "res"
7046 /* Name of function (attribute) to translate insn into internal insn
7048 #define INTERNAL_DFA_INSN_CODE_FUNC_NAME "internal_dfa_insn_code"
7050 /* Name of function (attribute) to translate insn into internal insn
7051 code with caching. */
7052 #define DFA_INSN_CODE_FUNC_NAME "dfa_insn_code"
7054 /* Output C type which is used for representation of codes of states
7057 output_state_member_type (FILE *f, automaton_t automaton)
7059 output_range_type (f, 0, automaton->achieved_states_num);
7062 /* Output definition of the structure representing current DFA(s)
7065 output_chip_definitions (void)
7067 automaton_t automaton;
7069 fprintf (output_file, "struct %s\n{\n", CHIP_NAME);
7070 for (automaton = description->first_automaton;
7072 automaton = automaton->next_automaton)
7074 fprintf (output_file, " ");
7075 output_state_member_type (output_file, automaton);
7076 fprintf (output_file, " ");
7077 output_chip_member_name (output_file, automaton);
7078 fprintf (output_file, ";\n");
7080 fprintf (output_file, "};\n\n");
7082 fprintf (output_file, "static struct %s %s;\n\n", CHIP_NAME, CHIP_NAME);
7087 /* The function outputs translate vector of internal insn code into
7088 insn equivalence class number. The equivalence class number is
7089 used to access to table and vectors representing DFA(s). */
7091 output_translate_vect (automaton_t automaton)
7095 vla_hwint_t translate_vect;
7097 translate_vect = VEC_alloc (vect_el_t, heap, description->insns_num);
7099 for (insn_value = 0; insn_value < description->insns_num; insn_value++)
7100 /* Undefined value */
7101 VEC_quick_push (vect_el_t, translate_vect,
7102 automaton->insn_equiv_classes_num);
7104 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
7105 VEC_replace (vect_el_t, translate_vect,
7106 ainsn->insn_reserv_decl->insn_num,
7107 ainsn->insn_equiv_class_num);
7109 fprintf (output_file,
7110 "/* Vector translating external insn codes to internal ones.*/\n");
7111 fprintf (output_file, "static const ");
7112 output_range_type (output_file, 0, automaton->insn_equiv_classes_num);
7113 fprintf (output_file, " ");
7114 output_translate_vect_name (output_file, automaton);
7115 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7116 output_vect (translate_vect);
7117 fprintf (output_file, "};\n\n");
7118 VEC_free (vect_el_t, heap, translate_vect);
7121 /* The value in a table state x ainsn -> something which represents
7123 static int undefined_vect_el_value;
7125 /* The following function returns nonzero value if the best
7126 representation of the table is comb vector. */
7128 comb_vect_p (state_ainsn_table_t tab)
7130 return (2 * VEC_length (vect_el_t, tab->full_vect)
7131 > 5 * VEC_length (vect_el_t, tab->comb_vect));
7134 /* The following function creates new table for AUTOMATON. */
7135 static state_ainsn_table_t
7136 create_state_ainsn_table (automaton_t automaton)
7138 state_ainsn_table_t tab;
7139 int full_vect_length;
7142 tab = XCREATENODE (struct state_ainsn_table);
7143 tab->automaton = automaton;
7145 tab->comb_vect = VEC_alloc (vect_el_t, heap, 10000);
7146 tab->check_vect = VEC_alloc (vect_el_t, heap, 10000);
7149 VEC_safe_grow (vect_el_t, heap, tab->base_vect,
7150 automaton->achieved_states_num);
7152 full_vect_length = (automaton->insn_equiv_classes_num
7153 * automaton->achieved_states_num);
7154 tab->full_vect = VEC_alloc (vect_el_t, heap, full_vect_length);
7155 for (i = 0; i < full_vect_length; i++)
7156 VEC_quick_push (vect_el_t, tab->full_vect, undefined_vect_el_value);
7158 tab->min_base_vect_el_value = 0;
7159 tab->max_base_vect_el_value = 0;
7160 tab->min_comb_vect_el_value = 0;
7161 tab->max_comb_vect_el_value = 0;
7165 /* The following function outputs the best C representation of the
7166 table TAB of given TABLE_NAME. */
7168 output_state_ainsn_table (state_ainsn_table_t tab, const char *table_name,
7169 void (*output_full_vect_name_func) (FILE *, automaton_t),
7170 void (*output_comb_vect_name_func) (FILE *, automaton_t),
7171 void (*output_check_vect_name_func) (FILE *, automaton_t),
7172 void (*output_base_vect_name_func) (FILE *, automaton_t))
7174 if (!comb_vect_p (tab))
7176 fprintf (output_file, "/* Vector for %s. */\n", table_name);
7177 fprintf (output_file, "static const ");
7178 output_range_type (output_file, tab->min_comb_vect_el_value,
7179 tab->max_comb_vect_el_value);
7180 fprintf (output_file, " ");
7181 (*output_full_vect_name_func) (output_file, tab->automaton);
7182 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7183 output_vect (tab->full_vect);
7184 fprintf (output_file, "};\n\n");
7188 fprintf (output_file, "/* Comb vector for %s. */\n", table_name);
7189 fprintf (output_file, "static const ");
7190 output_range_type (output_file, tab->min_comb_vect_el_value,
7191 tab->max_comb_vect_el_value);
7192 fprintf (output_file, " ");
7193 (*output_comb_vect_name_func) (output_file, tab->automaton);
7194 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7195 output_vect (tab->comb_vect);
7196 fprintf (output_file, "};\n\n");
7197 fprintf (output_file, "/* Check vector for %s. */\n", table_name);
7198 fprintf (output_file, "static const ");
7199 output_range_type (output_file, 0, tab->automaton->achieved_states_num);
7200 fprintf (output_file, " ");
7201 (*output_check_vect_name_func) (output_file, tab->automaton);
7202 fprintf (output_file, "[] = {\n");
7203 output_vect (tab->check_vect);
7204 fprintf (output_file, "};\n\n");
7205 fprintf (output_file, "/* Base vector for %s. */\n", table_name);
7206 fprintf (output_file, "static const ");
7207 output_range_type (output_file, tab->min_base_vect_el_value,
7208 tab->max_base_vect_el_value);
7209 fprintf (output_file, " ");
7210 (*output_base_vect_name_func) (output_file, tab->automaton);
7211 fprintf (output_file, "[] = {\n");
7212 output_vect (tab->base_vect);
7213 fprintf (output_file, "};\n\n");
7217 /* The following function adds vector VECT to table TAB as its line
7218 with number VECT_NUM. */
7220 add_vect (state_ainsn_table_t tab, int vect_num, vla_hwint_t vect)
7223 size_t real_vect_length;
7224 int comb_vect_index;
7225 int comb_vect_els_num;
7227 int first_unempty_vect_index;
7228 int additional_els_num;
7232 unsigned long vect_mask, comb_vect_mask;
7234 vect_length = VEC_length (vect_el_t, vect);
7235 gcc_assert (vect_length);
7236 gcc_assert (VEC_last (vect_el_t, vect) != undefined_vect_el_value);
7237 real_vect_length = tab->automaton->insn_equiv_classes_num;
7238 /* Form full vector in the table: */
7240 size_t full_base = tab->automaton->insn_equiv_classes_num * vect_num;
7241 if (VEC_length (vect_el_t, tab->full_vect) < full_base + vect_length)
7242 VEC_safe_grow (vect_el_t, heap, tab->full_vect,
7243 full_base + vect_length);
7244 for (i = 0; i < vect_length; i++)
7245 VEC_replace (vect_el_t, tab->full_vect, full_base + i,
7246 VEC_index (vect_el_t, vect, i));
7248 /* Form comb vector in the table: */
7249 gcc_assert (VEC_length (vect_el_t, tab->comb_vect)
7250 == VEC_length (vect_el_t, tab->check_vect));
7252 comb_vect_els_num = VEC_length (vect_el_t, tab->comb_vect);
7253 for (first_unempty_vect_index = 0;
7254 first_unempty_vect_index < vect_length;
7255 first_unempty_vect_index++)
7256 if (VEC_index (vect_el_t, vect, first_unempty_vect_index)
7257 != undefined_vect_el_value)
7260 /* Search for the place in comb vect for the inserted vect. */
7263 if (vect_length - first_unempty_vect_index >= SIZEOF_LONG * CHAR_BIT)
7265 for (comb_vect_index = 0;
7266 comb_vect_index < comb_vect_els_num;
7269 for (vect_index = first_unempty_vect_index;
7270 vect_index < vect_length
7271 && vect_index + comb_vect_index < comb_vect_els_num;
7273 if (VEC_index (vect_el_t, vect, vect_index)
7274 != undefined_vect_el_value
7275 && (VEC_index (vect_el_t, tab->comb_vect,
7276 vect_index + comb_vect_index)
7277 != undefined_vect_el_value))
7279 if (vect_index >= vect_length
7280 || vect_index + comb_vect_index >= comb_vect_els_num)
7288 for (vect_index = first_unempty_vect_index;
7289 vect_index < vect_length;
7292 vect_mask = vect_mask << 1;
7293 if (VEC_index (vect_el_t, vect, vect_index) != undefined_vect_el_value)
7297 /* Search for the place in comb vect for the inserted vect. */
7298 comb_vect_index = 0;
7299 if (comb_vect_els_num == 0)
7303 for (vect_index = first_unempty_vect_index;
7304 vect_index < vect_length && vect_index < comb_vect_els_num;
7307 comb_vect_mask <<= 1;
7308 if (vect_index + comb_vect_index < comb_vect_els_num
7309 && VEC_index (vect_el_t, tab->comb_vect, vect_index + comb_vect_index)
7310 != undefined_vect_el_value)
7311 comb_vect_mask |= 1;
7313 if ((vect_mask & comb_vect_mask) == 0)
7316 for (comb_vect_index = 1, i = vect_length; i < comb_vect_els_num;
7317 comb_vect_index++, i++)
7319 comb_vect_mask = (comb_vect_mask << 1) | 1;
7320 comb_vect_mask ^= (VEC_index (vect_el_t, tab->comb_vect, i)
7321 == undefined_vect_el_value);
7322 if ((vect_mask & comb_vect_mask) == 0)
7325 for ( ; comb_vect_index < comb_vect_els_num; comb_vect_index++)
7327 comb_vect_mask <<= 1;
7328 if ((vect_mask & comb_vect_mask) == 0)
7333 /* Slot was found. */
7334 additional_els_num = comb_vect_index + real_vect_length - comb_vect_els_num;
7335 if (additional_els_num < 0)
7336 additional_els_num = 0;
7337 /* Expand comb and check vectors. */
7338 vect_el = undefined_vect_el_value;
7339 no_state_value = tab->automaton->achieved_states_num;
7340 while (additional_els_num > 0)
7342 VEC_safe_push (vect_el_t, heap, tab->comb_vect, vect_el);
7343 VEC_safe_push (vect_el_t, heap, tab->check_vect, no_state_value);
7344 additional_els_num--;
7346 gcc_assert (VEC_length (vect_el_t, tab->comb_vect)
7347 >= comb_vect_index + real_vect_length);
7348 /* Fill comb and check vectors. */
7349 for (vect_index = 0; vect_index < vect_length; vect_index++)
7350 if (VEC_index (vect_el_t, vect, vect_index) != undefined_vect_el_value)
7352 vect_el_t x = VEC_index (vect_el_t, vect, vect_index);
7353 gcc_assert (VEC_index (vect_el_t, tab->comb_vect,
7354 comb_vect_index + vect_index)
7355 == undefined_vect_el_value);
7356 gcc_assert (x >= 0);
7357 if (tab->max_comb_vect_el_value < x)
7358 tab->max_comb_vect_el_value = x;
7359 if (tab->min_comb_vect_el_value > x)
7360 tab->min_comb_vect_el_value = x;
7361 VEC_replace (vect_el_t, tab->comb_vect,
7362 comb_vect_index + vect_index, x);
7363 VEC_replace (vect_el_t, tab->check_vect,
7364 comb_vect_index + vect_index, vect_num);
7366 if (tab->max_comb_vect_el_value < undefined_vect_el_value)
7367 tab->max_comb_vect_el_value = undefined_vect_el_value;
7368 if (tab->min_comb_vect_el_value > undefined_vect_el_value)
7369 tab->min_comb_vect_el_value = undefined_vect_el_value;
7370 if (tab->max_base_vect_el_value < comb_vect_index)
7371 tab->max_base_vect_el_value = comb_vect_index;
7372 if (tab->min_base_vect_el_value > comb_vect_index)
7373 tab->min_base_vect_el_value = comb_vect_index;
7375 VEC_replace (vect_el_t, tab->base_vect, vect_num, comb_vect_index);
7378 /* Return number of out arcs of STATE. */
7380 out_state_arcs_num (const_state_t state)
7386 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
7388 gcc_assert (arc->insn);
7389 if (arc->insn->first_ainsn_with_given_equivalence_num)
7395 /* Compare number of possible transitions from the states. */
7397 compare_transition_els_num (const void *state_ptr_1,
7398 const void *state_ptr_2)
7400 const int transition_els_num_1
7401 = out_state_arcs_num (*(const_state_t const*) state_ptr_1);
7402 const int transition_els_num_2
7403 = out_state_arcs_num (*(const_state_t const*) state_ptr_2);
7405 if (transition_els_num_1 < transition_els_num_2)
7407 else if (transition_els_num_1 == transition_els_num_2)
7413 /* The function adds element EL_VALUE to vector VECT for a table state
7416 add_vect_el (vla_hwint_t *vect, ainsn_t ainsn, int el_value)
7418 int equiv_class_num;
7422 equiv_class_num = ainsn->insn_equiv_class_num;
7423 for (vect_index = VEC_length (vect_el_t, *vect);
7424 vect_index <= equiv_class_num;
7426 VEC_safe_push (vect_el_t, heap, *vect, undefined_vect_el_value);
7427 VEC_replace (vect_el_t, *vect, equiv_class_num, el_value);
7430 /* This is for forming vector of states of an automaton. */
7431 static VEC(state_t, heap) *output_states_vect;
7433 /* The function is called by function pass_states. The function adds
7434 STATE to `output_states_vect'. */
7436 add_states_vect_el (state_t state)
7438 VEC_safe_push (state_t, heap, output_states_vect, state);
7441 /* Form and output vectors (comb, check, base or full vector)
7442 representing transition table of AUTOMATON. */
7444 output_trans_table (automaton_t automaton)
7448 vla_hwint_t transition_vect = 0;
7450 undefined_vect_el_value = automaton->achieved_states_num;
7451 automaton->trans_table = create_state_ainsn_table (automaton);
7452 /* Create vect of pointers to states ordered by num of transitions
7453 from the state (state with the maximum num is the first). */
7454 output_states_vect = 0;
7455 pass_states (automaton, add_states_vect_el);
7456 qsort (VEC_address (state_t, output_states_vect),
7457 VEC_length (state_t, output_states_vect),
7458 sizeof (state_t), compare_transition_els_num);
7460 for (i = 0; i < VEC_length (state_t, output_states_vect); i++)
7462 VEC_truncate (vect_el_t, transition_vect, 0);
7463 for (arc = first_out_arc (VEC_index (state_t, output_states_vect, i));
7465 arc = next_out_arc (arc))
7467 gcc_assert (arc->insn);
7468 if (arc->insn->first_ainsn_with_given_equivalence_num)
7469 add_vect_el (&transition_vect, arc->insn,
7470 arc->to_state->order_state_num);
7472 add_vect (automaton->trans_table,
7473 VEC_index (state_t, output_states_vect, i)->order_state_num,
7476 output_state_ainsn_table
7477 (automaton->trans_table, "state transitions",
7478 output_trans_full_vect_name, output_trans_comb_vect_name,
7479 output_trans_check_vect_name, output_trans_base_vect_name);
7481 VEC_free (state_t, heap, output_states_vect);
7482 VEC_free (vect_el_t, heap, transition_vect);
7485 /* Form and output vectors representing minimal issue delay table of
7486 AUTOMATON. The table is state x ainsn -> minimal issue delay of
7489 output_min_issue_delay_table (automaton_t automaton)
7491 vla_hwint_t min_issue_delay_vect;
7492 vla_hwint_t compressed_min_issue_delay_vect;
7495 size_t min_issue_delay_len, compressed_min_issue_delay_len;
7499 /* Create vect of pointers to states ordered by num of transitions
7500 from the state (state with the maximum num is the first). */
7501 output_states_vect = 0;
7502 pass_states (automaton, add_states_vect_el);
7504 min_issue_delay_len = (VEC_length (state_t, output_states_vect)
7505 * automaton->insn_equiv_classes_num);
7506 min_issue_delay_vect = VEC_alloc (vect_el_t, heap, min_issue_delay_len);
7507 for (i = 0; i < min_issue_delay_len; i++)
7508 VEC_quick_push (vect_el_t, min_issue_delay_vect, -1);
7510 automaton->max_min_delay = 0;
7518 for (state_no = 0; state_no < VEC_length (state_t, output_states_vect);
7521 state_t s = VEC_index (state_t, output_states_vect, state_no);
7524 for (arc = first_out_arc (s); arc; arc = next_out_arc (arc))
7528 size_t asn = s->order_state_num
7529 * automaton->insn_equiv_classes_num
7530 + arc->insn->insn_equiv_class_num;
7532 if (VEC_index (vect_el_t, min_issue_delay_vect, asn))
7534 VEC_replace (vect_el_t, min_issue_delay_vect, asn, 0);
7538 for (k = 0; k < automaton->insn_equiv_classes_num; k++)
7541 vect_el_t delay0, delay1;
7543 n0 = s->order_state_num
7544 * automaton->insn_equiv_classes_num
7546 n1 = arc->to_state->order_state_num
7547 * automaton->insn_equiv_classes_num
7549 delay0 = VEC_index (vect_el_t, min_issue_delay_vect, n0);
7550 delay1 = VEC_index (vect_el_t, min_issue_delay_vect, n1);
7553 if (arc->insn->insn_reserv_decl
7554 == DECL_INSN_RESERV (advance_cycle_insn_decl))
7556 if (delay1 < delay0 || delay0 == -1)
7558 VEC_replace (vect_el_t, min_issue_delay_vect, n0, delay1);
7568 automaton->max_min_delay = 0;
7570 for (ainsn = automaton->ainsn_list; ainsn; ainsn = ainsn->next_ainsn)
7571 if (ainsn->first_ainsn_with_given_equivalence_num)
7573 for (i = 0; i < VEC_length (state_t, output_states_vect); i++)
7575 state_t s = VEC_index (state_t, output_states_vect, i);
7576 size_t np = s->order_state_num
7577 * automaton->insn_equiv_classes_num
7578 + ainsn->insn_equiv_class_num;
7579 vect_el_t x = VEC_index (vect_el_t, min_issue_delay_vect, np);
7581 if (automaton->max_min_delay < x)
7582 automaton->max_min_delay = x;
7584 VEC_replace (vect_el_t, min_issue_delay_vect, np, 0);
7588 fprintf (output_file, "/* Vector of min issue delay of insns. */\n");
7589 fprintf (output_file, "static const ");
7590 output_range_type (output_file, 0, automaton->max_min_delay);
7591 fprintf (output_file, " ");
7592 output_min_issue_delay_vect_name (output_file, automaton);
7593 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7594 /* Compress the vector. */
7595 if (automaton->max_min_delay < 2)
7597 else if (automaton->max_min_delay < 4)
7599 else if (automaton->max_min_delay < 16)
7603 automaton->min_issue_delay_table_compression_factor = cfactor;
7605 compressed_min_issue_delay_len = (min_issue_delay_len+cfactor-1) / cfactor;
7606 compressed_min_issue_delay_vect
7607 = VEC_alloc (vect_el_t, heap, compressed_min_issue_delay_len);
7609 for (i = 0; i < compressed_min_issue_delay_len; i++)
7610 VEC_quick_push (vect_el_t, compressed_min_issue_delay_vect, 0);
7612 for (i = 0; i < min_issue_delay_len; i++)
7614 size_t ci = i / cfactor;
7615 vect_el_t x = VEC_index (vect_el_t, min_issue_delay_vect, i);
7616 vect_el_t cx = VEC_index (vect_el_t, compressed_min_issue_delay_vect, ci);
7618 cx |= x << (8 - (i % cfactor + 1) * (8 / cfactor));
7619 VEC_replace (vect_el_t, compressed_min_issue_delay_vect, ci, cx);
7621 output_vect (compressed_min_issue_delay_vect);
7622 fprintf (output_file, "};\n\n");
7623 VEC_free (state_t, heap, output_states_vect);
7624 VEC_free (vect_el_t, heap, min_issue_delay_vect);
7625 VEC_free (vect_el_t, heap, compressed_min_issue_delay_vect);
7628 /* Form and output vector representing the locked states of
7631 output_dead_lock_vect (automaton_t automaton)
7635 vla_hwint_t dead_lock_vect = 0;
7637 /* Create vect of pointers to states ordered by num of
7638 transitions from the state (state with the maximum num is the
7640 automaton->locked_states = 0;
7641 output_states_vect = 0;
7642 pass_states (automaton, add_states_vect_el);
7644 VEC_safe_grow (vect_el_t, heap, dead_lock_vect,
7645 VEC_length (state_t, output_states_vect));
7646 for (i = 0; i < VEC_length (state_t, output_states_vect); i++)
7648 state_t s = VEC_index (state_t, output_states_vect, i);
7649 arc = first_out_arc (s);
7651 if (next_out_arc (arc) == NULL
7652 && (arc->insn->insn_reserv_decl
7653 == DECL_INSN_RESERV (advance_cycle_insn_decl)))
7655 VEC_replace (vect_el_t, dead_lock_vect, s->order_state_num, 1);
7656 automaton->locked_states++;
7659 VEC_replace (vect_el_t, dead_lock_vect, s->order_state_num, 0);
7661 if (automaton->locked_states == 0)
7664 fprintf (output_file, "/* Vector for locked state flags. */\n");
7665 fprintf (output_file, "static const ");
7666 output_range_type (output_file, 0, 1);
7667 fprintf (output_file, " ");
7668 output_dead_lock_vect_name (output_file, automaton);
7669 fprintf (output_file, "[] = {\n");
7670 output_vect (dead_lock_vect);
7671 fprintf (output_file, "};\n\n");
7672 VEC_free (state_t, heap, output_states_vect);
7673 VEC_free (vect_el_t, heap, dead_lock_vect);
7676 /* Form and output vector representing reserved units of the states of
7679 output_reserved_units_table (automaton_t automaton)
7681 vla_hwint_t reserved_units_table = 0;
7682 int state_byte_size;
7683 int reserved_units_size;
7687 if (description->query_units_num == 0)
7690 /* Create vect of pointers to states. */
7691 output_states_vect = 0;
7692 pass_states (automaton, add_states_vect_el);
7693 /* Create vector. */
7694 state_byte_size = (description->query_units_num + 7) / 8;
7695 reserved_units_size = (VEC_length (state_t, output_states_vect)
7698 reserved_units_table = VEC_alloc (vect_el_t, heap, reserved_units_size);
7700 for (i = 0; i < reserved_units_size; i++)
7701 VEC_quick_push (vect_el_t, reserved_units_table, 0);
7702 for (n = 0; n < VEC_length (state_t, output_states_vect); n++)
7704 state_t s = VEC_index (state_t, output_states_vect, n);
7705 for (i = 0; i < description->units_num; i++)
7706 if (units_array [i]->query_p
7707 && first_cycle_unit_presence (s, i))
7709 int ri = (s->order_state_num * state_byte_size
7710 + units_array [i]->query_num / 8);
7711 vect_el_t x = VEC_index (vect_el_t, reserved_units_table, ri);
7713 x += 1 << (units_array [i]->query_num % 8);
7714 VEC_replace (vect_el_t, reserved_units_table, ri, x);
7717 fprintf (output_file, "\n#if %s\n", CPU_UNITS_QUERY_MACRO_NAME);
7718 fprintf (output_file, "/* Vector for reserved units of states. */\n");
7719 fprintf (output_file, "static const ");
7720 output_range_type (output_file, 0, 255);
7721 fprintf (output_file, " ");
7722 output_reserved_units_table_name (output_file, automaton);
7723 fprintf (output_file, "[] = {\n");
7724 output_vect (reserved_units_table);
7725 fprintf (output_file, "};\n#endif /* #if %s */\n\n",
7726 CPU_UNITS_QUERY_MACRO_NAME);
7728 VEC_free (state_t, heap, output_states_vect);
7729 VEC_free (vect_el_t, heap, reserved_units_table);
7732 /* The function outputs all tables representing DFA(s) used for fast
7733 pipeline hazards recognition. */
7735 output_tables (void)
7737 automaton_t automaton;
7739 for (automaton = description->first_automaton;
7741 automaton = automaton->next_automaton)
7743 output_translate_vect (automaton);
7744 output_trans_table (automaton);
7745 output_min_issue_delay_table (automaton);
7746 output_dead_lock_vect (automaton);
7747 output_reserved_units_table (automaton);
7749 fprintf (output_file, "\n#define %s %d\n\n", ADVANCE_CYCLE_VALUE_NAME,
7750 DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
7753 /* The function outputs definition and value of PHR interface variable
7754 `max_insn_queue_index'. Its value is not less than maximal queue
7755 length needed for the insn scheduler. */
7757 output_max_insn_queue_index_def (void)
7759 int i, max, latency;
7762 max = description->max_insn_reserv_cycles;
7763 for (i = 0; i < description->decls_num; i++)
7765 decl = description->decls [i];
7766 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
7768 latency = DECL_INSN_RESERV (decl)->default_latency;
7772 else if (decl->mode == dm_bypass)
7774 latency = DECL_BYPASS (decl)->latency;
7779 for (i = 0; (1 << i) <= max; i++)
7781 gcc_assert (i >= 0);
7782 fprintf (output_file, "\nconst int max_insn_queue_index = %d;\n\n",
7786 /* The function outputs switch cases for insn reservations using
7787 function *output_automata_list_code. */
7789 output_insn_code_cases (void (*output_automata_list_code)
7790 (automata_list_el_t))
7795 for (i = 0; i < description->decls_num; i++)
7797 decl = description->decls [i];
7798 if (decl->mode == dm_insn_reserv)
7799 DECL_INSN_RESERV (decl)->processed_p = FALSE;
7801 for (i = 0; i < description->decls_num; i++)
7803 decl = description->decls [i];
7804 if (decl->mode == dm_insn_reserv
7805 && !DECL_INSN_RESERV (decl)->processed_p)
7807 for (j = i; j < description->decls_num; j++)
7809 decl2 = description->decls [j];
7810 if (decl2->mode == dm_insn_reserv
7811 && (DECL_INSN_RESERV (decl2)->important_automata_list
7812 == DECL_INSN_RESERV (decl)->important_automata_list))
7814 DECL_INSN_RESERV (decl2)->processed_p = TRUE;
7815 fprintf (output_file, " case %d: /* %s */\n",
7816 DECL_INSN_RESERV (decl2)->insn_num,
7817 DECL_INSN_RESERV (decl2)->name);
7820 (*output_automata_list_code)
7821 (DECL_INSN_RESERV (decl)->important_automata_list);
7827 /* The function outputs a code for evaluation of a minimal delay of
7828 issue of insns which have reservations in given AUTOMATA_LIST. */
7830 output_automata_list_min_issue_delay_code (automata_list_el_t automata_list)
7832 automata_list_el_t el;
7833 automaton_t automaton;
7835 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
7837 automaton = el->automaton;
7838 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
7839 output_min_issue_delay_vect_name (output_file, automaton);
7840 fprintf (output_file,
7841 (automaton->min_issue_delay_table_compression_factor != 1
7843 output_translate_vect_name (output_file, automaton);
7844 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
7845 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7846 output_chip_member_name (output_file, automaton);
7847 fprintf (output_file, " * %d", automaton->insn_equiv_classes_num);
7848 if (automaton->min_issue_delay_table_compression_factor == 1)
7849 fprintf (output_file, "];\n");
7852 fprintf (output_file, ") / %d];\n",
7853 automaton->min_issue_delay_table_compression_factor);
7854 fprintf (output_file, " %s = (%s >> (8 - (",
7855 TEMPORARY_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
7856 output_translate_vect_name (output_file, automaton);
7858 (output_file, " [%s] %% %d + 1) * %d)) & %d;\n",
7859 INTERNAL_INSN_CODE_NAME,
7860 automaton->min_issue_delay_table_compression_factor,
7861 8 / automaton->min_issue_delay_table_compression_factor,
7862 (1 << (8 / automaton->min_issue_delay_table_compression_factor))
7865 if (el == automata_list)
7866 fprintf (output_file, " %s = %s;\n",
7867 RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
7870 fprintf (output_file, " if (%s > %s)\n",
7871 TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
7872 fprintf (output_file, " %s = %s;\n",
7873 RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
7876 fprintf (output_file, " break;\n\n");
7879 /* Output function `internal_min_issue_delay'. */
7881 output_internal_min_issue_delay_func (void)
7883 fprintf (output_file,
7884 "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
7885 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7886 CHIP_NAME, CHIP_PARAMETER_NAME);
7887 fprintf (output_file, "{\n int %s ATTRIBUTE_UNUSED;\n int %s = -1;\n",
7888 TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
7889 fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
7890 output_insn_code_cases (output_automata_list_min_issue_delay_code);
7891 fprintf (output_file,
7892 "\n default:\n %s = -1;\n break;\n }\n",
7893 RESULT_VARIABLE_NAME);
7894 fprintf (output_file, " return %s;\n", RESULT_VARIABLE_NAME);
7895 fprintf (output_file, "}\n\n");
7898 /* The function outputs a code changing state after issue of insns
7899 which have reservations in given AUTOMATA_LIST. */
7901 output_automata_list_transition_code (automata_list_el_t automata_list)
7903 automata_list_el_t el, next_el;
7905 fprintf (output_file, " {\n");
7906 if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
7907 for (el = automata_list;; el = next_el)
7909 next_el = el->next_automata_list_el;
7910 if (next_el == NULL)
7912 fprintf (output_file, " ");
7913 output_state_member_type (output_file, el->automaton);
7914 fprintf (output_file, " ");
7915 output_temp_chip_member_name (output_file, el->automaton);
7916 fprintf (output_file, ";\n");
7918 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
7919 if (comb_vect_p (el->automaton->trans_table))
7921 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
7922 output_trans_base_vect_name (output_file, el->automaton);
7923 fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
7924 output_chip_member_name (output_file, el->automaton);
7925 fprintf (output_file, "] + ");
7926 output_translate_vect_name (output_file, el->automaton);
7927 fprintf (output_file, " [%s];\n", INTERNAL_INSN_CODE_NAME);
7928 fprintf (output_file, " if (");
7929 output_trans_check_vect_name (output_file, el->automaton);
7930 fprintf (output_file, " [%s] != %s->",
7931 TEMPORARY_VARIABLE_NAME, CHIP_PARAMETER_NAME);
7932 output_chip_member_name (output_file, el->automaton);
7933 fprintf (output_file, ")\n");
7934 fprintf (output_file, " return %s (%s, %s);\n",
7935 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7936 CHIP_PARAMETER_NAME);
7937 fprintf (output_file, " else\n");
7938 fprintf (output_file, " ");
7939 if (el->next_automata_list_el != NULL)
7940 output_temp_chip_member_name (output_file, el->automaton);
7943 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7944 output_chip_member_name (output_file, el->automaton);
7946 fprintf (output_file, " = ");
7947 output_trans_comb_vect_name (output_file, el->automaton);
7948 fprintf (output_file, " [%s];\n", TEMPORARY_VARIABLE_NAME);
7952 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
7953 output_trans_full_vect_name (output_file, el->automaton);
7954 fprintf (output_file, " [");
7955 output_translate_vect_name (output_file, el->automaton);
7956 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
7957 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7958 output_chip_member_name (output_file, el->automaton);
7959 fprintf (output_file, " * %d];\n",
7960 el->automaton->insn_equiv_classes_num);
7961 fprintf (output_file, " if (%s >= %d)\n",
7962 TEMPORARY_VARIABLE_NAME, el->automaton->achieved_states_num);
7963 fprintf (output_file, " return %s (%s, %s);\n",
7964 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7965 CHIP_PARAMETER_NAME);
7966 fprintf (output_file, " else\n ");
7967 if (el->next_automata_list_el != NULL)
7968 output_temp_chip_member_name (output_file, el->automaton);
7971 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7972 output_chip_member_name (output_file, el->automaton);
7974 fprintf (output_file, " = %s;\n", TEMPORARY_VARIABLE_NAME);
7976 if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
7977 for (el = automata_list;; el = next_el)
7979 next_el = el->next_automata_list_el;
7980 if (next_el == NULL)
7982 fprintf (output_file, " %s->", CHIP_PARAMETER_NAME);
7983 output_chip_member_name (output_file, el->automaton);
7984 fprintf (output_file, " = ");
7985 output_temp_chip_member_name (output_file, el->automaton);
7986 fprintf (output_file, ";\n");
7988 fprintf (output_file, " return -1;\n");
7989 fprintf (output_file, " }\n");
7992 /* Output function `internal_state_transition'. */
7994 output_internal_trans_func (void)
7996 fprintf (output_file,
7997 "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
7998 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7999 CHIP_NAME, CHIP_PARAMETER_NAME);
8000 fprintf (output_file, "{\n int %s ATTRIBUTE_UNUSED;\n", TEMPORARY_VARIABLE_NAME);
8001 fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8002 output_insn_code_cases (output_automata_list_transition_code);
8003 fprintf (output_file, "\n default:\n return -1;\n }\n");
8004 fprintf (output_file, "}\n\n");
8011 insn_code = dfa_insn_code (insn);
8012 if (insn_code > DFA__ADVANCE_CYCLE)
8016 insn_code = DFA__ADVANCE_CYCLE;
8018 where insn denotes INSN_NAME, insn_code denotes INSN_CODE_NAME, and
8019 code denotes CODE. */
8021 output_internal_insn_code_evaluation (const char *insn_name,
8022 const char *insn_code_name,
8025 fprintf (output_file, "\n if (%s != 0)\n {\n", insn_name);
8026 fprintf (output_file, " %s = %s (%s);\n", insn_code_name,
8027 DFA_INSN_CODE_FUNC_NAME, insn_name);
8028 fprintf (output_file, " if (%s > %s)\n return %d;\n",
8029 insn_code_name, ADVANCE_CYCLE_VALUE_NAME, code);
8030 fprintf (output_file, " }\n else\n %s = %s;\n\n",
8031 insn_code_name, ADVANCE_CYCLE_VALUE_NAME);
8035 /* This function outputs `dfa_insn_code' and its helper function
8036 `dfa_insn_code_enlarge'. */
8038 output_dfa_insn_code_func (void)
8040 /* Emacs c-mode gets really confused if there's a { or } in column 0
8041 inside a string, so don't do that. */
8042 fprintf (output_file, "\
8044 dfa_insn_code_enlarge (int uid)\n\
8048 %s = XRESIZEVEC (int, %s,\n\
8050 for (; i < %s; i++)\n\
8051 %s[i] = -1;\n}\n\n",
8052 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8053 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8054 DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
8055 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8056 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8057 DFA_INSN_CODES_VARIABLE_NAME);
8058 fprintf (output_file, "\
8059 static inline int\n%s (rtx %s)\n\
8061 int uid = INSN_UID (%s);\n\
8063 DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME,
8064 INSN_PARAMETER_NAME, INTERNAL_INSN_CODE_NAME);
8066 fprintf (output_file,
8067 " if (uid >= %s)\n dfa_insn_code_enlarge (uid);\n\n",
8068 DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8069 fprintf (output_file, " %s = %s[uid];\n",
8070 INTERNAL_INSN_CODE_NAME, DFA_INSN_CODES_VARIABLE_NAME);
8071 fprintf (output_file, "\
8077 INTERNAL_INSN_CODE_NAME,
8078 INTERNAL_INSN_CODE_NAME,
8079 INTERNAL_DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME,
8080 DFA_INSN_CODES_VARIABLE_NAME, INTERNAL_INSN_CODE_NAME);
8081 fprintf (output_file, " return %s;\n}\n\n", INTERNAL_INSN_CODE_NAME);
8084 /* The function outputs PHR interface function `state_transition'. */
8086 output_trans_func (void)
8088 fprintf (output_file, "int\n%s (%s %s, rtx %s)\n",
8089 TRANSITION_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME,
8090 INSN_PARAMETER_NAME);
8091 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
8092 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8093 INTERNAL_INSN_CODE_NAME, -1);
8094 fprintf (output_file, " return %s (%s, (struct %s *) %s);\n}\n\n",
8095 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME, STATE_NAME);
8098 /* Output function `min_issue_delay'. */
8100 output_min_issue_delay_func (void)
8102 fprintf (output_file, "int\n%s (%s %s, rtx %s)\n",
8103 MIN_ISSUE_DELAY_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME,
8104 INSN_PARAMETER_NAME);
8105 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
8106 fprintf (output_file, "\n if (%s != 0)\n {\n", INSN_PARAMETER_NAME);
8107 fprintf (output_file, " %s = %s (%s);\n", INTERNAL_INSN_CODE_NAME,
8108 DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME);
8109 fprintf (output_file, " if (%s > %s)\n return 0;\n",
8110 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8111 fprintf (output_file, " }\n else\n %s = %s;\n",
8112 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8113 fprintf (output_file, "\n return %s (%s, (struct %s *) %s);\n",
8114 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8115 CHIP_NAME, STATE_NAME);
8116 fprintf (output_file, "}\n\n");
8119 /* Output function `internal_dead_lock'. */
8121 output_internal_dead_lock_func (void)
8123 automaton_t automaton;
8125 fprintf (output_file, "static int\n%s (struct %s *ARG_UNUSED (%s))\n",
8126 INTERNAL_DEAD_LOCK_FUNC_NAME, CHIP_NAME, CHIP_PARAMETER_NAME);
8127 fprintf (output_file, "{\n");
8128 for (automaton = description->first_automaton;
8130 automaton = automaton->next_automaton)
8131 if (automaton->locked_states)
8133 fprintf (output_file, " if (");
8134 output_dead_lock_vect_name (output_file, automaton);
8135 fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
8136 output_chip_member_name (output_file, automaton);
8137 fprintf (output_file, "])\n return 1/* TRUE */;\n");
8139 fprintf (output_file, " return 0/* FALSE */;\n}\n\n");
8142 /* The function outputs PHR interface function `state_dead_lock_p'. */
8144 output_dead_lock_func (void)
8146 fprintf (output_file, "int\n%s (%s %s)\n",
8147 DEAD_LOCK_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME);
8148 fprintf (output_file, "{\n return %s ((struct %s *) %s);\n}\n\n",
8149 INTERNAL_DEAD_LOCK_FUNC_NAME, CHIP_NAME, STATE_NAME);
8152 /* Output function `internal_reset'. */
8154 output_internal_reset_func (void)
8156 fprintf (output_file, "static inline void\n%s (struct %s *%s)\n",
8157 INTERNAL_RESET_FUNC_NAME, CHIP_NAME, CHIP_PARAMETER_NAME);
8158 fprintf (output_file, "{\n memset (%s, 0, sizeof (struct %s));\n}\n\n",
8159 CHIP_PARAMETER_NAME, CHIP_NAME);
8162 /* The function outputs PHR interface function `state_size'. */
8164 output_size_func (void)
8166 fprintf (output_file, "int\n%s (void)\n", SIZE_FUNC_NAME);
8167 fprintf (output_file, "{\n return sizeof (struct %s);\n}\n\n", CHIP_NAME);
8170 /* The function outputs PHR interface function `state_reset'. */
8172 output_reset_func (void)
8174 fprintf (output_file, "void\n%s (%s %s)\n",
8175 RESET_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME);
8176 fprintf (output_file, "{\n %s ((struct %s *) %s);\n}\n\n", INTERNAL_RESET_FUNC_NAME,
8177 CHIP_NAME, STATE_NAME);
8180 /* Output function `min_insn_conflict_delay'. */
8182 output_min_insn_conflict_delay_func (void)
8184 fprintf (output_file,
8185 "int\n%s (%s %s, rtx %s, rtx %s)\n",
8186 MIN_INSN_CONFLICT_DELAY_FUNC_NAME, STATE_TYPE_NAME,
8187 STATE_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8188 fprintf (output_file, "{\n struct %s %s;\n int %s, %s, transition;\n",
8189 CHIP_NAME, CHIP_NAME, INTERNAL_INSN_CODE_NAME,
8190 INTERNAL_INSN2_CODE_NAME);
8191 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8192 INTERNAL_INSN_CODE_NAME, 0);
8193 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
8194 INTERNAL_INSN2_CODE_NAME, 0);
8195 fprintf (output_file, " memcpy (&%s, %s, sizeof (%s));\n",
8196 CHIP_NAME, STATE_NAME, CHIP_NAME);
8197 fprintf (output_file, " %s (&%s);\n", INTERNAL_RESET_FUNC_NAME, CHIP_NAME);
8198 fprintf (output_file, " transition = %s (%s, &%s);\n",
8199 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME);
8200 fprintf (output_file, " gcc_assert (transition <= 0);\n");
8201 fprintf (output_file, " return %s (%s, &%s);\n",
8202 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN2_CODE_NAME,
8204 fprintf (output_file, "}\n\n");
8207 /* Output the array holding default latency values. These are used in
8208 insn_latency and maximal_insn_latency function implementations. */
8210 output_default_latencies (void)
8214 const char *tabletype = "unsigned char";
8216 /* Find the smallest integer type that can hold all the default
8218 for (i = 0; i < description->decls_num; i++)
8219 if (description->decls[i]->mode == dm_insn_reserv)
8221 decl = description->decls[i];
8222 if (DECL_INSN_RESERV (decl)->default_latency > UCHAR_MAX
8223 && tabletype[0] != 'i') /* Don't shrink it. */
8224 tabletype = "unsigned short";
8225 if (DECL_INSN_RESERV (decl)->default_latency > USHRT_MAX)
8229 fprintf (output_file, " static const %s default_latencies[] =\n {",
8232 for (i = 0, j = 0, col = 7; i < description->decls_num; i++)
8233 if (description->decls[i]->mode == dm_insn_reserv
8234 && description->decls[i] != advance_cycle_insn_decl)
8236 if ((col = (col+1) % 8) == 0)
8237 fputs ("\n ", output_file);
8238 decl = description->decls[i];
8239 gcc_assert (j++ == DECL_INSN_RESERV (decl)->insn_num);
8240 fprintf (output_file, "% 4d,",
8241 DECL_INSN_RESERV (decl)->default_latency);
8243 gcc_assert (j == DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
8244 fputs ("\n };\n", output_file);
8247 /* Output function `internal_insn_latency'. */
8249 output_internal_insn_latency_func (void)
8253 struct bypass_decl *bypass;
8255 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",
8256 INTERNAL_INSN_LATENCY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8257 INTERNAL_INSN2_CODE_NAME, INSN_PARAMETER_NAME,
8258 INSN2_PARAMETER_NAME);
8259 fprintf (output_file, "{\n");
8261 if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8263 fputs (" return 0;\n}\n\n", output_file);
8267 fprintf (output_file, " if (%s >= %s || %s >= %s)\n return 0;\n",
8268 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8269 INTERNAL_INSN2_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8271 fprintf (output_file, " switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8272 for (i = 0; i < description->decls_num; i++)
8273 if (description->decls[i]->mode == dm_insn_reserv
8274 && DECL_INSN_RESERV (description->decls[i])->bypass_list)
8276 decl = description->decls [i];
8277 fprintf (output_file,
8278 " case %d:\n switch (%s)\n {\n",
8279 DECL_INSN_RESERV (decl)->insn_num,
8280 INTERNAL_INSN2_CODE_NAME);
8281 for (bypass = DECL_INSN_RESERV (decl)->bypass_list;
8283 bypass = bypass->next)
8285 gcc_assert (bypass->in_insn_reserv->insn_num
8286 != (DECL_INSN_RESERV
8287 (advance_cycle_insn_decl)->insn_num));
8288 fprintf (output_file, " case %d:\n",
8289 bypass->in_insn_reserv->insn_num);
8292 if (bypass->bypass_guard_name == NULL)
8294 gcc_assert (bypass->next == NULL
8295 || (bypass->in_insn_reserv
8296 != bypass->next->in_insn_reserv));
8297 fprintf (output_file, " return %d;\n",
8302 fprintf (output_file,
8303 " if (%s (%s, %s))\n",
8304 bypass->bypass_guard_name, INSN_PARAMETER_NAME,
8305 INSN2_PARAMETER_NAME);
8306 fprintf (output_file, " return %d;\n",
8309 if (bypass->next == NULL
8310 || bypass->in_insn_reserv != bypass->next->in_insn_reserv)
8312 bypass = bypass->next;
8314 if (bypass->bypass_guard_name != NULL)
8315 fprintf (output_file, " break;\n");
8317 fputs (" }\n break;\n", output_file);
8320 fprintf (output_file, " }\n return default_latencies[%s];\n}\n\n",
8321 INTERNAL_INSN_CODE_NAME);
8324 /* Output function `internal_maximum_insn_latency'. */
8326 output_internal_maximal_insn_latency_func (void)
8329 struct bypass_decl *bypass;
8333 fprintf (output_file, "static int\n%s (int %s ATTRIBUTE_UNUSED,\n\trtx %s ATTRIBUTE_UNUSED)\n",
8334 "internal_maximal_insn_latency", INTERNAL_INSN_CODE_NAME,
8335 INSN_PARAMETER_NAME);
8336 fprintf (output_file, "{\n");
8338 if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8340 fputs (" return 0;\n}\n\n", output_file);
8344 fprintf (output_file, " switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8345 for (i = 0; i < description->decls_num; i++)
8346 if (description->decls[i]->mode == dm_insn_reserv
8347 && DECL_INSN_RESERV (description->decls[i])->bypass_list)
8349 decl = description->decls [i];
8350 max = DECL_INSN_RESERV (decl)->default_latency;
8351 fprintf (output_file,
8353 DECL_INSN_RESERV (decl)->insn_num);
8354 for (bypass = DECL_INSN_RESERV (decl)->bypass_list;
8356 bypass = bypass->next)
8358 if (bypass->latency > max)
8359 max = bypass->latency;
8361 fprintf (output_file, " return %d; }\n break;\n", max);
8364 fprintf (output_file, " }\n return default_latencies[%s];\n}\n\n",
8365 INTERNAL_INSN_CODE_NAME);
8368 /* The function outputs PHR interface function `insn_latency'. */
8370 output_insn_latency_func (void)
8372 fprintf (output_file, "int\n%s (rtx %s, rtx %s)\n",
8373 INSN_LATENCY_FUNC_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8374 fprintf (output_file, "{\n int %s, %s;\n",
8375 INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME);
8376 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8377 INTERNAL_INSN_CODE_NAME, 0);
8378 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
8379 INTERNAL_INSN2_CODE_NAME, 0);
8380 fprintf (output_file, " return %s (%s, %s, %s, %s);\n}\n\n",
8381 INTERNAL_INSN_LATENCY_FUNC_NAME,
8382 INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME,
8383 INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8386 /* The function outputs PHR interface function `maximal_insn_latency'. */
8388 output_maximal_insn_latency_func (void)
8390 fprintf (output_file, "int\n%s (rtx %s)\n",
8391 "maximal_insn_latency", INSN_PARAMETER_NAME);
8392 fprintf (output_file, "{\n int %s;\n",
8393 INTERNAL_INSN_CODE_NAME);
8394 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8395 INTERNAL_INSN_CODE_NAME, 0);
8396 fprintf (output_file, " return %s (%s, %s);\n}\n\n",
8397 "internal_maximal_insn_latency",
8398 INTERNAL_INSN_CODE_NAME, INSN_PARAMETER_NAME);
8401 /* The function outputs PHR interface function `print_reservation'. */
8403 output_print_reservation_func (void)
8408 fprintf (output_file,
8409 "void\n%s (FILE *%s, rtx %s ATTRIBUTE_UNUSED)\n{\n",
8410 PRINT_RESERVATION_FUNC_NAME, FILE_PARAMETER_NAME,
8411 INSN_PARAMETER_NAME);
8413 if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8415 fprintf (output_file, " fputs (\"%s\", %s);\n}\n\n",
8416 NOTHING_NAME, FILE_PARAMETER_NAME);
8421 fputs (" static const char *const reservation_names[] =\n {",
8424 for (i = 0, j = 0; i < description->decls_num; i++)
8426 decl = description->decls [i];
8427 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
8429 gcc_assert (j == DECL_INSN_RESERV (decl)->insn_num);
8432 fprintf (output_file, "\n \"%s\",",
8433 regexp_representation (DECL_INSN_RESERV (decl)->regexp));
8434 finish_regexp_representation ();
8437 gcc_assert (j == DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
8439 fprintf (output_file, "\n \"%s\"\n };\n int %s;\n\n",
8440 NOTHING_NAME, INTERNAL_INSN_CODE_NAME);
8442 fprintf (output_file, " if (%s == 0)\n %s = %s;\n",
8443 INSN_PARAMETER_NAME,
8444 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8445 fprintf (output_file, " else\n\
8451 INTERNAL_INSN_CODE_NAME, DFA_INSN_CODE_FUNC_NAME,
8452 INSN_PARAMETER_NAME,
8453 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8454 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8456 fprintf (output_file, " fputs (reservation_names[%s], %s);\n}\n\n",
8457 INTERNAL_INSN_CODE_NAME, FILE_PARAMETER_NAME);
8460 /* The following function is used to sort unit declaration by their
8463 units_cmp (const void *unit1, const void *unit2)
8465 const_unit_decl_t const u1 = *(const_unit_decl_t const*) unit1;
8466 const_unit_decl_t const u2 = *(const_unit_decl_t const*) unit2;
8468 return strcmp (u1->name, u2->name);
8471 /* The following macro value is name of struct containing unit name
8473 #define NAME_CODE_STRUCT_NAME "name_code"
8475 /* The following macro value is name of table of struct name_code. */
8476 #define NAME_CODE_TABLE_NAME "name_code_table"
8478 /* The following macro values are member names for struct name_code. */
8479 #define NAME_MEMBER_NAME "name"
8480 #define CODE_MEMBER_NAME "code"
8482 /* The following macro values are local variable names for function
8483 `get_cpu_unit_code'. */
8484 #define CMP_VARIABLE_NAME "cmp"
8485 #define LOW_VARIABLE_NAME "l"
8486 #define MIDDLE_VARIABLE_NAME "m"
8487 #define HIGH_VARIABLE_NAME "h"
8489 /* The following function outputs function to obtain internal cpu unit
8490 code by the cpu unit name. */
8492 output_get_cpu_unit_code_func (void)
8497 fprintf (output_file, "int\n%s (const char *%s)\n",
8498 GET_CPU_UNIT_CODE_FUNC_NAME, CPU_UNIT_NAME_PARAMETER_NAME);
8499 fprintf (output_file, "{\n struct %s {const char *%s; int %s;};\n",
8500 NAME_CODE_STRUCT_NAME, NAME_MEMBER_NAME, CODE_MEMBER_NAME);
8501 fprintf (output_file, " int %s, %s, %s, %s;\n", CMP_VARIABLE_NAME,
8502 LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8503 fprintf (output_file, " static struct %s %s [] =\n {\n",
8504 NAME_CODE_STRUCT_NAME, NAME_CODE_TABLE_NAME);
8505 units = XNEWVEC (unit_decl_t, description->units_num);
8506 memcpy (units, units_array, sizeof (unit_decl_t) * description->units_num);
8507 qsort (units, description->units_num, sizeof (unit_decl_t), units_cmp);
8508 for (i = 0; i < description->units_num; i++)
8509 if (units [i]->query_p)
8510 fprintf (output_file, " {\"%s\", %d},\n",
8511 units[i]->name, units[i]->query_num);
8512 fprintf (output_file, " };\n\n");
8513 fprintf (output_file, " /* The following is binary search: */\n");
8514 fprintf (output_file, " %s = 0;\n", LOW_VARIABLE_NAME);
8515 fprintf (output_file, " %s = sizeof (%s) / sizeof (struct %s) - 1;\n",
8516 HIGH_VARIABLE_NAME, NAME_CODE_TABLE_NAME, NAME_CODE_STRUCT_NAME);
8517 fprintf (output_file, " while (%s <= %s)\n {\n",
8518 LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8519 fprintf (output_file, " %s = (%s + %s) / 2;\n",
8520 MIDDLE_VARIABLE_NAME, LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8521 fprintf (output_file, " %s = strcmp (%s, %s [%s].%s);\n",
8522 CMP_VARIABLE_NAME, CPU_UNIT_NAME_PARAMETER_NAME,
8523 NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, NAME_MEMBER_NAME);
8524 fprintf (output_file, " if (%s < 0)\n", CMP_VARIABLE_NAME);
8525 fprintf (output_file, " %s = %s - 1;\n",
8526 HIGH_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
8527 fprintf (output_file, " else if (%s > 0)\n", CMP_VARIABLE_NAME);
8528 fprintf (output_file, " %s = %s + 1;\n",
8529 LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
8530 fprintf (output_file, " else\n");
8531 fprintf (output_file, " return %s [%s].%s;\n }\n",
8532 NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, CODE_MEMBER_NAME);
8533 fprintf (output_file, " return -1;\n}\n\n");
8537 /* The following function outputs function to check reservation of cpu
8538 unit (its internal code will be passed as the function argument) in
8541 output_cpu_unit_reservation_p (void)
8543 automaton_t automaton;
8545 fprintf (output_file, "int\n%s (%s %s, int %s)\n",
8546 CPU_UNIT_RESERVATION_P_FUNC_NAME,
8547 STATE_TYPE_NAME, STATE_NAME,
8548 CPU_CODE_PARAMETER_NAME);
8549 fprintf (output_file, "{\n gcc_assert (%s >= 0 && %s < %d);\n",
8550 CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME,
8551 description->query_units_num);
8552 if (description->query_units_num > 0)
8553 for (automaton = description->first_automaton;
8555 automaton = automaton->next_automaton)
8557 fprintf (output_file, " if ((");
8558 output_reserved_units_table_name (output_file, automaton);
8559 fprintf (output_file, " [((struct %s *) %s)->", CHIP_NAME, STATE_NAME);
8560 output_chip_member_name (output_file, automaton);
8561 fprintf (output_file, " * %d + %s / 8] >> (%s %% 8)) & 1)\n",
8562 (description->query_units_num + 7) / 8,
8563 CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME);
8564 fprintf (output_file, " return 1;\n");
8566 fprintf (output_file, " return 0;\n}\n\n");
8569 /* The following function outputs a function to check if insn
8570 has a dfa reservation. */
8572 output_insn_has_dfa_reservation_p (void)
8574 fprintf (output_file,
8575 "bool\n%s (rtx %s ATTRIBUTE_UNUSED)\n{\n",
8576 INSN_HAS_DFA_RESERVATION_P_FUNC_NAME,
8577 INSN_PARAMETER_NAME);
8579 if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8581 fprintf (output_file, " return false;\n}\n\n");
8585 fprintf (output_file, " int %s;\n\n", INTERNAL_INSN_CODE_NAME);
8587 fprintf (output_file, " if (%s == 0)\n %s = %s;\n",
8588 INSN_PARAMETER_NAME,
8589 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8590 fprintf (output_file, " else\n\
8596 INTERNAL_INSN_CODE_NAME, DFA_INSN_CODE_FUNC_NAME,
8597 INSN_PARAMETER_NAME,
8598 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8599 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8601 fprintf (output_file, " return %s != %s;\n}\n\n",
8602 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8605 /* The function outputs PHR interface functions `dfa_clean_insn_cache'
8606 and 'dfa_clear_single_insn_cache'. */
8608 output_dfa_clean_insn_cache_func (void)
8610 fprintf (output_file,
8611 "void\n%s (void)\n{\n int %s;\n\n",
8612 DFA_CLEAN_INSN_CACHE_FUNC_NAME, I_VARIABLE_NAME);
8613 fprintf (output_file,
8614 " for (%s = 0; %s < %s; %s++)\n %s [%s] = -1;\n}\n\n",
8615 I_VARIABLE_NAME, I_VARIABLE_NAME,
8616 DFA_INSN_CODES_LENGTH_VARIABLE_NAME, I_VARIABLE_NAME,
8617 DFA_INSN_CODES_VARIABLE_NAME, I_VARIABLE_NAME);
8619 fprintf (output_file,
8620 "void\n%s (rtx %s)\n{\n int %s;\n\n",
8621 DFA_CLEAR_SINGLE_INSN_CACHE_FUNC_NAME, INSN_PARAMETER_NAME,
8623 fprintf (output_file,
8624 " %s = INSN_UID (%s);\n if (%s < %s)\n %s [%s] = -1;\n}\n\n",
8625 I_VARIABLE_NAME, INSN_PARAMETER_NAME, I_VARIABLE_NAME,
8626 DFA_INSN_CODES_LENGTH_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
8630 /* The function outputs PHR interface function `dfa_start'. */
8632 output_dfa_start_func (void)
8634 fprintf (output_file,
8635 "void\n%s (void)\n{\n %s = get_max_uid ();\n",
8636 DFA_START_FUNC_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8637 fprintf (output_file, " %s = XNEWVEC (int, %s);\n",
8638 DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8639 fprintf (output_file, " %s ();\n}\n\n", DFA_CLEAN_INSN_CACHE_FUNC_NAME);
8642 /* The function outputs PHR interface function `dfa_finish'. */
8644 output_dfa_finish_func (void)
8646 fprintf (output_file, "void\n%s (void)\n{\n free (%s);\n}\n\n",
8647 DFA_FINISH_FUNC_NAME, DFA_INSN_CODES_VARIABLE_NAME);
8652 /* The page contains code for output description file (readable
8653 representation of original description and generated DFA(s). */
8655 /* The function outputs string representation of IR reservation. */
8657 output_regexp (regexp_t regexp)
8659 fprintf (output_description_file, "%s", regexp_representation (regexp));
8660 finish_regexp_representation ();
8663 /* Output names of units in LIST separated by comma. */
8665 output_unit_set_el_list (unit_set_el_t list)
8669 for (el = list; el != NULL; el = el->next_unit_set_el)
8672 fprintf (output_description_file, ", ");
8673 fprintf (output_description_file, "%s", el->unit_decl->name);
8677 /* Output patterns in LIST separated by comma. */
8679 output_pattern_set_el_list (pattern_set_el_t list)
8681 pattern_set_el_t el;
8684 for (el = list; el != NULL; el = el->next_pattern_set_el)
8687 fprintf (output_description_file, ", ");
8688 for (i = 0; i < el->units_num; i++)
8689 fprintf (output_description_file, (i == 0 ? "%s" : " %s"),
8690 el->unit_decls [i]->name);
8694 /* The function outputs string representation of IR define_reservation
8695 and define_insn_reservation. */
8697 output_description (void)
8702 for (i = 0; i < description->decls_num; i++)
8704 decl = description->decls [i];
8705 if (decl->mode == dm_unit)
8707 if (DECL_UNIT (decl)->excl_list != NULL)
8709 fprintf (output_description_file, "unit %s exclusion_set: ",
8710 DECL_UNIT (decl)->name);
8711 output_unit_set_el_list (DECL_UNIT (decl)->excl_list);
8712 fprintf (output_description_file, "\n");
8714 if (DECL_UNIT (decl)->presence_list != NULL)
8716 fprintf (output_description_file, "unit %s presence_set: ",
8717 DECL_UNIT (decl)->name);
8718 output_pattern_set_el_list (DECL_UNIT (decl)->presence_list);
8719 fprintf (output_description_file, "\n");
8721 if (DECL_UNIT (decl)->final_presence_list != NULL)
8723 fprintf (output_description_file, "unit %s final_presence_set: ",
8724 DECL_UNIT (decl)->name);
8725 output_pattern_set_el_list
8726 (DECL_UNIT (decl)->final_presence_list);
8727 fprintf (output_description_file, "\n");
8729 if (DECL_UNIT (decl)->absence_list != NULL)
8731 fprintf (output_description_file, "unit %s absence_set: ",
8732 DECL_UNIT (decl)->name);
8733 output_pattern_set_el_list (DECL_UNIT (decl)->absence_list);
8734 fprintf (output_description_file, "\n");
8736 if (DECL_UNIT (decl)->final_absence_list != NULL)
8738 fprintf (output_description_file, "unit %s final_absence_set: ",
8739 DECL_UNIT (decl)->name);
8740 output_pattern_set_el_list
8741 (DECL_UNIT (decl)->final_absence_list);
8742 fprintf (output_description_file, "\n");
8746 fprintf (output_description_file, "\n");
8747 for (i = 0; i < description->decls_num; i++)
8749 decl = description->decls [i];
8750 if (decl->mode == dm_reserv)
8752 fprintf (output_description_file, "reservation %s: ",
8753 DECL_RESERV (decl)->name);
8754 output_regexp (DECL_RESERV (decl)->regexp);
8755 fprintf (output_description_file, "\n");
8757 else if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
8759 fprintf (output_description_file, "insn reservation %s ",
8760 DECL_INSN_RESERV (decl)->name);
8761 print_rtl (output_description_file,
8762 DECL_INSN_RESERV (decl)->condexp);
8763 fprintf (output_description_file, ": ");
8764 output_regexp (DECL_INSN_RESERV (decl)->regexp);
8765 fprintf (output_description_file, "\n");
8767 else if (decl->mode == dm_bypass)
8768 fprintf (output_description_file, "bypass %d %s %s\n",
8769 DECL_BYPASS (decl)->latency,
8770 DECL_BYPASS (decl)->out_insn_name,
8771 DECL_BYPASS (decl)->in_insn_name);
8773 fprintf (output_description_file, "\n\f\n");
8776 /* The function outputs name of AUTOMATON. */
8778 output_automaton_name (FILE *f, automaton_t automaton)
8780 if (automaton->corresponding_automaton_decl == NULL)
8781 fprintf (f, "#%d", automaton->automaton_order_num);
8783 fprintf (f, "`%s'", automaton->corresponding_automaton_decl->name);
8786 /* Maximal length of line for pretty printing into description
8788 #define MAX_LINE_LENGTH 70
8790 /* The function outputs units name belonging to AUTOMATON. */
8792 output_automaton_units (automaton_t automaton)
8796 int curr_line_length;
8797 int there_is_an_automaton_unit;
8800 fprintf (output_description_file, "\n Corresponding units:\n");
8801 fprintf (output_description_file, " ");
8802 curr_line_length = 4;
8803 there_is_an_automaton_unit = 0;
8804 for (i = 0; i < description->decls_num; i++)
8806 decl = description->decls [i];
8807 if (decl->mode == dm_unit
8808 && (DECL_UNIT (decl)->corresponding_automaton_num
8809 == automaton->automaton_order_num))
8811 there_is_an_automaton_unit = 1;
8812 name = DECL_UNIT (decl)->name;
8813 if (curr_line_length + strlen (name) + 1 > MAX_LINE_LENGTH )
8815 curr_line_length = strlen (name) + 4;
8816 fprintf (output_description_file, "\n ");
8820 curr_line_length += strlen (name) + 1;
8821 fprintf (output_description_file, " ");
8823 fprintf (output_description_file, "%s", name);
8826 if (!there_is_an_automaton_unit)
8827 fprintf (output_description_file, "<None>");
8828 fprintf (output_description_file, "\n\n");
8831 /* The following variable is used for forming array of all possible cpu unit
8832 reservations described by the current DFA state. */
8833 static VEC(reserv_sets_t, heap) *state_reservs;
8835 /* The function forms `state_reservs' for STATE. */
8837 add_state_reservs (state_t state)
8839 alt_state_t curr_alt_state;
8841 if (state->component_states != NULL)
8842 for (curr_alt_state = state->component_states;
8843 curr_alt_state != NULL;
8844 curr_alt_state = curr_alt_state->next_sorted_alt_state)
8845 add_state_reservs (curr_alt_state->state);
8847 VEC_safe_push (reserv_sets_t, heap, state_reservs, state->reservs);
8850 /* The function outputs readable representation of all out arcs of
8853 output_state_arcs (state_t state)
8857 const char *insn_name;
8858 int curr_line_length;
8860 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
8863 gcc_assert (ainsn->first_insn_with_same_reservs);
8864 fprintf (output_description_file, " ");
8865 curr_line_length = 7;
8866 fprintf (output_description_file, "%2d: ", ainsn->insn_equiv_class_num);
8869 insn_name = ainsn->insn_reserv_decl->name;
8870 if (curr_line_length + strlen (insn_name) > MAX_LINE_LENGTH)
8872 if (ainsn != arc->insn)
8874 fprintf (output_description_file, ",\n ");
8875 curr_line_length = strlen (insn_name) + 6;
8878 curr_line_length += strlen (insn_name);
8882 curr_line_length += strlen (insn_name);
8883 if (ainsn != arc->insn)
8885 curr_line_length += 2;
8886 fprintf (output_description_file, ", ");
8889 fprintf (output_description_file, "%s", insn_name);
8890 ainsn = ainsn->next_same_reservs_insn;
8892 while (ainsn != NULL);
8893 fprintf (output_description_file, " %d \n",
8894 arc->to_state->order_state_num);
8896 fprintf (output_description_file, "\n");
8899 /* The following function is used for sorting possible cpu unit
8900 reservation of a DFA state. */
8902 state_reservs_cmp (const void *reservs_ptr_1, const void *reservs_ptr_2)
8904 return reserv_sets_cmp (*(const_reserv_sets_t const*) reservs_ptr_1,
8905 *(const_reserv_sets_t const*) reservs_ptr_2);
8908 /* The following function is used for sorting possible cpu unit
8909 reservation of a DFA state. */
8911 remove_state_duplicate_reservs (void)
8915 for (i = 1, j = 0; i < VEC_length (reserv_sets_t, state_reservs); i++)
8916 if (reserv_sets_cmp (VEC_index (reserv_sets_t, state_reservs, j),
8917 VEC_index (reserv_sets_t, state_reservs, i)))
8920 VEC_replace (reserv_sets_t, state_reservs, j,
8921 VEC_index (reserv_sets_t, state_reservs, i));
8923 VEC_truncate (reserv_sets_t, state_reservs, j + 1);
8926 /* The following function output readable representation of DFA(s)
8927 state used for fast recognition of pipeline hazards. State is
8928 described by possible (current and scheduled) cpu unit
8931 output_state (state_t state)
8937 fprintf (output_description_file, " State #%d", state->order_state_num);
8938 fprintf (output_description_file,
8939 state->new_cycle_p ? " (new cycle)\n" : "\n");
8940 add_state_reservs (state);
8941 qsort (VEC_address (reserv_sets_t, state_reservs),
8942 VEC_length (reserv_sets_t, state_reservs),
8943 sizeof (reserv_sets_t), state_reservs_cmp);
8944 remove_state_duplicate_reservs ();
8945 for (i = 0; i < VEC_length (reserv_sets_t, state_reservs); i++)
8947 fprintf (output_description_file, " ");
8948 output_reserv_sets (output_description_file,
8949 VEC_index (reserv_sets_t, state_reservs, i));
8950 fprintf (output_description_file, "\n");
8952 fprintf (output_description_file, "\n");
8953 output_state_arcs (state);
8954 VEC_free (reserv_sets_t, heap, state_reservs);
8957 /* The following function output readable representation of
8958 DFAs used for fast recognition of pipeline hazards. */
8960 output_automaton_descriptions (void)
8962 automaton_t automaton;
8964 for (automaton = description->first_automaton;
8966 automaton = automaton->next_automaton)
8968 fprintf (output_description_file, "\nAutomaton ");
8969 output_automaton_name (output_description_file, automaton);
8970 fprintf (output_description_file, "\n");
8971 output_automaton_units (automaton);
8972 pass_states (automaton, output_state);
8978 /* The page contains top level function for generation DFA(s) used for
8981 /* The function outputs statistics about work of different phases of
8984 output_statistics (FILE *f)
8986 automaton_t automaton;
8989 int transition_comb_vect_els = 0;
8990 int transition_full_vect_els = 0;
8991 int min_issue_delay_vect_els = 0;
8992 int locked_states = 0;
8995 for (automaton = description->first_automaton;
8997 automaton = automaton->next_automaton)
8999 fprintf (f, "\nAutomaton ");
9000 output_automaton_name (f, automaton);
9001 fprintf (f, "\n %5d NDFA states, %5d NDFA arcs\n",
9002 automaton->NDFA_states_num, automaton->NDFA_arcs_num);
9003 fprintf (f, " %5d DFA states, %5d DFA arcs\n",
9004 automaton->DFA_states_num, automaton->DFA_arcs_num);
9005 states_num = automaton->DFA_states_num;
9006 if (!no_minimization_flag)
9008 fprintf (f, " %5d minimal DFA states, %5d minimal DFA arcs\n",
9009 automaton->minimal_DFA_states_num,
9010 automaton->minimal_DFA_arcs_num);
9011 states_num = automaton->minimal_DFA_states_num;
9013 fprintf (f, " %5d all insns %5d insn equivalence classes\n",
9014 description->insns_num, automaton->insn_equiv_classes_num);
9015 fprintf (f, " %d locked states\n", automaton->locked_states);
9018 (f, "%5ld transition comb vector els, %5ld trans table els: %s\n",
9019 (long) VEC_length (vect_el_t, automaton->trans_table->comb_vect),
9020 (long) VEC_length (vect_el_t, automaton->trans_table->full_vect),
9021 (comb_vect_p (automaton->trans_table)
9022 ? "use comb vect" : "use simple vect"));
9024 (f, "%5ld min delay table els, compression factor %d\n",
9025 (long) states_num * automaton->insn_equiv_classes_num,
9026 automaton->min_issue_delay_table_compression_factor);
9027 transition_comb_vect_els
9028 += VEC_length (vect_el_t, automaton->trans_table->comb_vect);
9029 transition_full_vect_els
9030 += VEC_length (vect_el_t, automaton->trans_table->full_vect);
9031 min_issue_delay_vect_els
9032 += states_num * automaton->insn_equiv_classes_num;
9034 += automaton->locked_states;
9038 fprintf (f, "\n%5d all allocated states, %5d all allocated arcs\n",
9039 allocated_states_num, allocated_arcs_num);
9040 fprintf (f, "%5d all allocated alternative states\n",
9041 allocated_alt_states_num);
9042 fprintf (f, "%5d all transition comb vector els, %5d all trans table els\n",
9043 transition_comb_vect_els, transition_full_vect_els);
9044 fprintf (f, "%5d all min delay table els\n", min_issue_delay_vect_els);
9045 fprintf (f, "%5d all locked states\n", locked_states);
9049 /* The function output times of work of different phases of DFA
9052 output_time_statistics (FILE *f)
9054 fprintf (f, "\n transformation: ");
9055 print_active_time (f, transform_time);
9056 fprintf (f, (!ndfa_flag ? ", building DFA: " : ", building NDFA: "));
9057 print_active_time (f, NDFA_time);
9060 fprintf (f, ", NDFA -> DFA: ");
9061 print_active_time (f, NDFA_to_DFA_time);
9063 fprintf (f, "\n DFA minimization: ");
9064 print_active_time (f, minimize_time);
9065 fprintf (f, ", making insn equivalence: ");
9066 print_active_time (f, equiv_time);
9067 fprintf (f, "\n all automaton generation: ");
9068 print_active_time (f, automaton_generation_time);
9069 fprintf (f, ", output: ");
9070 print_active_time (f, output_time);
9074 /* The function generates DFA (deterministic finite state automaton)
9075 for fast recognition of pipeline hazards. No errors during
9076 checking must be fixed before this function call. */
9080 automata_num = split_argument;
9081 if (description->units_num < automata_num)
9082 automata_num = description->units_num;
9085 initiate_automata_lists ();
9086 initiate_pass_states ();
9087 initiate_excl_sets ();
9088 initiate_presence_absence_pattern_sets ();
9089 automaton_generation_time = create_ticker ();
9091 ticker_off (&automaton_generation_time);
9096 /* This page mainly contains top level functions of pipeline hazards
9097 description translator. */
9099 /* The following macro value is suffix of name of description file of
9100 pipeline hazards description translator. */
9101 #define STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX ".dfa"
9103 /* The function returns suffix of given file name. The returned
9104 string can not be changed. */
9106 file_name_suffix (const char *file_name)
9108 const char *last_period;
9110 for (last_period = NULL; *file_name != '\0'; file_name++)
9111 if (*file_name == '.')
9112 last_period = file_name;
9113 return (last_period == NULL ? file_name : last_period);
9116 /* The function returns base name of given file name, i.e. pointer to
9117 first char after last `/' (or `\' for WIN32) in given file name,
9118 given file name itself if the directory name is absent. The
9119 returned string can not be changed. */
9121 base_file_name (const char *file_name)
9123 int directory_name_length;
9125 directory_name_length = strlen (file_name);
9127 while (directory_name_length >= 0 && file_name[directory_name_length] != '/'
9128 && file_name[directory_name_length] != '\\')
9130 while (directory_name_length >= 0 && file_name[directory_name_length] != '/')
9132 directory_name_length--;
9133 return file_name + directory_name_length + 1;
9136 /* The following is top level function to initialize the work of
9137 pipeline hazards description translator. */
9139 initiate_automaton_gen (int argc, char **argv)
9141 const char *base_name;
9145 split_argument = 0; /* default value */
9146 no_minimization_flag = 0;
9152 for (i = 2; i < argc; i++)
9153 if (strcmp (argv [i], NO_MINIMIZATION_OPTION) == 0)
9154 no_minimization_flag = 1;
9155 else if (strcmp (argv [i], TIME_OPTION) == 0)
9157 else if (strcmp (argv [i], STATS_OPTION) == 0)
9159 else if (strcmp (argv [i], V_OPTION) == 0)
9161 else if (strcmp (argv [i], W_OPTION) == 0)
9163 else if (strcmp (argv [i], NDFA_OPTION) == 0)
9165 else if (strcmp (argv [i], PROGRESS_OPTION) == 0)
9167 else if (strcmp (argv [i], "-split") == 0)
9170 fatal ("-split has no argument.");
9171 fatal ("option `-split' has not been implemented yet\n");
9172 /* split_argument = atoi (argument_vect [i + 1]); */
9175 /* Initialize IR storage. */
9176 obstack_init (&irp);
9177 initiate_automaton_decl_table ();
9178 initiate_insn_decl_table ();
9179 initiate_decl_table ();
9180 output_file = stdout;
9181 output_description_file = NULL;
9182 base_name = base_file_name (argv[1]);
9183 obstack_grow (&irp, base_name,
9184 strlen (base_name) - strlen (file_name_suffix (base_name)));
9185 obstack_grow (&irp, STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX,
9186 strlen (STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX) + 1);
9187 obstack_1grow (&irp, '\0');
9188 output_description_file_name = obstack_base (&irp);
9189 obstack_finish (&irp);
9192 /* The following function checks existence at least one arc marked by
9195 check_automata_insn_issues (void)
9197 automaton_t automaton;
9198 ainsn_t ainsn, reserv_ainsn;
9200 for (automaton = description->first_automaton;
9202 automaton = automaton->next_automaton)
9204 for (ainsn = automaton->ainsn_list;
9206 ainsn = ainsn->next_ainsn)
9207 if (ainsn->first_insn_with_same_reservs && !ainsn->arc_exists_p)
9209 for (reserv_ainsn = ainsn;
9210 reserv_ainsn != NULL;
9211 reserv_ainsn = reserv_ainsn->next_same_reservs_insn)
9212 if (automaton->corresponding_automaton_decl != NULL)
9215 error ("Automaton `%s': Insn `%s' will never be issued",
9216 automaton->corresponding_automaton_decl->name,
9217 reserv_ainsn->insn_reserv_decl->name);
9219 warning ("Automaton `%s': Insn `%s' will never be issued",
9220 automaton->corresponding_automaton_decl->name,
9221 reserv_ainsn->insn_reserv_decl->name);
9226 error ("Insn `%s' will never be issued",
9227 reserv_ainsn->insn_reserv_decl->name);
9229 warning ("Insn `%s' will never be issued",
9230 reserv_ainsn->insn_reserv_decl->name);
9236 /* The following vla is used for storing pointers to all achieved
9238 static VEC(state_t, heap) *automaton_states;
9240 /* This function is called by function pass_states to add an achieved
9243 add_automaton_state (state_t state)
9245 VEC_safe_push (state_t, heap, automaton_states, state);
9248 /* The following function forms list of important automata (whose
9249 states may be changed after the insn issue) for each insn. */
9251 form_important_insn_automata_lists (void)
9253 automaton_t automaton;
9260 automaton_states = 0;
9261 /* Mark important ainsns. */
9262 for (automaton = description->first_automaton;
9264 automaton = automaton->next_automaton)
9266 VEC_truncate (state_t, automaton_states, 0);
9267 pass_states (automaton, add_automaton_state);
9268 for (n = 0; n < VEC_length (state_t, automaton_states); n++)
9270 state_t s = VEC_index (state_t, automaton_states, n);
9271 for (arc = first_out_arc (s);
9273 arc = next_out_arc (arc))
9274 if (arc->to_state != s)
9276 gcc_assert (arc->insn->first_insn_with_same_reservs);
9277 for (ainsn = arc->insn;
9279 ainsn = ainsn->next_same_reservs_insn)
9280 ainsn->important_p = TRUE;
9284 VEC_free (state_t, heap, automaton_states);
9286 /* Create automata sets for the insns. */
9287 for (i = 0; i < description->decls_num; i++)
9289 decl = description->decls [i];
9290 if (decl->mode == dm_insn_reserv)
9292 automata_list_start ();
9293 for (automaton = description->first_automaton;
9295 automaton = automaton->next_automaton)
9296 for (ainsn = automaton->ainsn_list;
9298 ainsn = ainsn->next_ainsn)
9299 if (ainsn->important_p
9300 && ainsn->insn_reserv_decl == DECL_INSN_RESERV (decl))
9302 automata_list_add (automaton);
9305 DECL_INSN_RESERV (decl)->important_automata_list
9306 = automata_list_finish ();
9312 /* The following is top level function to generate automat(a,on) for
9313 fast recognition of pipeline hazards. */
9315 expand_automata (void)
9319 description = XCREATENODEVAR (struct description,
9320 sizeof (struct description)
9321 /* One entry for cycle advancing insn. */
9322 + sizeof (decl_t) * VEC_length (decl_t, decls));
9323 description->decls_num = VEC_length (decl_t, decls);
9324 description->query_units_num = 0;
9325 for (i = 0; i < description->decls_num; i++)
9327 description->decls [i] = VEC_index (decl_t, decls, i);
9328 if (description->decls [i]->mode == dm_unit
9329 && DECL_UNIT (description->decls [i])->query_p)
9330 DECL_UNIT (description->decls [i])->query_num
9331 = description->query_units_num++;
9333 all_time = create_ticker ();
9334 check_time = create_ticker ();
9336 fprintf (stderr, "Check description...");
9337 check_all_description ();
9339 fprintf (stderr, "done\n");
9340 ticker_off (&check_time);
9341 generation_time = create_ticker ();
9344 transform_insn_regexps ();
9345 check_unit_distributions_to_automata ();
9350 check_automata_insn_issues ();
9354 form_important_insn_automata_lists ();
9356 ticker_off (&generation_time);
9359 /* The following is top level function to output PHR and to finish
9360 work with pipeline description translator. */
9362 write_automata (void)
9364 output_time = create_ticker ();
9366 fprintf (stderr, "Forming and outputting automata tables...");
9370 fprintf (stderr, "done\n");
9371 fprintf (stderr, "Output functions to work with automata...");
9373 output_chip_definitions ();
9374 output_max_insn_queue_index_def ();
9375 output_internal_min_issue_delay_func ();
9376 output_internal_trans_func ();
9377 /* Cache of insn dfa codes: */
9378 fprintf (output_file, "\nstatic int *%s;\n", DFA_INSN_CODES_VARIABLE_NAME);
9379 fprintf (output_file, "\nstatic int %s;\n\n",
9380 DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
9381 output_dfa_insn_code_func ();
9382 output_trans_func ();
9383 output_min_issue_delay_func ();
9384 output_internal_dead_lock_func ();
9385 output_dead_lock_func ();
9386 output_size_func ();
9387 output_internal_reset_func ();
9388 output_reset_func ();
9389 output_min_insn_conflict_delay_func ();
9390 output_default_latencies ();
9391 output_internal_insn_latency_func ();
9392 output_insn_latency_func ();
9393 output_internal_maximal_insn_latency_func ();
9394 output_maximal_insn_latency_func ();
9395 output_print_reservation_func ();
9396 /* Output function get_cpu_unit_code. */
9397 fprintf (output_file, "\n#if %s\n\n", CPU_UNITS_QUERY_MACRO_NAME);
9398 output_get_cpu_unit_code_func ();
9399 output_cpu_unit_reservation_p ();
9400 output_insn_has_dfa_reservation_p ();
9401 fprintf (output_file, "\n#endif /* #if %s */\n\n",
9402 CPU_UNITS_QUERY_MACRO_NAME);
9403 output_dfa_clean_insn_cache_func ();
9404 output_dfa_start_func ();
9405 output_dfa_finish_func ();
9407 fprintf (stderr, "done\n");
9410 output_description_file = fopen (output_description_file_name, "w");
9411 if (output_description_file == NULL)
9413 perror (output_description_file_name);
9414 exit (FATAL_EXIT_CODE);
9417 fprintf (stderr, "Output automata description...");
9418 output_description ();
9419 output_automaton_descriptions ();
9421 fprintf (stderr, "done\n");
9422 output_statistics (output_description_file);
9425 output_statistics (stderr);
9426 ticker_off (&output_time);
9428 output_time_statistics (stderr);
9431 finish_automata_lists ();
9434 fprintf (stderr, "Summary:\n");
9435 fprintf (stderr, " check time ");
9436 print_active_time (stderr, check_time);
9437 fprintf (stderr, ", generation time ");
9438 print_active_time (stderr, generation_time);
9439 fprintf (stderr, ", all time ");
9440 print_active_time (stderr, all_time);
9441 fprintf (stderr, "\n");
9443 /* Finish all work. */
9444 if (output_description_file != NULL)
9446 fflush (output_description_file);
9447 if (ferror (stdout) != 0)
9448 fatal ("Error in writing DFA description file %s: %s",
9449 output_description_file_name, xstrerror (errno));
9450 fclose (output_description_file);
9452 finish_automaton_decl_table ();
9453 finish_insn_decl_table ();
9454 finish_decl_table ();
9455 obstack_free (&irp, NULL);
9456 if (have_error && output_description_file != NULL)
9457 remove (output_description_file_name);
9461 main (int argc, char **argv)
9465 progname = "genautomata";
9467 if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
9468 return (FATAL_EXIT_CODE);
9470 initiate_automaton_gen (argc, argv);
9474 int insn_code_number;
9476 desc = read_md_rtx (&lineno, &insn_code_number);
9480 switch (GET_CODE (desc))
9482 case DEFINE_CPU_UNIT:
9483 gen_cpu_unit (desc);
9486 case DEFINE_QUERY_CPU_UNIT:
9487 gen_query_cpu_unit (desc);
9495 gen_excl_set (desc);
9499 gen_presence_set (desc);
9502 case FINAL_PRESENCE_SET:
9503 gen_final_presence_set (desc);
9507 gen_absence_set (desc);
9510 case FINAL_ABSENCE_SET:
9511 gen_final_absence_set (desc);
9514 case DEFINE_AUTOMATON:
9515 gen_automaton (desc);
9518 case AUTOMATA_OPTION:
9519 gen_automata_option (desc);
9522 case DEFINE_RESERVATION:
9526 case DEFINE_INSN_RESERVATION:
9527 gen_insn_reserv (desc);
9536 return FATAL_EXIT_CODE;
9538 if (VEC_length (decl_t, decls) > 0)
9543 puts ("/* Generated automatically by the program `genautomata'\n"
9544 " from the machine description file `md'. */\n\n"
9545 "#include \"config.h\"\n"
9546 "#include \"system.h\"\n"
9547 "#include \"coretypes.h\"\n"
9548 "#include \"tm.h\"\n"
9549 "#include \"rtl.h\"\n"
9550 "#include \"tm_p.h\"\n"
9551 "#include \"insn-config.h\"\n"
9552 "#include \"recog.h\"\n"
9553 "#include \"regs.h\"\n"
9554 "#include \"output.h\"\n"
9555 "#include \"insn-attr.h\"\n"
9556 "#include \"toplev.h\"\n"
9557 "#include \"flags.h\"\n"
9558 "#include \"function.h\"\n"
9559 "#include \"emit-rtl.h\"\n");
9560 /* FIXME: emit-rtl.h can go away once crtl is in rtl.h. */
9567 return (ferror (stdout) != 0 || have_error
9568 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);