1 /* Pipeline hazard description translator.
2 Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005
3 Free Software Foundation, Inc.
5 Written by Vladimir Makarov <vmakarov@redhat.com>
7 This file is part of GCC.
9 GCC is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by the
11 Free Software Foundation; either version 2, or (at your option) any
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 COPYING. If not, write to the Free
21 Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
26 1. Detecting pipeline structural hazards quickly. T. Proebsting,
27 C. Fraser. Proceedings of ACM SIGPLAN-SIGACT Symposium on
28 Principles of Programming Languages, pages 280--286, 1994.
30 This article is a good start point to understand usage of finite
31 state automata for pipeline hazard recognizers. But I'd
32 recommend the 2nd article for more deep understanding.
34 2. Efficient Instruction Scheduling Using Finite State Automata:
35 V. Bala and N. Rubin, Proceedings of MICRO-28. This is the best
36 article about usage of finite state automata for pipeline hazard
39 The current implementation is different from the 2nd article in the
42 1. New operator `|' (alternative) is permitted in functional unit
43 reservation which can be treated deterministically and
44 non-deterministically.
46 2. Possibility of usage of nondeterministic automata too.
48 3. Possibility to query functional unit reservations for given
51 4. Several constructions to describe impossible reservations
52 (`exclusion_set', `presence_set', `final_presence_set',
53 `absence_set', and `final_absence_set').
55 5. No reverse automata are generated. Trace instruction scheduling
56 requires this. It can be easily added in the future if we
59 6. Union of automaton states are not generated yet. It is planned
60 to be implemented. Such feature is needed to make more accurate
61 interlock insn scheduling to get state describing functional
62 unit reservation in a joint CFG point. */
64 /* This file code processes constructions of machine description file
65 which describes automaton used for recognition of processor pipeline
66 hazards by insn scheduler and can be used for other tasks (such as
69 The translator functions `gen_cpu_unit', `gen_query_cpu_unit',
70 `gen_bypass', `gen_excl_set', `gen_presence_set',
71 `gen_final_presence_set', `gen_absence_set',
72 `gen_final_absence_set', `gen_automaton', `gen_automata_option',
73 `gen_reserv', `gen_insn_reserv' are called from file
74 `genattrtab.c'. They transform RTL constructions describing
75 automata in .md file into internal representation convenient for
78 The translator major function `expand_automata' processes the
79 description internal representation into finite state automaton.
82 o checking correctness of the automaton pipeline description
83 (major function is `check_all_description').
85 o generating automaton (automata) from the description (major
86 function is `make_automaton').
88 o optional transformation of nondeterministic finite state
89 automata into deterministic ones if the alternative operator
90 `|' is treated nondeterministically in the description (major
91 function is NDFA_to_DFA).
93 o optional minimization of the finite state automata by merging
94 equivalent automaton states (major function is `minimize_DFA').
96 o forming tables (some as comb vectors) and attributes
97 representing the automata (functions output_..._table).
99 Function `write_automata' outputs the created finite state
100 automaton as different tables and functions which works with the
101 automata to inquire automaton state and to change its state. These
102 function are used by gcc instruction scheduler and may be some
107 #include "coretypes.h"
112 #include "gensupport.h"
122 /* Positions in machine description file. Now they are not used. But
123 they could be used in the future for better diagnostic messages. */
126 /* The following is element of vector of current (and planned in the
127 future) functional unit reservations. */
128 typedef unsigned HOST_WIDE_INT set_el_t
;
130 /* Reservations of function units are represented by value of the following
132 typedef set_el_t
*reserv_sets_t
;
134 /* The following structure describes a ticker. */
137 /* The following member value is time of the ticker creation with
138 taking into account time when the ticker is off. Active time of
139 the ticker is current time minus the value. */
140 int modified_creation_time
;
141 /* The following member value is time (incremented by one) when the
142 ticker was off. Zero value means that now the ticker is on. */
143 int incremented_off_time
;
146 /* The ticker is represented by the following type. */
147 typedef struct ticker ticker_t
;
149 /* The following type describes elements of output vectors. */
150 typedef HOST_WIDE_INT vect_el_t
;
152 /* Forward declaration of structures of internal representation of
153 pipeline description based on NDFA. */
158 struct automaton_decl
;
159 struct unit_pattern_rel_decl
;
161 struct insn_reserv_decl
;
164 struct result_regexp
;
165 struct reserv_regexp
;
166 struct nothing_regexp
;
167 struct sequence_regexp
;
168 struct repeat_regexp
;
174 struct pattern_set_el
;
175 struct pattern_reserv
;
181 struct state_ainsn_table
;
183 /* The following typedefs are for brevity. */
184 typedef struct unit_decl
*unit_decl_t
;
185 typedef struct decl
*decl_t
;
186 typedef struct regexp
*regexp_t
;
187 typedef struct unit_set_el
*unit_set_el_t
;
188 typedef struct pattern_set_el
*pattern_set_el_t
;
189 typedef struct pattern_reserv
*pattern_reserv_t
;
190 typedef struct alt_state
*alt_state_t
;
191 typedef struct state
*state_t
;
192 typedef struct arc
*arc_t
;
193 typedef struct ainsn
*ainsn_t
;
194 typedef struct automaton
*automaton_t
;
195 typedef struct automata_list_el
*automata_list_el_t
;
196 typedef struct state_ainsn_table
*state_ainsn_table_t
;
198 /* Undefined position. */
199 static pos_t no_pos
= 0;
201 /* All IR is stored in the following obstack. */
202 static struct obstack irp
;
205 /* Declare vector types for various data structures: */
207 DEF_VEC_P(alt_state_t
);
208 DEF_VEC_ALLOC_P(alt_state_t
,heap
);
210 DEF_VEC_ALLOC_P(ainsn_t
,heap
);
212 DEF_VEC_ALLOC_P(state_t
,heap
);
214 DEF_VEC_ALLOC_P(decl_t
,heap
);
215 DEF_VEC_P(reserv_sets_t
);
216 DEF_VEC_ALLOC_P(reserv_sets_t
,heap
);
218 DEF_VEC_I(vect_el_t
);
219 DEF_VEC_ALLOC_I(vect_el_t
, heap
);
220 typedef VEC(vect_el_t
,heap
) *vla_hwint_t
;
222 /* Forward declarations of functions used before their definitions, only. */
223 static regexp_t
gen_regexp_sequence (const char *);
224 static void reserv_sets_or (reserv_sets_t
, reserv_sets_t
,
226 static reserv_sets_t
get_excl_set (reserv_sets_t
);
227 static int check_presence_pattern_sets (reserv_sets_t
,
229 static int check_absence_pattern_sets (reserv_sets_t
, reserv_sets_t
,
231 static arc_t
first_out_arc (state_t
);
232 static arc_t
next_out_arc (arc_t
);
236 /* Options with the following names can be set up in automata_option
237 construction. Because the strings occur more one time we use the
240 #define NO_MINIMIZATION_OPTION "-no-minimization"
242 #define TIME_OPTION "-time"
244 #define V_OPTION "-v"
246 #define W_OPTION "-w"
248 #define NDFA_OPTION "-ndfa"
250 #define PROGRESS_OPTION "-progress"
252 /* The following flags are set up by function `initiate_automaton_gen'. */
254 /* Make automata with nondeterministic reservation by insns (`-ndfa'). */
255 static int ndfa_flag
;
257 /* Do not make minimization of DFA (`-no-minimization'). */
258 static int no_minimization_flag
;
260 /* Value of this variable is number of automata being generated. The
261 actual number of automata may be less this value if there is not
262 sufficient number of units. This value is defined by argument of
263 option `-split' or by constructions automaton if the value is zero
264 (it is default value of the argument). */
265 static int split_argument
;
267 /* Flag of output time statistics (`-time'). */
268 static int time_flag
;
270 /* Flag of creation of description file which contains description of
271 result automaton and statistics information (`-v'). */
274 /* Flag of output of a progress bar showing how many states were
275 generated so far for automaton being processed (`-progress'). */
276 static int progress_flag
;
278 /* Flag of generating warning instead of error for non-critical errors
283 /* Output file for pipeline hazard recognizer (PHR) being generated.
284 The value is NULL if the file is not defined. */
285 static FILE *output_file
;
287 /* Description file of PHR. The value is NULL if the file is not
289 static FILE *output_description_file
;
291 /* PHR description file name. */
292 static char *output_description_file_name
;
294 /* Value of the following variable is node representing description
295 being processed. This is start point of IR. */
296 static struct description
*description
;
300 /* This page contains description of IR structure (nodes). */
314 /* This describes define_cpu_unit and define_query_cpu_unit (see file
319 /* NULL if the automaton name is absent. */
320 const char *automaton_name
;
321 /* If the following value is not zero, the cpu unit reservation is
322 described in define_query_cpu_unit. */
325 /* The following fields are defined by checker. */
327 /* The following field value is nonzero if the unit is used in an
331 /* The following field value is order number (0, 1, ...) of given
334 /* The following field value is corresponding declaration of
335 automaton which was given in description. If the field value is
336 NULL then automaton in the unit declaration was absent. */
337 struct automaton_decl
*automaton_decl
;
338 /* The following field value is maximal cycle number (1, ...) on
339 which given unit occurs in insns. Zero value means that given
340 unit is not used in insns. */
341 int max_occ_cycle_num
;
342 /* The following field value is minimal cycle number (0, ...) on
343 which given unit occurs in insns. -1 value means that given
344 unit is not used in insns. */
345 int min_occ_cycle_num
;
346 /* The following list contains units which conflict with given
348 unit_set_el_t excl_list
;
349 /* The following list contains patterns which are required to
350 reservation of given unit. */
351 pattern_set_el_t presence_list
;
352 pattern_set_el_t final_presence_list
;
353 /* The following list contains patterns which should be not present
354 in reservation for given unit. */
355 pattern_set_el_t absence_list
;
356 pattern_set_el_t final_absence_list
;
357 /* The following is used only when `query_p' has nonzero value.
358 This is query number for the unit. */
360 /* The following is the last cycle on which the unit was checked for
361 correct distributions of units to automata in a regexp. */
362 int last_distribution_check_cycle
;
364 /* The following fields are defined by automaton generator. */
366 /* The following field value is number of the automaton to which
367 given unit belongs. */
368 int corresponding_automaton_num
;
369 /* If the following value is not zero, the cpu unit is present in a
370 `exclusion_set' or in right part of a `presence_set',
371 `final_presence_set', `absence_set', and
372 `final_absence_set'define_query_cpu_unit. */
376 /* This describes define_bypass (see file rtl.def). */
380 const char *out_insn_name
;
381 const char *in_insn_name
;
382 const char *bypass_guard_name
;
384 /* The following fields are defined by checker. */
386 /* output and input insns of given bypass. */
387 struct insn_reserv_decl
*out_insn_reserv
;
388 struct insn_reserv_decl
*in_insn_reserv
;
389 /* The next bypass for given output insn. */
390 struct bypass_decl
*next
;
393 /* This describes define_automaton (see file rtl.def). */
394 struct automaton_decl
398 /* The following fields are defined by automaton generator. */
400 /* The following field value is nonzero if the automaton is used in
401 an regexp definition. */
402 char automaton_is_used
;
404 /* The following fields are defined by checker. */
406 /* The following field value is the corresponding automaton. This
407 field is not NULL only if the automaton is present in unit
408 declarations and the automatic partition on automata is not
410 automaton_t corresponding_automaton
;
413 /* This describes exclusion relations: exclusion_set (see file
418 int first_list_length
;
422 /* This describes unit relations: [final_]presence_set or
423 [final_]absence_set (see file rtl.def). */
424 struct unit_pattern_rel_decl
433 /* This describes define_reservation (see file rtl.def). */
439 /* The following fields are defined by checker. */
441 /* The following field value is nonzero if the unit is used in an
444 /* The following field is used to check up cycle in expression
449 /* This describes define_insn_reservation (see file rtl.def). */
450 struct insn_reserv_decl
457 /* The following fields are defined by checker. */
459 /* The following field value is order number (0, 1, ...) of given
462 /* The following field value is list of bypasses in which given insn
464 struct bypass_decl
*bypass_list
;
466 /* The following fields are defined by automaton generator. */
468 /* The following field is the insn regexp transformed that
469 the regexp has not optional regexp, repetition regexp, and an
470 reservation name (i.e. reservation identifiers are changed by the
471 corresponding regexp) and all alternations are the topest level
472 of the regexp. The value can be NULL only if it is special
473 insn `cycle advancing'. */
474 regexp_t transformed_regexp
;
475 /* The following field value is list of arcs marked given
476 insn. The field is used in transformation NDFA -> DFA. */
477 arc_t arcs_marked_by_insn
;
478 /* The two following fields are used during minimization of a finite state
480 /* The field value is number of equivalence class of state into
481 which arc marked by given insn enters from a state (fixed during
482 an automaton minimization). */
484 /* The following member value is the list to automata which can be
485 changed by the insn issue. */
486 automata_list_el_t important_automata_list
;
487 /* The following member is used to process insn once for output. */
491 /* This contains a declaration mentioned above. */
494 /* What node in the union? */
499 struct unit_decl unit
;
500 struct bypass_decl bypass
;
501 struct automaton_decl automaton
;
502 struct excl_rel_decl excl
;
503 struct unit_pattern_rel_decl presence
;
504 struct unit_pattern_rel_decl absence
;
505 struct reserv_decl reserv
;
506 struct insn_reserv_decl insn_reserv
;
510 /* The following structures represent parsed reservation strings. */
522 /* Cpu unit in reservation. */
526 unit_decl_t unit_decl
;
529 /* Define_reservation in a reservation. */
533 struct reserv_decl
*reserv_decl
;
536 /* Absence of reservation (represented by string `nothing'). */
537 struct nothing_regexp
539 /* This used to be empty but ISO C doesn't allow that. */
543 /* Representation of reservations separated by ',' (see file
545 struct sequence_regexp
548 regexp_t regexps
[1];
551 /* Representation of construction `repeat' (see file rtl.def). */
558 /* Representation of reservations separated by '+' (see file
563 regexp_t regexps
[1];
566 /* Representation of reservations separated by '|' (see file
571 regexp_t regexps
[1];
574 /* Representation of a reservation string. */
577 /* What node in the union? */
578 enum regexp_mode mode
;
582 struct unit_regexp unit
;
583 struct reserv_regexp reserv
;
584 struct nothing_regexp nothing
;
585 struct sequence_regexp sequence
;
586 struct repeat_regexp repeat
;
587 struct allof_regexp allof
;
588 struct oneof_regexp oneof
;
592 /* Represents description of pipeline hazard description based on
598 /* The following fields are defined by checker. */
600 /* The following fields values are correspondingly number of all
601 units, query units, and insns in the description. */
605 /* The following field value is max length (in cycles) of
606 reservations of insns. The field value is defined only for
608 int max_insn_reserv_cycles
;
610 /* The following fields are defined by automaton generator. */
612 /* The following field value is the first automaton. */
613 automaton_t first_automaton
;
615 /* The following field is created by pipeline hazard parser and
616 contains all declarations. We allocate additional entry for
617 special insn "cycle advancing" which is added by the automaton
623 /* The following nodes are created in automaton checker. */
625 /* The following nodes represent exclusion set for cpu units. Each
626 element is accessed through only one excl_list. */
629 unit_decl_t unit_decl
;
630 unit_set_el_t next_unit_set_el
;
633 /* The following nodes represent presence or absence pattern for cpu
634 units. Each element is accessed through only one presence_list or
636 struct pattern_set_el
638 /* The number of units in unit_decls. */
640 /* The units forming the pattern. */
641 struct unit_decl
**unit_decls
;
642 pattern_set_el_t next_pattern_set_el
;
646 /* The following nodes are created in automaton generator. */
649 /* The following nodes represent presence or absence pattern for cpu
650 units. Each element is accessed through only one element of
651 unit_presence_set_table or unit_absence_set_table. */
652 struct pattern_reserv
654 reserv_sets_t reserv
;
655 pattern_reserv_t next_pattern_reserv
;
658 /* The following node type describes state automaton. The state may
659 be deterministic or non-deterministic. Non-deterministic state has
660 several component states which represent alternative cpu units
661 reservations. The state also is used for describing a
662 deterministic reservation of automaton insn. */
665 /* The following member value is nonzero if there is a transition by
668 /* The following field is list of processor unit reservations on
670 reserv_sets_t reservs
;
671 /* The following field is unique number of given state between other
674 /* The following field value is automaton to which given state
676 automaton_t automaton
;
677 /* The following field value is the first arc output from given
680 /* The following field is used to form NDFA. */
681 char it_was_placed_in_stack_for_NDFA_forming
;
682 /* The following field is used to form DFA. */
683 char it_was_placed_in_stack_for_DFA_forming
;
684 /* The following field is used to transform NDFA to DFA and DFA
685 minimization. The field value is not NULL if the state is a
686 compound state. In this case the value of field `unit_sets_list'
687 is NULL. All states in the list are in the hash table. The list
688 is formed through field `next_sorted_alt_state'. We should
689 support only one level of nesting state. */
690 alt_state_t component_states
;
691 /* The following field is used for passing graph of states. */
693 /* The list of states belonging to one equivalence class is formed
694 with the aid of the following field. */
695 state_t next_equiv_class_state
;
696 /* The two following fields are used during minimization of a finite
698 int equiv_class_num_1
, equiv_class_num_2
;
699 /* The following field is used during minimization of a finite state
700 automaton. The field value is state corresponding to equivalence
701 class to which given state belongs. */
702 state_t equiv_class_state
;
703 /* The following field value is the order number of given state.
704 The states in final DFA is enumerated with the aid of the
707 /* This member is used for passing states for searching minimal
710 /* The following member is used to evaluate min issue delay of insn
712 int min_insn_issue_delay
;
713 /* The following member is used to evaluate max issue rate of the
714 processor. The value of the member is maximal length of the path
715 from given state no containing arcs marked by special insn `cycle
717 int longest_path_length
;
720 /* The following macro is an initial value of member
721 `longest_path_length' of a state. */
722 #define UNDEFINED_LONGEST_PATH_LENGTH -1
727 /* The following field refers for the state into which given arc
730 /* The following field describes that the insn issue (with cycle
731 advancing for special insn `cycle advancing' and without cycle
732 advancing for others) makes transition from given state to
733 another given state. */
735 /* The following field value is the next arc output from the same
738 /* List of arcs marked given insn is formed with the following
739 field. The field is used in transformation NDFA -> DFA. */
740 arc_t next_arc_marked_by_insn
;
743 /* The following node type describes a deterministic alternative in
744 non-deterministic state which characterizes cpu unit reservations
745 of automaton insn or which is part of NDFA. */
748 /* The following field is a deterministic state which characterizes
749 unit reservations of the instruction. */
751 /* The following field refers to the next state which characterizes
752 unit reservations of the instruction. */
753 alt_state_t next_alt_state
;
754 /* The following field refers to the next state in sorted list. */
755 alt_state_t next_sorted_alt_state
;
758 /* The following node type describes insn of automaton. They are
759 labels of FA arcs. */
762 /* The following field value is the corresponding insn declaration
764 struct insn_reserv_decl
*insn_reserv_decl
;
765 /* The following field value is the next insn declaration for an
768 /* The following field is states which characterize automaton unit
769 reservations of the instruction. The value can be NULL only if it
770 is special insn `cycle advancing'. */
771 alt_state_t alt_states
;
772 /* The following field is sorted list of states which characterize
773 automaton unit reservations of the instruction. The value can be
774 NULL only if it is special insn `cycle advancing'. */
775 alt_state_t sorted_alt_states
;
776 /* The following field refers the next automaton insn with
777 the same reservations. */
778 ainsn_t next_same_reservs_insn
;
779 /* The following field is flag of the first automaton insn with the
780 same reservations in the declaration list. Only arcs marked such
781 insn is present in the automaton. This significantly decreases
782 memory requirements especially when several automata are
784 char first_insn_with_same_reservs
;
785 /* The following member has nonzero value if there is arc from state of
786 the automaton marked by the ainsn. */
788 /* Cyclic list of insns of an equivalence class is formed with the
789 aid of the following field. */
790 ainsn_t next_equiv_class_insn
;
791 /* The following field value is nonzero if the insn declaration is
792 the first insn declaration with given equivalence number. */
793 char first_ainsn_with_given_equivalence_num
;
794 /* The following field is number of class of equivalence of insns.
795 It is necessary because many insns may be equivalent with the
796 point of view of pipeline hazards. */
797 int insn_equiv_class_num
;
798 /* The following member value is TRUE if there is an arc in the
799 automaton marked by the insn into another state. In other
800 words, the insn can change the state of the automaton. */
804 /* The following describes an automaton for PHR. */
807 /* The following field value is the list of insn declarations for
810 /* The following field value is the corresponding automaton
811 declaration. This field is not NULL only if the automatic
812 partition on automata is not used. */
813 struct automaton_decl
*corresponding_automaton_decl
;
814 /* The following field value is the next automaton. */
815 automaton_t next_automaton
;
816 /* The following field is start state of FA. There are not unit
817 reservations in the state. */
819 /* The following field value is number of equivalence classes of
820 insns (see field `insn_equiv_class_num' in
821 `insn_reserv_decl'). */
822 int insn_equiv_classes_num
;
823 /* The following field value is number of states of final DFA. */
824 int achieved_states_num
;
825 /* The following field value is the order number (0, 1, ...) of
827 int automaton_order_num
;
828 /* The following fields contain statistics information about
829 building automaton. */
830 int NDFA_states_num
, DFA_states_num
;
831 /* The following field value is defined only if minimization of DFA
833 int minimal_DFA_states_num
;
834 int NDFA_arcs_num
, DFA_arcs_num
;
835 /* The following field value is defined only if minimization of DFA
837 int minimal_DFA_arcs_num
;
838 /* The following member refers for two table state x ainsn -> int.
839 ??? Above sentence is incomprehensible. */
840 state_ainsn_table_t trans_table
;
841 /* The following member value is maximal value of min issue delay
842 for insns of the automaton. */
844 /* Usually min issue delay is small and we can place several (2, 4,
845 8) elements in one vector element. So the compression factor can
846 be 1 (no compression), 2, 4, 8. */
847 int min_issue_delay_table_compression_factor
;
848 /* Total number of locked states in this automaton. */
852 /* The following is the element of the list of automata. */
853 struct automata_list_el
855 /* The automaton itself. */
856 automaton_t automaton
;
857 /* The next automata set element. */
858 automata_list_el_t next_automata_list_el
;
861 /* The following structure describes a table state X ainsn -> int(>= 0). */
862 struct state_ainsn_table
864 /* Automaton to which given table belongs. */
865 automaton_t automaton
;
866 /* The following tree vectors for comb vector implementation of the
868 vla_hwint_t comb_vect
;
869 vla_hwint_t check_vect
;
870 vla_hwint_t base_vect
;
871 /* This is simple implementation of the table. */
872 vla_hwint_t full_vect
;
873 /* Minimal and maximal values of the previous vectors. */
874 int min_comb_vect_el_value
, max_comb_vect_el_value
;
875 int min_base_vect_el_value
, max_base_vect_el_value
;
878 /* Macros to access members of unions. Use only them for access to
879 union members of declarations and regexps. */
881 #if defined ENABLE_CHECKING && (GCC_VERSION >= 2007)
883 #define DECL_UNIT(d) __extension__ \
884 (({ struct decl *const _decl = (d); \
885 if (_decl->mode != dm_unit) \
886 decl_mode_check_failed (_decl->mode, "dm_unit", \
887 __FILE__, __LINE__, __FUNCTION__); \
888 &(_decl)->decl.unit; }))
890 #define DECL_BYPASS(d) __extension__ \
891 (({ struct decl *const _decl = (d); \
892 if (_decl->mode != dm_bypass) \
893 decl_mode_check_failed (_decl->mode, "dm_bypass", \
894 __FILE__, __LINE__, __FUNCTION__); \
895 &(_decl)->decl.bypass; }))
897 #define DECL_AUTOMATON(d) __extension__ \
898 (({ struct decl *const _decl = (d); \
899 if (_decl->mode != dm_automaton) \
900 decl_mode_check_failed (_decl->mode, "dm_automaton", \
901 __FILE__, __LINE__, __FUNCTION__); \
902 &(_decl)->decl.automaton; }))
904 #define DECL_EXCL(d) __extension__ \
905 (({ struct decl *const _decl = (d); \
906 if (_decl->mode != dm_excl) \
907 decl_mode_check_failed (_decl->mode, "dm_excl", \
908 __FILE__, __LINE__, __FUNCTION__); \
909 &(_decl)->decl.excl; }))
911 #define DECL_PRESENCE(d) __extension__ \
912 (({ struct decl *const _decl = (d); \
913 if (_decl->mode != dm_presence) \
914 decl_mode_check_failed (_decl->mode, "dm_presence", \
915 __FILE__, __LINE__, __FUNCTION__); \
916 &(_decl)->decl.presence; }))
918 #define DECL_ABSENCE(d) __extension__ \
919 (({ struct decl *const _decl = (d); \
920 if (_decl->mode != dm_absence) \
921 decl_mode_check_failed (_decl->mode, "dm_absence", \
922 __FILE__, __LINE__, __FUNCTION__); \
923 &(_decl)->decl.absence; }))
925 #define DECL_RESERV(d) __extension__ \
926 (({ struct decl *const _decl = (d); \
927 if (_decl->mode != dm_reserv) \
928 decl_mode_check_failed (_decl->mode, "dm_reserv", \
929 __FILE__, __LINE__, __FUNCTION__); \
930 &(_decl)->decl.reserv; }))
932 #define DECL_INSN_RESERV(d) __extension__ \
933 (({ struct decl *const _decl = (d); \
934 if (_decl->mode != dm_insn_reserv) \
935 decl_mode_check_failed (_decl->mode, "dm_insn_reserv", \
936 __FILE__, __LINE__, __FUNCTION__); \
937 &(_decl)->decl.insn_reserv; }))
939 static const char *decl_name (enum decl_mode
);
940 static void decl_mode_check_failed (enum decl_mode
, const char *,
941 const char *, int, const char *)
944 /* Return string representation of declaration mode MODE. */
946 decl_name (enum decl_mode mode
)
948 static char str
[100];
952 else if (mode
== dm_bypass
)
954 else if (mode
== dm_automaton
)
955 return "dm_automaton";
956 else if (mode
== dm_excl
)
958 else if (mode
== dm_presence
)
959 return "dm_presence";
960 else if (mode
== dm_absence
)
962 else if (mode
== dm_reserv
)
964 else if (mode
== dm_insn_reserv
)
965 return "dm_insn_reserv";
967 sprintf (str
, "unknown (%d)", (int) mode
);
971 /* The function prints message about unexpected declaration and finish
974 decl_mode_check_failed (enum decl_mode mode
, const char *expected_mode_str
,
975 const char *file
, int line
, const char *func
)
979 "\n%s: %d: error in %s: DECL check: expected decl %s, have %s\n",
980 file
, line
, func
, expected_mode_str
, decl_name (mode
));
985 #define REGEXP_UNIT(r) __extension__ \
986 (({ struct regexp *const _regexp = (r); \
987 if (_regexp->mode != rm_unit) \
988 regexp_mode_check_failed (_regexp->mode, "rm_unit", \
989 __FILE__, __LINE__, __FUNCTION__); \
990 &(_regexp)->regexp.unit; }))
992 #define REGEXP_RESERV(r) __extension__ \
993 (({ struct regexp *const _regexp = (r); \
994 if (_regexp->mode != rm_reserv) \
995 regexp_mode_check_failed (_regexp->mode, "rm_reserv", \
996 __FILE__, __LINE__, __FUNCTION__); \
997 &(_regexp)->regexp.reserv; }))
999 #define REGEXP_SEQUENCE(r) __extension__ \
1000 (({ struct regexp *const _regexp = (r); \
1001 if (_regexp->mode != rm_sequence) \
1002 regexp_mode_check_failed (_regexp->mode, "rm_sequence", \
1003 __FILE__, __LINE__, __FUNCTION__); \
1004 &(_regexp)->regexp.sequence; }))
1006 #define REGEXP_REPEAT(r) __extension__ \
1007 (({ struct regexp *const _regexp = (r); \
1008 if (_regexp->mode != rm_repeat) \
1009 regexp_mode_check_failed (_regexp->mode, "rm_repeat", \
1010 __FILE__, __LINE__, __FUNCTION__); \
1011 &(_regexp)->regexp.repeat; }))
1013 #define REGEXP_ALLOF(r) __extension__ \
1014 (({ struct regexp *const _regexp = (r); \
1015 if (_regexp->mode != rm_allof) \
1016 regexp_mode_check_failed (_regexp->mode, "rm_allof", \
1017 __FILE__, __LINE__, __FUNCTION__); \
1018 &(_regexp)->regexp.allof; }))
1020 #define REGEXP_ONEOF(r) __extension__ \
1021 (({ struct regexp *const _regexp = (r); \
1022 if (_regexp->mode != rm_oneof) \
1023 regexp_mode_check_failed (_regexp->mode, "rm_oneof", \
1024 __FILE__, __LINE__, __FUNCTION__); \
1025 &(_regexp)->regexp.oneof; }))
1027 static const char *regexp_name (enum regexp_mode
);
1028 static void regexp_mode_check_failed (enum regexp_mode
, const char *,
1030 const char *) ATTRIBUTE_NORETURN
;
1033 /* Return string representation of regexp mode MODE. */
1035 regexp_name (enum regexp_mode mode
)
1044 return "rm_nothing";
1046 return "rm_sequence";
1058 /* The function prints message about unexpected regexp and finish the
1061 regexp_mode_check_failed (enum regexp_mode mode
,
1062 const char *expected_mode_str
,
1063 const char *file
, int line
, const char *func
)
1067 "\n%s: %d: error in %s: REGEXP check: expected decl %s, have %s\n",
1068 file
, line
, func
, expected_mode_str
, regexp_name (mode
));
1072 #else /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */
1074 #define DECL_UNIT(d) (&(d)->decl.unit)
1075 #define DECL_BYPASS(d) (&(d)->decl.bypass)
1076 #define DECL_AUTOMATON(d) (&(d)->decl.automaton)
1077 #define DECL_EXCL(d) (&(d)->decl.excl)
1078 #define DECL_PRESENCE(d) (&(d)->decl.presence)
1079 #define DECL_ABSENCE(d) (&(d)->decl.absence)
1080 #define DECL_RESERV(d) (&(d)->decl.reserv)
1081 #define DECL_INSN_RESERV(d) (&(d)->decl.insn_reserv)
1083 #define REGEXP_UNIT(r) (&(r)->regexp.unit)
1084 #define REGEXP_RESERV(r) (&(r)->regexp.reserv)
1085 #define REGEXP_SEQUENCE(r) (&(r)->regexp.sequence)
1086 #define REGEXP_REPEAT(r) (&(r)->regexp.repeat)
1087 #define REGEXP_ALLOF(r) (&(r)->regexp.allof)
1088 #define REGEXP_ONEOF(r) (&(r)->regexp.oneof)
1090 #endif /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */
1092 /* Create IR structure (node). */
1094 create_node (size_t size
)
1098 obstack_blank (&irp
, size
);
1099 result
= obstack_base (&irp
);
1100 obstack_finish (&irp
);
1101 /* Default values of members are NULL and zero. */
1102 memset (result
, 0, size
);
1106 /* Copy IR structure (node). */
1108 copy_node (const void *from
, size_t size
)
1110 void *const result
= create_node (size
);
1111 memcpy (result
, from
, size
);
1115 /* The function checks that NAME does not contain quotes (`"'). */
1117 check_name (const char * name
, pos_t pos ATTRIBUTE_UNUSED
)
1121 for (str
= name
; *str
!= '\0'; str
++)
1123 error ("Name `%s' contains quotes", name
);
1127 /* Pointers to all declarations during IR generation are stored in the
1129 static VEC(decl_t
,heap
) *decls
;
1131 /* Given a pointer to a (char *) and a separator, return an alloc'ed
1132 string containing the next separated element, taking parentheses
1133 into account if PAR_FLAG has nonzero value. Advance the pointer to
1134 after the string scanned, or the end-of-string. Return NULL if at
1137 next_sep_el (const char **pstr
, int sep
, int par_flag
)
1144 /* Remove leading whitespaces. */
1145 while (ISSPACE ((int) **pstr
))
1152 for (pars_num
= 0, p
= *pstr
; *p
!= '\0'; p
++)
1154 if (par_flag
&& *p
== '(')
1156 else if (par_flag
&& *p
== ')')
1158 else if (pars_num
== 0 && *p
== sep
)
1160 if (pars_num
== 0 && ISSPACE ((int) *p
))
1164 for (; n_spaces
!= 0; n_spaces
--)
1165 obstack_1grow (&irp
, p
[-n_spaces
]);
1166 obstack_1grow (&irp
, *p
);
1169 obstack_1grow (&irp
, '\0');
1170 out_str
= obstack_base (&irp
);
1171 obstack_finish (&irp
);
1180 /* Given a string and a separator, return the number of separated
1181 elements in it, taking parentheses into account if PAR_FLAG has
1182 nonzero value. Return 0 for the null string, -1 if parentheses is
1185 n_sep_els (const char *s
, int sep
, int par_flag
)
1193 for (pars_num
= 0, n
= 1; *s
; s
++)
1194 if (par_flag
&& *s
== '(')
1196 else if (par_flag
&& *s
== ')')
1198 else if (pars_num
== 0 && *s
== sep
)
1201 return (pars_num
!= 0 ? -1 : n
);
1204 /* Given a string and a separator, return vector of strings which are
1205 elements in the string and number of elements through els_num.
1206 Take parentheses into account if PAREN_P has nonzero value. The
1207 function also inserts the end marker NULL at the end of vector.
1208 Return 0 for the null string, -1 if parentheses are not balanced. */
1210 get_str_vect (const char *str
, int *els_num
, int sep
, int paren_p
)
1217 *els_num
= n_sep_els (str
, sep
, paren_p
);
1220 obstack_blank (&irp
, sizeof (char *) * (*els_num
+ 1));
1221 vect
= (char **) obstack_base (&irp
);
1222 obstack_finish (&irp
);
1224 for (i
= 0; i
< *els_num
; i
++)
1225 vect
[i
] = next_sep_el (pstr
, sep
, paren_p
);
1226 trail
= next_sep_el (pstr
, sep
, paren_p
);
1227 gcc_assert (!trail
);
1232 /* Process a DEFINE_CPU_UNIT.
1234 This gives information about a unit contained in CPU. We fill a
1235 struct unit_decl with information used later by `expand_automata'. */
1237 gen_cpu_unit (rtx def
)
1240 char **str_cpu_units
;
1244 str_cpu_units
= get_str_vect (XSTR (def
, 0), &vect_length
, ',', FALSE
);
1245 if (str_cpu_units
== NULL
)
1246 fatal ("invalid string `%s' in define_cpu_unit", XSTR (def
, 0));
1247 for (i
= 0; i
< vect_length
; i
++)
1249 decl
= create_node (sizeof (struct decl
));
1250 decl
->mode
= dm_unit
;
1252 DECL_UNIT (decl
)->name
= check_name (str_cpu_units
[i
], decl
->pos
);
1253 DECL_UNIT (decl
)->automaton_name
= XSTR (def
, 1);
1254 DECL_UNIT (decl
)->query_p
= 0;
1255 DECL_UNIT (decl
)->min_occ_cycle_num
= -1;
1256 DECL_UNIT (decl
)->in_set_p
= 0;
1257 VEC_safe_push (decl_t
,heap
, decls
, decl
);
1261 /* Process a DEFINE_QUERY_CPU_UNIT.
1263 This gives information about a unit contained in CPU. We fill a
1264 struct unit_decl with information used later by `expand_automata'. */
1266 gen_query_cpu_unit (rtx def
)
1269 char **str_cpu_units
;
1273 str_cpu_units
= get_str_vect (XSTR (def
, 0), &vect_length
, ',',
1275 if (str_cpu_units
== NULL
)
1276 fatal ("invalid string `%s' in define_query_cpu_unit", XSTR (def
, 0));
1277 for (i
= 0; i
< vect_length
; i
++)
1279 decl
= create_node (sizeof (struct decl
));
1280 decl
->mode
= dm_unit
;
1282 DECL_UNIT (decl
)->name
= check_name (str_cpu_units
[i
], decl
->pos
);
1283 DECL_UNIT (decl
)->automaton_name
= XSTR (def
, 1);
1284 DECL_UNIT (decl
)->query_p
= 1;
1285 VEC_safe_push (decl_t
,heap
, decls
, decl
);
1289 /* Process a DEFINE_BYPASS.
1291 This gives information about a unit contained in the CPU. We fill
1292 in a struct bypass_decl with information used later by
1293 `expand_automata'. */
1295 gen_bypass (rtx def
)
1304 out_insns
= get_str_vect (XSTR (def
, 1), &out_length
, ',', FALSE
);
1305 if (out_insns
== NULL
)
1306 fatal ("invalid string `%s' in define_bypass", XSTR (def
, 1));
1307 in_insns
= get_str_vect (XSTR (def
, 2), &in_length
, ',', FALSE
);
1308 if (in_insns
== NULL
)
1309 fatal ("invalid string `%s' in define_bypass", XSTR (def
, 2));
1310 for (i
= 0; i
< out_length
; i
++)
1311 for (j
= 0; j
< in_length
; j
++)
1313 decl
= create_node (sizeof (struct decl
));
1314 decl
->mode
= dm_bypass
;
1316 DECL_BYPASS (decl
)->latency
= XINT (def
, 0);
1317 DECL_BYPASS (decl
)->out_insn_name
= out_insns
[i
];
1318 DECL_BYPASS (decl
)->in_insn_name
= in_insns
[j
];
1319 DECL_BYPASS (decl
)->bypass_guard_name
= XSTR (def
, 3);
1320 VEC_safe_push (decl_t
,heap
, decls
, decl
);
1324 /* Process an EXCLUSION_SET.
1326 This gives information about a cpu unit conflicts. We fill a
1327 struct excl_rel_decl (excl) with information used later by
1328 `expand_automata'. */
1330 gen_excl_set (rtx def
)
1333 char **first_str_cpu_units
;
1334 char **second_str_cpu_units
;
1335 int first_vect_length
;
1340 = get_str_vect (XSTR (def
, 0), &first_vect_length
, ',', FALSE
);
1341 if (first_str_cpu_units
== NULL
)
1342 fatal ("invalid first string `%s' in exclusion_set", XSTR (def
, 0));
1343 second_str_cpu_units
= get_str_vect (XSTR (def
, 1), &length
, ',',
1345 if (second_str_cpu_units
== NULL
)
1346 fatal ("invalid second string `%s' in exclusion_set", XSTR (def
, 1));
1347 length
+= first_vect_length
;
1348 decl
= create_node (sizeof (struct decl
) + (length
- 1) * sizeof (char *));
1349 decl
->mode
= dm_excl
;
1351 DECL_EXCL (decl
)->all_names_num
= length
;
1352 DECL_EXCL (decl
)->first_list_length
= first_vect_length
;
1353 for (i
= 0; i
< length
; i
++)
1354 if (i
< first_vect_length
)
1355 DECL_EXCL (decl
)->names
[i
] = first_str_cpu_units
[i
];
1357 DECL_EXCL (decl
)->names
[i
]
1358 = second_str_cpu_units
[i
- first_vect_length
];
1359 VEC_safe_push (decl_t
,heap
, decls
, decl
);
1362 /* Process a PRESENCE_SET, a FINAL_PRESENCE_SET, an ABSENCE_SET,
1363 FINAL_ABSENCE_SET (it is depended on PRESENCE_P and FINAL_P).
1365 This gives information about a cpu unit reservation requirements.
1366 We fill a struct unit_pattern_rel_decl with information used later
1367 by `expand_automata'. */
1369 gen_presence_absence_set (rtx def
, int presence_p
, int final_p
)
1372 char **str_cpu_units
;
1373 char **str_pattern_lists
;
1374 char ***str_patterns
;
1375 int cpu_units_length
;
1377 int patterns_length
;
1380 str_cpu_units
= get_str_vect (XSTR (def
, 0), &cpu_units_length
, ',',
1382 if (str_cpu_units
== NULL
)
1385 ? "invalid first string `%s' in final_presence_set"
1386 : "invalid first string `%s' in presence_set")
1388 ? "invalid first string `%s' in final_absence_set"
1389 : "invalid first string `%s' in absence_set")),
1391 str_pattern_lists
= get_str_vect (XSTR (def
, 1),
1392 &patterns_length
, ',', FALSE
);
1393 if (str_pattern_lists
== NULL
)
1396 ? "invalid second string `%s' in final_presence_set"
1397 : "invalid second string `%s' in presence_set")
1399 ? "invalid second string `%s' in final_absence_set"
1400 : "invalid second string `%s' in absence_set")), XSTR (def
, 1));
1401 str_patterns
= obstack_alloc (&irp
, patterns_length
* sizeof (char **));
1402 for (i
= 0; i
< patterns_length
; i
++)
1404 str_patterns
[i
] = get_str_vect (str_pattern_lists
[i
],
1405 &length
, ' ', FALSE
);
1406 gcc_assert (str_patterns
[i
]);
1408 decl
= create_node (sizeof (struct decl
));
1412 decl
->mode
= dm_presence
;
1413 DECL_PRESENCE (decl
)->names_num
= cpu_units_length
;
1414 DECL_PRESENCE (decl
)->names
= str_cpu_units
;
1415 DECL_PRESENCE (decl
)->patterns
= str_patterns
;
1416 DECL_PRESENCE (decl
)->patterns_num
= patterns_length
;
1417 DECL_PRESENCE (decl
)->final_p
= final_p
;
1421 decl
->mode
= dm_absence
;
1422 DECL_ABSENCE (decl
)->names_num
= cpu_units_length
;
1423 DECL_ABSENCE (decl
)->names
= str_cpu_units
;
1424 DECL_ABSENCE (decl
)->patterns
= str_patterns
;
1425 DECL_ABSENCE (decl
)->patterns_num
= patterns_length
;
1426 DECL_ABSENCE (decl
)->final_p
= final_p
;
1428 VEC_safe_push (decl_t
,heap
, decls
, decl
);
1431 /* Process a PRESENCE_SET.
1433 This gives information about a cpu unit reservation requirements.
1434 We fill a struct unit_pattern_rel_decl (presence) with information
1435 used later by `expand_automata'. */
1437 gen_presence_set (rtx def
)
1439 gen_presence_absence_set (def
, TRUE
, FALSE
);
1442 /* Process a FINAL_PRESENCE_SET.
1444 This gives information about a cpu unit reservation requirements.
1445 We fill a struct unit_pattern_rel_decl (presence) with information
1446 used later by `expand_automata'. */
1448 gen_final_presence_set (rtx def
)
1450 gen_presence_absence_set (def
, TRUE
, TRUE
);
1453 /* Process an ABSENCE_SET.
1455 This gives information about a cpu unit reservation requirements.
1456 We fill a struct unit_pattern_rel_decl (absence) with information
1457 used later by `expand_automata'. */
1459 gen_absence_set (rtx def
)
1461 gen_presence_absence_set (def
, FALSE
, FALSE
);
1464 /* Process a FINAL_ABSENCE_SET.
1466 This gives information about a cpu unit reservation requirements.
1467 We fill a struct unit_pattern_rel_decl (absence) with information
1468 used later by `expand_automata'. */
1470 gen_final_absence_set (rtx def
)
1472 gen_presence_absence_set (def
, FALSE
, TRUE
);
1475 /* Process a DEFINE_AUTOMATON.
1477 This gives information about a finite state automaton used for
1478 recognizing pipeline hazards. We fill a struct automaton_decl
1479 with information used later by `expand_automata'. */
1481 gen_automaton (rtx def
)
1484 char **str_automata
;
1488 str_automata
= get_str_vect (XSTR (def
, 0), &vect_length
, ',', FALSE
);
1489 if (str_automata
== NULL
)
1490 fatal ("invalid string `%s' in define_automaton", XSTR (def
, 0));
1491 for (i
= 0; i
< vect_length
; i
++)
1493 decl
= create_node (sizeof (struct decl
));
1494 decl
->mode
= dm_automaton
;
1496 DECL_AUTOMATON (decl
)->name
= check_name (str_automata
[i
], decl
->pos
);
1497 VEC_safe_push (decl_t
,heap
, decls
, decl
);
1501 /* Process an AUTOMATA_OPTION.
1503 This gives information how to generate finite state automaton used
1504 for recognizing pipeline hazards. */
1506 gen_automata_option (rtx def
)
1508 if (strcmp (XSTR (def
, 0), NO_MINIMIZATION_OPTION
+ 1) == 0)
1509 no_minimization_flag
= 1;
1510 else if (strcmp (XSTR (def
, 0), TIME_OPTION
+ 1) == 0)
1512 else if (strcmp (XSTR (def
, 0), V_OPTION
+ 1) == 0)
1514 else if (strcmp (XSTR (def
, 0), W_OPTION
+ 1) == 0)
1516 else if (strcmp (XSTR (def
, 0), NDFA_OPTION
+ 1) == 0)
1518 else if (strcmp (XSTR (def
, 0), PROGRESS_OPTION
+ 1) == 0)
1521 fatal ("invalid option `%s' in automata_option", XSTR (def
, 0));
1524 /* Name in reservation to denote absence reservation. */
1525 #define NOTHING_NAME "nothing"
1527 /* The following string contains original reservation string being
1529 static const char *reserv_str
;
1531 /* Parse an element in STR. */
1533 gen_regexp_el (const char *str
)
1542 if (str
[len
- 1] != ')')
1543 fatal ("garbage after ) in reservation `%s'", reserv_str
);
1544 dstr
= alloca (len
- 1);
1545 memcpy (dstr
, str
+ 1, len
- 2);
1546 dstr
[len
-2] = '\0';
1547 regexp
= gen_regexp_sequence (dstr
);
1549 else if (strcmp (str
, NOTHING_NAME
) == 0)
1551 regexp
= create_node (sizeof (struct decl
));
1552 regexp
->mode
= rm_nothing
;
1556 regexp
= create_node (sizeof (struct decl
));
1557 regexp
->mode
= rm_unit
;
1558 REGEXP_UNIT (regexp
)->name
= str
;
1563 /* Parse construction `repeat' in STR. */
1565 gen_regexp_repeat (const char *str
)
1573 repeat_vect
= get_str_vect (str
, &els_num
, '*', TRUE
);
1574 if (repeat_vect
== NULL
)
1575 fatal ("invalid `%s' in reservation `%s'", str
, reserv_str
);
1578 regexp
= gen_regexp_el (repeat_vect
[0]);
1579 for (i
= 1; i
< els_num
; i
++)
1581 repeat
= create_node (sizeof (struct regexp
));
1582 repeat
->mode
= rm_repeat
;
1583 REGEXP_REPEAT (repeat
)->regexp
= regexp
;
1584 REGEXP_REPEAT (repeat
)->repeat_num
= atoi (repeat_vect
[i
]);
1585 if (REGEXP_REPEAT (repeat
)->repeat_num
<= 1)
1586 fatal ("repetition `%s' <= 1 in reservation `%s'",
1593 return gen_regexp_el (str
);
1596 /* Parse reservation STR which possibly contains separator '+'. */
1598 gen_regexp_allof (const char *str
)
1605 allof_vect
= get_str_vect (str
, &els_num
, '+', TRUE
);
1606 if (allof_vect
== NULL
)
1607 fatal ("invalid `%s' in reservation `%s'", str
, reserv_str
);
1610 allof
= create_node (sizeof (struct regexp
)
1611 + sizeof (regexp_t
) * (els_num
- 1));
1612 allof
->mode
= rm_allof
;
1613 REGEXP_ALLOF (allof
)->regexps_num
= els_num
;
1614 for (i
= 0; i
< els_num
; i
++)
1615 REGEXP_ALLOF (allof
)->regexps
[i
] = gen_regexp_repeat (allof_vect
[i
]);
1619 return gen_regexp_repeat (str
);
1622 /* Parse reservation STR which possibly contains separator '|'. */
1624 gen_regexp_oneof (const char *str
)
1631 oneof_vect
= get_str_vect (str
, &els_num
, '|', TRUE
);
1632 if (oneof_vect
== NULL
)
1633 fatal ("invalid `%s' in reservation `%s'", str
, reserv_str
);
1636 oneof
= create_node (sizeof (struct regexp
)
1637 + sizeof (regexp_t
) * (els_num
- 1));
1638 oneof
->mode
= rm_oneof
;
1639 REGEXP_ONEOF (oneof
)->regexps_num
= els_num
;
1640 for (i
= 0; i
< els_num
; i
++)
1641 REGEXP_ONEOF (oneof
)->regexps
[i
] = gen_regexp_allof (oneof_vect
[i
]);
1645 return gen_regexp_allof (str
);
1648 /* Parse reservation STR which possibly contains separator ','. */
1650 gen_regexp_sequence (const char *str
)
1653 char **sequence_vect
;
1657 sequence_vect
= get_str_vect (str
, &els_num
, ',', TRUE
);
1660 sequence
= create_node (sizeof (struct regexp
)
1661 + sizeof (regexp_t
) * (els_num
- 1));
1662 sequence
->mode
= rm_sequence
;
1663 REGEXP_SEQUENCE (sequence
)->regexps_num
= els_num
;
1664 for (i
= 0; i
< els_num
; i
++)
1665 REGEXP_SEQUENCE (sequence
)->regexps
[i
]
1666 = gen_regexp_oneof (sequence_vect
[i
]);
1670 return gen_regexp_oneof (str
);
1673 /* Parse construction reservation STR. */
1675 gen_regexp (const char *str
)
1678 return gen_regexp_sequence (str
);;
1681 /* Process a DEFINE_RESERVATION.
1683 This gives information about a reservation of cpu units. We fill
1684 in a struct reserv_decl with information used later by
1685 `expand_automata'. */
1687 gen_reserv (rtx def
)
1691 decl
= create_node (sizeof (struct decl
));
1692 decl
->mode
= dm_reserv
;
1694 DECL_RESERV (decl
)->name
= check_name (XSTR (def
, 0), decl
->pos
);
1695 DECL_RESERV (decl
)->regexp
= gen_regexp (XSTR (def
, 1));
1696 VEC_safe_push (decl_t
,heap
, decls
, decl
);
1699 /* Process a DEFINE_INSN_RESERVATION.
1701 This gives information about the reservation of cpu units by an
1702 insn. We fill a struct insn_reserv_decl with information used
1703 later by `expand_automata'. */
1705 gen_insn_reserv (rtx def
)
1709 decl
= create_node (sizeof (struct decl
));
1710 decl
->mode
= dm_insn_reserv
;
1712 DECL_INSN_RESERV (decl
)->name
1713 = check_name (XSTR (def
, 0), decl
->pos
);
1714 DECL_INSN_RESERV (decl
)->default_latency
= XINT (def
, 1);
1715 DECL_INSN_RESERV (decl
)->condexp
= XEXP (def
, 2);
1716 DECL_INSN_RESERV (decl
)->regexp
= gen_regexp (XSTR (def
, 3));
1717 VEC_safe_push (decl_t
,heap
, decls
, decl
);
1722 /* The function evaluates hash value (0..UINT_MAX) of string. */
1724 string_hash (const char *string
)
1728 for (result
= i
= 0;*string
++ != '\0'; i
++)
1729 result
+= ((unsigned char) *string
<< (i
% CHAR_BIT
));
1735 /* This page contains abstract data `table of automaton declarations'.
1736 Elements of the table is nodes representing automaton declarations.
1737 Key of the table elements is name of given automaton. Remember
1738 that automaton names have own space. */
1740 /* The function evaluates hash value of an automaton declaration. The
1741 function is used by abstract data `hashtab'. The function returns
1742 hash value (0..UINT_MAX) of given automaton declaration. */
1744 automaton_decl_hash (const void *automaton_decl
)
1746 const decl_t decl
= (decl_t
) automaton_decl
;
1748 gcc_assert (decl
->mode
!= dm_automaton
1749 || DECL_AUTOMATON (decl
)->name
);
1750 return string_hash (DECL_AUTOMATON (decl
)->name
);
1753 /* The function tests automaton declarations on equality of their
1754 keys. The function is used by abstract data `hashtab'. The
1755 function returns 1 if the declarations have the same key, 0
1758 automaton_decl_eq_p (const void* automaton_decl_1
,
1759 const void* automaton_decl_2
)
1761 const decl_t decl1
= (decl_t
) automaton_decl_1
;
1762 const decl_t decl2
= (decl_t
) automaton_decl_2
;
1764 gcc_assert (decl1
->mode
== dm_automaton
1765 && DECL_AUTOMATON (decl1
)->name
1766 && decl2
->mode
== dm_automaton
1767 && DECL_AUTOMATON (decl2
)->name
);
1768 return strcmp (DECL_AUTOMATON (decl1
)->name
,
1769 DECL_AUTOMATON (decl2
)->name
) == 0;
1772 /* The automaton declaration table itself is represented by the
1773 following variable. */
1774 static htab_t automaton_decl_table
;
1776 /* The function inserts automaton declaration into the table. The
1777 function does nothing if an automaton declaration with the same key
1778 exists already in the table. The function returns automaton
1779 declaration node in the table with the same key as given automaton
1780 declaration node. */
1782 insert_automaton_decl (decl_t automaton_decl
)
1786 entry_ptr
= htab_find_slot (automaton_decl_table
, automaton_decl
, 1);
1787 if (*entry_ptr
== NULL
)
1788 *entry_ptr
= (void *) automaton_decl
;
1789 return (decl_t
) *entry_ptr
;
1792 /* The following variable value is node representing automaton
1793 declaration. The node used for searching automaton declaration
1795 static struct decl work_automaton_decl
;
1797 /* The function searches for automaton declaration in the table with
1798 the same key as node representing name of the automaton
1799 declaration. The function returns node found in the table, NULL if
1800 such node does not exist in the table. */
1802 find_automaton_decl (const char *name
)
1806 work_automaton_decl
.mode
= dm_automaton
;
1807 DECL_AUTOMATON (&work_automaton_decl
)->name
= name
;
1808 entry
= htab_find (automaton_decl_table
, &work_automaton_decl
);
1809 return (decl_t
) entry
;
1812 /* The function creates empty automaton declaration table and node
1813 representing automaton declaration and used for searching automaton
1814 declaration with given name. The function must be called only once
1815 before any work with the automaton declaration table. */
1817 initiate_automaton_decl_table (void)
1819 work_automaton_decl
.mode
= dm_automaton
;
1820 automaton_decl_table
= htab_create (10, automaton_decl_hash
,
1821 automaton_decl_eq_p
, (htab_del
) 0);
1824 /* The function deletes the automaton declaration table. Only call of
1825 function `initiate_automaton_decl_table' is possible immediately
1826 after this function call. */
1828 finish_automaton_decl_table (void)
1830 htab_delete (automaton_decl_table
);
1835 /* This page contains abstract data `table of insn declarations'.
1836 Elements of the table is nodes representing insn declarations. Key
1837 of the table elements is name of given insn (in corresponding
1838 define_insn_reservation). Remember that insn names have own
1841 /* The function evaluates hash value of an insn declaration. The
1842 function is used by abstract data `hashtab'. The function returns
1843 hash value (0..UINT_MAX) of given insn declaration. */
1845 insn_decl_hash (const void *insn_decl
)
1847 const decl_t decl
= (decl_t
) insn_decl
;
1849 gcc_assert (decl
->mode
== dm_insn_reserv
1850 && DECL_INSN_RESERV (decl
)->name
);
1851 return string_hash (DECL_INSN_RESERV (decl
)->name
);
1854 /* The function tests insn declarations on equality of their keys.
1855 The function is used by abstract data `hashtab'. The function
1856 returns 1 if declarations have the same key, 0 otherwise. */
1858 insn_decl_eq_p (const void *insn_decl_1
, const void *insn_decl_2
)
1860 const decl_t decl1
= (decl_t
) insn_decl_1
;
1861 const decl_t decl2
= (decl_t
) insn_decl_2
;
1863 gcc_assert (decl1
->mode
== dm_insn_reserv
1864 && DECL_INSN_RESERV (decl1
)->name
1865 && decl2
->mode
== dm_insn_reserv
1866 && DECL_INSN_RESERV (decl2
)->name
);
1867 return strcmp (DECL_INSN_RESERV (decl1
)->name
,
1868 DECL_INSN_RESERV (decl2
)->name
) == 0;
1871 /* The insn declaration table itself is represented by the following
1872 variable. The table does not contain insn reservation
1874 static htab_t insn_decl_table
;
1876 /* The function inserts insn declaration into the table. The function
1877 does nothing if an insn declaration with the same key exists
1878 already in the table. The function returns insn declaration node
1879 in the table with the same key as given insn declaration node. */
1881 insert_insn_decl (decl_t insn_decl
)
1885 entry_ptr
= htab_find_slot (insn_decl_table
, insn_decl
, 1);
1886 if (*entry_ptr
== NULL
)
1887 *entry_ptr
= (void *) insn_decl
;
1888 return (decl_t
) *entry_ptr
;
1891 /* The following variable value is node representing insn reservation
1892 declaration. The node used for searching insn reservation
1893 declaration with given name. */
1894 static struct decl work_insn_decl
;
1896 /* The function searches for insn reservation declaration in the table
1897 with the same key as node representing name of the insn reservation
1898 declaration. The function returns node found in the table, NULL if
1899 such node does not exist in the table. */
1901 find_insn_decl (const char *name
)
1905 work_insn_decl
.mode
= dm_insn_reserv
;
1906 DECL_INSN_RESERV (&work_insn_decl
)->name
= name
;
1907 entry
= htab_find (insn_decl_table
, &work_insn_decl
);
1908 return (decl_t
) entry
;
1911 /* The function creates empty insn declaration table and node
1912 representing insn declaration and used for searching insn
1913 declaration with given name. The function must be called only once
1914 before any work with the insn declaration table. */
1916 initiate_insn_decl_table (void)
1918 work_insn_decl
.mode
= dm_insn_reserv
;
1919 insn_decl_table
= htab_create (10, insn_decl_hash
, insn_decl_eq_p
,
1923 /* The function deletes the insn declaration table. Only call of
1924 function `initiate_insn_decl_table' is possible immediately after
1925 this function call. */
1927 finish_insn_decl_table (void)
1929 htab_delete (insn_decl_table
);
1934 /* This page contains abstract data `table of declarations'. Elements
1935 of the table is nodes representing declarations (of units and
1936 reservations). Key of the table elements is names of given
1939 /* The function evaluates hash value of a declaration. The function
1940 is used by abstract data `hashtab'. The function returns hash
1941 value (0..UINT_MAX) of given declaration. */
1943 decl_hash (const void *decl
)
1945 const decl_t d
= (const decl_t
) decl
;
1947 gcc_assert ((d
->mode
== dm_unit
&& DECL_UNIT (d
)->name
)
1948 || (d
->mode
== dm_reserv
&& DECL_RESERV (d
)->name
));
1949 return string_hash (d
->mode
== dm_unit
1950 ? DECL_UNIT (d
)->name
: DECL_RESERV (d
)->name
);
1953 /* The function tests declarations on equality of their keys. The
1954 function is used by abstract data 'hashtab'. The function
1955 returns 1 if the declarations have the same key, 0 otherwise. */
1957 decl_eq_p (const void *decl_1
, const void *decl_2
)
1959 const decl_t d1
= (const decl_t
) decl_1
;
1960 const decl_t d2
= (const decl_t
) decl_2
;
1962 gcc_assert ((d1
->mode
== dm_unit
&& DECL_UNIT (d1
)->name
)
1963 || (d1
->mode
== dm_reserv
&& DECL_RESERV (d1
)->name
));
1964 gcc_assert ((d2
->mode
== dm_unit
&& DECL_UNIT (d2
)->name
)
1965 || (d2
->mode
== dm_reserv
&& DECL_RESERV (d2
)->name
));
1966 return strcmp ((d1
->mode
== dm_unit
1967 ? DECL_UNIT (d1
)->name
: DECL_RESERV (d1
)->name
),
1968 (d2
->mode
== dm_unit
1969 ? DECL_UNIT (d2
)->name
: DECL_RESERV (d2
)->name
)) == 0;
1972 /* The declaration table itself is represented by the following
1974 static htab_t decl_table
;
1976 /* The function inserts declaration into the table. The function does
1977 nothing if a declaration with the same key exists already in the
1978 table. The function returns declaration node in the table with the
1979 same key as given declaration node. */
1982 insert_decl (decl_t decl
)
1986 entry_ptr
= htab_find_slot (decl_table
, decl
, 1);
1987 if (*entry_ptr
== NULL
)
1988 *entry_ptr
= (void *) decl
;
1989 return (decl_t
) *entry_ptr
;
1992 /* The following variable value is node representing declaration. The
1993 node used for searching declaration with given name. */
1994 static struct decl work_decl
;
1996 /* The function searches for declaration in the table with the same
1997 key as node representing name of the declaration. The function
1998 returns node found in the table, NULL if such node does not exist
2001 find_decl (const char *name
)
2005 work_decl
.mode
= dm_unit
;
2006 DECL_UNIT (&work_decl
)->name
= name
;
2007 entry
= htab_find (decl_table
, &work_decl
);
2008 return (decl_t
) entry
;
2011 /* The function creates empty declaration table and node representing
2012 declaration and used for searching declaration with given name.
2013 The function must be called only once before any work with the
2014 declaration table. */
2016 initiate_decl_table (void)
2018 work_decl
.mode
= dm_unit
;
2019 decl_table
= htab_create (10, decl_hash
, decl_eq_p
, (htab_del
) 0);
2022 /* The function deletes the declaration table. Only call of function
2023 `initiate_declaration_table' is possible immediately after this
2026 finish_decl_table (void)
2028 htab_delete (decl_table
);
2033 /* This page contains checker of pipeline hazard description. */
2035 /* Checking NAMES in an exclusion clause vector and returning formed
2036 unit_set_el_list. */
2037 static unit_set_el_t
2038 process_excls (char **names
, int num
, pos_t excl_pos ATTRIBUTE_UNUSED
)
2040 unit_set_el_t el_list
;
2041 unit_set_el_t last_el
;
2042 unit_set_el_t new_el
;
2043 decl_t decl_in_table
;
2048 for (i
= 0; i
< num
; i
++)
2050 decl_in_table
= find_decl (names
[i
]);
2051 if (decl_in_table
== NULL
)
2052 error ("unit `%s' in exclusion is not declared", names
[i
]);
2053 else if (decl_in_table
->mode
!= dm_unit
)
2054 error ("`%s' in exclusion is not unit", names
[i
]);
2057 new_el
= create_node (sizeof (struct unit_set_el
));
2058 new_el
->unit_decl
= DECL_UNIT (decl_in_table
);
2059 new_el
->next_unit_set_el
= NULL
;
2060 if (last_el
== NULL
)
2061 el_list
= last_el
= new_el
;
2064 last_el
->next_unit_set_el
= new_el
;
2065 last_el
= last_el
->next_unit_set_el
;
2072 /* The function adds each element from SOURCE_LIST to the exclusion
2073 list of the each element from DEST_LIST. Checking situation "unit
2074 excludes itself". */
2076 add_excls (unit_set_el_t dest_list
, unit_set_el_t source_list
,
2077 pos_t excl_pos ATTRIBUTE_UNUSED
)
2081 unit_set_el_t curr_el
;
2082 unit_set_el_t prev_el
;
2085 for (dst
= dest_list
; dst
!= NULL
; dst
= dst
->next_unit_set_el
)
2086 for (src
= source_list
; src
!= NULL
; src
= src
->next_unit_set_el
)
2088 if (dst
->unit_decl
== src
->unit_decl
)
2090 error ("unit `%s' excludes itself", src
->unit_decl
->name
);
2093 if (dst
->unit_decl
->automaton_name
!= NULL
2094 && src
->unit_decl
->automaton_name
!= NULL
2095 && strcmp (dst
->unit_decl
->automaton_name
,
2096 src
->unit_decl
->automaton_name
) != 0)
2098 error ("units `%s' and `%s' in exclusion set belong to different automata",
2099 src
->unit_decl
->name
, dst
->unit_decl
->name
);
2102 for (curr_el
= dst
->unit_decl
->excl_list
, prev_el
= NULL
;
2104 prev_el
= curr_el
, curr_el
= curr_el
->next_unit_set_el
)
2105 if (curr_el
->unit_decl
== src
->unit_decl
)
2107 if (curr_el
== NULL
)
2109 /* Element not found - insert. */
2110 copy
= copy_node (src
, sizeof (*src
));
2111 copy
->next_unit_set_el
= NULL
;
2112 if (prev_el
== NULL
)
2113 dst
->unit_decl
->excl_list
= copy
;
2115 prev_el
->next_unit_set_el
= copy
;
2120 /* Checking NAMES in presence/absence clause and returning the
2121 formed unit_set_el_list. The function is called only after
2122 processing all exclusion sets. */
2123 static unit_set_el_t
2124 process_presence_absence_names (char **names
, int num
,
2125 pos_t req_pos ATTRIBUTE_UNUSED
,
2126 int presence_p
, int final_p
)
2128 unit_set_el_t el_list
;
2129 unit_set_el_t last_el
;
2130 unit_set_el_t new_el
;
2131 decl_t decl_in_table
;
2136 for (i
= 0; i
< num
; i
++)
2138 decl_in_table
= find_decl (names
[i
]);
2139 if (decl_in_table
== NULL
)
2142 ? "unit `%s' in final presence set is not declared"
2143 : "unit `%s' in presence set is not declared")
2145 ? "unit `%s' in final absence set is not declared"
2146 : "unit `%s' in absence set is not declared")), names
[i
]);
2147 else if (decl_in_table
->mode
!= dm_unit
)
2150 ? "`%s' in final presence set is not unit"
2151 : "`%s' in presence set is not unit")
2153 ? "`%s' in final absence set is not unit"
2154 : "`%s' in absence set is not unit")), names
[i
]);
2157 new_el
= create_node (sizeof (struct unit_set_el
));
2158 new_el
->unit_decl
= DECL_UNIT (decl_in_table
);
2159 new_el
->next_unit_set_el
= NULL
;
2160 if (last_el
== NULL
)
2161 el_list
= last_el
= new_el
;
2164 last_el
->next_unit_set_el
= new_el
;
2165 last_el
= last_el
->next_unit_set_el
;
2172 /* Checking NAMES in patterns of a presence/absence clause and
2173 returning the formed pattern_set_el_list. The function is called
2174 only after processing all exclusion sets. */
2175 static pattern_set_el_t
2176 process_presence_absence_patterns (char ***patterns
, int num
,
2177 pos_t req_pos ATTRIBUTE_UNUSED
,
2178 int presence_p
, int final_p
)
2180 pattern_set_el_t el_list
;
2181 pattern_set_el_t last_el
;
2182 pattern_set_el_t new_el
;
2183 decl_t decl_in_table
;
2188 for (i
= 0; i
< num
; i
++)
2190 for (j
= 0; patterns
[i
] [j
] != NULL
; j
++)
2192 new_el
= create_node (sizeof (struct pattern_set_el
)
2193 + sizeof (struct unit_decl
*) * j
);
2195 = (struct unit_decl
**) ((char *) new_el
2196 + sizeof (struct pattern_set_el
));
2197 new_el
->next_pattern_set_el
= NULL
;
2198 if (last_el
== NULL
)
2199 el_list
= last_el
= new_el
;
2202 last_el
->next_pattern_set_el
= new_el
;
2203 last_el
= last_el
->next_pattern_set_el
;
2205 new_el
->units_num
= 0;
2206 for (j
= 0; patterns
[i
] [j
] != NULL
; j
++)
2208 decl_in_table
= find_decl (patterns
[i
] [j
]);
2209 if (decl_in_table
== NULL
)
2212 ? "unit `%s' in final presence set is not declared"
2213 : "unit `%s' in presence set is not declared")
2215 ? "unit `%s' in final absence set is not declared"
2216 : "unit `%s' in absence set is not declared")),
2218 else if (decl_in_table
->mode
!= dm_unit
)
2221 ? "`%s' in final presence set is not unit"
2222 : "`%s' in presence set is not unit")
2224 ? "`%s' in final absence set is not unit"
2225 : "`%s' in absence set is not unit")),
2229 new_el
->unit_decls
[new_el
->units_num
]
2230 = DECL_UNIT (decl_in_table
);
2231 new_el
->units_num
++;
2238 /* The function adds each element from PATTERN_LIST to presence (if
2239 PRESENCE_P) or absence list of the each element from DEST_LIST.
2240 Checking situations "unit requires own absence", and "unit excludes
2241 and requires presence of ...", "unit requires absence and presence
2242 of ...", "units in (final) presence set belong to different
2243 automata", and "units in (final) absence set belong to different
2244 automata". Remember that we process absence sets only after all
2247 add_presence_absence (unit_set_el_t dest_list
,
2248 pattern_set_el_t pattern_list
,
2249 pos_t req_pos ATTRIBUTE_UNUSED
,
2250 int presence_p
, int final_p
)
2253 pattern_set_el_t pat
;
2254 struct unit_decl
*unit
;
2255 unit_set_el_t curr_excl_el
;
2256 pattern_set_el_t curr_pat_el
;
2257 pattern_set_el_t prev_el
;
2258 pattern_set_el_t copy
;
2262 for (dst
= dest_list
; dst
!= NULL
; dst
= dst
->next_unit_set_el
)
2263 for (pat
= pattern_list
; pat
!= NULL
; pat
= pat
->next_pattern_set_el
)
2265 for (i
= 0; i
< pat
->units_num
; i
++)
2267 unit
= pat
->unit_decls
[i
];
2268 if (dst
->unit_decl
== unit
&& pat
->units_num
== 1 && !presence_p
)
2270 error ("unit `%s' requires own absence", unit
->name
);
2273 if (dst
->unit_decl
->automaton_name
!= NULL
2274 && unit
->automaton_name
!= NULL
2275 && strcmp (dst
->unit_decl
->automaton_name
,
2276 unit
->automaton_name
) != 0)
2280 ? "units `%s' and `%s' in final presence set belong to different automata"
2281 : "units `%s' and `%s' in presence set belong to different automata")
2283 ? "units `%s' and `%s' in final absence set belong to different automata"
2284 : "units `%s' and `%s' in absence set belong to different automata")),
2285 unit
->name
, dst
->unit_decl
->name
);
2290 for (curr_excl_el
= dst
->unit_decl
->excl_list
;
2291 curr_excl_el
!= NULL
;
2292 curr_excl_el
= curr_excl_el
->next_unit_set_el
)
2294 if (unit
== curr_excl_el
->unit_decl
&& pat
->units_num
== 1)
2298 error ("unit `%s' excludes and requires presence of `%s'",
2299 dst
->unit_decl
->name
, unit
->name
);
2304 (0, "unit `%s' excludes and requires presence of `%s'",
2305 dst
->unit_decl
->name
, unit
->name
);
2308 else if (pat
->units_num
== 1)
2309 for (curr_pat_el
= dst
->unit_decl
->presence_list
;
2310 curr_pat_el
!= NULL
;
2311 curr_pat_el
= curr_pat_el
->next_pattern_set_el
)
2312 if (curr_pat_el
->units_num
== 1
2313 && unit
== curr_pat_el
->unit_decls
[0])
2318 ("unit `%s' requires absence and presence of `%s'",
2319 dst
->unit_decl
->name
, unit
->name
);
2324 (0, "unit `%s' requires absence and presence of `%s'",
2325 dst
->unit_decl
->name
, unit
->name
);
2329 for (prev_el
= (presence_p
2331 ? dst
->unit_decl
->final_presence_list
2332 : dst
->unit_decl
->final_presence_list
)
2334 ? dst
->unit_decl
->final_absence_list
2335 : dst
->unit_decl
->absence_list
));
2336 prev_el
!= NULL
&& prev_el
->next_pattern_set_el
!= NULL
;
2337 prev_el
= prev_el
->next_pattern_set_el
)
2339 copy
= copy_node (pat
, sizeof (*pat
));
2340 copy
->next_pattern_set_el
= NULL
;
2341 if (prev_el
== NULL
)
2346 dst
->unit_decl
->final_presence_list
= copy
;
2348 dst
->unit_decl
->presence_list
= copy
;
2351 dst
->unit_decl
->final_absence_list
= copy
;
2353 dst
->unit_decl
->absence_list
= copy
;
2356 prev_el
->next_pattern_set_el
= copy
;
2363 /* The function searches for bypass with given IN_INSN_RESERV in given
2365 static struct bypass_decl
*
2366 find_bypass (struct bypass_decl
*bypass_list
,
2367 struct insn_reserv_decl
*in_insn_reserv
)
2369 struct bypass_decl
*bypass
;
2371 for (bypass
= bypass_list
; bypass
!= NULL
; bypass
= bypass
->next
)
2372 if (bypass
->in_insn_reserv
== in_insn_reserv
)
2377 /* The function processes pipeline description declarations, checks
2378 their correctness, and forms exclusion/presence/absence sets. */
2380 process_decls (void)
2383 decl_t automaton_decl
;
2384 decl_t decl_in_table
;
2385 decl_t out_insn_reserv
;
2386 decl_t in_insn_reserv
;
2387 struct bypass_decl
*bypass
;
2388 int automaton_presence
;
2391 /* Checking repeated automata declarations. */
2392 automaton_presence
= 0;
2393 for (i
= 0; i
< description
->decls_num
; i
++)
2395 decl
= description
->decls
[i
];
2396 if (decl
->mode
== dm_automaton
)
2398 automaton_presence
= 1;
2399 decl_in_table
= insert_automaton_decl (decl
);
2400 if (decl_in_table
!= decl
)
2403 error ("repeated declaration of automaton `%s'",
2404 DECL_AUTOMATON (decl
)->name
);
2406 warning (0, "repeated declaration of automaton `%s'",
2407 DECL_AUTOMATON (decl
)->name
);
2411 /* Checking undeclared automata, repeated declarations (except for
2412 automata) and correctness of their attributes (insn latency times
2414 for (i
= 0; i
< description
->decls_num
; i
++)
2416 decl
= description
->decls
[i
];
2417 if (decl
->mode
== dm_insn_reserv
)
2419 if (DECL_INSN_RESERV (decl
)->default_latency
< 0)
2420 error ("define_insn_reservation `%s' has negative latency time",
2421 DECL_INSN_RESERV (decl
)->name
);
2422 DECL_INSN_RESERV (decl
)->insn_num
= description
->insns_num
;
2423 description
->insns_num
++;
2424 decl_in_table
= insert_insn_decl (decl
);
2425 if (decl_in_table
!= decl
)
2426 error ("`%s' is already used as insn reservation name",
2427 DECL_INSN_RESERV (decl
)->name
);
2429 else if (decl
->mode
== dm_bypass
)
2431 if (DECL_BYPASS (decl
)->latency
< 0)
2432 error ("define_bypass `%s - %s' has negative latency time",
2433 DECL_BYPASS (decl
)->out_insn_name
,
2434 DECL_BYPASS (decl
)->in_insn_name
);
2436 else if (decl
->mode
== dm_unit
|| decl
->mode
== dm_reserv
)
2438 if (decl
->mode
== dm_unit
)
2440 DECL_UNIT (decl
)->automaton_decl
= NULL
;
2441 if (DECL_UNIT (decl
)->automaton_name
!= NULL
)
2444 = find_automaton_decl (DECL_UNIT (decl
)->automaton_name
);
2445 if (automaton_decl
== NULL
)
2446 error ("automaton `%s' is not declared",
2447 DECL_UNIT (decl
)->automaton_name
);
2450 DECL_AUTOMATON (automaton_decl
)->automaton_is_used
= 1;
2451 DECL_UNIT (decl
)->automaton_decl
2452 = DECL_AUTOMATON (automaton_decl
);
2455 else if (automaton_presence
)
2456 error ("define_unit `%s' without automaton when one defined",
2457 DECL_UNIT (decl
)->name
);
2458 DECL_UNIT (decl
)->unit_num
= description
->units_num
;
2459 description
->units_num
++;
2460 if (strcmp (DECL_UNIT (decl
)->name
, NOTHING_NAME
) == 0)
2462 error ("`%s' is declared as cpu unit", NOTHING_NAME
);
2465 decl_in_table
= find_decl (DECL_UNIT (decl
)->name
);
2469 if (strcmp (DECL_RESERV (decl
)->name
, NOTHING_NAME
) == 0)
2471 error ("`%s' is declared as cpu reservation", NOTHING_NAME
);
2474 decl_in_table
= find_decl (DECL_RESERV (decl
)->name
);
2476 if (decl_in_table
== NULL
)
2477 decl_in_table
= insert_decl (decl
);
2480 if (decl
->mode
== dm_unit
)
2481 error ("repeated declaration of unit `%s'",
2482 DECL_UNIT (decl
)->name
);
2484 error ("repeated declaration of reservation `%s'",
2485 DECL_RESERV (decl
)->name
);
2489 /* Check bypasses and form list of bypasses for each (output)
2491 for (i
= 0; i
< description
->decls_num
; i
++)
2493 decl
= description
->decls
[i
];
2494 if (decl
->mode
== dm_bypass
)
2496 out_insn_reserv
= find_insn_decl (DECL_BYPASS (decl
)->out_insn_name
);
2497 in_insn_reserv
= find_insn_decl (DECL_BYPASS (decl
)->in_insn_name
);
2498 if (out_insn_reserv
== NULL
)
2499 error ("there is no insn reservation `%s'",
2500 DECL_BYPASS (decl
)->out_insn_name
);
2501 else if (in_insn_reserv
== NULL
)
2502 error ("there is no insn reservation `%s'",
2503 DECL_BYPASS (decl
)->in_insn_name
);
2506 DECL_BYPASS (decl
)->out_insn_reserv
2507 = DECL_INSN_RESERV (out_insn_reserv
);
2508 DECL_BYPASS (decl
)->in_insn_reserv
2509 = DECL_INSN_RESERV (in_insn_reserv
);
2511 = find_bypass (DECL_INSN_RESERV (out_insn_reserv
)->bypass_list
,
2512 DECL_BYPASS (decl
)->in_insn_reserv
);
2515 if (DECL_BYPASS (decl
)->latency
== bypass
->latency
)
2519 ("the same bypass `%s - %s' is already defined",
2520 DECL_BYPASS (decl
)->out_insn_name
,
2521 DECL_BYPASS (decl
)->in_insn_name
);
2524 (0, "the same bypass `%s - %s' is already defined",
2525 DECL_BYPASS (decl
)->out_insn_name
,
2526 DECL_BYPASS (decl
)->in_insn_name
);
2529 error ("bypass `%s - %s' is already defined",
2530 DECL_BYPASS (decl
)->out_insn_name
,
2531 DECL_BYPASS (decl
)->in_insn_name
);
2535 DECL_BYPASS (decl
)->next
2536 = DECL_INSN_RESERV (out_insn_reserv
)->bypass_list
;
2537 DECL_INSN_RESERV (out_insn_reserv
)->bypass_list
2538 = DECL_BYPASS (decl
);
2544 /* Check exclusion set declarations and form exclusion sets. */
2545 for (i
= 0; i
< description
->decls_num
; i
++)
2547 decl
= description
->decls
[i
];
2548 if (decl
->mode
== dm_excl
)
2550 unit_set_el_t unit_set_el_list
;
2551 unit_set_el_t unit_set_el_list_2
;
2554 = process_excls (DECL_EXCL (decl
)->names
,
2555 DECL_EXCL (decl
)->first_list_length
, decl
->pos
);
2557 = process_excls (&DECL_EXCL (decl
)->names
2558 [DECL_EXCL (decl
)->first_list_length
],
2559 DECL_EXCL (decl
)->all_names_num
2560 - DECL_EXCL (decl
)->first_list_length
,
2562 add_excls (unit_set_el_list
, unit_set_el_list_2
, decl
->pos
);
2563 add_excls (unit_set_el_list_2
, unit_set_el_list
, decl
->pos
);
2567 /* Check presence set declarations and form presence sets. */
2568 for (i
= 0; i
< description
->decls_num
; i
++)
2570 decl
= description
->decls
[i
];
2571 if (decl
->mode
== dm_presence
)
2573 unit_set_el_t unit_set_el_list
;
2574 pattern_set_el_t pattern_set_el_list
;
2577 = process_presence_absence_names
2578 (DECL_PRESENCE (decl
)->names
, DECL_PRESENCE (decl
)->names_num
,
2579 decl
->pos
, TRUE
, DECL_PRESENCE (decl
)->final_p
);
2581 = process_presence_absence_patterns
2582 (DECL_PRESENCE (decl
)->patterns
,
2583 DECL_PRESENCE (decl
)->patterns_num
,
2584 decl
->pos
, TRUE
, DECL_PRESENCE (decl
)->final_p
);
2585 add_presence_absence (unit_set_el_list
, pattern_set_el_list
,
2587 DECL_PRESENCE (decl
)->final_p
);
2591 /* Check absence set declarations and form absence sets. */
2592 for (i
= 0; i
< description
->decls_num
; i
++)
2594 decl
= description
->decls
[i
];
2595 if (decl
->mode
== dm_absence
)
2597 unit_set_el_t unit_set_el_list
;
2598 pattern_set_el_t pattern_set_el_list
;
2601 = process_presence_absence_names
2602 (DECL_ABSENCE (decl
)->names
, DECL_ABSENCE (decl
)->names_num
,
2603 decl
->pos
, FALSE
, DECL_ABSENCE (decl
)->final_p
);
2605 = process_presence_absence_patterns
2606 (DECL_ABSENCE (decl
)->patterns
,
2607 DECL_ABSENCE (decl
)->patterns_num
,
2608 decl
->pos
, FALSE
, DECL_ABSENCE (decl
)->final_p
);
2609 add_presence_absence (unit_set_el_list
, pattern_set_el_list
,
2611 DECL_ABSENCE (decl
)->final_p
);
2616 /* The following function checks that declared automaton is used. If
2617 the automaton is not used, the function fixes error/warning. The
2618 following function must be called only after `process_decls'. */
2620 check_automaton_usage (void)
2625 for (i
= 0; i
< description
->decls_num
; i
++)
2627 decl
= description
->decls
[i
];
2628 if (decl
->mode
== dm_automaton
2629 && !DECL_AUTOMATON (decl
)->automaton_is_used
)
2632 error ("automaton `%s' is not used", DECL_AUTOMATON (decl
)->name
);
2634 warning (0, "automaton `%s' is not used",
2635 DECL_AUTOMATON (decl
)->name
);
2640 /* The following recursive function processes all regexp in order to
2641 fix usage of units or reservations and to fix errors of undeclared
2642 name. The function may change unit_regexp onto reserv_regexp.
2643 Remember that reserv_regexp does not exist before the function
2646 process_regexp (regexp_t regexp
)
2648 decl_t decl_in_table
;
2649 regexp_t new_regexp
;
2652 switch (regexp
->mode
)
2655 decl_in_table
= find_decl (REGEXP_UNIT (regexp
)->name
);
2656 if (decl_in_table
== NULL
)
2657 error ("undeclared unit or reservation `%s'",
2658 REGEXP_UNIT (regexp
)->name
);
2660 switch (decl_in_table
->mode
)
2663 DECL_UNIT (decl_in_table
)->unit_is_used
= 1;
2664 REGEXP_UNIT (regexp
)->unit_decl
= DECL_UNIT (decl_in_table
);
2668 DECL_RESERV (decl_in_table
)->reserv_is_used
= 1;
2669 new_regexp
= create_node (sizeof (struct regexp
));
2670 new_regexp
->mode
= rm_reserv
;
2671 new_regexp
->pos
= regexp
->pos
;
2672 REGEXP_RESERV (new_regexp
)->name
= REGEXP_UNIT (regexp
)->name
;
2673 REGEXP_RESERV (new_regexp
)->reserv_decl
2674 = DECL_RESERV (decl_in_table
);
2675 regexp
= new_regexp
;
2683 for (i
= 0; i
<REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
2684 REGEXP_SEQUENCE (regexp
)->regexps
[i
]
2685 = process_regexp (REGEXP_SEQUENCE (regexp
)->regexps
[i
]);
2688 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
2689 REGEXP_ALLOF (regexp
)->regexps
[i
]
2690 = process_regexp (REGEXP_ALLOF (regexp
)->regexps
[i
]);
2693 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
2694 REGEXP_ONEOF (regexp
)->regexps
[i
]
2695 = process_regexp (REGEXP_ONEOF (regexp
)->regexps
[i
]);
2698 REGEXP_REPEAT (regexp
)->regexp
2699 = process_regexp (REGEXP_REPEAT (regexp
)->regexp
);
2709 /* The following function processes regexp of define_reservation and
2710 define_insn_reservation with the aid of function
2711 `process_regexp'. */
2713 process_regexp_decls (void)
2718 for (i
= 0; i
< description
->decls_num
; i
++)
2720 decl
= description
->decls
[i
];
2721 if (decl
->mode
== dm_reserv
)
2722 DECL_RESERV (decl
)->regexp
2723 = process_regexp (DECL_RESERV (decl
)->regexp
);
2724 else if (decl
->mode
== dm_insn_reserv
)
2725 DECL_INSN_RESERV (decl
)->regexp
2726 = process_regexp (DECL_INSN_RESERV (decl
)->regexp
);
2730 /* The following function checks that declared unit is used. If the
2731 unit is not used, the function fixes errors/warnings. The
2732 following function must be called only after `process_decls',
2733 `process_regexp_decls'. */
2740 for (i
= 0; i
< description
->decls_num
; i
++)
2742 decl
= description
->decls
[i
];
2743 if (decl
->mode
== dm_unit
&& !DECL_UNIT (decl
)->unit_is_used
)
2746 error ("unit `%s' is not used", DECL_UNIT (decl
)->name
);
2748 warning (0, "unit `%s' is not used", DECL_UNIT (decl
)->name
);
2750 else if (decl
->mode
== dm_reserv
&& !DECL_RESERV (decl
)->reserv_is_used
)
2753 error ("reservation `%s' is not used", DECL_RESERV (decl
)->name
);
2755 warning (0, "reservation `%s' is not used", DECL_RESERV (decl
)->name
);
2760 /* The following variable value is number of reservation being
2761 processed on loop recognition. */
2762 static int curr_loop_pass_num
;
2764 /* The following recursive function returns nonzero value if REGEXP
2765 contains given decl or reservations in given regexp refers for
2768 loop_in_regexp (regexp_t regexp
, decl_t start_decl
)
2774 switch (regexp
->mode
)
2780 if (start_decl
->mode
== dm_reserv
2781 && REGEXP_RESERV (regexp
)->reserv_decl
== DECL_RESERV (start_decl
))
2783 else if (REGEXP_RESERV (regexp
)->reserv_decl
->loop_pass_num
2784 == curr_loop_pass_num
)
2785 /* declaration has been processed. */
2789 REGEXP_RESERV (regexp
)->reserv_decl
->loop_pass_num
2790 = curr_loop_pass_num
;
2791 return loop_in_regexp (REGEXP_RESERV (regexp
)->reserv_decl
->regexp
,
2796 for (i
= 0; i
<REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
2797 if (loop_in_regexp (REGEXP_SEQUENCE (regexp
)->regexps
[i
], start_decl
))
2802 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
2803 if (loop_in_regexp (REGEXP_ALLOF (regexp
)->regexps
[i
], start_decl
))
2808 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
2809 if (loop_in_regexp (REGEXP_ONEOF (regexp
)->regexps
[i
], start_decl
))
2814 return loop_in_regexp (REGEXP_REPEAT (regexp
)->regexp
, start_decl
);
2824 /* The following function fixes errors "cycle in definition ...". The
2825 function uses function `loop_in_regexp' for that. */
2827 check_loops_in_regexps (void)
2832 for (i
= 0; i
< description
->decls_num
; i
++)
2834 decl
= description
->decls
[i
];
2835 if (decl
->mode
== dm_reserv
)
2836 DECL_RESERV (decl
)->loop_pass_num
= 0;
2838 for (i
= 0; i
< description
->decls_num
; i
++)
2840 decl
= description
->decls
[i
];
2841 curr_loop_pass_num
= i
;
2843 if (decl
->mode
== dm_reserv
)
2845 DECL_RESERV (decl
)->loop_pass_num
= curr_loop_pass_num
;
2846 if (loop_in_regexp (DECL_RESERV (decl
)->regexp
, decl
))
2848 gcc_assert (DECL_RESERV (decl
)->regexp
);
2849 error ("cycle in definition of reservation `%s'",
2850 DECL_RESERV (decl
)->name
);
2856 /* The function recursively processes IR of reservation and defines
2857 max and min cycle for reservation of unit. */
2859 process_regexp_cycles (regexp_t regexp
, int max_start_cycle
,
2860 int min_start_cycle
, int *max_finish_cycle
,
2861 int *min_finish_cycle
)
2865 switch (regexp
->mode
)
2868 if (REGEXP_UNIT (regexp
)->unit_decl
->max_occ_cycle_num
< max_start_cycle
)
2869 REGEXP_UNIT (regexp
)->unit_decl
->max_occ_cycle_num
= max_start_cycle
;
2870 if (REGEXP_UNIT (regexp
)->unit_decl
->min_occ_cycle_num
> min_start_cycle
2871 || REGEXP_UNIT (regexp
)->unit_decl
->min_occ_cycle_num
== -1)
2872 REGEXP_UNIT (regexp
)->unit_decl
->min_occ_cycle_num
= min_start_cycle
;
2873 *max_finish_cycle
= max_start_cycle
;
2874 *min_finish_cycle
= min_start_cycle
;
2878 process_regexp_cycles (REGEXP_RESERV (regexp
)->reserv_decl
->regexp
,
2879 max_start_cycle
, min_start_cycle
,
2880 max_finish_cycle
, min_finish_cycle
);
2884 for (i
= 0; i
< REGEXP_REPEAT (regexp
)->repeat_num
; i
++)
2886 process_regexp_cycles (REGEXP_REPEAT (regexp
)->regexp
,
2887 max_start_cycle
, min_start_cycle
,
2888 max_finish_cycle
, min_finish_cycle
);
2889 max_start_cycle
= *max_finish_cycle
+ 1;
2890 min_start_cycle
= *min_finish_cycle
+ 1;
2895 for (i
= 0; i
<REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
2897 process_regexp_cycles (REGEXP_SEQUENCE (regexp
)->regexps
[i
],
2898 max_start_cycle
, min_start_cycle
,
2899 max_finish_cycle
, min_finish_cycle
);
2900 max_start_cycle
= *max_finish_cycle
+ 1;
2901 min_start_cycle
= *min_finish_cycle
+ 1;
2910 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
2912 process_regexp_cycles (REGEXP_ALLOF (regexp
)->regexps
[i
],
2913 max_start_cycle
, min_start_cycle
,
2914 max_finish_cycle
, min_finish_cycle
);
2915 if (max_cycle
< *max_finish_cycle
)
2916 max_cycle
= *max_finish_cycle
;
2917 if (i
== 0 || min_cycle
> *min_finish_cycle
)
2918 min_cycle
= *min_finish_cycle
;
2920 *max_finish_cycle
= max_cycle
;
2921 *min_finish_cycle
= min_cycle
;
2930 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
2932 process_regexp_cycles (REGEXP_ONEOF (regexp
)->regexps
[i
],
2933 max_start_cycle
, min_start_cycle
,
2934 max_finish_cycle
, min_finish_cycle
);
2935 if (max_cycle
< *max_finish_cycle
)
2936 max_cycle
= *max_finish_cycle
;
2937 if (i
== 0 || min_cycle
> *min_finish_cycle
)
2938 min_cycle
= *min_finish_cycle
;
2940 *max_finish_cycle
= max_cycle
;
2941 *min_finish_cycle
= min_cycle
;
2946 *max_finish_cycle
= max_start_cycle
;
2947 *min_finish_cycle
= min_start_cycle
;
2955 /* The following function is called only for correct program. The
2956 function defines max reservation of insns in cycles. */
2958 evaluate_max_reserv_cycles (void)
2960 int max_insn_cycles_num
;
2961 int min_insn_cycles_num
;
2965 description
->max_insn_reserv_cycles
= 0;
2966 for (i
= 0; i
< description
->decls_num
; i
++)
2968 decl
= description
->decls
[i
];
2969 if (decl
->mode
== dm_insn_reserv
)
2971 process_regexp_cycles (DECL_INSN_RESERV (decl
)->regexp
, 0, 0,
2972 &max_insn_cycles_num
, &min_insn_cycles_num
);
2973 if (description
->max_insn_reserv_cycles
< max_insn_cycles_num
)
2974 description
->max_insn_reserv_cycles
= max_insn_cycles_num
;
2977 description
->max_insn_reserv_cycles
++;
2980 /* The following function calls functions for checking all
2983 check_all_description (void)
2986 check_automaton_usage ();
2987 process_regexp_decls ();
2989 check_loops_in_regexps ();
2991 evaluate_max_reserv_cycles ();
2996 /* The page contains abstract data `ticker'. This data is used to
2997 report time of different phases of building automata. It is
2998 possibly to write a description for which automata will be built
2999 during several minutes even on fast machine. */
3001 /* The following function creates ticker and makes it active. */
3003 create_ticker (void)
3007 ticker
.modified_creation_time
= get_run_time ();
3008 ticker
.incremented_off_time
= 0;
3012 /* The following function switches off given ticker. */
3014 ticker_off (ticker_t
*ticker
)
3016 if (ticker
->incremented_off_time
== 0)
3017 ticker
->incremented_off_time
= get_run_time () + 1;
3020 /* The following function switches on given ticker. */
3022 ticker_on (ticker_t
*ticker
)
3024 if (ticker
->incremented_off_time
!= 0)
3026 ticker
->modified_creation_time
3027 += get_run_time () - ticker
->incremented_off_time
+ 1;
3028 ticker
->incremented_off_time
= 0;
3032 /* The following function returns current time in milliseconds since
3033 the moment when given ticker was created. */
3035 active_time (ticker_t ticker
)
3037 if (ticker
.incremented_off_time
!= 0)
3038 return ticker
.incremented_off_time
- 1 - ticker
.modified_creation_time
;
3040 return get_run_time () - ticker
.modified_creation_time
;
3043 /* The following function returns string representation of active time
3044 of given ticker. The result is string representation of seconds
3045 with accuracy of 1/100 second. Only result of the last call of the
3046 function exists. Therefore the following code is not correct
3048 printf ("parser time: %s\ngeneration time: %s\n",
3049 active_time_string (parser_ticker),
3050 active_time_string (generation_ticker));
3052 Correct code has to be the following
3054 printf ("parser time: %s\n", active_time_string (parser_ticker));
3055 printf ("generation time: %s\n",
3056 active_time_string (generation_ticker));
3060 print_active_time (FILE *f
, ticker_t ticker
)
3064 msecs
= active_time (ticker
);
3065 fprintf (f
, "%d.%06d", msecs
/ 1000000, msecs
% 1000000);
3070 /* The following variable value is number of automaton which are
3071 really being created. This value is defined on the base of
3072 argument of option `-split'. If the variable has zero value the
3073 number of automata is defined by the constructions `%automaton'.
3074 This case occurs when option `-split' is absent or has zero
3075 argument. If constructions `define_automaton' is absent only one
3076 automaton is created. */
3077 static int automata_num
;
3079 /* The following variable values are times of
3080 o transformation of regular expressions
3081 o building NDFA (DFA if !ndfa_flag)
3082 o NDFA -> DFA (simply the same automaton if !ndfa_flag)
3084 o building insn equivalence classes
3087 static ticker_t transform_time
;
3088 static ticker_t NDFA_time
;
3089 static ticker_t NDFA_to_DFA_time
;
3090 static ticker_t minimize_time
;
3091 static ticker_t equiv_time
;
3092 static ticker_t automaton_generation_time
;
3093 static ticker_t output_time
;
3095 /* The following variable values are times of
3098 all pipeline hazard translator work */
3099 static ticker_t check_time
;
3100 static ticker_t generation_time
;
3101 static ticker_t all_time
;
3105 /* Pseudo insn decl which denotes advancing cycle. */
3106 static decl_t advance_cycle_insn_decl
;
3108 add_advance_cycle_insn_decl (void)
3110 advance_cycle_insn_decl
= create_node (sizeof (struct decl
));
3111 advance_cycle_insn_decl
->mode
= dm_insn_reserv
;
3112 advance_cycle_insn_decl
->pos
= no_pos
;
3113 DECL_INSN_RESERV (advance_cycle_insn_decl
)->regexp
= NULL
;
3114 DECL_INSN_RESERV (advance_cycle_insn_decl
)->name
= "$advance_cycle";
3115 DECL_INSN_RESERV (advance_cycle_insn_decl
)->insn_num
3116 = description
->insns_num
;
3117 description
->decls
[description
->decls_num
] = advance_cycle_insn_decl
;
3118 description
->decls_num
++;
3119 description
->insns_num
++;
3123 /* Abstract data `alternative states' which represents
3124 nondeterministic nature of the description (see comments for
3125 structures alt_state and state). */
3127 /* List of free states. */
3128 static alt_state_t first_free_alt_state
;
3131 /* The following variables is maximal number of allocated nodes
3133 static int allocated_alt_states_num
= 0;
3136 /* The following function returns free node alt_state. It may be new
3137 allocated node or node freed earlier. */
3139 get_free_alt_state (void)
3143 if (first_free_alt_state
!= NULL
)
3145 result
= first_free_alt_state
;
3146 first_free_alt_state
= first_free_alt_state
->next_alt_state
;
3151 allocated_alt_states_num
++;
3153 result
= create_node (sizeof (struct alt_state
));
3155 result
->state
= NULL
;
3156 result
->next_alt_state
= NULL
;
3157 result
->next_sorted_alt_state
= NULL
;
3161 /* The function frees node ALT_STATE. */
3163 free_alt_state (alt_state_t alt_state
)
3165 if (alt_state
== NULL
)
3167 alt_state
->next_alt_state
= first_free_alt_state
;
3168 first_free_alt_state
= alt_state
;
3171 /* The function frees list started with node ALT_STATE_LIST. */
3173 free_alt_states (alt_state_t alt_states_list
)
3175 alt_state_t curr_alt_state
;
3176 alt_state_t next_alt_state
;
3178 for (curr_alt_state
= alt_states_list
;
3179 curr_alt_state
!= NULL
;
3180 curr_alt_state
= next_alt_state
)
3182 next_alt_state
= curr_alt_state
->next_alt_state
;
3183 free_alt_state (curr_alt_state
);
3187 /* The function compares unique numbers of alt states. */
3189 alt_state_cmp (const void *alt_state_ptr_1
, const void *alt_state_ptr_2
)
3191 if ((*(alt_state_t
*) alt_state_ptr_1
)->state
->unique_num
3192 == (*(alt_state_t
*) alt_state_ptr_2
)->state
->unique_num
)
3194 else if ((*(alt_state_t
*) alt_state_ptr_1
)->state
->unique_num
3195 < (*(alt_state_t
*) alt_state_ptr_2
)->state
->unique_num
)
3201 /* The function sorts ALT_STATES_LIST and removes duplicated alt
3202 states from the list. The comparison key is alt state unique
3206 uniq_sort_alt_states (alt_state_t alt_states_list
)
3208 alt_state_t curr_alt_state
;
3209 VEC(alt_state_t
,heap
) *alt_states
;
3211 size_t prev_unique_state_ind
;
3214 if (alt_states_list
== 0)
3216 if (alt_states_list
->next_alt_state
== 0)
3217 return alt_states_list
;
3219 alt_states
= VEC_alloc (alt_state_t
,heap
, 150);
3220 for (curr_alt_state
= alt_states_list
;
3221 curr_alt_state
!= NULL
;
3222 curr_alt_state
= curr_alt_state
->next_alt_state
)
3223 VEC_safe_push (alt_state_t
,heap
, alt_states
, curr_alt_state
);
3225 qsort (VEC_address (alt_state_t
, alt_states
),
3226 VEC_length (alt_state_t
, alt_states
),
3227 sizeof (alt_state_t
), alt_state_cmp
);
3229 prev_unique_state_ind
= 0;
3230 for (i
= 1; i
< VEC_length (alt_state_t
, alt_states
); i
++)
3231 if (VEC_index (alt_state_t
, alt_states
, prev_unique_state_ind
)->state
3232 != VEC_index (alt_state_t
, alt_states
, i
)->state
)
3234 prev_unique_state_ind
++;
3235 VEC_replace (alt_state_t
, alt_states
, prev_unique_state_ind
,
3236 VEC_index (alt_state_t
, alt_states
, i
));
3238 VEC_truncate (alt_state_t
, alt_states
, prev_unique_state_ind
+ 1);
3240 for (i
= 1; i
< VEC_length (alt_state_t
, alt_states
); i
++)
3241 VEC_index (alt_state_t
, alt_states
, i
-1)->next_sorted_alt_state
3242 = VEC_index (alt_state_t
, alt_states
, i
);
3243 VEC_last (alt_state_t
, alt_states
)->next_sorted_alt_state
= 0;
3245 result
= VEC_index (alt_state_t
, alt_states
, 0);
3247 VEC_free (alt_state_t
,heap
, alt_states
);
3251 /* The function checks equality of alt state lists. Remember that the
3252 lists must be already sorted by the previous function. */
3254 alt_states_eq (alt_state_t alt_states_1
, alt_state_t alt_states_2
)
3256 while (alt_states_1
!= NULL
&& alt_states_2
!= NULL
3257 && alt_state_cmp (&alt_states_1
, &alt_states_2
) == 0)
3259 alt_states_1
= alt_states_1
->next_sorted_alt_state
;
3260 alt_states_2
= alt_states_2
->next_sorted_alt_state
;
3262 return alt_states_1
== alt_states_2
;
3265 /* Initialization of the abstract data. */
3267 initiate_alt_states (void)
3269 first_free_alt_state
= NULL
;
3272 /* Finishing work with the abstract data. */
3274 finish_alt_states (void)
3280 /* The page contains macros for work with bits strings. We could use
3281 standard gcc bitmap or sbitmap but it would result in difficulties
3282 of building canadian cross. */
3284 /* Set bit number bitno in the bit string. The macro is not side
3286 #define SET_BIT(bitstring, bitno) \
3287 (((char *) (bitstring)) [(bitno) / CHAR_BIT] |= 1 << (bitno) % CHAR_BIT)
3289 #define CLEAR_BIT(bitstring, bitno) \
3290 (((char *) (bitstring)) [(bitno) / CHAR_BIT] &= ~(1 << (bitno) % CHAR_BIT))
3292 /* Test if bit number bitno in the bitstring is set. The macro is not
3293 side effect proof. */
3294 #define TEST_BIT(bitstring, bitno) \
3295 (((char *) (bitstring)) [(bitno) / CHAR_BIT] >> (bitno) % CHAR_BIT & 1)
3299 /* This page contains abstract data `state'. */
3301 /* Maximal length of reservations in cycles (>= 1). */
3302 static int max_cycles_num
;
3304 /* Number of set elements (see type set_el_t) needed for
3305 representation of one cycle reservation. It is depended on units
3307 static int els_in_cycle_reserv
;
3309 /* Number of set elements (see type set_el_t) needed for
3310 representation of maximal length reservation. Deterministic
3311 reservation is stored as set (bit string) of length equal to the
3312 variable value * number of bits in set_el_t. */
3313 static int els_in_reservs
;
3315 /* Array of pointers to unit declarations. */
3316 static unit_decl_t
*units_array
;
3318 /* Temporary reservation of maximal length. */
3319 static reserv_sets_t temp_reserv
;
3321 /* The state table itself is represented by the following variable. */
3322 static htab_t state_table
;
3324 /* Linked list of free 'state' structures to be recycled. The
3325 next_equiv_class_state pointer is borrowed for a free list. */
3326 static state_t first_free_state
;
3328 static int curr_unique_state_num
;
3331 /* The following variables is maximal number of allocated nodes
3333 static int allocated_states_num
= 0;
3336 /* Allocate new reservation set. */
3337 static reserv_sets_t
3338 alloc_empty_reserv_sets (void)
3340 reserv_sets_t result
;
3342 obstack_blank (&irp
, els_in_reservs
* sizeof (set_el_t
));
3343 result
= (reserv_sets_t
) obstack_base (&irp
);
3344 obstack_finish (&irp
);
3345 memset (result
, 0, els_in_reservs
* sizeof (set_el_t
));
3349 /* Hash value of reservation set. */
3351 reserv_sets_hash_value (reserv_sets_t reservs
)
3353 set_el_t hash_value
;
3356 set_el_t
*reserv_ptr
;
3359 reservs_num
= els_in_reservs
;
3360 reserv_ptr
= reservs
;
3362 while (reservs_num
!= 0)
3365 hash_value
+= ((*reserv_ptr
>> i
)
3366 | (*reserv_ptr
<< (sizeof (set_el_t
) * CHAR_BIT
- i
)));
3368 if (i
== sizeof (set_el_t
) * CHAR_BIT
)
3372 if (sizeof (set_el_t
) <= sizeof (unsigned))
3375 for (i
= sizeof (set_el_t
); i
> 0; i
-= sizeof (unsigned) - 1)
3377 result
+= (unsigned) hash_value
;
3378 hash_value
>>= (sizeof (unsigned) - 1) * CHAR_BIT
;
3383 /* Comparison of given reservation sets. */
3385 reserv_sets_cmp (reserv_sets_t reservs_1
, reserv_sets_t reservs_2
)
3388 set_el_t
*reserv_ptr_1
;
3389 set_el_t
*reserv_ptr_2
;
3391 gcc_assert (reservs_1
&& reservs_2
);
3392 reservs_num
= els_in_reservs
;
3393 reserv_ptr_1
= reservs_1
;
3394 reserv_ptr_2
= reservs_2
;
3395 while (reservs_num
!= 0 && *reserv_ptr_1
== *reserv_ptr_2
)
3401 if (reservs_num
== 0)
3403 else if (*reserv_ptr_1
< *reserv_ptr_2
)
3409 /* The function checks equality of the reservation sets. */
3411 reserv_sets_eq (reserv_sets_t reservs_1
, reserv_sets_t reservs_2
)
3413 return reserv_sets_cmp (reservs_1
, reservs_2
) == 0;
3416 /* Set up in the reservation set that unit with UNIT_NUM is used on
3419 set_unit_reserv (reserv_sets_t reservs
, int cycle_num
, int unit_num
)
3421 gcc_assert (cycle_num
< max_cycles_num
);
3422 SET_BIT (reservs
, cycle_num
* els_in_cycle_reserv
3423 * sizeof (set_el_t
) * CHAR_BIT
+ unit_num
);
3426 /* Set up in the reservation set RESERVS that unit with UNIT_NUM is
3427 used on CYCLE_NUM. */
3429 test_unit_reserv (reserv_sets_t reservs
, int cycle_num
, int unit_num
)
3431 gcc_assert (cycle_num
< max_cycles_num
);
3432 return TEST_BIT (reservs
, cycle_num
* els_in_cycle_reserv
3433 * sizeof (set_el_t
) * CHAR_BIT
+ unit_num
);
3436 /* The function checks that the reservation sets are intersected,
3437 i.e. there is a unit reservation on a cycle in both reservation
3440 reserv_sets_are_intersected (reserv_sets_t operand_1
,
3441 reserv_sets_t operand_2
)
3445 set_el_t
*cycle_ptr_1
;
3446 set_el_t
*cycle_ptr_2
;
3448 gcc_assert (operand_1
&& operand_2
);
3449 for (el_ptr_1
= operand_1
, el_ptr_2
= operand_2
;
3450 el_ptr_1
< operand_1
+ els_in_reservs
;
3451 el_ptr_1
++, el_ptr_2
++)
3452 if (*el_ptr_1
& *el_ptr_2
)
3454 reserv_sets_or (temp_reserv
, operand_1
, operand_2
);
3455 for (cycle_ptr_1
= operand_1
, cycle_ptr_2
= operand_2
;
3456 cycle_ptr_1
< operand_1
+ els_in_reservs
;
3457 cycle_ptr_1
+= els_in_cycle_reserv
, cycle_ptr_2
+= els_in_cycle_reserv
)
3459 for (el_ptr_1
= cycle_ptr_1
, el_ptr_2
= get_excl_set (cycle_ptr_2
);
3460 el_ptr_1
< cycle_ptr_1
+ els_in_cycle_reserv
;
3461 el_ptr_1
++, el_ptr_2
++)
3462 if (*el_ptr_1
& *el_ptr_2
)
3464 if (!check_presence_pattern_sets (cycle_ptr_1
, cycle_ptr_2
, FALSE
))
3466 if (!check_presence_pattern_sets (temp_reserv
+ (cycle_ptr_2
3470 if (!check_absence_pattern_sets (cycle_ptr_1
, cycle_ptr_2
, FALSE
))
3472 if (!check_absence_pattern_sets (temp_reserv
+ (cycle_ptr_2
- operand_2
),
3479 /* The function sets up RESULT bits by bits of OPERAND shifted on one
3480 cpu cycle. The remaining bits of OPERAND (representing the last
3481 cycle unit reservations) are not changed. */
3483 reserv_sets_shift (reserv_sets_t result
, reserv_sets_t operand
)
3487 gcc_assert (result
&& operand
&& result
!= operand
);
3488 for (i
= els_in_cycle_reserv
; i
< els_in_reservs
; i
++)
3489 result
[i
- els_in_cycle_reserv
] = operand
[i
];
3492 /* OR of the reservation sets. */
3494 reserv_sets_or (reserv_sets_t result
, reserv_sets_t operand_1
,
3495 reserv_sets_t operand_2
)
3499 set_el_t
*result_set_el_ptr
;
3501 gcc_assert (result
&& operand_1
&& operand_2
);
3502 for (el_ptr_1
= operand_1
, el_ptr_2
= operand_2
, result_set_el_ptr
= result
;
3503 el_ptr_1
< operand_1
+ els_in_reservs
;
3504 el_ptr_1
++, el_ptr_2
++, result_set_el_ptr
++)
3505 *result_set_el_ptr
= *el_ptr_1
| *el_ptr_2
;
3508 /* AND of the reservation sets. */
3510 reserv_sets_and (reserv_sets_t result
, reserv_sets_t operand_1
,
3511 reserv_sets_t operand_2
)
3515 set_el_t
*result_set_el_ptr
;
3517 gcc_assert (result
&& operand_1
&& operand_2
);
3518 for (el_ptr_1
= operand_1
, el_ptr_2
= operand_2
, result_set_el_ptr
= result
;
3519 el_ptr_1
< operand_1
+ els_in_reservs
;
3520 el_ptr_1
++, el_ptr_2
++, result_set_el_ptr
++)
3521 *result_set_el_ptr
= *el_ptr_1
& *el_ptr_2
;
3524 /* The function outputs string representation of units reservation on
3525 cycle START_CYCLE in the reservation set. The function uses repeat
3526 construction if REPETITION_NUM > 1. */
3528 output_cycle_reservs (FILE *f
, reserv_sets_t reservs
, int start_cycle
,
3532 int reserved_units_num
;
3534 reserved_units_num
= 0;
3535 for (unit_num
= 0; unit_num
< description
->units_num
; unit_num
++)
3536 if (TEST_BIT (reservs
, start_cycle
* els_in_cycle_reserv
3537 * sizeof (set_el_t
) * CHAR_BIT
+ unit_num
))
3538 reserved_units_num
++;
3539 gcc_assert (repetition_num
> 0);
3540 if (repetition_num
!= 1 && reserved_units_num
> 1)
3542 reserved_units_num
= 0;
3544 unit_num
< description
->units_num
;
3546 if (TEST_BIT (reservs
, start_cycle
* els_in_cycle_reserv
3547 * sizeof (set_el_t
) * CHAR_BIT
+ unit_num
))
3549 if (reserved_units_num
!= 0)
3551 reserved_units_num
++;
3552 fprintf (f
, "%s", units_array
[unit_num
]->name
);
3554 if (reserved_units_num
== 0)
3555 fprintf (f
, NOTHING_NAME
);
3556 gcc_assert (repetition_num
> 0);
3557 if (repetition_num
!= 1 && reserved_units_num
> 1)
3559 if (repetition_num
!= 1)
3560 fprintf (f
, "*%d", repetition_num
);
3563 /* The function outputs string representation of units reservation in
3564 the reservation set. */
3566 output_reserv_sets (FILE *f
, reserv_sets_t reservs
)
3568 int start_cycle
= 0;
3573 for (cycle
= 0; cycle
< max_cycles_num
; cycle
++)
3574 if (repetition_num
== 0)
3577 start_cycle
= cycle
;
3580 ((char *) reservs
+ start_cycle
* els_in_cycle_reserv
3581 * sizeof (set_el_t
),
3582 (char *) reservs
+ cycle
* els_in_cycle_reserv
3583 * sizeof (set_el_t
),
3584 els_in_cycle_reserv
* sizeof (set_el_t
)) == 0)
3588 if (start_cycle
!= 0)
3590 output_cycle_reservs (f
, reservs
, start_cycle
, repetition_num
);
3592 start_cycle
= cycle
;
3594 if (start_cycle
< max_cycles_num
)
3596 if (start_cycle
!= 0)
3598 output_cycle_reservs (f
, reservs
, start_cycle
, repetition_num
);
3602 /* The following function returns free node state for AUTOMATON. It
3603 may be new allocated node or node freed earlier. The function also
3604 allocates reservation set if WITH_RESERVS has nonzero value. */
3606 get_free_state (int with_reservs
, automaton_t automaton
)
3610 gcc_assert (max_cycles_num
> 0 && automaton
);
3611 if (first_free_state
)
3613 result
= first_free_state
;
3614 first_free_state
= result
->next_equiv_class_state
;
3616 result
->next_equiv_class_state
= NULL
;
3617 result
->automaton
= automaton
;
3618 result
->first_out_arc
= NULL
;
3619 result
->it_was_placed_in_stack_for_NDFA_forming
= 0;
3620 result
->it_was_placed_in_stack_for_DFA_forming
= 0;
3621 result
->component_states
= NULL
;
3622 result
->longest_path_length
= UNDEFINED_LONGEST_PATH_LENGTH
;
3627 allocated_states_num
++;
3629 result
= create_node (sizeof (struct state
));
3630 result
->automaton
= automaton
;
3631 result
->first_out_arc
= NULL
;
3632 result
->unique_num
= curr_unique_state_num
;
3633 result
->longest_path_length
= UNDEFINED_LONGEST_PATH_LENGTH
;
3634 curr_unique_state_num
++;
3638 if (result
->reservs
== NULL
)
3639 result
->reservs
= alloc_empty_reserv_sets ();
3641 memset (result
->reservs
, 0, els_in_reservs
* sizeof (set_el_t
));
3646 /* The function frees node STATE. */
3648 free_state (state_t state
)
3650 free_alt_states (state
->component_states
);
3651 state
->next_equiv_class_state
= first_free_state
;
3652 first_free_state
= state
;
3655 /* Hash value of STATE. If STATE represents deterministic state it is
3656 simply hash value of the corresponding reservation set. Otherwise
3657 it is formed from hash values of the component deterministic
3658 states. One more key is order number of state automaton. */
3660 state_hash (const void *state
)
3662 unsigned int hash_value
;
3663 alt_state_t alt_state
;
3665 if (((state_t
) state
)->component_states
== NULL
)
3666 hash_value
= reserv_sets_hash_value (((state_t
) state
)->reservs
);
3670 for (alt_state
= ((state_t
) state
)->component_states
;
3672 alt_state
= alt_state
->next_sorted_alt_state
)
3673 hash_value
= (((hash_value
>> (sizeof (unsigned) - 1) * CHAR_BIT
)
3674 | (hash_value
<< CHAR_BIT
))
3675 + alt_state
->state
->unique_num
);
3677 hash_value
= (((hash_value
>> (sizeof (unsigned) - 1) * CHAR_BIT
)
3678 | (hash_value
<< CHAR_BIT
))
3679 + ((state_t
) state
)->automaton
->automaton_order_num
);
3683 /* Return nonzero value if the states are the same. */
3685 state_eq_p (const void *state_1
, const void *state_2
)
3687 alt_state_t alt_state_1
;
3688 alt_state_t alt_state_2
;
3690 if (((state_t
) state_1
)->automaton
!= ((state_t
) state_2
)->automaton
)
3692 else if (((state_t
) state_1
)->component_states
== NULL
3693 && ((state_t
) state_2
)->component_states
== NULL
)
3694 return reserv_sets_eq (((state_t
) state_1
)->reservs
,
3695 ((state_t
) state_2
)->reservs
);
3696 else if (((state_t
) state_1
)->component_states
!= NULL
3697 && ((state_t
) state_2
)->component_states
!= NULL
)
3699 for (alt_state_1
= ((state_t
) state_1
)->component_states
,
3700 alt_state_2
= ((state_t
) state_2
)->component_states
;
3701 alt_state_1
!= NULL
&& alt_state_2
!= NULL
;
3702 alt_state_1
= alt_state_1
->next_sorted_alt_state
,
3703 alt_state_2
= alt_state_2
->next_sorted_alt_state
)
3704 /* All state in the list must be already in the hash table.
3705 Also the lists must be sorted. */
3706 if (alt_state_1
->state
!= alt_state_2
->state
)
3708 return alt_state_1
== alt_state_2
;
3714 /* Insert STATE into the state table. */
3716 insert_state (state_t state
)
3720 entry_ptr
= htab_find_slot (state_table
, (void *) state
, 1);
3721 if (*entry_ptr
== NULL
)
3722 *entry_ptr
= (void *) state
;
3723 return (state_t
) *entry_ptr
;
3726 /* Add reservation of unit with UNIT_NUM on cycle CYCLE_NUM to
3727 deterministic STATE. */
3729 set_state_reserv (state_t state
, int cycle_num
, int unit_num
)
3731 set_unit_reserv (state
->reservs
, cycle_num
, unit_num
);
3734 /* Return nonzero value if the deterministic states contains a
3735 reservation of the same cpu unit on the same cpu cycle. */
3737 intersected_state_reservs_p (state_t state1
, state_t state2
)
3739 gcc_assert (state1
->automaton
== state2
->automaton
);
3740 return reserv_sets_are_intersected (state1
->reservs
, state2
->reservs
);
3743 /* Return deterministic state (inserted into the table) which
3744 representing the automaton state which is union of reservations of
3745 the deterministic states masked by RESERVS. */
3747 states_union (state_t state1
, state_t state2
, reserv_sets_t reservs
)
3750 state_t state_in_table
;
3752 gcc_assert (state1
->automaton
== state2
->automaton
);
3753 result
= get_free_state (1, state1
->automaton
);
3754 reserv_sets_or (result
->reservs
, state1
->reservs
, state2
->reservs
);
3755 reserv_sets_and (result
->reservs
, result
->reservs
, reservs
);
3756 state_in_table
= insert_state (result
);
3757 if (result
!= state_in_table
)
3759 free_state (result
);
3760 result
= state_in_table
;
3765 /* Return deterministic state (inserted into the table) which
3766 represent the automaton state is obtained from deterministic STATE
3767 by advancing cpu cycle and masking by RESERVS. */
3769 state_shift (state_t state
, reserv_sets_t reservs
)
3772 state_t state_in_table
;
3774 result
= get_free_state (1, state
->automaton
);
3775 reserv_sets_shift (result
->reservs
, state
->reservs
);
3776 reserv_sets_and (result
->reservs
, result
->reservs
, reservs
);
3777 state_in_table
= insert_state (result
);
3778 if (result
!= state_in_table
)
3780 free_state (result
);
3781 result
= state_in_table
;
3786 /* Initialization of the abstract data. */
3788 initiate_states (void)
3793 if (description
->units_num
)
3794 units_array
= XNEWVEC (unit_decl_t
, description
->units_num
);
3798 for (i
= 0; i
< description
->decls_num
; i
++)
3800 decl
= description
->decls
[i
];
3801 if (decl
->mode
== dm_unit
)
3802 units_array
[DECL_UNIT (decl
)->unit_num
] = DECL_UNIT (decl
);
3804 max_cycles_num
= description
->max_insn_reserv_cycles
;
3806 = ((description
->units_num
+ sizeof (set_el_t
) * CHAR_BIT
- 1)
3807 / (sizeof (set_el_t
) * CHAR_BIT
));
3808 els_in_reservs
= els_in_cycle_reserv
* max_cycles_num
;
3809 curr_unique_state_num
= 0;
3810 initiate_alt_states ();
3811 state_table
= htab_create (1500, state_hash
, state_eq_p
, (htab_del
) 0);
3812 temp_reserv
= alloc_empty_reserv_sets ();
3815 /* Finishing work with the abstract data. */
3817 finish_states (void)
3821 htab_delete (state_table
);
3822 first_free_state
= NULL
;
3823 finish_alt_states ();
3828 /* Abstract data `arcs'. */
3830 /* List of free arcs. */
3831 static arc_t first_free_arc
;
3834 /* The following variables is maximal number of allocated nodes
3836 static int allocated_arcs_num
= 0;
3839 /* The function frees node ARC. */
3841 free_arc (arc_t arc
)
3843 arc
->next_out_arc
= first_free_arc
;
3844 first_free_arc
= arc
;
3847 /* The function removes and frees ARC staring from FROM_STATE. */
3849 remove_arc (state_t from_state
, arc_t arc
)
3855 for (prev_arc
= NULL
, curr_arc
= from_state
->first_out_arc
;
3857 prev_arc
= curr_arc
, curr_arc
= curr_arc
->next_out_arc
)
3858 if (curr_arc
== arc
)
3860 gcc_assert (curr_arc
);
3861 if (prev_arc
== NULL
)
3862 from_state
->first_out_arc
= arc
->next_out_arc
;
3864 prev_arc
->next_out_arc
= arc
->next_out_arc
;
3868 /* The functions returns arc with given characteristics (or NULL if
3869 the arc does not exist). */
3871 find_arc (state_t from_state
, state_t to_state
, ainsn_t insn
)
3875 for (arc
= first_out_arc (from_state
); arc
!= NULL
; arc
= next_out_arc (arc
))
3876 if (arc
->to_state
== to_state
&& arc
->insn
== insn
)
3881 /* The function adds arc from FROM_STATE to TO_STATE marked by AINSN.
3882 The function returns added arc (or already existing arc). */
3884 add_arc (state_t from_state
, state_t to_state
, ainsn_t ainsn
)
3888 new_arc
= find_arc (from_state
, to_state
, ainsn
);
3889 if (new_arc
!= NULL
)
3891 if (first_free_arc
== NULL
)
3894 allocated_arcs_num
++;
3896 new_arc
= create_node (sizeof (struct arc
));
3897 new_arc
->to_state
= NULL
;
3898 new_arc
->insn
= NULL
;
3899 new_arc
->next_out_arc
= NULL
;
3903 new_arc
= first_free_arc
;
3904 first_free_arc
= first_free_arc
->next_out_arc
;
3906 new_arc
->to_state
= to_state
;
3907 new_arc
->insn
= ainsn
;
3908 ainsn
->arc_exists_p
= 1;
3909 new_arc
->next_out_arc
= from_state
->first_out_arc
;
3910 from_state
->first_out_arc
= new_arc
;
3911 new_arc
->next_arc_marked_by_insn
= NULL
;
3915 /* The function returns the first arc starting from STATE. */
3917 first_out_arc (state_t state
)
3919 return state
->first_out_arc
;
3922 /* The function returns next out arc after ARC. */
3924 next_out_arc (arc_t arc
)
3926 return arc
->next_out_arc
;
3929 /* Initialization of the abstract data. */
3931 initiate_arcs (void)
3933 first_free_arc
= NULL
;
3936 /* Finishing work with the abstract data. */
3944 /* Abstract data `automata lists'. */
3946 /* List of free states. */
3947 static automata_list_el_t first_free_automata_list_el
;
3949 /* The list being formed. */
3950 static automata_list_el_t current_automata_list
;
3952 /* Hash table of automata lists. */
3953 static htab_t automata_list_table
;
3955 /* The following function returns free automata list el. It may be
3956 new allocated node or node freed earlier. */
3957 static automata_list_el_t
3958 get_free_automata_list_el (void)
3960 automata_list_el_t result
;
3962 if (first_free_automata_list_el
!= NULL
)
3964 result
= first_free_automata_list_el
;
3965 first_free_automata_list_el
3966 = first_free_automata_list_el
->next_automata_list_el
;
3969 result
= create_node (sizeof (struct automata_list_el
));
3970 result
->automaton
= NULL
;
3971 result
->next_automata_list_el
= NULL
;
3975 /* The function frees node AUTOMATA_LIST_EL. */
3977 free_automata_list_el (automata_list_el_t automata_list_el
)
3979 if (automata_list_el
== NULL
)
3981 automata_list_el
->next_automata_list_el
= first_free_automata_list_el
;
3982 first_free_automata_list_el
= automata_list_el
;
3985 /* The function frees list AUTOMATA_LIST. */
3987 free_automata_list (automata_list_el_t automata_list
)
3989 automata_list_el_t curr_automata_list_el
;
3990 automata_list_el_t next_automata_list_el
;
3992 for (curr_automata_list_el
= automata_list
;
3993 curr_automata_list_el
!= NULL
;
3994 curr_automata_list_el
= next_automata_list_el
)
3996 next_automata_list_el
= curr_automata_list_el
->next_automata_list_el
;
3997 free_automata_list_el (curr_automata_list_el
);
4001 /* Hash value of AUTOMATA_LIST. */
4003 automata_list_hash (const void *automata_list
)
4005 unsigned int hash_value
;
4006 automata_list_el_t curr_automata_list_el
;
4009 for (curr_automata_list_el
= (automata_list_el_t
) automata_list
;
4010 curr_automata_list_el
!= NULL
;
4011 curr_automata_list_el
= curr_automata_list_el
->next_automata_list_el
)
4012 hash_value
= (((hash_value
>> (sizeof (unsigned) - 1) * CHAR_BIT
)
4013 | (hash_value
<< CHAR_BIT
))
4014 + curr_automata_list_el
->automaton
->automaton_order_num
);
4018 /* Return nonzero value if the automata_lists are the same. */
4020 automata_list_eq_p (const void *automata_list_1
, const void *automata_list_2
)
4022 automata_list_el_t automata_list_el_1
;
4023 automata_list_el_t automata_list_el_2
;
4025 for (automata_list_el_1
= (automata_list_el_t
) automata_list_1
,
4026 automata_list_el_2
= (automata_list_el_t
) automata_list_2
;
4027 automata_list_el_1
!= NULL
&& automata_list_el_2
!= NULL
;
4028 automata_list_el_1
= automata_list_el_1
->next_automata_list_el
,
4029 automata_list_el_2
= automata_list_el_2
->next_automata_list_el
)
4030 if (automata_list_el_1
->automaton
!= automata_list_el_2
->automaton
)
4032 return automata_list_el_1
== automata_list_el_2
;
4035 /* Initialization of the abstract data. */
4037 initiate_automata_lists (void)
4039 first_free_automata_list_el
= NULL
;
4040 automata_list_table
= htab_create (1500, automata_list_hash
,
4041 automata_list_eq_p
, (htab_del
) 0);
4044 /* The following function starts new automata list and makes it the
4047 automata_list_start (void)
4049 current_automata_list
= NULL
;
4052 /* The following function adds AUTOMATON to the current list. */
4054 automata_list_add (automaton_t automaton
)
4056 automata_list_el_t el
;
4058 el
= get_free_automata_list_el ();
4059 el
->automaton
= automaton
;
4060 el
->next_automata_list_el
= current_automata_list
;
4061 current_automata_list
= el
;
4064 /* The following function finishes forming the current list, inserts
4065 it into the table and returns it. */
4066 static automata_list_el_t
4067 automata_list_finish (void)
4071 if (current_automata_list
== NULL
)
4073 entry_ptr
= htab_find_slot (automata_list_table
,
4074 (void *) current_automata_list
, 1);
4075 if (*entry_ptr
== NULL
)
4076 *entry_ptr
= (void *) current_automata_list
;
4078 free_automata_list (current_automata_list
);
4079 current_automata_list
= NULL
;
4080 return (automata_list_el_t
) *entry_ptr
;
4083 /* Finishing work with the abstract data. */
4085 finish_automata_lists (void)
4087 htab_delete (automata_list_table
);
4092 /* The page contains abstract data for work with exclusion sets (see
4093 exclusion_set in file rtl.def). */
4095 /* The following variable refers to an exclusion set returned by
4096 get_excl_set. This is bit string of length equal to cpu units
4097 number. If exclusion set for given unit contains 1 for a unit,
4098 then simultaneous reservation of the units is prohibited. */
4099 static reserv_sets_t excl_set
;
4101 /* The array contains exclusion sets for each unit. */
4102 static reserv_sets_t
*unit_excl_set_table
;
4104 /* The following function forms the array containing exclusion sets
4107 initiate_excl_sets (void)
4110 reserv_sets_t unit_excl_set
;
4114 obstack_blank (&irp
, els_in_cycle_reserv
* sizeof (set_el_t
));
4115 excl_set
= (reserv_sets_t
) obstack_base (&irp
);
4116 obstack_finish (&irp
);
4117 obstack_blank (&irp
, description
->units_num
* sizeof (reserv_sets_t
));
4118 unit_excl_set_table
= (reserv_sets_t
*) obstack_base (&irp
);
4119 obstack_finish (&irp
);
4120 /* Evaluate unit exclusion sets. */
4121 for (i
= 0; i
< description
->decls_num
; i
++)
4123 decl
= description
->decls
[i
];
4124 if (decl
->mode
== dm_unit
)
4126 obstack_blank (&irp
, els_in_cycle_reserv
* sizeof (set_el_t
));
4127 unit_excl_set
= (reserv_sets_t
) obstack_base (&irp
);
4128 obstack_finish (&irp
);
4129 memset (unit_excl_set
, 0, els_in_cycle_reserv
* sizeof (set_el_t
));
4130 for (el
= DECL_UNIT (decl
)->excl_list
;
4132 el
= el
->next_unit_set_el
)
4134 SET_BIT (unit_excl_set
, el
->unit_decl
->unit_num
);
4135 el
->unit_decl
->in_set_p
= TRUE
;
4137 unit_excl_set_table
[DECL_UNIT (decl
)->unit_num
] = unit_excl_set
;
4142 /* The function sets up and return EXCL_SET which is union of
4143 exclusion sets for each unit in IN_SET. */
4144 static reserv_sets_t
4145 get_excl_set (reserv_sets_t in_set
)
4153 chars_num
= els_in_cycle_reserv
* sizeof (set_el_t
);
4154 memset (excl_set
, 0, chars_num
);
4155 for (excl_char_num
= 0; excl_char_num
< chars_num
; excl_char_num
++)
4156 if (((unsigned char *) in_set
) [excl_char_num
])
4157 for (i
= CHAR_BIT
- 1; i
>= 0; i
--)
4158 if ((((unsigned char *) in_set
) [excl_char_num
] >> i
) & 1)
4160 start_unit_num
= excl_char_num
* CHAR_BIT
+ i
;
4161 if (start_unit_num
>= description
->units_num
)
4163 for (unit_num
= 0; unit_num
< els_in_cycle_reserv
; unit_num
++)
4166 |= unit_excl_set_table
[start_unit_num
] [unit_num
];
4174 /* The page contains abstract data for work with presence/absence
4175 pattern sets (see presence_set/absence_set in file rtl.def). */
4177 /* The following arrays contain correspondingly presence, final
4178 presence, absence, and final absence patterns for each unit. */
4179 static pattern_reserv_t
*unit_presence_set_table
;
4180 static pattern_reserv_t
*unit_final_presence_set_table
;
4181 static pattern_reserv_t
*unit_absence_set_table
;
4182 static pattern_reserv_t
*unit_final_absence_set_table
;
4184 /* The following function forms list of reservation sets for given
4186 static pattern_reserv_t
4187 form_reserv_sets_list (pattern_set_el_t pattern_list
)
4189 pattern_set_el_t el
;
4190 pattern_reserv_t first
, curr
, prev
;
4193 prev
= first
= NULL
;
4194 for (el
= pattern_list
; el
!= NULL
; el
= el
->next_pattern_set_el
)
4196 curr
= create_node (sizeof (struct pattern_reserv
));
4197 curr
->reserv
= alloc_empty_reserv_sets ();
4198 curr
->next_pattern_reserv
= NULL
;
4199 for (i
= 0; i
< el
->units_num
; i
++)
4201 SET_BIT (curr
->reserv
, el
->unit_decls
[i
]->unit_num
);
4202 el
->unit_decls
[i
]->in_set_p
= TRUE
;
4205 prev
->next_pattern_reserv
= curr
;
4213 /* The following function forms the array containing presence and
4214 absence pattern sets for each unit. */
4216 initiate_presence_absence_pattern_sets (void)
4221 obstack_blank (&irp
, description
->units_num
* sizeof (pattern_reserv_t
));
4222 unit_presence_set_table
= (pattern_reserv_t
*) obstack_base (&irp
);
4223 obstack_finish (&irp
);
4224 obstack_blank (&irp
, description
->units_num
* sizeof (pattern_reserv_t
));
4225 unit_final_presence_set_table
= (pattern_reserv_t
*) obstack_base (&irp
);
4226 obstack_finish (&irp
);
4227 obstack_blank (&irp
, description
->units_num
* sizeof (pattern_reserv_t
));
4228 unit_absence_set_table
= (pattern_reserv_t
*) obstack_base (&irp
);
4229 obstack_finish (&irp
);
4230 obstack_blank (&irp
, description
->units_num
* sizeof (pattern_reserv_t
));
4231 unit_final_absence_set_table
= (pattern_reserv_t
*) obstack_base (&irp
);
4232 obstack_finish (&irp
);
4233 /* Evaluate unit presence/absence sets. */
4234 for (i
= 0; i
< description
->decls_num
; i
++)
4236 decl
= description
->decls
[i
];
4237 if (decl
->mode
== dm_unit
)
4239 unit_presence_set_table
[DECL_UNIT (decl
)->unit_num
]
4240 = form_reserv_sets_list (DECL_UNIT (decl
)->presence_list
);
4241 unit_final_presence_set_table
[DECL_UNIT (decl
)->unit_num
]
4242 = form_reserv_sets_list (DECL_UNIT (decl
)->final_presence_list
);
4243 unit_absence_set_table
[DECL_UNIT (decl
)->unit_num
]
4244 = form_reserv_sets_list (DECL_UNIT (decl
)->absence_list
);
4245 unit_final_absence_set_table
[DECL_UNIT (decl
)->unit_num
]
4246 = form_reserv_sets_list (DECL_UNIT (decl
)->final_absence_list
);
4251 /* The function checks that CHECKED_SET satisfies all presence pattern
4252 sets for units in ORIGIONAL_SET. The function returns TRUE if it
4255 check_presence_pattern_sets (reserv_sets_t checked_set
,
4256 reserv_sets_t origional_set
,
4265 pattern_reserv_t pat_reserv
;
4267 chars_num
= els_in_cycle_reserv
* sizeof (set_el_t
);
4268 for (char_num
= 0; char_num
< chars_num
; char_num
++)
4269 if (((unsigned char *) origional_set
) [char_num
])
4270 for (i
= CHAR_BIT
- 1; i
>= 0; i
--)
4271 if ((((unsigned char *) origional_set
) [char_num
] >> i
) & 1)
4273 start_unit_num
= char_num
* CHAR_BIT
+ i
;
4274 if (start_unit_num
>= description
->units_num
)
4277 && unit_final_presence_set_table
[start_unit_num
] == NULL
)
4279 && unit_presence_set_table
[start_unit_num
] == NULL
))
4282 for (pat_reserv
= (final_p
4283 ? unit_final_presence_set_table
[start_unit_num
]
4284 : unit_presence_set_table
[start_unit_num
]);
4286 pat_reserv
= pat_reserv
->next_pattern_reserv
)
4288 for (unit_num
= 0; unit_num
< els_in_cycle_reserv
; unit_num
++)
4289 if ((checked_set
[unit_num
] & pat_reserv
->reserv
[unit_num
])
4290 != pat_reserv
->reserv
[unit_num
])
4292 presence_p
= presence_p
|| unit_num
>= els_in_cycle_reserv
;
4300 /* The function checks that CHECKED_SET satisfies all absence pattern
4301 sets for units in ORIGIONAL_SET. The function returns TRUE if it
4304 check_absence_pattern_sets (reserv_sets_t checked_set
,
4305 reserv_sets_t origional_set
,
4313 pattern_reserv_t pat_reserv
;
4315 chars_num
= els_in_cycle_reserv
* sizeof (set_el_t
);
4316 for (char_num
= 0; char_num
< chars_num
; char_num
++)
4317 if (((unsigned char *) origional_set
) [char_num
])
4318 for (i
= CHAR_BIT
- 1; i
>= 0; i
--)
4319 if ((((unsigned char *) origional_set
) [char_num
] >> i
) & 1)
4321 start_unit_num
= char_num
* CHAR_BIT
+ i
;
4322 if (start_unit_num
>= description
->units_num
)
4324 for (pat_reserv
= (final_p
4325 ? unit_final_absence_set_table
[start_unit_num
]
4326 : unit_absence_set_table
[start_unit_num
]);
4328 pat_reserv
= pat_reserv
->next_pattern_reserv
)
4330 for (unit_num
= 0; unit_num
< els_in_cycle_reserv
; unit_num
++)
4331 if ((checked_set
[unit_num
] & pat_reserv
->reserv
[unit_num
])
4332 != pat_reserv
->reserv
[unit_num
]
4333 && pat_reserv
->reserv
[unit_num
])
4335 if (unit_num
>= els_in_cycle_reserv
)
4344 /* This page contains code for transformation of original reservations
4345 described in .md file. The main goal of transformations is
4346 simplifying reservation and lifting up all `|' on the top of IR
4347 reservation representation. */
4350 /* The following function makes copy of IR representation of
4351 reservation. The function also substitutes all reservations
4352 defined by define_reservation by corresponding value during making
4355 copy_insn_regexp (regexp_t regexp
)
4360 switch (regexp
->mode
)
4363 result
= copy_insn_regexp (REGEXP_RESERV (regexp
)->reserv_decl
->regexp
);
4367 result
= copy_node (regexp
, sizeof (struct regexp
));
4371 result
= copy_node (regexp
, sizeof (struct regexp
));
4372 REGEXP_REPEAT (result
)->regexp
4373 = copy_insn_regexp (REGEXP_REPEAT (regexp
)->regexp
);
4377 result
= copy_node (regexp
,
4378 sizeof (struct regexp
) + sizeof (regexp_t
)
4379 * (REGEXP_SEQUENCE (regexp
)->regexps_num
- 1));
4380 for (i
= 0; i
<REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
4381 REGEXP_SEQUENCE (result
)->regexps
[i
]
4382 = copy_insn_regexp (REGEXP_SEQUENCE (regexp
)->regexps
[i
]);
4386 result
= copy_node (regexp
,
4387 sizeof (struct regexp
) + sizeof (regexp_t
)
4388 * (REGEXP_ALLOF (regexp
)->regexps_num
- 1));
4389 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
4390 REGEXP_ALLOF (result
)->regexps
[i
]
4391 = copy_insn_regexp (REGEXP_ALLOF (regexp
)->regexps
[i
]);
4395 result
= copy_node (regexp
,
4396 sizeof (struct regexp
) + sizeof (regexp_t
)
4397 * (REGEXP_ONEOF (regexp
)->regexps_num
- 1));
4398 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
4399 REGEXP_ONEOF (result
)->regexps
[i
]
4400 = copy_insn_regexp (REGEXP_ONEOF (regexp
)->regexps
[i
]);
4404 result
= copy_node (regexp
, sizeof (struct regexp
));
4413 /* The following variable is set up 1 if a transformation has been
4415 static int regexp_transformed_p
;
4417 /* The function makes transformation
4420 transform_1 (regexp_t regexp
)
4427 if (regexp
->mode
== rm_repeat
)
4429 repeat_num
= REGEXP_REPEAT (regexp
)->repeat_num
;
4430 gcc_assert (repeat_num
> 1);
4431 operand
= REGEXP_REPEAT (regexp
)->regexp
;
4433 regexp
= create_node (sizeof (struct regexp
) + sizeof (regexp_t
)
4434 * (repeat_num
- 1));
4435 regexp
->mode
= rm_sequence
;
4437 REGEXP_SEQUENCE (regexp
)->regexps_num
= repeat_num
;
4438 for (i
= 0; i
< repeat_num
; i
++)
4439 REGEXP_SEQUENCE (regexp
)->regexps
[i
] = copy_insn_regexp (operand
);
4440 regexp_transformed_p
= 1;
4445 /* The function makes transformations
4446 ...,(A,B,...),C,... -> ...,A,B,...,C,...
4447 ...+(A+B+...)+C+... -> ...+A+B+...+C+...
4448 ...|(A|B|...)|C|... -> ...|A|B|...|C|... */
4450 transform_2 (regexp_t regexp
)
4452 if (regexp
->mode
== rm_sequence
)
4454 regexp_t sequence
= NULL
;
4456 int sequence_index
= 0;
4459 for (i
= 0; i
< REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
4460 if (REGEXP_SEQUENCE (regexp
)->regexps
[i
]->mode
== rm_sequence
)
4463 sequence
= REGEXP_SEQUENCE (regexp
)->regexps
[i
];
4466 if (i
< REGEXP_SEQUENCE (regexp
)->regexps_num
)
4468 gcc_assert (REGEXP_SEQUENCE (sequence
)->regexps_num
> 1
4469 && REGEXP_SEQUENCE (regexp
)->regexps_num
> 1);
4470 result
= create_node (sizeof (struct regexp
)
4472 * (REGEXP_SEQUENCE (regexp
)->regexps_num
4473 + REGEXP_SEQUENCE (sequence
)->regexps_num
4475 result
->mode
= rm_sequence
;
4476 result
->pos
= regexp
->pos
;
4477 REGEXP_SEQUENCE (result
)->regexps_num
4478 = (REGEXP_SEQUENCE (regexp
)->regexps_num
4479 + REGEXP_SEQUENCE (sequence
)->regexps_num
- 1);
4480 for (i
= 0; i
< REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
4481 if (i
< sequence_index
)
4482 REGEXP_SEQUENCE (result
)->regexps
[i
]
4483 = copy_insn_regexp (REGEXP_SEQUENCE (regexp
)->regexps
[i
]);
4484 else if (i
> sequence_index
)
4485 REGEXP_SEQUENCE (result
)->regexps
4486 [i
+ REGEXP_SEQUENCE (sequence
)->regexps_num
- 1]
4487 = copy_insn_regexp (REGEXP_SEQUENCE (regexp
)->regexps
[i
]);
4489 for (j
= 0; j
< REGEXP_SEQUENCE (sequence
)->regexps_num
; j
++)
4490 REGEXP_SEQUENCE (result
)->regexps
[i
+ j
]
4491 = copy_insn_regexp (REGEXP_SEQUENCE (sequence
)->regexps
[j
]);
4492 regexp_transformed_p
= 1;
4496 else if (regexp
->mode
== rm_allof
)
4498 regexp_t allof
= NULL
;
4500 int allof_index
= 0;
4503 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
4504 if (REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
== rm_allof
)
4507 allof
= REGEXP_ALLOF (regexp
)->regexps
[i
];
4510 if (i
< REGEXP_ALLOF (regexp
)->regexps_num
)
4512 gcc_assert (REGEXP_ALLOF (allof
)->regexps_num
> 1
4513 && REGEXP_ALLOF (regexp
)->regexps_num
> 1);
4514 result
= create_node (sizeof (struct regexp
)
4516 * (REGEXP_ALLOF (regexp
)->regexps_num
4517 + REGEXP_ALLOF (allof
)->regexps_num
- 2));
4518 result
->mode
= rm_allof
;
4519 result
->pos
= regexp
->pos
;
4520 REGEXP_ALLOF (result
)->regexps_num
4521 = (REGEXP_ALLOF (regexp
)->regexps_num
4522 + REGEXP_ALLOF (allof
)->regexps_num
- 1);
4523 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
4524 if (i
< allof_index
)
4525 REGEXP_ALLOF (result
)->regexps
[i
]
4526 = copy_insn_regexp (REGEXP_ALLOF (regexp
)->regexps
[i
]);
4527 else if (i
> allof_index
)
4528 REGEXP_ALLOF (result
)->regexps
4529 [i
+ REGEXP_ALLOF (allof
)->regexps_num
- 1]
4530 = copy_insn_regexp (REGEXP_ALLOF (regexp
)->regexps
[i
]);
4532 for (j
= 0; j
< REGEXP_ALLOF (allof
)->regexps_num
; j
++)
4533 REGEXP_ALLOF (result
)->regexps
[i
+ j
]
4534 = copy_insn_regexp (REGEXP_ALLOF (allof
)->regexps
[j
]);
4535 regexp_transformed_p
= 1;
4539 else if (regexp
->mode
== rm_oneof
)
4541 regexp_t oneof
= NULL
;
4543 int oneof_index
= 0;
4546 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
4547 if (REGEXP_ONEOF (regexp
)->regexps
[i
]->mode
== rm_oneof
)
4550 oneof
= REGEXP_ONEOF (regexp
)->regexps
[i
];
4553 if (i
< REGEXP_ONEOF (regexp
)->regexps_num
)
4555 gcc_assert (REGEXP_ONEOF (oneof
)->regexps_num
> 1
4556 && REGEXP_ONEOF (regexp
)->regexps_num
> 1);
4557 result
= create_node (sizeof (struct regexp
)
4559 * (REGEXP_ONEOF (regexp
)->regexps_num
4560 + REGEXP_ONEOF (oneof
)->regexps_num
- 2));
4561 result
->mode
= rm_oneof
;
4562 result
->pos
= regexp
->pos
;
4563 REGEXP_ONEOF (result
)->regexps_num
4564 = (REGEXP_ONEOF (regexp
)->regexps_num
4565 + REGEXP_ONEOF (oneof
)->regexps_num
- 1);
4566 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
4567 if (i
< oneof_index
)
4568 REGEXP_ONEOF (result
)->regexps
[i
]
4569 = copy_insn_regexp (REGEXP_ONEOF (regexp
)->regexps
[i
]);
4570 else if (i
> oneof_index
)
4571 REGEXP_ONEOF (result
)->regexps
4572 [i
+ REGEXP_ONEOF (oneof
)->regexps_num
- 1]
4573 = copy_insn_regexp (REGEXP_ONEOF (regexp
)->regexps
[i
]);
4575 for (j
= 0; j
< REGEXP_ONEOF (oneof
)->regexps_num
; j
++)
4576 REGEXP_ONEOF (result
)->regexps
[i
+ j
]
4577 = copy_insn_regexp (REGEXP_ONEOF (oneof
)->regexps
[j
]);
4578 regexp_transformed_p
= 1;
4585 /* The function makes transformations
4586 ...,A|B|...,C,... -> (...,A,C,...)|(...,B,C,...)|...
4587 ...+(A|B|...)+C+... -> (...+A+C+...)|(...+B+C+...)|...
4588 ...+(A,B,...)+C+... -> (...+A+C+...),B,...
4589 ...+(A,B,...)+(C,D,...) -> (A+C),(B+D),... */
4591 transform_3 (regexp_t regexp
)
4593 if (regexp
->mode
== rm_sequence
)
4595 regexp_t oneof
= NULL
;
4596 int oneof_index
= 0;
4601 for (i
= 0; i
<REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
4602 if (REGEXP_SEQUENCE (regexp
)->regexps
[i
]->mode
== rm_oneof
)
4605 oneof
= REGEXP_SEQUENCE (regexp
)->regexps
[i
];
4608 if (i
< REGEXP_SEQUENCE (regexp
)->regexps_num
)
4610 gcc_assert (REGEXP_ONEOF (oneof
)->regexps_num
> 1
4611 && REGEXP_SEQUENCE (regexp
)->regexps_num
> 1);
4612 result
= create_node (sizeof (struct regexp
)
4614 * (REGEXP_ONEOF (oneof
)->regexps_num
- 1));
4615 result
->mode
= rm_oneof
;
4616 result
->pos
= regexp
->pos
;
4617 REGEXP_ONEOF (result
)->regexps_num
4618 = REGEXP_ONEOF (oneof
)->regexps_num
;
4619 for (i
= 0; i
< REGEXP_ONEOF (result
)->regexps_num
; i
++)
4622 = create_node (sizeof (struct regexp
)
4624 * (REGEXP_SEQUENCE (regexp
)->regexps_num
- 1));
4625 sequence
->mode
= rm_sequence
;
4626 sequence
->pos
= regexp
->pos
;
4627 REGEXP_SEQUENCE (sequence
)->regexps_num
4628 = REGEXP_SEQUENCE (regexp
)->regexps_num
;
4629 REGEXP_ONEOF (result
)->regexps
[i
] = sequence
;
4630 for (j
= 0; j
< REGEXP_SEQUENCE (sequence
)->regexps_num
; j
++)
4631 if (j
!= oneof_index
)
4632 REGEXP_SEQUENCE (sequence
)->regexps
[j
]
4633 = copy_insn_regexp (REGEXP_SEQUENCE (regexp
)->regexps
[j
]);
4635 REGEXP_SEQUENCE (sequence
)->regexps
[j
]
4636 = copy_insn_regexp (REGEXP_ONEOF (oneof
)->regexps
[i
]);
4638 regexp_transformed_p
= 1;
4642 else if (regexp
->mode
== rm_allof
)
4644 regexp_t oneof
= NULL
;
4646 int oneof_index
= 0;
4647 int max_seq_length
, allof_length
;
4649 regexp_t allof
= NULL
;
4650 regexp_t allof_op
= NULL
;
4653 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
4654 if (REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
== rm_oneof
)
4657 oneof
= REGEXP_ALLOF (regexp
)->regexps
[i
];
4660 if (i
< REGEXP_ALLOF (regexp
)->regexps_num
)
4662 gcc_assert (REGEXP_ONEOF (oneof
)->regexps_num
> 1
4663 && REGEXP_ALLOF (regexp
)->regexps_num
> 1);
4664 result
= create_node (sizeof (struct regexp
)
4666 * (REGEXP_ONEOF (oneof
)->regexps_num
- 1));
4667 result
->mode
= rm_oneof
;
4668 result
->pos
= regexp
->pos
;
4669 REGEXP_ONEOF (result
)->regexps_num
4670 = REGEXP_ONEOF (oneof
)->regexps_num
;
4671 for (i
= 0; i
< REGEXP_ONEOF (result
)->regexps_num
; i
++)
4674 = create_node (sizeof (struct regexp
)
4676 * (REGEXP_ALLOF (regexp
)->regexps_num
- 1));
4677 allof
->mode
= rm_allof
;
4678 allof
->pos
= regexp
->pos
;
4679 REGEXP_ALLOF (allof
)->regexps_num
4680 = REGEXP_ALLOF (regexp
)->regexps_num
;
4681 REGEXP_ONEOF (result
)->regexps
[i
] = allof
;
4682 for (j
= 0; j
< REGEXP_ALLOF (allof
)->regexps_num
; j
++)
4683 if (j
!= oneof_index
)
4684 REGEXP_ALLOF (allof
)->regexps
[j
]
4685 = copy_insn_regexp (REGEXP_ALLOF (regexp
)->regexps
[j
]);
4687 REGEXP_ALLOF (allof
)->regexps
[j
]
4688 = copy_insn_regexp (REGEXP_ONEOF (oneof
)->regexps
[i
]);
4690 regexp_transformed_p
= 1;
4694 if (regexp
->mode
== rm_allof
)
4695 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
4697 switch (REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
)
4700 seq
= REGEXP_ALLOF (regexp
)->regexps
[i
];
4701 if (max_seq_length
< REGEXP_SEQUENCE (seq
)->regexps_num
)
4702 max_seq_length
= REGEXP_SEQUENCE (seq
)->regexps_num
;
4715 if (max_seq_length
!= 0)
4717 gcc_assert (max_seq_length
!= 1
4718 && REGEXP_ALLOF (regexp
)->regexps_num
> 1);
4719 result
= create_node (sizeof (struct regexp
)
4720 + sizeof (regexp_t
) * (max_seq_length
- 1));
4721 result
->mode
= rm_sequence
;
4722 result
->pos
= regexp
->pos
;
4723 REGEXP_SEQUENCE (result
)->regexps_num
= max_seq_length
;
4724 for (i
= 0; i
< max_seq_length
; i
++)
4727 for (j
= 0; j
< REGEXP_ALLOF (regexp
)->regexps_num
; j
++)
4728 switch (REGEXP_ALLOF (regexp
)->regexps
[j
]->mode
)
4731 if (i
< (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp
)
4732 ->regexps
[j
])->regexps_num
))
4735 = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp
)
4745 allof_op
= REGEXP_ALLOF (regexp
)->regexps
[j
];
4753 if (allof_length
== 1)
4754 REGEXP_SEQUENCE (result
)->regexps
[i
] = allof_op
;
4757 allof
= create_node (sizeof (struct regexp
)
4759 * (allof_length
- 1));
4760 allof
->mode
= rm_allof
;
4761 allof
->pos
= regexp
->pos
;
4762 REGEXP_ALLOF (allof
)->regexps_num
= allof_length
;
4763 REGEXP_SEQUENCE (result
)->regexps
[i
] = allof
;
4765 for (j
= 0; j
< REGEXP_ALLOF (regexp
)->regexps_num
; j
++)
4766 if (REGEXP_ALLOF (regexp
)->regexps
[j
]->mode
== rm_sequence
4768 (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp
)
4769 ->regexps
[j
])->regexps_num
)))
4771 allof_op
= (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp
)
4774 REGEXP_ALLOF (allof
)->regexps
[allof_length
]
4779 && (REGEXP_ALLOF (regexp
)->regexps
[j
]->mode
4781 || (REGEXP_ALLOF (regexp
)->regexps
[j
]->mode
4784 allof_op
= REGEXP_ALLOF (regexp
)->regexps
[j
];
4785 REGEXP_ALLOF (allof
)->regexps
[allof_length
]
4791 regexp_transformed_p
= 1;
4798 /* The function traverses IR of reservation and applies transformations
4799 implemented by FUNC. */
4801 regexp_transform_func (regexp_t regexp
, regexp_t (*func
) (regexp_t regexp
))
4805 switch (regexp
->mode
)
4808 for (i
= 0; i
< REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
4809 REGEXP_SEQUENCE (regexp
)->regexps
[i
]
4810 = regexp_transform_func (REGEXP_SEQUENCE (regexp
)->regexps
[i
],
4815 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
4816 REGEXP_ALLOF (regexp
)->regexps
[i
]
4817 = regexp_transform_func (REGEXP_ALLOF (regexp
)->regexps
[i
], func
);
4821 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
4822 REGEXP_ONEOF (regexp
)->regexps
[i
]
4823 = regexp_transform_func (REGEXP_ONEOF (regexp
)->regexps
[i
], func
);
4827 REGEXP_REPEAT (regexp
)->regexp
4828 = regexp_transform_func (REGEXP_REPEAT (regexp
)->regexp
, func
);
4838 return (*func
) (regexp
);
4841 /* The function applies all transformations for IR representation of
4842 reservation REGEXP. */
4844 transform_regexp (regexp_t regexp
)
4846 regexp
= regexp_transform_func (regexp
, transform_1
);
4849 regexp_transformed_p
= 0;
4850 regexp
= regexp_transform_func (regexp
, transform_2
);
4851 regexp
= regexp_transform_func (regexp
, transform_3
);
4853 while (regexp_transformed_p
);
4857 /* The function applies all transformations for reservations of all
4858 insn declarations. */
4860 transform_insn_regexps (void)
4865 transform_time
= create_ticker ();
4866 add_advance_cycle_insn_decl ();
4868 fprintf (stderr
, "Reservation transformation...");
4869 for (i
= 0; i
< description
->decls_num
; i
++)
4871 decl
= description
->decls
[i
];
4872 if (decl
->mode
== dm_insn_reserv
&& decl
!= advance_cycle_insn_decl
)
4873 DECL_INSN_RESERV (decl
)->transformed_regexp
4874 = transform_regexp (copy_insn_regexp
4875 (DECL_INSN_RESERV (decl
)->regexp
));
4878 fprintf (stderr
, "done\n");
4879 ticker_off (&transform_time
);
4884 /* The following variable value is TRUE if the first annotated message
4885 about units to automata distribution has been output. */
4886 static int annotation_message_reported_p
;
4888 /* The following structure describes usage of a unit in a reservation. */
4891 unit_decl_t unit_decl
;
4892 /* The following forms a list of units used on the same cycle in the
4893 same alternative. */
4894 struct unit_usage
*next
;
4896 typedef struct unit_usage
*unit_usage_t
;
4898 DEF_VEC_P(unit_usage_t
);
4899 DEF_VEC_ALLOC_P(unit_usage_t
,heap
);
4901 /* Obstack for unit_usage structures. */
4902 static struct obstack unit_usages
;
4904 /* VLA for representation of array of pointers to unit usage
4905 structures. There is an element for each combination of
4906 (alternative number, cycle). Unit usages on given cycle in
4907 alternative with given number are referred through element with
4908 index equals to the cycle * number of all alternatives in the regexp
4909 + the alternative number. */
4910 static VEC(unit_usage_t
,heap
) *cycle_alt_unit_usages
;
4912 /* The following function creates the structure unit_usage for UNIT on
4913 CYCLE in REGEXP alternative with ALT_NUM. The structure is made
4914 accessed through cycle_alt_unit_usages. */
4916 store_alt_unit_usage (regexp_t regexp
, regexp_t unit
, int cycle
,
4920 unit_decl_t unit_decl
;
4921 unit_usage_t unit_usage_ptr
;
4924 gcc_assert (regexp
&& regexp
->mode
== rm_oneof
4925 && alt_num
< REGEXP_ONEOF (regexp
)->regexps_num
);
4926 unit_decl
= REGEXP_UNIT (unit
)->unit_decl
;
4928 length
= (cycle
+ 1) * REGEXP_ONEOF (regexp
)->regexps_num
;
4929 while (VEC_length (unit_usage_t
, cycle_alt_unit_usages
) < length
)
4930 VEC_safe_push (unit_usage_t
,heap
, cycle_alt_unit_usages
, 0);
4932 obstack_blank (&unit_usages
, sizeof (struct unit_usage
));
4933 unit_usage_ptr
= (struct unit_usage
*) obstack_base (&unit_usages
);
4934 obstack_finish (&unit_usages
);
4935 unit_usage_ptr
->unit_decl
= unit_decl
;
4936 index
= cycle
* REGEXP_ONEOF (regexp
)->regexps_num
+ alt_num
;
4937 unit_usage_ptr
->next
= VEC_index (unit_usage_t
, cycle_alt_unit_usages
, index
);
4938 VEC_replace (unit_usage_t
, cycle_alt_unit_usages
, index
, unit_usage_ptr
);
4939 unit_decl
->last_distribution_check_cycle
= -1; /* undefined */
4942 /* The function processes given REGEXP to find units with the wrong
4945 check_regexp_units_distribution (const char *insn_reserv_name
,
4949 regexp_t seq
, allof
, unit
;
4950 struct unit_usage
*unit_usage_ptr
, *other_unit_usage_ptr
;
4952 if (regexp
== NULL
|| regexp
->mode
!= rm_oneof
)
4954 /* Store all unit usages in the regexp: */
4955 obstack_init (&unit_usages
);
4956 cycle_alt_unit_usages
= 0;
4958 for (i
= REGEXP_ONEOF (regexp
)->regexps_num
- 1; i
>= 0; i
--)
4960 seq
= REGEXP_ONEOF (regexp
)->regexps
[i
];
4964 for (j
= 0; j
< REGEXP_SEQUENCE (seq
)->regexps_num
; j
++)
4966 allof
= REGEXP_SEQUENCE (seq
)->regexps
[j
];
4967 switch (allof
->mode
)
4970 for (k
= 0; k
< REGEXP_ALLOF (allof
)->regexps_num
; k
++)
4972 unit
= REGEXP_ALLOF (allof
)->regexps
[k
];
4973 if (unit
->mode
== rm_unit
)
4974 store_alt_unit_usage (regexp
, unit
, j
, i
);
4976 gcc_assert (unit
->mode
== rm_nothing
);
4981 store_alt_unit_usage (regexp
, allof
, j
, i
);
4994 for (k
= 0; k
< REGEXP_ALLOF (seq
)->regexps_num
; k
++)
4996 unit
= REGEXP_ALLOF (seq
)->regexps
[k
];
5000 store_alt_unit_usage (regexp
, unit
, 0, i
);
5013 store_alt_unit_usage (regexp
, seq
, 0, i
);
5023 /* Check distribution: */
5024 for (i
= 0; i
< (int) VEC_length (unit_usage_t
, cycle_alt_unit_usages
); i
++)
5026 cycle
= i
/ REGEXP_ONEOF (regexp
)->regexps_num
;
5027 for (unit_usage_ptr
= VEC_index (unit_usage_t
, cycle_alt_unit_usages
, i
);
5028 unit_usage_ptr
!= NULL
;
5029 unit_usage_ptr
= unit_usage_ptr
->next
)
5030 if (cycle
!= unit_usage_ptr
->unit_decl
->last_distribution_check_cycle
)
5032 unit_usage_ptr
->unit_decl
->last_distribution_check_cycle
= cycle
;
5033 for (k
= cycle
* REGEXP_ONEOF (regexp
)->regexps_num
;
5034 k
< (int) VEC_length (unit_usage_t
, cycle_alt_unit_usages
)
5035 && k
== cycle
* REGEXP_ONEOF (regexp
)->regexps_num
;
5038 for (other_unit_usage_ptr
5039 = VEC_index (unit_usage_t
, cycle_alt_unit_usages
, k
);
5040 other_unit_usage_ptr
!= NULL
;
5041 other_unit_usage_ptr
= other_unit_usage_ptr
->next
)
5042 if (unit_usage_ptr
->unit_decl
->automaton_decl
5043 == other_unit_usage_ptr
->unit_decl
->automaton_decl
)
5045 if (other_unit_usage_ptr
== NULL
5046 && (VEC_index (unit_usage_t
, cycle_alt_unit_usages
, k
)
5050 if (k
< (int) VEC_length (unit_usage_t
, cycle_alt_unit_usages
)
5051 && k
== cycle
* REGEXP_ONEOF (regexp
)->regexps_num
)
5053 if (!annotation_message_reported_p
)
5055 fprintf (stderr
, "\n");
5056 error ("The following units do not satisfy units-automata distribution rule");
5057 error (" (A unit of given unit automaton should be on each reserv. altern.)");
5058 annotation_message_reported_p
= TRUE
;
5060 error ("Unit %s, reserv. %s, cycle %d",
5061 unit_usage_ptr
->unit_decl
->name
, insn_reserv_name
,
5066 VEC_free (unit_usage_t
,heap
, cycle_alt_unit_usages
);
5067 obstack_free (&unit_usages
, NULL
);
5070 /* The function finds units which violates units to automata
5071 distribution rule. If the units exist, report about them. */
5073 check_unit_distributions_to_automata (void)
5079 fprintf (stderr
, "Check unit distributions to automata...");
5080 annotation_message_reported_p
= FALSE
;
5081 for (i
= 0; i
< description
->decls_num
; i
++)
5083 decl
= description
->decls
[i
];
5084 if (decl
->mode
== dm_insn_reserv
)
5085 check_regexp_units_distribution
5086 (DECL_INSN_RESERV (decl
)->name
,
5087 DECL_INSN_RESERV (decl
)->transformed_regexp
);
5090 fprintf (stderr
, "done\n");
5095 /* The page contains code for building alt_states (see comments for
5096 IR) describing all possible insns reservations of an automaton. */
5098 /* Current state being formed for which the current alt_state
5100 static state_t state_being_formed
;
5102 /* Current alt_state being formed. */
5103 static alt_state_t alt_state_being_formed
;
5105 /* This recursive function processes `,' and units in reservation
5106 REGEXP for forming alt_states of AUTOMATON. It is believed that
5107 CURR_CYCLE is start cycle of all reservation REGEXP. */
5109 process_seq_for_forming_states (regexp_t regexp
, automaton_t automaton
,
5117 switch (regexp
->mode
)
5120 if (REGEXP_UNIT (regexp
)->unit_decl
->corresponding_automaton_num
5121 == automaton
->automaton_order_num
)
5122 set_state_reserv (state_being_formed
, curr_cycle
,
5123 REGEXP_UNIT (regexp
)->unit_decl
->unit_num
);
5127 for (i
= 0; i
< REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
5129 = process_seq_for_forming_states
5130 (REGEXP_SEQUENCE (regexp
)->regexps
[i
], automaton
, curr_cycle
) + 1;
5135 int finish_cycle
= 0;
5138 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
5140 cycle
= process_seq_for_forming_states (REGEXP_ALLOF (regexp
)
5142 automaton
, curr_cycle
);
5143 if (finish_cycle
< cycle
)
5144 finish_cycle
= cycle
;
5146 return finish_cycle
;
5157 /* This recursive function finishes forming ALT_STATE of AUTOMATON and
5158 inserts alt_state into the table. */
5160 finish_forming_alt_state (alt_state_t alt_state
,
5161 automaton_t automaton ATTRIBUTE_UNUSED
)
5163 state_t state_in_table
;
5164 state_t corresponding_state
;
5166 corresponding_state
= alt_state
->state
;
5167 state_in_table
= insert_state (corresponding_state
);
5168 if (state_in_table
!= corresponding_state
)
5170 free_state (corresponding_state
);
5171 alt_state
->state
= state_in_table
;
5175 /* The following variable value is current automaton insn for whose
5176 reservation the alt states are created. */
5177 static ainsn_t curr_ainsn
;
5179 /* This recursive function processes `|' in reservation REGEXP for
5180 forming alt_states of AUTOMATON. List of the alt states should
5181 have the same order as in the description. */
5183 process_alts_for_forming_states (regexp_t regexp
, automaton_t automaton
,
5188 if (regexp
->mode
!= rm_oneof
)
5190 alt_state_being_formed
= get_free_alt_state ();
5191 state_being_formed
= get_free_state (1, automaton
);
5192 alt_state_being_formed
->state
= state_being_formed
;
5193 /* We inserts in reverse order but we process alternatives also
5194 in reverse order. So we have the same order of alternative
5195 as in the description. */
5196 alt_state_being_formed
->next_alt_state
= curr_ainsn
->alt_states
;
5197 curr_ainsn
->alt_states
= alt_state_being_formed
;
5198 (void) process_seq_for_forming_states (regexp
, automaton
, 0);
5199 finish_forming_alt_state (alt_state_being_formed
, automaton
);
5203 gcc_assert (!inside_oneof_p
);
5204 /* We processes it in reverse order to get list with the same
5205 order as in the description. See also the previous
5207 for (i
= REGEXP_ONEOF (regexp
)->regexps_num
- 1; i
>= 0; i
--)
5208 process_alts_for_forming_states (REGEXP_ONEOF (regexp
)->regexps
[i
],
5213 /* Create nodes alt_state for all AUTOMATON insns. */
5215 create_alt_states (automaton_t automaton
)
5217 struct insn_reserv_decl
*reserv_decl
;
5219 for (curr_ainsn
= automaton
->ainsn_list
;
5221 curr_ainsn
= curr_ainsn
->next_ainsn
)
5223 reserv_decl
= curr_ainsn
->insn_reserv_decl
;
5224 if (reserv_decl
!= DECL_INSN_RESERV (advance_cycle_insn_decl
))
5226 curr_ainsn
->alt_states
= NULL
;
5227 process_alts_for_forming_states (reserv_decl
->transformed_regexp
,
5229 curr_ainsn
->sorted_alt_states
5230 = uniq_sort_alt_states (curr_ainsn
->alt_states
);
5237 /* The page contains major code for building DFA(s) for fast pipeline
5238 hazards recognition. */
5240 /* The function forms list of ainsns of AUTOMATON with the same
5244 form_ainsn_with_same_reservs (automaton_t automaton
)
5248 VEC(ainsn_t
,heap
) *last_insns
= VEC_alloc (ainsn_t
,heap
, 150);
5250 for (curr_ainsn
= automaton
->ainsn_list
;
5252 curr_ainsn
= curr_ainsn
->next_ainsn
)
5253 if (curr_ainsn
->insn_reserv_decl
5254 == DECL_INSN_RESERV (advance_cycle_insn_decl
))
5256 curr_ainsn
->next_same_reservs_insn
= NULL
;
5257 curr_ainsn
->first_insn_with_same_reservs
= 1;
5261 for (i
= 0; i
< VEC_length (ainsn_t
, last_insns
); i
++)
5263 (curr_ainsn
->sorted_alt_states
,
5264 VEC_index (ainsn_t
, last_insns
, i
)->sorted_alt_states
))
5266 curr_ainsn
->next_same_reservs_insn
= NULL
;
5267 if (i
< VEC_length (ainsn_t
, last_insns
))
5269 curr_ainsn
->first_insn_with_same_reservs
= 0;
5270 VEC_index (ainsn_t
, last_insns
, i
)->next_same_reservs_insn
5272 VEC_replace (ainsn_t
, last_insns
, i
, curr_ainsn
);
5276 VEC_safe_push (ainsn_t
, heap
, last_insns
, curr_ainsn
);
5277 curr_ainsn
->first_insn_with_same_reservs
= 1;
5280 VEC_free (ainsn_t
,heap
, last_insns
);
5283 /* Forming unit reservations which can affect creating the automaton
5284 states achieved from a given state. It permits to build smaller
5285 automata in many cases. We would have the same automata after
5286 the minimization without such optimization, but the automaton
5287 right after the building could be huge. So in other words, usage
5288 of reservs_matter means some minimization during building the
5290 static reserv_sets_t
5291 form_reservs_matter (automaton_t automaton
)
5294 reserv_sets_t reservs_matter
= alloc_empty_reserv_sets();
5296 for (cycle
= 0; cycle
< max_cycles_num
; cycle
++)
5297 for (unit
= 0; unit
< description
->units_num
; unit
++)
5298 if (units_array
[unit
]->automaton_decl
5299 == automaton
->corresponding_automaton_decl
5300 && (cycle
>= units_array
[unit
]->min_occ_cycle_num
5301 /* We can not remove queried unit from reservations. */
5302 || units_array
[unit
]->query_p
5303 /* We can not remove units which are used
5304 `exclusion_set', `presence_set',
5305 `final_presence_set', `absence_set', and
5306 `final_absence_set'. */
5307 || units_array
[unit
]->in_set_p
))
5308 set_unit_reserv (reservs_matter
, cycle
, unit
);
5309 return reservs_matter
;
5312 /* The following function creates all states of nondeterministic AUTOMATON. */
5314 make_automaton (automaton_t automaton
)
5317 struct insn_reserv_decl
*insn_reserv_decl
;
5318 alt_state_t alt_state
;
5320 state_t start_state
;
5322 ainsn_t advance_cycle_ainsn
;
5324 VEC(state_t
,heap
) *state_stack
= VEC_alloc(state_t
,heap
, 150);
5326 reserv_sets_t reservs_matter
= form_reservs_matter (automaton
);
5328 /* Create the start state (empty state). */
5329 start_state
= insert_state (get_free_state (1, automaton
));
5330 automaton
->start_state
= start_state
;
5331 start_state
->it_was_placed_in_stack_for_NDFA_forming
= 1;
5332 VEC_safe_push (state_t
,heap
, state_stack
, start_state
);
5334 while (VEC_length (state_t
, state_stack
) != 0)
5336 state
= VEC_pop (state_t
, state_stack
);
5337 advance_cycle_ainsn
= NULL
;
5338 for (ainsn
= automaton
->ainsn_list
;
5340 ainsn
= ainsn
->next_ainsn
)
5341 if (ainsn
->first_insn_with_same_reservs
)
5343 insn_reserv_decl
= ainsn
->insn_reserv_decl
;
5344 if (insn_reserv_decl
!= DECL_INSN_RESERV (advance_cycle_insn_decl
))
5346 /* We process alt_states in the same order as they are
5347 present in the description. */
5349 for (alt_state
= ainsn
->alt_states
;
5351 alt_state
= alt_state
->next_alt_state
)
5353 state2
= alt_state
->state
;
5354 if (!intersected_state_reservs_p (state
, state2
))
5356 state2
= states_union (state
, state2
, reservs_matter
);
5357 if (!state2
->it_was_placed_in_stack_for_NDFA_forming
)
5359 state2
->it_was_placed_in_stack_for_NDFA_forming
5361 VEC_safe_push (state_t
,heap
, state_stack
, state2
);
5363 if (progress_flag
&& states_n
% 100 == 0)
5364 fprintf (stderr
, ".");
5366 added_arc
= add_arc (state
, state2
, ainsn
);
5371 if (!ndfa_flag
&& added_arc
!= NULL
)
5373 for (alt_state
= ainsn
->alt_states
;
5375 alt_state
= alt_state
->next_alt_state
)
5376 state2
= alt_state
->state
;
5380 advance_cycle_ainsn
= ainsn
;
5382 /* Add transition to advance cycle. */
5383 state2
= state_shift (state
, reservs_matter
);
5384 if (!state2
->it_was_placed_in_stack_for_NDFA_forming
)
5386 state2
->it_was_placed_in_stack_for_NDFA_forming
= 1;
5387 VEC_safe_push (state_t
,heap
, state_stack
, state2
);
5389 if (progress_flag
&& states_n
% 100 == 0)
5390 fprintf (stderr
, ".");
5392 gcc_assert (advance_cycle_ainsn
);
5393 add_arc (state
, state2
, advance_cycle_ainsn
);
5395 VEC_free (state_t
,heap
, state_stack
);
5398 /* Foms lists of all arcs of STATE marked by the same ainsn. */
5400 form_arcs_marked_by_insn (state_t state
)
5406 for (i
= 0; i
< description
->decls_num
; i
++)
5408 decl
= description
->decls
[i
];
5409 if (decl
->mode
== dm_insn_reserv
)
5410 DECL_INSN_RESERV (decl
)->arcs_marked_by_insn
= NULL
;
5412 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
5414 gcc_assert (arc
->insn
);
5415 arc
->next_arc_marked_by_insn
5416 = arc
->insn
->insn_reserv_decl
->arcs_marked_by_insn
;
5417 arc
->insn
->insn_reserv_decl
->arcs_marked_by_insn
= arc
;
5421 /* The function creates composed state (see comments for IR) from
5422 ORIGINAL_STATE and list of arcs ARCS_MARKED_BY_INSN marked by the
5423 same insn. If the composed state is not in STATE_STACK yet, it is
5424 pushed into STATE_STACK. */
5427 create_composed_state (state_t original_state
, arc_t arcs_marked_by_insn
,
5428 VEC(state_t
,heap
) **state_stack
)
5431 alt_state_t alt_state
, curr_alt_state
;
5432 alt_state_t new_alt_state
;
5435 state_t state_in_table
;
5437 alt_state_t canonical_alt_states_list
;
5439 int new_state_p
= 0;
5441 if (arcs_marked_by_insn
== NULL
)
5443 if (arcs_marked_by_insn
->next_arc_marked_by_insn
== NULL
)
5444 state
= arcs_marked_by_insn
->to_state
;
5447 gcc_assert (ndfa_flag
);
5448 /* Create composed state. */
5449 state
= get_free_state (0, arcs_marked_by_insn
->to_state
->automaton
);
5450 curr_alt_state
= NULL
;
5451 for (curr_arc
= arcs_marked_by_insn
;
5453 curr_arc
= curr_arc
->next_arc_marked_by_insn
)
5454 if (curr_arc
->to_state
->component_states
== NULL
)
5456 new_alt_state
= get_free_alt_state ();
5457 new_alt_state
->next_alt_state
= curr_alt_state
;
5458 new_alt_state
->state
= curr_arc
->to_state
;
5459 curr_alt_state
= new_alt_state
;
5462 for (alt_state
= curr_arc
->to_state
->component_states
;
5464 alt_state
= alt_state
->next_sorted_alt_state
)
5466 new_alt_state
= get_free_alt_state ();
5467 new_alt_state
->next_alt_state
= curr_alt_state
;
5468 new_alt_state
->state
= alt_state
->state
;
5469 gcc_assert (!alt_state
->state
->component_states
);
5470 curr_alt_state
= new_alt_state
;
5472 /* There are not identical sets in the alt state list. */
5473 canonical_alt_states_list
= uniq_sort_alt_states (curr_alt_state
);
5474 if (canonical_alt_states_list
->next_sorted_alt_state
== NULL
)
5477 state
= canonical_alt_states_list
->state
;
5478 free_state (temp_state
);
5482 state
->component_states
= canonical_alt_states_list
;
5483 state_in_table
= insert_state (state
);
5484 if (state_in_table
!= state
)
5487 (state_in_table
->it_was_placed_in_stack_for_DFA_forming
);
5489 state
= state_in_table
;
5493 gcc_assert (!state
->it_was_placed_in_stack_for_DFA_forming
);
5495 for (curr_alt_state
= state
->component_states
;
5496 curr_alt_state
!= NULL
;
5497 curr_alt_state
= curr_alt_state
->next_sorted_alt_state
)
5498 for (curr_arc
= first_out_arc (curr_alt_state
->state
);
5500 curr_arc
= next_out_arc (curr_arc
))
5501 add_arc (state
, curr_arc
->to_state
, curr_arc
->insn
);
5503 arcs_marked_by_insn
->to_state
= state
;
5504 for (alts_number
= 0,
5505 curr_arc
= arcs_marked_by_insn
->next_arc_marked_by_insn
;
5507 curr_arc
= next_arc
)
5509 next_arc
= curr_arc
->next_arc_marked_by_insn
;
5510 remove_arc (original_state
, curr_arc
);
5515 if (!state
->it_was_placed_in_stack_for_DFA_forming
)
5517 state
->it_was_placed_in_stack_for_DFA_forming
= 1;
5518 VEC_safe_push (state_t
,heap
, *state_stack
, state
);
5523 /* The function transforms nondeterministic AUTOMATON into
5527 NDFA_to_DFA (automaton_t automaton
)
5529 state_t start_state
;
5532 VEC(state_t
,heap
) *state_stack
;
5536 state_stack
= VEC_alloc (state_t
,heap
, 0);
5538 /* Create the start state (empty state). */
5539 start_state
= automaton
->start_state
;
5540 start_state
->it_was_placed_in_stack_for_DFA_forming
= 1;
5541 VEC_safe_push (state_t
,heap
, state_stack
, start_state
);
5543 while (VEC_length (state_t
, state_stack
) != 0)
5545 state
= VEC_pop (state_t
, state_stack
);
5546 form_arcs_marked_by_insn (state
);
5547 for (i
= 0; i
< description
->decls_num
; i
++)
5549 decl
= description
->decls
[i
];
5550 if (decl
->mode
== dm_insn_reserv
5551 && create_composed_state
5552 (state
, DECL_INSN_RESERV (decl
)->arcs_marked_by_insn
,
5556 if (progress_flag
&& states_n
% 100 == 0)
5557 fprintf (stderr
, ".");
5561 VEC_free (state_t
,heap
, state_stack
);
5564 /* The following variable value is current number (1, 2, ...) of passing
5566 static int curr_state_graph_pass_num
;
5568 /* This recursive function passes all states achieved from START_STATE
5569 and applies APPLIED_FUNC to them. */
5571 pass_state_graph (state_t start_state
, void (*applied_func
) (state_t state
))
5575 if (start_state
->pass_num
== curr_state_graph_pass_num
)
5577 start_state
->pass_num
= curr_state_graph_pass_num
;
5578 (*applied_func
) (start_state
);
5579 for (arc
= first_out_arc (start_state
);
5581 arc
= next_out_arc (arc
))
5582 pass_state_graph (arc
->to_state
, applied_func
);
5585 /* This recursive function passes all states of AUTOMATON and applies
5586 APPLIED_FUNC to them. */
5588 pass_states (automaton_t automaton
, void (*applied_func
) (state_t state
))
5590 curr_state_graph_pass_num
++;
5591 pass_state_graph (automaton
->start_state
, applied_func
);
5594 /* The function initializes code for passing of all states. */
5596 initiate_pass_states (void)
5598 curr_state_graph_pass_num
= 0;
5601 /* The following vla is used for storing pointers to all achieved
5603 static VEC(state_t
,heap
) *all_achieved_states
;
5605 /* This function is called by function pass_states to add an achieved
5608 add_achieved_state (state_t state
)
5610 VEC_safe_push (state_t
,heap
, all_achieved_states
, state
);
5613 /* The function sets up equivalence numbers of insns which mark all
5614 out arcs of STATE by equiv_class_num_1 (if ODD_ITERATION_FLAG has
5615 nonzero value) or by equiv_class_num_2 of the destination state.
5616 The function returns number of out arcs of STATE. */
5618 set_out_arc_insns_equiv_num (state_t state
, int odd_iteration_flag
)
5620 int state_out_arcs_num
;
5623 state_out_arcs_num
= 0;
5624 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
5626 gcc_assert (!arc
->insn
->insn_reserv_decl
->equiv_class_num
);
5627 state_out_arcs_num
++;
5628 arc
->insn
->insn_reserv_decl
->equiv_class_num
5629 = (odd_iteration_flag
5630 ? arc
->to_state
->equiv_class_num_1
5631 : arc
->to_state
->equiv_class_num_2
);
5632 gcc_assert (arc
->insn
->insn_reserv_decl
->equiv_class_num
);
5634 return state_out_arcs_num
;
5637 /* The function clears equivalence numbers and alt_states in all insns
5638 which mark all out arcs of STATE. */
5640 clear_arc_insns_equiv_num (state_t state
)
5644 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
5645 arc
->insn
->insn_reserv_decl
->equiv_class_num
= 0;
5649 /* The following function returns TRUE if STATE reserves the unit with
5650 UNIT_NUM on the first cycle. */
5652 first_cycle_unit_presence (state_t state
, int unit_num
)
5654 alt_state_t alt_state
;
5656 if (state
->component_states
== NULL
)
5657 return test_unit_reserv (state
->reservs
, 0, unit_num
);
5660 for (alt_state
= state
->component_states
;
5662 alt_state
= alt_state
->next_sorted_alt_state
)
5663 if (test_unit_reserv (alt_state
->state
->reservs
, 0, unit_num
))
5669 /* The function returns nonzero value if STATE is not equivalent to
5670 ANOTHER_STATE from the same current partition on equivalence
5671 classes. Another state has ANOTHER_STATE_OUT_ARCS_NUM number of
5672 output arcs. Iteration of making equivalence partition is defined
5673 by ODD_ITERATION_FLAG. */
5675 state_is_differed (state_t state
, state_t another_state
,
5676 int another_state_out_arcs_num
, int odd_iteration_flag
)
5679 int state_out_arcs_num
;
5680 int i
, presence1_p
, presence2_p
;
5682 state_out_arcs_num
= 0;
5683 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
5685 state_out_arcs_num
++;
5686 if ((odd_iteration_flag
5687 ? arc
->to_state
->equiv_class_num_1
5688 : arc
->to_state
->equiv_class_num_2
)
5689 != arc
->insn
->insn_reserv_decl
->equiv_class_num
)
5692 if (state_out_arcs_num
!= another_state_out_arcs_num
)
5694 /* Now we are looking at the states with the point of view of query
5696 for (i
= 0; i
< description
->units_num
; i
++)
5697 if (units_array
[i
]->query_p
)
5699 presence1_p
= first_cycle_unit_presence (state
, i
);
5700 presence2_p
= first_cycle_unit_presence (another_state
, i
);
5701 if ((presence1_p
&& !presence2_p
) || (!presence1_p
&& presence2_p
))
5707 /* The function makes initial partition of STATES on equivalent
5710 init_equiv_class (VEC(state_t
,heap
) *states
)
5715 for (i
= 0; i
< VEC_length (state_t
, states
); i
++)
5717 VEC_index (state_t
, states
, i
)->equiv_class_num_1
= 1;
5718 VEC_index (state_t
, states
, i
)->next_equiv_class_state
= prev
;
5719 prev
= VEC_index (state_t
, states
, i
);
5724 /* The function copies pointers to equivalent states from vla FROM
5727 copy_equiv_class (VEC(state_t
,heap
) **to
, VEC(state_t
,heap
) *from
)
5729 VEC_free (state_t
,heap
, *to
);
5730 *to
= VEC_copy (state_t
,heap
, from
);
5732 /* The function processes equivalence class given by its first state,
5733 FIRST_STATE, on odd iteration if ODD_ITERATION_FLAG. If there
5734 are not equivalent states, the function partitions the class
5735 removing nonequivalent states and placing them in
5736 *NEXT_ITERATION_CLASSES, increments *NEW_EQUIV_CLASS_NUM_PTR ans
5737 assigns it to the state equivalence number. If the class has been
5738 partitioned, the function returns nonzero value. */
5740 partition_equiv_class (state_t first_state
, int odd_iteration_flag
,
5741 VEC(state_t
,heap
) **next_iteration_classes
,
5742 int *new_equiv_class_num_ptr
)
5744 state_t new_equiv_class
;
5753 while (first_state
!= NULL
)
5755 new_equiv_class
= NULL
;
5756 if (first_state
->next_equiv_class_state
!= NULL
)
5758 /* There are more one states in the class equivalence. */
5759 out_arcs_num
= set_out_arc_insns_equiv_num (first_state
,
5760 odd_iteration_flag
);
5761 for (prev_state
= first_state
,
5762 curr_state
= first_state
->next_equiv_class_state
;
5764 curr_state
= next_state
)
5766 next_state
= curr_state
->next_equiv_class_state
;
5767 if (state_is_differed (curr_state
, first_state
, out_arcs_num
,
5768 odd_iteration_flag
))
5770 /* Remove curr state from the class equivalence. */
5771 prev_state
->next_equiv_class_state
= next_state
;
5772 /* Add curr state to the new class equivalence. */
5773 curr_state
->next_equiv_class_state
= new_equiv_class
;
5774 if (new_equiv_class
== NULL
)
5775 (*new_equiv_class_num_ptr
)++;
5776 if (odd_iteration_flag
)
5777 curr_state
->equiv_class_num_2
= *new_equiv_class_num_ptr
;
5779 curr_state
->equiv_class_num_1
= *new_equiv_class_num_ptr
;
5780 new_equiv_class
= curr_state
;
5784 prev_state
= curr_state
;
5786 clear_arc_insns_equiv_num (first_state
);
5788 if (new_equiv_class
!= NULL
)
5789 VEC_safe_push (state_t
,heap
, *next_iteration_classes
, new_equiv_class
);
5790 first_state
= new_equiv_class
;
5795 /* The function finds equivalent states of AUTOMATON. */
5797 evaluate_equiv_classes (automaton_t automaton
,
5798 VEC(state_t
,heap
) **equiv_classes
)
5800 state_t new_equiv_class
;
5801 int new_equiv_class_num
;
5802 int odd_iteration_flag
;
5804 VEC (state_t
,heap
) *next_iteration_classes
;
5807 all_achieved_states
= VEC_alloc (state_t
,heap
, 1500);
5808 pass_states (automaton
, add_achieved_state
);
5809 new_equiv_class
= init_equiv_class (all_achieved_states
);
5810 odd_iteration_flag
= 0;
5811 new_equiv_class_num
= 1;
5813 next_iteration_classes
= VEC_alloc (state_t
,heap
, 150);
5814 VEC_quick_push (state_t
, next_iteration_classes
, new_equiv_class
);
5818 odd_iteration_flag
= !odd_iteration_flag
;
5820 copy_equiv_class (equiv_classes
, next_iteration_classes
);
5822 /* Transfer equiv numbers for the next iteration. */
5823 for (i
= 0; i
< VEC_length (state_t
, all_achieved_states
); i
++)
5824 if (odd_iteration_flag
)
5825 VEC_index (state_t
, all_achieved_states
, i
)->equiv_class_num_2
5826 = VEC_index (state_t
, all_achieved_states
, i
)->equiv_class_num_1
;
5828 VEC_index (state_t
, all_achieved_states
, i
)->equiv_class_num_1
5829 = VEC_index (state_t
, all_achieved_states
, i
)->equiv_class_num_2
;
5831 for (i
= 0; i
< VEC_length (state_t
, *equiv_classes
); i
++)
5832 if (partition_equiv_class (VEC_index (state_t
, *equiv_classes
, i
),
5834 &next_iteration_classes
,
5835 &new_equiv_class_num
))
5838 while (!finish_flag
);
5839 VEC_free (state_t
,heap
, next_iteration_classes
);
5840 VEC_free (state_t
,heap
, all_achieved_states
);
5843 /* The function merges equivalent states of AUTOMATON. */
5845 merge_states (automaton_t automaton
, VEC(state_t
,heap
) *equiv_classes
)
5849 state_t first_class_state
;
5850 alt_state_t alt_states
;
5851 alt_state_t alt_state
, new_alt_state
;
5856 /* Create states corresponding to equivalence classes containing two
5858 for (i
= 0; i
< VEC_length (state_t
, equiv_classes
); i
++)
5860 curr_state
= VEC_index (state_t
, equiv_classes
, i
);
5861 if (curr_state
->next_equiv_class_state
!= NULL
)
5863 /* There are more one states in the class equivalence. */
5864 /* Create new compound state. */
5865 new_state
= get_free_state (0, automaton
);
5867 first_class_state
= curr_state
;
5868 for (curr_state
= first_class_state
;
5870 curr_state
= curr_state
->next_equiv_class_state
)
5872 curr_state
->equiv_class_state
= new_state
;
5873 if (curr_state
->component_states
== NULL
)
5875 new_alt_state
= get_free_alt_state ();
5876 new_alt_state
->state
= curr_state
;
5877 new_alt_state
->next_alt_state
= alt_states
;
5878 alt_states
= new_alt_state
;
5881 for (alt_state
= curr_state
->component_states
;
5883 alt_state
= alt_state
->next_sorted_alt_state
)
5885 new_alt_state
= get_free_alt_state ();
5886 new_alt_state
->state
= alt_state
->state
;
5887 new_alt_state
->next_alt_state
= alt_states
;
5888 alt_states
= new_alt_state
;
5891 /* Its is important that alt states were sorted before and
5892 after merging to have the same querying results. */
5893 new_state
->component_states
= uniq_sort_alt_states (alt_states
);
5896 curr_state
->equiv_class_state
= curr_state
;
5899 for (i
= 0; i
< VEC_length (state_t
, equiv_classes
); i
++)
5901 curr_state
= VEC_index (state_t
, equiv_classes
, i
);
5902 if (curr_state
->next_equiv_class_state
!= NULL
)
5904 first_class_state
= curr_state
;
5905 /* Create new arcs output from the state corresponding to
5907 for (curr_arc
= first_out_arc (first_class_state
);
5909 curr_arc
= next_out_arc (curr_arc
))
5910 add_arc (first_class_state
->equiv_class_state
,
5911 curr_arc
->to_state
->equiv_class_state
,
5913 /* Delete output arcs from states of given class equivalence. */
5914 for (curr_state
= first_class_state
;
5916 curr_state
= curr_state
->next_equiv_class_state
)
5918 if (automaton
->start_state
== curr_state
)
5919 automaton
->start_state
= curr_state
->equiv_class_state
;
5920 /* Delete the state and its output arcs. */
5921 for (curr_arc
= first_out_arc (curr_state
);
5923 curr_arc
= next_arc
)
5925 next_arc
= next_out_arc (curr_arc
);
5926 free_arc (curr_arc
);
5932 /* Change `to_state' of arcs output from the state of given
5933 equivalence class. */
5934 for (curr_arc
= first_out_arc (curr_state
);
5936 curr_arc
= next_out_arc (curr_arc
))
5937 curr_arc
->to_state
= curr_arc
->to_state
->equiv_class_state
;
5942 /* The function sets up new_cycle_p for states if there is arc to the
5943 state marked by advance_cycle_insn_decl. */
5945 set_new_cycle_flags (state_t state
)
5949 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
5950 if (arc
->insn
->insn_reserv_decl
5951 == DECL_INSN_RESERV (advance_cycle_insn_decl
))
5952 arc
->to_state
->new_cycle_p
= 1;
5955 /* The top level function for minimization of deterministic
5958 minimize_DFA (automaton_t automaton
)
5960 VEC(state_t
,heap
) *equiv_classes
= 0;
5962 evaluate_equiv_classes (automaton
, &equiv_classes
);
5963 merge_states (automaton
, equiv_classes
);
5964 pass_states (automaton
, set_new_cycle_flags
);
5966 VEC_free (state_t
,heap
, equiv_classes
);
5969 /* Values of two variables are counted number of states and arcs in an
5971 static int curr_counted_states_num
;
5972 static int curr_counted_arcs_num
;
5974 /* The function is called by function `pass_states' to count states
5975 and arcs of an automaton. */
5977 incr_states_and_arcs_nums (state_t state
)
5981 curr_counted_states_num
++;
5982 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
5983 curr_counted_arcs_num
++;
5986 /* The function counts states and arcs of AUTOMATON. */
5988 count_states_and_arcs (automaton_t automaton
, int *states_num
,
5991 curr_counted_states_num
= 0;
5992 curr_counted_arcs_num
= 0;
5993 pass_states (automaton
, incr_states_and_arcs_nums
);
5994 *states_num
= curr_counted_states_num
;
5995 *arcs_num
= curr_counted_arcs_num
;
5998 /* The function builds one DFA AUTOMATON for fast pipeline hazards
5999 recognition after checking and simplifying IR of the
6002 build_automaton (automaton_t automaton
)
6007 ticker_on (&NDFA_time
);
6010 if (automaton
->corresponding_automaton_decl
== NULL
)
6011 fprintf (stderr
, "Create anonymous automaton");
6013 fprintf (stderr
, "Create automaton `%s'",
6014 automaton
->corresponding_automaton_decl
->name
);
6015 fprintf (stderr
, " (1 dot is 100 new states):");
6017 make_automaton (automaton
);
6019 fprintf (stderr
, " done\n");
6020 ticker_off (&NDFA_time
);
6021 count_states_and_arcs (automaton
, &states_num
, &arcs_num
);
6022 automaton
->NDFA_states_num
= states_num
;
6023 automaton
->NDFA_arcs_num
= arcs_num
;
6024 ticker_on (&NDFA_to_DFA_time
);
6027 if (automaton
->corresponding_automaton_decl
== NULL
)
6028 fprintf (stderr
, "Make anonymous DFA");
6030 fprintf (stderr
, "Make DFA `%s'",
6031 automaton
->corresponding_automaton_decl
->name
);
6032 fprintf (stderr
, " (1 dot is 100 new states):");
6034 NDFA_to_DFA (automaton
);
6036 fprintf (stderr
, " done\n");
6037 ticker_off (&NDFA_to_DFA_time
);
6038 count_states_and_arcs (automaton
, &states_num
, &arcs_num
);
6039 automaton
->DFA_states_num
= states_num
;
6040 automaton
->DFA_arcs_num
= arcs_num
;
6041 if (!no_minimization_flag
)
6043 ticker_on (&minimize_time
);
6046 if (automaton
->corresponding_automaton_decl
== NULL
)
6047 fprintf (stderr
, "Minimize anonymous DFA...");
6049 fprintf (stderr
, "Minimize DFA `%s'...",
6050 automaton
->corresponding_automaton_decl
->name
);
6052 minimize_DFA (automaton
);
6054 fprintf (stderr
, "done\n");
6055 ticker_off (&minimize_time
);
6056 count_states_and_arcs (automaton
, &states_num
, &arcs_num
);
6057 automaton
->minimal_DFA_states_num
= states_num
;
6058 automaton
->minimal_DFA_arcs_num
= arcs_num
;
6064 /* The page contains code for enumeration of all states of an automaton. */
6066 /* Variable used for enumeration of all states of an automaton. Its
6067 value is current number of automaton states. */
6068 static int curr_state_order_num
;
6070 /* The function is called by function `pass_states' for enumerating
6073 set_order_state_num (state_t state
)
6075 state
->order_state_num
= curr_state_order_num
;
6076 curr_state_order_num
++;
6079 /* The function enumerates all states of AUTOMATON. */
6081 enumerate_states (automaton_t automaton
)
6083 curr_state_order_num
= 0;
6084 pass_states (automaton
, set_order_state_num
);
6085 automaton
->achieved_states_num
= curr_state_order_num
;
6090 /* The page contains code for finding equivalent automaton insns
6093 /* The function inserts AINSN into cyclic list
6094 CYCLIC_EQUIV_CLASS_INSN_LIST of ainsns. */
6096 insert_ainsn_into_equiv_class (ainsn_t ainsn
,
6097 ainsn_t cyclic_equiv_class_insn_list
)
6099 if (cyclic_equiv_class_insn_list
== NULL
)
6100 ainsn
->next_equiv_class_insn
= ainsn
;
6103 ainsn
->next_equiv_class_insn
6104 = cyclic_equiv_class_insn_list
->next_equiv_class_insn
;
6105 cyclic_equiv_class_insn_list
->next_equiv_class_insn
= ainsn
;
6110 /* The function deletes equiv_class_insn into cyclic list of
6111 equivalent ainsns. */
6113 delete_ainsn_from_equiv_class (ainsn_t equiv_class_insn
)
6115 ainsn_t curr_equiv_class_insn
;
6116 ainsn_t prev_equiv_class_insn
;
6118 prev_equiv_class_insn
= equiv_class_insn
;
6119 for (curr_equiv_class_insn
= equiv_class_insn
->next_equiv_class_insn
;
6120 curr_equiv_class_insn
!= equiv_class_insn
;
6121 curr_equiv_class_insn
= curr_equiv_class_insn
->next_equiv_class_insn
)
6122 prev_equiv_class_insn
= curr_equiv_class_insn
;
6123 if (prev_equiv_class_insn
!= equiv_class_insn
)
6124 prev_equiv_class_insn
->next_equiv_class_insn
6125 = equiv_class_insn
->next_equiv_class_insn
;
6128 /* The function processes AINSN of a state in order to find equivalent
6129 ainsns. INSN_ARCS_ARRAY is table: code of insn -> out arc of the
6132 process_insn_equiv_class (ainsn_t ainsn
, arc_t
*insn_arcs_array
)
6136 ainsn_t cyclic_insn_list
;
6139 gcc_assert (insn_arcs_array
[ainsn
->insn_reserv_decl
->insn_num
]);
6141 /* New class of ainsns which are not equivalent to given ainsn. */
6142 cyclic_insn_list
= NULL
;
6145 next_insn
= curr_insn
->next_equiv_class_insn
;
6146 arc
= insn_arcs_array
[curr_insn
->insn_reserv_decl
->insn_num
];
6148 || (insn_arcs_array
[ainsn
->insn_reserv_decl
->insn_num
]->to_state
6151 delete_ainsn_from_equiv_class (curr_insn
);
6152 cyclic_insn_list
= insert_ainsn_into_equiv_class (curr_insn
,
6155 curr_insn
= next_insn
;
6157 while (curr_insn
!= ainsn
);
6160 /* The function processes STATE in order to find equivalent ainsns. */
6162 process_state_for_insn_equiv_partition (state_t state
)
6165 arc_t
*insn_arcs_array
= XCNEWVEC (arc_t
, description
->insns_num
);
6167 /* Process insns of the arcs. */
6168 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
6169 insn_arcs_array
[arc
->insn
->insn_reserv_decl
->insn_num
] = arc
;
6170 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
6171 process_insn_equiv_class (arc
->insn
, insn_arcs_array
);
6173 free (insn_arcs_array
);
6176 /* The function searches for equivalent ainsns of AUTOMATON. */
6178 set_insn_equiv_classes (automaton_t automaton
)
6183 ainsn_t cyclic_insn_list
;
6184 ainsn_t insn_with_same_reservs
;
6185 int equiv_classes_num
;
6187 /* All insns are included in one equivalence class. */
6188 cyclic_insn_list
= NULL
;
6189 for (ainsn
= automaton
->ainsn_list
; ainsn
!= NULL
; ainsn
= ainsn
->next_ainsn
)
6190 if (ainsn
->first_insn_with_same_reservs
)
6191 cyclic_insn_list
= insert_ainsn_into_equiv_class (ainsn
,
6193 /* Process insns in order to make equivalence partition. */
6194 pass_states (automaton
, process_state_for_insn_equiv_partition
);
6195 /* Enumerate equiv classes. */
6196 for (ainsn
= automaton
->ainsn_list
; ainsn
!= NULL
; ainsn
= ainsn
->next_ainsn
)
6197 /* Set undefined value. */
6198 ainsn
->insn_equiv_class_num
= -1;
6199 equiv_classes_num
= 0;
6200 for (ainsn
= automaton
->ainsn_list
; ainsn
!= NULL
; ainsn
= ainsn
->next_ainsn
)
6201 if (ainsn
->insn_equiv_class_num
< 0)
6204 gcc_assert (first_insn
->first_insn_with_same_reservs
);
6205 first_insn
->first_ainsn_with_given_equivalence_num
= 1;
6206 curr_insn
= first_insn
;
6209 for (insn_with_same_reservs
= curr_insn
;
6210 insn_with_same_reservs
!= NULL
;
6211 insn_with_same_reservs
6212 = insn_with_same_reservs
->next_same_reservs_insn
)
6213 insn_with_same_reservs
->insn_equiv_class_num
= equiv_classes_num
;
6214 curr_insn
= curr_insn
->next_equiv_class_insn
;
6216 while (curr_insn
!= first_insn
);
6217 equiv_classes_num
++;
6219 automaton
->insn_equiv_classes_num
= equiv_classes_num
;
6224 /* This page contains code for creating DFA(s) and calls functions
6228 /* The following value is used to prevent floating point overflow for
6229 estimating an automaton bound. The value should be less DBL_MAX on
6230 the host machine. We use here approximate minimum of maximal
6231 double floating point value required by ANSI C standard. It
6232 will work for non ANSI sun compiler too. */
6234 #define MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND 1.0E37
6236 /* The function estimate size of the single DFA used by PHR (pipeline
6237 hazards recognizer). */
6239 estimate_one_automaton_bound (void)
6242 double one_automaton_estimation_bound
;
6246 one_automaton_estimation_bound
= 1.0;
6247 for (i
= 0; i
< description
->decls_num
; i
++)
6249 decl
= description
->decls
[i
];
6250 if (decl
->mode
== dm_unit
)
6252 root_value
= exp (log (DECL_UNIT (decl
)->max_occ_cycle_num
6253 - DECL_UNIT (decl
)->min_occ_cycle_num
+ 1.0)
6255 if (MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND
/ root_value
6256 > one_automaton_estimation_bound
)
6257 one_automaton_estimation_bound
*= root_value
;
6260 return one_automaton_estimation_bound
;
6263 /* The function compares unit declarations according to their maximal
6264 cycle in reservations. */
6266 compare_max_occ_cycle_nums (const void *unit_decl_1
,
6267 const void *unit_decl_2
)
6269 if ((DECL_UNIT (*(decl_t
*) unit_decl_1
)->max_occ_cycle_num
)
6270 < (DECL_UNIT (*(decl_t
*) unit_decl_2
)->max_occ_cycle_num
))
6272 else if ((DECL_UNIT (*(decl_t
*) unit_decl_1
)->max_occ_cycle_num
)
6273 == (DECL_UNIT (*(decl_t
*) unit_decl_2
)->max_occ_cycle_num
))
6279 /* The function makes heuristic assigning automata to units. Actually
6280 efficacy of the algorithm has been checked yet??? */
6283 units_to_automata_heuristic_distr (void)
6285 double estimation_bound
;
6289 unit_decl_t
*unit_decls
;
6292 if (description
->units_num
== 0)
6294 estimation_bound
= estimate_one_automaton_bound ();
6295 unit_decls
= XNEWVEC (unit_decl_t
, description
->units_num
);
6297 for (i
= 0, j
= 0; i
< description
->decls_num
; i
++)
6298 if (description
->decls
[i
]->mode
== dm_unit
)
6299 unit_decls
[j
++] = DECL_UNIT (description
->decls
[i
]);
6300 gcc_assert (j
== description
->units_num
);
6302 qsort (unit_decls
, description
->units_num
,
6303 sizeof (unit_decl_t
), compare_max_occ_cycle_nums
);
6306 bound_value
= unit_decls
[0]->max_occ_cycle_num
;
6307 unit_decls
[0]->corresponding_automaton_num
= automaton_num
;
6309 for (i
= 1; i
< description
->units_num
; i
++)
6311 rest_units_num
= description
->units_num
- i
+ 1;
6312 gcc_assert (automata_num
- automaton_num
- 1 <= rest_units_num
);
6313 if (automaton_num
< automata_num
- 1
6314 && ((automata_num
- automaton_num
- 1 == rest_units_num
)
6317 / unit_decls
[i
]->max_occ_cycle_num
))))
6319 bound_value
= unit_decls
[i
]->max_occ_cycle_num
;
6323 bound_value
*= unit_decls
[i
]->max_occ_cycle_num
;
6324 unit_decls
[i
]->corresponding_automaton_num
= automaton_num
;
6326 gcc_assert (automaton_num
== automata_num
- 1);
6330 /* The functions creates automaton insns for each automata. Automaton
6331 insn is simply insn for given automaton which makes reservation
6332 only of units of the automaton. */
6334 create_ainsns (void)
6337 ainsn_t first_ainsn
;
6344 for (i
= 0; i
< description
->decls_num
; i
++)
6346 decl
= description
->decls
[i
];
6347 if (decl
->mode
== dm_insn_reserv
)
6349 curr_ainsn
= create_node (sizeof (struct ainsn
));
6350 curr_ainsn
->insn_reserv_decl
= DECL_INSN_RESERV (decl
);
6351 curr_ainsn
->important_p
= FALSE
;
6352 curr_ainsn
->next_ainsn
= NULL
;
6353 if (prev_ainsn
== NULL
)
6354 first_ainsn
= curr_ainsn
;
6356 prev_ainsn
->next_ainsn
= curr_ainsn
;
6357 prev_ainsn
= curr_ainsn
;
6363 /* The function assigns automata to units according to constructions
6364 `define_automaton' in the description. */
6366 units_to_automata_distr (void)
6371 for (i
= 0; i
< description
->decls_num
; i
++)
6373 decl
= description
->decls
[i
];
6374 if (decl
->mode
== dm_unit
)
6376 if (DECL_UNIT (decl
)->automaton_decl
== NULL
6377 || (DECL_UNIT (decl
)->automaton_decl
->corresponding_automaton
6379 /* Distribute to the first automaton. */
6380 DECL_UNIT (decl
)->corresponding_automaton_num
= 0;
6382 DECL_UNIT (decl
)->corresponding_automaton_num
6383 = (DECL_UNIT (decl
)->automaton_decl
6384 ->corresponding_automaton
->automaton_order_num
);
6389 /* The function creates DFA(s) for fast pipeline hazards recognition
6390 after checking and simplifying IR of the description. */
6392 create_automata (void)
6394 automaton_t curr_automaton
;
6395 automaton_t prev_automaton
;
6397 int curr_automaton_num
;
6400 if (automata_num
!= 0)
6402 units_to_automata_heuristic_distr ();
6403 for (prev_automaton
= NULL
, curr_automaton_num
= 0;
6404 curr_automaton_num
< automata_num
;
6405 curr_automaton_num
++, prev_automaton
= curr_automaton
)
6407 curr_automaton
= create_node (sizeof (struct automaton
));
6408 curr_automaton
->ainsn_list
= create_ainsns ();
6409 curr_automaton
->corresponding_automaton_decl
= NULL
;
6410 curr_automaton
->next_automaton
= NULL
;
6411 curr_automaton
->automaton_order_num
= curr_automaton_num
;
6412 if (prev_automaton
== NULL
)
6413 description
->first_automaton
= curr_automaton
;
6415 prev_automaton
->next_automaton
= curr_automaton
;
6420 curr_automaton_num
= 0;
6421 prev_automaton
= NULL
;
6422 for (i
= 0; i
< description
->decls_num
; i
++)
6424 decl
= description
->decls
[i
];
6425 if (decl
->mode
== dm_automaton
6426 && DECL_AUTOMATON (decl
)->automaton_is_used
)
6428 curr_automaton
= create_node (sizeof (struct automaton
));
6429 curr_automaton
->ainsn_list
= create_ainsns ();
6430 curr_automaton
->corresponding_automaton_decl
6431 = DECL_AUTOMATON (decl
);
6432 curr_automaton
->next_automaton
= NULL
;
6433 DECL_AUTOMATON (decl
)->corresponding_automaton
= curr_automaton
;
6434 curr_automaton
->automaton_order_num
= curr_automaton_num
;
6435 if (prev_automaton
== NULL
)
6436 description
->first_automaton
= curr_automaton
;
6438 prev_automaton
->next_automaton
= curr_automaton
;
6439 curr_automaton_num
++;
6440 prev_automaton
= curr_automaton
;
6443 if (curr_automaton_num
== 0)
6445 curr_automaton
= create_node (sizeof (struct automaton
));
6446 curr_automaton
->ainsn_list
= create_ainsns ();
6447 curr_automaton
->corresponding_automaton_decl
= NULL
;
6448 curr_automaton
->next_automaton
= NULL
;
6449 description
->first_automaton
= curr_automaton
;
6451 units_to_automata_distr ();
6453 NDFA_time
= create_ticker ();
6454 ticker_off (&NDFA_time
);
6455 NDFA_to_DFA_time
= create_ticker ();
6456 ticker_off (&NDFA_to_DFA_time
);
6457 minimize_time
= create_ticker ();
6458 ticker_off (&minimize_time
);
6459 equiv_time
= create_ticker ();
6460 ticker_off (&equiv_time
);
6461 for (curr_automaton
= description
->first_automaton
;
6462 curr_automaton
!= NULL
;
6463 curr_automaton
= curr_automaton
->next_automaton
)
6467 if (curr_automaton
->corresponding_automaton_decl
== NULL
)
6468 fprintf (stderr
, "Prepare anonymous automaton creation ... ");
6470 fprintf (stderr
, "Prepare automaton `%s' creation...",
6471 curr_automaton
->corresponding_automaton_decl
->name
);
6473 create_alt_states (curr_automaton
);
6474 form_ainsn_with_same_reservs (curr_automaton
);
6476 fprintf (stderr
, "done\n");
6477 build_automaton (curr_automaton
);
6478 enumerate_states (curr_automaton
);
6479 ticker_on (&equiv_time
);
6480 set_insn_equiv_classes (curr_automaton
);
6481 ticker_off (&equiv_time
);
6487 /* This page contains code for forming string representation of
6488 regexp. The representation is formed on IR obstack. So you should
6489 not work with IR obstack between regexp_representation and
6490 finish_regexp_representation calls. */
6492 /* This recursive function forms string representation of regexp
6493 (without tailing '\0'). */
6495 form_regexp (regexp_t regexp
)
6499 switch (regexp
->mode
)
6501 case rm_unit
: case rm_reserv
:
6503 const char *name
= (regexp
->mode
== rm_unit
6504 ? REGEXP_UNIT (regexp
)->name
6505 : REGEXP_RESERV (regexp
)->name
);
6507 obstack_grow (&irp
, name
, strlen (name
));
6512 for (i
= 0; i
< REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
6515 obstack_1grow (&irp
, ',');
6516 form_regexp (REGEXP_SEQUENCE (regexp
)->regexps
[i
]);
6521 obstack_1grow (&irp
, '(');
6522 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
6525 obstack_1grow (&irp
, '+');
6526 if (REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
== rm_sequence
6527 || REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
== rm_oneof
)
6528 obstack_1grow (&irp
, '(');
6529 form_regexp (REGEXP_ALLOF (regexp
)->regexps
[i
]);
6530 if (REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
== rm_sequence
6531 || REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
== rm_oneof
)
6532 obstack_1grow (&irp
, ')');
6534 obstack_1grow (&irp
, ')');
6538 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
6541 obstack_1grow (&irp
, '|');
6542 if (REGEXP_ONEOF (regexp
)->regexps
[i
]->mode
== rm_sequence
)
6543 obstack_1grow (&irp
, '(');
6544 form_regexp (REGEXP_ONEOF (regexp
)->regexps
[i
]);
6545 if (REGEXP_ONEOF (regexp
)->regexps
[i
]->mode
== rm_sequence
)
6546 obstack_1grow (&irp
, ')');
6554 if (REGEXP_REPEAT (regexp
)->regexp
->mode
== rm_sequence
6555 || REGEXP_REPEAT (regexp
)->regexp
->mode
== rm_allof
6556 || REGEXP_REPEAT (regexp
)->regexp
->mode
== rm_oneof
)
6557 obstack_1grow (&irp
, '(');
6558 form_regexp (REGEXP_REPEAT (regexp
)->regexp
);
6559 if (REGEXP_REPEAT (regexp
)->regexp
->mode
== rm_sequence
6560 || REGEXP_REPEAT (regexp
)->regexp
->mode
== rm_allof
6561 || REGEXP_REPEAT (regexp
)->regexp
->mode
== rm_oneof
)
6562 obstack_1grow (&irp
, ')');
6563 sprintf (digits
, "*%d", REGEXP_REPEAT (regexp
)->repeat_num
);
6564 obstack_grow (&irp
, digits
, strlen (digits
));
6569 obstack_grow (&irp
, NOTHING_NAME
, strlen (NOTHING_NAME
));
6577 /* The function returns string representation of REGEXP on IR
6580 regexp_representation (regexp_t regexp
)
6582 form_regexp (regexp
);
6583 obstack_1grow (&irp
, '\0');
6584 return obstack_base (&irp
);
6587 /* The function frees memory allocated for last formed string
6588 representation of regexp. */
6590 finish_regexp_representation (void)
6592 int length
= obstack_object_size (&irp
);
6594 obstack_blank_fast (&irp
, -length
);
6599 /* This page contains code for output PHR (pipeline hazards recognizer). */
6601 /* The function outputs minimal C type which is sufficient for
6602 representation numbers in range min_range_value and
6603 max_range_value. Because host machine and build machine may be
6604 different, we use here minimal values required by ANSI C standard
6605 instead of UCHAR_MAX, SHRT_MAX, SHRT_MIN, etc. This is a good
6609 output_range_type (FILE *f
, long int min_range_value
,
6610 long int max_range_value
)
6612 if (min_range_value
>= 0 && max_range_value
<= 255)
6613 fprintf (f
, "unsigned char");
6614 else if (min_range_value
>= -127 && max_range_value
<= 127)
6615 fprintf (f
, "signed char");
6616 else if (min_range_value
>= 0 && max_range_value
<= 65535)
6617 fprintf (f
, "unsigned short");
6618 else if (min_range_value
>= -32767 && max_range_value
<= 32767)
6619 fprintf (f
, "short");
6624 /* The following macro value is used as value of member
6625 `longest_path_length' of state when we are processing path and the
6626 state on the path. */
6628 #define ON_THE_PATH -2
6630 /* The following recursive function searches for the length of the
6631 longest path starting from STATE which does not contain cycles and
6632 `cycle advance' arcs. */
6635 longest_path_length (state_t state
)
6640 if (state
->longest_path_length
!= UNDEFINED_LONGEST_PATH_LENGTH
)
6642 /* We don't expect the path cycle here. Our graph may contain
6643 only cycles with one state on the path not containing `cycle
6644 advance' arcs -- see comment below. */
6645 gcc_assert (state
->longest_path_length
!= ON_THE_PATH
);
6647 /* We already visited the state. */
6648 return state
->longest_path_length
;
6652 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
6653 /* Ignore cycles containing one state and `cycle advance' arcs. */
6654 if (arc
->to_state
!= state
6655 && (arc
->insn
->insn_reserv_decl
6656 != DECL_INSN_RESERV (advance_cycle_insn_decl
)))
6658 length
= longest_path_length (arc
->to_state
);
6659 if (length
> result
)
6662 state
->longest_path_length
= result
+ 1;
6666 /* The function outputs all initialization values of VECT. */
6668 output_vect (vla_hwint_t vect
)
6671 size_t vect_length
= VEC_length (vect_el_t
, vect
);
6675 if (vect_length
== 0)
6676 fputs ("0 /* This is dummy el because the vect is empty */", output_file
);
6678 for (i
= 0; i
< vect_length
; i
++)
6680 fprintf (output_file
, "%5ld", (long) VEC_index (vect_el_t
, vect
, i
));
6681 if (els_on_line
== 10)
6684 fputs (",\n", output_file
);
6686 else if (i
< vect_length
-1)
6687 fputs (", ", output_file
);
6692 /* The following is name of the structure which represents DFA(s) for
6694 #define CHIP_NAME "DFA_chip"
6696 /* The following is name of member which represents state of a DFA for
6699 output_chip_member_name (FILE *f
, automaton_t automaton
)
6701 if (automaton
->corresponding_automaton_decl
== NULL
)
6702 fprintf (f
, "automaton_state_%d", automaton
->automaton_order_num
);
6704 fprintf (f
, "%s_automaton_state",
6705 automaton
->corresponding_automaton_decl
->name
);
6708 /* The following is name of temporary variable which stores state of a
6711 output_temp_chip_member_name (FILE *f
, automaton_t automaton
)
6714 output_chip_member_name (f
, automaton
);
6717 /* This is name of macro value which is code of pseudo_insn
6718 representing advancing cpu cycle. Its value is used as internal
6719 code unknown insn. */
6720 #define ADVANCE_CYCLE_VALUE_NAME "DFA__ADVANCE_CYCLE"
6722 /* Output name of translate vector for given automaton. */
6724 output_translate_vect_name (FILE *f
, automaton_t automaton
)
6726 if (automaton
->corresponding_automaton_decl
== NULL
)
6727 fprintf (f
, "translate_%d", automaton
->automaton_order_num
);
6729 fprintf (f
, "%s_translate", automaton
->corresponding_automaton_decl
->name
);
6732 /* Output name for simple transition table representation. */
6734 output_trans_full_vect_name (FILE *f
, automaton_t automaton
)
6736 if (automaton
->corresponding_automaton_decl
== NULL
)
6737 fprintf (f
, "transitions_%d", automaton
->automaton_order_num
);
6739 fprintf (f
, "%s_transitions",
6740 automaton
->corresponding_automaton_decl
->name
);
6743 /* Output name of comb vector of the transition table for given
6746 output_trans_comb_vect_name (FILE *f
, automaton_t automaton
)
6748 if (automaton
->corresponding_automaton_decl
== NULL
)
6749 fprintf (f
, "transitions_%d", automaton
->automaton_order_num
);
6751 fprintf (f
, "%s_transitions",
6752 automaton
->corresponding_automaton_decl
->name
);
6755 /* Output name of check vector of the transition table for given
6758 output_trans_check_vect_name (FILE *f
, automaton_t automaton
)
6760 if (automaton
->corresponding_automaton_decl
== NULL
)
6761 fprintf (f
, "check_%d", automaton
->automaton_order_num
);
6763 fprintf (f
, "%s_check", automaton
->corresponding_automaton_decl
->name
);
6766 /* Output name of base vector of the transition table for given
6769 output_trans_base_vect_name (FILE *f
, automaton_t automaton
)
6771 if (automaton
->corresponding_automaton_decl
== NULL
)
6772 fprintf (f
, "base_%d", automaton
->automaton_order_num
);
6774 fprintf (f
, "%s_base", automaton
->corresponding_automaton_decl
->name
);
6777 /* Output name of simple min issue delay table representation. */
6779 output_min_issue_delay_vect_name (FILE *f
, automaton_t automaton
)
6781 if (automaton
->corresponding_automaton_decl
== NULL
)
6782 fprintf (f
, "min_issue_delay_%d", automaton
->automaton_order_num
);
6784 fprintf (f
, "%s_min_issue_delay",
6785 automaton
->corresponding_automaton_decl
->name
);
6788 /* Output name of deadlock vector for given automaton. */
6790 output_dead_lock_vect_name (FILE *f
, automaton_t automaton
)
6792 if (automaton
->corresponding_automaton_decl
== NULL
)
6793 fprintf (f
, "dead_lock_%d", automaton
->automaton_order_num
);
6795 fprintf (f
, "%s_dead_lock", automaton
->corresponding_automaton_decl
->name
);
6798 /* Output name of reserved units table for AUTOMATON into file F. */
6800 output_reserved_units_table_name (FILE *f
, automaton_t automaton
)
6802 if (automaton
->corresponding_automaton_decl
== NULL
)
6803 fprintf (f
, "reserved_units_%d", automaton
->automaton_order_num
);
6805 fprintf (f
, "%s_reserved_units",
6806 automaton
->corresponding_automaton_decl
->name
);
6809 /* Name of the PHR interface macro. */
6810 #define CPU_UNITS_QUERY_MACRO_NAME "CPU_UNITS_QUERY"
6812 /* Names of an internal functions: */
6813 #define INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME "internal_min_issue_delay"
6815 /* This is external type of DFA(s) state. */
6816 #define STATE_TYPE_NAME "state_t"
6818 #define INTERNAL_TRANSITION_FUNC_NAME "internal_state_transition"
6820 #define INTERNAL_RESET_FUNC_NAME "internal_reset"
6822 #define INTERNAL_DEAD_LOCK_FUNC_NAME "internal_state_dead_lock_p"
6824 #define INTERNAL_INSN_LATENCY_FUNC_NAME "internal_insn_latency"
6826 /* Name of cache of insn dfa codes. */
6827 #define DFA_INSN_CODES_VARIABLE_NAME "dfa_insn_codes"
6829 /* Name of length of cache of insn dfa codes. */
6830 #define DFA_INSN_CODES_LENGTH_VARIABLE_NAME "dfa_insn_codes_length"
6832 /* Names of the PHR interface functions: */
6833 #define SIZE_FUNC_NAME "state_size"
6835 #define TRANSITION_FUNC_NAME "state_transition"
6837 #define MIN_ISSUE_DELAY_FUNC_NAME "min_issue_delay"
6839 #define MIN_INSN_CONFLICT_DELAY_FUNC_NAME "min_insn_conflict_delay"
6841 #define DEAD_LOCK_FUNC_NAME "state_dead_lock_p"
6843 #define RESET_FUNC_NAME "state_reset"
6845 #define INSN_LATENCY_FUNC_NAME "insn_latency"
6847 #define PRINT_RESERVATION_FUNC_NAME "print_reservation"
6849 #define GET_CPU_UNIT_CODE_FUNC_NAME "get_cpu_unit_code"
6851 #define CPU_UNIT_RESERVATION_P_FUNC_NAME "cpu_unit_reservation_p"
6853 #define DFA_CLEAN_INSN_CACHE_FUNC_NAME "dfa_clean_insn_cache"
6855 #define DFA_START_FUNC_NAME "dfa_start"
6857 #define DFA_FINISH_FUNC_NAME "dfa_finish"
6859 /* Names of parameters of the PHR interface functions. */
6860 #define STATE_NAME "state"
6862 #define INSN_PARAMETER_NAME "insn"
6864 #define INSN2_PARAMETER_NAME "insn2"
6866 #define CHIP_PARAMETER_NAME "chip"
6868 #define FILE_PARAMETER_NAME "f"
6870 #define CPU_UNIT_NAME_PARAMETER_NAME "cpu_unit_name"
6872 #define CPU_CODE_PARAMETER_NAME "cpu_unit_code"
6874 /* Names of the variables whose values are internal insn code of rtx
6876 #define INTERNAL_INSN_CODE_NAME "insn_code"
6878 #define INTERNAL_INSN2_CODE_NAME "insn2_code"
6880 /* Names of temporary variables in some functions. */
6881 #define TEMPORARY_VARIABLE_NAME "temp"
6883 #define I_VARIABLE_NAME "i"
6885 /* Name of result variable in some functions. */
6886 #define RESULT_VARIABLE_NAME "res"
6888 /* Name of function (attribute) to translate insn into internal insn
6890 #define INTERNAL_DFA_INSN_CODE_FUNC_NAME "internal_dfa_insn_code"
6892 /* Name of function (attribute) to translate insn into internal insn
6893 code with caching. */
6894 #define DFA_INSN_CODE_FUNC_NAME "dfa_insn_code"
6896 /* Output C type which is used for representation of codes of states
6899 output_state_member_type (FILE *f
, automaton_t automaton
)
6901 output_range_type (f
, 0, automaton
->achieved_states_num
);
6904 /* Output definition of the structure representing current DFA(s)
6907 output_chip_definitions (void)
6909 automaton_t automaton
;
6911 fprintf (output_file
, "struct %s\n{\n", CHIP_NAME
);
6912 for (automaton
= description
->first_automaton
;
6914 automaton
= automaton
->next_automaton
)
6916 fprintf (output_file
, " ");
6917 output_state_member_type (output_file
, automaton
);
6918 fprintf (output_file
, " ");
6919 output_chip_member_name (output_file
, automaton
);
6920 fprintf (output_file
, ";\n");
6922 fprintf (output_file
, "};\n\n");
6924 fprintf (output_file
, "static struct %s %s;\n\n", CHIP_NAME
, CHIP_NAME
);
6929 /* The function outputs translate vector of internal insn code into
6930 insn equivalence class number. The equivalence class number is
6931 used to access to table and vectors representing DFA(s). */
6933 output_translate_vect (automaton_t automaton
)
6937 vla_hwint_t translate_vect
;
6939 translate_vect
= VEC_alloc (vect_el_t
,heap
, description
->insns_num
);
6941 for (insn_value
= 0; insn_value
< description
->insns_num
; insn_value
++)
6942 /* Undefined value */
6943 VEC_quick_push (vect_el_t
, translate_vect
,
6944 automaton
->insn_equiv_classes_num
);
6946 for (ainsn
= automaton
->ainsn_list
; ainsn
!= NULL
; ainsn
= ainsn
->next_ainsn
)
6947 VEC_replace (vect_el_t
, translate_vect
,
6948 ainsn
->insn_reserv_decl
->insn_num
,
6949 ainsn
->insn_equiv_class_num
);
6951 fprintf (output_file
,
6952 "/* Vector translating external insn codes to internal ones.*/\n");
6953 fprintf (output_file
, "static const ");
6954 output_range_type (output_file
, 0, automaton
->insn_equiv_classes_num
);
6955 fprintf (output_file
, " ");
6956 output_translate_vect_name (output_file
, automaton
);
6957 fprintf (output_file
, "[] ATTRIBUTE_UNUSED = {\n");
6958 output_vect (translate_vect
);
6959 fprintf (output_file
, "};\n\n");
6960 VEC_free (vect_el_t
,heap
, translate_vect
);
6963 /* The value in a table state x ainsn -> something which represents
6965 static int undefined_vect_el_value
;
6967 /* The following function returns nonzero value if the best
6968 representation of the table is comb vector. */
6970 comb_vect_p (state_ainsn_table_t tab
)
6972 return (2 * VEC_length (vect_el_t
, tab
->full_vect
)
6973 > 5 * VEC_length (vect_el_t
, tab
->comb_vect
));
6976 /* The following function creates new table for AUTOMATON. */
6977 static state_ainsn_table_t
6978 create_state_ainsn_table (automaton_t automaton
)
6980 state_ainsn_table_t tab
;
6981 int full_vect_length
;
6984 tab
= create_node (sizeof (struct state_ainsn_table
));
6985 tab
->automaton
= automaton
;
6987 tab
->comb_vect
= VEC_alloc (vect_el_t
,heap
, 10000);
6988 tab
->check_vect
= VEC_alloc (vect_el_t
,heap
, 10000);
6991 VEC_safe_grow (vect_el_t
,heap
, tab
->base_vect
,
6992 automaton
->achieved_states_num
);
6994 full_vect_length
= (automaton
->insn_equiv_classes_num
6995 * automaton
->achieved_states_num
);
6996 tab
->full_vect
= VEC_alloc (vect_el_t
,heap
, full_vect_length
);
6997 for (i
= 0; i
< full_vect_length
; i
++)
6998 VEC_quick_push (vect_el_t
, tab
->full_vect
, undefined_vect_el_value
);
7000 tab
->min_base_vect_el_value
= 0;
7001 tab
->max_base_vect_el_value
= 0;
7002 tab
->min_comb_vect_el_value
= 0;
7003 tab
->max_comb_vect_el_value
= 0;
7007 /* The following function outputs the best C representation of the
7008 table TAB of given TABLE_NAME. */
7010 output_state_ainsn_table (state_ainsn_table_t tab
, const char *table_name
,
7011 void (*output_full_vect_name_func
) (FILE *, automaton_t
),
7012 void (*output_comb_vect_name_func
) (FILE *, automaton_t
),
7013 void (*output_check_vect_name_func
) (FILE *, automaton_t
),
7014 void (*output_base_vect_name_func
) (FILE *, automaton_t
))
7016 if (!comb_vect_p (tab
))
7018 fprintf (output_file
, "/* Vector for %s. */\n", table_name
);
7019 fprintf (output_file
, "static const ");
7020 output_range_type (output_file
, tab
->min_comb_vect_el_value
,
7021 tab
->max_comb_vect_el_value
);
7022 fprintf (output_file
, " ");
7023 (*output_full_vect_name_func
) (output_file
, tab
->automaton
);
7024 fprintf (output_file
, "[] ATTRIBUTE_UNUSED = {\n");
7025 output_vect (tab
->full_vect
);
7026 fprintf (output_file
, "};\n\n");
7030 fprintf (output_file
, "/* Comb vector for %s. */\n", table_name
);
7031 fprintf (output_file
, "static const ");
7032 output_range_type (output_file
, tab
->min_comb_vect_el_value
,
7033 tab
->max_comb_vect_el_value
);
7034 fprintf (output_file
, " ");
7035 (*output_comb_vect_name_func
) (output_file
, tab
->automaton
);
7036 fprintf (output_file
, "[] ATTRIBUTE_UNUSED = {\n");
7037 output_vect (tab
->comb_vect
);
7038 fprintf (output_file
, "};\n\n");
7039 fprintf (output_file
, "/* Check vector for %s. */\n", table_name
);
7040 fprintf (output_file
, "static const ");
7041 output_range_type (output_file
, 0, tab
->automaton
->achieved_states_num
);
7042 fprintf (output_file
, " ");
7043 (*output_check_vect_name_func
) (output_file
, tab
->automaton
);
7044 fprintf (output_file
, "[] = {\n");
7045 output_vect (tab
->check_vect
);
7046 fprintf (output_file
, "};\n\n");
7047 fprintf (output_file
, "/* Base vector for %s. */\n", table_name
);
7048 fprintf (output_file
, "static const ");
7049 output_range_type (output_file
, tab
->min_base_vect_el_value
,
7050 tab
->max_base_vect_el_value
);
7051 fprintf (output_file
, " ");
7052 (*output_base_vect_name_func
) (output_file
, tab
->automaton
);
7053 fprintf (output_file
, "[] = {\n");
7054 output_vect (tab
->base_vect
);
7055 fprintf (output_file
, "};\n\n");
7059 /* The following function adds vector VECT to table TAB as its line
7060 with number VECT_NUM. */
7062 add_vect (state_ainsn_table_t tab
, int vect_num
, vla_hwint_t vect
)
7065 size_t real_vect_length
;
7066 int comb_vect_index
;
7067 int comb_vect_els_num
;
7069 int first_unempty_vect_index
;
7070 int additional_els_num
;
7074 unsigned long vect_mask
, comb_vect_mask
;
7076 vect_length
= VEC_length (vect_el_t
, vect
);
7077 gcc_assert (vect_length
);
7078 gcc_assert (VEC_last (vect_el_t
, vect
) != undefined_vect_el_value
);
7079 real_vect_length
= tab
->automaton
->insn_equiv_classes_num
;
7080 /* Form full vector in the table: */
7082 size_t full_base
= tab
->automaton
->insn_equiv_classes_num
* vect_num
;
7083 if (VEC_length (vect_el_t
, tab
->full_vect
) < full_base
+ vect_length
)
7084 VEC_safe_grow (vect_el_t
,heap
, tab
->full_vect
,
7085 full_base
+ vect_length
);
7086 for (i
= 0; i
< vect_length
; i
++)
7087 VEC_replace (vect_el_t
, tab
->full_vect
, full_base
+ i
,
7088 VEC_index (vect_el_t
, vect
, i
));
7090 /* Form comb vector in the table: */
7091 gcc_assert (VEC_length (vect_el_t
, tab
->comb_vect
)
7092 == VEC_length (vect_el_t
, tab
->check_vect
));
7094 comb_vect_els_num
= VEC_length (vect_el_t
, tab
->comb_vect
);
7095 for (first_unempty_vect_index
= 0;
7096 first_unempty_vect_index
< vect_length
;
7097 first_unempty_vect_index
++)
7098 if (VEC_index (vect_el_t
, vect
, first_unempty_vect_index
)
7099 != undefined_vect_el_value
)
7102 /* Search for the place in comb vect for the inserted vect. */
7105 if (vect_length
- first_unempty_vect_index
>= SIZEOF_LONG
* CHAR_BIT
)
7107 for (comb_vect_index
= 0;
7108 comb_vect_index
< comb_vect_els_num
;
7111 for (vect_index
= first_unempty_vect_index
;
7112 vect_index
< vect_length
7113 && vect_index
+ comb_vect_index
< comb_vect_els_num
;
7115 if (VEC_index (vect_el_t
, vect
, vect_index
)
7116 != undefined_vect_el_value
7117 && (VEC_index (vect_el_t
, tab
->comb_vect
,
7118 vect_index
+ comb_vect_index
)
7119 != undefined_vect_el_value
))
7121 if (vect_index
>= vect_length
7122 || vect_index
+ comb_vect_index
>= comb_vect_els_num
)
7130 for (vect_index
= first_unempty_vect_index
;
7131 vect_index
< vect_length
;
7134 vect_mask
= vect_mask
<< 1;
7135 if (VEC_index (vect_el_t
, vect
, vect_index
) != undefined_vect_el_value
)
7139 /* Search for the place in comb vect for the inserted vect. */
7140 comb_vect_index
= 0;
7141 if (comb_vect_els_num
== 0)
7145 for (vect_index
= first_unempty_vect_index
;
7146 vect_index
< vect_length
&& vect_index
< comb_vect_els_num
;
7149 comb_vect_mask
<<= 1;
7150 if (vect_index
+ comb_vect_index
< comb_vect_els_num
7151 && VEC_index (vect_el_t
, tab
->comb_vect
, vect_index
+ comb_vect_index
)
7152 != undefined_vect_el_value
)
7153 comb_vect_mask
|= 1;
7155 if ((vect_mask
& comb_vect_mask
) == 0)
7158 for (comb_vect_index
= 1, i
= vect_length
; i
< comb_vect_els_num
;
7159 comb_vect_index
++, i
++)
7161 comb_vect_mask
= (comb_vect_mask
<< 1) | 1;
7162 comb_vect_mask
^= (VEC_index (vect_el_t
, tab
->comb_vect
, i
)
7163 == undefined_vect_el_value
);
7164 if ((vect_mask
& comb_vect_mask
) == 0)
7167 for ( ; comb_vect_index
< comb_vect_els_num
; comb_vect_index
++)
7169 comb_vect_mask
<<= 1;
7170 if ((vect_mask
& comb_vect_mask
) == 0)
7175 /* Slot was found. */
7176 additional_els_num
= comb_vect_index
+ real_vect_length
- comb_vect_els_num
;
7177 if (additional_els_num
< 0)
7178 additional_els_num
= 0;
7179 /* Expand comb and check vectors. */
7180 vect_el
= undefined_vect_el_value
;
7181 no_state_value
= tab
->automaton
->achieved_states_num
;
7182 while (additional_els_num
> 0)
7184 VEC_safe_push (vect_el_t
,heap
, tab
->comb_vect
, vect_el
);
7185 VEC_safe_push (vect_el_t
,heap
, tab
->check_vect
, no_state_value
);
7186 additional_els_num
--;
7188 gcc_assert (VEC_length (vect_el_t
, tab
->comb_vect
)
7189 >= comb_vect_index
+ real_vect_length
);
7190 /* Fill comb and check vectors. */
7191 for (vect_index
= 0; vect_index
< vect_length
; vect_index
++)
7192 if (VEC_index (vect_el_t
, vect
, vect_index
) != undefined_vect_el_value
)
7194 vect_el_t x
= VEC_index (vect_el_t
, vect
, vect_index
);
7195 gcc_assert (VEC_index (vect_el_t
, tab
->comb_vect
,
7196 comb_vect_index
+ vect_index
)
7197 == undefined_vect_el_value
);
7198 gcc_assert (x
>= 0);
7199 if (tab
->max_comb_vect_el_value
< x
)
7200 tab
->max_comb_vect_el_value
= x
;
7201 if (tab
->min_comb_vect_el_value
> x
)
7202 tab
->min_comb_vect_el_value
= x
;
7203 VEC_replace (vect_el_t
, tab
->comb_vect
,
7204 comb_vect_index
+ vect_index
, x
);
7205 VEC_replace (vect_el_t
, tab
->check_vect
,
7206 comb_vect_index
+ vect_index
, vect_num
);
7208 if (tab
->max_comb_vect_el_value
< undefined_vect_el_value
)
7209 tab
->max_comb_vect_el_value
= undefined_vect_el_value
;
7210 if (tab
->min_comb_vect_el_value
> undefined_vect_el_value
)
7211 tab
->min_comb_vect_el_value
= undefined_vect_el_value
;
7212 if (tab
->max_base_vect_el_value
< comb_vect_index
)
7213 tab
->max_base_vect_el_value
= comb_vect_index
;
7214 if (tab
->min_base_vect_el_value
> comb_vect_index
)
7215 tab
->min_base_vect_el_value
= comb_vect_index
;
7217 VEC_replace (vect_el_t
, tab
->base_vect
, vect_num
, comb_vect_index
);
7220 /* Return number of out arcs of STATE. */
7222 out_state_arcs_num (state_t state
)
7228 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
7230 gcc_assert (arc
->insn
);
7231 if (arc
->insn
->first_ainsn_with_given_equivalence_num
)
7237 /* Compare number of possible transitions from the states. */
7239 compare_transition_els_num (const void *state_ptr_1
,
7240 const void *state_ptr_2
)
7242 int transition_els_num_1
;
7243 int transition_els_num_2
;
7245 transition_els_num_1
= out_state_arcs_num (*(state_t
*) state_ptr_1
);
7246 transition_els_num_2
= out_state_arcs_num (*(state_t
*) state_ptr_2
);
7247 if (transition_els_num_1
< transition_els_num_2
)
7249 else if (transition_els_num_1
== transition_els_num_2
)
7255 /* The function adds element EL_VALUE to vector VECT for a table state
7258 add_vect_el (vla_hwint_t
*vect
, ainsn_t ainsn
, int el_value
)
7260 int equiv_class_num
;
7264 equiv_class_num
= ainsn
->insn_equiv_class_num
;
7265 for (vect_index
= VEC_length (vect_el_t
, *vect
);
7266 vect_index
<= equiv_class_num
;
7268 VEC_safe_push (vect_el_t
,heap
, *vect
, undefined_vect_el_value
);
7269 VEC_replace (vect_el_t
, *vect
, equiv_class_num
, el_value
);
7272 /* This is for forming vector of states of an automaton. */
7273 static VEC(state_t
,heap
) *output_states_vect
;
7275 /* The function is called by function pass_states. The function adds
7276 STATE to `output_states_vect'. */
7278 add_states_vect_el (state_t state
)
7280 VEC_safe_push (state_t
,heap
, output_states_vect
, state
);
7283 /* Form and output vectors (comb, check, base or full vector)
7284 representing transition table of AUTOMATON. */
7286 output_trans_table (automaton_t automaton
)
7290 vla_hwint_t transition_vect
= 0;
7292 undefined_vect_el_value
= automaton
->achieved_states_num
;
7293 automaton
->trans_table
= create_state_ainsn_table (automaton
);
7294 /* Create vect of pointers to states ordered by num of transitions
7295 from the state (state with the maximum num is the first). */
7296 output_states_vect
= 0;
7297 pass_states (automaton
, add_states_vect_el
);
7298 qsort (VEC_address (state_t
, output_states_vect
),
7299 VEC_length (state_t
, output_states_vect
),
7300 sizeof (state_t
), compare_transition_els_num
);
7302 for (i
= 0; i
< VEC_length (state_t
, output_states_vect
); i
++)
7304 VEC_truncate (vect_el_t
, transition_vect
, 0);
7305 for (arc
= first_out_arc (VEC_index (state_t
, output_states_vect
, i
));
7307 arc
= next_out_arc (arc
))
7309 gcc_assert (arc
->insn
);
7310 if (arc
->insn
->first_ainsn_with_given_equivalence_num
)
7311 add_vect_el (&transition_vect
, arc
->insn
,
7312 arc
->to_state
->order_state_num
);
7314 add_vect (automaton
->trans_table
,
7315 VEC_index (state_t
, output_states_vect
, i
)->order_state_num
,
7318 output_state_ainsn_table
7319 (automaton
->trans_table
, "state transitions",
7320 output_trans_full_vect_name
, output_trans_comb_vect_name
,
7321 output_trans_check_vect_name
, output_trans_base_vect_name
);
7323 VEC_free (state_t
,heap
, output_states_vect
);
7324 VEC_free (vect_el_t
,heap
, transition_vect
);
7327 /* The current number of passing states to find minimal issue delay
7328 value for an ainsn and state. */
7329 static int curr_state_pass_num
;
7331 /* This recursive function passes states to find minimal issue delay
7332 value for AINSN. The state being visited is STATE. The function
7333 returns minimal issue delay value for AINSN in STATE or -1 if we
7334 enter into a loop. */
7336 min_issue_delay_pass_states (state_t state
, ainsn_t ainsn
)
7339 int min_insn_issue_delay
, insn_issue_delay
;
7341 if (state
->state_pass_num
== curr_state_pass_num
7342 || state
->min_insn_issue_delay
!= -1)
7343 /* We've entered into a loop or already have the correct value for
7344 given state and ainsn. */
7345 return state
->min_insn_issue_delay
;
7346 state
->state_pass_num
= curr_state_pass_num
;
7347 min_insn_issue_delay
= -1;
7348 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
7349 if (arc
->insn
== ainsn
)
7351 min_insn_issue_delay
= 0;
7356 insn_issue_delay
= min_issue_delay_pass_states (arc
->to_state
, ainsn
);
7357 if (insn_issue_delay
!= -1)
7359 if (arc
->insn
->insn_reserv_decl
7360 == DECL_INSN_RESERV (advance_cycle_insn_decl
))
7362 if (min_insn_issue_delay
== -1
7363 || min_insn_issue_delay
> insn_issue_delay
)
7365 min_insn_issue_delay
= insn_issue_delay
;
7366 if (insn_issue_delay
== 0)
7371 return min_insn_issue_delay
;
7374 /* The function searches minimal issue delay value for AINSN in STATE.
7375 The function can return negative value if we can not issue AINSN. We
7376 will report about it later. */
7378 min_issue_delay (state_t state
, ainsn_t ainsn
)
7380 curr_state_pass_num
++;
7381 state
->min_insn_issue_delay
= min_issue_delay_pass_states (state
, ainsn
);
7382 return state
->min_insn_issue_delay
;
7385 /* The function initiates code for finding minimal issue delay values.
7386 It should be called only once. */
7388 initiate_min_issue_delay_pass_states (void)
7390 curr_state_pass_num
= 0;
7393 /* Form and output vectors representing minimal issue delay table of
7394 AUTOMATON. The table is state x ainsn -> minimal issue delay of
7397 output_min_issue_delay_table (automaton_t automaton
)
7399 vla_hwint_t min_issue_delay_vect
;
7400 vla_hwint_t compressed_min_issue_delay_vect
;
7401 vect_el_t min_delay
;
7403 size_t i
, min_issue_delay_len
;
7404 size_t compressed_min_issue_delay_len
;
7407 /* Create vect of pointers to states ordered by num of transitions
7408 from the state (state with the maximum num is the first). */
7409 output_states_vect
= 0;
7410 pass_states (automaton
, add_states_vect_el
);
7412 min_issue_delay_len
= (VEC_length (state_t
, output_states_vect
)
7413 * automaton
->insn_equiv_classes_num
);
7414 min_issue_delay_vect
= VEC_alloc (vect_el_t
,heap
, min_issue_delay_len
);
7415 for (i
= 0; i
< min_issue_delay_len
; i
++)
7416 VEC_quick_push (vect_el_t
, min_issue_delay_vect
, 0);
7418 automaton
->max_min_delay
= 0;
7419 for (ainsn
= automaton
->ainsn_list
; ainsn
!= NULL
; ainsn
= ainsn
->next_ainsn
)
7420 if (ainsn
->first_ainsn_with_given_equivalence_num
)
7422 for (i
= 0; i
< VEC_length (state_t
, output_states_vect
); i
++)
7423 VEC_index (state_t
, output_states_vect
, i
)->min_insn_issue_delay
= -1;
7424 for (i
= 0; i
< VEC_length (state_t
, output_states_vect
); i
++)
7426 state_t s
= VEC_index (state_t
, output_states_vect
, i
);
7427 min_delay
= min_issue_delay (s
, ainsn
);
7428 if (automaton
->max_min_delay
< min_delay
)
7429 automaton
->max_min_delay
= min_delay
;
7430 VEC_replace (vect_el_t
, min_issue_delay_vect
,
7432 * automaton
->insn_equiv_classes_num
7433 + ainsn
->insn_equiv_class_num
,
7437 fprintf (output_file
, "/* Vector of min issue delay of insns. */\n");
7438 fprintf (output_file
, "static const ");
7439 output_range_type (output_file
, 0, automaton
->max_min_delay
);
7440 fprintf (output_file
, " ");
7441 output_min_issue_delay_vect_name (output_file
, automaton
);
7442 fprintf (output_file
, "[] ATTRIBUTE_UNUSED = {\n");
7443 /* Compress the vector. */
7444 if (automaton
->max_min_delay
< 2)
7446 else if (automaton
->max_min_delay
< 4)
7448 else if (automaton
->max_min_delay
< 16)
7452 automaton
->min_issue_delay_table_compression_factor
= cfactor
;
7454 compressed_min_issue_delay_len
= (min_issue_delay_len
+cfactor
-1) / cfactor
;
7455 compressed_min_issue_delay_vect
7456 = VEC_alloc (vect_el_t
,heap
, compressed_min_issue_delay_len
);
7458 for (i
= 0; i
< compressed_min_issue_delay_len
; i
++)
7459 VEC_quick_push (vect_el_t
, compressed_min_issue_delay_vect
, 0);
7461 for (i
= 0; i
< min_issue_delay_len
; i
++)
7463 size_t ci
= i
/ cfactor
;
7464 vect_el_t x
= VEC_index (vect_el_t
, min_issue_delay_vect
, i
);
7465 vect_el_t cx
= VEC_index (vect_el_t
, compressed_min_issue_delay_vect
, ci
);
7467 cx
|= x
<< (8 - (i
% cfactor
+ 1) * (8 / cfactor
));
7468 VEC_replace (vect_el_t
, compressed_min_issue_delay_vect
, ci
, cx
);
7470 output_vect (compressed_min_issue_delay_vect
);
7471 fprintf (output_file
, "};\n\n");
7472 VEC_free (state_t
,heap
, output_states_vect
);
7473 VEC_free (vect_el_t
,heap
, min_issue_delay_vect
);
7474 VEC_free (vect_el_t
,heap
, compressed_min_issue_delay_vect
);
7477 /* Form and output vector representing the locked states of
7480 output_dead_lock_vect (automaton_t automaton
)
7484 vla_hwint_t dead_lock_vect
= 0;
7486 /* Create vect of pointers to states ordered by num of
7487 transitions from the state (state with the maximum num is the
7489 automaton
->locked_states
= 0;
7490 output_states_vect
= 0;
7491 pass_states (automaton
, add_states_vect_el
);
7493 VEC_safe_grow (vect_el_t
,heap
, dead_lock_vect
,
7494 VEC_length (state_t
, output_states_vect
));
7495 for (i
= 0; i
< VEC_length (state_t
, output_states_vect
); i
++)
7497 state_t s
= VEC_index (state_t
, output_states_vect
, i
);
7498 arc
= first_out_arc (s
);
7500 if (next_out_arc (arc
) == NULL
7501 && (arc
->insn
->insn_reserv_decl
7502 == DECL_INSN_RESERV (advance_cycle_insn_decl
)))
7504 VEC_replace (vect_el_t
, dead_lock_vect
, s
->order_state_num
, 1);
7505 automaton
->locked_states
++;
7508 VEC_replace (vect_el_t
, dead_lock_vect
, s
->order_state_num
, 0);
7510 if (automaton
->locked_states
== 0)
7513 fprintf (output_file
, "/* Vector for locked state flags. */\n");
7514 fprintf (output_file
, "static const ");
7515 output_range_type (output_file
, 0, 1);
7516 fprintf (output_file
, " ");
7517 output_dead_lock_vect_name (output_file
, automaton
);
7518 fprintf (output_file
, "[] = {\n");
7519 output_vect (dead_lock_vect
);
7520 fprintf (output_file
, "};\n\n");
7521 VEC_free (state_t
,heap
, output_states_vect
);
7522 VEC_free (vect_el_t
,heap
, dead_lock_vect
);
7525 /* Form and output vector representing reserved units of the states of
7528 output_reserved_units_table (automaton_t automaton
)
7530 vla_hwint_t reserved_units_table
= 0;
7531 int state_byte_size
;
7532 int reserved_units_size
;
7536 if (description
->query_units_num
== 0)
7539 /* Create vect of pointers to states. */
7540 output_states_vect
= 0;
7541 pass_states (automaton
, add_states_vect_el
);
7542 /* Create vector. */
7543 state_byte_size
= (description
->query_units_num
+ 7) / 8;
7544 reserved_units_size
= (VEC_length (state_t
, output_states_vect
)
7547 reserved_units_table
= VEC_alloc (vect_el_t
,heap
, reserved_units_size
);
7549 for (i
= 0; i
< reserved_units_size
; i
++)
7550 VEC_quick_push (vect_el_t
, reserved_units_table
, 0);
7551 for (n
= 0; n
< VEC_length (state_t
, output_states_vect
); n
++)
7553 state_t s
= VEC_index (state_t
, output_states_vect
, n
);
7554 for (i
= 0; i
< description
->units_num
; i
++)
7555 if (units_array
[i
]->query_p
7556 && first_cycle_unit_presence (s
, i
))
7558 int ri
= (s
->order_state_num
* state_byte_size
7559 + units_array
[i
]->query_num
/ 8);
7560 vect_el_t x
= VEC_index (vect_el_t
, reserved_units_table
, ri
);
7562 x
+= 1 << (units_array
[i
]->query_num
% 8);
7563 VEC_replace (vect_el_t
, reserved_units_table
, ri
, x
);
7566 fprintf (output_file
, "\n#if %s\n", CPU_UNITS_QUERY_MACRO_NAME
);
7567 fprintf (output_file
, "/* Vector for reserved units of states. */\n");
7568 fprintf (output_file
, "static const ");
7569 output_range_type (output_file
, 0, 255);
7570 fprintf (output_file
, " ");
7571 output_reserved_units_table_name (output_file
, automaton
);
7572 fprintf (output_file
, "[] = {\n");
7573 output_vect (reserved_units_table
);
7574 fprintf (output_file
, "};\n#endif /* #if %s */\n\n",
7575 CPU_UNITS_QUERY_MACRO_NAME
);
7577 VEC_free (state_t
,heap
, output_states_vect
);
7578 VEC_free (vect_el_t
,heap
, reserved_units_table
);
7581 /* The function outputs all tables representing DFA(s) used for fast
7582 pipeline hazards recognition. */
7584 output_tables (void)
7586 automaton_t automaton
;
7588 initiate_min_issue_delay_pass_states ();
7589 for (automaton
= description
->first_automaton
;
7591 automaton
= automaton
->next_automaton
)
7593 output_translate_vect (automaton
);
7594 output_trans_table (automaton
);
7595 output_min_issue_delay_table (automaton
);
7596 output_dead_lock_vect (automaton
);
7597 output_reserved_units_table (automaton
);
7599 fprintf (output_file
, "\n#define %s %d\n\n", ADVANCE_CYCLE_VALUE_NAME
,
7600 DECL_INSN_RESERV (advance_cycle_insn_decl
)->insn_num
);
7603 /* The function outputs definition and value of PHR interface variable
7604 `max_insn_queue_index'. Its value is not less than maximal queue
7605 length needed for the insn scheduler. */
7607 output_max_insn_queue_index_def (void)
7609 int i
, max
, latency
;
7612 max
= description
->max_insn_reserv_cycles
;
7613 for (i
= 0; i
< description
->decls_num
; i
++)
7615 decl
= description
->decls
[i
];
7616 if (decl
->mode
== dm_insn_reserv
&& decl
!= advance_cycle_insn_decl
)
7618 latency
= DECL_INSN_RESERV (decl
)->default_latency
;
7622 else if (decl
->mode
== dm_bypass
)
7624 latency
= DECL_BYPASS (decl
)->latency
;
7629 for (i
= 0; (1 << i
) <= max
; i
++)
7631 gcc_assert (i
>= 0);
7632 fprintf (output_file
, "\nconst int max_insn_queue_index = %d;\n\n",
7636 /* The function outputs switch cases for insn reservations using
7637 function *output_automata_list_code. */
7639 output_insn_code_cases (void (*output_automata_list_code
)
7640 (automata_list_el_t
))
7645 for (i
= 0; i
< description
->decls_num
; i
++)
7647 decl
= description
->decls
[i
];
7648 if (decl
->mode
== dm_insn_reserv
)
7649 DECL_INSN_RESERV (decl
)->processed_p
= FALSE
;
7651 for (i
= 0; i
< description
->decls_num
; i
++)
7653 decl
= description
->decls
[i
];
7654 if (decl
->mode
== dm_insn_reserv
7655 && !DECL_INSN_RESERV (decl
)->processed_p
)
7657 for (j
= i
; j
< description
->decls_num
; j
++)
7659 decl2
= description
->decls
[j
];
7660 if (decl2
->mode
== dm_insn_reserv
7661 && (DECL_INSN_RESERV (decl2
)->important_automata_list
7662 == DECL_INSN_RESERV (decl
)->important_automata_list
))
7664 DECL_INSN_RESERV (decl2
)->processed_p
= TRUE
;
7665 fprintf (output_file
, " case %d: /* %s */\n",
7666 DECL_INSN_RESERV (decl2
)->insn_num
,
7667 DECL_INSN_RESERV (decl2
)->name
);
7670 (*output_automata_list_code
)
7671 (DECL_INSN_RESERV (decl
)->important_automata_list
);
7677 /* The function outputs a code for evaluation of a minimal delay of
7678 issue of insns which have reservations in given AUTOMATA_LIST. */
7680 output_automata_list_min_issue_delay_code (automata_list_el_t automata_list
)
7682 automata_list_el_t el
;
7683 automaton_t automaton
;
7685 for (el
= automata_list
; el
!= NULL
; el
= el
->next_automata_list_el
)
7687 automaton
= el
->automaton
;
7688 fprintf (output_file
, "\n %s = ", TEMPORARY_VARIABLE_NAME
);
7689 output_min_issue_delay_vect_name (output_file
, automaton
);
7690 fprintf (output_file
,
7691 (automaton
->min_issue_delay_table_compression_factor
!= 1
7693 output_translate_vect_name (output_file
, automaton
);
7694 fprintf (output_file
, " [%s] + ", INTERNAL_INSN_CODE_NAME
);
7695 fprintf (output_file
, "%s->", CHIP_PARAMETER_NAME
);
7696 output_chip_member_name (output_file
, automaton
);
7697 fprintf (output_file
, " * %d", automaton
->insn_equiv_classes_num
);
7698 if (automaton
->min_issue_delay_table_compression_factor
== 1)
7699 fprintf (output_file
, "];\n");
7702 fprintf (output_file
, ") / %d];\n",
7703 automaton
->min_issue_delay_table_compression_factor
);
7704 fprintf (output_file
, " %s = (%s >> (8 - (",
7705 TEMPORARY_VARIABLE_NAME
, TEMPORARY_VARIABLE_NAME
);
7706 output_translate_vect_name (output_file
, automaton
);
7708 (output_file
, " [%s] %% %d + 1) * %d)) & %d;\n",
7709 INTERNAL_INSN_CODE_NAME
,
7710 automaton
->min_issue_delay_table_compression_factor
,
7711 8 / automaton
->min_issue_delay_table_compression_factor
,
7712 (1 << (8 / automaton
->min_issue_delay_table_compression_factor
))
7715 if (el
== automata_list
)
7716 fprintf (output_file
, " %s = %s;\n",
7717 RESULT_VARIABLE_NAME
, TEMPORARY_VARIABLE_NAME
);
7720 fprintf (output_file
, " if (%s > %s)\n",
7721 TEMPORARY_VARIABLE_NAME
, RESULT_VARIABLE_NAME
);
7722 fprintf (output_file
, " %s = %s;\n",
7723 RESULT_VARIABLE_NAME
, TEMPORARY_VARIABLE_NAME
);
7726 fprintf (output_file
, " break;\n\n");
7729 /* Output function `internal_min_issue_delay'. */
7731 output_internal_min_issue_delay_func (void)
7733 fprintf (output_file
,
7734 "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
7735 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
7736 CHIP_NAME
, CHIP_PARAMETER_NAME
);
7737 fprintf (output_file
, "{\n int %s ATTRIBUTE_UNUSED;\n int %s = -1;\n",
7738 TEMPORARY_VARIABLE_NAME
, RESULT_VARIABLE_NAME
);
7739 fprintf (output_file
, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME
);
7740 output_insn_code_cases (output_automata_list_min_issue_delay_code
);
7741 fprintf (output_file
,
7742 "\n default:\n %s = -1;\n break;\n }\n",
7743 RESULT_VARIABLE_NAME
);
7744 fprintf (output_file
, " return %s;\n", RESULT_VARIABLE_NAME
);
7745 fprintf (output_file
, "}\n\n");
7748 /* The function outputs a code changing state after issue of insns
7749 which have reservations in given AUTOMATA_LIST. */
7751 output_automata_list_transition_code (automata_list_el_t automata_list
)
7753 automata_list_el_t el
, next_el
;
7755 fprintf (output_file
, " {\n");
7756 if (automata_list
!= NULL
&& automata_list
->next_automata_list_el
!= NULL
)
7757 for (el
= automata_list
;; el
= next_el
)
7759 next_el
= el
->next_automata_list_el
;
7760 if (next_el
== NULL
)
7762 fprintf (output_file
, " ");
7763 output_state_member_type (output_file
, el
->automaton
);
7764 fprintf (output_file
, " ");
7765 output_temp_chip_member_name (output_file
, el
->automaton
);
7766 fprintf (output_file
, ";\n");
7768 for (el
= automata_list
; el
!= NULL
; el
= el
->next_automata_list_el
)
7769 if (comb_vect_p (el
->automaton
->trans_table
))
7771 fprintf (output_file
, "\n %s = ", TEMPORARY_VARIABLE_NAME
);
7772 output_trans_base_vect_name (output_file
, el
->automaton
);
7773 fprintf (output_file
, " [%s->", CHIP_PARAMETER_NAME
);
7774 output_chip_member_name (output_file
, el
->automaton
);
7775 fprintf (output_file
, "] + ");
7776 output_translate_vect_name (output_file
, el
->automaton
);
7777 fprintf (output_file
, " [%s];\n", INTERNAL_INSN_CODE_NAME
);
7778 fprintf (output_file
, " if (");
7779 output_trans_check_vect_name (output_file
, el
->automaton
);
7780 fprintf (output_file
, " [%s] != %s->",
7781 TEMPORARY_VARIABLE_NAME
, CHIP_PARAMETER_NAME
);
7782 output_chip_member_name (output_file
, el
->automaton
);
7783 fprintf (output_file
, ")\n");
7784 fprintf (output_file
, " return %s (%s, %s);\n",
7785 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
7786 CHIP_PARAMETER_NAME
);
7787 fprintf (output_file
, " else\n");
7788 fprintf (output_file
, " ");
7789 if (el
->next_automata_list_el
!= NULL
)
7790 output_temp_chip_member_name (output_file
, el
->automaton
);
7793 fprintf (output_file
, "%s->", CHIP_PARAMETER_NAME
);
7794 output_chip_member_name (output_file
, el
->automaton
);
7796 fprintf (output_file
, " = ");
7797 output_trans_comb_vect_name (output_file
, el
->automaton
);
7798 fprintf (output_file
, " [%s];\n", TEMPORARY_VARIABLE_NAME
);
7802 fprintf (output_file
, "\n %s = ", TEMPORARY_VARIABLE_NAME
);
7803 output_trans_full_vect_name (output_file
, el
->automaton
);
7804 fprintf (output_file
, " [");
7805 output_translate_vect_name (output_file
, el
->automaton
);
7806 fprintf (output_file
, " [%s] + ", INTERNAL_INSN_CODE_NAME
);
7807 fprintf (output_file
, "%s->", CHIP_PARAMETER_NAME
);
7808 output_chip_member_name (output_file
, el
->automaton
);
7809 fprintf (output_file
, " * %d];\n",
7810 el
->automaton
->insn_equiv_classes_num
);
7811 fprintf (output_file
, " if (%s >= %d)\n",
7812 TEMPORARY_VARIABLE_NAME
, el
->automaton
->achieved_states_num
);
7813 fprintf (output_file
, " return %s (%s, %s);\n",
7814 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
7815 CHIP_PARAMETER_NAME
);
7816 fprintf (output_file
, " else\n ");
7817 if (el
->next_automata_list_el
!= NULL
)
7818 output_temp_chip_member_name (output_file
, el
->automaton
);
7821 fprintf (output_file
, "%s->", CHIP_PARAMETER_NAME
);
7822 output_chip_member_name (output_file
, el
->automaton
);
7824 fprintf (output_file
, " = %s;\n", TEMPORARY_VARIABLE_NAME
);
7826 if (automata_list
!= NULL
&& automata_list
->next_automata_list_el
!= NULL
)
7827 for (el
= automata_list
;; el
= next_el
)
7829 next_el
= el
->next_automata_list_el
;
7830 if (next_el
== NULL
)
7832 fprintf (output_file
, " %s->", CHIP_PARAMETER_NAME
);
7833 output_chip_member_name (output_file
, el
->automaton
);
7834 fprintf (output_file
, " = ");
7835 output_temp_chip_member_name (output_file
, el
->automaton
);
7836 fprintf (output_file
, ";\n");
7838 fprintf (output_file
, " return -1;\n");
7839 fprintf (output_file
, " }\n");
7842 /* Output function `internal_state_transition'. */
7844 output_internal_trans_func (void)
7846 fprintf (output_file
,
7847 "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
7848 INTERNAL_TRANSITION_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
7849 CHIP_NAME
, CHIP_PARAMETER_NAME
);
7850 fprintf (output_file
, "{\n int %s ATTRIBUTE_UNUSED;\n", TEMPORARY_VARIABLE_NAME
);
7851 fprintf (output_file
, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME
);
7852 output_insn_code_cases (output_automata_list_transition_code
);
7853 fprintf (output_file
, "\n default:\n return -1;\n }\n");
7854 fprintf (output_file
, "}\n\n");
7861 insn_code = dfa_insn_code (insn);
7862 if (insn_code > DFA__ADVANCE_CYCLE)
7866 insn_code = DFA__ADVANCE_CYCLE;
7868 where insn denotes INSN_NAME, insn_code denotes INSN_CODE_NAME, and
7869 code denotes CODE. */
7871 output_internal_insn_code_evaluation (const char *insn_name
,
7872 const char *insn_code_name
,
7875 fprintf (output_file
, "\n if (%s != 0)\n {\n", insn_name
);
7876 fprintf (output_file
, " %s = %s (%s);\n", insn_code_name
,
7877 DFA_INSN_CODE_FUNC_NAME
, insn_name
);
7878 fprintf (output_file
, " if (%s > %s)\n return %d;\n",
7879 insn_code_name
, ADVANCE_CYCLE_VALUE_NAME
, code
);
7880 fprintf (output_file
, " }\n else\n %s = %s;\n\n",
7881 insn_code_name
, ADVANCE_CYCLE_VALUE_NAME
);
7885 /* This function outputs `dfa_insn_code' and its helper function
7886 `dfa_insn_code_enlarge'. */
7888 output_dfa_insn_code_func (void)
7890 /* Emacs c-mode gets really confused if there's a { or } in column 0
7891 inside a string, so don't do that. */
7892 fprintf (output_file
, "\
7894 dfa_insn_code_enlarge (int uid)\n\
7898 %s = xrealloc (%s,\n\
7899 %s * sizeof(int));\n\
7900 for (; i < %s; i++)\n\
7901 %s[i] = -1;\n}\n\n",
7902 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
,
7903 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
,
7904 DFA_INSN_CODES_VARIABLE_NAME
, DFA_INSN_CODES_VARIABLE_NAME
,
7905 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
,
7906 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
,
7907 DFA_INSN_CODES_VARIABLE_NAME
);
7908 fprintf (output_file
, "\
7909 static inline int\n%s (rtx %s)\n\
7911 int uid = INSN_UID (%s);\n\
7913 DFA_INSN_CODE_FUNC_NAME
, INSN_PARAMETER_NAME
,
7914 INSN_PARAMETER_NAME
, INTERNAL_INSN_CODE_NAME
);
7916 fprintf (output_file
,
7917 " if (uid >= %s)\n dfa_insn_code_enlarge (uid);\n\n",
7918 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
);
7919 fprintf (output_file
, " %s = %s[uid];\n",
7920 INTERNAL_INSN_CODE_NAME
, DFA_INSN_CODES_VARIABLE_NAME
);
7921 fprintf (output_file
, "\
7927 INTERNAL_INSN_CODE_NAME
,
7928 INTERNAL_INSN_CODE_NAME
,
7929 INTERNAL_DFA_INSN_CODE_FUNC_NAME
, INSN_PARAMETER_NAME
,
7930 DFA_INSN_CODES_VARIABLE_NAME
, INTERNAL_INSN_CODE_NAME
);
7931 fprintf (output_file
, " return %s;\n}\n\n", INTERNAL_INSN_CODE_NAME
);
7934 /* The function outputs PHR interface function `state_transition'. */
7936 output_trans_func (void)
7938 fprintf (output_file
, "int\n%s (%s %s, rtx %s)\n",
7939 TRANSITION_FUNC_NAME
, STATE_TYPE_NAME
, STATE_NAME
,
7940 INSN_PARAMETER_NAME
);
7941 fprintf (output_file
, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME
);
7942 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME
,
7943 INTERNAL_INSN_CODE_NAME
, -1);
7944 fprintf (output_file
, " return %s (%s, %s);\n}\n\n",
7945 INTERNAL_TRANSITION_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
, STATE_NAME
);
7948 /* Output function `min_issue_delay'. */
7950 output_min_issue_delay_func (void)
7952 fprintf (output_file
, "int\n%s (%s %s, rtx %s)\n",
7953 MIN_ISSUE_DELAY_FUNC_NAME
, STATE_TYPE_NAME
, STATE_NAME
,
7954 INSN_PARAMETER_NAME
);
7955 fprintf (output_file
, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME
);
7956 fprintf (output_file
, "\n if (%s != 0)\n {\n", INSN_PARAMETER_NAME
);
7957 fprintf (output_file
, " %s = %s (%s);\n", INTERNAL_INSN_CODE_NAME
,
7958 DFA_INSN_CODE_FUNC_NAME
, INSN_PARAMETER_NAME
);
7959 fprintf (output_file
, " if (%s > %s)\n return 0;\n",
7960 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
7961 fprintf (output_file
, " }\n else\n %s = %s;\n",
7962 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
7963 fprintf (output_file
, "\n return %s (%s, %s);\n",
7964 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
7966 fprintf (output_file
, "}\n\n");
7969 /* Output function `internal_dead_lock'. */
7971 output_internal_dead_lock_func (void)
7973 automaton_t automaton
;
7975 fprintf (output_file
, "static int\n%s (struct %s *ARG_UNUSED (%s))\n",
7976 INTERNAL_DEAD_LOCK_FUNC_NAME
, CHIP_NAME
, CHIP_PARAMETER_NAME
);
7977 fprintf (output_file
, "{\n");
7978 for (automaton
= description
->first_automaton
;
7980 automaton
= automaton
->next_automaton
)
7981 if (automaton
->locked_states
)
7983 fprintf (output_file
, " if (");
7984 output_dead_lock_vect_name (output_file
, automaton
);
7985 fprintf (output_file
, " [%s->", CHIP_PARAMETER_NAME
);
7986 output_chip_member_name (output_file
, automaton
);
7987 fprintf (output_file
, "])\n return 1/* TRUE */;\n");
7989 fprintf (output_file
, " return 0/* FALSE */;\n}\n\n");
7992 /* The function outputs PHR interface function `state_dead_lock_p'. */
7994 output_dead_lock_func (void)
7996 fprintf (output_file
, "int\n%s (%s %s)\n",
7997 DEAD_LOCK_FUNC_NAME
, STATE_TYPE_NAME
, STATE_NAME
);
7998 fprintf (output_file
, "{\n return %s (%s);\n}\n\n",
7999 INTERNAL_DEAD_LOCK_FUNC_NAME
, STATE_NAME
);
8002 /* Output function `internal_reset'. */
8004 output_internal_reset_func (void)
8006 fprintf (output_file
, "static inline void\n%s (struct %s *%s)\n",
8007 INTERNAL_RESET_FUNC_NAME
, CHIP_NAME
, CHIP_PARAMETER_NAME
);
8008 fprintf (output_file
, "{\n memset (%s, 0, sizeof (struct %s));\n}\n\n",
8009 CHIP_PARAMETER_NAME
, CHIP_NAME
);
8012 /* The function outputs PHR interface function `state_size'. */
8014 output_size_func (void)
8016 fprintf (output_file
, "int\n%s (void)\n", SIZE_FUNC_NAME
);
8017 fprintf (output_file
, "{\n return sizeof (struct %s);\n}\n\n", CHIP_NAME
);
8020 /* The function outputs PHR interface function `state_reset'. */
8022 output_reset_func (void)
8024 fprintf (output_file
, "void\n%s (%s %s)\n",
8025 RESET_FUNC_NAME
, STATE_TYPE_NAME
, STATE_NAME
);
8026 fprintf (output_file
, "{\n %s (%s);\n}\n\n", INTERNAL_RESET_FUNC_NAME
,
8030 /* Output function `min_insn_conflict_delay'. */
8032 output_min_insn_conflict_delay_func (void)
8034 fprintf (output_file
,
8035 "int\n%s (%s %s, rtx %s, rtx %s)\n",
8036 MIN_INSN_CONFLICT_DELAY_FUNC_NAME
, STATE_TYPE_NAME
,
8037 STATE_NAME
, INSN_PARAMETER_NAME
, INSN2_PARAMETER_NAME
);
8038 fprintf (output_file
, "{\n struct %s %s;\n int %s, %s, transition;\n",
8039 CHIP_NAME
, CHIP_NAME
, INTERNAL_INSN_CODE_NAME
,
8040 INTERNAL_INSN2_CODE_NAME
);
8041 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME
,
8042 INTERNAL_INSN_CODE_NAME
, 0);
8043 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME
,
8044 INTERNAL_INSN2_CODE_NAME
, 0);
8045 fprintf (output_file
, " memcpy (&%s, %s, sizeof (%s));\n",
8046 CHIP_NAME
, STATE_NAME
, CHIP_NAME
);
8047 fprintf (output_file
, " %s (&%s);\n", INTERNAL_RESET_FUNC_NAME
, CHIP_NAME
);
8048 fprintf (output_file
, " transition = %s (%s, &%s);\n",
8049 INTERNAL_TRANSITION_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
, CHIP_NAME
);
8050 fprintf (output_file
, " gcc_assert (transition <= 0);\n");
8051 fprintf (output_file
, " return %s (%s, &%s);\n",
8052 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME
, INTERNAL_INSN2_CODE_NAME
,
8054 fprintf (output_file
, "}\n\n");
8057 /* Output function `internal_insn_latency'. */
8059 output_internal_insn_latency_func (void)
8062 struct bypass_decl
*bypass
;
8064 const char *tabletype
= "unsigned char";
8066 /* Find the smallest integer type that can hold all the default
8068 for (i
= 0; i
< description
->decls_num
; i
++)
8069 if (description
->decls
[i
]->mode
== dm_insn_reserv
)
8071 decl
= description
->decls
[i
];
8072 if (DECL_INSN_RESERV (decl
)->default_latency
> UCHAR_MAX
8073 && tabletype
[0] != 'i') /* Don't shrink it. */
8074 tabletype
= "unsigned short";
8075 if (DECL_INSN_RESERV (decl
)->default_latency
> USHRT_MAX
)
8079 fprintf (output_file
, "static int\n%s (int %s ATTRIBUTE_UNUSED,\n\tint %s ATTRIBUTE_UNUSED,\n\trtx %s ATTRIBUTE_UNUSED,\n\trtx %s ATTRIBUTE_UNUSED)\n",
8080 INTERNAL_INSN_LATENCY_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
8081 INTERNAL_INSN2_CODE_NAME
, INSN_PARAMETER_NAME
,
8082 INSN2_PARAMETER_NAME
);
8083 fprintf (output_file
, "{\n");
8085 if (DECL_INSN_RESERV (advance_cycle_insn_decl
)->insn_num
== 0)
8087 fputs (" return 0;\n}\n\n", output_file
);
8091 fprintf (output_file
, " static const %s default_latencies[] =\n {",
8094 for (i
= 0, j
= 0, col
= 7; i
< description
->decls_num
; i
++)
8095 if (description
->decls
[i
]->mode
== dm_insn_reserv
8096 && description
->decls
[i
] != advance_cycle_insn_decl
)
8098 if ((col
= (col
+1) % 8) == 0)
8099 fputs ("\n ", output_file
);
8100 decl
= description
->decls
[i
];
8101 gcc_assert (j
++ == DECL_INSN_RESERV (decl
)->insn_num
);
8102 fprintf (output_file
, "% 4d,",
8103 DECL_INSN_RESERV (decl
)->default_latency
);
8105 gcc_assert (j
== DECL_INSN_RESERV (advance_cycle_insn_decl
)->insn_num
);
8106 fputs ("\n };\n", output_file
);
8108 fprintf (output_file
, " if (%s >= %s || %s >= %s)\n return 0;\n",
8109 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
,
8110 INTERNAL_INSN2_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
8112 fprintf (output_file
, " switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME
);
8113 for (i
= 0; i
< description
->decls_num
; i
++)
8114 if (description
->decls
[i
]->mode
== dm_insn_reserv
8115 && DECL_INSN_RESERV (description
->decls
[i
])->bypass_list
)
8117 decl
= description
->decls
[i
];
8118 fprintf (output_file
,
8119 " case %d:\n switch (%s)\n {\n",
8120 DECL_INSN_RESERV (decl
)->insn_num
,
8121 INTERNAL_INSN2_CODE_NAME
);
8122 for (bypass
= DECL_INSN_RESERV (decl
)->bypass_list
;
8124 bypass
= bypass
->next
)
8126 gcc_assert (bypass
->in_insn_reserv
->insn_num
8127 != (DECL_INSN_RESERV
8128 (advance_cycle_insn_decl
)->insn_num
));
8129 fprintf (output_file
, " case %d:\n",
8130 bypass
->in_insn_reserv
->insn_num
);
8131 if (bypass
->bypass_guard_name
== NULL
)
8132 fprintf (output_file
, " return %d;\n",
8136 fprintf (output_file
,
8137 " if (%s (%s, %s))\n",
8138 bypass
->bypass_guard_name
, INSN_PARAMETER_NAME
,
8139 INSN2_PARAMETER_NAME
);
8140 fprintf (output_file
,
8141 " return %d;\n break;\n",
8145 fputs (" }\n break;\n", output_file
);
8148 fprintf (output_file
, " }\n return default_latencies[%s];\n}\n\n",
8149 INTERNAL_INSN_CODE_NAME
);
8152 /* The function outputs PHR interface function `insn_latency'. */
8154 output_insn_latency_func (void)
8156 fprintf (output_file
, "int\n%s (rtx %s, rtx %s)\n",
8157 INSN_LATENCY_FUNC_NAME
, INSN_PARAMETER_NAME
, INSN2_PARAMETER_NAME
);
8158 fprintf (output_file
, "{\n int %s, %s;\n",
8159 INTERNAL_INSN_CODE_NAME
, INTERNAL_INSN2_CODE_NAME
);
8160 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME
,
8161 INTERNAL_INSN_CODE_NAME
, 0);
8162 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME
,
8163 INTERNAL_INSN2_CODE_NAME
, 0);
8164 fprintf (output_file
, " return %s (%s, %s, %s, %s);\n}\n\n",
8165 INTERNAL_INSN_LATENCY_FUNC_NAME
,
8166 INTERNAL_INSN_CODE_NAME
, INTERNAL_INSN2_CODE_NAME
,
8167 INSN_PARAMETER_NAME
, INSN2_PARAMETER_NAME
);
8170 /* The function outputs PHR interface function `print_reservation'. */
8172 output_print_reservation_func (void)
8177 fprintf (output_file
,
8178 "void\n%s (FILE *%s, rtx %s ATTRIBUTE_UNUSED)\n{\n",
8179 PRINT_RESERVATION_FUNC_NAME
, FILE_PARAMETER_NAME
,
8180 INSN_PARAMETER_NAME
);
8182 if (DECL_INSN_RESERV (advance_cycle_insn_decl
)->insn_num
== 0)
8184 fprintf (output_file
, " fputs (\"%s\", %s);\n}\n\n",
8185 NOTHING_NAME
, FILE_PARAMETER_NAME
);
8190 fputs (" static const char *const reservation_names[] =\n {",
8193 for (i
= 0, j
= 0; i
< description
->decls_num
; i
++)
8195 decl
= description
->decls
[i
];
8196 if (decl
->mode
== dm_insn_reserv
&& decl
!= advance_cycle_insn_decl
)
8198 gcc_assert (j
== DECL_INSN_RESERV (decl
)->insn_num
);
8201 fprintf (output_file
, "\n \"%s\",",
8202 regexp_representation (DECL_INSN_RESERV (decl
)->regexp
));
8203 finish_regexp_representation ();
8206 gcc_assert (j
== DECL_INSN_RESERV (advance_cycle_insn_decl
)->insn_num
);
8208 fprintf (output_file
, "\n \"%s\"\n };\n int %s;\n\n",
8209 NOTHING_NAME
, INTERNAL_INSN_CODE_NAME
);
8211 fprintf (output_file
, " if (%s == 0)\n %s = %s;\n",
8212 INSN_PARAMETER_NAME
,
8213 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
8214 fprintf (output_file
, " else\n\
8220 INTERNAL_INSN_CODE_NAME
, DFA_INSN_CODE_FUNC_NAME
,
8221 INSN_PARAMETER_NAME
,
8222 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
,
8223 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
8225 fprintf (output_file
, " fputs (reservation_names[%s], %s);\n}\n\n",
8226 INTERNAL_INSN_CODE_NAME
, FILE_PARAMETER_NAME
);
8229 /* The following function is used to sort unit declaration by their
8232 units_cmp (const void *unit1
, const void *unit2
)
8234 const unit_decl_t u1
= *(unit_decl_t
*) unit1
;
8235 const unit_decl_t u2
= *(unit_decl_t
*) unit2
;
8237 return strcmp (u1
->name
, u2
->name
);
8240 /* The following macro value is name of struct containing unit name
8242 #define NAME_CODE_STRUCT_NAME "name_code"
8244 /* The following macro value is name of table of struct name_code. */
8245 #define NAME_CODE_TABLE_NAME "name_code_table"
8247 /* The following macro values are member names for struct name_code. */
8248 #define NAME_MEMBER_NAME "name"
8249 #define CODE_MEMBER_NAME "code"
8251 /* The following macro values are local variable names for function
8252 `get_cpu_unit_code'. */
8253 #define CMP_VARIABLE_NAME "cmp"
8254 #define LOW_VARIABLE_NAME "l"
8255 #define MIDDLE_VARIABLE_NAME "m"
8256 #define HIGH_VARIABLE_NAME "h"
8258 /* The following function outputs function to obtain internal cpu unit
8259 code by the cpu unit name. */
8261 output_get_cpu_unit_code_func (void)
8266 fprintf (output_file
, "int\n%s (const char *%s)\n",
8267 GET_CPU_UNIT_CODE_FUNC_NAME
, CPU_UNIT_NAME_PARAMETER_NAME
);
8268 fprintf (output_file
, "{\n struct %s {const char *%s; int %s;};\n",
8269 NAME_CODE_STRUCT_NAME
, NAME_MEMBER_NAME
, CODE_MEMBER_NAME
);
8270 fprintf (output_file
, " int %s, %s, %s, %s;\n", CMP_VARIABLE_NAME
,
8271 LOW_VARIABLE_NAME
, MIDDLE_VARIABLE_NAME
, HIGH_VARIABLE_NAME
);
8272 fprintf (output_file
, " static struct %s %s [] =\n {\n",
8273 NAME_CODE_STRUCT_NAME
, NAME_CODE_TABLE_NAME
);
8274 units
= xmalloc (sizeof (unit_decl_t
) * description
->units_num
);
8275 memcpy (units
, units_array
, sizeof (unit_decl_t
) * description
->units_num
);
8276 qsort (units
, description
->units_num
, sizeof (unit_decl_t
), units_cmp
);
8277 for (i
= 0; i
< description
->units_num
; i
++)
8278 if (units
[i
]->query_p
)
8279 fprintf (output_file
, " {\"%s\", %d},\n",
8280 units
[i
]->name
, units
[i
]->query_num
);
8281 fprintf (output_file
, " };\n\n");
8282 fprintf (output_file
, " /* The following is binary search: */\n");
8283 fprintf (output_file
, " %s = 0;\n", LOW_VARIABLE_NAME
);
8284 fprintf (output_file
, " %s = sizeof (%s) / sizeof (struct %s) - 1;\n",
8285 HIGH_VARIABLE_NAME
, NAME_CODE_TABLE_NAME
, NAME_CODE_STRUCT_NAME
);
8286 fprintf (output_file
, " while (%s <= %s)\n {\n",
8287 LOW_VARIABLE_NAME
, HIGH_VARIABLE_NAME
);
8288 fprintf (output_file
, " %s = (%s + %s) / 2;\n",
8289 MIDDLE_VARIABLE_NAME
, LOW_VARIABLE_NAME
, HIGH_VARIABLE_NAME
);
8290 fprintf (output_file
, " %s = strcmp (%s, %s [%s].%s);\n",
8291 CMP_VARIABLE_NAME
, CPU_UNIT_NAME_PARAMETER_NAME
,
8292 NAME_CODE_TABLE_NAME
, MIDDLE_VARIABLE_NAME
, NAME_MEMBER_NAME
);
8293 fprintf (output_file
, " if (%s < 0)\n", CMP_VARIABLE_NAME
);
8294 fprintf (output_file
, " %s = %s - 1;\n",
8295 HIGH_VARIABLE_NAME
, MIDDLE_VARIABLE_NAME
);
8296 fprintf (output_file
, " else if (%s > 0)\n", CMP_VARIABLE_NAME
);
8297 fprintf (output_file
, " %s = %s + 1;\n",
8298 LOW_VARIABLE_NAME
, MIDDLE_VARIABLE_NAME
);
8299 fprintf (output_file
, " else\n");
8300 fprintf (output_file
, " return %s [%s].%s;\n }\n",
8301 NAME_CODE_TABLE_NAME
, MIDDLE_VARIABLE_NAME
, CODE_MEMBER_NAME
);
8302 fprintf (output_file
, " return -1;\n}\n\n");
8306 /* The following function outputs function to check reservation of cpu
8307 unit (its internal code will be passed as the function argument) in
8310 output_cpu_unit_reservation_p (void)
8312 automaton_t automaton
;
8314 fprintf (output_file
, "int\n%s (%s %s, int %s)\n",
8315 CPU_UNIT_RESERVATION_P_FUNC_NAME
,
8316 STATE_TYPE_NAME
, STATE_NAME
,
8317 CPU_CODE_PARAMETER_NAME
);
8318 fprintf (output_file
, "{\n gcc_assert (%s >= 0 && %s < %d);\n",
8319 CPU_CODE_PARAMETER_NAME
, CPU_CODE_PARAMETER_NAME
,
8320 description
->query_units_num
);
8321 if (description
->query_units_num
> 0)
8322 for (automaton
= description
->first_automaton
;
8324 automaton
= automaton
->next_automaton
)
8326 fprintf (output_file
, " if ((");
8327 output_reserved_units_table_name (output_file
, automaton
);
8328 fprintf (output_file
, " [((struct %s *) %s)->", CHIP_NAME
, STATE_NAME
);
8329 output_chip_member_name (output_file
, automaton
);
8330 fprintf (output_file
, " * %d + %s / 8] >> (%s %% 8)) & 1)\n",
8331 (description
->query_units_num
+ 7) / 8,
8332 CPU_CODE_PARAMETER_NAME
, CPU_CODE_PARAMETER_NAME
);
8333 fprintf (output_file
, " return 1;\n");
8335 fprintf (output_file
, " return 0;\n}\n\n");
8338 /* The function outputs PHR interface function `dfa_clean_insn_cache'. */
8340 output_dfa_clean_insn_cache_func (void)
8342 fprintf (output_file
,
8343 "void\n%s (void)\n{\n int %s;\n\n",
8344 DFA_CLEAN_INSN_CACHE_FUNC_NAME
, I_VARIABLE_NAME
);
8345 fprintf (output_file
,
8346 " for (%s = 0; %s < %s; %s++)\n %s [%s] = -1;\n}\n\n",
8347 I_VARIABLE_NAME
, I_VARIABLE_NAME
,
8348 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
, I_VARIABLE_NAME
,
8349 DFA_INSN_CODES_VARIABLE_NAME
, I_VARIABLE_NAME
);
8352 /* The function outputs PHR interface function `dfa_start'. */
8354 output_dfa_start_func (void)
8356 fprintf (output_file
,
8357 "void\n%s (void)\n{\n %s = get_max_uid ();\n",
8358 DFA_START_FUNC_NAME
, DFA_INSN_CODES_LENGTH_VARIABLE_NAME
);
8359 fprintf (output_file
, " %s = xmalloc (%s * sizeof (int));\n",
8360 DFA_INSN_CODES_VARIABLE_NAME
, DFA_INSN_CODES_LENGTH_VARIABLE_NAME
);
8361 fprintf (output_file
, " %s ();\n}\n\n", DFA_CLEAN_INSN_CACHE_FUNC_NAME
);
8364 /* The function outputs PHR interface function `dfa_finish'. */
8366 output_dfa_finish_func (void)
8368 fprintf (output_file
, "void\n%s (void)\n{\n free (%s);\n}\n\n",
8369 DFA_FINISH_FUNC_NAME
, DFA_INSN_CODES_VARIABLE_NAME
);
8374 /* The page contains code for output description file (readable
8375 representation of original description and generated DFA(s). */
8377 /* The function outputs string representation of IR reservation. */
8379 output_regexp (regexp_t regexp
)
8381 fprintf (output_description_file
, "%s", regexp_representation (regexp
));
8382 finish_regexp_representation ();
8385 /* Output names of units in LIST separated by comma. */
8387 output_unit_set_el_list (unit_set_el_t list
)
8391 for (el
= list
; el
!= NULL
; el
= el
->next_unit_set_el
)
8394 fprintf (output_description_file
, ", ");
8395 fprintf (output_description_file
, "%s", el
->unit_decl
->name
);
8399 /* Output patterns in LIST separated by comma. */
8401 output_pattern_set_el_list (pattern_set_el_t list
)
8403 pattern_set_el_t el
;
8406 for (el
= list
; el
!= NULL
; el
= el
->next_pattern_set_el
)
8409 fprintf (output_description_file
, ", ");
8410 for (i
= 0; i
< el
->units_num
; i
++)
8411 fprintf (output_description_file
, (i
== 0 ? "%s" : " %s"),
8412 el
->unit_decls
[i
]->name
);
8416 /* The function outputs string representation of IR define_reservation
8417 and define_insn_reservation. */
8419 output_description (void)
8424 for (i
= 0; i
< description
->decls_num
; i
++)
8426 decl
= description
->decls
[i
];
8427 if (decl
->mode
== dm_unit
)
8429 if (DECL_UNIT (decl
)->excl_list
!= NULL
)
8431 fprintf (output_description_file
, "unit %s exlusion_set: ",
8432 DECL_UNIT (decl
)->name
);
8433 output_unit_set_el_list (DECL_UNIT (decl
)->excl_list
);
8434 fprintf (output_description_file
, "\n");
8436 if (DECL_UNIT (decl
)->presence_list
!= NULL
)
8438 fprintf (output_description_file
, "unit %s presence_set: ",
8439 DECL_UNIT (decl
)->name
);
8440 output_pattern_set_el_list (DECL_UNIT (decl
)->presence_list
);
8441 fprintf (output_description_file
, "\n");
8443 if (DECL_UNIT (decl
)->final_presence_list
!= NULL
)
8445 fprintf (output_description_file
, "unit %s final_presence_set: ",
8446 DECL_UNIT (decl
)->name
);
8447 output_pattern_set_el_list
8448 (DECL_UNIT (decl
)->final_presence_list
);
8449 fprintf (output_description_file
, "\n");
8451 if (DECL_UNIT (decl
)->absence_list
!= NULL
)
8453 fprintf (output_description_file
, "unit %s absence_set: ",
8454 DECL_UNIT (decl
)->name
);
8455 output_pattern_set_el_list (DECL_UNIT (decl
)->absence_list
);
8456 fprintf (output_description_file
, "\n");
8458 if (DECL_UNIT (decl
)->final_absence_list
!= NULL
)
8460 fprintf (output_description_file
, "unit %s final_absence_set: ",
8461 DECL_UNIT (decl
)->name
);
8462 output_pattern_set_el_list
8463 (DECL_UNIT (decl
)->final_absence_list
);
8464 fprintf (output_description_file
, "\n");
8468 fprintf (output_description_file
, "\n");
8469 for (i
= 0; i
< description
->decls_num
; i
++)
8471 decl
= description
->decls
[i
];
8472 if (decl
->mode
== dm_reserv
)
8474 fprintf (output_description_file
, "reservation %s: ",
8475 DECL_RESERV (decl
)->name
);
8476 output_regexp (DECL_RESERV (decl
)->regexp
);
8477 fprintf (output_description_file
, "\n");
8479 else if (decl
->mode
== dm_insn_reserv
&& decl
!= advance_cycle_insn_decl
)
8481 fprintf (output_description_file
, "insn reservation %s ",
8482 DECL_INSN_RESERV (decl
)->name
);
8483 print_rtl (output_description_file
,
8484 DECL_INSN_RESERV (decl
)->condexp
);
8485 fprintf (output_description_file
, ": ");
8486 output_regexp (DECL_INSN_RESERV (decl
)->regexp
);
8487 fprintf (output_description_file
, "\n");
8489 else if (decl
->mode
== dm_bypass
)
8490 fprintf (output_description_file
, "bypass %d %s %s\n",
8491 DECL_BYPASS (decl
)->latency
,
8492 DECL_BYPASS (decl
)->out_insn_name
,
8493 DECL_BYPASS (decl
)->in_insn_name
);
8495 fprintf (output_description_file
, "\n\f\n");
8498 /* The function outputs name of AUTOMATON. */
8500 output_automaton_name (FILE *f
, automaton_t automaton
)
8502 if (automaton
->corresponding_automaton_decl
== NULL
)
8503 fprintf (f
, "#%d", automaton
->automaton_order_num
);
8505 fprintf (f
, "`%s'", automaton
->corresponding_automaton_decl
->name
);
8508 /* Maximal length of line for pretty printing into description
8510 #define MAX_LINE_LENGTH 70
8512 /* The function outputs units name belonging to AUTOMATON. */
8514 output_automaton_units (automaton_t automaton
)
8518 int curr_line_length
;
8519 int there_is_an_automaton_unit
;
8522 fprintf (output_description_file
, "\n Corresponding units:\n");
8523 fprintf (output_description_file
, " ");
8524 curr_line_length
= 4;
8525 there_is_an_automaton_unit
= 0;
8526 for (i
= 0; i
< description
->decls_num
; i
++)
8528 decl
= description
->decls
[i
];
8529 if (decl
->mode
== dm_unit
8530 && (DECL_UNIT (decl
)->corresponding_automaton_num
8531 == automaton
->automaton_order_num
))
8533 there_is_an_automaton_unit
= 1;
8534 name
= DECL_UNIT (decl
)->name
;
8535 if (curr_line_length
+ strlen (name
) + 1 > MAX_LINE_LENGTH
)
8537 curr_line_length
= strlen (name
) + 4;
8538 fprintf (output_description_file
, "\n ");
8542 curr_line_length
+= strlen (name
) + 1;
8543 fprintf (output_description_file
, " ");
8545 fprintf (output_description_file
, "%s", name
);
8548 if (!there_is_an_automaton_unit
)
8549 fprintf (output_description_file
, "<None>");
8550 fprintf (output_description_file
, "\n\n");
8553 /* The following variable is used for forming array of all possible cpu unit
8554 reservations described by the current DFA state. */
8555 static VEC(reserv_sets_t
,heap
) *state_reservs
;
8557 /* The function forms `state_reservs' for STATE. */
8559 add_state_reservs (state_t state
)
8561 alt_state_t curr_alt_state
;
8563 if (state
->component_states
!= NULL
)
8564 for (curr_alt_state
= state
->component_states
;
8565 curr_alt_state
!= NULL
;
8566 curr_alt_state
= curr_alt_state
->next_sorted_alt_state
)
8567 add_state_reservs (curr_alt_state
->state
);
8569 VEC_safe_push (reserv_sets_t
,heap
, state_reservs
, state
->reservs
);
8572 /* The function outputs readable representation of all out arcs of
8575 output_state_arcs (state_t state
)
8579 const char *insn_name
;
8580 int curr_line_length
;
8582 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
8585 gcc_assert (ainsn
->first_insn_with_same_reservs
);
8586 fprintf (output_description_file
, " ");
8587 curr_line_length
= 7;
8588 fprintf (output_description_file
, "%2d: ", ainsn
->insn_equiv_class_num
);
8591 insn_name
= ainsn
->insn_reserv_decl
->name
;
8592 if (curr_line_length
+ strlen (insn_name
) > MAX_LINE_LENGTH
)
8594 if (ainsn
!= arc
->insn
)
8596 fprintf (output_description_file
, ",\n ");
8597 curr_line_length
= strlen (insn_name
) + 6;
8600 curr_line_length
+= strlen (insn_name
);
8604 curr_line_length
+= strlen (insn_name
);
8605 if (ainsn
!= arc
->insn
)
8607 curr_line_length
+= 2;
8608 fprintf (output_description_file
, ", ");
8611 fprintf (output_description_file
, "%s", insn_name
);
8612 ainsn
= ainsn
->next_same_reservs_insn
;
8614 while (ainsn
!= NULL
);
8615 fprintf (output_description_file
, " %d \n",
8616 arc
->to_state
->order_state_num
);
8618 fprintf (output_description_file
, "\n");
8621 /* The following function is used for sorting possible cpu unit
8622 reservation of a DFA state. */
8624 state_reservs_cmp (const void *reservs_ptr_1
, const void *reservs_ptr_2
)
8626 return reserv_sets_cmp (*(reserv_sets_t
*) reservs_ptr_1
,
8627 *(reserv_sets_t
*) reservs_ptr_2
);
8630 /* The following function is used for sorting possible cpu unit
8631 reservation of a DFA state. */
8633 remove_state_duplicate_reservs (void)
8637 for (i
= 1, j
= 0; i
< VEC_length (reserv_sets_t
, state_reservs
); i
++)
8638 if (reserv_sets_cmp (VEC_index (reserv_sets_t
, state_reservs
, j
),
8639 VEC_index (reserv_sets_t
, state_reservs
, i
)))
8642 VEC_replace (reserv_sets_t
, state_reservs
, j
,
8643 VEC_index (reserv_sets_t
, state_reservs
, i
));
8645 VEC_truncate (reserv_sets_t
, state_reservs
, j
+ 1);
8648 /* The following function output readable representation of DFA(s)
8649 state used for fast recognition of pipeline hazards. State is
8650 described by possible (current and scheduled) cpu unit
8653 output_state (state_t state
)
8659 fprintf (output_description_file
, " State #%d", state
->order_state_num
);
8660 fprintf (output_description_file
,
8661 state
->new_cycle_p
? " (new cycle)\n" : "\n");
8662 add_state_reservs (state
);
8663 qsort (VEC_address (reserv_sets_t
, state_reservs
),
8664 VEC_length (reserv_sets_t
, state_reservs
),
8665 sizeof (reserv_sets_t
), state_reservs_cmp
);
8666 remove_state_duplicate_reservs ();
8667 for (i
= 1; i
< VEC_length (reserv_sets_t
, state_reservs
); i
++)
8669 fprintf (output_description_file
, " ");
8670 output_reserv_sets (output_description_file
,
8671 VEC_index (reserv_sets_t
, state_reservs
, i
));
8672 fprintf (output_description_file
, "\n");
8674 fprintf (output_description_file
, "\n");
8675 output_state_arcs (state
);
8676 VEC_free (reserv_sets_t
,heap
, state_reservs
);
8679 /* The following function output readable representation of
8680 DFAs used for fast recognition of pipeline hazards. */
8682 output_automaton_descriptions (void)
8684 automaton_t automaton
;
8686 for (automaton
= description
->first_automaton
;
8688 automaton
= automaton
->next_automaton
)
8690 fprintf (output_description_file
, "\nAutomaton ");
8691 output_automaton_name (output_description_file
, automaton
);
8692 fprintf (output_description_file
, "\n");
8693 output_automaton_units (automaton
);
8694 pass_states (automaton
, output_state
);
8700 /* The page contains top level function for generation DFA(s) used for
8703 /* The function outputs statistics about work of different phases of
8706 output_statistics (FILE *f
)
8708 automaton_t automaton
;
8711 int transition_comb_vect_els
= 0;
8712 int transition_full_vect_els
= 0;
8713 int min_issue_delay_vect_els
= 0;
8714 int locked_states
= 0;
8717 for (automaton
= description
->first_automaton
;
8719 automaton
= automaton
->next_automaton
)
8721 fprintf (f
, "\nAutomaton ");
8722 output_automaton_name (f
, automaton
);
8723 fprintf (f
, "\n %5d NDFA states, %5d NDFA arcs\n",
8724 automaton
->NDFA_states_num
, automaton
->NDFA_arcs_num
);
8725 fprintf (f
, " %5d DFA states, %5d DFA arcs\n",
8726 automaton
->DFA_states_num
, automaton
->DFA_arcs_num
);
8727 states_num
= automaton
->DFA_states_num
;
8728 if (!no_minimization_flag
)
8730 fprintf (f
, " %5d minimal DFA states, %5d minimal DFA arcs\n",
8731 automaton
->minimal_DFA_states_num
,
8732 automaton
->minimal_DFA_arcs_num
);
8733 states_num
= automaton
->minimal_DFA_states_num
;
8735 fprintf (f
, " %5d all insns %5d insn equivalence classes\n",
8736 description
->insns_num
, automaton
->insn_equiv_classes_num
);
8737 fprintf (f
, " %d locked states\n", automaton
->locked_states
);
8740 (f
, "%5ld transition comb vector els, %5ld trans table els: %s\n",
8741 (long) VEC_length (vect_el_t
, automaton
->trans_table
->comb_vect
),
8742 (long) VEC_length (vect_el_t
, automaton
->trans_table
->full_vect
),
8743 (comb_vect_p (automaton
->trans_table
)
8744 ? "use comb vect" : "use simple vect"));
8746 (f
, "%5ld min delay table els, compression factor %d\n",
8747 (long) states_num
* automaton
->insn_equiv_classes_num
,
8748 automaton
->min_issue_delay_table_compression_factor
);
8749 transition_comb_vect_els
8750 += VEC_length (vect_el_t
, automaton
->trans_table
->comb_vect
);
8751 transition_full_vect_els
8752 += VEC_length (vect_el_t
, automaton
->trans_table
->full_vect
);
8753 min_issue_delay_vect_els
8754 += states_num
* automaton
->insn_equiv_classes_num
;
8756 += automaton
->locked_states
;
8760 fprintf (f
, "\n%5d all allocated states, %5d all allocated arcs\n",
8761 allocated_states_num
, allocated_arcs_num
);
8762 fprintf (f
, "%5d all allocated alternative states\n",
8763 allocated_alt_states_num
);
8764 fprintf (f
, "%5d all transition comb vector els, %5d all trans table els\n",
8765 transition_comb_vect_els
, transition_full_vect_els
);
8766 fprintf (f
, "%5d all min delay table els\n", min_issue_delay_vect_els
);
8767 fprintf (f
, "%5d all locked states\n", locked_states
);
8771 /* The function output times of work of different phases of DFA
8774 output_time_statistics (FILE *f
)
8776 fprintf (f
, "\n transformation: ");
8777 print_active_time (f
, transform_time
);
8778 fprintf (f
, (!ndfa_flag
? ", building DFA: " : ", building NDFA: "));
8779 print_active_time (f
, NDFA_time
);
8782 fprintf (f
, ", NDFA -> DFA: ");
8783 print_active_time (f
, NDFA_to_DFA_time
);
8785 fprintf (f
, "\n DFA minimization: ");
8786 print_active_time (f
, minimize_time
);
8787 fprintf (f
, ", making insn equivalence: ");
8788 print_active_time (f
, equiv_time
);
8789 fprintf (f
, "\n all automaton generation: ");
8790 print_active_time (f
, automaton_generation_time
);
8791 fprintf (f
, ", output: ");
8792 print_active_time (f
, output_time
);
8796 /* The function generates DFA (deterministic finite state automaton)
8797 for fast recognition of pipeline hazards. No errors during
8798 checking must be fixed before this function call. */
8802 automata_num
= split_argument
;
8803 if (description
->units_num
< automata_num
)
8804 automata_num
= description
->units_num
;
8807 initiate_automata_lists ();
8808 initiate_pass_states ();
8809 initiate_excl_sets ();
8810 initiate_presence_absence_pattern_sets ();
8811 automaton_generation_time
= create_ticker ();
8813 ticker_off (&automaton_generation_time
);
8818 /* This page mainly contains top level functions of pipeline hazards
8819 description translator. */
8821 /* The following macro value is suffix of name of description file of
8822 pipeline hazards description translator. */
8823 #define STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX ".dfa"
8825 /* The function returns suffix of given file name. The returned
8826 string can not be changed. */
8828 file_name_suffix (const char *file_name
)
8830 const char *last_period
;
8832 for (last_period
= NULL
; *file_name
!= '\0'; file_name
++)
8833 if (*file_name
== '.')
8834 last_period
= file_name
;
8835 return (last_period
== NULL
? file_name
: last_period
);
8838 /* The function returns base name of given file name, i.e. pointer to
8839 first char after last `/' (or `\' for WIN32) in given file name,
8840 given file name itself if the directory name is absent. The
8841 returned string can not be changed. */
8843 base_file_name (const char *file_name
)
8845 int directory_name_length
;
8847 directory_name_length
= strlen (file_name
);
8849 while (directory_name_length
>= 0 && file_name
[directory_name_length
] != '/'
8850 && file_name
[directory_name_length
] != '\\')
8852 while (directory_name_length
>= 0 && file_name
[directory_name_length
] != '/')
8854 directory_name_length
--;
8855 return file_name
+ directory_name_length
+ 1;
8858 /* The following is top level function to initialize the work of
8859 pipeline hazards description translator. */
8861 initiate_automaton_gen (int argc
, char **argv
)
8863 const char *base_name
;
8867 split_argument
= 0; /* default value */
8868 no_minimization_flag
= 0;
8873 for (i
= 2; i
< argc
; i
++)
8874 if (strcmp (argv
[i
], NO_MINIMIZATION_OPTION
) == 0)
8875 no_minimization_flag
= 1;
8876 else if (strcmp (argv
[i
], TIME_OPTION
) == 0)
8878 else if (strcmp (argv
[i
], V_OPTION
) == 0)
8880 else if (strcmp (argv
[i
], W_OPTION
) == 0)
8882 else if (strcmp (argv
[i
], NDFA_OPTION
) == 0)
8884 else if (strcmp (argv
[i
], PROGRESS_OPTION
) == 0)
8886 else if (strcmp (argv
[i
], "-split") == 0)
8889 fatal ("-split has no argument.");
8890 fatal ("option `-split' has not been implemented yet\n");
8891 /* split_argument = atoi (argument_vect [i + 1]); */
8894 /* Initialize IR storage. */
8895 obstack_init (&irp
);
8896 initiate_automaton_decl_table ();
8897 initiate_insn_decl_table ();
8898 initiate_decl_table ();
8899 output_file
= stdout
;
8900 output_description_file
= NULL
;
8901 base_name
= base_file_name (argv
[1]);
8902 obstack_grow (&irp
, base_name
,
8903 strlen (base_name
) - strlen (file_name_suffix (base_name
)));
8904 obstack_grow (&irp
, STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX
,
8905 strlen (STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX
) + 1);
8906 obstack_1grow (&irp
, '\0');
8907 output_description_file_name
= obstack_base (&irp
);
8908 obstack_finish (&irp
);
8911 /* The following function checks existence at least one arc marked by
8914 check_automata_insn_issues (void)
8916 automaton_t automaton
;
8917 ainsn_t ainsn
, reserv_ainsn
;
8919 for (automaton
= description
->first_automaton
;
8921 automaton
= automaton
->next_automaton
)
8923 for (ainsn
= automaton
->ainsn_list
;
8925 ainsn
= ainsn
->next_ainsn
)
8926 if (ainsn
->first_insn_with_same_reservs
&& !ainsn
->arc_exists_p
)
8928 for (reserv_ainsn
= ainsn
;
8929 reserv_ainsn
!= NULL
;
8930 reserv_ainsn
= reserv_ainsn
->next_same_reservs_insn
)
8931 if (automaton
->corresponding_automaton_decl
!= NULL
)
8934 error ("Automaton `%s': Insn `%s' will never be issued",
8935 automaton
->corresponding_automaton_decl
->name
,
8936 reserv_ainsn
->insn_reserv_decl
->name
);
8939 (0, "Automaton `%s': Insn `%s' will never be issued",
8940 automaton
->corresponding_automaton_decl
->name
,
8941 reserv_ainsn
->insn_reserv_decl
->name
);
8946 error ("Insn `%s' will never be issued",
8947 reserv_ainsn
->insn_reserv_decl
->name
);
8949 warning (0, "Insn `%s' will never be issued",
8950 reserv_ainsn
->insn_reserv_decl
->name
);
8956 /* The following vla is used for storing pointers to all achieved
8958 static VEC(state_t
,heap
) *automaton_states
;
8960 /* This function is called by function pass_states to add an achieved
8963 add_automaton_state (state_t state
)
8965 VEC_safe_push (state_t
,heap
, automaton_states
, state
);
8968 /* The following function forms list of important automata (whose
8969 states may be changed after the insn issue) for each insn. */
8971 form_important_insn_automata_lists (void)
8973 automaton_t automaton
;
8980 automaton_states
= 0;
8981 /* Mark important ainsns. */
8982 for (automaton
= description
->first_automaton
;
8984 automaton
= automaton
->next_automaton
)
8986 VEC_truncate (state_t
, automaton_states
, 0);
8987 pass_states (automaton
, add_automaton_state
);
8988 for (n
= 0; n
< VEC_length (state_t
, automaton_states
); n
++)
8990 state_t s
= VEC_index (state_t
, automaton_states
, n
);
8991 for (arc
= first_out_arc (s
);
8993 arc
= next_out_arc (arc
))
8994 if (arc
->to_state
!= s
)
8996 gcc_assert (arc
->insn
->first_insn_with_same_reservs
);
8997 for (ainsn
= arc
->insn
;
8999 ainsn
= ainsn
->next_same_reservs_insn
)
9000 ainsn
->important_p
= TRUE
;
9004 VEC_free (state_t
,heap
, automaton_states
);
9006 /* Create automata sets for the insns. */
9007 for (i
= 0; i
< description
->decls_num
; i
++)
9009 decl
= description
->decls
[i
];
9010 if (decl
->mode
== dm_insn_reserv
)
9012 automata_list_start ();
9013 for (automaton
= description
->first_automaton
;
9015 automaton
= automaton
->next_automaton
)
9016 for (ainsn
= automaton
->ainsn_list
;
9018 ainsn
= ainsn
->next_ainsn
)
9019 if (ainsn
->important_p
9020 && ainsn
->insn_reserv_decl
== DECL_INSN_RESERV (decl
))
9022 automata_list_add (automaton
);
9025 DECL_INSN_RESERV (decl
)->important_automata_list
9026 = automata_list_finish ();
9032 /* The following is top level function to generate automat(a,on) for
9033 fast recognition of pipeline hazards. */
9035 expand_automata (void)
9039 description
= create_node (sizeof (struct description
)
9040 /* One entry for cycle advancing insn. */
9041 + sizeof (decl_t
) * VEC_length (decl_t
, decls
));
9042 description
->decls_num
= VEC_length (decl_t
, decls
);
9043 description
->query_units_num
= 0;
9044 for (i
= 0; i
< description
->decls_num
; i
++)
9046 description
->decls
[i
] = VEC_index (decl_t
, decls
, i
);
9047 if (description
->decls
[i
]->mode
== dm_unit
9048 && DECL_UNIT (description
->decls
[i
])->query_p
)
9049 DECL_UNIT (description
->decls
[i
])->query_num
9050 = description
->query_units_num
++;
9052 all_time
= create_ticker ();
9053 check_time
= create_ticker ();
9055 fprintf (stderr
, "Check description...");
9056 check_all_description ();
9058 fprintf (stderr
, "done\n");
9059 ticker_off (&check_time
);
9060 generation_time
= create_ticker ();
9063 transform_insn_regexps ();
9064 check_unit_distributions_to_automata ();
9069 check_automata_insn_issues ();
9073 form_important_insn_automata_lists ();
9075 ticker_off (&generation_time
);
9078 /* The following is top level function to output PHR and to finish
9079 work with pipeline description translator. */
9081 write_automata (void)
9083 output_time
= create_ticker ();
9085 fprintf (stderr
, "Forming and outputting automata tables...");
9089 fprintf (stderr
, "done\n");
9090 fprintf (stderr
, "Output functions to work with automata...");
9092 output_chip_definitions ();
9093 output_max_insn_queue_index_def ();
9094 output_internal_min_issue_delay_func ();
9095 output_internal_trans_func ();
9096 /* Cache of insn dfa codes: */
9097 fprintf (output_file
, "\nstatic int *%s;\n", DFA_INSN_CODES_VARIABLE_NAME
);
9098 fprintf (output_file
, "\nstatic int %s;\n\n",
9099 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
);
9100 output_dfa_insn_code_func ();
9101 output_trans_func ();
9102 output_min_issue_delay_func ();
9103 output_internal_dead_lock_func ();
9104 output_dead_lock_func ();
9105 output_size_func ();
9106 output_internal_reset_func ();
9107 output_reset_func ();
9108 output_min_insn_conflict_delay_func ();
9109 output_internal_insn_latency_func ();
9110 output_insn_latency_func ();
9111 output_print_reservation_func ();
9112 /* Output function get_cpu_unit_code. */
9113 fprintf (output_file
, "\n#if %s\n\n", CPU_UNITS_QUERY_MACRO_NAME
);
9114 output_get_cpu_unit_code_func ();
9115 output_cpu_unit_reservation_p ();
9116 fprintf (output_file
, "\n#endif /* #if %s */\n\n",
9117 CPU_UNITS_QUERY_MACRO_NAME
);
9118 output_dfa_clean_insn_cache_func ();
9119 output_dfa_start_func ();
9120 output_dfa_finish_func ();
9122 fprintf (stderr
, "done\n");
9125 output_description_file
= fopen (output_description_file_name
, "w");
9126 if (output_description_file
== NULL
)
9128 perror (output_description_file_name
);
9129 exit (FATAL_EXIT_CODE
);
9132 fprintf (stderr
, "Output automata description...");
9133 output_description ();
9134 output_automaton_descriptions ();
9136 fprintf (stderr
, "done\n");
9137 output_statistics (output_description_file
);
9139 output_statistics (stderr
);
9140 ticker_off (&output_time
);
9141 output_time_statistics (stderr
);
9144 finish_automata_lists ();
9147 fprintf (stderr
, "Summary:\n");
9148 fprintf (stderr
, " check time ");
9149 print_active_time (stderr
, check_time
);
9150 fprintf (stderr
, ", generation time ");
9151 print_active_time (stderr
, generation_time
);
9152 fprintf (stderr
, ", all time ");
9153 print_active_time (stderr
, all_time
);
9154 fprintf (stderr
, "\n");
9156 /* Finish all work. */
9157 if (output_description_file
!= NULL
)
9159 fflush (output_description_file
);
9160 if (ferror (stdout
) != 0)
9161 fatal ("Error in writing DFA description file %s",
9162 output_description_file_name
);
9163 fclose (output_description_file
);
9165 finish_automaton_decl_table ();
9166 finish_insn_decl_table ();
9167 finish_decl_table ();
9168 obstack_free (&irp
, NULL
);
9169 if (have_error
&& output_description_file
!= NULL
)
9170 remove (output_description_file_name
);
9174 main (int argc
, char **argv
)
9178 progname
= "genautomata";
9180 if (init_md_reader_args (argc
, argv
) != SUCCESS_EXIT_CODE
)
9181 return (FATAL_EXIT_CODE
);
9183 initiate_automaton_gen (argc
, argv
);
9187 int insn_code_number
;
9189 desc
= read_md_rtx (&lineno
, &insn_code_number
);
9193 switch (GET_CODE (desc
))
9195 case DEFINE_CPU_UNIT
:
9196 gen_cpu_unit (desc
);
9199 case DEFINE_QUERY_CPU_UNIT
:
9200 gen_query_cpu_unit (desc
);
9208 gen_excl_set (desc
);
9212 gen_presence_set (desc
);
9215 case FINAL_PRESENCE_SET
:
9216 gen_final_presence_set (desc
);
9220 gen_absence_set (desc
);
9223 case FINAL_ABSENCE_SET
:
9224 gen_final_absence_set (desc
);
9227 case DEFINE_AUTOMATON
:
9228 gen_automaton (desc
);
9231 case AUTOMATA_OPTION
:
9232 gen_automata_option (desc
);
9235 case DEFINE_RESERVATION
:
9239 case DEFINE_INSN_RESERVATION
:
9240 gen_insn_reserv (desc
);
9249 return FATAL_EXIT_CODE
;
9251 puts ("/* Generated automatically by the program `genautomata'\n"
9252 " from the machine description file `md'. */\n\n"
9253 "#include \"config.h\"\n"
9254 "#include \"system.h\"\n"
9255 "#include \"coretypes.h\"\n"
9256 "#include \"tm.h\"\n"
9257 "#include \"rtl.h\"\n"
9258 "#include \"tm_p.h\"\n"
9259 "#include \"insn-config.h\"\n"
9260 "#include \"recog.h\"\n"
9261 "#include \"regs.h\"\n"
9262 "#include \"real.h\"\n"
9263 "#include \"output.h\"\n"
9264 "#include \"insn-attr.h\"\n"
9265 "#include \"toplev.h\"\n"
9266 "#include \"flags.h\"\n"
9267 "#include \"function.h\"\n");
9269 if (VEC_length (decl_t
, decls
) > 0)
9276 return (ferror (stdout
) != 0 ? FATAL_EXIT_CODE
: SUCCESS_EXIT_CODE
);