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 unsigned int num_out_arcs
;
681 /* The following field is used to form NDFA. */
682 char it_was_placed_in_stack_for_NDFA_forming
;
683 /* The following field is used to form DFA. */
684 char it_was_placed_in_stack_for_DFA_forming
;
685 /* The following field is used to transform NDFA to DFA and DFA
686 minimization. The field value is not NULL if the state is a
687 compound state. In this case the value of field `unit_sets_list'
688 is NULL. All states in the list are in the hash table. The list
689 is formed through field `next_sorted_alt_state'. We should
690 support only one level of nesting state. */
691 alt_state_t component_states
;
692 /* The following field is used for passing graph of states. */
694 /* The list of states belonging to one equivalence class is formed
695 with the aid of the following field. */
696 state_t next_equiv_class_state
;
697 /* The two following fields are used during minimization of a finite
699 int equiv_class_num_1
, equiv_class_num_2
;
700 /* The following field is used during minimization of a finite state
701 automaton. The field value is state corresponding to equivalence
702 class to which given state belongs. */
703 state_t equiv_class_state
;
704 unsigned int *presence_signature
;
705 /* The following field value is the order number of given state.
706 The states in final DFA is enumerated with the aid of the
709 /* This member is used for passing states for searching minimal
712 /* The following member is used to evaluate min issue delay of insn
714 int min_insn_issue_delay
;
715 /* The following member is used to evaluate max issue rate of the
716 processor. The value of the member is maximal length of the path
717 from given state no containing arcs marked by special insn `cycle
719 int longest_path_length
;
722 /* The following macro is an initial value of member
723 `longest_path_length' of a state. */
724 #define UNDEFINED_LONGEST_PATH_LENGTH -1
729 /* The following field refers for the state into which given arc
732 /* The following field describes that the insn issue (with cycle
733 advancing for special insn `cycle advancing' and without cycle
734 advancing for others) makes transition from given state to
735 another given state. */
737 /* The following field value is the next arc output from the same
740 /* List of arcs marked given insn is formed with the following
741 field. The field is used in transformation NDFA -> DFA. */
742 arc_t next_arc_marked_by_insn
;
745 /* The following node type describes a deterministic alternative in
746 non-deterministic state which characterizes cpu unit reservations
747 of automaton insn or which is part of NDFA. */
750 /* The following field is a deterministic state which characterizes
751 unit reservations of the instruction. */
753 /* The following field refers to the next state which characterizes
754 unit reservations of the instruction. */
755 alt_state_t next_alt_state
;
756 /* The following field refers to the next state in sorted list. */
757 alt_state_t next_sorted_alt_state
;
760 /* The following node type describes insn of automaton. They are
761 labels of FA arcs. */
764 /* The following field value is the corresponding insn declaration
766 struct insn_reserv_decl
*insn_reserv_decl
;
767 /* The following field value is the next insn declaration for an
770 /* The following field is states which characterize automaton unit
771 reservations of the instruction. The value can be NULL only if it
772 is special insn `cycle advancing'. */
773 alt_state_t alt_states
;
774 /* The following field is sorted list of states which characterize
775 automaton unit reservations of the instruction. The value can be
776 NULL only if it is special insn `cycle advancing'. */
777 alt_state_t sorted_alt_states
;
778 /* The following field refers the next automaton insn with
779 the same reservations. */
780 ainsn_t next_same_reservs_insn
;
781 /* The following field is flag of the first automaton insn with the
782 same reservations in the declaration list. Only arcs marked such
783 insn is present in the automaton. This significantly decreases
784 memory requirements especially when several automata are
786 char first_insn_with_same_reservs
;
787 /* The following member has nonzero value if there is arc from state of
788 the automaton marked by the ainsn. */
790 /* Cyclic list of insns of an equivalence class is formed with the
791 aid of the following field. */
792 ainsn_t next_equiv_class_insn
;
793 /* The following field value is nonzero if the insn declaration is
794 the first insn declaration with given equivalence number. */
795 char first_ainsn_with_given_equivalence_num
;
796 /* The following field is number of class of equivalence of insns.
797 It is necessary because many insns may be equivalent with the
798 point of view of pipeline hazards. */
799 int insn_equiv_class_num
;
800 /* The following member value is TRUE if there is an arc in the
801 automaton marked by the insn into another state. In other
802 words, the insn can change the state of the automaton. */
806 /* The following describes an automaton for PHR. */
809 /* The following field value is the list of insn declarations for
812 /* The following field value is the corresponding automaton
813 declaration. This field is not NULL only if the automatic
814 partition on automata is not used. */
815 struct automaton_decl
*corresponding_automaton_decl
;
816 /* The following field value is the next automaton. */
817 automaton_t next_automaton
;
818 /* The following field is start state of FA. There are not unit
819 reservations in the state. */
821 /* The following field value is number of equivalence classes of
822 insns (see field `insn_equiv_class_num' in
823 `insn_reserv_decl'). */
824 int insn_equiv_classes_num
;
825 /* The following field value is number of states of final DFA. */
826 int achieved_states_num
;
827 /* The following field value is the order number (0, 1, ...) of
829 int automaton_order_num
;
830 /* The following fields contain statistics information about
831 building automaton. */
832 int NDFA_states_num
, DFA_states_num
;
833 /* The following field value is defined only if minimization of DFA
835 int minimal_DFA_states_num
;
836 int NDFA_arcs_num
, DFA_arcs_num
;
837 /* The following field value is defined only if minimization of DFA
839 int minimal_DFA_arcs_num
;
840 /* The following member refers for two table state x ainsn -> int.
841 ??? Above sentence is incomprehensible. */
842 state_ainsn_table_t trans_table
;
843 /* The following member value is maximal value of min issue delay
844 for insns of the automaton. */
846 /* Usually min issue delay is small and we can place several (2, 4,
847 8) elements in one vector element. So the compression factor can
848 be 1 (no compression), 2, 4, 8. */
849 int min_issue_delay_table_compression_factor
;
850 /* Total number of locked states in this automaton. */
854 /* The following is the element of the list of automata. */
855 struct automata_list_el
857 /* The automaton itself. */
858 automaton_t automaton
;
859 /* The next automata set element. */
860 automata_list_el_t next_automata_list_el
;
863 /* The following structure describes a table state X ainsn -> int(>= 0). */
864 struct state_ainsn_table
866 /* Automaton to which given table belongs. */
867 automaton_t automaton
;
868 /* The following tree vectors for comb vector implementation of the
870 vla_hwint_t comb_vect
;
871 vla_hwint_t check_vect
;
872 vla_hwint_t base_vect
;
873 /* This is simple implementation of the table. */
874 vla_hwint_t full_vect
;
875 /* Minimal and maximal values of the previous vectors. */
876 int min_comb_vect_el_value
, max_comb_vect_el_value
;
877 int min_base_vect_el_value
, max_base_vect_el_value
;
880 /* Macros to access members of unions. Use only them for access to
881 union members of declarations and regexps. */
883 #if defined ENABLE_CHECKING && (GCC_VERSION >= 2007)
885 #define DECL_UNIT(d) __extension__ \
886 (({ struct decl *const _decl = (d); \
887 if (_decl->mode != dm_unit) \
888 decl_mode_check_failed (_decl->mode, "dm_unit", \
889 __FILE__, __LINE__, __FUNCTION__); \
890 &(_decl)->decl.unit; }))
892 #define DECL_BYPASS(d) __extension__ \
893 (({ struct decl *const _decl = (d); \
894 if (_decl->mode != dm_bypass) \
895 decl_mode_check_failed (_decl->mode, "dm_bypass", \
896 __FILE__, __LINE__, __FUNCTION__); \
897 &(_decl)->decl.bypass; }))
899 #define DECL_AUTOMATON(d) __extension__ \
900 (({ struct decl *const _decl = (d); \
901 if (_decl->mode != dm_automaton) \
902 decl_mode_check_failed (_decl->mode, "dm_automaton", \
903 __FILE__, __LINE__, __FUNCTION__); \
904 &(_decl)->decl.automaton; }))
906 #define DECL_EXCL(d) __extension__ \
907 (({ struct decl *const _decl = (d); \
908 if (_decl->mode != dm_excl) \
909 decl_mode_check_failed (_decl->mode, "dm_excl", \
910 __FILE__, __LINE__, __FUNCTION__); \
911 &(_decl)->decl.excl; }))
913 #define DECL_PRESENCE(d) __extension__ \
914 (({ struct decl *const _decl = (d); \
915 if (_decl->mode != dm_presence) \
916 decl_mode_check_failed (_decl->mode, "dm_presence", \
917 __FILE__, __LINE__, __FUNCTION__); \
918 &(_decl)->decl.presence; }))
920 #define DECL_ABSENCE(d) __extension__ \
921 (({ struct decl *const _decl = (d); \
922 if (_decl->mode != dm_absence) \
923 decl_mode_check_failed (_decl->mode, "dm_absence", \
924 __FILE__, __LINE__, __FUNCTION__); \
925 &(_decl)->decl.absence; }))
927 #define DECL_RESERV(d) __extension__ \
928 (({ struct decl *const _decl = (d); \
929 if (_decl->mode != dm_reserv) \
930 decl_mode_check_failed (_decl->mode, "dm_reserv", \
931 __FILE__, __LINE__, __FUNCTION__); \
932 &(_decl)->decl.reserv; }))
934 #define DECL_INSN_RESERV(d) __extension__ \
935 (({ struct decl *const _decl = (d); \
936 if (_decl->mode != dm_insn_reserv) \
937 decl_mode_check_failed (_decl->mode, "dm_insn_reserv", \
938 __FILE__, __LINE__, __FUNCTION__); \
939 &(_decl)->decl.insn_reserv; }))
941 static const char *decl_name (enum decl_mode
);
942 static void decl_mode_check_failed (enum decl_mode
, const char *,
943 const char *, int, const char *)
946 /* Return string representation of declaration mode MODE. */
948 decl_name (enum decl_mode mode
)
950 static char str
[100];
954 else if (mode
== dm_bypass
)
956 else if (mode
== dm_automaton
)
957 return "dm_automaton";
958 else if (mode
== dm_excl
)
960 else if (mode
== dm_presence
)
961 return "dm_presence";
962 else if (mode
== dm_absence
)
964 else if (mode
== dm_reserv
)
966 else if (mode
== dm_insn_reserv
)
967 return "dm_insn_reserv";
969 sprintf (str
, "unknown (%d)", (int) mode
);
973 /* The function prints message about unexpected declaration and finish
976 decl_mode_check_failed (enum decl_mode mode
, const char *expected_mode_str
,
977 const char *file
, int line
, const char *func
)
981 "\n%s: %d: error in %s: DECL check: expected decl %s, have %s\n",
982 file
, line
, func
, expected_mode_str
, decl_name (mode
));
987 #define REGEXP_UNIT(r) __extension__ \
988 (({ struct regexp *const _regexp = (r); \
989 if (_regexp->mode != rm_unit) \
990 regexp_mode_check_failed (_regexp->mode, "rm_unit", \
991 __FILE__, __LINE__, __FUNCTION__); \
992 &(_regexp)->regexp.unit; }))
994 #define REGEXP_RESERV(r) __extension__ \
995 (({ struct regexp *const _regexp = (r); \
996 if (_regexp->mode != rm_reserv) \
997 regexp_mode_check_failed (_regexp->mode, "rm_reserv", \
998 __FILE__, __LINE__, __FUNCTION__); \
999 &(_regexp)->regexp.reserv; }))
1001 #define REGEXP_SEQUENCE(r) __extension__ \
1002 (({ struct regexp *const _regexp = (r); \
1003 if (_regexp->mode != rm_sequence) \
1004 regexp_mode_check_failed (_regexp->mode, "rm_sequence", \
1005 __FILE__, __LINE__, __FUNCTION__); \
1006 &(_regexp)->regexp.sequence; }))
1008 #define REGEXP_REPEAT(r) __extension__ \
1009 (({ struct regexp *const _regexp = (r); \
1010 if (_regexp->mode != rm_repeat) \
1011 regexp_mode_check_failed (_regexp->mode, "rm_repeat", \
1012 __FILE__, __LINE__, __FUNCTION__); \
1013 &(_regexp)->regexp.repeat; }))
1015 #define REGEXP_ALLOF(r) __extension__ \
1016 (({ struct regexp *const _regexp = (r); \
1017 if (_regexp->mode != rm_allof) \
1018 regexp_mode_check_failed (_regexp->mode, "rm_allof", \
1019 __FILE__, __LINE__, __FUNCTION__); \
1020 &(_regexp)->regexp.allof; }))
1022 #define REGEXP_ONEOF(r) __extension__ \
1023 (({ struct regexp *const _regexp = (r); \
1024 if (_regexp->mode != rm_oneof) \
1025 regexp_mode_check_failed (_regexp->mode, "rm_oneof", \
1026 __FILE__, __LINE__, __FUNCTION__); \
1027 &(_regexp)->regexp.oneof; }))
1029 static const char *regexp_name (enum regexp_mode
);
1030 static void regexp_mode_check_failed (enum regexp_mode
, const char *,
1032 const char *) ATTRIBUTE_NORETURN
;
1035 /* Return string representation of regexp mode MODE. */
1037 regexp_name (enum regexp_mode mode
)
1046 return "rm_nothing";
1048 return "rm_sequence";
1060 /* The function prints message about unexpected regexp and finish the
1063 regexp_mode_check_failed (enum regexp_mode mode
,
1064 const char *expected_mode_str
,
1065 const char *file
, int line
, const char *func
)
1069 "\n%s: %d: error in %s: REGEXP check: expected decl %s, have %s\n",
1070 file
, line
, func
, expected_mode_str
, regexp_name (mode
));
1074 #else /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */
1076 #define DECL_UNIT(d) (&(d)->decl.unit)
1077 #define DECL_BYPASS(d) (&(d)->decl.bypass)
1078 #define DECL_AUTOMATON(d) (&(d)->decl.automaton)
1079 #define DECL_EXCL(d) (&(d)->decl.excl)
1080 #define DECL_PRESENCE(d) (&(d)->decl.presence)
1081 #define DECL_ABSENCE(d) (&(d)->decl.absence)
1082 #define DECL_RESERV(d) (&(d)->decl.reserv)
1083 #define DECL_INSN_RESERV(d) (&(d)->decl.insn_reserv)
1085 #define REGEXP_UNIT(r) (&(r)->regexp.unit)
1086 #define REGEXP_RESERV(r) (&(r)->regexp.reserv)
1087 #define REGEXP_SEQUENCE(r) (&(r)->regexp.sequence)
1088 #define REGEXP_REPEAT(r) (&(r)->regexp.repeat)
1089 #define REGEXP_ALLOF(r) (&(r)->regexp.allof)
1090 #define REGEXP_ONEOF(r) (&(r)->regexp.oneof)
1092 #endif /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */
1094 /* Create IR structure (node). */
1096 create_node (size_t size
)
1100 obstack_blank (&irp
, size
);
1101 result
= obstack_base (&irp
);
1102 obstack_finish (&irp
);
1103 /* Default values of members are NULL and zero. */
1104 memset (result
, 0, size
);
1108 /* Copy IR structure (node). */
1110 copy_node (const void *from
, size_t size
)
1112 void *const result
= create_node (size
);
1113 memcpy (result
, from
, size
);
1117 /* The function checks that NAME does not contain quotes (`"'). */
1119 check_name (const char * name
, pos_t pos ATTRIBUTE_UNUSED
)
1123 for (str
= name
; *str
!= '\0'; str
++)
1125 error ("Name `%s' contains quotes", name
);
1129 /* Pointers to all declarations during IR generation are stored in the
1131 static VEC(decl_t
,heap
) *decls
;
1133 /* Given a pointer to a (char *) and a separator, return an alloc'ed
1134 string containing the next separated element, taking parentheses
1135 into account if PAR_FLAG has nonzero value. Advance the pointer to
1136 after the string scanned, or the end-of-string. Return NULL if at
1139 next_sep_el (const char **pstr
, int sep
, int par_flag
)
1146 /* Remove leading whitespaces. */
1147 while (ISSPACE ((int) **pstr
))
1154 for (pars_num
= 0, p
= *pstr
; *p
!= '\0'; p
++)
1156 if (par_flag
&& *p
== '(')
1158 else if (par_flag
&& *p
== ')')
1160 else if (pars_num
== 0 && *p
== sep
)
1162 if (pars_num
== 0 && ISSPACE ((int) *p
))
1166 for (; n_spaces
!= 0; n_spaces
--)
1167 obstack_1grow (&irp
, p
[-n_spaces
]);
1168 obstack_1grow (&irp
, *p
);
1171 obstack_1grow (&irp
, '\0');
1172 out_str
= obstack_base (&irp
);
1173 obstack_finish (&irp
);
1182 /* Given a string and a separator, return the number of separated
1183 elements in it, taking parentheses into account if PAR_FLAG has
1184 nonzero value. Return 0 for the null string, -1 if parentheses is
1187 n_sep_els (const char *s
, int sep
, int par_flag
)
1195 for (pars_num
= 0, n
= 1; *s
; s
++)
1196 if (par_flag
&& *s
== '(')
1198 else if (par_flag
&& *s
== ')')
1200 else if (pars_num
== 0 && *s
== sep
)
1203 return (pars_num
!= 0 ? -1 : n
);
1206 /* Given a string and a separator, return vector of strings which are
1207 elements in the string and number of elements through els_num.
1208 Take parentheses into account if PAREN_P has nonzero value. The
1209 function also inserts the end marker NULL at the end of vector.
1210 Return 0 for the null string, -1 if parentheses are not balanced. */
1212 get_str_vect (const char *str
, int *els_num
, int sep
, int paren_p
)
1219 *els_num
= n_sep_els (str
, sep
, paren_p
);
1222 obstack_blank (&irp
, sizeof (char *) * (*els_num
+ 1));
1223 vect
= (char **) obstack_base (&irp
);
1224 obstack_finish (&irp
);
1226 for (i
= 0; i
< *els_num
; i
++)
1227 vect
[i
] = next_sep_el (pstr
, sep
, paren_p
);
1228 trail
= next_sep_el (pstr
, sep
, paren_p
);
1229 gcc_assert (!trail
);
1234 /* Process a DEFINE_CPU_UNIT.
1236 This gives information about a unit contained in CPU. We fill a
1237 struct unit_decl with information used later by `expand_automata'. */
1239 gen_cpu_unit (rtx def
)
1242 char **str_cpu_units
;
1246 str_cpu_units
= get_str_vect (XSTR (def
, 0), &vect_length
, ',', FALSE
);
1247 if (str_cpu_units
== NULL
)
1248 fatal ("invalid string `%s' in define_cpu_unit", XSTR (def
, 0));
1249 for (i
= 0; i
< vect_length
; i
++)
1251 decl
= create_node (sizeof (struct decl
));
1252 decl
->mode
= dm_unit
;
1254 DECL_UNIT (decl
)->name
= check_name (str_cpu_units
[i
], decl
->pos
);
1255 DECL_UNIT (decl
)->automaton_name
= XSTR (def
, 1);
1256 DECL_UNIT (decl
)->query_p
= 0;
1257 DECL_UNIT (decl
)->min_occ_cycle_num
= -1;
1258 DECL_UNIT (decl
)->in_set_p
= 0;
1259 VEC_safe_push (decl_t
,heap
, decls
, decl
);
1263 /* Process a DEFINE_QUERY_CPU_UNIT.
1265 This gives information about a unit contained in CPU. We fill a
1266 struct unit_decl with information used later by `expand_automata'. */
1268 gen_query_cpu_unit (rtx def
)
1271 char **str_cpu_units
;
1275 str_cpu_units
= get_str_vect (XSTR (def
, 0), &vect_length
, ',',
1277 if (str_cpu_units
== NULL
)
1278 fatal ("invalid string `%s' in define_query_cpu_unit", XSTR (def
, 0));
1279 for (i
= 0; i
< vect_length
; i
++)
1281 decl
= create_node (sizeof (struct decl
));
1282 decl
->mode
= dm_unit
;
1284 DECL_UNIT (decl
)->name
= check_name (str_cpu_units
[i
], decl
->pos
);
1285 DECL_UNIT (decl
)->automaton_name
= XSTR (def
, 1);
1286 DECL_UNIT (decl
)->query_p
= 1;
1287 VEC_safe_push (decl_t
,heap
, decls
, decl
);
1291 /* Process a DEFINE_BYPASS.
1293 This gives information about a unit contained in the CPU. We fill
1294 in a struct bypass_decl with information used later by
1295 `expand_automata'. */
1297 gen_bypass (rtx def
)
1306 out_insns
= get_str_vect (XSTR (def
, 1), &out_length
, ',', FALSE
);
1307 if (out_insns
== NULL
)
1308 fatal ("invalid string `%s' in define_bypass", XSTR (def
, 1));
1309 in_insns
= get_str_vect (XSTR (def
, 2), &in_length
, ',', FALSE
);
1310 if (in_insns
== NULL
)
1311 fatal ("invalid string `%s' in define_bypass", XSTR (def
, 2));
1312 for (i
= 0; i
< out_length
; i
++)
1313 for (j
= 0; j
< in_length
; j
++)
1315 decl
= create_node (sizeof (struct decl
));
1316 decl
->mode
= dm_bypass
;
1318 DECL_BYPASS (decl
)->latency
= XINT (def
, 0);
1319 DECL_BYPASS (decl
)->out_insn_name
= out_insns
[i
];
1320 DECL_BYPASS (decl
)->in_insn_name
= in_insns
[j
];
1321 DECL_BYPASS (decl
)->bypass_guard_name
= XSTR (def
, 3);
1322 VEC_safe_push (decl_t
,heap
, decls
, decl
);
1326 /* Process an EXCLUSION_SET.
1328 This gives information about a cpu unit conflicts. We fill a
1329 struct excl_rel_decl (excl) with information used later by
1330 `expand_automata'. */
1332 gen_excl_set (rtx def
)
1335 char **first_str_cpu_units
;
1336 char **second_str_cpu_units
;
1337 int first_vect_length
;
1342 = get_str_vect (XSTR (def
, 0), &first_vect_length
, ',', FALSE
);
1343 if (first_str_cpu_units
== NULL
)
1344 fatal ("invalid first string `%s' in exclusion_set", XSTR (def
, 0));
1345 second_str_cpu_units
= get_str_vect (XSTR (def
, 1), &length
, ',',
1347 if (second_str_cpu_units
== NULL
)
1348 fatal ("invalid second string `%s' in exclusion_set", XSTR (def
, 1));
1349 length
+= first_vect_length
;
1350 decl
= create_node (sizeof (struct decl
) + (length
- 1) * sizeof (char *));
1351 decl
->mode
= dm_excl
;
1353 DECL_EXCL (decl
)->all_names_num
= length
;
1354 DECL_EXCL (decl
)->first_list_length
= first_vect_length
;
1355 for (i
= 0; i
< length
; i
++)
1356 if (i
< first_vect_length
)
1357 DECL_EXCL (decl
)->names
[i
] = first_str_cpu_units
[i
];
1359 DECL_EXCL (decl
)->names
[i
]
1360 = second_str_cpu_units
[i
- first_vect_length
];
1361 VEC_safe_push (decl_t
,heap
, decls
, decl
);
1364 /* Process a PRESENCE_SET, a FINAL_PRESENCE_SET, an ABSENCE_SET,
1365 FINAL_ABSENCE_SET (it is depended on PRESENCE_P and FINAL_P).
1367 This gives information about a cpu unit reservation requirements.
1368 We fill a struct unit_pattern_rel_decl with information used later
1369 by `expand_automata'. */
1371 gen_presence_absence_set (rtx def
, int presence_p
, int final_p
)
1374 char **str_cpu_units
;
1375 char **str_pattern_lists
;
1376 char ***str_patterns
;
1377 int cpu_units_length
;
1379 int patterns_length
;
1382 str_cpu_units
= get_str_vect (XSTR (def
, 0), &cpu_units_length
, ',',
1384 if (str_cpu_units
== NULL
)
1387 ? "invalid first string `%s' in final_presence_set"
1388 : "invalid first string `%s' in presence_set")
1390 ? "invalid first string `%s' in final_absence_set"
1391 : "invalid first string `%s' in absence_set")),
1393 str_pattern_lists
= get_str_vect (XSTR (def
, 1),
1394 &patterns_length
, ',', FALSE
);
1395 if (str_pattern_lists
== NULL
)
1398 ? "invalid second string `%s' in final_presence_set"
1399 : "invalid second string `%s' in presence_set")
1401 ? "invalid second string `%s' in final_absence_set"
1402 : "invalid second string `%s' in absence_set")), XSTR (def
, 1));
1403 str_patterns
= obstack_alloc (&irp
, patterns_length
* sizeof (char **));
1404 for (i
= 0; i
< patterns_length
; i
++)
1406 str_patterns
[i
] = get_str_vect (str_pattern_lists
[i
],
1407 &length
, ' ', FALSE
);
1408 gcc_assert (str_patterns
[i
]);
1410 decl
= create_node (sizeof (struct decl
));
1414 decl
->mode
= dm_presence
;
1415 DECL_PRESENCE (decl
)->names_num
= cpu_units_length
;
1416 DECL_PRESENCE (decl
)->names
= str_cpu_units
;
1417 DECL_PRESENCE (decl
)->patterns
= str_patterns
;
1418 DECL_PRESENCE (decl
)->patterns_num
= patterns_length
;
1419 DECL_PRESENCE (decl
)->final_p
= final_p
;
1423 decl
->mode
= dm_absence
;
1424 DECL_ABSENCE (decl
)->names_num
= cpu_units_length
;
1425 DECL_ABSENCE (decl
)->names
= str_cpu_units
;
1426 DECL_ABSENCE (decl
)->patterns
= str_patterns
;
1427 DECL_ABSENCE (decl
)->patterns_num
= patterns_length
;
1428 DECL_ABSENCE (decl
)->final_p
= final_p
;
1430 VEC_safe_push (decl_t
,heap
, decls
, decl
);
1433 /* Process a PRESENCE_SET.
1435 This gives information about a cpu unit reservation requirements.
1436 We fill a struct unit_pattern_rel_decl (presence) with information
1437 used later by `expand_automata'. */
1439 gen_presence_set (rtx def
)
1441 gen_presence_absence_set (def
, TRUE
, FALSE
);
1444 /* Process a FINAL_PRESENCE_SET.
1446 This gives information about a cpu unit reservation requirements.
1447 We fill a struct unit_pattern_rel_decl (presence) with information
1448 used later by `expand_automata'. */
1450 gen_final_presence_set (rtx def
)
1452 gen_presence_absence_set (def
, TRUE
, TRUE
);
1455 /* Process an ABSENCE_SET.
1457 This gives information about a cpu unit reservation requirements.
1458 We fill a struct unit_pattern_rel_decl (absence) with information
1459 used later by `expand_automata'. */
1461 gen_absence_set (rtx def
)
1463 gen_presence_absence_set (def
, FALSE
, FALSE
);
1466 /* Process a FINAL_ABSENCE_SET.
1468 This gives information about a cpu unit reservation requirements.
1469 We fill a struct unit_pattern_rel_decl (absence) with information
1470 used later by `expand_automata'. */
1472 gen_final_absence_set (rtx def
)
1474 gen_presence_absence_set (def
, FALSE
, TRUE
);
1477 /* Process a DEFINE_AUTOMATON.
1479 This gives information about a finite state automaton used for
1480 recognizing pipeline hazards. We fill a struct automaton_decl
1481 with information used later by `expand_automata'. */
1483 gen_automaton (rtx def
)
1486 char **str_automata
;
1490 str_automata
= get_str_vect (XSTR (def
, 0), &vect_length
, ',', FALSE
);
1491 if (str_automata
== NULL
)
1492 fatal ("invalid string `%s' in define_automaton", XSTR (def
, 0));
1493 for (i
= 0; i
< vect_length
; i
++)
1495 decl
= create_node (sizeof (struct decl
));
1496 decl
->mode
= dm_automaton
;
1498 DECL_AUTOMATON (decl
)->name
= check_name (str_automata
[i
], decl
->pos
);
1499 VEC_safe_push (decl_t
,heap
, decls
, decl
);
1503 /* Process an AUTOMATA_OPTION.
1505 This gives information how to generate finite state automaton used
1506 for recognizing pipeline hazards. */
1508 gen_automata_option (rtx def
)
1510 if (strcmp (XSTR (def
, 0), NO_MINIMIZATION_OPTION
+ 1) == 0)
1511 no_minimization_flag
= 1;
1512 else if (strcmp (XSTR (def
, 0), TIME_OPTION
+ 1) == 0)
1514 else if (strcmp (XSTR (def
, 0), V_OPTION
+ 1) == 0)
1516 else if (strcmp (XSTR (def
, 0), W_OPTION
+ 1) == 0)
1518 else if (strcmp (XSTR (def
, 0), NDFA_OPTION
+ 1) == 0)
1520 else if (strcmp (XSTR (def
, 0), PROGRESS_OPTION
+ 1) == 0)
1523 fatal ("invalid option `%s' in automata_option", XSTR (def
, 0));
1526 /* Name in reservation to denote absence reservation. */
1527 #define NOTHING_NAME "nothing"
1529 /* The following string contains original reservation string being
1531 static const char *reserv_str
;
1533 /* Parse an element in STR. */
1535 gen_regexp_el (const char *str
)
1544 if (str
[len
- 1] != ')')
1545 fatal ("garbage after ) in reservation `%s'", reserv_str
);
1546 dstr
= alloca (len
- 1);
1547 memcpy (dstr
, str
+ 1, len
- 2);
1548 dstr
[len
-2] = '\0';
1549 regexp
= gen_regexp_sequence (dstr
);
1551 else if (strcmp (str
, NOTHING_NAME
) == 0)
1553 regexp
= create_node (sizeof (struct decl
));
1554 regexp
->mode
= rm_nothing
;
1558 regexp
= create_node (sizeof (struct decl
));
1559 regexp
->mode
= rm_unit
;
1560 REGEXP_UNIT (regexp
)->name
= str
;
1565 /* Parse construction `repeat' in STR. */
1567 gen_regexp_repeat (const char *str
)
1575 repeat_vect
= get_str_vect (str
, &els_num
, '*', TRUE
);
1576 if (repeat_vect
== NULL
)
1577 fatal ("invalid `%s' in reservation `%s'", str
, reserv_str
);
1580 regexp
= gen_regexp_el (repeat_vect
[0]);
1581 for (i
= 1; i
< els_num
; i
++)
1583 repeat
= create_node (sizeof (struct regexp
));
1584 repeat
->mode
= rm_repeat
;
1585 REGEXP_REPEAT (repeat
)->regexp
= regexp
;
1586 REGEXP_REPEAT (repeat
)->repeat_num
= atoi (repeat_vect
[i
]);
1587 if (REGEXP_REPEAT (repeat
)->repeat_num
<= 1)
1588 fatal ("repetition `%s' <= 1 in reservation `%s'",
1595 return gen_regexp_el (str
);
1598 /* Parse reservation STR which possibly contains separator '+'. */
1600 gen_regexp_allof (const char *str
)
1607 allof_vect
= get_str_vect (str
, &els_num
, '+', TRUE
);
1608 if (allof_vect
== NULL
)
1609 fatal ("invalid `%s' in reservation `%s'", str
, reserv_str
);
1612 allof
= create_node (sizeof (struct regexp
)
1613 + sizeof (regexp_t
) * (els_num
- 1));
1614 allof
->mode
= rm_allof
;
1615 REGEXP_ALLOF (allof
)->regexps_num
= els_num
;
1616 for (i
= 0; i
< els_num
; i
++)
1617 REGEXP_ALLOF (allof
)->regexps
[i
] = gen_regexp_repeat (allof_vect
[i
]);
1621 return gen_regexp_repeat (str
);
1624 /* Parse reservation STR which possibly contains separator '|'. */
1626 gen_regexp_oneof (const char *str
)
1633 oneof_vect
= get_str_vect (str
, &els_num
, '|', TRUE
);
1634 if (oneof_vect
== NULL
)
1635 fatal ("invalid `%s' in reservation `%s'", str
, reserv_str
);
1638 oneof
= create_node (sizeof (struct regexp
)
1639 + sizeof (regexp_t
) * (els_num
- 1));
1640 oneof
->mode
= rm_oneof
;
1641 REGEXP_ONEOF (oneof
)->regexps_num
= els_num
;
1642 for (i
= 0; i
< els_num
; i
++)
1643 REGEXP_ONEOF (oneof
)->regexps
[i
] = gen_regexp_allof (oneof_vect
[i
]);
1647 return gen_regexp_allof (str
);
1650 /* Parse reservation STR which possibly contains separator ','. */
1652 gen_regexp_sequence (const char *str
)
1655 char **sequence_vect
;
1659 sequence_vect
= get_str_vect (str
, &els_num
, ',', TRUE
);
1662 sequence
= create_node (sizeof (struct regexp
)
1663 + sizeof (regexp_t
) * (els_num
- 1));
1664 sequence
->mode
= rm_sequence
;
1665 REGEXP_SEQUENCE (sequence
)->regexps_num
= els_num
;
1666 for (i
= 0; i
< els_num
; i
++)
1667 REGEXP_SEQUENCE (sequence
)->regexps
[i
]
1668 = gen_regexp_oneof (sequence_vect
[i
]);
1672 return gen_regexp_oneof (str
);
1675 /* Parse construction reservation STR. */
1677 gen_regexp (const char *str
)
1680 return gen_regexp_sequence (str
);;
1683 /* Process a DEFINE_RESERVATION.
1685 This gives information about a reservation of cpu units. We fill
1686 in a struct reserv_decl with information used later by
1687 `expand_automata'. */
1689 gen_reserv (rtx def
)
1693 decl
= create_node (sizeof (struct decl
));
1694 decl
->mode
= dm_reserv
;
1696 DECL_RESERV (decl
)->name
= check_name (XSTR (def
, 0), decl
->pos
);
1697 DECL_RESERV (decl
)->regexp
= gen_regexp (XSTR (def
, 1));
1698 VEC_safe_push (decl_t
,heap
, decls
, decl
);
1701 /* Process a DEFINE_INSN_RESERVATION.
1703 This gives information about the reservation of cpu units by an
1704 insn. We fill a struct insn_reserv_decl with information used
1705 later by `expand_automata'. */
1707 gen_insn_reserv (rtx def
)
1711 decl
= create_node (sizeof (struct decl
));
1712 decl
->mode
= dm_insn_reserv
;
1714 DECL_INSN_RESERV (decl
)->name
1715 = check_name (XSTR (def
, 0), decl
->pos
);
1716 DECL_INSN_RESERV (decl
)->default_latency
= XINT (def
, 1);
1717 DECL_INSN_RESERV (decl
)->condexp
= XEXP (def
, 2);
1718 DECL_INSN_RESERV (decl
)->regexp
= gen_regexp (XSTR (def
, 3));
1719 VEC_safe_push (decl_t
,heap
, decls
, decl
);
1724 /* The function evaluates hash value (0..UINT_MAX) of string. */
1726 string_hash (const char *string
)
1730 for (result
= i
= 0;*string
++ != '\0'; i
++)
1731 result
+= ((unsigned char) *string
<< (i
% CHAR_BIT
));
1737 /* This page contains abstract data `table of automaton declarations'.
1738 Elements of the table is nodes representing automaton declarations.
1739 Key of the table elements is name of given automaton. Remember
1740 that automaton names have own space. */
1742 /* The function evaluates hash value of an automaton declaration. The
1743 function is used by abstract data `hashtab'. The function returns
1744 hash value (0..UINT_MAX) of given automaton declaration. */
1746 automaton_decl_hash (const void *automaton_decl
)
1748 const decl_t decl
= (decl_t
) automaton_decl
;
1750 gcc_assert (decl
->mode
!= dm_automaton
1751 || DECL_AUTOMATON (decl
)->name
);
1752 return string_hash (DECL_AUTOMATON (decl
)->name
);
1755 /* The function tests automaton declarations on equality of their
1756 keys. The function is used by abstract data `hashtab'. The
1757 function returns 1 if the declarations have the same key, 0
1760 automaton_decl_eq_p (const void* automaton_decl_1
,
1761 const void* automaton_decl_2
)
1763 const decl_t decl1
= (decl_t
) automaton_decl_1
;
1764 const decl_t decl2
= (decl_t
) automaton_decl_2
;
1766 gcc_assert (decl1
->mode
== dm_automaton
1767 && DECL_AUTOMATON (decl1
)->name
1768 && decl2
->mode
== dm_automaton
1769 && DECL_AUTOMATON (decl2
)->name
);
1770 return strcmp (DECL_AUTOMATON (decl1
)->name
,
1771 DECL_AUTOMATON (decl2
)->name
) == 0;
1774 /* The automaton declaration table itself is represented by the
1775 following variable. */
1776 static htab_t automaton_decl_table
;
1778 /* The function inserts automaton declaration into the table. The
1779 function does nothing if an automaton declaration with the same key
1780 exists already in the table. The function returns automaton
1781 declaration node in the table with the same key as given automaton
1782 declaration node. */
1784 insert_automaton_decl (decl_t automaton_decl
)
1788 entry_ptr
= htab_find_slot (automaton_decl_table
, automaton_decl
, 1);
1789 if (*entry_ptr
== NULL
)
1790 *entry_ptr
= (void *) automaton_decl
;
1791 return (decl_t
) *entry_ptr
;
1794 /* The following variable value is node representing automaton
1795 declaration. The node used for searching automaton declaration
1797 static struct decl work_automaton_decl
;
1799 /* The function searches for automaton declaration in the table with
1800 the same key as node representing name of the automaton
1801 declaration. The function returns node found in the table, NULL if
1802 such node does not exist in the table. */
1804 find_automaton_decl (const char *name
)
1808 work_automaton_decl
.mode
= dm_automaton
;
1809 DECL_AUTOMATON (&work_automaton_decl
)->name
= name
;
1810 entry
= htab_find (automaton_decl_table
, &work_automaton_decl
);
1811 return (decl_t
) entry
;
1814 /* The function creates empty automaton declaration table and node
1815 representing automaton declaration and used for searching automaton
1816 declaration with given name. The function must be called only once
1817 before any work with the automaton declaration table. */
1819 initiate_automaton_decl_table (void)
1821 work_automaton_decl
.mode
= dm_automaton
;
1822 automaton_decl_table
= htab_create (10, automaton_decl_hash
,
1823 automaton_decl_eq_p
, (htab_del
) 0);
1826 /* The function deletes the automaton declaration table. Only call of
1827 function `initiate_automaton_decl_table' is possible immediately
1828 after this function call. */
1830 finish_automaton_decl_table (void)
1832 htab_delete (automaton_decl_table
);
1837 /* This page contains abstract data `table of insn declarations'.
1838 Elements of the table is nodes representing insn declarations. Key
1839 of the table elements is name of given insn (in corresponding
1840 define_insn_reservation). Remember that insn names have own
1843 /* The function evaluates hash value of an insn declaration. The
1844 function is used by abstract data `hashtab'. The function returns
1845 hash value (0..UINT_MAX) of given insn declaration. */
1847 insn_decl_hash (const void *insn_decl
)
1849 const decl_t decl
= (decl_t
) insn_decl
;
1851 gcc_assert (decl
->mode
== dm_insn_reserv
1852 && DECL_INSN_RESERV (decl
)->name
);
1853 return string_hash (DECL_INSN_RESERV (decl
)->name
);
1856 /* The function tests insn declarations on equality of their keys.
1857 The function is used by abstract data `hashtab'. The function
1858 returns 1 if declarations have the same key, 0 otherwise. */
1860 insn_decl_eq_p (const void *insn_decl_1
, const void *insn_decl_2
)
1862 const decl_t decl1
= (decl_t
) insn_decl_1
;
1863 const decl_t decl2
= (decl_t
) insn_decl_2
;
1865 gcc_assert (decl1
->mode
== dm_insn_reserv
1866 && DECL_INSN_RESERV (decl1
)->name
1867 && decl2
->mode
== dm_insn_reserv
1868 && DECL_INSN_RESERV (decl2
)->name
);
1869 return strcmp (DECL_INSN_RESERV (decl1
)->name
,
1870 DECL_INSN_RESERV (decl2
)->name
) == 0;
1873 /* The insn declaration table itself is represented by the following
1874 variable. The table does not contain insn reservation
1876 static htab_t insn_decl_table
;
1878 /* The function inserts insn declaration into the table. The function
1879 does nothing if an insn declaration with the same key exists
1880 already in the table. The function returns insn declaration node
1881 in the table with the same key as given insn declaration node. */
1883 insert_insn_decl (decl_t insn_decl
)
1887 entry_ptr
= htab_find_slot (insn_decl_table
, insn_decl
, 1);
1888 if (*entry_ptr
== NULL
)
1889 *entry_ptr
= (void *) insn_decl
;
1890 return (decl_t
) *entry_ptr
;
1893 /* The following variable value is node representing insn reservation
1894 declaration. The node used for searching insn reservation
1895 declaration with given name. */
1896 static struct decl work_insn_decl
;
1898 /* The function searches for insn reservation declaration in the table
1899 with the same key as node representing name of the insn reservation
1900 declaration. The function returns node found in the table, NULL if
1901 such node does not exist in the table. */
1903 find_insn_decl (const char *name
)
1907 work_insn_decl
.mode
= dm_insn_reserv
;
1908 DECL_INSN_RESERV (&work_insn_decl
)->name
= name
;
1909 entry
= htab_find (insn_decl_table
, &work_insn_decl
);
1910 return (decl_t
) entry
;
1913 /* The function creates empty insn declaration table and node
1914 representing insn declaration and used for searching insn
1915 declaration with given name. The function must be called only once
1916 before any work with the insn declaration table. */
1918 initiate_insn_decl_table (void)
1920 work_insn_decl
.mode
= dm_insn_reserv
;
1921 insn_decl_table
= htab_create (10, insn_decl_hash
, insn_decl_eq_p
,
1925 /* The function deletes the insn declaration table. Only call of
1926 function `initiate_insn_decl_table' is possible immediately after
1927 this function call. */
1929 finish_insn_decl_table (void)
1931 htab_delete (insn_decl_table
);
1936 /* This page contains abstract data `table of declarations'. Elements
1937 of the table is nodes representing declarations (of units and
1938 reservations). Key of the table elements is names of given
1941 /* The function evaluates hash value of a declaration. The function
1942 is used by abstract data `hashtab'. The function returns hash
1943 value (0..UINT_MAX) of given declaration. */
1945 decl_hash (const void *decl
)
1947 const decl_t d
= (const decl_t
) decl
;
1949 gcc_assert ((d
->mode
== dm_unit
&& DECL_UNIT (d
)->name
)
1950 || (d
->mode
== dm_reserv
&& DECL_RESERV (d
)->name
));
1951 return string_hash (d
->mode
== dm_unit
1952 ? DECL_UNIT (d
)->name
: DECL_RESERV (d
)->name
);
1955 /* The function tests declarations on equality of their keys. The
1956 function is used by abstract data 'hashtab'. The function
1957 returns 1 if the declarations have the same key, 0 otherwise. */
1959 decl_eq_p (const void *decl_1
, const void *decl_2
)
1961 const decl_t d1
= (const decl_t
) decl_1
;
1962 const decl_t d2
= (const decl_t
) decl_2
;
1964 gcc_assert ((d1
->mode
== dm_unit
&& DECL_UNIT (d1
)->name
)
1965 || (d1
->mode
== dm_reserv
&& DECL_RESERV (d1
)->name
));
1966 gcc_assert ((d2
->mode
== dm_unit
&& DECL_UNIT (d2
)->name
)
1967 || (d2
->mode
== dm_reserv
&& DECL_RESERV (d2
)->name
));
1968 return strcmp ((d1
->mode
== dm_unit
1969 ? DECL_UNIT (d1
)->name
: DECL_RESERV (d1
)->name
),
1970 (d2
->mode
== dm_unit
1971 ? DECL_UNIT (d2
)->name
: DECL_RESERV (d2
)->name
)) == 0;
1974 /* The declaration table itself is represented by the following
1976 static htab_t decl_table
;
1978 /* The function inserts declaration into the table. The function does
1979 nothing if a declaration with the same key exists already in the
1980 table. The function returns declaration node in the table with the
1981 same key as given declaration node. */
1984 insert_decl (decl_t decl
)
1988 entry_ptr
= htab_find_slot (decl_table
, decl
, 1);
1989 if (*entry_ptr
== NULL
)
1990 *entry_ptr
= (void *) decl
;
1991 return (decl_t
) *entry_ptr
;
1994 /* The following variable value is node representing declaration. The
1995 node used for searching declaration with given name. */
1996 static struct decl work_decl
;
1998 /* The function searches for declaration in the table with the same
1999 key as node representing name of the declaration. The function
2000 returns node found in the table, NULL if such node does not exist
2003 find_decl (const char *name
)
2007 work_decl
.mode
= dm_unit
;
2008 DECL_UNIT (&work_decl
)->name
= name
;
2009 entry
= htab_find (decl_table
, &work_decl
);
2010 return (decl_t
) entry
;
2013 /* The function creates empty declaration table and node representing
2014 declaration and used for searching declaration with given name.
2015 The function must be called only once before any work with the
2016 declaration table. */
2018 initiate_decl_table (void)
2020 work_decl
.mode
= dm_unit
;
2021 decl_table
= htab_create (10, decl_hash
, decl_eq_p
, (htab_del
) 0);
2024 /* The function deletes the declaration table. Only call of function
2025 `initiate_declaration_table' is possible immediately after this
2028 finish_decl_table (void)
2030 htab_delete (decl_table
);
2035 /* This page contains checker of pipeline hazard description. */
2037 /* Checking NAMES in an exclusion clause vector and returning formed
2038 unit_set_el_list. */
2039 static unit_set_el_t
2040 process_excls (char **names
, int num
, pos_t excl_pos ATTRIBUTE_UNUSED
)
2042 unit_set_el_t el_list
;
2043 unit_set_el_t last_el
;
2044 unit_set_el_t new_el
;
2045 decl_t decl_in_table
;
2050 for (i
= 0; i
< num
; i
++)
2052 decl_in_table
= find_decl (names
[i
]);
2053 if (decl_in_table
== NULL
)
2054 error ("unit `%s' in exclusion is not declared", names
[i
]);
2055 else if (decl_in_table
->mode
!= dm_unit
)
2056 error ("`%s' in exclusion is not unit", names
[i
]);
2059 new_el
= create_node (sizeof (struct unit_set_el
));
2060 new_el
->unit_decl
= DECL_UNIT (decl_in_table
);
2061 new_el
->next_unit_set_el
= NULL
;
2062 if (last_el
== NULL
)
2063 el_list
= last_el
= new_el
;
2066 last_el
->next_unit_set_el
= new_el
;
2067 last_el
= last_el
->next_unit_set_el
;
2074 /* The function adds each element from SOURCE_LIST to the exclusion
2075 list of the each element from DEST_LIST. Checking situation "unit
2076 excludes itself". */
2078 add_excls (unit_set_el_t dest_list
, unit_set_el_t source_list
,
2079 pos_t excl_pos ATTRIBUTE_UNUSED
)
2083 unit_set_el_t curr_el
;
2084 unit_set_el_t prev_el
;
2087 for (dst
= dest_list
; dst
!= NULL
; dst
= dst
->next_unit_set_el
)
2088 for (src
= source_list
; src
!= NULL
; src
= src
->next_unit_set_el
)
2090 if (dst
->unit_decl
== src
->unit_decl
)
2092 error ("unit `%s' excludes itself", src
->unit_decl
->name
);
2095 if (dst
->unit_decl
->automaton_name
!= NULL
2096 && src
->unit_decl
->automaton_name
!= NULL
2097 && strcmp (dst
->unit_decl
->automaton_name
,
2098 src
->unit_decl
->automaton_name
) != 0)
2100 error ("units `%s' and `%s' in exclusion set belong to different automata",
2101 src
->unit_decl
->name
, dst
->unit_decl
->name
);
2104 for (curr_el
= dst
->unit_decl
->excl_list
, prev_el
= NULL
;
2106 prev_el
= curr_el
, curr_el
= curr_el
->next_unit_set_el
)
2107 if (curr_el
->unit_decl
== src
->unit_decl
)
2109 if (curr_el
== NULL
)
2111 /* Element not found - insert. */
2112 copy
= copy_node (src
, sizeof (*src
));
2113 copy
->next_unit_set_el
= NULL
;
2114 if (prev_el
== NULL
)
2115 dst
->unit_decl
->excl_list
= copy
;
2117 prev_el
->next_unit_set_el
= copy
;
2122 /* Checking NAMES in presence/absence clause and returning the
2123 formed unit_set_el_list. The function is called only after
2124 processing all exclusion sets. */
2125 static unit_set_el_t
2126 process_presence_absence_names (char **names
, int num
,
2127 pos_t req_pos ATTRIBUTE_UNUSED
,
2128 int presence_p
, int final_p
)
2130 unit_set_el_t el_list
;
2131 unit_set_el_t last_el
;
2132 unit_set_el_t new_el
;
2133 decl_t decl_in_table
;
2138 for (i
= 0; i
< num
; i
++)
2140 decl_in_table
= find_decl (names
[i
]);
2141 if (decl_in_table
== NULL
)
2144 ? "unit `%s' in final presence set is not declared"
2145 : "unit `%s' in presence set is not declared")
2147 ? "unit `%s' in final absence set is not declared"
2148 : "unit `%s' in absence set is not declared")), names
[i
]);
2149 else if (decl_in_table
->mode
!= dm_unit
)
2152 ? "`%s' in final presence set is not unit"
2153 : "`%s' in presence set is not unit")
2155 ? "`%s' in final absence set is not unit"
2156 : "`%s' in absence set is not unit")), names
[i
]);
2159 new_el
= create_node (sizeof (struct unit_set_el
));
2160 new_el
->unit_decl
= DECL_UNIT (decl_in_table
);
2161 new_el
->next_unit_set_el
= NULL
;
2162 if (last_el
== NULL
)
2163 el_list
= last_el
= new_el
;
2166 last_el
->next_unit_set_el
= new_el
;
2167 last_el
= last_el
->next_unit_set_el
;
2174 /* Checking NAMES in patterns of a presence/absence clause and
2175 returning the formed pattern_set_el_list. The function is called
2176 only after processing all exclusion sets. */
2177 static pattern_set_el_t
2178 process_presence_absence_patterns (char ***patterns
, int num
,
2179 pos_t req_pos ATTRIBUTE_UNUSED
,
2180 int presence_p
, int final_p
)
2182 pattern_set_el_t el_list
;
2183 pattern_set_el_t last_el
;
2184 pattern_set_el_t new_el
;
2185 decl_t decl_in_table
;
2190 for (i
= 0; i
< num
; i
++)
2192 for (j
= 0; patterns
[i
] [j
] != NULL
; j
++)
2194 new_el
= create_node (sizeof (struct pattern_set_el
)
2195 + sizeof (struct unit_decl
*) * j
);
2197 = (struct unit_decl
**) ((char *) new_el
2198 + sizeof (struct pattern_set_el
));
2199 new_el
->next_pattern_set_el
= NULL
;
2200 if (last_el
== NULL
)
2201 el_list
= last_el
= new_el
;
2204 last_el
->next_pattern_set_el
= new_el
;
2205 last_el
= last_el
->next_pattern_set_el
;
2207 new_el
->units_num
= 0;
2208 for (j
= 0; patterns
[i
] [j
] != NULL
; j
++)
2210 decl_in_table
= find_decl (patterns
[i
] [j
]);
2211 if (decl_in_table
== NULL
)
2214 ? "unit `%s' in final presence set is not declared"
2215 : "unit `%s' in presence set is not declared")
2217 ? "unit `%s' in final absence set is not declared"
2218 : "unit `%s' in absence set is not declared")),
2220 else if (decl_in_table
->mode
!= dm_unit
)
2223 ? "`%s' in final presence set is not unit"
2224 : "`%s' in presence set is not unit")
2226 ? "`%s' in final absence set is not unit"
2227 : "`%s' in absence set is not unit")),
2231 new_el
->unit_decls
[new_el
->units_num
]
2232 = DECL_UNIT (decl_in_table
);
2233 new_el
->units_num
++;
2240 /* The function adds each element from PATTERN_LIST to presence (if
2241 PRESENCE_P) or absence list of the each element from DEST_LIST.
2242 Checking situations "unit requires own absence", and "unit excludes
2243 and requires presence of ...", "unit requires absence and presence
2244 of ...", "units in (final) presence set belong to different
2245 automata", and "units in (final) absence set belong to different
2246 automata". Remember that we process absence sets only after all
2249 add_presence_absence (unit_set_el_t dest_list
,
2250 pattern_set_el_t pattern_list
,
2251 pos_t req_pos ATTRIBUTE_UNUSED
,
2252 int presence_p
, int final_p
)
2255 pattern_set_el_t pat
;
2256 struct unit_decl
*unit
;
2257 unit_set_el_t curr_excl_el
;
2258 pattern_set_el_t curr_pat_el
;
2259 pattern_set_el_t prev_el
;
2260 pattern_set_el_t copy
;
2264 for (dst
= dest_list
; dst
!= NULL
; dst
= dst
->next_unit_set_el
)
2265 for (pat
= pattern_list
; pat
!= NULL
; pat
= pat
->next_pattern_set_el
)
2267 for (i
= 0; i
< pat
->units_num
; i
++)
2269 unit
= pat
->unit_decls
[i
];
2270 if (dst
->unit_decl
== unit
&& pat
->units_num
== 1 && !presence_p
)
2272 error ("unit `%s' requires own absence", unit
->name
);
2275 if (dst
->unit_decl
->automaton_name
!= NULL
2276 && unit
->automaton_name
!= NULL
2277 && strcmp (dst
->unit_decl
->automaton_name
,
2278 unit
->automaton_name
) != 0)
2282 ? "units `%s' and `%s' in final presence set belong to different automata"
2283 : "units `%s' and `%s' in presence set belong to different automata")
2285 ? "units `%s' and `%s' in final absence set belong to different automata"
2286 : "units `%s' and `%s' in absence set belong to different automata")),
2287 unit
->name
, dst
->unit_decl
->name
);
2292 for (curr_excl_el
= dst
->unit_decl
->excl_list
;
2293 curr_excl_el
!= NULL
;
2294 curr_excl_el
= curr_excl_el
->next_unit_set_el
)
2296 if (unit
== curr_excl_el
->unit_decl
&& pat
->units_num
== 1)
2300 error ("unit `%s' excludes and requires presence of `%s'",
2301 dst
->unit_decl
->name
, unit
->name
);
2306 (0, "unit `%s' excludes and requires presence of `%s'",
2307 dst
->unit_decl
->name
, unit
->name
);
2310 else if (pat
->units_num
== 1)
2311 for (curr_pat_el
= dst
->unit_decl
->presence_list
;
2312 curr_pat_el
!= NULL
;
2313 curr_pat_el
= curr_pat_el
->next_pattern_set_el
)
2314 if (curr_pat_el
->units_num
== 1
2315 && unit
== curr_pat_el
->unit_decls
[0])
2320 ("unit `%s' requires absence and presence of `%s'",
2321 dst
->unit_decl
->name
, unit
->name
);
2326 (0, "unit `%s' requires absence and presence of `%s'",
2327 dst
->unit_decl
->name
, unit
->name
);
2331 for (prev_el
= (presence_p
2333 ? dst
->unit_decl
->final_presence_list
2334 : dst
->unit_decl
->final_presence_list
)
2336 ? dst
->unit_decl
->final_absence_list
2337 : dst
->unit_decl
->absence_list
));
2338 prev_el
!= NULL
&& prev_el
->next_pattern_set_el
!= NULL
;
2339 prev_el
= prev_el
->next_pattern_set_el
)
2341 copy
= copy_node (pat
, sizeof (*pat
));
2342 copy
->next_pattern_set_el
= NULL
;
2343 if (prev_el
== NULL
)
2348 dst
->unit_decl
->final_presence_list
= copy
;
2350 dst
->unit_decl
->presence_list
= copy
;
2353 dst
->unit_decl
->final_absence_list
= copy
;
2355 dst
->unit_decl
->absence_list
= copy
;
2358 prev_el
->next_pattern_set_el
= copy
;
2365 /* The function searches for bypass with given IN_INSN_RESERV in given
2367 static struct bypass_decl
*
2368 find_bypass (struct bypass_decl
*bypass_list
,
2369 struct insn_reserv_decl
*in_insn_reserv
)
2371 struct bypass_decl
*bypass
;
2373 for (bypass
= bypass_list
; bypass
!= NULL
; bypass
= bypass
->next
)
2374 if (bypass
->in_insn_reserv
== in_insn_reserv
)
2379 /* The function processes pipeline description declarations, checks
2380 their correctness, and forms exclusion/presence/absence sets. */
2382 process_decls (void)
2385 decl_t automaton_decl
;
2386 decl_t decl_in_table
;
2387 decl_t out_insn_reserv
;
2388 decl_t in_insn_reserv
;
2389 struct bypass_decl
*bypass
;
2390 int automaton_presence
;
2393 /* Checking repeated automata declarations. */
2394 automaton_presence
= 0;
2395 for (i
= 0; i
< description
->decls_num
; i
++)
2397 decl
= description
->decls
[i
];
2398 if (decl
->mode
== dm_automaton
)
2400 automaton_presence
= 1;
2401 decl_in_table
= insert_automaton_decl (decl
);
2402 if (decl_in_table
!= decl
)
2405 error ("repeated declaration of automaton `%s'",
2406 DECL_AUTOMATON (decl
)->name
);
2408 warning (0, "repeated declaration of automaton `%s'",
2409 DECL_AUTOMATON (decl
)->name
);
2413 /* Checking undeclared automata, repeated declarations (except for
2414 automata) and correctness of their attributes (insn latency times
2416 for (i
= 0; i
< description
->decls_num
; i
++)
2418 decl
= description
->decls
[i
];
2419 if (decl
->mode
== dm_insn_reserv
)
2421 if (DECL_INSN_RESERV (decl
)->default_latency
< 0)
2422 error ("define_insn_reservation `%s' has negative latency time",
2423 DECL_INSN_RESERV (decl
)->name
);
2424 DECL_INSN_RESERV (decl
)->insn_num
= description
->insns_num
;
2425 description
->insns_num
++;
2426 decl_in_table
= insert_insn_decl (decl
);
2427 if (decl_in_table
!= decl
)
2428 error ("`%s' is already used as insn reservation name",
2429 DECL_INSN_RESERV (decl
)->name
);
2431 else if (decl
->mode
== dm_bypass
)
2433 if (DECL_BYPASS (decl
)->latency
< 0)
2434 error ("define_bypass `%s - %s' has negative latency time",
2435 DECL_BYPASS (decl
)->out_insn_name
,
2436 DECL_BYPASS (decl
)->in_insn_name
);
2438 else if (decl
->mode
== dm_unit
|| decl
->mode
== dm_reserv
)
2440 if (decl
->mode
== dm_unit
)
2442 DECL_UNIT (decl
)->automaton_decl
= NULL
;
2443 if (DECL_UNIT (decl
)->automaton_name
!= NULL
)
2446 = find_automaton_decl (DECL_UNIT (decl
)->automaton_name
);
2447 if (automaton_decl
== NULL
)
2448 error ("automaton `%s' is not declared",
2449 DECL_UNIT (decl
)->automaton_name
);
2452 DECL_AUTOMATON (automaton_decl
)->automaton_is_used
= 1;
2453 DECL_UNIT (decl
)->automaton_decl
2454 = DECL_AUTOMATON (automaton_decl
);
2457 else if (automaton_presence
)
2458 error ("define_unit `%s' without automaton when one defined",
2459 DECL_UNIT (decl
)->name
);
2460 DECL_UNIT (decl
)->unit_num
= description
->units_num
;
2461 description
->units_num
++;
2462 if (strcmp (DECL_UNIT (decl
)->name
, NOTHING_NAME
) == 0)
2464 error ("`%s' is declared as cpu unit", NOTHING_NAME
);
2467 decl_in_table
= find_decl (DECL_UNIT (decl
)->name
);
2471 if (strcmp (DECL_RESERV (decl
)->name
, NOTHING_NAME
) == 0)
2473 error ("`%s' is declared as cpu reservation", NOTHING_NAME
);
2476 decl_in_table
= find_decl (DECL_RESERV (decl
)->name
);
2478 if (decl_in_table
== NULL
)
2479 decl_in_table
= insert_decl (decl
);
2482 if (decl
->mode
== dm_unit
)
2483 error ("repeated declaration of unit `%s'",
2484 DECL_UNIT (decl
)->name
);
2486 error ("repeated declaration of reservation `%s'",
2487 DECL_RESERV (decl
)->name
);
2491 /* Check bypasses and form list of bypasses for each (output)
2493 for (i
= 0; i
< description
->decls_num
; i
++)
2495 decl
= description
->decls
[i
];
2496 if (decl
->mode
== dm_bypass
)
2498 out_insn_reserv
= find_insn_decl (DECL_BYPASS (decl
)->out_insn_name
);
2499 in_insn_reserv
= find_insn_decl (DECL_BYPASS (decl
)->in_insn_name
);
2500 if (out_insn_reserv
== NULL
)
2501 error ("there is no insn reservation `%s'",
2502 DECL_BYPASS (decl
)->out_insn_name
);
2503 else if (in_insn_reserv
== NULL
)
2504 error ("there is no insn reservation `%s'",
2505 DECL_BYPASS (decl
)->in_insn_name
);
2508 DECL_BYPASS (decl
)->out_insn_reserv
2509 = DECL_INSN_RESERV (out_insn_reserv
);
2510 DECL_BYPASS (decl
)->in_insn_reserv
2511 = DECL_INSN_RESERV (in_insn_reserv
);
2513 = find_bypass (DECL_INSN_RESERV (out_insn_reserv
)->bypass_list
,
2514 DECL_BYPASS (decl
)->in_insn_reserv
);
2517 if (DECL_BYPASS (decl
)->latency
== bypass
->latency
)
2521 ("the same bypass `%s - %s' is already defined",
2522 DECL_BYPASS (decl
)->out_insn_name
,
2523 DECL_BYPASS (decl
)->in_insn_name
);
2526 (0, "the same bypass `%s - %s' is already defined",
2527 DECL_BYPASS (decl
)->out_insn_name
,
2528 DECL_BYPASS (decl
)->in_insn_name
);
2531 error ("bypass `%s - %s' is already defined",
2532 DECL_BYPASS (decl
)->out_insn_name
,
2533 DECL_BYPASS (decl
)->in_insn_name
);
2537 DECL_BYPASS (decl
)->next
2538 = DECL_INSN_RESERV (out_insn_reserv
)->bypass_list
;
2539 DECL_INSN_RESERV (out_insn_reserv
)->bypass_list
2540 = DECL_BYPASS (decl
);
2546 /* Check exclusion set declarations and form exclusion sets. */
2547 for (i
= 0; i
< description
->decls_num
; i
++)
2549 decl
= description
->decls
[i
];
2550 if (decl
->mode
== dm_excl
)
2552 unit_set_el_t unit_set_el_list
;
2553 unit_set_el_t unit_set_el_list_2
;
2556 = process_excls (DECL_EXCL (decl
)->names
,
2557 DECL_EXCL (decl
)->first_list_length
, decl
->pos
);
2559 = process_excls (&DECL_EXCL (decl
)->names
2560 [DECL_EXCL (decl
)->first_list_length
],
2561 DECL_EXCL (decl
)->all_names_num
2562 - DECL_EXCL (decl
)->first_list_length
,
2564 add_excls (unit_set_el_list
, unit_set_el_list_2
, decl
->pos
);
2565 add_excls (unit_set_el_list_2
, unit_set_el_list
, decl
->pos
);
2569 /* Check presence set declarations and form presence sets. */
2570 for (i
= 0; i
< description
->decls_num
; i
++)
2572 decl
= description
->decls
[i
];
2573 if (decl
->mode
== dm_presence
)
2575 unit_set_el_t unit_set_el_list
;
2576 pattern_set_el_t pattern_set_el_list
;
2579 = process_presence_absence_names
2580 (DECL_PRESENCE (decl
)->names
, DECL_PRESENCE (decl
)->names_num
,
2581 decl
->pos
, TRUE
, DECL_PRESENCE (decl
)->final_p
);
2583 = process_presence_absence_patterns
2584 (DECL_PRESENCE (decl
)->patterns
,
2585 DECL_PRESENCE (decl
)->patterns_num
,
2586 decl
->pos
, TRUE
, DECL_PRESENCE (decl
)->final_p
);
2587 add_presence_absence (unit_set_el_list
, pattern_set_el_list
,
2589 DECL_PRESENCE (decl
)->final_p
);
2593 /* Check absence set declarations and form absence sets. */
2594 for (i
= 0; i
< description
->decls_num
; i
++)
2596 decl
= description
->decls
[i
];
2597 if (decl
->mode
== dm_absence
)
2599 unit_set_el_t unit_set_el_list
;
2600 pattern_set_el_t pattern_set_el_list
;
2603 = process_presence_absence_names
2604 (DECL_ABSENCE (decl
)->names
, DECL_ABSENCE (decl
)->names_num
,
2605 decl
->pos
, FALSE
, DECL_ABSENCE (decl
)->final_p
);
2607 = process_presence_absence_patterns
2608 (DECL_ABSENCE (decl
)->patterns
,
2609 DECL_ABSENCE (decl
)->patterns_num
,
2610 decl
->pos
, FALSE
, DECL_ABSENCE (decl
)->final_p
);
2611 add_presence_absence (unit_set_el_list
, pattern_set_el_list
,
2613 DECL_ABSENCE (decl
)->final_p
);
2618 /* The following function checks that declared automaton is used. If
2619 the automaton is not used, the function fixes error/warning. The
2620 following function must be called only after `process_decls'. */
2622 check_automaton_usage (void)
2627 for (i
= 0; i
< description
->decls_num
; i
++)
2629 decl
= description
->decls
[i
];
2630 if (decl
->mode
== dm_automaton
2631 && !DECL_AUTOMATON (decl
)->automaton_is_used
)
2634 error ("automaton `%s' is not used", DECL_AUTOMATON (decl
)->name
);
2636 warning (0, "automaton `%s' is not used",
2637 DECL_AUTOMATON (decl
)->name
);
2642 /* The following recursive function processes all regexp in order to
2643 fix usage of units or reservations and to fix errors of undeclared
2644 name. The function may change unit_regexp onto reserv_regexp.
2645 Remember that reserv_regexp does not exist before the function
2648 process_regexp (regexp_t regexp
)
2650 decl_t decl_in_table
;
2651 regexp_t new_regexp
;
2654 switch (regexp
->mode
)
2657 decl_in_table
= find_decl (REGEXP_UNIT (regexp
)->name
);
2658 if (decl_in_table
== NULL
)
2659 error ("undeclared unit or reservation `%s'",
2660 REGEXP_UNIT (regexp
)->name
);
2662 switch (decl_in_table
->mode
)
2665 DECL_UNIT (decl_in_table
)->unit_is_used
= 1;
2666 REGEXP_UNIT (regexp
)->unit_decl
= DECL_UNIT (decl_in_table
);
2670 DECL_RESERV (decl_in_table
)->reserv_is_used
= 1;
2671 new_regexp
= create_node (sizeof (struct regexp
));
2672 new_regexp
->mode
= rm_reserv
;
2673 new_regexp
->pos
= regexp
->pos
;
2674 REGEXP_RESERV (new_regexp
)->name
= REGEXP_UNIT (regexp
)->name
;
2675 REGEXP_RESERV (new_regexp
)->reserv_decl
2676 = DECL_RESERV (decl_in_table
);
2677 regexp
= new_regexp
;
2685 for (i
= 0; i
<REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
2686 REGEXP_SEQUENCE (regexp
)->regexps
[i
]
2687 = process_regexp (REGEXP_SEQUENCE (regexp
)->regexps
[i
]);
2690 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
2691 REGEXP_ALLOF (regexp
)->regexps
[i
]
2692 = process_regexp (REGEXP_ALLOF (regexp
)->regexps
[i
]);
2695 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
2696 REGEXP_ONEOF (regexp
)->regexps
[i
]
2697 = process_regexp (REGEXP_ONEOF (regexp
)->regexps
[i
]);
2700 REGEXP_REPEAT (regexp
)->regexp
2701 = process_regexp (REGEXP_REPEAT (regexp
)->regexp
);
2711 /* The following function processes regexp of define_reservation and
2712 define_insn_reservation with the aid of function
2713 `process_regexp'. */
2715 process_regexp_decls (void)
2720 for (i
= 0; i
< description
->decls_num
; i
++)
2722 decl
= description
->decls
[i
];
2723 if (decl
->mode
== dm_reserv
)
2724 DECL_RESERV (decl
)->regexp
2725 = process_regexp (DECL_RESERV (decl
)->regexp
);
2726 else if (decl
->mode
== dm_insn_reserv
)
2727 DECL_INSN_RESERV (decl
)->regexp
2728 = process_regexp (DECL_INSN_RESERV (decl
)->regexp
);
2732 /* The following function checks that declared unit is used. If the
2733 unit is not used, the function fixes errors/warnings. The
2734 following function must be called only after `process_decls',
2735 `process_regexp_decls'. */
2742 for (i
= 0; i
< description
->decls_num
; i
++)
2744 decl
= description
->decls
[i
];
2745 if (decl
->mode
== dm_unit
&& !DECL_UNIT (decl
)->unit_is_used
)
2748 error ("unit `%s' is not used", DECL_UNIT (decl
)->name
);
2750 warning (0, "unit `%s' is not used", DECL_UNIT (decl
)->name
);
2752 else if (decl
->mode
== dm_reserv
&& !DECL_RESERV (decl
)->reserv_is_used
)
2755 error ("reservation `%s' is not used", DECL_RESERV (decl
)->name
);
2757 warning (0, "reservation `%s' is not used", DECL_RESERV (decl
)->name
);
2762 /* The following variable value is number of reservation being
2763 processed on loop recognition. */
2764 static int curr_loop_pass_num
;
2766 /* The following recursive function returns nonzero value if REGEXP
2767 contains given decl or reservations in given regexp refers for
2770 loop_in_regexp (regexp_t regexp
, decl_t start_decl
)
2776 switch (regexp
->mode
)
2782 if (start_decl
->mode
== dm_reserv
2783 && REGEXP_RESERV (regexp
)->reserv_decl
== DECL_RESERV (start_decl
))
2785 else if (REGEXP_RESERV (regexp
)->reserv_decl
->loop_pass_num
2786 == curr_loop_pass_num
)
2787 /* declaration has been processed. */
2791 REGEXP_RESERV (regexp
)->reserv_decl
->loop_pass_num
2792 = curr_loop_pass_num
;
2793 return loop_in_regexp (REGEXP_RESERV (regexp
)->reserv_decl
->regexp
,
2798 for (i
= 0; i
<REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
2799 if (loop_in_regexp (REGEXP_SEQUENCE (regexp
)->regexps
[i
], start_decl
))
2804 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
2805 if (loop_in_regexp (REGEXP_ALLOF (regexp
)->regexps
[i
], start_decl
))
2810 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
2811 if (loop_in_regexp (REGEXP_ONEOF (regexp
)->regexps
[i
], start_decl
))
2816 return loop_in_regexp (REGEXP_REPEAT (regexp
)->regexp
, start_decl
);
2826 /* The following function fixes errors "cycle in definition ...". The
2827 function uses function `loop_in_regexp' for that. */
2829 check_loops_in_regexps (void)
2834 for (i
= 0; i
< description
->decls_num
; i
++)
2836 decl
= description
->decls
[i
];
2837 if (decl
->mode
== dm_reserv
)
2838 DECL_RESERV (decl
)->loop_pass_num
= 0;
2840 for (i
= 0; i
< description
->decls_num
; i
++)
2842 decl
= description
->decls
[i
];
2843 curr_loop_pass_num
= i
;
2845 if (decl
->mode
== dm_reserv
)
2847 DECL_RESERV (decl
)->loop_pass_num
= curr_loop_pass_num
;
2848 if (loop_in_regexp (DECL_RESERV (decl
)->regexp
, decl
))
2850 gcc_assert (DECL_RESERV (decl
)->regexp
);
2851 error ("cycle in definition of reservation `%s'",
2852 DECL_RESERV (decl
)->name
);
2858 /* The function recursively processes IR of reservation and defines
2859 max and min cycle for reservation of unit. */
2861 process_regexp_cycles (regexp_t regexp
, int max_start_cycle
,
2862 int min_start_cycle
, int *max_finish_cycle
,
2863 int *min_finish_cycle
)
2867 switch (regexp
->mode
)
2870 if (REGEXP_UNIT (regexp
)->unit_decl
->max_occ_cycle_num
< max_start_cycle
)
2871 REGEXP_UNIT (regexp
)->unit_decl
->max_occ_cycle_num
= max_start_cycle
;
2872 if (REGEXP_UNIT (regexp
)->unit_decl
->min_occ_cycle_num
> min_start_cycle
2873 || REGEXP_UNIT (regexp
)->unit_decl
->min_occ_cycle_num
== -1)
2874 REGEXP_UNIT (regexp
)->unit_decl
->min_occ_cycle_num
= min_start_cycle
;
2875 *max_finish_cycle
= max_start_cycle
;
2876 *min_finish_cycle
= min_start_cycle
;
2880 process_regexp_cycles (REGEXP_RESERV (regexp
)->reserv_decl
->regexp
,
2881 max_start_cycle
, min_start_cycle
,
2882 max_finish_cycle
, min_finish_cycle
);
2886 for (i
= 0; i
< REGEXP_REPEAT (regexp
)->repeat_num
; i
++)
2888 process_regexp_cycles (REGEXP_REPEAT (regexp
)->regexp
,
2889 max_start_cycle
, min_start_cycle
,
2890 max_finish_cycle
, min_finish_cycle
);
2891 max_start_cycle
= *max_finish_cycle
+ 1;
2892 min_start_cycle
= *min_finish_cycle
+ 1;
2897 for (i
= 0; i
<REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
2899 process_regexp_cycles (REGEXP_SEQUENCE (regexp
)->regexps
[i
],
2900 max_start_cycle
, min_start_cycle
,
2901 max_finish_cycle
, min_finish_cycle
);
2902 max_start_cycle
= *max_finish_cycle
+ 1;
2903 min_start_cycle
= *min_finish_cycle
+ 1;
2912 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
2914 process_regexp_cycles (REGEXP_ALLOF (regexp
)->regexps
[i
],
2915 max_start_cycle
, min_start_cycle
,
2916 max_finish_cycle
, min_finish_cycle
);
2917 if (max_cycle
< *max_finish_cycle
)
2918 max_cycle
= *max_finish_cycle
;
2919 if (i
== 0 || min_cycle
> *min_finish_cycle
)
2920 min_cycle
= *min_finish_cycle
;
2922 *max_finish_cycle
= max_cycle
;
2923 *min_finish_cycle
= min_cycle
;
2932 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
2934 process_regexp_cycles (REGEXP_ONEOF (regexp
)->regexps
[i
],
2935 max_start_cycle
, min_start_cycle
,
2936 max_finish_cycle
, min_finish_cycle
);
2937 if (max_cycle
< *max_finish_cycle
)
2938 max_cycle
= *max_finish_cycle
;
2939 if (i
== 0 || min_cycle
> *min_finish_cycle
)
2940 min_cycle
= *min_finish_cycle
;
2942 *max_finish_cycle
= max_cycle
;
2943 *min_finish_cycle
= min_cycle
;
2948 *max_finish_cycle
= max_start_cycle
;
2949 *min_finish_cycle
= min_start_cycle
;
2957 /* The following function is called only for correct program. The
2958 function defines max reservation of insns in cycles. */
2960 evaluate_max_reserv_cycles (void)
2962 int max_insn_cycles_num
;
2963 int min_insn_cycles_num
;
2967 description
->max_insn_reserv_cycles
= 0;
2968 for (i
= 0; i
< description
->decls_num
; i
++)
2970 decl
= description
->decls
[i
];
2971 if (decl
->mode
== dm_insn_reserv
)
2973 process_regexp_cycles (DECL_INSN_RESERV (decl
)->regexp
, 0, 0,
2974 &max_insn_cycles_num
, &min_insn_cycles_num
);
2975 if (description
->max_insn_reserv_cycles
< max_insn_cycles_num
)
2976 description
->max_insn_reserv_cycles
= max_insn_cycles_num
;
2979 description
->max_insn_reserv_cycles
++;
2982 /* The following function calls functions for checking all
2985 check_all_description (void)
2988 check_automaton_usage ();
2989 process_regexp_decls ();
2991 check_loops_in_regexps ();
2993 evaluate_max_reserv_cycles ();
2998 /* The page contains abstract data `ticker'. This data is used to
2999 report time of different phases of building automata. It is
3000 possibly to write a description for which automata will be built
3001 during several minutes even on fast machine. */
3003 /* The following function creates ticker and makes it active. */
3005 create_ticker (void)
3009 ticker
.modified_creation_time
= get_run_time ();
3010 ticker
.incremented_off_time
= 0;
3014 /* The following function switches off given ticker. */
3016 ticker_off (ticker_t
*ticker
)
3018 if (ticker
->incremented_off_time
== 0)
3019 ticker
->incremented_off_time
= get_run_time () + 1;
3022 /* The following function switches on given ticker. */
3024 ticker_on (ticker_t
*ticker
)
3026 if (ticker
->incremented_off_time
!= 0)
3028 ticker
->modified_creation_time
3029 += get_run_time () - ticker
->incremented_off_time
+ 1;
3030 ticker
->incremented_off_time
= 0;
3034 /* The following function returns current time in milliseconds since
3035 the moment when given ticker was created. */
3037 active_time (ticker_t ticker
)
3039 if (ticker
.incremented_off_time
!= 0)
3040 return ticker
.incremented_off_time
- 1 - ticker
.modified_creation_time
;
3042 return get_run_time () - ticker
.modified_creation_time
;
3045 /* The following function returns string representation of active time
3046 of given ticker. The result is string representation of seconds
3047 with accuracy of 1/100 second. Only result of the last call of the
3048 function exists. Therefore the following code is not correct
3050 printf ("parser time: %s\ngeneration time: %s\n",
3051 active_time_string (parser_ticker),
3052 active_time_string (generation_ticker));
3054 Correct code has to be the following
3056 printf ("parser time: %s\n", active_time_string (parser_ticker));
3057 printf ("generation time: %s\n",
3058 active_time_string (generation_ticker));
3062 print_active_time (FILE *f
, ticker_t ticker
)
3066 msecs
= active_time (ticker
);
3067 fprintf (f
, "%d.%06d", msecs
/ 1000000, msecs
% 1000000);
3072 /* The following variable value is number of automaton which are
3073 really being created. This value is defined on the base of
3074 argument of option `-split'. If the variable has zero value the
3075 number of automata is defined by the constructions `%automaton'.
3076 This case occurs when option `-split' is absent or has zero
3077 argument. If constructions `define_automaton' is absent only one
3078 automaton is created. */
3079 static int automata_num
;
3081 /* The following variable values are times of
3082 o transformation of regular expressions
3083 o building NDFA (DFA if !ndfa_flag)
3084 o NDFA -> DFA (simply the same automaton if !ndfa_flag)
3086 o building insn equivalence classes
3089 static ticker_t transform_time
;
3090 static ticker_t NDFA_time
;
3091 static ticker_t NDFA_to_DFA_time
;
3092 static ticker_t minimize_time
;
3093 static ticker_t equiv_time
;
3094 static ticker_t automaton_generation_time
;
3095 static ticker_t output_time
;
3097 /* The following variable values are times of
3100 all pipeline hazard translator work */
3101 static ticker_t check_time
;
3102 static ticker_t generation_time
;
3103 static ticker_t all_time
;
3107 /* Pseudo insn decl which denotes advancing cycle. */
3108 static decl_t advance_cycle_insn_decl
;
3110 add_advance_cycle_insn_decl (void)
3112 advance_cycle_insn_decl
= create_node (sizeof (struct decl
));
3113 advance_cycle_insn_decl
->mode
= dm_insn_reserv
;
3114 advance_cycle_insn_decl
->pos
= no_pos
;
3115 DECL_INSN_RESERV (advance_cycle_insn_decl
)->regexp
= NULL
;
3116 DECL_INSN_RESERV (advance_cycle_insn_decl
)->name
= "$advance_cycle";
3117 DECL_INSN_RESERV (advance_cycle_insn_decl
)->insn_num
3118 = description
->insns_num
;
3119 description
->decls
[description
->decls_num
] = advance_cycle_insn_decl
;
3120 description
->decls_num
++;
3121 description
->insns_num
++;
3125 /* Abstract data `alternative states' which represents
3126 nondeterministic nature of the description (see comments for
3127 structures alt_state and state). */
3129 /* List of free states. */
3130 static alt_state_t first_free_alt_state
;
3133 /* The following variables is maximal number of allocated nodes
3135 static int allocated_alt_states_num
= 0;
3138 /* The following function returns free node alt_state. It may be new
3139 allocated node or node freed earlier. */
3141 get_free_alt_state (void)
3145 if (first_free_alt_state
!= NULL
)
3147 result
= first_free_alt_state
;
3148 first_free_alt_state
= first_free_alt_state
->next_alt_state
;
3153 allocated_alt_states_num
++;
3155 result
= create_node (sizeof (struct alt_state
));
3157 result
->state
= NULL
;
3158 result
->next_alt_state
= NULL
;
3159 result
->next_sorted_alt_state
= NULL
;
3163 /* The function frees node ALT_STATE. */
3165 free_alt_state (alt_state_t alt_state
)
3167 if (alt_state
== NULL
)
3169 alt_state
->next_alt_state
= first_free_alt_state
;
3170 first_free_alt_state
= alt_state
;
3173 /* The function frees list started with node ALT_STATE_LIST. */
3175 free_alt_states (alt_state_t alt_states_list
)
3177 alt_state_t curr_alt_state
;
3178 alt_state_t next_alt_state
;
3180 for (curr_alt_state
= alt_states_list
;
3181 curr_alt_state
!= NULL
;
3182 curr_alt_state
= next_alt_state
)
3184 next_alt_state
= curr_alt_state
->next_alt_state
;
3185 free_alt_state (curr_alt_state
);
3189 /* The function compares unique numbers of alt states. */
3191 alt_state_cmp (const void *alt_state_ptr_1
, const void *alt_state_ptr_2
)
3193 if ((*(alt_state_t
*) alt_state_ptr_1
)->state
->unique_num
3194 == (*(alt_state_t
*) alt_state_ptr_2
)->state
->unique_num
)
3196 else if ((*(alt_state_t
*) alt_state_ptr_1
)->state
->unique_num
3197 < (*(alt_state_t
*) alt_state_ptr_2
)->state
->unique_num
)
3203 /* The function sorts ALT_STATES_LIST and removes duplicated alt
3204 states from the list. The comparison key is alt state unique
3208 uniq_sort_alt_states (alt_state_t alt_states_list
)
3210 alt_state_t curr_alt_state
;
3211 VEC(alt_state_t
,heap
) *alt_states
;
3213 size_t prev_unique_state_ind
;
3216 if (alt_states_list
== 0)
3218 if (alt_states_list
->next_alt_state
== 0)
3219 return alt_states_list
;
3221 alt_states
= VEC_alloc (alt_state_t
,heap
, 150);
3222 for (curr_alt_state
= alt_states_list
;
3223 curr_alt_state
!= NULL
;
3224 curr_alt_state
= curr_alt_state
->next_alt_state
)
3225 VEC_safe_push (alt_state_t
,heap
, alt_states
, curr_alt_state
);
3227 qsort (VEC_address (alt_state_t
, alt_states
),
3228 VEC_length (alt_state_t
, alt_states
),
3229 sizeof (alt_state_t
), alt_state_cmp
);
3231 prev_unique_state_ind
= 0;
3232 for (i
= 1; i
< VEC_length (alt_state_t
, alt_states
); i
++)
3233 if (VEC_index (alt_state_t
, alt_states
, prev_unique_state_ind
)->state
3234 != VEC_index (alt_state_t
, alt_states
, i
)->state
)
3236 prev_unique_state_ind
++;
3237 VEC_replace (alt_state_t
, alt_states
, prev_unique_state_ind
,
3238 VEC_index (alt_state_t
, alt_states
, i
));
3240 VEC_truncate (alt_state_t
, alt_states
, prev_unique_state_ind
+ 1);
3242 for (i
= 1; i
< VEC_length (alt_state_t
, alt_states
); i
++)
3243 VEC_index (alt_state_t
, alt_states
, i
-1)->next_sorted_alt_state
3244 = VEC_index (alt_state_t
, alt_states
, i
);
3245 VEC_last (alt_state_t
, alt_states
)->next_sorted_alt_state
= 0;
3247 result
= VEC_index (alt_state_t
, alt_states
, 0);
3249 VEC_free (alt_state_t
,heap
, alt_states
);
3253 /* The function checks equality of alt state lists. Remember that the
3254 lists must be already sorted by the previous function. */
3256 alt_states_eq (alt_state_t alt_states_1
, alt_state_t alt_states_2
)
3258 while (alt_states_1
!= NULL
&& alt_states_2
!= NULL
3259 && alt_state_cmp (&alt_states_1
, &alt_states_2
) == 0)
3261 alt_states_1
= alt_states_1
->next_sorted_alt_state
;
3262 alt_states_2
= alt_states_2
->next_sorted_alt_state
;
3264 return alt_states_1
== alt_states_2
;
3267 /* Initialization of the abstract data. */
3269 initiate_alt_states (void)
3271 first_free_alt_state
= NULL
;
3274 /* Finishing work with the abstract data. */
3276 finish_alt_states (void)
3282 /* The page contains macros for work with bits strings. We could use
3283 standard gcc bitmap or sbitmap but it would result in difficulties
3284 of building canadian cross. */
3286 /* Set bit number bitno in the bit string. The macro is not side
3288 #define SET_BIT(bitstring, bitno) \
3289 (((char *) (bitstring)) [(bitno) / CHAR_BIT] |= 1 << (bitno) % CHAR_BIT)
3291 #define CLEAR_BIT(bitstring, bitno) \
3292 (((char *) (bitstring)) [(bitno) / CHAR_BIT] &= ~(1 << (bitno) % CHAR_BIT))
3294 /* Test if bit number bitno in the bitstring is set. The macro is not
3295 side effect proof. */
3296 #define TEST_BIT(bitstring, bitno) \
3297 (((char *) (bitstring)) [(bitno) / CHAR_BIT] >> (bitno) % CHAR_BIT & 1)
3301 /* This page contains abstract data `state'. */
3303 /* Maximal length of reservations in cycles (>= 1). */
3304 static int max_cycles_num
;
3306 /* Number of set elements (see type set_el_t) needed for
3307 representation of one cycle reservation. It is depended on units
3309 static int els_in_cycle_reserv
;
3311 /* Number of set elements (see type set_el_t) needed for
3312 representation of maximal length reservation. Deterministic
3313 reservation is stored as set (bit string) of length equal to the
3314 variable value * number of bits in set_el_t. */
3315 static int els_in_reservs
;
3317 /* Array of pointers to unit declarations. */
3318 static unit_decl_t
*units_array
;
3320 /* Temporary reservation of maximal length. */
3321 static reserv_sets_t temp_reserv
;
3323 /* The state table itself is represented by the following variable. */
3324 static htab_t state_table
;
3326 /* Linked list of free 'state' structures to be recycled. The
3327 next_equiv_class_state pointer is borrowed for a free list. */
3328 static state_t first_free_state
;
3330 static int curr_unique_state_num
;
3333 /* The following variables is maximal number of allocated nodes
3335 static int allocated_states_num
= 0;
3338 /* Allocate new reservation set. */
3339 static reserv_sets_t
3340 alloc_empty_reserv_sets (void)
3342 reserv_sets_t result
;
3344 obstack_blank (&irp
, els_in_reservs
* sizeof (set_el_t
));
3345 result
= (reserv_sets_t
) obstack_base (&irp
);
3346 obstack_finish (&irp
);
3347 memset (result
, 0, els_in_reservs
* sizeof (set_el_t
));
3351 /* Hash value of reservation set. */
3353 reserv_sets_hash_value (reserv_sets_t reservs
)
3355 set_el_t hash_value
;
3358 set_el_t
*reserv_ptr
;
3361 reservs_num
= els_in_reservs
;
3362 reserv_ptr
= reservs
;
3364 while (reservs_num
!= 0)
3367 hash_value
+= ((*reserv_ptr
>> i
)
3368 | (*reserv_ptr
<< (sizeof (set_el_t
) * CHAR_BIT
- i
)));
3370 if (i
== sizeof (set_el_t
) * CHAR_BIT
)
3374 if (sizeof (set_el_t
) <= sizeof (unsigned))
3377 for (i
= sizeof (set_el_t
); i
> 0; i
-= sizeof (unsigned) - 1)
3379 result
+= (unsigned) hash_value
;
3380 hash_value
>>= (sizeof (unsigned) - 1) * CHAR_BIT
;
3385 /* Comparison of given reservation sets. */
3387 reserv_sets_cmp (reserv_sets_t reservs_1
, reserv_sets_t reservs_2
)
3390 set_el_t
*reserv_ptr_1
;
3391 set_el_t
*reserv_ptr_2
;
3393 gcc_assert (reservs_1
&& reservs_2
);
3394 reservs_num
= els_in_reservs
;
3395 reserv_ptr_1
= reservs_1
;
3396 reserv_ptr_2
= reservs_2
;
3397 while (reservs_num
!= 0 && *reserv_ptr_1
== *reserv_ptr_2
)
3403 if (reservs_num
== 0)
3405 else if (*reserv_ptr_1
< *reserv_ptr_2
)
3411 /* The function checks equality of the reservation sets. */
3413 reserv_sets_eq (reserv_sets_t reservs_1
, reserv_sets_t reservs_2
)
3415 return reserv_sets_cmp (reservs_1
, reservs_2
) == 0;
3418 /* Set up in the reservation set that unit with UNIT_NUM is used on
3421 set_unit_reserv (reserv_sets_t reservs
, int cycle_num
, int unit_num
)
3423 gcc_assert (cycle_num
< max_cycles_num
);
3424 SET_BIT (reservs
, cycle_num
* els_in_cycle_reserv
3425 * sizeof (set_el_t
) * CHAR_BIT
+ unit_num
);
3428 /* Set up in the reservation set RESERVS that unit with UNIT_NUM is
3429 used on CYCLE_NUM. */
3431 test_unit_reserv (reserv_sets_t reservs
, int cycle_num
, int unit_num
)
3433 gcc_assert (cycle_num
< max_cycles_num
);
3434 return TEST_BIT (reservs
, cycle_num
* els_in_cycle_reserv
3435 * sizeof (set_el_t
) * CHAR_BIT
+ unit_num
);
3438 /* The function checks that the reservation sets are intersected,
3439 i.e. there is a unit reservation on a cycle in both reservation
3442 reserv_sets_are_intersected (reserv_sets_t operand_1
,
3443 reserv_sets_t operand_2
)
3447 set_el_t
*cycle_ptr_1
;
3448 set_el_t
*cycle_ptr_2
;
3450 gcc_assert (operand_1
&& operand_2
);
3451 for (el_ptr_1
= operand_1
, el_ptr_2
= operand_2
;
3452 el_ptr_1
< operand_1
+ els_in_reservs
;
3453 el_ptr_1
++, el_ptr_2
++)
3454 if (*el_ptr_1
& *el_ptr_2
)
3456 reserv_sets_or (temp_reserv
, operand_1
, operand_2
);
3457 for (cycle_ptr_1
= operand_1
, cycle_ptr_2
= operand_2
;
3458 cycle_ptr_1
< operand_1
+ els_in_reservs
;
3459 cycle_ptr_1
+= els_in_cycle_reserv
, cycle_ptr_2
+= els_in_cycle_reserv
)
3461 for (el_ptr_1
= cycle_ptr_1
, el_ptr_2
= get_excl_set (cycle_ptr_2
);
3462 el_ptr_1
< cycle_ptr_1
+ els_in_cycle_reserv
;
3463 el_ptr_1
++, el_ptr_2
++)
3464 if (*el_ptr_1
& *el_ptr_2
)
3466 if (!check_presence_pattern_sets (cycle_ptr_1
, cycle_ptr_2
, FALSE
))
3468 if (!check_presence_pattern_sets (temp_reserv
+ (cycle_ptr_2
3472 if (!check_absence_pattern_sets (cycle_ptr_1
, cycle_ptr_2
, FALSE
))
3474 if (!check_absence_pattern_sets (temp_reserv
+ (cycle_ptr_2
- operand_2
),
3481 /* The function sets up RESULT bits by bits of OPERAND shifted on one
3482 cpu cycle. The remaining bits of OPERAND (representing the last
3483 cycle unit reservations) are not changed. */
3485 reserv_sets_shift (reserv_sets_t result
, reserv_sets_t operand
)
3489 gcc_assert (result
&& operand
&& result
!= operand
);
3490 for (i
= els_in_cycle_reserv
; i
< els_in_reservs
; i
++)
3491 result
[i
- els_in_cycle_reserv
] = operand
[i
];
3494 /* OR of the reservation sets. */
3496 reserv_sets_or (reserv_sets_t result
, reserv_sets_t operand_1
,
3497 reserv_sets_t operand_2
)
3501 set_el_t
*result_set_el_ptr
;
3503 gcc_assert (result
&& operand_1
&& operand_2
);
3504 for (el_ptr_1
= operand_1
, el_ptr_2
= operand_2
, result_set_el_ptr
= result
;
3505 el_ptr_1
< operand_1
+ els_in_reservs
;
3506 el_ptr_1
++, el_ptr_2
++, result_set_el_ptr
++)
3507 *result_set_el_ptr
= *el_ptr_1
| *el_ptr_2
;
3510 /* AND of the reservation sets. */
3512 reserv_sets_and (reserv_sets_t result
, reserv_sets_t operand_1
,
3513 reserv_sets_t operand_2
)
3517 set_el_t
*result_set_el_ptr
;
3519 gcc_assert (result
&& operand_1
&& operand_2
);
3520 for (el_ptr_1
= operand_1
, el_ptr_2
= operand_2
, result_set_el_ptr
= result
;
3521 el_ptr_1
< operand_1
+ els_in_reservs
;
3522 el_ptr_1
++, el_ptr_2
++, result_set_el_ptr
++)
3523 *result_set_el_ptr
= *el_ptr_1
& *el_ptr_2
;
3526 /* The function outputs string representation of units reservation on
3527 cycle START_CYCLE in the reservation set. The function uses repeat
3528 construction if REPETITION_NUM > 1. */
3530 output_cycle_reservs (FILE *f
, reserv_sets_t reservs
, int start_cycle
,
3534 int reserved_units_num
;
3536 reserved_units_num
= 0;
3537 for (unit_num
= 0; unit_num
< description
->units_num
; unit_num
++)
3538 if (TEST_BIT (reservs
, start_cycle
* els_in_cycle_reserv
3539 * sizeof (set_el_t
) * CHAR_BIT
+ unit_num
))
3540 reserved_units_num
++;
3541 gcc_assert (repetition_num
> 0);
3542 if (repetition_num
!= 1 && reserved_units_num
> 1)
3544 reserved_units_num
= 0;
3546 unit_num
< description
->units_num
;
3548 if (TEST_BIT (reservs
, start_cycle
* els_in_cycle_reserv
3549 * sizeof (set_el_t
) * CHAR_BIT
+ unit_num
))
3551 if (reserved_units_num
!= 0)
3553 reserved_units_num
++;
3554 fprintf (f
, "%s", units_array
[unit_num
]->name
);
3556 if (reserved_units_num
== 0)
3557 fprintf (f
, NOTHING_NAME
);
3558 gcc_assert (repetition_num
> 0);
3559 if (repetition_num
!= 1 && reserved_units_num
> 1)
3561 if (repetition_num
!= 1)
3562 fprintf (f
, "*%d", repetition_num
);
3565 /* The function outputs string representation of units reservation in
3566 the reservation set. */
3568 output_reserv_sets (FILE *f
, reserv_sets_t reservs
)
3570 int start_cycle
= 0;
3575 for (cycle
= 0; cycle
< max_cycles_num
; cycle
++)
3576 if (repetition_num
== 0)
3579 start_cycle
= cycle
;
3582 ((char *) reservs
+ start_cycle
* els_in_cycle_reserv
3583 * sizeof (set_el_t
),
3584 (char *) reservs
+ cycle
* els_in_cycle_reserv
3585 * sizeof (set_el_t
),
3586 els_in_cycle_reserv
* sizeof (set_el_t
)) == 0)
3590 if (start_cycle
!= 0)
3592 output_cycle_reservs (f
, reservs
, start_cycle
, repetition_num
);
3594 start_cycle
= cycle
;
3596 if (start_cycle
< max_cycles_num
)
3598 if (start_cycle
!= 0)
3600 output_cycle_reservs (f
, reservs
, start_cycle
, repetition_num
);
3604 /* The following function returns free node state for AUTOMATON. It
3605 may be new allocated node or node freed earlier. The function also
3606 allocates reservation set if WITH_RESERVS has nonzero value. */
3608 get_free_state (int with_reservs
, automaton_t automaton
)
3612 gcc_assert (max_cycles_num
> 0 && automaton
);
3613 if (first_free_state
)
3615 result
= first_free_state
;
3616 first_free_state
= result
->next_equiv_class_state
;
3618 result
->next_equiv_class_state
= NULL
;
3619 result
->automaton
= automaton
;
3620 result
->first_out_arc
= NULL
;
3621 result
->it_was_placed_in_stack_for_NDFA_forming
= 0;
3622 result
->it_was_placed_in_stack_for_DFA_forming
= 0;
3623 result
->component_states
= NULL
;
3624 result
->longest_path_length
= UNDEFINED_LONGEST_PATH_LENGTH
;
3629 allocated_states_num
++;
3631 result
= create_node (sizeof (struct state
));
3632 result
->automaton
= automaton
;
3633 result
->first_out_arc
= NULL
;
3634 result
->unique_num
= curr_unique_state_num
;
3635 result
->longest_path_length
= UNDEFINED_LONGEST_PATH_LENGTH
;
3636 curr_unique_state_num
++;
3640 if (result
->reservs
== NULL
)
3641 result
->reservs
= alloc_empty_reserv_sets ();
3643 memset (result
->reservs
, 0, els_in_reservs
* sizeof (set_el_t
));
3648 /* The function frees node STATE. */
3650 free_state (state_t state
)
3652 free_alt_states (state
->component_states
);
3653 state
->next_equiv_class_state
= first_free_state
;
3654 first_free_state
= state
;
3657 /* Hash value of STATE. If STATE represents deterministic state it is
3658 simply hash value of the corresponding reservation set. Otherwise
3659 it is formed from hash values of the component deterministic
3660 states. One more key is order number of state automaton. */
3662 state_hash (const void *state
)
3664 unsigned int hash_value
;
3665 alt_state_t alt_state
;
3667 if (((state_t
) state
)->component_states
== NULL
)
3668 hash_value
= reserv_sets_hash_value (((state_t
) state
)->reservs
);
3672 for (alt_state
= ((state_t
) state
)->component_states
;
3674 alt_state
= alt_state
->next_sorted_alt_state
)
3675 hash_value
= (((hash_value
>> (sizeof (unsigned) - 1) * CHAR_BIT
)
3676 | (hash_value
<< CHAR_BIT
))
3677 + alt_state
->state
->unique_num
);
3679 hash_value
= (((hash_value
>> (sizeof (unsigned) - 1) * CHAR_BIT
)
3680 | (hash_value
<< CHAR_BIT
))
3681 + ((state_t
) state
)->automaton
->automaton_order_num
);
3685 /* Return nonzero value if the states are the same. */
3687 state_eq_p (const void *state_1
, const void *state_2
)
3689 alt_state_t alt_state_1
;
3690 alt_state_t alt_state_2
;
3692 if (((state_t
) state_1
)->automaton
!= ((state_t
) state_2
)->automaton
)
3694 else if (((state_t
) state_1
)->component_states
== NULL
3695 && ((state_t
) state_2
)->component_states
== NULL
)
3696 return reserv_sets_eq (((state_t
) state_1
)->reservs
,
3697 ((state_t
) state_2
)->reservs
);
3698 else if (((state_t
) state_1
)->component_states
!= NULL
3699 && ((state_t
) state_2
)->component_states
!= NULL
)
3701 for (alt_state_1
= ((state_t
) state_1
)->component_states
,
3702 alt_state_2
= ((state_t
) state_2
)->component_states
;
3703 alt_state_1
!= NULL
&& alt_state_2
!= NULL
;
3704 alt_state_1
= alt_state_1
->next_sorted_alt_state
,
3705 alt_state_2
= alt_state_2
->next_sorted_alt_state
)
3706 /* All state in the list must be already in the hash table.
3707 Also the lists must be sorted. */
3708 if (alt_state_1
->state
!= alt_state_2
->state
)
3710 return alt_state_1
== alt_state_2
;
3716 /* Insert STATE into the state table. */
3718 insert_state (state_t state
)
3722 entry_ptr
= htab_find_slot (state_table
, (void *) state
, 1);
3723 if (*entry_ptr
== NULL
)
3724 *entry_ptr
= (void *) state
;
3725 return (state_t
) *entry_ptr
;
3728 /* Add reservation of unit with UNIT_NUM on cycle CYCLE_NUM to
3729 deterministic STATE. */
3731 set_state_reserv (state_t state
, int cycle_num
, int unit_num
)
3733 set_unit_reserv (state
->reservs
, cycle_num
, unit_num
);
3736 /* Return nonzero value if the deterministic states contains a
3737 reservation of the same cpu unit on the same cpu cycle. */
3739 intersected_state_reservs_p (state_t state1
, state_t state2
)
3741 gcc_assert (state1
->automaton
== state2
->automaton
);
3742 return reserv_sets_are_intersected (state1
->reservs
, state2
->reservs
);
3745 /* Return deterministic state (inserted into the table) which
3746 representing the automaton state which is union of reservations of
3747 the deterministic states masked by RESERVS. */
3749 states_union (state_t state1
, state_t state2
, reserv_sets_t reservs
)
3752 state_t state_in_table
;
3754 gcc_assert (state1
->automaton
== state2
->automaton
);
3755 result
= get_free_state (1, state1
->automaton
);
3756 reserv_sets_or (result
->reservs
, state1
->reservs
, state2
->reservs
);
3757 reserv_sets_and (result
->reservs
, result
->reservs
, reservs
);
3758 state_in_table
= insert_state (result
);
3759 if (result
!= state_in_table
)
3761 free_state (result
);
3762 result
= state_in_table
;
3767 /* Return deterministic state (inserted into the table) which
3768 represent the automaton state is obtained from deterministic STATE
3769 by advancing cpu cycle and masking by RESERVS. */
3771 state_shift (state_t state
, reserv_sets_t reservs
)
3774 state_t state_in_table
;
3776 result
= get_free_state (1, state
->automaton
);
3777 reserv_sets_shift (result
->reservs
, state
->reservs
);
3778 reserv_sets_and (result
->reservs
, result
->reservs
, reservs
);
3779 state_in_table
= insert_state (result
);
3780 if (result
!= state_in_table
)
3782 free_state (result
);
3783 result
= state_in_table
;
3788 /* Initialization of the abstract data. */
3790 initiate_states (void)
3795 if (description
->units_num
)
3796 units_array
= XNEWVEC (unit_decl_t
, description
->units_num
);
3800 for (i
= 0; i
< description
->decls_num
; i
++)
3802 decl
= description
->decls
[i
];
3803 if (decl
->mode
== dm_unit
)
3804 units_array
[DECL_UNIT (decl
)->unit_num
] = DECL_UNIT (decl
);
3806 max_cycles_num
= description
->max_insn_reserv_cycles
;
3808 = ((description
->units_num
+ sizeof (set_el_t
) * CHAR_BIT
- 1)
3809 / (sizeof (set_el_t
) * CHAR_BIT
));
3810 els_in_reservs
= els_in_cycle_reserv
* max_cycles_num
;
3811 curr_unique_state_num
= 0;
3812 initiate_alt_states ();
3813 state_table
= htab_create (1500, state_hash
, state_eq_p
, (htab_del
) 0);
3814 temp_reserv
= alloc_empty_reserv_sets ();
3817 /* Finishing work with the abstract data. */
3819 finish_states (void)
3823 htab_delete (state_table
);
3824 first_free_state
= NULL
;
3825 finish_alt_states ();
3830 /* Abstract data `arcs'. */
3832 /* List of free arcs. */
3833 static arc_t first_free_arc
;
3836 /* The following variables is maximal number of allocated nodes
3838 static int allocated_arcs_num
= 0;
3841 /* The function frees node ARC. */
3843 free_arc (arc_t arc
)
3845 arc
->next_out_arc
= first_free_arc
;
3846 first_free_arc
= arc
;
3849 /* The function removes and frees ARC staring from FROM_STATE. */
3851 remove_arc (state_t from_state
, arc_t arc
)
3857 for (prev_arc
= NULL
, curr_arc
= from_state
->first_out_arc
;
3859 prev_arc
= curr_arc
, curr_arc
= curr_arc
->next_out_arc
)
3860 if (curr_arc
== arc
)
3862 gcc_assert (curr_arc
);
3863 if (prev_arc
== NULL
)
3864 from_state
->first_out_arc
= arc
->next_out_arc
;
3866 prev_arc
->next_out_arc
= arc
->next_out_arc
;
3867 from_state
->num_out_arcs
--;
3871 /* The functions returns arc with given characteristics (or NULL if
3872 the arc does not exist). */
3874 find_arc (state_t from_state
, state_t to_state
, ainsn_t insn
)
3878 for (arc
= first_out_arc (from_state
); arc
!= NULL
; arc
= next_out_arc (arc
))
3879 if (arc
->to_state
== to_state
&& arc
->insn
== insn
)
3884 /* The function adds arc from FROM_STATE to TO_STATE marked by AINSN.
3885 The function returns added arc (or already existing arc). */
3887 add_arc (state_t from_state
, state_t to_state
, ainsn_t ainsn
)
3891 new_arc
= find_arc (from_state
, to_state
, ainsn
);
3892 if (new_arc
!= NULL
)
3894 if (first_free_arc
== NULL
)
3897 allocated_arcs_num
++;
3899 new_arc
= create_node (sizeof (struct arc
));
3900 new_arc
->to_state
= NULL
;
3901 new_arc
->insn
= NULL
;
3902 new_arc
->next_out_arc
= NULL
;
3906 new_arc
= first_free_arc
;
3907 first_free_arc
= first_free_arc
->next_out_arc
;
3909 new_arc
->to_state
= to_state
;
3910 new_arc
->insn
= ainsn
;
3911 ainsn
->arc_exists_p
= 1;
3912 new_arc
->next_out_arc
= from_state
->first_out_arc
;
3913 from_state
->first_out_arc
= new_arc
;
3914 from_state
->num_out_arcs
++;
3915 new_arc
->next_arc_marked_by_insn
= NULL
;
3919 /* The function returns the first arc starting from STATE. */
3921 first_out_arc (state_t state
)
3923 return state
->first_out_arc
;
3926 /* The function returns next out arc after ARC. */
3928 next_out_arc (arc_t arc
)
3930 return arc
->next_out_arc
;
3933 /* Initialization of the abstract data. */
3935 initiate_arcs (void)
3937 first_free_arc
= NULL
;
3940 /* Finishing work with the abstract data. */
3948 /* Abstract data `automata lists'. */
3950 /* List of free states. */
3951 static automata_list_el_t first_free_automata_list_el
;
3953 /* The list being formed. */
3954 static automata_list_el_t current_automata_list
;
3956 /* Hash table of automata lists. */
3957 static htab_t automata_list_table
;
3959 /* The following function returns free automata list el. It may be
3960 new allocated node or node freed earlier. */
3961 static automata_list_el_t
3962 get_free_automata_list_el (void)
3964 automata_list_el_t result
;
3966 if (first_free_automata_list_el
!= NULL
)
3968 result
= first_free_automata_list_el
;
3969 first_free_automata_list_el
3970 = first_free_automata_list_el
->next_automata_list_el
;
3973 result
= create_node (sizeof (struct automata_list_el
));
3974 result
->automaton
= NULL
;
3975 result
->next_automata_list_el
= NULL
;
3979 /* The function frees node AUTOMATA_LIST_EL. */
3981 free_automata_list_el (automata_list_el_t automata_list_el
)
3983 if (automata_list_el
== NULL
)
3985 automata_list_el
->next_automata_list_el
= first_free_automata_list_el
;
3986 first_free_automata_list_el
= automata_list_el
;
3989 /* The function frees list AUTOMATA_LIST. */
3991 free_automata_list (automata_list_el_t automata_list
)
3993 automata_list_el_t curr_automata_list_el
;
3994 automata_list_el_t next_automata_list_el
;
3996 for (curr_automata_list_el
= automata_list
;
3997 curr_automata_list_el
!= NULL
;
3998 curr_automata_list_el
= next_automata_list_el
)
4000 next_automata_list_el
= curr_automata_list_el
->next_automata_list_el
;
4001 free_automata_list_el (curr_automata_list_el
);
4005 /* Hash value of AUTOMATA_LIST. */
4007 automata_list_hash (const void *automata_list
)
4009 unsigned int hash_value
;
4010 automata_list_el_t curr_automata_list_el
;
4013 for (curr_automata_list_el
= (automata_list_el_t
) automata_list
;
4014 curr_automata_list_el
!= NULL
;
4015 curr_automata_list_el
= curr_automata_list_el
->next_automata_list_el
)
4016 hash_value
= (((hash_value
>> (sizeof (unsigned) - 1) * CHAR_BIT
)
4017 | (hash_value
<< CHAR_BIT
))
4018 + curr_automata_list_el
->automaton
->automaton_order_num
);
4022 /* Return nonzero value if the automata_lists are the same. */
4024 automata_list_eq_p (const void *automata_list_1
, const void *automata_list_2
)
4026 automata_list_el_t automata_list_el_1
;
4027 automata_list_el_t automata_list_el_2
;
4029 for (automata_list_el_1
= (automata_list_el_t
) automata_list_1
,
4030 automata_list_el_2
= (automata_list_el_t
) automata_list_2
;
4031 automata_list_el_1
!= NULL
&& automata_list_el_2
!= NULL
;
4032 automata_list_el_1
= automata_list_el_1
->next_automata_list_el
,
4033 automata_list_el_2
= automata_list_el_2
->next_automata_list_el
)
4034 if (automata_list_el_1
->automaton
!= automata_list_el_2
->automaton
)
4036 return automata_list_el_1
== automata_list_el_2
;
4039 /* Initialization of the abstract data. */
4041 initiate_automata_lists (void)
4043 first_free_automata_list_el
= NULL
;
4044 automata_list_table
= htab_create (1500, automata_list_hash
,
4045 automata_list_eq_p
, (htab_del
) 0);
4048 /* The following function starts new automata list and makes it the
4051 automata_list_start (void)
4053 current_automata_list
= NULL
;
4056 /* The following function adds AUTOMATON to the current list. */
4058 automata_list_add (automaton_t automaton
)
4060 automata_list_el_t el
;
4062 el
= get_free_automata_list_el ();
4063 el
->automaton
= automaton
;
4064 el
->next_automata_list_el
= current_automata_list
;
4065 current_automata_list
= el
;
4068 /* The following function finishes forming the current list, inserts
4069 it into the table and returns it. */
4070 static automata_list_el_t
4071 automata_list_finish (void)
4075 if (current_automata_list
== NULL
)
4077 entry_ptr
= htab_find_slot (automata_list_table
,
4078 (void *) current_automata_list
, 1);
4079 if (*entry_ptr
== NULL
)
4080 *entry_ptr
= (void *) current_automata_list
;
4082 free_automata_list (current_automata_list
);
4083 current_automata_list
= NULL
;
4084 return (automata_list_el_t
) *entry_ptr
;
4087 /* Finishing work with the abstract data. */
4089 finish_automata_lists (void)
4091 htab_delete (automata_list_table
);
4096 /* The page contains abstract data for work with exclusion sets (see
4097 exclusion_set in file rtl.def). */
4099 /* The following variable refers to an exclusion set returned by
4100 get_excl_set. This is bit string of length equal to cpu units
4101 number. If exclusion set for given unit contains 1 for a unit,
4102 then simultaneous reservation of the units is prohibited. */
4103 static reserv_sets_t excl_set
;
4105 /* The array contains exclusion sets for each unit. */
4106 static reserv_sets_t
*unit_excl_set_table
;
4108 /* The following function forms the array containing exclusion sets
4111 initiate_excl_sets (void)
4114 reserv_sets_t unit_excl_set
;
4118 obstack_blank (&irp
, els_in_cycle_reserv
* sizeof (set_el_t
));
4119 excl_set
= (reserv_sets_t
) obstack_base (&irp
);
4120 obstack_finish (&irp
);
4121 obstack_blank (&irp
, description
->units_num
* sizeof (reserv_sets_t
));
4122 unit_excl_set_table
= (reserv_sets_t
*) obstack_base (&irp
);
4123 obstack_finish (&irp
);
4124 /* Evaluate unit exclusion sets. */
4125 for (i
= 0; i
< description
->decls_num
; i
++)
4127 decl
= description
->decls
[i
];
4128 if (decl
->mode
== dm_unit
)
4130 obstack_blank (&irp
, els_in_cycle_reserv
* sizeof (set_el_t
));
4131 unit_excl_set
= (reserv_sets_t
) obstack_base (&irp
);
4132 obstack_finish (&irp
);
4133 memset (unit_excl_set
, 0, els_in_cycle_reserv
* sizeof (set_el_t
));
4134 for (el
= DECL_UNIT (decl
)->excl_list
;
4136 el
= el
->next_unit_set_el
)
4138 SET_BIT (unit_excl_set
, el
->unit_decl
->unit_num
);
4139 el
->unit_decl
->in_set_p
= TRUE
;
4141 unit_excl_set_table
[DECL_UNIT (decl
)->unit_num
] = unit_excl_set
;
4146 /* The function sets up and return EXCL_SET which is union of
4147 exclusion sets for each unit in IN_SET. */
4148 static reserv_sets_t
4149 get_excl_set (reserv_sets_t in_set
)
4157 chars_num
= els_in_cycle_reserv
* sizeof (set_el_t
);
4158 memset (excl_set
, 0, chars_num
);
4159 for (excl_char_num
= 0; excl_char_num
< chars_num
; excl_char_num
++)
4160 if (((unsigned char *) in_set
) [excl_char_num
])
4161 for (i
= CHAR_BIT
- 1; i
>= 0; i
--)
4162 if ((((unsigned char *) in_set
) [excl_char_num
] >> i
) & 1)
4164 start_unit_num
= excl_char_num
* CHAR_BIT
+ i
;
4165 if (start_unit_num
>= description
->units_num
)
4167 for (unit_num
= 0; unit_num
< els_in_cycle_reserv
; unit_num
++)
4170 |= unit_excl_set_table
[start_unit_num
] [unit_num
];
4178 /* The page contains abstract data for work with presence/absence
4179 pattern sets (see presence_set/absence_set in file rtl.def). */
4181 /* The following arrays contain correspondingly presence, final
4182 presence, absence, and final absence patterns for each unit. */
4183 static pattern_reserv_t
*unit_presence_set_table
;
4184 static pattern_reserv_t
*unit_final_presence_set_table
;
4185 static pattern_reserv_t
*unit_absence_set_table
;
4186 static pattern_reserv_t
*unit_final_absence_set_table
;
4188 /* The following function forms list of reservation sets for given
4190 static pattern_reserv_t
4191 form_reserv_sets_list (pattern_set_el_t pattern_list
)
4193 pattern_set_el_t el
;
4194 pattern_reserv_t first
, curr
, prev
;
4197 prev
= first
= NULL
;
4198 for (el
= pattern_list
; el
!= NULL
; el
= el
->next_pattern_set_el
)
4200 curr
= create_node (sizeof (struct pattern_reserv
));
4201 curr
->reserv
= alloc_empty_reserv_sets ();
4202 curr
->next_pattern_reserv
= NULL
;
4203 for (i
= 0; i
< el
->units_num
; i
++)
4205 SET_BIT (curr
->reserv
, el
->unit_decls
[i
]->unit_num
);
4206 el
->unit_decls
[i
]->in_set_p
= TRUE
;
4209 prev
->next_pattern_reserv
= curr
;
4217 /* The following function forms the array containing presence and
4218 absence pattern sets for each unit. */
4220 initiate_presence_absence_pattern_sets (void)
4225 obstack_blank (&irp
, description
->units_num
* sizeof (pattern_reserv_t
));
4226 unit_presence_set_table
= (pattern_reserv_t
*) obstack_base (&irp
);
4227 obstack_finish (&irp
);
4228 obstack_blank (&irp
, description
->units_num
* sizeof (pattern_reserv_t
));
4229 unit_final_presence_set_table
= (pattern_reserv_t
*) obstack_base (&irp
);
4230 obstack_finish (&irp
);
4231 obstack_blank (&irp
, description
->units_num
* sizeof (pattern_reserv_t
));
4232 unit_absence_set_table
= (pattern_reserv_t
*) obstack_base (&irp
);
4233 obstack_finish (&irp
);
4234 obstack_blank (&irp
, description
->units_num
* sizeof (pattern_reserv_t
));
4235 unit_final_absence_set_table
= (pattern_reserv_t
*) obstack_base (&irp
);
4236 obstack_finish (&irp
);
4237 /* Evaluate unit presence/absence sets. */
4238 for (i
= 0; i
< description
->decls_num
; i
++)
4240 decl
= description
->decls
[i
];
4241 if (decl
->mode
== dm_unit
)
4243 unit_presence_set_table
[DECL_UNIT (decl
)->unit_num
]
4244 = form_reserv_sets_list (DECL_UNIT (decl
)->presence_list
);
4245 unit_final_presence_set_table
[DECL_UNIT (decl
)->unit_num
]
4246 = form_reserv_sets_list (DECL_UNIT (decl
)->final_presence_list
);
4247 unit_absence_set_table
[DECL_UNIT (decl
)->unit_num
]
4248 = form_reserv_sets_list (DECL_UNIT (decl
)->absence_list
);
4249 unit_final_absence_set_table
[DECL_UNIT (decl
)->unit_num
]
4250 = form_reserv_sets_list (DECL_UNIT (decl
)->final_absence_list
);
4255 /* The function checks that CHECKED_SET satisfies all presence pattern
4256 sets for units in ORIGIONAL_SET. The function returns TRUE if it
4259 check_presence_pattern_sets (reserv_sets_t checked_set
,
4260 reserv_sets_t origional_set
,
4269 pattern_reserv_t pat_reserv
;
4271 chars_num
= els_in_cycle_reserv
* sizeof (set_el_t
);
4272 for (char_num
= 0; char_num
< chars_num
; char_num
++)
4273 if (((unsigned char *) origional_set
) [char_num
])
4274 for (i
= CHAR_BIT
- 1; i
>= 0; i
--)
4275 if ((((unsigned char *) origional_set
) [char_num
] >> i
) & 1)
4277 start_unit_num
= char_num
* CHAR_BIT
+ i
;
4278 if (start_unit_num
>= description
->units_num
)
4281 && unit_final_presence_set_table
[start_unit_num
] == NULL
)
4283 && unit_presence_set_table
[start_unit_num
] == NULL
))
4286 for (pat_reserv
= (final_p
4287 ? unit_final_presence_set_table
[start_unit_num
]
4288 : unit_presence_set_table
[start_unit_num
]);
4290 pat_reserv
= pat_reserv
->next_pattern_reserv
)
4292 for (unit_num
= 0; unit_num
< els_in_cycle_reserv
; unit_num
++)
4293 if ((checked_set
[unit_num
] & pat_reserv
->reserv
[unit_num
])
4294 != pat_reserv
->reserv
[unit_num
])
4296 presence_p
= presence_p
|| unit_num
>= els_in_cycle_reserv
;
4304 /* The function checks that CHECKED_SET satisfies all absence pattern
4305 sets for units in ORIGIONAL_SET. The function returns TRUE if it
4308 check_absence_pattern_sets (reserv_sets_t checked_set
,
4309 reserv_sets_t origional_set
,
4317 pattern_reserv_t pat_reserv
;
4319 chars_num
= els_in_cycle_reserv
* sizeof (set_el_t
);
4320 for (char_num
= 0; char_num
< chars_num
; char_num
++)
4321 if (((unsigned char *) origional_set
) [char_num
])
4322 for (i
= CHAR_BIT
- 1; i
>= 0; i
--)
4323 if ((((unsigned char *) origional_set
) [char_num
] >> i
) & 1)
4325 start_unit_num
= char_num
* CHAR_BIT
+ i
;
4326 if (start_unit_num
>= description
->units_num
)
4328 for (pat_reserv
= (final_p
4329 ? unit_final_absence_set_table
[start_unit_num
]
4330 : unit_absence_set_table
[start_unit_num
]);
4332 pat_reserv
= pat_reserv
->next_pattern_reserv
)
4334 for (unit_num
= 0; unit_num
< els_in_cycle_reserv
; unit_num
++)
4335 if ((checked_set
[unit_num
] & pat_reserv
->reserv
[unit_num
])
4336 != pat_reserv
->reserv
[unit_num
]
4337 && pat_reserv
->reserv
[unit_num
])
4339 if (unit_num
>= els_in_cycle_reserv
)
4348 /* This page contains code for transformation of original reservations
4349 described in .md file. The main goal of transformations is
4350 simplifying reservation and lifting up all `|' on the top of IR
4351 reservation representation. */
4354 /* The following function makes copy of IR representation of
4355 reservation. The function also substitutes all reservations
4356 defined by define_reservation by corresponding value during making
4359 copy_insn_regexp (regexp_t regexp
)
4364 switch (regexp
->mode
)
4367 result
= copy_insn_regexp (REGEXP_RESERV (regexp
)->reserv_decl
->regexp
);
4371 result
= copy_node (regexp
, sizeof (struct regexp
));
4375 result
= copy_node (regexp
, sizeof (struct regexp
));
4376 REGEXP_REPEAT (result
)->regexp
4377 = copy_insn_regexp (REGEXP_REPEAT (regexp
)->regexp
);
4381 result
= copy_node (regexp
,
4382 sizeof (struct regexp
) + sizeof (regexp_t
)
4383 * (REGEXP_SEQUENCE (regexp
)->regexps_num
- 1));
4384 for (i
= 0; i
<REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
4385 REGEXP_SEQUENCE (result
)->regexps
[i
]
4386 = copy_insn_regexp (REGEXP_SEQUENCE (regexp
)->regexps
[i
]);
4390 result
= copy_node (regexp
,
4391 sizeof (struct regexp
) + sizeof (regexp_t
)
4392 * (REGEXP_ALLOF (regexp
)->regexps_num
- 1));
4393 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
4394 REGEXP_ALLOF (result
)->regexps
[i
]
4395 = copy_insn_regexp (REGEXP_ALLOF (regexp
)->regexps
[i
]);
4399 result
= copy_node (regexp
,
4400 sizeof (struct regexp
) + sizeof (regexp_t
)
4401 * (REGEXP_ONEOF (regexp
)->regexps_num
- 1));
4402 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
4403 REGEXP_ONEOF (result
)->regexps
[i
]
4404 = copy_insn_regexp (REGEXP_ONEOF (regexp
)->regexps
[i
]);
4408 result
= copy_node (regexp
, sizeof (struct regexp
));
4417 /* The following variable is set up 1 if a transformation has been
4419 static int regexp_transformed_p
;
4421 /* The function makes transformation
4424 transform_1 (regexp_t regexp
)
4431 if (regexp
->mode
== rm_repeat
)
4433 repeat_num
= REGEXP_REPEAT (regexp
)->repeat_num
;
4434 gcc_assert (repeat_num
> 1);
4435 operand
= REGEXP_REPEAT (regexp
)->regexp
;
4437 regexp
= create_node (sizeof (struct regexp
) + sizeof (regexp_t
)
4438 * (repeat_num
- 1));
4439 regexp
->mode
= rm_sequence
;
4441 REGEXP_SEQUENCE (regexp
)->regexps_num
= repeat_num
;
4442 for (i
= 0; i
< repeat_num
; i
++)
4443 REGEXP_SEQUENCE (regexp
)->regexps
[i
] = copy_insn_regexp (operand
);
4444 regexp_transformed_p
= 1;
4449 /* The function makes transformations
4450 ...,(A,B,...),C,... -> ...,A,B,...,C,...
4451 ...+(A+B+...)+C+... -> ...+A+B+...+C+...
4452 ...|(A|B|...)|C|... -> ...|A|B|...|C|... */
4454 transform_2 (regexp_t regexp
)
4456 if (regexp
->mode
== rm_sequence
)
4458 regexp_t sequence
= NULL
;
4460 int sequence_index
= 0;
4463 for (i
= 0; i
< REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
4464 if (REGEXP_SEQUENCE (regexp
)->regexps
[i
]->mode
== rm_sequence
)
4467 sequence
= REGEXP_SEQUENCE (regexp
)->regexps
[i
];
4470 if (i
< REGEXP_SEQUENCE (regexp
)->regexps_num
)
4472 gcc_assert (REGEXP_SEQUENCE (sequence
)->regexps_num
> 1
4473 && REGEXP_SEQUENCE (regexp
)->regexps_num
> 1);
4474 result
= create_node (sizeof (struct regexp
)
4476 * (REGEXP_SEQUENCE (regexp
)->regexps_num
4477 + REGEXP_SEQUENCE (sequence
)->regexps_num
4479 result
->mode
= rm_sequence
;
4480 result
->pos
= regexp
->pos
;
4481 REGEXP_SEQUENCE (result
)->regexps_num
4482 = (REGEXP_SEQUENCE (regexp
)->regexps_num
4483 + REGEXP_SEQUENCE (sequence
)->regexps_num
- 1);
4484 for (i
= 0; i
< REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
4485 if (i
< sequence_index
)
4486 REGEXP_SEQUENCE (result
)->regexps
[i
]
4487 = copy_insn_regexp (REGEXP_SEQUENCE (regexp
)->regexps
[i
]);
4488 else if (i
> sequence_index
)
4489 REGEXP_SEQUENCE (result
)->regexps
4490 [i
+ REGEXP_SEQUENCE (sequence
)->regexps_num
- 1]
4491 = copy_insn_regexp (REGEXP_SEQUENCE (regexp
)->regexps
[i
]);
4493 for (j
= 0; j
< REGEXP_SEQUENCE (sequence
)->regexps_num
; j
++)
4494 REGEXP_SEQUENCE (result
)->regexps
[i
+ j
]
4495 = copy_insn_regexp (REGEXP_SEQUENCE (sequence
)->regexps
[j
]);
4496 regexp_transformed_p
= 1;
4500 else if (regexp
->mode
== rm_allof
)
4502 regexp_t allof
= NULL
;
4504 int allof_index
= 0;
4507 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
4508 if (REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
== rm_allof
)
4511 allof
= REGEXP_ALLOF (regexp
)->regexps
[i
];
4514 if (i
< REGEXP_ALLOF (regexp
)->regexps_num
)
4516 gcc_assert (REGEXP_ALLOF (allof
)->regexps_num
> 1
4517 && REGEXP_ALLOF (regexp
)->regexps_num
> 1);
4518 result
= create_node (sizeof (struct regexp
)
4520 * (REGEXP_ALLOF (regexp
)->regexps_num
4521 + REGEXP_ALLOF (allof
)->regexps_num
- 2));
4522 result
->mode
= rm_allof
;
4523 result
->pos
= regexp
->pos
;
4524 REGEXP_ALLOF (result
)->regexps_num
4525 = (REGEXP_ALLOF (regexp
)->regexps_num
4526 + REGEXP_ALLOF (allof
)->regexps_num
- 1);
4527 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
4528 if (i
< allof_index
)
4529 REGEXP_ALLOF (result
)->regexps
[i
]
4530 = copy_insn_regexp (REGEXP_ALLOF (regexp
)->regexps
[i
]);
4531 else if (i
> allof_index
)
4532 REGEXP_ALLOF (result
)->regexps
4533 [i
+ REGEXP_ALLOF (allof
)->regexps_num
- 1]
4534 = copy_insn_regexp (REGEXP_ALLOF (regexp
)->regexps
[i
]);
4536 for (j
= 0; j
< REGEXP_ALLOF (allof
)->regexps_num
; j
++)
4537 REGEXP_ALLOF (result
)->regexps
[i
+ j
]
4538 = copy_insn_regexp (REGEXP_ALLOF (allof
)->regexps
[j
]);
4539 regexp_transformed_p
= 1;
4543 else if (regexp
->mode
== rm_oneof
)
4545 regexp_t oneof
= NULL
;
4547 int oneof_index
= 0;
4550 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
4551 if (REGEXP_ONEOF (regexp
)->regexps
[i
]->mode
== rm_oneof
)
4554 oneof
= REGEXP_ONEOF (regexp
)->regexps
[i
];
4557 if (i
< REGEXP_ONEOF (regexp
)->regexps_num
)
4559 gcc_assert (REGEXP_ONEOF (oneof
)->regexps_num
> 1
4560 && REGEXP_ONEOF (regexp
)->regexps_num
> 1);
4561 result
= create_node (sizeof (struct regexp
)
4563 * (REGEXP_ONEOF (regexp
)->regexps_num
4564 + REGEXP_ONEOF (oneof
)->regexps_num
- 2));
4565 result
->mode
= rm_oneof
;
4566 result
->pos
= regexp
->pos
;
4567 REGEXP_ONEOF (result
)->regexps_num
4568 = (REGEXP_ONEOF (regexp
)->regexps_num
4569 + REGEXP_ONEOF (oneof
)->regexps_num
- 1);
4570 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
4571 if (i
< oneof_index
)
4572 REGEXP_ONEOF (result
)->regexps
[i
]
4573 = copy_insn_regexp (REGEXP_ONEOF (regexp
)->regexps
[i
]);
4574 else if (i
> oneof_index
)
4575 REGEXP_ONEOF (result
)->regexps
4576 [i
+ REGEXP_ONEOF (oneof
)->regexps_num
- 1]
4577 = copy_insn_regexp (REGEXP_ONEOF (regexp
)->regexps
[i
]);
4579 for (j
= 0; j
< REGEXP_ONEOF (oneof
)->regexps_num
; j
++)
4580 REGEXP_ONEOF (result
)->regexps
[i
+ j
]
4581 = copy_insn_regexp (REGEXP_ONEOF (oneof
)->regexps
[j
]);
4582 regexp_transformed_p
= 1;
4589 /* The function makes transformations
4590 ...,A|B|...,C,... -> (...,A,C,...)|(...,B,C,...)|...
4591 ...+(A|B|...)+C+... -> (...+A+C+...)|(...+B+C+...)|...
4592 ...+(A,B,...)+C+... -> (...+A+C+...),B,...
4593 ...+(A,B,...)+(C,D,...) -> (A+C),(B+D),... */
4595 transform_3 (regexp_t regexp
)
4597 if (regexp
->mode
== rm_sequence
)
4599 regexp_t oneof
= NULL
;
4600 int oneof_index
= 0;
4605 for (i
= 0; i
<REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
4606 if (REGEXP_SEQUENCE (regexp
)->regexps
[i
]->mode
== rm_oneof
)
4609 oneof
= REGEXP_SEQUENCE (regexp
)->regexps
[i
];
4612 if (i
< REGEXP_SEQUENCE (regexp
)->regexps_num
)
4614 gcc_assert (REGEXP_ONEOF (oneof
)->regexps_num
> 1
4615 && REGEXP_SEQUENCE (regexp
)->regexps_num
> 1);
4616 result
= create_node (sizeof (struct regexp
)
4618 * (REGEXP_ONEOF (oneof
)->regexps_num
- 1));
4619 result
->mode
= rm_oneof
;
4620 result
->pos
= regexp
->pos
;
4621 REGEXP_ONEOF (result
)->regexps_num
4622 = REGEXP_ONEOF (oneof
)->regexps_num
;
4623 for (i
= 0; i
< REGEXP_ONEOF (result
)->regexps_num
; i
++)
4626 = create_node (sizeof (struct regexp
)
4628 * (REGEXP_SEQUENCE (regexp
)->regexps_num
- 1));
4629 sequence
->mode
= rm_sequence
;
4630 sequence
->pos
= regexp
->pos
;
4631 REGEXP_SEQUENCE (sequence
)->regexps_num
4632 = REGEXP_SEQUENCE (regexp
)->regexps_num
;
4633 REGEXP_ONEOF (result
)->regexps
[i
] = sequence
;
4634 for (j
= 0; j
< REGEXP_SEQUENCE (sequence
)->regexps_num
; j
++)
4635 if (j
!= oneof_index
)
4636 REGEXP_SEQUENCE (sequence
)->regexps
[j
]
4637 = copy_insn_regexp (REGEXP_SEQUENCE (regexp
)->regexps
[j
]);
4639 REGEXP_SEQUENCE (sequence
)->regexps
[j
]
4640 = copy_insn_regexp (REGEXP_ONEOF (oneof
)->regexps
[i
]);
4642 regexp_transformed_p
= 1;
4646 else if (regexp
->mode
== rm_allof
)
4648 regexp_t oneof
= NULL
;
4650 int oneof_index
= 0;
4651 int max_seq_length
, allof_length
;
4653 regexp_t allof
= NULL
;
4654 regexp_t allof_op
= NULL
;
4657 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
4658 if (REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
== rm_oneof
)
4661 oneof
= REGEXP_ALLOF (regexp
)->regexps
[i
];
4664 if (i
< REGEXP_ALLOF (regexp
)->regexps_num
)
4666 gcc_assert (REGEXP_ONEOF (oneof
)->regexps_num
> 1
4667 && REGEXP_ALLOF (regexp
)->regexps_num
> 1);
4668 result
= create_node (sizeof (struct regexp
)
4670 * (REGEXP_ONEOF (oneof
)->regexps_num
- 1));
4671 result
->mode
= rm_oneof
;
4672 result
->pos
= regexp
->pos
;
4673 REGEXP_ONEOF (result
)->regexps_num
4674 = REGEXP_ONEOF (oneof
)->regexps_num
;
4675 for (i
= 0; i
< REGEXP_ONEOF (result
)->regexps_num
; i
++)
4678 = create_node (sizeof (struct regexp
)
4680 * (REGEXP_ALLOF (regexp
)->regexps_num
- 1));
4681 allof
->mode
= rm_allof
;
4682 allof
->pos
= regexp
->pos
;
4683 REGEXP_ALLOF (allof
)->regexps_num
4684 = REGEXP_ALLOF (regexp
)->regexps_num
;
4685 REGEXP_ONEOF (result
)->regexps
[i
] = allof
;
4686 for (j
= 0; j
< REGEXP_ALLOF (allof
)->regexps_num
; j
++)
4687 if (j
!= oneof_index
)
4688 REGEXP_ALLOF (allof
)->regexps
[j
]
4689 = copy_insn_regexp (REGEXP_ALLOF (regexp
)->regexps
[j
]);
4691 REGEXP_ALLOF (allof
)->regexps
[j
]
4692 = copy_insn_regexp (REGEXP_ONEOF (oneof
)->regexps
[i
]);
4694 regexp_transformed_p
= 1;
4698 if (regexp
->mode
== rm_allof
)
4699 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
4701 switch (REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
)
4704 seq
= REGEXP_ALLOF (regexp
)->regexps
[i
];
4705 if (max_seq_length
< REGEXP_SEQUENCE (seq
)->regexps_num
)
4706 max_seq_length
= REGEXP_SEQUENCE (seq
)->regexps_num
;
4719 if (max_seq_length
!= 0)
4721 gcc_assert (max_seq_length
!= 1
4722 && REGEXP_ALLOF (regexp
)->regexps_num
> 1);
4723 result
= create_node (sizeof (struct regexp
)
4724 + sizeof (regexp_t
) * (max_seq_length
- 1));
4725 result
->mode
= rm_sequence
;
4726 result
->pos
= regexp
->pos
;
4727 REGEXP_SEQUENCE (result
)->regexps_num
= max_seq_length
;
4728 for (i
= 0; i
< max_seq_length
; i
++)
4731 for (j
= 0; j
< REGEXP_ALLOF (regexp
)->regexps_num
; j
++)
4732 switch (REGEXP_ALLOF (regexp
)->regexps
[j
]->mode
)
4735 if (i
< (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp
)
4736 ->regexps
[j
])->regexps_num
))
4739 = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp
)
4749 allof_op
= REGEXP_ALLOF (regexp
)->regexps
[j
];
4757 if (allof_length
== 1)
4758 REGEXP_SEQUENCE (result
)->regexps
[i
] = allof_op
;
4761 allof
= create_node (sizeof (struct regexp
)
4763 * (allof_length
- 1));
4764 allof
->mode
= rm_allof
;
4765 allof
->pos
= regexp
->pos
;
4766 REGEXP_ALLOF (allof
)->regexps_num
= allof_length
;
4767 REGEXP_SEQUENCE (result
)->regexps
[i
] = allof
;
4769 for (j
= 0; j
< REGEXP_ALLOF (regexp
)->regexps_num
; j
++)
4770 if (REGEXP_ALLOF (regexp
)->regexps
[j
]->mode
== rm_sequence
4772 (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp
)
4773 ->regexps
[j
])->regexps_num
)))
4775 allof_op
= (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp
)
4778 REGEXP_ALLOF (allof
)->regexps
[allof_length
]
4783 && (REGEXP_ALLOF (regexp
)->regexps
[j
]->mode
4785 || (REGEXP_ALLOF (regexp
)->regexps
[j
]->mode
4788 allof_op
= REGEXP_ALLOF (regexp
)->regexps
[j
];
4789 REGEXP_ALLOF (allof
)->regexps
[allof_length
]
4795 regexp_transformed_p
= 1;
4802 /* The function traverses IR of reservation and applies transformations
4803 implemented by FUNC. */
4805 regexp_transform_func (regexp_t regexp
, regexp_t (*func
) (regexp_t regexp
))
4809 switch (regexp
->mode
)
4812 for (i
= 0; i
< REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
4813 REGEXP_SEQUENCE (regexp
)->regexps
[i
]
4814 = regexp_transform_func (REGEXP_SEQUENCE (regexp
)->regexps
[i
],
4819 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
4820 REGEXP_ALLOF (regexp
)->regexps
[i
]
4821 = regexp_transform_func (REGEXP_ALLOF (regexp
)->regexps
[i
], func
);
4825 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
4826 REGEXP_ONEOF (regexp
)->regexps
[i
]
4827 = regexp_transform_func (REGEXP_ONEOF (regexp
)->regexps
[i
], func
);
4831 REGEXP_REPEAT (regexp
)->regexp
4832 = regexp_transform_func (REGEXP_REPEAT (regexp
)->regexp
, func
);
4842 return (*func
) (regexp
);
4845 /* The function applies all transformations for IR representation of
4846 reservation REGEXP. */
4848 transform_regexp (regexp_t regexp
)
4850 regexp
= regexp_transform_func (regexp
, transform_1
);
4853 regexp_transformed_p
= 0;
4854 regexp
= regexp_transform_func (regexp
, transform_2
);
4855 regexp
= regexp_transform_func (regexp
, transform_3
);
4857 while (regexp_transformed_p
);
4861 /* The function applies all transformations for reservations of all
4862 insn declarations. */
4864 transform_insn_regexps (void)
4869 transform_time
= create_ticker ();
4870 add_advance_cycle_insn_decl ();
4872 fprintf (stderr
, "Reservation transformation...");
4873 for (i
= 0; i
< description
->decls_num
; i
++)
4875 decl
= description
->decls
[i
];
4876 if (decl
->mode
== dm_insn_reserv
&& decl
!= advance_cycle_insn_decl
)
4877 DECL_INSN_RESERV (decl
)->transformed_regexp
4878 = transform_regexp (copy_insn_regexp
4879 (DECL_INSN_RESERV (decl
)->regexp
));
4882 fprintf (stderr
, "done\n");
4883 ticker_off (&transform_time
);
4888 /* The following variable value is TRUE if the first annotated message
4889 about units to automata distribution has been output. */
4890 static int annotation_message_reported_p
;
4892 /* The following structure describes usage of a unit in a reservation. */
4895 unit_decl_t unit_decl
;
4896 /* The following forms a list of units used on the same cycle in the
4897 same alternative. */
4898 struct unit_usage
*next
;
4900 typedef struct unit_usage
*unit_usage_t
;
4902 DEF_VEC_P(unit_usage_t
);
4903 DEF_VEC_ALLOC_P(unit_usage_t
,heap
);
4905 /* Obstack for unit_usage structures. */
4906 static struct obstack unit_usages
;
4908 /* VLA for representation of array of pointers to unit usage
4909 structures. There is an element for each combination of
4910 (alternative number, cycle). Unit usages on given cycle in
4911 alternative with given number are referred through element with
4912 index equals to the cycle * number of all alternatives in the regexp
4913 + the alternative number. */
4914 static VEC(unit_usage_t
,heap
) *cycle_alt_unit_usages
;
4916 /* The following function creates the structure unit_usage for UNIT on
4917 CYCLE in REGEXP alternative with ALT_NUM. The structure is made
4918 accessed through cycle_alt_unit_usages. */
4920 store_alt_unit_usage (regexp_t regexp
, regexp_t unit
, int cycle
,
4924 unit_decl_t unit_decl
;
4925 unit_usage_t unit_usage_ptr
;
4928 gcc_assert (regexp
&& regexp
->mode
== rm_oneof
4929 && alt_num
< REGEXP_ONEOF (regexp
)->regexps_num
);
4930 unit_decl
= REGEXP_UNIT (unit
)->unit_decl
;
4932 length
= (cycle
+ 1) * REGEXP_ONEOF (regexp
)->regexps_num
;
4933 while (VEC_length (unit_usage_t
, cycle_alt_unit_usages
) < length
)
4934 VEC_safe_push (unit_usage_t
,heap
, cycle_alt_unit_usages
, 0);
4936 obstack_blank (&unit_usages
, sizeof (struct unit_usage
));
4937 unit_usage_ptr
= (struct unit_usage
*) obstack_base (&unit_usages
);
4938 obstack_finish (&unit_usages
);
4939 unit_usage_ptr
->unit_decl
= unit_decl
;
4940 index
= cycle
* REGEXP_ONEOF (regexp
)->regexps_num
+ alt_num
;
4941 unit_usage_ptr
->next
= VEC_index (unit_usage_t
, cycle_alt_unit_usages
, index
);
4942 VEC_replace (unit_usage_t
, cycle_alt_unit_usages
, index
, unit_usage_ptr
);
4943 unit_decl
->last_distribution_check_cycle
= -1; /* undefined */
4946 /* The function processes given REGEXP to find units with the wrong
4949 check_regexp_units_distribution (const char *insn_reserv_name
,
4953 regexp_t seq
, allof
, unit
;
4954 struct unit_usage
*unit_usage_ptr
, *other_unit_usage_ptr
;
4956 if (regexp
== NULL
|| regexp
->mode
!= rm_oneof
)
4958 /* Store all unit usages in the regexp: */
4959 obstack_init (&unit_usages
);
4960 cycle_alt_unit_usages
= 0;
4962 for (i
= REGEXP_ONEOF (regexp
)->regexps_num
- 1; i
>= 0; i
--)
4964 seq
= REGEXP_ONEOF (regexp
)->regexps
[i
];
4968 for (j
= 0; j
< REGEXP_SEQUENCE (seq
)->regexps_num
; j
++)
4970 allof
= REGEXP_SEQUENCE (seq
)->regexps
[j
];
4971 switch (allof
->mode
)
4974 for (k
= 0; k
< REGEXP_ALLOF (allof
)->regexps_num
; k
++)
4976 unit
= REGEXP_ALLOF (allof
)->regexps
[k
];
4977 if (unit
->mode
== rm_unit
)
4978 store_alt_unit_usage (regexp
, unit
, j
, i
);
4980 gcc_assert (unit
->mode
== rm_nothing
);
4985 store_alt_unit_usage (regexp
, allof
, j
, i
);
4998 for (k
= 0; k
< REGEXP_ALLOF (seq
)->regexps_num
; k
++)
5000 unit
= REGEXP_ALLOF (seq
)->regexps
[k
];
5004 store_alt_unit_usage (regexp
, unit
, 0, i
);
5017 store_alt_unit_usage (regexp
, seq
, 0, i
);
5027 /* Check distribution: */
5028 for (i
= 0; i
< (int) VEC_length (unit_usage_t
, cycle_alt_unit_usages
); i
++)
5030 cycle
= i
/ REGEXP_ONEOF (regexp
)->regexps_num
;
5031 for (unit_usage_ptr
= VEC_index (unit_usage_t
, cycle_alt_unit_usages
, i
);
5032 unit_usage_ptr
!= NULL
;
5033 unit_usage_ptr
= unit_usage_ptr
->next
)
5034 if (cycle
!= unit_usage_ptr
->unit_decl
->last_distribution_check_cycle
)
5036 unit_usage_ptr
->unit_decl
->last_distribution_check_cycle
= cycle
;
5037 for (k
= cycle
* REGEXP_ONEOF (regexp
)->regexps_num
;
5038 k
< (int) VEC_length (unit_usage_t
, cycle_alt_unit_usages
)
5039 && k
== cycle
* REGEXP_ONEOF (regexp
)->regexps_num
;
5042 for (other_unit_usage_ptr
5043 = VEC_index (unit_usage_t
, cycle_alt_unit_usages
, k
);
5044 other_unit_usage_ptr
!= NULL
;
5045 other_unit_usage_ptr
= other_unit_usage_ptr
->next
)
5046 if (unit_usage_ptr
->unit_decl
->automaton_decl
5047 == other_unit_usage_ptr
->unit_decl
->automaton_decl
)
5049 if (other_unit_usage_ptr
== NULL
5050 && (VEC_index (unit_usage_t
, cycle_alt_unit_usages
, k
)
5054 if (k
< (int) VEC_length (unit_usage_t
, cycle_alt_unit_usages
)
5055 && k
== cycle
* REGEXP_ONEOF (regexp
)->regexps_num
)
5057 if (!annotation_message_reported_p
)
5059 fprintf (stderr
, "\n");
5060 error ("The following units do not satisfy units-automata distribution rule");
5061 error (" (A unit of given unit automaton should be on each reserv. altern.)");
5062 annotation_message_reported_p
= TRUE
;
5064 error ("Unit %s, reserv. %s, cycle %d",
5065 unit_usage_ptr
->unit_decl
->name
, insn_reserv_name
,
5070 VEC_free (unit_usage_t
,heap
, cycle_alt_unit_usages
);
5071 obstack_free (&unit_usages
, NULL
);
5074 /* The function finds units which violates units to automata
5075 distribution rule. If the units exist, report about them. */
5077 check_unit_distributions_to_automata (void)
5083 fprintf (stderr
, "Check unit distributions to automata...");
5084 annotation_message_reported_p
= FALSE
;
5085 for (i
= 0; i
< description
->decls_num
; i
++)
5087 decl
= description
->decls
[i
];
5088 if (decl
->mode
== dm_insn_reserv
)
5089 check_regexp_units_distribution
5090 (DECL_INSN_RESERV (decl
)->name
,
5091 DECL_INSN_RESERV (decl
)->transformed_regexp
);
5094 fprintf (stderr
, "done\n");
5099 /* The page contains code for building alt_states (see comments for
5100 IR) describing all possible insns reservations of an automaton. */
5102 /* Current state being formed for which the current alt_state
5104 static state_t state_being_formed
;
5106 /* Current alt_state being formed. */
5107 static alt_state_t alt_state_being_formed
;
5109 /* This recursive function processes `,' and units in reservation
5110 REGEXP for forming alt_states of AUTOMATON. It is believed that
5111 CURR_CYCLE is start cycle of all reservation REGEXP. */
5113 process_seq_for_forming_states (regexp_t regexp
, automaton_t automaton
,
5121 switch (regexp
->mode
)
5124 if (REGEXP_UNIT (regexp
)->unit_decl
->corresponding_automaton_num
5125 == automaton
->automaton_order_num
)
5126 set_state_reserv (state_being_formed
, curr_cycle
,
5127 REGEXP_UNIT (regexp
)->unit_decl
->unit_num
);
5131 for (i
= 0; i
< REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
5133 = process_seq_for_forming_states
5134 (REGEXP_SEQUENCE (regexp
)->regexps
[i
], automaton
, curr_cycle
) + 1;
5139 int finish_cycle
= 0;
5142 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
5144 cycle
= process_seq_for_forming_states (REGEXP_ALLOF (regexp
)
5146 automaton
, curr_cycle
);
5147 if (finish_cycle
< cycle
)
5148 finish_cycle
= cycle
;
5150 return finish_cycle
;
5161 /* This recursive function finishes forming ALT_STATE of AUTOMATON and
5162 inserts alt_state into the table. */
5164 finish_forming_alt_state (alt_state_t alt_state
,
5165 automaton_t automaton ATTRIBUTE_UNUSED
)
5167 state_t state_in_table
;
5168 state_t corresponding_state
;
5170 corresponding_state
= alt_state
->state
;
5171 state_in_table
= insert_state (corresponding_state
);
5172 if (state_in_table
!= corresponding_state
)
5174 free_state (corresponding_state
);
5175 alt_state
->state
= state_in_table
;
5179 /* The following variable value is current automaton insn for whose
5180 reservation the alt states are created. */
5181 static ainsn_t curr_ainsn
;
5183 /* This recursive function processes `|' in reservation REGEXP for
5184 forming alt_states of AUTOMATON. List of the alt states should
5185 have the same order as in the description. */
5187 process_alts_for_forming_states (regexp_t regexp
, automaton_t automaton
,
5192 if (regexp
->mode
!= rm_oneof
)
5194 alt_state_being_formed
= get_free_alt_state ();
5195 state_being_formed
= get_free_state (1, automaton
);
5196 alt_state_being_formed
->state
= state_being_formed
;
5197 /* We inserts in reverse order but we process alternatives also
5198 in reverse order. So we have the same order of alternative
5199 as in the description. */
5200 alt_state_being_formed
->next_alt_state
= curr_ainsn
->alt_states
;
5201 curr_ainsn
->alt_states
= alt_state_being_formed
;
5202 (void) process_seq_for_forming_states (regexp
, automaton
, 0);
5203 finish_forming_alt_state (alt_state_being_formed
, automaton
);
5207 gcc_assert (!inside_oneof_p
);
5208 /* We processes it in reverse order to get list with the same
5209 order as in the description. See also the previous
5211 for (i
= REGEXP_ONEOF (regexp
)->regexps_num
- 1; i
>= 0; i
--)
5212 process_alts_for_forming_states (REGEXP_ONEOF (regexp
)->regexps
[i
],
5217 /* Create nodes alt_state for all AUTOMATON insns. */
5219 create_alt_states (automaton_t automaton
)
5221 struct insn_reserv_decl
*reserv_decl
;
5223 for (curr_ainsn
= automaton
->ainsn_list
;
5225 curr_ainsn
= curr_ainsn
->next_ainsn
)
5227 reserv_decl
= curr_ainsn
->insn_reserv_decl
;
5228 if (reserv_decl
!= DECL_INSN_RESERV (advance_cycle_insn_decl
))
5230 curr_ainsn
->alt_states
= NULL
;
5231 process_alts_for_forming_states (reserv_decl
->transformed_regexp
,
5233 curr_ainsn
->sorted_alt_states
5234 = uniq_sort_alt_states (curr_ainsn
->alt_states
);
5241 /* The page contains major code for building DFA(s) for fast pipeline
5242 hazards recognition. */
5244 /* The function forms list of ainsns of AUTOMATON with the same
5248 form_ainsn_with_same_reservs (automaton_t automaton
)
5252 VEC(ainsn_t
,heap
) *last_insns
= VEC_alloc (ainsn_t
,heap
, 150);
5254 for (curr_ainsn
= automaton
->ainsn_list
;
5256 curr_ainsn
= curr_ainsn
->next_ainsn
)
5257 if (curr_ainsn
->insn_reserv_decl
5258 == DECL_INSN_RESERV (advance_cycle_insn_decl
))
5260 curr_ainsn
->next_same_reservs_insn
= NULL
;
5261 curr_ainsn
->first_insn_with_same_reservs
= 1;
5265 for (i
= 0; i
< VEC_length (ainsn_t
, last_insns
); i
++)
5267 (curr_ainsn
->sorted_alt_states
,
5268 VEC_index (ainsn_t
, last_insns
, i
)->sorted_alt_states
))
5270 curr_ainsn
->next_same_reservs_insn
= NULL
;
5271 if (i
< VEC_length (ainsn_t
, last_insns
))
5273 curr_ainsn
->first_insn_with_same_reservs
= 0;
5274 VEC_index (ainsn_t
, last_insns
, i
)->next_same_reservs_insn
5276 VEC_replace (ainsn_t
, last_insns
, i
, curr_ainsn
);
5280 VEC_safe_push (ainsn_t
, heap
, last_insns
, curr_ainsn
);
5281 curr_ainsn
->first_insn_with_same_reservs
= 1;
5284 VEC_free (ainsn_t
,heap
, last_insns
);
5287 /* Forming unit reservations which can affect creating the automaton
5288 states achieved from a given state. It permits to build smaller
5289 automata in many cases. We would have the same automata after
5290 the minimization without such optimization, but the automaton
5291 right after the building could be huge. So in other words, usage
5292 of reservs_matter means some minimization during building the
5294 static reserv_sets_t
5295 form_reservs_matter (automaton_t automaton
)
5298 reserv_sets_t reservs_matter
= alloc_empty_reserv_sets();
5300 for (cycle
= 0; cycle
< max_cycles_num
; cycle
++)
5301 for (unit
= 0; unit
< description
->units_num
; unit
++)
5302 if (units_array
[unit
]->automaton_decl
5303 == automaton
->corresponding_automaton_decl
5304 && (cycle
>= units_array
[unit
]->min_occ_cycle_num
5305 /* We can not remove queried unit from reservations. */
5306 || units_array
[unit
]->query_p
5307 /* We can not remove units which are used
5308 `exclusion_set', `presence_set',
5309 `final_presence_set', `absence_set', and
5310 `final_absence_set'. */
5311 || units_array
[unit
]->in_set_p
))
5312 set_unit_reserv (reservs_matter
, cycle
, unit
);
5313 return reservs_matter
;
5316 /* The following function creates all states of nondeterministic AUTOMATON. */
5318 make_automaton (automaton_t automaton
)
5321 struct insn_reserv_decl
*insn_reserv_decl
;
5322 alt_state_t alt_state
;
5324 state_t start_state
;
5326 ainsn_t advance_cycle_ainsn
;
5328 VEC(state_t
,heap
) *state_stack
= VEC_alloc(state_t
,heap
, 150);
5330 reserv_sets_t reservs_matter
= form_reservs_matter (automaton
);
5332 /* Create the start state (empty state). */
5333 start_state
= insert_state (get_free_state (1, automaton
));
5334 automaton
->start_state
= start_state
;
5335 start_state
->it_was_placed_in_stack_for_NDFA_forming
= 1;
5336 VEC_safe_push (state_t
,heap
, state_stack
, start_state
);
5338 while (VEC_length (state_t
, state_stack
) != 0)
5340 state
= VEC_pop (state_t
, state_stack
);
5341 advance_cycle_ainsn
= NULL
;
5342 for (ainsn
= automaton
->ainsn_list
;
5344 ainsn
= ainsn
->next_ainsn
)
5345 if (ainsn
->first_insn_with_same_reservs
)
5347 insn_reserv_decl
= ainsn
->insn_reserv_decl
;
5348 if (insn_reserv_decl
!= DECL_INSN_RESERV (advance_cycle_insn_decl
))
5350 /* We process alt_states in the same order as they are
5351 present in the description. */
5353 for (alt_state
= ainsn
->alt_states
;
5355 alt_state
= alt_state
->next_alt_state
)
5357 state2
= alt_state
->state
;
5358 if (!intersected_state_reservs_p (state
, state2
))
5360 state2
= states_union (state
, state2
, reservs_matter
);
5361 if (!state2
->it_was_placed_in_stack_for_NDFA_forming
)
5363 state2
->it_was_placed_in_stack_for_NDFA_forming
5365 VEC_safe_push (state_t
,heap
, state_stack
, state2
);
5367 if (progress_flag
&& states_n
% 100 == 0)
5368 fprintf (stderr
, ".");
5370 added_arc
= add_arc (state
, state2
, ainsn
);
5375 if (!ndfa_flag
&& added_arc
!= NULL
)
5377 for (alt_state
= ainsn
->alt_states
;
5379 alt_state
= alt_state
->next_alt_state
)
5380 state2
= alt_state
->state
;
5384 advance_cycle_ainsn
= ainsn
;
5386 /* Add transition to advance cycle. */
5387 state2
= state_shift (state
, reservs_matter
);
5388 if (!state2
->it_was_placed_in_stack_for_NDFA_forming
)
5390 state2
->it_was_placed_in_stack_for_NDFA_forming
= 1;
5391 VEC_safe_push (state_t
,heap
, state_stack
, state2
);
5393 if (progress_flag
&& states_n
% 100 == 0)
5394 fprintf (stderr
, ".");
5396 gcc_assert (advance_cycle_ainsn
);
5397 add_arc (state
, state2
, advance_cycle_ainsn
);
5399 VEC_free (state_t
,heap
, state_stack
);
5402 /* Foms lists of all arcs of STATE marked by the same ainsn. */
5404 form_arcs_marked_by_insn (state_t state
)
5410 for (i
= 0; i
< description
->decls_num
; i
++)
5412 decl
= description
->decls
[i
];
5413 if (decl
->mode
== dm_insn_reserv
)
5414 DECL_INSN_RESERV (decl
)->arcs_marked_by_insn
= NULL
;
5416 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
5418 gcc_assert (arc
->insn
);
5419 arc
->next_arc_marked_by_insn
5420 = arc
->insn
->insn_reserv_decl
->arcs_marked_by_insn
;
5421 arc
->insn
->insn_reserv_decl
->arcs_marked_by_insn
= arc
;
5425 /* The function creates composed state (see comments for IR) from
5426 ORIGINAL_STATE and list of arcs ARCS_MARKED_BY_INSN marked by the
5427 same insn. If the composed state is not in STATE_STACK yet, it is
5428 pushed into STATE_STACK. */
5431 create_composed_state (state_t original_state
, arc_t arcs_marked_by_insn
,
5432 VEC(state_t
,heap
) **state_stack
)
5435 alt_state_t alt_state
, curr_alt_state
;
5436 alt_state_t new_alt_state
;
5439 state_t state_in_table
;
5441 alt_state_t canonical_alt_states_list
;
5443 int new_state_p
= 0;
5445 if (arcs_marked_by_insn
== NULL
)
5447 if (arcs_marked_by_insn
->next_arc_marked_by_insn
== NULL
)
5448 state
= arcs_marked_by_insn
->to_state
;
5451 gcc_assert (ndfa_flag
);
5452 /* Create composed state. */
5453 state
= get_free_state (0, arcs_marked_by_insn
->to_state
->automaton
);
5454 curr_alt_state
= NULL
;
5455 for (curr_arc
= arcs_marked_by_insn
;
5457 curr_arc
= curr_arc
->next_arc_marked_by_insn
)
5458 if (curr_arc
->to_state
->component_states
== NULL
)
5460 new_alt_state
= get_free_alt_state ();
5461 new_alt_state
->next_alt_state
= curr_alt_state
;
5462 new_alt_state
->state
= curr_arc
->to_state
;
5463 curr_alt_state
= new_alt_state
;
5466 for (alt_state
= curr_arc
->to_state
->component_states
;
5468 alt_state
= alt_state
->next_sorted_alt_state
)
5470 new_alt_state
= get_free_alt_state ();
5471 new_alt_state
->next_alt_state
= curr_alt_state
;
5472 new_alt_state
->state
= alt_state
->state
;
5473 gcc_assert (!alt_state
->state
->component_states
);
5474 curr_alt_state
= new_alt_state
;
5476 /* There are not identical sets in the alt state list. */
5477 canonical_alt_states_list
= uniq_sort_alt_states (curr_alt_state
);
5478 if (canonical_alt_states_list
->next_sorted_alt_state
== NULL
)
5481 state
= canonical_alt_states_list
->state
;
5482 free_state (temp_state
);
5486 state
->component_states
= canonical_alt_states_list
;
5487 state_in_table
= insert_state (state
);
5488 if (state_in_table
!= state
)
5491 (state_in_table
->it_was_placed_in_stack_for_DFA_forming
);
5493 state
= state_in_table
;
5497 gcc_assert (!state
->it_was_placed_in_stack_for_DFA_forming
);
5499 for (curr_alt_state
= state
->component_states
;
5500 curr_alt_state
!= NULL
;
5501 curr_alt_state
= curr_alt_state
->next_sorted_alt_state
)
5502 for (curr_arc
= first_out_arc (curr_alt_state
->state
);
5504 curr_arc
= next_out_arc (curr_arc
))
5505 add_arc (state
, curr_arc
->to_state
, curr_arc
->insn
);
5507 arcs_marked_by_insn
->to_state
= state
;
5508 for (alts_number
= 0,
5509 curr_arc
= arcs_marked_by_insn
->next_arc_marked_by_insn
;
5511 curr_arc
= next_arc
)
5513 next_arc
= curr_arc
->next_arc_marked_by_insn
;
5514 remove_arc (original_state
, curr_arc
);
5519 if (!state
->it_was_placed_in_stack_for_DFA_forming
)
5521 state
->it_was_placed_in_stack_for_DFA_forming
= 1;
5522 VEC_safe_push (state_t
,heap
, *state_stack
, state
);
5527 /* The function transforms nondeterministic AUTOMATON into
5531 NDFA_to_DFA (automaton_t automaton
)
5533 state_t start_state
;
5536 VEC(state_t
,heap
) *state_stack
;
5540 state_stack
= VEC_alloc (state_t
,heap
, 0);
5542 /* Create the start state (empty state). */
5543 start_state
= automaton
->start_state
;
5544 start_state
->it_was_placed_in_stack_for_DFA_forming
= 1;
5545 VEC_safe_push (state_t
,heap
, state_stack
, start_state
);
5547 while (VEC_length (state_t
, state_stack
) != 0)
5549 state
= VEC_pop (state_t
, state_stack
);
5550 form_arcs_marked_by_insn (state
);
5551 for (i
= 0; i
< description
->decls_num
; i
++)
5553 decl
= description
->decls
[i
];
5554 if (decl
->mode
== dm_insn_reserv
5555 && create_composed_state
5556 (state
, DECL_INSN_RESERV (decl
)->arcs_marked_by_insn
,
5560 if (progress_flag
&& states_n
% 100 == 0)
5561 fprintf (stderr
, ".");
5565 VEC_free (state_t
,heap
, state_stack
);
5568 /* The following variable value is current number (1, 2, ...) of passing
5570 static int curr_state_graph_pass_num
;
5572 /* This recursive function passes all states achieved from START_STATE
5573 and applies APPLIED_FUNC to them. */
5575 pass_state_graph (state_t start_state
, void (*applied_func
) (state_t state
))
5579 if (start_state
->pass_num
== curr_state_graph_pass_num
)
5581 start_state
->pass_num
= curr_state_graph_pass_num
;
5582 (*applied_func
) (start_state
);
5583 for (arc
= first_out_arc (start_state
);
5585 arc
= next_out_arc (arc
))
5586 pass_state_graph (arc
->to_state
, applied_func
);
5589 /* This recursive function passes all states of AUTOMATON and applies
5590 APPLIED_FUNC to them. */
5592 pass_states (automaton_t automaton
, void (*applied_func
) (state_t state
))
5594 curr_state_graph_pass_num
++;
5595 pass_state_graph (automaton
->start_state
, applied_func
);
5598 /* The function initializes code for passing of all states. */
5600 initiate_pass_states (void)
5602 curr_state_graph_pass_num
= 0;
5605 /* The following vla is used for storing pointers to all achieved
5607 static VEC(state_t
,heap
) *all_achieved_states
;
5609 /* This function is called by function pass_states to add an achieved
5612 add_achieved_state (state_t state
)
5614 VEC_safe_push (state_t
,heap
, all_achieved_states
, state
);
5617 /* The function sets up equivalence numbers of insns which mark all
5618 out arcs of STATE by equiv_class_num_1 (if ODD_ITERATION_FLAG has
5619 nonzero value) or by equiv_class_num_2 of the destination state.
5620 The function returns number of out arcs of STATE. */
5622 set_out_arc_insns_equiv_num (state_t state
, int odd_iteration_flag
)
5626 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
5628 gcc_assert (!arc
->insn
->insn_reserv_decl
->equiv_class_num
);
5629 arc
->insn
->insn_reserv_decl
->equiv_class_num
5630 = (odd_iteration_flag
5631 ? arc
->to_state
->equiv_class_num_1
5632 : arc
->to_state
->equiv_class_num_2
);
5633 gcc_assert (arc
->insn
->insn_reserv_decl
->equiv_class_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 /* This fills in the presence_signature[] member of STATE. */
5671 cache_presence (state_t state
)
5675 sz
= (description
->query_units_num
+ sizeof (int) * CHAR_BIT
- 1)
5676 / (sizeof (int) * CHAR_BIT
);
5678 state
->presence_signature
= create_node (sz
* sizeof (int));
5679 for (i
= 0; i
< description
->units_num
; i
++)
5680 if (units_array
[i
]->query_p
)
5682 int presence1_p
= first_cycle_unit_presence (state
, i
);
5683 state
->presence_signature
[num
/ (sizeof (int) * CHAR_BIT
)]
5684 |= (!!presence1_p
) << (num
% (sizeof (int) * CHAR_BIT
));
5689 /* The function returns nonzero value if STATE is not equivalent to
5690 ANOTHER_STATE from the same current partition on equivalence
5691 classes. Another state has ANOTHER_STATE_OUT_ARCS_NUM number of
5692 output arcs. Iteration of making equivalence partition is defined
5693 by ODD_ITERATION_FLAG. */
5695 state_is_differed (state_t state
, state_t another_state
,
5696 int odd_iteration_flag
)
5699 unsigned int sz
, si
;
5701 gcc_assert (state
->num_out_arcs
== another_state
->num_out_arcs
);
5703 sz
= (description
->query_units_num
+ sizeof (int) * CHAR_BIT
- 1)
5704 / (sizeof (int) * CHAR_BIT
);
5706 for (si
= 0; si
< sz
; si
++)
5707 gcc_assert (state
->presence_signature
[si
]
5708 == another_state
->presence_signature
[si
]);
5710 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
5712 if ((odd_iteration_flag
5713 ? arc
->to_state
->equiv_class_num_1
5714 : arc
->to_state
->equiv_class_num_2
)
5715 != arc
->insn
->insn_reserv_decl
->equiv_class_num
)
5722 /* Compares two states pointed to by STATE_PTR_1 and STATE_PTR_2
5723 and return -1, 0 or 1. This function can be used as predicate for
5724 qsort(). It requires the member presence_signature[] of both
5725 states be filled. */
5727 compare_states_for_equiv (const void *state_ptr_1
,
5728 const void *state_ptr_2
)
5730 state_t s1
= *(state_t
*)state_ptr_1
;
5731 state_t s2
= *(state_t
*)state_ptr_2
;
5732 unsigned int sz
, si
;
5733 if (s1
->num_out_arcs
< s2
->num_out_arcs
)
5735 else if (s1
->num_out_arcs
> s2
->num_out_arcs
)
5738 sz
= (description
->query_units_num
+ sizeof (int) * CHAR_BIT
- 1)
5739 / (sizeof (int) * CHAR_BIT
);
5741 for (si
= 0; si
< sz
; si
++)
5742 if (s1
->presence_signature
[si
] < s2
->presence_signature
[si
])
5744 else if (s1
->presence_signature
[si
] > s2
->presence_signature
[si
])
5749 /* The function makes initial partition of STATES on equivalent
5750 classes and saves it into *CLASSES. This function requires the input
5751 to be sorted via compare_states_for_equiv(). */
5753 init_equiv_class (VEC(state_t
,heap
) *states
, VEC (state_t
,heap
) **classes
)
5759 *classes
= VEC_alloc (state_t
,heap
, 150);
5760 for (i
= 0; i
< VEC_length (state_t
, states
); i
++)
5762 state_t state
= VEC_index (state_t
, states
, i
);
5765 if (compare_states_for_equiv (&prev
, &state
) != 0)
5767 VEC_safe_push (state_t
,heap
, *classes
, prev
);
5772 state
->equiv_class_num_1
= class_num
;
5773 state
->next_equiv_class_state
= prev
;
5777 VEC_safe_push (state_t
,heap
, *classes
, prev
);
5781 /* The function copies pointers to equivalent states from vla FROM
5784 copy_equiv_class (VEC(state_t
,heap
) **to
, VEC(state_t
,heap
) *from
)
5786 VEC_free (state_t
,heap
, *to
);
5787 *to
= VEC_copy (state_t
,heap
, from
);
5790 /* The function processes equivalence class given by its first state,
5791 FIRST_STATE, on odd iteration if ODD_ITERATION_FLAG. If there
5792 are not equivalent states, the function partitions the class
5793 removing nonequivalent states and placing them in
5794 *NEXT_ITERATION_CLASSES, increments *NEW_EQUIV_CLASS_NUM_PTR ans
5795 assigns it to the state equivalence number. If the class has been
5796 partitioned, the function returns nonzero value. */
5798 partition_equiv_class (state_t first_state
, int odd_iteration_flag
,
5799 VEC(state_t
,heap
) **next_iteration_classes
,
5800 int *new_equiv_class_num_ptr
)
5802 state_t new_equiv_class
;
5810 while (first_state
!= NULL
)
5812 new_equiv_class
= NULL
;
5813 if (first_state
->next_equiv_class_state
!= NULL
)
5815 /* There are more one states in the class equivalence. */
5816 set_out_arc_insns_equiv_num (first_state
, odd_iteration_flag
);
5817 for (prev_state
= first_state
,
5818 curr_state
= first_state
->next_equiv_class_state
;
5820 curr_state
= next_state
)
5822 next_state
= curr_state
->next_equiv_class_state
;
5823 if (state_is_differed (curr_state
, first_state
,
5824 odd_iteration_flag
))
5826 /* Remove curr state from the class equivalence. */
5827 prev_state
->next_equiv_class_state
= next_state
;
5828 /* Add curr state to the new class equivalence. */
5829 curr_state
->next_equiv_class_state
= new_equiv_class
;
5830 if (new_equiv_class
== NULL
)
5831 (*new_equiv_class_num_ptr
)++;
5832 if (odd_iteration_flag
)
5833 curr_state
->equiv_class_num_2
= *new_equiv_class_num_ptr
;
5835 curr_state
->equiv_class_num_1
= *new_equiv_class_num_ptr
;
5836 new_equiv_class
= curr_state
;
5840 prev_state
= curr_state
;
5842 clear_arc_insns_equiv_num (first_state
);
5844 if (new_equiv_class
!= NULL
)
5845 VEC_safe_push (state_t
,heap
, *next_iteration_classes
, new_equiv_class
);
5846 first_state
= new_equiv_class
;
5851 /* The function finds equivalent states of AUTOMATON. */
5853 evaluate_equiv_classes (automaton_t automaton
,
5854 VEC(state_t
,heap
) **equiv_classes
)
5856 int new_equiv_class_num
;
5857 int odd_iteration_flag
;
5859 VEC (state_t
,heap
) *next_iteration_classes
;
5862 all_achieved_states
= VEC_alloc (state_t
,heap
, 1500);
5863 pass_states (automaton
, add_achieved_state
);
5864 pass_states (automaton
, cache_presence
);
5865 qsort (VEC_address (state_t
, all_achieved_states
),
5866 VEC_length (state_t
, all_achieved_states
),
5867 sizeof (state_t
), compare_states_for_equiv
);
5869 odd_iteration_flag
= 0;
5870 new_equiv_class_num
= init_equiv_class (all_achieved_states
,
5871 &next_iteration_classes
);
5875 odd_iteration_flag
= !odd_iteration_flag
;
5877 copy_equiv_class (equiv_classes
, next_iteration_classes
);
5879 /* Transfer equiv numbers for the next iteration. */
5880 for (i
= 0; i
< VEC_length (state_t
, all_achieved_states
); i
++)
5881 if (odd_iteration_flag
)
5882 VEC_index (state_t
, all_achieved_states
, i
)->equiv_class_num_2
5883 = VEC_index (state_t
, all_achieved_states
, i
)->equiv_class_num_1
;
5885 VEC_index (state_t
, all_achieved_states
, i
)->equiv_class_num_1
5886 = VEC_index (state_t
, all_achieved_states
, i
)->equiv_class_num_2
;
5888 for (i
= 0; i
< VEC_length (state_t
, *equiv_classes
); i
++)
5889 if (partition_equiv_class (VEC_index (state_t
, *equiv_classes
, i
),
5891 &next_iteration_classes
,
5892 &new_equiv_class_num
))
5895 while (!finish_flag
);
5896 VEC_free (state_t
,heap
, next_iteration_classes
);
5897 VEC_free (state_t
,heap
, all_achieved_states
);
5900 /* The function merges equivalent states of AUTOMATON. */
5902 merge_states (automaton_t automaton
, VEC(state_t
,heap
) *equiv_classes
)
5906 state_t first_class_state
;
5907 alt_state_t alt_states
;
5908 alt_state_t alt_state
, new_alt_state
;
5913 /* Create states corresponding to equivalence classes containing two
5915 for (i
= 0; i
< VEC_length (state_t
, equiv_classes
); i
++)
5917 curr_state
= VEC_index (state_t
, equiv_classes
, i
);
5918 if (curr_state
->next_equiv_class_state
!= NULL
)
5920 /* There are more one states in the class equivalence. */
5921 /* Create new compound state. */
5922 new_state
= get_free_state (0, automaton
);
5924 first_class_state
= curr_state
;
5925 for (curr_state
= first_class_state
;
5927 curr_state
= curr_state
->next_equiv_class_state
)
5929 curr_state
->equiv_class_state
= new_state
;
5930 if (curr_state
->component_states
== NULL
)
5932 new_alt_state
= get_free_alt_state ();
5933 new_alt_state
->state
= curr_state
;
5934 new_alt_state
->next_alt_state
= alt_states
;
5935 alt_states
= new_alt_state
;
5938 for (alt_state
= curr_state
->component_states
;
5940 alt_state
= alt_state
->next_sorted_alt_state
)
5942 new_alt_state
= get_free_alt_state ();
5943 new_alt_state
->state
= alt_state
->state
;
5944 new_alt_state
->next_alt_state
= alt_states
;
5945 alt_states
= new_alt_state
;
5948 /* Its is important that alt states were sorted before and
5949 after merging to have the same querying results. */
5950 new_state
->component_states
= uniq_sort_alt_states (alt_states
);
5953 curr_state
->equiv_class_state
= curr_state
;
5956 for (i
= 0; i
< VEC_length (state_t
, equiv_classes
); i
++)
5958 curr_state
= VEC_index (state_t
, equiv_classes
, i
);
5959 if (curr_state
->next_equiv_class_state
!= NULL
)
5961 first_class_state
= curr_state
;
5962 /* Create new arcs output from the state corresponding to
5964 for (curr_arc
= first_out_arc (first_class_state
);
5966 curr_arc
= next_out_arc (curr_arc
))
5967 add_arc (first_class_state
->equiv_class_state
,
5968 curr_arc
->to_state
->equiv_class_state
,
5970 /* Delete output arcs from states of given class equivalence. */
5971 for (curr_state
= first_class_state
;
5973 curr_state
= curr_state
->next_equiv_class_state
)
5975 if (automaton
->start_state
== curr_state
)
5976 automaton
->start_state
= curr_state
->equiv_class_state
;
5977 /* Delete the state and its output arcs. */
5978 for (curr_arc
= first_out_arc (curr_state
);
5980 curr_arc
= next_arc
)
5982 next_arc
= next_out_arc (curr_arc
);
5983 free_arc (curr_arc
);
5989 /* Change `to_state' of arcs output from the state of given
5990 equivalence class. */
5991 for (curr_arc
= first_out_arc (curr_state
);
5993 curr_arc
= next_out_arc (curr_arc
))
5994 curr_arc
->to_state
= curr_arc
->to_state
->equiv_class_state
;
5999 /* The function sets up new_cycle_p for states if there is arc to the
6000 state marked by advance_cycle_insn_decl. */
6002 set_new_cycle_flags (state_t state
)
6006 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
6007 if (arc
->insn
->insn_reserv_decl
6008 == DECL_INSN_RESERV (advance_cycle_insn_decl
))
6009 arc
->to_state
->new_cycle_p
= 1;
6012 /* The top level function for minimization of deterministic
6015 minimize_DFA (automaton_t automaton
)
6017 VEC(state_t
,heap
) *equiv_classes
= 0;
6019 evaluate_equiv_classes (automaton
, &equiv_classes
);
6020 merge_states (automaton
, equiv_classes
);
6021 pass_states (automaton
, set_new_cycle_flags
);
6023 VEC_free (state_t
,heap
, equiv_classes
);
6026 /* Values of two variables are counted number of states and arcs in an
6028 static int curr_counted_states_num
;
6029 static int curr_counted_arcs_num
;
6031 /* The function is called by function `pass_states' to count states
6032 and arcs of an automaton. */
6034 incr_states_and_arcs_nums (state_t state
)
6038 curr_counted_states_num
++;
6039 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
6040 curr_counted_arcs_num
++;
6043 /* The function counts states and arcs of AUTOMATON. */
6045 count_states_and_arcs (automaton_t automaton
, int *states_num
,
6048 curr_counted_states_num
= 0;
6049 curr_counted_arcs_num
= 0;
6050 pass_states (automaton
, incr_states_and_arcs_nums
);
6051 *states_num
= curr_counted_states_num
;
6052 *arcs_num
= curr_counted_arcs_num
;
6055 /* The function builds one DFA AUTOMATON for fast pipeline hazards
6056 recognition after checking and simplifying IR of the
6059 build_automaton (automaton_t automaton
)
6064 ticker_on (&NDFA_time
);
6067 if (automaton
->corresponding_automaton_decl
== NULL
)
6068 fprintf (stderr
, "Create anonymous automaton");
6070 fprintf (stderr
, "Create automaton `%s'",
6071 automaton
->corresponding_automaton_decl
->name
);
6072 fprintf (stderr
, " (1 dot is 100 new states):");
6074 make_automaton (automaton
);
6076 fprintf (stderr
, " done\n");
6077 ticker_off (&NDFA_time
);
6078 count_states_and_arcs (automaton
, &states_num
, &arcs_num
);
6079 automaton
->NDFA_states_num
= states_num
;
6080 automaton
->NDFA_arcs_num
= arcs_num
;
6081 ticker_on (&NDFA_to_DFA_time
);
6084 if (automaton
->corresponding_automaton_decl
== NULL
)
6085 fprintf (stderr
, "Make anonymous DFA");
6087 fprintf (stderr
, "Make DFA `%s'",
6088 automaton
->corresponding_automaton_decl
->name
);
6089 fprintf (stderr
, " (1 dot is 100 new states):");
6091 NDFA_to_DFA (automaton
);
6093 fprintf (stderr
, " done\n");
6094 ticker_off (&NDFA_to_DFA_time
);
6095 count_states_and_arcs (automaton
, &states_num
, &arcs_num
);
6096 automaton
->DFA_states_num
= states_num
;
6097 automaton
->DFA_arcs_num
= arcs_num
;
6098 if (!no_minimization_flag
)
6100 ticker_on (&minimize_time
);
6103 if (automaton
->corresponding_automaton_decl
== NULL
)
6104 fprintf (stderr
, "Minimize anonymous DFA...");
6106 fprintf (stderr
, "Minimize DFA `%s'...",
6107 automaton
->corresponding_automaton_decl
->name
);
6109 minimize_DFA (automaton
);
6111 fprintf (stderr
, "done\n");
6112 ticker_off (&minimize_time
);
6113 count_states_and_arcs (automaton
, &states_num
, &arcs_num
);
6114 automaton
->minimal_DFA_states_num
= states_num
;
6115 automaton
->minimal_DFA_arcs_num
= arcs_num
;
6121 /* The page contains code for enumeration of all states of an automaton. */
6123 /* Variable used for enumeration of all states of an automaton. Its
6124 value is current number of automaton states. */
6125 static int curr_state_order_num
;
6127 /* The function is called by function `pass_states' for enumerating
6130 set_order_state_num (state_t state
)
6132 state
->order_state_num
= curr_state_order_num
;
6133 curr_state_order_num
++;
6136 /* The function enumerates all states of AUTOMATON. */
6138 enumerate_states (automaton_t automaton
)
6140 curr_state_order_num
= 0;
6141 pass_states (automaton
, set_order_state_num
);
6142 automaton
->achieved_states_num
= curr_state_order_num
;
6147 /* The page contains code for finding equivalent automaton insns
6150 /* The function inserts AINSN into cyclic list
6151 CYCLIC_EQUIV_CLASS_INSN_LIST of ainsns. */
6153 insert_ainsn_into_equiv_class (ainsn_t ainsn
,
6154 ainsn_t cyclic_equiv_class_insn_list
)
6156 if (cyclic_equiv_class_insn_list
== NULL
)
6157 ainsn
->next_equiv_class_insn
= ainsn
;
6160 ainsn
->next_equiv_class_insn
6161 = cyclic_equiv_class_insn_list
->next_equiv_class_insn
;
6162 cyclic_equiv_class_insn_list
->next_equiv_class_insn
= ainsn
;
6167 /* The function deletes equiv_class_insn into cyclic list of
6168 equivalent ainsns. */
6170 delete_ainsn_from_equiv_class (ainsn_t equiv_class_insn
)
6172 ainsn_t curr_equiv_class_insn
;
6173 ainsn_t prev_equiv_class_insn
;
6175 prev_equiv_class_insn
= equiv_class_insn
;
6176 for (curr_equiv_class_insn
= equiv_class_insn
->next_equiv_class_insn
;
6177 curr_equiv_class_insn
!= equiv_class_insn
;
6178 curr_equiv_class_insn
= curr_equiv_class_insn
->next_equiv_class_insn
)
6179 prev_equiv_class_insn
= curr_equiv_class_insn
;
6180 if (prev_equiv_class_insn
!= equiv_class_insn
)
6181 prev_equiv_class_insn
->next_equiv_class_insn
6182 = equiv_class_insn
->next_equiv_class_insn
;
6185 /* The function processes AINSN of a state in order to find equivalent
6186 ainsns. INSN_ARCS_ARRAY is table: code of insn -> out arc of the
6189 process_insn_equiv_class (ainsn_t ainsn
, arc_t
*insn_arcs_array
)
6193 ainsn_t cyclic_insn_list
;
6196 gcc_assert (insn_arcs_array
[ainsn
->insn_reserv_decl
->insn_num
]);
6198 /* New class of ainsns which are not equivalent to given ainsn. */
6199 cyclic_insn_list
= NULL
;
6202 next_insn
= curr_insn
->next_equiv_class_insn
;
6203 arc
= insn_arcs_array
[curr_insn
->insn_reserv_decl
->insn_num
];
6205 || (insn_arcs_array
[ainsn
->insn_reserv_decl
->insn_num
]->to_state
6208 delete_ainsn_from_equiv_class (curr_insn
);
6209 cyclic_insn_list
= insert_ainsn_into_equiv_class (curr_insn
,
6212 curr_insn
= next_insn
;
6214 while (curr_insn
!= ainsn
);
6217 /* The function processes STATE in order to find equivalent ainsns. */
6219 process_state_for_insn_equiv_partition (state_t state
)
6222 arc_t
*insn_arcs_array
= XCNEWVEC (arc_t
, description
->insns_num
);
6224 /* Process insns of the arcs. */
6225 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
6226 insn_arcs_array
[arc
->insn
->insn_reserv_decl
->insn_num
] = arc
;
6227 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
6228 process_insn_equiv_class (arc
->insn
, insn_arcs_array
);
6230 free (insn_arcs_array
);
6233 /* The function searches for equivalent ainsns of AUTOMATON. */
6235 set_insn_equiv_classes (automaton_t automaton
)
6240 ainsn_t cyclic_insn_list
;
6241 ainsn_t insn_with_same_reservs
;
6242 int equiv_classes_num
;
6244 /* All insns are included in one equivalence class. */
6245 cyclic_insn_list
= NULL
;
6246 for (ainsn
= automaton
->ainsn_list
; ainsn
!= NULL
; ainsn
= ainsn
->next_ainsn
)
6247 if (ainsn
->first_insn_with_same_reservs
)
6248 cyclic_insn_list
= insert_ainsn_into_equiv_class (ainsn
,
6250 /* Process insns in order to make equivalence partition. */
6251 pass_states (automaton
, process_state_for_insn_equiv_partition
);
6252 /* Enumerate equiv classes. */
6253 for (ainsn
= automaton
->ainsn_list
; ainsn
!= NULL
; ainsn
= ainsn
->next_ainsn
)
6254 /* Set undefined value. */
6255 ainsn
->insn_equiv_class_num
= -1;
6256 equiv_classes_num
= 0;
6257 for (ainsn
= automaton
->ainsn_list
; ainsn
!= NULL
; ainsn
= ainsn
->next_ainsn
)
6258 if (ainsn
->insn_equiv_class_num
< 0)
6261 gcc_assert (first_insn
->first_insn_with_same_reservs
);
6262 first_insn
->first_ainsn_with_given_equivalence_num
= 1;
6263 curr_insn
= first_insn
;
6266 for (insn_with_same_reservs
= curr_insn
;
6267 insn_with_same_reservs
!= NULL
;
6268 insn_with_same_reservs
6269 = insn_with_same_reservs
->next_same_reservs_insn
)
6270 insn_with_same_reservs
->insn_equiv_class_num
= equiv_classes_num
;
6271 curr_insn
= curr_insn
->next_equiv_class_insn
;
6273 while (curr_insn
!= first_insn
);
6274 equiv_classes_num
++;
6276 automaton
->insn_equiv_classes_num
= equiv_classes_num
;
6281 /* This page contains code for creating DFA(s) and calls functions
6285 /* The following value is used to prevent floating point overflow for
6286 estimating an automaton bound. The value should be less DBL_MAX on
6287 the host machine. We use here approximate minimum of maximal
6288 double floating point value required by ANSI C standard. It
6289 will work for non ANSI sun compiler too. */
6291 #define MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND 1.0E37
6293 /* The function estimate size of the single DFA used by PHR (pipeline
6294 hazards recognizer). */
6296 estimate_one_automaton_bound (void)
6299 double one_automaton_estimation_bound
;
6303 one_automaton_estimation_bound
= 1.0;
6304 for (i
= 0; i
< description
->decls_num
; i
++)
6306 decl
= description
->decls
[i
];
6307 if (decl
->mode
== dm_unit
)
6309 root_value
= exp (log (DECL_UNIT (decl
)->max_occ_cycle_num
6310 - DECL_UNIT (decl
)->min_occ_cycle_num
+ 1.0)
6312 if (MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND
/ root_value
6313 > one_automaton_estimation_bound
)
6314 one_automaton_estimation_bound
*= root_value
;
6317 return one_automaton_estimation_bound
;
6320 /* The function compares unit declarations according to their maximal
6321 cycle in reservations. */
6323 compare_max_occ_cycle_nums (const void *unit_decl_1
,
6324 const void *unit_decl_2
)
6326 if ((DECL_UNIT (*(decl_t
*) unit_decl_1
)->max_occ_cycle_num
)
6327 < (DECL_UNIT (*(decl_t
*) unit_decl_2
)->max_occ_cycle_num
))
6329 else if ((DECL_UNIT (*(decl_t
*) unit_decl_1
)->max_occ_cycle_num
)
6330 == (DECL_UNIT (*(decl_t
*) unit_decl_2
)->max_occ_cycle_num
))
6336 /* The function makes heuristic assigning automata to units. Actually
6337 efficacy of the algorithm has been checked yet??? */
6340 units_to_automata_heuristic_distr (void)
6342 double estimation_bound
;
6346 unit_decl_t
*unit_decls
;
6349 if (description
->units_num
== 0)
6351 estimation_bound
= estimate_one_automaton_bound ();
6352 unit_decls
= XNEWVEC (unit_decl_t
, description
->units_num
);
6354 for (i
= 0, j
= 0; i
< description
->decls_num
; i
++)
6355 if (description
->decls
[i
]->mode
== dm_unit
)
6356 unit_decls
[j
++] = DECL_UNIT (description
->decls
[i
]);
6357 gcc_assert (j
== description
->units_num
);
6359 qsort (unit_decls
, description
->units_num
,
6360 sizeof (unit_decl_t
), compare_max_occ_cycle_nums
);
6363 bound_value
= unit_decls
[0]->max_occ_cycle_num
;
6364 unit_decls
[0]->corresponding_automaton_num
= automaton_num
;
6366 for (i
= 1; i
< description
->units_num
; i
++)
6368 rest_units_num
= description
->units_num
- i
+ 1;
6369 gcc_assert (automata_num
- automaton_num
- 1 <= rest_units_num
);
6370 if (automaton_num
< automata_num
- 1
6371 && ((automata_num
- automaton_num
- 1 == rest_units_num
)
6374 / unit_decls
[i
]->max_occ_cycle_num
))))
6376 bound_value
= unit_decls
[i
]->max_occ_cycle_num
;
6380 bound_value
*= unit_decls
[i
]->max_occ_cycle_num
;
6381 unit_decls
[i
]->corresponding_automaton_num
= automaton_num
;
6383 gcc_assert (automaton_num
== automata_num
- 1);
6387 /* The functions creates automaton insns for each automata. Automaton
6388 insn is simply insn for given automaton which makes reservation
6389 only of units of the automaton. */
6391 create_ainsns (void)
6394 ainsn_t first_ainsn
;
6401 for (i
= 0; i
< description
->decls_num
; i
++)
6403 decl
= description
->decls
[i
];
6404 if (decl
->mode
== dm_insn_reserv
)
6406 curr_ainsn
= create_node (sizeof (struct ainsn
));
6407 curr_ainsn
->insn_reserv_decl
= DECL_INSN_RESERV (decl
);
6408 curr_ainsn
->important_p
= FALSE
;
6409 curr_ainsn
->next_ainsn
= NULL
;
6410 if (prev_ainsn
== NULL
)
6411 first_ainsn
= curr_ainsn
;
6413 prev_ainsn
->next_ainsn
= curr_ainsn
;
6414 prev_ainsn
= curr_ainsn
;
6420 /* The function assigns automata to units according to constructions
6421 `define_automaton' in the description. */
6423 units_to_automata_distr (void)
6428 for (i
= 0; i
< description
->decls_num
; i
++)
6430 decl
= description
->decls
[i
];
6431 if (decl
->mode
== dm_unit
)
6433 if (DECL_UNIT (decl
)->automaton_decl
== NULL
6434 || (DECL_UNIT (decl
)->automaton_decl
->corresponding_automaton
6436 /* Distribute to the first automaton. */
6437 DECL_UNIT (decl
)->corresponding_automaton_num
= 0;
6439 DECL_UNIT (decl
)->corresponding_automaton_num
6440 = (DECL_UNIT (decl
)->automaton_decl
6441 ->corresponding_automaton
->automaton_order_num
);
6446 /* The function creates DFA(s) for fast pipeline hazards recognition
6447 after checking and simplifying IR of the description. */
6449 create_automata (void)
6451 automaton_t curr_automaton
;
6452 automaton_t prev_automaton
;
6454 int curr_automaton_num
;
6457 if (automata_num
!= 0)
6459 units_to_automata_heuristic_distr ();
6460 for (prev_automaton
= NULL
, curr_automaton_num
= 0;
6461 curr_automaton_num
< automata_num
;
6462 curr_automaton_num
++, prev_automaton
= curr_automaton
)
6464 curr_automaton
= create_node (sizeof (struct automaton
));
6465 curr_automaton
->ainsn_list
= create_ainsns ();
6466 curr_automaton
->corresponding_automaton_decl
= NULL
;
6467 curr_automaton
->next_automaton
= NULL
;
6468 curr_automaton
->automaton_order_num
= curr_automaton_num
;
6469 if (prev_automaton
== NULL
)
6470 description
->first_automaton
= curr_automaton
;
6472 prev_automaton
->next_automaton
= curr_automaton
;
6477 curr_automaton_num
= 0;
6478 prev_automaton
= NULL
;
6479 for (i
= 0; i
< description
->decls_num
; i
++)
6481 decl
= description
->decls
[i
];
6482 if (decl
->mode
== dm_automaton
6483 && DECL_AUTOMATON (decl
)->automaton_is_used
)
6485 curr_automaton
= create_node (sizeof (struct automaton
));
6486 curr_automaton
->ainsn_list
= create_ainsns ();
6487 curr_automaton
->corresponding_automaton_decl
6488 = DECL_AUTOMATON (decl
);
6489 curr_automaton
->next_automaton
= NULL
;
6490 DECL_AUTOMATON (decl
)->corresponding_automaton
= curr_automaton
;
6491 curr_automaton
->automaton_order_num
= curr_automaton_num
;
6492 if (prev_automaton
== NULL
)
6493 description
->first_automaton
= curr_automaton
;
6495 prev_automaton
->next_automaton
= curr_automaton
;
6496 curr_automaton_num
++;
6497 prev_automaton
= curr_automaton
;
6500 if (curr_automaton_num
== 0)
6502 curr_automaton
= create_node (sizeof (struct automaton
));
6503 curr_automaton
->ainsn_list
= create_ainsns ();
6504 curr_automaton
->corresponding_automaton_decl
= NULL
;
6505 curr_automaton
->next_automaton
= NULL
;
6506 description
->first_automaton
= curr_automaton
;
6508 units_to_automata_distr ();
6510 NDFA_time
= create_ticker ();
6511 ticker_off (&NDFA_time
);
6512 NDFA_to_DFA_time
= create_ticker ();
6513 ticker_off (&NDFA_to_DFA_time
);
6514 minimize_time
= create_ticker ();
6515 ticker_off (&minimize_time
);
6516 equiv_time
= create_ticker ();
6517 ticker_off (&equiv_time
);
6518 for (curr_automaton
= description
->first_automaton
;
6519 curr_automaton
!= NULL
;
6520 curr_automaton
= curr_automaton
->next_automaton
)
6524 if (curr_automaton
->corresponding_automaton_decl
== NULL
)
6525 fprintf (stderr
, "Prepare anonymous automaton creation ... ");
6527 fprintf (stderr
, "Prepare automaton `%s' creation...",
6528 curr_automaton
->corresponding_automaton_decl
->name
);
6530 create_alt_states (curr_automaton
);
6531 form_ainsn_with_same_reservs (curr_automaton
);
6533 fprintf (stderr
, "done\n");
6534 build_automaton (curr_automaton
);
6535 enumerate_states (curr_automaton
);
6536 ticker_on (&equiv_time
);
6537 set_insn_equiv_classes (curr_automaton
);
6538 ticker_off (&equiv_time
);
6544 /* This page contains code for forming string representation of
6545 regexp. The representation is formed on IR obstack. So you should
6546 not work with IR obstack between regexp_representation and
6547 finish_regexp_representation calls. */
6549 /* This recursive function forms string representation of regexp
6550 (without tailing '\0'). */
6552 form_regexp (regexp_t regexp
)
6556 switch (regexp
->mode
)
6558 case rm_unit
: case rm_reserv
:
6560 const char *name
= (regexp
->mode
== rm_unit
6561 ? REGEXP_UNIT (regexp
)->name
6562 : REGEXP_RESERV (regexp
)->name
);
6564 obstack_grow (&irp
, name
, strlen (name
));
6569 for (i
= 0; i
< REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
6572 obstack_1grow (&irp
, ',');
6573 form_regexp (REGEXP_SEQUENCE (regexp
)->regexps
[i
]);
6578 obstack_1grow (&irp
, '(');
6579 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
6582 obstack_1grow (&irp
, '+');
6583 if (REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
== rm_sequence
6584 || REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
== rm_oneof
)
6585 obstack_1grow (&irp
, '(');
6586 form_regexp (REGEXP_ALLOF (regexp
)->regexps
[i
]);
6587 if (REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
== rm_sequence
6588 || REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
== rm_oneof
)
6589 obstack_1grow (&irp
, ')');
6591 obstack_1grow (&irp
, ')');
6595 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
6598 obstack_1grow (&irp
, '|');
6599 if (REGEXP_ONEOF (regexp
)->regexps
[i
]->mode
== rm_sequence
)
6600 obstack_1grow (&irp
, '(');
6601 form_regexp (REGEXP_ONEOF (regexp
)->regexps
[i
]);
6602 if (REGEXP_ONEOF (regexp
)->regexps
[i
]->mode
== rm_sequence
)
6603 obstack_1grow (&irp
, ')');
6611 if (REGEXP_REPEAT (regexp
)->regexp
->mode
== rm_sequence
6612 || REGEXP_REPEAT (regexp
)->regexp
->mode
== rm_allof
6613 || REGEXP_REPEAT (regexp
)->regexp
->mode
== rm_oneof
)
6614 obstack_1grow (&irp
, '(');
6615 form_regexp (REGEXP_REPEAT (regexp
)->regexp
);
6616 if (REGEXP_REPEAT (regexp
)->regexp
->mode
== rm_sequence
6617 || REGEXP_REPEAT (regexp
)->regexp
->mode
== rm_allof
6618 || REGEXP_REPEAT (regexp
)->regexp
->mode
== rm_oneof
)
6619 obstack_1grow (&irp
, ')');
6620 sprintf (digits
, "*%d", REGEXP_REPEAT (regexp
)->repeat_num
);
6621 obstack_grow (&irp
, digits
, strlen (digits
));
6626 obstack_grow (&irp
, NOTHING_NAME
, strlen (NOTHING_NAME
));
6634 /* The function returns string representation of REGEXP on IR
6637 regexp_representation (regexp_t regexp
)
6639 form_regexp (regexp
);
6640 obstack_1grow (&irp
, '\0');
6641 return obstack_base (&irp
);
6644 /* The function frees memory allocated for last formed string
6645 representation of regexp. */
6647 finish_regexp_representation (void)
6649 int length
= obstack_object_size (&irp
);
6651 obstack_blank_fast (&irp
, -length
);
6656 /* This page contains code for output PHR (pipeline hazards recognizer). */
6658 /* The function outputs minimal C type which is sufficient for
6659 representation numbers in range min_range_value and
6660 max_range_value. Because host machine and build machine may be
6661 different, we use here minimal values required by ANSI C standard
6662 instead of UCHAR_MAX, SHRT_MAX, SHRT_MIN, etc. This is a good
6666 output_range_type (FILE *f
, long int min_range_value
,
6667 long int max_range_value
)
6669 if (min_range_value
>= 0 && max_range_value
<= 255)
6670 fprintf (f
, "unsigned char");
6671 else if (min_range_value
>= -127 && max_range_value
<= 127)
6672 fprintf (f
, "signed char");
6673 else if (min_range_value
>= 0 && max_range_value
<= 65535)
6674 fprintf (f
, "unsigned short");
6675 else if (min_range_value
>= -32767 && max_range_value
<= 32767)
6676 fprintf (f
, "short");
6681 /* The following macro value is used as value of member
6682 `longest_path_length' of state when we are processing path and the
6683 state on the path. */
6685 #define ON_THE_PATH -2
6687 /* The following recursive function searches for the length of the
6688 longest path starting from STATE which does not contain cycles and
6689 `cycle advance' arcs. */
6692 longest_path_length (state_t state
)
6697 if (state
->longest_path_length
!= UNDEFINED_LONGEST_PATH_LENGTH
)
6699 /* We don't expect the path cycle here. Our graph may contain
6700 only cycles with one state on the path not containing `cycle
6701 advance' arcs -- see comment below. */
6702 gcc_assert (state
->longest_path_length
!= ON_THE_PATH
);
6704 /* We already visited the state. */
6705 return state
->longest_path_length
;
6709 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
6710 /* Ignore cycles containing one state and `cycle advance' arcs. */
6711 if (arc
->to_state
!= state
6712 && (arc
->insn
->insn_reserv_decl
6713 != DECL_INSN_RESERV (advance_cycle_insn_decl
)))
6715 length
= longest_path_length (arc
->to_state
);
6716 if (length
> result
)
6719 state
->longest_path_length
= result
+ 1;
6723 /* The function outputs all initialization values of VECT. */
6725 output_vect (vla_hwint_t vect
)
6728 size_t vect_length
= VEC_length (vect_el_t
, vect
);
6732 if (vect_length
== 0)
6733 fputs ("0 /* This is dummy el because the vect is empty */", output_file
);
6735 for (i
= 0; i
< vect_length
; i
++)
6737 fprintf (output_file
, "%5ld", (long) VEC_index (vect_el_t
, vect
, i
));
6738 if (els_on_line
== 10)
6741 fputs (",\n", output_file
);
6743 else if (i
< vect_length
-1)
6744 fputs (", ", output_file
);
6749 /* The following is name of the structure which represents DFA(s) for
6751 #define CHIP_NAME "DFA_chip"
6753 /* The following is name of member which represents state of a DFA for
6756 output_chip_member_name (FILE *f
, automaton_t automaton
)
6758 if (automaton
->corresponding_automaton_decl
== NULL
)
6759 fprintf (f
, "automaton_state_%d", automaton
->automaton_order_num
);
6761 fprintf (f
, "%s_automaton_state",
6762 automaton
->corresponding_automaton_decl
->name
);
6765 /* The following is name of temporary variable which stores state of a
6768 output_temp_chip_member_name (FILE *f
, automaton_t automaton
)
6771 output_chip_member_name (f
, automaton
);
6774 /* This is name of macro value which is code of pseudo_insn
6775 representing advancing cpu cycle. Its value is used as internal
6776 code unknown insn. */
6777 #define ADVANCE_CYCLE_VALUE_NAME "DFA__ADVANCE_CYCLE"
6779 /* Output name of translate vector for given automaton. */
6781 output_translate_vect_name (FILE *f
, automaton_t automaton
)
6783 if (automaton
->corresponding_automaton_decl
== NULL
)
6784 fprintf (f
, "translate_%d", automaton
->automaton_order_num
);
6786 fprintf (f
, "%s_translate", automaton
->corresponding_automaton_decl
->name
);
6789 /* Output name for simple transition table representation. */
6791 output_trans_full_vect_name (FILE *f
, automaton_t automaton
)
6793 if (automaton
->corresponding_automaton_decl
== NULL
)
6794 fprintf (f
, "transitions_%d", automaton
->automaton_order_num
);
6796 fprintf (f
, "%s_transitions",
6797 automaton
->corresponding_automaton_decl
->name
);
6800 /* Output name of comb vector of the transition table for given
6803 output_trans_comb_vect_name (FILE *f
, automaton_t automaton
)
6805 if (automaton
->corresponding_automaton_decl
== NULL
)
6806 fprintf (f
, "transitions_%d", automaton
->automaton_order_num
);
6808 fprintf (f
, "%s_transitions",
6809 automaton
->corresponding_automaton_decl
->name
);
6812 /* Output name of check vector of the transition table for given
6815 output_trans_check_vect_name (FILE *f
, automaton_t automaton
)
6817 if (automaton
->corresponding_automaton_decl
== NULL
)
6818 fprintf (f
, "check_%d", automaton
->automaton_order_num
);
6820 fprintf (f
, "%s_check", automaton
->corresponding_automaton_decl
->name
);
6823 /* Output name of base vector of the transition table for given
6826 output_trans_base_vect_name (FILE *f
, automaton_t automaton
)
6828 if (automaton
->corresponding_automaton_decl
== NULL
)
6829 fprintf (f
, "base_%d", automaton
->automaton_order_num
);
6831 fprintf (f
, "%s_base", automaton
->corresponding_automaton_decl
->name
);
6834 /* Output name of simple min issue delay table representation. */
6836 output_min_issue_delay_vect_name (FILE *f
, automaton_t automaton
)
6838 if (automaton
->corresponding_automaton_decl
== NULL
)
6839 fprintf (f
, "min_issue_delay_%d", automaton
->automaton_order_num
);
6841 fprintf (f
, "%s_min_issue_delay",
6842 automaton
->corresponding_automaton_decl
->name
);
6845 /* Output name of deadlock vector for given automaton. */
6847 output_dead_lock_vect_name (FILE *f
, automaton_t automaton
)
6849 if (automaton
->corresponding_automaton_decl
== NULL
)
6850 fprintf (f
, "dead_lock_%d", automaton
->automaton_order_num
);
6852 fprintf (f
, "%s_dead_lock", automaton
->corresponding_automaton_decl
->name
);
6855 /* Output name of reserved units table for AUTOMATON into file F. */
6857 output_reserved_units_table_name (FILE *f
, automaton_t automaton
)
6859 if (automaton
->corresponding_automaton_decl
== NULL
)
6860 fprintf (f
, "reserved_units_%d", automaton
->automaton_order_num
);
6862 fprintf (f
, "%s_reserved_units",
6863 automaton
->corresponding_automaton_decl
->name
);
6866 /* Name of the PHR interface macro. */
6867 #define CPU_UNITS_QUERY_MACRO_NAME "CPU_UNITS_QUERY"
6869 /* Names of an internal functions: */
6870 #define INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME "internal_min_issue_delay"
6872 /* This is external type of DFA(s) state. */
6873 #define STATE_TYPE_NAME "state_t"
6875 #define INTERNAL_TRANSITION_FUNC_NAME "internal_state_transition"
6877 #define INTERNAL_RESET_FUNC_NAME "internal_reset"
6879 #define INTERNAL_DEAD_LOCK_FUNC_NAME "internal_state_dead_lock_p"
6881 #define INTERNAL_INSN_LATENCY_FUNC_NAME "internal_insn_latency"
6883 /* Name of cache of insn dfa codes. */
6884 #define DFA_INSN_CODES_VARIABLE_NAME "dfa_insn_codes"
6886 /* Name of length of cache of insn dfa codes. */
6887 #define DFA_INSN_CODES_LENGTH_VARIABLE_NAME "dfa_insn_codes_length"
6889 /* Names of the PHR interface functions: */
6890 #define SIZE_FUNC_NAME "state_size"
6892 #define TRANSITION_FUNC_NAME "state_transition"
6894 #define MIN_ISSUE_DELAY_FUNC_NAME "min_issue_delay"
6896 #define MIN_INSN_CONFLICT_DELAY_FUNC_NAME "min_insn_conflict_delay"
6898 #define DEAD_LOCK_FUNC_NAME "state_dead_lock_p"
6900 #define RESET_FUNC_NAME "state_reset"
6902 #define INSN_LATENCY_FUNC_NAME "insn_latency"
6904 #define PRINT_RESERVATION_FUNC_NAME "print_reservation"
6906 #define GET_CPU_UNIT_CODE_FUNC_NAME "get_cpu_unit_code"
6908 #define CPU_UNIT_RESERVATION_P_FUNC_NAME "cpu_unit_reservation_p"
6910 #define DFA_CLEAN_INSN_CACHE_FUNC_NAME "dfa_clean_insn_cache"
6912 #define DFA_CLEAR_SINGLE_INSN_CACHE_FUNC_NAME "dfa_clear_single_insn_cache"
6914 #define DFA_START_FUNC_NAME "dfa_start"
6916 #define DFA_FINISH_FUNC_NAME "dfa_finish"
6918 /* Names of parameters of the PHR interface functions. */
6919 #define STATE_NAME "state"
6921 #define INSN_PARAMETER_NAME "insn"
6923 #define INSN2_PARAMETER_NAME "insn2"
6925 #define CHIP_PARAMETER_NAME "chip"
6927 #define FILE_PARAMETER_NAME "f"
6929 #define CPU_UNIT_NAME_PARAMETER_NAME "cpu_unit_name"
6931 #define CPU_CODE_PARAMETER_NAME "cpu_unit_code"
6933 /* Names of the variables whose values are internal insn code of rtx
6935 #define INTERNAL_INSN_CODE_NAME "insn_code"
6937 #define INTERNAL_INSN2_CODE_NAME "insn2_code"
6939 /* Names of temporary variables in some functions. */
6940 #define TEMPORARY_VARIABLE_NAME "temp"
6942 #define I_VARIABLE_NAME "i"
6944 /* Name of result variable in some functions. */
6945 #define RESULT_VARIABLE_NAME "res"
6947 /* Name of function (attribute) to translate insn into internal insn
6949 #define INTERNAL_DFA_INSN_CODE_FUNC_NAME "internal_dfa_insn_code"
6951 /* Name of function (attribute) to translate insn into internal insn
6952 code with caching. */
6953 #define DFA_INSN_CODE_FUNC_NAME "dfa_insn_code"
6955 /* Output C type which is used for representation of codes of states
6958 output_state_member_type (FILE *f
, automaton_t automaton
)
6960 output_range_type (f
, 0, automaton
->achieved_states_num
);
6963 /* Output definition of the structure representing current DFA(s)
6966 output_chip_definitions (void)
6968 automaton_t automaton
;
6970 fprintf (output_file
, "struct %s\n{\n", CHIP_NAME
);
6971 for (automaton
= description
->first_automaton
;
6973 automaton
= automaton
->next_automaton
)
6975 fprintf (output_file
, " ");
6976 output_state_member_type (output_file
, automaton
);
6977 fprintf (output_file
, " ");
6978 output_chip_member_name (output_file
, automaton
);
6979 fprintf (output_file
, ";\n");
6981 fprintf (output_file
, "};\n\n");
6983 fprintf (output_file
, "static struct %s %s;\n\n", CHIP_NAME
, CHIP_NAME
);
6988 /* The function outputs translate vector of internal insn code into
6989 insn equivalence class number. The equivalence class number is
6990 used to access to table and vectors representing DFA(s). */
6992 output_translate_vect (automaton_t automaton
)
6996 vla_hwint_t translate_vect
;
6998 translate_vect
= VEC_alloc (vect_el_t
,heap
, description
->insns_num
);
7000 for (insn_value
= 0; insn_value
< description
->insns_num
; insn_value
++)
7001 /* Undefined value */
7002 VEC_quick_push (vect_el_t
, translate_vect
,
7003 automaton
->insn_equiv_classes_num
);
7005 for (ainsn
= automaton
->ainsn_list
; ainsn
!= NULL
; ainsn
= ainsn
->next_ainsn
)
7006 VEC_replace (vect_el_t
, translate_vect
,
7007 ainsn
->insn_reserv_decl
->insn_num
,
7008 ainsn
->insn_equiv_class_num
);
7010 fprintf (output_file
,
7011 "/* Vector translating external insn codes to internal ones.*/\n");
7012 fprintf (output_file
, "static const ");
7013 output_range_type (output_file
, 0, automaton
->insn_equiv_classes_num
);
7014 fprintf (output_file
, " ");
7015 output_translate_vect_name (output_file
, automaton
);
7016 fprintf (output_file
, "[] ATTRIBUTE_UNUSED = {\n");
7017 output_vect (translate_vect
);
7018 fprintf (output_file
, "};\n\n");
7019 VEC_free (vect_el_t
,heap
, translate_vect
);
7022 /* The value in a table state x ainsn -> something which represents
7024 static int undefined_vect_el_value
;
7026 /* The following function returns nonzero value if the best
7027 representation of the table is comb vector. */
7029 comb_vect_p (state_ainsn_table_t tab
)
7031 return (2 * VEC_length (vect_el_t
, tab
->full_vect
)
7032 > 5 * VEC_length (vect_el_t
, tab
->comb_vect
));
7035 /* The following function creates new table for AUTOMATON. */
7036 static state_ainsn_table_t
7037 create_state_ainsn_table (automaton_t automaton
)
7039 state_ainsn_table_t tab
;
7040 int full_vect_length
;
7043 tab
= create_node (sizeof (struct state_ainsn_table
));
7044 tab
->automaton
= automaton
;
7046 tab
->comb_vect
= VEC_alloc (vect_el_t
,heap
, 10000);
7047 tab
->check_vect
= VEC_alloc (vect_el_t
,heap
, 10000);
7050 VEC_safe_grow (vect_el_t
,heap
, tab
->base_vect
,
7051 automaton
->achieved_states_num
);
7053 full_vect_length
= (automaton
->insn_equiv_classes_num
7054 * automaton
->achieved_states_num
);
7055 tab
->full_vect
= VEC_alloc (vect_el_t
,heap
, full_vect_length
);
7056 for (i
= 0; i
< full_vect_length
; i
++)
7057 VEC_quick_push (vect_el_t
, tab
->full_vect
, undefined_vect_el_value
);
7059 tab
->min_base_vect_el_value
= 0;
7060 tab
->max_base_vect_el_value
= 0;
7061 tab
->min_comb_vect_el_value
= 0;
7062 tab
->max_comb_vect_el_value
= 0;
7066 /* The following function outputs the best C representation of the
7067 table TAB of given TABLE_NAME. */
7069 output_state_ainsn_table (state_ainsn_table_t tab
, const char *table_name
,
7070 void (*output_full_vect_name_func
) (FILE *, automaton_t
),
7071 void (*output_comb_vect_name_func
) (FILE *, automaton_t
),
7072 void (*output_check_vect_name_func
) (FILE *, automaton_t
),
7073 void (*output_base_vect_name_func
) (FILE *, automaton_t
))
7075 if (!comb_vect_p (tab
))
7077 fprintf (output_file
, "/* Vector for %s. */\n", table_name
);
7078 fprintf (output_file
, "static const ");
7079 output_range_type (output_file
, tab
->min_comb_vect_el_value
,
7080 tab
->max_comb_vect_el_value
);
7081 fprintf (output_file
, " ");
7082 (*output_full_vect_name_func
) (output_file
, tab
->automaton
);
7083 fprintf (output_file
, "[] ATTRIBUTE_UNUSED = {\n");
7084 output_vect (tab
->full_vect
);
7085 fprintf (output_file
, "};\n\n");
7089 fprintf (output_file
, "/* Comb vector for %s. */\n", table_name
);
7090 fprintf (output_file
, "static const ");
7091 output_range_type (output_file
, tab
->min_comb_vect_el_value
,
7092 tab
->max_comb_vect_el_value
);
7093 fprintf (output_file
, " ");
7094 (*output_comb_vect_name_func
) (output_file
, tab
->automaton
);
7095 fprintf (output_file
, "[] ATTRIBUTE_UNUSED = {\n");
7096 output_vect (tab
->comb_vect
);
7097 fprintf (output_file
, "};\n\n");
7098 fprintf (output_file
, "/* Check vector for %s. */\n", table_name
);
7099 fprintf (output_file
, "static const ");
7100 output_range_type (output_file
, 0, tab
->automaton
->achieved_states_num
);
7101 fprintf (output_file
, " ");
7102 (*output_check_vect_name_func
) (output_file
, tab
->automaton
);
7103 fprintf (output_file
, "[] = {\n");
7104 output_vect (tab
->check_vect
);
7105 fprintf (output_file
, "};\n\n");
7106 fprintf (output_file
, "/* Base vector for %s. */\n", table_name
);
7107 fprintf (output_file
, "static const ");
7108 output_range_type (output_file
, tab
->min_base_vect_el_value
,
7109 tab
->max_base_vect_el_value
);
7110 fprintf (output_file
, " ");
7111 (*output_base_vect_name_func
) (output_file
, tab
->automaton
);
7112 fprintf (output_file
, "[] = {\n");
7113 output_vect (tab
->base_vect
);
7114 fprintf (output_file
, "};\n\n");
7118 /* The following function adds vector VECT to table TAB as its line
7119 with number VECT_NUM. */
7121 add_vect (state_ainsn_table_t tab
, int vect_num
, vla_hwint_t vect
)
7124 size_t real_vect_length
;
7125 int comb_vect_index
;
7126 int comb_vect_els_num
;
7128 int first_unempty_vect_index
;
7129 int additional_els_num
;
7133 unsigned long vect_mask
, comb_vect_mask
;
7135 vect_length
= VEC_length (vect_el_t
, vect
);
7136 gcc_assert (vect_length
);
7137 gcc_assert (VEC_last (vect_el_t
, vect
) != undefined_vect_el_value
);
7138 real_vect_length
= tab
->automaton
->insn_equiv_classes_num
;
7139 /* Form full vector in the table: */
7141 size_t full_base
= tab
->automaton
->insn_equiv_classes_num
* vect_num
;
7142 if (VEC_length (vect_el_t
, tab
->full_vect
) < full_base
+ vect_length
)
7143 VEC_safe_grow (vect_el_t
,heap
, tab
->full_vect
,
7144 full_base
+ vect_length
);
7145 for (i
= 0; i
< vect_length
; i
++)
7146 VEC_replace (vect_el_t
, tab
->full_vect
, full_base
+ i
,
7147 VEC_index (vect_el_t
, vect
, i
));
7149 /* Form comb vector in the table: */
7150 gcc_assert (VEC_length (vect_el_t
, tab
->comb_vect
)
7151 == VEC_length (vect_el_t
, tab
->check_vect
));
7153 comb_vect_els_num
= VEC_length (vect_el_t
, tab
->comb_vect
);
7154 for (first_unempty_vect_index
= 0;
7155 first_unempty_vect_index
< vect_length
;
7156 first_unempty_vect_index
++)
7157 if (VEC_index (vect_el_t
, vect
, first_unempty_vect_index
)
7158 != undefined_vect_el_value
)
7161 /* Search for the place in comb vect for the inserted vect. */
7164 if (vect_length
- first_unempty_vect_index
>= SIZEOF_LONG
* CHAR_BIT
)
7166 for (comb_vect_index
= 0;
7167 comb_vect_index
< comb_vect_els_num
;
7170 for (vect_index
= first_unempty_vect_index
;
7171 vect_index
< vect_length
7172 && vect_index
+ comb_vect_index
< comb_vect_els_num
;
7174 if (VEC_index (vect_el_t
, vect
, vect_index
)
7175 != undefined_vect_el_value
7176 && (VEC_index (vect_el_t
, tab
->comb_vect
,
7177 vect_index
+ comb_vect_index
)
7178 != undefined_vect_el_value
))
7180 if (vect_index
>= vect_length
7181 || vect_index
+ comb_vect_index
>= comb_vect_els_num
)
7189 for (vect_index
= first_unempty_vect_index
;
7190 vect_index
< vect_length
;
7193 vect_mask
= vect_mask
<< 1;
7194 if (VEC_index (vect_el_t
, vect
, vect_index
) != undefined_vect_el_value
)
7198 /* Search for the place in comb vect for the inserted vect. */
7199 comb_vect_index
= 0;
7200 if (comb_vect_els_num
== 0)
7204 for (vect_index
= first_unempty_vect_index
;
7205 vect_index
< vect_length
&& vect_index
< comb_vect_els_num
;
7208 comb_vect_mask
<<= 1;
7209 if (vect_index
+ comb_vect_index
< comb_vect_els_num
7210 && VEC_index (vect_el_t
, tab
->comb_vect
, vect_index
+ comb_vect_index
)
7211 != undefined_vect_el_value
)
7212 comb_vect_mask
|= 1;
7214 if ((vect_mask
& comb_vect_mask
) == 0)
7217 for (comb_vect_index
= 1, i
= vect_length
; i
< comb_vect_els_num
;
7218 comb_vect_index
++, i
++)
7220 comb_vect_mask
= (comb_vect_mask
<< 1) | 1;
7221 comb_vect_mask
^= (VEC_index (vect_el_t
, tab
->comb_vect
, i
)
7222 == undefined_vect_el_value
);
7223 if ((vect_mask
& comb_vect_mask
) == 0)
7226 for ( ; comb_vect_index
< comb_vect_els_num
; comb_vect_index
++)
7228 comb_vect_mask
<<= 1;
7229 if ((vect_mask
& comb_vect_mask
) == 0)
7234 /* Slot was found. */
7235 additional_els_num
= comb_vect_index
+ real_vect_length
- comb_vect_els_num
;
7236 if (additional_els_num
< 0)
7237 additional_els_num
= 0;
7238 /* Expand comb and check vectors. */
7239 vect_el
= undefined_vect_el_value
;
7240 no_state_value
= tab
->automaton
->achieved_states_num
;
7241 while (additional_els_num
> 0)
7243 VEC_safe_push (vect_el_t
,heap
, tab
->comb_vect
, vect_el
);
7244 VEC_safe_push (vect_el_t
,heap
, tab
->check_vect
, no_state_value
);
7245 additional_els_num
--;
7247 gcc_assert (VEC_length (vect_el_t
, tab
->comb_vect
)
7248 >= comb_vect_index
+ real_vect_length
);
7249 /* Fill comb and check vectors. */
7250 for (vect_index
= 0; vect_index
< vect_length
; vect_index
++)
7251 if (VEC_index (vect_el_t
, vect
, vect_index
) != undefined_vect_el_value
)
7253 vect_el_t x
= VEC_index (vect_el_t
, vect
, vect_index
);
7254 gcc_assert (VEC_index (vect_el_t
, tab
->comb_vect
,
7255 comb_vect_index
+ vect_index
)
7256 == undefined_vect_el_value
);
7257 gcc_assert (x
>= 0);
7258 if (tab
->max_comb_vect_el_value
< x
)
7259 tab
->max_comb_vect_el_value
= x
;
7260 if (tab
->min_comb_vect_el_value
> x
)
7261 tab
->min_comb_vect_el_value
= x
;
7262 VEC_replace (vect_el_t
, tab
->comb_vect
,
7263 comb_vect_index
+ vect_index
, x
);
7264 VEC_replace (vect_el_t
, tab
->check_vect
,
7265 comb_vect_index
+ vect_index
, vect_num
);
7267 if (tab
->max_comb_vect_el_value
< undefined_vect_el_value
)
7268 tab
->max_comb_vect_el_value
= undefined_vect_el_value
;
7269 if (tab
->min_comb_vect_el_value
> undefined_vect_el_value
)
7270 tab
->min_comb_vect_el_value
= undefined_vect_el_value
;
7271 if (tab
->max_base_vect_el_value
< comb_vect_index
)
7272 tab
->max_base_vect_el_value
= comb_vect_index
;
7273 if (tab
->min_base_vect_el_value
> comb_vect_index
)
7274 tab
->min_base_vect_el_value
= comb_vect_index
;
7276 VEC_replace (vect_el_t
, tab
->base_vect
, vect_num
, comb_vect_index
);
7279 /* Return number of out arcs of STATE. */
7281 out_state_arcs_num (state_t state
)
7287 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
7289 gcc_assert (arc
->insn
);
7290 if (arc
->insn
->first_ainsn_with_given_equivalence_num
)
7296 /* Compare number of possible transitions from the states. */
7298 compare_transition_els_num (const void *state_ptr_1
,
7299 const void *state_ptr_2
)
7301 int transition_els_num_1
;
7302 int transition_els_num_2
;
7304 transition_els_num_1
= out_state_arcs_num (*(state_t
*) state_ptr_1
);
7305 transition_els_num_2
= out_state_arcs_num (*(state_t
*) state_ptr_2
);
7306 if (transition_els_num_1
< transition_els_num_2
)
7308 else if (transition_els_num_1
== transition_els_num_2
)
7314 /* The function adds element EL_VALUE to vector VECT for a table state
7317 add_vect_el (vla_hwint_t
*vect
, ainsn_t ainsn
, int el_value
)
7319 int equiv_class_num
;
7323 equiv_class_num
= ainsn
->insn_equiv_class_num
;
7324 for (vect_index
= VEC_length (vect_el_t
, *vect
);
7325 vect_index
<= equiv_class_num
;
7327 VEC_safe_push (vect_el_t
,heap
, *vect
, undefined_vect_el_value
);
7328 VEC_replace (vect_el_t
, *vect
, equiv_class_num
, el_value
);
7331 /* This is for forming vector of states of an automaton. */
7332 static VEC(state_t
,heap
) *output_states_vect
;
7334 /* The function is called by function pass_states. The function adds
7335 STATE to `output_states_vect'. */
7337 add_states_vect_el (state_t state
)
7339 VEC_safe_push (state_t
,heap
, output_states_vect
, state
);
7342 /* Form and output vectors (comb, check, base or full vector)
7343 representing transition table of AUTOMATON. */
7345 output_trans_table (automaton_t automaton
)
7349 vla_hwint_t transition_vect
= 0;
7351 undefined_vect_el_value
= automaton
->achieved_states_num
;
7352 automaton
->trans_table
= create_state_ainsn_table (automaton
);
7353 /* Create vect of pointers to states ordered by num of transitions
7354 from the state (state with the maximum num is the first). */
7355 output_states_vect
= 0;
7356 pass_states (automaton
, add_states_vect_el
);
7357 qsort (VEC_address (state_t
, output_states_vect
),
7358 VEC_length (state_t
, output_states_vect
),
7359 sizeof (state_t
), compare_transition_els_num
);
7361 for (i
= 0; i
< VEC_length (state_t
, output_states_vect
); i
++)
7363 VEC_truncate (vect_el_t
, transition_vect
, 0);
7364 for (arc
= first_out_arc (VEC_index (state_t
, output_states_vect
, i
));
7366 arc
= next_out_arc (arc
))
7368 gcc_assert (arc
->insn
);
7369 if (arc
->insn
->first_ainsn_with_given_equivalence_num
)
7370 add_vect_el (&transition_vect
, arc
->insn
,
7371 arc
->to_state
->order_state_num
);
7373 add_vect (automaton
->trans_table
,
7374 VEC_index (state_t
, output_states_vect
, i
)->order_state_num
,
7377 output_state_ainsn_table
7378 (automaton
->trans_table
, "state transitions",
7379 output_trans_full_vect_name
, output_trans_comb_vect_name
,
7380 output_trans_check_vect_name
, output_trans_base_vect_name
);
7382 VEC_free (state_t
,heap
, output_states_vect
);
7383 VEC_free (vect_el_t
,heap
, transition_vect
);
7386 /* The current number of passing states to find minimal issue delay
7387 value for an ainsn and state. */
7388 static int curr_state_pass_num
;
7390 /* This recursive function passes states to find minimal issue delay
7391 value for AINSN. The state being visited is STATE. The function
7392 returns minimal issue delay value for AINSN in STATE or -1 if we
7393 enter into a loop. */
7395 min_issue_delay_pass_states (state_t state
, ainsn_t ainsn
)
7398 int min_insn_issue_delay
, insn_issue_delay
;
7400 if (state
->state_pass_num
== curr_state_pass_num
7401 || state
->min_insn_issue_delay
!= -1)
7402 /* We've entered into a loop or already have the correct value for
7403 given state and ainsn. */
7404 return state
->min_insn_issue_delay
;
7405 state
->state_pass_num
= curr_state_pass_num
;
7406 min_insn_issue_delay
= -1;
7407 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
7408 if (arc
->insn
== ainsn
)
7410 min_insn_issue_delay
= 0;
7415 insn_issue_delay
= min_issue_delay_pass_states (arc
->to_state
, ainsn
);
7416 if (insn_issue_delay
!= -1)
7418 if (arc
->insn
->insn_reserv_decl
7419 == DECL_INSN_RESERV (advance_cycle_insn_decl
))
7421 if (min_insn_issue_delay
== -1
7422 || min_insn_issue_delay
> insn_issue_delay
)
7424 min_insn_issue_delay
= insn_issue_delay
;
7425 if (insn_issue_delay
== 0)
7430 return min_insn_issue_delay
;
7433 /* The function searches minimal issue delay value for AINSN in STATE.
7434 The function can return negative value if we can not issue AINSN. We
7435 will report about it later. */
7437 min_issue_delay (state_t state
, ainsn_t ainsn
)
7439 curr_state_pass_num
++;
7440 state
->min_insn_issue_delay
= min_issue_delay_pass_states (state
, ainsn
);
7441 return state
->min_insn_issue_delay
;
7444 /* The function initiates code for finding minimal issue delay values.
7445 It should be called only once. */
7447 initiate_min_issue_delay_pass_states (void)
7449 curr_state_pass_num
= 0;
7452 /* Form and output vectors representing minimal issue delay table of
7453 AUTOMATON. The table is state x ainsn -> minimal issue delay of
7456 output_min_issue_delay_table (automaton_t automaton
)
7458 vla_hwint_t min_issue_delay_vect
;
7459 vla_hwint_t compressed_min_issue_delay_vect
;
7460 vect_el_t min_delay
;
7462 size_t i
, min_issue_delay_len
;
7463 size_t compressed_min_issue_delay_len
;
7466 /* Create vect of pointers to states ordered by num of transitions
7467 from the state (state with the maximum num is the first). */
7468 output_states_vect
= 0;
7469 pass_states (automaton
, add_states_vect_el
);
7471 min_issue_delay_len
= (VEC_length (state_t
, output_states_vect
)
7472 * automaton
->insn_equiv_classes_num
);
7473 min_issue_delay_vect
= VEC_alloc (vect_el_t
,heap
, min_issue_delay_len
);
7474 for (i
= 0; i
< min_issue_delay_len
; i
++)
7475 VEC_quick_push (vect_el_t
, min_issue_delay_vect
, 0);
7477 automaton
->max_min_delay
= 0;
7478 for (ainsn
= automaton
->ainsn_list
; ainsn
!= NULL
; ainsn
= ainsn
->next_ainsn
)
7479 if (ainsn
->first_ainsn_with_given_equivalence_num
)
7481 for (i
= 0; i
< VEC_length (state_t
, output_states_vect
); i
++)
7482 VEC_index (state_t
, output_states_vect
, i
)->min_insn_issue_delay
= -1;
7483 for (i
= 0; i
< VEC_length (state_t
, output_states_vect
); i
++)
7485 state_t s
= VEC_index (state_t
, output_states_vect
, i
);
7486 min_delay
= min_issue_delay (s
, ainsn
);
7487 if (automaton
->max_min_delay
< min_delay
)
7488 automaton
->max_min_delay
= min_delay
;
7489 VEC_replace (vect_el_t
, min_issue_delay_vect
,
7491 * automaton
->insn_equiv_classes_num
7492 + ainsn
->insn_equiv_class_num
,
7496 fprintf (output_file
, "/* Vector of min issue delay of insns. */\n");
7497 fprintf (output_file
, "static const ");
7498 output_range_type (output_file
, 0, automaton
->max_min_delay
);
7499 fprintf (output_file
, " ");
7500 output_min_issue_delay_vect_name (output_file
, automaton
);
7501 fprintf (output_file
, "[] ATTRIBUTE_UNUSED = {\n");
7502 /* Compress the vector. */
7503 if (automaton
->max_min_delay
< 2)
7505 else if (automaton
->max_min_delay
< 4)
7507 else if (automaton
->max_min_delay
< 16)
7511 automaton
->min_issue_delay_table_compression_factor
= cfactor
;
7513 compressed_min_issue_delay_len
= (min_issue_delay_len
+cfactor
-1) / cfactor
;
7514 compressed_min_issue_delay_vect
7515 = VEC_alloc (vect_el_t
,heap
, compressed_min_issue_delay_len
);
7517 for (i
= 0; i
< compressed_min_issue_delay_len
; i
++)
7518 VEC_quick_push (vect_el_t
, compressed_min_issue_delay_vect
, 0);
7520 for (i
= 0; i
< min_issue_delay_len
; i
++)
7522 size_t ci
= i
/ cfactor
;
7523 vect_el_t x
= VEC_index (vect_el_t
, min_issue_delay_vect
, i
);
7524 vect_el_t cx
= VEC_index (vect_el_t
, compressed_min_issue_delay_vect
, ci
);
7526 cx
|= x
<< (8 - (i
% cfactor
+ 1) * (8 / cfactor
));
7527 VEC_replace (vect_el_t
, compressed_min_issue_delay_vect
, ci
, cx
);
7529 output_vect (compressed_min_issue_delay_vect
);
7530 fprintf (output_file
, "};\n\n");
7531 VEC_free (state_t
,heap
, output_states_vect
);
7532 VEC_free (vect_el_t
,heap
, min_issue_delay_vect
);
7533 VEC_free (vect_el_t
,heap
, compressed_min_issue_delay_vect
);
7536 /* Form and output vector representing the locked states of
7539 output_dead_lock_vect (automaton_t automaton
)
7543 vla_hwint_t dead_lock_vect
= 0;
7545 /* Create vect of pointers to states ordered by num of
7546 transitions from the state (state with the maximum num is the
7548 automaton
->locked_states
= 0;
7549 output_states_vect
= 0;
7550 pass_states (automaton
, add_states_vect_el
);
7552 VEC_safe_grow (vect_el_t
,heap
, dead_lock_vect
,
7553 VEC_length (state_t
, output_states_vect
));
7554 for (i
= 0; i
< VEC_length (state_t
, output_states_vect
); i
++)
7556 state_t s
= VEC_index (state_t
, output_states_vect
, i
);
7557 arc
= first_out_arc (s
);
7559 if (next_out_arc (arc
) == NULL
7560 && (arc
->insn
->insn_reserv_decl
7561 == DECL_INSN_RESERV (advance_cycle_insn_decl
)))
7563 VEC_replace (vect_el_t
, dead_lock_vect
, s
->order_state_num
, 1);
7564 automaton
->locked_states
++;
7567 VEC_replace (vect_el_t
, dead_lock_vect
, s
->order_state_num
, 0);
7569 if (automaton
->locked_states
== 0)
7572 fprintf (output_file
, "/* Vector for locked state flags. */\n");
7573 fprintf (output_file
, "static const ");
7574 output_range_type (output_file
, 0, 1);
7575 fprintf (output_file
, " ");
7576 output_dead_lock_vect_name (output_file
, automaton
);
7577 fprintf (output_file
, "[] = {\n");
7578 output_vect (dead_lock_vect
);
7579 fprintf (output_file
, "};\n\n");
7580 VEC_free (state_t
,heap
, output_states_vect
);
7581 VEC_free (vect_el_t
,heap
, dead_lock_vect
);
7584 /* Form and output vector representing reserved units of the states of
7587 output_reserved_units_table (automaton_t automaton
)
7589 vla_hwint_t reserved_units_table
= 0;
7590 int state_byte_size
;
7591 int reserved_units_size
;
7595 if (description
->query_units_num
== 0)
7598 /* Create vect of pointers to states. */
7599 output_states_vect
= 0;
7600 pass_states (automaton
, add_states_vect_el
);
7601 /* Create vector. */
7602 state_byte_size
= (description
->query_units_num
+ 7) / 8;
7603 reserved_units_size
= (VEC_length (state_t
, output_states_vect
)
7606 reserved_units_table
= VEC_alloc (vect_el_t
,heap
, reserved_units_size
);
7608 for (i
= 0; i
< reserved_units_size
; i
++)
7609 VEC_quick_push (vect_el_t
, reserved_units_table
, 0);
7610 for (n
= 0; n
< VEC_length (state_t
, output_states_vect
); n
++)
7612 state_t s
= VEC_index (state_t
, output_states_vect
, n
);
7613 for (i
= 0; i
< description
->units_num
; i
++)
7614 if (units_array
[i
]->query_p
7615 && first_cycle_unit_presence (s
, i
))
7617 int ri
= (s
->order_state_num
* state_byte_size
7618 + units_array
[i
]->query_num
/ 8);
7619 vect_el_t x
= VEC_index (vect_el_t
, reserved_units_table
, ri
);
7621 x
+= 1 << (units_array
[i
]->query_num
% 8);
7622 VEC_replace (vect_el_t
, reserved_units_table
, ri
, x
);
7625 fprintf (output_file
, "\n#if %s\n", CPU_UNITS_QUERY_MACRO_NAME
);
7626 fprintf (output_file
, "/* Vector for reserved units of states. */\n");
7627 fprintf (output_file
, "static const ");
7628 output_range_type (output_file
, 0, 255);
7629 fprintf (output_file
, " ");
7630 output_reserved_units_table_name (output_file
, automaton
);
7631 fprintf (output_file
, "[] = {\n");
7632 output_vect (reserved_units_table
);
7633 fprintf (output_file
, "};\n#endif /* #if %s */\n\n",
7634 CPU_UNITS_QUERY_MACRO_NAME
);
7636 VEC_free (state_t
,heap
, output_states_vect
);
7637 VEC_free (vect_el_t
,heap
, reserved_units_table
);
7640 /* The function outputs all tables representing DFA(s) used for fast
7641 pipeline hazards recognition. */
7643 output_tables (void)
7645 automaton_t automaton
;
7647 initiate_min_issue_delay_pass_states ();
7648 for (automaton
= description
->first_automaton
;
7650 automaton
= automaton
->next_automaton
)
7652 output_translate_vect (automaton
);
7653 output_trans_table (automaton
);
7654 output_min_issue_delay_table (automaton
);
7655 output_dead_lock_vect (automaton
);
7656 output_reserved_units_table (automaton
);
7658 fprintf (output_file
, "\n#define %s %d\n\n", ADVANCE_CYCLE_VALUE_NAME
,
7659 DECL_INSN_RESERV (advance_cycle_insn_decl
)->insn_num
);
7662 /* The function outputs definition and value of PHR interface variable
7663 `max_insn_queue_index'. Its value is not less than maximal queue
7664 length needed for the insn scheduler. */
7666 output_max_insn_queue_index_def (void)
7668 int i
, max
, latency
;
7671 max
= description
->max_insn_reserv_cycles
;
7672 for (i
= 0; i
< description
->decls_num
; i
++)
7674 decl
= description
->decls
[i
];
7675 if (decl
->mode
== dm_insn_reserv
&& decl
!= advance_cycle_insn_decl
)
7677 latency
= DECL_INSN_RESERV (decl
)->default_latency
;
7681 else if (decl
->mode
== dm_bypass
)
7683 latency
= DECL_BYPASS (decl
)->latency
;
7688 for (i
= 0; (1 << i
) <= max
; i
++)
7690 gcc_assert (i
>= 0);
7691 fprintf (output_file
, "\nconst int max_insn_queue_index = %d;\n\n",
7695 /* The function outputs switch cases for insn reservations using
7696 function *output_automata_list_code. */
7698 output_insn_code_cases (void (*output_automata_list_code
)
7699 (automata_list_el_t
))
7704 for (i
= 0; i
< description
->decls_num
; i
++)
7706 decl
= description
->decls
[i
];
7707 if (decl
->mode
== dm_insn_reserv
)
7708 DECL_INSN_RESERV (decl
)->processed_p
= FALSE
;
7710 for (i
= 0; i
< description
->decls_num
; i
++)
7712 decl
= description
->decls
[i
];
7713 if (decl
->mode
== dm_insn_reserv
7714 && !DECL_INSN_RESERV (decl
)->processed_p
)
7716 for (j
= i
; j
< description
->decls_num
; j
++)
7718 decl2
= description
->decls
[j
];
7719 if (decl2
->mode
== dm_insn_reserv
7720 && (DECL_INSN_RESERV (decl2
)->important_automata_list
7721 == DECL_INSN_RESERV (decl
)->important_automata_list
))
7723 DECL_INSN_RESERV (decl2
)->processed_p
= TRUE
;
7724 fprintf (output_file
, " case %d: /* %s */\n",
7725 DECL_INSN_RESERV (decl2
)->insn_num
,
7726 DECL_INSN_RESERV (decl2
)->name
);
7729 (*output_automata_list_code
)
7730 (DECL_INSN_RESERV (decl
)->important_automata_list
);
7736 /* The function outputs a code for evaluation of a minimal delay of
7737 issue of insns which have reservations in given AUTOMATA_LIST. */
7739 output_automata_list_min_issue_delay_code (automata_list_el_t automata_list
)
7741 automata_list_el_t el
;
7742 automaton_t automaton
;
7744 for (el
= automata_list
; el
!= NULL
; el
= el
->next_automata_list_el
)
7746 automaton
= el
->automaton
;
7747 fprintf (output_file
, "\n %s = ", TEMPORARY_VARIABLE_NAME
);
7748 output_min_issue_delay_vect_name (output_file
, automaton
);
7749 fprintf (output_file
,
7750 (automaton
->min_issue_delay_table_compression_factor
!= 1
7752 output_translate_vect_name (output_file
, automaton
);
7753 fprintf (output_file
, " [%s] + ", INTERNAL_INSN_CODE_NAME
);
7754 fprintf (output_file
, "%s->", CHIP_PARAMETER_NAME
);
7755 output_chip_member_name (output_file
, automaton
);
7756 fprintf (output_file
, " * %d", automaton
->insn_equiv_classes_num
);
7757 if (automaton
->min_issue_delay_table_compression_factor
== 1)
7758 fprintf (output_file
, "];\n");
7761 fprintf (output_file
, ") / %d];\n",
7762 automaton
->min_issue_delay_table_compression_factor
);
7763 fprintf (output_file
, " %s = (%s >> (8 - (",
7764 TEMPORARY_VARIABLE_NAME
, TEMPORARY_VARIABLE_NAME
);
7765 output_translate_vect_name (output_file
, automaton
);
7767 (output_file
, " [%s] %% %d + 1) * %d)) & %d;\n",
7768 INTERNAL_INSN_CODE_NAME
,
7769 automaton
->min_issue_delay_table_compression_factor
,
7770 8 / automaton
->min_issue_delay_table_compression_factor
,
7771 (1 << (8 / automaton
->min_issue_delay_table_compression_factor
))
7774 if (el
== automata_list
)
7775 fprintf (output_file
, " %s = %s;\n",
7776 RESULT_VARIABLE_NAME
, TEMPORARY_VARIABLE_NAME
);
7779 fprintf (output_file
, " if (%s > %s)\n",
7780 TEMPORARY_VARIABLE_NAME
, RESULT_VARIABLE_NAME
);
7781 fprintf (output_file
, " %s = %s;\n",
7782 RESULT_VARIABLE_NAME
, TEMPORARY_VARIABLE_NAME
);
7785 fprintf (output_file
, " break;\n\n");
7788 /* Output function `internal_min_issue_delay'. */
7790 output_internal_min_issue_delay_func (void)
7792 fprintf (output_file
,
7793 "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
7794 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
7795 CHIP_NAME
, CHIP_PARAMETER_NAME
);
7796 fprintf (output_file
, "{\n int %s ATTRIBUTE_UNUSED;\n int %s = -1;\n",
7797 TEMPORARY_VARIABLE_NAME
, RESULT_VARIABLE_NAME
);
7798 fprintf (output_file
, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME
);
7799 output_insn_code_cases (output_automata_list_min_issue_delay_code
);
7800 fprintf (output_file
,
7801 "\n default:\n %s = -1;\n break;\n }\n",
7802 RESULT_VARIABLE_NAME
);
7803 fprintf (output_file
, " return %s;\n", RESULT_VARIABLE_NAME
);
7804 fprintf (output_file
, "}\n\n");
7807 /* The function outputs a code changing state after issue of insns
7808 which have reservations in given AUTOMATA_LIST. */
7810 output_automata_list_transition_code (automata_list_el_t automata_list
)
7812 automata_list_el_t el
, next_el
;
7814 fprintf (output_file
, " {\n");
7815 if (automata_list
!= NULL
&& automata_list
->next_automata_list_el
!= NULL
)
7816 for (el
= automata_list
;; el
= next_el
)
7818 next_el
= el
->next_automata_list_el
;
7819 if (next_el
== NULL
)
7821 fprintf (output_file
, " ");
7822 output_state_member_type (output_file
, el
->automaton
);
7823 fprintf (output_file
, " ");
7824 output_temp_chip_member_name (output_file
, el
->automaton
);
7825 fprintf (output_file
, ";\n");
7827 for (el
= automata_list
; el
!= NULL
; el
= el
->next_automata_list_el
)
7828 if (comb_vect_p (el
->automaton
->trans_table
))
7830 fprintf (output_file
, "\n %s = ", TEMPORARY_VARIABLE_NAME
);
7831 output_trans_base_vect_name (output_file
, el
->automaton
);
7832 fprintf (output_file
, " [%s->", CHIP_PARAMETER_NAME
);
7833 output_chip_member_name (output_file
, el
->automaton
);
7834 fprintf (output_file
, "] + ");
7835 output_translate_vect_name (output_file
, el
->automaton
);
7836 fprintf (output_file
, " [%s];\n", INTERNAL_INSN_CODE_NAME
);
7837 fprintf (output_file
, " if (");
7838 output_trans_check_vect_name (output_file
, el
->automaton
);
7839 fprintf (output_file
, " [%s] != %s->",
7840 TEMPORARY_VARIABLE_NAME
, CHIP_PARAMETER_NAME
);
7841 output_chip_member_name (output_file
, el
->automaton
);
7842 fprintf (output_file
, ")\n");
7843 fprintf (output_file
, " return %s (%s, %s);\n",
7844 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
7845 CHIP_PARAMETER_NAME
);
7846 fprintf (output_file
, " else\n");
7847 fprintf (output_file
, " ");
7848 if (el
->next_automata_list_el
!= NULL
)
7849 output_temp_chip_member_name (output_file
, el
->automaton
);
7852 fprintf (output_file
, "%s->", CHIP_PARAMETER_NAME
);
7853 output_chip_member_name (output_file
, el
->automaton
);
7855 fprintf (output_file
, " = ");
7856 output_trans_comb_vect_name (output_file
, el
->automaton
);
7857 fprintf (output_file
, " [%s];\n", TEMPORARY_VARIABLE_NAME
);
7861 fprintf (output_file
, "\n %s = ", TEMPORARY_VARIABLE_NAME
);
7862 output_trans_full_vect_name (output_file
, el
->automaton
);
7863 fprintf (output_file
, " [");
7864 output_translate_vect_name (output_file
, el
->automaton
);
7865 fprintf (output_file
, " [%s] + ", INTERNAL_INSN_CODE_NAME
);
7866 fprintf (output_file
, "%s->", CHIP_PARAMETER_NAME
);
7867 output_chip_member_name (output_file
, el
->automaton
);
7868 fprintf (output_file
, " * %d];\n",
7869 el
->automaton
->insn_equiv_classes_num
);
7870 fprintf (output_file
, " if (%s >= %d)\n",
7871 TEMPORARY_VARIABLE_NAME
, el
->automaton
->achieved_states_num
);
7872 fprintf (output_file
, " return %s (%s, %s);\n",
7873 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
7874 CHIP_PARAMETER_NAME
);
7875 fprintf (output_file
, " else\n ");
7876 if (el
->next_automata_list_el
!= NULL
)
7877 output_temp_chip_member_name (output_file
, el
->automaton
);
7880 fprintf (output_file
, "%s->", CHIP_PARAMETER_NAME
);
7881 output_chip_member_name (output_file
, el
->automaton
);
7883 fprintf (output_file
, " = %s;\n", TEMPORARY_VARIABLE_NAME
);
7885 if (automata_list
!= NULL
&& automata_list
->next_automata_list_el
!= NULL
)
7886 for (el
= automata_list
;; el
= next_el
)
7888 next_el
= el
->next_automata_list_el
;
7889 if (next_el
== NULL
)
7891 fprintf (output_file
, " %s->", CHIP_PARAMETER_NAME
);
7892 output_chip_member_name (output_file
, el
->automaton
);
7893 fprintf (output_file
, " = ");
7894 output_temp_chip_member_name (output_file
, el
->automaton
);
7895 fprintf (output_file
, ";\n");
7897 fprintf (output_file
, " return -1;\n");
7898 fprintf (output_file
, " }\n");
7901 /* Output function `internal_state_transition'. */
7903 output_internal_trans_func (void)
7905 fprintf (output_file
,
7906 "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
7907 INTERNAL_TRANSITION_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
7908 CHIP_NAME
, CHIP_PARAMETER_NAME
);
7909 fprintf (output_file
, "{\n int %s ATTRIBUTE_UNUSED;\n", TEMPORARY_VARIABLE_NAME
);
7910 fprintf (output_file
, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME
);
7911 output_insn_code_cases (output_automata_list_transition_code
);
7912 fprintf (output_file
, "\n default:\n return -1;\n }\n");
7913 fprintf (output_file
, "}\n\n");
7920 insn_code = dfa_insn_code (insn);
7921 if (insn_code > DFA__ADVANCE_CYCLE)
7925 insn_code = DFA__ADVANCE_CYCLE;
7927 where insn denotes INSN_NAME, insn_code denotes INSN_CODE_NAME, and
7928 code denotes CODE. */
7930 output_internal_insn_code_evaluation (const char *insn_name
,
7931 const char *insn_code_name
,
7934 fprintf (output_file
, "\n if (%s != 0)\n {\n", insn_name
);
7935 fprintf (output_file
, " %s = %s (%s);\n", insn_code_name
,
7936 DFA_INSN_CODE_FUNC_NAME
, insn_name
);
7937 fprintf (output_file
, " if (%s > %s)\n return %d;\n",
7938 insn_code_name
, ADVANCE_CYCLE_VALUE_NAME
, code
);
7939 fprintf (output_file
, " }\n else\n %s = %s;\n\n",
7940 insn_code_name
, ADVANCE_CYCLE_VALUE_NAME
);
7944 /* This function outputs `dfa_insn_code' and its helper function
7945 `dfa_insn_code_enlarge'. */
7947 output_dfa_insn_code_func (void)
7949 /* Emacs c-mode gets really confused if there's a { or } in column 0
7950 inside a string, so don't do that. */
7951 fprintf (output_file
, "\
7953 dfa_insn_code_enlarge (int uid)\n\
7957 %s = xrealloc (%s,\n\
7958 %s * sizeof(int));\n\
7959 for (; i < %s; i++)\n\
7960 %s[i] = -1;\n}\n\n",
7961 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
,
7962 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
,
7963 DFA_INSN_CODES_VARIABLE_NAME
, DFA_INSN_CODES_VARIABLE_NAME
,
7964 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
,
7965 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
,
7966 DFA_INSN_CODES_VARIABLE_NAME
);
7967 fprintf (output_file
, "\
7968 static inline int\n%s (rtx %s)\n\
7970 int uid = INSN_UID (%s);\n\
7972 DFA_INSN_CODE_FUNC_NAME
, INSN_PARAMETER_NAME
,
7973 INSN_PARAMETER_NAME
, INTERNAL_INSN_CODE_NAME
);
7975 fprintf (output_file
,
7976 " if (uid >= %s)\n dfa_insn_code_enlarge (uid);\n\n",
7977 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
);
7978 fprintf (output_file
, " %s = %s[uid];\n",
7979 INTERNAL_INSN_CODE_NAME
, DFA_INSN_CODES_VARIABLE_NAME
);
7980 fprintf (output_file
, "\
7986 INTERNAL_INSN_CODE_NAME
,
7987 INTERNAL_INSN_CODE_NAME
,
7988 INTERNAL_DFA_INSN_CODE_FUNC_NAME
, INSN_PARAMETER_NAME
,
7989 DFA_INSN_CODES_VARIABLE_NAME
, INTERNAL_INSN_CODE_NAME
);
7990 fprintf (output_file
, " return %s;\n}\n\n", INTERNAL_INSN_CODE_NAME
);
7993 /* The function outputs PHR interface function `state_transition'. */
7995 output_trans_func (void)
7997 fprintf (output_file
, "int\n%s (%s %s, rtx %s)\n",
7998 TRANSITION_FUNC_NAME
, STATE_TYPE_NAME
, STATE_NAME
,
7999 INSN_PARAMETER_NAME
);
8000 fprintf (output_file
, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME
);
8001 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME
,
8002 INTERNAL_INSN_CODE_NAME
, -1);
8003 fprintf (output_file
, " return %s (%s, %s);\n}\n\n",
8004 INTERNAL_TRANSITION_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
, STATE_NAME
);
8007 /* Output function `min_issue_delay'. */
8009 output_min_issue_delay_func (void)
8011 fprintf (output_file
, "int\n%s (%s %s, rtx %s)\n",
8012 MIN_ISSUE_DELAY_FUNC_NAME
, STATE_TYPE_NAME
, STATE_NAME
,
8013 INSN_PARAMETER_NAME
);
8014 fprintf (output_file
, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME
);
8015 fprintf (output_file
, "\n if (%s != 0)\n {\n", INSN_PARAMETER_NAME
);
8016 fprintf (output_file
, " %s = %s (%s);\n", INTERNAL_INSN_CODE_NAME
,
8017 DFA_INSN_CODE_FUNC_NAME
, INSN_PARAMETER_NAME
);
8018 fprintf (output_file
, " if (%s > %s)\n return 0;\n",
8019 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
8020 fprintf (output_file
, " }\n else\n %s = %s;\n",
8021 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
8022 fprintf (output_file
, "\n return %s (%s, %s);\n",
8023 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
8025 fprintf (output_file
, "}\n\n");
8028 /* Output function `internal_dead_lock'. */
8030 output_internal_dead_lock_func (void)
8032 automaton_t automaton
;
8034 fprintf (output_file
, "static int\n%s (struct %s *ARG_UNUSED (%s))\n",
8035 INTERNAL_DEAD_LOCK_FUNC_NAME
, CHIP_NAME
, CHIP_PARAMETER_NAME
);
8036 fprintf (output_file
, "{\n");
8037 for (automaton
= description
->first_automaton
;
8039 automaton
= automaton
->next_automaton
)
8040 if (automaton
->locked_states
)
8042 fprintf (output_file
, " if (");
8043 output_dead_lock_vect_name (output_file
, automaton
);
8044 fprintf (output_file
, " [%s->", CHIP_PARAMETER_NAME
);
8045 output_chip_member_name (output_file
, automaton
);
8046 fprintf (output_file
, "])\n return 1/* TRUE */;\n");
8048 fprintf (output_file
, " return 0/* FALSE */;\n}\n\n");
8051 /* The function outputs PHR interface function `state_dead_lock_p'. */
8053 output_dead_lock_func (void)
8055 fprintf (output_file
, "int\n%s (%s %s)\n",
8056 DEAD_LOCK_FUNC_NAME
, STATE_TYPE_NAME
, STATE_NAME
);
8057 fprintf (output_file
, "{\n return %s (%s);\n}\n\n",
8058 INTERNAL_DEAD_LOCK_FUNC_NAME
, STATE_NAME
);
8061 /* Output function `internal_reset'. */
8063 output_internal_reset_func (void)
8065 fprintf (output_file
, "static inline void\n%s (struct %s *%s)\n",
8066 INTERNAL_RESET_FUNC_NAME
, CHIP_NAME
, CHIP_PARAMETER_NAME
);
8067 fprintf (output_file
, "{\n memset (%s, 0, sizeof (struct %s));\n}\n\n",
8068 CHIP_PARAMETER_NAME
, CHIP_NAME
);
8071 /* The function outputs PHR interface function `state_size'. */
8073 output_size_func (void)
8075 fprintf (output_file
, "int\n%s (void)\n", SIZE_FUNC_NAME
);
8076 fprintf (output_file
, "{\n return sizeof (struct %s);\n}\n\n", CHIP_NAME
);
8079 /* The function outputs PHR interface function `state_reset'. */
8081 output_reset_func (void)
8083 fprintf (output_file
, "void\n%s (%s %s)\n",
8084 RESET_FUNC_NAME
, STATE_TYPE_NAME
, STATE_NAME
);
8085 fprintf (output_file
, "{\n %s (%s);\n}\n\n", INTERNAL_RESET_FUNC_NAME
,
8089 /* Output function `min_insn_conflict_delay'. */
8091 output_min_insn_conflict_delay_func (void)
8093 fprintf (output_file
,
8094 "int\n%s (%s %s, rtx %s, rtx %s)\n",
8095 MIN_INSN_CONFLICT_DELAY_FUNC_NAME
, STATE_TYPE_NAME
,
8096 STATE_NAME
, INSN_PARAMETER_NAME
, INSN2_PARAMETER_NAME
);
8097 fprintf (output_file
, "{\n struct %s %s;\n int %s, %s, transition;\n",
8098 CHIP_NAME
, CHIP_NAME
, INTERNAL_INSN_CODE_NAME
,
8099 INTERNAL_INSN2_CODE_NAME
);
8100 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME
,
8101 INTERNAL_INSN_CODE_NAME
, 0);
8102 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME
,
8103 INTERNAL_INSN2_CODE_NAME
, 0);
8104 fprintf (output_file
, " memcpy (&%s, %s, sizeof (%s));\n",
8105 CHIP_NAME
, STATE_NAME
, CHIP_NAME
);
8106 fprintf (output_file
, " %s (&%s);\n", INTERNAL_RESET_FUNC_NAME
, CHIP_NAME
);
8107 fprintf (output_file
, " transition = %s (%s, &%s);\n",
8108 INTERNAL_TRANSITION_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
, CHIP_NAME
);
8109 fprintf (output_file
, " gcc_assert (transition <= 0);\n");
8110 fprintf (output_file
, " return %s (%s, &%s);\n",
8111 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME
, INTERNAL_INSN2_CODE_NAME
,
8113 fprintf (output_file
, "}\n\n");
8116 /* Output function `internal_insn_latency'. */
8118 output_internal_insn_latency_func (void)
8121 struct bypass_decl
*bypass
;
8123 const char *tabletype
= "unsigned char";
8125 /* Find the smallest integer type that can hold all the default
8127 for (i
= 0; i
< description
->decls_num
; i
++)
8128 if (description
->decls
[i
]->mode
== dm_insn_reserv
)
8130 decl
= description
->decls
[i
];
8131 if (DECL_INSN_RESERV (decl
)->default_latency
> UCHAR_MAX
8132 && tabletype
[0] != 'i') /* Don't shrink it. */
8133 tabletype
= "unsigned short";
8134 if (DECL_INSN_RESERV (decl
)->default_latency
> USHRT_MAX
)
8138 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",
8139 INTERNAL_INSN_LATENCY_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
8140 INTERNAL_INSN2_CODE_NAME
, INSN_PARAMETER_NAME
,
8141 INSN2_PARAMETER_NAME
);
8142 fprintf (output_file
, "{\n");
8144 if (DECL_INSN_RESERV (advance_cycle_insn_decl
)->insn_num
== 0)
8146 fputs (" return 0;\n}\n\n", output_file
);
8150 fprintf (output_file
, " static const %s default_latencies[] =\n {",
8153 for (i
= 0, j
= 0, col
= 7; i
< description
->decls_num
; i
++)
8154 if (description
->decls
[i
]->mode
== dm_insn_reserv
8155 && description
->decls
[i
] != advance_cycle_insn_decl
)
8157 if ((col
= (col
+1) % 8) == 0)
8158 fputs ("\n ", output_file
);
8159 decl
= description
->decls
[i
];
8160 gcc_assert (j
++ == DECL_INSN_RESERV (decl
)->insn_num
);
8161 fprintf (output_file
, "% 4d,",
8162 DECL_INSN_RESERV (decl
)->default_latency
);
8164 gcc_assert (j
== DECL_INSN_RESERV (advance_cycle_insn_decl
)->insn_num
);
8165 fputs ("\n };\n", output_file
);
8167 fprintf (output_file
, " if (%s >= %s || %s >= %s)\n return 0;\n",
8168 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
,
8169 INTERNAL_INSN2_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
8171 fprintf (output_file
, " switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME
);
8172 for (i
= 0; i
< description
->decls_num
; i
++)
8173 if (description
->decls
[i
]->mode
== dm_insn_reserv
8174 && DECL_INSN_RESERV (description
->decls
[i
])->bypass_list
)
8176 decl
= description
->decls
[i
];
8177 fprintf (output_file
,
8178 " case %d:\n switch (%s)\n {\n",
8179 DECL_INSN_RESERV (decl
)->insn_num
,
8180 INTERNAL_INSN2_CODE_NAME
);
8181 for (bypass
= DECL_INSN_RESERV (decl
)->bypass_list
;
8183 bypass
= bypass
->next
)
8185 gcc_assert (bypass
->in_insn_reserv
->insn_num
8186 != (DECL_INSN_RESERV
8187 (advance_cycle_insn_decl
)->insn_num
));
8188 fprintf (output_file
, " case %d:\n",
8189 bypass
->in_insn_reserv
->insn_num
);
8190 if (bypass
->bypass_guard_name
== NULL
)
8191 fprintf (output_file
, " return %d;\n",
8195 fprintf (output_file
,
8196 " if (%s (%s, %s))\n",
8197 bypass
->bypass_guard_name
, INSN_PARAMETER_NAME
,
8198 INSN2_PARAMETER_NAME
);
8199 fprintf (output_file
,
8200 " return %d;\n break;\n",
8204 fputs (" }\n break;\n", output_file
);
8207 fprintf (output_file
, " }\n return default_latencies[%s];\n}\n\n",
8208 INTERNAL_INSN_CODE_NAME
);
8211 /* The function outputs PHR interface function `insn_latency'. */
8213 output_insn_latency_func (void)
8215 fprintf (output_file
, "int\n%s (rtx %s, rtx %s)\n",
8216 INSN_LATENCY_FUNC_NAME
, INSN_PARAMETER_NAME
, INSN2_PARAMETER_NAME
);
8217 fprintf (output_file
, "{\n int %s, %s;\n",
8218 INTERNAL_INSN_CODE_NAME
, INTERNAL_INSN2_CODE_NAME
);
8219 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME
,
8220 INTERNAL_INSN_CODE_NAME
, 0);
8221 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME
,
8222 INTERNAL_INSN2_CODE_NAME
, 0);
8223 fprintf (output_file
, " return %s (%s, %s, %s, %s);\n}\n\n",
8224 INTERNAL_INSN_LATENCY_FUNC_NAME
,
8225 INTERNAL_INSN_CODE_NAME
, INTERNAL_INSN2_CODE_NAME
,
8226 INSN_PARAMETER_NAME
, INSN2_PARAMETER_NAME
);
8229 /* The function outputs PHR interface function `print_reservation'. */
8231 output_print_reservation_func (void)
8236 fprintf (output_file
,
8237 "void\n%s (FILE *%s, rtx %s ATTRIBUTE_UNUSED)\n{\n",
8238 PRINT_RESERVATION_FUNC_NAME
, FILE_PARAMETER_NAME
,
8239 INSN_PARAMETER_NAME
);
8241 if (DECL_INSN_RESERV (advance_cycle_insn_decl
)->insn_num
== 0)
8243 fprintf (output_file
, " fputs (\"%s\", %s);\n}\n\n",
8244 NOTHING_NAME
, FILE_PARAMETER_NAME
);
8249 fputs (" static const char *const reservation_names[] =\n {",
8252 for (i
= 0, j
= 0; i
< description
->decls_num
; i
++)
8254 decl
= description
->decls
[i
];
8255 if (decl
->mode
== dm_insn_reserv
&& decl
!= advance_cycle_insn_decl
)
8257 gcc_assert (j
== DECL_INSN_RESERV (decl
)->insn_num
);
8260 fprintf (output_file
, "\n \"%s\",",
8261 regexp_representation (DECL_INSN_RESERV (decl
)->regexp
));
8262 finish_regexp_representation ();
8265 gcc_assert (j
== DECL_INSN_RESERV (advance_cycle_insn_decl
)->insn_num
);
8267 fprintf (output_file
, "\n \"%s\"\n };\n int %s;\n\n",
8268 NOTHING_NAME
, INTERNAL_INSN_CODE_NAME
);
8270 fprintf (output_file
, " if (%s == 0)\n %s = %s;\n",
8271 INSN_PARAMETER_NAME
,
8272 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
8273 fprintf (output_file
, " else\n\
8279 INTERNAL_INSN_CODE_NAME
, DFA_INSN_CODE_FUNC_NAME
,
8280 INSN_PARAMETER_NAME
,
8281 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
,
8282 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
8284 fprintf (output_file
, " fputs (reservation_names[%s], %s);\n}\n\n",
8285 INTERNAL_INSN_CODE_NAME
, FILE_PARAMETER_NAME
);
8288 /* The following function is used to sort unit declaration by their
8291 units_cmp (const void *unit1
, const void *unit2
)
8293 const unit_decl_t u1
= *(unit_decl_t
*) unit1
;
8294 const unit_decl_t u2
= *(unit_decl_t
*) unit2
;
8296 return strcmp (u1
->name
, u2
->name
);
8299 /* The following macro value is name of struct containing unit name
8301 #define NAME_CODE_STRUCT_NAME "name_code"
8303 /* The following macro value is name of table of struct name_code. */
8304 #define NAME_CODE_TABLE_NAME "name_code_table"
8306 /* The following macro values are member names for struct name_code. */
8307 #define NAME_MEMBER_NAME "name"
8308 #define CODE_MEMBER_NAME "code"
8310 /* The following macro values are local variable names for function
8311 `get_cpu_unit_code'. */
8312 #define CMP_VARIABLE_NAME "cmp"
8313 #define LOW_VARIABLE_NAME "l"
8314 #define MIDDLE_VARIABLE_NAME "m"
8315 #define HIGH_VARIABLE_NAME "h"
8317 /* The following function outputs function to obtain internal cpu unit
8318 code by the cpu unit name. */
8320 output_get_cpu_unit_code_func (void)
8325 fprintf (output_file
, "int\n%s (const char *%s)\n",
8326 GET_CPU_UNIT_CODE_FUNC_NAME
, CPU_UNIT_NAME_PARAMETER_NAME
);
8327 fprintf (output_file
, "{\n struct %s {const char *%s; int %s;};\n",
8328 NAME_CODE_STRUCT_NAME
, NAME_MEMBER_NAME
, CODE_MEMBER_NAME
);
8329 fprintf (output_file
, " int %s, %s, %s, %s;\n", CMP_VARIABLE_NAME
,
8330 LOW_VARIABLE_NAME
, MIDDLE_VARIABLE_NAME
, HIGH_VARIABLE_NAME
);
8331 fprintf (output_file
, " static struct %s %s [] =\n {\n",
8332 NAME_CODE_STRUCT_NAME
, NAME_CODE_TABLE_NAME
);
8333 units
= xmalloc (sizeof (unit_decl_t
) * description
->units_num
);
8334 memcpy (units
, units_array
, sizeof (unit_decl_t
) * description
->units_num
);
8335 qsort (units
, description
->units_num
, sizeof (unit_decl_t
), units_cmp
);
8336 for (i
= 0; i
< description
->units_num
; i
++)
8337 if (units
[i
]->query_p
)
8338 fprintf (output_file
, " {\"%s\", %d},\n",
8339 units
[i
]->name
, units
[i
]->query_num
);
8340 fprintf (output_file
, " };\n\n");
8341 fprintf (output_file
, " /* The following is binary search: */\n");
8342 fprintf (output_file
, " %s = 0;\n", LOW_VARIABLE_NAME
);
8343 fprintf (output_file
, " %s = sizeof (%s) / sizeof (struct %s) - 1;\n",
8344 HIGH_VARIABLE_NAME
, NAME_CODE_TABLE_NAME
, NAME_CODE_STRUCT_NAME
);
8345 fprintf (output_file
, " while (%s <= %s)\n {\n",
8346 LOW_VARIABLE_NAME
, HIGH_VARIABLE_NAME
);
8347 fprintf (output_file
, " %s = (%s + %s) / 2;\n",
8348 MIDDLE_VARIABLE_NAME
, LOW_VARIABLE_NAME
, HIGH_VARIABLE_NAME
);
8349 fprintf (output_file
, " %s = strcmp (%s, %s [%s].%s);\n",
8350 CMP_VARIABLE_NAME
, CPU_UNIT_NAME_PARAMETER_NAME
,
8351 NAME_CODE_TABLE_NAME
, MIDDLE_VARIABLE_NAME
, NAME_MEMBER_NAME
);
8352 fprintf (output_file
, " if (%s < 0)\n", CMP_VARIABLE_NAME
);
8353 fprintf (output_file
, " %s = %s - 1;\n",
8354 HIGH_VARIABLE_NAME
, MIDDLE_VARIABLE_NAME
);
8355 fprintf (output_file
, " else if (%s > 0)\n", CMP_VARIABLE_NAME
);
8356 fprintf (output_file
, " %s = %s + 1;\n",
8357 LOW_VARIABLE_NAME
, MIDDLE_VARIABLE_NAME
);
8358 fprintf (output_file
, " else\n");
8359 fprintf (output_file
, " return %s [%s].%s;\n }\n",
8360 NAME_CODE_TABLE_NAME
, MIDDLE_VARIABLE_NAME
, CODE_MEMBER_NAME
);
8361 fprintf (output_file
, " return -1;\n}\n\n");
8365 /* The following function outputs function to check reservation of cpu
8366 unit (its internal code will be passed as the function argument) in
8369 output_cpu_unit_reservation_p (void)
8371 automaton_t automaton
;
8373 fprintf (output_file
, "int\n%s (%s %s, int %s)\n",
8374 CPU_UNIT_RESERVATION_P_FUNC_NAME
,
8375 STATE_TYPE_NAME
, STATE_NAME
,
8376 CPU_CODE_PARAMETER_NAME
);
8377 fprintf (output_file
, "{\n gcc_assert (%s >= 0 && %s < %d);\n",
8378 CPU_CODE_PARAMETER_NAME
, CPU_CODE_PARAMETER_NAME
,
8379 description
->query_units_num
);
8380 if (description
->query_units_num
> 0)
8381 for (automaton
= description
->first_automaton
;
8383 automaton
= automaton
->next_automaton
)
8385 fprintf (output_file
, " if ((");
8386 output_reserved_units_table_name (output_file
, automaton
);
8387 fprintf (output_file
, " [((struct %s *) %s)->", CHIP_NAME
, STATE_NAME
);
8388 output_chip_member_name (output_file
, automaton
);
8389 fprintf (output_file
, " * %d + %s / 8] >> (%s %% 8)) & 1)\n",
8390 (description
->query_units_num
+ 7) / 8,
8391 CPU_CODE_PARAMETER_NAME
, CPU_CODE_PARAMETER_NAME
);
8392 fprintf (output_file
, " return 1;\n");
8394 fprintf (output_file
, " return 0;\n}\n\n");
8397 /* The function outputs PHR interface functions `dfa_clean_insn_cache'
8398 and 'dfa_clear_single_insn_cache'. */
8400 output_dfa_clean_insn_cache_func (void)
8402 fprintf (output_file
,
8403 "void\n%s (void)\n{\n int %s;\n\n",
8404 DFA_CLEAN_INSN_CACHE_FUNC_NAME
, I_VARIABLE_NAME
);
8405 fprintf (output_file
,
8406 " for (%s = 0; %s < %s; %s++)\n %s [%s] = -1;\n}\n\n",
8407 I_VARIABLE_NAME
, I_VARIABLE_NAME
,
8408 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
, I_VARIABLE_NAME
,
8409 DFA_INSN_CODES_VARIABLE_NAME
, I_VARIABLE_NAME
);
8411 fprintf (output_file
,
8412 "void\n%s (rtx %s)\n{\n int %s;\n\n",
8413 DFA_CLEAR_SINGLE_INSN_CACHE_FUNC_NAME
, INSN_PARAMETER_NAME
,
8415 fprintf (output_file
,
8416 " %s = INSN_UID (%s);\n if (%s < %s)\n %s [%s] = -1;\n}\n\n",
8417 I_VARIABLE_NAME
, INSN_PARAMETER_NAME
, I_VARIABLE_NAME
,
8418 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
, DFA_INSN_CODES_VARIABLE_NAME
,
8422 /* The function outputs PHR interface function `dfa_start'. */
8424 output_dfa_start_func (void)
8426 fprintf (output_file
,
8427 "void\n%s (void)\n{\n %s = get_max_uid ();\n",
8428 DFA_START_FUNC_NAME
, DFA_INSN_CODES_LENGTH_VARIABLE_NAME
);
8429 fprintf (output_file
, " %s = xmalloc (%s * sizeof (int));\n",
8430 DFA_INSN_CODES_VARIABLE_NAME
, DFA_INSN_CODES_LENGTH_VARIABLE_NAME
);
8431 fprintf (output_file
, " %s ();\n}\n\n", DFA_CLEAN_INSN_CACHE_FUNC_NAME
);
8434 /* The function outputs PHR interface function `dfa_finish'. */
8436 output_dfa_finish_func (void)
8438 fprintf (output_file
, "void\n%s (void)\n{\n free (%s);\n}\n\n",
8439 DFA_FINISH_FUNC_NAME
, DFA_INSN_CODES_VARIABLE_NAME
);
8444 /* The page contains code for output description file (readable
8445 representation of original description and generated DFA(s). */
8447 /* The function outputs string representation of IR reservation. */
8449 output_regexp (regexp_t regexp
)
8451 fprintf (output_description_file
, "%s", regexp_representation (regexp
));
8452 finish_regexp_representation ();
8455 /* Output names of units in LIST separated by comma. */
8457 output_unit_set_el_list (unit_set_el_t list
)
8461 for (el
= list
; el
!= NULL
; el
= el
->next_unit_set_el
)
8464 fprintf (output_description_file
, ", ");
8465 fprintf (output_description_file
, "%s", el
->unit_decl
->name
);
8469 /* Output patterns in LIST separated by comma. */
8471 output_pattern_set_el_list (pattern_set_el_t list
)
8473 pattern_set_el_t el
;
8476 for (el
= list
; el
!= NULL
; el
= el
->next_pattern_set_el
)
8479 fprintf (output_description_file
, ", ");
8480 for (i
= 0; i
< el
->units_num
; i
++)
8481 fprintf (output_description_file
, (i
== 0 ? "%s" : " %s"),
8482 el
->unit_decls
[i
]->name
);
8486 /* The function outputs string representation of IR define_reservation
8487 and define_insn_reservation. */
8489 output_description (void)
8494 for (i
= 0; i
< description
->decls_num
; i
++)
8496 decl
= description
->decls
[i
];
8497 if (decl
->mode
== dm_unit
)
8499 if (DECL_UNIT (decl
)->excl_list
!= NULL
)
8501 fprintf (output_description_file
, "unit %s exlusion_set: ",
8502 DECL_UNIT (decl
)->name
);
8503 output_unit_set_el_list (DECL_UNIT (decl
)->excl_list
);
8504 fprintf (output_description_file
, "\n");
8506 if (DECL_UNIT (decl
)->presence_list
!= NULL
)
8508 fprintf (output_description_file
, "unit %s presence_set: ",
8509 DECL_UNIT (decl
)->name
);
8510 output_pattern_set_el_list (DECL_UNIT (decl
)->presence_list
);
8511 fprintf (output_description_file
, "\n");
8513 if (DECL_UNIT (decl
)->final_presence_list
!= NULL
)
8515 fprintf (output_description_file
, "unit %s final_presence_set: ",
8516 DECL_UNIT (decl
)->name
);
8517 output_pattern_set_el_list
8518 (DECL_UNIT (decl
)->final_presence_list
);
8519 fprintf (output_description_file
, "\n");
8521 if (DECL_UNIT (decl
)->absence_list
!= NULL
)
8523 fprintf (output_description_file
, "unit %s absence_set: ",
8524 DECL_UNIT (decl
)->name
);
8525 output_pattern_set_el_list (DECL_UNIT (decl
)->absence_list
);
8526 fprintf (output_description_file
, "\n");
8528 if (DECL_UNIT (decl
)->final_absence_list
!= NULL
)
8530 fprintf (output_description_file
, "unit %s final_absence_set: ",
8531 DECL_UNIT (decl
)->name
);
8532 output_pattern_set_el_list
8533 (DECL_UNIT (decl
)->final_absence_list
);
8534 fprintf (output_description_file
, "\n");
8538 fprintf (output_description_file
, "\n");
8539 for (i
= 0; i
< description
->decls_num
; i
++)
8541 decl
= description
->decls
[i
];
8542 if (decl
->mode
== dm_reserv
)
8544 fprintf (output_description_file
, "reservation %s: ",
8545 DECL_RESERV (decl
)->name
);
8546 output_regexp (DECL_RESERV (decl
)->regexp
);
8547 fprintf (output_description_file
, "\n");
8549 else if (decl
->mode
== dm_insn_reserv
&& decl
!= advance_cycle_insn_decl
)
8551 fprintf (output_description_file
, "insn reservation %s ",
8552 DECL_INSN_RESERV (decl
)->name
);
8553 print_rtl (output_description_file
,
8554 DECL_INSN_RESERV (decl
)->condexp
);
8555 fprintf (output_description_file
, ": ");
8556 output_regexp (DECL_INSN_RESERV (decl
)->regexp
);
8557 fprintf (output_description_file
, "\n");
8559 else if (decl
->mode
== dm_bypass
)
8560 fprintf (output_description_file
, "bypass %d %s %s\n",
8561 DECL_BYPASS (decl
)->latency
,
8562 DECL_BYPASS (decl
)->out_insn_name
,
8563 DECL_BYPASS (decl
)->in_insn_name
);
8565 fprintf (output_description_file
, "\n\f\n");
8568 /* The function outputs name of AUTOMATON. */
8570 output_automaton_name (FILE *f
, automaton_t automaton
)
8572 if (automaton
->corresponding_automaton_decl
== NULL
)
8573 fprintf (f
, "#%d", automaton
->automaton_order_num
);
8575 fprintf (f
, "`%s'", automaton
->corresponding_automaton_decl
->name
);
8578 /* Maximal length of line for pretty printing into description
8580 #define MAX_LINE_LENGTH 70
8582 /* The function outputs units name belonging to AUTOMATON. */
8584 output_automaton_units (automaton_t automaton
)
8588 int curr_line_length
;
8589 int there_is_an_automaton_unit
;
8592 fprintf (output_description_file
, "\n Corresponding units:\n");
8593 fprintf (output_description_file
, " ");
8594 curr_line_length
= 4;
8595 there_is_an_automaton_unit
= 0;
8596 for (i
= 0; i
< description
->decls_num
; i
++)
8598 decl
= description
->decls
[i
];
8599 if (decl
->mode
== dm_unit
8600 && (DECL_UNIT (decl
)->corresponding_automaton_num
8601 == automaton
->automaton_order_num
))
8603 there_is_an_automaton_unit
= 1;
8604 name
= DECL_UNIT (decl
)->name
;
8605 if (curr_line_length
+ strlen (name
) + 1 > MAX_LINE_LENGTH
)
8607 curr_line_length
= strlen (name
) + 4;
8608 fprintf (output_description_file
, "\n ");
8612 curr_line_length
+= strlen (name
) + 1;
8613 fprintf (output_description_file
, " ");
8615 fprintf (output_description_file
, "%s", name
);
8618 if (!there_is_an_automaton_unit
)
8619 fprintf (output_description_file
, "<None>");
8620 fprintf (output_description_file
, "\n\n");
8623 /* The following variable is used for forming array of all possible cpu unit
8624 reservations described by the current DFA state. */
8625 static VEC(reserv_sets_t
,heap
) *state_reservs
;
8627 /* The function forms `state_reservs' for STATE. */
8629 add_state_reservs (state_t state
)
8631 alt_state_t curr_alt_state
;
8633 if (state
->component_states
!= NULL
)
8634 for (curr_alt_state
= state
->component_states
;
8635 curr_alt_state
!= NULL
;
8636 curr_alt_state
= curr_alt_state
->next_sorted_alt_state
)
8637 add_state_reservs (curr_alt_state
->state
);
8639 VEC_safe_push (reserv_sets_t
,heap
, state_reservs
, state
->reservs
);
8642 /* The function outputs readable representation of all out arcs of
8645 output_state_arcs (state_t state
)
8649 const char *insn_name
;
8650 int curr_line_length
;
8652 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
8655 gcc_assert (ainsn
->first_insn_with_same_reservs
);
8656 fprintf (output_description_file
, " ");
8657 curr_line_length
= 7;
8658 fprintf (output_description_file
, "%2d: ", ainsn
->insn_equiv_class_num
);
8661 insn_name
= ainsn
->insn_reserv_decl
->name
;
8662 if (curr_line_length
+ strlen (insn_name
) > MAX_LINE_LENGTH
)
8664 if (ainsn
!= arc
->insn
)
8666 fprintf (output_description_file
, ",\n ");
8667 curr_line_length
= strlen (insn_name
) + 6;
8670 curr_line_length
+= strlen (insn_name
);
8674 curr_line_length
+= strlen (insn_name
);
8675 if (ainsn
!= arc
->insn
)
8677 curr_line_length
+= 2;
8678 fprintf (output_description_file
, ", ");
8681 fprintf (output_description_file
, "%s", insn_name
);
8682 ainsn
= ainsn
->next_same_reservs_insn
;
8684 while (ainsn
!= NULL
);
8685 fprintf (output_description_file
, " %d \n",
8686 arc
->to_state
->order_state_num
);
8688 fprintf (output_description_file
, "\n");
8691 /* The following function is used for sorting possible cpu unit
8692 reservation of a DFA state. */
8694 state_reservs_cmp (const void *reservs_ptr_1
, const void *reservs_ptr_2
)
8696 return reserv_sets_cmp (*(reserv_sets_t
*) reservs_ptr_1
,
8697 *(reserv_sets_t
*) reservs_ptr_2
);
8700 /* The following function is used for sorting possible cpu unit
8701 reservation of a DFA state. */
8703 remove_state_duplicate_reservs (void)
8707 for (i
= 1, j
= 0; i
< VEC_length (reserv_sets_t
, state_reservs
); i
++)
8708 if (reserv_sets_cmp (VEC_index (reserv_sets_t
, state_reservs
, j
),
8709 VEC_index (reserv_sets_t
, state_reservs
, i
)))
8712 VEC_replace (reserv_sets_t
, state_reservs
, j
,
8713 VEC_index (reserv_sets_t
, state_reservs
, i
));
8715 VEC_truncate (reserv_sets_t
, state_reservs
, j
+ 1);
8718 /* The following function output readable representation of DFA(s)
8719 state used for fast recognition of pipeline hazards. State is
8720 described by possible (current and scheduled) cpu unit
8723 output_state (state_t state
)
8729 fprintf (output_description_file
, " State #%d", state
->order_state_num
);
8730 fprintf (output_description_file
,
8731 state
->new_cycle_p
? " (new cycle)\n" : "\n");
8732 add_state_reservs (state
);
8733 qsort (VEC_address (reserv_sets_t
, state_reservs
),
8734 VEC_length (reserv_sets_t
, state_reservs
),
8735 sizeof (reserv_sets_t
), state_reservs_cmp
);
8736 remove_state_duplicate_reservs ();
8737 for (i
= 1; i
< VEC_length (reserv_sets_t
, state_reservs
); i
++)
8739 fprintf (output_description_file
, " ");
8740 output_reserv_sets (output_description_file
,
8741 VEC_index (reserv_sets_t
, state_reservs
, i
));
8742 fprintf (output_description_file
, "\n");
8744 fprintf (output_description_file
, "\n");
8745 output_state_arcs (state
);
8746 VEC_free (reserv_sets_t
,heap
, state_reservs
);
8749 /* The following function output readable representation of
8750 DFAs used for fast recognition of pipeline hazards. */
8752 output_automaton_descriptions (void)
8754 automaton_t automaton
;
8756 for (automaton
= description
->first_automaton
;
8758 automaton
= automaton
->next_automaton
)
8760 fprintf (output_description_file
, "\nAutomaton ");
8761 output_automaton_name (output_description_file
, automaton
);
8762 fprintf (output_description_file
, "\n");
8763 output_automaton_units (automaton
);
8764 pass_states (automaton
, output_state
);
8770 /* The page contains top level function for generation DFA(s) used for
8773 /* The function outputs statistics about work of different phases of
8776 output_statistics (FILE *f
)
8778 automaton_t automaton
;
8781 int transition_comb_vect_els
= 0;
8782 int transition_full_vect_els
= 0;
8783 int min_issue_delay_vect_els
= 0;
8784 int locked_states
= 0;
8787 for (automaton
= description
->first_automaton
;
8789 automaton
= automaton
->next_automaton
)
8791 fprintf (f
, "\nAutomaton ");
8792 output_automaton_name (f
, automaton
);
8793 fprintf (f
, "\n %5d NDFA states, %5d NDFA arcs\n",
8794 automaton
->NDFA_states_num
, automaton
->NDFA_arcs_num
);
8795 fprintf (f
, " %5d DFA states, %5d DFA arcs\n",
8796 automaton
->DFA_states_num
, automaton
->DFA_arcs_num
);
8797 states_num
= automaton
->DFA_states_num
;
8798 if (!no_minimization_flag
)
8800 fprintf (f
, " %5d minimal DFA states, %5d minimal DFA arcs\n",
8801 automaton
->minimal_DFA_states_num
,
8802 automaton
->minimal_DFA_arcs_num
);
8803 states_num
= automaton
->minimal_DFA_states_num
;
8805 fprintf (f
, " %5d all insns %5d insn equivalence classes\n",
8806 description
->insns_num
, automaton
->insn_equiv_classes_num
);
8807 fprintf (f
, " %d locked states\n", automaton
->locked_states
);
8810 (f
, "%5ld transition comb vector els, %5ld trans table els: %s\n",
8811 (long) VEC_length (vect_el_t
, automaton
->trans_table
->comb_vect
),
8812 (long) VEC_length (vect_el_t
, automaton
->trans_table
->full_vect
),
8813 (comb_vect_p (automaton
->trans_table
)
8814 ? "use comb vect" : "use simple vect"));
8816 (f
, "%5ld min delay table els, compression factor %d\n",
8817 (long) states_num
* automaton
->insn_equiv_classes_num
,
8818 automaton
->min_issue_delay_table_compression_factor
);
8819 transition_comb_vect_els
8820 += VEC_length (vect_el_t
, automaton
->trans_table
->comb_vect
);
8821 transition_full_vect_els
8822 += VEC_length (vect_el_t
, automaton
->trans_table
->full_vect
);
8823 min_issue_delay_vect_els
8824 += states_num
* automaton
->insn_equiv_classes_num
;
8826 += automaton
->locked_states
;
8830 fprintf (f
, "\n%5d all allocated states, %5d all allocated arcs\n",
8831 allocated_states_num
, allocated_arcs_num
);
8832 fprintf (f
, "%5d all allocated alternative states\n",
8833 allocated_alt_states_num
);
8834 fprintf (f
, "%5d all transition comb vector els, %5d all trans table els\n",
8835 transition_comb_vect_els
, transition_full_vect_els
);
8836 fprintf (f
, "%5d all min delay table els\n", min_issue_delay_vect_els
);
8837 fprintf (f
, "%5d all locked states\n", locked_states
);
8841 /* The function output times of work of different phases of DFA
8844 output_time_statistics (FILE *f
)
8846 fprintf (f
, "\n transformation: ");
8847 print_active_time (f
, transform_time
);
8848 fprintf (f
, (!ndfa_flag
? ", building DFA: " : ", building NDFA: "));
8849 print_active_time (f
, NDFA_time
);
8852 fprintf (f
, ", NDFA -> DFA: ");
8853 print_active_time (f
, NDFA_to_DFA_time
);
8855 fprintf (f
, "\n DFA minimization: ");
8856 print_active_time (f
, minimize_time
);
8857 fprintf (f
, ", making insn equivalence: ");
8858 print_active_time (f
, equiv_time
);
8859 fprintf (f
, "\n all automaton generation: ");
8860 print_active_time (f
, automaton_generation_time
);
8861 fprintf (f
, ", output: ");
8862 print_active_time (f
, output_time
);
8866 /* The function generates DFA (deterministic finite state automaton)
8867 for fast recognition of pipeline hazards. No errors during
8868 checking must be fixed before this function call. */
8872 automata_num
= split_argument
;
8873 if (description
->units_num
< automata_num
)
8874 automata_num
= description
->units_num
;
8877 initiate_automata_lists ();
8878 initiate_pass_states ();
8879 initiate_excl_sets ();
8880 initiate_presence_absence_pattern_sets ();
8881 automaton_generation_time
= create_ticker ();
8883 ticker_off (&automaton_generation_time
);
8888 /* This page mainly contains top level functions of pipeline hazards
8889 description translator. */
8891 /* The following macro value is suffix of name of description file of
8892 pipeline hazards description translator. */
8893 #define STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX ".dfa"
8895 /* The function returns suffix of given file name. The returned
8896 string can not be changed. */
8898 file_name_suffix (const char *file_name
)
8900 const char *last_period
;
8902 for (last_period
= NULL
; *file_name
!= '\0'; file_name
++)
8903 if (*file_name
== '.')
8904 last_period
= file_name
;
8905 return (last_period
== NULL
? file_name
: last_period
);
8908 /* The function returns base name of given file name, i.e. pointer to
8909 first char after last `/' (or `\' for WIN32) in given file name,
8910 given file name itself if the directory name is absent. The
8911 returned string can not be changed. */
8913 base_file_name (const char *file_name
)
8915 int directory_name_length
;
8917 directory_name_length
= strlen (file_name
);
8919 while (directory_name_length
>= 0 && file_name
[directory_name_length
] != '/'
8920 && file_name
[directory_name_length
] != '\\')
8922 while (directory_name_length
>= 0 && file_name
[directory_name_length
] != '/')
8924 directory_name_length
--;
8925 return file_name
+ directory_name_length
+ 1;
8928 /* The following is top level function to initialize the work of
8929 pipeline hazards description translator. */
8931 initiate_automaton_gen (int argc
, char **argv
)
8933 const char *base_name
;
8937 split_argument
= 0; /* default value */
8938 no_minimization_flag
= 0;
8943 for (i
= 2; i
< argc
; i
++)
8944 if (strcmp (argv
[i
], NO_MINIMIZATION_OPTION
) == 0)
8945 no_minimization_flag
= 1;
8946 else if (strcmp (argv
[i
], TIME_OPTION
) == 0)
8948 else if (strcmp (argv
[i
], V_OPTION
) == 0)
8950 else if (strcmp (argv
[i
], W_OPTION
) == 0)
8952 else if (strcmp (argv
[i
], NDFA_OPTION
) == 0)
8954 else if (strcmp (argv
[i
], PROGRESS_OPTION
) == 0)
8956 else if (strcmp (argv
[i
], "-split") == 0)
8959 fatal ("-split has no argument.");
8960 fatal ("option `-split' has not been implemented yet\n");
8961 /* split_argument = atoi (argument_vect [i + 1]); */
8964 /* Initialize IR storage. */
8965 obstack_init (&irp
);
8966 initiate_automaton_decl_table ();
8967 initiate_insn_decl_table ();
8968 initiate_decl_table ();
8969 output_file
= stdout
;
8970 output_description_file
= NULL
;
8971 base_name
= base_file_name (argv
[1]);
8972 obstack_grow (&irp
, base_name
,
8973 strlen (base_name
) - strlen (file_name_suffix (base_name
)));
8974 obstack_grow (&irp
, STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX
,
8975 strlen (STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX
) + 1);
8976 obstack_1grow (&irp
, '\0');
8977 output_description_file_name
= obstack_base (&irp
);
8978 obstack_finish (&irp
);
8981 /* The following function checks existence at least one arc marked by
8984 check_automata_insn_issues (void)
8986 automaton_t automaton
;
8987 ainsn_t ainsn
, reserv_ainsn
;
8989 for (automaton
= description
->first_automaton
;
8991 automaton
= automaton
->next_automaton
)
8993 for (ainsn
= automaton
->ainsn_list
;
8995 ainsn
= ainsn
->next_ainsn
)
8996 if (ainsn
->first_insn_with_same_reservs
&& !ainsn
->arc_exists_p
)
8998 for (reserv_ainsn
= ainsn
;
8999 reserv_ainsn
!= NULL
;
9000 reserv_ainsn
= reserv_ainsn
->next_same_reservs_insn
)
9001 if (automaton
->corresponding_automaton_decl
!= NULL
)
9004 error ("Automaton `%s': Insn `%s' will never be issued",
9005 automaton
->corresponding_automaton_decl
->name
,
9006 reserv_ainsn
->insn_reserv_decl
->name
);
9009 (0, "Automaton `%s': Insn `%s' will never be issued",
9010 automaton
->corresponding_automaton_decl
->name
,
9011 reserv_ainsn
->insn_reserv_decl
->name
);
9016 error ("Insn `%s' will never be issued",
9017 reserv_ainsn
->insn_reserv_decl
->name
);
9019 warning (0, "Insn `%s' will never be issued",
9020 reserv_ainsn
->insn_reserv_decl
->name
);
9026 /* The following vla is used for storing pointers to all achieved
9028 static VEC(state_t
,heap
) *automaton_states
;
9030 /* This function is called by function pass_states to add an achieved
9033 add_automaton_state (state_t state
)
9035 VEC_safe_push (state_t
,heap
, automaton_states
, state
);
9038 /* The following function forms list of important automata (whose
9039 states may be changed after the insn issue) for each insn. */
9041 form_important_insn_automata_lists (void)
9043 automaton_t automaton
;
9050 automaton_states
= 0;
9051 /* Mark important ainsns. */
9052 for (automaton
= description
->first_automaton
;
9054 automaton
= automaton
->next_automaton
)
9056 VEC_truncate (state_t
, automaton_states
, 0);
9057 pass_states (automaton
, add_automaton_state
);
9058 for (n
= 0; n
< VEC_length (state_t
, automaton_states
); n
++)
9060 state_t s
= VEC_index (state_t
, automaton_states
, n
);
9061 for (arc
= first_out_arc (s
);
9063 arc
= next_out_arc (arc
))
9064 if (arc
->to_state
!= s
)
9066 gcc_assert (arc
->insn
->first_insn_with_same_reservs
);
9067 for (ainsn
= arc
->insn
;
9069 ainsn
= ainsn
->next_same_reservs_insn
)
9070 ainsn
->important_p
= TRUE
;
9074 VEC_free (state_t
,heap
, automaton_states
);
9076 /* Create automata sets for the insns. */
9077 for (i
= 0; i
< description
->decls_num
; i
++)
9079 decl
= description
->decls
[i
];
9080 if (decl
->mode
== dm_insn_reserv
)
9082 automata_list_start ();
9083 for (automaton
= description
->first_automaton
;
9085 automaton
= automaton
->next_automaton
)
9086 for (ainsn
= automaton
->ainsn_list
;
9088 ainsn
= ainsn
->next_ainsn
)
9089 if (ainsn
->important_p
9090 && ainsn
->insn_reserv_decl
== DECL_INSN_RESERV (decl
))
9092 automata_list_add (automaton
);
9095 DECL_INSN_RESERV (decl
)->important_automata_list
9096 = automata_list_finish ();
9102 /* The following is top level function to generate automat(a,on) for
9103 fast recognition of pipeline hazards. */
9105 expand_automata (void)
9109 description
= create_node (sizeof (struct description
)
9110 /* One entry for cycle advancing insn. */
9111 + sizeof (decl_t
) * VEC_length (decl_t
, decls
));
9112 description
->decls_num
= VEC_length (decl_t
, decls
);
9113 description
->query_units_num
= 0;
9114 for (i
= 0; i
< description
->decls_num
; i
++)
9116 description
->decls
[i
] = VEC_index (decl_t
, decls
, i
);
9117 if (description
->decls
[i
]->mode
== dm_unit
9118 && DECL_UNIT (description
->decls
[i
])->query_p
)
9119 DECL_UNIT (description
->decls
[i
])->query_num
9120 = description
->query_units_num
++;
9122 all_time
= create_ticker ();
9123 check_time
= create_ticker ();
9125 fprintf (stderr
, "Check description...");
9126 check_all_description ();
9128 fprintf (stderr
, "done\n");
9129 ticker_off (&check_time
);
9130 generation_time
= create_ticker ();
9133 transform_insn_regexps ();
9134 check_unit_distributions_to_automata ();
9139 check_automata_insn_issues ();
9143 form_important_insn_automata_lists ();
9145 ticker_off (&generation_time
);
9148 /* The following is top level function to output PHR and to finish
9149 work with pipeline description translator. */
9151 write_automata (void)
9153 output_time
= create_ticker ();
9155 fprintf (stderr
, "Forming and outputting automata tables...");
9159 fprintf (stderr
, "done\n");
9160 fprintf (stderr
, "Output functions to work with automata...");
9162 output_chip_definitions ();
9163 output_max_insn_queue_index_def ();
9164 output_internal_min_issue_delay_func ();
9165 output_internal_trans_func ();
9166 /* Cache of insn dfa codes: */
9167 fprintf (output_file
, "\nstatic int *%s;\n", DFA_INSN_CODES_VARIABLE_NAME
);
9168 fprintf (output_file
, "\nstatic int %s;\n\n",
9169 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
);
9170 output_dfa_insn_code_func ();
9171 output_trans_func ();
9172 output_min_issue_delay_func ();
9173 output_internal_dead_lock_func ();
9174 output_dead_lock_func ();
9175 output_size_func ();
9176 output_internal_reset_func ();
9177 output_reset_func ();
9178 output_min_insn_conflict_delay_func ();
9179 output_internal_insn_latency_func ();
9180 output_insn_latency_func ();
9181 output_print_reservation_func ();
9182 /* Output function get_cpu_unit_code. */
9183 fprintf (output_file
, "\n#if %s\n\n", CPU_UNITS_QUERY_MACRO_NAME
);
9184 output_get_cpu_unit_code_func ();
9185 output_cpu_unit_reservation_p ();
9186 fprintf (output_file
, "\n#endif /* #if %s */\n\n",
9187 CPU_UNITS_QUERY_MACRO_NAME
);
9188 output_dfa_clean_insn_cache_func ();
9189 output_dfa_start_func ();
9190 output_dfa_finish_func ();
9192 fprintf (stderr
, "done\n");
9195 output_description_file
= fopen (output_description_file_name
, "w");
9196 if (output_description_file
== NULL
)
9198 perror (output_description_file_name
);
9199 exit (FATAL_EXIT_CODE
);
9202 fprintf (stderr
, "Output automata description...");
9203 output_description ();
9204 output_automaton_descriptions ();
9206 fprintf (stderr
, "done\n");
9207 output_statistics (output_description_file
);
9209 output_statistics (stderr
);
9210 ticker_off (&output_time
);
9211 output_time_statistics (stderr
);
9214 finish_automata_lists ();
9217 fprintf (stderr
, "Summary:\n");
9218 fprintf (stderr
, " check time ");
9219 print_active_time (stderr
, check_time
);
9220 fprintf (stderr
, ", generation time ");
9221 print_active_time (stderr
, generation_time
);
9222 fprintf (stderr
, ", all time ");
9223 print_active_time (stderr
, all_time
);
9224 fprintf (stderr
, "\n");
9226 /* Finish all work. */
9227 if (output_description_file
!= NULL
)
9229 fflush (output_description_file
);
9230 if (ferror (stdout
) != 0)
9231 fatal ("Error in writing DFA description file %s",
9232 output_description_file_name
);
9233 fclose (output_description_file
);
9235 finish_automaton_decl_table ();
9236 finish_insn_decl_table ();
9237 finish_decl_table ();
9238 obstack_free (&irp
, NULL
);
9239 if (have_error
&& output_description_file
!= NULL
)
9240 remove (output_description_file_name
);
9244 main (int argc
, char **argv
)
9248 progname
= "genautomata";
9250 if (init_md_reader_args (argc
, argv
) != SUCCESS_EXIT_CODE
)
9251 return (FATAL_EXIT_CODE
);
9253 initiate_automaton_gen (argc
, argv
);
9257 int insn_code_number
;
9259 desc
= read_md_rtx (&lineno
, &insn_code_number
);
9263 switch (GET_CODE (desc
))
9265 case DEFINE_CPU_UNIT
:
9266 gen_cpu_unit (desc
);
9269 case DEFINE_QUERY_CPU_UNIT
:
9270 gen_query_cpu_unit (desc
);
9278 gen_excl_set (desc
);
9282 gen_presence_set (desc
);
9285 case FINAL_PRESENCE_SET
:
9286 gen_final_presence_set (desc
);
9290 gen_absence_set (desc
);
9293 case FINAL_ABSENCE_SET
:
9294 gen_final_absence_set (desc
);
9297 case DEFINE_AUTOMATON
:
9298 gen_automaton (desc
);
9301 case AUTOMATA_OPTION
:
9302 gen_automata_option (desc
);
9305 case DEFINE_RESERVATION
:
9309 case DEFINE_INSN_RESERVATION
:
9310 gen_insn_reserv (desc
);
9319 return FATAL_EXIT_CODE
;
9321 puts ("/* Generated automatically by the program `genautomata'\n"
9322 " from the machine description file `md'. */\n\n"
9323 "#include \"config.h\"\n"
9324 "#include \"system.h\"\n"
9325 "#include \"coretypes.h\"\n"
9326 "#include \"tm.h\"\n"
9327 "#include \"rtl.h\"\n"
9328 "#include \"tm_p.h\"\n"
9329 "#include \"insn-config.h\"\n"
9330 "#include \"recog.h\"\n"
9331 "#include \"regs.h\"\n"
9332 "#include \"real.h\"\n"
9333 "#include \"output.h\"\n"
9334 "#include \"insn-attr.h\"\n"
9335 "#include \"toplev.h\"\n"
9336 "#include \"flags.h\"\n"
9337 "#include \"function.h\"\n");
9339 if (VEC_length (decl_t
, decls
) > 0)
9346 return (ferror (stdout
) != 0 ? FATAL_EXIT_CODE
: SUCCESS_EXIT_CODE
);