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 3, or (at your option) any
14 GCC is distributed in the hope that it will be useful, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING3. If not see
21 <http://www.gnu.org/licenses/>. */
25 1. Detecting pipeline structural hazards quickly. T. Proebsting,
26 C. Fraser. Proceedings of ACM SIGPLAN-SIGACT Symposium on
27 Principles of Programming Languages, pages 280--286, 1994.
29 This article is a good start point to understand usage of finite
30 state automata for pipeline hazard recognizers. But I'd
31 recommend the 2nd article for more deep understanding.
33 2. Efficient Instruction Scheduling Using Finite State Automata:
34 V. Bala and N. Rubin, Proceedings of MICRO-28. This is the best
35 article about usage of finite state automata for pipeline hazard
38 The current implementation is different from the 2nd article in the
41 1. New operator `|' (alternative) is permitted in functional unit
42 reservation which can be treated deterministically and
43 non-deterministically.
45 2. Possibility of usage of nondeterministic automata too.
47 3. Possibility to query functional unit reservations for given
50 4. Several constructions to describe impossible reservations
51 (`exclusion_set', `presence_set', `final_presence_set',
52 `absence_set', and `final_absence_set').
54 5. No reverse automata are generated. Trace instruction scheduling
55 requires this. It can be easily added in the future if we
58 6. Union of automaton states are not generated yet. It is planned
59 to be implemented. Such feature is needed to make more accurate
60 interlock insn scheduling to get state describing functional
61 unit reservation in a joint CFG point. */
63 /* This file code processes constructions of machine description file
64 which describes automaton used for recognition of processor pipeline
65 hazards by insn scheduler and can be used for other tasks (such as
68 The translator functions `gen_cpu_unit', `gen_query_cpu_unit',
69 `gen_bypass', `gen_excl_set', `gen_presence_set',
70 `gen_final_presence_set', `gen_absence_set',
71 `gen_final_absence_set', `gen_automaton', `gen_automata_option',
72 `gen_reserv', `gen_insn_reserv' are called from file
73 `genattrtab.c'. They transform RTL constructions describing
74 automata in .md file into internal representation convenient for
77 The translator major function `expand_automata' processes the
78 description internal representation into finite state automaton.
81 o checking correctness of the automaton pipeline description
82 (major function is `check_all_description').
84 o generating automaton (automata) from the description (major
85 function is `make_automaton').
87 o optional transformation of nondeterministic finite state
88 automata into deterministic ones if the alternative operator
89 `|' is treated nondeterministically in the description (major
90 function is NDFA_to_DFA).
92 o optional minimization of the finite state automata by merging
93 equivalent automaton states (major function is `minimize_DFA').
95 o forming tables (some as comb vectors) and attributes
96 representing the automata (functions output_..._table).
98 Function `write_automata' outputs the created finite state
99 automaton as different tables and functions which works with the
100 automata to inquire automaton state and to change its state. These
101 function are used by gcc instruction scheduler and may be some
106 #include "coretypes.h"
111 #include "gensupport.h"
121 /* Positions in machine description file. Now they are not used. But
122 they could be used in the future for better diagnostic messages. */
125 /* The following is element of vector of current (and planned in the
126 future) functional unit reservations. */
127 typedef unsigned HOST_WIDE_INT set_el_t
;
129 /* Reservations of function units are represented by value of the following
131 typedef set_el_t
*reserv_sets_t
;
132 typedef const set_el_t
*const_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 const struct unit_decl
*const_unit_decl_t
;
186 typedef struct decl
*decl_t
;
187 typedef const struct decl
*const_decl_t
;
188 typedef struct regexp
*regexp_t
;
189 typedef struct unit_set_el
*unit_set_el_t
;
190 typedef struct pattern_set_el
*pattern_set_el_t
;
191 typedef struct pattern_reserv
*pattern_reserv_t
;
192 typedef struct alt_state
*alt_state_t
;
193 typedef struct state
*state_t
;
194 typedef const struct state
*const_state_t
;
195 typedef struct arc
*arc_t
;
196 typedef struct ainsn
*ainsn_t
;
197 typedef struct automaton
*automaton_t
;
198 typedef struct automata_list_el
*automata_list_el_t
;
199 typedef const struct automata_list_el
*const_automata_list_el_t
;
200 typedef struct state_ainsn_table
*state_ainsn_table_t
;
202 /* Undefined position. */
203 static pos_t no_pos
= 0;
205 /* All IR is stored in the following obstack. */
206 static struct obstack irp
;
209 /* Declare vector types for various data structures: */
211 DEF_VEC_P(alt_state_t
);
212 DEF_VEC_ALLOC_P(alt_state_t
,heap
);
214 DEF_VEC_ALLOC_P(ainsn_t
,heap
);
216 DEF_VEC_ALLOC_P(state_t
,heap
);
218 DEF_VEC_ALLOC_P(decl_t
,heap
);
219 DEF_VEC_P(reserv_sets_t
);
220 DEF_VEC_ALLOC_P(reserv_sets_t
,heap
);
222 DEF_VEC_I(vect_el_t
);
223 DEF_VEC_ALLOC_I(vect_el_t
, heap
);
224 typedef VEC(vect_el_t
,heap
) *vla_hwint_t
;
226 /* Forward declarations of functions used before their definitions, only. */
227 static regexp_t
gen_regexp_sequence (const char *);
228 static void reserv_sets_or (reserv_sets_t
, reserv_sets_t
,
230 static reserv_sets_t
get_excl_set (reserv_sets_t
);
231 static int check_presence_pattern_sets (reserv_sets_t
,
233 static int check_absence_pattern_sets (reserv_sets_t
, reserv_sets_t
,
235 static arc_t
first_out_arc (const_state_t
);
236 static arc_t
next_out_arc (arc_t
);
240 /* Options with the following names can be set up in automata_option
241 construction. Because the strings occur more one time we use the
244 #define NO_MINIMIZATION_OPTION "-no-minimization"
245 #define TIME_OPTION "-time"
246 #define STATS_OPTION "-stats"
247 #define V_OPTION "-v"
248 #define W_OPTION "-w"
249 #define NDFA_OPTION "-ndfa"
250 #define PROGRESS_OPTION "-progress"
252 /* The following flags are set up by function `initiate_automaton_gen'. */
254 /* Make automata with nondeterministic reservation by insns (`-ndfa'). */
255 static int ndfa_flag
;
257 /* Do not make minimization of DFA (`-no-minimization'). */
258 static int no_minimization_flag
;
260 /* Value of this variable is number of automata being generated. The
261 actual number of automata may be less this value if there is not
262 sufficient number of units. This value is defined by argument of
263 option `-split' or by constructions automaton if the value is zero
264 (it is default value of the argument). */
265 static int split_argument
;
267 /* Flag of output time statistics (`-time'). */
268 static int time_flag
;
270 /* Flag of automata statistics (`-stats'). */
271 static int stats_flag
;
273 /* Flag of creation of description file which contains description of
274 result automaton and statistics information (`-v'). */
277 /* Flag of output of a progress bar showing how many states were
278 generated so far for automaton being processed (`-progress'). */
279 static int progress_flag
;
281 /* Flag of generating warning instead of error for non-critical errors
286 /* Output file for pipeline hazard recognizer (PHR) being generated.
287 The value is NULL if the file is not defined. */
288 static FILE *output_file
;
290 /* Description file of PHR. The value is NULL if the file is not
292 static FILE *output_description_file
;
294 /* PHR description file name. */
295 static char *output_description_file_name
;
297 /* Value of the following variable is node representing description
298 being processed. This is start point of IR. */
299 static struct description
*description
;
303 /* This page contains description of IR structure (nodes). */
317 /* This describes define_cpu_unit and define_query_cpu_unit (see file
322 /* NULL if the automaton name is absent. */
323 const char *automaton_name
;
324 /* If the following value is not zero, the cpu unit reservation is
325 described in define_query_cpu_unit. */
328 /* The following fields are defined by checker. */
330 /* The following field value is nonzero if the unit is used in an
334 /* The following field value is order number (0, 1, ...) of given
337 /* The following field value is corresponding declaration of
338 automaton which was given in description. If the field value is
339 NULL then automaton in the unit declaration was absent. */
340 struct automaton_decl
*automaton_decl
;
341 /* The following field value is maximal cycle number (1, ...) on
342 which given unit occurs in insns. Zero value means that given
343 unit is not used in insns. */
344 int max_occ_cycle_num
;
345 /* The following field value is minimal cycle number (0, ...) on
346 which given unit occurs in insns. -1 value means that given
347 unit is not used in insns. */
348 int min_occ_cycle_num
;
349 /* The following list contains units which conflict with given
351 unit_set_el_t excl_list
;
352 /* The following list contains patterns which are required to
353 reservation of given unit. */
354 pattern_set_el_t presence_list
;
355 pattern_set_el_t final_presence_list
;
356 /* The following list contains patterns which should be not present
357 in reservation for given unit. */
358 pattern_set_el_t absence_list
;
359 pattern_set_el_t final_absence_list
;
360 /* The following is used only when `query_p' has nonzero value.
361 This is query number for the unit. */
363 /* The following is the last cycle on which the unit was checked for
364 correct distributions of units to automata in a regexp. */
365 int last_distribution_check_cycle
;
367 /* The following fields are defined by automaton generator. */
369 /* The following field value is number of the automaton to which
370 given unit belongs. */
371 int corresponding_automaton_num
;
372 /* If the following value is not zero, the cpu unit is present in a
373 `exclusion_set' or in right part of a `presence_set',
374 `final_presence_set', `absence_set', and
375 `final_absence_set'define_query_cpu_unit. */
379 /* This describes define_bypass (see file rtl.def). */
383 const char *out_insn_name
;
384 const char *in_insn_name
;
385 const char *bypass_guard_name
;
387 /* The following fields are defined by checker. */
389 /* output and input insns of given bypass. */
390 struct insn_reserv_decl
*out_insn_reserv
;
391 struct insn_reserv_decl
*in_insn_reserv
;
392 /* The next bypass for given output insn. */
393 struct bypass_decl
*next
;
396 /* This describes define_automaton (see file rtl.def). */
397 struct automaton_decl
401 /* The following fields are defined by automaton generator. */
403 /* The following field value is nonzero if the automaton is used in
404 an regexp definition. */
405 char automaton_is_used
;
407 /* The following fields are defined by checker. */
409 /* The following field value is the corresponding automaton. This
410 field is not NULL only if the automaton is present in unit
411 declarations and the automatic partition on automata is not
413 automaton_t corresponding_automaton
;
416 /* This describes exclusion relations: exclusion_set (see file
421 int first_list_length
;
425 /* This describes unit relations: [final_]presence_set or
426 [final_]absence_set (see file rtl.def). */
427 struct unit_pattern_rel_decl
436 /* This describes define_reservation (see file rtl.def). */
442 /* The following fields are defined by checker. */
444 /* The following field value is nonzero if the unit is used in an
447 /* The following field is used to check up cycle in expression
452 /* This describes define_insn_reservation (see file rtl.def). */
453 struct insn_reserv_decl
460 /* The following fields are defined by checker. */
462 /* The following field value is order number (0, 1, ...) of given
465 /* The following field value is list of bypasses in which given insn
467 struct bypass_decl
*bypass_list
;
469 /* The following fields are defined by automaton generator. */
471 /* The following field is the insn regexp transformed that
472 the regexp has not optional regexp, repetition regexp, and an
473 reservation name (i.e. reservation identifiers are changed by the
474 corresponding regexp) and all alternations are the topest level
475 of the regexp. The value can be NULL only if it is special
476 insn `cycle advancing'. */
477 regexp_t transformed_regexp
;
478 /* The following field value is list of arcs marked given
479 insn. The field is used in transformation NDFA -> DFA. */
480 arc_t arcs_marked_by_insn
;
481 /* The two following fields are used during minimization of a finite state
483 /* The field value is number of equivalence class of state into
484 which arc marked by given insn enters from a state (fixed during
485 an automaton minimization). */
487 /* The following member value is the list to automata which can be
488 changed by the insn issue. */
489 automata_list_el_t important_automata_list
;
490 /* The following member is used to process insn once for output. */
494 /* This contains a declaration mentioned above. */
497 /* What node in the union? */
502 struct unit_decl unit
;
503 struct bypass_decl bypass
;
504 struct automaton_decl automaton
;
505 struct excl_rel_decl excl
;
506 struct unit_pattern_rel_decl presence
;
507 struct unit_pattern_rel_decl absence
;
508 struct reserv_decl reserv
;
509 struct insn_reserv_decl insn_reserv
;
513 /* The following structures represent parsed reservation strings. */
525 /* Cpu unit in reservation. */
529 unit_decl_t unit_decl
;
532 /* Define_reservation in a reservation. */
536 struct reserv_decl
*reserv_decl
;
539 /* Absence of reservation (represented by string `nothing'). */
540 struct nothing_regexp
542 /* This used to be empty but ISO C doesn't allow that. */
546 /* Representation of reservations separated by ',' (see file
548 struct sequence_regexp
551 regexp_t regexps
[1];
554 /* Representation of construction `repeat' (see file rtl.def). */
561 /* Representation of reservations separated by '+' (see file
566 regexp_t regexps
[1];
569 /* Representation of reservations separated by '|' (see file
574 regexp_t regexps
[1];
577 /* Representation of a reservation string. */
580 /* What node in the union? */
581 enum regexp_mode mode
;
585 struct unit_regexp unit
;
586 struct reserv_regexp reserv
;
587 struct nothing_regexp nothing
;
588 struct sequence_regexp sequence
;
589 struct repeat_regexp repeat
;
590 struct allof_regexp allof
;
591 struct oneof_regexp oneof
;
595 /* Represents description of pipeline hazard description based on
601 /* The following fields are defined by checker. */
603 /* The following fields values are correspondingly number of all
604 units, query units, and insns in the description. */
608 /* The following field value is max length (in cycles) of
609 reservations of insns. The field value is defined only for
611 int max_insn_reserv_cycles
;
613 /* The following fields are defined by automaton generator. */
615 /* The following field value is the first automaton. */
616 automaton_t first_automaton
;
618 /* The following field is created by pipeline hazard parser and
619 contains all declarations. We allocate additional entry for
620 special insn "cycle advancing" which is added by the automaton
626 /* The following nodes are created in automaton checker. */
628 /* The following nodes represent exclusion set for cpu units. Each
629 element is accessed through only one excl_list. */
632 unit_decl_t unit_decl
;
633 unit_set_el_t next_unit_set_el
;
636 /* The following nodes represent presence or absence pattern for cpu
637 units. Each element is accessed through only one presence_list or
639 struct pattern_set_el
641 /* The number of units in unit_decls. */
643 /* The units forming the pattern. */
644 struct unit_decl
**unit_decls
;
645 pattern_set_el_t next_pattern_set_el
;
649 /* The following nodes are created in automaton generator. */
652 /* The following nodes represent presence or absence pattern for cpu
653 units. Each element is accessed through only one element of
654 unit_presence_set_table or unit_absence_set_table. */
655 struct pattern_reserv
657 reserv_sets_t reserv
;
658 pattern_reserv_t next_pattern_reserv
;
661 /* The following node type describes state automaton. The state may
662 be deterministic or non-deterministic. Non-deterministic state has
663 several component states which represent alternative cpu units
664 reservations. The state also is used for describing a
665 deterministic reservation of automaton insn. */
668 /* The following member value is nonzero if there is a transition by
671 /* The following field is list of processor unit reservations on
673 reserv_sets_t reservs
;
674 /* The following field is unique number of given state between other
677 /* The following field value is automaton to which given state
679 automaton_t automaton
;
680 /* The following field value is the first arc output from given
683 unsigned int num_out_arcs
;
684 /* The following field is used to form NDFA. */
685 char it_was_placed_in_stack_for_NDFA_forming
;
686 /* The following field is used to form DFA. */
687 char it_was_placed_in_stack_for_DFA_forming
;
688 /* The following field is used to transform NDFA to DFA and DFA
689 minimization. The field value is not NULL if the state is a
690 compound state. In this case the value of field `unit_sets_list'
691 is NULL. All states in the list are in the hash table. The list
692 is formed through field `next_sorted_alt_state'. We should
693 support only one level of nesting state. */
694 alt_state_t component_states
;
695 /* The following field is used for passing graph of states. */
697 /* The list of states belonging to one equivalence class is formed
698 with the aid of the following field. */
699 state_t next_equiv_class_state
;
700 /* The two following fields are used during minimization of a finite
702 int equiv_class_num_1
, equiv_class_num_2
;
703 /* The following field is used during minimization of a finite state
704 automaton. The field value is state corresponding to equivalence
705 class to which given state belongs. */
706 state_t equiv_class_state
;
707 unsigned int *presence_signature
;
708 /* The following field value is the order number of given state.
709 The states in final DFA is enumerated with the aid of the
712 /* This member is used for passing states for searching minimal
715 /* The following member is used to evaluate min issue delay of insn
717 int min_insn_issue_delay
;
723 /* The following field refers for the state into which given arc
726 /* The following field describes that the insn issue (with cycle
727 advancing for special insn `cycle advancing' and without cycle
728 advancing for others) makes transition from given state to
729 another given state. */
731 /* The following field value is the next arc output from the same
734 /* List of arcs marked given insn is formed with the following
735 field. The field is used in transformation NDFA -> DFA. */
736 arc_t next_arc_marked_by_insn
;
739 /* The following node type describes a deterministic alternative in
740 non-deterministic state which characterizes cpu unit reservations
741 of automaton insn or which is part of NDFA. */
744 /* The following field is a deterministic state which characterizes
745 unit reservations of the instruction. */
747 /* The following field refers to the next state which characterizes
748 unit reservations of the instruction. */
749 alt_state_t next_alt_state
;
750 /* The following field refers to the next state in sorted list. */
751 alt_state_t next_sorted_alt_state
;
754 /* The following node type describes insn of automaton. They are
755 labels of FA arcs. */
758 /* The following field value is the corresponding insn declaration
760 struct insn_reserv_decl
*insn_reserv_decl
;
761 /* The following field value is the next insn declaration for an
764 /* The following field is states which characterize automaton unit
765 reservations of the instruction. The value can be NULL only if it
766 is special insn `cycle advancing'. */
767 alt_state_t alt_states
;
768 /* The following field is sorted list of states which characterize
769 automaton unit reservations of the instruction. The value can be
770 NULL only if it is special insn `cycle advancing'. */
771 alt_state_t sorted_alt_states
;
772 /* The following field refers the next automaton insn with
773 the same reservations. */
774 ainsn_t next_same_reservs_insn
;
775 /* The following field is flag of the first automaton insn with the
776 same reservations in the declaration list. Only arcs marked such
777 insn is present in the automaton. This significantly decreases
778 memory requirements especially when several automata are
780 char first_insn_with_same_reservs
;
781 /* The following member has nonzero value if there is arc from state of
782 the automaton marked by the ainsn. */
784 /* Cyclic list of insns of an equivalence class is formed with the
785 aid of the following field. */
786 ainsn_t next_equiv_class_insn
;
787 /* The following field value is nonzero if the insn declaration is
788 the first insn declaration with given equivalence number. */
789 char first_ainsn_with_given_equivalence_num
;
790 /* The following field is number of class of equivalence of insns.
791 It is necessary because many insns may be equivalent with the
792 point of view of pipeline hazards. */
793 int insn_equiv_class_num
;
794 /* The following member value is TRUE if there is an arc in the
795 automaton marked by the insn into another state. In other
796 words, the insn can change the state of the automaton. */
800 /* The following describes an automaton for PHR. */
803 /* The following field value is the list of insn declarations for
806 /* The following field value is the corresponding automaton
807 declaration. This field is not NULL only if the automatic
808 partition on automata is not used. */
809 struct automaton_decl
*corresponding_automaton_decl
;
810 /* The following field value is the next automaton. */
811 automaton_t next_automaton
;
812 /* The following field is start state of FA. There are not unit
813 reservations in the state. */
815 /* The following field value is number of equivalence classes of
816 insns (see field `insn_equiv_class_num' in
817 `insn_reserv_decl'). */
818 int insn_equiv_classes_num
;
819 /* The following field value is number of states of final DFA. */
820 int achieved_states_num
;
821 /* The following field value is the order number (0, 1, ...) of
823 int automaton_order_num
;
824 /* The following fields contain statistics information about
825 building automaton. */
826 int NDFA_states_num
, DFA_states_num
;
827 /* The following field value is defined only if minimization of DFA
829 int minimal_DFA_states_num
;
830 int NDFA_arcs_num
, DFA_arcs_num
;
831 /* The following field value is defined only if minimization of DFA
833 int minimal_DFA_arcs_num
;
834 /* The following member refers for two table state x ainsn -> int.
835 ??? Above sentence is incomprehensible. */
836 state_ainsn_table_t trans_table
;
837 /* The following member value is maximal value of min issue delay
838 for insns of the automaton. */
840 /* Usually min issue delay is small and we can place several (2, 4,
841 8) elements in one vector element. So the compression factor can
842 be 1 (no compression), 2, 4, 8. */
843 int min_issue_delay_table_compression_factor
;
844 /* Total number of locked states in this automaton. */
848 /* The following is the element of the list of automata. */
849 struct automata_list_el
851 /* The automaton itself. */
852 automaton_t automaton
;
853 /* The next automata set element. */
854 automata_list_el_t next_automata_list_el
;
857 /* The following structure describes a table state X ainsn -> int(>= 0). */
858 struct state_ainsn_table
860 /* Automaton to which given table belongs. */
861 automaton_t automaton
;
862 /* The following tree vectors for comb vector implementation of the
864 vla_hwint_t comb_vect
;
865 vla_hwint_t check_vect
;
866 vla_hwint_t base_vect
;
867 /* This is simple implementation of the table. */
868 vla_hwint_t full_vect
;
869 /* Minimal and maximal values of the previous vectors. */
870 int min_comb_vect_el_value
, max_comb_vect_el_value
;
871 int min_base_vect_el_value
, max_base_vect_el_value
;
874 /* Macros to access members of unions. Use only them for access to
875 union members of declarations and regexps. */
877 #if defined ENABLE_CHECKING && (GCC_VERSION >= 2007)
879 #define DECL_UNIT(d) __extension__ \
880 (({ __typeof (d) const _decl = (d); \
881 if (_decl->mode != dm_unit) \
882 decl_mode_check_failed (_decl->mode, "dm_unit", \
883 __FILE__, __LINE__, __FUNCTION__); \
884 &(_decl)->decl.unit; }))
886 #define DECL_BYPASS(d) __extension__ \
887 (({ __typeof (d) const _decl = (d); \
888 if (_decl->mode != dm_bypass) \
889 decl_mode_check_failed (_decl->mode, "dm_bypass", \
890 __FILE__, __LINE__, __FUNCTION__); \
891 &(_decl)->decl.bypass; }))
893 #define DECL_AUTOMATON(d) __extension__ \
894 (({ __typeof (d) const _decl = (d); \
895 if (_decl->mode != dm_automaton) \
896 decl_mode_check_failed (_decl->mode, "dm_automaton", \
897 __FILE__, __LINE__, __FUNCTION__); \
898 &(_decl)->decl.automaton; }))
900 #define DECL_EXCL(d) __extension__ \
901 (({ __typeof (d) const _decl = (d); \
902 if (_decl->mode != dm_excl) \
903 decl_mode_check_failed (_decl->mode, "dm_excl", \
904 __FILE__, __LINE__, __FUNCTION__); \
905 &(_decl)->decl.excl; }))
907 #define DECL_PRESENCE(d) __extension__ \
908 (({ __typeof (d) const _decl = (d); \
909 if (_decl->mode != dm_presence) \
910 decl_mode_check_failed (_decl->mode, "dm_presence", \
911 __FILE__, __LINE__, __FUNCTION__); \
912 &(_decl)->decl.presence; }))
914 #define DECL_ABSENCE(d) __extension__ \
915 (({ __typeof (d) const _decl = (d); \
916 if (_decl->mode != dm_absence) \
917 decl_mode_check_failed (_decl->mode, "dm_absence", \
918 __FILE__, __LINE__, __FUNCTION__); \
919 &(_decl)->decl.absence; }))
921 #define DECL_RESERV(d) __extension__ \
922 (({ __typeof (d) const _decl = (d); \
923 if (_decl->mode != dm_reserv) \
924 decl_mode_check_failed (_decl->mode, "dm_reserv", \
925 __FILE__, __LINE__, __FUNCTION__); \
926 &(_decl)->decl.reserv; }))
928 #define DECL_INSN_RESERV(d) __extension__ \
929 (({ __typeof (d) const _decl = (d); \
930 if (_decl->mode != dm_insn_reserv) \
931 decl_mode_check_failed (_decl->mode, "dm_insn_reserv", \
932 __FILE__, __LINE__, __FUNCTION__); \
933 &(_decl)->decl.insn_reserv; }))
935 static const char *decl_name (enum decl_mode
);
936 static void decl_mode_check_failed (enum decl_mode
, const char *,
937 const char *, int, const char *)
940 /* Return string representation of declaration mode MODE. */
942 decl_name (enum decl_mode mode
)
944 static char str
[100];
948 else if (mode
== dm_bypass
)
950 else if (mode
== dm_automaton
)
951 return "dm_automaton";
952 else if (mode
== dm_excl
)
954 else if (mode
== dm_presence
)
955 return "dm_presence";
956 else if (mode
== dm_absence
)
958 else if (mode
== dm_reserv
)
960 else if (mode
== dm_insn_reserv
)
961 return "dm_insn_reserv";
963 sprintf (str
, "unknown (%d)", (int) mode
);
967 /* The function prints message about unexpected declaration and finish
970 decl_mode_check_failed (enum decl_mode mode
, const char *expected_mode_str
,
971 const char *file
, int line
, const char *func
)
975 "\n%s: %d: error in %s: DECL check: expected decl %s, have %s\n",
976 file
, line
, func
, expected_mode_str
, decl_name (mode
));
981 #define REGEXP_UNIT(r) __extension__ \
982 (({ struct regexp *const _regexp = (r); \
983 if (_regexp->mode != rm_unit) \
984 regexp_mode_check_failed (_regexp->mode, "rm_unit", \
985 __FILE__, __LINE__, __FUNCTION__); \
986 &(_regexp)->regexp.unit; }))
988 #define REGEXP_RESERV(r) __extension__ \
989 (({ struct regexp *const _regexp = (r); \
990 if (_regexp->mode != rm_reserv) \
991 regexp_mode_check_failed (_regexp->mode, "rm_reserv", \
992 __FILE__, __LINE__, __FUNCTION__); \
993 &(_regexp)->regexp.reserv; }))
995 #define REGEXP_SEQUENCE(r) __extension__ \
996 (({ struct regexp *const _regexp = (r); \
997 if (_regexp->mode != rm_sequence) \
998 regexp_mode_check_failed (_regexp->mode, "rm_sequence", \
999 __FILE__, __LINE__, __FUNCTION__); \
1000 &(_regexp)->regexp.sequence; }))
1002 #define REGEXP_REPEAT(r) __extension__ \
1003 (({ struct regexp *const _regexp = (r); \
1004 if (_regexp->mode != rm_repeat) \
1005 regexp_mode_check_failed (_regexp->mode, "rm_repeat", \
1006 __FILE__, __LINE__, __FUNCTION__); \
1007 &(_regexp)->regexp.repeat; }))
1009 #define REGEXP_ALLOF(r) __extension__ \
1010 (({ struct regexp *const _regexp = (r); \
1011 if (_regexp->mode != rm_allof) \
1012 regexp_mode_check_failed (_regexp->mode, "rm_allof", \
1013 __FILE__, __LINE__, __FUNCTION__); \
1014 &(_regexp)->regexp.allof; }))
1016 #define REGEXP_ONEOF(r) __extension__ \
1017 (({ struct regexp *const _regexp = (r); \
1018 if (_regexp->mode != rm_oneof) \
1019 regexp_mode_check_failed (_regexp->mode, "rm_oneof", \
1020 __FILE__, __LINE__, __FUNCTION__); \
1021 &(_regexp)->regexp.oneof; }))
1023 static const char *regexp_name (enum regexp_mode
);
1024 static void regexp_mode_check_failed (enum regexp_mode
, const char *,
1026 const char *) ATTRIBUTE_NORETURN
;
1029 /* Return string representation of regexp mode MODE. */
1031 regexp_name (enum regexp_mode mode
)
1040 return "rm_nothing";
1042 return "rm_sequence";
1054 /* The function prints message about unexpected regexp and finish the
1057 regexp_mode_check_failed (enum regexp_mode mode
,
1058 const char *expected_mode_str
,
1059 const char *file
, int line
, const char *func
)
1063 "\n%s: %d: error in %s: REGEXP check: expected decl %s, have %s\n",
1064 file
, line
, func
, expected_mode_str
, regexp_name (mode
));
1068 #else /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */
1070 #define DECL_UNIT(d) (&(d)->decl.unit)
1071 #define DECL_BYPASS(d) (&(d)->decl.bypass)
1072 #define DECL_AUTOMATON(d) (&(d)->decl.automaton)
1073 #define DECL_EXCL(d) (&(d)->decl.excl)
1074 #define DECL_PRESENCE(d) (&(d)->decl.presence)
1075 #define DECL_ABSENCE(d) (&(d)->decl.absence)
1076 #define DECL_RESERV(d) (&(d)->decl.reserv)
1077 #define DECL_INSN_RESERV(d) (&(d)->decl.insn_reserv)
1079 #define REGEXP_UNIT(r) (&(r)->regexp.unit)
1080 #define REGEXP_RESERV(r) (&(r)->regexp.reserv)
1081 #define REGEXP_SEQUENCE(r) (&(r)->regexp.sequence)
1082 #define REGEXP_REPEAT(r) (&(r)->regexp.repeat)
1083 #define REGEXP_ALLOF(r) (&(r)->regexp.allof)
1084 #define REGEXP_ONEOF(r) (&(r)->regexp.oneof)
1086 #endif /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */
1088 /* Create IR structure (node). */
1090 create_node (size_t size
)
1094 obstack_blank (&irp
, size
);
1095 result
= obstack_base (&irp
);
1096 obstack_finish (&irp
);
1097 /* Default values of members are NULL and zero. */
1098 memset (result
, 0, size
);
1102 /* Copy IR structure (node). */
1104 copy_node (const void *from
, size_t size
)
1106 void *const result
= create_node (size
);
1107 memcpy (result
, from
, size
);
1111 /* The function checks that NAME does not contain quotes (`"'). */
1113 check_name (const char * name
, pos_t pos ATTRIBUTE_UNUSED
)
1117 for (str
= name
; *str
!= '\0'; str
++)
1119 error ("Name `%s' contains quotes", name
);
1123 /* Pointers to all declarations during IR generation are stored in the
1125 static VEC(decl_t
,heap
) *decls
;
1127 /* Given a pointer to a (char *) and a separator, return an alloc'ed
1128 string containing the next separated element, taking parentheses
1129 into account if PAR_FLAG has nonzero value. Advance the pointer to
1130 after the string scanned, or the end-of-string. Return NULL if at
1133 next_sep_el (const char **pstr
, int sep
, int par_flag
)
1140 /* Remove leading whitespaces. */
1141 while (ISSPACE ((int) **pstr
))
1148 for (pars_num
= 0, p
= *pstr
; *p
!= '\0'; p
++)
1150 if (par_flag
&& *p
== '(')
1152 else if (par_flag
&& *p
== ')')
1154 else if (pars_num
== 0 && *p
== sep
)
1156 if (pars_num
== 0 && ISSPACE ((int) *p
))
1160 for (; n_spaces
!= 0; n_spaces
--)
1161 obstack_1grow (&irp
, p
[-n_spaces
]);
1162 obstack_1grow (&irp
, *p
);
1165 obstack_1grow (&irp
, '\0');
1166 out_str
= obstack_base (&irp
);
1167 obstack_finish (&irp
);
1176 /* Given a string and a separator, return the number of separated
1177 elements in it, taking parentheses into account if PAR_FLAG has
1178 nonzero value. Return 0 for the null string, -1 if parentheses is
1181 n_sep_els (const char *s
, int sep
, int par_flag
)
1189 for (pars_num
= 0, n
= 1; *s
; s
++)
1190 if (par_flag
&& *s
== '(')
1192 else if (par_flag
&& *s
== ')')
1194 else if (pars_num
== 0 && *s
== sep
)
1197 return (pars_num
!= 0 ? -1 : n
);
1200 /* Given a string and a separator, return vector of strings which are
1201 elements in the string and number of elements through els_num.
1202 Take parentheses into account if PAREN_P has nonzero value. The
1203 function also inserts the end marker NULL at the end of vector.
1204 Return 0 for the null string, -1 if parentheses are not balanced. */
1206 get_str_vect (const char *str
, int *els_num
, int sep
, int paren_p
)
1213 *els_num
= n_sep_els (str
, sep
, paren_p
);
1216 obstack_blank (&irp
, sizeof (char *) * (*els_num
+ 1));
1217 vect
= (char **) obstack_base (&irp
);
1218 obstack_finish (&irp
);
1220 for (i
= 0; i
< *els_num
; i
++)
1221 vect
[i
] = next_sep_el (pstr
, sep
, paren_p
);
1222 trail
= next_sep_el (pstr
, sep
, paren_p
);
1223 gcc_assert (!trail
);
1228 /* Process a DEFINE_CPU_UNIT.
1230 This gives information about a unit contained in CPU. We fill a
1231 struct unit_decl with information used later by `expand_automata'. */
1233 gen_cpu_unit (rtx def
)
1236 char **str_cpu_units
;
1240 str_cpu_units
= get_str_vect (XSTR (def
, 0), &vect_length
, ',', FALSE
);
1241 if (str_cpu_units
== NULL
)
1242 fatal ("invalid string `%s' in define_cpu_unit", XSTR (def
, 0));
1243 for (i
= 0; i
< vect_length
; i
++)
1245 decl
= create_node (sizeof (struct decl
));
1246 decl
->mode
= dm_unit
;
1248 DECL_UNIT (decl
)->name
= check_name (str_cpu_units
[i
], decl
->pos
);
1249 DECL_UNIT (decl
)->automaton_name
= XSTR (def
, 1);
1250 DECL_UNIT (decl
)->query_p
= 0;
1251 DECL_UNIT (decl
)->min_occ_cycle_num
= -1;
1252 DECL_UNIT (decl
)->in_set_p
= 0;
1253 VEC_safe_push (decl_t
,heap
, decls
, decl
);
1257 /* Process a DEFINE_QUERY_CPU_UNIT.
1259 This gives information about a unit contained in CPU. We fill a
1260 struct unit_decl with information used later by `expand_automata'. */
1262 gen_query_cpu_unit (rtx def
)
1265 char **str_cpu_units
;
1269 str_cpu_units
= get_str_vect (XSTR (def
, 0), &vect_length
, ',',
1271 if (str_cpu_units
== NULL
)
1272 fatal ("invalid string `%s' in define_query_cpu_unit", XSTR (def
, 0));
1273 for (i
= 0; i
< vect_length
; i
++)
1275 decl
= create_node (sizeof (struct decl
));
1276 decl
->mode
= dm_unit
;
1278 DECL_UNIT (decl
)->name
= check_name (str_cpu_units
[i
], decl
->pos
);
1279 DECL_UNIT (decl
)->automaton_name
= XSTR (def
, 1);
1280 DECL_UNIT (decl
)->query_p
= 1;
1281 VEC_safe_push (decl_t
,heap
, decls
, decl
);
1285 /* Process a DEFINE_BYPASS.
1287 This gives information about a unit contained in the CPU. We fill
1288 in a struct bypass_decl with information used later by
1289 `expand_automata'. */
1291 gen_bypass (rtx def
)
1300 out_insns
= get_str_vect (XSTR (def
, 1), &out_length
, ',', FALSE
);
1301 if (out_insns
== NULL
)
1302 fatal ("invalid string `%s' in define_bypass", XSTR (def
, 1));
1303 in_insns
= get_str_vect (XSTR (def
, 2), &in_length
, ',', FALSE
);
1304 if (in_insns
== NULL
)
1305 fatal ("invalid string `%s' in define_bypass", XSTR (def
, 2));
1306 for (i
= 0; i
< out_length
; i
++)
1307 for (j
= 0; j
< in_length
; j
++)
1309 decl
= create_node (sizeof (struct decl
));
1310 decl
->mode
= dm_bypass
;
1312 DECL_BYPASS (decl
)->latency
= XINT (def
, 0);
1313 DECL_BYPASS (decl
)->out_insn_name
= out_insns
[i
];
1314 DECL_BYPASS (decl
)->in_insn_name
= in_insns
[j
];
1315 DECL_BYPASS (decl
)->bypass_guard_name
= XSTR (def
, 3);
1316 VEC_safe_push (decl_t
,heap
, decls
, decl
);
1320 /* Process an EXCLUSION_SET.
1322 This gives information about a cpu unit conflicts. We fill a
1323 struct excl_rel_decl (excl) with information used later by
1324 `expand_automata'. */
1326 gen_excl_set (rtx def
)
1329 char **first_str_cpu_units
;
1330 char **second_str_cpu_units
;
1331 int first_vect_length
;
1336 = get_str_vect (XSTR (def
, 0), &first_vect_length
, ',', FALSE
);
1337 if (first_str_cpu_units
== NULL
)
1338 fatal ("invalid first string `%s' in exclusion_set", XSTR (def
, 0));
1339 second_str_cpu_units
= get_str_vect (XSTR (def
, 1), &length
, ',',
1341 if (second_str_cpu_units
== NULL
)
1342 fatal ("invalid second string `%s' in exclusion_set", XSTR (def
, 1));
1343 length
+= first_vect_length
;
1344 decl
= create_node (sizeof (struct decl
) + (length
- 1) * sizeof (char *));
1345 decl
->mode
= dm_excl
;
1347 DECL_EXCL (decl
)->all_names_num
= length
;
1348 DECL_EXCL (decl
)->first_list_length
= first_vect_length
;
1349 for (i
= 0; i
< length
; i
++)
1350 if (i
< first_vect_length
)
1351 DECL_EXCL (decl
)->names
[i
] = first_str_cpu_units
[i
];
1353 DECL_EXCL (decl
)->names
[i
]
1354 = second_str_cpu_units
[i
- first_vect_length
];
1355 VEC_safe_push (decl_t
,heap
, decls
, decl
);
1358 /* Process a PRESENCE_SET, a FINAL_PRESENCE_SET, an ABSENCE_SET,
1359 FINAL_ABSENCE_SET (it is depended on PRESENCE_P and FINAL_P).
1361 This gives information about a cpu unit reservation requirements.
1362 We fill a struct unit_pattern_rel_decl with information used later
1363 by `expand_automata'. */
1365 gen_presence_absence_set (rtx def
, int presence_p
, int final_p
)
1368 char **str_cpu_units
;
1369 char **str_pattern_lists
;
1370 char ***str_patterns
;
1371 int cpu_units_length
;
1373 int patterns_length
;
1376 str_cpu_units
= get_str_vect (XSTR (def
, 0), &cpu_units_length
, ',',
1378 if (str_cpu_units
== NULL
)
1381 ? "invalid first string `%s' in final_presence_set"
1382 : "invalid first string `%s' in presence_set")
1384 ? "invalid first string `%s' in final_absence_set"
1385 : "invalid first string `%s' in absence_set")),
1387 str_pattern_lists
= get_str_vect (XSTR (def
, 1),
1388 &patterns_length
, ',', FALSE
);
1389 if (str_pattern_lists
== NULL
)
1392 ? "invalid second string `%s' in final_presence_set"
1393 : "invalid second string `%s' in presence_set")
1395 ? "invalid second string `%s' in final_absence_set"
1396 : "invalid second string `%s' in absence_set")), XSTR (def
, 1));
1397 str_patterns
= obstack_alloc (&irp
, patterns_length
* sizeof (char **));
1398 for (i
= 0; i
< patterns_length
; i
++)
1400 str_patterns
[i
] = get_str_vect (str_pattern_lists
[i
],
1401 &length
, ' ', FALSE
);
1402 gcc_assert (str_patterns
[i
]);
1404 decl
= create_node (sizeof (struct decl
));
1408 decl
->mode
= dm_presence
;
1409 DECL_PRESENCE (decl
)->names_num
= cpu_units_length
;
1410 DECL_PRESENCE (decl
)->names
= str_cpu_units
;
1411 DECL_PRESENCE (decl
)->patterns
= str_patterns
;
1412 DECL_PRESENCE (decl
)->patterns_num
= patterns_length
;
1413 DECL_PRESENCE (decl
)->final_p
= final_p
;
1417 decl
->mode
= dm_absence
;
1418 DECL_ABSENCE (decl
)->names_num
= cpu_units_length
;
1419 DECL_ABSENCE (decl
)->names
= str_cpu_units
;
1420 DECL_ABSENCE (decl
)->patterns
= str_patterns
;
1421 DECL_ABSENCE (decl
)->patterns_num
= patterns_length
;
1422 DECL_ABSENCE (decl
)->final_p
= final_p
;
1424 VEC_safe_push (decl_t
,heap
, decls
, decl
);
1427 /* Process a PRESENCE_SET.
1429 This gives information about a cpu unit reservation requirements.
1430 We fill a struct unit_pattern_rel_decl (presence) with information
1431 used later by `expand_automata'. */
1433 gen_presence_set (rtx def
)
1435 gen_presence_absence_set (def
, TRUE
, FALSE
);
1438 /* Process a FINAL_PRESENCE_SET.
1440 This gives information about a cpu unit reservation requirements.
1441 We fill a struct unit_pattern_rel_decl (presence) with information
1442 used later by `expand_automata'. */
1444 gen_final_presence_set (rtx def
)
1446 gen_presence_absence_set (def
, TRUE
, TRUE
);
1449 /* Process an ABSENCE_SET.
1451 This gives information about a cpu unit reservation requirements.
1452 We fill a struct unit_pattern_rel_decl (absence) with information
1453 used later by `expand_automata'. */
1455 gen_absence_set (rtx def
)
1457 gen_presence_absence_set (def
, FALSE
, FALSE
);
1460 /* Process a FINAL_ABSENCE_SET.
1462 This gives information about a cpu unit reservation requirements.
1463 We fill a struct unit_pattern_rel_decl (absence) with information
1464 used later by `expand_automata'. */
1466 gen_final_absence_set (rtx def
)
1468 gen_presence_absence_set (def
, FALSE
, TRUE
);
1471 /* Process a DEFINE_AUTOMATON.
1473 This gives information about a finite state automaton used for
1474 recognizing pipeline hazards. We fill a struct automaton_decl
1475 with information used later by `expand_automata'. */
1477 gen_automaton (rtx def
)
1480 char **str_automata
;
1484 str_automata
= get_str_vect (XSTR (def
, 0), &vect_length
, ',', FALSE
);
1485 if (str_automata
== NULL
)
1486 fatal ("invalid string `%s' in define_automaton", XSTR (def
, 0));
1487 for (i
= 0; i
< vect_length
; i
++)
1489 decl
= create_node (sizeof (struct decl
));
1490 decl
->mode
= dm_automaton
;
1492 DECL_AUTOMATON (decl
)->name
= check_name (str_automata
[i
], decl
->pos
);
1493 VEC_safe_push (decl_t
,heap
, decls
, decl
);
1497 /* Process an AUTOMATA_OPTION.
1499 This gives information how to generate finite state automaton used
1500 for recognizing pipeline hazards. */
1502 gen_automata_option (rtx def
)
1504 if (strcmp (XSTR (def
, 0), NO_MINIMIZATION_OPTION
+ 1) == 0)
1505 no_minimization_flag
= 1;
1506 else if (strcmp (XSTR (def
, 0), TIME_OPTION
+ 1) == 0)
1508 else if (strcmp (XSTR (def
, 0), STATS_OPTION
+ 1) == 0)
1510 else if (strcmp (XSTR (def
, 0), V_OPTION
+ 1) == 0)
1512 else if (strcmp (XSTR (def
, 0), W_OPTION
+ 1) == 0)
1514 else if (strcmp (XSTR (def
, 0), NDFA_OPTION
+ 1) == 0)
1516 else if (strcmp (XSTR (def
, 0), PROGRESS_OPTION
+ 1) == 0)
1519 fatal ("invalid option `%s' in automata_option", XSTR (def
, 0));
1522 /* Name in reservation to denote absence reservation. */
1523 #define NOTHING_NAME "nothing"
1525 /* The following string contains original reservation string being
1527 static const char *reserv_str
;
1529 /* Parse an element in STR. */
1531 gen_regexp_el (const char *str
)
1540 if (str
[len
- 1] != ')')
1541 fatal ("garbage after ) in reservation `%s'", reserv_str
);
1542 dstr
= alloca (len
- 1);
1543 memcpy (dstr
, str
+ 1, len
- 2);
1544 dstr
[len
-2] = '\0';
1545 regexp
= gen_regexp_sequence (dstr
);
1547 else if (strcmp (str
, NOTHING_NAME
) == 0)
1549 regexp
= create_node (sizeof *regexp
);
1550 regexp
->mode
= rm_nothing
;
1554 regexp
= create_node (sizeof *regexp
);
1555 regexp
->mode
= rm_unit
;
1556 REGEXP_UNIT (regexp
)->name
= str
;
1561 /* Parse construction `repeat' in STR. */
1563 gen_regexp_repeat (const char *str
)
1571 repeat_vect
= get_str_vect (str
, &els_num
, '*', TRUE
);
1572 if (repeat_vect
== NULL
)
1573 fatal ("invalid `%s' in reservation `%s'", str
, reserv_str
);
1576 regexp
= gen_regexp_el (repeat_vect
[0]);
1577 for (i
= 1; i
< els_num
; i
++)
1579 repeat
= create_node (sizeof (struct regexp
));
1580 repeat
->mode
= rm_repeat
;
1581 REGEXP_REPEAT (repeat
)->regexp
= regexp
;
1582 REGEXP_REPEAT (repeat
)->repeat_num
= atoi (repeat_vect
[i
]);
1583 if (REGEXP_REPEAT (repeat
)->repeat_num
<= 1)
1584 fatal ("repetition `%s' <= 1 in reservation `%s'",
1591 return gen_regexp_el (str
);
1594 /* Parse reservation STR which possibly contains separator '+'. */
1596 gen_regexp_allof (const char *str
)
1603 allof_vect
= get_str_vect (str
, &els_num
, '+', TRUE
);
1604 if (allof_vect
== NULL
)
1605 fatal ("invalid `%s' in reservation `%s'", str
, reserv_str
);
1608 allof
= create_node (sizeof (struct regexp
)
1609 + sizeof (regexp_t
) * (els_num
- 1));
1610 allof
->mode
= rm_allof
;
1611 REGEXP_ALLOF (allof
)->regexps_num
= els_num
;
1612 for (i
= 0; i
< els_num
; i
++)
1613 REGEXP_ALLOF (allof
)->regexps
[i
] = gen_regexp_repeat (allof_vect
[i
]);
1617 return gen_regexp_repeat (str
);
1620 /* Parse reservation STR which possibly contains separator '|'. */
1622 gen_regexp_oneof (const char *str
)
1629 oneof_vect
= get_str_vect (str
, &els_num
, '|', TRUE
);
1630 if (oneof_vect
== NULL
)
1631 fatal ("invalid `%s' in reservation `%s'", str
, reserv_str
);
1634 oneof
= create_node (sizeof (struct regexp
)
1635 + sizeof (regexp_t
) * (els_num
- 1));
1636 oneof
->mode
= rm_oneof
;
1637 REGEXP_ONEOF (oneof
)->regexps_num
= els_num
;
1638 for (i
= 0; i
< els_num
; i
++)
1639 REGEXP_ONEOF (oneof
)->regexps
[i
] = gen_regexp_allof (oneof_vect
[i
]);
1643 return gen_regexp_allof (str
);
1646 /* Parse reservation STR which possibly contains separator ','. */
1648 gen_regexp_sequence (const char *str
)
1651 char **sequence_vect
;
1655 sequence_vect
= get_str_vect (str
, &els_num
, ',', TRUE
);
1658 sequence
= create_node (sizeof (struct regexp
)
1659 + sizeof (regexp_t
) * (els_num
- 1));
1660 sequence
->mode
= rm_sequence
;
1661 REGEXP_SEQUENCE (sequence
)->regexps_num
= els_num
;
1662 for (i
= 0; i
< els_num
; i
++)
1663 REGEXP_SEQUENCE (sequence
)->regexps
[i
]
1664 = gen_regexp_oneof (sequence_vect
[i
]);
1668 return gen_regexp_oneof (str
);
1671 /* Parse construction reservation STR. */
1673 gen_regexp (const char *str
)
1676 return gen_regexp_sequence (str
);;
1679 /* Process a DEFINE_RESERVATION.
1681 This gives information about a reservation of cpu units. We fill
1682 in a struct reserv_decl with information used later by
1683 `expand_automata'. */
1685 gen_reserv (rtx def
)
1689 decl
= create_node (sizeof (struct decl
));
1690 decl
->mode
= dm_reserv
;
1692 DECL_RESERV (decl
)->name
= check_name (XSTR (def
, 0), decl
->pos
);
1693 DECL_RESERV (decl
)->regexp
= gen_regexp (XSTR (def
, 1));
1694 VEC_safe_push (decl_t
,heap
, decls
, decl
);
1697 /* Process a DEFINE_INSN_RESERVATION.
1699 This gives information about the reservation of cpu units by an
1700 insn. We fill a struct insn_reserv_decl with information used
1701 later by `expand_automata'. */
1703 gen_insn_reserv (rtx def
)
1707 decl
= create_node (sizeof (struct decl
));
1708 decl
->mode
= dm_insn_reserv
;
1710 DECL_INSN_RESERV (decl
)->name
1711 = check_name (XSTR (def
, 0), decl
->pos
);
1712 DECL_INSN_RESERV (decl
)->default_latency
= XINT (def
, 1);
1713 DECL_INSN_RESERV (decl
)->condexp
= XEXP (def
, 2);
1714 DECL_INSN_RESERV (decl
)->regexp
= gen_regexp (XSTR (def
, 3));
1715 VEC_safe_push (decl_t
,heap
, decls
, decl
);
1720 /* The function evaluates hash value (0..UINT_MAX) of string. */
1722 string_hash (const char *string
)
1726 for (result
= i
= 0;*string
++ != '\0'; i
++)
1727 result
+= ((unsigned char) *string
<< (i
% CHAR_BIT
));
1733 /* This page contains abstract data `table of automaton declarations'.
1734 Elements of the table is nodes representing automaton declarations.
1735 Key of the table elements is name of given automaton. Remember
1736 that automaton names have own space. */
1738 /* The function evaluates hash value of an automaton declaration. The
1739 function is used by abstract data `hashtab'. The function returns
1740 hash value (0..UINT_MAX) of given automaton declaration. */
1742 automaton_decl_hash (const void *automaton_decl
)
1744 const_decl_t
const decl
= (const_decl_t
) automaton_decl
;
1746 gcc_assert (decl
->mode
!= dm_automaton
1747 || DECL_AUTOMATON (decl
)->name
);
1748 return string_hash (DECL_AUTOMATON (decl
)->name
);
1751 /* The function tests automaton declarations on equality of their
1752 keys. The function is used by abstract data `hashtab'. The
1753 function returns 1 if the declarations have the same key, 0
1756 automaton_decl_eq_p (const void* automaton_decl_1
,
1757 const void* automaton_decl_2
)
1759 const_decl_t
const decl1
= (const_decl_t
) automaton_decl_1
;
1760 const_decl_t
const decl2
= (const_decl_t
) automaton_decl_2
;
1762 gcc_assert (decl1
->mode
== dm_automaton
1763 && DECL_AUTOMATON (decl1
)->name
1764 && decl2
->mode
== dm_automaton
1765 && DECL_AUTOMATON (decl2
)->name
);
1766 return strcmp (DECL_AUTOMATON (decl1
)->name
,
1767 DECL_AUTOMATON (decl2
)->name
) == 0;
1770 /* The automaton declaration table itself is represented by the
1771 following variable. */
1772 static htab_t automaton_decl_table
;
1774 /* The function inserts automaton declaration into the table. The
1775 function does nothing if an automaton declaration with the same key
1776 exists already in the table. The function returns automaton
1777 declaration node in the table with the same key as given automaton
1778 declaration node. */
1780 insert_automaton_decl (decl_t automaton_decl
)
1784 entry_ptr
= htab_find_slot (automaton_decl_table
, automaton_decl
, 1);
1785 if (*entry_ptr
== NULL
)
1786 *entry_ptr
= (void *) automaton_decl
;
1787 return (decl_t
) *entry_ptr
;
1790 /* The following variable value is node representing automaton
1791 declaration. The node used for searching automaton declaration
1793 static struct decl work_automaton_decl
;
1795 /* The function searches for automaton declaration in the table with
1796 the same key as node representing name of the automaton
1797 declaration. The function returns node found in the table, NULL if
1798 such node does not exist in the table. */
1800 find_automaton_decl (const char *name
)
1804 work_automaton_decl
.mode
= dm_automaton
;
1805 DECL_AUTOMATON (&work_automaton_decl
)->name
= name
;
1806 entry
= htab_find (automaton_decl_table
, &work_automaton_decl
);
1807 return (decl_t
) entry
;
1810 /* The function creates empty automaton declaration table and node
1811 representing automaton declaration and used for searching automaton
1812 declaration with given name. The function must be called only once
1813 before any work with the automaton declaration table. */
1815 initiate_automaton_decl_table (void)
1817 work_automaton_decl
.mode
= dm_automaton
;
1818 automaton_decl_table
= htab_create (10, automaton_decl_hash
,
1819 automaton_decl_eq_p
, (htab_del
) 0);
1822 /* The function deletes the automaton declaration table. Only call of
1823 function `initiate_automaton_decl_table' is possible immediately
1824 after this function call. */
1826 finish_automaton_decl_table (void)
1828 htab_delete (automaton_decl_table
);
1833 /* This page contains abstract data `table of insn declarations'.
1834 Elements of the table is nodes representing insn declarations. Key
1835 of the table elements is name of given insn (in corresponding
1836 define_insn_reservation). Remember that insn names have own
1839 /* The function evaluates hash value of an insn declaration. The
1840 function is used by abstract data `hashtab'. The function returns
1841 hash value (0..UINT_MAX) of given insn declaration. */
1843 insn_decl_hash (const void *insn_decl
)
1845 const_decl_t
const decl
= (const_decl_t
) insn_decl
;
1847 gcc_assert (decl
->mode
== dm_insn_reserv
1848 && DECL_INSN_RESERV (decl
)->name
);
1849 return string_hash (DECL_INSN_RESERV (decl
)->name
);
1852 /* The function tests insn declarations on equality of their keys.
1853 The function is used by abstract data `hashtab'. The function
1854 returns 1 if declarations have the same key, 0 otherwise. */
1856 insn_decl_eq_p (const void *insn_decl_1
, const void *insn_decl_2
)
1858 const_decl_t
const decl1
= (const_decl_t
) insn_decl_1
;
1859 const_decl_t
const decl2
= (const_decl_t
) insn_decl_2
;
1861 gcc_assert (decl1
->mode
== dm_insn_reserv
1862 && DECL_INSN_RESERV (decl1
)->name
1863 && decl2
->mode
== dm_insn_reserv
1864 && DECL_INSN_RESERV (decl2
)->name
);
1865 return strcmp (DECL_INSN_RESERV (decl1
)->name
,
1866 DECL_INSN_RESERV (decl2
)->name
) == 0;
1869 /* The insn declaration table itself is represented by the following
1870 variable. The table does not contain insn reservation
1872 static htab_t insn_decl_table
;
1874 /* The function inserts insn declaration into the table. The function
1875 does nothing if an insn declaration with the same key exists
1876 already in the table. The function returns insn declaration node
1877 in the table with the same key as given insn declaration node. */
1879 insert_insn_decl (decl_t insn_decl
)
1883 entry_ptr
= htab_find_slot (insn_decl_table
, insn_decl
, 1);
1884 if (*entry_ptr
== NULL
)
1885 *entry_ptr
= (void *) insn_decl
;
1886 return (decl_t
) *entry_ptr
;
1889 /* The following variable value is node representing insn reservation
1890 declaration. The node used for searching insn reservation
1891 declaration with given name. */
1892 static struct decl work_insn_decl
;
1894 /* The function searches for insn reservation declaration in the table
1895 with the same key as node representing name of the insn reservation
1896 declaration. The function returns node found in the table, NULL if
1897 such node does not exist in the table. */
1899 find_insn_decl (const char *name
)
1903 work_insn_decl
.mode
= dm_insn_reserv
;
1904 DECL_INSN_RESERV (&work_insn_decl
)->name
= name
;
1905 entry
= htab_find (insn_decl_table
, &work_insn_decl
);
1906 return (decl_t
) entry
;
1909 /* The function creates empty insn declaration table and node
1910 representing insn declaration and used for searching insn
1911 declaration with given name. The function must be called only once
1912 before any work with the insn declaration table. */
1914 initiate_insn_decl_table (void)
1916 work_insn_decl
.mode
= dm_insn_reserv
;
1917 insn_decl_table
= htab_create (10, insn_decl_hash
, insn_decl_eq_p
,
1921 /* The function deletes the insn declaration table. Only call of
1922 function `initiate_insn_decl_table' is possible immediately after
1923 this function call. */
1925 finish_insn_decl_table (void)
1927 htab_delete (insn_decl_table
);
1932 /* This page contains abstract data `table of declarations'. Elements
1933 of the table is nodes representing declarations (of units and
1934 reservations). Key of the table elements is names of given
1937 /* The function evaluates hash value of a declaration. The function
1938 is used by abstract data `hashtab'. The function returns hash
1939 value (0..UINT_MAX) of given declaration. */
1941 decl_hash (const void *decl
)
1943 const_decl_t
const d
= (const_decl_t
) decl
;
1945 gcc_assert ((d
->mode
== dm_unit
&& DECL_UNIT (d
)->name
)
1946 || (d
->mode
== dm_reserv
&& DECL_RESERV (d
)->name
));
1947 return string_hash (d
->mode
== dm_unit
1948 ? DECL_UNIT (d
)->name
: DECL_RESERV (d
)->name
);
1951 /* The function tests declarations on equality of their keys. The
1952 function is used by abstract data 'hashtab'. The function
1953 returns 1 if the declarations have the same key, 0 otherwise. */
1955 decl_eq_p (const void *decl_1
, const void *decl_2
)
1957 const_decl_t
const d1
= (const_decl_t
) decl_1
;
1958 const_decl_t
const d2
= (const_decl_t
) decl_2
;
1960 gcc_assert ((d1
->mode
== dm_unit
&& DECL_UNIT (d1
)->name
)
1961 || (d1
->mode
== dm_reserv
&& DECL_RESERV (d1
)->name
));
1962 gcc_assert ((d2
->mode
== dm_unit
&& DECL_UNIT (d2
)->name
)
1963 || (d2
->mode
== dm_reserv
&& DECL_RESERV (d2
)->name
));
1964 return strcmp ((d1
->mode
== dm_unit
1965 ? DECL_UNIT (d1
)->name
: DECL_RESERV (d1
)->name
),
1966 (d2
->mode
== dm_unit
1967 ? DECL_UNIT (d2
)->name
: DECL_RESERV (d2
)->name
)) == 0;
1970 /* The declaration table itself is represented by the following
1972 static htab_t decl_table
;
1974 /* The function inserts declaration into the table. The function does
1975 nothing if a declaration with the same key exists already in the
1976 table. The function returns declaration node in the table with the
1977 same key as given declaration node. */
1980 insert_decl (decl_t decl
)
1984 entry_ptr
= htab_find_slot (decl_table
, decl
, 1);
1985 if (*entry_ptr
== NULL
)
1986 *entry_ptr
= (void *) decl
;
1987 return (decl_t
) *entry_ptr
;
1990 /* The following variable value is node representing declaration. The
1991 node used for searching declaration with given name. */
1992 static struct decl work_decl
;
1994 /* The function searches for declaration in the table with the same
1995 key as node representing name of the declaration. The function
1996 returns node found in the table, NULL if such node does not exist
1999 find_decl (const char *name
)
2003 work_decl
.mode
= dm_unit
;
2004 DECL_UNIT (&work_decl
)->name
= name
;
2005 entry
= htab_find (decl_table
, &work_decl
);
2006 return (decl_t
) entry
;
2009 /* The function creates empty declaration table and node representing
2010 declaration and used for searching declaration with given name.
2011 The function must be called only once before any work with the
2012 declaration table. */
2014 initiate_decl_table (void)
2016 work_decl
.mode
= dm_unit
;
2017 decl_table
= htab_create (10, decl_hash
, decl_eq_p
, (htab_del
) 0);
2020 /* The function deletes the declaration table. Only call of function
2021 `initiate_declaration_table' is possible immediately after this
2024 finish_decl_table (void)
2026 htab_delete (decl_table
);
2031 /* This page contains checker of pipeline hazard description. */
2033 /* Checking NAMES in an exclusion clause vector and returning formed
2034 unit_set_el_list. */
2035 static unit_set_el_t
2036 process_excls (char **names
, int num
, pos_t excl_pos ATTRIBUTE_UNUSED
)
2038 unit_set_el_t el_list
;
2039 unit_set_el_t last_el
;
2040 unit_set_el_t new_el
;
2041 decl_t decl_in_table
;
2046 for (i
= 0; i
< num
; i
++)
2048 decl_in_table
= find_decl (names
[i
]);
2049 if (decl_in_table
== NULL
)
2050 error ("unit `%s' in exclusion is not declared", names
[i
]);
2051 else if (decl_in_table
->mode
!= dm_unit
)
2052 error ("`%s' in exclusion is not unit", names
[i
]);
2055 new_el
= create_node (sizeof (struct unit_set_el
));
2056 new_el
->unit_decl
= DECL_UNIT (decl_in_table
);
2057 new_el
->next_unit_set_el
= NULL
;
2058 if (last_el
== NULL
)
2059 el_list
= last_el
= new_el
;
2062 last_el
->next_unit_set_el
= new_el
;
2063 last_el
= last_el
->next_unit_set_el
;
2070 /* The function adds each element from SOURCE_LIST to the exclusion
2071 list of the each element from DEST_LIST. Checking situation "unit
2072 excludes itself". */
2074 add_excls (unit_set_el_t dest_list
, unit_set_el_t source_list
,
2075 pos_t excl_pos ATTRIBUTE_UNUSED
)
2079 unit_set_el_t curr_el
;
2080 unit_set_el_t prev_el
;
2083 for (dst
= dest_list
; dst
!= NULL
; dst
= dst
->next_unit_set_el
)
2084 for (src
= source_list
; src
!= NULL
; src
= src
->next_unit_set_el
)
2086 if (dst
->unit_decl
== src
->unit_decl
)
2088 error ("unit `%s' excludes itself", src
->unit_decl
->name
);
2091 if (dst
->unit_decl
->automaton_name
!= NULL
2092 && src
->unit_decl
->automaton_name
!= NULL
2093 && strcmp (dst
->unit_decl
->automaton_name
,
2094 src
->unit_decl
->automaton_name
) != 0)
2096 error ("units `%s' and `%s' in exclusion set belong to different automata",
2097 src
->unit_decl
->name
, dst
->unit_decl
->name
);
2100 for (curr_el
= dst
->unit_decl
->excl_list
, prev_el
= NULL
;
2102 prev_el
= curr_el
, curr_el
= curr_el
->next_unit_set_el
)
2103 if (curr_el
->unit_decl
== src
->unit_decl
)
2105 if (curr_el
== NULL
)
2107 /* Element not found - insert. */
2108 copy
= copy_node (src
, sizeof (*src
));
2109 copy
->next_unit_set_el
= NULL
;
2110 if (prev_el
== NULL
)
2111 dst
->unit_decl
->excl_list
= copy
;
2113 prev_el
->next_unit_set_el
= copy
;
2118 /* Checking NAMES in presence/absence clause and returning the
2119 formed unit_set_el_list. The function is called only after
2120 processing all exclusion sets. */
2121 static unit_set_el_t
2122 process_presence_absence_names (char **names
, int num
,
2123 pos_t req_pos ATTRIBUTE_UNUSED
,
2124 int presence_p
, int final_p
)
2126 unit_set_el_t el_list
;
2127 unit_set_el_t last_el
;
2128 unit_set_el_t new_el
;
2129 decl_t decl_in_table
;
2134 for (i
= 0; i
< num
; i
++)
2136 decl_in_table
= find_decl (names
[i
]);
2137 if (decl_in_table
== NULL
)
2140 ? "unit `%s' in final presence set is not declared"
2141 : "unit `%s' in presence set is not declared")
2143 ? "unit `%s' in final absence set is not declared"
2144 : "unit `%s' in absence set is not declared")), names
[i
]);
2145 else if (decl_in_table
->mode
!= dm_unit
)
2148 ? "`%s' in final presence set is not unit"
2149 : "`%s' in presence set is not unit")
2151 ? "`%s' in final absence set is not unit"
2152 : "`%s' in absence set is not unit")), names
[i
]);
2155 new_el
= create_node (sizeof (struct unit_set_el
));
2156 new_el
->unit_decl
= DECL_UNIT (decl_in_table
);
2157 new_el
->next_unit_set_el
= NULL
;
2158 if (last_el
== NULL
)
2159 el_list
= last_el
= new_el
;
2162 last_el
->next_unit_set_el
= new_el
;
2163 last_el
= last_el
->next_unit_set_el
;
2170 /* Checking NAMES in patterns of a presence/absence clause and
2171 returning the formed pattern_set_el_list. The function is called
2172 only after processing all exclusion sets. */
2173 static pattern_set_el_t
2174 process_presence_absence_patterns (char ***patterns
, int num
,
2175 pos_t req_pos ATTRIBUTE_UNUSED
,
2176 int presence_p
, int final_p
)
2178 pattern_set_el_t el_list
;
2179 pattern_set_el_t last_el
;
2180 pattern_set_el_t new_el
;
2181 decl_t decl_in_table
;
2186 for (i
= 0; i
< num
; i
++)
2188 for (j
= 0; patterns
[i
] [j
] != NULL
; j
++)
2190 new_el
= create_node (sizeof (struct pattern_set_el
)
2191 + sizeof (struct unit_decl
*) * j
);
2193 = (struct unit_decl
**) ((char *) new_el
2194 + sizeof (struct pattern_set_el
));
2195 new_el
->next_pattern_set_el
= NULL
;
2196 if (last_el
== NULL
)
2197 el_list
= last_el
= new_el
;
2200 last_el
->next_pattern_set_el
= new_el
;
2201 last_el
= last_el
->next_pattern_set_el
;
2203 new_el
->units_num
= 0;
2204 for (j
= 0; patterns
[i
] [j
] != NULL
; j
++)
2206 decl_in_table
= find_decl (patterns
[i
] [j
]);
2207 if (decl_in_table
== NULL
)
2210 ? "unit `%s' in final presence set is not declared"
2211 : "unit `%s' in presence set is not declared")
2213 ? "unit `%s' in final absence set is not declared"
2214 : "unit `%s' in absence set is not declared")),
2216 else if (decl_in_table
->mode
!= dm_unit
)
2219 ? "`%s' in final presence set is not unit"
2220 : "`%s' in presence set is not unit")
2222 ? "`%s' in final absence set is not unit"
2223 : "`%s' in absence set is not unit")),
2227 new_el
->unit_decls
[new_el
->units_num
]
2228 = DECL_UNIT (decl_in_table
);
2229 new_el
->units_num
++;
2236 /* The function adds each element from PATTERN_LIST to presence (if
2237 PRESENCE_P) or absence list of the each element from DEST_LIST.
2238 Checking situations "unit requires own absence", and "unit excludes
2239 and requires presence of ...", "unit requires absence and presence
2240 of ...", "units in (final) presence set belong to different
2241 automata", and "units in (final) absence set belong to different
2242 automata". Remember that we process absence sets only after all
2245 add_presence_absence (unit_set_el_t dest_list
,
2246 pattern_set_el_t pattern_list
,
2247 pos_t req_pos ATTRIBUTE_UNUSED
,
2248 int presence_p
, int final_p
)
2251 pattern_set_el_t pat
;
2252 struct unit_decl
*unit
;
2253 unit_set_el_t curr_excl_el
;
2254 pattern_set_el_t curr_pat_el
;
2255 pattern_set_el_t prev_el
;
2256 pattern_set_el_t copy
;
2260 for (dst
= dest_list
; dst
!= NULL
; dst
= dst
->next_unit_set_el
)
2261 for (pat
= pattern_list
; pat
!= NULL
; pat
= pat
->next_pattern_set_el
)
2263 for (i
= 0; i
< pat
->units_num
; i
++)
2265 unit
= pat
->unit_decls
[i
];
2266 if (dst
->unit_decl
== unit
&& pat
->units_num
== 1 && !presence_p
)
2268 error ("unit `%s' requires own absence", unit
->name
);
2271 if (dst
->unit_decl
->automaton_name
!= NULL
2272 && unit
->automaton_name
!= NULL
2273 && strcmp (dst
->unit_decl
->automaton_name
,
2274 unit
->automaton_name
) != 0)
2278 ? "units `%s' and `%s' in final presence set belong to different automata"
2279 : "units `%s' and `%s' in presence set belong to different automata")
2281 ? "units `%s' and `%s' in final absence set belong to different automata"
2282 : "units `%s' and `%s' in absence set belong to different automata")),
2283 unit
->name
, dst
->unit_decl
->name
);
2288 for (curr_excl_el
= dst
->unit_decl
->excl_list
;
2289 curr_excl_el
!= NULL
;
2290 curr_excl_el
= curr_excl_el
->next_unit_set_el
)
2292 if (unit
== curr_excl_el
->unit_decl
&& pat
->units_num
== 1)
2296 error ("unit `%s' excludes and requires presence of `%s'",
2297 dst
->unit_decl
->name
, unit
->name
);
2302 (0, "unit `%s' excludes and requires presence of `%s'",
2303 dst
->unit_decl
->name
, unit
->name
);
2306 else if (pat
->units_num
== 1)
2307 for (curr_pat_el
= dst
->unit_decl
->presence_list
;
2308 curr_pat_el
!= NULL
;
2309 curr_pat_el
= curr_pat_el
->next_pattern_set_el
)
2310 if (curr_pat_el
->units_num
== 1
2311 && unit
== curr_pat_el
->unit_decls
[0])
2316 ("unit `%s' requires absence and presence of `%s'",
2317 dst
->unit_decl
->name
, unit
->name
);
2322 (0, "unit `%s' requires absence and presence of `%s'",
2323 dst
->unit_decl
->name
, unit
->name
);
2327 for (prev_el
= (presence_p
2329 ? dst
->unit_decl
->final_presence_list
2330 : dst
->unit_decl
->final_presence_list
)
2332 ? dst
->unit_decl
->final_absence_list
2333 : dst
->unit_decl
->absence_list
));
2334 prev_el
!= NULL
&& prev_el
->next_pattern_set_el
!= NULL
;
2335 prev_el
= prev_el
->next_pattern_set_el
)
2337 copy
= copy_node (pat
, sizeof (*pat
));
2338 copy
->next_pattern_set_el
= NULL
;
2339 if (prev_el
== NULL
)
2344 dst
->unit_decl
->final_presence_list
= copy
;
2346 dst
->unit_decl
->presence_list
= copy
;
2349 dst
->unit_decl
->final_absence_list
= copy
;
2351 dst
->unit_decl
->absence_list
= copy
;
2354 prev_el
->next_pattern_set_el
= copy
;
2361 /* The function searches for bypass with given IN_INSN_RESERV in given
2363 static struct bypass_decl
*
2364 find_bypass (struct bypass_decl
*bypass_list
,
2365 struct insn_reserv_decl
*in_insn_reserv
)
2367 struct bypass_decl
*bypass
;
2369 for (bypass
= bypass_list
; bypass
!= NULL
; bypass
= bypass
->next
)
2370 if (bypass
->in_insn_reserv
== in_insn_reserv
)
2375 /* The function processes pipeline description declarations, checks
2376 their correctness, and forms exclusion/presence/absence sets. */
2378 process_decls (void)
2381 decl_t automaton_decl
;
2382 decl_t decl_in_table
;
2383 decl_t out_insn_reserv
;
2384 decl_t in_insn_reserv
;
2385 struct bypass_decl
*bypass
;
2386 int automaton_presence
;
2389 /* Checking repeated automata declarations. */
2390 automaton_presence
= 0;
2391 for (i
= 0; i
< description
->decls_num
; i
++)
2393 decl
= description
->decls
[i
];
2394 if (decl
->mode
== dm_automaton
)
2396 automaton_presence
= 1;
2397 decl_in_table
= insert_automaton_decl (decl
);
2398 if (decl_in_table
!= decl
)
2401 error ("repeated declaration of automaton `%s'",
2402 DECL_AUTOMATON (decl
)->name
);
2404 warning (0, "repeated declaration of automaton `%s'",
2405 DECL_AUTOMATON (decl
)->name
);
2409 /* Checking undeclared automata, repeated declarations (except for
2410 automata) and correctness of their attributes (insn latency times
2412 for (i
= 0; i
< description
->decls_num
; i
++)
2414 decl
= description
->decls
[i
];
2415 if (decl
->mode
== dm_insn_reserv
)
2417 if (DECL_INSN_RESERV (decl
)->default_latency
< 0)
2418 error ("define_insn_reservation `%s' has negative latency time",
2419 DECL_INSN_RESERV (decl
)->name
);
2420 DECL_INSN_RESERV (decl
)->insn_num
= description
->insns_num
;
2421 description
->insns_num
++;
2422 decl_in_table
= insert_insn_decl (decl
);
2423 if (decl_in_table
!= decl
)
2424 error ("`%s' is already used as insn reservation name",
2425 DECL_INSN_RESERV (decl
)->name
);
2427 else if (decl
->mode
== dm_bypass
)
2429 if (DECL_BYPASS (decl
)->latency
< 0)
2430 error ("define_bypass `%s - %s' has negative latency time",
2431 DECL_BYPASS (decl
)->out_insn_name
,
2432 DECL_BYPASS (decl
)->in_insn_name
);
2434 else if (decl
->mode
== dm_unit
|| decl
->mode
== dm_reserv
)
2436 if (decl
->mode
== dm_unit
)
2438 DECL_UNIT (decl
)->automaton_decl
= NULL
;
2439 if (DECL_UNIT (decl
)->automaton_name
!= NULL
)
2442 = find_automaton_decl (DECL_UNIT (decl
)->automaton_name
);
2443 if (automaton_decl
== NULL
)
2444 error ("automaton `%s' is not declared",
2445 DECL_UNIT (decl
)->automaton_name
);
2448 DECL_AUTOMATON (automaton_decl
)->automaton_is_used
= 1;
2449 DECL_UNIT (decl
)->automaton_decl
2450 = DECL_AUTOMATON (automaton_decl
);
2453 else if (automaton_presence
)
2454 error ("define_unit `%s' without automaton when one defined",
2455 DECL_UNIT (decl
)->name
);
2456 DECL_UNIT (decl
)->unit_num
= description
->units_num
;
2457 description
->units_num
++;
2458 if (strcmp (DECL_UNIT (decl
)->name
, NOTHING_NAME
) == 0)
2460 error ("`%s' is declared as cpu unit", NOTHING_NAME
);
2463 decl_in_table
= find_decl (DECL_UNIT (decl
)->name
);
2467 if (strcmp (DECL_RESERV (decl
)->name
, NOTHING_NAME
) == 0)
2469 error ("`%s' is declared as cpu reservation", NOTHING_NAME
);
2472 decl_in_table
= find_decl (DECL_RESERV (decl
)->name
);
2474 if (decl_in_table
== NULL
)
2475 decl_in_table
= insert_decl (decl
);
2478 if (decl
->mode
== dm_unit
)
2479 error ("repeated declaration of unit `%s'",
2480 DECL_UNIT (decl
)->name
);
2482 error ("repeated declaration of reservation `%s'",
2483 DECL_RESERV (decl
)->name
);
2487 /* Check bypasses and form list of bypasses for each (output)
2489 for (i
= 0; i
< description
->decls_num
; i
++)
2491 decl
= description
->decls
[i
];
2492 if (decl
->mode
== dm_bypass
)
2494 out_insn_reserv
= find_insn_decl (DECL_BYPASS (decl
)->out_insn_name
);
2495 in_insn_reserv
= find_insn_decl (DECL_BYPASS (decl
)->in_insn_name
);
2496 if (out_insn_reserv
== NULL
)
2497 error ("there is no insn reservation `%s'",
2498 DECL_BYPASS (decl
)->out_insn_name
);
2499 else if (in_insn_reserv
== NULL
)
2500 error ("there is no insn reservation `%s'",
2501 DECL_BYPASS (decl
)->in_insn_name
);
2504 DECL_BYPASS (decl
)->out_insn_reserv
2505 = DECL_INSN_RESERV (out_insn_reserv
);
2506 DECL_BYPASS (decl
)->in_insn_reserv
2507 = DECL_INSN_RESERV (in_insn_reserv
);
2509 = find_bypass (DECL_INSN_RESERV (out_insn_reserv
)->bypass_list
,
2510 DECL_BYPASS (decl
)->in_insn_reserv
);
2513 if (DECL_BYPASS (decl
)->latency
== bypass
->latency
)
2517 ("the same bypass `%s - %s' is already defined",
2518 DECL_BYPASS (decl
)->out_insn_name
,
2519 DECL_BYPASS (decl
)->in_insn_name
);
2522 (0, "the same bypass `%s - %s' is already defined",
2523 DECL_BYPASS (decl
)->out_insn_name
,
2524 DECL_BYPASS (decl
)->in_insn_name
);
2527 error ("bypass `%s - %s' is already defined",
2528 DECL_BYPASS (decl
)->out_insn_name
,
2529 DECL_BYPASS (decl
)->in_insn_name
);
2533 DECL_BYPASS (decl
)->next
2534 = DECL_INSN_RESERV (out_insn_reserv
)->bypass_list
;
2535 DECL_INSN_RESERV (out_insn_reserv
)->bypass_list
2536 = DECL_BYPASS (decl
);
2542 /* Check exclusion set declarations and form exclusion sets. */
2543 for (i
= 0; i
< description
->decls_num
; i
++)
2545 decl
= description
->decls
[i
];
2546 if (decl
->mode
== dm_excl
)
2548 unit_set_el_t unit_set_el_list
;
2549 unit_set_el_t unit_set_el_list_2
;
2552 = process_excls (DECL_EXCL (decl
)->names
,
2553 DECL_EXCL (decl
)->first_list_length
, decl
->pos
);
2555 = process_excls (&DECL_EXCL (decl
)->names
2556 [DECL_EXCL (decl
)->first_list_length
],
2557 DECL_EXCL (decl
)->all_names_num
2558 - DECL_EXCL (decl
)->first_list_length
,
2560 add_excls (unit_set_el_list
, unit_set_el_list_2
, decl
->pos
);
2561 add_excls (unit_set_el_list_2
, unit_set_el_list
, decl
->pos
);
2565 /* Check presence set declarations and form presence sets. */
2566 for (i
= 0; i
< description
->decls_num
; i
++)
2568 decl
= description
->decls
[i
];
2569 if (decl
->mode
== dm_presence
)
2571 unit_set_el_t unit_set_el_list
;
2572 pattern_set_el_t pattern_set_el_list
;
2575 = process_presence_absence_names
2576 (DECL_PRESENCE (decl
)->names
, DECL_PRESENCE (decl
)->names_num
,
2577 decl
->pos
, TRUE
, DECL_PRESENCE (decl
)->final_p
);
2579 = process_presence_absence_patterns
2580 (DECL_PRESENCE (decl
)->patterns
,
2581 DECL_PRESENCE (decl
)->patterns_num
,
2582 decl
->pos
, TRUE
, DECL_PRESENCE (decl
)->final_p
);
2583 add_presence_absence (unit_set_el_list
, pattern_set_el_list
,
2585 DECL_PRESENCE (decl
)->final_p
);
2589 /* Check absence set declarations and form absence sets. */
2590 for (i
= 0; i
< description
->decls_num
; i
++)
2592 decl
= description
->decls
[i
];
2593 if (decl
->mode
== dm_absence
)
2595 unit_set_el_t unit_set_el_list
;
2596 pattern_set_el_t pattern_set_el_list
;
2599 = process_presence_absence_names
2600 (DECL_ABSENCE (decl
)->names
, DECL_ABSENCE (decl
)->names_num
,
2601 decl
->pos
, FALSE
, DECL_ABSENCE (decl
)->final_p
);
2603 = process_presence_absence_patterns
2604 (DECL_ABSENCE (decl
)->patterns
,
2605 DECL_ABSENCE (decl
)->patterns_num
,
2606 decl
->pos
, FALSE
, DECL_ABSENCE (decl
)->final_p
);
2607 add_presence_absence (unit_set_el_list
, pattern_set_el_list
,
2609 DECL_ABSENCE (decl
)->final_p
);
2614 /* The following function checks that declared automaton is used. If
2615 the automaton is not used, the function fixes error/warning. The
2616 following function must be called only after `process_decls'. */
2618 check_automaton_usage (void)
2623 for (i
= 0; i
< description
->decls_num
; i
++)
2625 decl
= description
->decls
[i
];
2626 if (decl
->mode
== dm_automaton
2627 && !DECL_AUTOMATON (decl
)->automaton_is_used
)
2630 error ("automaton `%s' is not used", DECL_AUTOMATON (decl
)->name
);
2632 warning (0, "automaton `%s' is not used",
2633 DECL_AUTOMATON (decl
)->name
);
2638 /* The following recursive function processes all regexp in order to
2639 fix usage of units or reservations and to fix errors of undeclared
2640 name. The function may change unit_regexp onto reserv_regexp.
2641 Remember that reserv_regexp does not exist before the function
2644 process_regexp (regexp_t regexp
)
2646 decl_t decl_in_table
;
2647 regexp_t new_regexp
;
2650 switch (regexp
->mode
)
2653 decl_in_table
= find_decl (REGEXP_UNIT (regexp
)->name
);
2654 if (decl_in_table
== NULL
)
2655 error ("undeclared unit or reservation `%s'",
2656 REGEXP_UNIT (regexp
)->name
);
2658 switch (decl_in_table
->mode
)
2661 DECL_UNIT (decl_in_table
)->unit_is_used
= 1;
2662 REGEXP_UNIT (regexp
)->unit_decl
= DECL_UNIT (decl_in_table
);
2666 DECL_RESERV (decl_in_table
)->reserv_is_used
= 1;
2667 new_regexp
= create_node (sizeof (struct regexp
));
2668 new_regexp
->mode
= rm_reserv
;
2669 new_regexp
->pos
= regexp
->pos
;
2670 REGEXP_RESERV (new_regexp
)->name
= REGEXP_UNIT (regexp
)->name
;
2671 REGEXP_RESERV (new_regexp
)->reserv_decl
2672 = DECL_RESERV (decl_in_table
);
2673 regexp
= new_regexp
;
2681 for (i
= 0; i
<REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
2682 REGEXP_SEQUENCE (regexp
)->regexps
[i
]
2683 = process_regexp (REGEXP_SEQUENCE (regexp
)->regexps
[i
]);
2686 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
2687 REGEXP_ALLOF (regexp
)->regexps
[i
]
2688 = process_regexp (REGEXP_ALLOF (regexp
)->regexps
[i
]);
2691 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
2692 REGEXP_ONEOF (regexp
)->regexps
[i
]
2693 = process_regexp (REGEXP_ONEOF (regexp
)->regexps
[i
]);
2696 REGEXP_REPEAT (regexp
)->regexp
2697 = process_regexp (REGEXP_REPEAT (regexp
)->regexp
);
2707 /* The following function processes regexp of define_reservation and
2708 define_insn_reservation with the aid of function
2709 `process_regexp'. */
2711 process_regexp_decls (void)
2716 for (i
= 0; i
< description
->decls_num
; i
++)
2718 decl
= description
->decls
[i
];
2719 if (decl
->mode
== dm_reserv
)
2720 DECL_RESERV (decl
)->regexp
2721 = process_regexp (DECL_RESERV (decl
)->regexp
);
2722 else if (decl
->mode
== dm_insn_reserv
)
2723 DECL_INSN_RESERV (decl
)->regexp
2724 = process_regexp (DECL_INSN_RESERV (decl
)->regexp
);
2728 /* The following function checks that declared unit is used. If the
2729 unit is not used, the function fixes errors/warnings. The
2730 following function must be called only after `process_decls',
2731 `process_regexp_decls'. */
2738 for (i
= 0; i
< description
->decls_num
; i
++)
2740 decl
= description
->decls
[i
];
2741 if (decl
->mode
== dm_unit
&& !DECL_UNIT (decl
)->unit_is_used
)
2744 error ("unit `%s' is not used", DECL_UNIT (decl
)->name
);
2746 warning (0, "unit `%s' is not used", DECL_UNIT (decl
)->name
);
2748 else if (decl
->mode
== dm_reserv
&& !DECL_RESERV (decl
)->reserv_is_used
)
2751 error ("reservation `%s' is not used", DECL_RESERV (decl
)->name
);
2753 warning (0, "reservation `%s' is not used", DECL_RESERV (decl
)->name
);
2758 /* The following variable value is number of reservation being
2759 processed on loop recognition. */
2760 static int curr_loop_pass_num
;
2762 /* The following recursive function returns nonzero value if REGEXP
2763 contains given decl or reservations in given regexp refers for
2766 loop_in_regexp (regexp_t regexp
, decl_t start_decl
)
2772 switch (regexp
->mode
)
2778 if (start_decl
->mode
== dm_reserv
2779 && REGEXP_RESERV (regexp
)->reserv_decl
== DECL_RESERV (start_decl
))
2781 else if (REGEXP_RESERV (regexp
)->reserv_decl
->loop_pass_num
2782 == curr_loop_pass_num
)
2783 /* declaration has been processed. */
2787 REGEXP_RESERV (regexp
)->reserv_decl
->loop_pass_num
2788 = curr_loop_pass_num
;
2789 return loop_in_regexp (REGEXP_RESERV (regexp
)->reserv_decl
->regexp
,
2794 for (i
= 0; i
<REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
2795 if (loop_in_regexp (REGEXP_SEQUENCE (regexp
)->regexps
[i
], start_decl
))
2800 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
2801 if (loop_in_regexp (REGEXP_ALLOF (regexp
)->regexps
[i
], start_decl
))
2806 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
2807 if (loop_in_regexp (REGEXP_ONEOF (regexp
)->regexps
[i
], start_decl
))
2812 return loop_in_regexp (REGEXP_REPEAT (regexp
)->regexp
, start_decl
);
2822 /* The following function fixes errors "cycle in definition ...". The
2823 function uses function `loop_in_regexp' for that. */
2825 check_loops_in_regexps (void)
2830 for (i
= 0; i
< description
->decls_num
; i
++)
2832 decl
= description
->decls
[i
];
2833 if (decl
->mode
== dm_reserv
)
2834 DECL_RESERV (decl
)->loop_pass_num
= 0;
2836 for (i
= 0; i
< description
->decls_num
; i
++)
2838 decl
= description
->decls
[i
];
2839 curr_loop_pass_num
= i
;
2841 if (decl
->mode
== dm_reserv
)
2843 DECL_RESERV (decl
)->loop_pass_num
= curr_loop_pass_num
;
2844 if (loop_in_regexp (DECL_RESERV (decl
)->regexp
, decl
))
2846 gcc_assert (DECL_RESERV (decl
)->regexp
);
2847 error ("cycle in definition of reservation `%s'",
2848 DECL_RESERV (decl
)->name
);
2854 /* The function recursively processes IR of reservation and defines
2855 max and min cycle for reservation of unit. */
2857 process_regexp_cycles (regexp_t regexp
, int max_start_cycle
,
2858 int min_start_cycle
, int *max_finish_cycle
,
2859 int *min_finish_cycle
)
2863 switch (regexp
->mode
)
2866 if (REGEXP_UNIT (regexp
)->unit_decl
->max_occ_cycle_num
< max_start_cycle
)
2867 REGEXP_UNIT (regexp
)->unit_decl
->max_occ_cycle_num
= max_start_cycle
;
2868 if (REGEXP_UNIT (regexp
)->unit_decl
->min_occ_cycle_num
> min_start_cycle
2869 || REGEXP_UNIT (regexp
)->unit_decl
->min_occ_cycle_num
== -1)
2870 REGEXP_UNIT (regexp
)->unit_decl
->min_occ_cycle_num
= min_start_cycle
;
2871 *max_finish_cycle
= max_start_cycle
;
2872 *min_finish_cycle
= min_start_cycle
;
2876 process_regexp_cycles (REGEXP_RESERV (regexp
)->reserv_decl
->regexp
,
2877 max_start_cycle
, min_start_cycle
,
2878 max_finish_cycle
, min_finish_cycle
);
2882 for (i
= 0; i
< REGEXP_REPEAT (regexp
)->repeat_num
; i
++)
2884 process_regexp_cycles (REGEXP_REPEAT (regexp
)->regexp
,
2885 max_start_cycle
, min_start_cycle
,
2886 max_finish_cycle
, min_finish_cycle
);
2887 max_start_cycle
= *max_finish_cycle
+ 1;
2888 min_start_cycle
= *min_finish_cycle
+ 1;
2893 for (i
= 0; i
<REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
2895 process_regexp_cycles (REGEXP_SEQUENCE (regexp
)->regexps
[i
],
2896 max_start_cycle
, min_start_cycle
,
2897 max_finish_cycle
, min_finish_cycle
);
2898 max_start_cycle
= *max_finish_cycle
+ 1;
2899 min_start_cycle
= *min_finish_cycle
+ 1;
2908 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
2910 process_regexp_cycles (REGEXP_ALLOF (regexp
)->regexps
[i
],
2911 max_start_cycle
, min_start_cycle
,
2912 max_finish_cycle
, min_finish_cycle
);
2913 if (max_cycle
< *max_finish_cycle
)
2914 max_cycle
= *max_finish_cycle
;
2915 if (i
== 0 || min_cycle
> *min_finish_cycle
)
2916 min_cycle
= *min_finish_cycle
;
2918 *max_finish_cycle
= max_cycle
;
2919 *min_finish_cycle
= min_cycle
;
2928 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
2930 process_regexp_cycles (REGEXP_ONEOF (regexp
)->regexps
[i
],
2931 max_start_cycle
, min_start_cycle
,
2932 max_finish_cycle
, min_finish_cycle
);
2933 if (max_cycle
< *max_finish_cycle
)
2934 max_cycle
= *max_finish_cycle
;
2935 if (i
== 0 || min_cycle
> *min_finish_cycle
)
2936 min_cycle
= *min_finish_cycle
;
2938 *max_finish_cycle
= max_cycle
;
2939 *min_finish_cycle
= min_cycle
;
2944 *max_finish_cycle
= max_start_cycle
;
2945 *min_finish_cycle
= min_start_cycle
;
2953 /* The following function is called only for correct program. The
2954 function defines max reservation of insns in cycles. */
2956 evaluate_max_reserv_cycles (void)
2958 int max_insn_cycles_num
;
2959 int min_insn_cycles_num
;
2963 description
->max_insn_reserv_cycles
= 0;
2964 for (i
= 0; i
< description
->decls_num
; i
++)
2966 decl
= description
->decls
[i
];
2967 if (decl
->mode
== dm_insn_reserv
)
2969 process_regexp_cycles (DECL_INSN_RESERV (decl
)->regexp
, 0, 0,
2970 &max_insn_cycles_num
, &min_insn_cycles_num
);
2971 if (description
->max_insn_reserv_cycles
< max_insn_cycles_num
)
2972 description
->max_insn_reserv_cycles
= max_insn_cycles_num
;
2975 description
->max_insn_reserv_cycles
++;
2978 /* The following function calls functions for checking all
2981 check_all_description (void)
2984 check_automaton_usage ();
2985 process_regexp_decls ();
2987 check_loops_in_regexps ();
2989 evaluate_max_reserv_cycles ();
2994 /* The page contains abstract data `ticker'. This data is used to
2995 report time of different phases of building automata. It is
2996 possibly to write a description for which automata will be built
2997 during several minutes even on fast machine. */
2999 /* The following function creates ticker and makes it active. */
3001 create_ticker (void)
3005 ticker
.modified_creation_time
= get_run_time ();
3006 ticker
.incremented_off_time
= 0;
3010 /* The following function switches off given ticker. */
3012 ticker_off (ticker_t
*ticker
)
3014 if (ticker
->incremented_off_time
== 0)
3015 ticker
->incremented_off_time
= get_run_time () + 1;
3018 /* The following function switches on given ticker. */
3020 ticker_on (ticker_t
*ticker
)
3022 if (ticker
->incremented_off_time
!= 0)
3024 ticker
->modified_creation_time
3025 += get_run_time () - ticker
->incremented_off_time
+ 1;
3026 ticker
->incremented_off_time
= 0;
3030 /* The following function returns current time in milliseconds since
3031 the moment when given ticker was created. */
3033 active_time (ticker_t ticker
)
3035 if (ticker
.incremented_off_time
!= 0)
3036 return ticker
.incremented_off_time
- 1 - ticker
.modified_creation_time
;
3038 return get_run_time () - ticker
.modified_creation_time
;
3041 /* The following function returns string representation of active time
3042 of given ticker. The result is string representation of seconds
3043 with accuracy of 1/100 second. Only result of the last call of the
3044 function exists. Therefore the following code is not correct
3046 printf ("parser time: %s\ngeneration time: %s\n",
3047 active_time_string (parser_ticker),
3048 active_time_string (generation_ticker));
3050 Correct code has to be the following
3052 printf ("parser time: %s\n", active_time_string (parser_ticker));
3053 printf ("generation time: %s\n",
3054 active_time_string (generation_ticker));
3058 print_active_time (FILE *f
, ticker_t ticker
)
3062 msecs
= active_time (ticker
);
3063 fprintf (f
, "%d.%06d", msecs
/ 1000000, msecs
% 1000000);
3068 /* The following variable value is number of automaton which are
3069 really being created. This value is defined on the base of
3070 argument of option `-split'. If the variable has zero value the
3071 number of automata is defined by the constructions `%automaton'.
3072 This case occurs when option `-split' is absent or has zero
3073 argument. If constructions `define_automaton' is absent only one
3074 automaton is created. */
3075 static int automata_num
;
3077 /* The following variable values are times of
3078 o transformation of regular expressions
3079 o building NDFA (DFA if !ndfa_flag)
3080 o NDFA -> DFA (simply the same automaton if !ndfa_flag)
3082 o building insn equivalence classes
3085 static ticker_t transform_time
;
3086 static ticker_t NDFA_time
;
3087 static ticker_t NDFA_to_DFA_time
;
3088 static ticker_t minimize_time
;
3089 static ticker_t equiv_time
;
3090 static ticker_t automaton_generation_time
;
3091 static ticker_t output_time
;
3093 /* The following variable values are times of
3096 all pipeline hazard translator work */
3097 static ticker_t check_time
;
3098 static ticker_t generation_time
;
3099 static ticker_t all_time
;
3103 /* Pseudo insn decl which denotes advancing cycle. */
3104 static decl_t advance_cycle_insn_decl
;
3106 add_advance_cycle_insn_decl (void)
3108 advance_cycle_insn_decl
= create_node (sizeof (struct decl
));
3109 advance_cycle_insn_decl
->mode
= dm_insn_reserv
;
3110 advance_cycle_insn_decl
->pos
= no_pos
;
3111 DECL_INSN_RESERV (advance_cycle_insn_decl
)->regexp
= NULL
;
3112 DECL_INSN_RESERV (advance_cycle_insn_decl
)->name
= "$advance_cycle";
3113 DECL_INSN_RESERV (advance_cycle_insn_decl
)->insn_num
3114 = description
->insns_num
;
3115 description
->decls
[description
->decls_num
] = advance_cycle_insn_decl
;
3116 description
->decls_num
++;
3117 description
->insns_num
++;
3121 /* Abstract data `alternative states' which represents
3122 nondeterministic nature of the description (see comments for
3123 structures alt_state and state). */
3125 /* List of free states. */
3126 static alt_state_t first_free_alt_state
;
3129 /* The following variables is maximal number of allocated nodes
3131 static int allocated_alt_states_num
= 0;
3134 /* The following function returns free node alt_state. It may be new
3135 allocated node or node freed earlier. */
3137 get_free_alt_state (void)
3141 if (first_free_alt_state
!= NULL
)
3143 result
= first_free_alt_state
;
3144 first_free_alt_state
= first_free_alt_state
->next_alt_state
;
3149 allocated_alt_states_num
++;
3151 result
= create_node (sizeof (struct alt_state
));
3153 result
->state
= NULL
;
3154 result
->next_alt_state
= NULL
;
3155 result
->next_sorted_alt_state
= NULL
;
3159 /* The function frees node ALT_STATE. */
3161 free_alt_state (alt_state_t alt_state
)
3163 if (alt_state
== NULL
)
3165 alt_state
->next_alt_state
= first_free_alt_state
;
3166 first_free_alt_state
= alt_state
;
3169 /* The function frees list started with node ALT_STATE_LIST. */
3171 free_alt_states (alt_state_t alt_states_list
)
3173 alt_state_t curr_alt_state
;
3174 alt_state_t next_alt_state
;
3176 for (curr_alt_state
= alt_states_list
;
3177 curr_alt_state
!= NULL
;
3178 curr_alt_state
= next_alt_state
)
3180 next_alt_state
= curr_alt_state
->next_alt_state
;
3181 free_alt_state (curr_alt_state
);
3185 /* The function compares unique numbers of alt states. */
3187 alt_state_cmp (const void *alt_state_ptr_1
, const void *alt_state_ptr_2
)
3189 if ((*(const alt_state_t
*) alt_state_ptr_1
)->state
->unique_num
3190 == (*(const alt_state_t
*) alt_state_ptr_2
)->state
->unique_num
)
3192 else if ((*(const alt_state_t
*) alt_state_ptr_1
)->state
->unique_num
3193 < (*(const alt_state_t
*) alt_state_ptr_2
)->state
->unique_num
)
3199 /* The function sorts ALT_STATES_LIST and removes duplicated alt
3200 states from the list. The comparison key is alt state unique
3204 uniq_sort_alt_states (alt_state_t alt_states_list
)
3206 alt_state_t curr_alt_state
;
3207 VEC(alt_state_t
,heap
) *alt_states
;
3209 size_t prev_unique_state_ind
;
3212 if (alt_states_list
== 0)
3214 if (alt_states_list
->next_alt_state
== 0)
3215 return alt_states_list
;
3217 alt_states
= VEC_alloc (alt_state_t
,heap
, 150);
3218 for (curr_alt_state
= alt_states_list
;
3219 curr_alt_state
!= NULL
;
3220 curr_alt_state
= curr_alt_state
->next_alt_state
)
3221 VEC_safe_push (alt_state_t
,heap
, alt_states
, curr_alt_state
);
3223 qsort (VEC_address (alt_state_t
, alt_states
),
3224 VEC_length (alt_state_t
, alt_states
),
3225 sizeof (alt_state_t
), alt_state_cmp
);
3227 prev_unique_state_ind
= 0;
3228 for (i
= 1; i
< VEC_length (alt_state_t
, alt_states
); i
++)
3229 if (VEC_index (alt_state_t
, alt_states
, prev_unique_state_ind
)->state
3230 != VEC_index (alt_state_t
, alt_states
, i
)->state
)
3232 prev_unique_state_ind
++;
3233 VEC_replace (alt_state_t
, alt_states
, prev_unique_state_ind
,
3234 VEC_index (alt_state_t
, alt_states
, i
));
3236 VEC_truncate (alt_state_t
, alt_states
, prev_unique_state_ind
+ 1);
3238 for (i
= 1; i
< VEC_length (alt_state_t
, alt_states
); i
++)
3239 VEC_index (alt_state_t
, alt_states
, i
-1)->next_sorted_alt_state
3240 = VEC_index (alt_state_t
, alt_states
, i
);
3241 VEC_last (alt_state_t
, alt_states
)->next_sorted_alt_state
= 0;
3243 result
= VEC_index (alt_state_t
, alt_states
, 0);
3245 VEC_free (alt_state_t
,heap
, alt_states
);
3249 /* The function checks equality of alt state lists. Remember that the
3250 lists must be already sorted by the previous function. */
3252 alt_states_eq (alt_state_t alt_states_1
, alt_state_t alt_states_2
)
3254 while (alt_states_1
!= NULL
&& alt_states_2
!= NULL
3255 && alt_state_cmp (&alt_states_1
, &alt_states_2
) == 0)
3257 alt_states_1
= alt_states_1
->next_sorted_alt_state
;
3258 alt_states_2
= alt_states_2
->next_sorted_alt_state
;
3260 return alt_states_1
== alt_states_2
;
3263 /* Initialization of the abstract data. */
3265 initiate_alt_states (void)
3267 first_free_alt_state
= NULL
;
3270 /* Finishing work with the abstract data. */
3272 finish_alt_states (void)
3278 /* The page contains macros for work with bits strings. We could use
3279 standard gcc bitmap or sbitmap but it would result in difficulties
3280 of building canadian cross. */
3282 /* Set bit number bitno in the bit string. The macro is not side
3284 #define SET_BIT(bitstring, bitno) \
3285 (((char *) (bitstring)) [(bitno) / CHAR_BIT] |= 1 << (bitno) % CHAR_BIT)
3287 #define CLEAR_BIT(bitstring, bitno) \
3288 (((char *) (bitstring)) [(bitno) / CHAR_BIT] &= ~(1 << (bitno) % CHAR_BIT))
3290 /* Test if bit number bitno in the bitstring is set. The macro is not
3291 side effect proof. */
3292 #define TEST_BIT(bitstring, bitno) \
3293 (((char *) (bitstring)) [(bitno) / CHAR_BIT] >> (bitno) % CHAR_BIT & 1)
3297 /* This page contains abstract data `state'. */
3299 /* Maximal length of reservations in cycles (>= 1). */
3300 static int max_cycles_num
;
3302 /* Number of set elements (see type set_el_t) needed for
3303 representation of one cycle reservation. It is depended on units
3305 static int els_in_cycle_reserv
;
3307 /* Number of set elements (see type set_el_t) needed for
3308 representation of maximal length reservation. Deterministic
3309 reservation is stored as set (bit string) of length equal to the
3310 variable value * number of bits in set_el_t. */
3311 static int els_in_reservs
;
3313 /* Array of pointers to unit declarations. */
3314 static unit_decl_t
*units_array
;
3316 /* Temporary reservation of maximal length. */
3317 static reserv_sets_t temp_reserv
;
3319 /* The state table itself is represented by the following variable. */
3320 static htab_t state_table
;
3322 /* Linked list of free 'state' structures to be recycled. The
3323 next_equiv_class_state pointer is borrowed for a free list. */
3324 static state_t first_free_state
;
3326 static int curr_unique_state_num
;
3329 /* The following variables is maximal number of allocated nodes
3331 static int allocated_states_num
= 0;
3334 /* Allocate new reservation set. */
3335 static reserv_sets_t
3336 alloc_empty_reserv_sets (void)
3338 reserv_sets_t result
;
3340 obstack_blank (&irp
, els_in_reservs
* sizeof (set_el_t
));
3341 result
= (reserv_sets_t
) obstack_base (&irp
);
3342 obstack_finish (&irp
);
3343 memset (result
, 0, els_in_reservs
* sizeof (set_el_t
));
3347 /* Hash value of reservation set. */
3349 reserv_sets_hash_value (reserv_sets_t reservs
)
3351 set_el_t hash_value
;
3354 set_el_t
*reserv_ptr
;
3357 reservs_num
= els_in_reservs
;
3358 reserv_ptr
= reservs
;
3360 while (reservs_num
!= 0)
3363 hash_value
+= ((*reserv_ptr
>> i
)
3364 | (*reserv_ptr
<< (sizeof (set_el_t
) * CHAR_BIT
- i
)));
3366 if (i
== sizeof (set_el_t
) * CHAR_BIT
)
3370 if (sizeof (set_el_t
) <= sizeof (unsigned))
3373 for (i
= sizeof (set_el_t
); i
> 0; i
-= sizeof (unsigned) - 1)
3375 result
+= (unsigned) hash_value
;
3376 hash_value
>>= (sizeof (unsigned) - 1) * CHAR_BIT
;
3381 /* Comparison of given reservation sets. */
3383 reserv_sets_cmp (const_reserv_sets_t reservs_1
, const_reserv_sets_t reservs_2
)
3386 const set_el_t
*reserv_ptr_1
;
3387 const set_el_t
*reserv_ptr_2
;
3389 gcc_assert (reservs_1
&& reservs_2
);
3390 reservs_num
= els_in_reservs
;
3391 reserv_ptr_1
= reservs_1
;
3392 reserv_ptr_2
= reservs_2
;
3393 while (reservs_num
!= 0 && *reserv_ptr_1
== *reserv_ptr_2
)
3399 if (reservs_num
== 0)
3401 else if (*reserv_ptr_1
< *reserv_ptr_2
)
3407 /* The function checks equality of the reservation sets. */
3409 reserv_sets_eq (const_reserv_sets_t reservs_1
, const_reserv_sets_t reservs_2
)
3411 return reserv_sets_cmp (reservs_1
, reservs_2
) == 0;
3414 /* Set up in the reservation set that unit with UNIT_NUM is used on
3417 set_unit_reserv (reserv_sets_t reservs
, int cycle_num
, int unit_num
)
3419 gcc_assert (cycle_num
< max_cycles_num
);
3420 SET_BIT (reservs
, cycle_num
* els_in_cycle_reserv
3421 * sizeof (set_el_t
) * CHAR_BIT
+ unit_num
);
3424 /* Set up in the reservation set RESERVS that unit with UNIT_NUM is
3425 used on CYCLE_NUM. */
3427 test_unit_reserv (reserv_sets_t reservs
, int cycle_num
, int unit_num
)
3429 gcc_assert (cycle_num
< max_cycles_num
);
3430 return TEST_BIT (reservs
, cycle_num
* els_in_cycle_reserv
3431 * sizeof (set_el_t
) * CHAR_BIT
+ unit_num
);
3434 /* The function checks that the reservation sets are intersected,
3435 i.e. there is a unit reservation on a cycle in both reservation
3438 reserv_sets_are_intersected (reserv_sets_t operand_1
,
3439 reserv_sets_t operand_2
)
3443 set_el_t
*cycle_ptr_1
;
3444 set_el_t
*cycle_ptr_2
;
3446 gcc_assert (operand_1
&& operand_2
);
3447 for (el_ptr_1
= operand_1
, el_ptr_2
= operand_2
;
3448 el_ptr_1
< operand_1
+ els_in_reservs
;
3449 el_ptr_1
++, el_ptr_2
++)
3450 if (*el_ptr_1
& *el_ptr_2
)
3452 reserv_sets_or (temp_reserv
, operand_1
, operand_2
);
3453 for (cycle_ptr_1
= operand_1
, cycle_ptr_2
= operand_2
;
3454 cycle_ptr_1
< operand_1
+ els_in_reservs
;
3455 cycle_ptr_1
+= els_in_cycle_reserv
, cycle_ptr_2
+= els_in_cycle_reserv
)
3457 for (el_ptr_1
= cycle_ptr_1
, el_ptr_2
= get_excl_set (cycle_ptr_2
);
3458 el_ptr_1
< cycle_ptr_1
+ els_in_cycle_reserv
;
3459 el_ptr_1
++, el_ptr_2
++)
3460 if (*el_ptr_1
& *el_ptr_2
)
3462 if (!check_presence_pattern_sets (cycle_ptr_1
, cycle_ptr_2
, FALSE
))
3464 if (!check_presence_pattern_sets (temp_reserv
+ (cycle_ptr_2
3468 if (!check_absence_pattern_sets (cycle_ptr_1
, cycle_ptr_2
, FALSE
))
3470 if (!check_absence_pattern_sets (temp_reserv
+ (cycle_ptr_2
- operand_2
),
3477 /* The function sets up RESULT bits by bits of OPERAND shifted on one
3478 cpu cycle. The remaining bits of OPERAND (representing the last
3479 cycle unit reservations) are not changed. */
3481 reserv_sets_shift (reserv_sets_t result
, reserv_sets_t operand
)
3485 gcc_assert (result
&& operand
&& result
!= operand
);
3486 for (i
= els_in_cycle_reserv
; i
< els_in_reservs
; i
++)
3487 result
[i
- els_in_cycle_reserv
] = operand
[i
];
3490 /* OR of the reservation sets. */
3492 reserv_sets_or (reserv_sets_t result
, reserv_sets_t operand_1
,
3493 reserv_sets_t operand_2
)
3497 set_el_t
*result_set_el_ptr
;
3499 gcc_assert (result
&& operand_1
&& operand_2
);
3500 for (el_ptr_1
= operand_1
, el_ptr_2
= operand_2
, result_set_el_ptr
= result
;
3501 el_ptr_1
< operand_1
+ els_in_reservs
;
3502 el_ptr_1
++, el_ptr_2
++, result_set_el_ptr
++)
3503 *result_set_el_ptr
= *el_ptr_1
| *el_ptr_2
;
3506 /* AND of the reservation sets. */
3508 reserv_sets_and (reserv_sets_t result
, reserv_sets_t operand_1
,
3509 reserv_sets_t operand_2
)
3513 set_el_t
*result_set_el_ptr
;
3515 gcc_assert (result
&& operand_1
&& operand_2
);
3516 for (el_ptr_1
= operand_1
, el_ptr_2
= operand_2
, result_set_el_ptr
= result
;
3517 el_ptr_1
< operand_1
+ els_in_reservs
;
3518 el_ptr_1
++, el_ptr_2
++, result_set_el_ptr
++)
3519 *result_set_el_ptr
= *el_ptr_1
& *el_ptr_2
;
3522 /* The function outputs string representation of units reservation on
3523 cycle START_CYCLE in the reservation set. The function uses repeat
3524 construction if REPETITION_NUM > 1. */
3526 output_cycle_reservs (FILE *f
, reserv_sets_t reservs
, int start_cycle
,
3530 int reserved_units_num
;
3532 reserved_units_num
= 0;
3533 for (unit_num
= 0; unit_num
< description
->units_num
; unit_num
++)
3534 if (TEST_BIT (reservs
, start_cycle
* els_in_cycle_reserv
3535 * sizeof (set_el_t
) * CHAR_BIT
+ unit_num
))
3536 reserved_units_num
++;
3537 gcc_assert (repetition_num
> 0);
3538 if (repetition_num
!= 1 && reserved_units_num
> 1)
3540 reserved_units_num
= 0;
3542 unit_num
< description
->units_num
;
3544 if (TEST_BIT (reservs
, start_cycle
* els_in_cycle_reserv
3545 * sizeof (set_el_t
) * CHAR_BIT
+ unit_num
))
3547 if (reserved_units_num
!= 0)
3549 reserved_units_num
++;
3550 fprintf (f
, "%s", units_array
[unit_num
]->name
);
3552 if (reserved_units_num
== 0)
3553 fprintf (f
, NOTHING_NAME
);
3554 gcc_assert (repetition_num
> 0);
3555 if (repetition_num
!= 1 && reserved_units_num
> 1)
3557 if (repetition_num
!= 1)
3558 fprintf (f
, "*%d", repetition_num
);
3561 /* The function outputs string representation of units reservation in
3562 the reservation set. */
3564 output_reserv_sets (FILE *f
, reserv_sets_t reservs
)
3566 int start_cycle
= 0;
3571 for (cycle
= 0; cycle
< max_cycles_num
; cycle
++)
3572 if (repetition_num
== 0)
3575 start_cycle
= cycle
;
3578 ((char *) reservs
+ start_cycle
* els_in_cycle_reserv
3579 * sizeof (set_el_t
),
3580 (char *) reservs
+ cycle
* els_in_cycle_reserv
3581 * sizeof (set_el_t
),
3582 els_in_cycle_reserv
* sizeof (set_el_t
)) == 0)
3586 if (start_cycle
!= 0)
3588 output_cycle_reservs (f
, reservs
, start_cycle
, repetition_num
);
3590 start_cycle
= cycle
;
3592 if (start_cycle
< max_cycles_num
)
3594 if (start_cycle
!= 0)
3596 output_cycle_reservs (f
, reservs
, start_cycle
, repetition_num
);
3600 /* The following function returns free node state for AUTOMATON. It
3601 may be new allocated node or node freed earlier. The function also
3602 allocates reservation set if WITH_RESERVS has nonzero value. */
3604 get_free_state (int with_reservs
, automaton_t automaton
)
3608 gcc_assert (max_cycles_num
> 0 && automaton
);
3609 if (first_free_state
)
3611 result
= first_free_state
;
3612 first_free_state
= result
->next_equiv_class_state
;
3614 result
->next_equiv_class_state
= NULL
;
3615 result
->automaton
= automaton
;
3616 result
->first_out_arc
= NULL
;
3617 result
->it_was_placed_in_stack_for_NDFA_forming
= 0;
3618 result
->it_was_placed_in_stack_for_DFA_forming
= 0;
3619 result
->component_states
= NULL
;
3624 allocated_states_num
++;
3626 result
= create_node (sizeof (struct state
));
3627 result
->automaton
= automaton
;
3628 result
->first_out_arc
= NULL
;
3629 result
->unique_num
= curr_unique_state_num
;
3630 curr_unique_state_num
++;
3634 if (result
->reservs
== NULL
)
3635 result
->reservs
= alloc_empty_reserv_sets ();
3637 memset (result
->reservs
, 0, els_in_reservs
* sizeof (set_el_t
));
3642 /* The function frees node STATE. */
3644 free_state (state_t state
)
3646 free_alt_states (state
->component_states
);
3647 state
->next_equiv_class_state
= first_free_state
;
3648 first_free_state
= state
;
3651 /* Hash value of STATE. If STATE represents deterministic state it is
3652 simply hash value of the corresponding reservation set. Otherwise
3653 it is formed from hash values of the component deterministic
3654 states. One more key is order number of state automaton. */
3656 state_hash (const void *state
)
3658 unsigned int hash_value
;
3659 alt_state_t alt_state
;
3661 if (((const_state_t
) state
)->component_states
== NULL
)
3662 hash_value
= reserv_sets_hash_value (((const_state_t
) state
)->reservs
);
3666 for (alt_state
= ((const_state_t
) state
)->component_states
;
3668 alt_state
= alt_state
->next_sorted_alt_state
)
3669 hash_value
= (((hash_value
>> (sizeof (unsigned) - 1) * CHAR_BIT
)
3670 | (hash_value
<< CHAR_BIT
))
3671 + alt_state
->state
->unique_num
);
3673 hash_value
= (((hash_value
>> (sizeof (unsigned) - 1) * CHAR_BIT
)
3674 | (hash_value
<< CHAR_BIT
))
3675 + ((const_state_t
) state
)->automaton
->automaton_order_num
);
3679 /* Return nonzero value if the states are the same. */
3681 state_eq_p (const void *state_1
, const void *state_2
)
3683 alt_state_t alt_state_1
;
3684 alt_state_t alt_state_2
;
3686 if (((const_state_t
) state_1
)->automaton
!= ((const_state_t
) state_2
)->automaton
)
3688 else if (((const_state_t
) state_1
)->component_states
== NULL
3689 && ((const_state_t
) state_2
)->component_states
== NULL
)
3690 return reserv_sets_eq (((const_state_t
) state_1
)->reservs
,
3691 ((const_state_t
) state_2
)->reservs
);
3692 else if (((const_state_t
) state_1
)->component_states
!= NULL
3693 && ((const_state_t
) state_2
)->component_states
!= NULL
)
3695 for (alt_state_1
= ((const_state_t
) state_1
)->component_states
,
3696 alt_state_2
= ((const_state_t
) state_2
)->component_states
;
3697 alt_state_1
!= NULL
&& alt_state_2
!= NULL
;
3698 alt_state_1
= alt_state_1
->next_sorted_alt_state
,
3699 alt_state_2
= alt_state_2
->next_sorted_alt_state
)
3700 /* All state in the list must be already in the hash table.
3701 Also the lists must be sorted. */
3702 if (alt_state_1
->state
!= alt_state_2
->state
)
3704 return alt_state_1
== alt_state_2
;
3710 /* Insert STATE into the state table. */
3712 insert_state (state_t state
)
3716 entry_ptr
= htab_find_slot (state_table
, (void *) state
, 1);
3717 if (*entry_ptr
== NULL
)
3718 *entry_ptr
= (void *) state
;
3719 return (state_t
) *entry_ptr
;
3722 /* Add reservation of unit with UNIT_NUM on cycle CYCLE_NUM to
3723 deterministic STATE. */
3725 set_state_reserv (state_t state
, int cycle_num
, int unit_num
)
3727 set_unit_reserv (state
->reservs
, cycle_num
, unit_num
);
3730 /* Return nonzero value if the deterministic states contains a
3731 reservation of the same cpu unit on the same cpu cycle. */
3733 intersected_state_reservs_p (state_t state1
, state_t state2
)
3735 gcc_assert (state1
->automaton
== state2
->automaton
);
3736 return reserv_sets_are_intersected (state1
->reservs
, state2
->reservs
);
3739 /* Return deterministic state (inserted into the table) which
3740 representing the automaton state which is union of reservations of
3741 the deterministic states masked by RESERVS. */
3743 states_union (state_t state1
, state_t state2
, reserv_sets_t reservs
)
3746 state_t state_in_table
;
3748 gcc_assert (state1
->automaton
== state2
->automaton
);
3749 result
= get_free_state (1, state1
->automaton
);
3750 reserv_sets_or (result
->reservs
, state1
->reservs
, state2
->reservs
);
3751 reserv_sets_and (result
->reservs
, result
->reservs
, reservs
);
3752 state_in_table
= insert_state (result
);
3753 if (result
!= state_in_table
)
3755 free_state (result
);
3756 result
= state_in_table
;
3761 /* Return deterministic state (inserted into the table) which
3762 represent the automaton state is obtained from deterministic STATE
3763 by advancing cpu cycle and masking by RESERVS. */
3765 state_shift (state_t state
, reserv_sets_t reservs
)
3768 state_t state_in_table
;
3770 result
= get_free_state (1, state
->automaton
);
3771 reserv_sets_shift (result
->reservs
, state
->reservs
);
3772 reserv_sets_and (result
->reservs
, result
->reservs
, reservs
);
3773 state_in_table
= insert_state (result
);
3774 if (result
!= state_in_table
)
3776 free_state (result
);
3777 result
= state_in_table
;
3782 /* Initialization of the abstract data. */
3784 initiate_states (void)
3789 if (description
->units_num
)
3790 units_array
= XNEWVEC (unit_decl_t
, description
->units_num
);
3794 for (i
= 0; i
< description
->decls_num
; i
++)
3796 decl
= description
->decls
[i
];
3797 if (decl
->mode
== dm_unit
)
3798 units_array
[DECL_UNIT (decl
)->unit_num
] = DECL_UNIT (decl
);
3800 max_cycles_num
= description
->max_insn_reserv_cycles
;
3802 = ((description
->units_num
+ sizeof (set_el_t
) * CHAR_BIT
- 1)
3803 / (sizeof (set_el_t
) * CHAR_BIT
));
3804 els_in_reservs
= els_in_cycle_reserv
* max_cycles_num
;
3805 curr_unique_state_num
= 0;
3806 initiate_alt_states ();
3807 state_table
= htab_create (1500, state_hash
, state_eq_p
, (htab_del
) 0);
3808 temp_reserv
= alloc_empty_reserv_sets ();
3811 /* Finishing work with the abstract data. */
3813 finish_states (void)
3817 htab_delete (state_table
);
3818 first_free_state
= NULL
;
3819 finish_alt_states ();
3824 /* Abstract data `arcs'. */
3826 /* List of free arcs. */
3827 static arc_t first_free_arc
;
3830 /* The following variables is maximal number of allocated nodes
3832 static int allocated_arcs_num
= 0;
3835 /* The function frees node ARC. */
3837 free_arc (arc_t arc
)
3839 arc
->next_out_arc
= first_free_arc
;
3840 first_free_arc
= arc
;
3843 /* The function removes and frees ARC staring from FROM_STATE. */
3845 remove_arc (state_t from_state
, arc_t arc
)
3851 for (prev_arc
= NULL
, curr_arc
= from_state
->first_out_arc
;
3853 prev_arc
= curr_arc
, curr_arc
= curr_arc
->next_out_arc
)
3854 if (curr_arc
== arc
)
3856 gcc_assert (curr_arc
);
3857 if (prev_arc
== NULL
)
3858 from_state
->first_out_arc
= arc
->next_out_arc
;
3860 prev_arc
->next_out_arc
= arc
->next_out_arc
;
3861 from_state
->num_out_arcs
--;
3865 /* The functions returns arc with given characteristics (or NULL if
3866 the arc does not exist). */
3868 find_arc (state_t from_state
, state_t to_state
, ainsn_t insn
)
3872 for (arc
= first_out_arc (from_state
); arc
!= NULL
; arc
= next_out_arc (arc
))
3873 if (arc
->to_state
== to_state
&& arc
->insn
== insn
)
3878 /* The function adds arc from FROM_STATE to TO_STATE marked by AINSN.
3879 The function returns added arc (or already existing arc). */
3881 add_arc (state_t from_state
, state_t to_state
, ainsn_t ainsn
)
3885 new_arc
= find_arc (from_state
, to_state
, ainsn
);
3886 if (new_arc
!= NULL
)
3888 if (first_free_arc
== NULL
)
3891 allocated_arcs_num
++;
3893 new_arc
= create_node (sizeof (struct arc
));
3894 new_arc
->to_state
= NULL
;
3895 new_arc
->insn
= NULL
;
3896 new_arc
->next_out_arc
= NULL
;
3900 new_arc
= first_free_arc
;
3901 first_free_arc
= first_free_arc
->next_out_arc
;
3903 new_arc
->to_state
= to_state
;
3904 new_arc
->insn
= ainsn
;
3905 ainsn
->arc_exists_p
= 1;
3906 new_arc
->next_out_arc
= from_state
->first_out_arc
;
3907 from_state
->first_out_arc
= new_arc
;
3908 from_state
->num_out_arcs
++;
3909 new_arc
->next_arc_marked_by_insn
= NULL
;
3913 /* The function returns the first arc starting from STATE. */
3915 first_out_arc (const_state_t state
)
3917 return state
->first_out_arc
;
3920 /* The function returns next out arc after ARC. */
3922 next_out_arc (arc_t arc
)
3924 return arc
->next_out_arc
;
3927 /* Initialization of the abstract data. */
3929 initiate_arcs (void)
3931 first_free_arc
= NULL
;
3934 /* Finishing work with the abstract data. */
3942 /* Abstract data `automata lists'. */
3944 /* List of free states. */
3945 static automata_list_el_t first_free_automata_list_el
;
3947 /* The list being formed. */
3948 static automata_list_el_t current_automata_list
;
3950 /* Hash table of automata lists. */
3951 static htab_t automata_list_table
;
3953 /* The following function returns free automata list el. It may be
3954 new allocated node or node freed earlier. */
3955 static automata_list_el_t
3956 get_free_automata_list_el (void)
3958 automata_list_el_t result
;
3960 if (first_free_automata_list_el
!= NULL
)
3962 result
= first_free_automata_list_el
;
3963 first_free_automata_list_el
3964 = first_free_automata_list_el
->next_automata_list_el
;
3967 result
= create_node (sizeof (struct automata_list_el
));
3968 result
->automaton
= NULL
;
3969 result
->next_automata_list_el
= NULL
;
3973 /* The function frees node AUTOMATA_LIST_EL. */
3975 free_automata_list_el (automata_list_el_t automata_list_el
)
3977 if (automata_list_el
== NULL
)
3979 automata_list_el
->next_automata_list_el
= first_free_automata_list_el
;
3980 first_free_automata_list_el
= automata_list_el
;
3983 /* The function frees list AUTOMATA_LIST. */
3985 free_automata_list (automata_list_el_t automata_list
)
3987 automata_list_el_t curr_automata_list_el
;
3988 automata_list_el_t next_automata_list_el
;
3990 for (curr_automata_list_el
= automata_list
;
3991 curr_automata_list_el
!= NULL
;
3992 curr_automata_list_el
= next_automata_list_el
)
3994 next_automata_list_el
= curr_automata_list_el
->next_automata_list_el
;
3995 free_automata_list_el (curr_automata_list_el
);
3999 /* Hash value of AUTOMATA_LIST. */
4001 automata_list_hash (const void *automata_list
)
4003 unsigned int hash_value
;
4004 const_automata_list_el_t curr_automata_list_el
;
4007 for (curr_automata_list_el
= (const_automata_list_el_t
) automata_list
;
4008 curr_automata_list_el
!= NULL
;
4009 curr_automata_list_el
= curr_automata_list_el
->next_automata_list_el
)
4010 hash_value
= (((hash_value
>> (sizeof (unsigned) - 1) * CHAR_BIT
)
4011 | (hash_value
<< CHAR_BIT
))
4012 + curr_automata_list_el
->automaton
->automaton_order_num
);
4016 /* Return nonzero value if the automata_lists are the same. */
4018 automata_list_eq_p (const void *automata_list_1
, const void *automata_list_2
)
4020 const_automata_list_el_t automata_list_el_1
;
4021 const_automata_list_el_t automata_list_el_2
;
4023 for (automata_list_el_1
= (const_automata_list_el_t
) automata_list_1
,
4024 automata_list_el_2
= (const_automata_list_el_t
) automata_list_2
;
4025 automata_list_el_1
!= NULL
&& automata_list_el_2
!= NULL
;
4026 automata_list_el_1
= automata_list_el_1
->next_automata_list_el
,
4027 automata_list_el_2
= automata_list_el_2
->next_automata_list_el
)
4028 if (automata_list_el_1
->automaton
!= automata_list_el_2
->automaton
)
4030 return automata_list_el_1
== automata_list_el_2
;
4033 /* Initialization of the abstract data. */
4035 initiate_automata_lists (void)
4037 first_free_automata_list_el
= NULL
;
4038 automata_list_table
= htab_create (1500, automata_list_hash
,
4039 automata_list_eq_p
, (htab_del
) 0);
4042 /* The following function starts new automata list and makes it the
4045 automata_list_start (void)
4047 current_automata_list
= NULL
;
4050 /* The following function adds AUTOMATON to the current list. */
4052 automata_list_add (automaton_t automaton
)
4054 automata_list_el_t el
;
4056 el
= get_free_automata_list_el ();
4057 el
->automaton
= automaton
;
4058 el
->next_automata_list_el
= current_automata_list
;
4059 current_automata_list
= el
;
4062 /* The following function finishes forming the current list, inserts
4063 it into the table and returns it. */
4064 static automata_list_el_t
4065 automata_list_finish (void)
4069 if (current_automata_list
== NULL
)
4071 entry_ptr
= htab_find_slot (automata_list_table
,
4072 (void *) current_automata_list
, 1);
4073 if (*entry_ptr
== NULL
)
4074 *entry_ptr
= (void *) current_automata_list
;
4076 free_automata_list (current_automata_list
);
4077 current_automata_list
= NULL
;
4078 return (automata_list_el_t
) *entry_ptr
;
4081 /* Finishing work with the abstract data. */
4083 finish_automata_lists (void)
4085 htab_delete (automata_list_table
);
4090 /* The page contains abstract data for work with exclusion sets (see
4091 exclusion_set in file rtl.def). */
4093 /* The following variable refers to an exclusion set returned by
4094 get_excl_set. This is bit string of length equal to cpu units
4095 number. If exclusion set for given unit contains 1 for a unit,
4096 then simultaneous reservation of the units is prohibited. */
4097 static reserv_sets_t excl_set
;
4099 /* The array contains exclusion sets for each unit. */
4100 static reserv_sets_t
*unit_excl_set_table
;
4102 /* The following function forms the array containing exclusion sets
4105 initiate_excl_sets (void)
4108 reserv_sets_t unit_excl_set
;
4112 obstack_blank (&irp
, els_in_cycle_reserv
* sizeof (set_el_t
));
4113 excl_set
= (reserv_sets_t
) obstack_base (&irp
);
4114 obstack_finish (&irp
);
4115 obstack_blank (&irp
, description
->units_num
* sizeof (reserv_sets_t
));
4116 unit_excl_set_table
= (reserv_sets_t
*) obstack_base (&irp
);
4117 obstack_finish (&irp
);
4118 /* Evaluate unit exclusion sets. */
4119 for (i
= 0; i
< description
->decls_num
; i
++)
4121 decl
= description
->decls
[i
];
4122 if (decl
->mode
== dm_unit
)
4124 obstack_blank (&irp
, els_in_cycle_reserv
* sizeof (set_el_t
));
4125 unit_excl_set
= (reserv_sets_t
) obstack_base (&irp
);
4126 obstack_finish (&irp
);
4127 memset (unit_excl_set
, 0, els_in_cycle_reserv
* sizeof (set_el_t
));
4128 for (el
= DECL_UNIT (decl
)->excl_list
;
4130 el
= el
->next_unit_set_el
)
4132 SET_BIT (unit_excl_set
, el
->unit_decl
->unit_num
);
4133 el
->unit_decl
->in_set_p
= TRUE
;
4135 unit_excl_set_table
[DECL_UNIT (decl
)->unit_num
] = unit_excl_set
;
4140 /* The function sets up and return EXCL_SET which is union of
4141 exclusion sets for each unit in IN_SET. */
4142 static reserv_sets_t
4143 get_excl_set (reserv_sets_t in_set
)
4151 chars_num
= els_in_cycle_reserv
* sizeof (set_el_t
);
4152 memset (excl_set
, 0, chars_num
);
4153 for (excl_char_num
= 0; excl_char_num
< chars_num
; excl_char_num
++)
4154 if (((unsigned char *) in_set
) [excl_char_num
])
4155 for (i
= CHAR_BIT
- 1; i
>= 0; i
--)
4156 if ((((unsigned char *) in_set
) [excl_char_num
] >> i
) & 1)
4158 start_unit_num
= excl_char_num
* CHAR_BIT
+ i
;
4159 if (start_unit_num
>= description
->units_num
)
4161 for (unit_num
= 0; unit_num
< els_in_cycle_reserv
; unit_num
++)
4164 |= unit_excl_set_table
[start_unit_num
] [unit_num
];
4172 /* The page contains abstract data for work with presence/absence
4173 pattern sets (see presence_set/absence_set in file rtl.def). */
4175 /* The following arrays contain correspondingly presence, final
4176 presence, absence, and final absence patterns for each unit. */
4177 static pattern_reserv_t
*unit_presence_set_table
;
4178 static pattern_reserv_t
*unit_final_presence_set_table
;
4179 static pattern_reserv_t
*unit_absence_set_table
;
4180 static pattern_reserv_t
*unit_final_absence_set_table
;
4182 /* The following function forms list of reservation sets for given
4184 static pattern_reserv_t
4185 form_reserv_sets_list (pattern_set_el_t pattern_list
)
4187 pattern_set_el_t el
;
4188 pattern_reserv_t first
, curr
, prev
;
4191 prev
= first
= NULL
;
4192 for (el
= pattern_list
; el
!= NULL
; el
= el
->next_pattern_set_el
)
4194 curr
= create_node (sizeof (struct pattern_reserv
));
4195 curr
->reserv
= alloc_empty_reserv_sets ();
4196 curr
->next_pattern_reserv
= NULL
;
4197 for (i
= 0; i
< el
->units_num
; i
++)
4199 SET_BIT (curr
->reserv
, el
->unit_decls
[i
]->unit_num
);
4200 el
->unit_decls
[i
]->in_set_p
= TRUE
;
4203 prev
->next_pattern_reserv
= curr
;
4211 /* The following function forms the array containing presence and
4212 absence pattern sets for each unit. */
4214 initiate_presence_absence_pattern_sets (void)
4219 obstack_blank (&irp
, description
->units_num
* sizeof (pattern_reserv_t
));
4220 unit_presence_set_table
= (pattern_reserv_t
*) obstack_base (&irp
);
4221 obstack_finish (&irp
);
4222 obstack_blank (&irp
, description
->units_num
* sizeof (pattern_reserv_t
));
4223 unit_final_presence_set_table
= (pattern_reserv_t
*) obstack_base (&irp
);
4224 obstack_finish (&irp
);
4225 obstack_blank (&irp
, description
->units_num
* sizeof (pattern_reserv_t
));
4226 unit_absence_set_table
= (pattern_reserv_t
*) obstack_base (&irp
);
4227 obstack_finish (&irp
);
4228 obstack_blank (&irp
, description
->units_num
* sizeof (pattern_reserv_t
));
4229 unit_final_absence_set_table
= (pattern_reserv_t
*) obstack_base (&irp
);
4230 obstack_finish (&irp
);
4231 /* Evaluate unit presence/absence sets. */
4232 for (i
= 0; i
< description
->decls_num
; i
++)
4234 decl
= description
->decls
[i
];
4235 if (decl
->mode
== dm_unit
)
4237 unit_presence_set_table
[DECL_UNIT (decl
)->unit_num
]
4238 = form_reserv_sets_list (DECL_UNIT (decl
)->presence_list
);
4239 unit_final_presence_set_table
[DECL_UNIT (decl
)->unit_num
]
4240 = form_reserv_sets_list (DECL_UNIT (decl
)->final_presence_list
);
4241 unit_absence_set_table
[DECL_UNIT (decl
)->unit_num
]
4242 = form_reserv_sets_list (DECL_UNIT (decl
)->absence_list
);
4243 unit_final_absence_set_table
[DECL_UNIT (decl
)->unit_num
]
4244 = form_reserv_sets_list (DECL_UNIT (decl
)->final_absence_list
);
4249 /* The function checks that CHECKED_SET satisfies all presence pattern
4250 sets for units in ORIGIONAL_SET. The function returns TRUE if it
4253 check_presence_pattern_sets (reserv_sets_t checked_set
,
4254 reserv_sets_t origional_set
,
4263 pattern_reserv_t pat_reserv
;
4265 chars_num
= els_in_cycle_reserv
* sizeof (set_el_t
);
4266 for (char_num
= 0; char_num
< chars_num
; char_num
++)
4267 if (((unsigned char *) origional_set
) [char_num
])
4268 for (i
= CHAR_BIT
- 1; i
>= 0; i
--)
4269 if ((((unsigned char *) origional_set
) [char_num
] >> i
) & 1)
4271 start_unit_num
= char_num
* CHAR_BIT
+ i
;
4272 if (start_unit_num
>= description
->units_num
)
4275 && unit_final_presence_set_table
[start_unit_num
] == NULL
)
4277 && unit_presence_set_table
[start_unit_num
] == NULL
))
4280 for (pat_reserv
= (final_p
4281 ? unit_final_presence_set_table
[start_unit_num
]
4282 : unit_presence_set_table
[start_unit_num
]);
4284 pat_reserv
= pat_reserv
->next_pattern_reserv
)
4286 for (unit_num
= 0; unit_num
< els_in_cycle_reserv
; unit_num
++)
4287 if ((checked_set
[unit_num
] & pat_reserv
->reserv
[unit_num
])
4288 != pat_reserv
->reserv
[unit_num
])
4290 presence_p
= presence_p
|| unit_num
>= els_in_cycle_reserv
;
4298 /* The function checks that CHECKED_SET satisfies all absence pattern
4299 sets for units in ORIGIONAL_SET. The function returns TRUE if it
4302 check_absence_pattern_sets (reserv_sets_t checked_set
,
4303 reserv_sets_t origional_set
,
4311 pattern_reserv_t pat_reserv
;
4313 chars_num
= els_in_cycle_reserv
* sizeof (set_el_t
);
4314 for (char_num
= 0; char_num
< chars_num
; char_num
++)
4315 if (((unsigned char *) origional_set
) [char_num
])
4316 for (i
= CHAR_BIT
- 1; i
>= 0; i
--)
4317 if ((((unsigned char *) origional_set
) [char_num
] >> i
) & 1)
4319 start_unit_num
= char_num
* CHAR_BIT
+ i
;
4320 if (start_unit_num
>= description
->units_num
)
4322 for (pat_reserv
= (final_p
4323 ? unit_final_absence_set_table
[start_unit_num
]
4324 : unit_absence_set_table
[start_unit_num
]);
4326 pat_reserv
= pat_reserv
->next_pattern_reserv
)
4328 for (unit_num
= 0; unit_num
< els_in_cycle_reserv
; unit_num
++)
4329 if ((checked_set
[unit_num
] & pat_reserv
->reserv
[unit_num
])
4330 != pat_reserv
->reserv
[unit_num
]
4331 && pat_reserv
->reserv
[unit_num
])
4333 if (unit_num
>= els_in_cycle_reserv
)
4342 /* This page contains code for transformation of original reservations
4343 described in .md file. The main goal of transformations is
4344 simplifying reservation and lifting up all `|' on the top of IR
4345 reservation representation. */
4348 /* The following function makes copy of IR representation of
4349 reservation. The function also substitutes all reservations
4350 defined by define_reservation by corresponding value during making
4353 copy_insn_regexp (regexp_t regexp
)
4358 switch (regexp
->mode
)
4361 result
= copy_insn_regexp (REGEXP_RESERV (regexp
)->reserv_decl
->regexp
);
4365 result
= copy_node (regexp
, sizeof (struct regexp
));
4369 result
= copy_node (regexp
, sizeof (struct regexp
));
4370 REGEXP_REPEAT (result
)->regexp
4371 = copy_insn_regexp (REGEXP_REPEAT (regexp
)->regexp
);
4375 result
= copy_node (regexp
,
4376 sizeof (struct regexp
) + sizeof (regexp_t
)
4377 * (REGEXP_SEQUENCE (regexp
)->regexps_num
- 1));
4378 for (i
= 0; i
<REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
4379 REGEXP_SEQUENCE (result
)->regexps
[i
]
4380 = copy_insn_regexp (REGEXP_SEQUENCE (regexp
)->regexps
[i
]);
4384 result
= copy_node (regexp
,
4385 sizeof (struct regexp
) + sizeof (regexp_t
)
4386 * (REGEXP_ALLOF (regexp
)->regexps_num
- 1));
4387 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
4388 REGEXP_ALLOF (result
)->regexps
[i
]
4389 = copy_insn_regexp (REGEXP_ALLOF (regexp
)->regexps
[i
]);
4393 result
= copy_node (regexp
,
4394 sizeof (struct regexp
) + sizeof (regexp_t
)
4395 * (REGEXP_ONEOF (regexp
)->regexps_num
- 1));
4396 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
4397 REGEXP_ONEOF (result
)->regexps
[i
]
4398 = copy_insn_regexp (REGEXP_ONEOF (regexp
)->regexps
[i
]);
4402 result
= copy_node (regexp
, sizeof (struct regexp
));
4411 /* The following variable is set up 1 if a transformation has been
4413 static int regexp_transformed_p
;
4415 /* The function makes transformation
4418 transform_1 (regexp_t regexp
)
4425 if (regexp
->mode
== rm_repeat
)
4427 repeat_num
= REGEXP_REPEAT (regexp
)->repeat_num
;
4428 gcc_assert (repeat_num
> 1);
4429 operand
= REGEXP_REPEAT (regexp
)->regexp
;
4431 regexp
= create_node (sizeof (struct regexp
) + sizeof (regexp_t
)
4432 * (repeat_num
- 1));
4433 regexp
->mode
= rm_sequence
;
4435 REGEXP_SEQUENCE (regexp
)->regexps_num
= repeat_num
;
4436 for (i
= 0; i
< repeat_num
; i
++)
4437 REGEXP_SEQUENCE (regexp
)->regexps
[i
] = copy_insn_regexp (operand
);
4438 regexp_transformed_p
= 1;
4443 /* The function makes transformations
4444 ...,(A,B,...),C,... -> ...,A,B,...,C,...
4445 ...+(A+B+...)+C+... -> ...+A+B+...+C+...
4446 ...|(A|B|...)|C|... -> ...|A|B|...|C|... */
4448 transform_2 (regexp_t regexp
)
4450 if (regexp
->mode
== rm_sequence
)
4452 regexp_t sequence
= NULL
;
4454 int sequence_index
= 0;
4457 for (i
= 0; i
< REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
4458 if (REGEXP_SEQUENCE (regexp
)->regexps
[i
]->mode
== rm_sequence
)
4461 sequence
= REGEXP_SEQUENCE (regexp
)->regexps
[i
];
4464 if (i
< REGEXP_SEQUENCE (regexp
)->regexps_num
)
4466 gcc_assert (REGEXP_SEQUENCE (sequence
)->regexps_num
> 1
4467 && REGEXP_SEQUENCE (regexp
)->regexps_num
> 1);
4468 result
= create_node (sizeof (struct regexp
)
4470 * (REGEXP_SEQUENCE (regexp
)->regexps_num
4471 + REGEXP_SEQUENCE (sequence
)->regexps_num
4473 result
->mode
= rm_sequence
;
4474 result
->pos
= regexp
->pos
;
4475 REGEXP_SEQUENCE (result
)->regexps_num
4476 = (REGEXP_SEQUENCE (regexp
)->regexps_num
4477 + REGEXP_SEQUENCE (sequence
)->regexps_num
- 1);
4478 for (i
= 0; i
< REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
4479 if (i
< sequence_index
)
4480 REGEXP_SEQUENCE (result
)->regexps
[i
]
4481 = copy_insn_regexp (REGEXP_SEQUENCE (regexp
)->regexps
[i
]);
4482 else if (i
> sequence_index
)
4483 REGEXP_SEQUENCE (result
)->regexps
4484 [i
+ REGEXP_SEQUENCE (sequence
)->regexps_num
- 1]
4485 = copy_insn_regexp (REGEXP_SEQUENCE (regexp
)->regexps
[i
]);
4487 for (j
= 0; j
< REGEXP_SEQUENCE (sequence
)->regexps_num
; j
++)
4488 REGEXP_SEQUENCE (result
)->regexps
[i
+ j
]
4489 = copy_insn_regexp (REGEXP_SEQUENCE (sequence
)->regexps
[j
]);
4490 regexp_transformed_p
= 1;
4494 else if (regexp
->mode
== rm_allof
)
4496 regexp_t allof
= NULL
;
4498 int allof_index
= 0;
4501 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
4502 if (REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
== rm_allof
)
4505 allof
= REGEXP_ALLOF (regexp
)->regexps
[i
];
4508 if (i
< REGEXP_ALLOF (regexp
)->regexps_num
)
4510 gcc_assert (REGEXP_ALLOF (allof
)->regexps_num
> 1
4511 && REGEXP_ALLOF (regexp
)->regexps_num
> 1);
4512 result
= create_node (sizeof (struct regexp
)
4514 * (REGEXP_ALLOF (regexp
)->regexps_num
4515 + REGEXP_ALLOF (allof
)->regexps_num
- 2));
4516 result
->mode
= rm_allof
;
4517 result
->pos
= regexp
->pos
;
4518 REGEXP_ALLOF (result
)->regexps_num
4519 = (REGEXP_ALLOF (regexp
)->regexps_num
4520 + REGEXP_ALLOF (allof
)->regexps_num
- 1);
4521 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
4522 if (i
< allof_index
)
4523 REGEXP_ALLOF (result
)->regexps
[i
]
4524 = copy_insn_regexp (REGEXP_ALLOF (regexp
)->regexps
[i
]);
4525 else if (i
> allof_index
)
4526 REGEXP_ALLOF (result
)->regexps
4527 [i
+ REGEXP_ALLOF (allof
)->regexps_num
- 1]
4528 = copy_insn_regexp (REGEXP_ALLOF (regexp
)->regexps
[i
]);
4530 for (j
= 0; j
< REGEXP_ALLOF (allof
)->regexps_num
; j
++)
4531 REGEXP_ALLOF (result
)->regexps
[i
+ j
]
4532 = copy_insn_regexp (REGEXP_ALLOF (allof
)->regexps
[j
]);
4533 regexp_transformed_p
= 1;
4537 else if (regexp
->mode
== rm_oneof
)
4539 regexp_t oneof
= NULL
;
4541 int oneof_index
= 0;
4544 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
4545 if (REGEXP_ONEOF (regexp
)->regexps
[i
]->mode
== rm_oneof
)
4548 oneof
= REGEXP_ONEOF (regexp
)->regexps
[i
];
4551 if (i
< REGEXP_ONEOF (regexp
)->regexps_num
)
4553 gcc_assert (REGEXP_ONEOF (oneof
)->regexps_num
> 1
4554 && REGEXP_ONEOF (regexp
)->regexps_num
> 1);
4555 result
= create_node (sizeof (struct regexp
)
4557 * (REGEXP_ONEOF (regexp
)->regexps_num
4558 + REGEXP_ONEOF (oneof
)->regexps_num
- 2));
4559 result
->mode
= rm_oneof
;
4560 result
->pos
= regexp
->pos
;
4561 REGEXP_ONEOF (result
)->regexps_num
4562 = (REGEXP_ONEOF (regexp
)->regexps_num
4563 + REGEXP_ONEOF (oneof
)->regexps_num
- 1);
4564 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
4565 if (i
< oneof_index
)
4566 REGEXP_ONEOF (result
)->regexps
[i
]
4567 = copy_insn_regexp (REGEXP_ONEOF (regexp
)->regexps
[i
]);
4568 else if (i
> oneof_index
)
4569 REGEXP_ONEOF (result
)->regexps
4570 [i
+ REGEXP_ONEOF (oneof
)->regexps_num
- 1]
4571 = copy_insn_regexp (REGEXP_ONEOF (regexp
)->regexps
[i
]);
4573 for (j
= 0; j
< REGEXP_ONEOF (oneof
)->regexps_num
; j
++)
4574 REGEXP_ONEOF (result
)->regexps
[i
+ j
]
4575 = copy_insn_regexp (REGEXP_ONEOF (oneof
)->regexps
[j
]);
4576 regexp_transformed_p
= 1;
4583 /* The function makes transformations
4584 ...,A|B|...,C,... -> (...,A,C,...)|(...,B,C,...)|...
4585 ...+(A|B|...)+C+... -> (...+A+C+...)|(...+B+C+...)|...
4586 ...+(A,B,...)+C+... -> (...+A+C+...),B,...
4587 ...+(A,B,...)+(C,D,...) -> (A+C),(B+D),... */
4589 transform_3 (regexp_t regexp
)
4591 if (regexp
->mode
== rm_sequence
)
4593 regexp_t oneof
= NULL
;
4594 int oneof_index
= 0;
4599 for (i
= 0; i
<REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
4600 if (REGEXP_SEQUENCE (regexp
)->regexps
[i
]->mode
== rm_oneof
)
4603 oneof
= REGEXP_SEQUENCE (regexp
)->regexps
[i
];
4606 if (i
< REGEXP_SEQUENCE (regexp
)->regexps_num
)
4608 gcc_assert (REGEXP_ONEOF (oneof
)->regexps_num
> 1
4609 && REGEXP_SEQUENCE (regexp
)->regexps_num
> 1);
4610 result
= create_node (sizeof (struct regexp
)
4612 * (REGEXP_ONEOF (oneof
)->regexps_num
- 1));
4613 result
->mode
= rm_oneof
;
4614 result
->pos
= regexp
->pos
;
4615 REGEXP_ONEOF (result
)->regexps_num
4616 = REGEXP_ONEOF (oneof
)->regexps_num
;
4617 for (i
= 0; i
< REGEXP_ONEOF (result
)->regexps_num
; i
++)
4620 = create_node (sizeof (struct regexp
)
4622 * (REGEXP_SEQUENCE (regexp
)->regexps_num
- 1));
4623 sequence
->mode
= rm_sequence
;
4624 sequence
->pos
= regexp
->pos
;
4625 REGEXP_SEQUENCE (sequence
)->regexps_num
4626 = REGEXP_SEQUENCE (regexp
)->regexps_num
;
4627 REGEXP_ONEOF (result
)->regexps
[i
] = sequence
;
4628 for (j
= 0; j
< REGEXP_SEQUENCE (sequence
)->regexps_num
; j
++)
4629 if (j
!= oneof_index
)
4630 REGEXP_SEQUENCE (sequence
)->regexps
[j
]
4631 = copy_insn_regexp (REGEXP_SEQUENCE (regexp
)->regexps
[j
]);
4633 REGEXP_SEQUENCE (sequence
)->regexps
[j
]
4634 = copy_insn_regexp (REGEXP_ONEOF (oneof
)->regexps
[i
]);
4636 regexp_transformed_p
= 1;
4640 else if (regexp
->mode
== rm_allof
)
4642 regexp_t oneof
= NULL
;
4644 int oneof_index
= 0;
4645 int max_seq_length
, allof_length
;
4647 regexp_t allof
= NULL
;
4648 regexp_t allof_op
= NULL
;
4651 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
4652 if (REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
== rm_oneof
)
4655 oneof
= REGEXP_ALLOF (regexp
)->regexps
[i
];
4658 if (i
< REGEXP_ALLOF (regexp
)->regexps_num
)
4660 gcc_assert (REGEXP_ONEOF (oneof
)->regexps_num
> 1
4661 && REGEXP_ALLOF (regexp
)->regexps_num
> 1);
4662 result
= create_node (sizeof (struct regexp
)
4664 * (REGEXP_ONEOF (oneof
)->regexps_num
- 1));
4665 result
->mode
= rm_oneof
;
4666 result
->pos
= regexp
->pos
;
4667 REGEXP_ONEOF (result
)->regexps_num
4668 = REGEXP_ONEOF (oneof
)->regexps_num
;
4669 for (i
= 0; i
< REGEXP_ONEOF (result
)->regexps_num
; i
++)
4672 = create_node (sizeof (struct regexp
)
4674 * (REGEXP_ALLOF (regexp
)->regexps_num
- 1));
4675 allof
->mode
= rm_allof
;
4676 allof
->pos
= regexp
->pos
;
4677 REGEXP_ALLOF (allof
)->regexps_num
4678 = REGEXP_ALLOF (regexp
)->regexps_num
;
4679 REGEXP_ONEOF (result
)->regexps
[i
] = allof
;
4680 for (j
= 0; j
< REGEXP_ALLOF (allof
)->regexps_num
; j
++)
4681 if (j
!= oneof_index
)
4682 REGEXP_ALLOF (allof
)->regexps
[j
]
4683 = copy_insn_regexp (REGEXP_ALLOF (regexp
)->regexps
[j
]);
4685 REGEXP_ALLOF (allof
)->regexps
[j
]
4686 = copy_insn_regexp (REGEXP_ONEOF (oneof
)->regexps
[i
]);
4688 regexp_transformed_p
= 1;
4692 if (regexp
->mode
== rm_allof
)
4693 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
4695 switch (REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
)
4698 seq
= REGEXP_ALLOF (regexp
)->regexps
[i
];
4699 if (max_seq_length
< REGEXP_SEQUENCE (seq
)->regexps_num
)
4700 max_seq_length
= REGEXP_SEQUENCE (seq
)->regexps_num
;
4713 if (max_seq_length
!= 0)
4715 gcc_assert (max_seq_length
!= 1
4716 && REGEXP_ALLOF (regexp
)->regexps_num
> 1);
4717 result
= create_node (sizeof (struct regexp
)
4718 + sizeof (regexp_t
) * (max_seq_length
- 1));
4719 result
->mode
= rm_sequence
;
4720 result
->pos
= regexp
->pos
;
4721 REGEXP_SEQUENCE (result
)->regexps_num
= max_seq_length
;
4722 for (i
= 0; i
< max_seq_length
; i
++)
4725 for (j
= 0; j
< REGEXP_ALLOF (regexp
)->regexps_num
; j
++)
4726 switch (REGEXP_ALLOF (regexp
)->regexps
[j
]->mode
)
4729 if (i
< (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp
)
4730 ->regexps
[j
])->regexps_num
))
4733 = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp
)
4743 allof_op
= REGEXP_ALLOF (regexp
)->regexps
[j
];
4751 if (allof_length
== 1)
4752 REGEXP_SEQUENCE (result
)->regexps
[i
] = allof_op
;
4755 allof
= create_node (sizeof (struct regexp
)
4757 * (allof_length
- 1));
4758 allof
->mode
= rm_allof
;
4759 allof
->pos
= regexp
->pos
;
4760 REGEXP_ALLOF (allof
)->regexps_num
= allof_length
;
4761 REGEXP_SEQUENCE (result
)->regexps
[i
] = allof
;
4763 for (j
= 0; j
< REGEXP_ALLOF (regexp
)->regexps_num
; j
++)
4764 if (REGEXP_ALLOF (regexp
)->regexps
[j
]->mode
== rm_sequence
4766 (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp
)
4767 ->regexps
[j
])->regexps_num
)))
4769 allof_op
= (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp
)
4772 REGEXP_ALLOF (allof
)->regexps
[allof_length
]
4777 && (REGEXP_ALLOF (regexp
)->regexps
[j
]->mode
4779 || (REGEXP_ALLOF (regexp
)->regexps
[j
]->mode
4782 allof_op
= REGEXP_ALLOF (regexp
)->regexps
[j
];
4783 REGEXP_ALLOF (allof
)->regexps
[allof_length
]
4789 regexp_transformed_p
= 1;
4796 /* The function traverses IR of reservation and applies transformations
4797 implemented by FUNC. */
4799 regexp_transform_func (regexp_t regexp
, regexp_t (*func
) (regexp_t regexp
))
4803 switch (regexp
->mode
)
4806 for (i
= 0; i
< REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
4807 REGEXP_SEQUENCE (regexp
)->regexps
[i
]
4808 = regexp_transform_func (REGEXP_SEQUENCE (regexp
)->regexps
[i
],
4813 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
4814 REGEXP_ALLOF (regexp
)->regexps
[i
]
4815 = regexp_transform_func (REGEXP_ALLOF (regexp
)->regexps
[i
], func
);
4819 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
4820 REGEXP_ONEOF (regexp
)->regexps
[i
]
4821 = regexp_transform_func (REGEXP_ONEOF (regexp
)->regexps
[i
], func
);
4825 REGEXP_REPEAT (regexp
)->regexp
4826 = regexp_transform_func (REGEXP_REPEAT (regexp
)->regexp
, func
);
4836 return (*func
) (regexp
);
4839 /* The function applies all transformations for IR representation of
4840 reservation REGEXP. */
4842 transform_regexp (regexp_t regexp
)
4844 regexp
= regexp_transform_func (regexp
, transform_1
);
4847 regexp_transformed_p
= 0;
4848 regexp
= regexp_transform_func (regexp
, transform_2
);
4849 regexp
= regexp_transform_func (regexp
, transform_3
);
4851 while (regexp_transformed_p
);
4855 /* The function applies all transformations for reservations of all
4856 insn declarations. */
4858 transform_insn_regexps (void)
4863 transform_time
= create_ticker ();
4864 add_advance_cycle_insn_decl ();
4866 fprintf (stderr
, "Reservation transformation...");
4867 for (i
= 0; i
< description
->decls_num
; i
++)
4869 decl
= description
->decls
[i
];
4870 if (decl
->mode
== dm_insn_reserv
&& decl
!= advance_cycle_insn_decl
)
4871 DECL_INSN_RESERV (decl
)->transformed_regexp
4872 = transform_regexp (copy_insn_regexp
4873 (DECL_INSN_RESERV (decl
)->regexp
));
4876 fprintf (stderr
, "done\n");
4877 ticker_off (&transform_time
);
4882 /* The following variable value is TRUE if the first annotated message
4883 about units to automata distribution has been output. */
4884 static int annotation_message_reported_p
;
4886 /* The following structure describes usage of a unit in a reservation. */
4889 unit_decl_t unit_decl
;
4890 /* The following forms a list of units used on the same cycle in the
4891 same alternative. */
4892 struct unit_usage
*next
;
4894 typedef struct unit_usage
*unit_usage_t
;
4896 DEF_VEC_P(unit_usage_t
);
4897 DEF_VEC_ALLOC_P(unit_usage_t
,heap
);
4899 /* Obstack for unit_usage structures. */
4900 static struct obstack unit_usages
;
4902 /* VLA for representation of array of pointers to unit usage
4903 structures. There is an element for each combination of
4904 (alternative number, cycle). Unit usages on given cycle in
4905 alternative with given number are referred through element with
4906 index equals to the cycle * number of all alternatives in the regexp
4907 + the alternative number. */
4908 static VEC(unit_usage_t
,heap
) *cycle_alt_unit_usages
;
4910 /* The following function creates the structure unit_usage for UNIT on
4911 CYCLE in REGEXP alternative with ALT_NUM. The structure is made
4912 accessed through cycle_alt_unit_usages. */
4914 store_alt_unit_usage (regexp_t regexp
, regexp_t unit
, int cycle
,
4918 unit_decl_t unit_decl
;
4919 unit_usage_t unit_usage_ptr
;
4922 gcc_assert (regexp
&& regexp
->mode
== rm_oneof
4923 && alt_num
< REGEXP_ONEOF (regexp
)->regexps_num
);
4924 unit_decl
= REGEXP_UNIT (unit
)->unit_decl
;
4926 length
= (cycle
+ 1) * REGEXP_ONEOF (regexp
)->regexps_num
;
4927 while (VEC_length (unit_usage_t
, cycle_alt_unit_usages
) < length
)
4928 VEC_safe_push (unit_usage_t
,heap
, cycle_alt_unit_usages
, 0);
4930 obstack_blank (&unit_usages
, sizeof (struct unit_usage
));
4931 unit_usage_ptr
= (struct unit_usage
*) obstack_base (&unit_usages
);
4932 obstack_finish (&unit_usages
);
4933 unit_usage_ptr
->unit_decl
= unit_decl
;
4934 index
= cycle
* REGEXP_ONEOF (regexp
)->regexps_num
+ alt_num
;
4935 unit_usage_ptr
->next
= VEC_index (unit_usage_t
, cycle_alt_unit_usages
, index
);
4936 VEC_replace (unit_usage_t
, cycle_alt_unit_usages
, index
, unit_usage_ptr
);
4937 unit_decl
->last_distribution_check_cycle
= -1; /* undefined */
4940 /* The function processes given REGEXP to find units with the wrong
4943 check_regexp_units_distribution (const char *insn_reserv_name
,
4947 regexp_t seq
, allof
, unit
;
4948 struct unit_usage
*unit_usage_ptr
, *other_unit_usage_ptr
;
4950 if (regexp
== NULL
|| regexp
->mode
!= rm_oneof
)
4952 /* Store all unit usages in the regexp: */
4953 obstack_init (&unit_usages
);
4954 cycle_alt_unit_usages
= 0;
4956 for (i
= REGEXP_ONEOF (regexp
)->regexps_num
- 1; i
>= 0; i
--)
4958 seq
= REGEXP_ONEOF (regexp
)->regexps
[i
];
4962 for (j
= 0; j
< REGEXP_SEQUENCE (seq
)->regexps_num
; j
++)
4964 allof
= REGEXP_SEQUENCE (seq
)->regexps
[j
];
4965 switch (allof
->mode
)
4968 for (k
= 0; k
< REGEXP_ALLOF (allof
)->regexps_num
; k
++)
4970 unit
= REGEXP_ALLOF (allof
)->regexps
[k
];
4971 if (unit
->mode
== rm_unit
)
4972 store_alt_unit_usage (regexp
, unit
, j
, i
);
4974 gcc_assert (unit
->mode
== rm_nothing
);
4979 store_alt_unit_usage (regexp
, allof
, j
, i
);
4992 for (k
= 0; k
< REGEXP_ALLOF (seq
)->regexps_num
; k
++)
4994 unit
= REGEXP_ALLOF (seq
)->regexps
[k
];
4998 store_alt_unit_usage (regexp
, unit
, 0, i
);
5011 store_alt_unit_usage (regexp
, seq
, 0, i
);
5021 /* Check distribution: */
5022 for (i
= 0; i
< (int) VEC_length (unit_usage_t
, cycle_alt_unit_usages
); i
++)
5024 cycle
= i
/ REGEXP_ONEOF (regexp
)->regexps_num
;
5025 for (unit_usage_ptr
= VEC_index (unit_usage_t
, cycle_alt_unit_usages
, i
);
5026 unit_usage_ptr
!= NULL
;
5027 unit_usage_ptr
= unit_usage_ptr
->next
)
5028 if (cycle
!= unit_usage_ptr
->unit_decl
->last_distribution_check_cycle
)
5030 unit_usage_ptr
->unit_decl
->last_distribution_check_cycle
= cycle
;
5031 for (k
= cycle
* REGEXP_ONEOF (regexp
)->regexps_num
;
5032 k
< (int) VEC_length (unit_usage_t
, cycle_alt_unit_usages
)
5033 && k
== cycle
* REGEXP_ONEOF (regexp
)->regexps_num
;
5036 for (other_unit_usage_ptr
5037 = VEC_index (unit_usage_t
, cycle_alt_unit_usages
, k
);
5038 other_unit_usage_ptr
!= NULL
;
5039 other_unit_usage_ptr
= other_unit_usage_ptr
->next
)
5040 if (unit_usage_ptr
->unit_decl
->automaton_decl
5041 == other_unit_usage_ptr
->unit_decl
->automaton_decl
)
5043 if (other_unit_usage_ptr
== NULL
5044 && (VEC_index (unit_usage_t
, cycle_alt_unit_usages
, k
)
5048 if (k
< (int) VEC_length (unit_usage_t
, cycle_alt_unit_usages
)
5049 && k
== cycle
* REGEXP_ONEOF (regexp
)->regexps_num
)
5051 if (!annotation_message_reported_p
)
5053 fprintf (stderr
, "\n");
5054 error ("The following units do not satisfy units-automata distribution rule");
5055 error (" (A unit of given unit automaton should be on each reserv. altern.)");
5056 annotation_message_reported_p
= TRUE
;
5058 error ("Unit %s, reserv. %s, cycle %d",
5059 unit_usage_ptr
->unit_decl
->name
, insn_reserv_name
,
5064 VEC_free (unit_usage_t
,heap
, cycle_alt_unit_usages
);
5065 obstack_free (&unit_usages
, NULL
);
5068 /* The function finds units which violates units to automata
5069 distribution rule. If the units exist, report about them. */
5071 check_unit_distributions_to_automata (void)
5077 fprintf (stderr
, "Check unit distributions to automata...");
5078 annotation_message_reported_p
= FALSE
;
5079 for (i
= 0; i
< description
->decls_num
; i
++)
5081 decl
= description
->decls
[i
];
5082 if (decl
->mode
== dm_insn_reserv
)
5083 check_regexp_units_distribution
5084 (DECL_INSN_RESERV (decl
)->name
,
5085 DECL_INSN_RESERV (decl
)->transformed_regexp
);
5088 fprintf (stderr
, "done\n");
5093 /* The page contains code for building alt_states (see comments for
5094 IR) describing all possible insns reservations of an automaton. */
5096 /* Current state being formed for which the current alt_state
5098 static state_t state_being_formed
;
5100 /* Current alt_state being formed. */
5101 static alt_state_t alt_state_being_formed
;
5103 /* This recursive function processes `,' and units in reservation
5104 REGEXP for forming alt_states of AUTOMATON. It is believed that
5105 CURR_CYCLE is start cycle of all reservation REGEXP. */
5107 process_seq_for_forming_states (regexp_t regexp
, automaton_t automaton
,
5115 switch (regexp
->mode
)
5118 if (REGEXP_UNIT (regexp
)->unit_decl
->corresponding_automaton_num
5119 == automaton
->automaton_order_num
)
5120 set_state_reserv (state_being_formed
, curr_cycle
,
5121 REGEXP_UNIT (regexp
)->unit_decl
->unit_num
);
5125 for (i
= 0; i
< REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
5127 = process_seq_for_forming_states
5128 (REGEXP_SEQUENCE (regexp
)->regexps
[i
], automaton
, curr_cycle
) + 1;
5133 int finish_cycle
= 0;
5136 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
5138 cycle
= process_seq_for_forming_states (REGEXP_ALLOF (regexp
)
5140 automaton
, curr_cycle
);
5141 if (finish_cycle
< cycle
)
5142 finish_cycle
= cycle
;
5144 return finish_cycle
;
5155 /* This recursive function finishes forming ALT_STATE of AUTOMATON and
5156 inserts alt_state into the table. */
5158 finish_forming_alt_state (alt_state_t alt_state
,
5159 automaton_t automaton ATTRIBUTE_UNUSED
)
5161 state_t state_in_table
;
5162 state_t corresponding_state
;
5164 corresponding_state
= alt_state
->state
;
5165 state_in_table
= insert_state (corresponding_state
);
5166 if (state_in_table
!= corresponding_state
)
5168 free_state (corresponding_state
);
5169 alt_state
->state
= state_in_table
;
5173 /* The following variable value is current automaton insn for whose
5174 reservation the alt states are created. */
5175 static ainsn_t curr_ainsn
;
5177 /* This recursive function processes `|' in reservation REGEXP for
5178 forming alt_states of AUTOMATON. List of the alt states should
5179 have the same order as in the description. */
5181 process_alts_for_forming_states (regexp_t regexp
, automaton_t automaton
,
5186 if (regexp
->mode
!= rm_oneof
)
5188 alt_state_being_formed
= get_free_alt_state ();
5189 state_being_formed
= get_free_state (1, automaton
);
5190 alt_state_being_formed
->state
= state_being_formed
;
5191 /* We inserts in reverse order but we process alternatives also
5192 in reverse order. So we have the same order of alternative
5193 as in the description. */
5194 alt_state_being_formed
->next_alt_state
= curr_ainsn
->alt_states
;
5195 curr_ainsn
->alt_states
= alt_state_being_formed
;
5196 (void) process_seq_for_forming_states (regexp
, automaton
, 0);
5197 finish_forming_alt_state (alt_state_being_formed
, automaton
);
5201 gcc_assert (!inside_oneof_p
);
5202 /* We processes it in reverse order to get list with the same
5203 order as in the description. See also the previous
5205 for (i
= REGEXP_ONEOF (regexp
)->regexps_num
- 1; i
>= 0; i
--)
5206 process_alts_for_forming_states (REGEXP_ONEOF (regexp
)->regexps
[i
],
5211 /* Create nodes alt_state for all AUTOMATON insns. */
5213 create_alt_states (automaton_t automaton
)
5215 struct insn_reserv_decl
*reserv_decl
;
5217 for (curr_ainsn
= automaton
->ainsn_list
;
5219 curr_ainsn
= curr_ainsn
->next_ainsn
)
5221 reserv_decl
= curr_ainsn
->insn_reserv_decl
;
5222 if (reserv_decl
!= DECL_INSN_RESERV (advance_cycle_insn_decl
))
5224 curr_ainsn
->alt_states
= NULL
;
5225 process_alts_for_forming_states (reserv_decl
->transformed_regexp
,
5227 curr_ainsn
->sorted_alt_states
5228 = uniq_sort_alt_states (curr_ainsn
->alt_states
);
5235 /* The page contains major code for building DFA(s) for fast pipeline
5236 hazards recognition. */
5238 /* The function forms list of ainsns of AUTOMATON with the same
5242 form_ainsn_with_same_reservs (automaton_t automaton
)
5246 VEC(ainsn_t
,heap
) *last_insns
= VEC_alloc (ainsn_t
,heap
, 150);
5248 for (curr_ainsn
= automaton
->ainsn_list
;
5250 curr_ainsn
= curr_ainsn
->next_ainsn
)
5251 if (curr_ainsn
->insn_reserv_decl
5252 == DECL_INSN_RESERV (advance_cycle_insn_decl
))
5254 curr_ainsn
->next_same_reservs_insn
= NULL
;
5255 curr_ainsn
->first_insn_with_same_reservs
= 1;
5259 for (i
= 0; i
< VEC_length (ainsn_t
, last_insns
); i
++)
5261 (curr_ainsn
->sorted_alt_states
,
5262 VEC_index (ainsn_t
, last_insns
, i
)->sorted_alt_states
))
5264 curr_ainsn
->next_same_reservs_insn
= NULL
;
5265 if (i
< VEC_length (ainsn_t
, last_insns
))
5267 curr_ainsn
->first_insn_with_same_reservs
= 0;
5268 VEC_index (ainsn_t
, last_insns
, i
)->next_same_reservs_insn
5270 VEC_replace (ainsn_t
, last_insns
, i
, curr_ainsn
);
5274 VEC_safe_push (ainsn_t
, heap
, last_insns
, curr_ainsn
);
5275 curr_ainsn
->first_insn_with_same_reservs
= 1;
5278 VEC_free (ainsn_t
,heap
, last_insns
);
5281 /* Forming unit reservations which can affect creating the automaton
5282 states achieved from a given state. It permits to build smaller
5283 automata in many cases. We would have the same automata after
5284 the minimization without such optimization, but the automaton
5285 right after the building could be huge. So in other words, usage
5286 of reservs_matter means some minimization during building the
5288 static reserv_sets_t
5289 form_reservs_matter (automaton_t automaton
)
5292 reserv_sets_t reservs_matter
= alloc_empty_reserv_sets();
5294 for (cycle
= 0; cycle
< max_cycles_num
; cycle
++)
5295 for (unit
= 0; unit
< description
->units_num
; unit
++)
5296 if (units_array
[unit
]->automaton_decl
5297 == automaton
->corresponding_automaton_decl
5298 && (cycle
>= units_array
[unit
]->min_occ_cycle_num
5299 /* We can not remove queried unit from reservations. */
5300 || units_array
[unit
]->query_p
5301 /* We can not remove units which are used
5302 `exclusion_set', `presence_set',
5303 `final_presence_set', `absence_set', and
5304 `final_absence_set'. */
5305 || units_array
[unit
]->in_set_p
))
5306 set_unit_reserv (reservs_matter
, cycle
, unit
);
5307 return reservs_matter
;
5310 /* The following function creates all states of nondeterministic AUTOMATON. */
5312 make_automaton (automaton_t automaton
)
5315 struct insn_reserv_decl
*insn_reserv_decl
;
5316 alt_state_t alt_state
;
5318 state_t start_state
;
5320 ainsn_t advance_cycle_ainsn
;
5322 VEC(state_t
,heap
) *state_stack
= VEC_alloc(state_t
,heap
, 150);
5324 reserv_sets_t reservs_matter
= form_reservs_matter (automaton
);
5326 /* Create the start state (empty state). */
5327 start_state
= insert_state (get_free_state (1, automaton
));
5328 automaton
->start_state
= start_state
;
5329 start_state
->it_was_placed_in_stack_for_NDFA_forming
= 1;
5330 VEC_safe_push (state_t
,heap
, state_stack
, start_state
);
5332 while (VEC_length (state_t
, state_stack
) != 0)
5334 state
= VEC_pop (state_t
, state_stack
);
5335 advance_cycle_ainsn
= NULL
;
5336 for (ainsn
= automaton
->ainsn_list
;
5338 ainsn
= ainsn
->next_ainsn
)
5339 if (ainsn
->first_insn_with_same_reservs
)
5341 insn_reserv_decl
= ainsn
->insn_reserv_decl
;
5342 if (insn_reserv_decl
!= DECL_INSN_RESERV (advance_cycle_insn_decl
))
5344 /* We process alt_states in the same order as they are
5345 present in the description. */
5347 for (alt_state
= ainsn
->alt_states
;
5349 alt_state
= alt_state
->next_alt_state
)
5351 state2
= alt_state
->state
;
5352 if (!intersected_state_reservs_p (state
, state2
))
5354 state2
= states_union (state
, state2
, reservs_matter
);
5355 if (!state2
->it_was_placed_in_stack_for_NDFA_forming
)
5357 state2
->it_was_placed_in_stack_for_NDFA_forming
5359 VEC_safe_push (state_t
,heap
, state_stack
, state2
);
5361 if (progress_flag
&& states_n
% 100 == 0)
5362 fprintf (stderr
, ".");
5364 added_arc
= add_arc (state
, state2
, ainsn
);
5369 if (!ndfa_flag
&& added_arc
!= NULL
)
5371 for (alt_state
= ainsn
->alt_states
;
5373 alt_state
= alt_state
->next_alt_state
)
5374 state2
= alt_state
->state
;
5378 advance_cycle_ainsn
= ainsn
;
5380 /* Add transition to advance cycle. */
5381 state2
= state_shift (state
, reservs_matter
);
5382 if (!state2
->it_was_placed_in_stack_for_NDFA_forming
)
5384 state2
->it_was_placed_in_stack_for_NDFA_forming
= 1;
5385 VEC_safe_push (state_t
,heap
, state_stack
, state2
);
5387 if (progress_flag
&& states_n
% 100 == 0)
5388 fprintf (stderr
, ".");
5390 gcc_assert (advance_cycle_ainsn
);
5391 add_arc (state
, state2
, advance_cycle_ainsn
);
5393 VEC_free (state_t
,heap
, state_stack
);
5396 /* Foms lists of all arcs of STATE marked by the same ainsn. */
5398 form_arcs_marked_by_insn (state_t state
)
5404 for (i
= 0; i
< description
->decls_num
; i
++)
5406 decl
= description
->decls
[i
];
5407 if (decl
->mode
== dm_insn_reserv
)
5408 DECL_INSN_RESERV (decl
)->arcs_marked_by_insn
= NULL
;
5410 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
5412 gcc_assert (arc
->insn
);
5413 arc
->next_arc_marked_by_insn
5414 = arc
->insn
->insn_reserv_decl
->arcs_marked_by_insn
;
5415 arc
->insn
->insn_reserv_decl
->arcs_marked_by_insn
= arc
;
5419 /* The function creates composed state (see comments for IR) from
5420 ORIGINAL_STATE and list of arcs ARCS_MARKED_BY_INSN marked by the
5421 same insn. If the composed state is not in STATE_STACK yet, it is
5422 pushed into STATE_STACK. */
5425 create_composed_state (state_t original_state
, arc_t arcs_marked_by_insn
,
5426 VEC(state_t
,heap
) **state_stack
)
5429 alt_state_t alt_state
, curr_alt_state
;
5430 alt_state_t new_alt_state
;
5433 state_t state_in_table
;
5435 alt_state_t canonical_alt_states_list
;
5437 int new_state_p
= 0;
5439 if (arcs_marked_by_insn
== NULL
)
5441 if (arcs_marked_by_insn
->next_arc_marked_by_insn
== NULL
)
5442 state
= arcs_marked_by_insn
->to_state
;
5445 gcc_assert (ndfa_flag
);
5446 /* Create composed state. */
5447 state
= get_free_state (0, arcs_marked_by_insn
->to_state
->automaton
);
5448 curr_alt_state
= NULL
;
5449 for (curr_arc
= arcs_marked_by_insn
;
5451 curr_arc
= curr_arc
->next_arc_marked_by_insn
)
5452 if (curr_arc
->to_state
->component_states
== NULL
)
5454 new_alt_state
= get_free_alt_state ();
5455 new_alt_state
->next_alt_state
= curr_alt_state
;
5456 new_alt_state
->state
= curr_arc
->to_state
;
5457 curr_alt_state
= new_alt_state
;
5460 for (alt_state
= curr_arc
->to_state
->component_states
;
5462 alt_state
= alt_state
->next_sorted_alt_state
)
5464 new_alt_state
= get_free_alt_state ();
5465 new_alt_state
->next_alt_state
= curr_alt_state
;
5466 new_alt_state
->state
= alt_state
->state
;
5467 gcc_assert (!alt_state
->state
->component_states
);
5468 curr_alt_state
= new_alt_state
;
5470 /* There are not identical sets in the alt state list. */
5471 canonical_alt_states_list
= uniq_sort_alt_states (curr_alt_state
);
5472 if (canonical_alt_states_list
->next_sorted_alt_state
== NULL
)
5475 state
= canonical_alt_states_list
->state
;
5476 free_state (temp_state
);
5480 state
->component_states
= canonical_alt_states_list
;
5481 state_in_table
= insert_state (state
);
5482 if (state_in_table
!= state
)
5485 (state_in_table
->it_was_placed_in_stack_for_DFA_forming
);
5487 state
= state_in_table
;
5491 gcc_assert (!state
->it_was_placed_in_stack_for_DFA_forming
);
5493 for (curr_alt_state
= state
->component_states
;
5494 curr_alt_state
!= NULL
;
5495 curr_alt_state
= curr_alt_state
->next_sorted_alt_state
)
5496 for (curr_arc
= first_out_arc (curr_alt_state
->state
);
5498 curr_arc
= next_out_arc (curr_arc
))
5499 add_arc (state
, curr_arc
->to_state
, curr_arc
->insn
);
5501 arcs_marked_by_insn
->to_state
= state
;
5502 for (alts_number
= 0,
5503 curr_arc
= arcs_marked_by_insn
->next_arc_marked_by_insn
;
5505 curr_arc
= next_arc
)
5507 next_arc
= curr_arc
->next_arc_marked_by_insn
;
5508 remove_arc (original_state
, curr_arc
);
5513 if (!state
->it_was_placed_in_stack_for_DFA_forming
)
5515 state
->it_was_placed_in_stack_for_DFA_forming
= 1;
5516 VEC_safe_push (state_t
,heap
, *state_stack
, state
);
5521 /* The function transforms nondeterministic AUTOMATON into
5525 NDFA_to_DFA (automaton_t automaton
)
5527 state_t start_state
;
5530 VEC(state_t
,heap
) *state_stack
;
5534 state_stack
= VEC_alloc (state_t
,heap
, 0);
5536 /* Create the start state (empty state). */
5537 start_state
= automaton
->start_state
;
5538 start_state
->it_was_placed_in_stack_for_DFA_forming
= 1;
5539 VEC_safe_push (state_t
,heap
, state_stack
, start_state
);
5541 while (VEC_length (state_t
, state_stack
) != 0)
5543 state
= VEC_pop (state_t
, state_stack
);
5544 form_arcs_marked_by_insn (state
);
5545 for (i
= 0; i
< description
->decls_num
; i
++)
5547 decl
= description
->decls
[i
];
5548 if (decl
->mode
== dm_insn_reserv
5549 && create_composed_state
5550 (state
, DECL_INSN_RESERV (decl
)->arcs_marked_by_insn
,
5554 if (progress_flag
&& states_n
% 100 == 0)
5555 fprintf (stderr
, ".");
5559 VEC_free (state_t
,heap
, state_stack
);
5562 /* The following variable value is current number (1, 2, ...) of passing
5564 static int curr_state_graph_pass_num
;
5566 /* This recursive function passes all states achieved from START_STATE
5567 and applies APPLIED_FUNC to them. */
5569 pass_state_graph (state_t start_state
, void (*applied_func
) (state_t state
))
5573 if (start_state
->pass_num
== curr_state_graph_pass_num
)
5575 start_state
->pass_num
= curr_state_graph_pass_num
;
5576 (*applied_func
) (start_state
);
5577 for (arc
= first_out_arc (start_state
);
5579 arc
= next_out_arc (arc
))
5580 pass_state_graph (arc
->to_state
, applied_func
);
5583 /* This recursive function passes all states of AUTOMATON and applies
5584 APPLIED_FUNC to them. */
5586 pass_states (automaton_t automaton
, void (*applied_func
) (state_t state
))
5588 curr_state_graph_pass_num
++;
5589 pass_state_graph (automaton
->start_state
, applied_func
);
5592 /* The function initializes code for passing of all states. */
5594 initiate_pass_states (void)
5596 curr_state_graph_pass_num
= 0;
5599 /* The following vla is used for storing pointers to all achieved
5601 static VEC(state_t
,heap
) *all_achieved_states
;
5603 /* This function is called by function pass_states to add an achieved
5606 add_achieved_state (state_t state
)
5608 VEC_safe_push (state_t
,heap
, all_achieved_states
, state
);
5611 /* The function sets up equivalence numbers of insns which mark all
5612 out arcs of STATE by equiv_class_num_1 (if ODD_ITERATION_FLAG has
5613 nonzero value) or by equiv_class_num_2 of the destination state.
5614 The function returns number of out arcs of STATE. */
5616 set_out_arc_insns_equiv_num (state_t state
, int odd_iteration_flag
)
5620 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
5622 gcc_assert (!arc
->insn
->insn_reserv_decl
->equiv_class_num
);
5623 arc
->insn
->insn_reserv_decl
->equiv_class_num
5624 = (odd_iteration_flag
5625 ? arc
->to_state
->equiv_class_num_1
5626 : arc
->to_state
->equiv_class_num_2
);
5627 gcc_assert (arc
->insn
->insn_reserv_decl
->equiv_class_num
);
5631 /* The function clears equivalence numbers and alt_states in all insns
5632 which mark all out arcs of STATE. */
5634 clear_arc_insns_equiv_num (state_t state
)
5638 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
5639 arc
->insn
->insn_reserv_decl
->equiv_class_num
= 0;
5643 /* The following function returns TRUE if STATE reserves the unit with
5644 UNIT_NUM on the first cycle. */
5646 first_cycle_unit_presence (state_t state
, int unit_num
)
5648 alt_state_t alt_state
;
5650 if (state
->component_states
== NULL
)
5651 return test_unit_reserv (state
->reservs
, 0, unit_num
);
5654 for (alt_state
= state
->component_states
;
5656 alt_state
= alt_state
->next_sorted_alt_state
)
5657 if (test_unit_reserv (alt_state
->state
->reservs
, 0, unit_num
))
5663 /* This fills in the presence_signature[] member of STATE. */
5665 cache_presence (state_t state
)
5669 sz
= (description
->query_units_num
+ sizeof (int) * CHAR_BIT
- 1)
5670 / (sizeof (int) * CHAR_BIT
);
5672 state
->presence_signature
= create_node (sz
* sizeof (int));
5673 for (i
= 0; i
< description
->units_num
; i
++)
5674 if (units_array
[i
]->query_p
)
5676 int presence1_p
= first_cycle_unit_presence (state
, i
);
5677 state
->presence_signature
[num
/ (sizeof (int) * CHAR_BIT
)]
5678 |= (!!presence1_p
) << (num
% (sizeof (int) * CHAR_BIT
));
5683 /* The function returns nonzero value if STATE is not equivalent to
5684 ANOTHER_STATE from the same current partition on equivalence
5685 classes. Another state has ANOTHER_STATE_OUT_ARCS_NUM number of
5686 output arcs. Iteration of making equivalence partition is defined
5687 by ODD_ITERATION_FLAG. */
5689 state_is_differed (state_t state
, state_t another_state
,
5690 int odd_iteration_flag
)
5693 unsigned int sz
, si
;
5695 gcc_assert (state
->num_out_arcs
== another_state
->num_out_arcs
);
5697 sz
= (description
->query_units_num
+ sizeof (int) * CHAR_BIT
- 1)
5698 / (sizeof (int) * CHAR_BIT
);
5700 for (si
= 0; si
< sz
; si
++)
5701 gcc_assert (state
->presence_signature
[si
]
5702 == another_state
->presence_signature
[si
]);
5704 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
5706 if ((odd_iteration_flag
5707 ? arc
->to_state
->equiv_class_num_1
5708 : arc
->to_state
->equiv_class_num_2
)
5709 != arc
->insn
->insn_reserv_decl
->equiv_class_num
)
5716 /* Compares two states pointed to by STATE_PTR_1 and STATE_PTR_2
5717 and return -1, 0 or 1. This function can be used as predicate for
5718 qsort(). It requires the member presence_signature[] of both
5719 states be filled. */
5721 compare_states_for_equiv (const void *state_ptr_1
,
5722 const void *state_ptr_2
)
5724 const_state_t
const s1
= *(const_state_t
const*)state_ptr_1
;
5725 const_state_t
const s2
= *(const_state_t
const*)state_ptr_2
;
5726 unsigned int sz
, si
;
5727 if (s1
->num_out_arcs
< s2
->num_out_arcs
)
5729 else if (s1
->num_out_arcs
> s2
->num_out_arcs
)
5732 sz
= (description
->query_units_num
+ sizeof (int) * CHAR_BIT
- 1)
5733 / (sizeof (int) * CHAR_BIT
);
5735 for (si
= 0; si
< sz
; si
++)
5736 if (s1
->presence_signature
[si
] < s2
->presence_signature
[si
])
5738 else if (s1
->presence_signature
[si
] > s2
->presence_signature
[si
])
5743 /* The function makes initial partition of STATES on equivalent
5744 classes and saves it into *CLASSES. This function requires the input
5745 to be sorted via compare_states_for_equiv(). */
5747 init_equiv_class (VEC(state_t
,heap
) *states
, VEC (state_t
,heap
) **classes
)
5753 *classes
= VEC_alloc (state_t
,heap
, 150);
5754 for (i
= 0; i
< VEC_length (state_t
, states
); i
++)
5756 state_t state
= VEC_index (state_t
, states
, i
);
5759 if (compare_states_for_equiv (&prev
, &state
) != 0)
5761 VEC_safe_push (state_t
,heap
, *classes
, prev
);
5766 state
->equiv_class_num_1
= class_num
;
5767 state
->next_equiv_class_state
= prev
;
5771 VEC_safe_push (state_t
,heap
, *classes
, prev
);
5775 /* The function copies pointers to equivalent states from vla FROM
5778 copy_equiv_class (VEC(state_t
,heap
) **to
, VEC(state_t
,heap
) *from
)
5780 VEC_free (state_t
,heap
, *to
);
5781 *to
= VEC_copy (state_t
,heap
, from
);
5784 /* The function processes equivalence class given by its first state,
5785 FIRST_STATE, on odd iteration if ODD_ITERATION_FLAG. If there
5786 are not equivalent states, the function partitions the class
5787 removing nonequivalent states and placing them in
5788 *NEXT_ITERATION_CLASSES, increments *NEW_EQUIV_CLASS_NUM_PTR ans
5789 assigns it to the state equivalence number. If the class has been
5790 partitioned, the function returns nonzero value. */
5792 partition_equiv_class (state_t first_state
, int odd_iteration_flag
,
5793 VEC(state_t
,heap
) **next_iteration_classes
,
5794 int *new_equiv_class_num_ptr
)
5796 state_t new_equiv_class
;
5804 while (first_state
!= NULL
)
5806 new_equiv_class
= NULL
;
5807 if (first_state
->next_equiv_class_state
!= NULL
)
5809 /* There are more one states in the class equivalence. */
5810 set_out_arc_insns_equiv_num (first_state
, odd_iteration_flag
);
5811 for (prev_state
= first_state
,
5812 curr_state
= first_state
->next_equiv_class_state
;
5814 curr_state
= next_state
)
5816 next_state
= curr_state
->next_equiv_class_state
;
5817 if (state_is_differed (curr_state
, first_state
,
5818 odd_iteration_flag
))
5820 /* Remove curr state from the class equivalence. */
5821 prev_state
->next_equiv_class_state
= next_state
;
5822 /* Add curr state to the new class equivalence. */
5823 curr_state
->next_equiv_class_state
= new_equiv_class
;
5824 if (new_equiv_class
== NULL
)
5825 (*new_equiv_class_num_ptr
)++;
5826 if (odd_iteration_flag
)
5827 curr_state
->equiv_class_num_2
= *new_equiv_class_num_ptr
;
5829 curr_state
->equiv_class_num_1
= *new_equiv_class_num_ptr
;
5830 new_equiv_class
= curr_state
;
5834 prev_state
= curr_state
;
5836 clear_arc_insns_equiv_num (first_state
);
5838 if (new_equiv_class
!= NULL
)
5839 VEC_safe_push (state_t
,heap
, *next_iteration_classes
, new_equiv_class
);
5840 first_state
= new_equiv_class
;
5845 /* The function finds equivalent states of AUTOMATON. */
5847 evaluate_equiv_classes (automaton_t automaton
,
5848 VEC(state_t
,heap
) **equiv_classes
)
5850 int new_equiv_class_num
;
5851 int odd_iteration_flag
;
5853 VEC (state_t
,heap
) *next_iteration_classes
;
5856 all_achieved_states
= VEC_alloc (state_t
,heap
, 1500);
5857 pass_states (automaton
, add_achieved_state
);
5858 pass_states (automaton
, cache_presence
);
5859 qsort (VEC_address (state_t
, all_achieved_states
),
5860 VEC_length (state_t
, all_achieved_states
),
5861 sizeof (state_t
), compare_states_for_equiv
);
5863 odd_iteration_flag
= 0;
5864 new_equiv_class_num
= init_equiv_class (all_achieved_states
,
5865 &next_iteration_classes
);
5869 odd_iteration_flag
= !odd_iteration_flag
;
5871 copy_equiv_class (equiv_classes
, next_iteration_classes
);
5873 /* Transfer equiv numbers for the next iteration. */
5874 for (i
= 0; i
< VEC_length (state_t
, all_achieved_states
); i
++)
5875 if (odd_iteration_flag
)
5876 VEC_index (state_t
, all_achieved_states
, i
)->equiv_class_num_2
5877 = VEC_index (state_t
, all_achieved_states
, i
)->equiv_class_num_1
;
5879 VEC_index (state_t
, all_achieved_states
, i
)->equiv_class_num_1
5880 = VEC_index (state_t
, all_achieved_states
, i
)->equiv_class_num_2
;
5882 for (i
= 0; i
< VEC_length (state_t
, *equiv_classes
); i
++)
5883 if (partition_equiv_class (VEC_index (state_t
, *equiv_classes
, i
),
5885 &next_iteration_classes
,
5886 &new_equiv_class_num
))
5889 while (!finish_flag
);
5890 VEC_free (state_t
,heap
, next_iteration_classes
);
5891 VEC_free (state_t
,heap
, all_achieved_states
);
5894 /* The function merges equivalent states of AUTOMATON. */
5896 merge_states (automaton_t automaton
, VEC(state_t
,heap
) *equiv_classes
)
5900 state_t first_class_state
;
5901 alt_state_t alt_states
;
5902 alt_state_t alt_state
, new_alt_state
;
5907 /* Create states corresponding to equivalence classes containing two
5909 for (i
= 0; i
< VEC_length (state_t
, equiv_classes
); i
++)
5911 curr_state
= VEC_index (state_t
, equiv_classes
, i
);
5912 if (curr_state
->next_equiv_class_state
!= NULL
)
5914 /* There are more one states in the class equivalence. */
5915 /* Create new compound state. */
5916 new_state
= get_free_state (0, automaton
);
5918 first_class_state
= curr_state
;
5919 for (curr_state
= first_class_state
;
5921 curr_state
= curr_state
->next_equiv_class_state
)
5923 curr_state
->equiv_class_state
= new_state
;
5924 if (curr_state
->component_states
== NULL
)
5926 new_alt_state
= get_free_alt_state ();
5927 new_alt_state
->state
= curr_state
;
5928 new_alt_state
->next_alt_state
= alt_states
;
5929 alt_states
= new_alt_state
;
5932 for (alt_state
= curr_state
->component_states
;
5934 alt_state
= alt_state
->next_sorted_alt_state
)
5936 new_alt_state
= get_free_alt_state ();
5937 new_alt_state
->state
= alt_state
->state
;
5938 new_alt_state
->next_alt_state
= alt_states
;
5939 alt_states
= new_alt_state
;
5942 /* Its is important that alt states were sorted before and
5943 after merging to have the same querying results. */
5944 new_state
->component_states
= uniq_sort_alt_states (alt_states
);
5947 curr_state
->equiv_class_state
= curr_state
;
5950 for (i
= 0; i
< VEC_length (state_t
, equiv_classes
); i
++)
5952 curr_state
= VEC_index (state_t
, equiv_classes
, i
);
5953 if (curr_state
->next_equiv_class_state
!= NULL
)
5955 first_class_state
= curr_state
;
5956 /* Create new arcs output from the state corresponding to
5958 for (curr_arc
= first_out_arc (first_class_state
);
5960 curr_arc
= next_out_arc (curr_arc
))
5961 add_arc (first_class_state
->equiv_class_state
,
5962 curr_arc
->to_state
->equiv_class_state
,
5964 /* Delete output arcs from states of given class equivalence. */
5965 for (curr_state
= first_class_state
;
5967 curr_state
= curr_state
->next_equiv_class_state
)
5969 if (automaton
->start_state
== curr_state
)
5970 automaton
->start_state
= curr_state
->equiv_class_state
;
5971 /* Delete the state and its output arcs. */
5972 for (curr_arc
= first_out_arc (curr_state
);
5974 curr_arc
= next_arc
)
5976 next_arc
= next_out_arc (curr_arc
);
5977 free_arc (curr_arc
);
5983 /* Change `to_state' of arcs output from the state of given
5984 equivalence class. */
5985 for (curr_arc
= first_out_arc (curr_state
);
5987 curr_arc
= next_out_arc (curr_arc
))
5988 curr_arc
->to_state
= curr_arc
->to_state
->equiv_class_state
;
5993 /* The function sets up new_cycle_p for states if there is arc to the
5994 state marked by advance_cycle_insn_decl. */
5996 set_new_cycle_flags (state_t state
)
6000 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
6001 if (arc
->insn
->insn_reserv_decl
6002 == DECL_INSN_RESERV (advance_cycle_insn_decl
))
6003 arc
->to_state
->new_cycle_p
= 1;
6006 /* The top level function for minimization of deterministic
6009 minimize_DFA (automaton_t automaton
)
6011 VEC(state_t
,heap
) *equiv_classes
= 0;
6013 evaluate_equiv_classes (automaton
, &equiv_classes
);
6014 merge_states (automaton
, equiv_classes
);
6015 pass_states (automaton
, set_new_cycle_flags
);
6017 VEC_free (state_t
,heap
, equiv_classes
);
6020 /* Values of two variables are counted number of states and arcs in an
6022 static int curr_counted_states_num
;
6023 static int curr_counted_arcs_num
;
6025 /* The function is called by function `pass_states' to count states
6026 and arcs of an automaton. */
6028 incr_states_and_arcs_nums (state_t state
)
6032 curr_counted_states_num
++;
6033 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
6034 curr_counted_arcs_num
++;
6037 /* The function counts states and arcs of AUTOMATON. */
6039 count_states_and_arcs (automaton_t automaton
, int *states_num
,
6042 curr_counted_states_num
= 0;
6043 curr_counted_arcs_num
= 0;
6044 pass_states (automaton
, incr_states_and_arcs_nums
);
6045 *states_num
= curr_counted_states_num
;
6046 *arcs_num
= curr_counted_arcs_num
;
6049 /* The function builds one DFA AUTOMATON for fast pipeline hazards
6050 recognition after checking and simplifying IR of the
6053 build_automaton (automaton_t automaton
)
6058 ticker_on (&NDFA_time
);
6061 if (automaton
->corresponding_automaton_decl
== NULL
)
6062 fprintf (stderr
, "Create anonymous automaton");
6064 fprintf (stderr
, "Create automaton `%s'",
6065 automaton
->corresponding_automaton_decl
->name
);
6066 fprintf (stderr
, " (1 dot is 100 new states):");
6068 make_automaton (automaton
);
6070 fprintf (stderr
, " done\n");
6071 ticker_off (&NDFA_time
);
6072 count_states_and_arcs (automaton
, &states_num
, &arcs_num
);
6073 automaton
->NDFA_states_num
= states_num
;
6074 automaton
->NDFA_arcs_num
= arcs_num
;
6075 ticker_on (&NDFA_to_DFA_time
);
6078 if (automaton
->corresponding_automaton_decl
== NULL
)
6079 fprintf (stderr
, "Make anonymous DFA");
6081 fprintf (stderr
, "Make DFA `%s'",
6082 automaton
->corresponding_automaton_decl
->name
);
6083 fprintf (stderr
, " (1 dot is 100 new states):");
6085 NDFA_to_DFA (automaton
);
6087 fprintf (stderr
, " done\n");
6088 ticker_off (&NDFA_to_DFA_time
);
6089 count_states_and_arcs (automaton
, &states_num
, &arcs_num
);
6090 automaton
->DFA_states_num
= states_num
;
6091 automaton
->DFA_arcs_num
= arcs_num
;
6092 if (!no_minimization_flag
)
6094 ticker_on (&minimize_time
);
6097 if (automaton
->corresponding_automaton_decl
== NULL
)
6098 fprintf (stderr
, "Minimize anonymous DFA...");
6100 fprintf (stderr
, "Minimize DFA `%s'...",
6101 automaton
->corresponding_automaton_decl
->name
);
6103 minimize_DFA (automaton
);
6105 fprintf (stderr
, "done\n");
6106 ticker_off (&minimize_time
);
6107 count_states_and_arcs (automaton
, &states_num
, &arcs_num
);
6108 automaton
->minimal_DFA_states_num
= states_num
;
6109 automaton
->minimal_DFA_arcs_num
= arcs_num
;
6115 /* The page contains code for enumeration of all states of an automaton. */
6117 /* Variable used for enumeration of all states of an automaton. Its
6118 value is current number of automaton states. */
6119 static int curr_state_order_num
;
6121 /* The function is called by function `pass_states' for enumerating
6124 set_order_state_num (state_t state
)
6126 state
->order_state_num
= curr_state_order_num
;
6127 curr_state_order_num
++;
6130 /* The function enumerates all states of AUTOMATON. */
6132 enumerate_states (automaton_t automaton
)
6134 curr_state_order_num
= 0;
6135 pass_states (automaton
, set_order_state_num
);
6136 automaton
->achieved_states_num
= curr_state_order_num
;
6141 /* The page contains code for finding equivalent automaton insns
6144 /* The function inserts AINSN into cyclic list
6145 CYCLIC_EQUIV_CLASS_INSN_LIST of ainsns. */
6147 insert_ainsn_into_equiv_class (ainsn_t ainsn
,
6148 ainsn_t cyclic_equiv_class_insn_list
)
6150 if (cyclic_equiv_class_insn_list
== NULL
)
6151 ainsn
->next_equiv_class_insn
= ainsn
;
6154 ainsn
->next_equiv_class_insn
6155 = cyclic_equiv_class_insn_list
->next_equiv_class_insn
;
6156 cyclic_equiv_class_insn_list
->next_equiv_class_insn
= ainsn
;
6161 /* The function deletes equiv_class_insn into cyclic list of
6162 equivalent ainsns. */
6164 delete_ainsn_from_equiv_class (ainsn_t equiv_class_insn
)
6166 ainsn_t curr_equiv_class_insn
;
6167 ainsn_t prev_equiv_class_insn
;
6169 prev_equiv_class_insn
= equiv_class_insn
;
6170 for (curr_equiv_class_insn
= equiv_class_insn
->next_equiv_class_insn
;
6171 curr_equiv_class_insn
!= equiv_class_insn
;
6172 curr_equiv_class_insn
= curr_equiv_class_insn
->next_equiv_class_insn
)
6173 prev_equiv_class_insn
= curr_equiv_class_insn
;
6174 if (prev_equiv_class_insn
!= equiv_class_insn
)
6175 prev_equiv_class_insn
->next_equiv_class_insn
6176 = equiv_class_insn
->next_equiv_class_insn
;
6179 /* The function processes AINSN of a state in order to find equivalent
6180 ainsns. INSN_ARCS_ARRAY is table: code of insn -> out arc of the
6183 process_insn_equiv_class (ainsn_t ainsn
, arc_t
*insn_arcs_array
)
6187 ainsn_t cyclic_insn_list
;
6190 gcc_assert (insn_arcs_array
[ainsn
->insn_reserv_decl
->insn_num
]);
6192 /* New class of ainsns which are not equivalent to given ainsn. */
6193 cyclic_insn_list
= NULL
;
6196 next_insn
= curr_insn
->next_equiv_class_insn
;
6197 arc
= insn_arcs_array
[curr_insn
->insn_reserv_decl
->insn_num
];
6199 || (insn_arcs_array
[ainsn
->insn_reserv_decl
->insn_num
]->to_state
6202 delete_ainsn_from_equiv_class (curr_insn
);
6203 cyclic_insn_list
= insert_ainsn_into_equiv_class (curr_insn
,
6206 curr_insn
= next_insn
;
6208 while (curr_insn
!= ainsn
);
6211 /* The function processes STATE in order to find equivalent ainsns. */
6213 process_state_for_insn_equiv_partition (state_t state
)
6216 arc_t
*insn_arcs_array
= XCNEWVEC (arc_t
, description
->insns_num
);
6218 /* Process insns of the arcs. */
6219 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
6220 insn_arcs_array
[arc
->insn
->insn_reserv_decl
->insn_num
] = arc
;
6221 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
6222 process_insn_equiv_class (arc
->insn
, insn_arcs_array
);
6224 free (insn_arcs_array
);
6227 /* The function searches for equivalent ainsns of AUTOMATON. */
6229 set_insn_equiv_classes (automaton_t automaton
)
6234 ainsn_t cyclic_insn_list
;
6235 ainsn_t insn_with_same_reservs
;
6236 int equiv_classes_num
;
6238 /* All insns are included in one equivalence class. */
6239 cyclic_insn_list
= NULL
;
6240 for (ainsn
= automaton
->ainsn_list
; ainsn
!= NULL
; ainsn
= ainsn
->next_ainsn
)
6241 if (ainsn
->first_insn_with_same_reservs
)
6242 cyclic_insn_list
= insert_ainsn_into_equiv_class (ainsn
,
6244 /* Process insns in order to make equivalence partition. */
6245 pass_states (automaton
, process_state_for_insn_equiv_partition
);
6246 /* Enumerate equiv classes. */
6247 for (ainsn
= automaton
->ainsn_list
; ainsn
!= NULL
; ainsn
= ainsn
->next_ainsn
)
6248 /* Set undefined value. */
6249 ainsn
->insn_equiv_class_num
= -1;
6250 equiv_classes_num
= 0;
6251 for (ainsn
= automaton
->ainsn_list
; ainsn
!= NULL
; ainsn
= ainsn
->next_ainsn
)
6252 if (ainsn
->insn_equiv_class_num
< 0)
6255 gcc_assert (first_insn
->first_insn_with_same_reservs
);
6256 first_insn
->first_ainsn_with_given_equivalence_num
= 1;
6257 curr_insn
= first_insn
;
6260 for (insn_with_same_reservs
= curr_insn
;
6261 insn_with_same_reservs
!= NULL
;
6262 insn_with_same_reservs
6263 = insn_with_same_reservs
->next_same_reservs_insn
)
6264 insn_with_same_reservs
->insn_equiv_class_num
= equiv_classes_num
;
6265 curr_insn
= curr_insn
->next_equiv_class_insn
;
6267 while (curr_insn
!= first_insn
);
6268 equiv_classes_num
++;
6270 automaton
->insn_equiv_classes_num
= equiv_classes_num
;
6275 /* This page contains code for creating DFA(s) and calls functions
6279 /* The following value is used to prevent floating point overflow for
6280 estimating an automaton bound. The value should be less DBL_MAX on
6281 the host machine. We use here approximate minimum of maximal
6282 double floating point value required by ANSI C standard. It
6283 will work for non ANSI sun compiler too. */
6285 #define MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND 1.0E37
6287 /* The function estimate size of the single DFA used by PHR (pipeline
6288 hazards recognizer). */
6290 estimate_one_automaton_bound (void)
6293 double one_automaton_estimation_bound
;
6297 one_automaton_estimation_bound
= 1.0;
6298 for (i
= 0; i
< description
->decls_num
; i
++)
6300 decl
= description
->decls
[i
];
6301 if (decl
->mode
== dm_unit
)
6303 root_value
= exp (log (DECL_UNIT (decl
)->max_occ_cycle_num
6304 - DECL_UNIT (decl
)->min_occ_cycle_num
+ 1.0)
6306 if (MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND
/ root_value
6307 > one_automaton_estimation_bound
)
6308 one_automaton_estimation_bound
*= root_value
;
6311 return one_automaton_estimation_bound
;
6314 /* The function compares unit declarations according to their maximal
6315 cycle in reservations. */
6317 compare_max_occ_cycle_nums (const void *unit_decl_1
,
6318 const void *unit_decl_2
)
6320 if ((DECL_UNIT (*(const_decl_t
const*) unit_decl_1
)->max_occ_cycle_num
)
6321 < (DECL_UNIT (*(const_decl_t
const*) unit_decl_2
)->max_occ_cycle_num
))
6323 else if ((DECL_UNIT (*(const_decl_t
const*) unit_decl_1
)->max_occ_cycle_num
)
6324 == (DECL_UNIT (*(const_decl_t
const*) unit_decl_2
)->max_occ_cycle_num
))
6330 /* The function makes heuristic assigning automata to units. Actually
6331 efficacy of the algorithm has been checked yet??? */
6334 units_to_automata_heuristic_distr (void)
6336 double estimation_bound
;
6340 unit_decl_t
*unit_decls
;
6343 if (description
->units_num
== 0)
6345 estimation_bound
= estimate_one_automaton_bound ();
6346 unit_decls
= XNEWVEC (unit_decl_t
, description
->units_num
);
6348 for (i
= 0, j
= 0; i
< description
->decls_num
; i
++)
6349 if (description
->decls
[i
]->mode
== dm_unit
)
6350 unit_decls
[j
++] = DECL_UNIT (description
->decls
[i
]);
6351 gcc_assert (j
== description
->units_num
);
6353 qsort (unit_decls
, description
->units_num
,
6354 sizeof (unit_decl_t
), compare_max_occ_cycle_nums
);
6357 bound_value
= unit_decls
[0]->max_occ_cycle_num
;
6358 unit_decls
[0]->corresponding_automaton_num
= automaton_num
;
6360 for (i
= 1; i
< description
->units_num
; i
++)
6362 rest_units_num
= description
->units_num
- i
+ 1;
6363 gcc_assert (automata_num
- automaton_num
- 1 <= rest_units_num
);
6364 if (automaton_num
< automata_num
- 1
6365 && ((automata_num
- automaton_num
- 1 == rest_units_num
)
6368 / unit_decls
[i
]->max_occ_cycle_num
))))
6370 bound_value
= unit_decls
[i
]->max_occ_cycle_num
;
6374 bound_value
*= unit_decls
[i
]->max_occ_cycle_num
;
6375 unit_decls
[i
]->corresponding_automaton_num
= automaton_num
;
6377 gcc_assert (automaton_num
== automata_num
- 1);
6381 /* The functions creates automaton insns for each automata. Automaton
6382 insn is simply insn for given automaton which makes reservation
6383 only of units of the automaton. */
6385 create_ainsns (void)
6388 ainsn_t first_ainsn
;
6395 for (i
= 0; i
< description
->decls_num
; i
++)
6397 decl
= description
->decls
[i
];
6398 if (decl
->mode
== dm_insn_reserv
)
6400 curr_ainsn
= create_node (sizeof (struct ainsn
));
6401 curr_ainsn
->insn_reserv_decl
= DECL_INSN_RESERV (decl
);
6402 curr_ainsn
->important_p
= FALSE
;
6403 curr_ainsn
->next_ainsn
= NULL
;
6404 if (prev_ainsn
== NULL
)
6405 first_ainsn
= curr_ainsn
;
6407 prev_ainsn
->next_ainsn
= curr_ainsn
;
6408 prev_ainsn
= curr_ainsn
;
6414 /* The function assigns automata to units according to constructions
6415 `define_automaton' in the description. */
6417 units_to_automata_distr (void)
6422 for (i
= 0; i
< description
->decls_num
; i
++)
6424 decl
= description
->decls
[i
];
6425 if (decl
->mode
== dm_unit
)
6427 if (DECL_UNIT (decl
)->automaton_decl
== NULL
6428 || (DECL_UNIT (decl
)->automaton_decl
->corresponding_automaton
6430 /* Distribute to the first automaton. */
6431 DECL_UNIT (decl
)->corresponding_automaton_num
= 0;
6433 DECL_UNIT (decl
)->corresponding_automaton_num
6434 = (DECL_UNIT (decl
)->automaton_decl
6435 ->corresponding_automaton
->automaton_order_num
);
6440 /* The function creates DFA(s) for fast pipeline hazards recognition
6441 after checking and simplifying IR of the description. */
6443 create_automata (void)
6445 automaton_t curr_automaton
;
6446 automaton_t prev_automaton
;
6448 int curr_automaton_num
;
6451 if (automata_num
!= 0)
6453 units_to_automata_heuristic_distr ();
6454 for (prev_automaton
= NULL
, curr_automaton_num
= 0;
6455 curr_automaton_num
< automata_num
;
6456 curr_automaton_num
++, prev_automaton
= curr_automaton
)
6458 curr_automaton
= create_node (sizeof (struct automaton
));
6459 curr_automaton
->ainsn_list
= create_ainsns ();
6460 curr_automaton
->corresponding_automaton_decl
= NULL
;
6461 curr_automaton
->next_automaton
= NULL
;
6462 curr_automaton
->automaton_order_num
= curr_automaton_num
;
6463 if (prev_automaton
== NULL
)
6464 description
->first_automaton
= curr_automaton
;
6466 prev_automaton
->next_automaton
= curr_automaton
;
6471 curr_automaton_num
= 0;
6472 prev_automaton
= NULL
;
6473 for (i
= 0; i
< description
->decls_num
; i
++)
6475 decl
= description
->decls
[i
];
6476 if (decl
->mode
== dm_automaton
6477 && DECL_AUTOMATON (decl
)->automaton_is_used
)
6479 curr_automaton
= create_node (sizeof (struct automaton
));
6480 curr_automaton
->ainsn_list
= create_ainsns ();
6481 curr_automaton
->corresponding_automaton_decl
6482 = DECL_AUTOMATON (decl
);
6483 curr_automaton
->next_automaton
= NULL
;
6484 DECL_AUTOMATON (decl
)->corresponding_automaton
= curr_automaton
;
6485 curr_automaton
->automaton_order_num
= curr_automaton_num
;
6486 if (prev_automaton
== NULL
)
6487 description
->first_automaton
= curr_automaton
;
6489 prev_automaton
->next_automaton
= curr_automaton
;
6490 curr_automaton_num
++;
6491 prev_automaton
= curr_automaton
;
6494 if (curr_automaton_num
== 0)
6496 curr_automaton
= create_node (sizeof (struct automaton
));
6497 curr_automaton
->ainsn_list
= create_ainsns ();
6498 curr_automaton
->corresponding_automaton_decl
= NULL
;
6499 curr_automaton
->next_automaton
= NULL
;
6500 description
->first_automaton
= curr_automaton
;
6502 units_to_automata_distr ();
6504 NDFA_time
= create_ticker ();
6505 ticker_off (&NDFA_time
);
6506 NDFA_to_DFA_time
= create_ticker ();
6507 ticker_off (&NDFA_to_DFA_time
);
6508 minimize_time
= create_ticker ();
6509 ticker_off (&minimize_time
);
6510 equiv_time
= create_ticker ();
6511 ticker_off (&equiv_time
);
6512 for (curr_automaton
= description
->first_automaton
;
6513 curr_automaton
!= NULL
;
6514 curr_automaton
= curr_automaton
->next_automaton
)
6518 if (curr_automaton
->corresponding_automaton_decl
== NULL
)
6519 fprintf (stderr
, "Prepare anonymous automaton creation ... ");
6521 fprintf (stderr
, "Prepare automaton `%s' creation...",
6522 curr_automaton
->corresponding_automaton_decl
->name
);
6524 create_alt_states (curr_automaton
);
6525 form_ainsn_with_same_reservs (curr_automaton
);
6527 fprintf (stderr
, "done\n");
6528 build_automaton (curr_automaton
);
6529 enumerate_states (curr_automaton
);
6530 ticker_on (&equiv_time
);
6531 set_insn_equiv_classes (curr_automaton
);
6532 ticker_off (&equiv_time
);
6538 /* This page contains code for forming string representation of
6539 regexp. The representation is formed on IR obstack. So you should
6540 not work with IR obstack between regexp_representation and
6541 finish_regexp_representation calls. */
6543 /* This recursive function forms string representation of regexp
6544 (without tailing '\0'). */
6546 form_regexp (regexp_t regexp
)
6550 switch (regexp
->mode
)
6552 case rm_unit
: case rm_reserv
:
6554 const char *name
= (regexp
->mode
== rm_unit
6555 ? REGEXP_UNIT (regexp
)->name
6556 : REGEXP_RESERV (regexp
)->name
);
6558 obstack_grow (&irp
, name
, strlen (name
));
6563 for (i
= 0; i
< REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
6566 obstack_1grow (&irp
, ',');
6567 form_regexp (REGEXP_SEQUENCE (regexp
)->regexps
[i
]);
6572 obstack_1grow (&irp
, '(');
6573 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
6576 obstack_1grow (&irp
, '+');
6577 if (REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
== rm_sequence
6578 || REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
== rm_oneof
)
6579 obstack_1grow (&irp
, '(');
6580 form_regexp (REGEXP_ALLOF (regexp
)->regexps
[i
]);
6581 if (REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
== rm_sequence
6582 || REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
== rm_oneof
)
6583 obstack_1grow (&irp
, ')');
6585 obstack_1grow (&irp
, ')');
6589 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
6592 obstack_1grow (&irp
, '|');
6593 if (REGEXP_ONEOF (regexp
)->regexps
[i
]->mode
== rm_sequence
)
6594 obstack_1grow (&irp
, '(');
6595 form_regexp (REGEXP_ONEOF (regexp
)->regexps
[i
]);
6596 if (REGEXP_ONEOF (regexp
)->regexps
[i
]->mode
== rm_sequence
)
6597 obstack_1grow (&irp
, ')');
6605 if (REGEXP_REPEAT (regexp
)->regexp
->mode
== rm_sequence
6606 || REGEXP_REPEAT (regexp
)->regexp
->mode
== rm_allof
6607 || REGEXP_REPEAT (regexp
)->regexp
->mode
== rm_oneof
)
6608 obstack_1grow (&irp
, '(');
6609 form_regexp (REGEXP_REPEAT (regexp
)->regexp
);
6610 if (REGEXP_REPEAT (regexp
)->regexp
->mode
== rm_sequence
6611 || REGEXP_REPEAT (regexp
)->regexp
->mode
== rm_allof
6612 || REGEXP_REPEAT (regexp
)->regexp
->mode
== rm_oneof
)
6613 obstack_1grow (&irp
, ')');
6614 sprintf (digits
, "*%d", REGEXP_REPEAT (regexp
)->repeat_num
);
6615 obstack_grow (&irp
, digits
, strlen (digits
));
6620 obstack_grow (&irp
, NOTHING_NAME
, strlen (NOTHING_NAME
));
6628 /* The function returns string representation of REGEXP on IR
6631 regexp_representation (regexp_t regexp
)
6633 form_regexp (regexp
);
6634 obstack_1grow (&irp
, '\0');
6635 return obstack_base (&irp
);
6638 /* The function frees memory allocated for last formed string
6639 representation of regexp. */
6641 finish_regexp_representation (void)
6643 int length
= obstack_object_size (&irp
);
6645 obstack_blank_fast (&irp
, -length
);
6650 /* This page contains code for output PHR (pipeline hazards recognizer). */
6652 /* The function outputs minimal C type which is sufficient for
6653 representation numbers in range min_range_value and
6654 max_range_value. Because host machine and build machine may be
6655 different, we use here minimal values required by ANSI C standard
6656 instead of UCHAR_MAX, SHRT_MAX, SHRT_MIN, etc. This is a good
6660 output_range_type (FILE *f
, long int min_range_value
,
6661 long int max_range_value
)
6663 if (min_range_value
>= 0 && max_range_value
<= 255)
6664 fprintf (f
, "unsigned char");
6665 else if (min_range_value
>= -127 && max_range_value
<= 127)
6666 fprintf (f
, "signed char");
6667 else if (min_range_value
>= 0 && max_range_value
<= 65535)
6668 fprintf (f
, "unsigned short");
6669 else if (min_range_value
>= -32767 && max_range_value
<= 32767)
6670 fprintf (f
, "short");
6675 /* The function outputs all initialization values of VECT. */
6677 output_vect (vla_hwint_t vect
)
6680 size_t vect_length
= VEC_length (vect_el_t
, vect
);
6684 if (vect_length
== 0)
6685 fputs ("0 /* This is dummy el because the vect is empty */", output_file
);
6687 for (i
= 0; i
< vect_length
; i
++)
6689 fprintf (output_file
, "%5ld", (long) VEC_index (vect_el_t
, vect
, i
));
6690 if (els_on_line
== 10)
6693 fputs (",\n", output_file
);
6695 else if (i
< vect_length
-1)
6696 fputs (", ", output_file
);
6701 /* The following is name of the structure which represents DFA(s) for
6703 #define CHIP_NAME "DFA_chip"
6705 /* The following is name of member which represents state of a DFA for
6708 output_chip_member_name (FILE *f
, automaton_t automaton
)
6710 if (automaton
->corresponding_automaton_decl
== NULL
)
6711 fprintf (f
, "automaton_state_%d", automaton
->automaton_order_num
);
6713 fprintf (f
, "%s_automaton_state",
6714 automaton
->corresponding_automaton_decl
->name
);
6717 /* The following is name of temporary variable which stores state of a
6720 output_temp_chip_member_name (FILE *f
, automaton_t automaton
)
6723 output_chip_member_name (f
, automaton
);
6726 /* This is name of macro value which is code of pseudo_insn
6727 representing advancing cpu cycle. Its value is used as internal
6728 code unknown insn. */
6729 #define ADVANCE_CYCLE_VALUE_NAME "DFA__ADVANCE_CYCLE"
6731 /* Output name of translate vector for given automaton. */
6733 output_translate_vect_name (FILE *f
, automaton_t automaton
)
6735 if (automaton
->corresponding_automaton_decl
== NULL
)
6736 fprintf (f
, "translate_%d", automaton
->automaton_order_num
);
6738 fprintf (f
, "%s_translate", automaton
->corresponding_automaton_decl
->name
);
6741 /* Output name for simple transition table representation. */
6743 output_trans_full_vect_name (FILE *f
, automaton_t automaton
)
6745 if (automaton
->corresponding_automaton_decl
== NULL
)
6746 fprintf (f
, "transitions_%d", automaton
->automaton_order_num
);
6748 fprintf (f
, "%s_transitions",
6749 automaton
->corresponding_automaton_decl
->name
);
6752 /* Output name of comb vector of the transition table for given
6755 output_trans_comb_vect_name (FILE *f
, automaton_t automaton
)
6757 if (automaton
->corresponding_automaton_decl
== NULL
)
6758 fprintf (f
, "transitions_%d", automaton
->automaton_order_num
);
6760 fprintf (f
, "%s_transitions",
6761 automaton
->corresponding_automaton_decl
->name
);
6764 /* Output name of check vector of the transition table for given
6767 output_trans_check_vect_name (FILE *f
, automaton_t automaton
)
6769 if (automaton
->corresponding_automaton_decl
== NULL
)
6770 fprintf (f
, "check_%d", automaton
->automaton_order_num
);
6772 fprintf (f
, "%s_check", automaton
->corresponding_automaton_decl
->name
);
6775 /* Output name of base vector of the transition table for given
6778 output_trans_base_vect_name (FILE *f
, automaton_t automaton
)
6780 if (automaton
->corresponding_automaton_decl
== NULL
)
6781 fprintf (f
, "base_%d", automaton
->automaton_order_num
);
6783 fprintf (f
, "%s_base", automaton
->corresponding_automaton_decl
->name
);
6786 /* Output name of simple min issue delay table representation. */
6788 output_min_issue_delay_vect_name (FILE *f
, automaton_t automaton
)
6790 if (automaton
->corresponding_automaton_decl
== NULL
)
6791 fprintf (f
, "min_issue_delay_%d", automaton
->automaton_order_num
);
6793 fprintf (f
, "%s_min_issue_delay",
6794 automaton
->corresponding_automaton_decl
->name
);
6797 /* Output name of deadlock vector for given automaton. */
6799 output_dead_lock_vect_name (FILE *f
, automaton_t automaton
)
6801 if (automaton
->corresponding_automaton_decl
== NULL
)
6802 fprintf (f
, "dead_lock_%d", automaton
->automaton_order_num
);
6804 fprintf (f
, "%s_dead_lock", automaton
->corresponding_automaton_decl
->name
);
6807 /* Output name of reserved units table for AUTOMATON into file F. */
6809 output_reserved_units_table_name (FILE *f
, automaton_t automaton
)
6811 if (automaton
->corresponding_automaton_decl
== NULL
)
6812 fprintf (f
, "reserved_units_%d", automaton
->automaton_order_num
);
6814 fprintf (f
, "%s_reserved_units",
6815 automaton
->corresponding_automaton_decl
->name
);
6818 /* Name of the PHR interface macro. */
6819 #define CPU_UNITS_QUERY_MACRO_NAME "CPU_UNITS_QUERY"
6821 /* Names of an internal functions: */
6822 #define INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME "internal_min_issue_delay"
6824 /* This is external type of DFA(s) state. */
6825 #define STATE_TYPE_NAME "state_t"
6827 #define INTERNAL_TRANSITION_FUNC_NAME "internal_state_transition"
6829 #define INTERNAL_RESET_FUNC_NAME "internal_reset"
6831 #define INTERNAL_DEAD_LOCK_FUNC_NAME "internal_state_dead_lock_p"
6833 #define INTERNAL_INSN_LATENCY_FUNC_NAME "internal_insn_latency"
6835 /* Name of cache of insn dfa codes. */
6836 #define DFA_INSN_CODES_VARIABLE_NAME "dfa_insn_codes"
6838 /* Name of length of cache of insn dfa codes. */
6839 #define DFA_INSN_CODES_LENGTH_VARIABLE_NAME "dfa_insn_codes_length"
6841 /* Names of the PHR interface functions: */
6842 #define SIZE_FUNC_NAME "state_size"
6844 #define TRANSITION_FUNC_NAME "state_transition"
6846 #define MIN_ISSUE_DELAY_FUNC_NAME "min_issue_delay"
6848 #define MIN_INSN_CONFLICT_DELAY_FUNC_NAME "min_insn_conflict_delay"
6850 #define DEAD_LOCK_FUNC_NAME "state_dead_lock_p"
6852 #define RESET_FUNC_NAME "state_reset"
6854 #define INSN_LATENCY_FUNC_NAME "insn_latency"
6856 #define PRINT_RESERVATION_FUNC_NAME "print_reservation"
6858 #define GET_CPU_UNIT_CODE_FUNC_NAME "get_cpu_unit_code"
6860 #define CPU_UNIT_RESERVATION_P_FUNC_NAME "cpu_unit_reservation_p"
6862 #define INSN_HAS_DFA_RESERVATION_P_FUNC_NAME "insn_has_dfa_reservation_p"
6864 #define DFA_CLEAN_INSN_CACHE_FUNC_NAME "dfa_clean_insn_cache"
6866 #define DFA_CLEAR_SINGLE_INSN_CACHE_FUNC_NAME "dfa_clear_single_insn_cache"
6868 #define DFA_START_FUNC_NAME "dfa_start"
6870 #define DFA_FINISH_FUNC_NAME "dfa_finish"
6872 /* Names of parameters of the PHR interface functions. */
6873 #define STATE_NAME "state"
6875 #define INSN_PARAMETER_NAME "insn"
6877 #define INSN2_PARAMETER_NAME "insn2"
6879 #define CHIP_PARAMETER_NAME "chip"
6881 #define FILE_PARAMETER_NAME "f"
6883 #define CPU_UNIT_NAME_PARAMETER_NAME "cpu_unit_name"
6885 #define CPU_CODE_PARAMETER_NAME "cpu_unit_code"
6887 /* Names of the variables whose values are internal insn code of rtx
6889 #define INTERNAL_INSN_CODE_NAME "insn_code"
6891 #define INTERNAL_INSN2_CODE_NAME "insn2_code"
6893 /* Names of temporary variables in some functions. */
6894 #define TEMPORARY_VARIABLE_NAME "temp"
6896 #define I_VARIABLE_NAME "i"
6898 /* Name of result variable in some functions. */
6899 #define RESULT_VARIABLE_NAME "res"
6901 /* Name of function (attribute) to translate insn into internal insn
6903 #define INTERNAL_DFA_INSN_CODE_FUNC_NAME "internal_dfa_insn_code"
6905 /* Name of function (attribute) to translate insn into internal insn
6906 code with caching. */
6907 #define DFA_INSN_CODE_FUNC_NAME "dfa_insn_code"
6909 /* Output C type which is used for representation of codes of states
6912 output_state_member_type (FILE *f
, automaton_t automaton
)
6914 output_range_type (f
, 0, automaton
->achieved_states_num
);
6917 /* Output definition of the structure representing current DFA(s)
6920 output_chip_definitions (void)
6922 automaton_t automaton
;
6924 fprintf (output_file
, "struct %s\n{\n", CHIP_NAME
);
6925 for (automaton
= description
->first_automaton
;
6927 automaton
= automaton
->next_automaton
)
6929 fprintf (output_file
, " ");
6930 output_state_member_type (output_file
, automaton
);
6931 fprintf (output_file
, " ");
6932 output_chip_member_name (output_file
, automaton
);
6933 fprintf (output_file
, ";\n");
6935 fprintf (output_file
, "};\n\n");
6937 fprintf (output_file
, "static struct %s %s;\n\n", CHIP_NAME
, CHIP_NAME
);
6942 /* The function outputs translate vector of internal insn code into
6943 insn equivalence class number. The equivalence class number is
6944 used to access to table and vectors representing DFA(s). */
6946 output_translate_vect (automaton_t automaton
)
6950 vla_hwint_t translate_vect
;
6952 translate_vect
= VEC_alloc (vect_el_t
,heap
, description
->insns_num
);
6954 for (insn_value
= 0; insn_value
< description
->insns_num
; insn_value
++)
6955 /* Undefined value */
6956 VEC_quick_push (vect_el_t
, translate_vect
,
6957 automaton
->insn_equiv_classes_num
);
6959 for (ainsn
= automaton
->ainsn_list
; ainsn
!= NULL
; ainsn
= ainsn
->next_ainsn
)
6960 VEC_replace (vect_el_t
, translate_vect
,
6961 ainsn
->insn_reserv_decl
->insn_num
,
6962 ainsn
->insn_equiv_class_num
);
6964 fprintf (output_file
,
6965 "/* Vector translating external insn codes to internal ones.*/\n");
6966 fprintf (output_file
, "static const ");
6967 output_range_type (output_file
, 0, automaton
->insn_equiv_classes_num
);
6968 fprintf (output_file
, " ");
6969 output_translate_vect_name (output_file
, automaton
);
6970 fprintf (output_file
, "[] ATTRIBUTE_UNUSED = {\n");
6971 output_vect (translate_vect
);
6972 fprintf (output_file
, "};\n\n");
6973 VEC_free (vect_el_t
,heap
, translate_vect
);
6976 /* The value in a table state x ainsn -> something which represents
6978 static int undefined_vect_el_value
;
6980 /* The following function returns nonzero value if the best
6981 representation of the table is comb vector. */
6983 comb_vect_p (state_ainsn_table_t tab
)
6985 return (2 * VEC_length (vect_el_t
, tab
->full_vect
)
6986 > 5 * VEC_length (vect_el_t
, tab
->comb_vect
));
6989 /* The following function creates new table for AUTOMATON. */
6990 static state_ainsn_table_t
6991 create_state_ainsn_table (automaton_t automaton
)
6993 state_ainsn_table_t tab
;
6994 int full_vect_length
;
6997 tab
= create_node (sizeof (struct state_ainsn_table
));
6998 tab
->automaton
= automaton
;
7000 tab
->comb_vect
= VEC_alloc (vect_el_t
,heap
, 10000);
7001 tab
->check_vect
= VEC_alloc (vect_el_t
,heap
, 10000);
7004 VEC_safe_grow (vect_el_t
,heap
, tab
->base_vect
,
7005 automaton
->achieved_states_num
);
7007 full_vect_length
= (automaton
->insn_equiv_classes_num
7008 * automaton
->achieved_states_num
);
7009 tab
->full_vect
= VEC_alloc (vect_el_t
,heap
, full_vect_length
);
7010 for (i
= 0; i
< full_vect_length
; i
++)
7011 VEC_quick_push (vect_el_t
, tab
->full_vect
, undefined_vect_el_value
);
7013 tab
->min_base_vect_el_value
= 0;
7014 tab
->max_base_vect_el_value
= 0;
7015 tab
->min_comb_vect_el_value
= 0;
7016 tab
->max_comb_vect_el_value
= 0;
7020 /* The following function outputs the best C representation of the
7021 table TAB of given TABLE_NAME. */
7023 output_state_ainsn_table (state_ainsn_table_t tab
, const char *table_name
,
7024 void (*output_full_vect_name_func
) (FILE *, automaton_t
),
7025 void (*output_comb_vect_name_func
) (FILE *, automaton_t
),
7026 void (*output_check_vect_name_func
) (FILE *, automaton_t
),
7027 void (*output_base_vect_name_func
) (FILE *, automaton_t
))
7029 if (!comb_vect_p (tab
))
7031 fprintf (output_file
, "/* Vector for %s. */\n", table_name
);
7032 fprintf (output_file
, "static const ");
7033 output_range_type (output_file
, tab
->min_comb_vect_el_value
,
7034 tab
->max_comb_vect_el_value
);
7035 fprintf (output_file
, " ");
7036 (*output_full_vect_name_func
) (output_file
, tab
->automaton
);
7037 fprintf (output_file
, "[] ATTRIBUTE_UNUSED = {\n");
7038 output_vect (tab
->full_vect
);
7039 fprintf (output_file
, "};\n\n");
7043 fprintf (output_file
, "/* Comb vector for %s. */\n", table_name
);
7044 fprintf (output_file
, "static const ");
7045 output_range_type (output_file
, tab
->min_comb_vect_el_value
,
7046 tab
->max_comb_vect_el_value
);
7047 fprintf (output_file
, " ");
7048 (*output_comb_vect_name_func
) (output_file
, tab
->automaton
);
7049 fprintf (output_file
, "[] ATTRIBUTE_UNUSED = {\n");
7050 output_vect (tab
->comb_vect
);
7051 fprintf (output_file
, "};\n\n");
7052 fprintf (output_file
, "/* Check vector for %s. */\n", table_name
);
7053 fprintf (output_file
, "static const ");
7054 output_range_type (output_file
, 0, tab
->automaton
->achieved_states_num
);
7055 fprintf (output_file
, " ");
7056 (*output_check_vect_name_func
) (output_file
, tab
->automaton
);
7057 fprintf (output_file
, "[] = {\n");
7058 output_vect (tab
->check_vect
);
7059 fprintf (output_file
, "};\n\n");
7060 fprintf (output_file
, "/* Base vector for %s. */\n", table_name
);
7061 fprintf (output_file
, "static const ");
7062 output_range_type (output_file
, tab
->min_base_vect_el_value
,
7063 tab
->max_base_vect_el_value
);
7064 fprintf (output_file
, " ");
7065 (*output_base_vect_name_func
) (output_file
, tab
->automaton
);
7066 fprintf (output_file
, "[] = {\n");
7067 output_vect (tab
->base_vect
);
7068 fprintf (output_file
, "};\n\n");
7072 /* The following function adds vector VECT to table TAB as its line
7073 with number VECT_NUM. */
7075 add_vect (state_ainsn_table_t tab
, int vect_num
, vla_hwint_t vect
)
7078 size_t real_vect_length
;
7079 int comb_vect_index
;
7080 int comb_vect_els_num
;
7082 int first_unempty_vect_index
;
7083 int additional_els_num
;
7087 unsigned long vect_mask
, comb_vect_mask
;
7089 vect_length
= VEC_length (vect_el_t
, vect
);
7090 gcc_assert (vect_length
);
7091 gcc_assert (VEC_last (vect_el_t
, vect
) != undefined_vect_el_value
);
7092 real_vect_length
= tab
->automaton
->insn_equiv_classes_num
;
7093 /* Form full vector in the table: */
7095 size_t full_base
= tab
->automaton
->insn_equiv_classes_num
* vect_num
;
7096 if (VEC_length (vect_el_t
, tab
->full_vect
) < full_base
+ vect_length
)
7097 VEC_safe_grow (vect_el_t
,heap
, tab
->full_vect
,
7098 full_base
+ vect_length
);
7099 for (i
= 0; i
< vect_length
; i
++)
7100 VEC_replace (vect_el_t
, tab
->full_vect
, full_base
+ i
,
7101 VEC_index (vect_el_t
, vect
, i
));
7103 /* Form comb vector in the table: */
7104 gcc_assert (VEC_length (vect_el_t
, tab
->comb_vect
)
7105 == VEC_length (vect_el_t
, tab
->check_vect
));
7107 comb_vect_els_num
= VEC_length (vect_el_t
, tab
->comb_vect
);
7108 for (first_unempty_vect_index
= 0;
7109 first_unempty_vect_index
< vect_length
;
7110 first_unempty_vect_index
++)
7111 if (VEC_index (vect_el_t
, vect
, first_unempty_vect_index
)
7112 != undefined_vect_el_value
)
7115 /* Search for the place in comb vect for the inserted vect. */
7118 if (vect_length
- first_unempty_vect_index
>= SIZEOF_LONG
* CHAR_BIT
)
7120 for (comb_vect_index
= 0;
7121 comb_vect_index
< comb_vect_els_num
;
7124 for (vect_index
= first_unempty_vect_index
;
7125 vect_index
< vect_length
7126 && vect_index
+ comb_vect_index
< comb_vect_els_num
;
7128 if (VEC_index (vect_el_t
, vect
, vect_index
)
7129 != undefined_vect_el_value
7130 && (VEC_index (vect_el_t
, tab
->comb_vect
,
7131 vect_index
+ comb_vect_index
)
7132 != undefined_vect_el_value
))
7134 if (vect_index
>= vect_length
7135 || vect_index
+ comb_vect_index
>= comb_vect_els_num
)
7143 for (vect_index
= first_unempty_vect_index
;
7144 vect_index
< vect_length
;
7147 vect_mask
= vect_mask
<< 1;
7148 if (VEC_index (vect_el_t
, vect
, vect_index
) != undefined_vect_el_value
)
7152 /* Search for the place in comb vect for the inserted vect. */
7153 comb_vect_index
= 0;
7154 if (comb_vect_els_num
== 0)
7158 for (vect_index
= first_unempty_vect_index
;
7159 vect_index
< vect_length
&& vect_index
< comb_vect_els_num
;
7162 comb_vect_mask
<<= 1;
7163 if (vect_index
+ comb_vect_index
< comb_vect_els_num
7164 && VEC_index (vect_el_t
, tab
->comb_vect
, vect_index
+ comb_vect_index
)
7165 != undefined_vect_el_value
)
7166 comb_vect_mask
|= 1;
7168 if ((vect_mask
& comb_vect_mask
) == 0)
7171 for (comb_vect_index
= 1, i
= vect_length
; i
< comb_vect_els_num
;
7172 comb_vect_index
++, i
++)
7174 comb_vect_mask
= (comb_vect_mask
<< 1) | 1;
7175 comb_vect_mask
^= (VEC_index (vect_el_t
, tab
->comb_vect
, i
)
7176 == undefined_vect_el_value
);
7177 if ((vect_mask
& comb_vect_mask
) == 0)
7180 for ( ; comb_vect_index
< comb_vect_els_num
; comb_vect_index
++)
7182 comb_vect_mask
<<= 1;
7183 if ((vect_mask
& comb_vect_mask
) == 0)
7188 /* Slot was found. */
7189 additional_els_num
= comb_vect_index
+ real_vect_length
- comb_vect_els_num
;
7190 if (additional_els_num
< 0)
7191 additional_els_num
= 0;
7192 /* Expand comb and check vectors. */
7193 vect_el
= undefined_vect_el_value
;
7194 no_state_value
= tab
->automaton
->achieved_states_num
;
7195 while (additional_els_num
> 0)
7197 VEC_safe_push (vect_el_t
,heap
, tab
->comb_vect
, vect_el
);
7198 VEC_safe_push (vect_el_t
,heap
, tab
->check_vect
, no_state_value
);
7199 additional_els_num
--;
7201 gcc_assert (VEC_length (vect_el_t
, tab
->comb_vect
)
7202 >= comb_vect_index
+ real_vect_length
);
7203 /* Fill comb and check vectors. */
7204 for (vect_index
= 0; vect_index
< vect_length
; vect_index
++)
7205 if (VEC_index (vect_el_t
, vect
, vect_index
) != undefined_vect_el_value
)
7207 vect_el_t x
= VEC_index (vect_el_t
, vect
, vect_index
);
7208 gcc_assert (VEC_index (vect_el_t
, tab
->comb_vect
,
7209 comb_vect_index
+ vect_index
)
7210 == undefined_vect_el_value
);
7211 gcc_assert (x
>= 0);
7212 if (tab
->max_comb_vect_el_value
< x
)
7213 tab
->max_comb_vect_el_value
= x
;
7214 if (tab
->min_comb_vect_el_value
> x
)
7215 tab
->min_comb_vect_el_value
= x
;
7216 VEC_replace (vect_el_t
, tab
->comb_vect
,
7217 comb_vect_index
+ vect_index
, x
);
7218 VEC_replace (vect_el_t
, tab
->check_vect
,
7219 comb_vect_index
+ vect_index
, vect_num
);
7221 if (tab
->max_comb_vect_el_value
< undefined_vect_el_value
)
7222 tab
->max_comb_vect_el_value
= undefined_vect_el_value
;
7223 if (tab
->min_comb_vect_el_value
> undefined_vect_el_value
)
7224 tab
->min_comb_vect_el_value
= undefined_vect_el_value
;
7225 if (tab
->max_base_vect_el_value
< comb_vect_index
)
7226 tab
->max_base_vect_el_value
= comb_vect_index
;
7227 if (tab
->min_base_vect_el_value
> comb_vect_index
)
7228 tab
->min_base_vect_el_value
= comb_vect_index
;
7230 VEC_replace (vect_el_t
, tab
->base_vect
, vect_num
, comb_vect_index
);
7233 /* Return number of out arcs of STATE. */
7235 out_state_arcs_num (const_state_t state
)
7241 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
7243 gcc_assert (arc
->insn
);
7244 if (arc
->insn
->first_ainsn_with_given_equivalence_num
)
7250 /* Compare number of possible transitions from the states. */
7252 compare_transition_els_num (const void *state_ptr_1
,
7253 const void *state_ptr_2
)
7255 const int transition_els_num_1
7256 = out_state_arcs_num (*(const_state_t
const*) state_ptr_1
);
7257 const int transition_els_num_2
7258 = out_state_arcs_num (*(const_state_t
const*) state_ptr_2
);
7260 if (transition_els_num_1
< transition_els_num_2
)
7262 else if (transition_els_num_1
== transition_els_num_2
)
7268 /* The function adds element EL_VALUE to vector VECT for a table state
7271 add_vect_el (vla_hwint_t
*vect
, ainsn_t ainsn
, int el_value
)
7273 int equiv_class_num
;
7277 equiv_class_num
= ainsn
->insn_equiv_class_num
;
7278 for (vect_index
= VEC_length (vect_el_t
, *vect
);
7279 vect_index
<= equiv_class_num
;
7281 VEC_safe_push (vect_el_t
,heap
, *vect
, undefined_vect_el_value
);
7282 VEC_replace (vect_el_t
, *vect
, equiv_class_num
, el_value
);
7285 /* This is for forming vector of states of an automaton. */
7286 static VEC(state_t
,heap
) *output_states_vect
;
7288 /* The function is called by function pass_states. The function adds
7289 STATE to `output_states_vect'. */
7291 add_states_vect_el (state_t state
)
7293 VEC_safe_push (state_t
,heap
, output_states_vect
, state
);
7296 /* Form and output vectors (comb, check, base or full vector)
7297 representing transition table of AUTOMATON. */
7299 output_trans_table (automaton_t automaton
)
7303 vla_hwint_t transition_vect
= 0;
7305 undefined_vect_el_value
= automaton
->achieved_states_num
;
7306 automaton
->trans_table
= create_state_ainsn_table (automaton
);
7307 /* Create vect of pointers to states ordered by num of transitions
7308 from the state (state with the maximum num is the first). */
7309 output_states_vect
= 0;
7310 pass_states (automaton
, add_states_vect_el
);
7311 qsort (VEC_address (state_t
, output_states_vect
),
7312 VEC_length (state_t
, output_states_vect
),
7313 sizeof (state_t
), compare_transition_els_num
);
7315 for (i
= 0; i
< VEC_length (state_t
, output_states_vect
); i
++)
7317 VEC_truncate (vect_el_t
, transition_vect
, 0);
7318 for (arc
= first_out_arc (VEC_index (state_t
, output_states_vect
, i
));
7320 arc
= next_out_arc (arc
))
7322 gcc_assert (arc
->insn
);
7323 if (arc
->insn
->first_ainsn_with_given_equivalence_num
)
7324 add_vect_el (&transition_vect
, arc
->insn
,
7325 arc
->to_state
->order_state_num
);
7327 add_vect (automaton
->trans_table
,
7328 VEC_index (state_t
, output_states_vect
, i
)->order_state_num
,
7331 output_state_ainsn_table
7332 (automaton
->trans_table
, "state transitions",
7333 output_trans_full_vect_name
, output_trans_comb_vect_name
,
7334 output_trans_check_vect_name
, output_trans_base_vect_name
);
7336 VEC_free (state_t
,heap
, output_states_vect
);
7337 VEC_free (vect_el_t
,heap
, transition_vect
);
7340 /* The current number of passing states to find minimal issue delay
7341 value for an ainsn and state. */
7342 static int curr_state_pass_num
;
7344 /* This recursive function passes states to find minimal issue delay
7345 value for AINSN. The state being visited is STATE. The function
7346 returns minimal issue delay value for AINSN in STATE or -1 if we
7347 enter into a loop. */
7349 min_issue_delay_pass_states (state_t state
, ainsn_t ainsn
)
7352 int min_insn_issue_delay
, insn_issue_delay
;
7354 if (state
->state_pass_num
== curr_state_pass_num
7355 || state
->min_insn_issue_delay
!= -1)
7356 /* We've entered into a loop or already have the correct value for
7357 given state and ainsn. */
7358 return state
->min_insn_issue_delay
;
7359 state
->state_pass_num
= curr_state_pass_num
;
7360 min_insn_issue_delay
= -1;
7361 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
7362 if (arc
->insn
== ainsn
)
7364 min_insn_issue_delay
= 0;
7369 insn_issue_delay
= min_issue_delay_pass_states (arc
->to_state
, ainsn
);
7370 if (insn_issue_delay
!= -1)
7372 if (arc
->insn
->insn_reserv_decl
7373 == DECL_INSN_RESERV (advance_cycle_insn_decl
))
7375 if (min_insn_issue_delay
== -1
7376 || min_insn_issue_delay
> insn_issue_delay
)
7378 min_insn_issue_delay
= insn_issue_delay
;
7379 if (insn_issue_delay
== 0)
7384 return min_insn_issue_delay
;
7387 /* The function searches minimal issue delay value for AINSN in STATE.
7388 The function can return negative value if we can not issue AINSN. We
7389 will report about it later. */
7391 min_issue_delay (state_t state
, ainsn_t ainsn
)
7393 curr_state_pass_num
++;
7394 state
->min_insn_issue_delay
= min_issue_delay_pass_states (state
, ainsn
);
7395 return state
->min_insn_issue_delay
;
7398 /* The function initiates code for finding minimal issue delay values.
7399 It should be called only once. */
7401 initiate_min_issue_delay_pass_states (void)
7403 curr_state_pass_num
= 0;
7406 /* Form and output vectors representing minimal issue delay table of
7407 AUTOMATON. The table is state x ainsn -> minimal issue delay of
7410 output_min_issue_delay_table (automaton_t automaton
)
7412 vla_hwint_t min_issue_delay_vect
;
7413 vla_hwint_t compressed_min_issue_delay_vect
;
7414 vect_el_t min_delay
;
7416 size_t i
, min_issue_delay_len
;
7417 size_t compressed_min_issue_delay_len
;
7420 /* Create vect of pointers to states ordered by num of transitions
7421 from the state (state with the maximum num is the first). */
7422 output_states_vect
= 0;
7423 pass_states (automaton
, add_states_vect_el
);
7425 min_issue_delay_len
= (VEC_length (state_t
, output_states_vect
)
7426 * automaton
->insn_equiv_classes_num
);
7427 min_issue_delay_vect
= VEC_alloc (vect_el_t
,heap
, min_issue_delay_len
);
7428 for (i
= 0; i
< min_issue_delay_len
; i
++)
7429 VEC_quick_push (vect_el_t
, min_issue_delay_vect
, 0);
7431 automaton
->max_min_delay
= 0;
7432 for (ainsn
= automaton
->ainsn_list
; ainsn
!= NULL
; ainsn
= ainsn
->next_ainsn
)
7433 if (ainsn
->first_ainsn_with_given_equivalence_num
)
7435 for (i
= 0; i
< VEC_length (state_t
, output_states_vect
); i
++)
7436 VEC_index (state_t
, output_states_vect
, i
)->min_insn_issue_delay
= -1;
7437 for (i
= 0; i
< VEC_length (state_t
, output_states_vect
); i
++)
7439 state_t s
= VEC_index (state_t
, output_states_vect
, i
);
7440 min_delay
= min_issue_delay (s
, ainsn
);
7441 if (automaton
->max_min_delay
< min_delay
)
7442 automaton
->max_min_delay
= min_delay
;
7443 VEC_replace (vect_el_t
, min_issue_delay_vect
,
7445 * automaton
->insn_equiv_classes_num
7446 + ainsn
->insn_equiv_class_num
,
7450 fprintf (output_file
, "/* Vector of min issue delay of insns. */\n");
7451 fprintf (output_file
, "static const ");
7452 output_range_type (output_file
, 0, automaton
->max_min_delay
);
7453 fprintf (output_file
, " ");
7454 output_min_issue_delay_vect_name (output_file
, automaton
);
7455 fprintf (output_file
, "[] ATTRIBUTE_UNUSED = {\n");
7456 /* Compress the vector. */
7457 if (automaton
->max_min_delay
< 2)
7459 else if (automaton
->max_min_delay
< 4)
7461 else if (automaton
->max_min_delay
< 16)
7465 automaton
->min_issue_delay_table_compression_factor
= cfactor
;
7467 compressed_min_issue_delay_len
= (min_issue_delay_len
+cfactor
-1) / cfactor
;
7468 compressed_min_issue_delay_vect
7469 = VEC_alloc (vect_el_t
,heap
, compressed_min_issue_delay_len
);
7471 for (i
= 0; i
< compressed_min_issue_delay_len
; i
++)
7472 VEC_quick_push (vect_el_t
, compressed_min_issue_delay_vect
, 0);
7474 for (i
= 0; i
< min_issue_delay_len
; i
++)
7476 size_t ci
= i
/ cfactor
;
7477 vect_el_t x
= VEC_index (vect_el_t
, min_issue_delay_vect
, i
);
7478 vect_el_t cx
= VEC_index (vect_el_t
, compressed_min_issue_delay_vect
, ci
);
7480 cx
|= x
<< (8 - (i
% cfactor
+ 1) * (8 / cfactor
));
7481 VEC_replace (vect_el_t
, compressed_min_issue_delay_vect
, ci
, cx
);
7483 output_vect (compressed_min_issue_delay_vect
);
7484 fprintf (output_file
, "};\n\n");
7485 VEC_free (state_t
,heap
, output_states_vect
);
7486 VEC_free (vect_el_t
,heap
, min_issue_delay_vect
);
7487 VEC_free (vect_el_t
,heap
, compressed_min_issue_delay_vect
);
7490 /* Form and output vector representing the locked states of
7493 output_dead_lock_vect (automaton_t automaton
)
7497 vla_hwint_t dead_lock_vect
= 0;
7499 /* Create vect of pointers to states ordered by num of
7500 transitions from the state (state with the maximum num is the
7502 automaton
->locked_states
= 0;
7503 output_states_vect
= 0;
7504 pass_states (automaton
, add_states_vect_el
);
7506 VEC_safe_grow (vect_el_t
,heap
, dead_lock_vect
,
7507 VEC_length (state_t
, output_states_vect
));
7508 for (i
= 0; i
< VEC_length (state_t
, output_states_vect
); i
++)
7510 state_t s
= VEC_index (state_t
, output_states_vect
, i
);
7511 arc
= first_out_arc (s
);
7513 if (next_out_arc (arc
) == NULL
7514 && (arc
->insn
->insn_reserv_decl
7515 == DECL_INSN_RESERV (advance_cycle_insn_decl
)))
7517 VEC_replace (vect_el_t
, dead_lock_vect
, s
->order_state_num
, 1);
7518 automaton
->locked_states
++;
7521 VEC_replace (vect_el_t
, dead_lock_vect
, s
->order_state_num
, 0);
7523 if (automaton
->locked_states
== 0)
7526 fprintf (output_file
, "/* Vector for locked state flags. */\n");
7527 fprintf (output_file
, "static const ");
7528 output_range_type (output_file
, 0, 1);
7529 fprintf (output_file
, " ");
7530 output_dead_lock_vect_name (output_file
, automaton
);
7531 fprintf (output_file
, "[] = {\n");
7532 output_vect (dead_lock_vect
);
7533 fprintf (output_file
, "};\n\n");
7534 VEC_free (state_t
,heap
, output_states_vect
);
7535 VEC_free (vect_el_t
,heap
, dead_lock_vect
);
7538 /* Form and output vector representing reserved units of the states of
7541 output_reserved_units_table (automaton_t automaton
)
7543 vla_hwint_t reserved_units_table
= 0;
7544 int state_byte_size
;
7545 int reserved_units_size
;
7549 if (description
->query_units_num
== 0)
7552 /* Create vect of pointers to states. */
7553 output_states_vect
= 0;
7554 pass_states (automaton
, add_states_vect_el
);
7555 /* Create vector. */
7556 state_byte_size
= (description
->query_units_num
+ 7) / 8;
7557 reserved_units_size
= (VEC_length (state_t
, output_states_vect
)
7560 reserved_units_table
= VEC_alloc (vect_el_t
,heap
, reserved_units_size
);
7562 for (i
= 0; i
< reserved_units_size
; i
++)
7563 VEC_quick_push (vect_el_t
, reserved_units_table
, 0);
7564 for (n
= 0; n
< VEC_length (state_t
, output_states_vect
); n
++)
7566 state_t s
= VEC_index (state_t
, output_states_vect
, n
);
7567 for (i
= 0; i
< description
->units_num
; i
++)
7568 if (units_array
[i
]->query_p
7569 && first_cycle_unit_presence (s
, i
))
7571 int ri
= (s
->order_state_num
* state_byte_size
7572 + units_array
[i
]->query_num
/ 8);
7573 vect_el_t x
= VEC_index (vect_el_t
, reserved_units_table
, ri
);
7575 x
+= 1 << (units_array
[i
]->query_num
% 8);
7576 VEC_replace (vect_el_t
, reserved_units_table
, ri
, x
);
7579 fprintf (output_file
, "\n#if %s\n", CPU_UNITS_QUERY_MACRO_NAME
);
7580 fprintf (output_file
, "/* Vector for reserved units of states. */\n");
7581 fprintf (output_file
, "static const ");
7582 output_range_type (output_file
, 0, 255);
7583 fprintf (output_file
, " ");
7584 output_reserved_units_table_name (output_file
, automaton
);
7585 fprintf (output_file
, "[] = {\n");
7586 output_vect (reserved_units_table
);
7587 fprintf (output_file
, "};\n#endif /* #if %s */\n\n",
7588 CPU_UNITS_QUERY_MACRO_NAME
);
7590 VEC_free (state_t
,heap
, output_states_vect
);
7591 VEC_free (vect_el_t
,heap
, reserved_units_table
);
7594 /* The function outputs all tables representing DFA(s) used for fast
7595 pipeline hazards recognition. */
7597 output_tables (void)
7599 automaton_t automaton
;
7601 initiate_min_issue_delay_pass_states ();
7602 for (automaton
= description
->first_automaton
;
7604 automaton
= automaton
->next_automaton
)
7606 output_translate_vect (automaton
);
7607 output_trans_table (automaton
);
7608 output_min_issue_delay_table (automaton
);
7609 output_dead_lock_vect (automaton
);
7610 output_reserved_units_table (automaton
);
7612 fprintf (output_file
, "\n#define %s %d\n\n", ADVANCE_CYCLE_VALUE_NAME
,
7613 DECL_INSN_RESERV (advance_cycle_insn_decl
)->insn_num
);
7616 /* The function outputs definition and value of PHR interface variable
7617 `max_insn_queue_index'. Its value is not less than maximal queue
7618 length needed for the insn scheduler. */
7620 output_max_insn_queue_index_def (void)
7622 int i
, max
, latency
;
7625 max
= description
->max_insn_reserv_cycles
;
7626 for (i
= 0; i
< description
->decls_num
; i
++)
7628 decl
= description
->decls
[i
];
7629 if (decl
->mode
== dm_insn_reserv
&& decl
!= advance_cycle_insn_decl
)
7631 latency
= DECL_INSN_RESERV (decl
)->default_latency
;
7635 else if (decl
->mode
== dm_bypass
)
7637 latency
= DECL_BYPASS (decl
)->latency
;
7642 for (i
= 0; (1 << i
) <= max
; i
++)
7644 gcc_assert (i
>= 0);
7645 fprintf (output_file
, "\nconst int max_insn_queue_index = %d;\n\n",
7649 /* The function outputs switch cases for insn reservations using
7650 function *output_automata_list_code. */
7652 output_insn_code_cases (void (*output_automata_list_code
)
7653 (automata_list_el_t
))
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
= FALSE
;
7664 for (i
= 0; i
< description
->decls_num
; i
++)
7666 decl
= description
->decls
[i
];
7667 if (decl
->mode
== dm_insn_reserv
7668 && !DECL_INSN_RESERV (decl
)->processed_p
)
7670 for (j
= i
; j
< description
->decls_num
; j
++)
7672 decl2
= description
->decls
[j
];
7673 if (decl2
->mode
== dm_insn_reserv
7674 && (DECL_INSN_RESERV (decl2
)->important_automata_list
7675 == DECL_INSN_RESERV (decl
)->important_automata_list
))
7677 DECL_INSN_RESERV (decl2
)->processed_p
= TRUE
;
7678 fprintf (output_file
, " case %d: /* %s */\n",
7679 DECL_INSN_RESERV (decl2
)->insn_num
,
7680 DECL_INSN_RESERV (decl2
)->name
);
7683 (*output_automata_list_code
)
7684 (DECL_INSN_RESERV (decl
)->important_automata_list
);
7690 /* The function outputs a code for evaluation of a minimal delay of
7691 issue of insns which have reservations in given AUTOMATA_LIST. */
7693 output_automata_list_min_issue_delay_code (automata_list_el_t automata_list
)
7695 automata_list_el_t el
;
7696 automaton_t automaton
;
7698 for (el
= automata_list
; el
!= NULL
; el
= el
->next_automata_list_el
)
7700 automaton
= el
->automaton
;
7701 fprintf (output_file
, "\n %s = ", TEMPORARY_VARIABLE_NAME
);
7702 output_min_issue_delay_vect_name (output_file
, automaton
);
7703 fprintf (output_file
,
7704 (automaton
->min_issue_delay_table_compression_factor
!= 1
7706 output_translate_vect_name (output_file
, automaton
);
7707 fprintf (output_file
, " [%s] + ", INTERNAL_INSN_CODE_NAME
);
7708 fprintf (output_file
, "%s->", CHIP_PARAMETER_NAME
);
7709 output_chip_member_name (output_file
, automaton
);
7710 fprintf (output_file
, " * %d", automaton
->insn_equiv_classes_num
);
7711 if (automaton
->min_issue_delay_table_compression_factor
== 1)
7712 fprintf (output_file
, "];\n");
7715 fprintf (output_file
, ") / %d];\n",
7716 automaton
->min_issue_delay_table_compression_factor
);
7717 fprintf (output_file
, " %s = (%s >> (8 - (",
7718 TEMPORARY_VARIABLE_NAME
, TEMPORARY_VARIABLE_NAME
);
7719 output_translate_vect_name (output_file
, automaton
);
7721 (output_file
, " [%s] %% %d + 1) * %d)) & %d;\n",
7722 INTERNAL_INSN_CODE_NAME
,
7723 automaton
->min_issue_delay_table_compression_factor
,
7724 8 / automaton
->min_issue_delay_table_compression_factor
,
7725 (1 << (8 / automaton
->min_issue_delay_table_compression_factor
))
7728 if (el
== automata_list
)
7729 fprintf (output_file
, " %s = %s;\n",
7730 RESULT_VARIABLE_NAME
, TEMPORARY_VARIABLE_NAME
);
7733 fprintf (output_file
, " if (%s > %s)\n",
7734 TEMPORARY_VARIABLE_NAME
, RESULT_VARIABLE_NAME
);
7735 fprintf (output_file
, " %s = %s;\n",
7736 RESULT_VARIABLE_NAME
, TEMPORARY_VARIABLE_NAME
);
7739 fprintf (output_file
, " break;\n\n");
7742 /* Output function `internal_min_issue_delay'. */
7744 output_internal_min_issue_delay_func (void)
7746 fprintf (output_file
,
7747 "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
7748 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
7749 CHIP_NAME
, CHIP_PARAMETER_NAME
);
7750 fprintf (output_file
, "{\n int %s ATTRIBUTE_UNUSED;\n int %s = -1;\n",
7751 TEMPORARY_VARIABLE_NAME
, RESULT_VARIABLE_NAME
);
7752 fprintf (output_file
, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME
);
7753 output_insn_code_cases (output_automata_list_min_issue_delay_code
);
7754 fprintf (output_file
,
7755 "\n default:\n %s = -1;\n break;\n }\n",
7756 RESULT_VARIABLE_NAME
);
7757 fprintf (output_file
, " return %s;\n", RESULT_VARIABLE_NAME
);
7758 fprintf (output_file
, "}\n\n");
7761 /* The function outputs a code changing state after issue of insns
7762 which have reservations in given AUTOMATA_LIST. */
7764 output_automata_list_transition_code (automata_list_el_t automata_list
)
7766 automata_list_el_t el
, next_el
;
7768 fprintf (output_file
, " {\n");
7769 if (automata_list
!= NULL
&& automata_list
->next_automata_list_el
!= NULL
)
7770 for (el
= automata_list
;; el
= next_el
)
7772 next_el
= el
->next_automata_list_el
;
7773 if (next_el
== NULL
)
7775 fprintf (output_file
, " ");
7776 output_state_member_type (output_file
, el
->automaton
);
7777 fprintf (output_file
, " ");
7778 output_temp_chip_member_name (output_file
, el
->automaton
);
7779 fprintf (output_file
, ";\n");
7781 for (el
= automata_list
; el
!= NULL
; el
= el
->next_automata_list_el
)
7782 if (comb_vect_p (el
->automaton
->trans_table
))
7784 fprintf (output_file
, "\n %s = ", TEMPORARY_VARIABLE_NAME
);
7785 output_trans_base_vect_name (output_file
, el
->automaton
);
7786 fprintf (output_file
, " [%s->", CHIP_PARAMETER_NAME
);
7787 output_chip_member_name (output_file
, el
->automaton
);
7788 fprintf (output_file
, "] + ");
7789 output_translate_vect_name (output_file
, el
->automaton
);
7790 fprintf (output_file
, " [%s];\n", INTERNAL_INSN_CODE_NAME
);
7791 fprintf (output_file
, " if (");
7792 output_trans_check_vect_name (output_file
, el
->automaton
);
7793 fprintf (output_file
, " [%s] != %s->",
7794 TEMPORARY_VARIABLE_NAME
, CHIP_PARAMETER_NAME
);
7795 output_chip_member_name (output_file
, el
->automaton
);
7796 fprintf (output_file
, ")\n");
7797 fprintf (output_file
, " return %s (%s, %s);\n",
7798 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
7799 CHIP_PARAMETER_NAME
);
7800 fprintf (output_file
, " else\n");
7801 fprintf (output_file
, " ");
7802 if (el
->next_automata_list_el
!= NULL
)
7803 output_temp_chip_member_name (output_file
, el
->automaton
);
7806 fprintf (output_file
, "%s->", CHIP_PARAMETER_NAME
);
7807 output_chip_member_name (output_file
, el
->automaton
);
7809 fprintf (output_file
, " = ");
7810 output_trans_comb_vect_name (output_file
, el
->automaton
);
7811 fprintf (output_file
, " [%s];\n", TEMPORARY_VARIABLE_NAME
);
7815 fprintf (output_file
, "\n %s = ", TEMPORARY_VARIABLE_NAME
);
7816 output_trans_full_vect_name (output_file
, el
->automaton
);
7817 fprintf (output_file
, " [");
7818 output_translate_vect_name (output_file
, el
->automaton
);
7819 fprintf (output_file
, " [%s] + ", INTERNAL_INSN_CODE_NAME
);
7820 fprintf (output_file
, "%s->", CHIP_PARAMETER_NAME
);
7821 output_chip_member_name (output_file
, el
->automaton
);
7822 fprintf (output_file
, " * %d];\n",
7823 el
->automaton
->insn_equiv_classes_num
);
7824 fprintf (output_file
, " if (%s >= %d)\n",
7825 TEMPORARY_VARIABLE_NAME
, el
->automaton
->achieved_states_num
);
7826 fprintf (output_file
, " return %s (%s, %s);\n",
7827 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
7828 CHIP_PARAMETER_NAME
);
7829 fprintf (output_file
, " else\n ");
7830 if (el
->next_automata_list_el
!= NULL
)
7831 output_temp_chip_member_name (output_file
, el
->automaton
);
7834 fprintf (output_file
, "%s->", CHIP_PARAMETER_NAME
);
7835 output_chip_member_name (output_file
, el
->automaton
);
7837 fprintf (output_file
, " = %s;\n", TEMPORARY_VARIABLE_NAME
);
7839 if (automata_list
!= NULL
&& automata_list
->next_automata_list_el
!= NULL
)
7840 for (el
= automata_list
;; el
= next_el
)
7842 next_el
= el
->next_automata_list_el
;
7843 if (next_el
== NULL
)
7845 fprintf (output_file
, " %s->", CHIP_PARAMETER_NAME
);
7846 output_chip_member_name (output_file
, el
->automaton
);
7847 fprintf (output_file
, " = ");
7848 output_temp_chip_member_name (output_file
, el
->automaton
);
7849 fprintf (output_file
, ";\n");
7851 fprintf (output_file
, " return -1;\n");
7852 fprintf (output_file
, " }\n");
7855 /* Output function `internal_state_transition'. */
7857 output_internal_trans_func (void)
7859 fprintf (output_file
,
7860 "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
7861 INTERNAL_TRANSITION_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
7862 CHIP_NAME
, CHIP_PARAMETER_NAME
);
7863 fprintf (output_file
, "{\n int %s ATTRIBUTE_UNUSED;\n", TEMPORARY_VARIABLE_NAME
);
7864 fprintf (output_file
, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME
);
7865 output_insn_code_cases (output_automata_list_transition_code
);
7866 fprintf (output_file
, "\n default:\n return -1;\n }\n");
7867 fprintf (output_file
, "}\n\n");
7874 insn_code = dfa_insn_code (insn);
7875 if (insn_code > DFA__ADVANCE_CYCLE)
7879 insn_code = DFA__ADVANCE_CYCLE;
7881 where insn denotes INSN_NAME, insn_code denotes INSN_CODE_NAME, and
7882 code denotes CODE. */
7884 output_internal_insn_code_evaluation (const char *insn_name
,
7885 const char *insn_code_name
,
7888 fprintf (output_file
, "\n if (%s != 0)\n {\n", insn_name
);
7889 fprintf (output_file
, " %s = %s (%s);\n", insn_code_name
,
7890 DFA_INSN_CODE_FUNC_NAME
, insn_name
);
7891 fprintf (output_file
, " if (%s > %s)\n return %d;\n",
7892 insn_code_name
, ADVANCE_CYCLE_VALUE_NAME
, code
);
7893 fprintf (output_file
, " }\n else\n %s = %s;\n\n",
7894 insn_code_name
, ADVANCE_CYCLE_VALUE_NAME
);
7898 /* This function outputs `dfa_insn_code' and its helper function
7899 `dfa_insn_code_enlarge'. */
7901 output_dfa_insn_code_func (void)
7903 /* Emacs c-mode gets really confused if there's a { or } in column 0
7904 inside a string, so don't do that. */
7905 fprintf (output_file
, "\
7907 dfa_insn_code_enlarge (int uid)\n\
7911 %s = xrealloc (%s,\n\
7912 %s * sizeof(int));\n\
7913 for (; i < %s; i++)\n\
7914 %s[i] = -1;\n}\n\n",
7915 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
,
7916 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
,
7917 DFA_INSN_CODES_VARIABLE_NAME
, DFA_INSN_CODES_VARIABLE_NAME
,
7918 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
,
7919 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
,
7920 DFA_INSN_CODES_VARIABLE_NAME
);
7921 fprintf (output_file
, "\
7922 static inline int\n%s (rtx %s)\n\
7924 int uid = INSN_UID (%s);\n\
7926 DFA_INSN_CODE_FUNC_NAME
, INSN_PARAMETER_NAME
,
7927 INSN_PARAMETER_NAME
, INTERNAL_INSN_CODE_NAME
);
7929 fprintf (output_file
,
7930 " if (uid >= %s)\n dfa_insn_code_enlarge (uid);\n\n",
7931 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
);
7932 fprintf (output_file
, " %s = %s[uid];\n",
7933 INTERNAL_INSN_CODE_NAME
, DFA_INSN_CODES_VARIABLE_NAME
);
7934 fprintf (output_file
, "\
7940 INTERNAL_INSN_CODE_NAME
,
7941 INTERNAL_INSN_CODE_NAME
,
7942 INTERNAL_DFA_INSN_CODE_FUNC_NAME
, INSN_PARAMETER_NAME
,
7943 DFA_INSN_CODES_VARIABLE_NAME
, INTERNAL_INSN_CODE_NAME
);
7944 fprintf (output_file
, " return %s;\n}\n\n", INTERNAL_INSN_CODE_NAME
);
7947 /* The function outputs PHR interface function `state_transition'. */
7949 output_trans_func (void)
7951 fprintf (output_file
, "int\n%s (%s %s, rtx %s)\n",
7952 TRANSITION_FUNC_NAME
, STATE_TYPE_NAME
, STATE_NAME
,
7953 INSN_PARAMETER_NAME
);
7954 fprintf (output_file
, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME
);
7955 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME
,
7956 INTERNAL_INSN_CODE_NAME
, -1);
7957 fprintf (output_file
, " return %s (%s, %s);\n}\n\n",
7958 INTERNAL_TRANSITION_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
, STATE_NAME
);
7961 /* Output function `min_issue_delay'. */
7963 output_min_issue_delay_func (void)
7965 fprintf (output_file
, "int\n%s (%s %s, rtx %s)\n",
7966 MIN_ISSUE_DELAY_FUNC_NAME
, STATE_TYPE_NAME
, STATE_NAME
,
7967 INSN_PARAMETER_NAME
);
7968 fprintf (output_file
, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME
);
7969 fprintf (output_file
, "\n if (%s != 0)\n {\n", INSN_PARAMETER_NAME
);
7970 fprintf (output_file
, " %s = %s (%s);\n", INTERNAL_INSN_CODE_NAME
,
7971 DFA_INSN_CODE_FUNC_NAME
, INSN_PARAMETER_NAME
);
7972 fprintf (output_file
, " if (%s > %s)\n return 0;\n",
7973 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
7974 fprintf (output_file
, " }\n else\n %s = %s;\n",
7975 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
7976 fprintf (output_file
, "\n return %s (%s, %s);\n",
7977 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
7979 fprintf (output_file
, "}\n\n");
7982 /* Output function `internal_dead_lock'. */
7984 output_internal_dead_lock_func (void)
7986 automaton_t automaton
;
7988 fprintf (output_file
, "static int\n%s (struct %s *ARG_UNUSED (%s))\n",
7989 INTERNAL_DEAD_LOCK_FUNC_NAME
, CHIP_NAME
, CHIP_PARAMETER_NAME
);
7990 fprintf (output_file
, "{\n");
7991 for (automaton
= description
->first_automaton
;
7993 automaton
= automaton
->next_automaton
)
7994 if (automaton
->locked_states
)
7996 fprintf (output_file
, " if (");
7997 output_dead_lock_vect_name (output_file
, automaton
);
7998 fprintf (output_file
, " [%s->", CHIP_PARAMETER_NAME
);
7999 output_chip_member_name (output_file
, automaton
);
8000 fprintf (output_file
, "])\n return 1/* TRUE */;\n");
8002 fprintf (output_file
, " return 0/* FALSE */;\n}\n\n");
8005 /* The function outputs PHR interface function `state_dead_lock_p'. */
8007 output_dead_lock_func (void)
8009 fprintf (output_file
, "int\n%s (%s %s)\n",
8010 DEAD_LOCK_FUNC_NAME
, STATE_TYPE_NAME
, STATE_NAME
);
8011 fprintf (output_file
, "{\n return %s (%s);\n}\n\n",
8012 INTERNAL_DEAD_LOCK_FUNC_NAME
, STATE_NAME
);
8015 /* Output function `internal_reset'. */
8017 output_internal_reset_func (void)
8019 fprintf (output_file
, "static inline void\n%s (struct %s *%s)\n",
8020 INTERNAL_RESET_FUNC_NAME
, CHIP_NAME
, CHIP_PARAMETER_NAME
);
8021 fprintf (output_file
, "{\n memset (%s, 0, sizeof (struct %s));\n}\n\n",
8022 CHIP_PARAMETER_NAME
, CHIP_NAME
);
8025 /* The function outputs PHR interface function `state_size'. */
8027 output_size_func (void)
8029 fprintf (output_file
, "int\n%s (void)\n", SIZE_FUNC_NAME
);
8030 fprintf (output_file
, "{\n return sizeof (struct %s);\n}\n\n", CHIP_NAME
);
8033 /* The function outputs PHR interface function `state_reset'. */
8035 output_reset_func (void)
8037 fprintf (output_file
, "void\n%s (%s %s)\n",
8038 RESET_FUNC_NAME
, STATE_TYPE_NAME
, STATE_NAME
);
8039 fprintf (output_file
, "{\n %s (%s);\n}\n\n", INTERNAL_RESET_FUNC_NAME
,
8043 /* Output function `min_insn_conflict_delay'. */
8045 output_min_insn_conflict_delay_func (void)
8047 fprintf (output_file
,
8048 "int\n%s (%s %s, rtx %s, rtx %s)\n",
8049 MIN_INSN_CONFLICT_DELAY_FUNC_NAME
, STATE_TYPE_NAME
,
8050 STATE_NAME
, INSN_PARAMETER_NAME
, INSN2_PARAMETER_NAME
);
8051 fprintf (output_file
, "{\n struct %s %s;\n int %s, %s, transition;\n",
8052 CHIP_NAME
, CHIP_NAME
, INTERNAL_INSN_CODE_NAME
,
8053 INTERNAL_INSN2_CODE_NAME
);
8054 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME
,
8055 INTERNAL_INSN_CODE_NAME
, 0);
8056 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME
,
8057 INTERNAL_INSN2_CODE_NAME
, 0);
8058 fprintf (output_file
, " memcpy (&%s, %s, sizeof (%s));\n",
8059 CHIP_NAME
, STATE_NAME
, CHIP_NAME
);
8060 fprintf (output_file
, " %s (&%s);\n", INTERNAL_RESET_FUNC_NAME
, CHIP_NAME
);
8061 fprintf (output_file
, " transition = %s (%s, &%s);\n",
8062 INTERNAL_TRANSITION_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
, CHIP_NAME
);
8063 fprintf (output_file
, " gcc_assert (transition <= 0);\n");
8064 fprintf (output_file
, " return %s (%s, &%s);\n",
8065 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME
, INTERNAL_INSN2_CODE_NAME
,
8067 fprintf (output_file
, "}\n\n");
8070 /* Output function `internal_insn_latency'. */
8072 output_internal_insn_latency_func (void)
8075 struct bypass_decl
*bypass
;
8077 const char *tabletype
= "unsigned char";
8079 /* Find the smallest integer type that can hold all the default
8081 for (i
= 0; i
< description
->decls_num
; i
++)
8082 if (description
->decls
[i
]->mode
== dm_insn_reserv
)
8084 decl
= description
->decls
[i
];
8085 if (DECL_INSN_RESERV (decl
)->default_latency
> UCHAR_MAX
8086 && tabletype
[0] != 'i') /* Don't shrink it. */
8087 tabletype
= "unsigned short";
8088 if (DECL_INSN_RESERV (decl
)->default_latency
> USHRT_MAX
)
8092 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",
8093 INTERNAL_INSN_LATENCY_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
8094 INTERNAL_INSN2_CODE_NAME
, INSN_PARAMETER_NAME
,
8095 INSN2_PARAMETER_NAME
);
8096 fprintf (output_file
, "{\n");
8098 if (DECL_INSN_RESERV (advance_cycle_insn_decl
)->insn_num
== 0)
8100 fputs (" return 0;\n}\n\n", output_file
);
8104 fprintf (output_file
, " static const %s default_latencies[] =\n {",
8107 for (i
= 0, j
= 0, col
= 7; i
< description
->decls_num
; i
++)
8108 if (description
->decls
[i
]->mode
== dm_insn_reserv
8109 && description
->decls
[i
] != advance_cycle_insn_decl
)
8111 if ((col
= (col
+1) % 8) == 0)
8112 fputs ("\n ", output_file
);
8113 decl
= description
->decls
[i
];
8114 gcc_assert (j
++ == DECL_INSN_RESERV (decl
)->insn_num
);
8115 fprintf (output_file
, "% 4d,",
8116 DECL_INSN_RESERV (decl
)->default_latency
);
8118 gcc_assert (j
== DECL_INSN_RESERV (advance_cycle_insn_decl
)->insn_num
);
8119 fputs ("\n };\n", output_file
);
8121 fprintf (output_file
, " if (%s >= %s || %s >= %s)\n return 0;\n",
8122 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
,
8123 INTERNAL_INSN2_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
8125 fprintf (output_file
, " switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME
);
8126 for (i
= 0; i
< description
->decls_num
; i
++)
8127 if (description
->decls
[i
]->mode
== dm_insn_reserv
8128 && DECL_INSN_RESERV (description
->decls
[i
])->bypass_list
)
8130 decl
= description
->decls
[i
];
8131 fprintf (output_file
,
8132 " case %d:\n switch (%s)\n {\n",
8133 DECL_INSN_RESERV (decl
)->insn_num
,
8134 INTERNAL_INSN2_CODE_NAME
);
8135 for (bypass
= DECL_INSN_RESERV (decl
)->bypass_list
;
8137 bypass
= bypass
->next
)
8139 gcc_assert (bypass
->in_insn_reserv
->insn_num
8140 != (DECL_INSN_RESERV
8141 (advance_cycle_insn_decl
)->insn_num
));
8142 fprintf (output_file
, " case %d:\n",
8143 bypass
->in_insn_reserv
->insn_num
);
8144 if (bypass
->bypass_guard_name
== NULL
)
8145 fprintf (output_file
, " return %d;\n",
8149 fprintf (output_file
,
8150 " if (%s (%s, %s))\n",
8151 bypass
->bypass_guard_name
, INSN_PARAMETER_NAME
,
8152 INSN2_PARAMETER_NAME
);
8153 fprintf (output_file
,
8154 " return %d;\n break;\n",
8158 fputs (" }\n break;\n", output_file
);
8161 fprintf (output_file
, " }\n return default_latencies[%s];\n}\n\n",
8162 INTERNAL_INSN_CODE_NAME
);
8165 /* The function outputs PHR interface function `insn_latency'. */
8167 output_insn_latency_func (void)
8169 fprintf (output_file
, "int\n%s (rtx %s, rtx %s)\n",
8170 INSN_LATENCY_FUNC_NAME
, INSN_PARAMETER_NAME
, INSN2_PARAMETER_NAME
);
8171 fprintf (output_file
, "{\n int %s, %s;\n",
8172 INTERNAL_INSN_CODE_NAME
, INTERNAL_INSN2_CODE_NAME
);
8173 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME
,
8174 INTERNAL_INSN_CODE_NAME
, 0);
8175 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME
,
8176 INTERNAL_INSN2_CODE_NAME
, 0);
8177 fprintf (output_file
, " return %s (%s, %s, %s, %s);\n}\n\n",
8178 INTERNAL_INSN_LATENCY_FUNC_NAME
,
8179 INTERNAL_INSN_CODE_NAME
, INTERNAL_INSN2_CODE_NAME
,
8180 INSN_PARAMETER_NAME
, INSN2_PARAMETER_NAME
);
8183 /* The function outputs PHR interface function `print_reservation'. */
8185 output_print_reservation_func (void)
8190 fprintf (output_file
,
8191 "void\n%s (FILE *%s, rtx %s ATTRIBUTE_UNUSED)\n{\n",
8192 PRINT_RESERVATION_FUNC_NAME
, FILE_PARAMETER_NAME
,
8193 INSN_PARAMETER_NAME
);
8195 if (DECL_INSN_RESERV (advance_cycle_insn_decl
)->insn_num
== 0)
8197 fprintf (output_file
, " fputs (\"%s\", %s);\n}\n\n",
8198 NOTHING_NAME
, FILE_PARAMETER_NAME
);
8203 fputs (" static const char *const reservation_names[] =\n {",
8206 for (i
= 0, j
= 0; i
< description
->decls_num
; i
++)
8208 decl
= description
->decls
[i
];
8209 if (decl
->mode
== dm_insn_reserv
&& decl
!= advance_cycle_insn_decl
)
8211 gcc_assert (j
== DECL_INSN_RESERV (decl
)->insn_num
);
8214 fprintf (output_file
, "\n \"%s\",",
8215 regexp_representation (DECL_INSN_RESERV (decl
)->regexp
));
8216 finish_regexp_representation ();
8219 gcc_assert (j
== DECL_INSN_RESERV (advance_cycle_insn_decl
)->insn_num
);
8221 fprintf (output_file
, "\n \"%s\"\n };\n int %s;\n\n",
8222 NOTHING_NAME
, INTERNAL_INSN_CODE_NAME
);
8224 fprintf (output_file
, " if (%s == 0)\n %s = %s;\n",
8225 INSN_PARAMETER_NAME
,
8226 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
8227 fprintf (output_file
, " else\n\
8233 INTERNAL_INSN_CODE_NAME
, DFA_INSN_CODE_FUNC_NAME
,
8234 INSN_PARAMETER_NAME
,
8235 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
,
8236 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
8238 fprintf (output_file
, " fputs (reservation_names[%s], %s);\n}\n\n",
8239 INTERNAL_INSN_CODE_NAME
, FILE_PARAMETER_NAME
);
8242 /* The following function is used to sort unit declaration by their
8245 units_cmp (const void *unit1
, const void *unit2
)
8247 const_unit_decl_t
const u1
= *(const_unit_decl_t
const*) unit1
;
8248 const_unit_decl_t
const u2
= *(const_unit_decl_t
const*) unit2
;
8250 return strcmp (u1
->name
, u2
->name
);
8253 /* The following macro value is name of struct containing unit name
8255 #define NAME_CODE_STRUCT_NAME "name_code"
8257 /* The following macro value is name of table of struct name_code. */
8258 #define NAME_CODE_TABLE_NAME "name_code_table"
8260 /* The following macro values are member names for struct name_code. */
8261 #define NAME_MEMBER_NAME "name"
8262 #define CODE_MEMBER_NAME "code"
8264 /* The following macro values are local variable names for function
8265 `get_cpu_unit_code'. */
8266 #define CMP_VARIABLE_NAME "cmp"
8267 #define LOW_VARIABLE_NAME "l"
8268 #define MIDDLE_VARIABLE_NAME "m"
8269 #define HIGH_VARIABLE_NAME "h"
8271 /* The following function outputs function to obtain internal cpu unit
8272 code by the cpu unit name. */
8274 output_get_cpu_unit_code_func (void)
8279 fprintf (output_file
, "int\n%s (const char *%s)\n",
8280 GET_CPU_UNIT_CODE_FUNC_NAME
, CPU_UNIT_NAME_PARAMETER_NAME
);
8281 fprintf (output_file
, "{\n struct %s {const char *%s; int %s;};\n",
8282 NAME_CODE_STRUCT_NAME
, NAME_MEMBER_NAME
, CODE_MEMBER_NAME
);
8283 fprintf (output_file
, " int %s, %s, %s, %s;\n", CMP_VARIABLE_NAME
,
8284 LOW_VARIABLE_NAME
, MIDDLE_VARIABLE_NAME
, HIGH_VARIABLE_NAME
);
8285 fprintf (output_file
, " static struct %s %s [] =\n {\n",
8286 NAME_CODE_STRUCT_NAME
, NAME_CODE_TABLE_NAME
);
8287 units
= xmalloc (sizeof (unit_decl_t
) * description
->units_num
);
8288 memcpy (units
, units_array
, sizeof (unit_decl_t
) * description
->units_num
);
8289 qsort (units
, description
->units_num
, sizeof (unit_decl_t
), units_cmp
);
8290 for (i
= 0; i
< description
->units_num
; i
++)
8291 if (units
[i
]->query_p
)
8292 fprintf (output_file
, " {\"%s\", %d},\n",
8293 units
[i
]->name
, units
[i
]->query_num
);
8294 fprintf (output_file
, " };\n\n");
8295 fprintf (output_file
, " /* The following is binary search: */\n");
8296 fprintf (output_file
, " %s = 0;\n", LOW_VARIABLE_NAME
);
8297 fprintf (output_file
, " %s = sizeof (%s) / sizeof (struct %s) - 1;\n",
8298 HIGH_VARIABLE_NAME
, NAME_CODE_TABLE_NAME
, NAME_CODE_STRUCT_NAME
);
8299 fprintf (output_file
, " while (%s <= %s)\n {\n",
8300 LOW_VARIABLE_NAME
, HIGH_VARIABLE_NAME
);
8301 fprintf (output_file
, " %s = (%s + %s) / 2;\n",
8302 MIDDLE_VARIABLE_NAME
, LOW_VARIABLE_NAME
, HIGH_VARIABLE_NAME
);
8303 fprintf (output_file
, " %s = strcmp (%s, %s [%s].%s);\n",
8304 CMP_VARIABLE_NAME
, CPU_UNIT_NAME_PARAMETER_NAME
,
8305 NAME_CODE_TABLE_NAME
, MIDDLE_VARIABLE_NAME
, NAME_MEMBER_NAME
);
8306 fprintf (output_file
, " if (%s < 0)\n", CMP_VARIABLE_NAME
);
8307 fprintf (output_file
, " %s = %s - 1;\n",
8308 HIGH_VARIABLE_NAME
, MIDDLE_VARIABLE_NAME
);
8309 fprintf (output_file
, " else if (%s > 0)\n", CMP_VARIABLE_NAME
);
8310 fprintf (output_file
, " %s = %s + 1;\n",
8311 LOW_VARIABLE_NAME
, MIDDLE_VARIABLE_NAME
);
8312 fprintf (output_file
, " else\n");
8313 fprintf (output_file
, " return %s [%s].%s;\n }\n",
8314 NAME_CODE_TABLE_NAME
, MIDDLE_VARIABLE_NAME
, CODE_MEMBER_NAME
);
8315 fprintf (output_file
, " return -1;\n}\n\n");
8319 /* The following function outputs function to check reservation of cpu
8320 unit (its internal code will be passed as the function argument) in
8323 output_cpu_unit_reservation_p (void)
8325 automaton_t automaton
;
8327 fprintf (output_file
, "int\n%s (%s %s, int %s)\n",
8328 CPU_UNIT_RESERVATION_P_FUNC_NAME
,
8329 STATE_TYPE_NAME
, STATE_NAME
,
8330 CPU_CODE_PARAMETER_NAME
);
8331 fprintf (output_file
, "{\n gcc_assert (%s >= 0 && %s < %d);\n",
8332 CPU_CODE_PARAMETER_NAME
, CPU_CODE_PARAMETER_NAME
,
8333 description
->query_units_num
);
8334 if (description
->query_units_num
> 0)
8335 for (automaton
= description
->first_automaton
;
8337 automaton
= automaton
->next_automaton
)
8339 fprintf (output_file
, " if ((");
8340 output_reserved_units_table_name (output_file
, automaton
);
8341 fprintf (output_file
, " [((struct %s *) %s)->", CHIP_NAME
, STATE_NAME
);
8342 output_chip_member_name (output_file
, automaton
);
8343 fprintf (output_file
, " * %d + %s / 8] >> (%s %% 8)) & 1)\n",
8344 (description
->query_units_num
+ 7) / 8,
8345 CPU_CODE_PARAMETER_NAME
, CPU_CODE_PARAMETER_NAME
);
8346 fprintf (output_file
, " return 1;\n");
8348 fprintf (output_file
, " return 0;\n}\n\n");
8351 /* The following function outputs a function to check if insn
8352 has a dfa reservation. */
8354 output_insn_has_dfa_reservation_p (void)
8356 fprintf (output_file
,
8357 "bool\n%s (rtx %s ATTRIBUTE_UNUSED)\n{\n",
8358 INSN_HAS_DFA_RESERVATION_P_FUNC_NAME
,
8359 INSN_PARAMETER_NAME
);
8361 if (DECL_INSN_RESERV (advance_cycle_insn_decl
)->insn_num
== 0)
8363 fprintf (output_file
, " return false;\n}\n\n");
8367 fprintf (output_file
, " int %s;\n\n", INTERNAL_INSN_CODE_NAME
);
8369 fprintf (output_file
, " if (%s == 0)\n %s = %s;\n",
8370 INSN_PARAMETER_NAME
,
8371 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
8372 fprintf (output_file
, " else\n\
8378 INTERNAL_INSN_CODE_NAME
, DFA_INSN_CODE_FUNC_NAME
,
8379 INSN_PARAMETER_NAME
,
8380 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
,
8381 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
8383 fprintf (output_file
, " return %s != %s;\n}\n\n",
8384 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
8387 /* The function outputs PHR interface functions `dfa_clean_insn_cache'
8388 and 'dfa_clear_single_insn_cache'. */
8390 output_dfa_clean_insn_cache_func (void)
8392 fprintf (output_file
,
8393 "void\n%s (void)\n{\n int %s;\n\n",
8394 DFA_CLEAN_INSN_CACHE_FUNC_NAME
, I_VARIABLE_NAME
);
8395 fprintf (output_file
,
8396 " for (%s = 0; %s < %s; %s++)\n %s [%s] = -1;\n}\n\n",
8397 I_VARIABLE_NAME
, I_VARIABLE_NAME
,
8398 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
, I_VARIABLE_NAME
,
8399 DFA_INSN_CODES_VARIABLE_NAME
, I_VARIABLE_NAME
);
8401 fprintf (output_file
,
8402 "void\n%s (rtx %s)\n{\n int %s;\n\n",
8403 DFA_CLEAR_SINGLE_INSN_CACHE_FUNC_NAME
, INSN_PARAMETER_NAME
,
8405 fprintf (output_file
,
8406 " %s = INSN_UID (%s);\n if (%s < %s)\n %s [%s] = -1;\n}\n\n",
8407 I_VARIABLE_NAME
, INSN_PARAMETER_NAME
, I_VARIABLE_NAME
,
8408 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
, DFA_INSN_CODES_VARIABLE_NAME
,
8412 /* The function outputs PHR interface function `dfa_start'. */
8414 output_dfa_start_func (void)
8416 fprintf (output_file
,
8417 "void\n%s (void)\n{\n %s = get_max_uid ();\n",
8418 DFA_START_FUNC_NAME
, DFA_INSN_CODES_LENGTH_VARIABLE_NAME
);
8419 fprintf (output_file
, " %s = xmalloc (%s * sizeof (int));\n",
8420 DFA_INSN_CODES_VARIABLE_NAME
, DFA_INSN_CODES_LENGTH_VARIABLE_NAME
);
8421 fprintf (output_file
, " %s ();\n}\n\n", DFA_CLEAN_INSN_CACHE_FUNC_NAME
);
8424 /* The function outputs PHR interface function `dfa_finish'. */
8426 output_dfa_finish_func (void)
8428 fprintf (output_file
, "void\n%s (void)\n{\n free (%s);\n}\n\n",
8429 DFA_FINISH_FUNC_NAME
, DFA_INSN_CODES_VARIABLE_NAME
);
8434 /* The page contains code for output description file (readable
8435 representation of original description and generated DFA(s). */
8437 /* The function outputs string representation of IR reservation. */
8439 output_regexp (regexp_t regexp
)
8441 fprintf (output_description_file
, "%s", regexp_representation (regexp
));
8442 finish_regexp_representation ();
8445 /* Output names of units in LIST separated by comma. */
8447 output_unit_set_el_list (unit_set_el_t list
)
8451 for (el
= list
; el
!= NULL
; el
= el
->next_unit_set_el
)
8454 fprintf (output_description_file
, ", ");
8455 fprintf (output_description_file
, "%s", el
->unit_decl
->name
);
8459 /* Output patterns in LIST separated by comma. */
8461 output_pattern_set_el_list (pattern_set_el_t list
)
8463 pattern_set_el_t el
;
8466 for (el
= list
; el
!= NULL
; el
= el
->next_pattern_set_el
)
8469 fprintf (output_description_file
, ", ");
8470 for (i
= 0; i
< el
->units_num
; i
++)
8471 fprintf (output_description_file
, (i
== 0 ? "%s" : " %s"),
8472 el
->unit_decls
[i
]->name
);
8476 /* The function outputs string representation of IR define_reservation
8477 and define_insn_reservation. */
8479 output_description (void)
8484 for (i
= 0; i
< description
->decls_num
; i
++)
8486 decl
= description
->decls
[i
];
8487 if (decl
->mode
== dm_unit
)
8489 if (DECL_UNIT (decl
)->excl_list
!= NULL
)
8491 fprintf (output_description_file
, "unit %s exlusion_set: ",
8492 DECL_UNIT (decl
)->name
);
8493 output_unit_set_el_list (DECL_UNIT (decl
)->excl_list
);
8494 fprintf (output_description_file
, "\n");
8496 if (DECL_UNIT (decl
)->presence_list
!= NULL
)
8498 fprintf (output_description_file
, "unit %s presence_set: ",
8499 DECL_UNIT (decl
)->name
);
8500 output_pattern_set_el_list (DECL_UNIT (decl
)->presence_list
);
8501 fprintf (output_description_file
, "\n");
8503 if (DECL_UNIT (decl
)->final_presence_list
!= NULL
)
8505 fprintf (output_description_file
, "unit %s final_presence_set: ",
8506 DECL_UNIT (decl
)->name
);
8507 output_pattern_set_el_list
8508 (DECL_UNIT (decl
)->final_presence_list
);
8509 fprintf (output_description_file
, "\n");
8511 if (DECL_UNIT (decl
)->absence_list
!= NULL
)
8513 fprintf (output_description_file
, "unit %s absence_set: ",
8514 DECL_UNIT (decl
)->name
);
8515 output_pattern_set_el_list (DECL_UNIT (decl
)->absence_list
);
8516 fprintf (output_description_file
, "\n");
8518 if (DECL_UNIT (decl
)->final_absence_list
!= NULL
)
8520 fprintf (output_description_file
, "unit %s final_absence_set: ",
8521 DECL_UNIT (decl
)->name
);
8522 output_pattern_set_el_list
8523 (DECL_UNIT (decl
)->final_absence_list
);
8524 fprintf (output_description_file
, "\n");
8528 fprintf (output_description_file
, "\n");
8529 for (i
= 0; i
< description
->decls_num
; i
++)
8531 decl
= description
->decls
[i
];
8532 if (decl
->mode
== dm_reserv
)
8534 fprintf (output_description_file
, "reservation %s: ",
8535 DECL_RESERV (decl
)->name
);
8536 output_regexp (DECL_RESERV (decl
)->regexp
);
8537 fprintf (output_description_file
, "\n");
8539 else if (decl
->mode
== dm_insn_reserv
&& decl
!= advance_cycle_insn_decl
)
8541 fprintf (output_description_file
, "insn reservation %s ",
8542 DECL_INSN_RESERV (decl
)->name
);
8543 print_rtl (output_description_file
,
8544 DECL_INSN_RESERV (decl
)->condexp
);
8545 fprintf (output_description_file
, ": ");
8546 output_regexp (DECL_INSN_RESERV (decl
)->regexp
);
8547 fprintf (output_description_file
, "\n");
8549 else if (decl
->mode
== dm_bypass
)
8550 fprintf (output_description_file
, "bypass %d %s %s\n",
8551 DECL_BYPASS (decl
)->latency
,
8552 DECL_BYPASS (decl
)->out_insn_name
,
8553 DECL_BYPASS (decl
)->in_insn_name
);
8555 fprintf (output_description_file
, "\n\f\n");
8558 /* The function outputs name of AUTOMATON. */
8560 output_automaton_name (FILE *f
, automaton_t automaton
)
8562 if (automaton
->corresponding_automaton_decl
== NULL
)
8563 fprintf (f
, "#%d", automaton
->automaton_order_num
);
8565 fprintf (f
, "`%s'", automaton
->corresponding_automaton_decl
->name
);
8568 /* Maximal length of line for pretty printing into description
8570 #define MAX_LINE_LENGTH 70
8572 /* The function outputs units name belonging to AUTOMATON. */
8574 output_automaton_units (automaton_t automaton
)
8578 int curr_line_length
;
8579 int there_is_an_automaton_unit
;
8582 fprintf (output_description_file
, "\n Corresponding units:\n");
8583 fprintf (output_description_file
, " ");
8584 curr_line_length
= 4;
8585 there_is_an_automaton_unit
= 0;
8586 for (i
= 0; i
< description
->decls_num
; i
++)
8588 decl
= description
->decls
[i
];
8589 if (decl
->mode
== dm_unit
8590 && (DECL_UNIT (decl
)->corresponding_automaton_num
8591 == automaton
->automaton_order_num
))
8593 there_is_an_automaton_unit
= 1;
8594 name
= DECL_UNIT (decl
)->name
;
8595 if (curr_line_length
+ strlen (name
) + 1 > MAX_LINE_LENGTH
)
8597 curr_line_length
= strlen (name
) + 4;
8598 fprintf (output_description_file
, "\n ");
8602 curr_line_length
+= strlen (name
) + 1;
8603 fprintf (output_description_file
, " ");
8605 fprintf (output_description_file
, "%s", name
);
8608 if (!there_is_an_automaton_unit
)
8609 fprintf (output_description_file
, "<None>");
8610 fprintf (output_description_file
, "\n\n");
8613 /* The following variable is used for forming array of all possible cpu unit
8614 reservations described by the current DFA state. */
8615 static VEC(reserv_sets_t
,heap
) *state_reservs
;
8617 /* The function forms `state_reservs' for STATE. */
8619 add_state_reservs (state_t state
)
8621 alt_state_t curr_alt_state
;
8623 if (state
->component_states
!= NULL
)
8624 for (curr_alt_state
= state
->component_states
;
8625 curr_alt_state
!= NULL
;
8626 curr_alt_state
= curr_alt_state
->next_sorted_alt_state
)
8627 add_state_reservs (curr_alt_state
->state
);
8629 VEC_safe_push (reserv_sets_t
,heap
, state_reservs
, state
->reservs
);
8632 /* The function outputs readable representation of all out arcs of
8635 output_state_arcs (state_t state
)
8639 const char *insn_name
;
8640 int curr_line_length
;
8642 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
8645 gcc_assert (ainsn
->first_insn_with_same_reservs
);
8646 fprintf (output_description_file
, " ");
8647 curr_line_length
= 7;
8648 fprintf (output_description_file
, "%2d: ", ainsn
->insn_equiv_class_num
);
8651 insn_name
= ainsn
->insn_reserv_decl
->name
;
8652 if (curr_line_length
+ strlen (insn_name
) > MAX_LINE_LENGTH
)
8654 if (ainsn
!= arc
->insn
)
8656 fprintf (output_description_file
, ",\n ");
8657 curr_line_length
= strlen (insn_name
) + 6;
8660 curr_line_length
+= strlen (insn_name
);
8664 curr_line_length
+= strlen (insn_name
);
8665 if (ainsn
!= arc
->insn
)
8667 curr_line_length
+= 2;
8668 fprintf (output_description_file
, ", ");
8671 fprintf (output_description_file
, "%s", insn_name
);
8672 ainsn
= ainsn
->next_same_reservs_insn
;
8674 while (ainsn
!= NULL
);
8675 fprintf (output_description_file
, " %d \n",
8676 arc
->to_state
->order_state_num
);
8678 fprintf (output_description_file
, "\n");
8681 /* The following function is used for sorting possible cpu unit
8682 reservation of a DFA state. */
8684 state_reservs_cmp (const void *reservs_ptr_1
, const void *reservs_ptr_2
)
8686 return reserv_sets_cmp (*(const_reserv_sets_t
const*) reservs_ptr_1
,
8687 *(const_reserv_sets_t
const*) reservs_ptr_2
);
8690 /* The following function is used for sorting possible cpu unit
8691 reservation of a DFA state. */
8693 remove_state_duplicate_reservs (void)
8697 for (i
= 1, j
= 0; i
< VEC_length (reserv_sets_t
, state_reservs
); i
++)
8698 if (reserv_sets_cmp (VEC_index (reserv_sets_t
, state_reservs
, j
),
8699 VEC_index (reserv_sets_t
, state_reservs
, i
)))
8702 VEC_replace (reserv_sets_t
, state_reservs
, j
,
8703 VEC_index (reserv_sets_t
, state_reservs
, i
));
8705 VEC_truncate (reserv_sets_t
, state_reservs
, j
+ 1);
8708 /* The following function output readable representation of DFA(s)
8709 state used for fast recognition of pipeline hazards. State is
8710 described by possible (current and scheduled) cpu unit
8713 output_state (state_t state
)
8719 fprintf (output_description_file
, " State #%d", state
->order_state_num
);
8720 fprintf (output_description_file
,
8721 state
->new_cycle_p
? " (new cycle)\n" : "\n");
8722 add_state_reservs (state
);
8723 qsort (VEC_address (reserv_sets_t
, state_reservs
),
8724 VEC_length (reserv_sets_t
, state_reservs
),
8725 sizeof (reserv_sets_t
), state_reservs_cmp
);
8726 remove_state_duplicate_reservs ();
8727 for (i
= 1; i
< VEC_length (reserv_sets_t
, state_reservs
); i
++)
8729 fprintf (output_description_file
, " ");
8730 output_reserv_sets (output_description_file
,
8731 VEC_index (reserv_sets_t
, state_reservs
, i
));
8732 fprintf (output_description_file
, "\n");
8734 fprintf (output_description_file
, "\n");
8735 output_state_arcs (state
);
8736 VEC_free (reserv_sets_t
,heap
, state_reservs
);
8739 /* The following function output readable representation of
8740 DFAs used for fast recognition of pipeline hazards. */
8742 output_automaton_descriptions (void)
8744 automaton_t automaton
;
8746 for (automaton
= description
->first_automaton
;
8748 automaton
= automaton
->next_automaton
)
8750 fprintf (output_description_file
, "\nAutomaton ");
8751 output_automaton_name (output_description_file
, automaton
);
8752 fprintf (output_description_file
, "\n");
8753 output_automaton_units (automaton
);
8754 pass_states (automaton
, output_state
);
8760 /* The page contains top level function for generation DFA(s) used for
8763 /* The function outputs statistics about work of different phases of
8766 output_statistics (FILE *f
)
8768 automaton_t automaton
;
8771 int transition_comb_vect_els
= 0;
8772 int transition_full_vect_els
= 0;
8773 int min_issue_delay_vect_els
= 0;
8774 int locked_states
= 0;
8777 for (automaton
= description
->first_automaton
;
8779 automaton
= automaton
->next_automaton
)
8781 fprintf (f
, "\nAutomaton ");
8782 output_automaton_name (f
, automaton
);
8783 fprintf (f
, "\n %5d NDFA states, %5d NDFA arcs\n",
8784 automaton
->NDFA_states_num
, automaton
->NDFA_arcs_num
);
8785 fprintf (f
, " %5d DFA states, %5d DFA arcs\n",
8786 automaton
->DFA_states_num
, automaton
->DFA_arcs_num
);
8787 states_num
= automaton
->DFA_states_num
;
8788 if (!no_minimization_flag
)
8790 fprintf (f
, " %5d minimal DFA states, %5d minimal DFA arcs\n",
8791 automaton
->minimal_DFA_states_num
,
8792 automaton
->minimal_DFA_arcs_num
);
8793 states_num
= automaton
->minimal_DFA_states_num
;
8795 fprintf (f
, " %5d all insns %5d insn equivalence classes\n",
8796 description
->insns_num
, automaton
->insn_equiv_classes_num
);
8797 fprintf (f
, " %d locked states\n", automaton
->locked_states
);
8800 (f
, "%5ld transition comb vector els, %5ld trans table els: %s\n",
8801 (long) VEC_length (vect_el_t
, automaton
->trans_table
->comb_vect
),
8802 (long) VEC_length (vect_el_t
, automaton
->trans_table
->full_vect
),
8803 (comb_vect_p (automaton
->trans_table
)
8804 ? "use comb vect" : "use simple vect"));
8806 (f
, "%5ld min delay table els, compression factor %d\n",
8807 (long) states_num
* automaton
->insn_equiv_classes_num
,
8808 automaton
->min_issue_delay_table_compression_factor
);
8809 transition_comb_vect_els
8810 += VEC_length (vect_el_t
, automaton
->trans_table
->comb_vect
);
8811 transition_full_vect_els
8812 += VEC_length (vect_el_t
, automaton
->trans_table
->full_vect
);
8813 min_issue_delay_vect_els
8814 += states_num
* automaton
->insn_equiv_classes_num
;
8816 += automaton
->locked_states
;
8820 fprintf (f
, "\n%5d all allocated states, %5d all allocated arcs\n",
8821 allocated_states_num
, allocated_arcs_num
);
8822 fprintf (f
, "%5d all allocated alternative states\n",
8823 allocated_alt_states_num
);
8824 fprintf (f
, "%5d all transition comb vector els, %5d all trans table els\n",
8825 transition_comb_vect_els
, transition_full_vect_els
);
8826 fprintf (f
, "%5d all min delay table els\n", min_issue_delay_vect_els
);
8827 fprintf (f
, "%5d all locked states\n", locked_states
);
8831 /* The function output times of work of different phases of DFA
8834 output_time_statistics (FILE *f
)
8836 fprintf (f
, "\n transformation: ");
8837 print_active_time (f
, transform_time
);
8838 fprintf (f
, (!ndfa_flag
? ", building DFA: " : ", building NDFA: "));
8839 print_active_time (f
, NDFA_time
);
8842 fprintf (f
, ", NDFA -> DFA: ");
8843 print_active_time (f
, NDFA_to_DFA_time
);
8845 fprintf (f
, "\n DFA minimization: ");
8846 print_active_time (f
, minimize_time
);
8847 fprintf (f
, ", making insn equivalence: ");
8848 print_active_time (f
, equiv_time
);
8849 fprintf (f
, "\n all automaton generation: ");
8850 print_active_time (f
, automaton_generation_time
);
8851 fprintf (f
, ", output: ");
8852 print_active_time (f
, output_time
);
8856 /* The function generates DFA (deterministic finite state automaton)
8857 for fast recognition of pipeline hazards. No errors during
8858 checking must be fixed before this function call. */
8862 automata_num
= split_argument
;
8863 if (description
->units_num
< automata_num
)
8864 automata_num
= description
->units_num
;
8867 initiate_automata_lists ();
8868 initiate_pass_states ();
8869 initiate_excl_sets ();
8870 initiate_presence_absence_pattern_sets ();
8871 automaton_generation_time
= create_ticker ();
8873 ticker_off (&automaton_generation_time
);
8878 /* This page mainly contains top level functions of pipeline hazards
8879 description translator. */
8881 /* The following macro value is suffix of name of description file of
8882 pipeline hazards description translator. */
8883 #define STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX ".dfa"
8885 /* The function returns suffix of given file name. The returned
8886 string can not be changed. */
8888 file_name_suffix (const char *file_name
)
8890 const char *last_period
;
8892 for (last_period
= NULL
; *file_name
!= '\0'; file_name
++)
8893 if (*file_name
== '.')
8894 last_period
= file_name
;
8895 return (last_period
== NULL
? file_name
: last_period
);
8898 /* The function returns base name of given file name, i.e. pointer to
8899 first char after last `/' (or `\' for WIN32) in given file name,
8900 given file name itself if the directory name is absent. The
8901 returned string can not be changed. */
8903 base_file_name (const char *file_name
)
8905 int directory_name_length
;
8907 directory_name_length
= strlen (file_name
);
8909 while (directory_name_length
>= 0 && file_name
[directory_name_length
] != '/'
8910 && file_name
[directory_name_length
] != '\\')
8912 while (directory_name_length
>= 0 && file_name
[directory_name_length
] != '/')
8914 directory_name_length
--;
8915 return file_name
+ directory_name_length
+ 1;
8918 /* The following is top level function to initialize the work of
8919 pipeline hazards description translator. */
8921 initiate_automaton_gen (int argc
, char **argv
)
8923 const char *base_name
;
8927 split_argument
= 0; /* default value */
8928 no_minimization_flag
= 0;
8934 for (i
= 2; i
< argc
; i
++)
8935 if (strcmp (argv
[i
], NO_MINIMIZATION_OPTION
) == 0)
8936 no_minimization_flag
= 1;
8937 else if (strcmp (argv
[i
], TIME_OPTION
) == 0)
8939 else if (strcmp (argv
[i
], STATS_OPTION
) == 0)
8941 else if (strcmp (argv
[i
], V_OPTION
) == 0)
8943 else if (strcmp (argv
[i
], W_OPTION
) == 0)
8945 else if (strcmp (argv
[i
], NDFA_OPTION
) == 0)
8947 else if (strcmp (argv
[i
], PROGRESS_OPTION
) == 0)
8949 else if (strcmp (argv
[i
], "-split") == 0)
8952 fatal ("-split has no argument.");
8953 fatal ("option `-split' has not been implemented yet\n");
8954 /* split_argument = atoi (argument_vect [i + 1]); */
8957 /* Initialize IR storage. */
8958 obstack_init (&irp
);
8959 initiate_automaton_decl_table ();
8960 initiate_insn_decl_table ();
8961 initiate_decl_table ();
8962 output_file
= stdout
;
8963 output_description_file
= NULL
;
8964 base_name
= base_file_name (argv
[1]);
8965 obstack_grow (&irp
, base_name
,
8966 strlen (base_name
) - strlen (file_name_suffix (base_name
)));
8967 obstack_grow (&irp
, STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX
,
8968 strlen (STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX
) + 1);
8969 obstack_1grow (&irp
, '\0');
8970 output_description_file_name
= obstack_base (&irp
);
8971 obstack_finish (&irp
);
8974 /* The following function checks existence at least one arc marked by
8977 check_automata_insn_issues (void)
8979 automaton_t automaton
;
8980 ainsn_t ainsn
, reserv_ainsn
;
8982 for (automaton
= description
->first_automaton
;
8984 automaton
= automaton
->next_automaton
)
8986 for (ainsn
= automaton
->ainsn_list
;
8988 ainsn
= ainsn
->next_ainsn
)
8989 if (ainsn
->first_insn_with_same_reservs
&& !ainsn
->arc_exists_p
)
8991 for (reserv_ainsn
= ainsn
;
8992 reserv_ainsn
!= NULL
;
8993 reserv_ainsn
= reserv_ainsn
->next_same_reservs_insn
)
8994 if (automaton
->corresponding_automaton_decl
!= NULL
)
8997 error ("Automaton `%s': Insn `%s' will never be issued",
8998 automaton
->corresponding_automaton_decl
->name
,
8999 reserv_ainsn
->insn_reserv_decl
->name
);
9002 (0, "Automaton `%s': Insn `%s' will never be issued",
9003 automaton
->corresponding_automaton_decl
->name
,
9004 reserv_ainsn
->insn_reserv_decl
->name
);
9009 error ("Insn `%s' will never be issued",
9010 reserv_ainsn
->insn_reserv_decl
->name
);
9012 warning (0, "Insn `%s' will never be issued",
9013 reserv_ainsn
->insn_reserv_decl
->name
);
9019 /* The following vla is used for storing pointers to all achieved
9021 static VEC(state_t
,heap
) *automaton_states
;
9023 /* This function is called by function pass_states to add an achieved
9026 add_automaton_state (state_t state
)
9028 VEC_safe_push (state_t
,heap
, automaton_states
, state
);
9031 /* The following function forms list of important automata (whose
9032 states may be changed after the insn issue) for each insn. */
9034 form_important_insn_automata_lists (void)
9036 automaton_t automaton
;
9043 automaton_states
= 0;
9044 /* Mark important ainsns. */
9045 for (automaton
= description
->first_automaton
;
9047 automaton
= automaton
->next_automaton
)
9049 VEC_truncate (state_t
, automaton_states
, 0);
9050 pass_states (automaton
, add_automaton_state
);
9051 for (n
= 0; n
< VEC_length (state_t
, automaton_states
); n
++)
9053 state_t s
= VEC_index (state_t
, automaton_states
, n
);
9054 for (arc
= first_out_arc (s
);
9056 arc
= next_out_arc (arc
))
9057 if (arc
->to_state
!= s
)
9059 gcc_assert (arc
->insn
->first_insn_with_same_reservs
);
9060 for (ainsn
= arc
->insn
;
9062 ainsn
= ainsn
->next_same_reservs_insn
)
9063 ainsn
->important_p
= TRUE
;
9067 VEC_free (state_t
,heap
, automaton_states
);
9069 /* Create automata sets for the insns. */
9070 for (i
= 0; i
< description
->decls_num
; i
++)
9072 decl
= description
->decls
[i
];
9073 if (decl
->mode
== dm_insn_reserv
)
9075 automata_list_start ();
9076 for (automaton
= description
->first_automaton
;
9078 automaton
= automaton
->next_automaton
)
9079 for (ainsn
= automaton
->ainsn_list
;
9081 ainsn
= ainsn
->next_ainsn
)
9082 if (ainsn
->important_p
9083 && ainsn
->insn_reserv_decl
== DECL_INSN_RESERV (decl
))
9085 automata_list_add (automaton
);
9088 DECL_INSN_RESERV (decl
)->important_automata_list
9089 = automata_list_finish ();
9095 /* The following is top level function to generate automat(a,on) for
9096 fast recognition of pipeline hazards. */
9098 expand_automata (void)
9102 description
= create_node (sizeof (struct description
)
9103 /* One entry for cycle advancing insn. */
9104 + sizeof (decl_t
) * VEC_length (decl_t
, decls
));
9105 description
->decls_num
= VEC_length (decl_t
, decls
);
9106 description
->query_units_num
= 0;
9107 for (i
= 0; i
< description
->decls_num
; i
++)
9109 description
->decls
[i
] = VEC_index (decl_t
, decls
, i
);
9110 if (description
->decls
[i
]->mode
== dm_unit
9111 && DECL_UNIT (description
->decls
[i
])->query_p
)
9112 DECL_UNIT (description
->decls
[i
])->query_num
9113 = description
->query_units_num
++;
9115 all_time
= create_ticker ();
9116 check_time
= create_ticker ();
9118 fprintf (stderr
, "Check description...");
9119 check_all_description ();
9121 fprintf (stderr
, "done\n");
9122 ticker_off (&check_time
);
9123 generation_time
= create_ticker ();
9126 transform_insn_regexps ();
9127 check_unit_distributions_to_automata ();
9132 check_automata_insn_issues ();
9136 form_important_insn_automata_lists ();
9138 ticker_off (&generation_time
);
9141 /* The following is top level function to output PHR and to finish
9142 work with pipeline description translator. */
9144 write_automata (void)
9146 output_time
= create_ticker ();
9148 fprintf (stderr
, "Forming and outputting automata tables...");
9152 fprintf (stderr
, "done\n");
9153 fprintf (stderr
, "Output functions to work with automata...");
9155 output_chip_definitions ();
9156 output_max_insn_queue_index_def ();
9157 output_internal_min_issue_delay_func ();
9158 output_internal_trans_func ();
9159 /* Cache of insn dfa codes: */
9160 fprintf (output_file
, "\nstatic int *%s;\n", DFA_INSN_CODES_VARIABLE_NAME
);
9161 fprintf (output_file
, "\nstatic int %s;\n\n",
9162 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
);
9163 output_dfa_insn_code_func ();
9164 output_trans_func ();
9165 output_min_issue_delay_func ();
9166 output_internal_dead_lock_func ();
9167 output_dead_lock_func ();
9168 output_size_func ();
9169 output_internal_reset_func ();
9170 output_reset_func ();
9171 output_min_insn_conflict_delay_func ();
9172 output_internal_insn_latency_func ();
9173 output_insn_latency_func ();
9174 output_print_reservation_func ();
9175 /* Output function get_cpu_unit_code. */
9176 fprintf (output_file
, "\n#if %s\n\n", CPU_UNITS_QUERY_MACRO_NAME
);
9177 output_get_cpu_unit_code_func ();
9178 output_cpu_unit_reservation_p ();
9179 output_insn_has_dfa_reservation_p ();
9180 fprintf (output_file
, "\n#endif /* #if %s */\n\n",
9181 CPU_UNITS_QUERY_MACRO_NAME
);
9182 output_dfa_clean_insn_cache_func ();
9183 output_dfa_start_func ();
9184 output_dfa_finish_func ();
9186 fprintf (stderr
, "done\n");
9189 output_description_file
= fopen (output_description_file_name
, "w");
9190 if (output_description_file
== NULL
)
9192 perror (output_description_file_name
);
9193 exit (FATAL_EXIT_CODE
);
9196 fprintf (stderr
, "Output automata description...");
9197 output_description ();
9198 output_automaton_descriptions ();
9200 fprintf (stderr
, "done\n");
9201 output_statistics (output_description_file
);
9204 output_statistics (stderr
);
9205 ticker_off (&output_time
);
9207 output_time_statistics (stderr
);
9210 finish_automata_lists ();
9213 fprintf (stderr
, "Summary:\n");
9214 fprintf (stderr
, " check time ");
9215 print_active_time (stderr
, check_time
);
9216 fprintf (stderr
, ", generation time ");
9217 print_active_time (stderr
, generation_time
);
9218 fprintf (stderr
, ", all time ");
9219 print_active_time (stderr
, all_time
);
9220 fprintf (stderr
, "\n");
9222 /* Finish all work. */
9223 if (output_description_file
!= NULL
)
9225 fflush (output_description_file
);
9226 if (ferror (stdout
) != 0)
9227 fatal ("Error in writing DFA description file %s: %s",
9228 output_description_file_name
, xstrerror (errno
));
9229 fclose (output_description_file
);
9231 finish_automaton_decl_table ();
9232 finish_insn_decl_table ();
9233 finish_decl_table ();
9234 obstack_free (&irp
, NULL
);
9235 if (have_error
&& output_description_file
!= NULL
)
9236 remove (output_description_file_name
);
9240 main (int argc
, char **argv
)
9244 progname
= "genautomata";
9246 if (init_md_reader_args (argc
, argv
) != SUCCESS_EXIT_CODE
)
9247 return (FATAL_EXIT_CODE
);
9249 initiate_automaton_gen (argc
, argv
);
9253 int insn_code_number
;
9255 desc
= read_md_rtx (&lineno
, &insn_code_number
);
9259 switch (GET_CODE (desc
))
9261 case DEFINE_CPU_UNIT
:
9262 gen_cpu_unit (desc
);
9265 case DEFINE_QUERY_CPU_UNIT
:
9266 gen_query_cpu_unit (desc
);
9274 gen_excl_set (desc
);
9278 gen_presence_set (desc
);
9281 case FINAL_PRESENCE_SET
:
9282 gen_final_presence_set (desc
);
9286 gen_absence_set (desc
);
9289 case FINAL_ABSENCE_SET
:
9290 gen_final_absence_set (desc
);
9293 case DEFINE_AUTOMATON
:
9294 gen_automaton (desc
);
9297 case AUTOMATA_OPTION
:
9298 gen_automata_option (desc
);
9301 case DEFINE_RESERVATION
:
9305 case DEFINE_INSN_RESERVATION
:
9306 gen_insn_reserv (desc
);
9315 return FATAL_EXIT_CODE
;
9317 puts ("/* Generated automatically by the program `genautomata'\n"
9318 " from the machine description file `md'. */\n\n"
9319 "#include \"config.h\"\n"
9320 "#include \"system.h\"\n"
9321 "#include \"coretypes.h\"\n"
9322 "#include \"tm.h\"\n"
9323 "#include \"rtl.h\"\n"
9324 "#include \"tm_p.h\"\n"
9325 "#include \"insn-config.h\"\n"
9326 "#include \"recog.h\"\n"
9327 "#include \"regs.h\"\n"
9328 "#include \"real.h\"\n"
9329 "#include \"output.h\"\n"
9330 "#include \"insn-attr.h\"\n"
9331 "#include \"toplev.h\"\n"
9332 "#include \"flags.h\"\n"
9333 "#include \"function.h\"\n");
9335 if (VEC_length (decl_t
, decls
) > 0)
9342 return (ferror (stdout
) != 0 ? FATAL_EXIT_CODE
: SUCCESS_EXIT_CODE
);