1 /* Pipeline hazard description translator.
2 Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007
3 Free Software Foundation, Inc.
5 Written by Vladimir Makarov <vmakarov@redhat.com>
7 This file is part of GCC.
9 GCC is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by the
11 Free Software Foundation; either version 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"
241 #define TIME_OPTION "-time"
242 #define STATS_OPTION "-stats"
243 #define V_OPTION "-v"
244 #define W_OPTION "-w"
245 #define NDFA_OPTION "-ndfa"
246 #define PROGRESS_OPTION "-progress"
248 /* The following flags are set up by function `initiate_automaton_gen'. */
250 /* Make automata with nondeterministic reservation by insns (`-ndfa'). */
251 static int ndfa_flag
;
253 /* Do not make minimization of DFA (`-no-minimization'). */
254 static int no_minimization_flag
;
256 /* Value of this variable is number of automata being generated. The
257 actual number of automata may be less this value if there is not
258 sufficient number of units. This value is defined by argument of
259 option `-split' or by constructions automaton if the value is zero
260 (it is default value of the argument). */
261 static int split_argument
;
263 /* Flag of output time statistics (`-time'). */
264 static int time_flag
;
266 /* Flag of automata statistics (`-stats'). */
267 static int stats_flag
;
269 /* Flag of creation of description file which contains description of
270 result automaton and statistics information (`-v'). */
273 /* Flag of output of a progress bar showing how many states were
274 generated so far for automaton being processed (`-progress'). */
275 static int progress_flag
;
277 /* Flag of generating warning instead of error for non-critical errors
282 /* Output file for pipeline hazard recognizer (PHR) being generated.
283 The value is NULL if the file is not defined. */
284 static FILE *output_file
;
286 /* Description file of PHR. The value is NULL if the file is not
288 static FILE *output_description_file
;
290 /* PHR description file name. */
291 static char *output_description_file_name
;
293 /* Value of the following variable is node representing description
294 being processed. This is start point of IR. */
295 static struct description
*description
;
299 /* This page contains description of IR structure (nodes). */
313 /* This describes define_cpu_unit and define_query_cpu_unit (see file
318 /* NULL if the automaton name is absent. */
319 const char *automaton_name
;
320 /* If the following value is not zero, the cpu unit reservation is
321 described in define_query_cpu_unit. */
324 /* The following fields are defined by checker. */
326 /* The following field value is nonzero if the unit is used in an
330 /* The following field value is order number (0, 1, ...) of given
333 /* The following field value is corresponding declaration of
334 automaton which was given in description. If the field value is
335 NULL then automaton in the unit declaration was absent. */
336 struct automaton_decl
*automaton_decl
;
337 /* The following field value is maximal cycle number (1, ...) on
338 which given unit occurs in insns. Zero value means that given
339 unit is not used in insns. */
340 int max_occ_cycle_num
;
341 /* The following field value is minimal cycle number (0, ...) on
342 which given unit occurs in insns. -1 value means that given
343 unit is not used in insns. */
344 int min_occ_cycle_num
;
345 /* The following list contains units which conflict with given
347 unit_set_el_t excl_list
;
348 /* The following list contains patterns which are required to
349 reservation of given unit. */
350 pattern_set_el_t presence_list
;
351 pattern_set_el_t final_presence_list
;
352 /* The following list contains patterns which should be not present
353 in reservation for given unit. */
354 pattern_set_el_t absence_list
;
355 pattern_set_el_t final_absence_list
;
356 /* The following is used only when `query_p' has nonzero value.
357 This is query number for the unit. */
359 /* The following is the last cycle on which the unit was checked for
360 correct distributions of units to automata in a regexp. */
361 int last_distribution_check_cycle
;
363 /* The following fields are defined by automaton generator. */
365 /* The following field value is number of the automaton to which
366 given unit belongs. */
367 int corresponding_automaton_num
;
368 /* If the following value is not zero, the cpu unit is present in a
369 `exclusion_set' or in right part of a `presence_set',
370 `final_presence_set', `absence_set', and
371 `final_absence_set'define_query_cpu_unit. */
375 /* This describes define_bypass (see file rtl.def). */
379 const char *out_insn_name
;
380 const char *in_insn_name
;
381 const char *bypass_guard_name
;
383 /* The following fields are defined by checker. */
385 /* output and input insns of given bypass. */
386 struct insn_reserv_decl
*out_insn_reserv
;
387 struct insn_reserv_decl
*in_insn_reserv
;
388 /* The next bypass for given output insn. */
389 struct bypass_decl
*next
;
392 /* This describes define_automaton (see file rtl.def). */
393 struct automaton_decl
397 /* The following fields are defined by automaton generator. */
399 /* The following field value is nonzero if the automaton is used in
400 an regexp definition. */
401 char automaton_is_used
;
403 /* The following fields are defined by checker. */
405 /* The following field value is the corresponding automaton. This
406 field is not NULL only if the automaton is present in unit
407 declarations and the automatic partition on automata is not
409 automaton_t corresponding_automaton
;
412 /* This describes exclusion relations: exclusion_set (see file
417 int first_list_length
;
421 /* This describes unit relations: [final_]presence_set or
422 [final_]absence_set (see file rtl.def). */
423 struct unit_pattern_rel_decl
432 /* This describes define_reservation (see file rtl.def). */
438 /* The following fields are defined by checker. */
440 /* The following field value is nonzero if the unit is used in an
443 /* The following field is used to check up cycle in expression
448 /* This describes define_insn_reservation (see file rtl.def). */
449 struct insn_reserv_decl
456 /* The following fields are defined by checker. */
458 /* The following field value is order number (0, 1, ...) of given
461 /* The following field value is list of bypasses in which given insn
463 struct bypass_decl
*bypass_list
;
465 /* The following fields are defined by automaton generator. */
467 /* The following field is the insn regexp transformed that
468 the regexp has not optional regexp, repetition regexp, and an
469 reservation name (i.e. reservation identifiers are changed by the
470 corresponding regexp) and all alternations are the topest level
471 of the regexp. The value can be NULL only if it is special
472 insn `cycle advancing'. */
473 regexp_t transformed_regexp
;
474 /* The following field value is list of arcs marked given
475 insn. The field is used in transformation NDFA -> DFA. */
476 arc_t arcs_marked_by_insn
;
477 /* The two following fields are used during minimization of a finite state
479 /* The field value is number of equivalence class of state into
480 which arc marked by given insn enters from a state (fixed during
481 an automaton minimization). */
483 /* The following member value is the list to automata which can be
484 changed by the insn issue. */
485 automata_list_el_t important_automata_list
;
486 /* The following member is used to process insn once for output. */
490 /* This contains a declaration mentioned above. */
493 /* What node in the union? */
498 struct unit_decl unit
;
499 struct bypass_decl bypass
;
500 struct automaton_decl automaton
;
501 struct excl_rel_decl excl
;
502 struct unit_pattern_rel_decl presence
;
503 struct unit_pattern_rel_decl absence
;
504 struct reserv_decl reserv
;
505 struct insn_reserv_decl insn_reserv
;
509 /* The following structures represent parsed reservation strings. */
521 /* Cpu unit in reservation. */
525 unit_decl_t unit_decl
;
528 /* Define_reservation in a reservation. */
532 struct reserv_decl
*reserv_decl
;
535 /* Absence of reservation (represented by string `nothing'). */
536 struct nothing_regexp
538 /* This used to be empty but ISO C doesn't allow that. */
542 /* Representation of reservations separated by ',' (see file
544 struct sequence_regexp
547 regexp_t regexps
[1];
550 /* Representation of construction `repeat' (see file rtl.def). */
557 /* Representation of reservations separated by '+' (see file
562 regexp_t regexps
[1];
565 /* Representation of reservations separated by '|' (see file
570 regexp_t regexps
[1];
573 /* Representation of a reservation string. */
576 /* What node in the union? */
577 enum regexp_mode mode
;
581 struct unit_regexp unit
;
582 struct reserv_regexp reserv
;
583 struct nothing_regexp nothing
;
584 struct sequence_regexp sequence
;
585 struct repeat_regexp repeat
;
586 struct allof_regexp allof
;
587 struct oneof_regexp oneof
;
591 /* Represents description of pipeline hazard description based on
597 /* The following fields are defined by checker. */
599 /* The following fields values are correspondingly number of all
600 units, query units, and insns in the description. */
604 /* The following field value is max length (in cycles) of
605 reservations of insns. The field value is defined only for
607 int max_insn_reserv_cycles
;
609 /* The following fields are defined by automaton generator. */
611 /* The following field value is the first automaton. */
612 automaton_t first_automaton
;
614 /* The following field is created by pipeline hazard parser and
615 contains all declarations. We allocate additional entry for
616 special insn "cycle advancing" which is added by the automaton
622 /* The following nodes are created in automaton checker. */
624 /* The following nodes represent exclusion set for cpu units. Each
625 element is accessed through only one excl_list. */
628 unit_decl_t unit_decl
;
629 unit_set_el_t next_unit_set_el
;
632 /* The following nodes represent presence or absence pattern for cpu
633 units. Each element is accessed through only one presence_list or
635 struct pattern_set_el
637 /* The number of units in unit_decls. */
639 /* The units forming the pattern. */
640 struct unit_decl
**unit_decls
;
641 pattern_set_el_t next_pattern_set_el
;
645 /* The following nodes are created in automaton generator. */
648 /* The following nodes represent presence or absence pattern for cpu
649 units. Each element is accessed through only one element of
650 unit_presence_set_table or unit_absence_set_table. */
651 struct pattern_reserv
653 reserv_sets_t reserv
;
654 pattern_reserv_t next_pattern_reserv
;
657 /* The following node type describes state automaton. The state may
658 be deterministic or non-deterministic. Non-deterministic state has
659 several component states which represent alternative cpu units
660 reservations. The state also is used for describing a
661 deterministic reservation of automaton insn. */
664 /* The following member value is nonzero if there is a transition by
667 /* The following field is list of processor unit reservations on
669 reserv_sets_t reservs
;
670 /* The following field is unique number of given state between other
673 /* The following field value is automaton to which given state
675 automaton_t automaton
;
676 /* The following field value is the first arc output from given
679 unsigned int num_out_arcs
;
680 /* The following field is used to form NDFA. */
681 char it_was_placed_in_stack_for_NDFA_forming
;
682 /* The following field is used to form DFA. */
683 char it_was_placed_in_stack_for_DFA_forming
;
684 /* The following field is used to transform NDFA to DFA and DFA
685 minimization. The field value is not NULL if the state is a
686 compound state. In this case the value of field `unit_sets_list'
687 is NULL. All states in the list are in the hash table. The list
688 is formed through field `next_sorted_alt_state'. We should
689 support only one level of nesting state. */
690 alt_state_t component_states
;
691 /* The following field is used for passing graph of states. */
693 /* The list of states belonging to one equivalence class is formed
694 with the aid of the following field. */
695 state_t next_equiv_class_state
;
696 /* The two following fields are used during minimization of a finite
698 int equiv_class_num_1
, equiv_class_num_2
;
699 /* The following field is used during minimization of a finite state
700 automaton. The field value is state corresponding to equivalence
701 class to which given state belongs. */
702 state_t equiv_class_state
;
703 unsigned int *presence_signature
;
704 /* The following field value is the order number of given state.
705 The states in final DFA is enumerated with the aid of the
708 /* This member is used for passing states for searching minimal
711 /* The following member is used to evaluate min issue delay of insn
713 int min_insn_issue_delay
;
719 /* The following field refers for the state into which given arc
722 /* The following field describes that the insn issue (with cycle
723 advancing for special insn `cycle advancing' and without cycle
724 advancing for others) makes transition from given state to
725 another given state. */
727 /* The following field value is the next arc output from the same
730 /* List of arcs marked given insn is formed with the following
731 field. The field is used in transformation NDFA -> DFA. */
732 arc_t next_arc_marked_by_insn
;
735 /* The following node type describes a deterministic alternative in
736 non-deterministic state which characterizes cpu unit reservations
737 of automaton insn or which is part of NDFA. */
740 /* The following field is a deterministic state which characterizes
741 unit reservations of the instruction. */
743 /* The following field refers to the next state which characterizes
744 unit reservations of the instruction. */
745 alt_state_t next_alt_state
;
746 /* The following field refers to the next state in sorted list. */
747 alt_state_t next_sorted_alt_state
;
750 /* The following node type describes insn of automaton. They are
751 labels of FA arcs. */
754 /* The following field value is the corresponding insn declaration
756 struct insn_reserv_decl
*insn_reserv_decl
;
757 /* The following field value is the next insn declaration for an
760 /* The following field is states which characterize automaton unit
761 reservations of the instruction. The value can be NULL only if it
762 is special insn `cycle advancing'. */
763 alt_state_t alt_states
;
764 /* The following field is sorted list of states which characterize
765 automaton unit reservations of the instruction. The value can be
766 NULL only if it is special insn `cycle advancing'. */
767 alt_state_t sorted_alt_states
;
768 /* The following field refers the next automaton insn with
769 the same reservations. */
770 ainsn_t next_same_reservs_insn
;
771 /* The following field is flag of the first automaton insn with the
772 same reservations in the declaration list. Only arcs marked such
773 insn is present in the automaton. This significantly decreases
774 memory requirements especially when several automata are
776 char first_insn_with_same_reservs
;
777 /* The following member has nonzero value if there is arc from state of
778 the automaton marked by the ainsn. */
780 /* Cyclic list of insns of an equivalence class is formed with the
781 aid of the following field. */
782 ainsn_t next_equiv_class_insn
;
783 /* The following field value is nonzero if the insn declaration is
784 the first insn declaration with given equivalence number. */
785 char first_ainsn_with_given_equivalence_num
;
786 /* The following field is number of class of equivalence of insns.
787 It is necessary because many insns may be equivalent with the
788 point of view of pipeline hazards. */
789 int insn_equiv_class_num
;
790 /* The following member value is TRUE if there is an arc in the
791 automaton marked by the insn into another state. In other
792 words, the insn can change the state of the automaton. */
796 /* The following describes an automaton for PHR. */
799 /* The following field value is the list of insn declarations for
802 /* The following field value is the corresponding automaton
803 declaration. This field is not NULL only if the automatic
804 partition on automata is not used. */
805 struct automaton_decl
*corresponding_automaton_decl
;
806 /* The following field value is the next automaton. */
807 automaton_t next_automaton
;
808 /* The following field is start state of FA. There are not unit
809 reservations in the state. */
811 /* The following field value is number of equivalence classes of
812 insns (see field `insn_equiv_class_num' in
813 `insn_reserv_decl'). */
814 int insn_equiv_classes_num
;
815 /* The following field value is number of states of final DFA. */
816 int achieved_states_num
;
817 /* The following field value is the order number (0, 1, ...) of
819 int automaton_order_num
;
820 /* The following fields contain statistics information about
821 building automaton. */
822 int NDFA_states_num
, DFA_states_num
;
823 /* The following field value is defined only if minimization of DFA
825 int minimal_DFA_states_num
;
826 int NDFA_arcs_num
, DFA_arcs_num
;
827 /* The following field value is defined only if minimization of DFA
829 int minimal_DFA_arcs_num
;
830 /* The following member refers for two table state x ainsn -> int.
831 ??? Above sentence is incomprehensible. */
832 state_ainsn_table_t trans_table
;
833 /* The following member value is maximal value of min issue delay
834 for insns of the automaton. */
836 /* Usually min issue delay is small and we can place several (2, 4,
837 8) elements in one vector element. So the compression factor can
838 be 1 (no compression), 2, 4, 8. */
839 int min_issue_delay_table_compression_factor
;
840 /* Total number of locked states in this automaton. */
844 /* The following is the element of the list of automata. */
845 struct automata_list_el
847 /* The automaton itself. */
848 automaton_t automaton
;
849 /* The next automata set element. */
850 automata_list_el_t next_automata_list_el
;
853 /* The following structure describes a table state X ainsn -> int(>= 0). */
854 struct state_ainsn_table
856 /* Automaton to which given table belongs. */
857 automaton_t automaton
;
858 /* The following tree vectors for comb vector implementation of the
860 vla_hwint_t comb_vect
;
861 vla_hwint_t check_vect
;
862 vla_hwint_t base_vect
;
863 /* This is simple implementation of the table. */
864 vla_hwint_t full_vect
;
865 /* Minimal and maximal values of the previous vectors. */
866 int min_comb_vect_el_value
, max_comb_vect_el_value
;
867 int min_base_vect_el_value
, max_base_vect_el_value
;
870 /* Macros to access members of unions. Use only them for access to
871 union members of declarations and regexps. */
873 #if defined ENABLE_CHECKING && (GCC_VERSION >= 2007)
875 #define DECL_UNIT(d) __extension__ \
876 (({ struct decl *const _decl = (d); \
877 if (_decl->mode != dm_unit) \
878 decl_mode_check_failed (_decl->mode, "dm_unit", \
879 __FILE__, __LINE__, __FUNCTION__); \
880 &(_decl)->decl.unit; }))
882 #define DECL_BYPASS(d) __extension__ \
883 (({ struct decl *const _decl = (d); \
884 if (_decl->mode != dm_bypass) \
885 decl_mode_check_failed (_decl->mode, "dm_bypass", \
886 __FILE__, __LINE__, __FUNCTION__); \
887 &(_decl)->decl.bypass; }))
889 #define DECL_AUTOMATON(d) __extension__ \
890 (({ struct decl *const _decl = (d); \
891 if (_decl->mode != dm_automaton) \
892 decl_mode_check_failed (_decl->mode, "dm_automaton", \
893 __FILE__, __LINE__, __FUNCTION__); \
894 &(_decl)->decl.automaton; }))
896 #define DECL_EXCL(d) __extension__ \
897 (({ struct decl *const _decl = (d); \
898 if (_decl->mode != dm_excl) \
899 decl_mode_check_failed (_decl->mode, "dm_excl", \
900 __FILE__, __LINE__, __FUNCTION__); \
901 &(_decl)->decl.excl; }))
903 #define DECL_PRESENCE(d) __extension__ \
904 (({ struct decl *const _decl = (d); \
905 if (_decl->mode != dm_presence) \
906 decl_mode_check_failed (_decl->mode, "dm_presence", \
907 __FILE__, __LINE__, __FUNCTION__); \
908 &(_decl)->decl.presence; }))
910 #define DECL_ABSENCE(d) __extension__ \
911 (({ struct decl *const _decl = (d); \
912 if (_decl->mode != dm_absence) \
913 decl_mode_check_failed (_decl->mode, "dm_absence", \
914 __FILE__, __LINE__, __FUNCTION__); \
915 &(_decl)->decl.absence; }))
917 #define DECL_RESERV(d) __extension__ \
918 (({ struct decl *const _decl = (d); \
919 if (_decl->mode != dm_reserv) \
920 decl_mode_check_failed (_decl->mode, "dm_reserv", \
921 __FILE__, __LINE__, __FUNCTION__); \
922 &(_decl)->decl.reserv; }))
924 #define DECL_INSN_RESERV(d) __extension__ \
925 (({ struct decl *const _decl = (d); \
926 if (_decl->mode != dm_insn_reserv) \
927 decl_mode_check_failed (_decl->mode, "dm_insn_reserv", \
928 __FILE__, __LINE__, __FUNCTION__); \
929 &(_decl)->decl.insn_reserv; }))
931 static const char *decl_name (enum decl_mode
);
932 static void decl_mode_check_failed (enum decl_mode
, const char *,
933 const char *, int, const char *)
936 /* Return string representation of declaration mode MODE. */
938 decl_name (enum decl_mode mode
)
940 static char str
[100];
944 else if (mode
== dm_bypass
)
946 else if (mode
== dm_automaton
)
947 return "dm_automaton";
948 else if (mode
== dm_excl
)
950 else if (mode
== dm_presence
)
951 return "dm_presence";
952 else if (mode
== dm_absence
)
954 else if (mode
== dm_reserv
)
956 else if (mode
== dm_insn_reserv
)
957 return "dm_insn_reserv";
959 sprintf (str
, "unknown (%d)", (int) mode
);
963 /* The function prints message about unexpected declaration and finish
966 decl_mode_check_failed (enum decl_mode mode
, const char *expected_mode_str
,
967 const char *file
, int line
, const char *func
)
971 "\n%s: %d: error in %s: DECL check: expected decl %s, have %s\n",
972 file
, line
, func
, expected_mode_str
, decl_name (mode
));
977 #define REGEXP_UNIT(r) __extension__ \
978 (({ struct regexp *const _regexp = (r); \
979 if (_regexp->mode != rm_unit) \
980 regexp_mode_check_failed (_regexp->mode, "rm_unit", \
981 __FILE__, __LINE__, __FUNCTION__); \
982 &(_regexp)->regexp.unit; }))
984 #define REGEXP_RESERV(r) __extension__ \
985 (({ struct regexp *const _regexp = (r); \
986 if (_regexp->mode != rm_reserv) \
987 regexp_mode_check_failed (_regexp->mode, "rm_reserv", \
988 __FILE__, __LINE__, __FUNCTION__); \
989 &(_regexp)->regexp.reserv; }))
991 #define REGEXP_SEQUENCE(r) __extension__ \
992 (({ struct regexp *const _regexp = (r); \
993 if (_regexp->mode != rm_sequence) \
994 regexp_mode_check_failed (_regexp->mode, "rm_sequence", \
995 __FILE__, __LINE__, __FUNCTION__); \
996 &(_regexp)->regexp.sequence; }))
998 #define REGEXP_REPEAT(r) __extension__ \
999 (({ struct regexp *const _regexp = (r); \
1000 if (_regexp->mode != rm_repeat) \
1001 regexp_mode_check_failed (_regexp->mode, "rm_repeat", \
1002 __FILE__, __LINE__, __FUNCTION__); \
1003 &(_regexp)->regexp.repeat; }))
1005 #define REGEXP_ALLOF(r) __extension__ \
1006 (({ struct regexp *const _regexp = (r); \
1007 if (_regexp->mode != rm_allof) \
1008 regexp_mode_check_failed (_regexp->mode, "rm_allof", \
1009 __FILE__, __LINE__, __FUNCTION__); \
1010 &(_regexp)->regexp.allof; }))
1012 #define REGEXP_ONEOF(r) __extension__ \
1013 (({ struct regexp *const _regexp = (r); \
1014 if (_regexp->mode != rm_oneof) \
1015 regexp_mode_check_failed (_regexp->mode, "rm_oneof", \
1016 __FILE__, __LINE__, __FUNCTION__); \
1017 &(_regexp)->regexp.oneof; }))
1019 static const char *regexp_name (enum regexp_mode
);
1020 static void regexp_mode_check_failed (enum regexp_mode
, const char *,
1022 const char *) ATTRIBUTE_NORETURN
;
1025 /* Return string representation of regexp mode MODE. */
1027 regexp_name (enum regexp_mode mode
)
1036 return "rm_nothing";
1038 return "rm_sequence";
1050 /* The function prints message about unexpected regexp and finish the
1053 regexp_mode_check_failed (enum regexp_mode mode
,
1054 const char *expected_mode_str
,
1055 const char *file
, int line
, const char *func
)
1059 "\n%s: %d: error in %s: REGEXP check: expected decl %s, have %s\n",
1060 file
, line
, func
, expected_mode_str
, regexp_name (mode
));
1064 #else /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */
1066 #define DECL_UNIT(d) (&(d)->decl.unit)
1067 #define DECL_BYPASS(d) (&(d)->decl.bypass)
1068 #define DECL_AUTOMATON(d) (&(d)->decl.automaton)
1069 #define DECL_EXCL(d) (&(d)->decl.excl)
1070 #define DECL_PRESENCE(d) (&(d)->decl.presence)
1071 #define DECL_ABSENCE(d) (&(d)->decl.absence)
1072 #define DECL_RESERV(d) (&(d)->decl.reserv)
1073 #define DECL_INSN_RESERV(d) (&(d)->decl.insn_reserv)
1075 #define REGEXP_UNIT(r) (&(r)->regexp.unit)
1076 #define REGEXP_RESERV(r) (&(r)->regexp.reserv)
1077 #define REGEXP_SEQUENCE(r) (&(r)->regexp.sequence)
1078 #define REGEXP_REPEAT(r) (&(r)->regexp.repeat)
1079 #define REGEXP_ALLOF(r) (&(r)->regexp.allof)
1080 #define REGEXP_ONEOF(r) (&(r)->regexp.oneof)
1082 #endif /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */
1084 /* Create IR structure (node). */
1086 create_node (size_t size
)
1090 obstack_blank (&irp
, size
);
1091 result
= obstack_base (&irp
);
1092 obstack_finish (&irp
);
1093 /* Default values of members are NULL and zero. */
1094 memset (result
, 0, size
);
1098 /* Copy IR structure (node). */
1100 copy_node (const void *from
, size_t size
)
1102 void *const result
= create_node (size
);
1103 memcpy (result
, from
, size
);
1107 /* The function checks that NAME does not contain quotes (`"'). */
1109 check_name (const char * name
, pos_t pos ATTRIBUTE_UNUSED
)
1113 for (str
= name
; *str
!= '\0'; str
++)
1115 error ("Name `%s' contains quotes", name
);
1119 /* Pointers to all declarations during IR generation are stored in the
1121 static VEC(decl_t
,heap
) *decls
;
1123 /* Given a pointer to a (char *) and a separator, return an alloc'ed
1124 string containing the next separated element, taking parentheses
1125 into account if PAR_FLAG has nonzero value. Advance the pointer to
1126 after the string scanned, or the end-of-string. Return NULL if at
1129 next_sep_el (const char **pstr
, int sep
, int par_flag
)
1136 /* Remove leading whitespaces. */
1137 while (ISSPACE ((int) **pstr
))
1144 for (pars_num
= 0, p
= *pstr
; *p
!= '\0'; p
++)
1146 if (par_flag
&& *p
== '(')
1148 else if (par_flag
&& *p
== ')')
1150 else if (pars_num
== 0 && *p
== sep
)
1152 if (pars_num
== 0 && ISSPACE ((int) *p
))
1156 for (; n_spaces
!= 0; n_spaces
--)
1157 obstack_1grow (&irp
, p
[-n_spaces
]);
1158 obstack_1grow (&irp
, *p
);
1161 obstack_1grow (&irp
, '\0');
1162 out_str
= obstack_base (&irp
);
1163 obstack_finish (&irp
);
1172 /* Given a string and a separator, return the number of separated
1173 elements in it, taking parentheses into account if PAR_FLAG has
1174 nonzero value. Return 0 for the null string, -1 if parentheses is
1177 n_sep_els (const char *s
, int sep
, int par_flag
)
1185 for (pars_num
= 0, n
= 1; *s
; s
++)
1186 if (par_flag
&& *s
== '(')
1188 else if (par_flag
&& *s
== ')')
1190 else if (pars_num
== 0 && *s
== sep
)
1193 return (pars_num
!= 0 ? -1 : n
);
1196 /* Given a string and a separator, return vector of strings which are
1197 elements in the string and number of elements through els_num.
1198 Take parentheses into account if PAREN_P has nonzero value. The
1199 function also inserts the end marker NULL at the end of vector.
1200 Return 0 for the null string, -1 if parentheses are not balanced. */
1202 get_str_vect (const char *str
, int *els_num
, int sep
, int paren_p
)
1209 *els_num
= n_sep_els (str
, sep
, paren_p
);
1212 obstack_blank (&irp
, sizeof (char *) * (*els_num
+ 1));
1213 vect
= (char **) obstack_base (&irp
);
1214 obstack_finish (&irp
);
1216 for (i
= 0; i
< *els_num
; i
++)
1217 vect
[i
] = next_sep_el (pstr
, sep
, paren_p
);
1218 trail
= next_sep_el (pstr
, sep
, paren_p
);
1219 gcc_assert (!trail
);
1224 /* Process a DEFINE_CPU_UNIT.
1226 This gives information about a unit contained in CPU. We fill a
1227 struct unit_decl with information used later by `expand_automata'. */
1229 gen_cpu_unit (rtx def
)
1232 char **str_cpu_units
;
1236 str_cpu_units
= get_str_vect (XSTR (def
, 0), &vect_length
, ',', FALSE
);
1237 if (str_cpu_units
== NULL
)
1238 fatal ("invalid string `%s' in define_cpu_unit", XSTR (def
, 0));
1239 for (i
= 0; i
< vect_length
; i
++)
1241 decl
= create_node (sizeof (struct decl
));
1242 decl
->mode
= dm_unit
;
1244 DECL_UNIT (decl
)->name
= check_name (str_cpu_units
[i
], decl
->pos
);
1245 DECL_UNIT (decl
)->automaton_name
= XSTR (def
, 1);
1246 DECL_UNIT (decl
)->query_p
= 0;
1247 DECL_UNIT (decl
)->min_occ_cycle_num
= -1;
1248 DECL_UNIT (decl
)->in_set_p
= 0;
1249 VEC_safe_push (decl_t
,heap
, decls
, decl
);
1253 /* Process a DEFINE_QUERY_CPU_UNIT.
1255 This gives information about a unit contained in CPU. We fill a
1256 struct unit_decl with information used later by `expand_automata'. */
1258 gen_query_cpu_unit (rtx def
)
1261 char **str_cpu_units
;
1265 str_cpu_units
= get_str_vect (XSTR (def
, 0), &vect_length
, ',',
1267 if (str_cpu_units
== NULL
)
1268 fatal ("invalid string `%s' in define_query_cpu_unit", XSTR (def
, 0));
1269 for (i
= 0; i
< vect_length
; i
++)
1271 decl
= create_node (sizeof (struct decl
));
1272 decl
->mode
= dm_unit
;
1274 DECL_UNIT (decl
)->name
= check_name (str_cpu_units
[i
], decl
->pos
);
1275 DECL_UNIT (decl
)->automaton_name
= XSTR (def
, 1);
1276 DECL_UNIT (decl
)->query_p
= 1;
1277 VEC_safe_push (decl_t
,heap
, decls
, decl
);
1281 /* Process a DEFINE_BYPASS.
1283 This gives information about a unit contained in the CPU. We fill
1284 in a struct bypass_decl with information used later by
1285 `expand_automata'. */
1287 gen_bypass (rtx def
)
1296 out_insns
= get_str_vect (XSTR (def
, 1), &out_length
, ',', FALSE
);
1297 if (out_insns
== NULL
)
1298 fatal ("invalid string `%s' in define_bypass", XSTR (def
, 1));
1299 in_insns
= get_str_vect (XSTR (def
, 2), &in_length
, ',', FALSE
);
1300 if (in_insns
== NULL
)
1301 fatal ("invalid string `%s' in define_bypass", XSTR (def
, 2));
1302 for (i
= 0; i
< out_length
; i
++)
1303 for (j
= 0; j
< in_length
; j
++)
1305 decl
= create_node (sizeof (struct decl
));
1306 decl
->mode
= dm_bypass
;
1308 DECL_BYPASS (decl
)->latency
= XINT (def
, 0);
1309 DECL_BYPASS (decl
)->out_insn_name
= out_insns
[i
];
1310 DECL_BYPASS (decl
)->in_insn_name
= in_insns
[j
];
1311 DECL_BYPASS (decl
)->bypass_guard_name
= XSTR (def
, 3);
1312 VEC_safe_push (decl_t
,heap
, decls
, decl
);
1316 /* Process an EXCLUSION_SET.
1318 This gives information about a cpu unit conflicts. We fill a
1319 struct excl_rel_decl (excl) with information used later by
1320 `expand_automata'. */
1322 gen_excl_set (rtx def
)
1325 char **first_str_cpu_units
;
1326 char **second_str_cpu_units
;
1327 int first_vect_length
;
1332 = get_str_vect (XSTR (def
, 0), &first_vect_length
, ',', FALSE
);
1333 if (first_str_cpu_units
== NULL
)
1334 fatal ("invalid first string `%s' in exclusion_set", XSTR (def
, 0));
1335 second_str_cpu_units
= get_str_vect (XSTR (def
, 1), &length
, ',',
1337 if (second_str_cpu_units
== NULL
)
1338 fatal ("invalid second string `%s' in exclusion_set", XSTR (def
, 1));
1339 length
+= first_vect_length
;
1340 decl
= create_node (sizeof (struct decl
) + (length
- 1) * sizeof (char *));
1341 decl
->mode
= dm_excl
;
1343 DECL_EXCL (decl
)->all_names_num
= length
;
1344 DECL_EXCL (decl
)->first_list_length
= first_vect_length
;
1345 for (i
= 0; i
< length
; i
++)
1346 if (i
< first_vect_length
)
1347 DECL_EXCL (decl
)->names
[i
] = first_str_cpu_units
[i
];
1349 DECL_EXCL (decl
)->names
[i
]
1350 = second_str_cpu_units
[i
- first_vect_length
];
1351 VEC_safe_push (decl_t
,heap
, decls
, decl
);
1354 /* Process a PRESENCE_SET, a FINAL_PRESENCE_SET, an ABSENCE_SET,
1355 FINAL_ABSENCE_SET (it is depended on PRESENCE_P and FINAL_P).
1357 This gives information about a cpu unit reservation requirements.
1358 We fill a struct unit_pattern_rel_decl with information used later
1359 by `expand_automata'. */
1361 gen_presence_absence_set (rtx def
, int presence_p
, int final_p
)
1364 char **str_cpu_units
;
1365 char **str_pattern_lists
;
1366 char ***str_patterns
;
1367 int cpu_units_length
;
1369 int patterns_length
;
1372 str_cpu_units
= get_str_vect (XSTR (def
, 0), &cpu_units_length
, ',',
1374 if (str_cpu_units
== NULL
)
1377 ? "invalid first string `%s' in final_presence_set"
1378 : "invalid first string `%s' in presence_set")
1380 ? "invalid first string `%s' in final_absence_set"
1381 : "invalid first string `%s' in absence_set")),
1383 str_pattern_lists
= get_str_vect (XSTR (def
, 1),
1384 &patterns_length
, ',', FALSE
);
1385 if (str_pattern_lists
== NULL
)
1388 ? "invalid second string `%s' in final_presence_set"
1389 : "invalid second string `%s' in presence_set")
1391 ? "invalid second string `%s' in final_absence_set"
1392 : "invalid second string `%s' in absence_set")), XSTR (def
, 1));
1393 str_patterns
= obstack_alloc (&irp
, patterns_length
* sizeof (char **));
1394 for (i
= 0; i
< patterns_length
; i
++)
1396 str_patterns
[i
] = get_str_vect (str_pattern_lists
[i
],
1397 &length
, ' ', FALSE
);
1398 gcc_assert (str_patterns
[i
]);
1400 decl
= create_node (sizeof (struct decl
));
1404 decl
->mode
= dm_presence
;
1405 DECL_PRESENCE (decl
)->names_num
= cpu_units_length
;
1406 DECL_PRESENCE (decl
)->names
= str_cpu_units
;
1407 DECL_PRESENCE (decl
)->patterns
= str_patterns
;
1408 DECL_PRESENCE (decl
)->patterns_num
= patterns_length
;
1409 DECL_PRESENCE (decl
)->final_p
= final_p
;
1413 decl
->mode
= dm_absence
;
1414 DECL_ABSENCE (decl
)->names_num
= cpu_units_length
;
1415 DECL_ABSENCE (decl
)->names
= str_cpu_units
;
1416 DECL_ABSENCE (decl
)->patterns
= str_patterns
;
1417 DECL_ABSENCE (decl
)->patterns_num
= patterns_length
;
1418 DECL_ABSENCE (decl
)->final_p
= final_p
;
1420 VEC_safe_push (decl_t
,heap
, decls
, decl
);
1423 /* Process a PRESENCE_SET.
1425 This gives information about a cpu unit reservation requirements.
1426 We fill a struct unit_pattern_rel_decl (presence) with information
1427 used later by `expand_automata'. */
1429 gen_presence_set (rtx def
)
1431 gen_presence_absence_set (def
, TRUE
, FALSE
);
1434 /* Process a FINAL_PRESENCE_SET.
1436 This gives information about a cpu unit reservation requirements.
1437 We fill a struct unit_pattern_rel_decl (presence) with information
1438 used later by `expand_automata'. */
1440 gen_final_presence_set (rtx def
)
1442 gen_presence_absence_set (def
, TRUE
, TRUE
);
1445 /* Process an ABSENCE_SET.
1447 This gives information about a cpu unit reservation requirements.
1448 We fill a struct unit_pattern_rel_decl (absence) with information
1449 used later by `expand_automata'. */
1451 gen_absence_set (rtx def
)
1453 gen_presence_absence_set (def
, FALSE
, FALSE
);
1456 /* Process a FINAL_ABSENCE_SET.
1458 This gives information about a cpu unit reservation requirements.
1459 We fill a struct unit_pattern_rel_decl (absence) with information
1460 used later by `expand_automata'. */
1462 gen_final_absence_set (rtx def
)
1464 gen_presence_absence_set (def
, FALSE
, TRUE
);
1467 /* Process a DEFINE_AUTOMATON.
1469 This gives information about a finite state automaton used for
1470 recognizing pipeline hazards. We fill a struct automaton_decl
1471 with information used later by `expand_automata'. */
1473 gen_automaton (rtx def
)
1476 char **str_automata
;
1480 str_automata
= get_str_vect (XSTR (def
, 0), &vect_length
, ',', FALSE
);
1481 if (str_automata
== NULL
)
1482 fatal ("invalid string `%s' in define_automaton", XSTR (def
, 0));
1483 for (i
= 0; i
< vect_length
; i
++)
1485 decl
= create_node (sizeof (struct decl
));
1486 decl
->mode
= dm_automaton
;
1488 DECL_AUTOMATON (decl
)->name
= check_name (str_automata
[i
], decl
->pos
);
1489 VEC_safe_push (decl_t
,heap
, decls
, decl
);
1493 /* Process an AUTOMATA_OPTION.
1495 This gives information how to generate finite state automaton used
1496 for recognizing pipeline hazards. */
1498 gen_automata_option (rtx def
)
1500 if (strcmp (XSTR (def
, 0), NO_MINIMIZATION_OPTION
+ 1) == 0)
1501 no_minimization_flag
= 1;
1502 else if (strcmp (XSTR (def
, 0), TIME_OPTION
+ 1) == 0)
1504 else if (strcmp (XSTR (def
, 0), STATS_OPTION
+ 1) == 0)
1506 else if (strcmp (XSTR (def
, 0), V_OPTION
+ 1) == 0)
1508 else if (strcmp (XSTR (def
, 0), W_OPTION
+ 1) == 0)
1510 else if (strcmp (XSTR (def
, 0), NDFA_OPTION
+ 1) == 0)
1512 else if (strcmp (XSTR (def
, 0), PROGRESS_OPTION
+ 1) == 0)
1515 fatal ("invalid option `%s' in automata_option", XSTR (def
, 0));
1518 /* Name in reservation to denote absence reservation. */
1519 #define NOTHING_NAME "nothing"
1521 /* The following string contains original reservation string being
1523 static const char *reserv_str
;
1525 /* Parse an element in STR. */
1527 gen_regexp_el (const char *str
)
1536 if (str
[len
- 1] != ')')
1537 fatal ("garbage after ) in reservation `%s'", reserv_str
);
1538 dstr
= alloca (len
- 1);
1539 memcpy (dstr
, str
+ 1, len
- 2);
1540 dstr
[len
-2] = '\0';
1541 regexp
= gen_regexp_sequence (dstr
);
1543 else if (strcmp (str
, NOTHING_NAME
) == 0)
1545 regexp
= create_node (sizeof (struct decl
));
1546 regexp
->mode
= rm_nothing
;
1550 regexp
= create_node (sizeof (struct decl
));
1551 regexp
->mode
= rm_unit
;
1552 REGEXP_UNIT (regexp
)->name
= str
;
1557 /* Parse construction `repeat' in STR. */
1559 gen_regexp_repeat (const char *str
)
1567 repeat_vect
= get_str_vect (str
, &els_num
, '*', TRUE
);
1568 if (repeat_vect
== NULL
)
1569 fatal ("invalid `%s' in reservation `%s'", str
, reserv_str
);
1572 regexp
= gen_regexp_el (repeat_vect
[0]);
1573 for (i
= 1; i
< els_num
; i
++)
1575 repeat
= create_node (sizeof (struct regexp
));
1576 repeat
->mode
= rm_repeat
;
1577 REGEXP_REPEAT (repeat
)->regexp
= regexp
;
1578 REGEXP_REPEAT (repeat
)->repeat_num
= atoi (repeat_vect
[i
]);
1579 if (REGEXP_REPEAT (repeat
)->repeat_num
<= 1)
1580 fatal ("repetition `%s' <= 1 in reservation `%s'",
1587 return gen_regexp_el (str
);
1590 /* Parse reservation STR which possibly contains separator '+'. */
1592 gen_regexp_allof (const char *str
)
1599 allof_vect
= get_str_vect (str
, &els_num
, '+', TRUE
);
1600 if (allof_vect
== NULL
)
1601 fatal ("invalid `%s' in reservation `%s'", str
, reserv_str
);
1604 allof
= create_node (sizeof (struct regexp
)
1605 + sizeof (regexp_t
) * (els_num
- 1));
1606 allof
->mode
= rm_allof
;
1607 REGEXP_ALLOF (allof
)->regexps_num
= els_num
;
1608 for (i
= 0; i
< els_num
; i
++)
1609 REGEXP_ALLOF (allof
)->regexps
[i
] = gen_regexp_repeat (allof_vect
[i
]);
1613 return gen_regexp_repeat (str
);
1616 /* Parse reservation STR which possibly contains separator '|'. */
1618 gen_regexp_oneof (const char *str
)
1625 oneof_vect
= get_str_vect (str
, &els_num
, '|', TRUE
);
1626 if (oneof_vect
== NULL
)
1627 fatal ("invalid `%s' in reservation `%s'", str
, reserv_str
);
1630 oneof
= create_node (sizeof (struct regexp
)
1631 + sizeof (regexp_t
) * (els_num
- 1));
1632 oneof
->mode
= rm_oneof
;
1633 REGEXP_ONEOF (oneof
)->regexps_num
= els_num
;
1634 for (i
= 0; i
< els_num
; i
++)
1635 REGEXP_ONEOF (oneof
)->regexps
[i
] = gen_regexp_allof (oneof_vect
[i
]);
1639 return gen_regexp_allof (str
);
1642 /* Parse reservation STR which possibly contains separator ','. */
1644 gen_regexp_sequence (const char *str
)
1647 char **sequence_vect
;
1651 sequence_vect
= get_str_vect (str
, &els_num
, ',', TRUE
);
1654 sequence
= create_node (sizeof (struct regexp
)
1655 + sizeof (regexp_t
) * (els_num
- 1));
1656 sequence
->mode
= rm_sequence
;
1657 REGEXP_SEQUENCE (sequence
)->regexps_num
= els_num
;
1658 for (i
= 0; i
< els_num
; i
++)
1659 REGEXP_SEQUENCE (sequence
)->regexps
[i
]
1660 = gen_regexp_oneof (sequence_vect
[i
]);
1664 return gen_regexp_oneof (str
);
1667 /* Parse construction reservation STR. */
1669 gen_regexp (const char *str
)
1672 return gen_regexp_sequence (str
);;
1675 /* Process a DEFINE_RESERVATION.
1677 This gives information about a reservation of cpu units. We fill
1678 in a struct reserv_decl with information used later by
1679 `expand_automata'. */
1681 gen_reserv (rtx def
)
1685 decl
= create_node (sizeof (struct decl
));
1686 decl
->mode
= dm_reserv
;
1688 DECL_RESERV (decl
)->name
= check_name (XSTR (def
, 0), decl
->pos
);
1689 DECL_RESERV (decl
)->regexp
= gen_regexp (XSTR (def
, 1));
1690 VEC_safe_push (decl_t
,heap
, decls
, decl
);
1693 /* Process a DEFINE_INSN_RESERVATION.
1695 This gives information about the reservation of cpu units by an
1696 insn. We fill a struct insn_reserv_decl with information used
1697 later by `expand_automata'. */
1699 gen_insn_reserv (rtx def
)
1703 decl
= create_node (sizeof (struct decl
));
1704 decl
->mode
= dm_insn_reserv
;
1706 DECL_INSN_RESERV (decl
)->name
1707 = check_name (XSTR (def
, 0), decl
->pos
);
1708 DECL_INSN_RESERV (decl
)->default_latency
= XINT (def
, 1);
1709 DECL_INSN_RESERV (decl
)->condexp
= XEXP (def
, 2);
1710 DECL_INSN_RESERV (decl
)->regexp
= gen_regexp (XSTR (def
, 3));
1711 VEC_safe_push (decl_t
,heap
, decls
, decl
);
1716 /* The function evaluates hash value (0..UINT_MAX) of string. */
1718 string_hash (const char *string
)
1722 for (result
= i
= 0;*string
++ != '\0'; i
++)
1723 result
+= ((unsigned char) *string
<< (i
% CHAR_BIT
));
1729 /* This page contains abstract data `table of automaton declarations'.
1730 Elements of the table is nodes representing automaton declarations.
1731 Key of the table elements is name of given automaton. Remember
1732 that automaton names have own space. */
1734 /* The function evaluates hash value of an automaton declaration. The
1735 function is used by abstract data `hashtab'. The function returns
1736 hash value (0..UINT_MAX) of given automaton declaration. */
1738 automaton_decl_hash (const void *automaton_decl
)
1740 const decl_t decl
= (decl_t
) automaton_decl
;
1742 gcc_assert (decl
->mode
!= dm_automaton
1743 || DECL_AUTOMATON (decl
)->name
);
1744 return string_hash (DECL_AUTOMATON (decl
)->name
);
1747 /* The function tests automaton declarations on equality of their
1748 keys. The function is used by abstract data `hashtab'. The
1749 function returns 1 if the declarations have the same key, 0
1752 automaton_decl_eq_p (const void* automaton_decl_1
,
1753 const void* automaton_decl_2
)
1755 const decl_t decl1
= (decl_t
) automaton_decl_1
;
1756 const decl_t decl2
= (decl_t
) automaton_decl_2
;
1758 gcc_assert (decl1
->mode
== dm_automaton
1759 && DECL_AUTOMATON (decl1
)->name
1760 && decl2
->mode
== dm_automaton
1761 && DECL_AUTOMATON (decl2
)->name
);
1762 return strcmp (DECL_AUTOMATON (decl1
)->name
,
1763 DECL_AUTOMATON (decl2
)->name
) == 0;
1766 /* The automaton declaration table itself is represented by the
1767 following variable. */
1768 static htab_t automaton_decl_table
;
1770 /* The function inserts automaton declaration into the table. The
1771 function does nothing if an automaton declaration with the same key
1772 exists already in the table. The function returns automaton
1773 declaration node in the table with the same key as given automaton
1774 declaration node. */
1776 insert_automaton_decl (decl_t automaton_decl
)
1780 entry_ptr
= htab_find_slot (automaton_decl_table
, automaton_decl
, 1);
1781 if (*entry_ptr
== NULL
)
1782 *entry_ptr
= (void *) automaton_decl
;
1783 return (decl_t
) *entry_ptr
;
1786 /* The following variable value is node representing automaton
1787 declaration. The node used for searching automaton declaration
1789 static struct decl work_automaton_decl
;
1791 /* The function searches for automaton declaration in the table with
1792 the same key as node representing name of the automaton
1793 declaration. The function returns node found in the table, NULL if
1794 such node does not exist in the table. */
1796 find_automaton_decl (const char *name
)
1800 work_automaton_decl
.mode
= dm_automaton
;
1801 DECL_AUTOMATON (&work_automaton_decl
)->name
= name
;
1802 entry
= htab_find (automaton_decl_table
, &work_automaton_decl
);
1803 return (decl_t
) entry
;
1806 /* The function creates empty automaton declaration table and node
1807 representing automaton declaration and used for searching automaton
1808 declaration with given name. The function must be called only once
1809 before any work with the automaton declaration table. */
1811 initiate_automaton_decl_table (void)
1813 work_automaton_decl
.mode
= dm_automaton
;
1814 automaton_decl_table
= htab_create (10, automaton_decl_hash
,
1815 automaton_decl_eq_p
, (htab_del
) 0);
1818 /* The function deletes the automaton declaration table. Only call of
1819 function `initiate_automaton_decl_table' is possible immediately
1820 after this function call. */
1822 finish_automaton_decl_table (void)
1824 htab_delete (automaton_decl_table
);
1829 /* This page contains abstract data `table of insn declarations'.
1830 Elements of the table is nodes representing insn declarations. Key
1831 of the table elements is name of given insn (in corresponding
1832 define_insn_reservation). Remember that insn names have own
1835 /* The function evaluates hash value of an insn declaration. The
1836 function is used by abstract data `hashtab'. The function returns
1837 hash value (0..UINT_MAX) of given insn declaration. */
1839 insn_decl_hash (const void *insn_decl
)
1841 const decl_t decl
= (decl_t
) insn_decl
;
1843 gcc_assert (decl
->mode
== dm_insn_reserv
1844 && DECL_INSN_RESERV (decl
)->name
);
1845 return string_hash (DECL_INSN_RESERV (decl
)->name
);
1848 /* The function tests insn declarations on equality of their keys.
1849 The function is used by abstract data `hashtab'. The function
1850 returns 1 if declarations have the same key, 0 otherwise. */
1852 insn_decl_eq_p (const void *insn_decl_1
, const void *insn_decl_2
)
1854 const decl_t decl1
= (decl_t
) insn_decl_1
;
1855 const decl_t decl2
= (decl_t
) insn_decl_2
;
1857 gcc_assert (decl1
->mode
== dm_insn_reserv
1858 && DECL_INSN_RESERV (decl1
)->name
1859 && decl2
->mode
== dm_insn_reserv
1860 && DECL_INSN_RESERV (decl2
)->name
);
1861 return strcmp (DECL_INSN_RESERV (decl1
)->name
,
1862 DECL_INSN_RESERV (decl2
)->name
) == 0;
1865 /* The insn declaration table itself is represented by the following
1866 variable. The table does not contain insn reservation
1868 static htab_t insn_decl_table
;
1870 /* The function inserts insn declaration into the table. The function
1871 does nothing if an insn declaration with the same key exists
1872 already in the table. The function returns insn declaration node
1873 in the table with the same key as given insn declaration node. */
1875 insert_insn_decl (decl_t insn_decl
)
1879 entry_ptr
= htab_find_slot (insn_decl_table
, insn_decl
, 1);
1880 if (*entry_ptr
== NULL
)
1881 *entry_ptr
= (void *) insn_decl
;
1882 return (decl_t
) *entry_ptr
;
1885 /* The following variable value is node representing insn reservation
1886 declaration. The node used for searching insn reservation
1887 declaration with given name. */
1888 static struct decl work_insn_decl
;
1890 /* The function searches for insn reservation declaration in the table
1891 with the same key as node representing name of the insn reservation
1892 declaration. The function returns node found in the table, NULL if
1893 such node does not exist in the table. */
1895 find_insn_decl (const char *name
)
1899 work_insn_decl
.mode
= dm_insn_reserv
;
1900 DECL_INSN_RESERV (&work_insn_decl
)->name
= name
;
1901 entry
= htab_find (insn_decl_table
, &work_insn_decl
);
1902 return (decl_t
) entry
;
1905 /* The function creates empty insn declaration table and node
1906 representing insn declaration and used for searching insn
1907 declaration with given name. The function must be called only once
1908 before any work with the insn declaration table. */
1910 initiate_insn_decl_table (void)
1912 work_insn_decl
.mode
= dm_insn_reserv
;
1913 insn_decl_table
= htab_create (10, insn_decl_hash
, insn_decl_eq_p
,
1917 /* The function deletes the insn declaration table. Only call of
1918 function `initiate_insn_decl_table' is possible immediately after
1919 this function call. */
1921 finish_insn_decl_table (void)
1923 htab_delete (insn_decl_table
);
1928 /* This page contains abstract data `table of declarations'. Elements
1929 of the table is nodes representing declarations (of units and
1930 reservations). Key of the table elements is names of given
1933 /* The function evaluates hash value of a declaration. The function
1934 is used by abstract data `hashtab'. The function returns hash
1935 value (0..UINT_MAX) of given declaration. */
1937 decl_hash (const void *decl
)
1939 const decl_t d
= (const decl_t
) decl
;
1941 gcc_assert ((d
->mode
== dm_unit
&& DECL_UNIT (d
)->name
)
1942 || (d
->mode
== dm_reserv
&& DECL_RESERV (d
)->name
));
1943 return string_hash (d
->mode
== dm_unit
1944 ? DECL_UNIT (d
)->name
: DECL_RESERV (d
)->name
);
1947 /* The function tests declarations on equality of their keys. The
1948 function is used by abstract data 'hashtab'. The function
1949 returns 1 if the declarations have the same key, 0 otherwise. */
1951 decl_eq_p (const void *decl_1
, const void *decl_2
)
1953 const decl_t d1
= (const decl_t
) decl_1
;
1954 const decl_t d2
= (const decl_t
) decl_2
;
1956 gcc_assert ((d1
->mode
== dm_unit
&& DECL_UNIT (d1
)->name
)
1957 || (d1
->mode
== dm_reserv
&& DECL_RESERV (d1
)->name
));
1958 gcc_assert ((d2
->mode
== dm_unit
&& DECL_UNIT (d2
)->name
)
1959 || (d2
->mode
== dm_reserv
&& DECL_RESERV (d2
)->name
));
1960 return strcmp ((d1
->mode
== dm_unit
1961 ? DECL_UNIT (d1
)->name
: DECL_RESERV (d1
)->name
),
1962 (d2
->mode
== dm_unit
1963 ? DECL_UNIT (d2
)->name
: DECL_RESERV (d2
)->name
)) == 0;
1966 /* The declaration table itself is represented by the following
1968 static htab_t decl_table
;
1970 /* The function inserts declaration into the table. The function does
1971 nothing if a declaration with the same key exists already in the
1972 table. The function returns declaration node in the table with the
1973 same key as given declaration node. */
1976 insert_decl (decl_t decl
)
1980 entry_ptr
= htab_find_slot (decl_table
, decl
, 1);
1981 if (*entry_ptr
== NULL
)
1982 *entry_ptr
= (void *) decl
;
1983 return (decl_t
) *entry_ptr
;
1986 /* The following variable value is node representing declaration. The
1987 node used for searching declaration with given name. */
1988 static struct decl work_decl
;
1990 /* The function searches for declaration in the table with the same
1991 key as node representing name of the declaration. The function
1992 returns node found in the table, NULL if such node does not exist
1995 find_decl (const char *name
)
1999 work_decl
.mode
= dm_unit
;
2000 DECL_UNIT (&work_decl
)->name
= name
;
2001 entry
= htab_find (decl_table
, &work_decl
);
2002 return (decl_t
) entry
;
2005 /* The function creates empty declaration table and node representing
2006 declaration and used for searching declaration with given name.
2007 The function must be called only once before any work with the
2008 declaration table. */
2010 initiate_decl_table (void)
2012 work_decl
.mode
= dm_unit
;
2013 decl_table
= htab_create (10, decl_hash
, decl_eq_p
, (htab_del
) 0);
2016 /* The function deletes the declaration table. Only call of function
2017 `initiate_declaration_table' is possible immediately after this
2020 finish_decl_table (void)
2022 htab_delete (decl_table
);
2027 /* This page contains checker of pipeline hazard description. */
2029 /* Checking NAMES in an exclusion clause vector and returning formed
2030 unit_set_el_list. */
2031 static unit_set_el_t
2032 process_excls (char **names
, int num
, pos_t excl_pos ATTRIBUTE_UNUSED
)
2034 unit_set_el_t el_list
;
2035 unit_set_el_t last_el
;
2036 unit_set_el_t new_el
;
2037 decl_t decl_in_table
;
2042 for (i
= 0; i
< num
; i
++)
2044 decl_in_table
= find_decl (names
[i
]);
2045 if (decl_in_table
== NULL
)
2046 error ("unit `%s' in exclusion is not declared", names
[i
]);
2047 else if (decl_in_table
->mode
!= dm_unit
)
2048 error ("`%s' in exclusion is not unit", names
[i
]);
2051 new_el
= create_node (sizeof (struct unit_set_el
));
2052 new_el
->unit_decl
= DECL_UNIT (decl_in_table
);
2053 new_el
->next_unit_set_el
= NULL
;
2054 if (last_el
== NULL
)
2055 el_list
= last_el
= new_el
;
2058 last_el
->next_unit_set_el
= new_el
;
2059 last_el
= last_el
->next_unit_set_el
;
2066 /* The function adds each element from SOURCE_LIST to the exclusion
2067 list of the each element from DEST_LIST. Checking situation "unit
2068 excludes itself". */
2070 add_excls (unit_set_el_t dest_list
, unit_set_el_t source_list
,
2071 pos_t excl_pos ATTRIBUTE_UNUSED
)
2075 unit_set_el_t curr_el
;
2076 unit_set_el_t prev_el
;
2079 for (dst
= dest_list
; dst
!= NULL
; dst
= dst
->next_unit_set_el
)
2080 for (src
= source_list
; src
!= NULL
; src
= src
->next_unit_set_el
)
2082 if (dst
->unit_decl
== src
->unit_decl
)
2084 error ("unit `%s' excludes itself", src
->unit_decl
->name
);
2087 if (dst
->unit_decl
->automaton_name
!= NULL
2088 && src
->unit_decl
->automaton_name
!= NULL
2089 && strcmp (dst
->unit_decl
->automaton_name
,
2090 src
->unit_decl
->automaton_name
) != 0)
2092 error ("units `%s' and `%s' in exclusion set belong to different automata",
2093 src
->unit_decl
->name
, dst
->unit_decl
->name
);
2096 for (curr_el
= dst
->unit_decl
->excl_list
, prev_el
= NULL
;
2098 prev_el
= curr_el
, curr_el
= curr_el
->next_unit_set_el
)
2099 if (curr_el
->unit_decl
== src
->unit_decl
)
2101 if (curr_el
== NULL
)
2103 /* Element not found - insert. */
2104 copy
= copy_node (src
, sizeof (*src
));
2105 copy
->next_unit_set_el
= NULL
;
2106 if (prev_el
== NULL
)
2107 dst
->unit_decl
->excl_list
= copy
;
2109 prev_el
->next_unit_set_el
= copy
;
2114 /* Checking NAMES in presence/absence clause and returning the
2115 formed unit_set_el_list. The function is called only after
2116 processing all exclusion sets. */
2117 static unit_set_el_t
2118 process_presence_absence_names (char **names
, int num
,
2119 pos_t req_pos ATTRIBUTE_UNUSED
,
2120 int presence_p
, int final_p
)
2122 unit_set_el_t el_list
;
2123 unit_set_el_t last_el
;
2124 unit_set_el_t new_el
;
2125 decl_t decl_in_table
;
2130 for (i
= 0; i
< num
; i
++)
2132 decl_in_table
= find_decl (names
[i
]);
2133 if (decl_in_table
== NULL
)
2136 ? "unit `%s' in final presence set is not declared"
2137 : "unit `%s' in presence set is not declared")
2139 ? "unit `%s' in final absence set is not declared"
2140 : "unit `%s' in absence set is not declared")), names
[i
]);
2141 else if (decl_in_table
->mode
!= dm_unit
)
2144 ? "`%s' in final presence set is not unit"
2145 : "`%s' in presence set is not unit")
2147 ? "`%s' in final absence set is not unit"
2148 : "`%s' in absence set is not unit")), names
[i
]);
2151 new_el
= create_node (sizeof (struct unit_set_el
));
2152 new_el
->unit_decl
= DECL_UNIT (decl_in_table
);
2153 new_el
->next_unit_set_el
= NULL
;
2154 if (last_el
== NULL
)
2155 el_list
= last_el
= new_el
;
2158 last_el
->next_unit_set_el
= new_el
;
2159 last_el
= last_el
->next_unit_set_el
;
2166 /* Checking NAMES in patterns of a presence/absence clause and
2167 returning the formed pattern_set_el_list. The function is called
2168 only after processing all exclusion sets. */
2169 static pattern_set_el_t
2170 process_presence_absence_patterns (char ***patterns
, int num
,
2171 pos_t req_pos ATTRIBUTE_UNUSED
,
2172 int presence_p
, int final_p
)
2174 pattern_set_el_t el_list
;
2175 pattern_set_el_t last_el
;
2176 pattern_set_el_t new_el
;
2177 decl_t decl_in_table
;
2182 for (i
= 0; i
< num
; i
++)
2184 for (j
= 0; patterns
[i
] [j
] != NULL
; j
++)
2186 new_el
= create_node (sizeof (struct pattern_set_el
)
2187 + sizeof (struct unit_decl
*) * j
);
2189 = (struct unit_decl
**) ((char *) new_el
2190 + sizeof (struct pattern_set_el
));
2191 new_el
->next_pattern_set_el
= NULL
;
2192 if (last_el
== NULL
)
2193 el_list
= last_el
= new_el
;
2196 last_el
->next_pattern_set_el
= new_el
;
2197 last_el
= last_el
->next_pattern_set_el
;
2199 new_el
->units_num
= 0;
2200 for (j
= 0; patterns
[i
] [j
] != NULL
; j
++)
2202 decl_in_table
= find_decl (patterns
[i
] [j
]);
2203 if (decl_in_table
== NULL
)
2206 ? "unit `%s' in final presence set is not declared"
2207 : "unit `%s' in presence set is not declared")
2209 ? "unit `%s' in final absence set is not declared"
2210 : "unit `%s' in absence set is not declared")),
2212 else if (decl_in_table
->mode
!= dm_unit
)
2215 ? "`%s' in final presence set is not unit"
2216 : "`%s' in presence set is not unit")
2218 ? "`%s' in final absence set is not unit"
2219 : "`%s' in absence set is not unit")),
2223 new_el
->unit_decls
[new_el
->units_num
]
2224 = DECL_UNIT (decl_in_table
);
2225 new_el
->units_num
++;
2232 /* The function adds each element from PATTERN_LIST to presence (if
2233 PRESENCE_P) or absence list of the each element from DEST_LIST.
2234 Checking situations "unit requires own absence", and "unit excludes
2235 and requires presence of ...", "unit requires absence and presence
2236 of ...", "units in (final) presence set belong to different
2237 automata", and "units in (final) absence set belong to different
2238 automata". Remember that we process absence sets only after all
2241 add_presence_absence (unit_set_el_t dest_list
,
2242 pattern_set_el_t pattern_list
,
2243 pos_t req_pos ATTRIBUTE_UNUSED
,
2244 int presence_p
, int final_p
)
2247 pattern_set_el_t pat
;
2248 struct unit_decl
*unit
;
2249 unit_set_el_t curr_excl_el
;
2250 pattern_set_el_t curr_pat_el
;
2251 pattern_set_el_t prev_el
;
2252 pattern_set_el_t copy
;
2256 for (dst
= dest_list
; dst
!= NULL
; dst
= dst
->next_unit_set_el
)
2257 for (pat
= pattern_list
; pat
!= NULL
; pat
= pat
->next_pattern_set_el
)
2259 for (i
= 0; i
< pat
->units_num
; i
++)
2261 unit
= pat
->unit_decls
[i
];
2262 if (dst
->unit_decl
== unit
&& pat
->units_num
== 1 && !presence_p
)
2264 error ("unit `%s' requires own absence", unit
->name
);
2267 if (dst
->unit_decl
->automaton_name
!= NULL
2268 && unit
->automaton_name
!= NULL
2269 && strcmp (dst
->unit_decl
->automaton_name
,
2270 unit
->automaton_name
) != 0)
2274 ? "units `%s' and `%s' in final presence set belong to different automata"
2275 : "units `%s' and `%s' in presence set belong to different automata")
2277 ? "units `%s' and `%s' in final absence set belong to different automata"
2278 : "units `%s' and `%s' in absence set belong to different automata")),
2279 unit
->name
, dst
->unit_decl
->name
);
2284 for (curr_excl_el
= dst
->unit_decl
->excl_list
;
2285 curr_excl_el
!= NULL
;
2286 curr_excl_el
= curr_excl_el
->next_unit_set_el
)
2288 if (unit
== curr_excl_el
->unit_decl
&& pat
->units_num
== 1)
2292 error ("unit `%s' excludes and requires presence of `%s'",
2293 dst
->unit_decl
->name
, unit
->name
);
2298 (0, "unit `%s' excludes and requires presence of `%s'",
2299 dst
->unit_decl
->name
, unit
->name
);
2302 else if (pat
->units_num
== 1)
2303 for (curr_pat_el
= dst
->unit_decl
->presence_list
;
2304 curr_pat_el
!= NULL
;
2305 curr_pat_el
= curr_pat_el
->next_pattern_set_el
)
2306 if (curr_pat_el
->units_num
== 1
2307 && unit
== curr_pat_el
->unit_decls
[0])
2312 ("unit `%s' requires absence and presence of `%s'",
2313 dst
->unit_decl
->name
, unit
->name
);
2318 (0, "unit `%s' requires absence and presence of `%s'",
2319 dst
->unit_decl
->name
, unit
->name
);
2323 for (prev_el
= (presence_p
2325 ? dst
->unit_decl
->final_presence_list
2326 : dst
->unit_decl
->final_presence_list
)
2328 ? dst
->unit_decl
->final_absence_list
2329 : dst
->unit_decl
->absence_list
));
2330 prev_el
!= NULL
&& prev_el
->next_pattern_set_el
!= NULL
;
2331 prev_el
= prev_el
->next_pattern_set_el
)
2333 copy
= copy_node (pat
, sizeof (*pat
));
2334 copy
->next_pattern_set_el
= NULL
;
2335 if (prev_el
== NULL
)
2340 dst
->unit_decl
->final_presence_list
= copy
;
2342 dst
->unit_decl
->presence_list
= copy
;
2345 dst
->unit_decl
->final_absence_list
= copy
;
2347 dst
->unit_decl
->absence_list
= copy
;
2350 prev_el
->next_pattern_set_el
= copy
;
2357 /* The function searches for bypass with given IN_INSN_RESERV in given
2359 static struct bypass_decl
*
2360 find_bypass (struct bypass_decl
*bypass_list
,
2361 struct insn_reserv_decl
*in_insn_reserv
)
2363 struct bypass_decl
*bypass
;
2365 for (bypass
= bypass_list
; bypass
!= NULL
; bypass
= bypass
->next
)
2366 if (bypass
->in_insn_reserv
== in_insn_reserv
)
2371 /* The function processes pipeline description declarations, checks
2372 their correctness, and forms exclusion/presence/absence sets. */
2374 process_decls (void)
2377 decl_t automaton_decl
;
2378 decl_t decl_in_table
;
2379 decl_t out_insn_reserv
;
2380 decl_t in_insn_reserv
;
2381 struct bypass_decl
*bypass
;
2382 int automaton_presence
;
2385 /* Checking repeated automata declarations. */
2386 automaton_presence
= 0;
2387 for (i
= 0; i
< description
->decls_num
; i
++)
2389 decl
= description
->decls
[i
];
2390 if (decl
->mode
== dm_automaton
)
2392 automaton_presence
= 1;
2393 decl_in_table
= insert_automaton_decl (decl
);
2394 if (decl_in_table
!= decl
)
2397 error ("repeated declaration of automaton `%s'",
2398 DECL_AUTOMATON (decl
)->name
);
2400 warning (0, "repeated declaration of automaton `%s'",
2401 DECL_AUTOMATON (decl
)->name
);
2405 /* Checking undeclared automata, repeated declarations (except for
2406 automata) and correctness of their attributes (insn latency times
2408 for (i
= 0; i
< description
->decls_num
; i
++)
2410 decl
= description
->decls
[i
];
2411 if (decl
->mode
== dm_insn_reserv
)
2413 if (DECL_INSN_RESERV (decl
)->default_latency
< 0)
2414 error ("define_insn_reservation `%s' has negative latency time",
2415 DECL_INSN_RESERV (decl
)->name
);
2416 DECL_INSN_RESERV (decl
)->insn_num
= description
->insns_num
;
2417 description
->insns_num
++;
2418 decl_in_table
= insert_insn_decl (decl
);
2419 if (decl_in_table
!= decl
)
2420 error ("`%s' is already used as insn reservation name",
2421 DECL_INSN_RESERV (decl
)->name
);
2423 else if (decl
->mode
== dm_bypass
)
2425 if (DECL_BYPASS (decl
)->latency
< 0)
2426 error ("define_bypass `%s - %s' has negative latency time",
2427 DECL_BYPASS (decl
)->out_insn_name
,
2428 DECL_BYPASS (decl
)->in_insn_name
);
2430 else if (decl
->mode
== dm_unit
|| decl
->mode
== dm_reserv
)
2432 if (decl
->mode
== dm_unit
)
2434 DECL_UNIT (decl
)->automaton_decl
= NULL
;
2435 if (DECL_UNIT (decl
)->automaton_name
!= NULL
)
2438 = find_automaton_decl (DECL_UNIT (decl
)->automaton_name
);
2439 if (automaton_decl
== NULL
)
2440 error ("automaton `%s' is not declared",
2441 DECL_UNIT (decl
)->automaton_name
);
2444 DECL_AUTOMATON (automaton_decl
)->automaton_is_used
= 1;
2445 DECL_UNIT (decl
)->automaton_decl
2446 = DECL_AUTOMATON (automaton_decl
);
2449 else if (automaton_presence
)
2450 error ("define_unit `%s' without automaton when one defined",
2451 DECL_UNIT (decl
)->name
);
2452 DECL_UNIT (decl
)->unit_num
= description
->units_num
;
2453 description
->units_num
++;
2454 if (strcmp (DECL_UNIT (decl
)->name
, NOTHING_NAME
) == 0)
2456 error ("`%s' is declared as cpu unit", NOTHING_NAME
);
2459 decl_in_table
= find_decl (DECL_UNIT (decl
)->name
);
2463 if (strcmp (DECL_RESERV (decl
)->name
, NOTHING_NAME
) == 0)
2465 error ("`%s' is declared as cpu reservation", NOTHING_NAME
);
2468 decl_in_table
= find_decl (DECL_RESERV (decl
)->name
);
2470 if (decl_in_table
== NULL
)
2471 decl_in_table
= insert_decl (decl
);
2474 if (decl
->mode
== dm_unit
)
2475 error ("repeated declaration of unit `%s'",
2476 DECL_UNIT (decl
)->name
);
2478 error ("repeated declaration of reservation `%s'",
2479 DECL_RESERV (decl
)->name
);
2483 /* Check bypasses and form list of bypasses for each (output)
2485 for (i
= 0; i
< description
->decls_num
; i
++)
2487 decl
= description
->decls
[i
];
2488 if (decl
->mode
== dm_bypass
)
2490 out_insn_reserv
= find_insn_decl (DECL_BYPASS (decl
)->out_insn_name
);
2491 in_insn_reserv
= find_insn_decl (DECL_BYPASS (decl
)->in_insn_name
);
2492 if (out_insn_reserv
== NULL
)
2493 error ("there is no insn reservation `%s'",
2494 DECL_BYPASS (decl
)->out_insn_name
);
2495 else if (in_insn_reserv
== NULL
)
2496 error ("there is no insn reservation `%s'",
2497 DECL_BYPASS (decl
)->in_insn_name
);
2500 DECL_BYPASS (decl
)->out_insn_reserv
2501 = DECL_INSN_RESERV (out_insn_reserv
);
2502 DECL_BYPASS (decl
)->in_insn_reserv
2503 = DECL_INSN_RESERV (in_insn_reserv
);
2505 = find_bypass (DECL_INSN_RESERV (out_insn_reserv
)->bypass_list
,
2506 DECL_BYPASS (decl
)->in_insn_reserv
);
2509 if (DECL_BYPASS (decl
)->latency
== bypass
->latency
)
2513 ("the same bypass `%s - %s' is already defined",
2514 DECL_BYPASS (decl
)->out_insn_name
,
2515 DECL_BYPASS (decl
)->in_insn_name
);
2518 (0, "the same bypass `%s - %s' is already defined",
2519 DECL_BYPASS (decl
)->out_insn_name
,
2520 DECL_BYPASS (decl
)->in_insn_name
);
2523 error ("bypass `%s - %s' is already defined",
2524 DECL_BYPASS (decl
)->out_insn_name
,
2525 DECL_BYPASS (decl
)->in_insn_name
);
2529 DECL_BYPASS (decl
)->next
2530 = DECL_INSN_RESERV (out_insn_reserv
)->bypass_list
;
2531 DECL_INSN_RESERV (out_insn_reserv
)->bypass_list
2532 = DECL_BYPASS (decl
);
2538 /* Check exclusion set declarations and form exclusion sets. */
2539 for (i
= 0; i
< description
->decls_num
; i
++)
2541 decl
= description
->decls
[i
];
2542 if (decl
->mode
== dm_excl
)
2544 unit_set_el_t unit_set_el_list
;
2545 unit_set_el_t unit_set_el_list_2
;
2548 = process_excls (DECL_EXCL (decl
)->names
,
2549 DECL_EXCL (decl
)->first_list_length
, decl
->pos
);
2551 = process_excls (&DECL_EXCL (decl
)->names
2552 [DECL_EXCL (decl
)->first_list_length
],
2553 DECL_EXCL (decl
)->all_names_num
2554 - DECL_EXCL (decl
)->first_list_length
,
2556 add_excls (unit_set_el_list
, unit_set_el_list_2
, decl
->pos
);
2557 add_excls (unit_set_el_list_2
, unit_set_el_list
, decl
->pos
);
2561 /* Check presence set declarations and form presence sets. */
2562 for (i
= 0; i
< description
->decls_num
; i
++)
2564 decl
= description
->decls
[i
];
2565 if (decl
->mode
== dm_presence
)
2567 unit_set_el_t unit_set_el_list
;
2568 pattern_set_el_t pattern_set_el_list
;
2571 = process_presence_absence_names
2572 (DECL_PRESENCE (decl
)->names
, DECL_PRESENCE (decl
)->names_num
,
2573 decl
->pos
, TRUE
, DECL_PRESENCE (decl
)->final_p
);
2575 = process_presence_absence_patterns
2576 (DECL_PRESENCE (decl
)->patterns
,
2577 DECL_PRESENCE (decl
)->patterns_num
,
2578 decl
->pos
, TRUE
, DECL_PRESENCE (decl
)->final_p
);
2579 add_presence_absence (unit_set_el_list
, pattern_set_el_list
,
2581 DECL_PRESENCE (decl
)->final_p
);
2585 /* Check absence set declarations and form absence sets. */
2586 for (i
= 0; i
< description
->decls_num
; i
++)
2588 decl
= description
->decls
[i
];
2589 if (decl
->mode
== dm_absence
)
2591 unit_set_el_t unit_set_el_list
;
2592 pattern_set_el_t pattern_set_el_list
;
2595 = process_presence_absence_names
2596 (DECL_ABSENCE (decl
)->names
, DECL_ABSENCE (decl
)->names_num
,
2597 decl
->pos
, FALSE
, DECL_ABSENCE (decl
)->final_p
);
2599 = process_presence_absence_patterns
2600 (DECL_ABSENCE (decl
)->patterns
,
2601 DECL_ABSENCE (decl
)->patterns_num
,
2602 decl
->pos
, FALSE
, DECL_ABSENCE (decl
)->final_p
);
2603 add_presence_absence (unit_set_el_list
, pattern_set_el_list
,
2605 DECL_ABSENCE (decl
)->final_p
);
2610 /* The following function checks that declared automaton is used. If
2611 the automaton is not used, the function fixes error/warning. The
2612 following function must be called only after `process_decls'. */
2614 check_automaton_usage (void)
2619 for (i
= 0; i
< description
->decls_num
; i
++)
2621 decl
= description
->decls
[i
];
2622 if (decl
->mode
== dm_automaton
2623 && !DECL_AUTOMATON (decl
)->automaton_is_used
)
2626 error ("automaton `%s' is not used", DECL_AUTOMATON (decl
)->name
);
2628 warning (0, "automaton `%s' is not used",
2629 DECL_AUTOMATON (decl
)->name
);
2634 /* The following recursive function processes all regexp in order to
2635 fix usage of units or reservations and to fix errors of undeclared
2636 name. The function may change unit_regexp onto reserv_regexp.
2637 Remember that reserv_regexp does not exist before the function
2640 process_regexp (regexp_t regexp
)
2642 decl_t decl_in_table
;
2643 regexp_t new_regexp
;
2646 switch (regexp
->mode
)
2649 decl_in_table
= find_decl (REGEXP_UNIT (regexp
)->name
);
2650 if (decl_in_table
== NULL
)
2651 error ("undeclared unit or reservation `%s'",
2652 REGEXP_UNIT (regexp
)->name
);
2654 switch (decl_in_table
->mode
)
2657 DECL_UNIT (decl_in_table
)->unit_is_used
= 1;
2658 REGEXP_UNIT (regexp
)->unit_decl
= DECL_UNIT (decl_in_table
);
2662 DECL_RESERV (decl_in_table
)->reserv_is_used
= 1;
2663 new_regexp
= create_node (sizeof (struct regexp
));
2664 new_regexp
->mode
= rm_reserv
;
2665 new_regexp
->pos
= regexp
->pos
;
2666 REGEXP_RESERV (new_regexp
)->name
= REGEXP_UNIT (regexp
)->name
;
2667 REGEXP_RESERV (new_regexp
)->reserv_decl
2668 = DECL_RESERV (decl_in_table
);
2669 regexp
= new_regexp
;
2677 for (i
= 0; i
<REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
2678 REGEXP_SEQUENCE (regexp
)->regexps
[i
]
2679 = process_regexp (REGEXP_SEQUENCE (regexp
)->regexps
[i
]);
2682 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
2683 REGEXP_ALLOF (regexp
)->regexps
[i
]
2684 = process_regexp (REGEXP_ALLOF (regexp
)->regexps
[i
]);
2687 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
2688 REGEXP_ONEOF (regexp
)->regexps
[i
]
2689 = process_regexp (REGEXP_ONEOF (regexp
)->regexps
[i
]);
2692 REGEXP_REPEAT (regexp
)->regexp
2693 = process_regexp (REGEXP_REPEAT (regexp
)->regexp
);
2703 /* The following function processes regexp of define_reservation and
2704 define_insn_reservation with the aid of function
2705 `process_regexp'. */
2707 process_regexp_decls (void)
2712 for (i
= 0; i
< description
->decls_num
; i
++)
2714 decl
= description
->decls
[i
];
2715 if (decl
->mode
== dm_reserv
)
2716 DECL_RESERV (decl
)->regexp
2717 = process_regexp (DECL_RESERV (decl
)->regexp
);
2718 else if (decl
->mode
== dm_insn_reserv
)
2719 DECL_INSN_RESERV (decl
)->regexp
2720 = process_regexp (DECL_INSN_RESERV (decl
)->regexp
);
2724 /* The following function checks that declared unit is used. If the
2725 unit is not used, the function fixes errors/warnings. The
2726 following function must be called only after `process_decls',
2727 `process_regexp_decls'. */
2734 for (i
= 0; i
< description
->decls_num
; i
++)
2736 decl
= description
->decls
[i
];
2737 if (decl
->mode
== dm_unit
&& !DECL_UNIT (decl
)->unit_is_used
)
2740 error ("unit `%s' is not used", DECL_UNIT (decl
)->name
);
2742 warning (0, "unit `%s' is not used", DECL_UNIT (decl
)->name
);
2744 else if (decl
->mode
== dm_reserv
&& !DECL_RESERV (decl
)->reserv_is_used
)
2747 error ("reservation `%s' is not used", DECL_RESERV (decl
)->name
);
2749 warning (0, "reservation `%s' is not used", DECL_RESERV (decl
)->name
);
2754 /* The following variable value is number of reservation being
2755 processed on loop recognition. */
2756 static int curr_loop_pass_num
;
2758 /* The following recursive function returns nonzero value if REGEXP
2759 contains given decl or reservations in given regexp refers for
2762 loop_in_regexp (regexp_t regexp
, decl_t start_decl
)
2768 switch (regexp
->mode
)
2774 if (start_decl
->mode
== dm_reserv
2775 && REGEXP_RESERV (regexp
)->reserv_decl
== DECL_RESERV (start_decl
))
2777 else if (REGEXP_RESERV (regexp
)->reserv_decl
->loop_pass_num
2778 == curr_loop_pass_num
)
2779 /* declaration has been processed. */
2783 REGEXP_RESERV (regexp
)->reserv_decl
->loop_pass_num
2784 = curr_loop_pass_num
;
2785 return loop_in_regexp (REGEXP_RESERV (regexp
)->reserv_decl
->regexp
,
2790 for (i
= 0; i
<REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
2791 if (loop_in_regexp (REGEXP_SEQUENCE (regexp
)->regexps
[i
], start_decl
))
2796 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
2797 if (loop_in_regexp (REGEXP_ALLOF (regexp
)->regexps
[i
], start_decl
))
2802 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
2803 if (loop_in_regexp (REGEXP_ONEOF (regexp
)->regexps
[i
], start_decl
))
2808 return loop_in_regexp (REGEXP_REPEAT (regexp
)->regexp
, start_decl
);
2818 /* The following function fixes errors "cycle in definition ...". The
2819 function uses function `loop_in_regexp' for that. */
2821 check_loops_in_regexps (void)
2826 for (i
= 0; i
< description
->decls_num
; i
++)
2828 decl
= description
->decls
[i
];
2829 if (decl
->mode
== dm_reserv
)
2830 DECL_RESERV (decl
)->loop_pass_num
= 0;
2832 for (i
= 0; i
< description
->decls_num
; i
++)
2834 decl
= description
->decls
[i
];
2835 curr_loop_pass_num
= i
;
2837 if (decl
->mode
== dm_reserv
)
2839 DECL_RESERV (decl
)->loop_pass_num
= curr_loop_pass_num
;
2840 if (loop_in_regexp (DECL_RESERV (decl
)->regexp
, decl
))
2842 gcc_assert (DECL_RESERV (decl
)->regexp
);
2843 error ("cycle in definition of reservation `%s'",
2844 DECL_RESERV (decl
)->name
);
2850 /* The function recursively processes IR of reservation and defines
2851 max and min cycle for reservation of unit. */
2853 process_regexp_cycles (regexp_t regexp
, int max_start_cycle
,
2854 int min_start_cycle
, int *max_finish_cycle
,
2855 int *min_finish_cycle
)
2859 switch (regexp
->mode
)
2862 if (REGEXP_UNIT (regexp
)->unit_decl
->max_occ_cycle_num
< max_start_cycle
)
2863 REGEXP_UNIT (regexp
)->unit_decl
->max_occ_cycle_num
= max_start_cycle
;
2864 if (REGEXP_UNIT (regexp
)->unit_decl
->min_occ_cycle_num
> min_start_cycle
2865 || REGEXP_UNIT (regexp
)->unit_decl
->min_occ_cycle_num
== -1)
2866 REGEXP_UNIT (regexp
)->unit_decl
->min_occ_cycle_num
= min_start_cycle
;
2867 *max_finish_cycle
= max_start_cycle
;
2868 *min_finish_cycle
= min_start_cycle
;
2872 process_regexp_cycles (REGEXP_RESERV (regexp
)->reserv_decl
->regexp
,
2873 max_start_cycle
, min_start_cycle
,
2874 max_finish_cycle
, min_finish_cycle
);
2878 for (i
= 0; i
< REGEXP_REPEAT (regexp
)->repeat_num
; i
++)
2880 process_regexp_cycles (REGEXP_REPEAT (regexp
)->regexp
,
2881 max_start_cycle
, min_start_cycle
,
2882 max_finish_cycle
, min_finish_cycle
);
2883 max_start_cycle
= *max_finish_cycle
+ 1;
2884 min_start_cycle
= *min_finish_cycle
+ 1;
2889 for (i
= 0; i
<REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
2891 process_regexp_cycles (REGEXP_SEQUENCE (regexp
)->regexps
[i
],
2892 max_start_cycle
, min_start_cycle
,
2893 max_finish_cycle
, min_finish_cycle
);
2894 max_start_cycle
= *max_finish_cycle
+ 1;
2895 min_start_cycle
= *min_finish_cycle
+ 1;
2904 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
2906 process_regexp_cycles (REGEXP_ALLOF (regexp
)->regexps
[i
],
2907 max_start_cycle
, min_start_cycle
,
2908 max_finish_cycle
, min_finish_cycle
);
2909 if (max_cycle
< *max_finish_cycle
)
2910 max_cycle
= *max_finish_cycle
;
2911 if (i
== 0 || min_cycle
> *min_finish_cycle
)
2912 min_cycle
= *min_finish_cycle
;
2914 *max_finish_cycle
= max_cycle
;
2915 *min_finish_cycle
= min_cycle
;
2924 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
2926 process_regexp_cycles (REGEXP_ONEOF (regexp
)->regexps
[i
],
2927 max_start_cycle
, min_start_cycle
,
2928 max_finish_cycle
, min_finish_cycle
);
2929 if (max_cycle
< *max_finish_cycle
)
2930 max_cycle
= *max_finish_cycle
;
2931 if (i
== 0 || min_cycle
> *min_finish_cycle
)
2932 min_cycle
= *min_finish_cycle
;
2934 *max_finish_cycle
= max_cycle
;
2935 *min_finish_cycle
= min_cycle
;
2940 *max_finish_cycle
= max_start_cycle
;
2941 *min_finish_cycle
= min_start_cycle
;
2949 /* The following function is called only for correct program. The
2950 function defines max reservation of insns in cycles. */
2952 evaluate_max_reserv_cycles (void)
2954 int max_insn_cycles_num
;
2955 int min_insn_cycles_num
;
2959 description
->max_insn_reserv_cycles
= 0;
2960 for (i
= 0; i
< description
->decls_num
; i
++)
2962 decl
= description
->decls
[i
];
2963 if (decl
->mode
== dm_insn_reserv
)
2965 process_regexp_cycles (DECL_INSN_RESERV (decl
)->regexp
, 0, 0,
2966 &max_insn_cycles_num
, &min_insn_cycles_num
);
2967 if (description
->max_insn_reserv_cycles
< max_insn_cycles_num
)
2968 description
->max_insn_reserv_cycles
= max_insn_cycles_num
;
2971 description
->max_insn_reserv_cycles
++;
2974 /* The following function calls functions for checking all
2977 check_all_description (void)
2980 check_automaton_usage ();
2981 process_regexp_decls ();
2983 check_loops_in_regexps ();
2985 evaluate_max_reserv_cycles ();
2990 /* The page contains abstract data `ticker'. This data is used to
2991 report time of different phases of building automata. It is
2992 possibly to write a description for which automata will be built
2993 during several minutes even on fast machine. */
2995 /* The following function creates ticker and makes it active. */
2997 create_ticker (void)
3001 ticker
.modified_creation_time
= get_run_time ();
3002 ticker
.incremented_off_time
= 0;
3006 /* The following function switches off given ticker. */
3008 ticker_off (ticker_t
*ticker
)
3010 if (ticker
->incremented_off_time
== 0)
3011 ticker
->incremented_off_time
= get_run_time () + 1;
3014 /* The following function switches on given ticker. */
3016 ticker_on (ticker_t
*ticker
)
3018 if (ticker
->incremented_off_time
!= 0)
3020 ticker
->modified_creation_time
3021 += get_run_time () - ticker
->incremented_off_time
+ 1;
3022 ticker
->incremented_off_time
= 0;
3026 /* The following function returns current time in milliseconds since
3027 the moment when given ticker was created. */
3029 active_time (ticker_t ticker
)
3031 if (ticker
.incremented_off_time
!= 0)
3032 return ticker
.incremented_off_time
- 1 - ticker
.modified_creation_time
;
3034 return get_run_time () - ticker
.modified_creation_time
;
3037 /* The following function returns string representation of active time
3038 of given ticker. The result is string representation of seconds
3039 with accuracy of 1/100 second. Only result of the last call of the
3040 function exists. Therefore the following code is not correct
3042 printf ("parser time: %s\ngeneration time: %s\n",
3043 active_time_string (parser_ticker),
3044 active_time_string (generation_ticker));
3046 Correct code has to be the following
3048 printf ("parser time: %s\n", active_time_string (parser_ticker));
3049 printf ("generation time: %s\n",
3050 active_time_string (generation_ticker));
3054 print_active_time (FILE *f
, ticker_t ticker
)
3058 msecs
= active_time (ticker
);
3059 fprintf (f
, "%d.%06d", msecs
/ 1000000, msecs
% 1000000);
3064 /* The following variable value is number of automaton which are
3065 really being created. This value is defined on the base of
3066 argument of option `-split'. If the variable has zero value the
3067 number of automata is defined by the constructions `%automaton'.
3068 This case occurs when option `-split' is absent or has zero
3069 argument. If constructions `define_automaton' is absent only one
3070 automaton is created. */
3071 static int automata_num
;
3073 /* The following variable values are times of
3074 o transformation of regular expressions
3075 o building NDFA (DFA if !ndfa_flag)
3076 o NDFA -> DFA (simply the same automaton if !ndfa_flag)
3078 o building insn equivalence classes
3081 static ticker_t transform_time
;
3082 static ticker_t NDFA_time
;
3083 static ticker_t NDFA_to_DFA_time
;
3084 static ticker_t minimize_time
;
3085 static ticker_t equiv_time
;
3086 static ticker_t automaton_generation_time
;
3087 static ticker_t output_time
;
3089 /* The following variable values are times of
3092 all pipeline hazard translator work */
3093 static ticker_t check_time
;
3094 static ticker_t generation_time
;
3095 static ticker_t all_time
;
3099 /* Pseudo insn decl which denotes advancing cycle. */
3100 static decl_t advance_cycle_insn_decl
;
3102 add_advance_cycle_insn_decl (void)
3104 advance_cycle_insn_decl
= create_node (sizeof (struct decl
));
3105 advance_cycle_insn_decl
->mode
= dm_insn_reserv
;
3106 advance_cycle_insn_decl
->pos
= no_pos
;
3107 DECL_INSN_RESERV (advance_cycle_insn_decl
)->regexp
= NULL
;
3108 DECL_INSN_RESERV (advance_cycle_insn_decl
)->name
= "$advance_cycle";
3109 DECL_INSN_RESERV (advance_cycle_insn_decl
)->insn_num
3110 = description
->insns_num
;
3111 description
->decls
[description
->decls_num
] = advance_cycle_insn_decl
;
3112 description
->decls_num
++;
3113 description
->insns_num
++;
3117 /* Abstract data `alternative states' which represents
3118 nondeterministic nature of the description (see comments for
3119 structures alt_state and state). */
3121 /* List of free states. */
3122 static alt_state_t first_free_alt_state
;
3125 /* The following variables is maximal number of allocated nodes
3127 static int allocated_alt_states_num
= 0;
3130 /* The following function returns free node alt_state. It may be new
3131 allocated node or node freed earlier. */
3133 get_free_alt_state (void)
3137 if (first_free_alt_state
!= NULL
)
3139 result
= first_free_alt_state
;
3140 first_free_alt_state
= first_free_alt_state
->next_alt_state
;
3145 allocated_alt_states_num
++;
3147 result
= create_node (sizeof (struct alt_state
));
3149 result
->state
= NULL
;
3150 result
->next_alt_state
= NULL
;
3151 result
->next_sorted_alt_state
= NULL
;
3155 /* The function frees node ALT_STATE. */
3157 free_alt_state (alt_state_t alt_state
)
3159 if (alt_state
== NULL
)
3161 alt_state
->next_alt_state
= first_free_alt_state
;
3162 first_free_alt_state
= alt_state
;
3165 /* The function frees list started with node ALT_STATE_LIST. */
3167 free_alt_states (alt_state_t alt_states_list
)
3169 alt_state_t curr_alt_state
;
3170 alt_state_t next_alt_state
;
3172 for (curr_alt_state
= alt_states_list
;
3173 curr_alt_state
!= NULL
;
3174 curr_alt_state
= next_alt_state
)
3176 next_alt_state
= curr_alt_state
->next_alt_state
;
3177 free_alt_state (curr_alt_state
);
3181 /* The function compares unique numbers of alt states. */
3183 alt_state_cmp (const void *alt_state_ptr_1
, const void *alt_state_ptr_2
)
3185 if ((*(alt_state_t
*) alt_state_ptr_1
)->state
->unique_num
3186 == (*(alt_state_t
*) alt_state_ptr_2
)->state
->unique_num
)
3188 else if ((*(alt_state_t
*) alt_state_ptr_1
)->state
->unique_num
3189 < (*(alt_state_t
*) alt_state_ptr_2
)->state
->unique_num
)
3195 /* The function sorts ALT_STATES_LIST and removes duplicated alt
3196 states from the list. The comparison key is alt state unique
3200 uniq_sort_alt_states (alt_state_t alt_states_list
)
3202 alt_state_t curr_alt_state
;
3203 VEC(alt_state_t
,heap
) *alt_states
;
3205 size_t prev_unique_state_ind
;
3208 if (alt_states_list
== 0)
3210 if (alt_states_list
->next_alt_state
== 0)
3211 return alt_states_list
;
3213 alt_states
= VEC_alloc (alt_state_t
,heap
, 150);
3214 for (curr_alt_state
= alt_states_list
;
3215 curr_alt_state
!= NULL
;
3216 curr_alt_state
= curr_alt_state
->next_alt_state
)
3217 VEC_safe_push (alt_state_t
,heap
, alt_states
, curr_alt_state
);
3219 qsort (VEC_address (alt_state_t
, alt_states
),
3220 VEC_length (alt_state_t
, alt_states
),
3221 sizeof (alt_state_t
), alt_state_cmp
);
3223 prev_unique_state_ind
= 0;
3224 for (i
= 1; i
< VEC_length (alt_state_t
, alt_states
); i
++)
3225 if (VEC_index (alt_state_t
, alt_states
, prev_unique_state_ind
)->state
3226 != VEC_index (alt_state_t
, alt_states
, i
)->state
)
3228 prev_unique_state_ind
++;
3229 VEC_replace (alt_state_t
, alt_states
, prev_unique_state_ind
,
3230 VEC_index (alt_state_t
, alt_states
, i
));
3232 VEC_truncate (alt_state_t
, alt_states
, prev_unique_state_ind
+ 1);
3234 for (i
= 1; i
< VEC_length (alt_state_t
, alt_states
); i
++)
3235 VEC_index (alt_state_t
, alt_states
, i
-1)->next_sorted_alt_state
3236 = VEC_index (alt_state_t
, alt_states
, i
);
3237 VEC_last (alt_state_t
, alt_states
)->next_sorted_alt_state
= 0;
3239 result
= VEC_index (alt_state_t
, alt_states
, 0);
3241 VEC_free (alt_state_t
,heap
, alt_states
);
3245 /* The function checks equality of alt state lists. Remember that the
3246 lists must be already sorted by the previous function. */
3248 alt_states_eq (alt_state_t alt_states_1
, alt_state_t alt_states_2
)
3250 while (alt_states_1
!= NULL
&& alt_states_2
!= NULL
3251 && alt_state_cmp (&alt_states_1
, &alt_states_2
) == 0)
3253 alt_states_1
= alt_states_1
->next_sorted_alt_state
;
3254 alt_states_2
= alt_states_2
->next_sorted_alt_state
;
3256 return alt_states_1
== alt_states_2
;
3259 /* Initialization of the abstract data. */
3261 initiate_alt_states (void)
3263 first_free_alt_state
= NULL
;
3266 /* Finishing work with the abstract data. */
3268 finish_alt_states (void)
3274 /* The page contains macros for work with bits strings. We could use
3275 standard gcc bitmap or sbitmap but it would result in difficulties
3276 of building canadian cross. */
3278 /* Set bit number bitno in the bit string. The macro is not side
3280 #define SET_BIT(bitstring, bitno) \
3281 (((char *) (bitstring)) [(bitno) / CHAR_BIT] |= 1 << (bitno) % CHAR_BIT)
3283 #define CLEAR_BIT(bitstring, bitno) \
3284 (((char *) (bitstring)) [(bitno) / CHAR_BIT] &= ~(1 << (bitno) % CHAR_BIT))
3286 /* Test if bit number bitno in the bitstring is set. The macro is not
3287 side effect proof. */
3288 #define TEST_BIT(bitstring, bitno) \
3289 (((char *) (bitstring)) [(bitno) / CHAR_BIT] >> (bitno) % CHAR_BIT & 1)
3293 /* This page contains abstract data `state'. */
3295 /* Maximal length of reservations in cycles (>= 1). */
3296 static int max_cycles_num
;
3298 /* Number of set elements (see type set_el_t) needed for
3299 representation of one cycle reservation. It is depended on units
3301 static int els_in_cycle_reserv
;
3303 /* Number of set elements (see type set_el_t) needed for
3304 representation of maximal length reservation. Deterministic
3305 reservation is stored as set (bit string) of length equal to the
3306 variable value * number of bits in set_el_t. */
3307 static int els_in_reservs
;
3309 /* Array of pointers to unit declarations. */
3310 static unit_decl_t
*units_array
;
3312 /* Temporary reservation of maximal length. */
3313 static reserv_sets_t temp_reserv
;
3315 /* The state table itself is represented by the following variable. */
3316 static htab_t state_table
;
3318 /* Linked list of free 'state' structures to be recycled. The
3319 next_equiv_class_state pointer is borrowed for a free list. */
3320 static state_t first_free_state
;
3322 static int curr_unique_state_num
;
3325 /* The following variables is maximal number of allocated nodes
3327 static int allocated_states_num
= 0;
3330 /* Allocate new reservation set. */
3331 static reserv_sets_t
3332 alloc_empty_reserv_sets (void)
3334 reserv_sets_t result
;
3336 obstack_blank (&irp
, els_in_reservs
* sizeof (set_el_t
));
3337 result
= (reserv_sets_t
) obstack_base (&irp
);
3338 obstack_finish (&irp
);
3339 memset (result
, 0, els_in_reservs
* sizeof (set_el_t
));
3343 /* Hash value of reservation set. */
3345 reserv_sets_hash_value (reserv_sets_t reservs
)
3347 set_el_t hash_value
;
3350 set_el_t
*reserv_ptr
;
3353 reservs_num
= els_in_reservs
;
3354 reserv_ptr
= reservs
;
3356 while (reservs_num
!= 0)
3359 hash_value
+= ((*reserv_ptr
>> i
)
3360 | (*reserv_ptr
<< (sizeof (set_el_t
) * CHAR_BIT
- i
)));
3362 if (i
== sizeof (set_el_t
) * CHAR_BIT
)
3366 if (sizeof (set_el_t
) <= sizeof (unsigned))
3369 for (i
= sizeof (set_el_t
); i
> 0; i
-= sizeof (unsigned) - 1)
3371 result
+= (unsigned) hash_value
;
3372 hash_value
>>= (sizeof (unsigned) - 1) * CHAR_BIT
;
3377 /* Comparison of given reservation sets. */
3379 reserv_sets_cmp (reserv_sets_t reservs_1
, reserv_sets_t reservs_2
)
3382 set_el_t
*reserv_ptr_1
;
3383 set_el_t
*reserv_ptr_2
;
3385 gcc_assert (reservs_1
&& reservs_2
);
3386 reservs_num
= els_in_reservs
;
3387 reserv_ptr_1
= reservs_1
;
3388 reserv_ptr_2
= reservs_2
;
3389 while (reservs_num
!= 0 && *reserv_ptr_1
== *reserv_ptr_2
)
3395 if (reservs_num
== 0)
3397 else if (*reserv_ptr_1
< *reserv_ptr_2
)
3403 /* The function checks equality of the reservation sets. */
3405 reserv_sets_eq (reserv_sets_t reservs_1
, reserv_sets_t reservs_2
)
3407 return reserv_sets_cmp (reservs_1
, reservs_2
) == 0;
3410 /* Set up in the reservation set that unit with UNIT_NUM is used on
3413 set_unit_reserv (reserv_sets_t reservs
, int cycle_num
, int unit_num
)
3415 gcc_assert (cycle_num
< max_cycles_num
);
3416 SET_BIT (reservs
, cycle_num
* els_in_cycle_reserv
3417 * sizeof (set_el_t
) * CHAR_BIT
+ unit_num
);
3420 /* Set up in the reservation set RESERVS that unit with UNIT_NUM is
3421 used on CYCLE_NUM. */
3423 test_unit_reserv (reserv_sets_t reservs
, int cycle_num
, int unit_num
)
3425 gcc_assert (cycle_num
< max_cycles_num
);
3426 return TEST_BIT (reservs
, cycle_num
* els_in_cycle_reserv
3427 * sizeof (set_el_t
) * CHAR_BIT
+ unit_num
);
3430 /* The function checks that the reservation sets are intersected,
3431 i.e. there is a unit reservation on a cycle in both reservation
3434 reserv_sets_are_intersected (reserv_sets_t operand_1
,
3435 reserv_sets_t operand_2
)
3439 set_el_t
*cycle_ptr_1
;
3440 set_el_t
*cycle_ptr_2
;
3442 gcc_assert (operand_1
&& operand_2
);
3443 for (el_ptr_1
= operand_1
, el_ptr_2
= operand_2
;
3444 el_ptr_1
< operand_1
+ els_in_reservs
;
3445 el_ptr_1
++, el_ptr_2
++)
3446 if (*el_ptr_1
& *el_ptr_2
)
3448 reserv_sets_or (temp_reserv
, operand_1
, operand_2
);
3449 for (cycle_ptr_1
= operand_1
, cycle_ptr_2
= operand_2
;
3450 cycle_ptr_1
< operand_1
+ els_in_reservs
;
3451 cycle_ptr_1
+= els_in_cycle_reserv
, cycle_ptr_2
+= els_in_cycle_reserv
)
3453 for (el_ptr_1
= cycle_ptr_1
, el_ptr_2
= get_excl_set (cycle_ptr_2
);
3454 el_ptr_1
< cycle_ptr_1
+ els_in_cycle_reserv
;
3455 el_ptr_1
++, el_ptr_2
++)
3456 if (*el_ptr_1
& *el_ptr_2
)
3458 if (!check_presence_pattern_sets (cycle_ptr_1
, cycle_ptr_2
, FALSE
))
3460 if (!check_presence_pattern_sets (temp_reserv
+ (cycle_ptr_2
3464 if (!check_absence_pattern_sets (cycle_ptr_1
, cycle_ptr_2
, FALSE
))
3466 if (!check_absence_pattern_sets (temp_reserv
+ (cycle_ptr_2
- operand_2
),
3473 /* The function sets up RESULT bits by bits of OPERAND shifted on one
3474 cpu cycle. The remaining bits of OPERAND (representing the last
3475 cycle unit reservations) are not changed. */
3477 reserv_sets_shift (reserv_sets_t result
, reserv_sets_t operand
)
3481 gcc_assert (result
&& operand
&& result
!= operand
);
3482 for (i
= els_in_cycle_reserv
; i
< els_in_reservs
; i
++)
3483 result
[i
- els_in_cycle_reserv
] = operand
[i
];
3486 /* OR of the reservation sets. */
3488 reserv_sets_or (reserv_sets_t result
, reserv_sets_t operand_1
,
3489 reserv_sets_t operand_2
)
3493 set_el_t
*result_set_el_ptr
;
3495 gcc_assert (result
&& operand_1
&& operand_2
);
3496 for (el_ptr_1
= operand_1
, el_ptr_2
= operand_2
, result_set_el_ptr
= result
;
3497 el_ptr_1
< operand_1
+ els_in_reservs
;
3498 el_ptr_1
++, el_ptr_2
++, result_set_el_ptr
++)
3499 *result_set_el_ptr
= *el_ptr_1
| *el_ptr_2
;
3502 /* AND of the reservation sets. */
3504 reserv_sets_and (reserv_sets_t result
, reserv_sets_t operand_1
,
3505 reserv_sets_t operand_2
)
3509 set_el_t
*result_set_el_ptr
;
3511 gcc_assert (result
&& operand_1
&& operand_2
);
3512 for (el_ptr_1
= operand_1
, el_ptr_2
= operand_2
, result_set_el_ptr
= result
;
3513 el_ptr_1
< operand_1
+ els_in_reservs
;
3514 el_ptr_1
++, el_ptr_2
++, result_set_el_ptr
++)
3515 *result_set_el_ptr
= *el_ptr_1
& *el_ptr_2
;
3518 /* The function outputs string representation of units reservation on
3519 cycle START_CYCLE in the reservation set. The function uses repeat
3520 construction if REPETITION_NUM > 1. */
3522 output_cycle_reservs (FILE *f
, reserv_sets_t reservs
, int start_cycle
,
3526 int reserved_units_num
;
3528 reserved_units_num
= 0;
3529 for (unit_num
= 0; unit_num
< description
->units_num
; unit_num
++)
3530 if (TEST_BIT (reservs
, start_cycle
* els_in_cycle_reserv
3531 * sizeof (set_el_t
) * CHAR_BIT
+ unit_num
))
3532 reserved_units_num
++;
3533 gcc_assert (repetition_num
> 0);
3534 if (repetition_num
!= 1 && reserved_units_num
> 1)
3536 reserved_units_num
= 0;
3538 unit_num
< description
->units_num
;
3540 if (TEST_BIT (reservs
, start_cycle
* els_in_cycle_reserv
3541 * sizeof (set_el_t
) * CHAR_BIT
+ unit_num
))
3543 if (reserved_units_num
!= 0)
3545 reserved_units_num
++;
3546 fprintf (f
, "%s", units_array
[unit_num
]->name
);
3548 if (reserved_units_num
== 0)
3549 fprintf (f
, NOTHING_NAME
);
3550 gcc_assert (repetition_num
> 0);
3551 if (repetition_num
!= 1 && reserved_units_num
> 1)
3553 if (repetition_num
!= 1)
3554 fprintf (f
, "*%d", repetition_num
);
3557 /* The function outputs string representation of units reservation in
3558 the reservation set. */
3560 output_reserv_sets (FILE *f
, reserv_sets_t reservs
)
3562 int start_cycle
= 0;
3567 for (cycle
= 0; cycle
< max_cycles_num
; cycle
++)
3568 if (repetition_num
== 0)
3571 start_cycle
= cycle
;
3574 ((char *) reservs
+ start_cycle
* els_in_cycle_reserv
3575 * sizeof (set_el_t
),
3576 (char *) reservs
+ cycle
* els_in_cycle_reserv
3577 * sizeof (set_el_t
),
3578 els_in_cycle_reserv
* sizeof (set_el_t
)) == 0)
3582 if (start_cycle
!= 0)
3584 output_cycle_reservs (f
, reservs
, start_cycle
, repetition_num
);
3586 start_cycle
= cycle
;
3588 if (start_cycle
< max_cycles_num
)
3590 if (start_cycle
!= 0)
3592 output_cycle_reservs (f
, reservs
, start_cycle
, repetition_num
);
3596 /* The following function returns free node state for AUTOMATON. It
3597 may be new allocated node or node freed earlier. The function also
3598 allocates reservation set if WITH_RESERVS has nonzero value. */
3600 get_free_state (int with_reservs
, automaton_t automaton
)
3604 gcc_assert (max_cycles_num
> 0 && automaton
);
3605 if (first_free_state
)
3607 result
= first_free_state
;
3608 first_free_state
= result
->next_equiv_class_state
;
3610 result
->next_equiv_class_state
= NULL
;
3611 result
->automaton
= automaton
;
3612 result
->first_out_arc
= NULL
;
3613 result
->it_was_placed_in_stack_for_NDFA_forming
= 0;
3614 result
->it_was_placed_in_stack_for_DFA_forming
= 0;
3615 result
->component_states
= NULL
;
3620 allocated_states_num
++;
3622 result
= create_node (sizeof (struct state
));
3623 result
->automaton
= automaton
;
3624 result
->first_out_arc
= NULL
;
3625 result
->unique_num
= curr_unique_state_num
;
3626 curr_unique_state_num
++;
3630 if (result
->reservs
== NULL
)
3631 result
->reservs
= alloc_empty_reserv_sets ();
3633 memset (result
->reservs
, 0, els_in_reservs
* sizeof (set_el_t
));
3638 /* The function frees node STATE. */
3640 free_state (state_t state
)
3642 free_alt_states (state
->component_states
);
3643 state
->next_equiv_class_state
= first_free_state
;
3644 first_free_state
= state
;
3647 /* Hash value of STATE. If STATE represents deterministic state it is
3648 simply hash value of the corresponding reservation set. Otherwise
3649 it is formed from hash values of the component deterministic
3650 states. One more key is order number of state automaton. */
3652 state_hash (const void *state
)
3654 unsigned int hash_value
;
3655 alt_state_t alt_state
;
3657 if (((state_t
) state
)->component_states
== NULL
)
3658 hash_value
= reserv_sets_hash_value (((state_t
) state
)->reservs
);
3662 for (alt_state
= ((state_t
) state
)->component_states
;
3664 alt_state
= alt_state
->next_sorted_alt_state
)
3665 hash_value
= (((hash_value
>> (sizeof (unsigned) - 1) * CHAR_BIT
)
3666 | (hash_value
<< CHAR_BIT
))
3667 + alt_state
->state
->unique_num
);
3669 hash_value
= (((hash_value
>> (sizeof (unsigned) - 1) * CHAR_BIT
)
3670 | (hash_value
<< CHAR_BIT
))
3671 + ((state_t
) state
)->automaton
->automaton_order_num
);
3675 /* Return nonzero value if the states are the same. */
3677 state_eq_p (const void *state_1
, const void *state_2
)
3679 alt_state_t alt_state_1
;
3680 alt_state_t alt_state_2
;
3682 if (((state_t
) state_1
)->automaton
!= ((state_t
) state_2
)->automaton
)
3684 else if (((state_t
) state_1
)->component_states
== NULL
3685 && ((state_t
) state_2
)->component_states
== NULL
)
3686 return reserv_sets_eq (((state_t
) state_1
)->reservs
,
3687 ((state_t
) state_2
)->reservs
);
3688 else if (((state_t
) state_1
)->component_states
!= NULL
3689 && ((state_t
) state_2
)->component_states
!= NULL
)
3691 for (alt_state_1
= ((state_t
) state_1
)->component_states
,
3692 alt_state_2
= ((state_t
) state_2
)->component_states
;
3693 alt_state_1
!= NULL
&& alt_state_2
!= NULL
;
3694 alt_state_1
= alt_state_1
->next_sorted_alt_state
,
3695 alt_state_2
= alt_state_2
->next_sorted_alt_state
)
3696 /* All state in the list must be already in the hash table.
3697 Also the lists must be sorted. */
3698 if (alt_state_1
->state
!= alt_state_2
->state
)
3700 return alt_state_1
== alt_state_2
;
3706 /* Insert STATE into the state table. */
3708 insert_state (state_t state
)
3712 entry_ptr
= htab_find_slot (state_table
, (void *) state
, 1);
3713 if (*entry_ptr
== NULL
)
3714 *entry_ptr
= (void *) state
;
3715 return (state_t
) *entry_ptr
;
3718 /* Add reservation of unit with UNIT_NUM on cycle CYCLE_NUM to
3719 deterministic STATE. */
3721 set_state_reserv (state_t state
, int cycle_num
, int unit_num
)
3723 set_unit_reserv (state
->reservs
, cycle_num
, unit_num
);
3726 /* Return nonzero value if the deterministic states contains a
3727 reservation of the same cpu unit on the same cpu cycle. */
3729 intersected_state_reservs_p (state_t state1
, state_t state2
)
3731 gcc_assert (state1
->automaton
== state2
->automaton
);
3732 return reserv_sets_are_intersected (state1
->reservs
, state2
->reservs
);
3735 /* Return deterministic state (inserted into the table) which
3736 representing the automaton state which is union of reservations of
3737 the deterministic states masked by RESERVS. */
3739 states_union (state_t state1
, state_t state2
, reserv_sets_t reservs
)
3742 state_t state_in_table
;
3744 gcc_assert (state1
->automaton
== state2
->automaton
);
3745 result
= get_free_state (1, state1
->automaton
);
3746 reserv_sets_or (result
->reservs
, state1
->reservs
, state2
->reservs
);
3747 reserv_sets_and (result
->reservs
, result
->reservs
, reservs
);
3748 state_in_table
= insert_state (result
);
3749 if (result
!= state_in_table
)
3751 free_state (result
);
3752 result
= state_in_table
;
3757 /* Return deterministic state (inserted into the table) which
3758 represent the automaton state is obtained from deterministic STATE
3759 by advancing cpu cycle and masking by RESERVS. */
3761 state_shift (state_t state
, reserv_sets_t reservs
)
3764 state_t state_in_table
;
3766 result
= get_free_state (1, state
->automaton
);
3767 reserv_sets_shift (result
->reservs
, state
->reservs
);
3768 reserv_sets_and (result
->reservs
, result
->reservs
, reservs
);
3769 state_in_table
= insert_state (result
);
3770 if (result
!= state_in_table
)
3772 free_state (result
);
3773 result
= state_in_table
;
3778 /* Initialization of the abstract data. */
3780 initiate_states (void)
3785 if (description
->units_num
)
3786 units_array
= XNEWVEC (unit_decl_t
, description
->units_num
);
3790 for (i
= 0; i
< description
->decls_num
; i
++)
3792 decl
= description
->decls
[i
];
3793 if (decl
->mode
== dm_unit
)
3794 units_array
[DECL_UNIT (decl
)->unit_num
] = DECL_UNIT (decl
);
3796 max_cycles_num
= description
->max_insn_reserv_cycles
;
3798 = ((description
->units_num
+ sizeof (set_el_t
) * CHAR_BIT
- 1)
3799 / (sizeof (set_el_t
) * CHAR_BIT
));
3800 els_in_reservs
= els_in_cycle_reserv
* max_cycles_num
;
3801 curr_unique_state_num
= 0;
3802 initiate_alt_states ();
3803 state_table
= htab_create (1500, state_hash
, state_eq_p
, (htab_del
) 0);
3804 temp_reserv
= alloc_empty_reserv_sets ();
3807 /* Finishing work with the abstract data. */
3809 finish_states (void)
3813 htab_delete (state_table
);
3814 first_free_state
= NULL
;
3815 finish_alt_states ();
3820 /* Abstract data `arcs'. */
3822 /* List of free arcs. */
3823 static arc_t first_free_arc
;
3826 /* The following variables is maximal number of allocated nodes
3828 static int allocated_arcs_num
= 0;
3831 /* The function frees node ARC. */
3833 free_arc (arc_t arc
)
3835 arc
->next_out_arc
= first_free_arc
;
3836 first_free_arc
= arc
;
3839 /* The function removes and frees ARC staring from FROM_STATE. */
3841 remove_arc (state_t from_state
, arc_t arc
)
3847 for (prev_arc
= NULL
, curr_arc
= from_state
->first_out_arc
;
3849 prev_arc
= curr_arc
, curr_arc
= curr_arc
->next_out_arc
)
3850 if (curr_arc
== arc
)
3852 gcc_assert (curr_arc
);
3853 if (prev_arc
== NULL
)
3854 from_state
->first_out_arc
= arc
->next_out_arc
;
3856 prev_arc
->next_out_arc
= arc
->next_out_arc
;
3857 from_state
->num_out_arcs
--;
3861 /* The functions returns arc with given characteristics (or NULL if
3862 the arc does not exist). */
3864 find_arc (state_t from_state
, state_t to_state
, ainsn_t insn
)
3868 for (arc
= first_out_arc (from_state
); arc
!= NULL
; arc
= next_out_arc (arc
))
3869 if (arc
->to_state
== to_state
&& arc
->insn
== insn
)
3874 /* The function adds arc from FROM_STATE to TO_STATE marked by AINSN.
3875 The function returns added arc (or already existing arc). */
3877 add_arc (state_t from_state
, state_t to_state
, ainsn_t ainsn
)
3881 new_arc
= find_arc (from_state
, to_state
, ainsn
);
3882 if (new_arc
!= NULL
)
3884 if (first_free_arc
== NULL
)
3887 allocated_arcs_num
++;
3889 new_arc
= create_node (sizeof (struct arc
));
3890 new_arc
->to_state
= NULL
;
3891 new_arc
->insn
= NULL
;
3892 new_arc
->next_out_arc
= NULL
;
3896 new_arc
= first_free_arc
;
3897 first_free_arc
= first_free_arc
->next_out_arc
;
3899 new_arc
->to_state
= to_state
;
3900 new_arc
->insn
= ainsn
;
3901 ainsn
->arc_exists_p
= 1;
3902 new_arc
->next_out_arc
= from_state
->first_out_arc
;
3903 from_state
->first_out_arc
= new_arc
;
3904 from_state
->num_out_arcs
++;
3905 new_arc
->next_arc_marked_by_insn
= NULL
;
3909 /* The function returns the first arc starting from STATE. */
3911 first_out_arc (state_t state
)
3913 return state
->first_out_arc
;
3916 /* The function returns next out arc after ARC. */
3918 next_out_arc (arc_t arc
)
3920 return arc
->next_out_arc
;
3923 /* Initialization of the abstract data. */
3925 initiate_arcs (void)
3927 first_free_arc
= NULL
;
3930 /* Finishing work with the abstract data. */
3938 /* Abstract data `automata lists'. */
3940 /* List of free states. */
3941 static automata_list_el_t first_free_automata_list_el
;
3943 /* The list being formed. */
3944 static automata_list_el_t current_automata_list
;
3946 /* Hash table of automata lists. */
3947 static htab_t automata_list_table
;
3949 /* The following function returns free automata list el. It may be
3950 new allocated node or node freed earlier. */
3951 static automata_list_el_t
3952 get_free_automata_list_el (void)
3954 automata_list_el_t result
;
3956 if (first_free_automata_list_el
!= NULL
)
3958 result
= first_free_automata_list_el
;
3959 first_free_automata_list_el
3960 = first_free_automata_list_el
->next_automata_list_el
;
3963 result
= create_node (sizeof (struct automata_list_el
));
3964 result
->automaton
= NULL
;
3965 result
->next_automata_list_el
= NULL
;
3969 /* The function frees node AUTOMATA_LIST_EL. */
3971 free_automata_list_el (automata_list_el_t automata_list_el
)
3973 if (automata_list_el
== NULL
)
3975 automata_list_el
->next_automata_list_el
= first_free_automata_list_el
;
3976 first_free_automata_list_el
= automata_list_el
;
3979 /* The function frees list AUTOMATA_LIST. */
3981 free_automata_list (automata_list_el_t automata_list
)
3983 automata_list_el_t curr_automata_list_el
;
3984 automata_list_el_t next_automata_list_el
;
3986 for (curr_automata_list_el
= automata_list
;
3987 curr_automata_list_el
!= NULL
;
3988 curr_automata_list_el
= next_automata_list_el
)
3990 next_automata_list_el
= curr_automata_list_el
->next_automata_list_el
;
3991 free_automata_list_el (curr_automata_list_el
);
3995 /* Hash value of AUTOMATA_LIST. */
3997 automata_list_hash (const void *automata_list
)
3999 unsigned int hash_value
;
4000 automata_list_el_t curr_automata_list_el
;
4003 for (curr_automata_list_el
= (automata_list_el_t
) automata_list
;
4004 curr_automata_list_el
!= NULL
;
4005 curr_automata_list_el
= curr_automata_list_el
->next_automata_list_el
)
4006 hash_value
= (((hash_value
>> (sizeof (unsigned) - 1) * CHAR_BIT
)
4007 | (hash_value
<< CHAR_BIT
))
4008 + curr_automata_list_el
->automaton
->automaton_order_num
);
4012 /* Return nonzero value if the automata_lists are the same. */
4014 automata_list_eq_p (const void *automata_list_1
, const void *automata_list_2
)
4016 automata_list_el_t automata_list_el_1
;
4017 automata_list_el_t automata_list_el_2
;
4019 for (automata_list_el_1
= (automata_list_el_t
) automata_list_1
,
4020 automata_list_el_2
= (automata_list_el_t
) automata_list_2
;
4021 automata_list_el_1
!= NULL
&& automata_list_el_2
!= NULL
;
4022 automata_list_el_1
= automata_list_el_1
->next_automata_list_el
,
4023 automata_list_el_2
= automata_list_el_2
->next_automata_list_el
)
4024 if (automata_list_el_1
->automaton
!= automata_list_el_2
->automaton
)
4026 return automata_list_el_1
== automata_list_el_2
;
4029 /* Initialization of the abstract data. */
4031 initiate_automata_lists (void)
4033 first_free_automata_list_el
= NULL
;
4034 automata_list_table
= htab_create (1500, automata_list_hash
,
4035 automata_list_eq_p
, (htab_del
) 0);
4038 /* The following function starts new automata list and makes it the
4041 automata_list_start (void)
4043 current_automata_list
= NULL
;
4046 /* The following function adds AUTOMATON to the current list. */
4048 automata_list_add (automaton_t automaton
)
4050 automata_list_el_t el
;
4052 el
= get_free_automata_list_el ();
4053 el
->automaton
= automaton
;
4054 el
->next_automata_list_el
= current_automata_list
;
4055 current_automata_list
= el
;
4058 /* The following function finishes forming the current list, inserts
4059 it into the table and returns it. */
4060 static automata_list_el_t
4061 automata_list_finish (void)
4065 if (current_automata_list
== NULL
)
4067 entry_ptr
= htab_find_slot (automata_list_table
,
4068 (void *) current_automata_list
, 1);
4069 if (*entry_ptr
== NULL
)
4070 *entry_ptr
= (void *) current_automata_list
;
4072 free_automata_list (current_automata_list
);
4073 current_automata_list
= NULL
;
4074 return (automata_list_el_t
) *entry_ptr
;
4077 /* Finishing work with the abstract data. */
4079 finish_automata_lists (void)
4081 htab_delete (automata_list_table
);
4086 /* The page contains abstract data for work with exclusion sets (see
4087 exclusion_set in file rtl.def). */
4089 /* The following variable refers to an exclusion set returned by
4090 get_excl_set. This is bit string of length equal to cpu units
4091 number. If exclusion set for given unit contains 1 for a unit,
4092 then simultaneous reservation of the units is prohibited. */
4093 static reserv_sets_t excl_set
;
4095 /* The array contains exclusion sets for each unit. */
4096 static reserv_sets_t
*unit_excl_set_table
;
4098 /* The following function forms the array containing exclusion sets
4101 initiate_excl_sets (void)
4104 reserv_sets_t unit_excl_set
;
4108 obstack_blank (&irp
, els_in_cycle_reserv
* sizeof (set_el_t
));
4109 excl_set
= (reserv_sets_t
) obstack_base (&irp
);
4110 obstack_finish (&irp
);
4111 obstack_blank (&irp
, description
->units_num
* sizeof (reserv_sets_t
));
4112 unit_excl_set_table
= (reserv_sets_t
*) obstack_base (&irp
);
4113 obstack_finish (&irp
);
4114 /* Evaluate unit exclusion sets. */
4115 for (i
= 0; i
< description
->decls_num
; i
++)
4117 decl
= description
->decls
[i
];
4118 if (decl
->mode
== dm_unit
)
4120 obstack_blank (&irp
, els_in_cycle_reserv
* sizeof (set_el_t
));
4121 unit_excl_set
= (reserv_sets_t
) obstack_base (&irp
);
4122 obstack_finish (&irp
);
4123 memset (unit_excl_set
, 0, els_in_cycle_reserv
* sizeof (set_el_t
));
4124 for (el
= DECL_UNIT (decl
)->excl_list
;
4126 el
= el
->next_unit_set_el
)
4128 SET_BIT (unit_excl_set
, el
->unit_decl
->unit_num
);
4129 el
->unit_decl
->in_set_p
= TRUE
;
4131 unit_excl_set_table
[DECL_UNIT (decl
)->unit_num
] = unit_excl_set
;
4136 /* The function sets up and return EXCL_SET which is union of
4137 exclusion sets for each unit in IN_SET. */
4138 static reserv_sets_t
4139 get_excl_set (reserv_sets_t in_set
)
4147 chars_num
= els_in_cycle_reserv
* sizeof (set_el_t
);
4148 memset (excl_set
, 0, chars_num
);
4149 for (excl_char_num
= 0; excl_char_num
< chars_num
; excl_char_num
++)
4150 if (((unsigned char *) in_set
) [excl_char_num
])
4151 for (i
= CHAR_BIT
- 1; i
>= 0; i
--)
4152 if ((((unsigned char *) in_set
) [excl_char_num
] >> i
) & 1)
4154 start_unit_num
= excl_char_num
* CHAR_BIT
+ i
;
4155 if (start_unit_num
>= description
->units_num
)
4157 for (unit_num
= 0; unit_num
< els_in_cycle_reserv
; unit_num
++)
4160 |= unit_excl_set_table
[start_unit_num
] [unit_num
];
4168 /* The page contains abstract data for work with presence/absence
4169 pattern sets (see presence_set/absence_set in file rtl.def). */
4171 /* The following arrays contain correspondingly presence, final
4172 presence, absence, and final absence patterns for each unit. */
4173 static pattern_reserv_t
*unit_presence_set_table
;
4174 static pattern_reserv_t
*unit_final_presence_set_table
;
4175 static pattern_reserv_t
*unit_absence_set_table
;
4176 static pattern_reserv_t
*unit_final_absence_set_table
;
4178 /* The following function forms list of reservation sets for given
4180 static pattern_reserv_t
4181 form_reserv_sets_list (pattern_set_el_t pattern_list
)
4183 pattern_set_el_t el
;
4184 pattern_reserv_t first
, curr
, prev
;
4187 prev
= first
= NULL
;
4188 for (el
= pattern_list
; el
!= NULL
; el
= el
->next_pattern_set_el
)
4190 curr
= create_node (sizeof (struct pattern_reserv
));
4191 curr
->reserv
= alloc_empty_reserv_sets ();
4192 curr
->next_pattern_reserv
= NULL
;
4193 for (i
= 0; i
< el
->units_num
; i
++)
4195 SET_BIT (curr
->reserv
, el
->unit_decls
[i
]->unit_num
);
4196 el
->unit_decls
[i
]->in_set_p
= TRUE
;
4199 prev
->next_pattern_reserv
= curr
;
4207 /* The following function forms the array containing presence and
4208 absence pattern sets for each unit. */
4210 initiate_presence_absence_pattern_sets (void)
4215 obstack_blank (&irp
, description
->units_num
* sizeof (pattern_reserv_t
));
4216 unit_presence_set_table
= (pattern_reserv_t
*) obstack_base (&irp
);
4217 obstack_finish (&irp
);
4218 obstack_blank (&irp
, description
->units_num
* sizeof (pattern_reserv_t
));
4219 unit_final_presence_set_table
= (pattern_reserv_t
*) obstack_base (&irp
);
4220 obstack_finish (&irp
);
4221 obstack_blank (&irp
, description
->units_num
* sizeof (pattern_reserv_t
));
4222 unit_absence_set_table
= (pattern_reserv_t
*) obstack_base (&irp
);
4223 obstack_finish (&irp
);
4224 obstack_blank (&irp
, description
->units_num
* sizeof (pattern_reserv_t
));
4225 unit_final_absence_set_table
= (pattern_reserv_t
*) obstack_base (&irp
);
4226 obstack_finish (&irp
);
4227 /* Evaluate unit presence/absence sets. */
4228 for (i
= 0; i
< description
->decls_num
; i
++)
4230 decl
= description
->decls
[i
];
4231 if (decl
->mode
== dm_unit
)
4233 unit_presence_set_table
[DECL_UNIT (decl
)->unit_num
]
4234 = form_reserv_sets_list (DECL_UNIT (decl
)->presence_list
);
4235 unit_final_presence_set_table
[DECL_UNIT (decl
)->unit_num
]
4236 = form_reserv_sets_list (DECL_UNIT (decl
)->final_presence_list
);
4237 unit_absence_set_table
[DECL_UNIT (decl
)->unit_num
]
4238 = form_reserv_sets_list (DECL_UNIT (decl
)->absence_list
);
4239 unit_final_absence_set_table
[DECL_UNIT (decl
)->unit_num
]
4240 = form_reserv_sets_list (DECL_UNIT (decl
)->final_absence_list
);
4245 /* The function checks that CHECKED_SET satisfies all presence pattern
4246 sets for units in ORIGIONAL_SET. The function returns TRUE if it
4249 check_presence_pattern_sets (reserv_sets_t checked_set
,
4250 reserv_sets_t origional_set
,
4259 pattern_reserv_t pat_reserv
;
4261 chars_num
= els_in_cycle_reserv
* sizeof (set_el_t
);
4262 for (char_num
= 0; char_num
< chars_num
; char_num
++)
4263 if (((unsigned char *) origional_set
) [char_num
])
4264 for (i
= CHAR_BIT
- 1; i
>= 0; i
--)
4265 if ((((unsigned char *) origional_set
) [char_num
] >> i
) & 1)
4267 start_unit_num
= char_num
* CHAR_BIT
+ i
;
4268 if (start_unit_num
>= description
->units_num
)
4271 && unit_final_presence_set_table
[start_unit_num
] == NULL
)
4273 && unit_presence_set_table
[start_unit_num
] == NULL
))
4276 for (pat_reserv
= (final_p
4277 ? unit_final_presence_set_table
[start_unit_num
]
4278 : unit_presence_set_table
[start_unit_num
]);
4280 pat_reserv
= pat_reserv
->next_pattern_reserv
)
4282 for (unit_num
= 0; unit_num
< els_in_cycle_reserv
; unit_num
++)
4283 if ((checked_set
[unit_num
] & pat_reserv
->reserv
[unit_num
])
4284 != pat_reserv
->reserv
[unit_num
])
4286 presence_p
= presence_p
|| unit_num
>= els_in_cycle_reserv
;
4294 /* The function checks that CHECKED_SET satisfies all absence pattern
4295 sets for units in ORIGIONAL_SET. The function returns TRUE if it
4298 check_absence_pattern_sets (reserv_sets_t checked_set
,
4299 reserv_sets_t origional_set
,
4307 pattern_reserv_t pat_reserv
;
4309 chars_num
= els_in_cycle_reserv
* sizeof (set_el_t
);
4310 for (char_num
= 0; char_num
< chars_num
; char_num
++)
4311 if (((unsigned char *) origional_set
) [char_num
])
4312 for (i
= CHAR_BIT
- 1; i
>= 0; i
--)
4313 if ((((unsigned char *) origional_set
) [char_num
] >> i
) & 1)
4315 start_unit_num
= char_num
* CHAR_BIT
+ i
;
4316 if (start_unit_num
>= description
->units_num
)
4318 for (pat_reserv
= (final_p
4319 ? unit_final_absence_set_table
[start_unit_num
]
4320 : unit_absence_set_table
[start_unit_num
]);
4322 pat_reserv
= pat_reserv
->next_pattern_reserv
)
4324 for (unit_num
= 0; unit_num
< els_in_cycle_reserv
; unit_num
++)
4325 if ((checked_set
[unit_num
] & pat_reserv
->reserv
[unit_num
])
4326 != pat_reserv
->reserv
[unit_num
]
4327 && pat_reserv
->reserv
[unit_num
])
4329 if (unit_num
>= els_in_cycle_reserv
)
4338 /* This page contains code for transformation of original reservations
4339 described in .md file. The main goal of transformations is
4340 simplifying reservation and lifting up all `|' on the top of IR
4341 reservation representation. */
4344 /* The following function makes copy of IR representation of
4345 reservation. The function also substitutes all reservations
4346 defined by define_reservation by corresponding value during making
4349 copy_insn_regexp (regexp_t regexp
)
4354 switch (regexp
->mode
)
4357 result
= copy_insn_regexp (REGEXP_RESERV (regexp
)->reserv_decl
->regexp
);
4361 result
= copy_node (regexp
, sizeof (struct regexp
));
4365 result
= copy_node (regexp
, sizeof (struct regexp
));
4366 REGEXP_REPEAT (result
)->regexp
4367 = copy_insn_regexp (REGEXP_REPEAT (regexp
)->regexp
);
4371 result
= copy_node (regexp
,
4372 sizeof (struct regexp
) + sizeof (regexp_t
)
4373 * (REGEXP_SEQUENCE (regexp
)->regexps_num
- 1));
4374 for (i
= 0; i
<REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
4375 REGEXP_SEQUENCE (result
)->regexps
[i
]
4376 = copy_insn_regexp (REGEXP_SEQUENCE (regexp
)->regexps
[i
]);
4380 result
= copy_node (regexp
,
4381 sizeof (struct regexp
) + sizeof (regexp_t
)
4382 * (REGEXP_ALLOF (regexp
)->regexps_num
- 1));
4383 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
4384 REGEXP_ALLOF (result
)->regexps
[i
]
4385 = copy_insn_regexp (REGEXP_ALLOF (regexp
)->regexps
[i
]);
4389 result
= copy_node (regexp
,
4390 sizeof (struct regexp
) + sizeof (regexp_t
)
4391 * (REGEXP_ONEOF (regexp
)->regexps_num
- 1));
4392 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
4393 REGEXP_ONEOF (result
)->regexps
[i
]
4394 = copy_insn_regexp (REGEXP_ONEOF (regexp
)->regexps
[i
]);
4398 result
= copy_node (regexp
, sizeof (struct regexp
));
4407 /* The following variable is set up 1 if a transformation has been
4409 static int regexp_transformed_p
;
4411 /* The function makes transformation
4414 transform_1 (regexp_t regexp
)
4421 if (regexp
->mode
== rm_repeat
)
4423 repeat_num
= REGEXP_REPEAT (regexp
)->repeat_num
;
4424 gcc_assert (repeat_num
> 1);
4425 operand
= REGEXP_REPEAT (regexp
)->regexp
;
4427 regexp
= create_node (sizeof (struct regexp
) + sizeof (regexp_t
)
4428 * (repeat_num
- 1));
4429 regexp
->mode
= rm_sequence
;
4431 REGEXP_SEQUENCE (regexp
)->regexps_num
= repeat_num
;
4432 for (i
= 0; i
< repeat_num
; i
++)
4433 REGEXP_SEQUENCE (regexp
)->regexps
[i
] = copy_insn_regexp (operand
);
4434 regexp_transformed_p
= 1;
4439 /* The function makes transformations
4440 ...,(A,B,...),C,... -> ...,A,B,...,C,...
4441 ...+(A+B+...)+C+... -> ...+A+B+...+C+...
4442 ...|(A|B|...)|C|... -> ...|A|B|...|C|... */
4444 transform_2 (regexp_t regexp
)
4446 if (regexp
->mode
== rm_sequence
)
4448 regexp_t sequence
= NULL
;
4450 int sequence_index
= 0;
4453 for (i
= 0; i
< REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
4454 if (REGEXP_SEQUENCE (regexp
)->regexps
[i
]->mode
== rm_sequence
)
4457 sequence
= REGEXP_SEQUENCE (regexp
)->regexps
[i
];
4460 if (i
< REGEXP_SEQUENCE (regexp
)->regexps_num
)
4462 gcc_assert (REGEXP_SEQUENCE (sequence
)->regexps_num
> 1
4463 && REGEXP_SEQUENCE (regexp
)->regexps_num
> 1);
4464 result
= create_node (sizeof (struct regexp
)
4466 * (REGEXP_SEQUENCE (regexp
)->regexps_num
4467 + REGEXP_SEQUENCE (sequence
)->regexps_num
4469 result
->mode
= rm_sequence
;
4470 result
->pos
= regexp
->pos
;
4471 REGEXP_SEQUENCE (result
)->regexps_num
4472 = (REGEXP_SEQUENCE (regexp
)->regexps_num
4473 + REGEXP_SEQUENCE (sequence
)->regexps_num
- 1);
4474 for (i
= 0; i
< REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
4475 if (i
< sequence_index
)
4476 REGEXP_SEQUENCE (result
)->regexps
[i
]
4477 = copy_insn_regexp (REGEXP_SEQUENCE (regexp
)->regexps
[i
]);
4478 else if (i
> sequence_index
)
4479 REGEXP_SEQUENCE (result
)->regexps
4480 [i
+ REGEXP_SEQUENCE (sequence
)->regexps_num
- 1]
4481 = copy_insn_regexp (REGEXP_SEQUENCE (regexp
)->regexps
[i
]);
4483 for (j
= 0; j
< REGEXP_SEQUENCE (sequence
)->regexps_num
; j
++)
4484 REGEXP_SEQUENCE (result
)->regexps
[i
+ j
]
4485 = copy_insn_regexp (REGEXP_SEQUENCE (sequence
)->regexps
[j
]);
4486 regexp_transformed_p
= 1;
4490 else if (regexp
->mode
== rm_allof
)
4492 regexp_t allof
= NULL
;
4494 int allof_index
= 0;
4497 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
4498 if (REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
== rm_allof
)
4501 allof
= REGEXP_ALLOF (regexp
)->regexps
[i
];
4504 if (i
< REGEXP_ALLOF (regexp
)->regexps_num
)
4506 gcc_assert (REGEXP_ALLOF (allof
)->regexps_num
> 1
4507 && REGEXP_ALLOF (regexp
)->regexps_num
> 1);
4508 result
= create_node (sizeof (struct regexp
)
4510 * (REGEXP_ALLOF (regexp
)->regexps_num
4511 + REGEXP_ALLOF (allof
)->regexps_num
- 2));
4512 result
->mode
= rm_allof
;
4513 result
->pos
= regexp
->pos
;
4514 REGEXP_ALLOF (result
)->regexps_num
4515 = (REGEXP_ALLOF (regexp
)->regexps_num
4516 + REGEXP_ALLOF (allof
)->regexps_num
- 1);
4517 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
4518 if (i
< allof_index
)
4519 REGEXP_ALLOF (result
)->regexps
[i
]
4520 = copy_insn_regexp (REGEXP_ALLOF (regexp
)->regexps
[i
]);
4521 else if (i
> allof_index
)
4522 REGEXP_ALLOF (result
)->regexps
4523 [i
+ REGEXP_ALLOF (allof
)->regexps_num
- 1]
4524 = copy_insn_regexp (REGEXP_ALLOF (regexp
)->regexps
[i
]);
4526 for (j
= 0; j
< REGEXP_ALLOF (allof
)->regexps_num
; j
++)
4527 REGEXP_ALLOF (result
)->regexps
[i
+ j
]
4528 = copy_insn_regexp (REGEXP_ALLOF (allof
)->regexps
[j
]);
4529 regexp_transformed_p
= 1;
4533 else if (regexp
->mode
== rm_oneof
)
4535 regexp_t oneof
= NULL
;
4537 int oneof_index
= 0;
4540 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
4541 if (REGEXP_ONEOF (regexp
)->regexps
[i
]->mode
== rm_oneof
)
4544 oneof
= REGEXP_ONEOF (regexp
)->regexps
[i
];
4547 if (i
< REGEXP_ONEOF (regexp
)->regexps_num
)
4549 gcc_assert (REGEXP_ONEOF (oneof
)->regexps_num
> 1
4550 && REGEXP_ONEOF (regexp
)->regexps_num
> 1);
4551 result
= create_node (sizeof (struct regexp
)
4553 * (REGEXP_ONEOF (regexp
)->regexps_num
4554 + REGEXP_ONEOF (oneof
)->regexps_num
- 2));
4555 result
->mode
= rm_oneof
;
4556 result
->pos
= regexp
->pos
;
4557 REGEXP_ONEOF (result
)->regexps_num
4558 = (REGEXP_ONEOF (regexp
)->regexps_num
4559 + REGEXP_ONEOF (oneof
)->regexps_num
- 1);
4560 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
4561 if (i
< oneof_index
)
4562 REGEXP_ONEOF (result
)->regexps
[i
]
4563 = copy_insn_regexp (REGEXP_ONEOF (regexp
)->regexps
[i
]);
4564 else if (i
> oneof_index
)
4565 REGEXP_ONEOF (result
)->regexps
4566 [i
+ REGEXP_ONEOF (oneof
)->regexps_num
- 1]
4567 = copy_insn_regexp (REGEXP_ONEOF (regexp
)->regexps
[i
]);
4569 for (j
= 0; j
< REGEXP_ONEOF (oneof
)->regexps_num
; j
++)
4570 REGEXP_ONEOF (result
)->regexps
[i
+ j
]
4571 = copy_insn_regexp (REGEXP_ONEOF (oneof
)->regexps
[j
]);
4572 regexp_transformed_p
= 1;
4579 /* The function makes transformations
4580 ...,A|B|...,C,... -> (...,A,C,...)|(...,B,C,...)|...
4581 ...+(A|B|...)+C+... -> (...+A+C+...)|(...+B+C+...)|...
4582 ...+(A,B,...)+C+... -> (...+A+C+...),B,...
4583 ...+(A,B,...)+(C,D,...) -> (A+C),(B+D),... */
4585 transform_3 (regexp_t regexp
)
4587 if (regexp
->mode
== rm_sequence
)
4589 regexp_t oneof
= NULL
;
4590 int oneof_index
= 0;
4595 for (i
= 0; i
<REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
4596 if (REGEXP_SEQUENCE (regexp
)->regexps
[i
]->mode
== rm_oneof
)
4599 oneof
= REGEXP_SEQUENCE (regexp
)->regexps
[i
];
4602 if (i
< REGEXP_SEQUENCE (regexp
)->regexps_num
)
4604 gcc_assert (REGEXP_ONEOF (oneof
)->regexps_num
> 1
4605 && REGEXP_SEQUENCE (regexp
)->regexps_num
> 1);
4606 result
= create_node (sizeof (struct regexp
)
4608 * (REGEXP_ONEOF (oneof
)->regexps_num
- 1));
4609 result
->mode
= rm_oneof
;
4610 result
->pos
= regexp
->pos
;
4611 REGEXP_ONEOF (result
)->regexps_num
4612 = REGEXP_ONEOF (oneof
)->regexps_num
;
4613 for (i
= 0; i
< REGEXP_ONEOF (result
)->regexps_num
; i
++)
4616 = create_node (sizeof (struct regexp
)
4618 * (REGEXP_SEQUENCE (regexp
)->regexps_num
- 1));
4619 sequence
->mode
= rm_sequence
;
4620 sequence
->pos
= regexp
->pos
;
4621 REGEXP_SEQUENCE (sequence
)->regexps_num
4622 = REGEXP_SEQUENCE (regexp
)->regexps_num
;
4623 REGEXP_ONEOF (result
)->regexps
[i
] = sequence
;
4624 for (j
= 0; j
< REGEXP_SEQUENCE (sequence
)->regexps_num
; j
++)
4625 if (j
!= oneof_index
)
4626 REGEXP_SEQUENCE (sequence
)->regexps
[j
]
4627 = copy_insn_regexp (REGEXP_SEQUENCE (regexp
)->regexps
[j
]);
4629 REGEXP_SEQUENCE (sequence
)->regexps
[j
]
4630 = copy_insn_regexp (REGEXP_ONEOF (oneof
)->regexps
[i
]);
4632 regexp_transformed_p
= 1;
4636 else if (regexp
->mode
== rm_allof
)
4638 regexp_t oneof
= NULL
;
4640 int oneof_index
= 0;
4641 int max_seq_length
, allof_length
;
4643 regexp_t allof
= NULL
;
4644 regexp_t allof_op
= NULL
;
4647 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
4648 if (REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
== rm_oneof
)
4651 oneof
= REGEXP_ALLOF (regexp
)->regexps
[i
];
4654 if (i
< REGEXP_ALLOF (regexp
)->regexps_num
)
4656 gcc_assert (REGEXP_ONEOF (oneof
)->regexps_num
> 1
4657 && REGEXP_ALLOF (regexp
)->regexps_num
> 1);
4658 result
= create_node (sizeof (struct regexp
)
4660 * (REGEXP_ONEOF (oneof
)->regexps_num
- 1));
4661 result
->mode
= rm_oneof
;
4662 result
->pos
= regexp
->pos
;
4663 REGEXP_ONEOF (result
)->regexps_num
4664 = REGEXP_ONEOF (oneof
)->regexps_num
;
4665 for (i
= 0; i
< REGEXP_ONEOF (result
)->regexps_num
; i
++)
4668 = create_node (sizeof (struct regexp
)
4670 * (REGEXP_ALLOF (regexp
)->regexps_num
- 1));
4671 allof
->mode
= rm_allof
;
4672 allof
->pos
= regexp
->pos
;
4673 REGEXP_ALLOF (allof
)->regexps_num
4674 = REGEXP_ALLOF (regexp
)->regexps_num
;
4675 REGEXP_ONEOF (result
)->regexps
[i
] = allof
;
4676 for (j
= 0; j
< REGEXP_ALLOF (allof
)->regexps_num
; j
++)
4677 if (j
!= oneof_index
)
4678 REGEXP_ALLOF (allof
)->regexps
[j
]
4679 = copy_insn_regexp (REGEXP_ALLOF (regexp
)->regexps
[j
]);
4681 REGEXP_ALLOF (allof
)->regexps
[j
]
4682 = copy_insn_regexp (REGEXP_ONEOF (oneof
)->regexps
[i
]);
4684 regexp_transformed_p
= 1;
4688 if (regexp
->mode
== rm_allof
)
4689 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
4691 switch (REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
)
4694 seq
= REGEXP_ALLOF (regexp
)->regexps
[i
];
4695 if (max_seq_length
< REGEXP_SEQUENCE (seq
)->regexps_num
)
4696 max_seq_length
= REGEXP_SEQUENCE (seq
)->regexps_num
;
4709 if (max_seq_length
!= 0)
4711 gcc_assert (max_seq_length
!= 1
4712 && REGEXP_ALLOF (regexp
)->regexps_num
> 1);
4713 result
= create_node (sizeof (struct regexp
)
4714 + sizeof (regexp_t
) * (max_seq_length
- 1));
4715 result
->mode
= rm_sequence
;
4716 result
->pos
= regexp
->pos
;
4717 REGEXP_SEQUENCE (result
)->regexps_num
= max_seq_length
;
4718 for (i
= 0; i
< max_seq_length
; i
++)
4721 for (j
= 0; j
< REGEXP_ALLOF (regexp
)->regexps_num
; j
++)
4722 switch (REGEXP_ALLOF (regexp
)->regexps
[j
]->mode
)
4725 if (i
< (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp
)
4726 ->regexps
[j
])->regexps_num
))
4729 = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp
)
4739 allof_op
= REGEXP_ALLOF (regexp
)->regexps
[j
];
4747 if (allof_length
== 1)
4748 REGEXP_SEQUENCE (result
)->regexps
[i
] = allof_op
;
4751 allof
= create_node (sizeof (struct regexp
)
4753 * (allof_length
- 1));
4754 allof
->mode
= rm_allof
;
4755 allof
->pos
= regexp
->pos
;
4756 REGEXP_ALLOF (allof
)->regexps_num
= allof_length
;
4757 REGEXP_SEQUENCE (result
)->regexps
[i
] = allof
;
4759 for (j
= 0; j
< REGEXP_ALLOF (regexp
)->regexps_num
; j
++)
4760 if (REGEXP_ALLOF (regexp
)->regexps
[j
]->mode
== rm_sequence
4762 (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp
)
4763 ->regexps
[j
])->regexps_num
)))
4765 allof_op
= (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp
)
4768 REGEXP_ALLOF (allof
)->regexps
[allof_length
]
4773 && (REGEXP_ALLOF (regexp
)->regexps
[j
]->mode
4775 || (REGEXP_ALLOF (regexp
)->regexps
[j
]->mode
4778 allof_op
= REGEXP_ALLOF (regexp
)->regexps
[j
];
4779 REGEXP_ALLOF (allof
)->regexps
[allof_length
]
4785 regexp_transformed_p
= 1;
4792 /* The function traverses IR of reservation and applies transformations
4793 implemented by FUNC. */
4795 regexp_transform_func (regexp_t regexp
, regexp_t (*func
) (regexp_t regexp
))
4799 switch (regexp
->mode
)
4802 for (i
= 0; i
< REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
4803 REGEXP_SEQUENCE (regexp
)->regexps
[i
]
4804 = regexp_transform_func (REGEXP_SEQUENCE (regexp
)->regexps
[i
],
4809 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
4810 REGEXP_ALLOF (regexp
)->regexps
[i
]
4811 = regexp_transform_func (REGEXP_ALLOF (regexp
)->regexps
[i
], func
);
4815 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
4816 REGEXP_ONEOF (regexp
)->regexps
[i
]
4817 = regexp_transform_func (REGEXP_ONEOF (regexp
)->regexps
[i
], func
);
4821 REGEXP_REPEAT (regexp
)->regexp
4822 = regexp_transform_func (REGEXP_REPEAT (regexp
)->regexp
, func
);
4832 return (*func
) (regexp
);
4835 /* The function applies all transformations for IR representation of
4836 reservation REGEXP. */
4838 transform_regexp (regexp_t regexp
)
4840 regexp
= regexp_transform_func (regexp
, transform_1
);
4843 regexp_transformed_p
= 0;
4844 regexp
= regexp_transform_func (regexp
, transform_2
);
4845 regexp
= regexp_transform_func (regexp
, transform_3
);
4847 while (regexp_transformed_p
);
4851 /* The function applies all transformations for reservations of all
4852 insn declarations. */
4854 transform_insn_regexps (void)
4859 transform_time
= create_ticker ();
4860 add_advance_cycle_insn_decl ();
4862 fprintf (stderr
, "Reservation transformation...");
4863 for (i
= 0; i
< description
->decls_num
; i
++)
4865 decl
= description
->decls
[i
];
4866 if (decl
->mode
== dm_insn_reserv
&& decl
!= advance_cycle_insn_decl
)
4867 DECL_INSN_RESERV (decl
)->transformed_regexp
4868 = transform_regexp (copy_insn_regexp
4869 (DECL_INSN_RESERV (decl
)->regexp
));
4872 fprintf (stderr
, "done\n");
4873 ticker_off (&transform_time
);
4878 /* The following variable value is TRUE if the first annotated message
4879 about units to automata distribution has been output. */
4880 static int annotation_message_reported_p
;
4882 /* The following structure describes usage of a unit in a reservation. */
4885 unit_decl_t unit_decl
;
4886 /* The following forms a list of units used on the same cycle in the
4887 same alternative. */
4888 struct unit_usage
*next
;
4890 typedef struct unit_usage
*unit_usage_t
;
4892 DEF_VEC_P(unit_usage_t
);
4893 DEF_VEC_ALLOC_P(unit_usage_t
,heap
);
4895 /* Obstack for unit_usage structures. */
4896 static struct obstack unit_usages
;
4898 /* VLA for representation of array of pointers to unit usage
4899 structures. There is an element for each combination of
4900 (alternative number, cycle). Unit usages on given cycle in
4901 alternative with given number are referred through element with
4902 index equals to the cycle * number of all alternatives in the regexp
4903 + the alternative number. */
4904 static VEC(unit_usage_t
,heap
) *cycle_alt_unit_usages
;
4906 /* The following function creates the structure unit_usage for UNIT on
4907 CYCLE in REGEXP alternative with ALT_NUM. The structure is made
4908 accessed through cycle_alt_unit_usages. */
4910 store_alt_unit_usage (regexp_t regexp
, regexp_t unit
, int cycle
,
4914 unit_decl_t unit_decl
;
4915 unit_usage_t unit_usage_ptr
;
4918 gcc_assert (regexp
&& regexp
->mode
== rm_oneof
4919 && alt_num
< REGEXP_ONEOF (regexp
)->regexps_num
);
4920 unit_decl
= REGEXP_UNIT (unit
)->unit_decl
;
4922 length
= (cycle
+ 1) * REGEXP_ONEOF (regexp
)->regexps_num
;
4923 while (VEC_length (unit_usage_t
, cycle_alt_unit_usages
) < length
)
4924 VEC_safe_push (unit_usage_t
,heap
, cycle_alt_unit_usages
, 0);
4926 obstack_blank (&unit_usages
, sizeof (struct unit_usage
));
4927 unit_usage_ptr
= (struct unit_usage
*) obstack_base (&unit_usages
);
4928 obstack_finish (&unit_usages
);
4929 unit_usage_ptr
->unit_decl
= unit_decl
;
4930 index
= cycle
* REGEXP_ONEOF (regexp
)->regexps_num
+ alt_num
;
4931 unit_usage_ptr
->next
= VEC_index (unit_usage_t
, cycle_alt_unit_usages
, index
);
4932 VEC_replace (unit_usage_t
, cycle_alt_unit_usages
, index
, unit_usage_ptr
);
4933 unit_decl
->last_distribution_check_cycle
= -1; /* undefined */
4936 /* The function processes given REGEXP to find units with the wrong
4939 check_regexp_units_distribution (const char *insn_reserv_name
,
4943 regexp_t seq
, allof
, unit
;
4944 struct unit_usage
*unit_usage_ptr
, *other_unit_usage_ptr
;
4946 if (regexp
== NULL
|| regexp
->mode
!= rm_oneof
)
4948 /* Store all unit usages in the regexp: */
4949 obstack_init (&unit_usages
);
4950 cycle_alt_unit_usages
= 0;
4952 for (i
= REGEXP_ONEOF (regexp
)->regexps_num
- 1; i
>= 0; i
--)
4954 seq
= REGEXP_ONEOF (regexp
)->regexps
[i
];
4958 for (j
= 0; j
< REGEXP_SEQUENCE (seq
)->regexps_num
; j
++)
4960 allof
= REGEXP_SEQUENCE (seq
)->regexps
[j
];
4961 switch (allof
->mode
)
4964 for (k
= 0; k
< REGEXP_ALLOF (allof
)->regexps_num
; k
++)
4966 unit
= REGEXP_ALLOF (allof
)->regexps
[k
];
4967 if (unit
->mode
== rm_unit
)
4968 store_alt_unit_usage (regexp
, unit
, j
, i
);
4970 gcc_assert (unit
->mode
== rm_nothing
);
4975 store_alt_unit_usage (regexp
, allof
, j
, i
);
4988 for (k
= 0; k
< REGEXP_ALLOF (seq
)->regexps_num
; k
++)
4990 unit
= REGEXP_ALLOF (seq
)->regexps
[k
];
4994 store_alt_unit_usage (regexp
, unit
, 0, i
);
5007 store_alt_unit_usage (regexp
, seq
, 0, i
);
5017 /* Check distribution: */
5018 for (i
= 0; i
< (int) VEC_length (unit_usage_t
, cycle_alt_unit_usages
); i
++)
5020 cycle
= i
/ REGEXP_ONEOF (regexp
)->regexps_num
;
5021 for (unit_usage_ptr
= VEC_index (unit_usage_t
, cycle_alt_unit_usages
, i
);
5022 unit_usage_ptr
!= NULL
;
5023 unit_usage_ptr
= unit_usage_ptr
->next
)
5024 if (cycle
!= unit_usage_ptr
->unit_decl
->last_distribution_check_cycle
)
5026 unit_usage_ptr
->unit_decl
->last_distribution_check_cycle
= cycle
;
5027 for (k
= cycle
* REGEXP_ONEOF (regexp
)->regexps_num
;
5028 k
< (int) VEC_length (unit_usage_t
, cycle_alt_unit_usages
)
5029 && k
== cycle
* REGEXP_ONEOF (regexp
)->regexps_num
;
5032 for (other_unit_usage_ptr
5033 = VEC_index (unit_usage_t
, cycle_alt_unit_usages
, k
);
5034 other_unit_usage_ptr
!= NULL
;
5035 other_unit_usage_ptr
= other_unit_usage_ptr
->next
)
5036 if (unit_usage_ptr
->unit_decl
->automaton_decl
5037 == other_unit_usage_ptr
->unit_decl
->automaton_decl
)
5039 if (other_unit_usage_ptr
== NULL
5040 && (VEC_index (unit_usage_t
, cycle_alt_unit_usages
, k
)
5044 if (k
< (int) VEC_length (unit_usage_t
, cycle_alt_unit_usages
)
5045 && k
== cycle
* REGEXP_ONEOF (regexp
)->regexps_num
)
5047 if (!annotation_message_reported_p
)
5049 fprintf (stderr
, "\n");
5050 error ("The following units do not satisfy units-automata distribution rule");
5051 error (" (A unit of given unit automaton should be on each reserv. altern.)");
5052 annotation_message_reported_p
= TRUE
;
5054 error ("Unit %s, reserv. %s, cycle %d",
5055 unit_usage_ptr
->unit_decl
->name
, insn_reserv_name
,
5060 VEC_free (unit_usage_t
,heap
, cycle_alt_unit_usages
);
5061 obstack_free (&unit_usages
, NULL
);
5064 /* The function finds units which violates units to automata
5065 distribution rule. If the units exist, report about them. */
5067 check_unit_distributions_to_automata (void)
5073 fprintf (stderr
, "Check unit distributions to automata...");
5074 annotation_message_reported_p
= FALSE
;
5075 for (i
= 0; i
< description
->decls_num
; i
++)
5077 decl
= description
->decls
[i
];
5078 if (decl
->mode
== dm_insn_reserv
)
5079 check_regexp_units_distribution
5080 (DECL_INSN_RESERV (decl
)->name
,
5081 DECL_INSN_RESERV (decl
)->transformed_regexp
);
5084 fprintf (stderr
, "done\n");
5089 /* The page contains code for building alt_states (see comments for
5090 IR) describing all possible insns reservations of an automaton. */
5092 /* Current state being formed for which the current alt_state
5094 static state_t state_being_formed
;
5096 /* Current alt_state being formed. */
5097 static alt_state_t alt_state_being_formed
;
5099 /* This recursive function processes `,' and units in reservation
5100 REGEXP for forming alt_states of AUTOMATON. It is believed that
5101 CURR_CYCLE is start cycle of all reservation REGEXP. */
5103 process_seq_for_forming_states (regexp_t regexp
, automaton_t automaton
,
5111 switch (regexp
->mode
)
5114 if (REGEXP_UNIT (regexp
)->unit_decl
->corresponding_automaton_num
5115 == automaton
->automaton_order_num
)
5116 set_state_reserv (state_being_formed
, curr_cycle
,
5117 REGEXP_UNIT (regexp
)->unit_decl
->unit_num
);
5121 for (i
= 0; i
< REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
5123 = process_seq_for_forming_states
5124 (REGEXP_SEQUENCE (regexp
)->regexps
[i
], automaton
, curr_cycle
) + 1;
5129 int finish_cycle
= 0;
5132 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
5134 cycle
= process_seq_for_forming_states (REGEXP_ALLOF (regexp
)
5136 automaton
, curr_cycle
);
5137 if (finish_cycle
< cycle
)
5138 finish_cycle
= cycle
;
5140 return finish_cycle
;
5151 /* This recursive function finishes forming ALT_STATE of AUTOMATON and
5152 inserts alt_state into the table. */
5154 finish_forming_alt_state (alt_state_t alt_state
,
5155 automaton_t automaton ATTRIBUTE_UNUSED
)
5157 state_t state_in_table
;
5158 state_t corresponding_state
;
5160 corresponding_state
= alt_state
->state
;
5161 state_in_table
= insert_state (corresponding_state
);
5162 if (state_in_table
!= corresponding_state
)
5164 free_state (corresponding_state
);
5165 alt_state
->state
= state_in_table
;
5169 /* The following variable value is current automaton insn for whose
5170 reservation the alt states are created. */
5171 static ainsn_t curr_ainsn
;
5173 /* This recursive function processes `|' in reservation REGEXP for
5174 forming alt_states of AUTOMATON. List of the alt states should
5175 have the same order as in the description. */
5177 process_alts_for_forming_states (regexp_t regexp
, automaton_t automaton
,
5182 if (regexp
->mode
!= rm_oneof
)
5184 alt_state_being_formed
= get_free_alt_state ();
5185 state_being_formed
= get_free_state (1, automaton
);
5186 alt_state_being_formed
->state
= state_being_formed
;
5187 /* We inserts in reverse order but we process alternatives also
5188 in reverse order. So we have the same order of alternative
5189 as in the description. */
5190 alt_state_being_formed
->next_alt_state
= curr_ainsn
->alt_states
;
5191 curr_ainsn
->alt_states
= alt_state_being_formed
;
5192 (void) process_seq_for_forming_states (regexp
, automaton
, 0);
5193 finish_forming_alt_state (alt_state_being_formed
, automaton
);
5197 gcc_assert (!inside_oneof_p
);
5198 /* We processes it in reverse order to get list with the same
5199 order as in the description. See also the previous
5201 for (i
= REGEXP_ONEOF (regexp
)->regexps_num
- 1; i
>= 0; i
--)
5202 process_alts_for_forming_states (REGEXP_ONEOF (regexp
)->regexps
[i
],
5207 /* Create nodes alt_state for all AUTOMATON insns. */
5209 create_alt_states (automaton_t automaton
)
5211 struct insn_reserv_decl
*reserv_decl
;
5213 for (curr_ainsn
= automaton
->ainsn_list
;
5215 curr_ainsn
= curr_ainsn
->next_ainsn
)
5217 reserv_decl
= curr_ainsn
->insn_reserv_decl
;
5218 if (reserv_decl
!= DECL_INSN_RESERV (advance_cycle_insn_decl
))
5220 curr_ainsn
->alt_states
= NULL
;
5221 process_alts_for_forming_states (reserv_decl
->transformed_regexp
,
5223 curr_ainsn
->sorted_alt_states
5224 = uniq_sort_alt_states (curr_ainsn
->alt_states
);
5231 /* The page contains major code for building DFA(s) for fast pipeline
5232 hazards recognition. */
5234 /* The function forms list of ainsns of AUTOMATON with the same
5238 form_ainsn_with_same_reservs (automaton_t automaton
)
5242 VEC(ainsn_t
,heap
) *last_insns
= VEC_alloc (ainsn_t
,heap
, 150);
5244 for (curr_ainsn
= automaton
->ainsn_list
;
5246 curr_ainsn
= curr_ainsn
->next_ainsn
)
5247 if (curr_ainsn
->insn_reserv_decl
5248 == DECL_INSN_RESERV (advance_cycle_insn_decl
))
5250 curr_ainsn
->next_same_reservs_insn
= NULL
;
5251 curr_ainsn
->first_insn_with_same_reservs
= 1;
5255 for (i
= 0; i
< VEC_length (ainsn_t
, last_insns
); i
++)
5257 (curr_ainsn
->sorted_alt_states
,
5258 VEC_index (ainsn_t
, last_insns
, i
)->sorted_alt_states
))
5260 curr_ainsn
->next_same_reservs_insn
= NULL
;
5261 if (i
< VEC_length (ainsn_t
, last_insns
))
5263 curr_ainsn
->first_insn_with_same_reservs
= 0;
5264 VEC_index (ainsn_t
, last_insns
, i
)->next_same_reservs_insn
5266 VEC_replace (ainsn_t
, last_insns
, i
, curr_ainsn
);
5270 VEC_safe_push (ainsn_t
, heap
, last_insns
, curr_ainsn
);
5271 curr_ainsn
->first_insn_with_same_reservs
= 1;
5274 VEC_free (ainsn_t
,heap
, last_insns
);
5277 /* Forming unit reservations which can affect creating the automaton
5278 states achieved from a given state. It permits to build smaller
5279 automata in many cases. We would have the same automata after
5280 the minimization without such optimization, but the automaton
5281 right after the building could be huge. So in other words, usage
5282 of reservs_matter means some minimization during building the
5284 static reserv_sets_t
5285 form_reservs_matter (automaton_t automaton
)
5288 reserv_sets_t reservs_matter
= alloc_empty_reserv_sets();
5290 for (cycle
= 0; cycle
< max_cycles_num
; cycle
++)
5291 for (unit
= 0; unit
< description
->units_num
; unit
++)
5292 if (units_array
[unit
]->automaton_decl
5293 == automaton
->corresponding_automaton_decl
5294 && (cycle
>= units_array
[unit
]->min_occ_cycle_num
5295 /* We can not remove queried unit from reservations. */
5296 || units_array
[unit
]->query_p
5297 /* We can not remove units which are used
5298 `exclusion_set', `presence_set',
5299 `final_presence_set', `absence_set', and
5300 `final_absence_set'. */
5301 || units_array
[unit
]->in_set_p
))
5302 set_unit_reserv (reservs_matter
, cycle
, unit
);
5303 return reservs_matter
;
5306 /* The following function creates all states of nondeterministic AUTOMATON. */
5308 make_automaton (automaton_t automaton
)
5311 struct insn_reserv_decl
*insn_reserv_decl
;
5312 alt_state_t alt_state
;
5314 state_t start_state
;
5316 ainsn_t advance_cycle_ainsn
;
5318 VEC(state_t
,heap
) *state_stack
= VEC_alloc(state_t
,heap
, 150);
5320 reserv_sets_t reservs_matter
= form_reservs_matter (automaton
);
5322 /* Create the start state (empty state). */
5323 start_state
= insert_state (get_free_state (1, automaton
));
5324 automaton
->start_state
= start_state
;
5325 start_state
->it_was_placed_in_stack_for_NDFA_forming
= 1;
5326 VEC_safe_push (state_t
,heap
, state_stack
, start_state
);
5328 while (VEC_length (state_t
, state_stack
) != 0)
5330 state
= VEC_pop (state_t
, state_stack
);
5331 advance_cycle_ainsn
= NULL
;
5332 for (ainsn
= automaton
->ainsn_list
;
5334 ainsn
= ainsn
->next_ainsn
)
5335 if (ainsn
->first_insn_with_same_reservs
)
5337 insn_reserv_decl
= ainsn
->insn_reserv_decl
;
5338 if (insn_reserv_decl
!= DECL_INSN_RESERV (advance_cycle_insn_decl
))
5340 /* We process alt_states in the same order as they are
5341 present in the description. */
5343 for (alt_state
= ainsn
->alt_states
;
5345 alt_state
= alt_state
->next_alt_state
)
5347 state2
= alt_state
->state
;
5348 if (!intersected_state_reservs_p (state
, state2
))
5350 state2
= states_union (state
, state2
, reservs_matter
);
5351 if (!state2
->it_was_placed_in_stack_for_NDFA_forming
)
5353 state2
->it_was_placed_in_stack_for_NDFA_forming
5355 VEC_safe_push (state_t
,heap
, state_stack
, state2
);
5357 if (progress_flag
&& states_n
% 100 == 0)
5358 fprintf (stderr
, ".");
5360 added_arc
= add_arc (state
, state2
, ainsn
);
5365 if (!ndfa_flag
&& added_arc
!= NULL
)
5367 for (alt_state
= ainsn
->alt_states
;
5369 alt_state
= alt_state
->next_alt_state
)
5370 state2
= alt_state
->state
;
5374 advance_cycle_ainsn
= ainsn
;
5376 /* Add transition to advance cycle. */
5377 state2
= state_shift (state
, reservs_matter
);
5378 if (!state2
->it_was_placed_in_stack_for_NDFA_forming
)
5380 state2
->it_was_placed_in_stack_for_NDFA_forming
= 1;
5381 VEC_safe_push (state_t
,heap
, state_stack
, state2
);
5383 if (progress_flag
&& states_n
% 100 == 0)
5384 fprintf (stderr
, ".");
5386 gcc_assert (advance_cycle_ainsn
);
5387 add_arc (state
, state2
, advance_cycle_ainsn
);
5389 VEC_free (state_t
,heap
, state_stack
);
5392 /* Foms lists of all arcs of STATE marked by the same ainsn. */
5394 form_arcs_marked_by_insn (state_t state
)
5400 for (i
= 0; i
< description
->decls_num
; i
++)
5402 decl
= description
->decls
[i
];
5403 if (decl
->mode
== dm_insn_reserv
)
5404 DECL_INSN_RESERV (decl
)->arcs_marked_by_insn
= NULL
;
5406 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
5408 gcc_assert (arc
->insn
);
5409 arc
->next_arc_marked_by_insn
5410 = arc
->insn
->insn_reserv_decl
->arcs_marked_by_insn
;
5411 arc
->insn
->insn_reserv_decl
->arcs_marked_by_insn
= arc
;
5415 /* The function creates composed state (see comments for IR) from
5416 ORIGINAL_STATE and list of arcs ARCS_MARKED_BY_INSN marked by the
5417 same insn. If the composed state is not in STATE_STACK yet, it is
5418 pushed into STATE_STACK. */
5421 create_composed_state (state_t original_state
, arc_t arcs_marked_by_insn
,
5422 VEC(state_t
,heap
) **state_stack
)
5425 alt_state_t alt_state
, curr_alt_state
;
5426 alt_state_t new_alt_state
;
5429 state_t state_in_table
;
5431 alt_state_t canonical_alt_states_list
;
5433 int new_state_p
= 0;
5435 if (arcs_marked_by_insn
== NULL
)
5437 if (arcs_marked_by_insn
->next_arc_marked_by_insn
== NULL
)
5438 state
= arcs_marked_by_insn
->to_state
;
5441 gcc_assert (ndfa_flag
);
5442 /* Create composed state. */
5443 state
= get_free_state (0, arcs_marked_by_insn
->to_state
->automaton
);
5444 curr_alt_state
= NULL
;
5445 for (curr_arc
= arcs_marked_by_insn
;
5447 curr_arc
= curr_arc
->next_arc_marked_by_insn
)
5448 if (curr_arc
->to_state
->component_states
== NULL
)
5450 new_alt_state
= get_free_alt_state ();
5451 new_alt_state
->next_alt_state
= curr_alt_state
;
5452 new_alt_state
->state
= curr_arc
->to_state
;
5453 curr_alt_state
= new_alt_state
;
5456 for (alt_state
= curr_arc
->to_state
->component_states
;
5458 alt_state
= alt_state
->next_sorted_alt_state
)
5460 new_alt_state
= get_free_alt_state ();
5461 new_alt_state
->next_alt_state
= curr_alt_state
;
5462 new_alt_state
->state
= alt_state
->state
;
5463 gcc_assert (!alt_state
->state
->component_states
);
5464 curr_alt_state
= new_alt_state
;
5466 /* There are not identical sets in the alt state list. */
5467 canonical_alt_states_list
= uniq_sort_alt_states (curr_alt_state
);
5468 if (canonical_alt_states_list
->next_sorted_alt_state
== NULL
)
5471 state
= canonical_alt_states_list
->state
;
5472 free_state (temp_state
);
5476 state
->component_states
= canonical_alt_states_list
;
5477 state_in_table
= insert_state (state
);
5478 if (state_in_table
!= state
)
5481 (state_in_table
->it_was_placed_in_stack_for_DFA_forming
);
5483 state
= state_in_table
;
5487 gcc_assert (!state
->it_was_placed_in_stack_for_DFA_forming
);
5489 for (curr_alt_state
= state
->component_states
;
5490 curr_alt_state
!= NULL
;
5491 curr_alt_state
= curr_alt_state
->next_sorted_alt_state
)
5492 for (curr_arc
= first_out_arc (curr_alt_state
->state
);
5494 curr_arc
= next_out_arc (curr_arc
))
5495 add_arc (state
, curr_arc
->to_state
, curr_arc
->insn
);
5497 arcs_marked_by_insn
->to_state
= state
;
5498 for (alts_number
= 0,
5499 curr_arc
= arcs_marked_by_insn
->next_arc_marked_by_insn
;
5501 curr_arc
= next_arc
)
5503 next_arc
= curr_arc
->next_arc_marked_by_insn
;
5504 remove_arc (original_state
, curr_arc
);
5509 if (!state
->it_was_placed_in_stack_for_DFA_forming
)
5511 state
->it_was_placed_in_stack_for_DFA_forming
= 1;
5512 VEC_safe_push (state_t
,heap
, *state_stack
, state
);
5517 /* The function transforms nondeterministic AUTOMATON into
5521 NDFA_to_DFA (automaton_t automaton
)
5523 state_t start_state
;
5526 VEC(state_t
,heap
) *state_stack
;
5530 state_stack
= VEC_alloc (state_t
,heap
, 0);
5532 /* Create the start state (empty state). */
5533 start_state
= automaton
->start_state
;
5534 start_state
->it_was_placed_in_stack_for_DFA_forming
= 1;
5535 VEC_safe_push (state_t
,heap
, state_stack
, start_state
);
5537 while (VEC_length (state_t
, state_stack
) != 0)
5539 state
= VEC_pop (state_t
, state_stack
);
5540 form_arcs_marked_by_insn (state
);
5541 for (i
= 0; i
< description
->decls_num
; i
++)
5543 decl
= description
->decls
[i
];
5544 if (decl
->mode
== dm_insn_reserv
5545 && create_composed_state
5546 (state
, DECL_INSN_RESERV (decl
)->arcs_marked_by_insn
,
5550 if (progress_flag
&& states_n
% 100 == 0)
5551 fprintf (stderr
, ".");
5555 VEC_free (state_t
,heap
, state_stack
);
5558 /* The following variable value is current number (1, 2, ...) of passing
5560 static int curr_state_graph_pass_num
;
5562 /* This recursive function passes all states achieved from START_STATE
5563 and applies APPLIED_FUNC to them. */
5565 pass_state_graph (state_t start_state
, void (*applied_func
) (state_t state
))
5569 if (start_state
->pass_num
== curr_state_graph_pass_num
)
5571 start_state
->pass_num
= curr_state_graph_pass_num
;
5572 (*applied_func
) (start_state
);
5573 for (arc
= first_out_arc (start_state
);
5575 arc
= next_out_arc (arc
))
5576 pass_state_graph (arc
->to_state
, applied_func
);
5579 /* This recursive function passes all states of AUTOMATON and applies
5580 APPLIED_FUNC to them. */
5582 pass_states (automaton_t automaton
, void (*applied_func
) (state_t state
))
5584 curr_state_graph_pass_num
++;
5585 pass_state_graph (automaton
->start_state
, applied_func
);
5588 /* The function initializes code for passing of all states. */
5590 initiate_pass_states (void)
5592 curr_state_graph_pass_num
= 0;
5595 /* The following vla is used for storing pointers to all achieved
5597 static VEC(state_t
,heap
) *all_achieved_states
;
5599 /* This function is called by function pass_states to add an achieved
5602 add_achieved_state (state_t state
)
5604 VEC_safe_push (state_t
,heap
, all_achieved_states
, state
);
5607 /* The function sets up equivalence numbers of insns which mark all
5608 out arcs of STATE by equiv_class_num_1 (if ODD_ITERATION_FLAG has
5609 nonzero value) or by equiv_class_num_2 of the destination state.
5610 The function returns number of out arcs of STATE. */
5612 set_out_arc_insns_equiv_num (state_t state
, int odd_iteration_flag
)
5616 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
5618 gcc_assert (!arc
->insn
->insn_reserv_decl
->equiv_class_num
);
5619 arc
->insn
->insn_reserv_decl
->equiv_class_num
5620 = (odd_iteration_flag
5621 ? arc
->to_state
->equiv_class_num_1
5622 : arc
->to_state
->equiv_class_num_2
);
5623 gcc_assert (arc
->insn
->insn_reserv_decl
->equiv_class_num
);
5627 /* The function clears equivalence numbers and alt_states in all insns
5628 which mark all out arcs of STATE. */
5630 clear_arc_insns_equiv_num (state_t state
)
5634 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
5635 arc
->insn
->insn_reserv_decl
->equiv_class_num
= 0;
5639 /* The following function returns TRUE if STATE reserves the unit with
5640 UNIT_NUM on the first cycle. */
5642 first_cycle_unit_presence (state_t state
, int unit_num
)
5644 alt_state_t alt_state
;
5646 if (state
->component_states
== NULL
)
5647 return test_unit_reserv (state
->reservs
, 0, unit_num
);
5650 for (alt_state
= state
->component_states
;
5652 alt_state
= alt_state
->next_sorted_alt_state
)
5653 if (test_unit_reserv (alt_state
->state
->reservs
, 0, unit_num
))
5659 /* This fills in the presence_signature[] member of STATE. */
5661 cache_presence (state_t state
)
5665 sz
= (description
->query_units_num
+ sizeof (int) * CHAR_BIT
- 1)
5666 / (sizeof (int) * CHAR_BIT
);
5668 state
->presence_signature
= create_node (sz
* sizeof (int));
5669 for (i
= 0; i
< description
->units_num
; i
++)
5670 if (units_array
[i
]->query_p
)
5672 int presence1_p
= first_cycle_unit_presence (state
, i
);
5673 state
->presence_signature
[num
/ (sizeof (int) * CHAR_BIT
)]
5674 |= (!!presence1_p
) << (num
% (sizeof (int) * CHAR_BIT
));
5679 /* The function returns nonzero value if STATE is not equivalent to
5680 ANOTHER_STATE from the same current partition on equivalence
5681 classes. Another state has ANOTHER_STATE_OUT_ARCS_NUM number of
5682 output arcs. Iteration of making equivalence partition is defined
5683 by ODD_ITERATION_FLAG. */
5685 state_is_differed (state_t state
, state_t another_state
,
5686 int odd_iteration_flag
)
5689 unsigned int sz
, si
;
5691 gcc_assert (state
->num_out_arcs
== another_state
->num_out_arcs
);
5693 sz
= (description
->query_units_num
+ sizeof (int) * CHAR_BIT
- 1)
5694 / (sizeof (int) * CHAR_BIT
);
5696 for (si
= 0; si
< sz
; si
++)
5697 gcc_assert (state
->presence_signature
[si
]
5698 == another_state
->presence_signature
[si
]);
5700 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
5702 if ((odd_iteration_flag
5703 ? arc
->to_state
->equiv_class_num_1
5704 : arc
->to_state
->equiv_class_num_2
)
5705 != arc
->insn
->insn_reserv_decl
->equiv_class_num
)
5712 /* Compares two states pointed to by STATE_PTR_1 and STATE_PTR_2
5713 and return -1, 0 or 1. This function can be used as predicate for
5714 qsort(). It requires the member presence_signature[] of both
5715 states be filled. */
5717 compare_states_for_equiv (const void *state_ptr_1
,
5718 const void *state_ptr_2
)
5720 state_t s1
= *(state_t
*)state_ptr_1
;
5721 state_t s2
= *(state_t
*)state_ptr_2
;
5722 unsigned int sz
, si
;
5723 if (s1
->num_out_arcs
< s2
->num_out_arcs
)
5725 else if (s1
->num_out_arcs
> s2
->num_out_arcs
)
5728 sz
= (description
->query_units_num
+ sizeof (int) * CHAR_BIT
- 1)
5729 / (sizeof (int) * CHAR_BIT
);
5731 for (si
= 0; si
< sz
; si
++)
5732 if (s1
->presence_signature
[si
] < s2
->presence_signature
[si
])
5734 else if (s1
->presence_signature
[si
] > s2
->presence_signature
[si
])
5739 /* The function makes initial partition of STATES on equivalent
5740 classes and saves it into *CLASSES. This function requires the input
5741 to be sorted via compare_states_for_equiv(). */
5743 init_equiv_class (VEC(state_t
,heap
) *states
, VEC (state_t
,heap
) **classes
)
5749 *classes
= VEC_alloc (state_t
,heap
, 150);
5750 for (i
= 0; i
< VEC_length (state_t
, states
); i
++)
5752 state_t state
= VEC_index (state_t
, states
, i
);
5755 if (compare_states_for_equiv (&prev
, &state
) != 0)
5757 VEC_safe_push (state_t
,heap
, *classes
, prev
);
5762 state
->equiv_class_num_1
= class_num
;
5763 state
->next_equiv_class_state
= prev
;
5767 VEC_safe_push (state_t
,heap
, *classes
, prev
);
5771 /* The function copies pointers to equivalent states from vla FROM
5774 copy_equiv_class (VEC(state_t
,heap
) **to
, VEC(state_t
,heap
) *from
)
5776 VEC_free (state_t
,heap
, *to
);
5777 *to
= VEC_copy (state_t
,heap
, from
);
5780 /* The function processes equivalence class given by its first state,
5781 FIRST_STATE, on odd iteration if ODD_ITERATION_FLAG. If there
5782 are not equivalent states, the function partitions the class
5783 removing nonequivalent states and placing them in
5784 *NEXT_ITERATION_CLASSES, increments *NEW_EQUIV_CLASS_NUM_PTR ans
5785 assigns it to the state equivalence number. If the class has been
5786 partitioned, the function returns nonzero value. */
5788 partition_equiv_class (state_t first_state
, int odd_iteration_flag
,
5789 VEC(state_t
,heap
) **next_iteration_classes
,
5790 int *new_equiv_class_num_ptr
)
5792 state_t new_equiv_class
;
5800 while (first_state
!= NULL
)
5802 new_equiv_class
= NULL
;
5803 if (first_state
->next_equiv_class_state
!= NULL
)
5805 /* There are more one states in the class equivalence. */
5806 set_out_arc_insns_equiv_num (first_state
, odd_iteration_flag
);
5807 for (prev_state
= first_state
,
5808 curr_state
= first_state
->next_equiv_class_state
;
5810 curr_state
= next_state
)
5812 next_state
= curr_state
->next_equiv_class_state
;
5813 if (state_is_differed (curr_state
, first_state
,
5814 odd_iteration_flag
))
5816 /* Remove curr state from the class equivalence. */
5817 prev_state
->next_equiv_class_state
= next_state
;
5818 /* Add curr state to the new class equivalence. */
5819 curr_state
->next_equiv_class_state
= new_equiv_class
;
5820 if (new_equiv_class
== NULL
)
5821 (*new_equiv_class_num_ptr
)++;
5822 if (odd_iteration_flag
)
5823 curr_state
->equiv_class_num_2
= *new_equiv_class_num_ptr
;
5825 curr_state
->equiv_class_num_1
= *new_equiv_class_num_ptr
;
5826 new_equiv_class
= curr_state
;
5830 prev_state
= curr_state
;
5832 clear_arc_insns_equiv_num (first_state
);
5834 if (new_equiv_class
!= NULL
)
5835 VEC_safe_push (state_t
,heap
, *next_iteration_classes
, new_equiv_class
);
5836 first_state
= new_equiv_class
;
5841 /* The function finds equivalent states of AUTOMATON. */
5843 evaluate_equiv_classes (automaton_t automaton
,
5844 VEC(state_t
,heap
) **equiv_classes
)
5846 int new_equiv_class_num
;
5847 int odd_iteration_flag
;
5849 VEC (state_t
,heap
) *next_iteration_classes
;
5852 all_achieved_states
= VEC_alloc (state_t
,heap
, 1500);
5853 pass_states (automaton
, add_achieved_state
);
5854 pass_states (automaton
, cache_presence
);
5855 qsort (VEC_address (state_t
, all_achieved_states
),
5856 VEC_length (state_t
, all_achieved_states
),
5857 sizeof (state_t
), compare_states_for_equiv
);
5859 odd_iteration_flag
= 0;
5860 new_equiv_class_num
= init_equiv_class (all_achieved_states
,
5861 &next_iteration_classes
);
5865 odd_iteration_flag
= !odd_iteration_flag
;
5867 copy_equiv_class (equiv_classes
, next_iteration_classes
);
5869 /* Transfer equiv numbers for the next iteration. */
5870 for (i
= 0; i
< VEC_length (state_t
, all_achieved_states
); i
++)
5871 if (odd_iteration_flag
)
5872 VEC_index (state_t
, all_achieved_states
, i
)->equiv_class_num_2
5873 = VEC_index (state_t
, all_achieved_states
, i
)->equiv_class_num_1
;
5875 VEC_index (state_t
, all_achieved_states
, i
)->equiv_class_num_1
5876 = VEC_index (state_t
, all_achieved_states
, i
)->equiv_class_num_2
;
5878 for (i
= 0; i
< VEC_length (state_t
, *equiv_classes
); i
++)
5879 if (partition_equiv_class (VEC_index (state_t
, *equiv_classes
, i
),
5881 &next_iteration_classes
,
5882 &new_equiv_class_num
))
5885 while (!finish_flag
);
5886 VEC_free (state_t
,heap
, next_iteration_classes
);
5887 VEC_free (state_t
,heap
, all_achieved_states
);
5890 /* The function merges equivalent states of AUTOMATON. */
5892 merge_states (automaton_t automaton
, VEC(state_t
,heap
) *equiv_classes
)
5896 state_t first_class_state
;
5897 alt_state_t alt_states
;
5898 alt_state_t alt_state
, new_alt_state
;
5903 /* Create states corresponding to equivalence classes containing two
5905 for (i
= 0; i
< VEC_length (state_t
, equiv_classes
); i
++)
5907 curr_state
= VEC_index (state_t
, equiv_classes
, i
);
5908 if (curr_state
->next_equiv_class_state
!= NULL
)
5910 /* There are more one states in the class equivalence. */
5911 /* Create new compound state. */
5912 new_state
= get_free_state (0, automaton
);
5914 first_class_state
= curr_state
;
5915 for (curr_state
= first_class_state
;
5917 curr_state
= curr_state
->next_equiv_class_state
)
5919 curr_state
->equiv_class_state
= new_state
;
5920 if (curr_state
->component_states
== NULL
)
5922 new_alt_state
= get_free_alt_state ();
5923 new_alt_state
->state
= curr_state
;
5924 new_alt_state
->next_alt_state
= alt_states
;
5925 alt_states
= new_alt_state
;
5928 for (alt_state
= curr_state
->component_states
;
5930 alt_state
= alt_state
->next_sorted_alt_state
)
5932 new_alt_state
= get_free_alt_state ();
5933 new_alt_state
->state
= alt_state
->state
;
5934 new_alt_state
->next_alt_state
= alt_states
;
5935 alt_states
= new_alt_state
;
5938 /* Its is important that alt states were sorted before and
5939 after merging to have the same querying results. */
5940 new_state
->component_states
= uniq_sort_alt_states (alt_states
);
5943 curr_state
->equiv_class_state
= curr_state
;
5946 for (i
= 0; i
< VEC_length (state_t
, equiv_classes
); i
++)
5948 curr_state
= VEC_index (state_t
, equiv_classes
, i
);
5949 if (curr_state
->next_equiv_class_state
!= NULL
)
5951 first_class_state
= curr_state
;
5952 /* Create new arcs output from the state corresponding to
5954 for (curr_arc
= first_out_arc (first_class_state
);
5956 curr_arc
= next_out_arc (curr_arc
))
5957 add_arc (first_class_state
->equiv_class_state
,
5958 curr_arc
->to_state
->equiv_class_state
,
5960 /* Delete output arcs from states of given class equivalence. */
5961 for (curr_state
= first_class_state
;
5963 curr_state
= curr_state
->next_equiv_class_state
)
5965 if (automaton
->start_state
== curr_state
)
5966 automaton
->start_state
= curr_state
->equiv_class_state
;
5967 /* Delete the state and its output arcs. */
5968 for (curr_arc
= first_out_arc (curr_state
);
5970 curr_arc
= next_arc
)
5972 next_arc
= next_out_arc (curr_arc
);
5973 free_arc (curr_arc
);
5979 /* Change `to_state' of arcs output from the state of given
5980 equivalence class. */
5981 for (curr_arc
= first_out_arc (curr_state
);
5983 curr_arc
= next_out_arc (curr_arc
))
5984 curr_arc
->to_state
= curr_arc
->to_state
->equiv_class_state
;
5989 /* The function sets up new_cycle_p for states if there is arc to the
5990 state marked by advance_cycle_insn_decl. */
5992 set_new_cycle_flags (state_t state
)
5996 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
5997 if (arc
->insn
->insn_reserv_decl
5998 == DECL_INSN_RESERV (advance_cycle_insn_decl
))
5999 arc
->to_state
->new_cycle_p
= 1;
6002 /* The top level function for minimization of deterministic
6005 minimize_DFA (automaton_t automaton
)
6007 VEC(state_t
,heap
) *equiv_classes
= 0;
6009 evaluate_equiv_classes (automaton
, &equiv_classes
);
6010 merge_states (automaton
, equiv_classes
);
6011 pass_states (automaton
, set_new_cycle_flags
);
6013 VEC_free (state_t
,heap
, equiv_classes
);
6016 /* Values of two variables are counted number of states and arcs in an
6018 static int curr_counted_states_num
;
6019 static int curr_counted_arcs_num
;
6021 /* The function is called by function `pass_states' to count states
6022 and arcs of an automaton. */
6024 incr_states_and_arcs_nums (state_t state
)
6028 curr_counted_states_num
++;
6029 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
6030 curr_counted_arcs_num
++;
6033 /* The function counts states and arcs of AUTOMATON. */
6035 count_states_and_arcs (automaton_t automaton
, int *states_num
,
6038 curr_counted_states_num
= 0;
6039 curr_counted_arcs_num
= 0;
6040 pass_states (automaton
, incr_states_and_arcs_nums
);
6041 *states_num
= curr_counted_states_num
;
6042 *arcs_num
= curr_counted_arcs_num
;
6045 /* The function builds one DFA AUTOMATON for fast pipeline hazards
6046 recognition after checking and simplifying IR of the
6049 build_automaton (automaton_t automaton
)
6054 ticker_on (&NDFA_time
);
6057 if (automaton
->corresponding_automaton_decl
== NULL
)
6058 fprintf (stderr
, "Create anonymous automaton");
6060 fprintf (stderr
, "Create automaton `%s'",
6061 automaton
->corresponding_automaton_decl
->name
);
6062 fprintf (stderr
, " (1 dot is 100 new states):");
6064 make_automaton (automaton
);
6066 fprintf (stderr
, " done\n");
6067 ticker_off (&NDFA_time
);
6068 count_states_and_arcs (automaton
, &states_num
, &arcs_num
);
6069 automaton
->NDFA_states_num
= states_num
;
6070 automaton
->NDFA_arcs_num
= arcs_num
;
6071 ticker_on (&NDFA_to_DFA_time
);
6074 if (automaton
->corresponding_automaton_decl
== NULL
)
6075 fprintf (stderr
, "Make anonymous DFA");
6077 fprintf (stderr
, "Make DFA `%s'",
6078 automaton
->corresponding_automaton_decl
->name
);
6079 fprintf (stderr
, " (1 dot is 100 new states):");
6081 NDFA_to_DFA (automaton
);
6083 fprintf (stderr
, " done\n");
6084 ticker_off (&NDFA_to_DFA_time
);
6085 count_states_and_arcs (automaton
, &states_num
, &arcs_num
);
6086 automaton
->DFA_states_num
= states_num
;
6087 automaton
->DFA_arcs_num
= arcs_num
;
6088 if (!no_minimization_flag
)
6090 ticker_on (&minimize_time
);
6093 if (automaton
->corresponding_automaton_decl
== NULL
)
6094 fprintf (stderr
, "Minimize anonymous DFA...");
6096 fprintf (stderr
, "Minimize DFA `%s'...",
6097 automaton
->corresponding_automaton_decl
->name
);
6099 minimize_DFA (automaton
);
6101 fprintf (stderr
, "done\n");
6102 ticker_off (&minimize_time
);
6103 count_states_and_arcs (automaton
, &states_num
, &arcs_num
);
6104 automaton
->minimal_DFA_states_num
= states_num
;
6105 automaton
->minimal_DFA_arcs_num
= arcs_num
;
6111 /* The page contains code for enumeration of all states of an automaton. */
6113 /* Variable used for enumeration of all states of an automaton. Its
6114 value is current number of automaton states. */
6115 static int curr_state_order_num
;
6117 /* The function is called by function `pass_states' for enumerating
6120 set_order_state_num (state_t state
)
6122 state
->order_state_num
= curr_state_order_num
;
6123 curr_state_order_num
++;
6126 /* The function enumerates all states of AUTOMATON. */
6128 enumerate_states (automaton_t automaton
)
6130 curr_state_order_num
= 0;
6131 pass_states (automaton
, set_order_state_num
);
6132 automaton
->achieved_states_num
= curr_state_order_num
;
6137 /* The page contains code for finding equivalent automaton insns
6140 /* The function inserts AINSN into cyclic list
6141 CYCLIC_EQUIV_CLASS_INSN_LIST of ainsns. */
6143 insert_ainsn_into_equiv_class (ainsn_t ainsn
,
6144 ainsn_t cyclic_equiv_class_insn_list
)
6146 if (cyclic_equiv_class_insn_list
== NULL
)
6147 ainsn
->next_equiv_class_insn
= ainsn
;
6150 ainsn
->next_equiv_class_insn
6151 = cyclic_equiv_class_insn_list
->next_equiv_class_insn
;
6152 cyclic_equiv_class_insn_list
->next_equiv_class_insn
= ainsn
;
6157 /* The function deletes equiv_class_insn into cyclic list of
6158 equivalent ainsns. */
6160 delete_ainsn_from_equiv_class (ainsn_t equiv_class_insn
)
6162 ainsn_t curr_equiv_class_insn
;
6163 ainsn_t prev_equiv_class_insn
;
6165 prev_equiv_class_insn
= equiv_class_insn
;
6166 for (curr_equiv_class_insn
= equiv_class_insn
->next_equiv_class_insn
;
6167 curr_equiv_class_insn
!= equiv_class_insn
;
6168 curr_equiv_class_insn
= curr_equiv_class_insn
->next_equiv_class_insn
)
6169 prev_equiv_class_insn
= curr_equiv_class_insn
;
6170 if (prev_equiv_class_insn
!= equiv_class_insn
)
6171 prev_equiv_class_insn
->next_equiv_class_insn
6172 = equiv_class_insn
->next_equiv_class_insn
;
6175 /* The function processes AINSN of a state in order to find equivalent
6176 ainsns. INSN_ARCS_ARRAY is table: code of insn -> out arc of the
6179 process_insn_equiv_class (ainsn_t ainsn
, arc_t
*insn_arcs_array
)
6183 ainsn_t cyclic_insn_list
;
6186 gcc_assert (insn_arcs_array
[ainsn
->insn_reserv_decl
->insn_num
]);
6188 /* New class of ainsns which are not equivalent to given ainsn. */
6189 cyclic_insn_list
= NULL
;
6192 next_insn
= curr_insn
->next_equiv_class_insn
;
6193 arc
= insn_arcs_array
[curr_insn
->insn_reserv_decl
->insn_num
];
6195 || (insn_arcs_array
[ainsn
->insn_reserv_decl
->insn_num
]->to_state
6198 delete_ainsn_from_equiv_class (curr_insn
);
6199 cyclic_insn_list
= insert_ainsn_into_equiv_class (curr_insn
,
6202 curr_insn
= next_insn
;
6204 while (curr_insn
!= ainsn
);
6207 /* The function processes STATE in order to find equivalent ainsns. */
6209 process_state_for_insn_equiv_partition (state_t state
)
6212 arc_t
*insn_arcs_array
= XCNEWVEC (arc_t
, description
->insns_num
);
6214 /* Process insns of the arcs. */
6215 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
6216 insn_arcs_array
[arc
->insn
->insn_reserv_decl
->insn_num
] = arc
;
6217 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
6218 process_insn_equiv_class (arc
->insn
, insn_arcs_array
);
6220 free (insn_arcs_array
);
6223 /* The function searches for equivalent ainsns of AUTOMATON. */
6225 set_insn_equiv_classes (automaton_t automaton
)
6230 ainsn_t cyclic_insn_list
;
6231 ainsn_t insn_with_same_reservs
;
6232 int equiv_classes_num
;
6234 /* All insns are included in one equivalence class. */
6235 cyclic_insn_list
= NULL
;
6236 for (ainsn
= automaton
->ainsn_list
; ainsn
!= NULL
; ainsn
= ainsn
->next_ainsn
)
6237 if (ainsn
->first_insn_with_same_reservs
)
6238 cyclic_insn_list
= insert_ainsn_into_equiv_class (ainsn
,
6240 /* Process insns in order to make equivalence partition. */
6241 pass_states (automaton
, process_state_for_insn_equiv_partition
);
6242 /* Enumerate equiv classes. */
6243 for (ainsn
= automaton
->ainsn_list
; ainsn
!= NULL
; ainsn
= ainsn
->next_ainsn
)
6244 /* Set undefined value. */
6245 ainsn
->insn_equiv_class_num
= -1;
6246 equiv_classes_num
= 0;
6247 for (ainsn
= automaton
->ainsn_list
; ainsn
!= NULL
; ainsn
= ainsn
->next_ainsn
)
6248 if (ainsn
->insn_equiv_class_num
< 0)
6251 gcc_assert (first_insn
->first_insn_with_same_reservs
);
6252 first_insn
->first_ainsn_with_given_equivalence_num
= 1;
6253 curr_insn
= first_insn
;
6256 for (insn_with_same_reservs
= curr_insn
;
6257 insn_with_same_reservs
!= NULL
;
6258 insn_with_same_reservs
6259 = insn_with_same_reservs
->next_same_reservs_insn
)
6260 insn_with_same_reservs
->insn_equiv_class_num
= equiv_classes_num
;
6261 curr_insn
= curr_insn
->next_equiv_class_insn
;
6263 while (curr_insn
!= first_insn
);
6264 equiv_classes_num
++;
6266 automaton
->insn_equiv_classes_num
= equiv_classes_num
;
6271 /* This page contains code for creating DFA(s) and calls functions
6275 /* The following value is used to prevent floating point overflow for
6276 estimating an automaton bound. The value should be less DBL_MAX on
6277 the host machine. We use here approximate minimum of maximal
6278 double floating point value required by ANSI C standard. It
6279 will work for non ANSI sun compiler too. */
6281 #define MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND 1.0E37
6283 /* The function estimate size of the single DFA used by PHR (pipeline
6284 hazards recognizer). */
6286 estimate_one_automaton_bound (void)
6289 double one_automaton_estimation_bound
;
6293 one_automaton_estimation_bound
= 1.0;
6294 for (i
= 0; i
< description
->decls_num
; i
++)
6296 decl
= description
->decls
[i
];
6297 if (decl
->mode
== dm_unit
)
6299 root_value
= exp (log (DECL_UNIT (decl
)->max_occ_cycle_num
6300 - DECL_UNIT (decl
)->min_occ_cycle_num
+ 1.0)
6302 if (MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND
/ root_value
6303 > one_automaton_estimation_bound
)
6304 one_automaton_estimation_bound
*= root_value
;
6307 return one_automaton_estimation_bound
;
6310 /* The function compares unit declarations according to their maximal
6311 cycle in reservations. */
6313 compare_max_occ_cycle_nums (const void *unit_decl_1
,
6314 const void *unit_decl_2
)
6316 if ((DECL_UNIT (*(decl_t
*) unit_decl_1
)->max_occ_cycle_num
)
6317 < (DECL_UNIT (*(decl_t
*) unit_decl_2
)->max_occ_cycle_num
))
6319 else if ((DECL_UNIT (*(decl_t
*) unit_decl_1
)->max_occ_cycle_num
)
6320 == (DECL_UNIT (*(decl_t
*) unit_decl_2
)->max_occ_cycle_num
))
6326 /* The function makes heuristic assigning automata to units. Actually
6327 efficacy of the algorithm has been checked yet??? */
6330 units_to_automata_heuristic_distr (void)
6332 double estimation_bound
;
6336 unit_decl_t
*unit_decls
;
6339 if (description
->units_num
== 0)
6341 estimation_bound
= estimate_one_automaton_bound ();
6342 unit_decls
= XNEWVEC (unit_decl_t
, description
->units_num
);
6344 for (i
= 0, j
= 0; i
< description
->decls_num
; i
++)
6345 if (description
->decls
[i
]->mode
== dm_unit
)
6346 unit_decls
[j
++] = DECL_UNIT (description
->decls
[i
]);
6347 gcc_assert (j
== description
->units_num
);
6349 qsort (unit_decls
, description
->units_num
,
6350 sizeof (unit_decl_t
), compare_max_occ_cycle_nums
);
6353 bound_value
= unit_decls
[0]->max_occ_cycle_num
;
6354 unit_decls
[0]->corresponding_automaton_num
= automaton_num
;
6356 for (i
= 1; i
< description
->units_num
; i
++)
6358 rest_units_num
= description
->units_num
- i
+ 1;
6359 gcc_assert (automata_num
- automaton_num
- 1 <= rest_units_num
);
6360 if (automaton_num
< automata_num
- 1
6361 && ((automata_num
- automaton_num
- 1 == rest_units_num
)
6364 / unit_decls
[i
]->max_occ_cycle_num
))))
6366 bound_value
= unit_decls
[i
]->max_occ_cycle_num
;
6370 bound_value
*= unit_decls
[i
]->max_occ_cycle_num
;
6371 unit_decls
[i
]->corresponding_automaton_num
= automaton_num
;
6373 gcc_assert (automaton_num
== automata_num
- 1);
6377 /* The functions creates automaton insns for each automata. Automaton
6378 insn is simply insn for given automaton which makes reservation
6379 only of units of the automaton. */
6381 create_ainsns (void)
6384 ainsn_t first_ainsn
;
6391 for (i
= 0; i
< description
->decls_num
; i
++)
6393 decl
= description
->decls
[i
];
6394 if (decl
->mode
== dm_insn_reserv
)
6396 curr_ainsn
= create_node (sizeof (struct ainsn
));
6397 curr_ainsn
->insn_reserv_decl
= DECL_INSN_RESERV (decl
);
6398 curr_ainsn
->important_p
= FALSE
;
6399 curr_ainsn
->next_ainsn
= NULL
;
6400 if (prev_ainsn
== NULL
)
6401 first_ainsn
= curr_ainsn
;
6403 prev_ainsn
->next_ainsn
= curr_ainsn
;
6404 prev_ainsn
= curr_ainsn
;
6410 /* The function assigns automata to units according to constructions
6411 `define_automaton' in the description. */
6413 units_to_automata_distr (void)
6418 for (i
= 0; i
< description
->decls_num
; i
++)
6420 decl
= description
->decls
[i
];
6421 if (decl
->mode
== dm_unit
)
6423 if (DECL_UNIT (decl
)->automaton_decl
== NULL
6424 || (DECL_UNIT (decl
)->automaton_decl
->corresponding_automaton
6426 /* Distribute to the first automaton. */
6427 DECL_UNIT (decl
)->corresponding_automaton_num
= 0;
6429 DECL_UNIT (decl
)->corresponding_automaton_num
6430 = (DECL_UNIT (decl
)->automaton_decl
6431 ->corresponding_automaton
->automaton_order_num
);
6436 /* The function creates DFA(s) for fast pipeline hazards recognition
6437 after checking and simplifying IR of the description. */
6439 create_automata (void)
6441 automaton_t curr_automaton
;
6442 automaton_t prev_automaton
;
6444 int curr_automaton_num
;
6447 if (automata_num
!= 0)
6449 units_to_automata_heuristic_distr ();
6450 for (prev_automaton
= NULL
, curr_automaton_num
= 0;
6451 curr_automaton_num
< automata_num
;
6452 curr_automaton_num
++, prev_automaton
= curr_automaton
)
6454 curr_automaton
= create_node (sizeof (struct automaton
));
6455 curr_automaton
->ainsn_list
= create_ainsns ();
6456 curr_automaton
->corresponding_automaton_decl
= NULL
;
6457 curr_automaton
->next_automaton
= NULL
;
6458 curr_automaton
->automaton_order_num
= curr_automaton_num
;
6459 if (prev_automaton
== NULL
)
6460 description
->first_automaton
= curr_automaton
;
6462 prev_automaton
->next_automaton
= curr_automaton
;
6467 curr_automaton_num
= 0;
6468 prev_automaton
= NULL
;
6469 for (i
= 0; i
< description
->decls_num
; i
++)
6471 decl
= description
->decls
[i
];
6472 if (decl
->mode
== dm_automaton
6473 && DECL_AUTOMATON (decl
)->automaton_is_used
)
6475 curr_automaton
= create_node (sizeof (struct automaton
));
6476 curr_automaton
->ainsn_list
= create_ainsns ();
6477 curr_automaton
->corresponding_automaton_decl
6478 = DECL_AUTOMATON (decl
);
6479 curr_automaton
->next_automaton
= NULL
;
6480 DECL_AUTOMATON (decl
)->corresponding_automaton
= curr_automaton
;
6481 curr_automaton
->automaton_order_num
= curr_automaton_num
;
6482 if (prev_automaton
== NULL
)
6483 description
->first_automaton
= curr_automaton
;
6485 prev_automaton
->next_automaton
= curr_automaton
;
6486 curr_automaton_num
++;
6487 prev_automaton
= curr_automaton
;
6490 if (curr_automaton_num
== 0)
6492 curr_automaton
= create_node (sizeof (struct automaton
));
6493 curr_automaton
->ainsn_list
= create_ainsns ();
6494 curr_automaton
->corresponding_automaton_decl
= NULL
;
6495 curr_automaton
->next_automaton
= NULL
;
6496 description
->first_automaton
= curr_automaton
;
6498 units_to_automata_distr ();
6500 NDFA_time
= create_ticker ();
6501 ticker_off (&NDFA_time
);
6502 NDFA_to_DFA_time
= create_ticker ();
6503 ticker_off (&NDFA_to_DFA_time
);
6504 minimize_time
= create_ticker ();
6505 ticker_off (&minimize_time
);
6506 equiv_time
= create_ticker ();
6507 ticker_off (&equiv_time
);
6508 for (curr_automaton
= description
->first_automaton
;
6509 curr_automaton
!= NULL
;
6510 curr_automaton
= curr_automaton
->next_automaton
)
6514 if (curr_automaton
->corresponding_automaton_decl
== NULL
)
6515 fprintf (stderr
, "Prepare anonymous automaton creation ... ");
6517 fprintf (stderr
, "Prepare automaton `%s' creation...",
6518 curr_automaton
->corresponding_automaton_decl
->name
);
6520 create_alt_states (curr_automaton
);
6521 form_ainsn_with_same_reservs (curr_automaton
);
6523 fprintf (stderr
, "done\n");
6524 build_automaton (curr_automaton
);
6525 enumerate_states (curr_automaton
);
6526 ticker_on (&equiv_time
);
6527 set_insn_equiv_classes (curr_automaton
);
6528 ticker_off (&equiv_time
);
6534 /* This page contains code for forming string representation of
6535 regexp. The representation is formed on IR obstack. So you should
6536 not work with IR obstack between regexp_representation and
6537 finish_regexp_representation calls. */
6539 /* This recursive function forms string representation of regexp
6540 (without tailing '\0'). */
6542 form_regexp (regexp_t regexp
)
6546 switch (regexp
->mode
)
6548 case rm_unit
: case rm_reserv
:
6550 const char *name
= (regexp
->mode
== rm_unit
6551 ? REGEXP_UNIT (regexp
)->name
6552 : REGEXP_RESERV (regexp
)->name
);
6554 obstack_grow (&irp
, name
, strlen (name
));
6559 for (i
= 0; i
< REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
6562 obstack_1grow (&irp
, ',');
6563 form_regexp (REGEXP_SEQUENCE (regexp
)->regexps
[i
]);
6568 obstack_1grow (&irp
, '(');
6569 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
6572 obstack_1grow (&irp
, '+');
6573 if (REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
== rm_sequence
6574 || REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
== rm_oneof
)
6575 obstack_1grow (&irp
, '(');
6576 form_regexp (REGEXP_ALLOF (regexp
)->regexps
[i
]);
6577 if (REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
== rm_sequence
6578 || REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
== rm_oneof
)
6579 obstack_1grow (&irp
, ')');
6581 obstack_1grow (&irp
, ')');
6585 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
6588 obstack_1grow (&irp
, '|');
6589 if (REGEXP_ONEOF (regexp
)->regexps
[i
]->mode
== rm_sequence
)
6590 obstack_1grow (&irp
, '(');
6591 form_regexp (REGEXP_ONEOF (regexp
)->regexps
[i
]);
6592 if (REGEXP_ONEOF (regexp
)->regexps
[i
]->mode
== rm_sequence
)
6593 obstack_1grow (&irp
, ')');
6601 if (REGEXP_REPEAT (regexp
)->regexp
->mode
== rm_sequence
6602 || REGEXP_REPEAT (regexp
)->regexp
->mode
== rm_allof
6603 || REGEXP_REPEAT (regexp
)->regexp
->mode
== rm_oneof
)
6604 obstack_1grow (&irp
, '(');
6605 form_regexp (REGEXP_REPEAT (regexp
)->regexp
);
6606 if (REGEXP_REPEAT (regexp
)->regexp
->mode
== rm_sequence
6607 || REGEXP_REPEAT (regexp
)->regexp
->mode
== rm_allof
6608 || REGEXP_REPEAT (regexp
)->regexp
->mode
== rm_oneof
)
6609 obstack_1grow (&irp
, ')');
6610 sprintf (digits
, "*%d", REGEXP_REPEAT (regexp
)->repeat_num
);
6611 obstack_grow (&irp
, digits
, strlen (digits
));
6616 obstack_grow (&irp
, NOTHING_NAME
, strlen (NOTHING_NAME
));
6624 /* The function returns string representation of REGEXP on IR
6627 regexp_representation (regexp_t regexp
)
6629 form_regexp (regexp
);
6630 obstack_1grow (&irp
, '\0');
6631 return obstack_base (&irp
);
6634 /* The function frees memory allocated for last formed string
6635 representation of regexp. */
6637 finish_regexp_representation (void)
6639 int length
= obstack_object_size (&irp
);
6641 obstack_blank_fast (&irp
, -length
);
6646 /* This page contains code for output PHR (pipeline hazards recognizer). */
6648 /* The function outputs minimal C type which is sufficient for
6649 representation numbers in range min_range_value and
6650 max_range_value. Because host machine and build machine may be
6651 different, we use here minimal values required by ANSI C standard
6652 instead of UCHAR_MAX, SHRT_MAX, SHRT_MIN, etc. This is a good
6656 output_range_type (FILE *f
, long int min_range_value
,
6657 long int max_range_value
)
6659 if (min_range_value
>= 0 && max_range_value
<= 255)
6660 fprintf (f
, "unsigned char");
6661 else if (min_range_value
>= -127 && max_range_value
<= 127)
6662 fprintf (f
, "signed char");
6663 else if (min_range_value
>= 0 && max_range_value
<= 65535)
6664 fprintf (f
, "unsigned short");
6665 else if (min_range_value
>= -32767 && max_range_value
<= 32767)
6666 fprintf (f
, "short");
6671 /* The function outputs all initialization values of VECT. */
6673 output_vect (vla_hwint_t vect
)
6676 size_t vect_length
= VEC_length (vect_el_t
, vect
);
6680 if (vect_length
== 0)
6681 fputs ("0 /* This is dummy el because the vect is empty */", output_file
);
6683 for (i
= 0; i
< vect_length
; i
++)
6685 fprintf (output_file
, "%5ld", (long) VEC_index (vect_el_t
, vect
, i
));
6686 if (els_on_line
== 10)
6689 fputs (",\n", output_file
);
6691 else if (i
< vect_length
-1)
6692 fputs (", ", output_file
);
6697 /* The following is name of the structure which represents DFA(s) for
6699 #define CHIP_NAME "DFA_chip"
6701 /* The following is name of member which represents state of a DFA for
6704 output_chip_member_name (FILE *f
, automaton_t automaton
)
6706 if (automaton
->corresponding_automaton_decl
== NULL
)
6707 fprintf (f
, "automaton_state_%d", automaton
->automaton_order_num
);
6709 fprintf (f
, "%s_automaton_state",
6710 automaton
->corresponding_automaton_decl
->name
);
6713 /* The following is name of temporary variable which stores state of a
6716 output_temp_chip_member_name (FILE *f
, automaton_t automaton
)
6719 output_chip_member_name (f
, automaton
);
6722 /* This is name of macro value which is code of pseudo_insn
6723 representing advancing cpu cycle. Its value is used as internal
6724 code unknown insn. */
6725 #define ADVANCE_CYCLE_VALUE_NAME "DFA__ADVANCE_CYCLE"
6727 /* Output name of translate vector for given automaton. */
6729 output_translate_vect_name (FILE *f
, automaton_t automaton
)
6731 if (automaton
->corresponding_automaton_decl
== NULL
)
6732 fprintf (f
, "translate_%d", automaton
->automaton_order_num
);
6734 fprintf (f
, "%s_translate", automaton
->corresponding_automaton_decl
->name
);
6737 /* Output name for simple transition table representation. */
6739 output_trans_full_vect_name (FILE *f
, automaton_t automaton
)
6741 if (automaton
->corresponding_automaton_decl
== NULL
)
6742 fprintf (f
, "transitions_%d", automaton
->automaton_order_num
);
6744 fprintf (f
, "%s_transitions",
6745 automaton
->corresponding_automaton_decl
->name
);
6748 /* Output name of comb vector of the transition table for given
6751 output_trans_comb_vect_name (FILE *f
, automaton_t automaton
)
6753 if (automaton
->corresponding_automaton_decl
== NULL
)
6754 fprintf (f
, "transitions_%d", automaton
->automaton_order_num
);
6756 fprintf (f
, "%s_transitions",
6757 automaton
->corresponding_automaton_decl
->name
);
6760 /* Output name of check vector of the transition table for given
6763 output_trans_check_vect_name (FILE *f
, automaton_t automaton
)
6765 if (automaton
->corresponding_automaton_decl
== NULL
)
6766 fprintf (f
, "check_%d", automaton
->automaton_order_num
);
6768 fprintf (f
, "%s_check", automaton
->corresponding_automaton_decl
->name
);
6771 /* Output name of base vector of the transition table for given
6774 output_trans_base_vect_name (FILE *f
, automaton_t automaton
)
6776 if (automaton
->corresponding_automaton_decl
== NULL
)
6777 fprintf (f
, "base_%d", automaton
->automaton_order_num
);
6779 fprintf (f
, "%s_base", automaton
->corresponding_automaton_decl
->name
);
6782 /* Output name of simple min issue delay table representation. */
6784 output_min_issue_delay_vect_name (FILE *f
, automaton_t automaton
)
6786 if (automaton
->corresponding_automaton_decl
== NULL
)
6787 fprintf (f
, "min_issue_delay_%d", automaton
->automaton_order_num
);
6789 fprintf (f
, "%s_min_issue_delay",
6790 automaton
->corresponding_automaton_decl
->name
);
6793 /* Output name of deadlock vector for given automaton. */
6795 output_dead_lock_vect_name (FILE *f
, automaton_t automaton
)
6797 if (automaton
->corresponding_automaton_decl
== NULL
)
6798 fprintf (f
, "dead_lock_%d", automaton
->automaton_order_num
);
6800 fprintf (f
, "%s_dead_lock", automaton
->corresponding_automaton_decl
->name
);
6803 /* Output name of reserved units table for AUTOMATON into file F. */
6805 output_reserved_units_table_name (FILE *f
, automaton_t automaton
)
6807 if (automaton
->corresponding_automaton_decl
== NULL
)
6808 fprintf (f
, "reserved_units_%d", automaton
->automaton_order_num
);
6810 fprintf (f
, "%s_reserved_units",
6811 automaton
->corresponding_automaton_decl
->name
);
6814 /* Name of the PHR interface macro. */
6815 #define CPU_UNITS_QUERY_MACRO_NAME "CPU_UNITS_QUERY"
6817 /* Names of an internal functions: */
6818 #define INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME "internal_min_issue_delay"
6820 /* This is external type of DFA(s) state. */
6821 #define STATE_TYPE_NAME "state_t"
6823 #define INTERNAL_TRANSITION_FUNC_NAME "internal_state_transition"
6825 #define INTERNAL_RESET_FUNC_NAME "internal_reset"
6827 #define INTERNAL_DEAD_LOCK_FUNC_NAME "internal_state_dead_lock_p"
6829 #define INTERNAL_INSN_LATENCY_FUNC_NAME "internal_insn_latency"
6831 /* Name of cache of insn dfa codes. */
6832 #define DFA_INSN_CODES_VARIABLE_NAME "dfa_insn_codes"
6834 /* Name of length of cache of insn dfa codes. */
6835 #define DFA_INSN_CODES_LENGTH_VARIABLE_NAME "dfa_insn_codes_length"
6837 /* Names of the PHR interface functions: */
6838 #define SIZE_FUNC_NAME "state_size"
6840 #define TRANSITION_FUNC_NAME "state_transition"
6842 #define MIN_ISSUE_DELAY_FUNC_NAME "min_issue_delay"
6844 #define MIN_INSN_CONFLICT_DELAY_FUNC_NAME "min_insn_conflict_delay"
6846 #define DEAD_LOCK_FUNC_NAME "state_dead_lock_p"
6848 #define RESET_FUNC_NAME "state_reset"
6850 #define INSN_LATENCY_FUNC_NAME "insn_latency"
6852 #define PRINT_RESERVATION_FUNC_NAME "print_reservation"
6854 #define GET_CPU_UNIT_CODE_FUNC_NAME "get_cpu_unit_code"
6856 #define CPU_UNIT_RESERVATION_P_FUNC_NAME "cpu_unit_reservation_p"
6858 #define DFA_CLEAN_INSN_CACHE_FUNC_NAME "dfa_clean_insn_cache"
6860 #define DFA_CLEAR_SINGLE_INSN_CACHE_FUNC_NAME "dfa_clear_single_insn_cache"
6862 #define DFA_START_FUNC_NAME "dfa_start"
6864 #define DFA_FINISH_FUNC_NAME "dfa_finish"
6866 /* Names of parameters of the PHR interface functions. */
6867 #define STATE_NAME "state"
6869 #define INSN_PARAMETER_NAME "insn"
6871 #define INSN2_PARAMETER_NAME "insn2"
6873 #define CHIP_PARAMETER_NAME "chip"
6875 #define FILE_PARAMETER_NAME "f"
6877 #define CPU_UNIT_NAME_PARAMETER_NAME "cpu_unit_name"
6879 #define CPU_CODE_PARAMETER_NAME "cpu_unit_code"
6881 /* Names of the variables whose values are internal insn code of rtx
6883 #define INTERNAL_INSN_CODE_NAME "insn_code"
6885 #define INTERNAL_INSN2_CODE_NAME "insn2_code"
6887 /* Names of temporary variables in some functions. */
6888 #define TEMPORARY_VARIABLE_NAME "temp"
6890 #define I_VARIABLE_NAME "i"
6892 /* Name of result variable in some functions. */
6893 #define RESULT_VARIABLE_NAME "res"
6895 /* Name of function (attribute) to translate insn into internal insn
6897 #define INTERNAL_DFA_INSN_CODE_FUNC_NAME "internal_dfa_insn_code"
6899 /* Name of function (attribute) to translate insn into internal insn
6900 code with caching. */
6901 #define DFA_INSN_CODE_FUNC_NAME "dfa_insn_code"
6903 /* Output C type which is used for representation of codes of states
6906 output_state_member_type (FILE *f
, automaton_t automaton
)
6908 output_range_type (f
, 0, automaton
->achieved_states_num
);
6911 /* Output definition of the structure representing current DFA(s)
6914 output_chip_definitions (void)
6916 automaton_t automaton
;
6918 fprintf (output_file
, "struct %s\n{\n", CHIP_NAME
);
6919 for (automaton
= description
->first_automaton
;
6921 automaton
= automaton
->next_automaton
)
6923 fprintf (output_file
, " ");
6924 output_state_member_type (output_file
, automaton
);
6925 fprintf (output_file
, " ");
6926 output_chip_member_name (output_file
, automaton
);
6927 fprintf (output_file
, ";\n");
6929 fprintf (output_file
, "};\n\n");
6931 fprintf (output_file
, "static struct %s %s;\n\n", CHIP_NAME
, CHIP_NAME
);
6936 /* The function outputs translate vector of internal insn code into
6937 insn equivalence class number. The equivalence class number is
6938 used to access to table and vectors representing DFA(s). */
6940 output_translate_vect (automaton_t automaton
)
6944 vla_hwint_t translate_vect
;
6946 translate_vect
= VEC_alloc (vect_el_t
,heap
, description
->insns_num
);
6948 for (insn_value
= 0; insn_value
< description
->insns_num
; insn_value
++)
6949 /* Undefined value */
6950 VEC_quick_push (vect_el_t
, translate_vect
,
6951 automaton
->insn_equiv_classes_num
);
6953 for (ainsn
= automaton
->ainsn_list
; ainsn
!= NULL
; ainsn
= ainsn
->next_ainsn
)
6954 VEC_replace (vect_el_t
, translate_vect
,
6955 ainsn
->insn_reserv_decl
->insn_num
,
6956 ainsn
->insn_equiv_class_num
);
6958 fprintf (output_file
,
6959 "/* Vector translating external insn codes to internal ones.*/\n");
6960 fprintf (output_file
, "static const ");
6961 output_range_type (output_file
, 0, automaton
->insn_equiv_classes_num
);
6962 fprintf (output_file
, " ");
6963 output_translate_vect_name (output_file
, automaton
);
6964 fprintf (output_file
, "[] ATTRIBUTE_UNUSED = {\n");
6965 output_vect (translate_vect
);
6966 fprintf (output_file
, "};\n\n");
6967 VEC_free (vect_el_t
,heap
, translate_vect
);
6970 /* The value in a table state x ainsn -> something which represents
6972 static int undefined_vect_el_value
;
6974 /* The following function returns nonzero value if the best
6975 representation of the table is comb vector. */
6977 comb_vect_p (state_ainsn_table_t tab
)
6979 return (2 * VEC_length (vect_el_t
, tab
->full_vect
)
6980 > 5 * VEC_length (vect_el_t
, tab
->comb_vect
));
6983 /* The following function creates new table for AUTOMATON. */
6984 static state_ainsn_table_t
6985 create_state_ainsn_table (automaton_t automaton
)
6987 state_ainsn_table_t tab
;
6988 int full_vect_length
;
6991 tab
= create_node (sizeof (struct state_ainsn_table
));
6992 tab
->automaton
= automaton
;
6994 tab
->comb_vect
= VEC_alloc (vect_el_t
,heap
, 10000);
6995 tab
->check_vect
= VEC_alloc (vect_el_t
,heap
, 10000);
6998 VEC_safe_grow (vect_el_t
,heap
, tab
->base_vect
,
6999 automaton
->achieved_states_num
);
7001 full_vect_length
= (automaton
->insn_equiv_classes_num
7002 * automaton
->achieved_states_num
);
7003 tab
->full_vect
= VEC_alloc (vect_el_t
,heap
, full_vect_length
);
7004 for (i
= 0; i
< full_vect_length
; i
++)
7005 VEC_quick_push (vect_el_t
, tab
->full_vect
, undefined_vect_el_value
);
7007 tab
->min_base_vect_el_value
= 0;
7008 tab
->max_base_vect_el_value
= 0;
7009 tab
->min_comb_vect_el_value
= 0;
7010 tab
->max_comb_vect_el_value
= 0;
7014 /* The following function outputs the best C representation of the
7015 table TAB of given TABLE_NAME. */
7017 output_state_ainsn_table (state_ainsn_table_t tab
, const char *table_name
,
7018 void (*output_full_vect_name_func
) (FILE *, automaton_t
),
7019 void (*output_comb_vect_name_func
) (FILE *, automaton_t
),
7020 void (*output_check_vect_name_func
) (FILE *, automaton_t
),
7021 void (*output_base_vect_name_func
) (FILE *, automaton_t
))
7023 if (!comb_vect_p (tab
))
7025 fprintf (output_file
, "/* Vector for %s. */\n", table_name
);
7026 fprintf (output_file
, "static const ");
7027 output_range_type (output_file
, tab
->min_comb_vect_el_value
,
7028 tab
->max_comb_vect_el_value
);
7029 fprintf (output_file
, " ");
7030 (*output_full_vect_name_func
) (output_file
, tab
->automaton
);
7031 fprintf (output_file
, "[] ATTRIBUTE_UNUSED = {\n");
7032 output_vect (tab
->full_vect
);
7033 fprintf (output_file
, "};\n\n");
7037 fprintf (output_file
, "/* Comb vector for %s. */\n", table_name
);
7038 fprintf (output_file
, "static const ");
7039 output_range_type (output_file
, tab
->min_comb_vect_el_value
,
7040 tab
->max_comb_vect_el_value
);
7041 fprintf (output_file
, " ");
7042 (*output_comb_vect_name_func
) (output_file
, tab
->automaton
);
7043 fprintf (output_file
, "[] ATTRIBUTE_UNUSED = {\n");
7044 output_vect (tab
->comb_vect
);
7045 fprintf (output_file
, "};\n\n");
7046 fprintf (output_file
, "/* Check vector for %s. */\n", table_name
);
7047 fprintf (output_file
, "static const ");
7048 output_range_type (output_file
, 0, tab
->automaton
->achieved_states_num
);
7049 fprintf (output_file
, " ");
7050 (*output_check_vect_name_func
) (output_file
, tab
->automaton
);
7051 fprintf (output_file
, "[] = {\n");
7052 output_vect (tab
->check_vect
);
7053 fprintf (output_file
, "};\n\n");
7054 fprintf (output_file
, "/* Base vector for %s. */\n", table_name
);
7055 fprintf (output_file
, "static const ");
7056 output_range_type (output_file
, tab
->min_base_vect_el_value
,
7057 tab
->max_base_vect_el_value
);
7058 fprintf (output_file
, " ");
7059 (*output_base_vect_name_func
) (output_file
, tab
->automaton
);
7060 fprintf (output_file
, "[] = {\n");
7061 output_vect (tab
->base_vect
);
7062 fprintf (output_file
, "};\n\n");
7066 /* The following function adds vector VECT to table TAB as its line
7067 with number VECT_NUM. */
7069 add_vect (state_ainsn_table_t tab
, int vect_num
, vla_hwint_t vect
)
7072 size_t real_vect_length
;
7073 int comb_vect_index
;
7074 int comb_vect_els_num
;
7076 int first_unempty_vect_index
;
7077 int additional_els_num
;
7081 unsigned long vect_mask
, comb_vect_mask
;
7083 vect_length
= VEC_length (vect_el_t
, vect
);
7084 gcc_assert (vect_length
);
7085 gcc_assert (VEC_last (vect_el_t
, vect
) != undefined_vect_el_value
);
7086 real_vect_length
= tab
->automaton
->insn_equiv_classes_num
;
7087 /* Form full vector in the table: */
7089 size_t full_base
= tab
->automaton
->insn_equiv_classes_num
* vect_num
;
7090 if (VEC_length (vect_el_t
, tab
->full_vect
) < full_base
+ vect_length
)
7091 VEC_safe_grow (vect_el_t
,heap
, tab
->full_vect
,
7092 full_base
+ vect_length
);
7093 for (i
= 0; i
< vect_length
; i
++)
7094 VEC_replace (vect_el_t
, tab
->full_vect
, full_base
+ i
,
7095 VEC_index (vect_el_t
, vect
, i
));
7097 /* Form comb vector in the table: */
7098 gcc_assert (VEC_length (vect_el_t
, tab
->comb_vect
)
7099 == VEC_length (vect_el_t
, tab
->check_vect
));
7101 comb_vect_els_num
= VEC_length (vect_el_t
, tab
->comb_vect
);
7102 for (first_unempty_vect_index
= 0;
7103 first_unempty_vect_index
< vect_length
;
7104 first_unempty_vect_index
++)
7105 if (VEC_index (vect_el_t
, vect
, first_unempty_vect_index
)
7106 != undefined_vect_el_value
)
7109 /* Search for the place in comb vect for the inserted vect. */
7112 if (vect_length
- first_unempty_vect_index
>= SIZEOF_LONG
* CHAR_BIT
)
7114 for (comb_vect_index
= 0;
7115 comb_vect_index
< comb_vect_els_num
;
7118 for (vect_index
= first_unempty_vect_index
;
7119 vect_index
< vect_length
7120 && vect_index
+ comb_vect_index
< comb_vect_els_num
;
7122 if (VEC_index (vect_el_t
, vect
, vect_index
)
7123 != undefined_vect_el_value
7124 && (VEC_index (vect_el_t
, tab
->comb_vect
,
7125 vect_index
+ comb_vect_index
)
7126 != undefined_vect_el_value
))
7128 if (vect_index
>= vect_length
7129 || vect_index
+ comb_vect_index
>= comb_vect_els_num
)
7137 for (vect_index
= first_unempty_vect_index
;
7138 vect_index
< vect_length
;
7141 vect_mask
= vect_mask
<< 1;
7142 if (VEC_index (vect_el_t
, vect
, vect_index
) != undefined_vect_el_value
)
7146 /* Search for the place in comb vect for the inserted vect. */
7147 comb_vect_index
= 0;
7148 if (comb_vect_els_num
== 0)
7152 for (vect_index
= first_unempty_vect_index
;
7153 vect_index
< vect_length
&& vect_index
< comb_vect_els_num
;
7156 comb_vect_mask
<<= 1;
7157 if (vect_index
+ comb_vect_index
< comb_vect_els_num
7158 && VEC_index (vect_el_t
, tab
->comb_vect
, vect_index
+ comb_vect_index
)
7159 != undefined_vect_el_value
)
7160 comb_vect_mask
|= 1;
7162 if ((vect_mask
& comb_vect_mask
) == 0)
7165 for (comb_vect_index
= 1, i
= vect_length
; i
< comb_vect_els_num
;
7166 comb_vect_index
++, i
++)
7168 comb_vect_mask
= (comb_vect_mask
<< 1) | 1;
7169 comb_vect_mask
^= (VEC_index (vect_el_t
, tab
->comb_vect
, i
)
7170 == undefined_vect_el_value
);
7171 if ((vect_mask
& comb_vect_mask
) == 0)
7174 for ( ; comb_vect_index
< comb_vect_els_num
; comb_vect_index
++)
7176 comb_vect_mask
<<= 1;
7177 if ((vect_mask
& comb_vect_mask
) == 0)
7182 /* Slot was found. */
7183 additional_els_num
= comb_vect_index
+ real_vect_length
- comb_vect_els_num
;
7184 if (additional_els_num
< 0)
7185 additional_els_num
= 0;
7186 /* Expand comb and check vectors. */
7187 vect_el
= undefined_vect_el_value
;
7188 no_state_value
= tab
->automaton
->achieved_states_num
;
7189 while (additional_els_num
> 0)
7191 VEC_safe_push (vect_el_t
,heap
, tab
->comb_vect
, vect_el
);
7192 VEC_safe_push (vect_el_t
,heap
, tab
->check_vect
, no_state_value
);
7193 additional_els_num
--;
7195 gcc_assert (VEC_length (vect_el_t
, tab
->comb_vect
)
7196 >= comb_vect_index
+ real_vect_length
);
7197 /* Fill comb and check vectors. */
7198 for (vect_index
= 0; vect_index
< vect_length
; vect_index
++)
7199 if (VEC_index (vect_el_t
, vect
, vect_index
) != undefined_vect_el_value
)
7201 vect_el_t x
= VEC_index (vect_el_t
, vect
, vect_index
);
7202 gcc_assert (VEC_index (vect_el_t
, tab
->comb_vect
,
7203 comb_vect_index
+ vect_index
)
7204 == undefined_vect_el_value
);
7205 gcc_assert (x
>= 0);
7206 if (tab
->max_comb_vect_el_value
< x
)
7207 tab
->max_comb_vect_el_value
= x
;
7208 if (tab
->min_comb_vect_el_value
> x
)
7209 tab
->min_comb_vect_el_value
= x
;
7210 VEC_replace (vect_el_t
, tab
->comb_vect
,
7211 comb_vect_index
+ vect_index
, x
);
7212 VEC_replace (vect_el_t
, tab
->check_vect
,
7213 comb_vect_index
+ vect_index
, vect_num
);
7215 if (tab
->max_comb_vect_el_value
< undefined_vect_el_value
)
7216 tab
->max_comb_vect_el_value
= undefined_vect_el_value
;
7217 if (tab
->min_comb_vect_el_value
> undefined_vect_el_value
)
7218 tab
->min_comb_vect_el_value
= undefined_vect_el_value
;
7219 if (tab
->max_base_vect_el_value
< comb_vect_index
)
7220 tab
->max_base_vect_el_value
= comb_vect_index
;
7221 if (tab
->min_base_vect_el_value
> comb_vect_index
)
7222 tab
->min_base_vect_el_value
= comb_vect_index
;
7224 VEC_replace (vect_el_t
, tab
->base_vect
, vect_num
, comb_vect_index
);
7227 /* Return number of out arcs of STATE. */
7229 out_state_arcs_num (state_t state
)
7235 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
7237 gcc_assert (arc
->insn
);
7238 if (arc
->insn
->first_ainsn_with_given_equivalence_num
)
7244 /* Compare number of possible transitions from the states. */
7246 compare_transition_els_num (const void *state_ptr_1
,
7247 const void *state_ptr_2
)
7249 int transition_els_num_1
;
7250 int transition_els_num_2
;
7252 transition_els_num_1
= out_state_arcs_num (*(state_t
*) state_ptr_1
);
7253 transition_els_num_2
= out_state_arcs_num (*(state_t
*) state_ptr_2
);
7254 if (transition_els_num_1
< transition_els_num_2
)
7256 else if (transition_els_num_1
== transition_els_num_2
)
7262 /* The function adds element EL_VALUE to vector VECT for a table state
7265 add_vect_el (vla_hwint_t
*vect
, ainsn_t ainsn
, int el_value
)
7267 int equiv_class_num
;
7271 equiv_class_num
= ainsn
->insn_equiv_class_num
;
7272 for (vect_index
= VEC_length (vect_el_t
, *vect
);
7273 vect_index
<= equiv_class_num
;
7275 VEC_safe_push (vect_el_t
,heap
, *vect
, undefined_vect_el_value
);
7276 VEC_replace (vect_el_t
, *vect
, equiv_class_num
, el_value
);
7279 /* This is for forming vector of states of an automaton. */
7280 static VEC(state_t
,heap
) *output_states_vect
;
7282 /* The function is called by function pass_states. The function adds
7283 STATE to `output_states_vect'. */
7285 add_states_vect_el (state_t state
)
7287 VEC_safe_push (state_t
,heap
, output_states_vect
, state
);
7290 /* Form and output vectors (comb, check, base or full vector)
7291 representing transition table of AUTOMATON. */
7293 output_trans_table (automaton_t automaton
)
7297 vla_hwint_t transition_vect
= 0;
7299 undefined_vect_el_value
= automaton
->achieved_states_num
;
7300 automaton
->trans_table
= create_state_ainsn_table (automaton
);
7301 /* Create vect of pointers to states ordered by num of transitions
7302 from the state (state with the maximum num is the first). */
7303 output_states_vect
= 0;
7304 pass_states (automaton
, add_states_vect_el
);
7305 qsort (VEC_address (state_t
, output_states_vect
),
7306 VEC_length (state_t
, output_states_vect
),
7307 sizeof (state_t
), compare_transition_els_num
);
7309 for (i
= 0; i
< VEC_length (state_t
, output_states_vect
); i
++)
7311 VEC_truncate (vect_el_t
, transition_vect
, 0);
7312 for (arc
= first_out_arc (VEC_index (state_t
, output_states_vect
, i
));
7314 arc
= next_out_arc (arc
))
7316 gcc_assert (arc
->insn
);
7317 if (arc
->insn
->first_ainsn_with_given_equivalence_num
)
7318 add_vect_el (&transition_vect
, arc
->insn
,
7319 arc
->to_state
->order_state_num
);
7321 add_vect (automaton
->trans_table
,
7322 VEC_index (state_t
, output_states_vect
, i
)->order_state_num
,
7325 output_state_ainsn_table
7326 (automaton
->trans_table
, "state transitions",
7327 output_trans_full_vect_name
, output_trans_comb_vect_name
,
7328 output_trans_check_vect_name
, output_trans_base_vect_name
);
7330 VEC_free (state_t
,heap
, output_states_vect
);
7331 VEC_free (vect_el_t
,heap
, transition_vect
);
7334 /* The current number of passing states to find minimal issue delay
7335 value for an ainsn and state. */
7336 static int curr_state_pass_num
;
7338 /* This recursive function passes states to find minimal issue delay
7339 value for AINSN. The state being visited is STATE. The function
7340 returns minimal issue delay value for AINSN in STATE or -1 if we
7341 enter into a loop. */
7343 min_issue_delay_pass_states (state_t state
, ainsn_t ainsn
)
7346 int min_insn_issue_delay
, insn_issue_delay
;
7348 if (state
->state_pass_num
== curr_state_pass_num
7349 || state
->min_insn_issue_delay
!= -1)
7350 /* We've entered into a loop or already have the correct value for
7351 given state and ainsn. */
7352 return state
->min_insn_issue_delay
;
7353 state
->state_pass_num
= curr_state_pass_num
;
7354 min_insn_issue_delay
= -1;
7355 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
7356 if (arc
->insn
== ainsn
)
7358 min_insn_issue_delay
= 0;
7363 insn_issue_delay
= min_issue_delay_pass_states (arc
->to_state
, ainsn
);
7364 if (insn_issue_delay
!= -1)
7366 if (arc
->insn
->insn_reserv_decl
7367 == DECL_INSN_RESERV (advance_cycle_insn_decl
))
7369 if (min_insn_issue_delay
== -1
7370 || min_insn_issue_delay
> insn_issue_delay
)
7372 min_insn_issue_delay
= insn_issue_delay
;
7373 if (insn_issue_delay
== 0)
7378 return min_insn_issue_delay
;
7381 /* The function searches minimal issue delay value for AINSN in STATE.
7382 The function can return negative value if we can not issue AINSN. We
7383 will report about it later. */
7385 min_issue_delay (state_t state
, ainsn_t ainsn
)
7387 curr_state_pass_num
++;
7388 state
->min_insn_issue_delay
= min_issue_delay_pass_states (state
, ainsn
);
7389 return state
->min_insn_issue_delay
;
7392 /* The function initiates code for finding minimal issue delay values.
7393 It should be called only once. */
7395 initiate_min_issue_delay_pass_states (void)
7397 curr_state_pass_num
= 0;
7400 /* Form and output vectors representing minimal issue delay table of
7401 AUTOMATON. The table is state x ainsn -> minimal issue delay of
7404 output_min_issue_delay_table (automaton_t automaton
)
7406 vla_hwint_t min_issue_delay_vect
;
7407 vla_hwint_t compressed_min_issue_delay_vect
;
7408 vect_el_t min_delay
;
7410 size_t i
, min_issue_delay_len
;
7411 size_t compressed_min_issue_delay_len
;
7414 /* Create vect of pointers to states ordered by num of transitions
7415 from the state (state with the maximum num is the first). */
7416 output_states_vect
= 0;
7417 pass_states (automaton
, add_states_vect_el
);
7419 min_issue_delay_len
= (VEC_length (state_t
, output_states_vect
)
7420 * automaton
->insn_equiv_classes_num
);
7421 min_issue_delay_vect
= VEC_alloc (vect_el_t
,heap
, min_issue_delay_len
);
7422 for (i
= 0; i
< min_issue_delay_len
; i
++)
7423 VEC_quick_push (vect_el_t
, min_issue_delay_vect
, 0);
7425 automaton
->max_min_delay
= 0;
7426 for (ainsn
= automaton
->ainsn_list
; ainsn
!= NULL
; ainsn
= ainsn
->next_ainsn
)
7427 if (ainsn
->first_ainsn_with_given_equivalence_num
)
7429 for (i
= 0; i
< VEC_length (state_t
, output_states_vect
); i
++)
7430 VEC_index (state_t
, output_states_vect
, i
)->min_insn_issue_delay
= -1;
7431 for (i
= 0; i
< VEC_length (state_t
, output_states_vect
); i
++)
7433 state_t s
= VEC_index (state_t
, output_states_vect
, i
);
7434 min_delay
= min_issue_delay (s
, ainsn
);
7435 if (automaton
->max_min_delay
< min_delay
)
7436 automaton
->max_min_delay
= min_delay
;
7437 VEC_replace (vect_el_t
, min_issue_delay_vect
,
7439 * automaton
->insn_equiv_classes_num
7440 + ainsn
->insn_equiv_class_num
,
7444 fprintf (output_file
, "/* Vector of min issue delay of insns. */\n");
7445 fprintf (output_file
, "static const ");
7446 output_range_type (output_file
, 0, automaton
->max_min_delay
);
7447 fprintf (output_file
, " ");
7448 output_min_issue_delay_vect_name (output_file
, automaton
);
7449 fprintf (output_file
, "[] ATTRIBUTE_UNUSED = {\n");
7450 /* Compress the vector. */
7451 if (automaton
->max_min_delay
< 2)
7453 else if (automaton
->max_min_delay
< 4)
7455 else if (automaton
->max_min_delay
< 16)
7459 automaton
->min_issue_delay_table_compression_factor
= cfactor
;
7461 compressed_min_issue_delay_len
= (min_issue_delay_len
+cfactor
-1) / cfactor
;
7462 compressed_min_issue_delay_vect
7463 = VEC_alloc (vect_el_t
,heap
, compressed_min_issue_delay_len
);
7465 for (i
= 0; i
< compressed_min_issue_delay_len
; i
++)
7466 VEC_quick_push (vect_el_t
, compressed_min_issue_delay_vect
, 0);
7468 for (i
= 0; i
< min_issue_delay_len
; i
++)
7470 size_t ci
= i
/ cfactor
;
7471 vect_el_t x
= VEC_index (vect_el_t
, min_issue_delay_vect
, i
);
7472 vect_el_t cx
= VEC_index (vect_el_t
, compressed_min_issue_delay_vect
, ci
);
7474 cx
|= x
<< (8 - (i
% cfactor
+ 1) * (8 / cfactor
));
7475 VEC_replace (vect_el_t
, compressed_min_issue_delay_vect
, ci
, cx
);
7477 output_vect (compressed_min_issue_delay_vect
);
7478 fprintf (output_file
, "};\n\n");
7479 VEC_free (state_t
,heap
, output_states_vect
);
7480 VEC_free (vect_el_t
,heap
, min_issue_delay_vect
);
7481 VEC_free (vect_el_t
,heap
, compressed_min_issue_delay_vect
);
7484 /* Form and output vector representing the locked states of
7487 output_dead_lock_vect (automaton_t automaton
)
7491 vla_hwint_t dead_lock_vect
= 0;
7493 /* Create vect of pointers to states ordered by num of
7494 transitions from the state (state with the maximum num is the
7496 automaton
->locked_states
= 0;
7497 output_states_vect
= 0;
7498 pass_states (automaton
, add_states_vect_el
);
7500 VEC_safe_grow (vect_el_t
,heap
, dead_lock_vect
,
7501 VEC_length (state_t
, output_states_vect
));
7502 for (i
= 0; i
< VEC_length (state_t
, output_states_vect
); i
++)
7504 state_t s
= VEC_index (state_t
, output_states_vect
, i
);
7505 arc
= first_out_arc (s
);
7507 if (next_out_arc (arc
) == NULL
7508 && (arc
->insn
->insn_reserv_decl
7509 == DECL_INSN_RESERV (advance_cycle_insn_decl
)))
7511 VEC_replace (vect_el_t
, dead_lock_vect
, s
->order_state_num
, 1);
7512 automaton
->locked_states
++;
7515 VEC_replace (vect_el_t
, dead_lock_vect
, s
->order_state_num
, 0);
7517 if (automaton
->locked_states
== 0)
7520 fprintf (output_file
, "/* Vector for locked state flags. */\n");
7521 fprintf (output_file
, "static const ");
7522 output_range_type (output_file
, 0, 1);
7523 fprintf (output_file
, " ");
7524 output_dead_lock_vect_name (output_file
, automaton
);
7525 fprintf (output_file
, "[] = {\n");
7526 output_vect (dead_lock_vect
);
7527 fprintf (output_file
, "};\n\n");
7528 VEC_free (state_t
,heap
, output_states_vect
);
7529 VEC_free (vect_el_t
,heap
, dead_lock_vect
);
7532 /* Form and output vector representing reserved units of the states of
7535 output_reserved_units_table (automaton_t automaton
)
7537 vla_hwint_t reserved_units_table
= 0;
7538 int state_byte_size
;
7539 int reserved_units_size
;
7543 if (description
->query_units_num
== 0)
7546 /* Create vect of pointers to states. */
7547 output_states_vect
= 0;
7548 pass_states (automaton
, add_states_vect_el
);
7549 /* Create vector. */
7550 state_byte_size
= (description
->query_units_num
+ 7) / 8;
7551 reserved_units_size
= (VEC_length (state_t
, output_states_vect
)
7554 reserved_units_table
= VEC_alloc (vect_el_t
,heap
, reserved_units_size
);
7556 for (i
= 0; i
< reserved_units_size
; i
++)
7557 VEC_quick_push (vect_el_t
, reserved_units_table
, 0);
7558 for (n
= 0; n
< VEC_length (state_t
, output_states_vect
); n
++)
7560 state_t s
= VEC_index (state_t
, output_states_vect
, n
);
7561 for (i
= 0; i
< description
->units_num
; i
++)
7562 if (units_array
[i
]->query_p
7563 && first_cycle_unit_presence (s
, i
))
7565 int ri
= (s
->order_state_num
* state_byte_size
7566 + units_array
[i
]->query_num
/ 8);
7567 vect_el_t x
= VEC_index (vect_el_t
, reserved_units_table
, ri
);
7569 x
+= 1 << (units_array
[i
]->query_num
% 8);
7570 VEC_replace (vect_el_t
, reserved_units_table
, ri
, x
);
7573 fprintf (output_file
, "\n#if %s\n", CPU_UNITS_QUERY_MACRO_NAME
);
7574 fprintf (output_file
, "/* Vector for reserved units of states. */\n");
7575 fprintf (output_file
, "static const ");
7576 output_range_type (output_file
, 0, 255);
7577 fprintf (output_file
, " ");
7578 output_reserved_units_table_name (output_file
, automaton
);
7579 fprintf (output_file
, "[] = {\n");
7580 output_vect (reserved_units_table
);
7581 fprintf (output_file
, "};\n#endif /* #if %s */\n\n",
7582 CPU_UNITS_QUERY_MACRO_NAME
);
7584 VEC_free (state_t
,heap
, output_states_vect
);
7585 VEC_free (vect_el_t
,heap
, reserved_units_table
);
7588 /* The function outputs all tables representing DFA(s) used for fast
7589 pipeline hazards recognition. */
7591 output_tables (void)
7593 automaton_t automaton
;
7595 initiate_min_issue_delay_pass_states ();
7596 for (automaton
= description
->first_automaton
;
7598 automaton
= automaton
->next_automaton
)
7600 output_translate_vect (automaton
);
7601 output_trans_table (automaton
);
7602 output_min_issue_delay_table (automaton
);
7603 output_dead_lock_vect (automaton
);
7604 output_reserved_units_table (automaton
);
7606 fprintf (output_file
, "\n#define %s %d\n\n", ADVANCE_CYCLE_VALUE_NAME
,
7607 DECL_INSN_RESERV (advance_cycle_insn_decl
)->insn_num
);
7610 /* The function outputs definition and value of PHR interface variable
7611 `max_insn_queue_index'. Its value is not less than maximal queue
7612 length needed for the insn scheduler. */
7614 output_max_insn_queue_index_def (void)
7616 int i
, max
, latency
;
7619 max
= description
->max_insn_reserv_cycles
;
7620 for (i
= 0; i
< description
->decls_num
; i
++)
7622 decl
= description
->decls
[i
];
7623 if (decl
->mode
== dm_insn_reserv
&& decl
!= advance_cycle_insn_decl
)
7625 latency
= DECL_INSN_RESERV (decl
)->default_latency
;
7629 else if (decl
->mode
== dm_bypass
)
7631 latency
= DECL_BYPASS (decl
)->latency
;
7636 for (i
= 0; (1 << i
) <= max
; i
++)
7638 gcc_assert (i
>= 0);
7639 fprintf (output_file
, "\nconst int max_insn_queue_index = %d;\n\n",
7643 /* The function outputs switch cases for insn reservations using
7644 function *output_automata_list_code. */
7646 output_insn_code_cases (void (*output_automata_list_code
)
7647 (automata_list_el_t
))
7652 for (i
= 0; i
< description
->decls_num
; i
++)
7654 decl
= description
->decls
[i
];
7655 if (decl
->mode
== dm_insn_reserv
)
7656 DECL_INSN_RESERV (decl
)->processed_p
= FALSE
;
7658 for (i
= 0; i
< description
->decls_num
; i
++)
7660 decl
= description
->decls
[i
];
7661 if (decl
->mode
== dm_insn_reserv
7662 && !DECL_INSN_RESERV (decl
)->processed_p
)
7664 for (j
= i
; j
< description
->decls_num
; j
++)
7666 decl2
= description
->decls
[j
];
7667 if (decl2
->mode
== dm_insn_reserv
7668 && (DECL_INSN_RESERV (decl2
)->important_automata_list
7669 == DECL_INSN_RESERV (decl
)->important_automata_list
))
7671 DECL_INSN_RESERV (decl2
)->processed_p
= TRUE
;
7672 fprintf (output_file
, " case %d: /* %s */\n",
7673 DECL_INSN_RESERV (decl2
)->insn_num
,
7674 DECL_INSN_RESERV (decl2
)->name
);
7677 (*output_automata_list_code
)
7678 (DECL_INSN_RESERV (decl
)->important_automata_list
);
7684 /* The function outputs a code for evaluation of a minimal delay of
7685 issue of insns which have reservations in given AUTOMATA_LIST. */
7687 output_automata_list_min_issue_delay_code (automata_list_el_t automata_list
)
7689 automata_list_el_t el
;
7690 automaton_t automaton
;
7692 for (el
= automata_list
; el
!= NULL
; el
= el
->next_automata_list_el
)
7694 automaton
= el
->automaton
;
7695 fprintf (output_file
, "\n %s = ", TEMPORARY_VARIABLE_NAME
);
7696 output_min_issue_delay_vect_name (output_file
, automaton
);
7697 fprintf (output_file
,
7698 (automaton
->min_issue_delay_table_compression_factor
!= 1
7700 output_translate_vect_name (output_file
, automaton
);
7701 fprintf (output_file
, " [%s] + ", INTERNAL_INSN_CODE_NAME
);
7702 fprintf (output_file
, "%s->", CHIP_PARAMETER_NAME
);
7703 output_chip_member_name (output_file
, automaton
);
7704 fprintf (output_file
, " * %d", automaton
->insn_equiv_classes_num
);
7705 if (automaton
->min_issue_delay_table_compression_factor
== 1)
7706 fprintf (output_file
, "];\n");
7709 fprintf (output_file
, ") / %d];\n",
7710 automaton
->min_issue_delay_table_compression_factor
);
7711 fprintf (output_file
, " %s = (%s >> (8 - (",
7712 TEMPORARY_VARIABLE_NAME
, TEMPORARY_VARIABLE_NAME
);
7713 output_translate_vect_name (output_file
, automaton
);
7715 (output_file
, " [%s] %% %d + 1) * %d)) & %d;\n",
7716 INTERNAL_INSN_CODE_NAME
,
7717 automaton
->min_issue_delay_table_compression_factor
,
7718 8 / automaton
->min_issue_delay_table_compression_factor
,
7719 (1 << (8 / automaton
->min_issue_delay_table_compression_factor
))
7722 if (el
== automata_list
)
7723 fprintf (output_file
, " %s = %s;\n",
7724 RESULT_VARIABLE_NAME
, TEMPORARY_VARIABLE_NAME
);
7727 fprintf (output_file
, " if (%s > %s)\n",
7728 TEMPORARY_VARIABLE_NAME
, RESULT_VARIABLE_NAME
);
7729 fprintf (output_file
, " %s = %s;\n",
7730 RESULT_VARIABLE_NAME
, TEMPORARY_VARIABLE_NAME
);
7733 fprintf (output_file
, " break;\n\n");
7736 /* Output function `internal_min_issue_delay'. */
7738 output_internal_min_issue_delay_func (void)
7740 fprintf (output_file
,
7741 "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
7742 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
7743 CHIP_NAME
, CHIP_PARAMETER_NAME
);
7744 fprintf (output_file
, "{\n int %s ATTRIBUTE_UNUSED;\n int %s = -1;\n",
7745 TEMPORARY_VARIABLE_NAME
, RESULT_VARIABLE_NAME
);
7746 fprintf (output_file
, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME
);
7747 output_insn_code_cases (output_automata_list_min_issue_delay_code
);
7748 fprintf (output_file
,
7749 "\n default:\n %s = -1;\n break;\n }\n",
7750 RESULT_VARIABLE_NAME
);
7751 fprintf (output_file
, " return %s;\n", RESULT_VARIABLE_NAME
);
7752 fprintf (output_file
, "}\n\n");
7755 /* The function outputs a code changing state after issue of insns
7756 which have reservations in given AUTOMATA_LIST. */
7758 output_automata_list_transition_code (automata_list_el_t automata_list
)
7760 automata_list_el_t el
, next_el
;
7762 fprintf (output_file
, " {\n");
7763 if (automata_list
!= NULL
&& automata_list
->next_automata_list_el
!= NULL
)
7764 for (el
= automata_list
;; el
= next_el
)
7766 next_el
= el
->next_automata_list_el
;
7767 if (next_el
== NULL
)
7769 fprintf (output_file
, " ");
7770 output_state_member_type (output_file
, el
->automaton
);
7771 fprintf (output_file
, " ");
7772 output_temp_chip_member_name (output_file
, el
->automaton
);
7773 fprintf (output_file
, ";\n");
7775 for (el
= automata_list
; el
!= NULL
; el
= el
->next_automata_list_el
)
7776 if (comb_vect_p (el
->automaton
->trans_table
))
7778 fprintf (output_file
, "\n %s = ", TEMPORARY_VARIABLE_NAME
);
7779 output_trans_base_vect_name (output_file
, el
->automaton
);
7780 fprintf (output_file
, " [%s->", CHIP_PARAMETER_NAME
);
7781 output_chip_member_name (output_file
, el
->automaton
);
7782 fprintf (output_file
, "] + ");
7783 output_translate_vect_name (output_file
, el
->automaton
);
7784 fprintf (output_file
, " [%s];\n", INTERNAL_INSN_CODE_NAME
);
7785 fprintf (output_file
, " if (");
7786 output_trans_check_vect_name (output_file
, el
->automaton
);
7787 fprintf (output_file
, " [%s] != %s->",
7788 TEMPORARY_VARIABLE_NAME
, CHIP_PARAMETER_NAME
);
7789 output_chip_member_name (output_file
, el
->automaton
);
7790 fprintf (output_file
, ")\n");
7791 fprintf (output_file
, " return %s (%s, %s);\n",
7792 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
7793 CHIP_PARAMETER_NAME
);
7794 fprintf (output_file
, " else\n");
7795 fprintf (output_file
, " ");
7796 if (el
->next_automata_list_el
!= NULL
)
7797 output_temp_chip_member_name (output_file
, el
->automaton
);
7800 fprintf (output_file
, "%s->", CHIP_PARAMETER_NAME
);
7801 output_chip_member_name (output_file
, el
->automaton
);
7803 fprintf (output_file
, " = ");
7804 output_trans_comb_vect_name (output_file
, el
->automaton
);
7805 fprintf (output_file
, " [%s];\n", TEMPORARY_VARIABLE_NAME
);
7809 fprintf (output_file
, "\n %s = ", TEMPORARY_VARIABLE_NAME
);
7810 output_trans_full_vect_name (output_file
, el
->automaton
);
7811 fprintf (output_file
, " [");
7812 output_translate_vect_name (output_file
, el
->automaton
);
7813 fprintf (output_file
, " [%s] + ", INTERNAL_INSN_CODE_NAME
);
7814 fprintf (output_file
, "%s->", CHIP_PARAMETER_NAME
);
7815 output_chip_member_name (output_file
, el
->automaton
);
7816 fprintf (output_file
, " * %d];\n",
7817 el
->automaton
->insn_equiv_classes_num
);
7818 fprintf (output_file
, " if (%s >= %d)\n",
7819 TEMPORARY_VARIABLE_NAME
, el
->automaton
->achieved_states_num
);
7820 fprintf (output_file
, " return %s (%s, %s);\n",
7821 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
7822 CHIP_PARAMETER_NAME
);
7823 fprintf (output_file
, " else\n ");
7824 if (el
->next_automata_list_el
!= NULL
)
7825 output_temp_chip_member_name (output_file
, el
->automaton
);
7828 fprintf (output_file
, "%s->", CHIP_PARAMETER_NAME
);
7829 output_chip_member_name (output_file
, el
->automaton
);
7831 fprintf (output_file
, " = %s;\n", TEMPORARY_VARIABLE_NAME
);
7833 if (automata_list
!= NULL
&& automata_list
->next_automata_list_el
!= NULL
)
7834 for (el
= automata_list
;; el
= next_el
)
7836 next_el
= el
->next_automata_list_el
;
7837 if (next_el
== NULL
)
7839 fprintf (output_file
, " %s->", CHIP_PARAMETER_NAME
);
7840 output_chip_member_name (output_file
, el
->automaton
);
7841 fprintf (output_file
, " = ");
7842 output_temp_chip_member_name (output_file
, el
->automaton
);
7843 fprintf (output_file
, ";\n");
7845 fprintf (output_file
, " return -1;\n");
7846 fprintf (output_file
, " }\n");
7849 /* Output function `internal_state_transition'. */
7851 output_internal_trans_func (void)
7853 fprintf (output_file
,
7854 "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
7855 INTERNAL_TRANSITION_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
7856 CHIP_NAME
, CHIP_PARAMETER_NAME
);
7857 fprintf (output_file
, "{\n int %s ATTRIBUTE_UNUSED;\n", TEMPORARY_VARIABLE_NAME
);
7858 fprintf (output_file
, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME
);
7859 output_insn_code_cases (output_automata_list_transition_code
);
7860 fprintf (output_file
, "\n default:\n return -1;\n }\n");
7861 fprintf (output_file
, "}\n\n");
7868 insn_code = dfa_insn_code (insn);
7869 if (insn_code > DFA__ADVANCE_CYCLE)
7873 insn_code = DFA__ADVANCE_CYCLE;
7875 where insn denotes INSN_NAME, insn_code denotes INSN_CODE_NAME, and
7876 code denotes CODE. */
7878 output_internal_insn_code_evaluation (const char *insn_name
,
7879 const char *insn_code_name
,
7882 fprintf (output_file
, "\n if (%s != 0)\n {\n", insn_name
);
7883 fprintf (output_file
, " %s = %s (%s);\n", insn_code_name
,
7884 DFA_INSN_CODE_FUNC_NAME
, insn_name
);
7885 fprintf (output_file
, " if (%s > %s)\n return %d;\n",
7886 insn_code_name
, ADVANCE_CYCLE_VALUE_NAME
, code
);
7887 fprintf (output_file
, " }\n else\n %s = %s;\n\n",
7888 insn_code_name
, ADVANCE_CYCLE_VALUE_NAME
);
7892 /* This function outputs `dfa_insn_code' and its helper function
7893 `dfa_insn_code_enlarge'. */
7895 output_dfa_insn_code_func (void)
7897 /* Emacs c-mode gets really confused if there's a { or } in column 0
7898 inside a string, so don't do that. */
7899 fprintf (output_file
, "\
7901 dfa_insn_code_enlarge (int uid)\n\
7905 %s = xrealloc (%s,\n\
7906 %s * sizeof(int));\n\
7907 for (; i < %s; i++)\n\
7908 %s[i] = -1;\n}\n\n",
7909 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
,
7910 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
,
7911 DFA_INSN_CODES_VARIABLE_NAME
, DFA_INSN_CODES_VARIABLE_NAME
,
7912 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
,
7913 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
,
7914 DFA_INSN_CODES_VARIABLE_NAME
);
7915 fprintf (output_file
, "\
7916 static inline int\n%s (rtx %s)\n\
7918 int uid = INSN_UID (%s);\n\
7920 DFA_INSN_CODE_FUNC_NAME
, INSN_PARAMETER_NAME
,
7921 INSN_PARAMETER_NAME
, INTERNAL_INSN_CODE_NAME
);
7923 fprintf (output_file
,
7924 " if (uid >= %s)\n dfa_insn_code_enlarge (uid);\n\n",
7925 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
);
7926 fprintf (output_file
, " %s = %s[uid];\n",
7927 INTERNAL_INSN_CODE_NAME
, DFA_INSN_CODES_VARIABLE_NAME
);
7928 fprintf (output_file
, "\
7934 INTERNAL_INSN_CODE_NAME
,
7935 INTERNAL_INSN_CODE_NAME
,
7936 INTERNAL_DFA_INSN_CODE_FUNC_NAME
, INSN_PARAMETER_NAME
,
7937 DFA_INSN_CODES_VARIABLE_NAME
, INTERNAL_INSN_CODE_NAME
);
7938 fprintf (output_file
, " return %s;\n}\n\n", INTERNAL_INSN_CODE_NAME
);
7941 /* The function outputs PHR interface function `state_transition'. */
7943 output_trans_func (void)
7945 fprintf (output_file
, "int\n%s (%s %s, rtx %s)\n",
7946 TRANSITION_FUNC_NAME
, STATE_TYPE_NAME
, STATE_NAME
,
7947 INSN_PARAMETER_NAME
);
7948 fprintf (output_file
, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME
);
7949 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME
,
7950 INTERNAL_INSN_CODE_NAME
, -1);
7951 fprintf (output_file
, " return %s (%s, %s);\n}\n\n",
7952 INTERNAL_TRANSITION_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
, STATE_NAME
);
7955 /* Output function `min_issue_delay'. */
7957 output_min_issue_delay_func (void)
7959 fprintf (output_file
, "int\n%s (%s %s, rtx %s)\n",
7960 MIN_ISSUE_DELAY_FUNC_NAME
, STATE_TYPE_NAME
, STATE_NAME
,
7961 INSN_PARAMETER_NAME
);
7962 fprintf (output_file
, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME
);
7963 fprintf (output_file
, "\n if (%s != 0)\n {\n", INSN_PARAMETER_NAME
);
7964 fprintf (output_file
, " %s = %s (%s);\n", INTERNAL_INSN_CODE_NAME
,
7965 DFA_INSN_CODE_FUNC_NAME
, INSN_PARAMETER_NAME
);
7966 fprintf (output_file
, " if (%s > %s)\n return 0;\n",
7967 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
7968 fprintf (output_file
, " }\n else\n %s = %s;\n",
7969 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
7970 fprintf (output_file
, "\n return %s (%s, %s);\n",
7971 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
7973 fprintf (output_file
, "}\n\n");
7976 /* Output function `internal_dead_lock'. */
7978 output_internal_dead_lock_func (void)
7980 automaton_t automaton
;
7982 fprintf (output_file
, "static int\n%s (struct %s *ARG_UNUSED (%s))\n",
7983 INTERNAL_DEAD_LOCK_FUNC_NAME
, CHIP_NAME
, CHIP_PARAMETER_NAME
);
7984 fprintf (output_file
, "{\n");
7985 for (automaton
= description
->first_automaton
;
7987 automaton
= automaton
->next_automaton
)
7988 if (automaton
->locked_states
)
7990 fprintf (output_file
, " if (");
7991 output_dead_lock_vect_name (output_file
, automaton
);
7992 fprintf (output_file
, " [%s->", CHIP_PARAMETER_NAME
);
7993 output_chip_member_name (output_file
, automaton
);
7994 fprintf (output_file
, "])\n return 1/* TRUE */;\n");
7996 fprintf (output_file
, " return 0/* FALSE */;\n}\n\n");
7999 /* The function outputs PHR interface function `state_dead_lock_p'. */
8001 output_dead_lock_func (void)
8003 fprintf (output_file
, "int\n%s (%s %s)\n",
8004 DEAD_LOCK_FUNC_NAME
, STATE_TYPE_NAME
, STATE_NAME
);
8005 fprintf (output_file
, "{\n return %s (%s);\n}\n\n",
8006 INTERNAL_DEAD_LOCK_FUNC_NAME
, STATE_NAME
);
8009 /* Output function `internal_reset'. */
8011 output_internal_reset_func (void)
8013 fprintf (output_file
, "static inline void\n%s (struct %s *%s)\n",
8014 INTERNAL_RESET_FUNC_NAME
, CHIP_NAME
, CHIP_PARAMETER_NAME
);
8015 fprintf (output_file
, "{\n memset (%s, 0, sizeof (struct %s));\n}\n\n",
8016 CHIP_PARAMETER_NAME
, CHIP_NAME
);
8019 /* The function outputs PHR interface function `state_size'. */
8021 output_size_func (void)
8023 fprintf (output_file
, "int\n%s (void)\n", SIZE_FUNC_NAME
);
8024 fprintf (output_file
, "{\n return sizeof (struct %s);\n}\n\n", CHIP_NAME
);
8027 /* The function outputs PHR interface function `state_reset'. */
8029 output_reset_func (void)
8031 fprintf (output_file
, "void\n%s (%s %s)\n",
8032 RESET_FUNC_NAME
, STATE_TYPE_NAME
, STATE_NAME
);
8033 fprintf (output_file
, "{\n %s (%s);\n}\n\n", INTERNAL_RESET_FUNC_NAME
,
8037 /* Output function `min_insn_conflict_delay'. */
8039 output_min_insn_conflict_delay_func (void)
8041 fprintf (output_file
,
8042 "int\n%s (%s %s, rtx %s, rtx %s)\n",
8043 MIN_INSN_CONFLICT_DELAY_FUNC_NAME
, STATE_TYPE_NAME
,
8044 STATE_NAME
, INSN_PARAMETER_NAME
, INSN2_PARAMETER_NAME
);
8045 fprintf (output_file
, "{\n struct %s %s;\n int %s, %s, transition;\n",
8046 CHIP_NAME
, CHIP_NAME
, INTERNAL_INSN_CODE_NAME
,
8047 INTERNAL_INSN2_CODE_NAME
);
8048 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME
,
8049 INTERNAL_INSN_CODE_NAME
, 0);
8050 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME
,
8051 INTERNAL_INSN2_CODE_NAME
, 0);
8052 fprintf (output_file
, " memcpy (&%s, %s, sizeof (%s));\n",
8053 CHIP_NAME
, STATE_NAME
, CHIP_NAME
);
8054 fprintf (output_file
, " %s (&%s);\n", INTERNAL_RESET_FUNC_NAME
, CHIP_NAME
);
8055 fprintf (output_file
, " transition = %s (%s, &%s);\n",
8056 INTERNAL_TRANSITION_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
, CHIP_NAME
);
8057 fprintf (output_file
, " gcc_assert (transition <= 0);\n");
8058 fprintf (output_file
, " return %s (%s, &%s);\n",
8059 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME
, INTERNAL_INSN2_CODE_NAME
,
8061 fprintf (output_file
, "}\n\n");
8064 /* Output function `internal_insn_latency'. */
8066 output_internal_insn_latency_func (void)
8069 struct bypass_decl
*bypass
;
8071 const char *tabletype
= "unsigned char";
8073 /* Find the smallest integer type that can hold all the default
8075 for (i
= 0; i
< description
->decls_num
; i
++)
8076 if (description
->decls
[i
]->mode
== dm_insn_reserv
)
8078 decl
= description
->decls
[i
];
8079 if (DECL_INSN_RESERV (decl
)->default_latency
> UCHAR_MAX
8080 && tabletype
[0] != 'i') /* Don't shrink it. */
8081 tabletype
= "unsigned short";
8082 if (DECL_INSN_RESERV (decl
)->default_latency
> USHRT_MAX
)
8086 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",
8087 INTERNAL_INSN_LATENCY_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
8088 INTERNAL_INSN2_CODE_NAME
, INSN_PARAMETER_NAME
,
8089 INSN2_PARAMETER_NAME
);
8090 fprintf (output_file
, "{\n");
8092 if (DECL_INSN_RESERV (advance_cycle_insn_decl
)->insn_num
== 0)
8094 fputs (" return 0;\n}\n\n", output_file
);
8098 fprintf (output_file
, " static const %s default_latencies[] =\n {",
8101 for (i
= 0, j
= 0, col
= 7; i
< description
->decls_num
; i
++)
8102 if (description
->decls
[i
]->mode
== dm_insn_reserv
8103 && description
->decls
[i
] != advance_cycle_insn_decl
)
8105 if ((col
= (col
+1) % 8) == 0)
8106 fputs ("\n ", output_file
);
8107 decl
= description
->decls
[i
];
8108 gcc_assert (j
++ == DECL_INSN_RESERV (decl
)->insn_num
);
8109 fprintf (output_file
, "% 4d,",
8110 DECL_INSN_RESERV (decl
)->default_latency
);
8112 gcc_assert (j
== DECL_INSN_RESERV (advance_cycle_insn_decl
)->insn_num
);
8113 fputs ("\n };\n", output_file
);
8115 fprintf (output_file
, " if (%s >= %s || %s >= %s)\n return 0;\n",
8116 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
,
8117 INTERNAL_INSN2_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
8119 fprintf (output_file
, " switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME
);
8120 for (i
= 0; i
< description
->decls_num
; i
++)
8121 if (description
->decls
[i
]->mode
== dm_insn_reserv
8122 && DECL_INSN_RESERV (description
->decls
[i
])->bypass_list
)
8124 decl
= description
->decls
[i
];
8125 fprintf (output_file
,
8126 " case %d:\n switch (%s)\n {\n",
8127 DECL_INSN_RESERV (decl
)->insn_num
,
8128 INTERNAL_INSN2_CODE_NAME
);
8129 for (bypass
= DECL_INSN_RESERV (decl
)->bypass_list
;
8131 bypass
= bypass
->next
)
8133 gcc_assert (bypass
->in_insn_reserv
->insn_num
8134 != (DECL_INSN_RESERV
8135 (advance_cycle_insn_decl
)->insn_num
));
8136 fprintf (output_file
, " case %d:\n",
8137 bypass
->in_insn_reserv
->insn_num
);
8138 if (bypass
->bypass_guard_name
== NULL
)
8139 fprintf (output_file
, " return %d;\n",
8143 fprintf (output_file
,
8144 " if (%s (%s, %s))\n",
8145 bypass
->bypass_guard_name
, INSN_PARAMETER_NAME
,
8146 INSN2_PARAMETER_NAME
);
8147 fprintf (output_file
,
8148 " return %d;\n break;\n",
8152 fputs (" }\n break;\n", output_file
);
8155 fprintf (output_file
, " }\n return default_latencies[%s];\n}\n\n",
8156 INTERNAL_INSN_CODE_NAME
);
8159 /* The function outputs PHR interface function `insn_latency'. */
8161 output_insn_latency_func (void)
8163 fprintf (output_file
, "int\n%s (rtx %s, rtx %s)\n",
8164 INSN_LATENCY_FUNC_NAME
, INSN_PARAMETER_NAME
, INSN2_PARAMETER_NAME
);
8165 fprintf (output_file
, "{\n int %s, %s;\n",
8166 INTERNAL_INSN_CODE_NAME
, INTERNAL_INSN2_CODE_NAME
);
8167 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME
,
8168 INTERNAL_INSN_CODE_NAME
, 0);
8169 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME
,
8170 INTERNAL_INSN2_CODE_NAME
, 0);
8171 fprintf (output_file
, " return %s (%s, %s, %s, %s);\n}\n\n",
8172 INTERNAL_INSN_LATENCY_FUNC_NAME
,
8173 INTERNAL_INSN_CODE_NAME
, INTERNAL_INSN2_CODE_NAME
,
8174 INSN_PARAMETER_NAME
, INSN2_PARAMETER_NAME
);
8177 /* The function outputs PHR interface function `print_reservation'. */
8179 output_print_reservation_func (void)
8184 fprintf (output_file
,
8185 "void\n%s (FILE *%s, rtx %s ATTRIBUTE_UNUSED)\n{\n",
8186 PRINT_RESERVATION_FUNC_NAME
, FILE_PARAMETER_NAME
,
8187 INSN_PARAMETER_NAME
);
8189 if (DECL_INSN_RESERV (advance_cycle_insn_decl
)->insn_num
== 0)
8191 fprintf (output_file
, " fputs (\"%s\", %s);\n}\n\n",
8192 NOTHING_NAME
, FILE_PARAMETER_NAME
);
8197 fputs (" static const char *const reservation_names[] =\n {",
8200 for (i
= 0, j
= 0; i
< description
->decls_num
; i
++)
8202 decl
= description
->decls
[i
];
8203 if (decl
->mode
== dm_insn_reserv
&& decl
!= advance_cycle_insn_decl
)
8205 gcc_assert (j
== DECL_INSN_RESERV (decl
)->insn_num
);
8208 fprintf (output_file
, "\n \"%s\",",
8209 regexp_representation (DECL_INSN_RESERV (decl
)->regexp
));
8210 finish_regexp_representation ();
8213 gcc_assert (j
== DECL_INSN_RESERV (advance_cycle_insn_decl
)->insn_num
);
8215 fprintf (output_file
, "\n \"%s\"\n };\n int %s;\n\n",
8216 NOTHING_NAME
, INTERNAL_INSN_CODE_NAME
);
8218 fprintf (output_file
, " if (%s == 0)\n %s = %s;\n",
8219 INSN_PARAMETER_NAME
,
8220 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
8221 fprintf (output_file
, " else\n\
8227 INTERNAL_INSN_CODE_NAME
, DFA_INSN_CODE_FUNC_NAME
,
8228 INSN_PARAMETER_NAME
,
8229 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
,
8230 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
8232 fprintf (output_file
, " fputs (reservation_names[%s], %s);\n}\n\n",
8233 INTERNAL_INSN_CODE_NAME
, FILE_PARAMETER_NAME
);
8236 /* The following function is used to sort unit declaration by their
8239 units_cmp (const void *unit1
, const void *unit2
)
8241 const unit_decl_t u1
= *(unit_decl_t
*) unit1
;
8242 const unit_decl_t u2
= *(unit_decl_t
*) unit2
;
8244 return strcmp (u1
->name
, u2
->name
);
8247 /* The following macro value is name of struct containing unit name
8249 #define NAME_CODE_STRUCT_NAME "name_code"
8251 /* The following macro value is name of table of struct name_code. */
8252 #define NAME_CODE_TABLE_NAME "name_code_table"
8254 /* The following macro values are member names for struct name_code. */
8255 #define NAME_MEMBER_NAME "name"
8256 #define CODE_MEMBER_NAME "code"
8258 /* The following macro values are local variable names for function
8259 `get_cpu_unit_code'. */
8260 #define CMP_VARIABLE_NAME "cmp"
8261 #define LOW_VARIABLE_NAME "l"
8262 #define MIDDLE_VARIABLE_NAME "m"
8263 #define HIGH_VARIABLE_NAME "h"
8265 /* The following function outputs function to obtain internal cpu unit
8266 code by the cpu unit name. */
8268 output_get_cpu_unit_code_func (void)
8273 fprintf (output_file
, "int\n%s (const char *%s)\n",
8274 GET_CPU_UNIT_CODE_FUNC_NAME
, CPU_UNIT_NAME_PARAMETER_NAME
);
8275 fprintf (output_file
, "{\n struct %s {const char *%s; int %s;};\n",
8276 NAME_CODE_STRUCT_NAME
, NAME_MEMBER_NAME
, CODE_MEMBER_NAME
);
8277 fprintf (output_file
, " int %s, %s, %s, %s;\n", CMP_VARIABLE_NAME
,
8278 LOW_VARIABLE_NAME
, MIDDLE_VARIABLE_NAME
, HIGH_VARIABLE_NAME
);
8279 fprintf (output_file
, " static struct %s %s [] =\n {\n",
8280 NAME_CODE_STRUCT_NAME
, NAME_CODE_TABLE_NAME
);
8281 units
= xmalloc (sizeof (unit_decl_t
) * description
->units_num
);
8282 memcpy (units
, units_array
, sizeof (unit_decl_t
) * description
->units_num
);
8283 qsort (units
, description
->units_num
, sizeof (unit_decl_t
), units_cmp
);
8284 for (i
= 0; i
< description
->units_num
; i
++)
8285 if (units
[i
]->query_p
)
8286 fprintf (output_file
, " {\"%s\", %d},\n",
8287 units
[i
]->name
, units
[i
]->query_num
);
8288 fprintf (output_file
, " };\n\n");
8289 fprintf (output_file
, " /* The following is binary search: */\n");
8290 fprintf (output_file
, " %s = 0;\n", LOW_VARIABLE_NAME
);
8291 fprintf (output_file
, " %s = sizeof (%s) / sizeof (struct %s) - 1;\n",
8292 HIGH_VARIABLE_NAME
, NAME_CODE_TABLE_NAME
, NAME_CODE_STRUCT_NAME
);
8293 fprintf (output_file
, " while (%s <= %s)\n {\n",
8294 LOW_VARIABLE_NAME
, HIGH_VARIABLE_NAME
);
8295 fprintf (output_file
, " %s = (%s + %s) / 2;\n",
8296 MIDDLE_VARIABLE_NAME
, LOW_VARIABLE_NAME
, HIGH_VARIABLE_NAME
);
8297 fprintf (output_file
, " %s = strcmp (%s, %s [%s].%s);\n",
8298 CMP_VARIABLE_NAME
, CPU_UNIT_NAME_PARAMETER_NAME
,
8299 NAME_CODE_TABLE_NAME
, MIDDLE_VARIABLE_NAME
, NAME_MEMBER_NAME
);
8300 fprintf (output_file
, " if (%s < 0)\n", CMP_VARIABLE_NAME
);
8301 fprintf (output_file
, " %s = %s - 1;\n",
8302 HIGH_VARIABLE_NAME
, MIDDLE_VARIABLE_NAME
);
8303 fprintf (output_file
, " else if (%s > 0)\n", CMP_VARIABLE_NAME
);
8304 fprintf (output_file
, " %s = %s + 1;\n",
8305 LOW_VARIABLE_NAME
, MIDDLE_VARIABLE_NAME
);
8306 fprintf (output_file
, " else\n");
8307 fprintf (output_file
, " return %s [%s].%s;\n }\n",
8308 NAME_CODE_TABLE_NAME
, MIDDLE_VARIABLE_NAME
, CODE_MEMBER_NAME
);
8309 fprintf (output_file
, " return -1;\n}\n\n");
8313 /* The following function outputs function to check reservation of cpu
8314 unit (its internal code will be passed as the function argument) in
8317 output_cpu_unit_reservation_p (void)
8319 automaton_t automaton
;
8321 fprintf (output_file
, "int\n%s (%s %s, int %s)\n",
8322 CPU_UNIT_RESERVATION_P_FUNC_NAME
,
8323 STATE_TYPE_NAME
, STATE_NAME
,
8324 CPU_CODE_PARAMETER_NAME
);
8325 fprintf (output_file
, "{\n gcc_assert (%s >= 0 && %s < %d);\n",
8326 CPU_CODE_PARAMETER_NAME
, CPU_CODE_PARAMETER_NAME
,
8327 description
->query_units_num
);
8328 if (description
->query_units_num
> 0)
8329 for (automaton
= description
->first_automaton
;
8331 automaton
= automaton
->next_automaton
)
8333 fprintf (output_file
, " if ((");
8334 output_reserved_units_table_name (output_file
, automaton
);
8335 fprintf (output_file
, " [((struct %s *) %s)->", CHIP_NAME
, STATE_NAME
);
8336 output_chip_member_name (output_file
, automaton
);
8337 fprintf (output_file
, " * %d + %s / 8] >> (%s %% 8)) & 1)\n",
8338 (description
->query_units_num
+ 7) / 8,
8339 CPU_CODE_PARAMETER_NAME
, CPU_CODE_PARAMETER_NAME
);
8340 fprintf (output_file
, " return 1;\n");
8342 fprintf (output_file
, " return 0;\n}\n\n");
8345 /* The function outputs PHR interface functions `dfa_clean_insn_cache'
8346 and 'dfa_clear_single_insn_cache'. */
8348 output_dfa_clean_insn_cache_func (void)
8350 fprintf (output_file
,
8351 "void\n%s (void)\n{\n int %s;\n\n",
8352 DFA_CLEAN_INSN_CACHE_FUNC_NAME
, I_VARIABLE_NAME
);
8353 fprintf (output_file
,
8354 " for (%s = 0; %s < %s; %s++)\n %s [%s] = -1;\n}\n\n",
8355 I_VARIABLE_NAME
, I_VARIABLE_NAME
,
8356 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
, I_VARIABLE_NAME
,
8357 DFA_INSN_CODES_VARIABLE_NAME
, I_VARIABLE_NAME
);
8359 fprintf (output_file
,
8360 "void\n%s (rtx %s)\n{\n int %s;\n\n",
8361 DFA_CLEAR_SINGLE_INSN_CACHE_FUNC_NAME
, INSN_PARAMETER_NAME
,
8363 fprintf (output_file
,
8364 " %s = INSN_UID (%s);\n if (%s < %s)\n %s [%s] = -1;\n}\n\n",
8365 I_VARIABLE_NAME
, INSN_PARAMETER_NAME
, I_VARIABLE_NAME
,
8366 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
, DFA_INSN_CODES_VARIABLE_NAME
,
8370 /* The function outputs PHR interface function `dfa_start'. */
8372 output_dfa_start_func (void)
8374 fprintf (output_file
,
8375 "void\n%s (void)\n{\n %s = get_max_uid ();\n",
8376 DFA_START_FUNC_NAME
, DFA_INSN_CODES_LENGTH_VARIABLE_NAME
);
8377 fprintf (output_file
, " %s = xmalloc (%s * sizeof (int));\n",
8378 DFA_INSN_CODES_VARIABLE_NAME
, DFA_INSN_CODES_LENGTH_VARIABLE_NAME
);
8379 fprintf (output_file
, " %s ();\n}\n\n", DFA_CLEAN_INSN_CACHE_FUNC_NAME
);
8382 /* The function outputs PHR interface function `dfa_finish'. */
8384 output_dfa_finish_func (void)
8386 fprintf (output_file
, "void\n%s (void)\n{\n free (%s);\n}\n\n",
8387 DFA_FINISH_FUNC_NAME
, DFA_INSN_CODES_VARIABLE_NAME
);
8392 /* The page contains code for output description file (readable
8393 representation of original description and generated DFA(s). */
8395 /* The function outputs string representation of IR reservation. */
8397 output_regexp (regexp_t regexp
)
8399 fprintf (output_description_file
, "%s", regexp_representation (regexp
));
8400 finish_regexp_representation ();
8403 /* Output names of units in LIST separated by comma. */
8405 output_unit_set_el_list (unit_set_el_t list
)
8409 for (el
= list
; el
!= NULL
; el
= el
->next_unit_set_el
)
8412 fprintf (output_description_file
, ", ");
8413 fprintf (output_description_file
, "%s", el
->unit_decl
->name
);
8417 /* Output patterns in LIST separated by comma. */
8419 output_pattern_set_el_list (pattern_set_el_t list
)
8421 pattern_set_el_t el
;
8424 for (el
= list
; el
!= NULL
; el
= el
->next_pattern_set_el
)
8427 fprintf (output_description_file
, ", ");
8428 for (i
= 0; i
< el
->units_num
; i
++)
8429 fprintf (output_description_file
, (i
== 0 ? "%s" : " %s"),
8430 el
->unit_decls
[i
]->name
);
8434 /* The function outputs string representation of IR define_reservation
8435 and define_insn_reservation. */
8437 output_description (void)
8442 for (i
= 0; i
< description
->decls_num
; i
++)
8444 decl
= description
->decls
[i
];
8445 if (decl
->mode
== dm_unit
)
8447 if (DECL_UNIT (decl
)->excl_list
!= NULL
)
8449 fprintf (output_description_file
, "unit %s exlusion_set: ",
8450 DECL_UNIT (decl
)->name
);
8451 output_unit_set_el_list (DECL_UNIT (decl
)->excl_list
);
8452 fprintf (output_description_file
, "\n");
8454 if (DECL_UNIT (decl
)->presence_list
!= NULL
)
8456 fprintf (output_description_file
, "unit %s presence_set: ",
8457 DECL_UNIT (decl
)->name
);
8458 output_pattern_set_el_list (DECL_UNIT (decl
)->presence_list
);
8459 fprintf (output_description_file
, "\n");
8461 if (DECL_UNIT (decl
)->final_presence_list
!= NULL
)
8463 fprintf (output_description_file
, "unit %s final_presence_set: ",
8464 DECL_UNIT (decl
)->name
);
8465 output_pattern_set_el_list
8466 (DECL_UNIT (decl
)->final_presence_list
);
8467 fprintf (output_description_file
, "\n");
8469 if (DECL_UNIT (decl
)->absence_list
!= NULL
)
8471 fprintf (output_description_file
, "unit %s absence_set: ",
8472 DECL_UNIT (decl
)->name
);
8473 output_pattern_set_el_list (DECL_UNIT (decl
)->absence_list
);
8474 fprintf (output_description_file
, "\n");
8476 if (DECL_UNIT (decl
)->final_absence_list
!= NULL
)
8478 fprintf (output_description_file
, "unit %s final_absence_set: ",
8479 DECL_UNIT (decl
)->name
);
8480 output_pattern_set_el_list
8481 (DECL_UNIT (decl
)->final_absence_list
);
8482 fprintf (output_description_file
, "\n");
8486 fprintf (output_description_file
, "\n");
8487 for (i
= 0; i
< description
->decls_num
; i
++)
8489 decl
= description
->decls
[i
];
8490 if (decl
->mode
== dm_reserv
)
8492 fprintf (output_description_file
, "reservation %s: ",
8493 DECL_RESERV (decl
)->name
);
8494 output_regexp (DECL_RESERV (decl
)->regexp
);
8495 fprintf (output_description_file
, "\n");
8497 else if (decl
->mode
== dm_insn_reserv
&& decl
!= advance_cycle_insn_decl
)
8499 fprintf (output_description_file
, "insn reservation %s ",
8500 DECL_INSN_RESERV (decl
)->name
);
8501 print_rtl (output_description_file
,
8502 DECL_INSN_RESERV (decl
)->condexp
);
8503 fprintf (output_description_file
, ": ");
8504 output_regexp (DECL_INSN_RESERV (decl
)->regexp
);
8505 fprintf (output_description_file
, "\n");
8507 else if (decl
->mode
== dm_bypass
)
8508 fprintf (output_description_file
, "bypass %d %s %s\n",
8509 DECL_BYPASS (decl
)->latency
,
8510 DECL_BYPASS (decl
)->out_insn_name
,
8511 DECL_BYPASS (decl
)->in_insn_name
);
8513 fprintf (output_description_file
, "\n\f\n");
8516 /* The function outputs name of AUTOMATON. */
8518 output_automaton_name (FILE *f
, automaton_t automaton
)
8520 if (automaton
->corresponding_automaton_decl
== NULL
)
8521 fprintf (f
, "#%d", automaton
->automaton_order_num
);
8523 fprintf (f
, "`%s'", automaton
->corresponding_automaton_decl
->name
);
8526 /* Maximal length of line for pretty printing into description
8528 #define MAX_LINE_LENGTH 70
8530 /* The function outputs units name belonging to AUTOMATON. */
8532 output_automaton_units (automaton_t automaton
)
8536 int curr_line_length
;
8537 int there_is_an_automaton_unit
;
8540 fprintf (output_description_file
, "\n Corresponding units:\n");
8541 fprintf (output_description_file
, " ");
8542 curr_line_length
= 4;
8543 there_is_an_automaton_unit
= 0;
8544 for (i
= 0; i
< description
->decls_num
; i
++)
8546 decl
= description
->decls
[i
];
8547 if (decl
->mode
== dm_unit
8548 && (DECL_UNIT (decl
)->corresponding_automaton_num
8549 == automaton
->automaton_order_num
))
8551 there_is_an_automaton_unit
= 1;
8552 name
= DECL_UNIT (decl
)->name
;
8553 if (curr_line_length
+ strlen (name
) + 1 > MAX_LINE_LENGTH
)
8555 curr_line_length
= strlen (name
) + 4;
8556 fprintf (output_description_file
, "\n ");
8560 curr_line_length
+= strlen (name
) + 1;
8561 fprintf (output_description_file
, " ");
8563 fprintf (output_description_file
, "%s", name
);
8566 if (!there_is_an_automaton_unit
)
8567 fprintf (output_description_file
, "<None>");
8568 fprintf (output_description_file
, "\n\n");
8571 /* The following variable is used for forming array of all possible cpu unit
8572 reservations described by the current DFA state. */
8573 static VEC(reserv_sets_t
,heap
) *state_reservs
;
8575 /* The function forms `state_reservs' for STATE. */
8577 add_state_reservs (state_t state
)
8579 alt_state_t curr_alt_state
;
8581 if (state
->component_states
!= NULL
)
8582 for (curr_alt_state
= state
->component_states
;
8583 curr_alt_state
!= NULL
;
8584 curr_alt_state
= curr_alt_state
->next_sorted_alt_state
)
8585 add_state_reservs (curr_alt_state
->state
);
8587 VEC_safe_push (reserv_sets_t
,heap
, state_reservs
, state
->reservs
);
8590 /* The function outputs readable representation of all out arcs of
8593 output_state_arcs (state_t state
)
8597 const char *insn_name
;
8598 int curr_line_length
;
8600 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
8603 gcc_assert (ainsn
->first_insn_with_same_reservs
);
8604 fprintf (output_description_file
, " ");
8605 curr_line_length
= 7;
8606 fprintf (output_description_file
, "%2d: ", ainsn
->insn_equiv_class_num
);
8609 insn_name
= ainsn
->insn_reserv_decl
->name
;
8610 if (curr_line_length
+ strlen (insn_name
) > MAX_LINE_LENGTH
)
8612 if (ainsn
!= arc
->insn
)
8614 fprintf (output_description_file
, ",\n ");
8615 curr_line_length
= strlen (insn_name
) + 6;
8618 curr_line_length
+= strlen (insn_name
);
8622 curr_line_length
+= strlen (insn_name
);
8623 if (ainsn
!= arc
->insn
)
8625 curr_line_length
+= 2;
8626 fprintf (output_description_file
, ", ");
8629 fprintf (output_description_file
, "%s", insn_name
);
8630 ainsn
= ainsn
->next_same_reservs_insn
;
8632 while (ainsn
!= NULL
);
8633 fprintf (output_description_file
, " %d \n",
8634 arc
->to_state
->order_state_num
);
8636 fprintf (output_description_file
, "\n");
8639 /* The following function is used for sorting possible cpu unit
8640 reservation of a DFA state. */
8642 state_reservs_cmp (const void *reservs_ptr_1
, const void *reservs_ptr_2
)
8644 return reserv_sets_cmp (*(reserv_sets_t
*) reservs_ptr_1
,
8645 *(reserv_sets_t
*) reservs_ptr_2
);
8648 /* The following function is used for sorting possible cpu unit
8649 reservation of a DFA state. */
8651 remove_state_duplicate_reservs (void)
8655 for (i
= 1, j
= 0; i
< VEC_length (reserv_sets_t
, state_reservs
); i
++)
8656 if (reserv_sets_cmp (VEC_index (reserv_sets_t
, state_reservs
, j
),
8657 VEC_index (reserv_sets_t
, state_reservs
, i
)))
8660 VEC_replace (reserv_sets_t
, state_reservs
, j
,
8661 VEC_index (reserv_sets_t
, state_reservs
, i
));
8663 VEC_truncate (reserv_sets_t
, state_reservs
, j
+ 1);
8666 /* The following function output readable representation of DFA(s)
8667 state used for fast recognition of pipeline hazards. State is
8668 described by possible (current and scheduled) cpu unit
8671 output_state (state_t state
)
8677 fprintf (output_description_file
, " State #%d", state
->order_state_num
);
8678 fprintf (output_description_file
,
8679 state
->new_cycle_p
? " (new cycle)\n" : "\n");
8680 add_state_reservs (state
);
8681 qsort (VEC_address (reserv_sets_t
, state_reservs
),
8682 VEC_length (reserv_sets_t
, state_reservs
),
8683 sizeof (reserv_sets_t
), state_reservs_cmp
);
8684 remove_state_duplicate_reservs ();
8685 for (i
= 1; i
< VEC_length (reserv_sets_t
, state_reservs
); i
++)
8687 fprintf (output_description_file
, " ");
8688 output_reserv_sets (output_description_file
,
8689 VEC_index (reserv_sets_t
, state_reservs
, i
));
8690 fprintf (output_description_file
, "\n");
8692 fprintf (output_description_file
, "\n");
8693 output_state_arcs (state
);
8694 VEC_free (reserv_sets_t
,heap
, state_reservs
);
8697 /* The following function output readable representation of
8698 DFAs used for fast recognition of pipeline hazards. */
8700 output_automaton_descriptions (void)
8702 automaton_t automaton
;
8704 for (automaton
= description
->first_automaton
;
8706 automaton
= automaton
->next_automaton
)
8708 fprintf (output_description_file
, "\nAutomaton ");
8709 output_automaton_name (output_description_file
, automaton
);
8710 fprintf (output_description_file
, "\n");
8711 output_automaton_units (automaton
);
8712 pass_states (automaton
, output_state
);
8718 /* The page contains top level function for generation DFA(s) used for
8721 /* The function outputs statistics about work of different phases of
8724 output_statistics (FILE *f
)
8726 automaton_t automaton
;
8729 int transition_comb_vect_els
= 0;
8730 int transition_full_vect_els
= 0;
8731 int min_issue_delay_vect_els
= 0;
8732 int locked_states
= 0;
8735 for (automaton
= description
->first_automaton
;
8737 automaton
= automaton
->next_automaton
)
8739 fprintf (f
, "\nAutomaton ");
8740 output_automaton_name (f
, automaton
);
8741 fprintf (f
, "\n %5d NDFA states, %5d NDFA arcs\n",
8742 automaton
->NDFA_states_num
, automaton
->NDFA_arcs_num
);
8743 fprintf (f
, " %5d DFA states, %5d DFA arcs\n",
8744 automaton
->DFA_states_num
, automaton
->DFA_arcs_num
);
8745 states_num
= automaton
->DFA_states_num
;
8746 if (!no_minimization_flag
)
8748 fprintf (f
, " %5d minimal DFA states, %5d minimal DFA arcs\n",
8749 automaton
->minimal_DFA_states_num
,
8750 automaton
->minimal_DFA_arcs_num
);
8751 states_num
= automaton
->minimal_DFA_states_num
;
8753 fprintf (f
, " %5d all insns %5d insn equivalence classes\n",
8754 description
->insns_num
, automaton
->insn_equiv_classes_num
);
8755 fprintf (f
, " %d locked states\n", automaton
->locked_states
);
8758 (f
, "%5ld transition comb vector els, %5ld trans table els: %s\n",
8759 (long) VEC_length (vect_el_t
, automaton
->trans_table
->comb_vect
),
8760 (long) VEC_length (vect_el_t
, automaton
->trans_table
->full_vect
),
8761 (comb_vect_p (automaton
->trans_table
)
8762 ? "use comb vect" : "use simple vect"));
8764 (f
, "%5ld min delay table els, compression factor %d\n",
8765 (long) states_num
* automaton
->insn_equiv_classes_num
,
8766 automaton
->min_issue_delay_table_compression_factor
);
8767 transition_comb_vect_els
8768 += VEC_length (vect_el_t
, automaton
->trans_table
->comb_vect
);
8769 transition_full_vect_els
8770 += VEC_length (vect_el_t
, automaton
->trans_table
->full_vect
);
8771 min_issue_delay_vect_els
8772 += states_num
* automaton
->insn_equiv_classes_num
;
8774 += automaton
->locked_states
;
8778 fprintf (f
, "\n%5d all allocated states, %5d all allocated arcs\n",
8779 allocated_states_num
, allocated_arcs_num
);
8780 fprintf (f
, "%5d all allocated alternative states\n",
8781 allocated_alt_states_num
);
8782 fprintf (f
, "%5d all transition comb vector els, %5d all trans table els\n",
8783 transition_comb_vect_els
, transition_full_vect_els
);
8784 fprintf (f
, "%5d all min delay table els\n", min_issue_delay_vect_els
);
8785 fprintf (f
, "%5d all locked states\n", locked_states
);
8789 /* The function output times of work of different phases of DFA
8792 output_time_statistics (FILE *f
)
8794 fprintf (f
, "\n transformation: ");
8795 print_active_time (f
, transform_time
);
8796 fprintf (f
, (!ndfa_flag
? ", building DFA: " : ", building NDFA: "));
8797 print_active_time (f
, NDFA_time
);
8800 fprintf (f
, ", NDFA -> DFA: ");
8801 print_active_time (f
, NDFA_to_DFA_time
);
8803 fprintf (f
, "\n DFA minimization: ");
8804 print_active_time (f
, minimize_time
);
8805 fprintf (f
, ", making insn equivalence: ");
8806 print_active_time (f
, equiv_time
);
8807 fprintf (f
, "\n all automaton generation: ");
8808 print_active_time (f
, automaton_generation_time
);
8809 fprintf (f
, ", output: ");
8810 print_active_time (f
, output_time
);
8814 /* The function generates DFA (deterministic finite state automaton)
8815 for fast recognition of pipeline hazards. No errors during
8816 checking must be fixed before this function call. */
8820 automata_num
= split_argument
;
8821 if (description
->units_num
< automata_num
)
8822 automata_num
= description
->units_num
;
8825 initiate_automata_lists ();
8826 initiate_pass_states ();
8827 initiate_excl_sets ();
8828 initiate_presence_absence_pattern_sets ();
8829 automaton_generation_time
= create_ticker ();
8831 ticker_off (&automaton_generation_time
);
8836 /* This page mainly contains top level functions of pipeline hazards
8837 description translator. */
8839 /* The following macro value is suffix of name of description file of
8840 pipeline hazards description translator. */
8841 #define STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX ".dfa"
8843 /* The function returns suffix of given file name. The returned
8844 string can not be changed. */
8846 file_name_suffix (const char *file_name
)
8848 const char *last_period
;
8850 for (last_period
= NULL
; *file_name
!= '\0'; file_name
++)
8851 if (*file_name
== '.')
8852 last_period
= file_name
;
8853 return (last_period
== NULL
? file_name
: last_period
);
8856 /* The function returns base name of given file name, i.e. pointer to
8857 first char after last `/' (or `\' for WIN32) in given file name,
8858 given file name itself if the directory name is absent. The
8859 returned string can not be changed. */
8861 base_file_name (const char *file_name
)
8863 int directory_name_length
;
8865 directory_name_length
= strlen (file_name
);
8867 while (directory_name_length
>= 0 && file_name
[directory_name_length
] != '/'
8868 && file_name
[directory_name_length
] != '\\')
8870 while (directory_name_length
>= 0 && file_name
[directory_name_length
] != '/')
8872 directory_name_length
--;
8873 return file_name
+ directory_name_length
+ 1;
8876 /* The following is top level function to initialize the work of
8877 pipeline hazards description translator. */
8879 initiate_automaton_gen (int argc
, char **argv
)
8881 const char *base_name
;
8885 split_argument
= 0; /* default value */
8886 no_minimization_flag
= 0;
8892 for (i
= 2; i
< argc
; i
++)
8893 if (strcmp (argv
[i
], NO_MINIMIZATION_OPTION
) == 0)
8894 no_minimization_flag
= 1;
8895 else if (strcmp (argv
[i
], TIME_OPTION
) == 0)
8897 else if (strcmp (argv
[i
], STATS_OPTION
) == 0)
8899 else if (strcmp (argv
[i
], V_OPTION
) == 0)
8901 else if (strcmp (argv
[i
], W_OPTION
) == 0)
8903 else if (strcmp (argv
[i
], NDFA_OPTION
) == 0)
8905 else if (strcmp (argv
[i
], PROGRESS_OPTION
) == 0)
8907 else if (strcmp (argv
[i
], "-split") == 0)
8910 fatal ("-split has no argument.");
8911 fatal ("option `-split' has not been implemented yet\n");
8912 /* split_argument = atoi (argument_vect [i + 1]); */
8915 /* Initialize IR storage. */
8916 obstack_init (&irp
);
8917 initiate_automaton_decl_table ();
8918 initiate_insn_decl_table ();
8919 initiate_decl_table ();
8920 output_file
= stdout
;
8921 output_description_file
= NULL
;
8922 base_name
= base_file_name (argv
[1]);
8923 obstack_grow (&irp
, base_name
,
8924 strlen (base_name
) - strlen (file_name_suffix (base_name
)));
8925 obstack_grow (&irp
, STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX
,
8926 strlen (STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX
) + 1);
8927 obstack_1grow (&irp
, '\0');
8928 output_description_file_name
= obstack_base (&irp
);
8929 obstack_finish (&irp
);
8932 /* The following function checks existence at least one arc marked by
8935 check_automata_insn_issues (void)
8937 automaton_t automaton
;
8938 ainsn_t ainsn
, reserv_ainsn
;
8940 for (automaton
= description
->first_automaton
;
8942 automaton
= automaton
->next_automaton
)
8944 for (ainsn
= automaton
->ainsn_list
;
8946 ainsn
= ainsn
->next_ainsn
)
8947 if (ainsn
->first_insn_with_same_reservs
&& !ainsn
->arc_exists_p
)
8949 for (reserv_ainsn
= ainsn
;
8950 reserv_ainsn
!= NULL
;
8951 reserv_ainsn
= reserv_ainsn
->next_same_reservs_insn
)
8952 if (automaton
->corresponding_automaton_decl
!= NULL
)
8955 error ("Automaton `%s': Insn `%s' will never be issued",
8956 automaton
->corresponding_automaton_decl
->name
,
8957 reserv_ainsn
->insn_reserv_decl
->name
);
8960 (0, "Automaton `%s': Insn `%s' will never be issued",
8961 automaton
->corresponding_automaton_decl
->name
,
8962 reserv_ainsn
->insn_reserv_decl
->name
);
8967 error ("Insn `%s' will never be issued",
8968 reserv_ainsn
->insn_reserv_decl
->name
);
8970 warning (0, "Insn `%s' will never be issued",
8971 reserv_ainsn
->insn_reserv_decl
->name
);
8977 /* The following vla is used for storing pointers to all achieved
8979 static VEC(state_t
,heap
) *automaton_states
;
8981 /* This function is called by function pass_states to add an achieved
8984 add_automaton_state (state_t state
)
8986 VEC_safe_push (state_t
,heap
, automaton_states
, state
);
8989 /* The following function forms list of important automata (whose
8990 states may be changed after the insn issue) for each insn. */
8992 form_important_insn_automata_lists (void)
8994 automaton_t automaton
;
9001 automaton_states
= 0;
9002 /* Mark important ainsns. */
9003 for (automaton
= description
->first_automaton
;
9005 automaton
= automaton
->next_automaton
)
9007 VEC_truncate (state_t
, automaton_states
, 0);
9008 pass_states (automaton
, add_automaton_state
);
9009 for (n
= 0; n
< VEC_length (state_t
, automaton_states
); n
++)
9011 state_t s
= VEC_index (state_t
, automaton_states
, n
);
9012 for (arc
= first_out_arc (s
);
9014 arc
= next_out_arc (arc
))
9015 if (arc
->to_state
!= s
)
9017 gcc_assert (arc
->insn
->first_insn_with_same_reservs
);
9018 for (ainsn
= arc
->insn
;
9020 ainsn
= ainsn
->next_same_reservs_insn
)
9021 ainsn
->important_p
= TRUE
;
9025 VEC_free (state_t
,heap
, automaton_states
);
9027 /* Create automata sets for the insns. */
9028 for (i
= 0; i
< description
->decls_num
; i
++)
9030 decl
= description
->decls
[i
];
9031 if (decl
->mode
== dm_insn_reserv
)
9033 automata_list_start ();
9034 for (automaton
= description
->first_automaton
;
9036 automaton
= automaton
->next_automaton
)
9037 for (ainsn
= automaton
->ainsn_list
;
9039 ainsn
= ainsn
->next_ainsn
)
9040 if (ainsn
->important_p
9041 && ainsn
->insn_reserv_decl
== DECL_INSN_RESERV (decl
))
9043 automata_list_add (automaton
);
9046 DECL_INSN_RESERV (decl
)->important_automata_list
9047 = automata_list_finish ();
9053 /* The following is top level function to generate automat(a,on) for
9054 fast recognition of pipeline hazards. */
9056 expand_automata (void)
9060 description
= create_node (sizeof (struct description
)
9061 /* One entry for cycle advancing insn. */
9062 + sizeof (decl_t
) * VEC_length (decl_t
, decls
));
9063 description
->decls_num
= VEC_length (decl_t
, decls
);
9064 description
->query_units_num
= 0;
9065 for (i
= 0; i
< description
->decls_num
; i
++)
9067 description
->decls
[i
] = VEC_index (decl_t
, decls
, i
);
9068 if (description
->decls
[i
]->mode
== dm_unit
9069 && DECL_UNIT (description
->decls
[i
])->query_p
)
9070 DECL_UNIT (description
->decls
[i
])->query_num
9071 = description
->query_units_num
++;
9073 all_time
= create_ticker ();
9074 check_time
= create_ticker ();
9076 fprintf (stderr
, "Check description...");
9077 check_all_description ();
9079 fprintf (stderr
, "done\n");
9080 ticker_off (&check_time
);
9081 generation_time
= create_ticker ();
9084 transform_insn_regexps ();
9085 check_unit_distributions_to_automata ();
9090 check_automata_insn_issues ();
9094 form_important_insn_automata_lists ();
9096 ticker_off (&generation_time
);
9099 /* The following is top level function to output PHR and to finish
9100 work with pipeline description translator. */
9102 write_automata (void)
9104 output_time
= create_ticker ();
9106 fprintf (stderr
, "Forming and outputting automata tables...");
9110 fprintf (stderr
, "done\n");
9111 fprintf (stderr
, "Output functions to work with automata...");
9113 output_chip_definitions ();
9114 output_max_insn_queue_index_def ();
9115 output_internal_min_issue_delay_func ();
9116 output_internal_trans_func ();
9117 /* Cache of insn dfa codes: */
9118 fprintf (output_file
, "\nstatic int *%s;\n", DFA_INSN_CODES_VARIABLE_NAME
);
9119 fprintf (output_file
, "\nstatic int %s;\n\n",
9120 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
);
9121 output_dfa_insn_code_func ();
9122 output_trans_func ();
9123 output_min_issue_delay_func ();
9124 output_internal_dead_lock_func ();
9125 output_dead_lock_func ();
9126 output_size_func ();
9127 output_internal_reset_func ();
9128 output_reset_func ();
9129 output_min_insn_conflict_delay_func ();
9130 output_internal_insn_latency_func ();
9131 output_insn_latency_func ();
9132 output_print_reservation_func ();
9133 /* Output function get_cpu_unit_code. */
9134 fprintf (output_file
, "\n#if %s\n\n", CPU_UNITS_QUERY_MACRO_NAME
);
9135 output_get_cpu_unit_code_func ();
9136 output_cpu_unit_reservation_p ();
9137 fprintf (output_file
, "\n#endif /* #if %s */\n\n",
9138 CPU_UNITS_QUERY_MACRO_NAME
);
9139 output_dfa_clean_insn_cache_func ();
9140 output_dfa_start_func ();
9141 output_dfa_finish_func ();
9143 fprintf (stderr
, "done\n");
9146 output_description_file
= fopen (output_description_file_name
, "w");
9147 if (output_description_file
== NULL
)
9149 perror (output_description_file_name
);
9150 exit (FATAL_EXIT_CODE
);
9153 fprintf (stderr
, "Output automata description...");
9154 output_description ();
9155 output_automaton_descriptions ();
9157 fprintf (stderr
, "done\n");
9158 output_statistics (output_description_file
);
9161 output_statistics (stderr
);
9162 ticker_off (&output_time
);
9164 output_time_statistics (stderr
);
9167 finish_automata_lists ();
9170 fprintf (stderr
, "Summary:\n");
9171 fprintf (stderr
, " check time ");
9172 print_active_time (stderr
, check_time
);
9173 fprintf (stderr
, ", generation time ");
9174 print_active_time (stderr
, generation_time
);
9175 fprintf (stderr
, ", all time ");
9176 print_active_time (stderr
, all_time
);
9177 fprintf (stderr
, "\n");
9179 /* Finish all work. */
9180 if (output_description_file
!= NULL
)
9182 fflush (output_description_file
);
9183 if (ferror (stdout
) != 0)
9184 fatal ("Error in writing DFA description file %s: %s",
9185 output_description_file_name
, xstrerror (errno
));
9186 fclose (output_description_file
);
9188 finish_automaton_decl_table ();
9189 finish_insn_decl_table ();
9190 finish_decl_table ();
9191 obstack_free (&irp
, NULL
);
9192 if (have_error
&& output_description_file
!= NULL
)
9193 remove (output_description_file_name
);
9197 main (int argc
, char **argv
)
9201 progname
= "genautomata";
9203 if (init_md_reader_args (argc
, argv
) != SUCCESS_EXIT_CODE
)
9204 return (FATAL_EXIT_CODE
);
9206 initiate_automaton_gen (argc
, argv
);
9210 int insn_code_number
;
9212 desc
= read_md_rtx (&lineno
, &insn_code_number
);
9216 switch (GET_CODE (desc
))
9218 case DEFINE_CPU_UNIT
:
9219 gen_cpu_unit (desc
);
9222 case DEFINE_QUERY_CPU_UNIT
:
9223 gen_query_cpu_unit (desc
);
9231 gen_excl_set (desc
);
9235 gen_presence_set (desc
);
9238 case FINAL_PRESENCE_SET
:
9239 gen_final_presence_set (desc
);
9243 gen_absence_set (desc
);
9246 case FINAL_ABSENCE_SET
:
9247 gen_final_absence_set (desc
);
9250 case DEFINE_AUTOMATON
:
9251 gen_automaton (desc
);
9254 case AUTOMATA_OPTION
:
9255 gen_automata_option (desc
);
9258 case DEFINE_RESERVATION
:
9262 case DEFINE_INSN_RESERVATION
:
9263 gen_insn_reserv (desc
);
9272 return FATAL_EXIT_CODE
;
9274 puts ("/* Generated automatically by the program `genautomata'\n"
9275 " from the machine description file `md'. */\n\n"
9276 "#include \"config.h\"\n"
9277 "#include \"system.h\"\n"
9278 "#include \"coretypes.h\"\n"
9279 "#include \"tm.h\"\n"
9280 "#include \"rtl.h\"\n"
9281 "#include \"tm_p.h\"\n"
9282 "#include \"insn-config.h\"\n"
9283 "#include \"recog.h\"\n"
9284 "#include \"regs.h\"\n"
9285 "#include \"real.h\"\n"
9286 "#include \"output.h\"\n"
9287 "#include \"insn-attr.h\"\n"
9288 "#include \"toplev.h\"\n"
9289 "#include \"flags.h\"\n"
9290 "#include \"function.h\"\n");
9292 if (VEC_length (decl_t
, decls
) > 0)
9299 return (ferror (stdout
) != 0 ? FATAL_EXIT_CODE
: SUCCESS_EXIT_CODE
);