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, 1);
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, 1);
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, 1);
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);
2318 (0, "unit `%s' excludes and requires presence of `%s'",
2319 dst->unit_decl->name, unit->name);
2322 else if (pat->units_num == 1)
2323 for (curr_pat_el = dst->unit_decl->presence_list;
2324 curr_pat_el != NULL;
2325 curr_pat_el = curr_pat_el->next_pattern_set_el)
2326 if (curr_pat_el->units_num == 1
2327 && unit == curr_pat_el->unit_decls [0])
2332 ("unit `%s' requires absence and presence of `%s'",
2333 dst->unit_decl->name, unit->name);
2338 (0, "unit `%s' requires absence and presence of `%s'",
2339 dst->unit_decl->name, unit->name);
2343 for (prev_el = (presence_p
2345 ? dst->unit_decl->final_presence_list
2346 : dst->unit_decl->final_presence_list)
2348 ? dst->unit_decl->final_absence_list
2349 : dst->unit_decl->absence_list));
2350 prev_el != NULL && prev_el->next_pattern_set_el != NULL;
2351 prev_el = prev_el->next_pattern_set_el)
2353 copy = XCOPYNODE (struct pattern_set_el, pat);
2354 copy->next_pattern_set_el = NULL;
2355 if (prev_el == NULL)
2360 dst->unit_decl->final_presence_list = copy;
2362 dst->unit_decl->presence_list = copy;
2365 dst->unit_decl->final_absence_list = copy;
2367 dst->unit_decl->absence_list = copy;
2370 prev_el->next_pattern_set_el = copy;
2377 /* The function inserts BYPASS in the list of bypasses of the
2378 corresponding output insn. The order of bypasses in the list is
2379 decribed in a comment for member `bypass_list' (see above). If
2380 there is already the same bypass in the list the function reports
2381 this and does nothing. */
2383 insert_bypass (struct bypass_decl *bypass)
2385 struct bypass_decl *curr, *last;
2386 struct insn_reserv_decl *out_insn_reserv = bypass->out_insn_reserv;
2387 struct insn_reserv_decl *in_insn_reserv = bypass->in_insn_reserv;
2389 for (curr = out_insn_reserv->bypass_list, last = NULL;
2391 last = curr, curr = curr->next)
2392 if (curr->in_insn_reserv == in_insn_reserv)
2394 if ((bypass->bypass_guard_name != NULL
2395 && curr->bypass_guard_name != NULL
2396 && ! strcmp (bypass->bypass_guard_name, curr->bypass_guard_name))
2397 || bypass->bypass_guard_name == curr->bypass_guard_name)
2399 if (bypass->bypass_guard_name == NULL)
2402 error ("the same bypass `%s - %s' is already defined",
2403 bypass->out_insn_name, bypass->in_insn_name);
2405 warning (0, "the same bypass `%s - %s' is already defined",
2406 bypass->out_insn_name, bypass->in_insn_name);
2409 error ("the same bypass `%s - %s' (guard %s) is already defined",
2410 bypass->out_insn_name, bypass->in_insn_name,
2411 bypass->bypass_guard_name);
2414 (0, "the same bypass `%s - %s' (guard %s) is already defined",
2415 bypass->out_insn_name, bypass->in_insn_name,
2416 bypass->bypass_guard_name);
2419 if (curr->bypass_guard_name == NULL)
2421 if (curr->next == NULL || curr->next->in_insn_reserv != in_insn_reserv)
2430 bypass->next = out_insn_reserv->bypass_list;
2431 out_insn_reserv->bypass_list = bypass;
2435 bypass->next = last->next;
2436 last->next = bypass;
2440 /* The function processes pipeline description declarations, checks
2441 their correctness, and forms exclusion/presence/absence sets. */
2443 process_decls (void)
2446 decl_t automaton_decl;
2447 decl_t decl_in_table;
2448 decl_t out_insn_reserv;
2449 decl_t in_insn_reserv;
2450 int automaton_presence;
2453 /* Checking repeated automata declarations. */
2454 automaton_presence = 0;
2455 for (i = 0; i < description->decls_num; i++)
2457 decl = description->decls [i];
2458 if (decl->mode == dm_automaton)
2460 automaton_presence = 1;
2461 decl_in_table = insert_automaton_decl (decl);
2462 if (decl_in_table != decl)
2465 error ("repeated declaration of automaton `%s'",
2466 DECL_AUTOMATON (decl)->name);
2468 warning (0, "repeated declaration of automaton `%s'",
2469 DECL_AUTOMATON (decl)->name);
2473 /* Checking undeclared automata, repeated declarations (except for
2474 automata) and correctness of their attributes (insn latency times
2476 for (i = 0; i < description->decls_num; i++)
2478 decl = description->decls [i];
2479 if (decl->mode == dm_insn_reserv)
2481 if (DECL_INSN_RESERV (decl)->default_latency < 0)
2482 error ("define_insn_reservation `%s' has negative latency time",
2483 DECL_INSN_RESERV (decl)->name);
2484 DECL_INSN_RESERV (decl)->insn_num = description->insns_num;
2485 description->insns_num++;
2486 decl_in_table = insert_insn_decl (decl);
2487 if (decl_in_table != decl)
2488 error ("`%s' is already used as insn reservation name",
2489 DECL_INSN_RESERV (decl)->name);
2491 else if (decl->mode == dm_bypass)
2493 if (DECL_BYPASS (decl)->latency < 0)
2494 error ("define_bypass `%s - %s' has negative latency time",
2495 DECL_BYPASS (decl)->out_insn_name,
2496 DECL_BYPASS (decl)->in_insn_name);
2498 else if (decl->mode == dm_unit || decl->mode == dm_reserv)
2500 if (decl->mode == dm_unit)
2502 DECL_UNIT (decl)->automaton_decl = NULL;
2503 if (DECL_UNIT (decl)->automaton_name != NULL)
2506 = find_automaton_decl (DECL_UNIT (decl)->automaton_name);
2507 if (automaton_decl == NULL)
2508 error ("automaton `%s' is not declared",
2509 DECL_UNIT (decl)->automaton_name);
2512 DECL_AUTOMATON (automaton_decl)->automaton_is_used = 1;
2513 DECL_UNIT (decl)->automaton_decl
2514 = DECL_AUTOMATON (automaton_decl);
2517 else if (automaton_presence)
2518 error ("define_unit `%s' without automaton when one defined",
2519 DECL_UNIT (decl)->name);
2520 DECL_UNIT (decl)->unit_num = description->units_num;
2521 description->units_num++;
2522 if (strcmp (DECL_UNIT (decl)->name, NOTHING_NAME) == 0)
2524 error ("`%s' is declared as cpu unit", NOTHING_NAME);
2527 decl_in_table = find_decl (DECL_UNIT (decl)->name);
2531 if (strcmp (DECL_RESERV (decl)->name, NOTHING_NAME) == 0)
2533 error ("`%s' is declared as cpu reservation", NOTHING_NAME);
2536 decl_in_table = find_decl (DECL_RESERV (decl)->name);
2538 if (decl_in_table == NULL)
2539 decl_in_table = insert_decl (decl);
2542 if (decl->mode == dm_unit)
2543 error ("repeated declaration of unit `%s'",
2544 DECL_UNIT (decl)->name);
2546 error ("repeated declaration of reservation `%s'",
2547 DECL_RESERV (decl)->name);
2551 /* Check bypasses and form list of bypasses for each (output)
2553 for (i = 0; i < description->decls_num; i++)
2555 decl = description->decls [i];
2556 if (decl->mode == dm_bypass)
2558 out_insn_reserv = find_insn_decl (DECL_BYPASS (decl)->out_insn_name);
2559 in_insn_reserv = find_insn_decl (DECL_BYPASS (decl)->in_insn_name);
2560 if (out_insn_reserv == NULL)
2561 error ("there is no insn reservation `%s'",
2562 DECL_BYPASS (decl)->out_insn_name);
2563 else if (in_insn_reserv == NULL)
2564 error ("there is no insn reservation `%s'",
2565 DECL_BYPASS (decl)->in_insn_name);
2568 DECL_BYPASS (decl)->out_insn_reserv
2569 = DECL_INSN_RESERV (out_insn_reserv);
2570 DECL_BYPASS (decl)->in_insn_reserv
2571 = DECL_INSN_RESERV (in_insn_reserv);
2572 insert_bypass (DECL_BYPASS (decl));
2577 /* Check exclusion set declarations and form exclusion sets. */
2578 for (i = 0; i < description->decls_num; i++)
2580 decl = description->decls [i];
2581 if (decl->mode == dm_excl)
2583 unit_set_el_t unit_set_el_list;
2584 unit_set_el_t unit_set_el_list_2;
2587 = process_excls (DECL_EXCL (decl)->names,
2588 DECL_EXCL (decl)->first_list_length, decl->pos);
2590 = process_excls (&DECL_EXCL (decl)->names
2591 [DECL_EXCL (decl)->first_list_length],
2592 DECL_EXCL (decl)->all_names_num
2593 - DECL_EXCL (decl)->first_list_length,
2595 add_excls (unit_set_el_list, unit_set_el_list_2, decl->pos);
2596 add_excls (unit_set_el_list_2, unit_set_el_list, decl->pos);
2600 /* Check presence set declarations and form presence sets. */
2601 for (i = 0; i < description->decls_num; i++)
2603 decl = description->decls [i];
2604 if (decl->mode == dm_presence)
2606 unit_set_el_t unit_set_el_list;
2607 pattern_set_el_t pattern_set_el_list;
2610 = process_presence_absence_names
2611 (DECL_PRESENCE (decl)->names, DECL_PRESENCE (decl)->names_num,
2612 decl->pos, TRUE, DECL_PRESENCE (decl)->final_p);
2614 = process_presence_absence_patterns
2615 (DECL_PRESENCE (decl)->patterns,
2616 DECL_PRESENCE (decl)->patterns_num,
2617 decl->pos, TRUE, DECL_PRESENCE (decl)->final_p);
2618 add_presence_absence (unit_set_el_list, pattern_set_el_list,
2620 DECL_PRESENCE (decl)->final_p);
2624 /* Check absence set declarations and form absence sets. */
2625 for (i = 0; i < description->decls_num; i++)
2627 decl = description->decls [i];
2628 if (decl->mode == dm_absence)
2630 unit_set_el_t unit_set_el_list;
2631 pattern_set_el_t pattern_set_el_list;
2634 = process_presence_absence_names
2635 (DECL_ABSENCE (decl)->names, DECL_ABSENCE (decl)->names_num,
2636 decl->pos, FALSE, DECL_ABSENCE (decl)->final_p);
2638 = process_presence_absence_patterns
2639 (DECL_ABSENCE (decl)->patterns,
2640 DECL_ABSENCE (decl)->patterns_num,
2641 decl->pos, FALSE, DECL_ABSENCE (decl)->final_p);
2642 add_presence_absence (unit_set_el_list, pattern_set_el_list,
2644 DECL_ABSENCE (decl)->final_p);
2649 /* The following function checks that declared automaton is used. If
2650 the automaton is not used, the function fixes error/warning. The
2651 following function must be called only after `process_decls'. */
2653 check_automaton_usage (void)
2658 for (i = 0; i < description->decls_num; i++)
2660 decl = description->decls [i];
2661 if (decl->mode == dm_automaton
2662 && !DECL_AUTOMATON (decl)->automaton_is_used)
2665 error ("automaton `%s' is not used", DECL_AUTOMATON (decl)->name);
2667 warning (0, "automaton `%s' is not used",
2668 DECL_AUTOMATON (decl)->name);
2673 /* The following recursive function processes all regexp in order to
2674 fix usage of units or reservations and to fix errors of undeclared
2675 name. The function may change unit_regexp onto reserv_regexp.
2676 Remember that reserv_regexp does not exist before the function
2679 process_regexp (regexp_t regexp)
2681 decl_t decl_in_table;
2682 regexp_t new_regexp;
2685 switch (regexp->mode)
2688 decl_in_table = find_decl (REGEXP_UNIT (regexp)->name);
2689 if (decl_in_table == NULL)
2690 error ("undeclared unit or reservation `%s'",
2691 REGEXP_UNIT (regexp)->name);
2693 switch (decl_in_table->mode)
2696 DECL_UNIT (decl_in_table)->unit_is_used = 1;
2697 REGEXP_UNIT (regexp)->unit_decl = DECL_UNIT (decl_in_table);
2701 DECL_RESERV (decl_in_table)->reserv_is_used = 1;
2702 new_regexp = XCREATENODE (struct regexp);
2703 new_regexp->mode = rm_reserv;
2704 new_regexp->pos = regexp->pos;
2705 REGEXP_RESERV (new_regexp)->name = REGEXP_UNIT (regexp)->name;
2706 REGEXP_RESERV (new_regexp)->reserv_decl
2707 = DECL_RESERV (decl_in_table);
2708 regexp = new_regexp;
2716 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
2717 REGEXP_SEQUENCE (regexp)->regexps [i]
2718 = process_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
2721 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
2722 REGEXP_ALLOF (regexp)->regexps [i]
2723 = process_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
2726 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
2727 REGEXP_ONEOF (regexp)->regexps [i]
2728 = process_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
2731 REGEXP_REPEAT (regexp)->regexp
2732 = process_regexp (REGEXP_REPEAT (regexp)->regexp);
2742 /* The following function processes regexp of define_reservation and
2743 define_insn_reservation with the aid of function
2744 `process_regexp'. */
2746 process_regexp_decls (void)
2751 for (i = 0; i < description->decls_num; i++)
2753 decl = description->decls [i];
2754 if (decl->mode == dm_reserv)
2755 DECL_RESERV (decl)->regexp
2756 = process_regexp (DECL_RESERV (decl)->regexp);
2757 else if (decl->mode == dm_insn_reserv)
2758 DECL_INSN_RESERV (decl)->regexp
2759 = process_regexp (DECL_INSN_RESERV (decl)->regexp);
2763 /* The following function checks that declared unit is used. If the
2764 unit is not used, the function fixes errors/warnings. The
2765 following function must be called only after `process_decls',
2766 `process_regexp_decls'. */
2773 for (i = 0; i < description->decls_num; i++)
2775 decl = description->decls [i];
2776 if (decl->mode == dm_unit && !DECL_UNIT (decl)->unit_is_used)
2779 error ("unit `%s' is not used", DECL_UNIT (decl)->name);
2781 warning (0, "unit `%s' is not used", DECL_UNIT (decl)->name);
2783 else if (decl->mode == dm_reserv && !DECL_RESERV (decl)->reserv_is_used)
2786 error ("reservation `%s' is not used", DECL_RESERV (decl)->name);
2788 warning (0, "reservation `%s' is not used", DECL_RESERV (decl)->name);
2793 /* The following variable value is number of reservation being
2794 processed on loop recognition. */
2795 static int curr_loop_pass_num;
2797 /* The following recursive function returns nonzero value if REGEXP
2798 contains given decl or reservations in given regexp refers for
2801 loop_in_regexp (regexp_t regexp, decl_t start_decl)
2807 switch (regexp->mode)
2813 if (start_decl->mode == dm_reserv
2814 && REGEXP_RESERV (regexp)->reserv_decl == DECL_RESERV (start_decl))
2816 else if (REGEXP_RESERV (regexp)->reserv_decl->loop_pass_num
2817 == curr_loop_pass_num)
2818 /* declaration has been processed. */
2822 REGEXP_RESERV (regexp)->reserv_decl->loop_pass_num
2823 = curr_loop_pass_num;
2824 return loop_in_regexp (REGEXP_RESERV (regexp)->reserv_decl->regexp,
2829 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
2830 if (loop_in_regexp (REGEXP_SEQUENCE (regexp)->regexps [i], start_decl))
2835 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
2836 if (loop_in_regexp (REGEXP_ALLOF (regexp)->regexps [i], start_decl))
2841 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
2842 if (loop_in_regexp (REGEXP_ONEOF (regexp)->regexps [i], start_decl))
2847 return loop_in_regexp (REGEXP_REPEAT (regexp)->regexp, start_decl);
2857 /* The following function fixes errors "cycle in definition ...". The
2858 function uses function `loop_in_regexp' for that. */
2860 check_loops_in_regexps (void)
2865 for (i = 0; i < description->decls_num; i++)
2867 decl = description->decls [i];
2868 if (decl->mode == dm_reserv)
2869 DECL_RESERV (decl)->loop_pass_num = 0;
2871 for (i = 0; i < description->decls_num; i++)
2873 decl = description->decls [i];
2874 curr_loop_pass_num = i;
2876 if (decl->mode == dm_reserv)
2878 DECL_RESERV (decl)->loop_pass_num = curr_loop_pass_num;
2879 if (loop_in_regexp (DECL_RESERV (decl)->regexp, decl))
2881 gcc_assert (DECL_RESERV (decl)->regexp);
2882 error ("cycle in definition of reservation `%s'",
2883 DECL_RESERV (decl)->name);
2889 /* The function recursively processes IR of reservation and defines
2890 max and min cycle for reservation of unit. */
2892 process_regexp_cycles (regexp_t regexp, int max_start_cycle,
2893 int min_start_cycle, int *max_finish_cycle,
2894 int *min_finish_cycle)
2898 switch (regexp->mode)
2901 if (REGEXP_UNIT (regexp)->unit_decl->max_occ_cycle_num < max_start_cycle)
2902 REGEXP_UNIT (regexp)->unit_decl->max_occ_cycle_num = max_start_cycle;
2903 if (REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num > min_start_cycle
2904 || REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num == -1)
2905 REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num = min_start_cycle;
2906 *max_finish_cycle = max_start_cycle;
2907 *min_finish_cycle = min_start_cycle;
2911 process_regexp_cycles (REGEXP_RESERV (regexp)->reserv_decl->regexp,
2912 max_start_cycle, min_start_cycle,
2913 max_finish_cycle, min_finish_cycle);
2917 for (i = 0; i < REGEXP_REPEAT (regexp)->repeat_num; i++)
2919 process_regexp_cycles (REGEXP_REPEAT (regexp)->regexp,
2920 max_start_cycle, min_start_cycle,
2921 max_finish_cycle, min_finish_cycle);
2922 max_start_cycle = *max_finish_cycle + 1;
2923 min_start_cycle = *min_finish_cycle + 1;
2928 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
2930 process_regexp_cycles (REGEXP_SEQUENCE (regexp)->regexps [i],
2931 max_start_cycle, min_start_cycle,
2932 max_finish_cycle, min_finish_cycle);
2933 max_start_cycle = *max_finish_cycle + 1;
2934 min_start_cycle = *min_finish_cycle + 1;
2943 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
2945 process_regexp_cycles (REGEXP_ALLOF (regexp)->regexps [i],
2946 max_start_cycle, min_start_cycle,
2947 max_finish_cycle, min_finish_cycle);
2948 if (max_cycle < *max_finish_cycle)
2949 max_cycle = *max_finish_cycle;
2950 if (i == 0 || min_cycle > *min_finish_cycle)
2951 min_cycle = *min_finish_cycle;
2953 *max_finish_cycle = max_cycle;
2954 *min_finish_cycle = min_cycle;
2963 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
2965 process_regexp_cycles (REGEXP_ONEOF (regexp)->regexps [i],
2966 max_start_cycle, min_start_cycle,
2967 max_finish_cycle, min_finish_cycle);
2968 if (max_cycle < *max_finish_cycle)
2969 max_cycle = *max_finish_cycle;
2970 if (i == 0 || min_cycle > *min_finish_cycle)
2971 min_cycle = *min_finish_cycle;
2973 *max_finish_cycle = max_cycle;
2974 *min_finish_cycle = min_cycle;
2979 *max_finish_cycle = max_start_cycle;
2980 *min_finish_cycle = min_start_cycle;
2988 /* The following function is called only for correct program. The
2989 function defines max reservation of insns in cycles. */
2991 evaluate_max_reserv_cycles (void)
2993 int max_insn_cycles_num;
2994 int min_insn_cycles_num;
2998 description->max_insn_reserv_cycles = 0;
2999 for (i = 0; i < description->decls_num; i++)
3001 decl = description->decls [i];
3002 if (decl->mode == dm_insn_reserv)
3004 process_regexp_cycles (DECL_INSN_RESERV (decl)->regexp, 0, 0,
3005 &max_insn_cycles_num, &min_insn_cycles_num);
3006 if (description->max_insn_reserv_cycles < max_insn_cycles_num)
3007 description->max_insn_reserv_cycles = max_insn_cycles_num;
3010 description->max_insn_reserv_cycles++;
3013 /* The following function calls functions for checking all
3016 check_all_description (void)
3019 check_automaton_usage ();
3020 process_regexp_decls ();
3022 check_loops_in_regexps ();
3024 evaluate_max_reserv_cycles ();
3029 /* The page contains abstract data `ticker'. This data is used to
3030 report time of different phases of building automata. It is
3031 possibly to write a description for which automata will be built
3032 during several minutes even on fast machine. */
3034 /* The following function creates ticker and makes it active. */
3036 create_ticker (void)
3040 ticker.modified_creation_time = get_run_time ();
3041 ticker.incremented_off_time = 0;
3045 /* The following function switches off given ticker. */
3047 ticker_off (ticker_t *ticker)
3049 if (ticker->incremented_off_time == 0)
3050 ticker->incremented_off_time = get_run_time () + 1;
3053 /* The following function switches on given ticker. */
3055 ticker_on (ticker_t *ticker)
3057 if (ticker->incremented_off_time != 0)
3059 ticker->modified_creation_time
3060 += get_run_time () - ticker->incremented_off_time + 1;
3061 ticker->incremented_off_time = 0;
3065 /* The following function returns current time in milliseconds since
3066 the moment when given ticker was created. */
3068 active_time (ticker_t ticker)
3070 if (ticker.incremented_off_time != 0)
3071 return ticker.incremented_off_time - 1 - ticker.modified_creation_time;
3073 return get_run_time () - ticker.modified_creation_time;
3076 /* The following function returns string representation of active time
3077 of given ticker. The result is string representation of seconds
3078 with accuracy of 1/100 second. Only result of the last call of the
3079 function exists. Therefore the following code is not correct
3081 printf ("parser time: %s\ngeneration time: %s\n",
3082 active_time_string (parser_ticker),
3083 active_time_string (generation_ticker));
3085 Correct code has to be the following
3087 printf ("parser time: %s\n", active_time_string (parser_ticker));
3088 printf ("generation time: %s\n",
3089 active_time_string (generation_ticker));
3093 print_active_time (FILE *f, ticker_t ticker)
3097 msecs = active_time (ticker);
3098 fprintf (f, "%d.%06d", msecs / 1000000, msecs % 1000000);
3103 /* The following variable value is number of automaton which are
3104 really being created. This value is defined on the base of
3105 argument of option `-split'. If the variable has zero value the
3106 number of automata is defined by the constructions `%automaton'.
3107 This case occurs when option `-split' is absent or has zero
3108 argument. If constructions `define_automaton' is absent only one
3109 automaton is created. */
3110 static int automata_num;
3112 /* The following variable values are times of
3113 o transformation of regular expressions
3114 o building NDFA (DFA if !ndfa_flag)
3115 o NDFA -> DFA (simply the same automaton if !ndfa_flag)
3117 o building insn equivalence classes
3120 static ticker_t transform_time;
3121 static ticker_t NDFA_time;
3122 static ticker_t NDFA_to_DFA_time;
3123 static ticker_t minimize_time;
3124 static ticker_t equiv_time;
3125 static ticker_t automaton_generation_time;
3126 static ticker_t output_time;
3128 /* The following variable values are times of
3131 all pipeline hazard translator work */
3132 static ticker_t check_time;
3133 static ticker_t generation_time;
3134 static ticker_t all_time;
3138 /* Pseudo insn decl which denotes advancing cycle. */
3139 static decl_t advance_cycle_insn_decl;
3141 add_advance_cycle_insn_decl (void)
3143 advance_cycle_insn_decl = XCREATENODE (struct decl);
3144 advance_cycle_insn_decl->mode = dm_insn_reserv;
3145 advance_cycle_insn_decl->pos = no_pos;
3146 DECL_INSN_RESERV (advance_cycle_insn_decl)->regexp = NULL;
3147 DECL_INSN_RESERV (advance_cycle_insn_decl)->name = "$advance_cycle";
3148 DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num
3149 = description->insns_num;
3150 description->decls [description->decls_num] = advance_cycle_insn_decl;
3151 description->decls_num++;
3152 description->insns_num++;
3156 /* Abstract data `alternative states' which represents
3157 nondeterministic nature of the description (see comments for
3158 structures alt_state and state). */
3160 /* List of free states. */
3161 static alt_state_t first_free_alt_state;
3164 /* The following variables is maximal number of allocated nodes
3166 static int allocated_alt_states_num = 0;
3169 /* The following function returns free node alt_state. It may be new
3170 allocated node or node freed earlier. */
3172 get_free_alt_state (void)
3176 if (first_free_alt_state != NULL)
3178 result = first_free_alt_state;
3179 first_free_alt_state = first_free_alt_state->next_alt_state;
3184 allocated_alt_states_num++;
3186 result = XCREATENODE (struct alt_state);
3188 result->state = NULL;
3189 result->next_alt_state = NULL;
3190 result->next_sorted_alt_state = NULL;
3194 /* The function frees node ALT_STATE. */
3196 free_alt_state (alt_state_t alt_state)
3198 if (alt_state == NULL)
3200 alt_state->next_alt_state = first_free_alt_state;
3201 first_free_alt_state = alt_state;
3204 /* The function frees list started with node ALT_STATE_LIST. */
3206 free_alt_states (alt_state_t alt_states_list)
3208 alt_state_t curr_alt_state;
3209 alt_state_t next_alt_state;
3211 for (curr_alt_state = alt_states_list;
3212 curr_alt_state != NULL;
3213 curr_alt_state = next_alt_state)
3215 next_alt_state = curr_alt_state->next_alt_state;
3216 free_alt_state (curr_alt_state);
3220 /* The function compares unique numbers of alt states. */
3222 alt_state_cmp (const void *alt_state_ptr_1, const void *alt_state_ptr_2)
3224 if ((*(const alt_state_t *) alt_state_ptr_1)->state->unique_num
3225 == (*(const alt_state_t *) alt_state_ptr_2)->state->unique_num)
3227 else if ((*(const alt_state_t *) alt_state_ptr_1)->state->unique_num
3228 < (*(const alt_state_t *) alt_state_ptr_2)->state->unique_num)
3234 /* The function sorts ALT_STATES_LIST and removes duplicated alt
3235 states from the list. The comparison key is alt state unique
3239 uniq_sort_alt_states (alt_state_t alt_states_list)
3241 alt_state_t curr_alt_state;
3242 VEC(alt_state_t, heap) *alt_states;
3244 size_t prev_unique_state_ind;
3247 if (alt_states_list == 0)
3249 if (alt_states_list->next_alt_state == 0)
3250 return alt_states_list;
3252 alt_states = VEC_alloc (alt_state_t, heap, 150);
3253 for (curr_alt_state = alt_states_list;
3254 curr_alt_state != NULL;
3255 curr_alt_state = curr_alt_state->next_alt_state)
3256 VEC_safe_push (alt_state_t, heap, alt_states, curr_alt_state);
3258 qsort (VEC_address (alt_state_t, alt_states),
3259 VEC_length (alt_state_t, alt_states),
3260 sizeof (alt_state_t), alt_state_cmp);
3262 prev_unique_state_ind = 0;
3263 for (i = 1; i < VEC_length (alt_state_t, alt_states); i++)
3264 if (VEC_index (alt_state_t, alt_states, prev_unique_state_ind)->state
3265 != VEC_index (alt_state_t, alt_states, i)->state)
3267 prev_unique_state_ind++;
3268 VEC_replace (alt_state_t, alt_states, prev_unique_state_ind,
3269 VEC_index (alt_state_t, alt_states, i));
3271 VEC_truncate (alt_state_t, alt_states, prev_unique_state_ind + 1);
3273 for (i = 1; i < VEC_length (alt_state_t, alt_states); i++)
3274 VEC_index (alt_state_t, alt_states, i-1)->next_sorted_alt_state
3275 = VEC_index (alt_state_t, alt_states, i);
3276 VEC_last (alt_state_t, alt_states)->next_sorted_alt_state = 0;
3278 result = VEC_index (alt_state_t, alt_states, 0);
3280 VEC_free (alt_state_t, heap, alt_states);
3284 /* The function checks equality of alt state lists. Remember that the
3285 lists must be already sorted by the previous function. */
3287 alt_states_eq (alt_state_t alt_states_1, alt_state_t alt_states_2)
3289 while (alt_states_1 != NULL && alt_states_2 != NULL
3290 && alt_state_cmp (&alt_states_1, &alt_states_2) == 0)
3292 alt_states_1 = alt_states_1->next_sorted_alt_state;
3293 alt_states_2 = alt_states_2->next_sorted_alt_state;
3295 return alt_states_1 == alt_states_2;
3298 /* Initialization of the abstract data. */
3300 initiate_alt_states (void)
3302 first_free_alt_state = NULL;
3305 /* Finishing work with the abstract data. */
3307 finish_alt_states (void)
3313 /* The page contains macros for work with bits strings. We could use
3314 standard gcc bitmap or sbitmap but it would result in difficulties
3315 of building canadian cross. */
3317 /* Set bit number bitno in the bit string. The macro is not side
3319 #define SET_BIT(bitstring, bitno) \
3320 (((char *) (bitstring)) [(bitno) / CHAR_BIT] |= 1 << (bitno) % CHAR_BIT)
3322 #define CLEAR_BIT(bitstring, bitno) \
3323 (((char *) (bitstring)) [(bitno) / CHAR_BIT] &= ~(1 << (bitno) % CHAR_BIT))
3325 /* Test if bit number bitno in the bitstring is set. The macro is not
3326 side effect proof. */
3327 #define TEST_BIT(bitstring, bitno) \
3328 (((char *) (bitstring)) [(bitno) / CHAR_BIT] >> (bitno) % CHAR_BIT & 1)
3332 /* This page contains abstract data `state'. */
3334 /* Maximal length of reservations in cycles (>= 1). */
3335 static int max_cycles_num;
3337 /* Number of set elements (see type set_el_t) needed for
3338 representation of one cycle reservation. It is depended on units
3340 static int els_in_cycle_reserv;
3342 /* Number of set elements (see type set_el_t) needed for
3343 representation of maximal length reservation. Deterministic
3344 reservation is stored as set (bit string) of length equal to the
3345 variable value * number of bits in set_el_t. */
3346 static int els_in_reservs;
3348 /* Array of pointers to unit declarations. */
3349 static unit_decl_t *units_array;
3351 /* Temporary reservation of maximal length. */
3352 static reserv_sets_t temp_reserv;
3354 /* The state table itself is represented by the following variable. */
3355 static htab_t state_table;
3357 /* Linked list of free 'state' structures to be recycled. The
3358 next_equiv_class_state pointer is borrowed for a free list. */
3359 static state_t first_free_state;
3361 static int curr_unique_state_num;
3364 /* The following variables is maximal number of allocated nodes
3366 static int allocated_states_num = 0;
3369 /* Allocate new reservation set. */
3370 static reserv_sets_t
3371 alloc_empty_reserv_sets (void)
3373 reserv_sets_t result;
3375 obstack_blank (&irp, els_in_reservs * sizeof (set_el_t));
3376 result = (reserv_sets_t) obstack_base (&irp);
3377 obstack_finish (&irp);
3378 memset (result, 0, els_in_reservs * sizeof (set_el_t));
3382 /* Hash value of reservation set. */
3384 reserv_sets_hash_value (reserv_sets_t reservs)
3386 set_el_t hash_value;
3389 set_el_t *reserv_ptr;
3392 reservs_num = els_in_reservs;
3393 reserv_ptr = reservs;
3395 while (reservs_num != 0)
3398 hash_value += ((*reserv_ptr >> i)
3399 | (*reserv_ptr << (sizeof (set_el_t) * CHAR_BIT - i)));
3401 if (i == sizeof (set_el_t) * CHAR_BIT)
3405 if (sizeof (set_el_t) <= sizeof (unsigned))
3408 for (i = sizeof (set_el_t); i > 0; i -= sizeof (unsigned) - 1)
3410 result += (unsigned) hash_value;
3411 hash_value >>= (sizeof (unsigned) - 1) * CHAR_BIT;
3416 /* Comparison of given reservation sets. */
3418 reserv_sets_cmp (const_reserv_sets_t reservs_1, const_reserv_sets_t reservs_2)
3421 const set_el_t *reserv_ptr_1;
3422 const set_el_t *reserv_ptr_2;
3424 gcc_assert (reservs_1 && reservs_2);
3425 reservs_num = els_in_reservs;
3426 reserv_ptr_1 = reservs_1;
3427 reserv_ptr_2 = reservs_2;
3428 while (reservs_num != 0 && *reserv_ptr_1 == *reserv_ptr_2)
3434 if (reservs_num == 0)
3436 else if (*reserv_ptr_1 < *reserv_ptr_2)
3442 /* The function checks equality of the reservation sets. */
3444 reserv_sets_eq (const_reserv_sets_t reservs_1, const_reserv_sets_t reservs_2)
3446 return reserv_sets_cmp (reservs_1, reservs_2) == 0;
3449 /* Set up in the reservation set that unit with UNIT_NUM is used on
3452 set_unit_reserv (reserv_sets_t reservs, int cycle_num, int unit_num)
3454 gcc_assert (cycle_num < max_cycles_num);
3455 SET_BIT (reservs, cycle_num * els_in_cycle_reserv
3456 * sizeof (set_el_t) * CHAR_BIT + unit_num);
3459 /* Set up in the reservation set RESERVS that unit with UNIT_NUM is
3460 used on CYCLE_NUM. */
3462 test_unit_reserv (reserv_sets_t reservs, int cycle_num, int unit_num)
3464 gcc_assert (cycle_num < max_cycles_num);
3465 return TEST_BIT (reservs, cycle_num * els_in_cycle_reserv
3466 * sizeof (set_el_t) * CHAR_BIT + unit_num);
3469 /* The function checks that the reservation sets are intersected,
3470 i.e. there is a unit reservation on a cycle in both reservation
3473 reserv_sets_are_intersected (reserv_sets_t operand_1,
3474 reserv_sets_t operand_2)
3478 set_el_t *cycle_ptr_1;
3479 set_el_t *cycle_ptr_2;
3481 gcc_assert (operand_1 && operand_2);
3482 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2;
3483 el_ptr_1 < operand_1 + els_in_reservs;
3484 el_ptr_1++, el_ptr_2++)
3485 if (*el_ptr_1 & *el_ptr_2)
3487 reserv_sets_or (temp_reserv, operand_1, operand_2);
3488 for (cycle_ptr_1 = operand_1, cycle_ptr_2 = operand_2;
3489 cycle_ptr_1 < operand_1 + els_in_reservs;
3490 cycle_ptr_1 += els_in_cycle_reserv, cycle_ptr_2 += els_in_cycle_reserv)
3492 for (el_ptr_1 = cycle_ptr_1, el_ptr_2 = get_excl_set (cycle_ptr_2);
3493 el_ptr_1 < cycle_ptr_1 + els_in_cycle_reserv;
3494 el_ptr_1++, el_ptr_2++)
3495 if (*el_ptr_1 & *el_ptr_2)
3497 if (!check_presence_pattern_sets (cycle_ptr_1, cycle_ptr_2, FALSE))
3499 if (!check_presence_pattern_sets (temp_reserv + (cycle_ptr_2
3503 if (!check_absence_pattern_sets (cycle_ptr_1, cycle_ptr_2, FALSE))
3505 if (!check_absence_pattern_sets (temp_reserv + (cycle_ptr_2 - operand_2),
3512 /* The function sets up RESULT bits by bits of OPERAND shifted on one
3513 cpu cycle. The remaining bits of OPERAND (representing the last
3514 cycle unit reservations) are not changed. */
3516 reserv_sets_shift (reserv_sets_t result, reserv_sets_t operand)
3520 gcc_assert (result && operand && result != operand);
3521 for (i = els_in_cycle_reserv; i < els_in_reservs; i++)
3522 result [i - els_in_cycle_reserv] = operand [i];
3525 /* OR of the reservation sets. */
3527 reserv_sets_or (reserv_sets_t result, reserv_sets_t operand_1,
3528 reserv_sets_t operand_2)
3532 set_el_t *result_set_el_ptr;
3534 gcc_assert (result && operand_1 && operand_2);
3535 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2, result_set_el_ptr = result;
3536 el_ptr_1 < operand_1 + els_in_reservs;
3537 el_ptr_1++, el_ptr_2++, result_set_el_ptr++)
3538 *result_set_el_ptr = *el_ptr_1 | *el_ptr_2;
3541 /* AND of the reservation sets. */
3543 reserv_sets_and (reserv_sets_t result, reserv_sets_t operand_1,
3544 reserv_sets_t operand_2)
3548 set_el_t *result_set_el_ptr;
3550 gcc_assert (result && operand_1 && operand_2);
3551 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2, result_set_el_ptr = result;
3552 el_ptr_1 < operand_1 + els_in_reservs;
3553 el_ptr_1++, el_ptr_2++, result_set_el_ptr++)
3554 *result_set_el_ptr = *el_ptr_1 & *el_ptr_2;
3557 /* The function outputs string representation of units reservation on
3558 cycle START_CYCLE in the reservation set. The function uses repeat
3559 construction if REPETITION_NUM > 1. */
3561 output_cycle_reservs (FILE *f, reserv_sets_t reservs, int start_cycle,
3565 int reserved_units_num;
3567 reserved_units_num = 0;
3568 for (unit_num = 0; unit_num < description->units_num; unit_num++)
3569 if (TEST_BIT (reservs, start_cycle * els_in_cycle_reserv
3570 * sizeof (set_el_t) * CHAR_BIT + unit_num))
3571 reserved_units_num++;
3572 gcc_assert (repetition_num > 0);
3573 if (repetition_num != 1 && reserved_units_num > 1)
3575 reserved_units_num = 0;
3577 unit_num < description->units_num;
3579 if (TEST_BIT (reservs, start_cycle * els_in_cycle_reserv
3580 * sizeof (set_el_t) * CHAR_BIT + unit_num))
3582 if (reserved_units_num != 0)
3584 reserved_units_num++;
3585 fprintf (f, "%s", units_array [unit_num]->name);
3587 if (reserved_units_num == 0)
3588 fprintf (f, NOTHING_NAME);
3589 gcc_assert (repetition_num > 0);
3590 if (repetition_num != 1 && reserved_units_num > 1)
3592 if (repetition_num != 1)
3593 fprintf (f, "*%d", repetition_num);
3596 /* The function outputs string representation of units reservation in
3597 the reservation set. */
3599 output_reserv_sets (FILE *f, reserv_sets_t reservs)
3601 int start_cycle = 0;
3606 for (cycle = 0; cycle < max_cycles_num; cycle++)
3607 if (repetition_num == 0)
3610 start_cycle = cycle;
3613 ((char *) reservs + start_cycle * els_in_cycle_reserv
3614 * sizeof (set_el_t),
3615 (char *) reservs + cycle * els_in_cycle_reserv
3616 * sizeof (set_el_t),
3617 els_in_cycle_reserv * sizeof (set_el_t)) == 0)
3621 if (start_cycle != 0)
3623 output_cycle_reservs (f, reservs, start_cycle, repetition_num);
3625 start_cycle = cycle;
3627 if (start_cycle < max_cycles_num)
3629 if (start_cycle != 0)
3631 output_cycle_reservs (f, reservs, start_cycle, repetition_num);
3635 /* The following function returns free node state for AUTOMATON. It
3636 may be new allocated node or node freed earlier. The function also
3637 allocates reservation set if WITH_RESERVS has nonzero value. */
3639 get_free_state (int with_reservs, automaton_t automaton)
3643 gcc_assert (max_cycles_num > 0 && automaton);
3644 if (first_free_state)
3646 result = first_free_state;
3647 first_free_state = result->next_equiv_class_state;
3649 result->next_equiv_class_state = NULL;
3650 result->automaton = automaton;
3651 result->first_out_arc = NULL;
3652 result->it_was_placed_in_stack_for_NDFA_forming = 0;
3653 result->it_was_placed_in_stack_for_DFA_forming = 0;
3654 result->component_states = NULL;
3659 allocated_states_num++;
3661 result = XCREATENODE (struct state);
3662 result->automaton = automaton;
3663 result->first_out_arc = NULL;
3664 result->unique_num = curr_unique_state_num;
3665 curr_unique_state_num++;
3669 if (result->reservs == NULL)
3670 result->reservs = alloc_empty_reserv_sets ();
3672 memset (result->reservs, 0, els_in_reservs * sizeof (set_el_t));
3677 /* The function frees node STATE. */
3679 free_state (state_t state)
3681 free_alt_states (state->component_states);
3682 state->next_equiv_class_state = first_free_state;
3683 first_free_state = state;
3686 /* Hash value of STATE. If STATE represents deterministic state it is
3687 simply hash value of the corresponding reservation set. Otherwise
3688 it is formed from hash values of the component deterministic
3689 states. One more key is order number of state automaton. */
3691 state_hash (const void *state)
3693 unsigned int hash_value;
3694 alt_state_t alt_state;
3696 if (((const_state_t) state)->component_states == NULL)
3697 hash_value = reserv_sets_hash_value (((const_state_t) state)->reservs);
3701 for (alt_state = ((const_state_t) state)->component_states;
3703 alt_state = alt_state->next_sorted_alt_state)
3704 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
3705 | (hash_value << CHAR_BIT))
3706 + alt_state->state->unique_num);
3708 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
3709 | (hash_value << CHAR_BIT))
3710 + ((const_state_t) state)->automaton->automaton_order_num);
3714 /* Return nonzero value if the states are the same. */
3716 state_eq_p (const void *state_1, const void *state_2)
3718 alt_state_t alt_state_1;
3719 alt_state_t alt_state_2;
3721 if (((const_state_t) state_1)->automaton != ((const_state_t) state_2)->automaton)
3723 else if (((const_state_t) state_1)->component_states == NULL
3724 && ((const_state_t) state_2)->component_states == NULL)
3725 return reserv_sets_eq (((const_state_t) state_1)->reservs,
3726 ((const_state_t) state_2)->reservs);
3727 else if (((const_state_t) state_1)->component_states != NULL
3728 && ((const_state_t) state_2)->component_states != NULL)
3730 for (alt_state_1 = ((const_state_t) state_1)->component_states,
3731 alt_state_2 = ((const_state_t) state_2)->component_states;
3732 alt_state_1 != NULL && alt_state_2 != NULL;
3733 alt_state_1 = alt_state_1->next_sorted_alt_state,
3734 alt_state_2 = alt_state_2->next_sorted_alt_state)
3735 /* All state in the list must be already in the hash table.
3736 Also the lists must be sorted. */
3737 if (alt_state_1->state != alt_state_2->state)
3739 return alt_state_1 == alt_state_2;
3745 /* Insert STATE into the state table. */
3747 insert_state (state_t state)
3751 entry_ptr = htab_find_slot (state_table, (void *) state, 1);
3752 if (*entry_ptr == NULL)
3753 *entry_ptr = (void *) state;
3754 return (state_t) *entry_ptr;
3757 /* Add reservation of unit with UNIT_NUM on cycle CYCLE_NUM to
3758 deterministic STATE. */
3760 set_state_reserv (state_t state, int cycle_num, int unit_num)
3762 set_unit_reserv (state->reservs, cycle_num, unit_num);
3765 /* Return nonzero value if the deterministic states contains a
3766 reservation of the same cpu unit on the same cpu cycle. */
3768 intersected_state_reservs_p (state_t state1, state_t state2)
3770 gcc_assert (state1->automaton == state2->automaton);
3771 return reserv_sets_are_intersected (state1->reservs, state2->reservs);
3774 /* Return deterministic state (inserted into the table) which
3775 representing the automaton state which is union of reservations of
3776 the deterministic states masked by RESERVS. */
3778 states_union (state_t state1, state_t state2, reserv_sets_t reservs)
3781 state_t state_in_table;
3783 gcc_assert (state1->automaton == state2->automaton);
3784 result = get_free_state (1, state1->automaton);
3785 reserv_sets_or (result->reservs, state1->reservs, state2->reservs);
3786 reserv_sets_and (result->reservs, result->reservs, reservs);
3787 state_in_table = insert_state (result);
3788 if (result != state_in_table)
3790 free_state (result);
3791 result = state_in_table;
3796 /* Return deterministic state (inserted into the table) which
3797 represent the automaton state is obtained from deterministic STATE
3798 by advancing cpu cycle and masking by RESERVS. */
3800 state_shift (state_t state, reserv_sets_t reservs)
3803 state_t state_in_table;
3805 result = get_free_state (1, state->automaton);
3806 reserv_sets_shift (result->reservs, state->reservs);
3807 reserv_sets_and (result->reservs, result->reservs, reservs);
3808 state_in_table = insert_state (result);
3809 if (result != state_in_table)
3811 free_state (result);
3812 result = state_in_table;
3817 /* Initialization of the abstract data. */
3819 initiate_states (void)
3824 if (description->units_num)
3825 units_array = XNEWVEC (unit_decl_t, description->units_num);
3829 for (i = 0; i < description->decls_num; i++)
3831 decl = description->decls [i];
3832 if (decl->mode == dm_unit)
3833 units_array [DECL_UNIT (decl)->unit_num] = DECL_UNIT (decl);
3835 max_cycles_num = description->max_insn_reserv_cycles;
3837 = ((description->units_num + sizeof (set_el_t) * CHAR_BIT - 1)
3838 / (sizeof (set_el_t) * CHAR_BIT));
3839 els_in_reservs = els_in_cycle_reserv * max_cycles_num;
3840 curr_unique_state_num = 0;
3841 initiate_alt_states ();
3842 state_table = htab_create (1500, state_hash, state_eq_p, (htab_del) 0);
3843 temp_reserv = alloc_empty_reserv_sets ();
3846 /* Finishing work with the abstract data. */
3848 finish_states (void)
3852 htab_delete (state_table);
3853 first_free_state = NULL;
3854 finish_alt_states ();
3859 /* Abstract data `arcs'. */
3861 /* List of free arcs. */
3862 static arc_t first_free_arc;
3865 /* The following variables is maximal number of allocated nodes
3867 static int allocated_arcs_num = 0;
3870 /* The function frees node ARC. */
3872 free_arc (arc_t arc)
3874 arc->next_out_arc = first_free_arc;
3875 first_free_arc = arc;
3878 /* The function removes and frees ARC staring from FROM_STATE. */
3880 remove_arc (state_t from_state, arc_t arc)
3886 for (prev_arc = NULL, curr_arc = from_state->first_out_arc;
3888 prev_arc = curr_arc, curr_arc = curr_arc->next_out_arc)
3889 if (curr_arc == arc)
3891 gcc_assert (curr_arc);
3892 if (prev_arc == NULL)
3893 from_state->first_out_arc = arc->next_out_arc;
3895 prev_arc->next_out_arc = arc->next_out_arc;
3896 from_state->num_out_arcs--;
3900 /* The functions returns arc with given characteristics (or NULL if
3901 the arc does not exist). */
3903 find_arc (state_t from_state, state_t to_state, ainsn_t insn)
3907 for (arc = first_out_arc (from_state); arc != NULL; arc = next_out_arc (arc))
3908 if (arc->to_state == to_state && arc->insn == insn)
3913 /* The function adds arc from FROM_STATE to TO_STATE marked by AINSN.
3914 The function returns added arc (or already existing arc). */
3916 add_arc (state_t from_state, state_t to_state, ainsn_t ainsn)
3920 new_arc = find_arc (from_state, to_state, ainsn);
3921 if (new_arc != NULL)
3923 if (first_free_arc == NULL)
3926 allocated_arcs_num++;
3928 new_arc = XCREATENODE (struct arc);
3929 new_arc->to_state = NULL;
3930 new_arc->insn = NULL;
3931 new_arc->next_out_arc = NULL;
3935 new_arc = first_free_arc;
3936 first_free_arc = first_free_arc->next_out_arc;
3938 new_arc->to_state = to_state;
3939 new_arc->insn = ainsn;
3940 ainsn->arc_exists_p = 1;
3941 new_arc->next_out_arc = from_state->first_out_arc;
3942 from_state->first_out_arc = new_arc;
3943 from_state->num_out_arcs++;
3944 new_arc->next_arc_marked_by_insn = NULL;
3948 /* The function returns the first arc starting from STATE. */
3950 first_out_arc (const_state_t state)
3952 return state->first_out_arc;
3955 /* The function returns next out arc after ARC. */
3957 next_out_arc (arc_t arc)
3959 return arc->next_out_arc;
3962 /* Initialization of the abstract data. */
3964 initiate_arcs (void)
3966 first_free_arc = NULL;
3969 /* Finishing work with the abstract data. */
3977 /* Abstract data `automata lists'. */
3979 /* List of free states. */
3980 static automata_list_el_t first_free_automata_list_el;
3982 /* The list being formed. */
3983 static automata_list_el_t current_automata_list;
3985 /* Hash table of automata lists. */
3986 static htab_t automata_list_table;
3988 /* The following function returns free automata list el. It may be
3989 new allocated node or node freed earlier. */
3990 static automata_list_el_t
3991 get_free_automata_list_el (void)
3993 automata_list_el_t result;
3995 if (first_free_automata_list_el != NULL)
3997 result = first_free_automata_list_el;
3998 first_free_automata_list_el
3999 = first_free_automata_list_el->next_automata_list_el;
4002 result = XCREATENODE (struct automata_list_el);
4003 result->automaton = NULL;
4004 result->next_automata_list_el = NULL;
4008 /* The function frees node AUTOMATA_LIST_EL. */
4010 free_automata_list_el (automata_list_el_t automata_list_el)
4012 if (automata_list_el == NULL)
4014 automata_list_el->next_automata_list_el = first_free_automata_list_el;
4015 first_free_automata_list_el = automata_list_el;
4018 /* The function frees list AUTOMATA_LIST. */
4020 free_automata_list (automata_list_el_t automata_list)
4022 automata_list_el_t curr_automata_list_el;
4023 automata_list_el_t next_automata_list_el;
4025 for (curr_automata_list_el = automata_list;
4026 curr_automata_list_el != NULL;
4027 curr_automata_list_el = next_automata_list_el)
4029 next_automata_list_el = curr_automata_list_el->next_automata_list_el;
4030 free_automata_list_el (curr_automata_list_el);
4034 /* Hash value of AUTOMATA_LIST. */
4036 automata_list_hash (const void *automata_list)
4038 unsigned int hash_value;
4039 const_automata_list_el_t curr_automata_list_el;
4042 for (curr_automata_list_el = (const_automata_list_el_t) automata_list;
4043 curr_automata_list_el != NULL;
4044 curr_automata_list_el = curr_automata_list_el->next_automata_list_el)
4045 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
4046 | (hash_value << CHAR_BIT))
4047 + curr_automata_list_el->automaton->automaton_order_num);
4051 /* Return nonzero value if the automata_lists are the same. */
4053 automata_list_eq_p (const void *automata_list_1, const void *automata_list_2)
4055 const_automata_list_el_t automata_list_el_1;
4056 const_automata_list_el_t automata_list_el_2;
4058 for (automata_list_el_1 = (const_automata_list_el_t) automata_list_1,
4059 automata_list_el_2 = (const_automata_list_el_t) automata_list_2;
4060 automata_list_el_1 != NULL && automata_list_el_2 != NULL;
4061 automata_list_el_1 = automata_list_el_1->next_automata_list_el,
4062 automata_list_el_2 = automata_list_el_2->next_automata_list_el)
4063 if (automata_list_el_1->automaton != automata_list_el_2->automaton)
4065 return automata_list_el_1 == automata_list_el_2;
4068 /* Initialization of the abstract data. */
4070 initiate_automata_lists (void)
4072 first_free_automata_list_el = NULL;
4073 automata_list_table = htab_create (1500, automata_list_hash,
4074 automata_list_eq_p, (htab_del) 0);
4077 /* The following function starts new automata list and makes it the
4080 automata_list_start (void)
4082 current_automata_list = NULL;
4085 /* The following function adds AUTOMATON to the current list. */
4087 automata_list_add (automaton_t automaton)
4089 automata_list_el_t el;
4091 el = get_free_automata_list_el ();
4092 el->automaton = automaton;
4093 el->next_automata_list_el = current_automata_list;
4094 current_automata_list = el;
4097 /* The following function finishes forming the current list, inserts
4098 it into the table and returns it. */
4099 static automata_list_el_t
4100 automata_list_finish (void)
4104 if (current_automata_list == NULL)
4106 entry_ptr = htab_find_slot (automata_list_table,
4107 (void *) current_automata_list, 1);
4108 if (*entry_ptr == NULL)
4109 *entry_ptr = (void *) current_automata_list;
4111 free_automata_list (current_automata_list);
4112 current_automata_list = NULL;
4113 return (automata_list_el_t) *entry_ptr;
4116 /* Finishing work with the abstract data. */
4118 finish_automata_lists (void)
4120 htab_delete (automata_list_table);
4125 /* The page contains abstract data for work with exclusion sets (see
4126 exclusion_set in file rtl.def). */
4128 /* The following variable refers to an exclusion set returned by
4129 get_excl_set. This is bit string of length equal to cpu units
4130 number. If exclusion set for given unit contains 1 for a unit,
4131 then simultaneous reservation of the units is prohibited. */
4132 static reserv_sets_t excl_set;
4134 /* The array contains exclusion sets for each unit. */
4135 static reserv_sets_t *unit_excl_set_table;
4137 /* The following function forms the array containing exclusion sets
4140 initiate_excl_sets (void)
4143 reserv_sets_t unit_excl_set;
4147 obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4148 excl_set = (reserv_sets_t) obstack_base (&irp);
4149 obstack_finish (&irp);
4150 obstack_blank (&irp, description->units_num * sizeof (reserv_sets_t));
4151 unit_excl_set_table = (reserv_sets_t *) obstack_base (&irp);
4152 obstack_finish (&irp);
4153 /* Evaluate unit exclusion sets. */
4154 for (i = 0; i < description->decls_num; i++)
4156 decl = description->decls [i];
4157 if (decl->mode == dm_unit)
4159 obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4160 unit_excl_set = (reserv_sets_t) obstack_base (&irp);
4161 obstack_finish (&irp);
4162 memset (unit_excl_set, 0, els_in_cycle_reserv * sizeof (set_el_t));
4163 for (el = DECL_UNIT (decl)->excl_list;
4165 el = el->next_unit_set_el)
4167 SET_BIT (unit_excl_set, el->unit_decl->unit_num);
4168 el->unit_decl->in_set_p = TRUE;
4170 unit_excl_set_table [DECL_UNIT (decl)->unit_num] = unit_excl_set;
4175 /* The function sets up and return EXCL_SET which is union of
4176 exclusion sets for each unit in IN_SET. */
4177 static reserv_sets_t
4178 get_excl_set (reserv_sets_t in_set)
4186 chars_num = els_in_cycle_reserv * sizeof (set_el_t);
4187 memset (excl_set, 0, chars_num);
4188 for (excl_char_num = 0; excl_char_num < chars_num; excl_char_num++)
4189 if (((unsigned char *) in_set) [excl_char_num])
4190 for (i = CHAR_BIT - 1; i >= 0; i--)
4191 if ((((unsigned char *) in_set) [excl_char_num] >> i) & 1)
4193 start_unit_num = excl_char_num * CHAR_BIT + i;
4194 if (start_unit_num >= description->units_num)
4196 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4199 |= unit_excl_set_table [start_unit_num] [unit_num];
4207 /* The page contains abstract data for work with presence/absence
4208 pattern sets (see presence_set/absence_set in file rtl.def). */
4210 /* The following arrays contain correspondingly presence, final
4211 presence, absence, and final absence patterns for each unit. */
4212 static pattern_reserv_t *unit_presence_set_table;
4213 static pattern_reserv_t *unit_final_presence_set_table;
4214 static pattern_reserv_t *unit_absence_set_table;
4215 static pattern_reserv_t *unit_final_absence_set_table;
4217 /* The following function forms list of reservation sets for given
4219 static pattern_reserv_t
4220 form_reserv_sets_list (pattern_set_el_t pattern_list)
4222 pattern_set_el_t el;
4223 pattern_reserv_t first, curr, prev;
4226 prev = first = NULL;
4227 for (el = pattern_list; el != NULL; el = el->next_pattern_set_el)
4229 curr = XCREATENODE (struct pattern_reserv);
4230 curr->reserv = alloc_empty_reserv_sets ();
4231 curr->next_pattern_reserv = NULL;
4232 for (i = 0; i < el->units_num; i++)
4234 SET_BIT (curr->reserv, el->unit_decls [i]->unit_num);
4235 el->unit_decls [i]->in_set_p = TRUE;
4238 prev->next_pattern_reserv = curr;
4246 /* The following function forms the array containing presence and
4247 absence pattern sets for each unit. */
4249 initiate_presence_absence_pattern_sets (void)
4254 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4255 unit_presence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4256 obstack_finish (&irp);
4257 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4258 unit_final_presence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4259 obstack_finish (&irp);
4260 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4261 unit_absence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4262 obstack_finish (&irp);
4263 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4264 unit_final_absence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4265 obstack_finish (&irp);
4266 /* Evaluate unit presence/absence sets. */
4267 for (i = 0; i < description->decls_num; i++)
4269 decl = description->decls [i];
4270 if (decl->mode == dm_unit)
4272 unit_presence_set_table [DECL_UNIT (decl)->unit_num]
4273 = form_reserv_sets_list (DECL_UNIT (decl)->presence_list);
4274 unit_final_presence_set_table [DECL_UNIT (decl)->unit_num]
4275 = form_reserv_sets_list (DECL_UNIT (decl)->final_presence_list);
4276 unit_absence_set_table [DECL_UNIT (decl)->unit_num]
4277 = form_reserv_sets_list (DECL_UNIT (decl)->absence_list);
4278 unit_final_absence_set_table [DECL_UNIT (decl)->unit_num]
4279 = form_reserv_sets_list (DECL_UNIT (decl)->final_absence_list);
4284 /* The function checks that CHECKED_SET satisfies all presence pattern
4285 sets for units in ORIGINAL_SET. The function returns TRUE if it
4288 check_presence_pattern_sets (reserv_sets_t checked_set,
4289 reserv_sets_t original_set,
4298 pattern_reserv_t pat_reserv;
4300 chars_num = els_in_cycle_reserv * sizeof (set_el_t);
4301 for (char_num = 0; char_num < chars_num; char_num++)
4302 if (((unsigned char *) original_set) [char_num])
4303 for (i = CHAR_BIT - 1; i >= 0; i--)
4304 if ((((unsigned char *) original_set) [char_num] >> i) & 1)
4306 start_unit_num = char_num * CHAR_BIT + i;
4307 if (start_unit_num >= description->units_num)
4310 && unit_final_presence_set_table [start_unit_num] == NULL)
4312 && unit_presence_set_table [start_unit_num] == NULL))
4315 for (pat_reserv = (final_p
4316 ? unit_final_presence_set_table [start_unit_num]
4317 : unit_presence_set_table [start_unit_num]);
4319 pat_reserv = pat_reserv->next_pattern_reserv)
4321 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4322 if ((checked_set [unit_num] & pat_reserv->reserv [unit_num])
4323 != pat_reserv->reserv [unit_num])
4325 presence_p = presence_p || unit_num >= els_in_cycle_reserv;
4333 /* The function checks that CHECKED_SET satisfies all absence pattern
4334 sets for units in ORIGINAL_SET. The function returns TRUE if it
4337 check_absence_pattern_sets (reserv_sets_t checked_set,
4338 reserv_sets_t original_set,
4346 pattern_reserv_t pat_reserv;
4348 chars_num = els_in_cycle_reserv * sizeof (set_el_t);
4349 for (char_num = 0; char_num < chars_num; char_num++)
4350 if (((unsigned char *) original_set) [char_num])
4351 for (i = CHAR_BIT - 1; i >= 0; i--)
4352 if ((((unsigned char *) original_set) [char_num] >> i) & 1)
4354 start_unit_num = char_num * CHAR_BIT + i;
4355 if (start_unit_num >= description->units_num)
4357 for (pat_reserv = (final_p
4358 ? unit_final_absence_set_table [start_unit_num]
4359 : unit_absence_set_table [start_unit_num]);
4361 pat_reserv = pat_reserv->next_pattern_reserv)
4363 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4364 if ((checked_set [unit_num] & pat_reserv->reserv [unit_num])
4365 != pat_reserv->reserv [unit_num]
4366 && pat_reserv->reserv [unit_num])
4368 if (unit_num >= els_in_cycle_reserv)
4377 /* This page contains code for transformation of original reservations
4378 described in .md file. The main goal of transformations is
4379 simplifying reservation and lifting up all `|' on the top of IR
4380 reservation representation. */
4383 /* The following function makes copy of IR representation of
4384 reservation. The function also substitutes all reservations
4385 defined by define_reservation by corresponding value during making
4388 copy_insn_regexp (regexp_t regexp)
4393 switch (regexp->mode)
4396 result = copy_insn_regexp (REGEXP_RESERV (regexp)->reserv_decl->regexp);
4400 result = XCOPYNODE (struct regexp, regexp);
4404 result = XCOPYNODE (struct regexp, regexp);
4405 REGEXP_REPEAT (result)->regexp
4406 = copy_insn_regexp (REGEXP_REPEAT (regexp)->regexp);
4410 result = XCOPYNODEVAR (struct regexp, regexp,
4411 sizeof (struct regexp) + sizeof (regexp_t)
4412 * (REGEXP_SEQUENCE (regexp)->regexps_num - 1));
4413 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4414 REGEXP_SEQUENCE (result)->regexps [i]
4415 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4419 result = XCOPYNODEVAR (struct regexp, regexp,
4420 sizeof (struct regexp) + sizeof (regexp_t)
4421 * (REGEXP_ALLOF (regexp)->regexps_num - 1));
4422 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4423 REGEXP_ALLOF (result)->regexps [i]
4424 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4428 result = XCOPYNODEVAR (struct regexp, regexp,
4429 sizeof (struct regexp) + sizeof (regexp_t)
4430 * (REGEXP_ONEOF (regexp)->regexps_num - 1));
4431 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4432 REGEXP_ONEOF (result)->regexps [i]
4433 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4437 result = XCOPYNODE (struct regexp, regexp);
4446 /* The following variable is set up 1 if a transformation has been
4448 static int regexp_transformed_p;
4450 /* The function makes transformation
4453 transform_1 (regexp_t regexp)
4460 if (regexp->mode == rm_repeat)
4462 repeat_num = REGEXP_REPEAT (regexp)->repeat_num;
4463 gcc_assert (repeat_num > 1);
4464 operand = REGEXP_REPEAT (regexp)->regexp;
4466 regexp = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4467 + sizeof (regexp_t) * (repeat_num - 1));
4468 regexp->mode = rm_sequence;
4470 REGEXP_SEQUENCE (regexp)->regexps_num = repeat_num;
4471 for (i = 0; i < repeat_num; i++)
4472 REGEXP_SEQUENCE (regexp)->regexps [i] = copy_insn_regexp (operand);
4473 regexp_transformed_p = 1;
4478 /* The function makes transformations
4479 ...,(A,B,...),C,... -> ...,A,B,...,C,...
4480 ...+(A+B+...)+C+... -> ...+A+B+...+C+...
4481 ...|(A|B|...)|C|... -> ...|A|B|...|C|... */
4483 transform_2 (regexp_t regexp)
4485 if (regexp->mode == rm_sequence)
4487 regexp_t sequence = NULL;
4489 int sequence_index = 0;
4492 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4493 if (REGEXP_SEQUENCE (regexp)->regexps [i]->mode == rm_sequence)
4496 sequence = REGEXP_SEQUENCE (regexp)->regexps [i];
4499 if (i < REGEXP_SEQUENCE (regexp)->regexps_num)
4501 gcc_assert (REGEXP_SEQUENCE (sequence)->regexps_num > 1
4502 && REGEXP_SEQUENCE (regexp)->regexps_num > 1);
4503 result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4505 * (REGEXP_SEQUENCE (regexp)->regexps_num
4506 + REGEXP_SEQUENCE (sequence)->regexps_num
4508 result->mode = rm_sequence;
4509 result->pos = regexp->pos;
4510 REGEXP_SEQUENCE (result)->regexps_num
4511 = (REGEXP_SEQUENCE (regexp)->regexps_num
4512 + REGEXP_SEQUENCE (sequence)->regexps_num - 1);
4513 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4514 if (i < sequence_index)
4515 REGEXP_SEQUENCE (result)->regexps [i]
4516 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4517 else if (i > sequence_index)
4518 REGEXP_SEQUENCE (result)->regexps
4519 [i + REGEXP_SEQUENCE (sequence)->regexps_num - 1]
4520 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4522 for (j = 0; j < REGEXP_SEQUENCE (sequence)->regexps_num; j++)
4523 REGEXP_SEQUENCE (result)->regexps [i + j]
4524 = copy_insn_regexp (REGEXP_SEQUENCE (sequence)->regexps [j]);
4525 regexp_transformed_p = 1;
4529 else if (regexp->mode == rm_allof)
4531 regexp_t allof = NULL;
4533 int allof_index = 0;
4536 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4537 if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_allof)
4540 allof = REGEXP_ALLOF (regexp)->regexps [i];
4543 if (i < REGEXP_ALLOF (regexp)->regexps_num)
4545 gcc_assert (REGEXP_ALLOF (allof)->regexps_num > 1
4546 && REGEXP_ALLOF (regexp)->regexps_num > 1);
4547 result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4549 * (REGEXP_ALLOF (regexp)->regexps_num
4550 + REGEXP_ALLOF (allof)->regexps_num - 2));
4551 result->mode = rm_allof;
4552 result->pos = regexp->pos;
4553 REGEXP_ALLOF (result)->regexps_num
4554 = (REGEXP_ALLOF (regexp)->regexps_num
4555 + REGEXP_ALLOF (allof)->regexps_num - 1);
4556 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4557 if (i < allof_index)
4558 REGEXP_ALLOF (result)->regexps [i]
4559 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4560 else if (i > allof_index)
4561 REGEXP_ALLOF (result)->regexps
4562 [i + REGEXP_ALLOF (allof)->regexps_num - 1]
4563 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4565 for (j = 0; j < REGEXP_ALLOF (allof)->regexps_num; j++)
4566 REGEXP_ALLOF (result)->regexps [i + j]
4567 = copy_insn_regexp (REGEXP_ALLOF (allof)->regexps [j]);
4568 regexp_transformed_p = 1;
4572 else if (regexp->mode == rm_oneof)
4574 regexp_t oneof = NULL;
4576 int oneof_index = 0;
4579 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4580 if (REGEXP_ONEOF (regexp)->regexps [i]->mode == rm_oneof)
4583 oneof = REGEXP_ONEOF (regexp)->regexps [i];
4586 if (i < REGEXP_ONEOF (regexp)->regexps_num)
4588 gcc_assert (REGEXP_ONEOF (oneof)->regexps_num > 1
4589 && REGEXP_ONEOF (regexp)->regexps_num > 1);
4590 result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4592 * (REGEXP_ONEOF (regexp)->regexps_num
4593 + REGEXP_ONEOF (oneof)->regexps_num - 2));
4594 result->mode = rm_oneof;
4595 result->pos = regexp->pos;
4596 REGEXP_ONEOF (result)->regexps_num
4597 = (REGEXP_ONEOF (regexp)->regexps_num
4598 + REGEXP_ONEOF (oneof)->regexps_num - 1);
4599 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4600 if (i < oneof_index)
4601 REGEXP_ONEOF (result)->regexps [i]
4602 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4603 else if (i > oneof_index)
4604 REGEXP_ONEOF (result)->regexps
4605 [i + REGEXP_ONEOF (oneof)->regexps_num - 1]
4606 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4608 for (j = 0; j < REGEXP_ONEOF (oneof)->regexps_num; j++)
4609 REGEXP_ONEOF (result)->regexps [i + j]
4610 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [j]);
4611 regexp_transformed_p = 1;
4618 /* The function makes transformations
4619 ...,A|B|...,C,... -> (...,A,C,...)|(...,B,C,...)|...
4620 ...+(A|B|...)+C+... -> (...+A+C+...)|(...+B+C+...)|...
4621 ...+(A,B,...)+C+... -> (...+A+C+...),B,...
4622 ...+(A,B,...)+(C,D,...) -> (A+C),(B+D),... */
4624 transform_3 (regexp_t regexp)
4626 if (regexp->mode == rm_sequence)
4628 regexp_t oneof = NULL;
4629 int oneof_index = 0;
4634 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4635 if (REGEXP_SEQUENCE (regexp)->regexps [i]->mode == rm_oneof)
4638 oneof = REGEXP_SEQUENCE (regexp)->regexps [i];
4641 if (i < REGEXP_SEQUENCE (regexp)->regexps_num)
4643 gcc_assert (REGEXP_ONEOF (oneof)->regexps_num > 1
4644 && REGEXP_SEQUENCE (regexp)->regexps_num > 1);
4645 result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4647 * (REGEXP_ONEOF (oneof)->regexps_num - 1));
4648 result->mode = rm_oneof;
4649 result->pos = regexp->pos;
4650 REGEXP_ONEOF (result)->regexps_num
4651 = REGEXP_ONEOF (oneof)->regexps_num;
4652 for (i = 0; i < REGEXP_ONEOF (result)->regexps_num; i++)
4655 = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4657 * (REGEXP_SEQUENCE (regexp)->regexps_num - 1));
4658 sequence->mode = rm_sequence;
4659 sequence->pos = regexp->pos;
4660 REGEXP_SEQUENCE (sequence)->regexps_num
4661 = REGEXP_SEQUENCE (regexp)->regexps_num;
4662 REGEXP_ONEOF (result)->regexps [i] = sequence;
4663 for (j = 0; j < REGEXP_SEQUENCE (sequence)->regexps_num; j++)
4664 if (j != oneof_index)
4665 REGEXP_SEQUENCE (sequence)->regexps [j]
4666 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [j]);
4668 REGEXP_SEQUENCE (sequence)->regexps [j]
4669 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [i]);
4671 regexp_transformed_p = 1;
4675 else if (regexp->mode == rm_allof)
4677 regexp_t oneof = NULL;
4679 int oneof_index = 0;
4680 int max_seq_length, allof_length;
4682 regexp_t allof = NULL;
4683 regexp_t allof_op = NULL;
4686 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4687 if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_oneof)
4690 oneof = REGEXP_ALLOF (regexp)->regexps [i];
4693 if (i < REGEXP_ALLOF (regexp)->regexps_num)
4695 gcc_assert (REGEXP_ONEOF (oneof)->regexps_num > 1
4696 && REGEXP_ALLOF (regexp)->regexps_num > 1);
4697 result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4699 * (REGEXP_ONEOF (oneof)->regexps_num - 1));
4700 result->mode = rm_oneof;
4701 result->pos = regexp->pos;
4702 REGEXP_ONEOF (result)->regexps_num
4703 = REGEXP_ONEOF (oneof)->regexps_num;
4704 for (i = 0; i < REGEXP_ONEOF (result)->regexps_num; i++)
4707 = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4709 * (REGEXP_ALLOF (regexp)->regexps_num - 1));
4710 allof->mode = rm_allof;
4711 allof->pos = regexp->pos;
4712 REGEXP_ALLOF (allof)->regexps_num
4713 = REGEXP_ALLOF (regexp)->regexps_num;
4714 REGEXP_ONEOF (result)->regexps [i] = allof;
4715 for (j = 0; j < REGEXP_ALLOF (allof)->regexps_num; j++)
4716 if (j != oneof_index)
4717 REGEXP_ALLOF (allof)->regexps [j]
4718 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [j]);
4720 REGEXP_ALLOF (allof)->regexps [j]
4721 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [i]);
4723 regexp_transformed_p = 1;
4727 if (regexp->mode == rm_allof)
4728 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4730 switch (REGEXP_ALLOF (regexp)->regexps [i]->mode)
4733 seq = REGEXP_ALLOF (regexp)->regexps [i];
4734 if (max_seq_length < REGEXP_SEQUENCE (seq)->regexps_num)
4735 max_seq_length = REGEXP_SEQUENCE (seq)->regexps_num;
4748 if (max_seq_length != 0)
4750 gcc_assert (max_seq_length != 1
4751 && REGEXP_ALLOF (regexp)->regexps_num > 1);
4752 result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4753 + sizeof (regexp_t) * (max_seq_length - 1));
4754 result->mode = rm_sequence;
4755 result->pos = regexp->pos;
4756 REGEXP_SEQUENCE (result)->regexps_num = max_seq_length;
4757 for (i = 0; i < max_seq_length; i++)
4760 for (j = 0; j < REGEXP_ALLOF (regexp)->regexps_num; j++)
4761 switch (REGEXP_ALLOF (regexp)->regexps [j]->mode)
4764 if (i < (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4765 ->regexps [j])->regexps_num))
4768 = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4778 allof_op = REGEXP_ALLOF (regexp)->regexps [j];
4786 if (allof_length == 1)
4787 REGEXP_SEQUENCE (result)->regexps [i] = allof_op;
4790 allof = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4792 * (allof_length - 1));
4793 allof->mode = rm_allof;
4794 allof->pos = regexp->pos;
4795 REGEXP_ALLOF (allof)->regexps_num = allof_length;
4796 REGEXP_SEQUENCE (result)->regexps [i] = allof;
4798 for (j = 0; j < REGEXP_ALLOF (regexp)->regexps_num; j++)
4799 if (REGEXP_ALLOF (regexp)->regexps [j]->mode == rm_sequence
4801 (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4802 ->regexps [j])->regexps_num)))
4804 allof_op = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4807 REGEXP_ALLOF (allof)->regexps [allof_length]
4812 && (REGEXP_ALLOF (regexp)->regexps [j]->mode
4814 || (REGEXP_ALLOF (regexp)->regexps [j]->mode
4817 allof_op = REGEXP_ALLOF (regexp)->regexps [j];
4818 REGEXP_ALLOF (allof)->regexps [allof_length]
4824 regexp_transformed_p = 1;
4831 /* The function traverses IR of reservation and applies transformations
4832 implemented by FUNC. */
4834 regexp_transform_func (regexp_t regexp, regexp_t (*func) (regexp_t regexp))
4838 switch (regexp->mode)
4841 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4842 REGEXP_SEQUENCE (regexp)->regexps [i]
4843 = regexp_transform_func (REGEXP_SEQUENCE (regexp)->regexps [i],
4848 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4849 REGEXP_ALLOF (regexp)->regexps [i]
4850 = regexp_transform_func (REGEXP_ALLOF (regexp)->regexps [i], func);
4854 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4855 REGEXP_ONEOF (regexp)->regexps [i]
4856 = regexp_transform_func (REGEXP_ONEOF (regexp)->regexps [i], func);
4860 REGEXP_REPEAT (regexp)->regexp
4861 = regexp_transform_func (REGEXP_REPEAT (regexp)->regexp, func);
4871 return (*func) (regexp);
4874 /* The function applies all transformations for IR representation of
4875 reservation REGEXP. */
4877 transform_regexp (regexp_t regexp)
4879 regexp = regexp_transform_func (regexp, transform_1);
4882 regexp_transformed_p = 0;
4883 regexp = regexp_transform_func (regexp, transform_2);
4884 regexp = regexp_transform_func (regexp, transform_3);
4886 while (regexp_transformed_p);
4890 /* The function applies all transformations for reservations of all
4891 insn declarations. */
4893 transform_insn_regexps (void)
4898 transform_time = create_ticker ();
4899 add_advance_cycle_insn_decl ();
4901 fprintf (stderr, "Reservation transformation...");
4902 for (i = 0; i < description->decls_num; i++)
4904 decl = description->decls [i];
4905 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
4906 DECL_INSN_RESERV (decl)->transformed_regexp
4907 = transform_regexp (copy_insn_regexp
4908 (DECL_INSN_RESERV (decl)->regexp));
4911 fprintf (stderr, "done\n");
4912 ticker_off (&transform_time);
4917 /* The following variable value is TRUE if the first annotated message
4918 about units to automata distribution has been output. */
4919 static int annotation_message_reported_p;
4921 /* The vector contains all decls which are automata. */
4922 static VEC(decl_t, heap) *automaton_decls;
4924 /* The following structure describes usage of a unit in a reservation. */
4927 unit_decl_t unit_decl;
4928 /* The following forms a list of units used on the same cycle in the
4929 same alternative. The list is ordered by the correspdoning unit
4930 declarations and there is no unit declaration duplication in the
4932 struct unit_usage *next;
4934 typedef struct unit_usage *unit_usage_t;
4936 DEF_VEC_P(unit_usage_t);
4937 DEF_VEC_ALLOC_P(unit_usage_t, heap);
4939 /* Obstack for unit_usage structures. */
4940 static struct obstack unit_usages;
4942 /* VLA for representation of array of pointers to unit usage
4943 structures. There is an element for each combination of
4944 (alternative number, cycle). Unit usages on given cycle in
4945 alternative with given number are referred through element with
4946 index equals to the cycle * number of all alternatives in the
4947 regexp + the alternative number. */
4948 static VEC(unit_usage_t, heap) *cycle_alt_unit_usages;
4950 /* The following function creates the structure unit_usage for UNIT on
4951 CYCLE in REGEXP alternative with ALT_NUM. The structure is made
4952 accessed through cycle_alt_unit_usages. */
4954 store_alt_unit_usage (regexp_t regexp, regexp_t unit, int cycle,
4958 unit_decl_t unit_decl;
4959 unit_usage_t unit_usage_ptr, curr, prev;
4962 gcc_assert (regexp && regexp->mode == rm_oneof
4963 && alt_num < REGEXP_ONEOF (regexp)->regexps_num);
4964 unit_decl = REGEXP_UNIT (unit)->unit_decl;
4966 length = (cycle + 1) * REGEXP_ONEOF (regexp)->regexps_num;
4967 while (VEC_length (unit_usage_t, cycle_alt_unit_usages) < length)
4968 VEC_safe_push (unit_usage_t, heap, cycle_alt_unit_usages, 0);
4970 index = cycle * REGEXP_ONEOF (regexp)->regexps_num + alt_num;
4972 for (curr = VEC_index (unit_usage_t, cycle_alt_unit_usages, index);
4974 prev = curr, curr = curr->next)
4975 if (curr->unit_decl >= unit_decl)
4977 if (curr != NULL && curr->unit_decl == unit_decl)
4979 obstack_blank (&unit_usages, sizeof (struct unit_usage));
4980 unit_usage_ptr = (struct unit_usage *) obstack_base (&unit_usages);
4981 obstack_finish (&unit_usages);
4982 unit_usage_ptr->unit_decl = unit_decl;
4983 unit_decl->last_distribution_check_cycle = -1; /* undefined */
4984 unit_usage_ptr->next = curr;
4986 VEC_replace (unit_usage_t, cycle_alt_unit_usages, index, unit_usage_ptr);
4988 prev->next = unit_usage_ptr;
4991 /* Return true if unit UNIT_DECL is present on the LIST. */
4993 unit_present_on_list_p (unit_usage_t list, unit_decl_t unit_decl)
4995 while (list != NULL)
4997 if (list->unit_decl == unit_decl)
5004 /* The function returns true if reservations of alternatives ALT1 and
5005 ALT2 are equal after excluding reservations of units of
5006 EXCLUDED_AUTOMATON_DECL. */
5008 equal_alternatives_p (int alt1, int alt2, int n_alts,
5009 struct automaton_decl *excluded_automaton_decl)
5012 unit_usage_t list1, list2;
5015 i < (int) VEC_length (unit_usage_t, cycle_alt_unit_usages);
5018 for (list1 = VEC_index (unit_usage_t, cycle_alt_unit_usages, i + alt1),
5019 list2 = VEC_index (unit_usage_t, cycle_alt_unit_usages, i + alt2);;
5020 list1 = list1->next, list2 = list2->next)
5022 while (list1 != NULL
5023 && list1->unit_decl->automaton_decl == excluded_automaton_decl)
5024 list1 = list1->next;
5025 while (list2 != NULL
5026 && list2->unit_decl->automaton_decl == excluded_automaton_decl)
5027 list2 = list2->next;
5028 if (list1 == NULL || list2 == NULL)
5035 if (list1->unit_decl != list2->unit_decl)
5043 DEF_VEC_ALLOC_I(int, heap);
5045 /* The function processes given REGEXP to find units with the wrong
5048 check_regexp_units_distribution (const char *insn_reserv_name,
5051 int i, j, k, cycle, cycle2, start, n_alts, alt, alt2;
5052 bool annotation_reservation_message_reported_p;
5053 regexp_t seq, allof, unit;
5054 struct unit_usage *unit_usage_ptr;
5055 VEC(int, heap) *marked;
5057 if (regexp == NULL || regexp->mode != rm_oneof)
5059 /* Store all unit usages in the regexp: */
5060 obstack_init (&unit_usages);
5061 cycle_alt_unit_usages = VEC_alloc (unit_usage_t, heap, 10);
5063 for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
5065 seq = REGEXP_ONEOF (regexp)->regexps [i];
5069 for (j = 0; j < REGEXP_SEQUENCE (seq)->regexps_num; j++)
5071 allof = REGEXP_SEQUENCE (seq)->regexps [j];
5072 switch (allof->mode)
5075 for (k = 0; k < REGEXP_ALLOF (allof)->regexps_num; k++)
5077 unit = REGEXP_ALLOF (allof)->regexps [k];
5078 if (unit->mode == rm_unit)
5079 store_alt_unit_usage (regexp, unit, j, i);
5081 gcc_assert (unit->mode == rm_nothing);
5086 store_alt_unit_usage (regexp, allof, j, i);
5099 for (k = 0; k < REGEXP_ALLOF (seq)->regexps_num; k++)
5101 unit = REGEXP_ALLOF (seq)->regexps [k];
5105 store_alt_unit_usage (regexp, unit, 0, i);
5118 store_alt_unit_usage (regexp, seq, 0, i);
5128 /* Check distribution: */
5129 for (i = 0; i < (int) VEC_length (unit_usage_t, cycle_alt_unit_usages); i++)
5130 for (unit_usage_ptr = VEC_index (unit_usage_t, cycle_alt_unit_usages, i);
5131 unit_usage_ptr != NULL;
5132 unit_usage_ptr = unit_usage_ptr->next)
5133 unit_usage_ptr->unit_decl->last_distribution_check_cycle = -1;
5134 n_alts = REGEXP_ONEOF (regexp)->regexps_num;
5135 marked = VEC_alloc (int, heap, n_alts);
5136 for (i = 0; i < n_alts; i++)
5137 VEC_safe_push (int, heap, marked, 0);
5138 annotation_reservation_message_reported_p = false;
5139 for (i = 0; i < (int) VEC_length (unit_usage_t, cycle_alt_unit_usages); i++)
5142 start = cycle * n_alts;
5143 for (unit_usage_ptr = VEC_index (unit_usage_t, cycle_alt_unit_usages, i);
5144 unit_usage_ptr != NULL;
5145 unit_usage_ptr = unit_usage_ptr->next)
5147 if (unit_usage_ptr->unit_decl->last_distribution_check_cycle == cycle)
5149 unit_usage_ptr->unit_decl->last_distribution_check_cycle = cycle;
5150 for (alt = 0; alt < n_alts; alt++)
5151 if (! unit_present_on_list_p (VEC_index (unit_usage_t,
5152 cycle_alt_unit_usages,
5154 unit_usage_ptr->unit_decl))
5158 memset (VEC_address (int, marked), 0, n_alts * sizeof (int));
5159 for (alt = 0; alt < n_alts; alt++)
5161 if (! unit_present_on_list_p (VEC_index (unit_usage_t,
5162 cycle_alt_unit_usages,
5164 unit_usage_ptr->unit_decl))
5167 j < (int) VEC_length (unit_usage_t, cycle_alt_unit_usages);
5170 cycle2 = j / n_alts;
5172 if (! unit_present_on_list_p
5173 (VEC_index (unit_usage_t, cycle_alt_unit_usages,
5175 unit_usage_ptr->unit_decl)
5176 && equal_alternatives_p (alt, alt2, n_alts,
5178 ->unit_decl->automaton_decl))
5180 VEC_replace (int, marked, alt, 1);
5181 VEC_replace (int, marked, alt2, 1);
5185 for (alt = 0; alt < n_alts && VEC_index (int, marked, alt); alt++)
5187 if (alt < n_alts && 0)
5189 if (! annotation_message_reported_p)
5191 fprintf (stderr, "\n");
5192 error ("The following units do not satisfy units-automata distribution rule");
5193 error ("(Unit presence on one alt and its absence on other alt\n");
5194 error (" result in different other automata reservations)");
5195 annotation_message_reported_p = TRUE;
5197 if (! annotation_reservation_message_reported_p)
5199 error ("Reserv %s:", insn_reserv_name);
5200 annotation_reservation_message_reported_p = true;
5202 error (" Unit %s, cycle %d, alt %d, another alt %d",
5203 unit_usage_ptr->unit_decl->name, cycle, i % n_alts, alt);
5207 VEC_free (int, heap, marked);
5208 VEC_free (unit_usage_t, heap, cycle_alt_unit_usages);
5209 obstack_free (&unit_usages, NULL);
5212 /* The function finds units which violates units to automata
5213 distribution rule. If the units exist, report about them. */
5215 check_unit_distributions_to_automata (void)
5221 fprintf (stderr, "Check unit distributions to automata...");
5222 automaton_decls = NULL;
5223 for (i = 0; i < description->decls_num; i++)
5225 decl = description->decls [i];
5226 if (decl->mode == dm_automaton)
5227 VEC_safe_push (decl_t, heap, automaton_decls, decl);
5229 if (VEC_length (decl_t, automaton_decls) > 1)
5231 annotation_message_reported_p = FALSE;
5232 for (i = 0; i < description->decls_num; i++)
5234 decl = description->decls [i];
5235 if (decl->mode == dm_insn_reserv)
5236 check_regexp_units_distribution
5237 (DECL_INSN_RESERV (decl)->name,
5238 DECL_INSN_RESERV (decl)->transformed_regexp);
5241 VEC_free (decl_t, heap, automaton_decls);
5243 fprintf (stderr, "done\n");
5248 /* The page contains code for building alt_states (see comments for
5249 IR) describing all possible insns reservations of an automaton. */
5251 /* Current state being formed for which the current alt_state
5253 static state_t state_being_formed;
5255 /* Current alt_state being formed. */
5256 static alt_state_t alt_state_being_formed;
5258 /* This recursive function processes `,' and units in reservation
5259 REGEXP for forming alt_states of AUTOMATON. It is believed that
5260 CURR_CYCLE is start cycle of all reservation REGEXP. */
5262 process_seq_for_forming_states (regexp_t regexp, automaton_t automaton,
5270 switch (regexp->mode)
5273 if (REGEXP_UNIT (regexp)->unit_decl->corresponding_automaton_num
5274 == automaton->automaton_order_num)
5275 set_state_reserv (state_being_formed, curr_cycle,
5276 REGEXP_UNIT (regexp)->unit_decl->unit_num);
5280 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
5282 = process_seq_for_forming_states
5283 (REGEXP_SEQUENCE (regexp)->regexps [i], automaton, curr_cycle) + 1;
5288 int finish_cycle = 0;
5291 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
5293 cycle = process_seq_for_forming_states (REGEXP_ALLOF (regexp)
5295 automaton, curr_cycle);
5296 if (finish_cycle < cycle)
5297 finish_cycle = cycle;
5299 return finish_cycle;
5310 /* This recursive function finishes forming ALT_STATE of AUTOMATON and
5311 inserts alt_state into the table. */
5313 finish_forming_alt_state (alt_state_t alt_state,
5314 automaton_t automaton ATTRIBUTE_UNUSED)
5316 state_t state_in_table;
5317 state_t corresponding_state;
5319 corresponding_state = alt_state->state;
5320 state_in_table = insert_state (corresponding_state);
5321 if (state_in_table != corresponding_state)
5323 free_state (corresponding_state);
5324 alt_state->state = state_in_table;
5328 /* The following variable value is current automaton insn for whose
5329 reservation the alt states are created. */
5330 static ainsn_t curr_ainsn;
5332 /* This recursive function processes `|' in reservation REGEXP for
5333 forming alt_states of AUTOMATON. List of the alt states should
5334 have the same order as in the description. */
5336 process_alts_for_forming_states (regexp_t regexp, automaton_t automaton,
5341 if (regexp->mode != rm_oneof)
5343 alt_state_being_formed = get_free_alt_state ();
5344 state_being_formed = get_free_state (1, automaton);
5345 alt_state_being_formed->state = state_being_formed;
5346 /* We inserts in reverse order but we process alternatives also
5347 in reverse order. So we have the same order of alternative
5348 as in the description. */
5349 alt_state_being_formed->next_alt_state = curr_ainsn->alt_states;
5350 curr_ainsn->alt_states = alt_state_being_formed;
5351 (void) process_seq_for_forming_states (regexp, automaton, 0);
5352 finish_forming_alt_state (alt_state_being_formed, automaton);
5356 gcc_assert (!inside_oneof_p);
5357 /* We processes it in reverse order to get list with the same
5358 order as in the description. See also the previous
5360 for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
5361 process_alts_for_forming_states (REGEXP_ONEOF (regexp)->regexps [i],
5366 /* Create nodes alt_state for all AUTOMATON insns. */
5368 create_alt_states (automaton_t automaton)
5370 struct insn_reserv_decl *reserv_decl;
5372 for (curr_ainsn = automaton->ainsn_list;
5374 curr_ainsn = curr_ainsn->next_ainsn)
5376 reserv_decl = curr_ainsn->insn_reserv_decl;
5377 if (reserv_decl != DECL_INSN_RESERV (advance_cycle_insn_decl))
5379 curr_ainsn->alt_states = NULL;
5380 process_alts_for_forming_states (reserv_decl->transformed_regexp,
5382 curr_ainsn->sorted_alt_states
5383 = uniq_sort_alt_states (curr_ainsn->alt_states);
5390 /* The page contains major code for building DFA(s) for fast pipeline
5391 hazards recognition. */
5393 /* The function forms list of ainsns of AUTOMATON with the same
5397 form_ainsn_with_same_reservs (automaton_t automaton)
5401 VEC(ainsn_t, heap) *last_insns = VEC_alloc (ainsn_t, heap, 150);
5403 for (curr_ainsn = automaton->ainsn_list;
5405 curr_ainsn = curr_ainsn->next_ainsn)
5406 if (curr_ainsn->insn_reserv_decl
5407 == DECL_INSN_RESERV (advance_cycle_insn_decl))
5409 curr_ainsn->next_same_reservs_insn = NULL;
5410 curr_ainsn->first_insn_with_same_reservs = 1;
5414 for (i = 0; i < VEC_length (ainsn_t, last_insns); i++)
5416 (curr_ainsn->sorted_alt_states,
5417 VEC_index (ainsn_t, last_insns, i)->sorted_alt_states))
5419 curr_ainsn->next_same_reservs_insn = NULL;
5420 if (i < VEC_length (ainsn_t, last_insns))
5422 curr_ainsn->first_insn_with_same_reservs = 0;
5423 VEC_index (ainsn_t, last_insns, i)->next_same_reservs_insn
5425 VEC_replace (ainsn_t, last_insns, i, curr_ainsn);
5429 VEC_safe_push (ainsn_t, heap, last_insns, curr_ainsn);
5430 curr_ainsn->first_insn_with_same_reservs = 1;
5433 VEC_free (ainsn_t, heap, last_insns);
5436 /* Forming unit reservations which can affect creating the automaton
5437 states achieved from a given state. It permits to build smaller
5438 automata in many cases. We would have the same automata after
5439 the minimization without such optimization, but the automaton
5440 right after the building could be huge. So in other words, usage
5441 of reservs_matter means some minimization during building the
5443 static reserv_sets_t
5444 form_reservs_matter (automaton_t automaton)
5447 reserv_sets_t reservs_matter = alloc_empty_reserv_sets();
5449 for (cycle = 0; cycle < max_cycles_num; cycle++)
5450 for (unit = 0; unit < description->units_num; unit++)
5451 if (units_array [unit]->automaton_decl
5452 == automaton->corresponding_automaton_decl
5453 && (cycle >= units_array [unit]->min_occ_cycle_num
5454 /* We can not remove queried unit from reservations. */
5455 || units_array [unit]->query_p
5456 /* We can not remove units which are used
5457 `exclusion_set', `presence_set',
5458 `final_presence_set', `absence_set', and
5459 `final_absence_set'. */
5460 || units_array [unit]->in_set_p))
5461 set_unit_reserv (reservs_matter, cycle, unit);
5462 return reservs_matter;
5465 /* The following function creates all states of nondeterministic AUTOMATON. */
5467 make_automaton (automaton_t automaton)
5470 struct insn_reserv_decl *insn_reserv_decl;
5471 alt_state_t alt_state;
5473 state_t start_state;
5475 ainsn_t advance_cycle_ainsn;
5477 VEC(state_t, heap) *state_stack = VEC_alloc(state_t, heap, 150);
5479 reserv_sets_t reservs_matter = form_reservs_matter (automaton);
5481 /* Create the start state (empty state). */
5482 start_state = insert_state (get_free_state (1, automaton));
5483 automaton->start_state = start_state;
5484 start_state->it_was_placed_in_stack_for_NDFA_forming = 1;
5485 VEC_safe_push (state_t, heap, state_stack, start_state);
5487 while (VEC_length (state_t, state_stack) != 0)
5489 state = VEC_pop (state_t, state_stack);
5490 advance_cycle_ainsn = NULL;
5491 for (ainsn = automaton->ainsn_list;
5493 ainsn = ainsn->next_ainsn)
5494 if (ainsn->first_insn_with_same_reservs)
5496 insn_reserv_decl = ainsn->insn_reserv_decl;
5497 if (insn_reserv_decl != DECL_INSN_RESERV (advance_cycle_insn_decl))
5499 /* We process alt_states in the same order as they are
5500 present in the description. */
5502 for (alt_state = ainsn->alt_states;
5504 alt_state = alt_state->next_alt_state)
5506 state2 = alt_state->state;
5507 if (!intersected_state_reservs_p (state, state2))
5509 state2 = states_union (state, state2, reservs_matter);
5510 if (!state2->it_was_placed_in_stack_for_NDFA_forming)
5512 state2->it_was_placed_in_stack_for_NDFA_forming
5514 VEC_safe_push (state_t, heap, state_stack, state2);
5516 if (progress_flag && states_n % 100 == 0)
5517 fprintf (stderr, ".");
5519 added_arc = add_arc (state, state2, ainsn);
5524 if (!ndfa_flag && added_arc != NULL)
5526 for (alt_state = ainsn->alt_states;
5528 alt_state = alt_state->next_alt_state)
5529 state2 = alt_state->state;
5533 advance_cycle_ainsn = ainsn;
5535 /* Add transition to advance cycle. */
5536 state2 = state_shift (state, reservs_matter);
5537 if (!state2->it_was_placed_in_stack_for_NDFA_forming)
5539 state2->it_was_placed_in_stack_for_NDFA_forming = 1;
5540 VEC_safe_push (state_t, heap, state_stack, state2);
5542 if (progress_flag && states_n % 100 == 0)
5543 fprintf (stderr, ".");
5545 gcc_assert (advance_cycle_ainsn);
5546 add_arc (state, state2, advance_cycle_ainsn);
5548 VEC_free (state_t, heap, state_stack);
5551 /* Form lists of all arcs of STATE marked by the same ainsn. */
5553 form_arcs_marked_by_insn (state_t state)
5559 for (i = 0; i < description->decls_num; i++)
5561 decl = description->decls [i];
5562 if (decl->mode == dm_insn_reserv)
5563 DECL_INSN_RESERV (decl)->arcs_marked_by_insn = NULL;
5565 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5567 gcc_assert (arc->insn);
5568 arc->next_arc_marked_by_insn
5569 = arc->insn->insn_reserv_decl->arcs_marked_by_insn;
5570 arc->insn->insn_reserv_decl->arcs_marked_by_insn = arc;
5574 /* The function creates composed state (see comments for IR) from
5575 ORIGINAL_STATE and list of arcs ARCS_MARKED_BY_INSN marked by the
5576 same insn. If the composed state is not in STATE_STACK yet, it is
5577 pushed into STATE_STACK. */
5580 create_composed_state (state_t original_state, arc_t arcs_marked_by_insn,
5581 VEC(state_t, heap) **state_stack)
5584 alt_state_t alt_state, curr_alt_state;
5585 alt_state_t new_alt_state;
5588 state_t state_in_table;
5590 alt_state_t canonical_alt_states_list;
5592 int new_state_p = 0;
5594 if (arcs_marked_by_insn == NULL)
5596 if (arcs_marked_by_insn->next_arc_marked_by_insn == NULL)
5597 state = arcs_marked_by_insn->to_state;
5600 gcc_assert (ndfa_flag);
5601 /* Create composed state. */
5602 state = get_free_state (0, arcs_marked_by_insn->to_state->automaton);
5603 curr_alt_state = NULL;
5604 for (curr_arc = arcs_marked_by_insn;
5606 curr_arc = curr_arc->next_arc_marked_by_insn)
5607 if (curr_arc->to_state->component_states == NULL)
5609 new_alt_state = get_free_alt_state ();
5610 new_alt_state->next_alt_state = curr_alt_state;
5611 new_alt_state->state = curr_arc->to_state;
5612 curr_alt_state = new_alt_state;
5615 for (alt_state = curr_arc->to_state->component_states;
5617 alt_state = alt_state->next_sorted_alt_state)
5619 new_alt_state = get_free_alt_state ();
5620 new_alt_state->next_alt_state = curr_alt_state;
5621 new_alt_state->state = alt_state->state;
5622 gcc_assert (!alt_state->state->component_states);
5623 curr_alt_state = new_alt_state;
5625 /* There are not identical sets in the alt state list. */
5626 canonical_alt_states_list = uniq_sort_alt_states (curr_alt_state);
5627 if (canonical_alt_states_list->next_sorted_alt_state == NULL)
5630 state = canonical_alt_states_list->state;
5631 free_state (temp_state);
5635 state->component_states = canonical_alt_states_list;
5636 state_in_table = insert_state (state);
5637 if (state_in_table != state)
5640 (state_in_table->it_was_placed_in_stack_for_DFA_forming);
5642 state = state_in_table;
5646 gcc_assert (!state->it_was_placed_in_stack_for_DFA_forming);
5648 for (curr_alt_state = state->component_states;
5649 curr_alt_state != NULL;
5650 curr_alt_state = curr_alt_state->next_sorted_alt_state)
5651 for (curr_arc = first_out_arc (curr_alt_state->state);
5653 curr_arc = next_out_arc (curr_arc))
5654 add_arc (state, curr_arc->to_state, curr_arc->insn);
5656 arcs_marked_by_insn->to_state = state;
5657 for (alts_number = 0,
5658 curr_arc = arcs_marked_by_insn->next_arc_marked_by_insn;
5660 curr_arc = next_arc)
5662 next_arc = curr_arc->next_arc_marked_by_insn;
5663 remove_arc (original_state, curr_arc);
5668 if (!state->it_was_placed_in_stack_for_DFA_forming)
5670 state->it_was_placed_in_stack_for_DFA_forming = 1;
5671 VEC_safe_push (state_t, heap, *state_stack, state);
5676 /* The function transforms nondeterministic AUTOMATON into
5680 NDFA_to_DFA (automaton_t automaton)
5682 state_t start_state;
5685 VEC(state_t, heap) *state_stack;
5689 state_stack = VEC_alloc (state_t, heap, 0);
5691 /* Create the start state (empty state). */
5692 start_state = automaton->start_state;
5693 start_state->it_was_placed_in_stack_for_DFA_forming = 1;
5694 VEC_safe_push (state_t, heap, state_stack, start_state);
5696 while (VEC_length (state_t, state_stack) != 0)
5698 state = VEC_pop (state_t, state_stack);
5699 form_arcs_marked_by_insn (state);
5700 for (i = 0; i < description->decls_num; i++)
5702 decl = description->decls [i];
5703 if (decl->mode == dm_insn_reserv
5704 && create_composed_state
5705 (state, DECL_INSN_RESERV (decl)->arcs_marked_by_insn,
5709 if (progress_flag && states_n % 100 == 0)
5710 fprintf (stderr, ".");
5714 VEC_free (state_t, heap, state_stack);
5717 /* The following variable value is current number (1, 2, ...) of passing
5719 static int curr_state_graph_pass_num;
5721 /* This recursive function passes all states achieved from START_STATE
5722 and applies APPLIED_FUNC to them. */
5724 pass_state_graph (state_t start_state, void (*applied_func) (state_t state))
5728 if (start_state->pass_num == curr_state_graph_pass_num)
5730 start_state->pass_num = curr_state_graph_pass_num;
5731 (*applied_func) (start_state);
5732 for (arc = first_out_arc (start_state);
5734 arc = next_out_arc (arc))
5735 pass_state_graph (arc->to_state, applied_func);
5738 /* This recursive function passes all states of AUTOMATON and applies
5739 APPLIED_FUNC to them. */
5741 pass_states (automaton_t automaton, void (*applied_func) (state_t state))
5743 curr_state_graph_pass_num++;
5744 pass_state_graph (automaton->start_state, applied_func);
5747 /* The function initializes code for passing of all states. */
5749 initiate_pass_states (void)
5751 curr_state_graph_pass_num = 0;
5754 /* The following vla is used for storing pointers to all achieved
5756 static VEC(state_t, heap) *all_achieved_states;
5758 /* This function is called by function pass_states to add an achieved
5761 add_achieved_state (state_t state)
5763 VEC_safe_push (state_t, heap, all_achieved_states, state);
5766 /* The function sets up equivalence numbers of insns which mark all
5767 out arcs of STATE by equiv_class_num_1 (if ODD_ITERATION_FLAG has
5768 nonzero value) or by equiv_class_num_2 of the destination state.
5769 The function returns number of out arcs of STATE. */
5771 set_out_arc_insns_equiv_num (state_t state, int odd_iteration_flag)
5775 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5777 gcc_assert (!arc->insn->insn_reserv_decl->equiv_class_num);
5778 arc->insn->insn_reserv_decl->equiv_class_num
5779 = (odd_iteration_flag
5780 ? arc->to_state->equiv_class_num_1
5781 : arc->to_state->equiv_class_num_2);
5782 gcc_assert (arc->insn->insn_reserv_decl->equiv_class_num);
5786 /* The function clears equivalence numbers and alt_states in all insns
5787 which mark all out arcs of STATE. */
5789 clear_arc_insns_equiv_num (state_t state)
5793 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5794 arc->insn->insn_reserv_decl->equiv_class_num = 0;
5798 /* The following function returns TRUE if STATE reserves the unit with
5799 UNIT_NUM on the first cycle. */
5801 first_cycle_unit_presence (state_t state, int unit_num)
5803 alt_state_t alt_state;
5805 if (state->component_states == NULL)
5806 return test_unit_reserv (state->reservs, 0, unit_num);
5809 for (alt_state = state->component_states;
5811 alt_state = alt_state->next_sorted_alt_state)
5812 if (test_unit_reserv (alt_state->state->reservs, 0, unit_num))
5818 /* This fills in the presence_signature[] member of STATE. */
5820 cache_presence (state_t state)
5824 sz = (description->query_units_num + sizeof (int) * CHAR_BIT - 1)
5825 / (sizeof (int) * CHAR_BIT);
5827 state->presence_signature = XCREATENODEVEC (unsigned int, sz);
5828 for (i = 0; i < description->units_num; i++)
5829 if (units_array [i]->query_p)
5831 int presence1_p = first_cycle_unit_presence (state, i);
5832 state->presence_signature[num / (sizeof (int) * CHAR_BIT)]
5833 |= (!!presence1_p) << (num % (sizeof (int) * CHAR_BIT));
5838 /* The function returns nonzero value if STATE is not equivalent to
5839 ANOTHER_STATE from the same current partition on equivalence
5840 classes. Another state has ANOTHER_STATE_OUT_ARCS_NUM number of
5841 output arcs. Iteration of making equivalence partition is defined
5842 by ODD_ITERATION_FLAG. */
5844 state_is_differed (state_t state, state_t another_state,
5845 int odd_iteration_flag)
5848 unsigned int sz, si;
5850 gcc_assert (state->num_out_arcs == another_state->num_out_arcs);
5852 sz = (description->query_units_num + sizeof (int) * CHAR_BIT - 1)
5853 / (sizeof (int) * CHAR_BIT);
5855 for (si = 0; si < sz; si++)
5856 gcc_assert (state->presence_signature[si]
5857 == another_state->presence_signature[si]);
5859 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5861 if ((odd_iteration_flag
5862 ? arc->to_state->equiv_class_num_1
5863 : arc->to_state->equiv_class_num_2)
5864 != arc->insn->insn_reserv_decl->equiv_class_num)
5871 /* Compares two states pointed to by STATE_PTR_1 and STATE_PTR_2
5872 and return -1, 0 or 1. This function can be used as predicate for
5873 qsort(). It requires the member presence_signature[] of both
5874 states be filled. */
5876 compare_states_for_equiv (const void *state_ptr_1,
5877 const void *state_ptr_2)
5879 const_state_t const s1 = *(const_state_t const*)state_ptr_1;
5880 const_state_t const s2 = *(const_state_t const*)state_ptr_2;
5881 unsigned int sz, si;
5882 if (s1->num_out_arcs < s2->num_out_arcs)
5884 else if (s1->num_out_arcs > s2->num_out_arcs)
5887 sz = (description->query_units_num + sizeof (int) * CHAR_BIT - 1)
5888 / (sizeof (int) * CHAR_BIT);
5890 for (si = 0; si < sz; si++)
5891 if (s1->presence_signature[si] < s2->presence_signature[si])
5893 else if (s1->presence_signature[si] > s2->presence_signature[si])
5898 /* The function makes initial partition of STATES on equivalent
5899 classes and saves it into *CLASSES. This function requires the input
5900 to be sorted via compare_states_for_equiv(). */
5902 init_equiv_class (VEC(state_t, heap) *states, VEC (state_t, heap) **classes)
5908 *classes = VEC_alloc (state_t, heap, 150);
5909 for (i = 0; i < VEC_length (state_t, states); i++)
5911 state_t state = VEC_index (state_t, states, i);
5914 if (compare_states_for_equiv (&prev, &state) != 0)
5916 VEC_safe_push (state_t, heap, *classes, prev);
5921 state->equiv_class_num_1 = class_num;
5922 state->next_equiv_class_state = prev;
5926 VEC_safe_push (state_t, heap, *classes, prev);
5930 /* The function copies pointers to equivalent states from vla FROM
5933 copy_equiv_class (VEC(state_t, heap) **to, VEC(state_t, heap) *from)
5935 VEC_free (state_t, heap, *to);
5936 *to = VEC_copy (state_t, heap, from);
5939 /* The function processes equivalence class given by its first state,
5940 FIRST_STATE, on odd iteration if ODD_ITERATION_FLAG. If there
5941 are not equivalent states, the function partitions the class
5942 removing nonequivalent states and placing them in
5943 *NEXT_ITERATION_CLASSES, increments *NEW_EQUIV_CLASS_NUM_PTR ans
5944 assigns it to the state equivalence number. If the class has been
5945 partitioned, the function returns nonzero value. */
5947 partition_equiv_class (state_t first_state, int odd_iteration_flag,
5948 VEC(state_t, heap) **next_iteration_classes,
5949 int *new_equiv_class_num_ptr)
5951 state_t new_equiv_class;
5959 while (first_state != NULL)
5961 new_equiv_class = NULL;
5962 if (first_state->next_equiv_class_state != NULL)
5964 /* There are more one states in the class equivalence. */
5965 set_out_arc_insns_equiv_num (first_state, odd_iteration_flag);
5966 for (prev_state = first_state,
5967 curr_state = first_state->next_equiv_class_state;
5969 curr_state = next_state)
5971 next_state = curr_state->next_equiv_class_state;
5972 if (state_is_differed (curr_state, first_state,
5973 odd_iteration_flag))
5975 /* Remove curr state from the class equivalence. */
5976 prev_state->next_equiv_class_state = next_state;
5977 /* Add curr state to the new class equivalence. */
5978 curr_state->next_equiv_class_state = new_equiv_class;
5979 if (new_equiv_class == NULL)
5980 (*new_equiv_class_num_ptr)++;
5981 if (odd_iteration_flag)
5982 curr_state->equiv_class_num_2 = *new_equiv_class_num_ptr;
5984 curr_state->equiv_class_num_1 = *new_equiv_class_num_ptr;
5985 new_equiv_class = curr_state;
5989 prev_state = curr_state;
5991 clear_arc_insns_equiv_num (first_state);
5993 if (new_equiv_class != NULL)
5994 VEC_safe_push (state_t, heap, *next_iteration_classes, new_equiv_class);
5995 first_state = new_equiv_class;
6000 /* The function finds equivalent states of AUTOMATON. */
6002 evaluate_equiv_classes (automaton_t automaton,
6003 VEC(state_t, heap) **equiv_classes)
6005 int new_equiv_class_num;
6006 int odd_iteration_flag;
6008 VEC (state_t, heap) *next_iteration_classes;
6011 all_achieved_states = VEC_alloc (state_t, heap, 1500);
6012 pass_states (automaton, add_achieved_state);
6013 pass_states (automaton, cache_presence);
6014 qsort (VEC_address (state_t, all_achieved_states),
6015 VEC_length (state_t, all_achieved_states),
6016 sizeof (state_t), compare_states_for_equiv);
6018 odd_iteration_flag = 0;
6019 new_equiv_class_num = init_equiv_class (all_achieved_states,
6020 &next_iteration_classes);
6024 odd_iteration_flag = !odd_iteration_flag;
6026 copy_equiv_class (equiv_classes, next_iteration_classes);
6028 /* Transfer equiv numbers for the next iteration. */
6029 for (i = 0; i < VEC_length (state_t, all_achieved_states); i++)
6030 if (odd_iteration_flag)
6031 VEC_index (state_t, all_achieved_states, i)->equiv_class_num_2
6032 = VEC_index (state_t, all_achieved_states, i)->equiv_class_num_1;
6034 VEC_index (state_t, all_achieved_states, i)->equiv_class_num_1
6035 = VEC_index (state_t, all_achieved_states, i)->equiv_class_num_2;
6037 for (i = 0; i < VEC_length (state_t, *equiv_classes); i++)
6038 if (partition_equiv_class (VEC_index (state_t, *equiv_classes, i),
6040 &next_iteration_classes,
6041 &new_equiv_class_num))
6044 while (!finish_flag);
6045 VEC_free (state_t, heap, next_iteration_classes);
6046 VEC_free (state_t, heap, all_achieved_states);
6049 /* The function merges equivalent states of AUTOMATON. */
6051 merge_states (automaton_t automaton, VEC(state_t, heap) *equiv_classes)
6055 state_t first_class_state;
6056 alt_state_t alt_states;
6057 alt_state_t alt_state, new_alt_state;
6062 /* Create states corresponding to equivalence classes containing two
6064 for (i = 0; i < VEC_length (state_t, equiv_classes); i++)
6066 curr_state = VEC_index (state_t, equiv_classes, i);
6067 if (curr_state->next_equiv_class_state != NULL)
6069 /* There are more one states in the class equivalence. */
6070 /* Create new compound state. */
6071 new_state = get_free_state (0, automaton);
6073 first_class_state = curr_state;
6074 for (curr_state = first_class_state;
6076 curr_state = curr_state->next_equiv_class_state)
6078 curr_state->equiv_class_state = new_state;
6079 if (curr_state->component_states == NULL)
6081 new_alt_state = get_free_alt_state ();
6082 new_alt_state->state = curr_state;
6083 new_alt_state->next_alt_state = alt_states;
6084 alt_states = new_alt_state;
6087 for (alt_state = curr_state->component_states;
6089 alt_state = alt_state->next_sorted_alt_state)
6091 new_alt_state = get_free_alt_state ();
6092 new_alt_state->state = alt_state->state;
6093 new_alt_state->next_alt_state = alt_states;
6094 alt_states = new_alt_state;
6097 /* Its is important that alt states were sorted before and
6098 after merging to have the same querying results. */
6099 new_state->component_states = uniq_sort_alt_states (alt_states);
6102 curr_state->equiv_class_state = curr_state;
6105 for (i = 0; i < VEC_length (state_t, equiv_classes); i++)
6107 curr_state = VEC_index (state_t, equiv_classes, i);
6108 if (curr_state->next_equiv_class_state != NULL)
6110 first_class_state = curr_state;
6111 /* Create new arcs output from the state corresponding to
6113 for (curr_arc = first_out_arc (first_class_state);
6115 curr_arc = next_out_arc (curr_arc))
6116 add_arc (first_class_state->equiv_class_state,
6117 curr_arc->to_state->equiv_class_state,
6119 /* Delete output arcs from states of given class equivalence. */
6120 for (curr_state = first_class_state;
6122 curr_state = curr_state->next_equiv_class_state)
6124 if (automaton->start_state == curr_state)
6125 automaton->start_state = curr_state->equiv_class_state;
6126 /* Delete the state and its output arcs. */
6127 for (curr_arc = first_out_arc (curr_state);
6129 curr_arc = next_arc)
6131 next_arc = next_out_arc (curr_arc);
6132 free_arc (curr_arc);
6138 /* Change `to_state' of arcs output from the state of given
6139 equivalence class. */
6140 for (curr_arc = first_out_arc (curr_state);
6142 curr_arc = next_out_arc (curr_arc))
6143 curr_arc->to_state = curr_arc->to_state->equiv_class_state;
6148 /* The function sets up new_cycle_p for states if there is arc to the
6149 state marked by advance_cycle_insn_decl. */
6151 set_new_cycle_flags (state_t state)
6155 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6156 if (arc->insn->insn_reserv_decl
6157 == DECL_INSN_RESERV (advance_cycle_insn_decl))
6158 arc->to_state->new_cycle_p = 1;
6161 /* The top level function for minimization of deterministic
6164 minimize_DFA (automaton_t automaton)
6166 VEC(state_t, heap) *equiv_classes = 0;
6168 evaluate_equiv_classes (automaton, &equiv_classes);
6169 merge_states (automaton, equiv_classes);
6170 pass_states (automaton, set_new_cycle_flags);
6172 VEC_free (state_t, heap, equiv_classes);
6175 /* Values of two variables are counted number of states and arcs in an
6177 static int curr_counted_states_num;
6178 static int curr_counted_arcs_num;
6180 /* The function is called by function `pass_states' to count states
6181 and arcs of an automaton. */
6183 incr_states_and_arcs_nums (state_t state)
6187 curr_counted_states_num++;
6188 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6189 curr_counted_arcs_num++;
6192 /* The function counts states and arcs of AUTOMATON. */
6194 count_states_and_arcs (automaton_t automaton, int *states_num,
6197 curr_counted_states_num = 0;
6198 curr_counted_arcs_num = 0;
6199 pass_states (automaton, incr_states_and_arcs_nums);
6200 *states_num = curr_counted_states_num;
6201 *arcs_num = curr_counted_arcs_num;
6204 /* The function builds one DFA AUTOMATON for fast pipeline hazards
6205 recognition after checking and simplifying IR of the
6208 build_automaton (automaton_t automaton)
6213 ticker_on (&NDFA_time);
6216 if (automaton->corresponding_automaton_decl == NULL)
6217 fprintf (stderr, "Create anonymous automaton");
6219 fprintf (stderr, "Create automaton `%s'",
6220 automaton->corresponding_automaton_decl->name);
6221 fprintf (stderr, " (1 dot is 100 new states):");
6223 make_automaton (automaton);
6225 fprintf (stderr, " done\n");
6226 ticker_off (&NDFA_time);
6227 count_states_and_arcs (automaton, &states_num, &arcs_num);
6228 automaton->NDFA_states_num = states_num;
6229 automaton->NDFA_arcs_num = arcs_num;
6230 ticker_on (&NDFA_to_DFA_time);
6233 if (automaton->corresponding_automaton_decl == NULL)
6234 fprintf (stderr, "Make anonymous DFA");
6236 fprintf (stderr, "Make DFA `%s'",
6237 automaton->corresponding_automaton_decl->name);
6238 fprintf (stderr, " (1 dot is 100 new states):");
6240 NDFA_to_DFA (automaton);
6242 fprintf (stderr, " done\n");
6243 ticker_off (&NDFA_to_DFA_time);
6244 count_states_and_arcs (automaton, &states_num, &arcs_num);
6245 automaton->DFA_states_num = states_num;
6246 automaton->DFA_arcs_num = arcs_num;
6247 if (!no_minimization_flag)
6249 ticker_on (&minimize_time);
6252 if (automaton->corresponding_automaton_decl == NULL)
6253 fprintf (stderr, "Minimize anonymous DFA...");
6255 fprintf (stderr, "Minimize DFA `%s'...",
6256 automaton->corresponding_automaton_decl->name);
6258 minimize_DFA (automaton);
6260 fprintf (stderr, "done\n");
6261 ticker_off (&minimize_time);
6262 count_states_and_arcs (automaton, &states_num, &arcs_num);
6263 automaton->minimal_DFA_states_num = states_num;
6264 automaton->minimal_DFA_arcs_num = arcs_num;
6270 /* The page contains code for enumeration of all states of an automaton. */
6272 /* Variable used for enumeration of all states of an automaton. Its
6273 value is current number of automaton states. */
6274 static int curr_state_order_num;
6276 /* The function is called by function `pass_states' for enumerating
6279 set_order_state_num (state_t state)
6281 state->order_state_num = curr_state_order_num;
6282 curr_state_order_num++;
6285 /* The function enumerates all states of AUTOMATON. */
6287 enumerate_states (automaton_t automaton)
6289 curr_state_order_num = 0;
6290 pass_states (automaton, set_order_state_num);
6291 automaton->achieved_states_num = curr_state_order_num;
6296 /* The page contains code for finding equivalent automaton insns
6299 /* The function inserts AINSN into cyclic list
6300 CYCLIC_EQUIV_CLASS_INSN_LIST of ainsns. */
6302 insert_ainsn_into_equiv_class (ainsn_t ainsn,
6303 ainsn_t cyclic_equiv_class_insn_list)
6305 if (cyclic_equiv_class_insn_list == NULL)
6306 ainsn->next_equiv_class_insn = ainsn;
6309 ainsn->next_equiv_class_insn
6310 = cyclic_equiv_class_insn_list->next_equiv_class_insn;
6311 cyclic_equiv_class_insn_list->next_equiv_class_insn = ainsn;
6316 /* The function deletes equiv_class_insn into cyclic list of
6317 equivalent ainsns. */
6319 delete_ainsn_from_equiv_class (ainsn_t equiv_class_insn)
6321 ainsn_t curr_equiv_class_insn;
6322 ainsn_t prev_equiv_class_insn;
6324 prev_equiv_class_insn = equiv_class_insn;
6325 for (curr_equiv_class_insn = equiv_class_insn->next_equiv_class_insn;
6326 curr_equiv_class_insn != equiv_class_insn;
6327 curr_equiv_class_insn = curr_equiv_class_insn->next_equiv_class_insn)
6328 prev_equiv_class_insn = curr_equiv_class_insn;
6329 if (prev_equiv_class_insn != equiv_class_insn)
6330 prev_equiv_class_insn->next_equiv_class_insn
6331 = equiv_class_insn->next_equiv_class_insn;
6334 /* The function processes AINSN of a state in order to find equivalent
6335 ainsns. INSN_ARCS_ARRAY is table: code of insn -> out arc of the
6338 process_insn_equiv_class (ainsn_t ainsn, arc_t *insn_arcs_array)
6342 ainsn_t cyclic_insn_list;
6345 gcc_assert (insn_arcs_array [ainsn->insn_reserv_decl->insn_num]);
6347 /* New class of ainsns which are not equivalent to given ainsn. */
6348 cyclic_insn_list = NULL;
6351 next_insn = curr_insn->next_equiv_class_insn;
6352 arc = insn_arcs_array [curr_insn->insn_reserv_decl->insn_num];
6354 || (insn_arcs_array [ainsn->insn_reserv_decl->insn_num]->to_state
6357 delete_ainsn_from_equiv_class (curr_insn);
6358 cyclic_insn_list = insert_ainsn_into_equiv_class (curr_insn,
6361 curr_insn = next_insn;
6363 while (curr_insn != ainsn);
6366 /* The function processes STATE in order to find equivalent ainsns. */
6368 process_state_for_insn_equiv_partition (state_t state)
6371 arc_t *insn_arcs_array = XCNEWVEC (arc_t, description->insns_num);
6373 /* Process insns of the arcs. */
6374 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6375 insn_arcs_array [arc->insn->insn_reserv_decl->insn_num] = arc;
6376 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6377 process_insn_equiv_class (arc->insn, insn_arcs_array);
6379 free (insn_arcs_array);
6382 /* The function searches for equivalent ainsns of AUTOMATON. */
6384 set_insn_equiv_classes (automaton_t automaton)
6389 ainsn_t cyclic_insn_list;
6390 ainsn_t insn_with_same_reservs;
6391 int equiv_classes_num;
6393 /* All insns are included in one equivalence class. */
6394 cyclic_insn_list = NULL;
6395 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6396 if (ainsn->first_insn_with_same_reservs)
6397 cyclic_insn_list = insert_ainsn_into_equiv_class (ainsn,
6399 /* Process insns in order to make equivalence partition. */
6400 pass_states (automaton, process_state_for_insn_equiv_partition);
6401 /* Enumerate equiv classes. */
6402 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6403 /* Set undefined value. */
6404 ainsn->insn_equiv_class_num = -1;
6405 equiv_classes_num = 0;
6406 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6407 if (ainsn->insn_equiv_class_num < 0)
6410 gcc_assert (first_insn->first_insn_with_same_reservs);
6411 first_insn->first_ainsn_with_given_equivalence_num = 1;
6412 curr_insn = first_insn;
6415 for (insn_with_same_reservs = curr_insn;
6416 insn_with_same_reservs != NULL;
6417 insn_with_same_reservs
6418 = insn_with_same_reservs->next_same_reservs_insn)
6419 insn_with_same_reservs->insn_equiv_class_num = equiv_classes_num;
6420 curr_insn = curr_insn->next_equiv_class_insn;
6422 while (curr_insn != first_insn);
6423 equiv_classes_num++;
6425 automaton->insn_equiv_classes_num = equiv_classes_num;
6430 /* This page contains code for creating DFA(s) and calls functions
6434 /* The following value is used to prevent floating point overflow for
6435 estimating an automaton bound. The value should be less DBL_MAX on
6436 the host machine. We use here approximate minimum of maximal
6437 double floating point value required by ANSI C standard. It
6438 will work for non ANSI sun compiler too. */
6440 #define MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND 1.0E37
6442 /* The function estimate size of the single DFA used by PHR (pipeline
6443 hazards recognizer). */
6445 estimate_one_automaton_bound (void)
6448 double one_automaton_estimation_bound;
6452 one_automaton_estimation_bound = 1.0;
6453 for (i = 0; i < description->decls_num; i++)
6455 decl = description->decls [i];
6456 if (decl->mode == dm_unit)
6458 root_value = exp (log (DECL_UNIT (decl)->max_occ_cycle_num
6459 - DECL_UNIT (decl)->min_occ_cycle_num + 1.0)
6461 if (MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND / root_value
6462 > one_automaton_estimation_bound)
6463 one_automaton_estimation_bound *= root_value;
6466 return one_automaton_estimation_bound;
6469 /* The function compares unit declarations according to their maximal
6470 cycle in reservations. */
6472 compare_max_occ_cycle_nums (const void *unit_decl_1,
6473 const void *unit_decl_2)
6475 if ((DECL_UNIT (*(const_decl_t const*) unit_decl_1)->max_occ_cycle_num)
6476 < (DECL_UNIT (*(const_decl_t const*) unit_decl_2)->max_occ_cycle_num))
6478 else if ((DECL_UNIT (*(const_decl_t const*) unit_decl_1)->max_occ_cycle_num)
6479 == (DECL_UNIT (*(const_decl_t const*) unit_decl_2)->max_occ_cycle_num))
6485 /* The function makes heuristic assigning automata to units. Actually
6486 efficacy of the algorithm has been checked yet??? */
6489 units_to_automata_heuristic_distr (void)
6491 double estimation_bound;
6495 unit_decl_t *unit_decls;
6498 if (description->units_num == 0)
6500 estimation_bound = estimate_one_automaton_bound ();
6501 unit_decls = XNEWVEC (unit_decl_t, description->units_num);
6503 for (i = 0, j = 0; i < description->decls_num; i++)
6504 if (description->decls[i]->mode == dm_unit)
6505 unit_decls[j++] = DECL_UNIT (description->decls[i]);
6506 gcc_assert (j == description->units_num);
6508 qsort (unit_decls, description->units_num,
6509 sizeof (unit_decl_t), compare_max_occ_cycle_nums);
6512 bound_value = unit_decls[0]->max_occ_cycle_num;
6513 unit_decls[0]->corresponding_automaton_num = automaton_num;
6515 for (i = 1; i < description->units_num; i++)
6517 rest_units_num = description->units_num - i + 1;
6518 gcc_assert (automata_num - automaton_num - 1 <= rest_units_num);
6519 if (automaton_num < automata_num - 1
6520 && ((automata_num - automaton_num - 1 == rest_units_num)
6523 / unit_decls[i]->max_occ_cycle_num))))
6525 bound_value = unit_decls[i]->max_occ_cycle_num;
6529 bound_value *= unit_decls[i]->max_occ_cycle_num;
6530 unit_decls[i]->corresponding_automaton_num = automaton_num;
6532 gcc_assert (automaton_num == automata_num - 1);
6536 /* The functions creates automaton insns for each automata. Automaton
6537 insn is simply insn for given automaton which makes reservation
6538 only of units of the automaton. */
6540 create_ainsns (void)
6543 ainsn_t first_ainsn;
6550 for (i = 0; i < description->decls_num; i++)
6552 decl = description->decls [i];
6553 if (decl->mode == dm_insn_reserv)
6555 curr_ainsn = XCREATENODE (struct ainsn);
6556 curr_ainsn->insn_reserv_decl = DECL_INSN_RESERV (decl);
6557 curr_ainsn->important_p = FALSE;
6558 curr_ainsn->next_ainsn = NULL;
6559 if (prev_ainsn == NULL)
6560 first_ainsn = curr_ainsn;
6562 prev_ainsn->next_ainsn = curr_ainsn;
6563 prev_ainsn = curr_ainsn;
6569 /* The function assigns automata to units according to constructions
6570 `define_automaton' in the description. */
6572 units_to_automata_distr (void)
6577 for (i = 0; i < description->decls_num; i++)
6579 decl = description->decls [i];
6580 if (decl->mode == dm_unit)
6582 if (DECL_UNIT (decl)->automaton_decl == NULL
6583 || (DECL_UNIT (decl)->automaton_decl->corresponding_automaton
6585 /* Distribute to the first automaton. */
6586 DECL_UNIT (decl)->corresponding_automaton_num = 0;
6588 DECL_UNIT (decl)->corresponding_automaton_num
6589 = (DECL_UNIT (decl)->automaton_decl
6590 ->corresponding_automaton->automaton_order_num);
6595 /* The function creates DFA(s) for fast pipeline hazards recognition
6596 after checking and simplifying IR of the description. */
6598 create_automata (void)
6600 automaton_t curr_automaton;
6601 automaton_t prev_automaton;
6603 int curr_automaton_num;
6606 if (automata_num != 0)
6608 units_to_automata_heuristic_distr ();
6609 for (prev_automaton = NULL, curr_automaton_num = 0;
6610 curr_automaton_num < automata_num;
6611 curr_automaton_num++, prev_automaton = curr_automaton)
6613 curr_automaton = XCREATENODE (struct automaton);
6614 curr_automaton->ainsn_list = create_ainsns ();
6615 curr_automaton->corresponding_automaton_decl = NULL;
6616 curr_automaton->next_automaton = NULL;
6617 curr_automaton->automaton_order_num = curr_automaton_num;
6618 if (prev_automaton == NULL)
6619 description->first_automaton = curr_automaton;
6621 prev_automaton->next_automaton = curr_automaton;
6626 curr_automaton_num = 0;
6627 prev_automaton = NULL;
6628 for (i = 0; i < description->decls_num; i++)
6630 decl = description->decls [i];
6631 if (decl->mode == dm_automaton
6632 && DECL_AUTOMATON (decl)->automaton_is_used)
6634 curr_automaton = XCREATENODE (struct automaton);
6635 curr_automaton->ainsn_list = create_ainsns ();
6636 curr_automaton->corresponding_automaton_decl
6637 = DECL_AUTOMATON (decl);
6638 curr_automaton->next_automaton = NULL;
6639 DECL_AUTOMATON (decl)->corresponding_automaton = curr_automaton;
6640 curr_automaton->automaton_order_num = curr_automaton_num;
6641 if (prev_automaton == NULL)
6642 description->first_automaton = curr_automaton;
6644 prev_automaton->next_automaton = curr_automaton;
6645 curr_automaton_num++;
6646 prev_automaton = curr_automaton;
6649 if (curr_automaton_num == 0)
6651 curr_automaton = XCREATENODE (struct automaton);
6652 curr_automaton->ainsn_list = create_ainsns ();
6653 curr_automaton->corresponding_automaton_decl = NULL;
6654 curr_automaton->next_automaton = NULL;
6655 description->first_automaton = curr_automaton;
6657 units_to_automata_distr ();
6659 NDFA_time = create_ticker ();
6660 ticker_off (&NDFA_time);
6661 NDFA_to_DFA_time = create_ticker ();
6662 ticker_off (&NDFA_to_DFA_time);
6663 minimize_time = create_ticker ();
6664 ticker_off (&minimize_time);
6665 equiv_time = create_ticker ();
6666 ticker_off (&equiv_time);
6667 for (curr_automaton = description->first_automaton;
6668 curr_automaton != NULL;
6669 curr_automaton = curr_automaton->next_automaton)
6673 if (curr_automaton->corresponding_automaton_decl == NULL)
6674 fprintf (stderr, "Prepare anonymous automaton creation ... ");
6676 fprintf (stderr, "Prepare automaton `%s' creation...",
6677 curr_automaton->corresponding_automaton_decl->name);
6679 create_alt_states (curr_automaton);
6680 form_ainsn_with_same_reservs (curr_automaton);
6682 fprintf (stderr, "done\n");
6683 build_automaton (curr_automaton);
6684 enumerate_states (curr_automaton);
6685 ticker_on (&equiv_time);
6686 set_insn_equiv_classes (curr_automaton);
6687 ticker_off (&equiv_time);
6693 /* This page contains code for forming string representation of
6694 regexp. The representation is formed on IR obstack. So you should
6695 not work with IR obstack between regexp_representation and
6696 finish_regexp_representation calls. */
6698 /* This recursive function forms string representation of regexp
6699 (without tailing '\0'). */
6701 form_regexp (regexp_t regexp)
6705 switch (regexp->mode)
6707 case rm_unit: case rm_reserv:
6709 const char *name = (regexp->mode == rm_unit
6710 ? REGEXP_UNIT (regexp)->name
6711 : REGEXP_RESERV (regexp)->name);
6713 obstack_grow (&irp, name, strlen (name));
6718 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
6721 obstack_1grow (&irp, ',');
6722 form_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
6727 obstack_1grow (&irp, '(');
6728 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
6731 obstack_1grow (&irp, '+');
6732 if (REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_sequence
6733 || REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_oneof)
6734 obstack_1grow (&irp, '(');
6735 form_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
6736 if (REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_sequence
6737 || REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_oneof)
6738 obstack_1grow (&irp, ')');
6740 obstack_1grow (&irp, ')');
6744 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
6747 obstack_1grow (&irp, '|');
6748 if (REGEXP_ONEOF (regexp)->regexps[i]->mode == rm_sequence)
6749 obstack_1grow (&irp, '(');
6750 form_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
6751 if (REGEXP_ONEOF (regexp)->regexps[i]->mode == rm_sequence)
6752 obstack_1grow (&irp, ')');
6760 if (REGEXP_REPEAT (regexp)->regexp->mode == rm_sequence
6761 || REGEXP_REPEAT (regexp)->regexp->mode == rm_allof
6762 || REGEXP_REPEAT (regexp)->regexp->mode == rm_oneof)
6763 obstack_1grow (&irp, '(');
6764 form_regexp (REGEXP_REPEAT (regexp)->regexp);
6765 if (REGEXP_REPEAT (regexp)->regexp->mode == rm_sequence
6766 || REGEXP_REPEAT (regexp)->regexp->mode == rm_allof
6767 || REGEXP_REPEAT (regexp)->regexp->mode == rm_oneof)
6768 obstack_1grow (&irp, ')');
6769 sprintf (digits, "*%d", REGEXP_REPEAT (regexp)->repeat_num);
6770 obstack_grow (&irp, digits, strlen (digits));
6775 obstack_grow (&irp, NOTHING_NAME, strlen (NOTHING_NAME));
6783 /* The function returns string representation of REGEXP on IR
6786 regexp_representation (regexp_t regexp)
6788 form_regexp (regexp);
6789 obstack_1grow (&irp, '\0');
6790 return obstack_base (&irp);
6793 /* The function frees memory allocated for last formed string
6794 representation of regexp. */
6796 finish_regexp_representation (void)
6798 int length = obstack_object_size (&irp);
6800 obstack_blank_fast (&irp, -length);
6805 /* This page contains code for output PHR (pipeline hazards recognizer). */
6807 /* The function outputs minimal C type which is sufficient for
6808 representation numbers in range min_range_value and
6809 max_range_value. Because host machine and build machine may be
6810 different, we use here minimal values required by ANSI C standard
6811 instead of UCHAR_MAX, SHRT_MAX, SHRT_MIN, etc. This is a good
6815 output_range_type (FILE *f, long int min_range_value,
6816 long int max_range_value)
6818 if (min_range_value >= 0 && max_range_value <= 255)
6819 fprintf (f, "unsigned char");
6820 else if (min_range_value >= -127 && max_range_value <= 127)
6821 fprintf (f, "signed char");
6822 else if (min_range_value >= 0 && max_range_value <= 65535)
6823 fprintf (f, "unsigned short");
6824 else if (min_range_value >= -32767 && max_range_value <= 32767)
6825 fprintf (f, "short");
6830 /* The function outputs all initialization values of VECT. */
6832 output_vect (vla_hwint_t vect)
6835 size_t vect_length = VEC_length (vect_el_t, vect);
6839 if (vect_length == 0)
6840 fputs ("0 /* This is dummy el because the vect is empty */", output_file);
6842 for (i = 0; i < vect_length; i++)
6844 fprintf (output_file, "%5ld", (long) VEC_index (vect_el_t, vect, i));
6845 if (els_on_line == 10)
6848 fputs (",\n", output_file);
6850 else if (i < vect_length-1)
6851 fputs (", ", output_file);
6856 /* The following is name of the structure which represents DFA(s) for
6858 #define CHIP_NAME "DFA_chip"
6860 /* The following is name of member which represents state of a DFA for
6863 output_chip_member_name (FILE *f, automaton_t automaton)
6865 if (automaton->corresponding_automaton_decl == NULL)
6866 fprintf (f, "automaton_state_%d", automaton->automaton_order_num);
6868 fprintf (f, "%s_automaton_state",
6869 automaton->corresponding_automaton_decl->name);
6872 /* The following is name of temporary variable which stores state of a
6875 output_temp_chip_member_name (FILE *f, automaton_t automaton)
6878 output_chip_member_name (f, automaton);
6881 /* This is name of macro value which is code of pseudo_insn
6882 representing advancing cpu cycle. Its value is used as internal
6883 code unknown insn. */
6884 #define ADVANCE_CYCLE_VALUE_NAME "DFA__ADVANCE_CYCLE"
6886 /* Output name of translate vector for given automaton. */
6888 output_translate_vect_name (FILE *f, automaton_t automaton)
6890 if (automaton->corresponding_automaton_decl == NULL)
6891 fprintf (f, "translate_%d", automaton->automaton_order_num);
6893 fprintf (f, "%s_translate", automaton->corresponding_automaton_decl->name);
6896 /* Output name for simple transition table representation. */
6898 output_trans_full_vect_name (FILE *f, automaton_t automaton)
6900 if (automaton->corresponding_automaton_decl == NULL)
6901 fprintf (f, "transitions_%d", automaton->automaton_order_num);
6903 fprintf (f, "%s_transitions",
6904 automaton->corresponding_automaton_decl->name);
6907 /* Output name of comb vector of the transition table for given
6910 output_trans_comb_vect_name (FILE *f, automaton_t automaton)
6912 if (automaton->corresponding_automaton_decl == NULL)
6913 fprintf (f, "transitions_%d", automaton->automaton_order_num);
6915 fprintf (f, "%s_transitions",
6916 automaton->corresponding_automaton_decl->name);
6919 /* Output name of check vector of the transition table for given
6922 output_trans_check_vect_name (FILE *f, automaton_t automaton)
6924 if (automaton->corresponding_automaton_decl == NULL)
6925 fprintf (f, "check_%d", automaton->automaton_order_num);
6927 fprintf (f, "%s_check", automaton->corresponding_automaton_decl->name);
6930 /* Output name of base vector of the transition table for given
6933 output_trans_base_vect_name (FILE *f, automaton_t automaton)
6935 if (automaton->corresponding_automaton_decl == NULL)
6936 fprintf (f, "base_%d", automaton->automaton_order_num);
6938 fprintf (f, "%s_base", automaton->corresponding_automaton_decl->name);
6941 /* Output name of simple min issue delay table representation. */
6943 output_min_issue_delay_vect_name (FILE *f, automaton_t automaton)
6945 if (automaton->corresponding_automaton_decl == NULL)
6946 fprintf (f, "min_issue_delay_%d", automaton->automaton_order_num);
6948 fprintf (f, "%s_min_issue_delay",
6949 automaton->corresponding_automaton_decl->name);
6952 /* Output name of deadlock vector for given automaton. */
6954 output_dead_lock_vect_name (FILE *f, automaton_t automaton)
6956 if (automaton->corresponding_automaton_decl == NULL)
6957 fprintf (f, "dead_lock_%d", automaton->automaton_order_num);
6959 fprintf (f, "%s_dead_lock", automaton->corresponding_automaton_decl->name);
6962 /* Output name of reserved units table for AUTOMATON into file F. */
6964 output_reserved_units_table_name (FILE *f, automaton_t automaton)
6966 if (automaton->corresponding_automaton_decl == NULL)
6967 fprintf (f, "reserved_units_%d", automaton->automaton_order_num);
6969 fprintf (f, "%s_reserved_units",
6970 automaton->corresponding_automaton_decl->name);
6973 /* Name of the PHR interface macro. */
6974 #define CPU_UNITS_QUERY_MACRO_NAME "CPU_UNITS_QUERY"
6976 /* Names of an internal functions: */
6977 #define INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME "internal_min_issue_delay"
6979 /* This is external type of DFA(s) state. */
6980 #define STATE_TYPE_NAME "state_t"
6982 #define INTERNAL_TRANSITION_FUNC_NAME "internal_state_transition"
6984 #define INTERNAL_RESET_FUNC_NAME "internal_reset"
6986 #define INTERNAL_DEAD_LOCK_FUNC_NAME "internal_state_dead_lock_p"
6988 #define INTERNAL_INSN_LATENCY_FUNC_NAME "internal_insn_latency"
6990 /* Name of cache of insn dfa codes. */
6991 #define DFA_INSN_CODES_VARIABLE_NAME "dfa_insn_codes"
6993 /* Name of length of cache of insn dfa codes. */
6994 #define DFA_INSN_CODES_LENGTH_VARIABLE_NAME "dfa_insn_codes_length"
6996 /* Names of the PHR interface functions: */
6997 #define SIZE_FUNC_NAME "state_size"
6999 #define TRANSITION_FUNC_NAME "state_transition"
7001 #define MIN_ISSUE_DELAY_FUNC_NAME "min_issue_delay"
7003 #define MIN_INSN_CONFLICT_DELAY_FUNC_NAME "min_insn_conflict_delay"
7005 #define DEAD_LOCK_FUNC_NAME "state_dead_lock_p"
7007 #define RESET_FUNC_NAME "state_reset"
7009 #define INSN_LATENCY_FUNC_NAME "insn_latency"
7011 #define PRINT_RESERVATION_FUNC_NAME "print_reservation"
7013 #define GET_CPU_UNIT_CODE_FUNC_NAME "get_cpu_unit_code"
7015 #define CPU_UNIT_RESERVATION_P_FUNC_NAME "cpu_unit_reservation_p"
7017 #define INSN_HAS_DFA_RESERVATION_P_FUNC_NAME "insn_has_dfa_reservation_p"
7019 #define DFA_CLEAN_INSN_CACHE_FUNC_NAME "dfa_clean_insn_cache"
7021 #define DFA_CLEAR_SINGLE_INSN_CACHE_FUNC_NAME "dfa_clear_single_insn_cache"
7023 #define DFA_START_FUNC_NAME "dfa_start"
7025 #define DFA_FINISH_FUNC_NAME "dfa_finish"
7027 /* Names of parameters of the PHR interface functions. */
7028 #define STATE_NAME "state"
7030 #define INSN_PARAMETER_NAME "insn"
7032 #define INSN2_PARAMETER_NAME "insn2"
7034 #define CHIP_PARAMETER_NAME "chip"
7036 #define FILE_PARAMETER_NAME "f"
7038 #define CPU_UNIT_NAME_PARAMETER_NAME "cpu_unit_name"
7040 #define CPU_CODE_PARAMETER_NAME "cpu_unit_code"
7042 /* Names of the variables whose values are internal insn code of rtx
7044 #define INTERNAL_INSN_CODE_NAME "insn_code"
7046 #define INTERNAL_INSN2_CODE_NAME "insn2_code"
7048 /* Names of temporary variables in some functions. */
7049 #define TEMPORARY_VARIABLE_NAME "temp"
7051 #define I_VARIABLE_NAME "i"
7053 /* Name of result variable in some functions. */
7054 #define RESULT_VARIABLE_NAME "res"
7056 /* Name of function (attribute) to translate insn into internal insn
7058 #define INTERNAL_DFA_INSN_CODE_FUNC_NAME "internal_dfa_insn_code"
7060 /* Name of function (attribute) to translate insn into internal insn
7061 code with caching. */
7062 #define DFA_INSN_CODE_FUNC_NAME "dfa_insn_code"
7064 /* Output C type which is used for representation of codes of states
7067 output_state_member_type (FILE *f, automaton_t automaton)
7069 output_range_type (f, 0, automaton->achieved_states_num);
7072 /* Output definition of the structure representing current DFA(s)
7075 output_chip_definitions (void)
7077 automaton_t automaton;
7079 fprintf (output_file, "struct %s\n{\n", CHIP_NAME);
7080 for (automaton = description->first_automaton;
7082 automaton = automaton->next_automaton)
7084 fprintf (output_file, " ");
7085 output_state_member_type (output_file, automaton);
7086 fprintf (output_file, " ");
7087 output_chip_member_name (output_file, automaton);
7088 fprintf (output_file, ";\n");
7090 fprintf (output_file, "};\n\n");
7092 fprintf (output_file, "static struct %s %s;\n\n", CHIP_NAME, CHIP_NAME);
7097 /* The function outputs translate vector of internal insn code into
7098 insn equivalence class number. The equivalence class number is
7099 used to access to table and vectors representing DFA(s). */
7101 output_translate_vect (automaton_t automaton)
7105 vla_hwint_t translate_vect;
7107 translate_vect = VEC_alloc (vect_el_t, heap, description->insns_num);
7109 for (insn_value = 0; insn_value < description->insns_num; insn_value++)
7110 /* Undefined value */
7111 VEC_quick_push (vect_el_t, translate_vect,
7112 automaton->insn_equiv_classes_num);
7114 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
7115 VEC_replace (vect_el_t, translate_vect,
7116 ainsn->insn_reserv_decl->insn_num,
7117 ainsn->insn_equiv_class_num);
7119 fprintf (output_file,
7120 "/* Vector translating external insn codes to internal ones.*/\n");
7121 fprintf (output_file, "static const ");
7122 output_range_type (output_file, 0, automaton->insn_equiv_classes_num);
7123 fprintf (output_file, " ");
7124 output_translate_vect_name (output_file, automaton);
7125 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7126 output_vect (translate_vect);
7127 fprintf (output_file, "};\n\n");
7128 VEC_free (vect_el_t, heap, translate_vect);
7131 /* The value in a table state x ainsn -> something which represents
7133 static int undefined_vect_el_value;
7135 /* The following function returns nonzero value if the best
7136 representation of the table is comb vector. */
7138 comb_vect_p (state_ainsn_table_t tab)
7140 return (2 * VEC_length (vect_el_t, tab->full_vect)
7141 > 5 * VEC_length (vect_el_t, tab->comb_vect));
7144 /* The following function creates new table for AUTOMATON. */
7145 static state_ainsn_table_t
7146 create_state_ainsn_table (automaton_t automaton)
7148 state_ainsn_table_t tab;
7149 int full_vect_length;
7152 tab = XCREATENODE (struct state_ainsn_table);
7153 tab->automaton = automaton;
7155 tab->comb_vect = VEC_alloc (vect_el_t, heap, 10000);
7156 tab->check_vect = VEC_alloc (vect_el_t, heap, 10000);
7159 VEC_safe_grow (vect_el_t, heap, tab->base_vect,
7160 automaton->achieved_states_num);
7162 full_vect_length = (automaton->insn_equiv_classes_num
7163 * automaton->achieved_states_num);
7164 tab->full_vect = VEC_alloc (vect_el_t, heap, full_vect_length);
7165 for (i = 0; i < full_vect_length; i++)
7166 VEC_quick_push (vect_el_t, tab->full_vect, undefined_vect_el_value);
7168 tab->min_base_vect_el_value = 0;
7169 tab->max_base_vect_el_value = 0;
7170 tab->min_comb_vect_el_value = 0;
7171 tab->max_comb_vect_el_value = 0;
7175 /* The following function outputs the best C representation of the
7176 table TAB of given TABLE_NAME. */
7178 output_state_ainsn_table (state_ainsn_table_t tab, const char *table_name,
7179 void (*output_full_vect_name_func) (FILE *, automaton_t),
7180 void (*output_comb_vect_name_func) (FILE *, automaton_t),
7181 void (*output_check_vect_name_func) (FILE *, automaton_t),
7182 void (*output_base_vect_name_func) (FILE *, automaton_t))
7184 if (!comb_vect_p (tab))
7186 fprintf (output_file, "/* Vector for %s. */\n", table_name);
7187 fprintf (output_file, "static const ");
7188 output_range_type (output_file, tab->min_comb_vect_el_value,
7189 tab->max_comb_vect_el_value);
7190 fprintf (output_file, " ");
7191 (*output_full_vect_name_func) (output_file, tab->automaton);
7192 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7193 output_vect (tab->full_vect);
7194 fprintf (output_file, "};\n\n");
7198 fprintf (output_file, "/* Comb vector for %s. */\n", table_name);
7199 fprintf (output_file, "static const ");
7200 output_range_type (output_file, tab->min_comb_vect_el_value,
7201 tab->max_comb_vect_el_value);
7202 fprintf (output_file, " ");
7203 (*output_comb_vect_name_func) (output_file, tab->automaton);
7204 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7205 output_vect (tab->comb_vect);
7206 fprintf (output_file, "};\n\n");
7207 fprintf (output_file, "/* Check vector for %s. */\n", table_name);
7208 fprintf (output_file, "static const ");
7209 output_range_type (output_file, 0, tab->automaton->achieved_states_num);
7210 fprintf (output_file, " ");
7211 (*output_check_vect_name_func) (output_file, tab->automaton);
7212 fprintf (output_file, "[] = {\n");
7213 output_vect (tab->check_vect);
7214 fprintf (output_file, "};\n\n");
7215 fprintf (output_file, "/* Base vector for %s. */\n", table_name);
7216 fprintf (output_file, "static const ");
7217 output_range_type (output_file, tab->min_base_vect_el_value,
7218 tab->max_base_vect_el_value);
7219 fprintf (output_file, " ");
7220 (*output_base_vect_name_func) (output_file, tab->automaton);
7221 fprintf (output_file, "[] = {\n");
7222 output_vect (tab->base_vect);
7223 fprintf (output_file, "};\n\n");
7227 /* The following function adds vector VECT to table TAB as its line
7228 with number VECT_NUM. */
7230 add_vect (state_ainsn_table_t tab, int vect_num, vla_hwint_t vect)
7233 size_t real_vect_length;
7234 int comb_vect_index;
7235 int comb_vect_els_num;
7237 int first_unempty_vect_index;
7238 int additional_els_num;
7242 unsigned long vect_mask, comb_vect_mask;
7244 vect_length = VEC_length (vect_el_t, vect);
7245 gcc_assert (vect_length);
7246 gcc_assert (VEC_last (vect_el_t, vect) != undefined_vect_el_value);
7247 real_vect_length = tab->automaton->insn_equiv_classes_num;
7248 /* Form full vector in the table: */
7250 size_t full_base = tab->automaton->insn_equiv_classes_num * vect_num;
7251 if (VEC_length (vect_el_t, tab->full_vect) < full_base + vect_length)
7252 VEC_safe_grow (vect_el_t, heap, tab->full_vect,
7253 full_base + vect_length);
7254 for (i = 0; i < vect_length; i++)
7255 VEC_replace (vect_el_t, tab->full_vect, full_base + i,
7256 VEC_index (vect_el_t, vect, i));
7258 /* Form comb vector in the table: */
7259 gcc_assert (VEC_length (vect_el_t, tab->comb_vect)
7260 == VEC_length (vect_el_t, tab->check_vect));
7262 comb_vect_els_num = VEC_length (vect_el_t, tab->comb_vect);
7263 for (first_unempty_vect_index = 0;
7264 first_unempty_vect_index < vect_length;
7265 first_unempty_vect_index++)
7266 if (VEC_index (vect_el_t, vect, first_unempty_vect_index)
7267 != undefined_vect_el_value)
7270 /* Search for the place in comb vect for the inserted vect. */
7273 if (vect_length - first_unempty_vect_index >= SIZEOF_LONG * CHAR_BIT)
7275 for (comb_vect_index = 0;
7276 comb_vect_index < comb_vect_els_num;
7279 for (vect_index = first_unempty_vect_index;
7280 vect_index < vect_length
7281 && vect_index + comb_vect_index < comb_vect_els_num;
7283 if (VEC_index (vect_el_t, vect, vect_index)
7284 != undefined_vect_el_value
7285 && (VEC_index (vect_el_t, tab->comb_vect,
7286 vect_index + comb_vect_index)
7287 != undefined_vect_el_value))
7289 if (vect_index >= vect_length
7290 || vect_index + comb_vect_index >= comb_vect_els_num)
7298 for (vect_index = first_unempty_vect_index;
7299 vect_index < vect_length;
7302 vect_mask = vect_mask << 1;
7303 if (VEC_index (vect_el_t, vect, vect_index) != undefined_vect_el_value)
7307 /* Search for the place in comb vect for the inserted vect. */
7308 comb_vect_index = 0;
7309 if (comb_vect_els_num == 0)
7313 for (vect_index = first_unempty_vect_index;
7314 vect_index < vect_length && vect_index < comb_vect_els_num;
7317 comb_vect_mask <<= 1;
7318 if (vect_index + comb_vect_index < comb_vect_els_num
7319 && VEC_index (vect_el_t, tab->comb_vect, vect_index + comb_vect_index)
7320 != undefined_vect_el_value)
7321 comb_vect_mask |= 1;
7323 if ((vect_mask & comb_vect_mask) == 0)
7326 for (comb_vect_index = 1, i = vect_length; i < comb_vect_els_num;
7327 comb_vect_index++, i++)
7329 comb_vect_mask = (comb_vect_mask << 1) | 1;
7330 comb_vect_mask ^= (VEC_index (vect_el_t, tab->comb_vect, i)
7331 == undefined_vect_el_value);
7332 if ((vect_mask & comb_vect_mask) == 0)
7335 for ( ; comb_vect_index < comb_vect_els_num; comb_vect_index++)
7337 comb_vect_mask <<= 1;
7338 if ((vect_mask & comb_vect_mask) == 0)
7343 /* Slot was found. */
7344 additional_els_num = comb_vect_index + real_vect_length - comb_vect_els_num;
7345 if (additional_els_num < 0)
7346 additional_els_num = 0;
7347 /* Expand comb and check vectors. */
7348 vect_el = undefined_vect_el_value;
7349 no_state_value = tab->automaton->achieved_states_num;
7350 while (additional_els_num > 0)
7352 VEC_safe_push (vect_el_t, heap, tab->comb_vect, vect_el);
7353 VEC_safe_push (vect_el_t, heap, tab->check_vect, no_state_value);
7354 additional_els_num--;
7356 gcc_assert (VEC_length (vect_el_t, tab->comb_vect)
7357 >= comb_vect_index + real_vect_length);
7358 /* Fill comb and check vectors. */
7359 for (vect_index = 0; vect_index < vect_length; vect_index++)
7360 if (VEC_index (vect_el_t, vect, vect_index) != undefined_vect_el_value)
7362 vect_el_t x = VEC_index (vect_el_t, vect, vect_index);
7363 gcc_assert (VEC_index (vect_el_t, tab->comb_vect,
7364 comb_vect_index + vect_index)
7365 == undefined_vect_el_value);
7366 gcc_assert (x >= 0);
7367 if (tab->max_comb_vect_el_value < x)
7368 tab->max_comb_vect_el_value = x;
7369 if (tab->min_comb_vect_el_value > x)
7370 tab->min_comb_vect_el_value = x;
7371 VEC_replace (vect_el_t, tab->comb_vect,
7372 comb_vect_index + vect_index, x);
7373 VEC_replace (vect_el_t, tab->check_vect,
7374 comb_vect_index + vect_index, vect_num);
7376 if (tab->max_comb_vect_el_value < undefined_vect_el_value)
7377 tab->max_comb_vect_el_value = undefined_vect_el_value;
7378 if (tab->min_comb_vect_el_value > undefined_vect_el_value)
7379 tab->min_comb_vect_el_value = undefined_vect_el_value;
7380 if (tab->max_base_vect_el_value < comb_vect_index)
7381 tab->max_base_vect_el_value = comb_vect_index;
7382 if (tab->min_base_vect_el_value > comb_vect_index)
7383 tab->min_base_vect_el_value = comb_vect_index;
7385 VEC_replace (vect_el_t, tab->base_vect, vect_num, comb_vect_index);
7388 /* Return number of out arcs of STATE. */
7390 out_state_arcs_num (const_state_t state)
7396 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
7398 gcc_assert (arc->insn);
7399 if (arc->insn->first_ainsn_with_given_equivalence_num)
7405 /* Compare number of possible transitions from the states. */
7407 compare_transition_els_num (const void *state_ptr_1,
7408 const void *state_ptr_2)
7410 const int transition_els_num_1
7411 = out_state_arcs_num (*(const_state_t const*) state_ptr_1);
7412 const int transition_els_num_2
7413 = out_state_arcs_num (*(const_state_t const*) state_ptr_2);
7415 if (transition_els_num_1 < transition_els_num_2)
7417 else if (transition_els_num_1 == transition_els_num_2)
7423 /* The function adds element EL_VALUE to vector VECT for a table state
7426 add_vect_el (vla_hwint_t *vect, ainsn_t ainsn, int el_value)
7428 int equiv_class_num;
7432 equiv_class_num = ainsn->insn_equiv_class_num;
7433 for (vect_index = VEC_length (vect_el_t, *vect);
7434 vect_index <= equiv_class_num;
7436 VEC_safe_push (vect_el_t, heap, *vect, undefined_vect_el_value);
7437 VEC_replace (vect_el_t, *vect, equiv_class_num, el_value);
7440 /* This is for forming vector of states of an automaton. */
7441 static VEC(state_t, heap) *output_states_vect;
7443 /* The function is called by function pass_states. The function adds
7444 STATE to `output_states_vect'. */
7446 add_states_vect_el (state_t state)
7448 VEC_safe_push (state_t, heap, output_states_vect, state);
7451 /* Form and output vectors (comb, check, base or full vector)
7452 representing transition table of AUTOMATON. */
7454 output_trans_table (automaton_t automaton)
7458 vla_hwint_t transition_vect = 0;
7460 undefined_vect_el_value = automaton->achieved_states_num;
7461 automaton->trans_table = create_state_ainsn_table (automaton);
7462 /* Create vect of pointers to states ordered by num of transitions
7463 from the state (state with the maximum num is the first). */
7464 output_states_vect = 0;
7465 pass_states (automaton, add_states_vect_el);
7466 qsort (VEC_address (state_t, output_states_vect),
7467 VEC_length (state_t, output_states_vect),
7468 sizeof (state_t), compare_transition_els_num);
7470 for (i = 0; i < VEC_length (state_t, output_states_vect); i++)
7472 VEC_truncate (vect_el_t, transition_vect, 0);
7473 for (arc = first_out_arc (VEC_index (state_t, output_states_vect, i));
7475 arc = next_out_arc (arc))
7477 gcc_assert (arc->insn);
7478 if (arc->insn->first_ainsn_with_given_equivalence_num)
7479 add_vect_el (&transition_vect, arc->insn,
7480 arc->to_state->order_state_num);
7482 add_vect (automaton->trans_table,
7483 VEC_index (state_t, output_states_vect, i)->order_state_num,
7486 output_state_ainsn_table
7487 (automaton->trans_table, "state transitions",
7488 output_trans_full_vect_name, output_trans_comb_vect_name,
7489 output_trans_check_vect_name, output_trans_base_vect_name);
7491 VEC_free (state_t, heap, output_states_vect);
7492 VEC_free (vect_el_t, heap, transition_vect);
7495 /* The current number of passing states to find minimal issue delay
7496 value for an ainsn and state. */
7497 static int curr_state_pass_num;
7499 /* This recursive function passes states to find minimal issue delay
7500 value for AINSN. The state being visited is STATE. The function
7501 returns minimal issue delay value for AINSN in STATE or -1 if we
7502 enter into a loop. */
7504 min_issue_delay_pass_states (state_t state, ainsn_t ainsn)
7507 int min_insn_issue_delay, insn_issue_delay;
7509 if (state->state_pass_num == curr_state_pass_num
7510 || state->min_insn_issue_delay != -1)
7511 /* We've entered into a loop or already have the correct value for
7512 given state and ainsn. */
7513 return state->min_insn_issue_delay;
7514 state->state_pass_num = curr_state_pass_num;
7515 min_insn_issue_delay = -1;
7516 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
7517 if (arc->insn == ainsn)
7519 min_insn_issue_delay = 0;
7524 insn_issue_delay = min_issue_delay_pass_states (arc->to_state, ainsn);
7525 if (insn_issue_delay != -1)
7527 if (arc->insn->insn_reserv_decl
7528 == DECL_INSN_RESERV (advance_cycle_insn_decl))
7530 if (min_insn_issue_delay == -1
7531 || min_insn_issue_delay > insn_issue_delay)
7533 min_insn_issue_delay = insn_issue_delay;
7534 if (insn_issue_delay == 0)
7539 return min_insn_issue_delay;
7542 /* The function searches minimal issue delay value for AINSN in STATE.
7543 The function can return negative value if we can not issue AINSN. We
7544 will report about it later. */
7546 min_issue_delay (state_t state, ainsn_t ainsn)
7548 curr_state_pass_num++;
7549 state->min_insn_issue_delay = min_issue_delay_pass_states (state, ainsn);
7550 return state->min_insn_issue_delay;
7553 /* The function initiates code for finding minimal issue delay values.
7554 It should be called only once. */
7556 initiate_min_issue_delay_pass_states (void)
7558 curr_state_pass_num = 0;
7561 /* Form and output vectors representing minimal issue delay table of
7562 AUTOMATON. The table is state x ainsn -> minimal issue delay of
7565 output_min_issue_delay_table (automaton_t automaton)
7567 vla_hwint_t min_issue_delay_vect;
7568 vla_hwint_t compressed_min_issue_delay_vect;
7569 vect_el_t min_delay;
7571 size_t i, min_issue_delay_len;
7572 size_t compressed_min_issue_delay_len;
7575 /* Create vect of pointers to states ordered by num of transitions
7576 from the state (state with the maximum num is the first). */
7577 output_states_vect = 0;
7578 pass_states (automaton, add_states_vect_el);
7580 min_issue_delay_len = (VEC_length (state_t, output_states_vect)
7581 * automaton->insn_equiv_classes_num);
7582 min_issue_delay_vect = VEC_alloc (vect_el_t, heap, min_issue_delay_len);
7583 for (i = 0; i < min_issue_delay_len; i++)
7584 VEC_quick_push (vect_el_t, min_issue_delay_vect, 0);
7586 automaton->max_min_delay = 0;
7587 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
7588 if (ainsn->first_ainsn_with_given_equivalence_num)
7590 for (i = 0; i < VEC_length (state_t, output_states_vect); i++)
7591 VEC_index (state_t, output_states_vect, i)->min_insn_issue_delay = -1;
7592 for (i = 0; i < VEC_length (state_t, output_states_vect); i++)
7594 state_t s = VEC_index (state_t, output_states_vect, i);
7595 min_delay = min_issue_delay (s, ainsn);
7596 if (automaton->max_min_delay < min_delay)
7597 automaton->max_min_delay = min_delay;
7598 VEC_replace (vect_el_t, min_issue_delay_vect,
7600 * automaton->insn_equiv_classes_num
7601 + ainsn->insn_equiv_class_num,
7605 fprintf (output_file, "/* Vector of min issue delay of insns. */\n");
7606 fprintf (output_file, "static const ");
7607 output_range_type (output_file, 0, automaton->max_min_delay);
7608 fprintf (output_file, " ");
7609 output_min_issue_delay_vect_name (output_file, automaton);
7610 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7611 /* Compress the vector. */
7612 if (automaton->max_min_delay < 2)
7614 else if (automaton->max_min_delay < 4)
7616 else if (automaton->max_min_delay < 16)
7620 automaton->min_issue_delay_table_compression_factor = cfactor;
7622 compressed_min_issue_delay_len = (min_issue_delay_len+cfactor-1) / cfactor;
7623 compressed_min_issue_delay_vect
7624 = VEC_alloc (vect_el_t, heap, compressed_min_issue_delay_len);
7626 for (i = 0; i < compressed_min_issue_delay_len; i++)
7627 VEC_quick_push (vect_el_t, compressed_min_issue_delay_vect, 0);
7629 for (i = 0; i < min_issue_delay_len; i++)
7631 size_t ci = i / cfactor;
7632 vect_el_t x = VEC_index (vect_el_t, min_issue_delay_vect, i);
7633 vect_el_t cx = VEC_index (vect_el_t, compressed_min_issue_delay_vect, ci);
7635 cx |= x << (8 - (i % cfactor + 1) * (8 / cfactor));
7636 VEC_replace (vect_el_t, compressed_min_issue_delay_vect, ci, cx);
7638 output_vect (compressed_min_issue_delay_vect);
7639 fprintf (output_file, "};\n\n");
7640 VEC_free (state_t, heap, output_states_vect);
7641 VEC_free (vect_el_t, heap, min_issue_delay_vect);
7642 VEC_free (vect_el_t, heap, compressed_min_issue_delay_vect);
7645 /* Form and output vector representing the locked states of
7648 output_dead_lock_vect (automaton_t automaton)
7652 vla_hwint_t dead_lock_vect = 0;
7654 /* Create vect of pointers to states ordered by num of
7655 transitions from the state (state with the maximum num is the
7657 automaton->locked_states = 0;
7658 output_states_vect = 0;
7659 pass_states (automaton, add_states_vect_el);
7661 VEC_safe_grow (vect_el_t, heap, dead_lock_vect,
7662 VEC_length (state_t, output_states_vect));
7663 for (i = 0; i < VEC_length (state_t, output_states_vect); i++)
7665 state_t s = VEC_index (state_t, output_states_vect, i);
7666 arc = first_out_arc (s);
7668 if (next_out_arc (arc) == NULL
7669 && (arc->insn->insn_reserv_decl
7670 == DECL_INSN_RESERV (advance_cycle_insn_decl)))
7672 VEC_replace (vect_el_t, dead_lock_vect, s->order_state_num, 1);
7673 automaton->locked_states++;
7676 VEC_replace (vect_el_t, dead_lock_vect, s->order_state_num, 0);
7678 if (automaton->locked_states == 0)
7681 fprintf (output_file, "/* Vector for locked state flags. */\n");
7682 fprintf (output_file, "static const ");
7683 output_range_type (output_file, 0, 1);
7684 fprintf (output_file, " ");
7685 output_dead_lock_vect_name (output_file, automaton);
7686 fprintf (output_file, "[] = {\n");
7687 output_vect (dead_lock_vect);
7688 fprintf (output_file, "};\n\n");
7689 VEC_free (state_t, heap, output_states_vect);
7690 VEC_free (vect_el_t, heap, dead_lock_vect);
7693 /* Form and output vector representing reserved units of the states of
7696 output_reserved_units_table (automaton_t automaton)
7698 vla_hwint_t reserved_units_table = 0;
7699 int state_byte_size;
7700 int reserved_units_size;
7704 if (description->query_units_num == 0)
7707 /* Create vect of pointers to states. */
7708 output_states_vect = 0;
7709 pass_states (automaton, add_states_vect_el);
7710 /* Create vector. */
7711 state_byte_size = (description->query_units_num + 7) / 8;
7712 reserved_units_size = (VEC_length (state_t, output_states_vect)
7715 reserved_units_table = VEC_alloc (vect_el_t, heap, reserved_units_size);
7717 for (i = 0; i < reserved_units_size; i++)
7718 VEC_quick_push (vect_el_t, reserved_units_table, 0);
7719 for (n = 0; n < VEC_length (state_t, output_states_vect); n++)
7721 state_t s = VEC_index (state_t, output_states_vect, n);
7722 for (i = 0; i < description->units_num; i++)
7723 if (units_array [i]->query_p
7724 && first_cycle_unit_presence (s, i))
7726 int ri = (s->order_state_num * state_byte_size
7727 + units_array [i]->query_num / 8);
7728 vect_el_t x = VEC_index (vect_el_t, reserved_units_table, ri);
7730 x += 1 << (units_array [i]->query_num % 8);
7731 VEC_replace (vect_el_t, reserved_units_table, ri, x);
7734 fprintf (output_file, "\n#if %s\n", CPU_UNITS_QUERY_MACRO_NAME);
7735 fprintf (output_file, "/* Vector for reserved units of states. */\n");
7736 fprintf (output_file, "static const ");
7737 output_range_type (output_file, 0, 255);
7738 fprintf (output_file, " ");
7739 output_reserved_units_table_name (output_file, automaton);
7740 fprintf (output_file, "[] = {\n");
7741 output_vect (reserved_units_table);
7742 fprintf (output_file, "};\n#endif /* #if %s */\n\n",
7743 CPU_UNITS_QUERY_MACRO_NAME);
7745 VEC_free (state_t, heap, output_states_vect);
7746 VEC_free (vect_el_t, heap, reserved_units_table);
7749 /* The function outputs all tables representing DFA(s) used for fast
7750 pipeline hazards recognition. */
7752 output_tables (void)
7754 automaton_t automaton;
7756 initiate_min_issue_delay_pass_states ();
7757 for (automaton = description->first_automaton;
7759 automaton = automaton->next_automaton)
7761 output_translate_vect (automaton);
7762 output_trans_table (automaton);
7763 output_min_issue_delay_table (automaton);
7764 output_dead_lock_vect (automaton);
7765 output_reserved_units_table (automaton);
7767 fprintf (output_file, "\n#define %s %d\n\n", ADVANCE_CYCLE_VALUE_NAME,
7768 DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
7771 /* The function outputs definition and value of PHR interface variable
7772 `max_insn_queue_index'. Its value is not less than maximal queue
7773 length needed for the insn scheduler. */
7775 output_max_insn_queue_index_def (void)
7777 int i, max, latency;
7780 max = description->max_insn_reserv_cycles;
7781 for (i = 0; i < description->decls_num; i++)
7783 decl = description->decls [i];
7784 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
7786 latency = DECL_INSN_RESERV (decl)->default_latency;
7790 else if (decl->mode == dm_bypass)
7792 latency = DECL_BYPASS (decl)->latency;
7797 for (i = 0; (1 << i) <= max; i++)
7799 gcc_assert (i >= 0);
7800 fprintf (output_file, "\nconst int max_insn_queue_index = %d;\n\n",
7804 /* The function outputs switch cases for insn reservations using
7805 function *output_automata_list_code. */
7807 output_insn_code_cases (void (*output_automata_list_code)
7808 (automata_list_el_t))
7813 for (i = 0; i < description->decls_num; i++)
7815 decl = description->decls [i];
7816 if (decl->mode == dm_insn_reserv)
7817 DECL_INSN_RESERV (decl)->processed_p = FALSE;
7819 for (i = 0; i < description->decls_num; i++)
7821 decl = description->decls [i];
7822 if (decl->mode == dm_insn_reserv
7823 && !DECL_INSN_RESERV (decl)->processed_p)
7825 for (j = i; j < description->decls_num; j++)
7827 decl2 = description->decls [j];
7828 if (decl2->mode == dm_insn_reserv
7829 && (DECL_INSN_RESERV (decl2)->important_automata_list
7830 == DECL_INSN_RESERV (decl)->important_automata_list))
7832 DECL_INSN_RESERV (decl2)->processed_p = TRUE;
7833 fprintf (output_file, " case %d: /* %s */\n",
7834 DECL_INSN_RESERV (decl2)->insn_num,
7835 DECL_INSN_RESERV (decl2)->name);
7838 (*output_automata_list_code)
7839 (DECL_INSN_RESERV (decl)->important_automata_list);
7845 /* The function outputs a code for evaluation of a minimal delay of
7846 issue of insns which have reservations in given AUTOMATA_LIST. */
7848 output_automata_list_min_issue_delay_code (automata_list_el_t automata_list)
7850 automata_list_el_t el;
7851 automaton_t automaton;
7853 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
7855 automaton = el->automaton;
7856 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
7857 output_min_issue_delay_vect_name (output_file, automaton);
7858 fprintf (output_file,
7859 (automaton->min_issue_delay_table_compression_factor != 1
7861 output_translate_vect_name (output_file, automaton);
7862 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
7863 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7864 output_chip_member_name (output_file, automaton);
7865 fprintf (output_file, " * %d", automaton->insn_equiv_classes_num);
7866 if (automaton->min_issue_delay_table_compression_factor == 1)
7867 fprintf (output_file, "];\n");
7870 fprintf (output_file, ") / %d];\n",
7871 automaton->min_issue_delay_table_compression_factor);
7872 fprintf (output_file, " %s = (%s >> (8 - (",
7873 TEMPORARY_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
7874 output_translate_vect_name (output_file, automaton);
7876 (output_file, " [%s] %% %d + 1) * %d)) & %d;\n",
7877 INTERNAL_INSN_CODE_NAME,
7878 automaton->min_issue_delay_table_compression_factor,
7879 8 / automaton->min_issue_delay_table_compression_factor,
7880 (1 << (8 / automaton->min_issue_delay_table_compression_factor))
7883 if (el == automata_list)
7884 fprintf (output_file, " %s = %s;\n",
7885 RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
7888 fprintf (output_file, " if (%s > %s)\n",
7889 TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
7890 fprintf (output_file, " %s = %s;\n",
7891 RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
7894 fprintf (output_file, " break;\n\n");
7897 /* Output function `internal_min_issue_delay'. */
7899 output_internal_min_issue_delay_func (void)
7901 fprintf (output_file,
7902 "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
7903 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7904 CHIP_NAME, CHIP_PARAMETER_NAME);
7905 fprintf (output_file, "{\n int %s ATTRIBUTE_UNUSED;\n int %s = -1;\n",
7906 TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
7907 fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
7908 output_insn_code_cases (output_automata_list_min_issue_delay_code);
7909 fprintf (output_file,
7910 "\n default:\n %s = -1;\n break;\n }\n",
7911 RESULT_VARIABLE_NAME);
7912 fprintf (output_file, " return %s;\n", RESULT_VARIABLE_NAME);
7913 fprintf (output_file, "}\n\n");
7916 /* The function outputs a code changing state after issue of insns
7917 which have reservations in given AUTOMATA_LIST. */
7919 output_automata_list_transition_code (automata_list_el_t automata_list)
7921 automata_list_el_t el, next_el;
7923 fprintf (output_file, " {\n");
7924 if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
7925 for (el = automata_list;; el = next_el)
7927 next_el = el->next_automata_list_el;
7928 if (next_el == NULL)
7930 fprintf (output_file, " ");
7931 output_state_member_type (output_file, el->automaton);
7932 fprintf (output_file, " ");
7933 output_temp_chip_member_name (output_file, el->automaton);
7934 fprintf (output_file, ";\n");
7936 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
7937 if (comb_vect_p (el->automaton->trans_table))
7939 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
7940 output_trans_base_vect_name (output_file, el->automaton);
7941 fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
7942 output_chip_member_name (output_file, el->automaton);
7943 fprintf (output_file, "] + ");
7944 output_translate_vect_name (output_file, el->automaton);
7945 fprintf (output_file, " [%s];\n", INTERNAL_INSN_CODE_NAME);
7946 fprintf (output_file, " if (");
7947 output_trans_check_vect_name (output_file, el->automaton);
7948 fprintf (output_file, " [%s] != %s->",
7949 TEMPORARY_VARIABLE_NAME, CHIP_PARAMETER_NAME);
7950 output_chip_member_name (output_file, el->automaton);
7951 fprintf (output_file, ")\n");
7952 fprintf (output_file, " return %s (%s, %s);\n",
7953 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7954 CHIP_PARAMETER_NAME);
7955 fprintf (output_file, " else\n");
7956 fprintf (output_file, " ");
7957 if (el->next_automata_list_el != NULL)
7958 output_temp_chip_member_name (output_file, el->automaton);
7961 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7962 output_chip_member_name (output_file, el->automaton);
7964 fprintf (output_file, " = ");
7965 output_trans_comb_vect_name (output_file, el->automaton);
7966 fprintf (output_file, " [%s];\n", TEMPORARY_VARIABLE_NAME);
7970 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
7971 output_trans_full_vect_name (output_file, el->automaton);
7972 fprintf (output_file, " [");
7973 output_translate_vect_name (output_file, el->automaton);
7974 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
7975 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7976 output_chip_member_name (output_file, el->automaton);
7977 fprintf (output_file, " * %d];\n",
7978 el->automaton->insn_equiv_classes_num);
7979 fprintf (output_file, " if (%s >= %d)\n",
7980 TEMPORARY_VARIABLE_NAME, el->automaton->achieved_states_num);
7981 fprintf (output_file, " return %s (%s, %s);\n",
7982 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7983 CHIP_PARAMETER_NAME);
7984 fprintf (output_file, " else\n ");
7985 if (el->next_automata_list_el != NULL)
7986 output_temp_chip_member_name (output_file, el->automaton);
7989 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7990 output_chip_member_name (output_file, el->automaton);
7992 fprintf (output_file, " = %s;\n", TEMPORARY_VARIABLE_NAME);
7994 if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
7995 for (el = automata_list;; el = next_el)
7997 next_el = el->next_automata_list_el;
7998 if (next_el == NULL)
8000 fprintf (output_file, " %s->", CHIP_PARAMETER_NAME);
8001 output_chip_member_name (output_file, el->automaton);
8002 fprintf (output_file, " = ");
8003 output_temp_chip_member_name (output_file, el->automaton);
8004 fprintf (output_file, ";\n");
8006 fprintf (output_file, " return -1;\n");
8007 fprintf (output_file, " }\n");
8010 /* Output function `internal_state_transition'. */
8012 output_internal_trans_func (void)
8014 fprintf (output_file,
8015 "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
8016 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8017 CHIP_NAME, CHIP_PARAMETER_NAME);
8018 fprintf (output_file, "{\n int %s ATTRIBUTE_UNUSED;\n", TEMPORARY_VARIABLE_NAME);
8019 fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8020 output_insn_code_cases (output_automata_list_transition_code);
8021 fprintf (output_file, "\n default:\n return -1;\n }\n");
8022 fprintf (output_file, "}\n\n");
8029 insn_code = dfa_insn_code (insn);
8030 if (insn_code > DFA__ADVANCE_CYCLE)
8034 insn_code = DFA__ADVANCE_CYCLE;
8036 where insn denotes INSN_NAME, insn_code denotes INSN_CODE_NAME, and
8037 code denotes CODE. */
8039 output_internal_insn_code_evaluation (const char *insn_name,
8040 const char *insn_code_name,
8043 fprintf (output_file, "\n if (%s != 0)\n {\n", insn_name);
8044 fprintf (output_file, " %s = %s (%s);\n", insn_code_name,
8045 DFA_INSN_CODE_FUNC_NAME, insn_name);
8046 fprintf (output_file, " if (%s > %s)\n return %d;\n",
8047 insn_code_name, ADVANCE_CYCLE_VALUE_NAME, code);
8048 fprintf (output_file, " }\n else\n %s = %s;\n\n",
8049 insn_code_name, ADVANCE_CYCLE_VALUE_NAME);
8053 /* This function outputs `dfa_insn_code' and its helper function
8054 `dfa_insn_code_enlarge'. */
8056 output_dfa_insn_code_func (void)
8058 /* Emacs c-mode gets really confused if there's a { or } in column 0
8059 inside a string, so don't do that. */
8060 fprintf (output_file, "\
8062 dfa_insn_code_enlarge (int uid)\n\
8066 %s = XRESIZEVEC (int, %s,\n\
8068 for (; i < %s; i++)\n\
8069 %s[i] = -1;\n}\n\n",
8070 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8071 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8072 DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
8073 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8074 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8075 DFA_INSN_CODES_VARIABLE_NAME);
8076 fprintf (output_file, "\
8077 static inline int\n%s (rtx %s)\n\
8079 int uid = INSN_UID (%s);\n\
8081 DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME,
8082 INSN_PARAMETER_NAME, INTERNAL_INSN_CODE_NAME);
8084 fprintf (output_file,
8085 " if (uid >= %s)\n dfa_insn_code_enlarge (uid);\n\n",
8086 DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8087 fprintf (output_file, " %s = %s[uid];\n",
8088 INTERNAL_INSN_CODE_NAME, DFA_INSN_CODES_VARIABLE_NAME);
8089 fprintf (output_file, "\
8095 INTERNAL_INSN_CODE_NAME,
8096 INTERNAL_INSN_CODE_NAME,
8097 INTERNAL_DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME,
8098 DFA_INSN_CODES_VARIABLE_NAME, INTERNAL_INSN_CODE_NAME);
8099 fprintf (output_file, " return %s;\n}\n\n", INTERNAL_INSN_CODE_NAME);
8102 /* The function outputs PHR interface function `state_transition'. */
8104 output_trans_func (void)
8106 fprintf (output_file, "int\n%s (%s %s, rtx %s)\n",
8107 TRANSITION_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME,
8108 INSN_PARAMETER_NAME);
8109 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
8110 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8111 INTERNAL_INSN_CODE_NAME, -1);
8112 fprintf (output_file, " return %s (%s, (struct %s *) %s);\n}\n\n",
8113 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME, STATE_NAME);
8116 /* Output function `min_issue_delay'. */
8118 output_min_issue_delay_func (void)
8120 fprintf (output_file, "int\n%s (%s %s, rtx %s)\n",
8121 MIN_ISSUE_DELAY_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME,
8122 INSN_PARAMETER_NAME);
8123 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
8124 fprintf (output_file, "\n if (%s != 0)\n {\n", INSN_PARAMETER_NAME);
8125 fprintf (output_file, " %s = %s (%s);\n", INTERNAL_INSN_CODE_NAME,
8126 DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME);
8127 fprintf (output_file, " if (%s > %s)\n return 0;\n",
8128 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8129 fprintf (output_file, " }\n else\n %s = %s;\n",
8130 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8131 fprintf (output_file, "\n return %s (%s, (struct %s *) %s);\n",
8132 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8133 CHIP_NAME, STATE_NAME);
8134 fprintf (output_file, "}\n\n");
8137 /* Output function `internal_dead_lock'. */
8139 output_internal_dead_lock_func (void)
8141 automaton_t automaton;
8143 fprintf (output_file, "static int\n%s (struct %s *ARG_UNUSED (%s))\n",
8144 INTERNAL_DEAD_LOCK_FUNC_NAME, CHIP_NAME, CHIP_PARAMETER_NAME);
8145 fprintf (output_file, "{\n");
8146 for (automaton = description->first_automaton;
8148 automaton = automaton->next_automaton)
8149 if (automaton->locked_states)
8151 fprintf (output_file, " if (");
8152 output_dead_lock_vect_name (output_file, automaton);
8153 fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
8154 output_chip_member_name (output_file, automaton);
8155 fprintf (output_file, "])\n return 1/* TRUE */;\n");
8157 fprintf (output_file, " return 0/* FALSE */;\n}\n\n");
8160 /* The function outputs PHR interface function `state_dead_lock_p'. */
8162 output_dead_lock_func (void)
8164 fprintf (output_file, "int\n%s (%s %s)\n",
8165 DEAD_LOCK_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME);
8166 fprintf (output_file, "{\n return %s ((struct %s *) %s);\n}\n\n",
8167 INTERNAL_DEAD_LOCK_FUNC_NAME, CHIP_NAME, STATE_NAME);
8170 /* Output function `internal_reset'. */
8172 output_internal_reset_func (void)
8174 fprintf (output_file, "static inline void\n%s (struct %s *%s)\n",
8175 INTERNAL_RESET_FUNC_NAME, CHIP_NAME, CHIP_PARAMETER_NAME);
8176 fprintf (output_file, "{\n memset (%s, 0, sizeof (struct %s));\n}\n\n",
8177 CHIP_PARAMETER_NAME, CHIP_NAME);
8180 /* The function outputs PHR interface function `state_size'. */
8182 output_size_func (void)
8184 fprintf (output_file, "int\n%s (void)\n", SIZE_FUNC_NAME);
8185 fprintf (output_file, "{\n return sizeof (struct %s);\n}\n\n", CHIP_NAME);
8188 /* The function outputs PHR interface function `state_reset'. */
8190 output_reset_func (void)
8192 fprintf (output_file, "void\n%s (%s %s)\n",
8193 RESET_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME);
8194 fprintf (output_file, "{\n %s ((struct %s *) %s);\n}\n\n", INTERNAL_RESET_FUNC_NAME,
8195 CHIP_NAME, STATE_NAME);
8198 /* Output function `min_insn_conflict_delay'. */
8200 output_min_insn_conflict_delay_func (void)
8202 fprintf (output_file,
8203 "int\n%s (%s %s, rtx %s, rtx %s)\n",
8204 MIN_INSN_CONFLICT_DELAY_FUNC_NAME, STATE_TYPE_NAME,
8205 STATE_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8206 fprintf (output_file, "{\n struct %s %s;\n int %s, %s, transition;\n",
8207 CHIP_NAME, CHIP_NAME, INTERNAL_INSN_CODE_NAME,
8208 INTERNAL_INSN2_CODE_NAME);
8209 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8210 INTERNAL_INSN_CODE_NAME, 0);
8211 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
8212 INTERNAL_INSN2_CODE_NAME, 0);
8213 fprintf (output_file, " memcpy (&%s, %s, sizeof (%s));\n",
8214 CHIP_NAME, STATE_NAME, CHIP_NAME);
8215 fprintf (output_file, " %s (&%s);\n", INTERNAL_RESET_FUNC_NAME, CHIP_NAME);
8216 fprintf (output_file, " transition = %s (%s, &%s);\n",
8217 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME);
8218 fprintf (output_file, " gcc_assert (transition <= 0);\n");
8219 fprintf (output_file, " return %s (%s, &%s);\n",
8220 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN2_CODE_NAME,
8222 fprintf (output_file, "}\n\n");
8225 /* Output the array holding default latency values. These are used in
8226 insn_latency and maximal_insn_latency function implementations. */
8228 output_default_latencies (void)
8232 const char *tabletype = "unsigned char";
8234 /* Find the smallest integer type that can hold all the default
8236 for (i = 0; i < description->decls_num; i++)
8237 if (description->decls[i]->mode == dm_insn_reserv)
8239 decl = description->decls[i];
8240 if (DECL_INSN_RESERV (decl)->default_latency > UCHAR_MAX
8241 && tabletype[0] != 'i') /* Don't shrink it. */
8242 tabletype = "unsigned short";
8243 if (DECL_INSN_RESERV (decl)->default_latency > USHRT_MAX)
8247 fprintf (output_file, " static const %s default_latencies[] =\n {",
8250 for (i = 0, j = 0, col = 7; i < description->decls_num; i++)
8251 if (description->decls[i]->mode == dm_insn_reserv
8252 && description->decls[i] != advance_cycle_insn_decl)
8254 if ((col = (col+1) % 8) == 0)
8255 fputs ("\n ", output_file);
8256 decl = description->decls[i];
8257 gcc_assert (j++ == DECL_INSN_RESERV (decl)->insn_num);
8258 fprintf (output_file, "% 4d,",
8259 DECL_INSN_RESERV (decl)->default_latency);
8261 gcc_assert (j == DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
8262 fputs ("\n };\n", output_file);
8265 /* Output function `internal_insn_latency'. */
8267 output_internal_insn_latency_func (void)
8271 struct bypass_decl *bypass;
8273 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",
8274 INTERNAL_INSN_LATENCY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8275 INTERNAL_INSN2_CODE_NAME, INSN_PARAMETER_NAME,
8276 INSN2_PARAMETER_NAME);
8277 fprintf (output_file, "{\n");
8279 if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8281 fputs (" return 0;\n}\n\n", output_file);
8285 fprintf (output_file, " if (%s >= %s || %s >= %s)\n return 0;\n",
8286 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8287 INTERNAL_INSN2_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8289 fprintf (output_file, " switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8290 for (i = 0; i < description->decls_num; i++)
8291 if (description->decls[i]->mode == dm_insn_reserv
8292 && DECL_INSN_RESERV (description->decls[i])->bypass_list)
8294 decl = description->decls [i];
8295 fprintf (output_file,
8296 " case %d:\n switch (%s)\n {\n",
8297 DECL_INSN_RESERV (decl)->insn_num,
8298 INTERNAL_INSN2_CODE_NAME);
8299 for (bypass = DECL_INSN_RESERV (decl)->bypass_list;
8301 bypass = bypass->next)
8303 gcc_assert (bypass->in_insn_reserv->insn_num
8304 != (DECL_INSN_RESERV
8305 (advance_cycle_insn_decl)->insn_num));
8306 fprintf (output_file, " case %d:\n",
8307 bypass->in_insn_reserv->insn_num);
8310 if (bypass->bypass_guard_name == NULL)
8312 gcc_assert (bypass->next == NULL
8313 || (bypass->in_insn_reserv
8314 != bypass->next->in_insn_reserv));
8315 fprintf (output_file, " return %d;\n",
8320 fprintf (output_file,
8321 " if (%s (%s, %s))\n",
8322 bypass->bypass_guard_name, INSN_PARAMETER_NAME,
8323 INSN2_PARAMETER_NAME);
8324 fprintf (output_file, " return %d;\n",
8327 if (bypass->next == NULL
8328 || bypass->in_insn_reserv != bypass->next->in_insn_reserv)
8330 bypass = bypass->next;
8332 if (bypass->bypass_guard_name != NULL)
8333 fprintf (output_file, " break;\n");
8335 fputs (" }\n break;\n", output_file);
8338 fprintf (output_file, " }\n return default_latencies[%s];\n}\n\n",
8339 INTERNAL_INSN_CODE_NAME);
8342 /* Output function `internal_maximum_insn_latency'. */
8344 output_internal_maximal_insn_latency_func (void)
8347 struct bypass_decl *bypass;
8351 fprintf (output_file, "static int\n%s (int %s ATTRIBUTE_UNUSED,\n\trtx %s ATTRIBUTE_UNUSED)\n",
8352 "internal_maximal_insn_latency", INTERNAL_INSN_CODE_NAME,
8353 INSN_PARAMETER_NAME);
8354 fprintf (output_file, "{\n");
8356 if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8358 fputs (" return 0;\n}\n\n", output_file);
8362 fprintf (output_file, " switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8363 for (i = 0; i < description->decls_num; i++)
8364 if (description->decls[i]->mode == dm_insn_reserv
8365 && DECL_INSN_RESERV (description->decls[i])->bypass_list)
8367 decl = description->decls [i];
8368 max = DECL_INSN_RESERV (decl)->default_latency;
8369 fprintf (output_file,
8371 DECL_INSN_RESERV (decl)->insn_num);
8372 for (bypass = DECL_INSN_RESERV (decl)->bypass_list;
8374 bypass = bypass->next)
8376 if (bypass->latency > max)
8377 max = bypass->latency;
8379 fprintf (output_file, " return %d; }\n break;\n", max);
8382 fprintf (output_file, " }\n return default_latencies[%s];\n}\n\n",
8383 INTERNAL_INSN_CODE_NAME);
8386 /* The function outputs PHR interface function `insn_latency'. */
8388 output_insn_latency_func (void)
8390 fprintf (output_file, "int\n%s (rtx %s, rtx %s)\n",
8391 INSN_LATENCY_FUNC_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8392 fprintf (output_file, "{\n int %s, %s;\n",
8393 INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME);
8394 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8395 INTERNAL_INSN_CODE_NAME, 0);
8396 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
8397 INTERNAL_INSN2_CODE_NAME, 0);
8398 fprintf (output_file, " return %s (%s, %s, %s, %s);\n}\n\n",
8399 INTERNAL_INSN_LATENCY_FUNC_NAME,
8400 INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME,
8401 INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8404 /* The function outputs PHR interface function `maximal_insn_latency'. */
8406 output_maximal_insn_latency_func (void)
8408 fprintf (output_file, "int\n%s (rtx %s)\n",
8409 "maximal_insn_latency", INSN_PARAMETER_NAME);
8410 fprintf (output_file, "{\n int %s;\n",
8411 INTERNAL_INSN_CODE_NAME);
8412 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8413 INTERNAL_INSN_CODE_NAME, 0);
8414 fprintf (output_file, " return %s (%s, %s);\n}\n\n",
8415 "internal_maximal_insn_latency",
8416 INTERNAL_INSN_CODE_NAME, INSN_PARAMETER_NAME);
8419 /* The function outputs PHR interface function `print_reservation'. */
8421 output_print_reservation_func (void)
8426 fprintf (output_file,
8427 "void\n%s (FILE *%s, rtx %s ATTRIBUTE_UNUSED)\n{\n",
8428 PRINT_RESERVATION_FUNC_NAME, FILE_PARAMETER_NAME,
8429 INSN_PARAMETER_NAME);
8431 if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8433 fprintf (output_file, " fputs (\"%s\", %s);\n}\n\n",
8434 NOTHING_NAME, FILE_PARAMETER_NAME);
8439 fputs (" static const char *const reservation_names[] =\n {",
8442 for (i = 0, j = 0; i < description->decls_num; i++)
8444 decl = description->decls [i];
8445 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
8447 gcc_assert (j == DECL_INSN_RESERV (decl)->insn_num);
8450 fprintf (output_file, "\n \"%s\",",
8451 regexp_representation (DECL_INSN_RESERV (decl)->regexp));
8452 finish_regexp_representation ();
8455 gcc_assert (j == DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
8457 fprintf (output_file, "\n \"%s\"\n };\n int %s;\n\n",
8458 NOTHING_NAME, INTERNAL_INSN_CODE_NAME);
8460 fprintf (output_file, " if (%s == 0)\n %s = %s;\n",
8461 INSN_PARAMETER_NAME,
8462 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8463 fprintf (output_file, " else\n\
8469 INTERNAL_INSN_CODE_NAME, DFA_INSN_CODE_FUNC_NAME,
8470 INSN_PARAMETER_NAME,
8471 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8472 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8474 fprintf (output_file, " fputs (reservation_names[%s], %s);\n}\n\n",
8475 INTERNAL_INSN_CODE_NAME, FILE_PARAMETER_NAME);
8478 /* The following function is used to sort unit declaration by their
8481 units_cmp (const void *unit1, const void *unit2)
8483 const_unit_decl_t const u1 = *(const_unit_decl_t const*) unit1;
8484 const_unit_decl_t const u2 = *(const_unit_decl_t const*) unit2;
8486 return strcmp (u1->name, u2->name);
8489 /* The following macro value is name of struct containing unit name
8491 #define NAME_CODE_STRUCT_NAME "name_code"
8493 /* The following macro value is name of table of struct name_code. */
8494 #define NAME_CODE_TABLE_NAME "name_code_table"
8496 /* The following macro values are member names for struct name_code. */
8497 #define NAME_MEMBER_NAME "name"
8498 #define CODE_MEMBER_NAME "code"
8500 /* The following macro values are local variable names for function
8501 `get_cpu_unit_code'. */
8502 #define CMP_VARIABLE_NAME "cmp"
8503 #define LOW_VARIABLE_NAME "l"
8504 #define MIDDLE_VARIABLE_NAME "m"
8505 #define HIGH_VARIABLE_NAME "h"
8507 /* The following function outputs function to obtain internal cpu unit
8508 code by the cpu unit name. */
8510 output_get_cpu_unit_code_func (void)
8515 fprintf (output_file, "int\n%s (const char *%s)\n",
8516 GET_CPU_UNIT_CODE_FUNC_NAME, CPU_UNIT_NAME_PARAMETER_NAME);
8517 fprintf (output_file, "{\n struct %s {const char *%s; int %s;};\n",
8518 NAME_CODE_STRUCT_NAME, NAME_MEMBER_NAME, CODE_MEMBER_NAME);
8519 fprintf (output_file, " int %s, %s, %s, %s;\n", CMP_VARIABLE_NAME,
8520 LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8521 fprintf (output_file, " static struct %s %s [] =\n {\n",
8522 NAME_CODE_STRUCT_NAME, NAME_CODE_TABLE_NAME);
8523 units = XNEWVEC (unit_decl_t, description->units_num);
8524 memcpy (units, units_array, sizeof (unit_decl_t) * description->units_num);
8525 qsort (units, description->units_num, sizeof (unit_decl_t), units_cmp);
8526 for (i = 0; i < description->units_num; i++)
8527 if (units [i]->query_p)
8528 fprintf (output_file, " {\"%s\", %d},\n",
8529 units[i]->name, units[i]->query_num);
8530 fprintf (output_file, " };\n\n");
8531 fprintf (output_file, " /* The following is binary search: */\n");
8532 fprintf (output_file, " %s = 0;\n", LOW_VARIABLE_NAME);
8533 fprintf (output_file, " %s = sizeof (%s) / sizeof (struct %s) - 1;\n",
8534 HIGH_VARIABLE_NAME, NAME_CODE_TABLE_NAME, NAME_CODE_STRUCT_NAME);
8535 fprintf (output_file, " while (%s <= %s)\n {\n",
8536 LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8537 fprintf (output_file, " %s = (%s + %s) / 2;\n",
8538 MIDDLE_VARIABLE_NAME, LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8539 fprintf (output_file, " %s = strcmp (%s, %s [%s].%s);\n",
8540 CMP_VARIABLE_NAME, CPU_UNIT_NAME_PARAMETER_NAME,
8541 NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, NAME_MEMBER_NAME);
8542 fprintf (output_file, " if (%s < 0)\n", CMP_VARIABLE_NAME);
8543 fprintf (output_file, " %s = %s - 1;\n",
8544 HIGH_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
8545 fprintf (output_file, " else if (%s > 0)\n", CMP_VARIABLE_NAME);
8546 fprintf (output_file, " %s = %s + 1;\n",
8547 LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
8548 fprintf (output_file, " else\n");
8549 fprintf (output_file, " return %s [%s].%s;\n }\n",
8550 NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, CODE_MEMBER_NAME);
8551 fprintf (output_file, " return -1;\n}\n\n");
8555 /* The following function outputs function to check reservation of cpu
8556 unit (its internal code will be passed as the function argument) in
8559 output_cpu_unit_reservation_p (void)
8561 automaton_t automaton;
8563 fprintf (output_file, "int\n%s (%s %s, int %s)\n",
8564 CPU_UNIT_RESERVATION_P_FUNC_NAME,
8565 STATE_TYPE_NAME, STATE_NAME,
8566 CPU_CODE_PARAMETER_NAME);
8567 fprintf (output_file, "{\n gcc_assert (%s >= 0 && %s < %d);\n",
8568 CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME,
8569 description->query_units_num);
8570 if (description->query_units_num > 0)
8571 for (automaton = description->first_automaton;
8573 automaton = automaton->next_automaton)
8575 fprintf (output_file, " if ((");
8576 output_reserved_units_table_name (output_file, automaton);
8577 fprintf (output_file, " [((struct %s *) %s)->", CHIP_NAME, STATE_NAME);
8578 output_chip_member_name (output_file, automaton);
8579 fprintf (output_file, " * %d + %s / 8] >> (%s %% 8)) & 1)\n",
8580 (description->query_units_num + 7) / 8,
8581 CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME);
8582 fprintf (output_file, " return 1;\n");
8584 fprintf (output_file, " return 0;\n}\n\n");
8587 /* The following function outputs a function to check if insn
8588 has a dfa reservation. */
8590 output_insn_has_dfa_reservation_p (void)
8592 fprintf (output_file,
8593 "bool\n%s (rtx %s ATTRIBUTE_UNUSED)\n{\n",
8594 INSN_HAS_DFA_RESERVATION_P_FUNC_NAME,
8595 INSN_PARAMETER_NAME);
8597 if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8599 fprintf (output_file, " return false;\n}\n\n");
8603 fprintf (output_file, " int %s;\n\n", INTERNAL_INSN_CODE_NAME);
8605 fprintf (output_file, " if (%s == 0)\n %s = %s;\n",
8606 INSN_PARAMETER_NAME,
8607 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8608 fprintf (output_file, " else\n\
8614 INTERNAL_INSN_CODE_NAME, DFA_INSN_CODE_FUNC_NAME,
8615 INSN_PARAMETER_NAME,
8616 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8617 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8619 fprintf (output_file, " return %s != %s;\n}\n\n",
8620 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8623 /* The function outputs PHR interface functions `dfa_clean_insn_cache'
8624 and 'dfa_clear_single_insn_cache'. */
8626 output_dfa_clean_insn_cache_func (void)
8628 fprintf (output_file,
8629 "void\n%s (void)\n{\n int %s;\n\n",
8630 DFA_CLEAN_INSN_CACHE_FUNC_NAME, I_VARIABLE_NAME);
8631 fprintf (output_file,
8632 " for (%s = 0; %s < %s; %s++)\n %s [%s] = -1;\n}\n\n",
8633 I_VARIABLE_NAME, I_VARIABLE_NAME,
8634 DFA_INSN_CODES_LENGTH_VARIABLE_NAME, I_VARIABLE_NAME,
8635 DFA_INSN_CODES_VARIABLE_NAME, I_VARIABLE_NAME);
8637 fprintf (output_file,
8638 "void\n%s (rtx %s)\n{\n int %s;\n\n",
8639 DFA_CLEAR_SINGLE_INSN_CACHE_FUNC_NAME, INSN_PARAMETER_NAME,
8641 fprintf (output_file,
8642 " %s = INSN_UID (%s);\n if (%s < %s)\n %s [%s] = -1;\n}\n\n",
8643 I_VARIABLE_NAME, INSN_PARAMETER_NAME, I_VARIABLE_NAME,
8644 DFA_INSN_CODES_LENGTH_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
8648 /* The function outputs PHR interface function `dfa_start'. */
8650 output_dfa_start_func (void)
8652 fprintf (output_file,
8653 "void\n%s (void)\n{\n %s = get_max_uid ();\n",
8654 DFA_START_FUNC_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8655 fprintf (output_file, " %s = XNEWVEC (int, %s);\n",
8656 DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8657 fprintf (output_file, " %s ();\n}\n\n", DFA_CLEAN_INSN_CACHE_FUNC_NAME);
8660 /* The function outputs PHR interface function `dfa_finish'. */
8662 output_dfa_finish_func (void)
8664 fprintf (output_file, "void\n%s (void)\n{\n free (%s);\n}\n\n",
8665 DFA_FINISH_FUNC_NAME, DFA_INSN_CODES_VARIABLE_NAME);
8670 /* The page contains code for output description file (readable
8671 representation of original description and generated DFA(s). */
8673 /* The function outputs string representation of IR reservation. */
8675 output_regexp (regexp_t regexp)
8677 fprintf (output_description_file, "%s", regexp_representation (regexp));
8678 finish_regexp_representation ();
8681 /* Output names of units in LIST separated by comma. */
8683 output_unit_set_el_list (unit_set_el_t list)
8687 for (el = list; el != NULL; el = el->next_unit_set_el)
8690 fprintf (output_description_file, ", ");
8691 fprintf (output_description_file, "%s", el->unit_decl->name);
8695 /* Output patterns in LIST separated by comma. */
8697 output_pattern_set_el_list (pattern_set_el_t list)
8699 pattern_set_el_t el;
8702 for (el = list; el != NULL; el = el->next_pattern_set_el)
8705 fprintf (output_description_file, ", ");
8706 for (i = 0; i < el->units_num; i++)
8707 fprintf (output_description_file, (i == 0 ? "%s" : " %s"),
8708 el->unit_decls [i]->name);
8712 /* The function outputs string representation of IR define_reservation
8713 and define_insn_reservation. */
8715 output_description (void)
8720 for (i = 0; i < description->decls_num; i++)
8722 decl = description->decls [i];
8723 if (decl->mode == dm_unit)
8725 if (DECL_UNIT (decl)->excl_list != NULL)
8727 fprintf (output_description_file, "unit %s exclusion_set: ",
8728 DECL_UNIT (decl)->name);
8729 output_unit_set_el_list (DECL_UNIT (decl)->excl_list);
8730 fprintf (output_description_file, "\n");
8732 if (DECL_UNIT (decl)->presence_list != NULL)
8734 fprintf (output_description_file, "unit %s presence_set: ",
8735 DECL_UNIT (decl)->name);
8736 output_pattern_set_el_list (DECL_UNIT (decl)->presence_list);
8737 fprintf (output_description_file, "\n");
8739 if (DECL_UNIT (decl)->final_presence_list != NULL)
8741 fprintf (output_description_file, "unit %s final_presence_set: ",
8742 DECL_UNIT (decl)->name);
8743 output_pattern_set_el_list
8744 (DECL_UNIT (decl)->final_presence_list);
8745 fprintf (output_description_file, "\n");
8747 if (DECL_UNIT (decl)->absence_list != NULL)
8749 fprintf (output_description_file, "unit %s absence_set: ",
8750 DECL_UNIT (decl)->name);
8751 output_pattern_set_el_list (DECL_UNIT (decl)->absence_list);
8752 fprintf (output_description_file, "\n");
8754 if (DECL_UNIT (decl)->final_absence_list != NULL)
8756 fprintf (output_description_file, "unit %s final_absence_set: ",
8757 DECL_UNIT (decl)->name);
8758 output_pattern_set_el_list
8759 (DECL_UNIT (decl)->final_absence_list);
8760 fprintf (output_description_file, "\n");
8764 fprintf (output_description_file, "\n");
8765 for (i = 0; i < description->decls_num; i++)
8767 decl = description->decls [i];
8768 if (decl->mode == dm_reserv)
8770 fprintf (output_description_file, "reservation %s: ",
8771 DECL_RESERV (decl)->name);
8772 output_regexp (DECL_RESERV (decl)->regexp);
8773 fprintf (output_description_file, "\n");
8775 else if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
8777 fprintf (output_description_file, "insn reservation %s ",
8778 DECL_INSN_RESERV (decl)->name);
8779 print_rtl (output_description_file,
8780 DECL_INSN_RESERV (decl)->condexp);
8781 fprintf (output_description_file, ": ");
8782 output_regexp (DECL_INSN_RESERV (decl)->regexp);
8783 fprintf (output_description_file, "\n");
8785 else if (decl->mode == dm_bypass)
8786 fprintf (output_description_file, "bypass %d %s %s\n",
8787 DECL_BYPASS (decl)->latency,
8788 DECL_BYPASS (decl)->out_insn_name,
8789 DECL_BYPASS (decl)->in_insn_name);
8791 fprintf (output_description_file, "\n\f\n");
8794 /* The function outputs name of AUTOMATON. */
8796 output_automaton_name (FILE *f, automaton_t automaton)
8798 if (automaton->corresponding_automaton_decl == NULL)
8799 fprintf (f, "#%d", automaton->automaton_order_num);
8801 fprintf (f, "`%s'", automaton->corresponding_automaton_decl->name);
8804 /* Maximal length of line for pretty printing into description
8806 #define MAX_LINE_LENGTH 70
8808 /* The function outputs units name belonging to AUTOMATON. */
8810 output_automaton_units (automaton_t automaton)
8814 int curr_line_length;
8815 int there_is_an_automaton_unit;
8818 fprintf (output_description_file, "\n Corresponding units:\n");
8819 fprintf (output_description_file, " ");
8820 curr_line_length = 4;
8821 there_is_an_automaton_unit = 0;
8822 for (i = 0; i < description->decls_num; i++)
8824 decl = description->decls [i];
8825 if (decl->mode == dm_unit
8826 && (DECL_UNIT (decl)->corresponding_automaton_num
8827 == automaton->automaton_order_num))
8829 there_is_an_automaton_unit = 1;
8830 name = DECL_UNIT (decl)->name;
8831 if (curr_line_length + strlen (name) + 1 > MAX_LINE_LENGTH )
8833 curr_line_length = strlen (name) + 4;
8834 fprintf (output_description_file, "\n ");
8838 curr_line_length += strlen (name) + 1;
8839 fprintf (output_description_file, " ");
8841 fprintf (output_description_file, "%s", name);
8844 if (!there_is_an_automaton_unit)
8845 fprintf (output_description_file, "<None>");
8846 fprintf (output_description_file, "\n\n");
8849 /* The following variable is used for forming array of all possible cpu unit
8850 reservations described by the current DFA state. */
8851 static VEC(reserv_sets_t, heap) *state_reservs;
8853 /* The function forms `state_reservs' for STATE. */
8855 add_state_reservs (state_t state)
8857 alt_state_t curr_alt_state;
8859 if (state->component_states != NULL)
8860 for (curr_alt_state = state->component_states;
8861 curr_alt_state != NULL;
8862 curr_alt_state = curr_alt_state->next_sorted_alt_state)
8863 add_state_reservs (curr_alt_state->state);
8865 VEC_safe_push (reserv_sets_t, heap, state_reservs, state->reservs);
8868 /* The function outputs readable representation of all out arcs of
8871 output_state_arcs (state_t state)
8875 const char *insn_name;
8876 int curr_line_length;
8878 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
8881 gcc_assert (ainsn->first_insn_with_same_reservs);
8882 fprintf (output_description_file, " ");
8883 curr_line_length = 7;
8884 fprintf (output_description_file, "%2d: ", ainsn->insn_equiv_class_num);
8887 insn_name = ainsn->insn_reserv_decl->name;
8888 if (curr_line_length + strlen (insn_name) > MAX_LINE_LENGTH)
8890 if (ainsn != arc->insn)
8892 fprintf (output_description_file, ",\n ");
8893 curr_line_length = strlen (insn_name) + 6;
8896 curr_line_length += strlen (insn_name);
8900 curr_line_length += strlen (insn_name);
8901 if (ainsn != arc->insn)
8903 curr_line_length += 2;
8904 fprintf (output_description_file, ", ");
8907 fprintf (output_description_file, "%s", insn_name);
8908 ainsn = ainsn->next_same_reservs_insn;
8910 while (ainsn != NULL);
8911 fprintf (output_description_file, " %d \n",
8912 arc->to_state->order_state_num);
8914 fprintf (output_description_file, "\n");
8917 /* The following function is used for sorting possible cpu unit
8918 reservation of a DFA state. */
8920 state_reservs_cmp (const void *reservs_ptr_1, const void *reservs_ptr_2)
8922 return reserv_sets_cmp (*(const_reserv_sets_t const*) reservs_ptr_1,
8923 *(const_reserv_sets_t const*) reservs_ptr_2);
8926 /* The following function is used for sorting possible cpu unit
8927 reservation of a DFA state. */
8929 remove_state_duplicate_reservs (void)
8933 for (i = 1, j = 0; i < VEC_length (reserv_sets_t, state_reservs); i++)
8934 if (reserv_sets_cmp (VEC_index (reserv_sets_t, state_reservs, j),
8935 VEC_index (reserv_sets_t, state_reservs, i)))
8938 VEC_replace (reserv_sets_t, state_reservs, j,
8939 VEC_index (reserv_sets_t, state_reservs, i));
8941 VEC_truncate (reserv_sets_t, state_reservs, j + 1);
8944 /* The following function output readable representation of DFA(s)
8945 state used for fast recognition of pipeline hazards. State is
8946 described by possible (current and scheduled) cpu unit
8949 output_state (state_t state)
8955 fprintf (output_description_file, " State #%d", state->order_state_num);
8956 fprintf (output_description_file,
8957 state->new_cycle_p ? " (new cycle)\n" : "\n");
8958 add_state_reservs (state);
8959 qsort (VEC_address (reserv_sets_t, state_reservs),
8960 VEC_length (reserv_sets_t, state_reservs),
8961 sizeof (reserv_sets_t), state_reservs_cmp);
8962 remove_state_duplicate_reservs ();
8963 for (i = 0; i < VEC_length (reserv_sets_t, state_reservs); i++)
8965 fprintf (output_description_file, " ");
8966 output_reserv_sets (output_description_file,
8967 VEC_index (reserv_sets_t, state_reservs, i));
8968 fprintf (output_description_file, "\n");
8970 fprintf (output_description_file, "\n");
8971 output_state_arcs (state);
8972 VEC_free (reserv_sets_t, heap, state_reservs);
8975 /* The following function output readable representation of
8976 DFAs used for fast recognition of pipeline hazards. */
8978 output_automaton_descriptions (void)
8980 automaton_t automaton;
8982 for (automaton = description->first_automaton;
8984 automaton = automaton->next_automaton)
8986 fprintf (output_description_file, "\nAutomaton ");
8987 output_automaton_name (output_description_file, automaton);
8988 fprintf (output_description_file, "\n");
8989 output_automaton_units (automaton);
8990 pass_states (automaton, output_state);
8996 /* The page contains top level function for generation DFA(s) used for
8999 /* The function outputs statistics about work of different phases of
9002 output_statistics (FILE *f)
9004 automaton_t automaton;
9007 int transition_comb_vect_els = 0;
9008 int transition_full_vect_els = 0;
9009 int min_issue_delay_vect_els = 0;
9010 int locked_states = 0;
9013 for (automaton = description->first_automaton;
9015 automaton = automaton->next_automaton)
9017 fprintf (f, "\nAutomaton ");
9018 output_automaton_name (f, automaton);
9019 fprintf (f, "\n %5d NDFA states, %5d NDFA arcs\n",
9020 automaton->NDFA_states_num, automaton->NDFA_arcs_num);
9021 fprintf (f, " %5d DFA states, %5d DFA arcs\n",
9022 automaton->DFA_states_num, automaton->DFA_arcs_num);
9023 states_num = automaton->DFA_states_num;
9024 if (!no_minimization_flag)
9026 fprintf (f, " %5d minimal DFA states, %5d minimal DFA arcs\n",
9027 automaton->minimal_DFA_states_num,
9028 automaton->minimal_DFA_arcs_num);
9029 states_num = automaton->minimal_DFA_states_num;
9031 fprintf (f, " %5d all insns %5d insn equivalence classes\n",
9032 description->insns_num, automaton->insn_equiv_classes_num);
9033 fprintf (f, " %d locked states\n", automaton->locked_states);
9036 (f, "%5ld transition comb vector els, %5ld trans table els: %s\n",
9037 (long) VEC_length (vect_el_t, automaton->trans_table->comb_vect),
9038 (long) VEC_length (vect_el_t, automaton->trans_table->full_vect),
9039 (comb_vect_p (automaton->trans_table)
9040 ? "use comb vect" : "use simple vect"));
9042 (f, "%5ld min delay table els, compression factor %d\n",
9043 (long) states_num * automaton->insn_equiv_classes_num,
9044 automaton->min_issue_delay_table_compression_factor);
9045 transition_comb_vect_els
9046 += VEC_length (vect_el_t, automaton->trans_table->comb_vect);
9047 transition_full_vect_els
9048 += VEC_length (vect_el_t, automaton->trans_table->full_vect);
9049 min_issue_delay_vect_els
9050 += states_num * automaton->insn_equiv_classes_num;
9052 += automaton->locked_states;
9056 fprintf (f, "\n%5d all allocated states, %5d all allocated arcs\n",
9057 allocated_states_num, allocated_arcs_num);
9058 fprintf (f, "%5d all allocated alternative states\n",
9059 allocated_alt_states_num);
9060 fprintf (f, "%5d all transition comb vector els, %5d all trans table els\n",
9061 transition_comb_vect_els, transition_full_vect_els);
9062 fprintf (f, "%5d all min delay table els\n", min_issue_delay_vect_els);
9063 fprintf (f, "%5d all locked states\n", locked_states);
9067 /* The function output times of work of different phases of DFA
9070 output_time_statistics (FILE *f)
9072 fprintf (f, "\n transformation: ");
9073 print_active_time (f, transform_time);
9074 fprintf (f, (!ndfa_flag ? ", building DFA: " : ", building NDFA: "));
9075 print_active_time (f, NDFA_time);
9078 fprintf (f, ", NDFA -> DFA: ");
9079 print_active_time (f, NDFA_to_DFA_time);
9081 fprintf (f, "\n DFA minimization: ");
9082 print_active_time (f, minimize_time);
9083 fprintf (f, ", making insn equivalence: ");
9084 print_active_time (f, equiv_time);
9085 fprintf (f, "\n all automaton generation: ");
9086 print_active_time (f, automaton_generation_time);
9087 fprintf (f, ", output: ");
9088 print_active_time (f, output_time);
9092 /* The function generates DFA (deterministic finite state automaton)
9093 for fast recognition of pipeline hazards. No errors during
9094 checking must be fixed before this function call. */
9098 automata_num = split_argument;
9099 if (description->units_num < automata_num)
9100 automata_num = description->units_num;
9103 initiate_automata_lists ();
9104 initiate_pass_states ();
9105 initiate_excl_sets ();
9106 initiate_presence_absence_pattern_sets ();
9107 automaton_generation_time = create_ticker ();
9109 ticker_off (&automaton_generation_time);
9114 /* This page mainly contains top level functions of pipeline hazards
9115 description translator. */
9117 /* The following macro value is suffix of name of description file of
9118 pipeline hazards description translator. */
9119 #define STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX ".dfa"
9121 /* The function returns suffix of given file name. The returned
9122 string can not be changed. */
9124 file_name_suffix (const char *file_name)
9126 const char *last_period;
9128 for (last_period = NULL; *file_name != '\0'; file_name++)
9129 if (*file_name == '.')
9130 last_period = file_name;
9131 return (last_period == NULL ? file_name : last_period);
9134 /* The function returns base name of given file name, i.e. pointer to
9135 first char after last `/' (or `\' for WIN32) in given file name,
9136 given file name itself if the directory name is absent. The
9137 returned string can not be changed. */
9139 base_file_name (const char *file_name)
9141 int directory_name_length;
9143 directory_name_length = strlen (file_name);
9145 while (directory_name_length >= 0 && file_name[directory_name_length] != '/'
9146 && file_name[directory_name_length] != '\\')
9148 while (directory_name_length >= 0 && file_name[directory_name_length] != '/')
9150 directory_name_length--;
9151 return file_name + directory_name_length + 1;
9154 /* The following is top level function to initialize the work of
9155 pipeline hazards description translator. */
9157 initiate_automaton_gen (int argc, char **argv)
9159 const char *base_name;
9163 split_argument = 0; /* default value */
9164 no_minimization_flag = 0;
9170 for (i = 2; i < argc; i++)
9171 if (strcmp (argv [i], NO_MINIMIZATION_OPTION) == 0)
9172 no_minimization_flag = 1;
9173 else if (strcmp (argv [i], TIME_OPTION) == 0)
9175 else if (strcmp (argv [i], STATS_OPTION) == 0)
9177 else if (strcmp (argv [i], V_OPTION) == 0)
9179 else if (strcmp (argv [i], W_OPTION) == 0)
9181 else if (strcmp (argv [i], NDFA_OPTION) == 0)
9183 else if (strcmp (argv [i], PROGRESS_OPTION) == 0)
9185 else if (strcmp (argv [i], "-split") == 0)
9188 fatal ("-split has no argument.");
9189 fatal ("option `-split' has not been implemented yet\n");
9190 /* split_argument = atoi (argument_vect [i + 1]); */
9193 /* Initialize IR storage. */
9194 obstack_init (&irp);
9195 initiate_automaton_decl_table ();
9196 initiate_insn_decl_table ();
9197 initiate_decl_table ();
9198 output_file = stdout;
9199 output_description_file = NULL;
9200 base_name = base_file_name (argv[1]);
9201 obstack_grow (&irp, base_name,
9202 strlen (base_name) - strlen (file_name_suffix (base_name)));
9203 obstack_grow (&irp, STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX,
9204 strlen (STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX) + 1);
9205 obstack_1grow (&irp, '\0');
9206 output_description_file_name = obstack_base (&irp);
9207 obstack_finish (&irp);
9210 /* The following function checks existence at least one arc marked by
9213 check_automata_insn_issues (void)
9215 automaton_t automaton;
9216 ainsn_t ainsn, reserv_ainsn;
9218 for (automaton = description->first_automaton;
9220 automaton = automaton->next_automaton)
9222 for (ainsn = automaton->ainsn_list;
9224 ainsn = ainsn->next_ainsn)
9225 if (ainsn->first_insn_with_same_reservs && !ainsn->arc_exists_p)
9227 for (reserv_ainsn = ainsn;
9228 reserv_ainsn != NULL;
9229 reserv_ainsn = reserv_ainsn->next_same_reservs_insn)
9230 if (automaton->corresponding_automaton_decl != NULL)
9233 error ("Automaton `%s': Insn `%s' will never be issued",
9234 automaton->corresponding_automaton_decl->name,
9235 reserv_ainsn->insn_reserv_decl->name);
9238 (0, "Automaton `%s': Insn `%s' will never be issued",
9239 automaton->corresponding_automaton_decl->name,
9240 reserv_ainsn->insn_reserv_decl->name);
9245 error ("Insn `%s' will never be issued",
9246 reserv_ainsn->insn_reserv_decl->name);
9248 warning (0, "Insn `%s' will never be issued",
9249 reserv_ainsn->insn_reserv_decl->name);
9255 /* The following vla is used for storing pointers to all achieved
9257 static VEC(state_t, heap) *automaton_states;
9259 /* This function is called by function pass_states to add an achieved
9262 add_automaton_state (state_t state)
9264 VEC_safe_push (state_t, heap, automaton_states, state);
9267 /* The following function forms list of important automata (whose
9268 states may be changed after the insn issue) for each insn. */
9270 form_important_insn_automata_lists (void)
9272 automaton_t automaton;
9279 automaton_states = 0;
9280 /* Mark important ainsns. */
9281 for (automaton = description->first_automaton;
9283 automaton = automaton->next_automaton)
9285 VEC_truncate (state_t, automaton_states, 0);
9286 pass_states (automaton, add_automaton_state);
9287 for (n = 0; n < VEC_length (state_t, automaton_states); n++)
9289 state_t s = VEC_index (state_t, automaton_states, n);
9290 for (arc = first_out_arc (s);
9292 arc = next_out_arc (arc))
9293 if (arc->to_state != s)
9295 gcc_assert (arc->insn->first_insn_with_same_reservs);
9296 for (ainsn = arc->insn;
9298 ainsn = ainsn->next_same_reservs_insn)
9299 ainsn->important_p = TRUE;
9303 VEC_free (state_t, heap, automaton_states);
9305 /* Create automata sets for the insns. */
9306 for (i = 0; i < description->decls_num; i++)
9308 decl = description->decls [i];
9309 if (decl->mode == dm_insn_reserv)
9311 automata_list_start ();
9312 for (automaton = description->first_automaton;
9314 automaton = automaton->next_automaton)
9315 for (ainsn = automaton->ainsn_list;
9317 ainsn = ainsn->next_ainsn)
9318 if (ainsn->important_p
9319 && ainsn->insn_reserv_decl == DECL_INSN_RESERV (decl))
9321 automata_list_add (automaton);
9324 DECL_INSN_RESERV (decl)->important_automata_list
9325 = automata_list_finish ();
9331 /* The following is top level function to generate automat(a,on) for
9332 fast recognition of pipeline hazards. */
9334 expand_automata (void)
9338 description = XCREATENODEVAR (struct description,
9339 sizeof (struct description)
9340 /* One entry for cycle advancing insn. */
9341 + sizeof (decl_t) * VEC_length (decl_t, decls));
9342 description->decls_num = VEC_length (decl_t, decls);
9343 description->query_units_num = 0;
9344 for (i = 0; i < description->decls_num; i++)
9346 description->decls [i] = VEC_index (decl_t, decls, i);
9347 if (description->decls [i]->mode == dm_unit
9348 && DECL_UNIT (description->decls [i])->query_p)
9349 DECL_UNIT (description->decls [i])->query_num
9350 = description->query_units_num++;
9352 all_time = create_ticker ();
9353 check_time = create_ticker ();
9355 fprintf (stderr, "Check description...");
9356 check_all_description ();
9358 fprintf (stderr, "done\n");
9359 ticker_off (&check_time);
9360 generation_time = create_ticker ();
9363 transform_insn_regexps ();
9364 check_unit_distributions_to_automata ();
9369 check_automata_insn_issues ();
9373 form_important_insn_automata_lists ();
9375 ticker_off (&generation_time);
9378 /* The following is top level function to output PHR and to finish
9379 work with pipeline description translator. */
9381 write_automata (void)
9383 output_time = create_ticker ();
9385 fprintf (stderr, "Forming and outputting automata tables...");
9389 fprintf (stderr, "done\n");
9390 fprintf (stderr, "Output functions to work with automata...");
9392 output_chip_definitions ();
9393 output_max_insn_queue_index_def ();
9394 output_internal_min_issue_delay_func ();
9395 output_internal_trans_func ();
9396 /* Cache of insn dfa codes: */
9397 fprintf (output_file, "\nstatic int *%s;\n", DFA_INSN_CODES_VARIABLE_NAME);
9398 fprintf (output_file, "\nstatic int %s;\n\n",
9399 DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
9400 output_dfa_insn_code_func ();
9401 output_trans_func ();
9402 output_min_issue_delay_func ();
9403 output_internal_dead_lock_func ();
9404 output_dead_lock_func ();
9405 output_size_func ();
9406 output_internal_reset_func ();
9407 output_reset_func ();
9408 output_min_insn_conflict_delay_func ();
9409 output_default_latencies ();
9410 output_internal_insn_latency_func ();
9411 output_insn_latency_func ();
9412 output_internal_maximal_insn_latency_func ();
9413 output_maximal_insn_latency_func ();
9414 output_print_reservation_func ();
9415 /* Output function get_cpu_unit_code. */
9416 fprintf (output_file, "\n#if %s\n\n", CPU_UNITS_QUERY_MACRO_NAME);
9417 output_get_cpu_unit_code_func ();
9418 output_cpu_unit_reservation_p ();
9419 output_insn_has_dfa_reservation_p ();
9420 fprintf (output_file, "\n#endif /* #if %s */\n\n",
9421 CPU_UNITS_QUERY_MACRO_NAME);
9422 output_dfa_clean_insn_cache_func ();
9423 output_dfa_start_func ();
9424 output_dfa_finish_func ();
9426 fprintf (stderr, "done\n");
9429 output_description_file = fopen (output_description_file_name, "w");
9430 if (output_description_file == NULL)
9432 perror (output_description_file_name);
9433 exit (FATAL_EXIT_CODE);
9436 fprintf (stderr, "Output automata description...");
9437 output_description ();
9438 output_automaton_descriptions ();
9440 fprintf (stderr, "done\n");
9441 output_statistics (output_description_file);
9444 output_statistics (stderr);
9445 ticker_off (&output_time);
9447 output_time_statistics (stderr);
9450 finish_automata_lists ();
9453 fprintf (stderr, "Summary:\n");
9454 fprintf (stderr, " check time ");
9455 print_active_time (stderr, check_time);
9456 fprintf (stderr, ", generation time ");
9457 print_active_time (stderr, generation_time);
9458 fprintf (stderr, ", all time ");
9459 print_active_time (stderr, all_time);
9460 fprintf (stderr, "\n");
9462 /* Finish all work. */
9463 if (output_description_file != NULL)
9465 fflush (output_description_file);
9466 if (ferror (stdout) != 0)
9467 fatal ("Error in writing DFA description file %s: %s",
9468 output_description_file_name, xstrerror (errno));
9469 fclose (output_description_file);
9471 finish_automaton_decl_table ();
9472 finish_insn_decl_table ();
9473 finish_decl_table ();
9474 obstack_free (&irp, NULL);
9475 if (have_error && output_description_file != NULL)
9476 remove (output_description_file_name);
9480 main (int argc, char **argv)
9484 progname = "genautomata";
9486 if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
9487 return (FATAL_EXIT_CODE);
9489 initiate_automaton_gen (argc, argv);
9493 int insn_code_number;
9495 desc = read_md_rtx (&lineno, &insn_code_number);
9499 switch (GET_CODE (desc))
9501 case DEFINE_CPU_UNIT:
9502 gen_cpu_unit (desc);
9505 case DEFINE_QUERY_CPU_UNIT:
9506 gen_query_cpu_unit (desc);
9514 gen_excl_set (desc);
9518 gen_presence_set (desc);
9521 case FINAL_PRESENCE_SET:
9522 gen_final_presence_set (desc);
9526 gen_absence_set (desc);
9529 case FINAL_ABSENCE_SET:
9530 gen_final_absence_set (desc);
9533 case DEFINE_AUTOMATON:
9534 gen_automaton (desc);
9537 case AUTOMATA_OPTION:
9538 gen_automata_option (desc);
9541 case DEFINE_RESERVATION:
9545 case DEFINE_INSN_RESERVATION:
9546 gen_insn_reserv (desc);
9555 return FATAL_EXIT_CODE;
9557 if (VEC_length (decl_t, decls) > 0)
9562 puts ("/* Generated automatically by the program `genautomata'\n"
9563 " from the machine description file `md'. */\n\n"
9564 "#include \"config.h\"\n"
9565 "#include \"system.h\"\n"
9566 "#include \"coretypes.h\"\n"
9567 "#include \"tm.h\"\n"
9568 "#include \"rtl.h\"\n"
9569 "#include \"tm_p.h\"\n"
9570 "#include \"insn-config.h\"\n"
9571 "#include \"recog.h\"\n"
9572 "#include \"regs.h\"\n"
9573 "#include \"real.h\"\n"
9574 "#include \"output.h\"\n"
9575 "#include \"insn-attr.h\"\n"
9576 "#include \"toplev.h\"\n"
9577 "#include \"flags.h\"\n"
9578 "#include \"function.h\"\n");
9585 return (ferror (stdout) != 0 || have_error
9586 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);