1 /* Pipeline hazard description translator.
2 Copyright (C) 2000-2024 Free Software Foundation, Inc.
4 Written by Vladimir Makarov <vmakarov@redhat.com>
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 3, or (at your option) any
13 GCC is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. */
24 1. The finite state automaton based pipeline hazard recognizer and
25 instruction scheduler in GCC. V. Makarov. Proceedings of GCC
28 2. Detecting pipeline structural hazards quickly. T. Proebsting,
29 C. Fraser. Proceedings of ACM SIGPLAN-SIGACT Symposium on
30 Principles of Programming Languages, pages 280--286, 1994.
32 This article is a good start point to understand usage of finite
33 state automata for pipeline hazard recognizers. But I'd
34 recommend the 1st and 3rd article for more deep understanding.
36 3. Efficient Instruction Scheduling Using Finite State Automata:
37 V. Bala and N. Rubin, Proceedings of MICRO-28. This is the best
38 article about usage of finite state automata for pipeline hazard
41 The current implementation is described in the 1st article and it
42 is different from the 3rd article in the following:
44 1. New operator `|' (alternative) is permitted in functional unit
45 reservation which can be treated deterministically and
46 non-deterministically.
48 2. Possibility of usage of nondeterministic automata too.
50 3. Possibility to query functional unit reservations for given
53 4. Several constructions to describe impossible reservations
54 (`exclusion_set', `presence_set', `final_presence_set',
55 `absence_set', and `final_absence_set').
57 5. No reverse automata are generated. Trace instruction scheduling
58 requires this. It can be easily added in the future if we
61 6. Union of automaton states are not generated yet. It is planned
62 to be implemented. Such feature is needed to make more accurate
63 interlock insn scheduling to get state describing functional
64 unit reservation in a joint CFG point. */
66 /* This file code processes constructions of machine description file
67 which describes automaton used for recognition of processor pipeline
68 hazards by insn scheduler and can be used for other tasks (such as
71 The translator functions `gen_cpu_unit', `gen_query_cpu_unit',
72 `gen_bypass', `gen_excl_set', `gen_presence_set',
73 `gen_final_presence_set', `gen_absence_set',
74 `gen_final_absence_set', `gen_automaton', `gen_automata_option',
75 `gen_reserv', `gen_insn_reserv' are called from file
76 `genattrtab.cc'. They transform RTL constructions describing
77 automata in .md file into internal representation convenient for
80 The translator major function `expand_automata' processes the
81 description internal representation into finite state automaton.
84 o checking correctness of the automaton pipeline description
85 (major function is `check_all_description').
87 o generating automaton (automata) from the description (major
88 function is `make_automaton').
90 o optional transformation of nondeterministic finite state
91 automata into deterministic ones if the alternative operator
92 `|' is treated nondeterministically in the description (major
93 function is NDFA_to_DFA).
95 o optional minimization of the finite state automata by merging
96 equivalent automaton states (major function is `minimize_DFA').
98 o forming tables (some as comb vectors) and attributes
99 representing the automata (functions output_..._table).
101 Function `write_automata' outputs the created finite state
102 automaton as different tables and functions which works with the
103 automata to inquire automaton state and to change its state. These
104 function are used by gcc instruction scheduler and may be some
109 #include "coretypes.h"
114 #include "gensupport.h"
123 /* Positions in machine description file. Now they are not used. But
124 they could be used in the future for better diagnostic messages. */
127 /* The following is element of vector of current (and planned in the
128 future) functional unit reservations. */
129 typedef unsigned HOST_WIDE_INT set_el_t
;
131 /* Reservations of function units are represented by value of the following
133 typedef set_el_t
*reserv_sets_t
;
134 typedef const set_el_t
*const_reserv_sets_t
;
136 /* The following structure describes a ticker. */
139 /* The following member value is time of the ticker creation with
140 taking into account time when the ticker is off. Active time of
141 the ticker is current time minus the value. */
142 int modified_creation_time
;
143 /* The following member value is time (incremented by one) when the
144 ticker was off. Zero value means that now the ticker is on. */
145 int incremented_off_time
;
148 /* The ticker is represented by the following type. */
149 typedef struct ticker ticker_t
;
151 /* The following type describes elements of output vectors. */
152 typedef HOST_WIDE_INT vect_el_t
;
154 /* Forward declaration of structures of internal representation of
155 pipeline description based on NDFA. */
160 struct automaton_decl
;
161 struct unit_pattern_rel_decl
;
163 struct insn_reserv_decl
;
166 struct result_regexp
;
167 struct reserv_regexp
;
168 struct nothing_regexp
;
169 struct sequence_regexp
;
170 struct repeat_regexp
;
176 struct pattern_set_el
;
177 struct pattern_reserv
;
183 struct state_ainsn_table
;
185 /* The following typedefs are for brevity. */
186 typedef struct unit_decl
*unit_decl_t
;
187 typedef const struct unit_decl
*const_unit_decl_t
;
188 typedef struct decl
*decl_t
;
189 typedef const struct decl
*const_decl_t
;
190 typedef struct regexp
*regexp_t
;
191 typedef struct unit_set_el
*unit_set_el_t
;
192 typedef struct pattern_set_el
*pattern_set_el_t
;
193 typedef struct pattern_reserv
*pattern_reserv_t
;
194 typedef struct alt_state
*alt_state_t
;
195 typedef struct state
*state_t
;
196 typedef const struct state
*const_state_t
;
197 typedef struct arc
*arc_t
;
198 typedef struct ainsn
*ainsn_t
;
199 typedef struct automaton
*automaton_t
;
200 typedef struct automata_list_el
*automata_list_el_t
;
201 typedef const struct automata_list_el
*const_automata_list_el_t
;
202 typedef struct state_ainsn_table
*state_ainsn_table_t
;
204 /* Undefined position. */
205 static pos_t no_pos
= 0;
207 /* All IR is stored in the following obstack. */
208 static struct obstack irp
;
211 /* Declare vector types for various data structures: */
214 typedef vec
<vect_el_t
> vla_hwint_t
;
216 /* Forward declarations of functions used before their definitions, only. */
217 static regexp_t
gen_regexp_sequence (const char *);
218 static void reserv_sets_or (reserv_sets_t
, reserv_sets_t
,
220 static reserv_sets_t
get_excl_set (reserv_sets_t
);
221 static int check_presence_pattern_sets (reserv_sets_t
,
223 static int check_absence_pattern_sets (reserv_sets_t
, reserv_sets_t
,
225 static arc_t
first_out_arc (const_state_t
);
226 static arc_t
next_out_arc (arc_t
);
230 /* Options with the following names can be set up in automata_option
231 construction. Because the strings occur more one time we use the
234 #define NO_MINIMIZATION_OPTION "-no-minimization"
235 #define TIME_OPTION "-time"
236 #define STATS_OPTION "-stats"
237 #define V_OPTION "-v"
238 #define W_OPTION "-w"
239 #define NDFA_OPTION "-ndfa"
240 #define COLLAPSE_OPTION "-collapse-ndfa"
241 #define NO_COMB_OPTION "-no-comb-vect"
242 #define PROGRESS_OPTION "-progress"
244 /* The following flags are set up by function `initiate_automaton_gen'. */
246 /* Make automata with nondeterministic reservation by insns (`-ndfa'). */
247 static int ndfa_flag
;
249 /* When making an NDFA, produce additional transitions that collapse
250 NDFA state into a deterministic one suitable for querying CPU units.
251 Provide advance-state transitions only for deterministic states. */
252 static int collapse_flag
;
254 /* Do not make minimization of DFA (`-no-minimization'). */
255 static int no_minimization_flag
;
257 /* Do not try to generate a comb vector (`-no-comb-vect'). */
258 static int no_comb_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_pattern
;
384 const char *in_pattern
;
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
466 is output insn. Bypasses with the same input insn stay one after
467 another in the list in the same order as their occurrences in the
468 description but the bypass without a guard stays always the last
469 in a row of bypasses with the same input insn. */
470 struct bypass_decl
*bypass_list
;
472 /* The following fields are defined by automaton generator. */
474 /* The following field is the insn regexp transformed that
475 the regexp has not optional regexp, repetition regexp, and an
476 reservation name (i.e. reservation identifiers are changed by the
477 corresponding regexp) and all alternations are the top level
478 of the regexp. The value can be NULL only if it is special
479 insn `cycle advancing'. */
480 regexp_t transformed_regexp
;
481 /* The following field value is list of arcs marked given
482 insn. The field is used in transformation NDFA -> DFA. */
483 arc_t arcs_marked_by_insn
;
484 /* The two following fields are used during minimization of a finite state
486 /* The field value is number of equivalence class of state into
487 which arc marked by given insn enters from a state (fixed during
488 an automaton minimization). */
490 /* The following member value is the list to automata which can be
491 changed by the insn issue. */
492 automata_list_el_t important_automata_list
;
493 /* The following member is used to process insn once for output. */
497 /* This contains a declaration mentioned above. */
500 /* What node in the union? */
505 struct unit_decl unit
;
506 struct bypass_decl bypass
;
507 struct automaton_decl automaton
;
508 struct excl_rel_decl excl
;
509 struct unit_pattern_rel_decl presence
;
510 struct unit_pattern_rel_decl absence
;
511 struct reserv_decl reserv
;
512 struct insn_reserv_decl insn_reserv
;
516 /* The following structures represent parsed reservation strings. */
528 /* Cpu unit in reservation. */
532 unit_decl_t unit_decl
;
535 /* Define_reservation in a reservation. */
539 struct reserv_decl
*reserv_decl
;
542 /* Absence of reservation (represented by string `nothing'). */
543 struct nothing_regexp
545 /* This used to be empty but ISO C doesn't allow that. */
549 /* Representation of reservations separated by ',' (see file
551 struct sequence_regexp
554 regexp_t regexps
[1];
557 /* Representation of construction `repeat' (see file rtl.def). */
564 /* Representation of reservations separated by '+' (see file
569 regexp_t regexps
[1];
572 /* Representation of reservations separated by '|' (see file
577 regexp_t regexps
[1];
580 /* Representation of a reservation string. */
583 /* What node in the union? */
584 enum regexp_mode mode
;
588 struct unit_regexp unit
;
589 struct reserv_regexp reserv
;
590 struct nothing_regexp nothing
;
591 struct sequence_regexp sequence
;
592 struct repeat_regexp repeat
;
593 struct allof_regexp allof
;
594 struct oneof_regexp oneof
;
598 /* Represents description of pipeline hazard description based on
602 int decls_num
, normal_decls_num
;
604 /* The following fields are defined by checker. */
606 /* The following fields values are correspondingly number of all
607 units, query units, and insns in the description. */
611 /* The following field value is max length (in cycles) of
612 reservations of insns. The field value is defined only for
614 int max_insn_reserv_cycles
;
616 /* The following fields are defined by automaton generator. */
618 /* The following field value is the first automaton. */
619 automaton_t first_automaton
;
621 /* The following field is created by pipeline hazard parser and
622 contains all declarations. We allocate additional entries for
623 two special insns which are added by the automaton generator. */
628 /* The following nodes are created in automaton checker. */
630 /* The following nodes represent exclusion set for cpu units. Each
631 element is accessed through only one excl_list. */
634 unit_decl_t unit_decl
;
635 unit_set_el_t next_unit_set_el
;
638 /* The following nodes represent presence or absence pattern for cpu
639 units. Each element is accessed through only one presence_list or
641 struct pattern_set_el
643 /* The number of units in unit_decls. */
645 /* The units forming the pattern. */
646 struct unit_decl
**unit_decls
;
647 pattern_set_el_t next_pattern_set_el
;
651 /* The following nodes are created in automaton generator. */
654 /* The following nodes represent presence or absence pattern for cpu
655 units. Each element is accessed through only one element of
656 unit_presence_set_table or unit_absence_set_table. */
657 struct pattern_reserv
659 reserv_sets_t reserv
;
660 pattern_reserv_t next_pattern_reserv
;
663 /* The following node type describes state automaton. The state may
664 be deterministic or non-deterministic. Non-deterministic state has
665 several component states which represent alternative cpu units
666 reservations. The state also is used for describing a
667 deterministic reservation of automaton insn. */
670 /* The following member value is nonzero if there is a transition by
673 /* The following field is list of processor unit reservations on
675 reserv_sets_t reservs
;
676 /* The following field is unique number of given state between other
679 /* The following field value is automaton to which given state
681 automaton_t automaton
;
682 /* The following field value is the first arc output from given
685 unsigned int num_out_arcs
;
686 /* The following field is used to form NDFA. */
687 char it_was_placed_in_stack_for_NDFA_forming
;
688 /* The following field is used to form DFA. */
689 char it_was_placed_in_stack_for_DFA_forming
;
690 /* The following field is used to transform NDFA to DFA and DFA
691 minimization. The field value is not NULL if the state is a
692 compound state. In this case the value of field `unit_sets_list'
693 is NULL. All states in the list are in the hash table. The list
694 is formed through field `next_sorted_alt_state'. We should
695 support only one level of nesting state. */
696 alt_state_t component_states
;
697 /* The following field is used for passing graph of states. */
699 /* The list of states belonging to one equivalence class is formed
700 with the aid of the following field. */
701 state_t next_equiv_class_state
;
702 /* The two following fields are used during minimization of a finite
704 int equiv_class_num_1
, equiv_class_num_2
;
705 /* The following field is used during minimization of a finite state
706 automaton. The field value is state corresponding to equivalence
707 class to which given state belongs. */
708 state_t equiv_class_state
;
709 unsigned int *presence_signature
;
710 /* The following field value is the order number of given state.
711 The states in final DFA is enumerated with the aid of the
714 /* This member is used for passing states for searching minimal
717 /* The following member is used to evaluate min issue delay of insn
719 int min_insn_issue_delay
;
725 /* The following field refers for the state into which given arc
728 /* The following field describes that the insn issue (with cycle
729 advancing for special insn `cycle advancing' and without cycle
730 advancing for others) makes transition from given state to
731 another given state. */
733 /* The following field value is the next arc output from the same
736 /* List of arcs marked given insn is formed with the following
737 field. The field is used in transformation NDFA -> DFA. */
738 arc_t next_arc_marked_by_insn
;
741 /* The following node type describes a deterministic alternative in
742 non-deterministic state which characterizes cpu unit reservations
743 of automaton insn or which is part of NDFA. */
746 /* The following field is a deterministic state which characterizes
747 unit reservations of the instruction. */
749 /* The following field refers to the next state which characterizes
750 unit reservations of the instruction. */
751 alt_state_t next_alt_state
;
752 /* The following field refers to the next state in sorted list. */
753 alt_state_t next_sorted_alt_state
;
756 /* The following node type describes insn of automaton. They are
757 labels of FA arcs. */
760 /* The following field value is the corresponding insn declaration
762 struct insn_reserv_decl
*insn_reserv_decl
;
763 /* The following field value is the next insn declaration for an
766 /* The following field is states which characterize automaton unit
767 reservations of the instruction. The value can be NULL only if it
768 is special insn `cycle advancing'. */
769 alt_state_t alt_states
;
770 /* The following field is sorted list of states which characterize
771 automaton unit reservations of the instruction. The value can be
772 NULL only if it is special insn `cycle advancing'. */
773 alt_state_t sorted_alt_states
;
774 /* The following field refers the next automaton insn with
775 the same reservations. */
776 ainsn_t next_same_reservs_insn
;
777 /* The following field is flag of the first automaton insn with the
778 same reservations in the declaration list. Only arcs marked such
779 insn is present in the automaton. This significantly decreases
780 memory requirements especially when several automata are
782 char first_insn_with_same_reservs
;
783 /* The following member has nonzero value if there is arc from state of
784 the automaton marked by the ainsn. */
786 /* Cyclic list of insns of an equivalence class is formed with the
787 aid of the following field. */
788 ainsn_t next_equiv_class_insn
;
789 /* The following field value is nonzero if the insn declaration is
790 the first insn declaration with given equivalence number. */
791 char first_ainsn_with_given_equivalence_num
;
792 /* The following field is number of class of equivalence of insns.
793 It is necessary because many insns may be equivalent with the
794 point of view of pipeline hazards. */
795 int insn_equiv_class_num
;
796 /* The following member value is TRUE if there is an arc in the
797 automaton marked by the insn into another state. In other
798 words, the insn can change the state of the automaton. */
802 /* The following describes an automaton for PHR. */
805 /* The following field value is the list of insn declarations for
808 /* Pointers to the ainsns corresponding to the special reservations. */
809 ainsn_t advance_ainsn
, collapse_ainsn
;
811 /* The following field value is the corresponding automaton
812 declaration. This field is not NULL only if the automatic
813 partition on automata is not used. */
814 struct automaton_decl
*corresponding_automaton_decl
;
815 /* The following field value is the next automaton. */
816 automaton_t next_automaton
;
817 /* The following field is start state of FA. There are not unit
818 reservations in the state. */
820 /* The following field value is number of equivalence classes of
821 insns (see field `insn_equiv_class_num' in
822 `insn_reserv_decl'). */
823 int insn_equiv_classes_num
;
824 /* The following field value is number of states of final DFA. */
825 int achieved_states_num
;
826 /* The following field value is the order number (0, 1, ...) of
828 int automaton_order_num
;
829 /* The following fields contain statistics information about
830 building automaton. */
831 int NDFA_states_num
, DFA_states_num
;
832 /* The following field value is defined only if minimization of DFA
834 int minimal_DFA_states_num
;
835 int NDFA_arcs_num
, DFA_arcs_num
;
836 /* The following field value is defined only if minimization of DFA
838 int minimal_DFA_arcs_num
;
839 /* The following member refers for two table state x ainsn -> int.
840 ??? Above sentence is incomprehensible. */
841 state_ainsn_table_t trans_table
;
842 /* The following member value is maximal value of min issue delay
843 for insns of the automaton. */
845 /* Usually min issue delay is small and we can place several (2, 4,
846 8) elements in one vector element. So the compression factor can
847 be 1 (no compression), 2, 4, 8. */
848 int min_issue_delay_table_compression_factor
;
849 /* Total number of locked states in this automaton. */
853 /* The following is the element of the list of automata. */
854 struct automata_list_el
856 /* The automaton itself. */
857 automaton_t automaton
;
858 /* The next automata set element. */
859 automata_list_el_t next_automata_list_el
;
862 /* The following structure describes a table state X ainsn -> int(>= 0). */
863 struct state_ainsn_table
865 /* Automaton to which given table belongs. */
866 automaton_t automaton
;
867 /* The following tree vectors for comb vector implementation of the
869 vla_hwint_t comb_vect
;
870 vla_hwint_t check_vect
;
871 vla_hwint_t base_vect
;
872 /* This is simple implementation of the table. */
873 vla_hwint_t full_vect
;
874 /* Minimal and maximal values of the previous vectors. */
875 int min_comb_vect_el_value
, max_comb_vect_el_value
;
876 int min_base_vect_el_value
, max_base_vect_el_value
;
879 /* Macros to access members of unions. Use only them for access to
880 union members of declarations and regexps. */
882 #if CHECKING_P && (GCC_VERSION >= 2007)
884 #define DECL_UNIT(d) __extension__ \
885 (({ __typeof (d) const _decl = (d); \
886 if (_decl->mode != dm_unit) \
887 decl_mode_check_failed (_decl->mode, "dm_unit", \
888 __FILE__, __LINE__, __FUNCTION__); \
889 &(_decl)->decl.unit; }))
891 #define DECL_BYPASS(d) __extension__ \
892 (({ __typeof (d) const _decl = (d); \
893 if (_decl->mode != dm_bypass) \
894 decl_mode_check_failed (_decl->mode, "dm_bypass", \
895 __FILE__, __LINE__, __FUNCTION__); \
896 &(_decl)->decl.bypass; }))
898 #define DECL_AUTOMATON(d) __extension__ \
899 (({ __typeof (d) const _decl = (d); \
900 if (_decl->mode != dm_automaton) \
901 decl_mode_check_failed (_decl->mode, "dm_automaton", \
902 __FILE__, __LINE__, __FUNCTION__); \
903 &(_decl)->decl.automaton; }))
905 #define DECL_EXCL(d) __extension__ \
906 (({ __typeof (d) const _decl = (d); \
907 if (_decl->mode != dm_excl) \
908 decl_mode_check_failed (_decl->mode, "dm_excl", \
909 __FILE__, __LINE__, __FUNCTION__); \
910 &(_decl)->decl.excl; }))
912 #define DECL_PRESENCE(d) __extension__ \
913 (({ __typeof (d) const _decl = (d); \
914 if (_decl->mode != dm_presence) \
915 decl_mode_check_failed (_decl->mode, "dm_presence", \
916 __FILE__, __LINE__, __FUNCTION__); \
917 &(_decl)->decl.presence; }))
919 #define DECL_ABSENCE(d) __extension__ \
920 (({ __typeof (d) const _decl = (d); \
921 if (_decl->mode != dm_absence) \
922 decl_mode_check_failed (_decl->mode, "dm_absence", \
923 __FILE__, __LINE__, __FUNCTION__); \
924 &(_decl)->decl.absence; }))
926 #define DECL_RESERV(d) __extension__ \
927 (({ __typeof (d) const _decl = (d); \
928 if (_decl->mode != dm_reserv) \
929 decl_mode_check_failed (_decl->mode, "dm_reserv", \
930 __FILE__, __LINE__, __FUNCTION__); \
931 &(_decl)->decl.reserv; }))
933 #define DECL_INSN_RESERV(d) __extension__ \
934 (({ __typeof (d) const _decl = (d); \
935 if (_decl->mode != dm_insn_reserv) \
936 decl_mode_check_failed (_decl->mode, "dm_insn_reserv", \
937 __FILE__, __LINE__, __FUNCTION__); \
938 &(_decl)->decl.insn_reserv; }))
940 static const char *decl_name (enum decl_mode
);
941 static void decl_mode_check_failed (enum decl_mode
, const char *,
942 const char *, int, const char *)
945 /* Return string representation of declaration mode MODE. */
947 decl_name (enum decl_mode mode
)
949 static char str
[100];
953 else if (mode
== dm_bypass
)
955 else if (mode
== dm_automaton
)
956 return "dm_automaton";
957 else if (mode
== dm_excl
)
959 else if (mode
== dm_presence
)
960 return "dm_presence";
961 else if (mode
== dm_absence
)
963 else if (mode
== dm_reserv
)
965 else if (mode
== dm_insn_reserv
)
966 return "dm_insn_reserv";
968 sprintf (str
, "unknown (%d)", (int) mode
);
972 /* The function prints message about unexpected declaration and finish
975 decl_mode_check_failed (enum decl_mode mode
, const char *expected_mode_str
,
976 const char *file
, int line
, const char *func
)
980 "\n%s: %d: error in %s: DECL check: expected decl %s, have %s\n",
981 file
, line
, func
, expected_mode_str
, decl_name (mode
));
986 #define REGEXP_UNIT(r) __extension__ \
987 (({ struct regexp *const _regexp = (r); \
988 if (_regexp->mode != rm_unit) \
989 regexp_mode_check_failed (_regexp->mode, "rm_unit", \
990 __FILE__, __LINE__, __FUNCTION__); \
991 &(_regexp)->regexp.unit; }))
993 #define REGEXP_RESERV(r) __extension__ \
994 (({ struct regexp *const _regexp = (r); \
995 if (_regexp->mode != rm_reserv) \
996 regexp_mode_check_failed (_regexp->mode, "rm_reserv", \
997 __FILE__, __LINE__, __FUNCTION__); \
998 &(_regexp)->regexp.reserv; }))
1000 #define REGEXP_SEQUENCE(r) __extension__ \
1001 (({ struct regexp *const _regexp = (r); \
1002 if (_regexp->mode != rm_sequence) \
1003 regexp_mode_check_failed (_regexp->mode, "rm_sequence", \
1004 __FILE__, __LINE__, __FUNCTION__); \
1005 &(_regexp)->regexp.sequence; }))
1007 #define REGEXP_REPEAT(r) __extension__ \
1008 (({ struct regexp *const _regexp = (r); \
1009 if (_regexp->mode != rm_repeat) \
1010 regexp_mode_check_failed (_regexp->mode, "rm_repeat", \
1011 __FILE__, __LINE__, __FUNCTION__); \
1012 &(_regexp)->regexp.repeat; }))
1014 #define REGEXP_ALLOF(r) __extension__ \
1015 (({ struct regexp *const _regexp = (r); \
1016 if (_regexp->mode != rm_allof) \
1017 regexp_mode_check_failed (_regexp->mode, "rm_allof", \
1018 __FILE__, __LINE__, __FUNCTION__); \
1019 &(_regexp)->regexp.allof; }))
1021 #define REGEXP_ONEOF(r) __extension__ \
1022 (({ struct regexp *const _regexp = (r); \
1023 if (_regexp->mode != rm_oneof) \
1024 regexp_mode_check_failed (_regexp->mode, "rm_oneof", \
1025 __FILE__, __LINE__, __FUNCTION__); \
1026 &(_regexp)->regexp.oneof; }))
1028 static const char *regexp_name (enum regexp_mode
);
1029 static void regexp_mode_check_failed (enum regexp_mode
, const char *,
1031 const char *) ATTRIBUTE_NORETURN
;
1034 /* Return string representation of regexp mode MODE. */
1036 regexp_name (enum regexp_mode mode
)
1045 return "rm_nothing";
1047 return "rm_sequence";
1059 /* The function prints message about unexpected regexp and finish the
1062 regexp_mode_check_failed (enum regexp_mode mode
,
1063 const char *expected_mode_str
,
1064 const char *file
, int line
, const char *func
)
1068 "\n%s: %d: error in %s: REGEXP check: expected decl %s, have %s\n",
1069 file
, line
, func
, expected_mode_str
, regexp_name (mode
));
1073 #else /* #if CHECKING_P && (GCC_VERSION >= 2007) */
1075 #define DECL_UNIT(d) (&(d)->decl.unit)
1076 #define DECL_BYPASS(d) (&(d)->decl.bypass)
1077 #define DECL_AUTOMATON(d) (&(d)->decl.automaton)
1078 #define DECL_EXCL(d) (&(d)->decl.excl)
1079 #define DECL_PRESENCE(d) (&(d)->decl.presence)
1080 #define DECL_ABSENCE(d) (&(d)->decl.absence)
1081 #define DECL_RESERV(d) (&(d)->decl.reserv)
1082 #define DECL_INSN_RESERV(d) (&(d)->decl.insn_reserv)
1084 #define REGEXP_UNIT(r) (&(r)->regexp.unit)
1085 #define REGEXP_RESERV(r) (&(r)->regexp.reserv)
1086 #define REGEXP_SEQUENCE(r) (&(r)->regexp.sequence)
1087 #define REGEXP_REPEAT(r) (&(r)->regexp.repeat)
1088 #define REGEXP_ALLOF(r) (&(r)->regexp.allof)
1089 #define REGEXP_ONEOF(r) (&(r)->regexp.oneof)
1091 #endif /* #if CHECKING_P && (GCC_VERSION >= 2007) */
1093 #define XCREATENODE(T) ((T *) create_node (sizeof (T)))
1094 #define XCREATENODEVEC(T, N) ((T *) create_node (sizeof (T) * (N)))
1095 #define XCREATENODEVAR(T, S) ((T *) create_node ((S)))
1097 #define XCOPYNODE(T, P) ((T *) copy_node ((P), sizeof (T)))
1098 #define XCOPYNODEVEC(T, P, N) ((T *) copy_node ((P), sizeof (T) * (N)))
1099 #define XCOPYNODEVAR(T, P, S) ((T *) copy_node ((P), (S)))
1101 /* Create IR structure (node). */
1103 create_node (size_t size
)
1107 obstack_blank (&irp
, size
);
1108 result
= obstack_base (&irp
);
1109 obstack_finish (&irp
);
1110 /* Default values of members are NULL and zero. */
1111 memset (result
, 0, size
);
1115 /* Copy IR structure (node). */
1117 copy_node (const void *from
, size_t size
)
1119 void *const result
= create_node (size
);
1120 memcpy (result
, from
, size
);
1124 /* The function checks that NAME does not contain quotes (`"'). */
1126 check_name (const char * name
, pos_t pos ATTRIBUTE_UNUSED
)
1130 for (str
= name
; *str
!= '\0'; str
++)
1132 error ("Name `%s' contains quotes", name
);
1136 /* Pointers to all declarations during IR generation are stored in the
1138 static vec
<decl_t
> decls
;
1140 /* Given a pointer to a (char *) and a separator, return an alloc'ed
1141 string containing the next separated element, taking parentheses
1142 into account if PAR_FLAG has nonzero value. Advance the pointer to
1143 after the string scanned, or the end-of-string. Return NULL if at
1146 next_sep_el (const char **pstr
, int sep
, int par_flag
)
1153 /* Remove leading whitespaces. */
1154 while (ISSPACE ((int) **pstr
))
1161 for (pars_num
= 0, p
= *pstr
; *p
!= '\0'; p
++)
1163 if (par_flag
&& *p
== '(')
1165 else if (par_flag
&& *p
== ')')
1167 else if (pars_num
== 0 && *p
== sep
)
1169 if (pars_num
== 0 && ISSPACE ((int) *p
))
1173 for (; n_spaces
!= 0; n_spaces
--)
1174 obstack_1grow (&irp
, p
[-n_spaces
]);
1175 obstack_1grow (&irp
, *p
);
1178 obstack_1grow (&irp
, '\0');
1179 out_str
= (char *) obstack_base (&irp
);
1180 obstack_finish (&irp
);
1189 /* Given a string and a separator, return the number of separated
1190 elements in it, taking parentheses into account if PAR_FLAG has
1191 nonzero value. Return 0 for the null string, -1 if parentheses is
1194 n_sep_els (const char *s
, int sep
, int par_flag
)
1202 for (pars_num
= 0, n
= 1; *s
; s
++)
1203 if (par_flag
&& *s
== '(')
1205 else if (par_flag
&& *s
== ')')
1207 else if (pars_num
== 0 && *s
== sep
)
1210 return (pars_num
!= 0 ? -1 : n
);
1213 /* Given a string and a separator, return vector of strings which are
1214 elements in the string and number of elements through els_num.
1215 Take parentheses into account if PAREN_P has nonzero value. The
1216 function also inserts the end marker NULL at the end of vector.
1217 Return 0 for the null string, -1 if parentheses are not balanced. */
1219 get_str_vect (const char *str
, int *els_num
, int sep
, int paren_p
)
1226 *els_num
= n_sep_els (str
, sep
, paren_p
);
1229 obstack_blank (&irp
, sizeof (char *) * (*els_num
+ 1));
1230 vect
= (char **) obstack_base (&irp
);
1231 obstack_finish (&irp
);
1233 for (i
= 0; i
< *els_num
; i
++)
1234 vect
[i
] = next_sep_el (pstr
, sep
, paren_p
);
1235 trail
= next_sep_el (pstr
, sep
, paren_p
);
1236 gcc_assert (!trail
);
1241 /* Process a DEFINE_CPU_UNIT.
1243 This gives information about a unit contained in CPU. We fill a
1244 struct unit_decl with information used later by `expand_automata'. */
1246 gen_cpu_unit (md_rtx_info
*info
)
1249 char **str_cpu_units
;
1253 rtx def
= info
->def
;
1254 str_cpu_units
= get_str_vect (XSTR (def
, 0), &vect_length
, ',', false);
1255 if (str_cpu_units
== NULL
)
1256 fatal_at (info
->loc
, "invalid string `%s' in %s",
1257 XSTR (def
, 0), GET_RTX_NAME (GET_CODE (def
)));
1258 for (i
= 0; i
< vect_length
; i
++)
1260 decl
= XCREATENODE (struct decl
);
1261 decl
->mode
= dm_unit
;
1263 DECL_UNIT (decl
)->name
= check_name (str_cpu_units
[i
], decl
->pos
);
1264 DECL_UNIT (decl
)->automaton_name
= XSTR (def
, 1);
1265 DECL_UNIT (decl
)->query_p
= 0;
1266 DECL_UNIT (decl
)->min_occ_cycle_num
= -1;
1267 DECL_UNIT (decl
)->in_set_p
= 0;
1268 decls
.safe_push (decl
);
1272 /* Process a DEFINE_QUERY_CPU_UNIT.
1274 This gives information about a unit contained in CPU. We fill a
1275 struct unit_decl with information used later by `expand_automata'. */
1277 gen_query_cpu_unit (md_rtx_info
*info
)
1280 char **str_cpu_units
;
1284 rtx def
= info
->def
;
1285 str_cpu_units
= get_str_vect (XSTR (def
, 0), &vect_length
, ',',
1287 if (str_cpu_units
== NULL
)
1288 fatal_at (info
->loc
, "invalid string `%s' in %s",
1289 XSTR (def
, 0), GET_RTX_NAME (GET_CODE (def
)));
1290 for (i
= 0; i
< vect_length
; i
++)
1292 decl
= XCREATENODE (struct decl
);
1293 decl
->mode
= dm_unit
;
1295 DECL_UNIT (decl
)->name
= check_name (str_cpu_units
[i
], decl
->pos
);
1296 DECL_UNIT (decl
)->automaton_name
= XSTR (def
, 1);
1297 DECL_UNIT (decl
)->query_p
= 1;
1298 decls
.safe_push (decl
);
1302 /* Process a DEFINE_BYPASS.
1304 This gives information about a unit contained in the CPU. We fill
1305 in a struct bypass_decl with information used later by
1306 `expand_automata'. */
1308 gen_bypass (md_rtx_info
*info
)
1311 char **out_patterns
;
1317 rtx def
= info
->def
;
1318 out_patterns
= get_str_vect (XSTR (def
, 1), &out_length
, ',', false);
1319 if (out_patterns
== NULL
)
1320 fatal_at (info
->loc
, "invalid string `%s' in %s",
1321 XSTR (def
, 1), GET_RTX_NAME (GET_CODE (def
)));
1322 in_patterns
= get_str_vect (XSTR (def
, 2), &in_length
, ',', false);
1323 if (in_patterns
== NULL
)
1324 fatal_at (info
->loc
, "invalid string `%s' in %s",
1325 XSTR (def
, 2), GET_RTX_NAME (GET_CODE (def
)));
1326 for (i
= 0; i
< out_length
; i
++)
1327 for (j
= 0; j
< in_length
; j
++)
1329 decl
= XCREATENODE (struct decl
);
1330 decl
->mode
= dm_bypass
;
1332 DECL_BYPASS (decl
)->latency
= XINT (def
, 0);
1333 DECL_BYPASS (decl
)->out_pattern
= out_patterns
[i
];
1334 DECL_BYPASS (decl
)->in_pattern
= in_patterns
[j
];
1335 DECL_BYPASS (decl
)->bypass_guard_name
= XSTR (def
, 3);
1336 decls
.safe_push (decl
);
1340 /* Process an EXCLUSION_SET.
1342 This gives information about a cpu unit conflicts. We fill a
1343 struct excl_rel_decl (excl) with information used later by
1344 `expand_automata'. */
1346 gen_excl_set (md_rtx_info
*info
)
1349 char **first_str_cpu_units
;
1350 char **second_str_cpu_units
;
1351 int first_vect_length
;
1355 rtx def
= info
->def
;
1357 = get_str_vect (XSTR (def
, 0), &first_vect_length
, ',', false);
1358 if (first_str_cpu_units
== NULL
)
1359 fatal_at (info
->loc
, "invalid string `%s' in %s",
1360 XSTR (def
, 0), GET_RTX_NAME (GET_CODE (def
)));
1361 second_str_cpu_units
= get_str_vect (XSTR (def
, 1), &length
, ',',
1363 if (second_str_cpu_units
== NULL
)
1364 fatal_at (info
->loc
, "invalid string `%s' in %s",
1365 XSTR (def
, 1), GET_RTX_NAME (GET_CODE (def
)));
1366 length
+= first_vect_length
;
1367 decl
= XCREATENODEVAR (struct decl
, (sizeof (struct decl
)
1368 + (length
- 1) * sizeof (char *)));
1369 decl
->mode
= dm_excl
;
1371 DECL_EXCL (decl
)->all_names_num
= length
;
1372 DECL_EXCL (decl
)->first_list_length
= first_vect_length
;
1373 for (i
= 0; i
< length
; i
++)
1374 if (i
< first_vect_length
)
1375 DECL_EXCL (decl
)->names
[i
] = first_str_cpu_units
[i
];
1377 DECL_EXCL (decl
)->names
[i
]
1378 = second_str_cpu_units
[i
- first_vect_length
];
1379 decls
.safe_push (decl
);
1382 /* Process a PRESENCE_SET, a FINAL_PRESENCE_SET, an ABSENCE_SET,
1383 FINAL_ABSENCE_SET (it is depended on PRESENCE_P and FINAL_P).
1385 This gives information about a cpu unit reservation requirements.
1386 We fill a struct unit_pattern_rel_decl with information used later
1387 by `expand_automata'. */
1389 gen_presence_absence_set (md_rtx_info
*info
, int presence_p
, int final_p
)
1392 char **str_cpu_units
;
1393 char **str_pattern_lists
;
1394 char ***str_patterns
;
1395 int cpu_units_length
;
1397 int patterns_length
;
1400 rtx def
= info
->def
;
1401 str_cpu_units
= get_str_vect (XSTR (def
, 0), &cpu_units_length
, ',',
1403 if (str_cpu_units
== NULL
)
1404 fatal_at (info
->loc
, "invalid string `%s' in %s",
1405 XSTR (def
, 0), GET_RTX_NAME (GET_CODE (def
)));
1406 str_pattern_lists
= get_str_vect (XSTR (def
, 1),
1407 &patterns_length
, ',', false);
1408 if (str_pattern_lists
== NULL
)
1409 fatal_at (info
->loc
, "invalid string `%s' in %s",
1410 XSTR (def
, 1), GET_RTX_NAME (GET_CODE (def
)));
1411 str_patterns
= XOBNEWVEC (&irp
, char **, patterns_length
);
1412 for (i
= 0; i
< patterns_length
; i
++)
1414 str_patterns
[i
] = get_str_vect (str_pattern_lists
[i
],
1415 &length
, ' ', false);
1416 gcc_assert (str_patterns
[i
]);
1418 decl
= XCREATENODE (struct decl
);
1422 decl
->mode
= dm_presence
;
1423 DECL_PRESENCE (decl
)->names_num
= cpu_units_length
;
1424 DECL_PRESENCE (decl
)->names
= str_cpu_units
;
1425 DECL_PRESENCE (decl
)->patterns
= str_patterns
;
1426 DECL_PRESENCE (decl
)->patterns_num
= patterns_length
;
1427 DECL_PRESENCE (decl
)->final_p
= final_p
;
1431 decl
->mode
= dm_absence
;
1432 DECL_ABSENCE (decl
)->names_num
= cpu_units_length
;
1433 DECL_ABSENCE (decl
)->names
= str_cpu_units
;
1434 DECL_ABSENCE (decl
)->patterns
= str_patterns
;
1435 DECL_ABSENCE (decl
)->patterns_num
= patterns_length
;
1436 DECL_ABSENCE (decl
)->final_p
= final_p
;
1438 decls
.safe_push (decl
);
1441 /* Process a PRESENCE_SET.
1443 This gives information about a cpu unit reservation requirements.
1444 We fill a struct unit_pattern_rel_decl (presence) with information
1445 used later by `expand_automata'. */
1447 gen_presence_set (md_rtx_info
*info
)
1449 gen_presence_absence_set (info
, true, false);
1452 /* Process a FINAL_PRESENCE_SET.
1454 This gives information about a cpu unit reservation requirements.
1455 We fill a struct unit_pattern_rel_decl (presence) with information
1456 used later by `expand_automata'. */
1458 gen_final_presence_set (md_rtx_info
*info
)
1460 gen_presence_absence_set (info
, true, true);
1463 /* Process an ABSENCE_SET.
1465 This gives information about a cpu unit reservation requirements.
1466 We fill a struct unit_pattern_rel_decl (absence) with information
1467 used later by `expand_automata'. */
1469 gen_absence_set (md_rtx_info
*info
)
1471 gen_presence_absence_set (info
, false, false);
1474 /* Process a FINAL_ABSENCE_SET.
1476 This gives information about a cpu unit reservation requirements.
1477 We fill a struct unit_pattern_rel_decl (absence) with information
1478 used later by `expand_automata'. */
1480 gen_final_absence_set (md_rtx_info
*info
)
1482 gen_presence_absence_set (info
, false, true);
1485 /* Process a DEFINE_AUTOMATON.
1487 This gives information about a finite state automaton used for
1488 recognizing pipeline hazards. We fill a struct automaton_decl
1489 with information used later by `expand_automata'. */
1491 gen_automaton (md_rtx_info
*info
)
1494 char **str_automata
;
1498 rtx def
= info
->def
;
1499 str_automata
= get_str_vect (XSTR (def
, 0), &vect_length
, ',', false);
1500 if (str_automata
== NULL
)
1501 fatal_at (info
->loc
, "invalid string `%s' in %s",
1502 XSTR (def
, 0), GET_RTX_NAME (GET_CODE (def
)));
1503 for (i
= 0; i
< vect_length
; i
++)
1505 decl
= XCREATENODE (struct decl
);
1506 decl
->mode
= dm_automaton
;
1508 DECL_AUTOMATON (decl
)->name
= check_name (str_automata
[i
], decl
->pos
);
1509 decls
.safe_push (decl
);
1513 /* Process an AUTOMATA_OPTION.
1515 This gives information how to generate finite state automaton used
1516 for recognizing pipeline hazards. */
1518 gen_automata_option (md_rtx_info
*info
)
1520 const char *option
= XSTR (info
->def
, 0);
1521 if (strcmp (option
, NO_MINIMIZATION_OPTION
+ 1) == 0)
1522 no_minimization_flag
= 1;
1523 else if (strcmp (option
, TIME_OPTION
+ 1) == 0)
1525 else if (strcmp (option
, STATS_OPTION
+ 1) == 0)
1527 else if (strcmp (option
, V_OPTION
+ 1) == 0)
1529 else if (strcmp (option
, W_OPTION
+ 1) == 0)
1531 else if (strcmp (option
, NDFA_OPTION
+ 1) == 0)
1533 else if (strcmp (option
, COLLAPSE_OPTION
+ 1) == 0)
1535 else if (strcmp (option
, NO_COMB_OPTION
+ 1) == 0)
1537 else if (strcmp (option
, PROGRESS_OPTION
+ 1) == 0)
1540 fatal_at (info
->loc
, "invalid option `%s' in %s",
1541 option
, GET_RTX_NAME (GET_CODE (info
->def
)));
1544 /* Name in reservation to denote absence reservation. */
1545 #define NOTHING_NAME "nothing"
1547 /* The following string contains original reservation string being
1549 static const char *reserv_str
;
1551 /* Parse an element in STR. */
1553 gen_regexp_el (const char *str
)
1562 if (str
[len
- 1] != ')')
1563 fatal ("garbage after ) in reservation `%s'", reserv_str
);
1564 dstr
= XALLOCAVAR (char, len
- 1);
1565 memcpy (dstr
, str
+ 1, len
- 2);
1566 dstr
[len
-2] = '\0';
1567 regexp
= gen_regexp_sequence (dstr
);
1569 else if (strcmp (str
, NOTHING_NAME
) == 0)
1571 regexp
= XCREATENODE (struct regexp
);
1572 regexp
->mode
= rm_nothing
;
1576 regexp
= XCREATENODE (struct regexp
);
1577 regexp
->mode
= rm_unit
;
1578 REGEXP_UNIT (regexp
)->name
= str
;
1583 /* Parse construction `repeat' in STR. */
1585 gen_regexp_repeat (const char *str
)
1593 repeat_vect
= get_str_vect (str
, &els_num
, '*', true);
1594 if (repeat_vect
== NULL
)
1595 fatal ("invalid `%s' in reservation `%s'", str
, reserv_str
);
1598 regexp
= gen_regexp_el (repeat_vect
[0]);
1599 for (i
= 1; i
< els_num
; i
++)
1601 repeat
= XCREATENODE (struct regexp
);
1602 repeat
->mode
= rm_repeat
;
1603 REGEXP_REPEAT (repeat
)->regexp
= regexp
;
1604 REGEXP_REPEAT (repeat
)->repeat_num
= atoi (repeat_vect
[i
]);
1605 if (REGEXP_REPEAT (repeat
)->repeat_num
<= 1)
1606 fatal ("repetition `%s' <= 1 in reservation `%s'",
1613 return gen_regexp_el (repeat_vect
[0]);
1616 /* Parse reservation STR which possibly contains separator '+'. */
1618 gen_regexp_allof (const char *str
)
1625 allof_vect
= get_str_vect (str
, &els_num
, '+', true);
1626 if (allof_vect
== NULL
)
1627 fatal ("invalid `%s' in reservation `%s'", str
, reserv_str
);
1630 allof
= XCREATENODEVAR (struct regexp
, sizeof (struct regexp
)
1631 + sizeof (regexp_t
) * (els_num
- 1));
1632 allof
->mode
= rm_allof
;
1633 REGEXP_ALLOF (allof
)->regexps_num
= els_num
;
1634 for (i
= 0; i
< els_num
; i
++)
1635 REGEXP_ALLOF (allof
)->regexps
[i
] = gen_regexp_repeat (allof_vect
[i
]);
1639 return gen_regexp_repeat (allof_vect
[0]);
1642 /* Parse reservation STR which possibly contains separator '|'. */
1644 gen_regexp_oneof (const char *str
)
1651 oneof_vect
= get_str_vect (str
, &els_num
, '|', true);
1652 if (oneof_vect
== NULL
)
1653 fatal ("invalid `%s' in reservation `%s'", str
, reserv_str
);
1656 oneof
= XCREATENODEVAR (struct regexp
, sizeof (struct regexp
)
1657 + sizeof (regexp_t
) * (els_num
- 1));
1658 oneof
->mode
= rm_oneof
;
1659 REGEXP_ONEOF (oneof
)->regexps_num
= els_num
;
1660 for (i
= 0; i
< els_num
; i
++)
1661 REGEXP_ONEOF (oneof
)->regexps
[i
] = gen_regexp_allof (oneof_vect
[i
]);
1665 return gen_regexp_allof (oneof_vect
[0]);
1668 /* Parse reservation STR which possibly contains separator ','. */
1670 gen_regexp_sequence (const char *str
)
1673 char **sequence_vect
;
1677 sequence_vect
= get_str_vect (str
, &els_num
, ',', true);
1679 fatal ("unbalanced parentheses in reservation `%s'", str
);
1680 if (sequence_vect
== NULL
)
1681 fatal ("invalid reservation `%s'", str
);
1684 sequence
= XCREATENODEVAR (struct regexp
, sizeof (struct regexp
)
1685 + sizeof (regexp_t
) * (els_num
- 1));
1686 sequence
->mode
= rm_sequence
;
1687 REGEXP_SEQUENCE (sequence
)->regexps_num
= els_num
;
1688 for (i
= 0; i
< els_num
; i
++)
1689 REGEXP_SEQUENCE (sequence
)->regexps
[i
]
1690 = gen_regexp_oneof (sequence_vect
[i
]);
1694 return gen_regexp_oneof (sequence_vect
[0]);
1697 /* Parse construction reservation STR. */
1699 gen_regexp (const char *str
)
1702 return gen_regexp_sequence (str
);
1705 /* Process a DEFINE_RESERVATION.
1707 This gives information about a reservation of cpu units. We fill
1708 in a struct reserv_decl with information used later by
1709 `expand_automata'. */
1711 gen_reserv (md_rtx_info
*info
)
1715 rtx def
= info
->def
;
1716 decl
= XCREATENODE (struct decl
);
1717 decl
->mode
= dm_reserv
;
1719 DECL_RESERV (decl
)->name
= check_name (XSTR (def
, 0), decl
->pos
);
1720 DECL_RESERV (decl
)->regexp
= gen_regexp (XSTR (def
, 1));
1721 decls
.safe_push (decl
);
1724 /* Process a DEFINE_INSN_RESERVATION.
1726 This gives information about the reservation of cpu units by an
1727 insn. We fill a struct insn_reserv_decl with information used
1728 later by `expand_automata'. */
1730 gen_insn_reserv (md_rtx_info
*info
)
1734 rtx def
= info
->def
;
1735 decl
= XCREATENODE (struct decl
);
1736 decl
->mode
= dm_insn_reserv
;
1738 DECL_INSN_RESERV (decl
)->name
1739 = check_name (XSTR (def
, 0), decl
->pos
);
1740 DECL_INSN_RESERV (decl
)->default_latency
= XINT (def
, 1);
1741 DECL_INSN_RESERV (decl
)->condexp
= XEXP (def
, 2);
1742 DECL_INSN_RESERV (decl
)->regexp
= gen_regexp (XSTR (def
, 3));
1743 decls
.safe_push (decl
);
1748 /* The function evaluates hash value (0..UINT_MAX) of string. */
1750 string_hash (const char *string
)
1754 for (result
= i
= 0;*string
++ != '\0'; i
++)
1755 result
+= ((unsigned char) *string
<< (i
% CHAR_BIT
));
1761 /* This page contains abstract data `table of automaton declarations'.
1762 Elements of the table is nodes representing automaton declarations.
1763 Key of the table elements is name of given automaton. Remember
1764 that automaton names have own space. */
1766 /* The function evaluates hash value of an automaton declaration. The
1767 function is used by abstract data `hashtab'. The function returns
1768 hash value (0..UINT_MAX) of given automaton declaration. */
1770 automaton_decl_hash (const void *automaton_decl
)
1772 const_decl_t
const decl
= (const_decl_t
) automaton_decl
;
1774 gcc_assert (decl
->mode
!= dm_automaton
1775 || DECL_AUTOMATON (decl
)->name
);
1776 return string_hash (DECL_AUTOMATON (decl
)->name
);
1779 /* The function tests automaton declarations on equality of their
1780 keys. The function is used by abstract data `hashtab'. The
1781 function returns 1 if the declarations have the same key, 0
1784 automaton_decl_eq_p (const void* automaton_decl_1
,
1785 const void* automaton_decl_2
)
1787 const_decl_t
const decl1
= (const_decl_t
) automaton_decl_1
;
1788 const_decl_t
const decl2
= (const_decl_t
) automaton_decl_2
;
1790 gcc_assert (decl1
->mode
== dm_automaton
1791 && DECL_AUTOMATON (decl1
)->name
1792 && decl2
->mode
== dm_automaton
1793 && DECL_AUTOMATON (decl2
)->name
);
1794 return strcmp (DECL_AUTOMATON (decl1
)->name
,
1795 DECL_AUTOMATON (decl2
)->name
) == 0;
1798 /* The automaton declaration table itself is represented by the
1799 following variable. */
1800 static htab_t automaton_decl_table
;
1802 /* The function inserts automaton declaration into the table. The
1803 function does nothing if an automaton declaration with the same key
1804 exists already in the table. The function returns automaton
1805 declaration node in the table with the same key as given automaton
1806 declaration node. */
1808 insert_automaton_decl (decl_t automaton_decl
)
1812 entry_ptr
= htab_find_slot (automaton_decl_table
, automaton_decl
, INSERT
);
1813 if (*entry_ptr
== NULL
)
1814 *entry_ptr
= (void *) automaton_decl
;
1815 return (decl_t
) *entry_ptr
;
1818 /* The following variable value is node representing automaton
1819 declaration. The node used for searching automaton declaration
1821 static struct decl work_automaton_decl
;
1823 /* The function searches for automaton declaration in the table with
1824 the same key as node representing name of the automaton
1825 declaration. The function returns node found in the table, NULL if
1826 such node does not exist in the table. */
1828 find_automaton_decl (const char *name
)
1832 work_automaton_decl
.mode
= dm_automaton
;
1833 DECL_AUTOMATON (&work_automaton_decl
)->name
= name
;
1834 entry
= htab_find (automaton_decl_table
, &work_automaton_decl
);
1835 return (decl_t
) entry
;
1838 /* The function creates empty automaton declaration table and node
1839 representing automaton declaration and used for searching automaton
1840 declaration with given name. The function must be called only once
1841 before any work with the automaton declaration table. */
1843 initiate_automaton_decl_table (void)
1845 work_automaton_decl
.mode
= dm_automaton
;
1846 automaton_decl_table
= htab_create (10, automaton_decl_hash
,
1847 automaton_decl_eq_p
, (htab_del
) 0);
1850 /* The function deletes the automaton declaration table. Only call of
1851 function `initiate_automaton_decl_table' is possible immediately
1852 after this function call. */
1854 finish_automaton_decl_table (void)
1856 htab_delete (automaton_decl_table
);
1861 /* This page contains abstract data `table of insn declarations'.
1862 Elements of the table is nodes representing insn declarations. Key
1863 of the table elements is name of given insn (in corresponding
1864 define_insn_reservation). Remember that insn names have own
1867 /* The function evaluates hash value of an insn declaration. The
1868 function is used by abstract data `hashtab'. The function returns
1869 hash value (0..UINT_MAX) of given insn declaration. */
1871 insn_decl_hash (const void *insn_decl
)
1873 const_decl_t
const decl
= (const_decl_t
) insn_decl
;
1875 gcc_assert (decl
->mode
== dm_insn_reserv
1876 && DECL_INSN_RESERV (decl
)->name
);
1877 return string_hash (DECL_INSN_RESERV (decl
)->name
);
1880 /* The function tests insn declarations on equality of their keys.
1881 The function is used by abstract data `hashtab'. The function
1882 returns 1 if declarations have the same key, 0 otherwise. */
1884 insn_decl_eq_p (const void *insn_decl_1
, const void *insn_decl_2
)
1886 const_decl_t
const decl1
= (const_decl_t
) insn_decl_1
;
1887 const_decl_t
const decl2
= (const_decl_t
) insn_decl_2
;
1889 gcc_assert (decl1
->mode
== dm_insn_reserv
1890 && DECL_INSN_RESERV (decl1
)->name
1891 && decl2
->mode
== dm_insn_reserv
1892 && DECL_INSN_RESERV (decl2
)->name
);
1893 return strcmp (DECL_INSN_RESERV (decl1
)->name
,
1894 DECL_INSN_RESERV (decl2
)->name
) == 0;
1897 /* The insn declaration table itself is represented by the following
1898 variable. The table does not contain insn reservation
1900 static htab_t insn_decl_table
;
1902 /* The function inserts insn declaration into the table. The function
1903 does nothing if an insn declaration with the same key exists
1904 already in the table. The function returns insn declaration node
1905 in the table with the same key as given insn declaration node. */
1907 insert_insn_decl (decl_t insn_decl
)
1911 entry_ptr
= htab_find_slot (insn_decl_table
, insn_decl
, INSERT
);
1912 if (*entry_ptr
== NULL
)
1913 *entry_ptr
= (void *) insn_decl
;
1914 return (decl_t
) *entry_ptr
;
1917 /* The following variable value is node representing insn reservation
1918 declaration. The node used for searching insn reservation
1919 declaration with given name. */
1920 static struct decl work_insn_decl
;
1922 /* The function searches for insn reservation declaration in the table
1923 with the same key as node representing name of the insn reservation
1924 declaration. The function returns node found in the table, NULL if
1925 such node does not exist in the table. */
1927 find_insn_decl (const char *name
)
1931 work_insn_decl
.mode
= dm_insn_reserv
;
1932 DECL_INSN_RESERV (&work_insn_decl
)->name
= name
;
1933 entry
= htab_find (insn_decl_table
, &work_insn_decl
);
1934 return (decl_t
) entry
;
1937 /* The function creates empty insn declaration table and node
1938 representing insn declaration and used for searching insn
1939 declaration with given name. The function must be called only once
1940 before any work with the insn declaration table. */
1942 initiate_insn_decl_table (void)
1944 work_insn_decl
.mode
= dm_insn_reserv
;
1945 insn_decl_table
= htab_create (10, insn_decl_hash
, insn_decl_eq_p
,
1949 /* The function deletes the insn declaration table. Only call of
1950 function `initiate_insn_decl_table' is possible immediately after
1951 this function call. */
1953 finish_insn_decl_table (void)
1955 htab_delete (insn_decl_table
);
1960 /* This page contains abstract data `table of declarations'. Elements
1961 of the table is nodes representing declarations (of units and
1962 reservations). Key of the table elements is names of given
1965 /* The function evaluates hash value of a declaration. The function
1966 is used by abstract data `hashtab'. The function returns hash
1967 value (0..UINT_MAX) of given declaration. */
1969 decl_hash (const void *decl
)
1971 const_decl_t
const d
= (const_decl_t
) decl
;
1973 gcc_assert ((d
->mode
== dm_unit
&& DECL_UNIT (d
)->name
)
1974 || (d
->mode
== dm_reserv
&& DECL_RESERV (d
)->name
));
1975 return string_hash (d
->mode
== dm_unit
1976 ? DECL_UNIT (d
)->name
: DECL_RESERV (d
)->name
);
1979 /* The function tests declarations on equality of their keys. The
1980 function is used by abstract data 'hashtab'. The function
1981 returns 1 if the declarations have the same key, 0 otherwise. */
1983 decl_eq_p (const void *decl_1
, const void *decl_2
)
1985 const_decl_t
const d1
= (const_decl_t
) decl_1
;
1986 const_decl_t
const d2
= (const_decl_t
) decl_2
;
1988 gcc_assert ((d1
->mode
== dm_unit
&& DECL_UNIT (d1
)->name
)
1989 || (d1
->mode
== dm_reserv
&& DECL_RESERV (d1
)->name
));
1990 gcc_assert ((d2
->mode
== dm_unit
&& DECL_UNIT (d2
)->name
)
1991 || (d2
->mode
== dm_reserv
&& DECL_RESERV (d2
)->name
));
1992 return strcmp ((d1
->mode
== dm_unit
1993 ? DECL_UNIT (d1
)->name
: DECL_RESERV (d1
)->name
),
1994 (d2
->mode
== dm_unit
1995 ? DECL_UNIT (d2
)->name
: DECL_RESERV (d2
)->name
)) == 0;
1998 /* The declaration table itself is represented by the following
2000 static htab_t decl_table
;
2002 /* The function inserts declaration into the table. The function does
2003 nothing if a declaration with the same key exists already in the
2004 table. The function returns declaration node in the table with the
2005 same key as given declaration node. */
2008 insert_decl (decl_t decl
)
2012 entry_ptr
= htab_find_slot (decl_table
, decl
, INSERT
);
2013 if (*entry_ptr
== NULL
)
2014 *entry_ptr
= (void *) decl
;
2015 return (decl_t
) *entry_ptr
;
2018 /* The following variable value is node representing declaration. The
2019 node used for searching declaration with given name. */
2020 static struct decl work_decl
;
2022 /* The function searches for declaration in the table with the same
2023 key as node representing name of the declaration. The function
2024 returns node found in the table, NULL if such node does not exist
2027 find_decl (const char *name
)
2031 work_decl
.mode
= dm_unit
;
2032 DECL_UNIT (&work_decl
)->name
= name
;
2033 entry
= htab_find (decl_table
, &work_decl
);
2034 return (decl_t
) entry
;
2037 /* The function creates empty declaration table and node representing
2038 declaration and used for searching declaration with given name.
2039 The function must be called only once before any work with the
2040 declaration table. */
2042 initiate_decl_table (void)
2044 work_decl
.mode
= dm_unit
;
2045 decl_table
= htab_create (10, decl_hash
, decl_eq_p
, (htab_del
) 0);
2048 /* The function deletes the declaration table. Only call of function
2049 `initiate_declaration_table' is possible immediately after this
2052 finish_decl_table (void)
2054 htab_delete (decl_table
);
2059 /* This page contains checker of pipeline hazard description. */
2061 /* Checking NAMES in an exclusion clause vector and returning formed
2062 unit_set_el_list. */
2063 static unit_set_el_t
2064 process_excls (char **names
, int num
, pos_t excl_pos ATTRIBUTE_UNUSED
)
2066 unit_set_el_t el_list
;
2067 unit_set_el_t last_el
;
2068 unit_set_el_t new_el
;
2069 decl_t decl_in_table
;
2074 for (i
= 0; i
< num
; i
++)
2076 decl_in_table
= find_decl (names
[i
]);
2077 if (decl_in_table
== NULL
)
2078 error ("unit `%s' in exclusion is not declared", names
[i
]);
2079 else if (decl_in_table
->mode
!= dm_unit
)
2080 error ("`%s' in exclusion is not unit", names
[i
]);
2083 new_el
= XCREATENODE (struct unit_set_el
);
2084 new_el
->unit_decl
= DECL_UNIT (decl_in_table
);
2085 new_el
->next_unit_set_el
= NULL
;
2086 if (last_el
== NULL
)
2087 el_list
= last_el
= new_el
;
2090 last_el
->next_unit_set_el
= new_el
;
2091 last_el
= last_el
->next_unit_set_el
;
2098 /* The function adds each element from SOURCE_LIST to the exclusion
2099 list of the each element from DEST_LIST. Checking situation "unit
2100 excludes itself". */
2102 add_excls (unit_set_el_t dest_list
, unit_set_el_t source_list
,
2103 pos_t excl_pos ATTRIBUTE_UNUSED
)
2107 unit_set_el_t curr_el
;
2108 unit_set_el_t prev_el
;
2111 for (dst
= dest_list
; dst
!= NULL
; dst
= dst
->next_unit_set_el
)
2112 for (src
= source_list
; src
!= NULL
; src
= src
->next_unit_set_el
)
2114 if (dst
->unit_decl
== src
->unit_decl
)
2116 error ("unit `%s' excludes itself", src
->unit_decl
->name
);
2119 if (dst
->unit_decl
->automaton_name
!= NULL
2120 && src
->unit_decl
->automaton_name
!= NULL
2121 && strcmp (dst
->unit_decl
->automaton_name
,
2122 src
->unit_decl
->automaton_name
) != 0)
2124 error ("units `%s' and `%s' in exclusion set belong to different automata",
2125 src
->unit_decl
->name
, dst
->unit_decl
->name
);
2128 for (curr_el
= dst
->unit_decl
->excl_list
, prev_el
= NULL
;
2130 prev_el
= curr_el
, curr_el
= curr_el
->next_unit_set_el
)
2131 if (curr_el
->unit_decl
== src
->unit_decl
)
2133 if (curr_el
== NULL
)
2135 /* Element not found - insert. */
2136 copy
= XCOPYNODE (struct unit_set_el
, src
);
2137 copy
->next_unit_set_el
= NULL
;
2138 if (prev_el
== NULL
)
2139 dst
->unit_decl
->excl_list
= copy
;
2141 prev_el
->next_unit_set_el
= copy
;
2146 /* Checking NAMES in presence/absence clause and returning the
2147 formed unit_set_el_list. The function is called only after
2148 processing all exclusion sets. */
2149 static unit_set_el_t
2150 process_presence_absence_names (char **names
, int num
,
2151 pos_t req_pos ATTRIBUTE_UNUSED
,
2152 int presence_p
, int final_p
)
2154 unit_set_el_t el_list
;
2155 unit_set_el_t last_el
;
2156 unit_set_el_t new_el
;
2157 decl_t decl_in_table
;
2162 for (i
= 0; i
< num
; i
++)
2164 decl_in_table
= find_decl (names
[i
]);
2165 if (decl_in_table
== NULL
)
2168 ? "unit `%s' in final presence set is not declared"
2169 : "unit `%s' in presence set is not declared")
2171 ? "unit `%s' in final absence set is not declared"
2172 : "unit `%s' in absence set is not declared")), names
[i
]);
2173 else if (decl_in_table
->mode
!= dm_unit
)
2176 ? "`%s' in final presence set is not unit"
2177 : "`%s' in presence set is not unit")
2179 ? "`%s' in final absence set is not unit"
2180 : "`%s' in absence set is not unit")), names
[i
]);
2183 new_el
= XCREATENODE (struct unit_set_el
);
2184 new_el
->unit_decl
= DECL_UNIT (decl_in_table
);
2185 new_el
->next_unit_set_el
= NULL
;
2186 if (last_el
== NULL
)
2187 el_list
= last_el
= new_el
;
2190 last_el
->next_unit_set_el
= new_el
;
2191 last_el
= last_el
->next_unit_set_el
;
2198 /* Checking NAMES in patterns of a presence/absence clause and
2199 returning the formed pattern_set_el_list. The function is called
2200 only after processing all exclusion sets. */
2201 static pattern_set_el_t
2202 process_presence_absence_patterns (char ***patterns
, int num
,
2203 pos_t req_pos ATTRIBUTE_UNUSED
,
2204 int presence_p
, int final_p
)
2206 pattern_set_el_t el_list
;
2207 pattern_set_el_t last_el
;
2208 pattern_set_el_t new_el
;
2209 decl_t decl_in_table
;
2214 for (i
= 0; i
< num
; i
++)
2216 for (j
= 0; patterns
[i
] [j
] != NULL
; j
++)
2218 new_el
= XCREATENODEVAR (struct pattern_set_el
,
2219 sizeof (struct pattern_set_el
)
2220 + sizeof (struct unit_decl
*) * j
);
2222 = (struct unit_decl
**) ((char *) new_el
2223 + sizeof (struct pattern_set_el
));
2224 new_el
->next_pattern_set_el
= NULL
;
2225 if (last_el
== NULL
)
2226 el_list
= last_el
= new_el
;
2229 last_el
->next_pattern_set_el
= new_el
;
2230 last_el
= last_el
->next_pattern_set_el
;
2232 new_el
->units_num
= 0;
2233 for (j
= 0; patterns
[i
] [j
] != NULL
; j
++)
2235 decl_in_table
= find_decl (patterns
[i
] [j
]);
2236 if (decl_in_table
== NULL
)
2239 ? "unit `%s' in final presence set is not declared"
2240 : "unit `%s' in presence set is not declared")
2242 ? "unit `%s' in final absence set is not declared"
2243 : "unit `%s' in absence set is not declared")),
2245 else if (decl_in_table
->mode
!= dm_unit
)
2248 ? "`%s' in final presence set is not unit"
2249 : "`%s' in presence set is not unit")
2251 ? "`%s' in final absence set is not unit"
2252 : "`%s' in absence set is not unit")),
2256 new_el
->unit_decls
[new_el
->units_num
]
2257 = DECL_UNIT (decl_in_table
);
2258 new_el
->units_num
++;
2265 /* The function adds each element from PATTERN_LIST to presence (if
2266 PRESENCE_P) or absence list of the each element from DEST_LIST.
2267 Checking situations "unit requires own absence", and "unit excludes
2268 and requires presence of ...", "unit requires absence and presence
2269 of ...", "units in (final) presence set belong to different
2270 automata", and "units in (final) absence set belong to different
2271 automata". Remember that we process absence sets only after all
2274 add_presence_absence (unit_set_el_t dest_list
,
2275 pattern_set_el_t pattern_list
,
2276 pos_t req_pos ATTRIBUTE_UNUSED
,
2277 int presence_p
, int final_p
)
2280 pattern_set_el_t pat
;
2281 struct unit_decl
*unit
;
2282 unit_set_el_t curr_excl_el
;
2283 pattern_set_el_t curr_pat_el
;
2284 pattern_set_el_t prev_el
;
2285 pattern_set_el_t copy
;
2289 for (dst
= dest_list
; dst
!= NULL
; dst
= dst
->next_unit_set_el
)
2290 for (pat
= pattern_list
; pat
!= NULL
; pat
= pat
->next_pattern_set_el
)
2292 for (i
= 0; i
< pat
->units_num
; i
++)
2294 unit
= pat
->unit_decls
[i
];
2295 if (dst
->unit_decl
== unit
&& pat
->units_num
== 1 && !presence_p
)
2297 error ("unit `%s' requires own absence", unit
->name
);
2300 if (dst
->unit_decl
->automaton_name
!= NULL
2301 && unit
->automaton_name
!= NULL
2302 && strcmp (dst
->unit_decl
->automaton_name
,
2303 unit
->automaton_name
) != 0)
2307 ? "units `%s' and `%s' in final presence set belong to different automata"
2308 : "units `%s' and `%s' in presence set belong to different automata")
2310 ? "units `%s' and `%s' in final absence set belong to different automata"
2311 : "units `%s' and `%s' in absence set belong to different automata")),
2312 unit
->name
, dst
->unit_decl
->name
);
2317 for (curr_excl_el
= dst
->unit_decl
->excl_list
;
2318 curr_excl_el
!= NULL
;
2319 curr_excl_el
= curr_excl_el
->next_unit_set_el
)
2321 if (unit
== curr_excl_el
->unit_decl
&& pat
->units_num
== 1)
2325 error ("unit `%s' excludes and requires presence of `%s'",
2326 dst
->unit_decl
->name
, unit
->name
);
2330 warning ("unit `%s' excludes and requires presence of `%s'",
2331 dst
->unit_decl
->name
, unit
->name
);
2334 else if (pat
->units_num
== 1)
2335 for (curr_pat_el
= dst
->unit_decl
->presence_list
;
2336 curr_pat_el
!= NULL
;
2337 curr_pat_el
= curr_pat_el
->next_pattern_set_el
)
2338 if (curr_pat_el
->units_num
== 1
2339 && unit
== curr_pat_el
->unit_decls
[0])
2343 error ("unit `%s' requires absence and presence of `%s'",
2344 dst
->unit_decl
->name
, unit
->name
);
2348 warning ("unit `%s' requires absence and presence of `%s'",
2349 dst
->unit_decl
->name
, unit
->name
);
2353 for (prev_el
= (presence_p
2355 ? dst
->unit_decl
->final_presence_list
2356 : dst
->unit_decl
->presence_list
)
2358 ? dst
->unit_decl
->final_absence_list
2359 : dst
->unit_decl
->absence_list
));
2360 prev_el
!= NULL
&& prev_el
->next_pattern_set_el
!= NULL
;
2361 prev_el
= prev_el
->next_pattern_set_el
)
2363 copy
= XCOPYNODE (struct pattern_set_el
, pat
);
2364 copy
->next_pattern_set_el
= NULL
;
2365 if (prev_el
== NULL
)
2370 dst
->unit_decl
->final_presence_list
= copy
;
2372 dst
->unit_decl
->presence_list
= copy
;
2375 dst
->unit_decl
->final_absence_list
= copy
;
2377 dst
->unit_decl
->absence_list
= copy
;
2380 prev_el
->next_pattern_set_el
= copy
;
2387 /* The function inserts BYPASS in the list of bypasses of the
2388 corresponding output insn. The order of bypasses in the list is
2389 described in a comment for member `bypass_list' (see above). If
2390 there is already the same bypass in the list the function reports
2391 this and does nothing. */
2393 insert_bypass (struct bypass_decl
*bypass
)
2395 struct bypass_decl
*curr
, *last
;
2396 struct insn_reserv_decl
*out_insn_reserv
= bypass
->out_insn_reserv
;
2397 struct insn_reserv_decl
*in_insn_reserv
= bypass
->in_insn_reserv
;
2399 for (curr
= out_insn_reserv
->bypass_list
, last
= NULL
;
2401 last
= curr
, curr
= curr
->next
)
2402 if (curr
->in_insn_reserv
== in_insn_reserv
)
2404 if ((bypass
->bypass_guard_name
!= NULL
2405 && curr
->bypass_guard_name
!= NULL
2406 && ! strcmp (bypass
->bypass_guard_name
, curr
->bypass_guard_name
))
2407 || bypass
->bypass_guard_name
== curr
->bypass_guard_name
)
2409 if (bypass
->bypass_guard_name
== NULL
)
2412 error ("the same bypass `%s - %s' is already defined",
2413 bypass
->out_pattern
, bypass
->in_pattern
);
2415 warning ("the same bypass `%s - %s' is already defined",
2416 bypass
->out_pattern
, bypass
->in_pattern
);
2419 error ("the same bypass `%s - %s' (guard %s) is already defined",
2420 bypass
->out_pattern
, bypass
->in_pattern
,
2421 bypass
->bypass_guard_name
);
2424 ("the same bypass `%s - %s' (guard %s) is already defined",
2425 bypass
->out_pattern
, bypass
->in_pattern
,
2426 bypass
->bypass_guard_name
);
2429 if (curr
->bypass_guard_name
== NULL
)
2431 if (curr
->next
== NULL
|| curr
->next
->in_insn_reserv
!= in_insn_reserv
)
2440 bypass
->next
= out_insn_reserv
->bypass_list
;
2441 out_insn_reserv
->bypass_list
= bypass
;
2445 bypass
->next
= last
->next
;
2446 last
->next
= bypass
;
2450 /* BYPASS is a define_bypass decl that includes glob pattern PATTERN.
2451 Call FN (BYPASS, INSN, DATA) for each matching instruction INSN. */
2454 for_each_matching_insn (decl_t bypass
, const char *pattern
,
2455 void (*fn
) (decl_t
, decl_t
, void *), void *data
)
2462 if (strpbrk (pattern
, "*?["))
2463 for (i
= 0; i
< description
->decls_num
; i
++)
2465 insn_reserv
= description
->decls
[i
];
2466 if (insn_reserv
->mode
== dm_insn_reserv
2467 && fnmatch (pattern
, DECL_INSN_RESERV (insn_reserv
)->name
, 0) == 0)
2469 fn (bypass
, insn_reserv
, data
);
2475 insn_reserv
= find_insn_decl (pattern
);
2478 fn (bypass
, insn_reserv
, data
);
2483 error ("there is no insn reservation that matches `%s'", pattern
);
2486 /* A subroutine of process_bypass that is called for each pair
2487 of matching instructions. OUT_INSN_RESERV is the output
2488 instruction and DATA is the input instruction. */
2491 process_bypass_2 (decl_t model
, decl_t out_insn_reserv
, void *data
)
2493 struct bypass_decl
*bypass
;
2494 decl_t in_insn_reserv
;
2496 in_insn_reserv
= (decl_t
) data
;
2497 if (strcmp (DECL_INSN_RESERV (in_insn_reserv
)->name
,
2498 DECL_BYPASS (model
)->in_pattern
) == 0
2499 && strcmp (DECL_INSN_RESERV (out_insn_reserv
)->name
,
2500 DECL_BYPASS (model
)->out_pattern
) == 0)
2501 bypass
= DECL_BYPASS (model
);
2504 bypass
= XCNEW (struct bypass_decl
);
2505 bypass
->latency
= DECL_BYPASS (model
)->latency
;
2506 bypass
->out_pattern
= DECL_INSN_RESERV (out_insn_reserv
)->name
;
2507 bypass
->in_pattern
= DECL_INSN_RESERV (in_insn_reserv
)->name
;
2508 bypass
->bypass_guard_name
= DECL_BYPASS (model
)->bypass_guard_name
;
2510 bypass
->out_insn_reserv
= DECL_INSN_RESERV (out_insn_reserv
);
2511 bypass
->in_insn_reserv
= DECL_INSN_RESERV (in_insn_reserv
);
2512 insert_bypass (bypass
);
2515 /* A subroutine of process_bypass that is called for each input
2516 instruction IN_INSN_RESERV. */
2519 process_bypass_1 (decl_t bypass
, decl_t in_insn_reserv
,
2520 void *data ATTRIBUTE_UNUSED
)
2522 for_each_matching_insn (bypass
, DECL_BYPASS (bypass
)->out_pattern
,
2523 process_bypass_2
, in_insn_reserv
);
2526 /* Process define_bypass decl BYPASS, inserting a bypass for each specific
2527 pair of insn reservations. */
2530 process_bypass (decl_t bypass
)
2532 for_each_matching_insn (bypass
, DECL_BYPASS (bypass
)->in_pattern
,
2533 process_bypass_1
, NULL
);
2536 /* The function processes pipeline description declarations, checks
2537 their correctness, and forms exclusion/presence/absence sets. */
2539 process_decls (void)
2542 decl_t automaton_decl
;
2543 decl_t decl_in_table
;
2544 int automaton_presence
;
2547 /* Checking repeated automata declarations. */
2548 automaton_presence
= 0;
2549 for (i
= 0; i
< description
->decls_num
; i
++)
2551 decl
= description
->decls
[i
];
2552 if (decl
->mode
== dm_automaton
)
2554 automaton_presence
= 1;
2555 decl_in_table
= insert_automaton_decl (decl
);
2556 if (decl_in_table
!= decl
)
2559 error ("repeated declaration of automaton `%s'",
2560 DECL_AUTOMATON (decl
)->name
);
2562 warning ("repeated declaration of automaton `%s'",
2563 DECL_AUTOMATON (decl
)->name
);
2567 /* Checking undeclared automata, repeated declarations (except for
2568 automata) and correctness of their attributes (insn latency times
2570 for (i
= 0; i
< description
->decls_num
; i
++)
2572 decl
= description
->decls
[i
];
2573 if (decl
->mode
== dm_insn_reserv
)
2575 if (DECL_INSN_RESERV (decl
)->default_latency
< 0)
2576 error ("define_insn_reservation `%s' has negative latency time",
2577 DECL_INSN_RESERV (decl
)->name
);
2578 DECL_INSN_RESERV (decl
)->insn_num
= description
->insns_num
;
2579 description
->insns_num
++;
2580 decl_in_table
= insert_insn_decl (decl
);
2581 if (decl_in_table
!= decl
)
2582 error ("`%s' is already used as insn reservation name",
2583 DECL_INSN_RESERV (decl
)->name
);
2585 else if (decl
->mode
== dm_bypass
)
2587 if (DECL_BYPASS (decl
)->latency
< 0)
2588 error ("define_bypass `%s - %s' has negative latency time",
2589 DECL_BYPASS (decl
)->out_pattern
,
2590 DECL_BYPASS (decl
)->in_pattern
);
2592 else if (decl
->mode
== dm_unit
|| decl
->mode
== dm_reserv
)
2594 if (decl
->mode
== dm_unit
)
2596 DECL_UNIT (decl
)->automaton_decl
= NULL
;
2597 if (DECL_UNIT (decl
)->automaton_name
!= NULL
)
2600 = find_automaton_decl (DECL_UNIT (decl
)->automaton_name
);
2601 if (automaton_decl
== NULL
)
2602 error ("automaton `%s' is not declared",
2603 DECL_UNIT (decl
)->automaton_name
);
2606 DECL_AUTOMATON (automaton_decl
)->automaton_is_used
= 1;
2607 DECL_UNIT (decl
)->automaton_decl
2608 = DECL_AUTOMATON (automaton_decl
);
2611 else if (automaton_presence
)
2612 error ("define_unit `%s' without automaton when one defined",
2613 DECL_UNIT (decl
)->name
);
2614 DECL_UNIT (decl
)->unit_num
= description
->units_num
;
2615 description
->units_num
++;
2616 if (strcmp (DECL_UNIT (decl
)->name
, NOTHING_NAME
) == 0)
2618 error ("`%s' is declared as cpu unit", NOTHING_NAME
);
2621 decl_in_table
= find_decl (DECL_UNIT (decl
)->name
);
2625 if (strcmp (DECL_RESERV (decl
)->name
, NOTHING_NAME
) == 0)
2627 error ("`%s' is declared as cpu reservation", NOTHING_NAME
);
2630 decl_in_table
= find_decl (DECL_RESERV (decl
)->name
);
2632 if (decl_in_table
== NULL
)
2633 decl_in_table
= insert_decl (decl
);
2636 if (decl
->mode
== dm_unit
)
2637 error ("repeated declaration of unit `%s'",
2638 DECL_UNIT (decl
)->name
);
2640 error ("repeated declaration of reservation `%s'",
2641 DECL_RESERV (decl
)->name
);
2645 /* Check bypasses and form list of bypasses for each (output)
2647 for (i
= 0; i
< description
->decls_num
; i
++)
2649 decl
= description
->decls
[i
];
2650 if (decl
->mode
== dm_bypass
)
2651 process_bypass (decl
);
2654 /* Check exclusion set declarations and form exclusion sets. */
2655 for (i
= 0; i
< description
->decls_num
; i
++)
2657 decl
= description
->decls
[i
];
2658 if (decl
->mode
== dm_excl
)
2660 unit_set_el_t unit_set_el_list
;
2661 unit_set_el_t unit_set_el_list_2
;
2664 = process_excls (DECL_EXCL (decl
)->names
,
2665 DECL_EXCL (decl
)->first_list_length
, decl
->pos
);
2667 = process_excls (&DECL_EXCL (decl
)->names
2668 [DECL_EXCL (decl
)->first_list_length
],
2669 DECL_EXCL (decl
)->all_names_num
2670 - DECL_EXCL (decl
)->first_list_length
,
2672 add_excls (unit_set_el_list
, unit_set_el_list_2
, decl
->pos
);
2673 add_excls (unit_set_el_list_2
, unit_set_el_list
, decl
->pos
);
2677 /* Check presence set declarations and form presence sets. */
2678 for (i
= 0; i
< description
->decls_num
; i
++)
2680 decl
= description
->decls
[i
];
2681 if (decl
->mode
== dm_presence
)
2683 unit_set_el_t unit_set_el_list
;
2684 pattern_set_el_t pattern_set_el_list
;
2687 = process_presence_absence_names
2688 (DECL_PRESENCE (decl
)->names
, DECL_PRESENCE (decl
)->names_num
,
2689 decl
->pos
, true, DECL_PRESENCE (decl
)->final_p
);
2691 = process_presence_absence_patterns
2692 (DECL_PRESENCE (decl
)->patterns
,
2693 DECL_PRESENCE (decl
)->patterns_num
,
2694 decl
->pos
, true, DECL_PRESENCE (decl
)->final_p
);
2695 add_presence_absence (unit_set_el_list
, pattern_set_el_list
,
2697 DECL_PRESENCE (decl
)->final_p
);
2701 /* Check absence set declarations and form absence sets. */
2702 for (i
= 0; i
< description
->decls_num
; i
++)
2704 decl
= description
->decls
[i
];
2705 if (decl
->mode
== dm_absence
)
2707 unit_set_el_t unit_set_el_list
;
2708 pattern_set_el_t pattern_set_el_list
;
2711 = process_presence_absence_names
2712 (DECL_ABSENCE (decl
)->names
, DECL_ABSENCE (decl
)->names_num
,
2713 decl
->pos
, false, DECL_ABSENCE (decl
)->final_p
);
2715 = process_presence_absence_patterns
2716 (DECL_ABSENCE (decl
)->patterns
,
2717 DECL_ABSENCE (decl
)->patterns_num
,
2718 decl
->pos
, false, DECL_ABSENCE (decl
)->final_p
);
2719 add_presence_absence (unit_set_el_list
, pattern_set_el_list
,
2721 DECL_ABSENCE (decl
)->final_p
);
2726 /* The following function checks that declared automaton is used. If
2727 the automaton is not used, the function fixes error/warning. The
2728 following function must be called only after `process_decls'. */
2730 check_automaton_usage (void)
2735 for (i
= 0; i
< description
->decls_num
; i
++)
2737 decl
= description
->decls
[i
];
2738 if (decl
->mode
== dm_automaton
2739 && !DECL_AUTOMATON (decl
)->automaton_is_used
)
2742 error ("automaton `%s' is not used", DECL_AUTOMATON (decl
)->name
);
2744 warning ("automaton `%s' is not used",
2745 DECL_AUTOMATON (decl
)->name
);
2750 /* The following recursive function processes all regexp in order to
2751 fix usage of units or reservations and to fix errors of undeclared
2752 name. The function may change unit_regexp onto reserv_regexp.
2753 Remember that reserv_regexp does not exist before the function
2756 process_regexp (regexp_t regexp
)
2758 decl_t decl_in_table
;
2759 regexp_t new_regexp
;
2762 switch (regexp
->mode
)
2765 decl_in_table
= find_decl (REGEXP_UNIT (regexp
)->name
);
2766 if (decl_in_table
== NULL
)
2767 error ("undeclared unit or reservation `%s'",
2768 REGEXP_UNIT (regexp
)->name
);
2770 switch (decl_in_table
->mode
)
2773 DECL_UNIT (decl_in_table
)->unit_is_used
= 1;
2774 REGEXP_UNIT (regexp
)->unit_decl
= DECL_UNIT (decl_in_table
);
2778 DECL_RESERV (decl_in_table
)->reserv_is_used
= 1;
2779 new_regexp
= XCREATENODE (struct regexp
);
2780 new_regexp
->mode
= rm_reserv
;
2781 new_regexp
->pos
= regexp
->pos
;
2782 REGEXP_RESERV (new_regexp
)->name
= REGEXP_UNIT (regexp
)->name
;
2783 REGEXP_RESERV (new_regexp
)->reserv_decl
2784 = DECL_RESERV (decl_in_table
);
2785 regexp
= new_regexp
;
2793 for (i
= 0; i
<REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
2794 REGEXP_SEQUENCE (regexp
)->regexps
[i
]
2795 = process_regexp (REGEXP_SEQUENCE (regexp
)->regexps
[i
]);
2798 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
2799 REGEXP_ALLOF (regexp
)->regexps
[i
]
2800 = process_regexp (REGEXP_ALLOF (regexp
)->regexps
[i
]);
2803 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
2804 REGEXP_ONEOF (regexp
)->regexps
[i
]
2805 = process_regexp (REGEXP_ONEOF (regexp
)->regexps
[i
]);
2808 REGEXP_REPEAT (regexp
)->regexp
2809 = process_regexp (REGEXP_REPEAT (regexp
)->regexp
);
2819 /* The following function processes regexp of define_reservation and
2820 define_insn_reservation with the aid of function
2821 `process_regexp'. */
2823 process_regexp_decls (void)
2828 for (i
= 0; i
< description
->decls_num
; i
++)
2830 decl
= description
->decls
[i
];
2831 if (decl
->mode
== dm_reserv
)
2832 DECL_RESERV (decl
)->regexp
2833 = process_regexp (DECL_RESERV (decl
)->regexp
);
2834 else if (decl
->mode
== dm_insn_reserv
)
2835 DECL_INSN_RESERV (decl
)->regexp
2836 = process_regexp (DECL_INSN_RESERV (decl
)->regexp
);
2840 /* The following function checks that declared unit is used. If the
2841 unit is not used, the function fixes errors/warnings. The
2842 following function must be called only after `process_decls',
2843 `process_regexp_decls'. */
2850 for (i
= 0; i
< description
->decls_num
; i
++)
2852 decl
= description
->decls
[i
];
2853 if (decl
->mode
== dm_unit
&& !DECL_UNIT (decl
)->unit_is_used
)
2856 error ("unit `%s' is not used", DECL_UNIT (decl
)->name
);
2858 warning ("unit `%s' is not used", DECL_UNIT (decl
)->name
);
2860 else if (decl
->mode
== dm_reserv
&& !DECL_RESERV (decl
)->reserv_is_used
)
2863 error ("reservation `%s' is not used", DECL_RESERV (decl
)->name
);
2865 warning ("reservation `%s' is not used", DECL_RESERV (decl
)->name
);
2870 /* The following variable value is number of reservation being
2871 processed on loop recognition. */
2872 static int curr_loop_pass_num
;
2874 /* The following recursive function returns nonzero value if REGEXP
2875 contains given decl or reservations in given regexp refers for
2878 loop_in_regexp (regexp_t regexp
, decl_t start_decl
)
2884 switch (regexp
->mode
)
2890 if (start_decl
->mode
== dm_reserv
2891 && REGEXP_RESERV (regexp
)->reserv_decl
== DECL_RESERV (start_decl
))
2893 else if (REGEXP_RESERV (regexp
)->reserv_decl
->loop_pass_num
2894 == curr_loop_pass_num
)
2895 /* declaration has been processed. */
2899 REGEXP_RESERV (regexp
)->reserv_decl
->loop_pass_num
2900 = curr_loop_pass_num
;
2901 return loop_in_regexp (REGEXP_RESERV (regexp
)->reserv_decl
->regexp
,
2906 for (i
= 0; i
<REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
2907 if (loop_in_regexp (REGEXP_SEQUENCE (regexp
)->regexps
[i
], start_decl
))
2912 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
2913 if (loop_in_regexp (REGEXP_ALLOF (regexp
)->regexps
[i
], start_decl
))
2918 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
2919 if (loop_in_regexp (REGEXP_ONEOF (regexp
)->regexps
[i
], start_decl
))
2924 return loop_in_regexp (REGEXP_REPEAT (regexp
)->regexp
, start_decl
);
2934 /* The following function fixes errors "cycle in definition ...". The
2935 function uses function `loop_in_regexp' for that. */
2937 check_loops_in_regexps (void)
2942 for (i
= 0; i
< description
->decls_num
; i
++)
2944 decl
= description
->decls
[i
];
2945 if (decl
->mode
== dm_reserv
)
2946 DECL_RESERV (decl
)->loop_pass_num
= 0;
2948 for (i
= 0; i
< description
->decls_num
; i
++)
2950 decl
= description
->decls
[i
];
2951 curr_loop_pass_num
= i
;
2953 if (decl
->mode
== dm_reserv
)
2955 DECL_RESERV (decl
)->loop_pass_num
= curr_loop_pass_num
;
2956 if (loop_in_regexp (DECL_RESERV (decl
)->regexp
, decl
))
2958 gcc_assert (DECL_RESERV (decl
)->regexp
);
2959 error ("cycle in definition of reservation `%s'",
2960 DECL_RESERV (decl
)->name
);
2966 /* The function recursively processes IR of reservation and defines
2967 max and min cycle for reservation of unit. */
2969 process_regexp_cycles (regexp_t regexp
, int max_start_cycle
,
2970 int min_start_cycle
, int *max_finish_cycle
,
2971 int *min_finish_cycle
)
2975 switch (regexp
->mode
)
2978 if (REGEXP_UNIT (regexp
)->unit_decl
->max_occ_cycle_num
< max_start_cycle
)
2979 REGEXP_UNIT (regexp
)->unit_decl
->max_occ_cycle_num
= max_start_cycle
;
2980 if (REGEXP_UNIT (regexp
)->unit_decl
->min_occ_cycle_num
> min_start_cycle
2981 || REGEXP_UNIT (regexp
)->unit_decl
->min_occ_cycle_num
== -1)
2982 REGEXP_UNIT (regexp
)->unit_decl
->min_occ_cycle_num
= min_start_cycle
;
2983 *max_finish_cycle
= max_start_cycle
;
2984 *min_finish_cycle
= min_start_cycle
;
2988 process_regexp_cycles (REGEXP_RESERV (regexp
)->reserv_decl
->regexp
,
2989 max_start_cycle
, min_start_cycle
,
2990 max_finish_cycle
, min_finish_cycle
);
2994 for (i
= 0; i
< REGEXP_REPEAT (regexp
)->repeat_num
; i
++)
2996 process_regexp_cycles (REGEXP_REPEAT (regexp
)->regexp
,
2997 max_start_cycle
, min_start_cycle
,
2998 max_finish_cycle
, min_finish_cycle
);
2999 max_start_cycle
= *max_finish_cycle
+ 1;
3000 min_start_cycle
= *min_finish_cycle
+ 1;
3005 for (i
= 0; i
<REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
3007 process_regexp_cycles (REGEXP_SEQUENCE (regexp
)->regexps
[i
],
3008 max_start_cycle
, min_start_cycle
,
3009 max_finish_cycle
, min_finish_cycle
);
3010 max_start_cycle
= *max_finish_cycle
+ 1;
3011 min_start_cycle
= *min_finish_cycle
+ 1;
3020 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
3022 process_regexp_cycles (REGEXP_ALLOF (regexp
)->regexps
[i
],
3023 max_start_cycle
, min_start_cycle
,
3024 max_finish_cycle
, min_finish_cycle
);
3025 if (max_cycle
< *max_finish_cycle
)
3026 max_cycle
= *max_finish_cycle
;
3027 if (i
== 0 || min_cycle
> *min_finish_cycle
)
3028 min_cycle
= *min_finish_cycle
;
3030 *max_finish_cycle
= max_cycle
;
3031 *min_finish_cycle
= min_cycle
;
3040 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
3042 process_regexp_cycles (REGEXP_ONEOF (regexp
)->regexps
[i
],
3043 max_start_cycle
, min_start_cycle
,
3044 max_finish_cycle
, min_finish_cycle
);
3045 if (max_cycle
< *max_finish_cycle
)
3046 max_cycle
= *max_finish_cycle
;
3047 if (i
== 0 || min_cycle
> *min_finish_cycle
)
3048 min_cycle
= *min_finish_cycle
;
3050 *max_finish_cycle
= max_cycle
;
3051 *min_finish_cycle
= min_cycle
;
3056 *max_finish_cycle
= max_start_cycle
;
3057 *min_finish_cycle
= min_start_cycle
;
3065 /* The following function is called only for correct program. The
3066 function defines max reservation of insns in cycles. */
3068 evaluate_max_reserv_cycles (void)
3070 int max_insn_cycles_num
;
3071 int min_insn_cycles_num
;
3075 description
->max_insn_reserv_cycles
= 0;
3076 for (i
= 0; i
< description
->decls_num
; i
++)
3078 decl
= description
->decls
[i
];
3079 if (decl
->mode
== dm_insn_reserv
)
3081 process_regexp_cycles (DECL_INSN_RESERV (decl
)->regexp
, 0, 0,
3082 &max_insn_cycles_num
, &min_insn_cycles_num
);
3083 if (description
->max_insn_reserv_cycles
< max_insn_cycles_num
)
3084 description
->max_insn_reserv_cycles
= max_insn_cycles_num
;
3087 description
->max_insn_reserv_cycles
++;
3090 /* The following function calls functions for checking all
3093 check_all_description (void)
3096 check_automaton_usage ();
3097 process_regexp_decls ();
3099 check_loops_in_regexps ();
3101 evaluate_max_reserv_cycles ();
3106 /* The page contains abstract data `ticker'. This data is used to
3107 report time of different phases of building automata. It is
3108 possibly to write a description for which automata will be built
3109 during several minutes even on fast machine. */
3111 /* The following function creates ticker and makes it active. */
3113 create_ticker (void)
3117 ticker
.modified_creation_time
= get_run_time ();
3118 ticker
.incremented_off_time
= 0;
3122 /* The following function switches off given ticker. */
3124 ticker_off (ticker_t
*ticker
)
3126 if (ticker
->incremented_off_time
== 0)
3127 ticker
->incremented_off_time
= get_run_time () + 1;
3130 /* The following function switches on given ticker. */
3132 ticker_on (ticker_t
*ticker
)
3134 if (ticker
->incremented_off_time
!= 0)
3136 ticker
->modified_creation_time
3137 += get_run_time () - ticker
->incremented_off_time
+ 1;
3138 ticker
->incremented_off_time
= 0;
3142 /* The following function returns current time in milliseconds since
3143 the moment when given ticker was created. */
3145 active_time (ticker_t ticker
)
3147 if (ticker
.incremented_off_time
!= 0)
3148 return ticker
.incremented_off_time
- 1 - ticker
.modified_creation_time
;
3150 return get_run_time () - ticker
.modified_creation_time
;
3153 /* The following function returns string representation of active time
3154 of given ticker. The result is string representation of seconds
3155 with accuracy of 1/100 second. Only result of the last call of the
3156 function exists. Therefore the following code is not correct
3158 printf ("parser time: %s\ngeneration time: %s\n",
3159 active_time_string (parser_ticker),
3160 active_time_string (generation_ticker));
3162 Correct code has to be the following
3164 printf ("parser time: %s\n", active_time_string (parser_ticker));
3165 printf ("generation time: %s\n",
3166 active_time_string (generation_ticker));
3170 print_active_time (FILE *f
, ticker_t ticker
)
3174 msecs
= active_time (ticker
);
3175 fprintf (f
, "%d.%06d", msecs
/ 1000000, msecs
% 1000000);
3180 /* The following variable value is number of automaton which are
3181 really being created. This value is defined on the base of
3182 argument of option `-split'. If the variable has zero value the
3183 number of automata is defined by the constructions `%automaton'.
3184 This case occurs when option `-split' is absent or has zero
3185 argument. If constructions `define_automaton' is absent only one
3186 automaton is created. */
3187 static int automata_num
;
3189 /* The following variable values are times of
3190 o transformation of regular expressions
3191 o building NDFA (DFA if !ndfa_flag)
3192 o NDFA -> DFA (simply the same automaton if !ndfa_flag)
3194 o building insn equivalence classes
3197 static ticker_t transform_time
;
3198 static ticker_t NDFA_time
;
3199 static ticker_t NDFA_to_DFA_time
;
3200 static ticker_t minimize_time
;
3201 static ticker_t equiv_time
;
3202 static ticker_t automaton_generation_time
;
3203 static ticker_t output_time
;
3205 /* The following variable values are times of
3208 all pipeline hazard translator work */
3209 static ticker_t check_time
;
3210 static ticker_t generation_time
;
3211 static ticker_t all_time
;
3215 /* Pseudo insn decl which denotes advancing cycle. */
3216 static decl_t advance_cycle_insn_decl
;
3217 /* Pseudo insn decl which denotes collapsing the NDFA state. */
3218 static decl_t collapse_ndfa_insn_decl
;
3220 /* Create and record a decl for the special advance-cycle transition. */
3222 add_advance_cycle_insn_decl (void)
3224 advance_cycle_insn_decl
= XCREATENODE (struct decl
);
3225 advance_cycle_insn_decl
->mode
= dm_insn_reserv
;
3226 advance_cycle_insn_decl
->pos
= no_pos
;
3227 DECL_INSN_RESERV (advance_cycle_insn_decl
)->regexp
= NULL
;
3228 DECL_INSN_RESERV (advance_cycle_insn_decl
)->name
= "$advance_cycle";
3229 DECL_INSN_RESERV (advance_cycle_insn_decl
)->insn_num
3230 = description
->insns_num
;
3231 description
->decls
[description
->decls_num
] = advance_cycle_insn_decl
;
3232 description
->decls_num
++;
3233 description
->insns_num
++;
3236 /* Create and record a decl for the special collapse-NDFA transition. */
3238 add_collapse_ndfa_insn_decl (void)
3240 collapse_ndfa_insn_decl
= XCREATENODE (struct decl
);
3241 collapse_ndfa_insn_decl
->mode
= dm_insn_reserv
;
3242 collapse_ndfa_insn_decl
->pos
= no_pos
;
3243 DECL_INSN_RESERV (collapse_ndfa_insn_decl
)->regexp
= NULL
;
3244 DECL_INSN_RESERV (collapse_ndfa_insn_decl
)->name
= "$collapse_ndfa";
3245 DECL_INSN_RESERV (collapse_ndfa_insn_decl
)->insn_num
3246 = description
->insns_num
;
3247 description
->decls
[description
->decls_num
] = collapse_ndfa_insn_decl
;
3248 description
->decls_num
++;
3249 description
->insns_num
++;
3252 /* True if DECL is either of the two special decls we created. */
3254 special_decl_p (struct insn_reserv_decl
*decl
)
3256 return (decl
== DECL_INSN_RESERV (advance_cycle_insn_decl
)
3258 && decl
== DECL_INSN_RESERV (collapse_ndfa_insn_decl
)));
3262 /* Abstract data `alternative states' which represents
3263 nondeterministic nature of the description (see comments for
3264 structures alt_state and state). */
3266 /* List of free states. */
3267 static alt_state_t first_free_alt_state
;
3270 /* The following variables is maximal number of allocated nodes
3272 static int allocated_alt_states_num
= 0;
3275 /* The following function returns free node alt_state. It may be new
3276 allocated node or node freed earlier. */
3278 get_free_alt_state (void)
3282 if (first_free_alt_state
!= NULL
)
3284 result
= first_free_alt_state
;
3285 first_free_alt_state
= first_free_alt_state
->next_alt_state
;
3290 allocated_alt_states_num
++;
3292 result
= XCREATENODE (struct alt_state
);
3294 result
->state
= NULL
;
3295 result
->next_alt_state
= NULL
;
3296 result
->next_sorted_alt_state
= NULL
;
3300 /* The function frees node ALT_STATE. */
3302 free_alt_state (alt_state_t alt_state
)
3304 if (alt_state
== NULL
)
3306 alt_state
->next_alt_state
= first_free_alt_state
;
3307 first_free_alt_state
= alt_state
;
3310 /* The function frees list started with node ALT_STATE_LIST. */
3312 free_alt_states (alt_state_t alt_states_list
)
3314 alt_state_t curr_alt_state
;
3315 alt_state_t next_alt_state
;
3317 for (curr_alt_state
= alt_states_list
;
3318 curr_alt_state
!= NULL
;
3319 curr_alt_state
= next_alt_state
)
3321 next_alt_state
= curr_alt_state
->next_alt_state
;
3322 free_alt_state (curr_alt_state
);
3326 /* The function compares unique numbers of alt states. */
3328 alt_state_cmp (const void *alt_state_ptr_1
, const void *alt_state_ptr_2
)
3330 if ((*(const alt_state_t
*) alt_state_ptr_1
)->state
->unique_num
3331 == (*(const alt_state_t
*) alt_state_ptr_2
)->state
->unique_num
)
3333 else if ((*(const alt_state_t
*) alt_state_ptr_1
)->state
->unique_num
3334 < (*(const alt_state_t
*) alt_state_ptr_2
)->state
->unique_num
)
3340 /* The function sorts ALT_STATES_LIST and removes duplicated alt
3341 states from the list. The comparison key is alt state unique
3345 uniq_sort_alt_states (alt_state_t alt_states_list
)
3347 alt_state_t curr_alt_state
;
3349 size_t prev_unique_state_ind
;
3352 if (alt_states_list
== 0)
3354 if (alt_states_list
->next_alt_state
== 0)
3355 return alt_states_list
;
3357 auto_vec
<alt_state_t
, 150> alt_states
;
3358 for (curr_alt_state
= alt_states_list
;
3359 curr_alt_state
!= NULL
;
3360 curr_alt_state
= curr_alt_state
->next_alt_state
)
3361 alt_states
.safe_push (curr_alt_state
);
3363 alt_states
.qsort (alt_state_cmp
);
3365 prev_unique_state_ind
= 0;
3366 for (i
= 1; i
< alt_states
.length (); i
++)
3367 if (alt_states
[prev_unique_state_ind
]->state
!= alt_states
[i
]->state
)
3369 prev_unique_state_ind
++;
3370 alt_states
[prev_unique_state_ind
] = alt_states
[i
];
3372 alt_states
.truncate (prev_unique_state_ind
+ 1);
3374 for (i
= 1; i
< alt_states
.length (); i
++)
3375 alt_states
[i
-1]->next_sorted_alt_state
3377 alt_states
.last ()->next_sorted_alt_state
= 0;
3379 result
= alt_states
[0];
3384 /* The function checks equality of alt state lists. Remember that the
3385 lists must be already sorted by the previous function. */
3387 alt_states_eq (alt_state_t alt_states_1
, alt_state_t alt_states_2
)
3389 while (alt_states_1
!= NULL
&& alt_states_2
!= NULL
3390 && alt_state_cmp (&alt_states_1
, &alt_states_2
) == 0)
3392 alt_states_1
= alt_states_1
->next_sorted_alt_state
;
3393 alt_states_2
= alt_states_2
->next_sorted_alt_state
;
3395 return alt_states_1
== alt_states_2
;
3398 /* Initialization of the abstract data. */
3400 initiate_alt_states (void)
3402 first_free_alt_state
= NULL
;
3405 /* Finishing work with the abstract data. */
3407 finish_alt_states (void)
3413 /* The page contains macros for work with bits strings. We could use
3414 standard gcc bitmap or sbitmap but it would result in difficulties
3415 of building canadian cross. */
3417 /* Set bit number bitno in the bit string. The macro is not side
3419 #define bitmap_set_bit(bitstring, bitno) \
3420 ((bitstring)[(bitno) / (sizeof (*(bitstring)) * CHAR_BIT)] |= \
3421 (HOST_WIDE_INT)1 << (bitno) % (sizeof (*(bitstring)) * CHAR_BIT))
3423 #define CLEAR_BIT(bitstring, bitno) \
3424 ((bitstring)[(bitno) / (sizeof (*(bitstring)) * CHAR_BIT)] &= \
3425 ~((HOST_WIDE_INT)1 << (bitno) % (sizeof (*(bitstring)) * CHAR_BIT)))
3427 /* Test if bit number bitno in the bitstring is set. The macro is not
3428 side effect proof. */
3429 #define bitmap_bit_p(bitstring, bitno) \
3430 ((bitstring)[(bitno) / (sizeof (*(bitstring)) * CHAR_BIT)] >> \
3431 (bitno) % (sizeof (*(bitstring)) * CHAR_BIT) & 1)
3435 /* This page contains abstract data `state'. */
3437 /* Maximal length of reservations in cycles (>= 1). */
3438 static int max_cycles_num
;
3440 /* Number of set elements (see type set_el_t) needed for
3441 representation of one cycle reservation. It is depended on units
3443 static int els_in_cycle_reserv
;
3445 /* Number of set elements (see type set_el_t) needed for
3446 representation of maximal length reservation. Deterministic
3447 reservation is stored as set (bit string) of length equal to the
3448 variable value * number of bits in set_el_t. */
3449 static int els_in_reservs
;
3451 /* Array of pointers to unit declarations. */
3452 static unit_decl_t
*units_array
;
3454 /* Temporary reservation of maximal length. */
3455 static reserv_sets_t temp_reserv
;
3457 /* The state table itself is represented by the following variable. */
3458 static htab_t state_table
;
3460 /* Linked list of free 'state' structures to be recycled. The
3461 next_equiv_class_state pointer is borrowed for a free list. */
3462 static state_t first_free_state
;
3464 static int curr_unique_state_num
;
3467 /* The following variables is maximal number of allocated nodes
3469 static int allocated_states_num
= 0;
3472 /* Allocate new reservation set. */
3473 static reserv_sets_t
3474 alloc_empty_reserv_sets (void)
3476 reserv_sets_t result
;
3478 obstack_blank (&irp
, els_in_reservs
* sizeof (set_el_t
));
3479 result
= (reserv_sets_t
) obstack_base (&irp
);
3480 obstack_finish (&irp
);
3481 memset (result
, 0, els_in_reservs
* sizeof (set_el_t
));
3485 /* Hash value of reservation set. */
3487 reserv_sets_hash_value (reserv_sets_t reservs
)
3489 set_el_t hash_value
;
3492 set_el_t
*reserv_ptr
;
3495 reservs_num
= els_in_reservs
;
3496 reserv_ptr
= reservs
;
3498 while (reservs_num
!= 0)
3501 hash_value
+= ((*reserv_ptr
>> i
)
3502 | (*reserv_ptr
<< (((sizeof (set_el_t
) * CHAR_BIT
) - 1) & -i
)));
3504 if (i
== sizeof (set_el_t
) * CHAR_BIT
)
3508 if (sizeof (set_el_t
) <= sizeof (unsigned))
3511 for (i
= sizeof (set_el_t
); i
> 0; i
-= sizeof (unsigned) - 1)
3513 result
+= (unsigned) hash_value
;
3514 hash_value
>>= (sizeof (unsigned) - 1) * CHAR_BIT
;
3519 /* Comparison of given reservation sets. */
3521 reserv_sets_cmp (const_reserv_sets_t reservs_1
, const_reserv_sets_t reservs_2
)
3524 const set_el_t
*reserv_ptr_1
;
3525 const set_el_t
*reserv_ptr_2
;
3527 gcc_assert (reservs_1
&& reservs_2
);
3528 reservs_num
= els_in_reservs
;
3529 reserv_ptr_1
= reservs_1
;
3530 reserv_ptr_2
= reservs_2
;
3531 while (reservs_num
!= 0 && *reserv_ptr_1
== *reserv_ptr_2
)
3537 if (reservs_num
== 0)
3539 else if (*reserv_ptr_1
< *reserv_ptr_2
)
3545 /* The function checks equality of the reservation sets. */
3547 reserv_sets_eq (const_reserv_sets_t reservs_1
, const_reserv_sets_t reservs_2
)
3549 return reserv_sets_cmp (reservs_1
, reservs_2
) == 0;
3552 /* Set up in the reservation set that unit with UNIT_NUM is used on
3555 set_unit_reserv (reserv_sets_t reservs
, int cycle_num
, int unit_num
)
3557 gcc_assert (cycle_num
< max_cycles_num
);
3558 bitmap_set_bit (reservs
, cycle_num
* els_in_cycle_reserv
3559 * sizeof (set_el_t
) * CHAR_BIT
+ unit_num
);
3562 /* Set up in the reservation set RESERVS that unit with UNIT_NUM is
3563 used on CYCLE_NUM. */
3565 test_unit_reserv (reserv_sets_t reservs
, int cycle_num
, int unit_num
)
3567 gcc_assert (cycle_num
< max_cycles_num
);
3568 return bitmap_bit_p (reservs
, cycle_num
* els_in_cycle_reserv
3569 * sizeof (set_el_t
) * CHAR_BIT
+ unit_num
);
3572 /* The function checks that the reservation sets are intersected,
3573 i.e. there is a unit reservation on a cycle in both reservation
3576 reserv_sets_are_intersected (reserv_sets_t operand_1
,
3577 reserv_sets_t operand_2
)
3581 set_el_t
*cycle_ptr_1
;
3582 set_el_t
*cycle_ptr_2
;
3584 gcc_assert (operand_1
&& operand_2
);
3585 for (el_ptr_1
= operand_1
, el_ptr_2
= operand_2
;
3586 el_ptr_1
< operand_1
+ els_in_reservs
;
3587 el_ptr_1
++, el_ptr_2
++)
3588 if (*el_ptr_1
& *el_ptr_2
)
3590 reserv_sets_or (temp_reserv
, operand_1
, operand_2
);
3591 for (cycle_ptr_1
= operand_1
, cycle_ptr_2
= operand_2
;
3592 cycle_ptr_1
< operand_1
+ els_in_reservs
;
3593 cycle_ptr_1
+= els_in_cycle_reserv
, cycle_ptr_2
+= els_in_cycle_reserv
)
3595 for (el_ptr_1
= cycle_ptr_1
, el_ptr_2
= get_excl_set (cycle_ptr_2
);
3596 el_ptr_1
< cycle_ptr_1
+ els_in_cycle_reserv
;
3597 el_ptr_1
++, el_ptr_2
++)
3598 if (*el_ptr_1
& *el_ptr_2
)
3600 if (!check_presence_pattern_sets (cycle_ptr_1
, cycle_ptr_2
, false))
3602 if (!check_presence_pattern_sets (temp_reserv
+ (cycle_ptr_2
3606 if (!check_absence_pattern_sets (cycle_ptr_1
, cycle_ptr_2
, false))
3608 if (!check_absence_pattern_sets (temp_reserv
+ (cycle_ptr_2
- operand_2
),
3615 /* The function sets up RESULT bits by bits of OPERAND shifted on one
3616 cpu cycle. The remaining bits of OPERAND (representing the last
3617 cycle unit reservations) are not changed. */
3619 reserv_sets_shift (reserv_sets_t result
, reserv_sets_t operand
)
3623 gcc_assert (result
&& operand
&& result
!= operand
);
3624 for (i
= els_in_cycle_reserv
; i
< els_in_reservs
; i
++)
3625 result
[i
- els_in_cycle_reserv
] = operand
[i
];
3628 /* OR of the reservation sets. */
3630 reserv_sets_or (reserv_sets_t result
, reserv_sets_t operand_1
,
3631 reserv_sets_t operand_2
)
3635 set_el_t
*result_set_el_ptr
;
3637 gcc_assert (result
&& operand_1
&& operand_2
);
3638 for (el_ptr_1
= operand_1
, el_ptr_2
= operand_2
, result_set_el_ptr
= result
;
3639 el_ptr_1
< operand_1
+ els_in_reservs
;
3640 el_ptr_1
++, el_ptr_2
++, result_set_el_ptr
++)
3641 *result_set_el_ptr
= *el_ptr_1
| *el_ptr_2
;
3644 /* AND of the reservation sets. */
3646 reserv_sets_and (reserv_sets_t result
, reserv_sets_t operand_1
,
3647 reserv_sets_t operand_2
)
3651 set_el_t
*result_set_el_ptr
;
3653 gcc_assert (result
&& operand_1
&& operand_2
);
3654 for (el_ptr_1
= operand_1
, el_ptr_2
= operand_2
, result_set_el_ptr
= result
;
3655 el_ptr_1
< operand_1
+ els_in_reservs
;
3656 el_ptr_1
++, el_ptr_2
++, result_set_el_ptr
++)
3657 *result_set_el_ptr
= *el_ptr_1
& *el_ptr_2
;
3660 /* The function outputs string representation of units reservation on
3661 cycle START_CYCLE in the reservation set. The function uses repeat
3662 construction if REPETITION_NUM > 1. */
3664 output_cycle_reservs (FILE *f
, reserv_sets_t reservs
, int start_cycle
,
3668 int reserved_units_num
;
3670 reserved_units_num
= 0;
3671 for (unit_num
= 0; unit_num
< description
->units_num
; unit_num
++)
3672 if (bitmap_bit_p (reservs
, start_cycle
* els_in_cycle_reserv
3673 * sizeof (set_el_t
) * CHAR_BIT
+ unit_num
))
3674 reserved_units_num
++;
3675 gcc_assert (repetition_num
> 0);
3676 if (repetition_num
!= 1 && reserved_units_num
> 1)
3678 reserved_units_num
= 0;
3680 unit_num
< description
->units_num
;
3682 if (bitmap_bit_p (reservs
, start_cycle
* els_in_cycle_reserv
3683 * sizeof (set_el_t
) * CHAR_BIT
+ unit_num
))
3685 if (reserved_units_num
!= 0)
3687 reserved_units_num
++;
3688 fprintf (f
, "%s", units_array
[unit_num
]->name
);
3690 if (reserved_units_num
== 0)
3691 fprintf (f
, NOTHING_NAME
);
3692 gcc_assert (repetition_num
> 0);
3693 if (repetition_num
!= 1 && reserved_units_num
> 1)
3695 if (repetition_num
!= 1)
3696 fprintf (f
, "*%d", repetition_num
);
3699 /* The function outputs string representation of units reservation in
3700 the reservation set. */
3702 output_reserv_sets (FILE *f
, reserv_sets_t reservs
)
3704 int start_cycle
= 0;
3709 for (cycle
= 0; cycle
< max_cycles_num
; cycle
++)
3710 if (repetition_num
== 0)
3713 start_cycle
= cycle
;
3716 ((char *) reservs
+ start_cycle
* els_in_cycle_reserv
3717 * sizeof (set_el_t
),
3718 (char *) reservs
+ cycle
* els_in_cycle_reserv
3719 * sizeof (set_el_t
),
3720 els_in_cycle_reserv
* sizeof (set_el_t
)) == 0)
3724 if (start_cycle
!= 0)
3726 output_cycle_reservs (f
, reservs
, start_cycle
, repetition_num
);
3728 start_cycle
= cycle
;
3730 if (start_cycle
< max_cycles_num
)
3732 if (start_cycle
!= 0)
3734 output_cycle_reservs (f
, reservs
, start_cycle
, repetition_num
);
3738 /* The following function returns free node state for AUTOMATON. It
3739 may be new allocated node or node freed earlier. The function also
3740 allocates reservation set if WITH_RESERVS has nonzero value. */
3742 get_free_state (int with_reservs
, automaton_t automaton
)
3746 gcc_assert (max_cycles_num
> 0 && automaton
);
3747 if (first_free_state
)
3749 result
= first_free_state
;
3750 first_free_state
= result
->next_equiv_class_state
;
3752 result
->next_equiv_class_state
= NULL
;
3753 result
->automaton
= automaton
;
3754 result
->first_out_arc
= NULL
;
3755 result
->it_was_placed_in_stack_for_NDFA_forming
= 0;
3756 result
->it_was_placed_in_stack_for_DFA_forming
= 0;
3757 result
->component_states
= NULL
;
3762 allocated_states_num
++;
3764 result
= XCREATENODE (struct state
);
3765 result
->automaton
= automaton
;
3766 result
->first_out_arc
= NULL
;
3767 result
->unique_num
= curr_unique_state_num
;
3768 curr_unique_state_num
++;
3772 if (result
->reservs
== NULL
)
3773 result
->reservs
= alloc_empty_reserv_sets ();
3775 memset (result
->reservs
, 0, els_in_reservs
* sizeof (set_el_t
));
3780 /* The function frees node STATE. */
3782 free_state (state_t state
)
3784 free_alt_states (state
->component_states
);
3785 state
->next_equiv_class_state
= first_free_state
;
3786 first_free_state
= state
;
3789 /* Hash value of STATE. If STATE represents deterministic state it is
3790 simply hash value of the corresponding reservation set. Otherwise
3791 it is formed from hash values of the component deterministic
3792 states. One more key is order number of state automaton. */
3794 state_hash (const void *state
)
3796 unsigned int hash_value
;
3797 alt_state_t alt_state
;
3799 if (((const_state_t
) state
)->component_states
== NULL
)
3800 hash_value
= reserv_sets_hash_value (((const_state_t
) state
)->reservs
);
3804 for (alt_state
= ((const_state_t
) state
)->component_states
;
3806 alt_state
= alt_state
->next_sorted_alt_state
)
3807 hash_value
= (((hash_value
>> (sizeof (unsigned) - 1) * CHAR_BIT
)
3808 | (hash_value
<< CHAR_BIT
))
3809 + alt_state
->state
->unique_num
);
3811 hash_value
= (((hash_value
>> (sizeof (unsigned) - 1) * CHAR_BIT
)
3812 | (hash_value
<< CHAR_BIT
))
3813 + ((const_state_t
) state
)->automaton
->automaton_order_num
);
3817 /* Return nonzero value if the states are the same. */
3819 state_eq_p (const void *state_1
, const void *state_2
)
3821 alt_state_t alt_state_1
;
3822 alt_state_t alt_state_2
;
3824 if (((const_state_t
) state_1
)->automaton
!= ((const_state_t
) state_2
)->automaton
)
3826 else if (((const_state_t
) state_1
)->component_states
== NULL
3827 && ((const_state_t
) state_2
)->component_states
== NULL
)
3828 return reserv_sets_eq (((const_state_t
) state_1
)->reservs
,
3829 ((const_state_t
) state_2
)->reservs
);
3830 else if (((const_state_t
) state_1
)->component_states
!= NULL
3831 && ((const_state_t
) state_2
)->component_states
!= NULL
)
3833 for (alt_state_1
= ((const_state_t
) state_1
)->component_states
,
3834 alt_state_2
= ((const_state_t
) state_2
)->component_states
;
3835 alt_state_1
!= NULL
&& alt_state_2
!= NULL
;
3836 alt_state_1
= alt_state_1
->next_sorted_alt_state
,
3837 alt_state_2
= alt_state_2
->next_sorted_alt_state
)
3838 /* All state in the list must be already in the hash table.
3839 Also the lists must be sorted. */
3840 if (alt_state_1
->state
!= alt_state_2
->state
)
3842 return alt_state_1
== alt_state_2
;
3848 /* Insert STATE into the state table. */
3850 insert_state (state_t state
)
3854 entry_ptr
= htab_find_slot (state_table
, (void *) state
, INSERT
);
3855 if (*entry_ptr
== NULL
)
3856 *entry_ptr
= (void *) state
;
3857 return (state_t
) *entry_ptr
;
3860 /* Add reservation of unit with UNIT_NUM on cycle CYCLE_NUM to
3861 deterministic STATE. */
3863 set_state_reserv (state_t state
, int cycle_num
, int unit_num
)
3865 set_unit_reserv (state
->reservs
, cycle_num
, unit_num
);
3868 /* Return nonzero value if the deterministic states contains a
3869 reservation of the same cpu unit on the same cpu cycle. */
3871 intersected_state_reservs_p (state_t state1
, state_t state2
)
3873 gcc_assert (state1
->automaton
== state2
->automaton
);
3874 return reserv_sets_are_intersected (state1
->reservs
, state2
->reservs
);
3877 /* Return deterministic state (inserted into the table) which
3878 representing the automaton state which is union of reservations of
3879 the deterministic states masked by RESERVS. */
3881 states_union (state_t state1
, state_t state2
, reserv_sets_t reservs
)
3884 state_t state_in_table
;
3886 gcc_assert (state1
->automaton
== state2
->automaton
);
3887 result
= get_free_state (1, state1
->automaton
);
3888 reserv_sets_or (result
->reservs
, state1
->reservs
, state2
->reservs
);
3889 reserv_sets_and (result
->reservs
, result
->reservs
, reservs
);
3890 state_in_table
= insert_state (result
);
3891 if (result
!= state_in_table
)
3893 free_state (result
);
3894 result
= state_in_table
;
3899 /* Return deterministic state (inserted into the table) which
3900 represent the automaton state is obtained from deterministic STATE
3901 by advancing cpu cycle and masking by RESERVS. */
3903 state_shift (state_t state
, reserv_sets_t reservs
)
3906 state_t state_in_table
;
3908 result
= get_free_state (1, state
->automaton
);
3909 reserv_sets_shift (result
->reservs
, state
->reservs
);
3910 reserv_sets_and (result
->reservs
, result
->reservs
, reservs
);
3911 state_in_table
= insert_state (result
);
3912 if (result
!= state_in_table
)
3914 free_state (result
);
3915 result
= state_in_table
;
3920 /* Initialization of the abstract data. */
3922 initiate_states (void)
3927 if (description
->units_num
)
3928 units_array
= XNEWVEC (unit_decl_t
, description
->units_num
);
3932 for (i
= 0; i
< description
->decls_num
; i
++)
3934 decl
= description
->decls
[i
];
3935 if (decl
->mode
== dm_unit
)
3936 units_array
[DECL_UNIT (decl
)->unit_num
] = DECL_UNIT (decl
);
3938 max_cycles_num
= description
->max_insn_reserv_cycles
;
3940 = ((description
->units_num
+ sizeof (set_el_t
) * CHAR_BIT
- 1)
3941 / (sizeof (set_el_t
) * CHAR_BIT
));
3942 els_in_reservs
= els_in_cycle_reserv
* max_cycles_num
;
3943 curr_unique_state_num
= 0;
3944 initiate_alt_states ();
3945 state_table
= htab_create (1500, state_hash
, state_eq_p
, (htab_del
) 0);
3946 temp_reserv
= alloc_empty_reserv_sets ();
3949 /* Finishing work with the abstract data. */
3951 finish_states (void)
3955 htab_delete (state_table
);
3956 first_free_state
= NULL
;
3957 finish_alt_states ();
3962 /* Abstract data `arcs'. */
3964 /* List of free arcs. */
3965 static arc_t first_free_arc
;
3968 /* The following variables is maximal number of allocated nodes
3970 static int allocated_arcs_num
= 0;
3973 /* The function frees node ARC. */
3975 free_arc (arc_t arc
)
3977 arc
->next_out_arc
= first_free_arc
;
3978 first_free_arc
= arc
;
3981 /* The function removes and frees ARC staring from FROM_STATE. */
3983 remove_arc (state_t from_state
, arc_t arc
)
3989 for (prev_arc
= NULL
, curr_arc
= from_state
->first_out_arc
;
3991 prev_arc
= curr_arc
, curr_arc
= curr_arc
->next_out_arc
)
3992 if (curr_arc
== arc
)
3994 gcc_assert (curr_arc
);
3995 if (prev_arc
== NULL
)
3996 from_state
->first_out_arc
= arc
->next_out_arc
;
3998 prev_arc
->next_out_arc
= arc
->next_out_arc
;
3999 from_state
->num_out_arcs
--;
4003 /* The functions returns arc with given characteristics (or NULL if
4004 the arc does not exist). */
4006 find_arc (state_t from_state
, state_t to_state
, ainsn_t insn
)
4010 for (arc
= first_out_arc (from_state
); arc
!= NULL
; arc
= next_out_arc (arc
))
4011 if (arc
->insn
== insn
4012 && (arc
->to_state
== to_state
4014 /* Any arc is good enough for a collapse-ndfa transition. */
4015 && (insn
->insn_reserv_decl
4016 == DECL_INSN_RESERV (collapse_ndfa_insn_decl
)))))
4021 /* The function adds arc from FROM_STATE to TO_STATE marked by AINSN,
4022 unless such an arc already exists. */
4024 add_arc (state_t from_state
, state_t to_state
, ainsn_t ainsn
)
4028 new_arc
= find_arc (from_state
, to_state
, ainsn
);
4029 if (new_arc
!= NULL
)
4031 if (first_free_arc
== NULL
)
4034 allocated_arcs_num
++;
4036 new_arc
= XCREATENODE (struct arc
);
4037 new_arc
->to_state
= NULL
;
4038 new_arc
->insn
= NULL
;
4039 new_arc
->next_out_arc
= NULL
;
4043 new_arc
= first_free_arc
;
4044 first_free_arc
= first_free_arc
->next_out_arc
;
4046 new_arc
->to_state
= to_state
;
4047 new_arc
->insn
= ainsn
;
4048 ainsn
->arc_exists_p
= 1;
4049 new_arc
->next_out_arc
= from_state
->first_out_arc
;
4050 from_state
->first_out_arc
= new_arc
;
4051 from_state
->num_out_arcs
++;
4052 new_arc
->next_arc_marked_by_insn
= NULL
;
4055 /* The function returns the first arc starting from STATE. */
4057 first_out_arc (const_state_t state
)
4059 return state
->first_out_arc
;
4062 /* The function returns next out arc after ARC. */
4064 next_out_arc (arc_t arc
)
4066 return arc
->next_out_arc
;
4069 /* Initialization of the abstract data. */
4071 initiate_arcs (void)
4073 first_free_arc
= NULL
;
4076 /* Finishing work with the abstract data. */
4084 /* Abstract data `automata lists'. */
4086 /* List of free states. */
4087 static automata_list_el_t first_free_automata_list_el
;
4089 /* The list being formed. */
4090 static automata_list_el_t current_automata_list
;
4092 /* Hash table of automata lists. */
4093 static htab_t automata_list_table
;
4095 /* The following function returns free automata list el. It may be
4096 new allocated node or node freed earlier. */
4097 static automata_list_el_t
4098 get_free_automata_list_el (void)
4100 automata_list_el_t result
;
4102 if (first_free_automata_list_el
!= NULL
)
4104 result
= first_free_automata_list_el
;
4105 first_free_automata_list_el
4106 = first_free_automata_list_el
->next_automata_list_el
;
4109 result
= XCREATENODE (struct automata_list_el
);
4110 result
->automaton
= NULL
;
4111 result
->next_automata_list_el
= NULL
;
4115 /* The function frees node AUTOMATA_LIST_EL. */
4117 free_automata_list_el (automata_list_el_t automata_list_el
)
4119 if (automata_list_el
== NULL
)
4121 automata_list_el
->next_automata_list_el
= first_free_automata_list_el
;
4122 first_free_automata_list_el
= automata_list_el
;
4125 /* The function frees list AUTOMATA_LIST. */
4127 free_automata_list (automata_list_el_t automata_list
)
4129 automata_list_el_t curr_automata_list_el
;
4130 automata_list_el_t next_automata_list_el
;
4132 for (curr_automata_list_el
= automata_list
;
4133 curr_automata_list_el
!= NULL
;
4134 curr_automata_list_el
= next_automata_list_el
)
4136 next_automata_list_el
= curr_automata_list_el
->next_automata_list_el
;
4137 free_automata_list_el (curr_automata_list_el
);
4141 /* Hash value of AUTOMATA_LIST. */
4143 automata_list_hash (const void *automata_list
)
4145 unsigned int hash_value
;
4146 const_automata_list_el_t curr_automata_list_el
;
4149 for (curr_automata_list_el
= (const_automata_list_el_t
) automata_list
;
4150 curr_automata_list_el
!= NULL
;
4151 curr_automata_list_el
= curr_automata_list_el
->next_automata_list_el
)
4152 hash_value
= (((hash_value
>> (sizeof (unsigned) - 1) * CHAR_BIT
)
4153 | (hash_value
<< CHAR_BIT
))
4154 + curr_automata_list_el
->automaton
->automaton_order_num
);
4158 /* Return nonzero value if the automata_lists are the same. */
4160 automata_list_eq_p (const void *automata_list_1
, const void *automata_list_2
)
4162 const_automata_list_el_t automata_list_el_1
;
4163 const_automata_list_el_t automata_list_el_2
;
4165 for (automata_list_el_1
= (const_automata_list_el_t
) automata_list_1
,
4166 automata_list_el_2
= (const_automata_list_el_t
) automata_list_2
;
4167 automata_list_el_1
!= NULL
&& automata_list_el_2
!= NULL
;
4168 automata_list_el_1
= automata_list_el_1
->next_automata_list_el
,
4169 automata_list_el_2
= automata_list_el_2
->next_automata_list_el
)
4170 if (automata_list_el_1
->automaton
!= automata_list_el_2
->automaton
)
4172 return automata_list_el_1
== automata_list_el_2
;
4175 /* Initialization of the abstract data. */
4177 initiate_automata_lists (void)
4179 first_free_automata_list_el
= NULL
;
4180 automata_list_table
= htab_create (1500, automata_list_hash
,
4181 automata_list_eq_p
, (htab_del
) 0);
4184 /* The following function starts new automata list and makes it the
4187 automata_list_start (void)
4189 current_automata_list
= NULL
;
4192 /* The following function adds AUTOMATON to the current list. */
4194 automata_list_add (automaton_t automaton
)
4196 automata_list_el_t el
;
4198 el
= get_free_automata_list_el ();
4199 el
->automaton
= automaton
;
4200 el
->next_automata_list_el
= current_automata_list
;
4201 current_automata_list
= el
;
4204 /* The following function finishes forming the current list, inserts
4205 it into the table and returns it. */
4206 static automata_list_el_t
4207 automata_list_finish (void)
4211 if (current_automata_list
== NULL
)
4213 entry_ptr
= htab_find_slot (automata_list_table
,
4214 (void *) current_automata_list
, INSERT
);
4215 if (*entry_ptr
== NULL
)
4216 *entry_ptr
= (void *) current_automata_list
;
4218 free_automata_list (current_automata_list
);
4219 current_automata_list
= NULL
;
4220 return (automata_list_el_t
) *entry_ptr
;
4223 /* Finishing work with the abstract data. */
4225 finish_automata_lists (void)
4227 htab_delete (automata_list_table
);
4232 /* The page contains abstract data for work with exclusion sets (see
4233 exclusion_set in file rtl.def). */
4235 /* The following variable refers to an exclusion set returned by
4236 get_excl_set. This is bit string of length equal to cpu units
4237 number. If exclusion set for given unit contains 1 for a unit,
4238 then simultaneous reservation of the units is prohibited. */
4239 static reserv_sets_t excl_set
;
4241 /* The array contains exclusion sets for each unit. */
4242 static reserv_sets_t
*unit_excl_set_table
;
4244 /* The following function forms the array containing exclusion sets
4247 initiate_excl_sets (void)
4250 reserv_sets_t unit_excl_set
;
4254 obstack_blank (&irp
, els_in_cycle_reserv
* sizeof (set_el_t
));
4255 excl_set
= (reserv_sets_t
) obstack_base (&irp
);
4256 obstack_finish (&irp
);
4257 obstack_blank (&irp
, description
->units_num
* sizeof (reserv_sets_t
));
4258 unit_excl_set_table
= (reserv_sets_t
*) obstack_base (&irp
);
4259 obstack_finish (&irp
);
4260 /* Evaluate unit exclusion sets. */
4261 for (i
= 0; i
< description
->decls_num
; i
++)
4263 decl
= description
->decls
[i
];
4264 if (decl
->mode
== dm_unit
)
4266 obstack_blank (&irp
, els_in_cycle_reserv
* sizeof (set_el_t
));
4267 unit_excl_set
= (reserv_sets_t
) obstack_base (&irp
);
4268 obstack_finish (&irp
);
4269 memset (unit_excl_set
, 0, els_in_cycle_reserv
* sizeof (set_el_t
));
4270 for (el
= DECL_UNIT (decl
)->excl_list
;
4272 el
= el
->next_unit_set_el
)
4274 bitmap_set_bit (unit_excl_set
, el
->unit_decl
->unit_num
);
4275 el
->unit_decl
->in_set_p
= true;
4277 unit_excl_set_table
[DECL_UNIT (decl
)->unit_num
] = unit_excl_set
;
4282 /* The function sets up and return EXCL_SET which is union of
4283 exclusion sets for each unit in IN_SET. */
4284 static reserv_sets_t
4285 get_excl_set (reserv_sets_t in_set
)
4292 memset (excl_set
, 0, els_in_cycle_reserv
* sizeof (set_el_t
));
4293 for (el
= 0; el
< els_in_cycle_reserv
; el
++)
4295 for (i
= 0; i
< CHAR_BIT
* sizeof (set_el_t
); i
++)
4296 if ((in_set
[el
] >> i
) & 1)
4298 start_unit_num
= el
* CHAR_BIT
* sizeof (set_el_t
) + i
;
4299 if (start_unit_num
>= description
->units_num
)
4301 for (unit_num
= 0; unit_num
< els_in_cycle_reserv
; unit_num
++)
4304 |= unit_excl_set_table
[start_unit_num
] [unit_num
];
4312 /* The page contains abstract data for work with presence/absence
4313 pattern sets (see presence_set/absence_set in file rtl.def). */
4315 /* The following arrays contain correspondingly presence, final
4316 presence, absence, and final absence patterns for each unit. */
4317 static pattern_reserv_t
*unit_presence_set_table
;
4318 static pattern_reserv_t
*unit_final_presence_set_table
;
4319 static pattern_reserv_t
*unit_absence_set_table
;
4320 static pattern_reserv_t
*unit_final_absence_set_table
;
4322 /* The following function forms list of reservation sets for given
4324 static pattern_reserv_t
4325 form_reserv_sets_list (pattern_set_el_t pattern_list
)
4327 pattern_set_el_t el
;
4328 pattern_reserv_t first
, curr
, prev
;
4331 prev
= first
= NULL
;
4332 for (el
= pattern_list
; el
!= NULL
; el
= el
->next_pattern_set_el
)
4334 curr
= XCREATENODE (struct pattern_reserv
);
4335 curr
->reserv
= alloc_empty_reserv_sets ();
4336 curr
->next_pattern_reserv
= NULL
;
4337 for (i
= 0; i
< el
->units_num
; i
++)
4339 bitmap_set_bit (curr
->reserv
, el
->unit_decls
[i
]->unit_num
);
4340 el
->unit_decls
[i
]->in_set_p
= true;
4343 prev
->next_pattern_reserv
= curr
;
4351 /* The following function forms the array containing presence and
4352 absence pattern sets for each unit. */
4354 initiate_presence_absence_pattern_sets (void)
4359 obstack_blank (&irp
, description
->units_num
* sizeof (pattern_reserv_t
));
4360 unit_presence_set_table
= (pattern_reserv_t
*) obstack_base (&irp
);
4361 obstack_finish (&irp
);
4362 obstack_blank (&irp
, description
->units_num
* sizeof (pattern_reserv_t
));
4363 unit_final_presence_set_table
= (pattern_reserv_t
*) obstack_base (&irp
);
4364 obstack_finish (&irp
);
4365 obstack_blank (&irp
, description
->units_num
* sizeof (pattern_reserv_t
));
4366 unit_absence_set_table
= (pattern_reserv_t
*) obstack_base (&irp
);
4367 obstack_finish (&irp
);
4368 obstack_blank (&irp
, description
->units_num
* sizeof (pattern_reserv_t
));
4369 unit_final_absence_set_table
= (pattern_reserv_t
*) obstack_base (&irp
);
4370 obstack_finish (&irp
);
4371 /* Evaluate unit presence/absence sets. */
4372 for (i
= 0; i
< description
->decls_num
; i
++)
4374 decl
= description
->decls
[i
];
4375 if (decl
->mode
== dm_unit
)
4377 unit_presence_set_table
[DECL_UNIT (decl
)->unit_num
]
4378 = form_reserv_sets_list (DECL_UNIT (decl
)->presence_list
);
4379 unit_final_presence_set_table
[DECL_UNIT (decl
)->unit_num
]
4380 = form_reserv_sets_list (DECL_UNIT (decl
)->final_presence_list
);
4381 unit_absence_set_table
[DECL_UNIT (decl
)->unit_num
]
4382 = form_reserv_sets_list (DECL_UNIT (decl
)->absence_list
);
4383 unit_final_absence_set_table
[DECL_UNIT (decl
)->unit_num
]
4384 = form_reserv_sets_list (DECL_UNIT (decl
)->final_absence_list
);
4389 /* The function checks that CHECKED_SET satisfies all presence pattern
4390 sets for units in ORIGINAL_SET. The function returns TRUE if it
4393 check_presence_pattern_sets (reserv_sets_t checked_set
,
4394 reserv_sets_t original_set
,
4402 pattern_reserv_t pat_reserv
;
4404 for (el
= 0; el
< els_in_cycle_reserv
; el
++)
4405 if (original_set
[el
])
4406 for (i
= 0; i
< CHAR_BIT
* sizeof (set_el_t
); i
++)
4407 if ((original_set
[el
] >> i
) & 1)
4409 start_unit_num
= el
* CHAR_BIT
* sizeof (set_el_t
) + i
;
4410 if (start_unit_num
>= description
->units_num
)
4413 && unit_final_presence_set_table
[start_unit_num
] == NULL
)
4415 && unit_presence_set_table
[start_unit_num
] == NULL
))
4418 for (pat_reserv
= (final_p
4419 ? unit_final_presence_set_table
[start_unit_num
]
4420 : unit_presence_set_table
[start_unit_num
]);
4422 pat_reserv
= pat_reserv
->next_pattern_reserv
)
4424 for (unit_num
= 0; unit_num
< els_in_cycle_reserv
; unit_num
++)
4425 if ((checked_set
[unit_num
] & pat_reserv
->reserv
[unit_num
])
4426 != pat_reserv
->reserv
[unit_num
])
4428 presence_p
= presence_p
|| unit_num
>= els_in_cycle_reserv
;
4436 /* The function checks that CHECKED_SET satisfies all absence pattern
4437 sets for units in ORIGINAL_SET. The function returns TRUE if it
4440 check_absence_pattern_sets (reserv_sets_t checked_set
,
4441 reserv_sets_t original_set
,
4448 pattern_reserv_t pat_reserv
;
4450 for (el
= 0; el
< els_in_cycle_reserv
; el
++)
4451 if (original_set
[el
])
4452 for (i
= 0; i
< CHAR_BIT
* sizeof (set_el_t
); i
++)
4453 if ((original_set
[el
] >> i
) & 1)
4455 start_unit_num
= el
* CHAR_BIT
* sizeof (set_el_t
) + i
;
4456 if (start_unit_num
>= description
->units_num
)
4458 for (pat_reserv
= (final_p
4459 ? unit_final_absence_set_table
[start_unit_num
]
4460 : unit_absence_set_table
[start_unit_num
]);
4462 pat_reserv
= pat_reserv
->next_pattern_reserv
)
4464 for (unit_num
= 0; unit_num
< els_in_cycle_reserv
; unit_num
++)
4465 if ((checked_set
[unit_num
] & pat_reserv
->reserv
[unit_num
])
4466 != pat_reserv
->reserv
[unit_num
]
4467 && pat_reserv
->reserv
[unit_num
])
4469 if (unit_num
>= els_in_cycle_reserv
)
4478 /* This page contains code for transformation of original reservations
4479 described in .md file. The main goal of transformations is
4480 simplifying reservation and lifting up all `|' on the top of IR
4481 reservation representation. */
4484 /* The following function makes copy of IR representation of
4485 reservation. The function also substitutes all reservations
4486 defined by define_reservation by corresponding value during making
4489 copy_insn_regexp (regexp_t regexp
)
4494 switch (regexp
->mode
)
4497 result
= copy_insn_regexp (REGEXP_RESERV (regexp
)->reserv_decl
->regexp
);
4501 result
= XCOPYNODE (struct regexp
, regexp
);
4505 result
= XCOPYNODE (struct regexp
, regexp
);
4506 REGEXP_REPEAT (result
)->regexp
4507 = copy_insn_regexp (REGEXP_REPEAT (regexp
)->regexp
);
4511 result
= XCOPYNODEVAR (struct regexp
, regexp
,
4512 sizeof (struct regexp
) + sizeof (regexp_t
)
4513 * (REGEXP_SEQUENCE (regexp
)->regexps_num
- 1));
4514 for (i
= 0; i
<REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
4515 REGEXP_SEQUENCE (result
)->regexps
[i
]
4516 = copy_insn_regexp (REGEXP_SEQUENCE (regexp
)->regexps
[i
]);
4520 result
= XCOPYNODEVAR (struct regexp
, regexp
,
4521 sizeof (struct regexp
) + sizeof (regexp_t
)
4522 * (REGEXP_ALLOF (regexp
)->regexps_num
- 1));
4523 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
4524 REGEXP_ALLOF (result
)->regexps
[i
]
4525 = copy_insn_regexp (REGEXP_ALLOF (regexp
)->regexps
[i
]);
4529 result
= XCOPYNODEVAR (struct regexp
, regexp
,
4530 sizeof (struct regexp
) + sizeof (regexp_t
)
4531 * (REGEXP_ONEOF (regexp
)->regexps_num
- 1));
4532 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
4533 REGEXP_ONEOF (result
)->regexps
[i
]
4534 = copy_insn_regexp (REGEXP_ONEOF (regexp
)->regexps
[i
]);
4538 result
= XCOPYNODE (struct regexp
, regexp
);
4547 /* The following variable is set up 1 if a transformation has been
4549 static int regexp_transformed_p
;
4551 /* The function makes transformation
4554 transform_1 (regexp_t regexp
)
4561 if (regexp
->mode
== rm_repeat
)
4563 repeat_num
= REGEXP_REPEAT (regexp
)->repeat_num
;
4564 gcc_assert (repeat_num
> 1);
4565 operand
= REGEXP_REPEAT (regexp
)->regexp
;
4567 regexp
= XCREATENODEVAR (struct regexp
, sizeof (struct regexp
)
4568 + sizeof (regexp_t
) * (repeat_num
- 1));
4569 regexp
->mode
= rm_sequence
;
4571 REGEXP_SEQUENCE (regexp
)->regexps_num
= repeat_num
;
4572 for (i
= 0; i
< repeat_num
; i
++)
4573 REGEXP_SEQUENCE (regexp
)->regexps
[i
] = copy_insn_regexp (operand
);
4574 regexp_transformed_p
= 1;
4579 /* The function makes transformations
4580 ...,(A,B,...),C,... -> ...,A,B,...,C,...
4581 ...+(A+B+...)+C+... -> ...+A+B+...+C+...
4582 ...|(A|B|...)|C|... -> ...|A|B|...|C|... */
4584 transform_2 (regexp_t regexp
)
4586 if (regexp
->mode
== rm_sequence
)
4588 regexp_t sequence
= NULL
;
4590 int sequence_index
= 0;
4593 for (i
= 0; i
< REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
4594 if (REGEXP_SEQUENCE (regexp
)->regexps
[i
]->mode
== rm_sequence
)
4597 sequence
= REGEXP_SEQUENCE (regexp
)->regexps
[i
];
4600 if (i
< REGEXP_SEQUENCE (regexp
)->regexps_num
)
4602 gcc_assert (REGEXP_SEQUENCE (sequence
)->regexps_num
> 1
4603 && REGEXP_SEQUENCE (regexp
)->regexps_num
> 1);
4604 result
= XCREATENODEVAR (struct regexp
, sizeof (struct regexp
)
4606 * (REGEXP_SEQUENCE (regexp
)->regexps_num
4607 + REGEXP_SEQUENCE (sequence
)->regexps_num
4609 result
->mode
= rm_sequence
;
4610 result
->pos
= regexp
->pos
;
4611 REGEXP_SEQUENCE (result
)->regexps_num
4612 = (REGEXP_SEQUENCE (regexp
)->regexps_num
4613 + REGEXP_SEQUENCE (sequence
)->regexps_num
- 1);
4614 for (i
= 0; i
< REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
4615 if (i
< sequence_index
)
4616 REGEXP_SEQUENCE (result
)->regexps
[i
]
4617 = copy_insn_regexp (REGEXP_SEQUENCE (regexp
)->regexps
[i
]);
4618 else if (i
> sequence_index
)
4619 REGEXP_SEQUENCE (result
)->regexps
4620 [i
+ REGEXP_SEQUENCE (sequence
)->regexps_num
- 1]
4621 = copy_insn_regexp (REGEXP_SEQUENCE (regexp
)->regexps
[i
]);
4623 for (j
= 0; j
< REGEXP_SEQUENCE (sequence
)->regexps_num
; j
++)
4624 REGEXP_SEQUENCE (result
)->regexps
[i
+ j
]
4625 = copy_insn_regexp (REGEXP_SEQUENCE (sequence
)->regexps
[j
]);
4626 regexp_transformed_p
= 1;
4630 else if (regexp
->mode
== rm_allof
)
4632 regexp_t allof
= NULL
;
4634 int allof_index
= 0;
4637 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
4638 if (REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
== rm_allof
)
4641 allof
= REGEXP_ALLOF (regexp
)->regexps
[i
];
4644 if (i
< REGEXP_ALLOF (regexp
)->regexps_num
)
4646 gcc_assert (REGEXP_ALLOF (allof
)->regexps_num
> 1
4647 && REGEXP_ALLOF (regexp
)->regexps_num
> 1);
4648 result
= XCREATENODEVAR (struct regexp
, sizeof (struct regexp
)
4650 * (REGEXP_ALLOF (regexp
)->regexps_num
4651 + REGEXP_ALLOF (allof
)->regexps_num
- 2));
4652 result
->mode
= rm_allof
;
4653 result
->pos
= regexp
->pos
;
4654 REGEXP_ALLOF (result
)->regexps_num
4655 = (REGEXP_ALLOF (regexp
)->regexps_num
4656 + REGEXP_ALLOF (allof
)->regexps_num
- 1);
4657 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
4658 if (i
< allof_index
)
4659 REGEXP_ALLOF (result
)->regexps
[i
]
4660 = copy_insn_regexp (REGEXP_ALLOF (regexp
)->regexps
[i
]);
4661 else if (i
> allof_index
)
4662 REGEXP_ALLOF (result
)->regexps
4663 [i
+ REGEXP_ALLOF (allof
)->regexps_num
- 1]
4664 = copy_insn_regexp (REGEXP_ALLOF (regexp
)->regexps
[i
]);
4666 for (j
= 0; j
< REGEXP_ALLOF (allof
)->regexps_num
; j
++)
4667 REGEXP_ALLOF (result
)->regexps
[i
+ j
]
4668 = copy_insn_regexp (REGEXP_ALLOF (allof
)->regexps
[j
]);
4669 regexp_transformed_p
= 1;
4673 else if (regexp
->mode
== rm_oneof
)
4675 regexp_t oneof
= NULL
;
4677 int oneof_index
= 0;
4680 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
4681 if (REGEXP_ONEOF (regexp
)->regexps
[i
]->mode
== rm_oneof
)
4684 oneof
= REGEXP_ONEOF (regexp
)->regexps
[i
];
4687 if (i
< REGEXP_ONEOF (regexp
)->regexps_num
)
4689 gcc_assert (REGEXP_ONEOF (oneof
)->regexps_num
> 1
4690 && REGEXP_ONEOF (regexp
)->regexps_num
> 1);
4691 result
= XCREATENODEVAR (struct regexp
, sizeof (struct regexp
)
4693 * (REGEXP_ONEOF (regexp
)->regexps_num
4694 + REGEXP_ONEOF (oneof
)->regexps_num
- 2));
4695 result
->mode
= rm_oneof
;
4696 result
->pos
= regexp
->pos
;
4697 REGEXP_ONEOF (result
)->regexps_num
4698 = (REGEXP_ONEOF (regexp
)->regexps_num
4699 + REGEXP_ONEOF (oneof
)->regexps_num
- 1);
4700 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
4701 if (i
< oneof_index
)
4702 REGEXP_ONEOF (result
)->regexps
[i
]
4703 = copy_insn_regexp (REGEXP_ONEOF (regexp
)->regexps
[i
]);
4704 else if (i
> oneof_index
)
4705 REGEXP_ONEOF (result
)->regexps
4706 [i
+ REGEXP_ONEOF (oneof
)->regexps_num
- 1]
4707 = copy_insn_regexp (REGEXP_ONEOF (regexp
)->regexps
[i
]);
4709 for (j
= 0; j
< REGEXP_ONEOF (oneof
)->regexps_num
; j
++)
4710 REGEXP_ONEOF (result
)->regexps
[i
+ j
]
4711 = copy_insn_regexp (REGEXP_ONEOF (oneof
)->regexps
[j
]);
4712 regexp_transformed_p
= 1;
4719 /* The function makes transformations
4720 ...,A|B|...,C,... -> (...,A,C,...)|(...,B,C,...)|...
4721 ...+(A|B|...)+C+... -> (...+A+C+...)|(...+B+C+...)|...
4722 ...+(A,B,...)+C+... -> (...+A+C+...),B,...
4723 ...+(A,B,...)+(C,D,...) -> (A+C),(B+D),... */
4725 transform_3 (regexp_t regexp
)
4727 if (regexp
->mode
== rm_sequence
)
4729 regexp_t oneof
= NULL
;
4730 int oneof_index
= 0;
4735 for (i
= 0; i
<REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
4736 if (REGEXP_SEQUENCE (regexp
)->regexps
[i
]->mode
== rm_oneof
)
4739 oneof
= REGEXP_SEQUENCE (regexp
)->regexps
[i
];
4742 if (i
< REGEXP_SEQUENCE (regexp
)->regexps_num
)
4744 gcc_assert (REGEXP_ONEOF (oneof
)->regexps_num
> 1
4745 && REGEXP_SEQUENCE (regexp
)->regexps_num
> 1);
4746 result
= XCREATENODEVAR (struct regexp
, sizeof (struct regexp
)
4748 * (REGEXP_ONEOF (oneof
)->regexps_num
- 1));
4749 result
->mode
= rm_oneof
;
4750 result
->pos
= regexp
->pos
;
4751 REGEXP_ONEOF (result
)->regexps_num
4752 = REGEXP_ONEOF (oneof
)->regexps_num
;
4753 for (i
= 0; i
< REGEXP_ONEOF (result
)->regexps_num
; i
++)
4756 = XCREATENODEVAR (struct regexp
, sizeof (struct regexp
)
4758 * (REGEXP_SEQUENCE (regexp
)->regexps_num
- 1));
4759 sequence
->mode
= rm_sequence
;
4760 sequence
->pos
= regexp
->pos
;
4761 REGEXP_SEQUENCE (sequence
)->regexps_num
4762 = REGEXP_SEQUENCE (regexp
)->regexps_num
;
4763 REGEXP_ONEOF (result
)->regexps
[i
] = sequence
;
4764 for (j
= 0; j
< REGEXP_SEQUENCE (sequence
)->regexps_num
; j
++)
4765 if (j
!= oneof_index
)
4766 REGEXP_SEQUENCE (sequence
)->regexps
[j
]
4767 = copy_insn_regexp (REGEXP_SEQUENCE (regexp
)->regexps
[j
]);
4769 REGEXP_SEQUENCE (sequence
)->regexps
[j
]
4770 = copy_insn_regexp (REGEXP_ONEOF (oneof
)->regexps
[i
]);
4772 regexp_transformed_p
= 1;
4776 else if (regexp
->mode
== rm_allof
)
4778 regexp_t oneof
= NULL
;
4780 int oneof_index
= 0;
4781 int max_seq_length
, allof_length
;
4783 regexp_t allof
= NULL
;
4784 regexp_t allof_op
= NULL
;
4787 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
4788 if (REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
== rm_oneof
)
4791 oneof
= REGEXP_ALLOF (regexp
)->regexps
[i
];
4794 if (i
< REGEXP_ALLOF (regexp
)->regexps_num
)
4796 gcc_assert (REGEXP_ONEOF (oneof
)->regexps_num
> 1
4797 && REGEXP_ALLOF (regexp
)->regexps_num
> 1);
4798 result
= XCREATENODEVAR (struct regexp
, sizeof (struct regexp
)
4800 * (REGEXP_ONEOF (oneof
)->regexps_num
- 1));
4801 result
->mode
= rm_oneof
;
4802 result
->pos
= regexp
->pos
;
4803 REGEXP_ONEOF (result
)->regexps_num
4804 = REGEXP_ONEOF (oneof
)->regexps_num
;
4805 for (i
= 0; i
< REGEXP_ONEOF (result
)->regexps_num
; i
++)
4808 = XCREATENODEVAR (struct regexp
, sizeof (struct regexp
)
4810 * (REGEXP_ALLOF (regexp
)->regexps_num
- 1));
4811 allof
->mode
= rm_allof
;
4812 allof
->pos
= regexp
->pos
;
4813 REGEXP_ALLOF (allof
)->regexps_num
4814 = REGEXP_ALLOF (regexp
)->regexps_num
;
4815 REGEXP_ONEOF (result
)->regexps
[i
] = allof
;
4816 for (j
= 0; j
< REGEXP_ALLOF (allof
)->regexps_num
; j
++)
4817 if (j
!= oneof_index
)
4818 REGEXP_ALLOF (allof
)->regexps
[j
]
4819 = copy_insn_regexp (REGEXP_ALLOF (regexp
)->regexps
[j
]);
4821 REGEXP_ALLOF (allof
)->regexps
[j
]
4822 = copy_insn_regexp (REGEXP_ONEOF (oneof
)->regexps
[i
]);
4824 regexp_transformed_p
= 1;
4828 if (regexp
->mode
== rm_allof
)
4829 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
4831 switch (REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
)
4834 seq
= REGEXP_ALLOF (regexp
)->regexps
[i
];
4835 if (max_seq_length
< REGEXP_SEQUENCE (seq
)->regexps_num
)
4836 max_seq_length
= REGEXP_SEQUENCE (seq
)->regexps_num
;
4849 if (max_seq_length
!= 0)
4851 gcc_assert (max_seq_length
!= 1
4852 && REGEXP_ALLOF (regexp
)->regexps_num
> 1);
4853 result
= XCREATENODEVAR (struct regexp
, sizeof (struct regexp
)
4854 + sizeof (regexp_t
) * (max_seq_length
- 1));
4855 result
->mode
= rm_sequence
;
4856 result
->pos
= regexp
->pos
;
4857 REGEXP_SEQUENCE (result
)->regexps_num
= max_seq_length
;
4858 for (i
= 0; i
< max_seq_length
; i
++)
4861 for (j
= 0; j
< REGEXP_ALLOF (regexp
)->regexps_num
; j
++)
4862 switch (REGEXP_ALLOF (regexp
)->regexps
[j
]->mode
)
4865 if (i
< (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp
)
4866 ->regexps
[j
])->regexps_num
))
4869 = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp
)
4879 allof_op
= REGEXP_ALLOF (regexp
)->regexps
[j
];
4887 if (allof_length
== 1)
4888 REGEXP_SEQUENCE (result
)->regexps
[i
] = allof_op
;
4891 allof
= XCREATENODEVAR (struct regexp
, sizeof (struct regexp
)
4893 * (allof_length
- 1));
4894 allof
->mode
= rm_allof
;
4895 allof
->pos
= regexp
->pos
;
4896 REGEXP_ALLOF (allof
)->regexps_num
= allof_length
;
4897 REGEXP_SEQUENCE (result
)->regexps
[i
] = allof
;
4899 for (j
= 0; j
< REGEXP_ALLOF (regexp
)->regexps_num
; j
++)
4900 if (REGEXP_ALLOF (regexp
)->regexps
[j
]->mode
== rm_sequence
4902 (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp
)
4903 ->regexps
[j
])->regexps_num
)))
4905 allof_op
= (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp
)
4908 REGEXP_ALLOF (allof
)->regexps
[allof_length
]
4913 && (REGEXP_ALLOF (regexp
)->regexps
[j
]->mode
4915 || (REGEXP_ALLOF (regexp
)->regexps
[j
]->mode
4918 allof_op
= REGEXP_ALLOF (regexp
)->regexps
[j
];
4919 REGEXP_ALLOF (allof
)->regexps
[allof_length
]
4925 regexp_transformed_p
= 1;
4932 /* The function traverses IR of reservation and applies transformations
4933 implemented by FUNC. */
4935 regexp_transform_func (regexp_t regexp
, regexp_t (*func
) (regexp_t regexp
))
4939 switch (regexp
->mode
)
4942 for (i
= 0; i
< REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
4943 REGEXP_SEQUENCE (regexp
)->regexps
[i
]
4944 = regexp_transform_func (REGEXP_SEQUENCE (regexp
)->regexps
[i
],
4949 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
4950 REGEXP_ALLOF (regexp
)->regexps
[i
]
4951 = regexp_transform_func (REGEXP_ALLOF (regexp
)->regexps
[i
], func
);
4955 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
4956 REGEXP_ONEOF (regexp
)->regexps
[i
]
4957 = regexp_transform_func (REGEXP_ONEOF (regexp
)->regexps
[i
], func
);
4961 REGEXP_REPEAT (regexp
)->regexp
4962 = regexp_transform_func (REGEXP_REPEAT (regexp
)->regexp
, func
);
4972 return (*func
) (regexp
);
4975 /* The function applies all transformations for IR representation of
4976 reservation REGEXP. */
4978 transform_regexp (regexp_t regexp
)
4980 regexp
= regexp_transform_func (regexp
, transform_1
);
4983 regexp_transformed_p
= 0;
4984 regexp
= regexp_transform_func (regexp
, transform_2
);
4985 regexp
= regexp_transform_func (regexp
, transform_3
);
4987 while (regexp_transformed_p
);
4991 /* The function applies all transformations for reservations of all
4992 insn declarations. */
4994 transform_insn_regexps (void)
4999 transform_time
= create_ticker ();
5000 add_advance_cycle_insn_decl ();
5002 add_collapse_ndfa_insn_decl ();
5004 fprintf (stderr
, "Reservation transformation...");
5005 for (i
= 0; i
< description
->normal_decls_num
; i
++)
5007 decl
= description
->decls
[i
];
5008 if (decl
->mode
== dm_insn_reserv
)
5009 DECL_INSN_RESERV (decl
)->transformed_regexp
5010 = transform_regexp (copy_insn_regexp
5011 (DECL_INSN_RESERV (decl
)->regexp
));
5014 fprintf (stderr
, "done\n");
5015 ticker_off (&transform_time
);
5020 /* The following variable value is TRUE if the first annotated message
5021 about units to automata distribution has been output. */
5022 static int annotation_message_reported_p
;
5024 /* The vector contains all decls which are automata. */
5025 static vec
<decl_t
> automaton_decls
;
5027 /* The following structure describes usage of a unit in a reservation. */
5030 unit_decl_t unit_decl
;
5031 /* The following forms a list of units used on the same cycle in the
5032 same alternative. The list is ordered by the correspdoning unit
5033 declarations and there is no unit declaration duplication in the
5035 struct unit_usage
*next
;
5037 typedef struct unit_usage
*unit_usage_t
;
5040 /* Obstack for unit_usage structures. */
5041 static struct obstack unit_usages
;
5043 /* VLA for representation of array of pointers to unit usage
5044 structures. There is an element for each combination of
5045 (alternative number, cycle). Unit usages on given cycle in
5046 alternative with given number are referred through element with
5047 index equals to the cycle * number of all alternatives in the
5048 regexp + the alternative number. */
5049 static vec
<unit_usage_t
> cycle_alt_unit_usages
;
5051 /* The following function creates the structure unit_usage for UNIT on
5052 CYCLE in REGEXP alternative with ALT_NUM. The structure is made
5053 accessed through cycle_alt_unit_usages. */
5055 store_alt_unit_usage (regexp_t regexp
, regexp_t unit
, int cycle
,
5059 unit_decl_t unit_decl
;
5060 unit_usage_t unit_usage_ptr
, curr
, prev
;
5063 gcc_assert (regexp
&& regexp
->mode
== rm_oneof
5064 && alt_num
< REGEXP_ONEOF (regexp
)->regexps_num
);
5065 unit_decl
= REGEXP_UNIT (unit
)->unit_decl
;
5067 length
= (cycle
+ 1) * REGEXP_ONEOF (regexp
)->regexps_num
;
5068 while (cycle_alt_unit_usages
.length () < length
)
5069 cycle_alt_unit_usages
.safe_push (NULL
);
5071 index
= cycle
* REGEXP_ONEOF (regexp
)->regexps_num
+ alt_num
;
5073 for (curr
= cycle_alt_unit_usages
[index
];
5075 prev
= curr
, curr
= curr
->next
)
5076 if (curr
->unit_decl
>= unit_decl
)
5078 if (curr
!= NULL
&& curr
->unit_decl
== unit_decl
)
5080 obstack_blank (&unit_usages
, sizeof (struct unit_usage
));
5081 unit_usage_ptr
= (struct unit_usage
*) obstack_base (&unit_usages
);
5082 obstack_finish (&unit_usages
);
5083 unit_usage_ptr
->unit_decl
= unit_decl
;
5084 unit_decl
->last_distribution_check_cycle
= -1; /* undefined */
5085 unit_usage_ptr
->next
= curr
;
5087 cycle_alt_unit_usages
[index
] = unit_usage_ptr
;
5089 prev
->next
= unit_usage_ptr
;
5092 /* Return true if unit UNIT_DECL is present on the LIST. */
5094 unit_present_on_list_p (unit_usage_t list
, unit_decl_t unit_decl
)
5096 while (list
!= NULL
)
5098 if (list
->unit_decl
== unit_decl
)
5105 /* The function returns true if reservations of alternatives ALT1 and
5106 ALT2 are equal after excluding reservations of units of
5107 EXCLUDED_AUTOMATON_DECL. */
5109 equal_alternatives_p (int alt1
, int alt2
, int n_alts
,
5110 struct automaton_decl
*excluded_automaton_decl
)
5113 unit_usage_t list1
, list2
;
5116 i
< (int) cycle_alt_unit_usages
.length ();
5119 for (list1
= cycle_alt_unit_usages
[i
+ alt1
],
5120 list2
= cycle_alt_unit_usages
[i
+ alt2
];;
5121 list1
= list1
->next
, list2
= list2
->next
)
5123 while (list1
!= NULL
5124 && list1
->unit_decl
->automaton_decl
== excluded_automaton_decl
)
5125 list1
= list1
->next
;
5126 while (list2
!= NULL
5127 && list2
->unit_decl
->automaton_decl
== excluded_automaton_decl
)
5128 list2
= list2
->next
;
5129 if (list1
== NULL
|| list2
== NULL
)
5136 if (list1
->unit_decl
!= list2
->unit_decl
)
5144 /* The function processes given REGEXP to find units with the wrong
5147 check_regexp_units_distribution (const char *insn_reserv_name
,
5150 int i
, j
, k
, cycle
, start
, n_alts
, alt
, alt2
;
5151 bool annotation_reservation_message_reported_p
;
5152 regexp_t seq
, allof
, unit
;
5153 struct unit_usage
*unit_usage_ptr
;
5155 if (regexp
== NULL
|| regexp
->mode
!= rm_oneof
)
5157 /* Store all unit usages in the regexp: */
5158 obstack_init (&unit_usages
);
5159 cycle_alt_unit_usages
.create (10);
5161 for (i
= REGEXP_ONEOF (regexp
)->regexps_num
- 1; i
>= 0; i
--)
5163 seq
= REGEXP_ONEOF (regexp
)->regexps
[i
];
5167 for (j
= 0; j
< REGEXP_SEQUENCE (seq
)->regexps_num
; j
++)
5169 allof
= REGEXP_SEQUENCE (seq
)->regexps
[j
];
5170 switch (allof
->mode
)
5173 for (k
= 0; k
< REGEXP_ALLOF (allof
)->regexps_num
; k
++)
5175 unit
= REGEXP_ALLOF (allof
)->regexps
[k
];
5176 if (unit
->mode
== rm_unit
)
5177 store_alt_unit_usage (regexp
, unit
, j
, i
);
5179 gcc_assert (unit
->mode
== rm_nothing
);
5184 store_alt_unit_usage (regexp
, allof
, j
, i
);
5197 for (k
= 0; k
< REGEXP_ALLOF (seq
)->regexps_num
; k
++)
5199 unit
= REGEXP_ALLOF (seq
)->regexps
[k
];
5203 store_alt_unit_usage (regexp
, unit
, 0, i
);
5216 store_alt_unit_usage (regexp
, seq
, 0, i
);
5226 /* Check distribution: */
5227 for (i
= 0; i
< (int) cycle_alt_unit_usages
.length (); i
++)
5228 for (unit_usage_ptr
= cycle_alt_unit_usages
[i
];
5229 unit_usage_ptr
!= NULL
;
5230 unit_usage_ptr
= unit_usage_ptr
->next
)
5231 unit_usage_ptr
->unit_decl
->last_distribution_check_cycle
= -1;
5232 n_alts
= REGEXP_ONEOF (regexp
)->regexps_num
;
5233 auto_vec
<int> marked (n_alts
);
5234 for (i
= 0; i
< n_alts
; i
++)
5235 marked
.safe_push (0);
5236 annotation_reservation_message_reported_p
= false;
5237 for (i
= 0; i
< (int) cycle_alt_unit_usages
.length (); i
++)
5240 start
= cycle
* n_alts
;
5241 for (unit_usage_ptr
= cycle_alt_unit_usages
[i
];
5242 unit_usage_ptr
!= NULL
;
5243 unit_usage_ptr
= unit_usage_ptr
->next
)
5245 if (unit_usage_ptr
->unit_decl
->last_distribution_check_cycle
== cycle
)
5247 unit_usage_ptr
->unit_decl
->last_distribution_check_cycle
= cycle
;
5248 for (alt
= 0; alt
< n_alts
; alt
++)
5249 if (! unit_present_on_list_p (cycle_alt_unit_usages
[start
+ alt
],
5250 unit_usage_ptr
->unit_decl
))
5254 memset (marked
.address (), 0, n_alts
* sizeof (int));
5255 for (alt
= 0; alt
< n_alts
; alt
++)
5257 if (! unit_present_on_list_p (cycle_alt_unit_usages
[start
+ alt
],
5258 unit_usage_ptr
->unit_decl
))
5261 j
< (int) cycle_alt_unit_usages
.length ();
5265 if (! unit_present_on_list_p
5266 (cycle_alt_unit_usages
[start
+ alt2
],
5267 unit_usage_ptr
->unit_decl
)
5268 && equal_alternatives_p (alt
, alt2
, n_alts
,
5270 ->unit_decl
->automaton_decl
))
5277 for (alt
= 0; alt
< n_alts
&& marked
[alt
]; alt
++)
5279 if (alt
< n_alts
&& 0)
5281 if (! annotation_message_reported_p
)
5283 fprintf (stderr
, "\n");
5284 error ("The following units do not satisfy units-automata distribution rule");
5285 error ("(Unit presence on one alt and its absence on other alt\n");
5286 error (" result in different other automata reservations)");
5287 annotation_message_reported_p
= true;
5289 if (! annotation_reservation_message_reported_p
)
5291 error ("Reserv %s:", insn_reserv_name
);
5292 annotation_reservation_message_reported_p
= true;
5294 error (" Unit %s, cycle %d, alt %d, another alt %d",
5295 unit_usage_ptr
->unit_decl
->name
, cycle
, i
% n_alts
, alt
);
5299 cycle_alt_unit_usages
.release ();
5300 obstack_free (&unit_usages
, NULL
);
5303 /* The function finds units which violates units to automata
5304 distribution rule. If the units exist, report about them. */
5306 check_unit_distributions_to_automata (void)
5312 fprintf (stderr
, "Check unit distributions to automata...");
5313 automaton_decls
.create (0);
5314 for (i
= 0; i
< description
->decls_num
; i
++)
5316 decl
= description
->decls
[i
];
5317 if (decl
->mode
== dm_automaton
)
5318 automaton_decls
.safe_push (decl
);
5320 if (automaton_decls
.length () > 1)
5322 annotation_message_reported_p
= false;
5323 for (i
= 0; i
< description
->decls_num
; i
++)
5325 decl
= description
->decls
[i
];
5326 if (decl
->mode
== dm_insn_reserv
)
5327 check_regexp_units_distribution
5328 (DECL_INSN_RESERV (decl
)->name
,
5329 DECL_INSN_RESERV (decl
)->transformed_regexp
);
5332 automaton_decls
.release ();
5334 fprintf (stderr
, "done\n");
5339 /* The page contains code for building alt_states (see comments for
5340 IR) describing all possible insns reservations of an automaton. */
5342 /* Current state being formed for which the current alt_state
5344 static state_t state_being_formed
;
5346 /* Current alt_state being formed. */
5347 static alt_state_t alt_state_being_formed
;
5349 /* This recursive function processes `,' and units in reservation
5350 REGEXP for forming alt_states of AUTOMATON. It is believed that
5351 CURR_CYCLE is start cycle of all reservation REGEXP. */
5353 process_seq_for_forming_states (regexp_t regexp
, automaton_t automaton
,
5361 switch (regexp
->mode
)
5364 if (REGEXP_UNIT (regexp
)->unit_decl
->corresponding_automaton_num
5365 == automaton
->automaton_order_num
)
5366 set_state_reserv (state_being_formed
, curr_cycle
,
5367 REGEXP_UNIT (regexp
)->unit_decl
->unit_num
);
5371 for (i
= 0; i
< REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
5373 = process_seq_for_forming_states
5374 (REGEXP_SEQUENCE (regexp
)->regexps
[i
], automaton
, curr_cycle
) + 1;
5379 int finish_cycle
= 0;
5382 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
5384 cycle
= process_seq_for_forming_states (REGEXP_ALLOF (regexp
)
5386 automaton
, curr_cycle
);
5387 if (finish_cycle
< cycle
)
5388 finish_cycle
= cycle
;
5390 return finish_cycle
;
5401 /* This recursive function finishes forming ALT_STATE of AUTOMATON and
5402 inserts alt_state into the table. */
5404 finish_forming_alt_state (alt_state_t alt_state
,
5405 automaton_t automaton ATTRIBUTE_UNUSED
)
5407 state_t state_in_table
;
5408 state_t corresponding_state
;
5410 corresponding_state
= alt_state
->state
;
5411 state_in_table
= insert_state (corresponding_state
);
5412 if (state_in_table
!= corresponding_state
)
5414 free_state (corresponding_state
);
5415 alt_state
->state
= state_in_table
;
5419 /* The following variable value is current automaton insn for whose
5420 reservation the alt states are created. */
5421 static ainsn_t curr_ainsn
;
5423 /* This recursive function processes `|' in reservation REGEXP for
5424 forming alt_states of AUTOMATON. List of the alt states should
5425 have the same order as in the description. */
5427 process_alts_for_forming_states (regexp_t regexp
, automaton_t automaton
,
5432 if (regexp
->mode
!= rm_oneof
)
5434 alt_state_being_formed
= get_free_alt_state ();
5435 state_being_formed
= get_free_state (1, automaton
);
5436 alt_state_being_formed
->state
= state_being_formed
;
5437 /* We inserts in reverse order but we process alternatives also
5438 in reverse order. So we have the same order of alternative
5439 as in the description. */
5440 alt_state_being_formed
->next_alt_state
= curr_ainsn
->alt_states
;
5441 curr_ainsn
->alt_states
= alt_state_being_formed
;
5442 (void) process_seq_for_forming_states (regexp
, automaton
, 0);
5443 finish_forming_alt_state (alt_state_being_formed
, automaton
);
5447 gcc_assert (!inside_oneof_p
);
5448 /* We processes it in reverse order to get list with the same
5449 order as in the description. See also the previous
5451 for (i
= REGEXP_ONEOF (regexp
)->regexps_num
- 1; i
>= 0; i
--)
5452 process_alts_for_forming_states (REGEXP_ONEOF (regexp
)->regexps
[i
],
5457 /* Create nodes alt_state for all AUTOMATON insns. */
5459 create_alt_states (automaton_t automaton
)
5461 struct insn_reserv_decl
*reserv_decl
;
5463 for (curr_ainsn
= automaton
->ainsn_list
;
5465 curr_ainsn
= curr_ainsn
->next_ainsn
)
5467 reserv_decl
= curr_ainsn
->insn_reserv_decl
;
5468 if (!special_decl_p (reserv_decl
))
5470 curr_ainsn
->alt_states
= NULL
;
5471 process_alts_for_forming_states (reserv_decl
->transformed_regexp
,
5473 curr_ainsn
->sorted_alt_states
5474 = uniq_sort_alt_states (curr_ainsn
->alt_states
);
5481 /* The page contains major code for building DFA(s) for fast pipeline
5482 hazards recognition. */
5484 /* The function forms list of ainsns of AUTOMATON with the same
5488 form_ainsn_with_same_reservs (automaton_t automaton
)
5492 auto_vec
<ainsn_t
, 150> last_insns
;
5494 for (curr_ainsn
= automaton
->ainsn_list
;
5496 curr_ainsn
= curr_ainsn
->next_ainsn
)
5497 if (special_decl_p (curr_ainsn
->insn_reserv_decl
))
5499 curr_ainsn
->next_same_reservs_insn
= NULL
;
5500 curr_ainsn
->first_insn_with_same_reservs
= 1;
5504 for (i
= 0; i
< last_insns
.length (); i
++)
5506 (curr_ainsn
->sorted_alt_states
,
5507 last_insns
[i
]->sorted_alt_states
))
5509 curr_ainsn
->next_same_reservs_insn
= NULL
;
5510 if (i
< last_insns
.length ())
5512 curr_ainsn
->first_insn_with_same_reservs
= 0;
5513 last_insns
[i
]->next_same_reservs_insn
= curr_ainsn
;
5514 last_insns
[i
] = curr_ainsn
;
5518 last_insns
.safe_push (curr_ainsn
);
5519 curr_ainsn
->first_insn_with_same_reservs
= 1;
5524 /* Forming unit reservations which can affect creating the automaton
5525 states achieved from a given state. It permits to build smaller
5526 automata in many cases. We would have the same automata after
5527 the minimization without such optimization, but the automaton
5528 right after the building could be huge. So in other words, usage
5529 of reservs_matter means some minimization during building the
5531 static reserv_sets_t
5532 form_reservs_matter (automaton_t automaton
)
5535 reserv_sets_t reservs_matter
= alloc_empty_reserv_sets ();
5537 for (cycle
= 0; cycle
< max_cycles_num
; cycle
++)
5538 for (unit
= 0; unit
< description
->units_num
; unit
++)
5539 if (units_array
[unit
]->automaton_decl
5540 == automaton
->corresponding_automaton_decl
5541 && (cycle
>= units_array
[unit
]->min_occ_cycle_num
5542 /* We cannot remove queried unit from reservations. */
5543 || units_array
[unit
]->query_p
5544 /* We cannot remove units which are used
5545 `exclusion_set', `presence_set',
5546 `final_presence_set', `absence_set', and
5547 `final_absence_set'. */
5548 || units_array
[unit
]->in_set_p
))
5549 set_unit_reserv (reservs_matter
, cycle
, unit
);
5550 return reservs_matter
;
5553 /* The following function creates all states of nondeterministic AUTOMATON. */
5555 make_automaton (automaton_t automaton
)
5558 struct insn_reserv_decl
*insn_reserv_decl
;
5559 alt_state_t alt_state
;
5561 state_t start_state
;
5563 auto_vec
<state_t
, 150> state_stack
;
5565 reserv_sets_t reservs_matter
= form_reservs_matter (automaton
);
5567 /* Create the start state (empty state). */
5568 start_state
= insert_state (get_free_state (1, automaton
));
5569 automaton
->start_state
= start_state
;
5570 start_state
->it_was_placed_in_stack_for_NDFA_forming
= 1;
5571 state_stack
.safe_push (start_state
);
5573 while (state_stack
.length () != 0)
5575 state
= state_stack
.pop ();
5576 for (ainsn
= automaton
->ainsn_list
;
5578 ainsn
= ainsn
->next_ainsn
)
5579 if (ainsn
->first_insn_with_same_reservs
)
5581 insn_reserv_decl
= ainsn
->insn_reserv_decl
;
5582 if (!special_decl_p (insn_reserv_decl
))
5584 /* We process alt_states in the same order as they are
5585 present in the description. */
5586 for (alt_state
= ainsn
->alt_states
;
5588 alt_state
= alt_state
->next_alt_state
)
5590 state2
= alt_state
->state
;
5591 if (!intersected_state_reservs_p (state
, state2
))
5593 state2
= states_union (state
, state2
, reservs_matter
);
5594 if (!state2
->it_was_placed_in_stack_for_NDFA_forming
)
5596 state2
->it_was_placed_in_stack_for_NDFA_forming
5598 state_stack
.safe_push (state2
);
5600 if (progress_flag
&& states_n
% 100 == 0)
5601 fprintf (stderr
, ".");
5603 add_arc (state
, state2
, ainsn
);
5610 /* Add transition to advance cycle. */
5611 state2
= state_shift (state
, reservs_matter
);
5612 if (!state2
->it_was_placed_in_stack_for_NDFA_forming
)
5614 state2
->it_was_placed_in_stack_for_NDFA_forming
= 1;
5615 state_stack
.safe_push (state2
);
5617 if (progress_flag
&& states_n
% 100 == 0)
5618 fprintf (stderr
, ".");
5620 add_arc (state
, state2
, automaton
->advance_ainsn
);
5624 /* Form lists of all arcs of STATE marked by the same ainsn. */
5626 form_arcs_marked_by_insn (state_t state
)
5632 for (i
= 0; i
< description
->decls_num
; i
++)
5634 decl
= description
->decls
[i
];
5635 if (decl
->mode
== dm_insn_reserv
)
5636 DECL_INSN_RESERV (decl
)->arcs_marked_by_insn
= NULL
;
5638 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
5640 gcc_assert (arc
->insn
);
5641 arc
->next_arc_marked_by_insn
5642 = arc
->insn
->insn_reserv_decl
->arcs_marked_by_insn
;
5643 arc
->insn
->insn_reserv_decl
->arcs_marked_by_insn
= arc
;
5647 /* The function creates composed state (see comments for IR) from
5648 ORIGINAL_STATE and list of arcs ARCS_MARKED_BY_INSN marked by the
5649 same insn. If the composed state is not in STATE_STACK yet, it is
5650 pushed into STATE_STACK. */
5653 create_composed_state (state_t original_state
, arc_t arcs_marked_by_insn
,
5654 vec
<state_t
> *state_stack
)
5657 alt_state_t alt_state
, curr_alt_state
;
5658 alt_state_t new_alt_state
;
5661 state_t state_in_table
;
5663 alt_state_t canonical_alt_states_list
;
5664 int new_state_p
= 0;
5666 if (arcs_marked_by_insn
== NULL
)
5668 if (arcs_marked_by_insn
->next_arc_marked_by_insn
== NULL
)
5669 state
= arcs_marked_by_insn
->to_state
;
5672 gcc_assert (ndfa_flag
);
5673 /* Create composed state. */
5674 state
= get_free_state (0, arcs_marked_by_insn
->to_state
->automaton
);
5675 curr_alt_state
= NULL
;
5676 for (curr_arc
= arcs_marked_by_insn
;
5678 curr_arc
= curr_arc
->next_arc_marked_by_insn
)
5679 if (curr_arc
->to_state
->component_states
== NULL
)
5681 new_alt_state
= get_free_alt_state ();
5682 new_alt_state
->next_alt_state
= curr_alt_state
;
5683 new_alt_state
->state
= curr_arc
->to_state
;
5684 curr_alt_state
= new_alt_state
;
5687 for (alt_state
= curr_arc
->to_state
->component_states
;
5689 alt_state
= alt_state
->next_sorted_alt_state
)
5691 new_alt_state
= get_free_alt_state ();
5692 new_alt_state
->next_alt_state
= curr_alt_state
;
5693 new_alt_state
->state
= alt_state
->state
;
5694 gcc_assert (!alt_state
->state
->component_states
);
5695 curr_alt_state
= new_alt_state
;
5697 /* There are not identical sets in the alt state list. */
5698 canonical_alt_states_list
= uniq_sort_alt_states (curr_alt_state
);
5699 if (canonical_alt_states_list
->next_sorted_alt_state
== NULL
)
5702 state
= canonical_alt_states_list
->state
;
5703 free_state (temp_state
);
5707 state
->component_states
= canonical_alt_states_list
;
5708 state_in_table
= insert_state (state
);
5709 if (state_in_table
!= state
)
5712 (state_in_table
->it_was_placed_in_stack_for_DFA_forming
);
5714 state
= state_in_table
;
5718 gcc_assert (!state
->it_was_placed_in_stack_for_DFA_forming
);
5720 for (curr_alt_state
= state
->component_states
;
5721 curr_alt_state
!= NULL
;
5722 curr_alt_state
= curr_alt_state
->next_sorted_alt_state
)
5723 for (curr_arc
= first_out_arc (curr_alt_state
->state
);
5725 curr_arc
= next_out_arc (curr_arc
))
5727 /* When producing collapse-NDFA transitions, we
5728 only add advance-cycle transitions to the
5729 collapsed states. */
5730 || (curr_arc
->insn
->insn_reserv_decl
5731 != DECL_INSN_RESERV (advance_cycle_insn_decl
)))
5732 add_arc (state
, curr_arc
->to_state
, curr_arc
->insn
);
5734 arcs_marked_by_insn
->to_state
= state
;
5735 for (curr_arc
= arcs_marked_by_insn
->next_arc_marked_by_insn
;
5737 curr_arc
= next_arc
)
5739 next_arc
= curr_arc
->next_arc_marked_by_insn
;
5740 remove_arc (original_state
, curr_arc
);
5744 if (!state
->it_was_placed_in_stack_for_DFA_forming
)
5746 state
->it_was_placed_in_stack_for_DFA_forming
= 1;
5747 state_stack
->safe_push (state
);
5752 /* The function transforms nondeterministic AUTOMATON into
5756 NDFA_to_DFA (automaton_t automaton
)
5758 state_t start_state
;
5761 auto_vec
<state_t
> state_stack
;
5765 /* Create the start state (empty state). */
5766 start_state
= automaton
->start_state
;
5767 start_state
->it_was_placed_in_stack_for_DFA_forming
= 1;
5768 state_stack
.safe_push (start_state
);
5770 while (state_stack
.length () != 0)
5772 state
= state_stack
.pop ();
5773 form_arcs_marked_by_insn (state
);
5774 for (i
= 0; i
< description
->decls_num
; i
++)
5776 decl
= description
->decls
[i
];
5777 if (decl
->mode
== dm_insn_reserv
5778 && decl
!= collapse_ndfa_insn_decl
5779 && create_composed_state
5780 (state
, DECL_INSN_RESERV (decl
)->arcs_marked_by_insn
,
5784 if (progress_flag
&& states_n
% 100 == 0)
5785 fprintf (stderr
, ".");
5788 /* Add a transition to collapse the NDFA. */
5791 if (state
->component_states
!= NULL
)
5793 state_t state2
= state
->component_states
->state
;
5794 if (!state2
->it_was_placed_in_stack_for_DFA_forming
)
5796 state2
->it_was_placed_in_stack_for_DFA_forming
= 1;
5797 state_stack
.safe_push (state2
);
5799 add_arc (state
, state2
, automaton
->collapse_ainsn
);
5802 add_arc (state
, state
, automaton
->collapse_ainsn
);
5807 /* The following variable value is current number (1, 2, ...) of passing
5809 static int curr_state_graph_pass_num
;
5811 /* This recursive function passes all states achieved from START_STATE
5812 and applies APPLIED_FUNC to them. */
5814 pass_state_graph (state_t start_state
, void (*applied_func
) (state_t state
))
5818 if (start_state
->pass_num
== curr_state_graph_pass_num
)
5820 start_state
->pass_num
= curr_state_graph_pass_num
;
5821 (*applied_func
) (start_state
);
5822 for (arc
= first_out_arc (start_state
);
5824 arc
= next_out_arc (arc
))
5825 pass_state_graph (arc
->to_state
, applied_func
);
5828 /* This recursive function passes all states of AUTOMATON and applies
5829 APPLIED_FUNC to them. */
5831 pass_states (automaton_t automaton
, void (*applied_func
) (state_t state
))
5833 curr_state_graph_pass_num
++;
5834 pass_state_graph (automaton
->start_state
, applied_func
);
5837 /* The function initializes code for passing of all states. */
5839 initiate_pass_states (void)
5841 curr_state_graph_pass_num
= 0;
5844 /* The following vla is used for storing pointers to all achieved
5846 static vec
<state_t
> all_achieved_states
;
5848 /* This function is called by function pass_states to add an achieved
5851 add_achieved_state (state_t state
)
5853 all_achieved_states
.safe_push (state
);
5856 /* The function sets up equivalence numbers of insns which mark all
5857 out arcs of STATE by equiv_class_num_1 (if ODD_ITERATION_FLAG has
5858 nonzero value) or by equiv_class_num_2 of the destination state. */
5860 set_out_arc_insns_equiv_num (state_t state
, int odd_iteration_flag
)
5864 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
5866 gcc_assert (!arc
->insn
->insn_reserv_decl
->equiv_class_num
);
5867 arc
->insn
->insn_reserv_decl
->equiv_class_num
5868 = (odd_iteration_flag
5869 ? arc
->to_state
->equiv_class_num_1
5870 : arc
->to_state
->equiv_class_num_2
);
5871 gcc_assert (arc
->insn
->insn_reserv_decl
->equiv_class_num
);
5875 /* The function clears equivalence numbers and alt_states in all insns
5876 which mark all out arcs of STATE. */
5878 clear_arc_insns_equiv_num (state_t state
)
5882 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
5883 arc
->insn
->insn_reserv_decl
->equiv_class_num
= 0;
5887 /* The following function returns TRUE if STATE reserves the unit with
5888 UNIT_NUM on the first cycle. */
5890 first_cycle_unit_presence (state_t state
, int unit_num
)
5892 alt_state_t alt_state
;
5894 if (state
->component_states
== NULL
)
5895 return test_unit_reserv (state
->reservs
, 0, unit_num
);
5898 for (alt_state
= state
->component_states
;
5900 alt_state
= alt_state
->next_sorted_alt_state
)
5901 if (test_unit_reserv (alt_state
->state
->reservs
, 0, unit_num
))
5907 /* This fills in the presence_signature[] member of STATE. */
5909 cache_presence (state_t state
)
5913 sz
= (description
->query_units_num
+ sizeof (int) * CHAR_BIT
- 1)
5914 / (sizeof (int) * CHAR_BIT
);
5916 state
->presence_signature
= XCREATENODEVEC (unsigned int, sz
);
5917 for (i
= 0; i
< description
->units_num
; i
++)
5918 if (units_array
[i
]->query_p
)
5920 int presence1_p
= first_cycle_unit_presence (state
, i
);
5921 state
->presence_signature
[num
/ (sizeof (int) * CHAR_BIT
)]
5922 |= (!!presence1_p
) << (num
% (sizeof (int) * CHAR_BIT
));
5927 /* The function returns nonzero value if STATE is not equivalent to
5928 ANOTHER_STATE from the same current partition on equivalence
5929 classes. Another state has ANOTHER_STATE_OUT_ARCS_NUM number of
5930 output arcs. Iteration of making equivalence partition is defined
5931 by ODD_ITERATION_FLAG. */
5933 state_is_differed (state_t state
, state_t another_state
,
5934 int odd_iteration_flag
)
5937 unsigned int sz
, si
;
5939 gcc_assert (state
->num_out_arcs
== another_state
->num_out_arcs
);
5941 sz
= (description
->query_units_num
+ sizeof (int) * CHAR_BIT
- 1)
5942 / (sizeof (int) * CHAR_BIT
);
5944 for (si
= 0; si
< sz
; si
++)
5945 gcc_assert (state
->presence_signature
[si
]
5946 == another_state
->presence_signature
[si
]);
5948 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
5950 if ((odd_iteration_flag
5951 ? arc
->to_state
->equiv_class_num_1
5952 : arc
->to_state
->equiv_class_num_2
)
5953 != arc
->insn
->insn_reserv_decl
->equiv_class_num
)
5960 /* Compares two states pointed to by STATE_PTR_1 and STATE_PTR_2
5961 and return -1, 0 or 1. This function can be used as predicate for
5962 qsort(). It requires the member presence_signature[] of both
5963 states be filled. */
5965 compare_states_for_equiv (const void *state_ptr_1
,
5966 const void *state_ptr_2
)
5968 const_state_t
const s1
= *(const_state_t
const*)state_ptr_1
;
5969 const_state_t
const s2
= *(const_state_t
const*)state_ptr_2
;
5970 unsigned int sz
, si
;
5971 if (s1
->num_out_arcs
< s2
->num_out_arcs
)
5973 else if (s1
->num_out_arcs
> s2
->num_out_arcs
)
5976 sz
= (description
->query_units_num
+ sizeof (int) * CHAR_BIT
- 1)
5977 / (sizeof (int) * CHAR_BIT
);
5979 for (si
= 0; si
< sz
; si
++)
5980 if (s1
->presence_signature
[si
] < s2
->presence_signature
[si
])
5982 else if (s1
->presence_signature
[si
] > s2
->presence_signature
[si
])
5987 /* The function makes initial partition of STATES on equivalent
5988 classes and saves it into CLASSES. This function requires the input
5989 to be sorted via compare_states_for_equiv(). */
5991 init_equiv_class (vec
<state_t
> states
, vec
<state_t
> *classes
)
5997 classes
->create (150);
5998 for (i
= 0; i
< states
.length (); i
++)
6000 state_t state
= states
[i
];
6003 if (compare_states_for_equiv (&prev
, &state
) != 0)
6005 classes
->safe_push (prev
);
6010 state
->equiv_class_num_1
= class_num
;
6011 state
->next_equiv_class_state
= prev
;
6015 classes
->safe_push (prev
);
6019 /* The function copies pointers to equivalent states from vla FROM
6022 copy_equiv_class (vec
<state_t
> *to
, vec
<state_t
> from
)
6028 /* The function processes equivalence class given by its first state,
6029 FIRST_STATE, on odd iteration if ODD_ITERATION_FLAG. If there
6030 are not equivalent states, the function partitions the class
6031 removing nonequivalent states and placing them in
6032 *NEXT_ITERATION_CLASSES, increments *NEW_EQUIV_CLASS_NUM_PTR ans
6033 assigns it to the state equivalence number. If the class has been
6034 partitioned, the function returns nonzero value. */
6036 partition_equiv_class (state_t first_state
, int odd_iteration_flag
,
6037 vec
<state_t
> *next_iteration_classes
,
6038 int *new_equiv_class_num_ptr
)
6040 state_t new_equiv_class
;
6048 while (first_state
!= NULL
)
6050 new_equiv_class
= NULL
;
6051 if (first_state
->next_equiv_class_state
!= NULL
)
6053 /* There are more one states in the class equivalence. */
6054 set_out_arc_insns_equiv_num (first_state
, odd_iteration_flag
);
6055 for (prev_state
= first_state
,
6056 curr_state
= first_state
->next_equiv_class_state
;
6058 curr_state
= next_state
)
6060 next_state
= curr_state
->next_equiv_class_state
;
6061 if (state_is_differed (curr_state
, first_state
,
6062 odd_iteration_flag
))
6064 /* Remove curr state from the class equivalence. */
6065 prev_state
->next_equiv_class_state
= next_state
;
6066 /* Add curr state to the new class equivalence. */
6067 curr_state
->next_equiv_class_state
= new_equiv_class
;
6068 if (new_equiv_class
== NULL
)
6069 (*new_equiv_class_num_ptr
)++;
6070 if (odd_iteration_flag
)
6071 curr_state
->equiv_class_num_2
= *new_equiv_class_num_ptr
;
6073 curr_state
->equiv_class_num_1
= *new_equiv_class_num_ptr
;
6074 new_equiv_class
= curr_state
;
6078 prev_state
= curr_state
;
6080 clear_arc_insns_equiv_num (first_state
);
6082 if (new_equiv_class
!= NULL
)
6083 next_iteration_classes
->safe_push (new_equiv_class
);
6084 first_state
= new_equiv_class
;
6089 /* The function finds equivalent states of AUTOMATON. */
6091 evaluate_equiv_classes (automaton_t automaton
, vec
<state_t
> *equiv_classes
)
6093 int new_equiv_class_num
;
6094 int odd_iteration_flag
;
6096 vec
<state_t
> next_iteration_classes
;
6099 all_achieved_states
.create (1500);
6100 pass_states (automaton
, add_achieved_state
);
6101 pass_states (automaton
, cache_presence
);
6102 all_achieved_states
.qsort (compare_states_for_equiv
);
6104 odd_iteration_flag
= 0;
6105 new_equiv_class_num
= init_equiv_class (all_achieved_states
,
6106 &next_iteration_classes
);
6110 odd_iteration_flag
= !odd_iteration_flag
;
6112 copy_equiv_class (equiv_classes
, next_iteration_classes
);
6114 /* Transfer equiv numbers for the next iteration. */
6115 for (i
= 0; i
< all_achieved_states
.length (); i
++)
6116 if (odd_iteration_flag
)
6117 all_achieved_states
[i
]->equiv_class_num_2
6118 = all_achieved_states
[i
]->equiv_class_num_1
;
6120 all_achieved_states
[i
]->equiv_class_num_1
6121 = all_achieved_states
[i
]->equiv_class_num_2
;
6123 for (i
= 0; i
< equiv_classes
->length (); i
++)
6124 if (partition_equiv_class ((*equiv_classes
)[i
],
6126 &next_iteration_classes
,
6127 &new_equiv_class_num
))
6130 while (!finish_flag
);
6131 next_iteration_classes
.release ();
6132 all_achieved_states
.release ();
6135 /* The function merges equivalent states of AUTOMATON. */
6137 merge_states (automaton_t automaton
, const vec
<state_t
> &equiv_classes
)
6141 state_t first_class_state
;
6142 alt_state_t alt_states
;
6143 alt_state_t alt_state
, new_alt_state
;
6148 /* Create states corresponding to equivalence classes containing two
6150 for (i
= 0; i
< equiv_classes
.length (); i
++)
6152 curr_state
= equiv_classes
[i
];
6153 if (curr_state
->next_equiv_class_state
!= NULL
)
6155 /* There are more one states in the class equivalence. */
6156 /* Create new compound state. */
6157 new_state
= get_free_state (0, automaton
);
6159 first_class_state
= curr_state
;
6160 for (curr_state
= first_class_state
;
6162 curr_state
= curr_state
->next_equiv_class_state
)
6164 curr_state
->equiv_class_state
= new_state
;
6165 if (curr_state
->component_states
== NULL
)
6167 new_alt_state
= get_free_alt_state ();
6168 new_alt_state
->state
= curr_state
;
6169 new_alt_state
->next_alt_state
= alt_states
;
6170 alt_states
= new_alt_state
;
6173 for (alt_state
= curr_state
->component_states
;
6175 alt_state
= alt_state
->next_sorted_alt_state
)
6177 new_alt_state
= get_free_alt_state ();
6178 new_alt_state
->state
= alt_state
->state
;
6179 new_alt_state
->next_alt_state
= alt_states
;
6180 alt_states
= new_alt_state
;
6183 /* It is important that alt states were sorted before and
6184 after merging to have the same querying results. */
6185 new_state
->component_states
= uniq_sort_alt_states (alt_states
);
6188 curr_state
->equiv_class_state
= curr_state
;
6191 for (i
= 0; i
< equiv_classes
.length (); i
++)
6193 curr_state
= equiv_classes
[i
];
6194 if (curr_state
->next_equiv_class_state
!= NULL
)
6196 first_class_state
= curr_state
;
6197 /* Create new arcs output from the state corresponding to
6199 for (curr_arc
= first_out_arc (first_class_state
);
6201 curr_arc
= next_out_arc (curr_arc
))
6202 add_arc (first_class_state
->equiv_class_state
,
6203 curr_arc
->to_state
->equiv_class_state
,
6205 /* Delete output arcs from states of given class equivalence. */
6206 for (curr_state
= first_class_state
;
6208 curr_state
= curr_state
->next_equiv_class_state
)
6210 if (automaton
->start_state
== curr_state
)
6211 automaton
->start_state
= curr_state
->equiv_class_state
;
6212 /* Delete the state and its output arcs. */
6213 for (curr_arc
= first_out_arc (curr_state
);
6215 curr_arc
= next_arc
)
6217 next_arc
= next_out_arc (curr_arc
);
6218 free_arc (curr_arc
);
6224 /* Change `to_state' of arcs output from the state of given
6225 equivalence class. */
6226 for (curr_arc
= first_out_arc (curr_state
);
6228 curr_arc
= next_out_arc (curr_arc
))
6229 curr_arc
->to_state
= curr_arc
->to_state
->equiv_class_state
;
6234 /* The function sets up new_cycle_p for states if there is arc to the
6235 state marked by advance_cycle_insn_decl. */
6237 set_new_cycle_flags (state_t state
)
6241 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
6242 if (arc
->insn
->insn_reserv_decl
6243 == DECL_INSN_RESERV (advance_cycle_insn_decl
))
6244 arc
->to_state
->new_cycle_p
= 1;
6247 /* The top level function for minimization of deterministic
6250 minimize_DFA (automaton_t automaton
)
6252 auto_vec
<state_t
> equiv_classes
;
6254 evaluate_equiv_classes (automaton
, &equiv_classes
);
6255 merge_states (automaton
, equiv_classes
);
6256 pass_states (automaton
, set_new_cycle_flags
);
6259 /* Values of two variables are counted number of states and arcs in an
6261 static int curr_counted_states_num
;
6262 static int curr_counted_arcs_num
;
6264 /* The function is called by function `pass_states' to count states
6265 and arcs of an automaton. */
6267 incr_states_and_arcs_nums (state_t state
)
6271 curr_counted_states_num
++;
6272 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
6273 curr_counted_arcs_num
++;
6276 /* The function counts states and arcs of AUTOMATON. */
6278 count_states_and_arcs (automaton_t automaton
, int *states_num
,
6281 curr_counted_states_num
= 0;
6282 curr_counted_arcs_num
= 0;
6283 pass_states (automaton
, incr_states_and_arcs_nums
);
6284 *states_num
= curr_counted_states_num
;
6285 *arcs_num
= curr_counted_arcs_num
;
6288 /* The function builds one DFA AUTOMATON for fast pipeline hazards
6289 recognition after checking and simplifying IR of the
6292 build_automaton (automaton_t automaton
)
6297 ticker_on (&NDFA_time
);
6300 if (automaton
->corresponding_automaton_decl
== NULL
)
6301 fprintf (stderr
, "Create anonymous automaton");
6303 fprintf (stderr
, "Create automaton `%s'",
6304 automaton
->corresponding_automaton_decl
->name
);
6305 fprintf (stderr
, " (1 dot is 100 new states):");
6307 make_automaton (automaton
);
6309 fprintf (stderr
, " done\n");
6310 ticker_off (&NDFA_time
);
6311 count_states_and_arcs (automaton
, &states_num
, &arcs_num
);
6312 automaton
->NDFA_states_num
= states_num
;
6313 automaton
->NDFA_arcs_num
= arcs_num
;
6314 ticker_on (&NDFA_to_DFA_time
);
6317 if (automaton
->corresponding_automaton_decl
== NULL
)
6318 fprintf (stderr
, "Make anonymous DFA");
6320 fprintf (stderr
, "Make DFA `%s'",
6321 automaton
->corresponding_automaton_decl
->name
);
6322 fprintf (stderr
, " (1 dot is 100 new states):");
6324 NDFA_to_DFA (automaton
);
6326 fprintf (stderr
, " done\n");
6327 ticker_off (&NDFA_to_DFA_time
);
6328 count_states_and_arcs (automaton
, &states_num
, &arcs_num
);
6329 automaton
->DFA_states_num
= states_num
;
6330 automaton
->DFA_arcs_num
= arcs_num
;
6331 if (!no_minimization_flag
)
6333 ticker_on (&minimize_time
);
6336 if (automaton
->corresponding_automaton_decl
== NULL
)
6337 fprintf (stderr
, "Minimize anonymous DFA...");
6339 fprintf (stderr
, "Minimize DFA `%s'...",
6340 automaton
->corresponding_automaton_decl
->name
);
6342 minimize_DFA (automaton
);
6344 fprintf (stderr
, "done\n");
6345 ticker_off (&minimize_time
);
6346 count_states_and_arcs (automaton
, &states_num
, &arcs_num
);
6347 automaton
->minimal_DFA_states_num
= states_num
;
6348 automaton
->minimal_DFA_arcs_num
= arcs_num
;
6354 /* The page contains code for enumeration of all states of an automaton. */
6356 /* Variable used for enumeration of all states of an automaton. Its
6357 value is current number of automaton states. */
6358 static int curr_state_order_num
;
6360 /* The function is called by function `pass_states' for enumerating
6363 set_order_state_num (state_t state
)
6365 state
->order_state_num
= curr_state_order_num
;
6366 curr_state_order_num
++;
6369 /* The function enumerates all states of AUTOMATON. */
6371 enumerate_states (automaton_t automaton
)
6373 curr_state_order_num
= 0;
6374 pass_states (automaton
, set_order_state_num
);
6375 automaton
->achieved_states_num
= curr_state_order_num
;
6380 /* The page contains code for finding equivalent automaton insns
6383 /* The function inserts AINSN into cyclic list
6384 CYCLIC_EQUIV_CLASS_INSN_LIST of ainsns. */
6386 insert_ainsn_into_equiv_class (ainsn_t ainsn
,
6387 ainsn_t cyclic_equiv_class_insn_list
)
6389 if (cyclic_equiv_class_insn_list
== NULL
)
6390 ainsn
->next_equiv_class_insn
= ainsn
;
6393 ainsn
->next_equiv_class_insn
6394 = cyclic_equiv_class_insn_list
->next_equiv_class_insn
;
6395 cyclic_equiv_class_insn_list
->next_equiv_class_insn
= ainsn
;
6400 /* The function deletes equiv_class_insn into cyclic list of
6401 equivalent ainsns. */
6403 delete_ainsn_from_equiv_class (ainsn_t equiv_class_insn
)
6405 ainsn_t curr_equiv_class_insn
;
6406 ainsn_t prev_equiv_class_insn
;
6408 prev_equiv_class_insn
= equiv_class_insn
;
6409 for (curr_equiv_class_insn
= equiv_class_insn
->next_equiv_class_insn
;
6410 curr_equiv_class_insn
!= equiv_class_insn
;
6411 curr_equiv_class_insn
= curr_equiv_class_insn
->next_equiv_class_insn
)
6412 prev_equiv_class_insn
= curr_equiv_class_insn
;
6413 if (prev_equiv_class_insn
!= equiv_class_insn
)
6414 prev_equiv_class_insn
->next_equiv_class_insn
6415 = equiv_class_insn
->next_equiv_class_insn
;
6418 /* The function processes AINSN of a state in order to find equivalent
6419 ainsns. INSN_ARCS_ARRAY is table: code of insn -> out arc of the
6422 process_insn_equiv_class (ainsn_t ainsn
, arc_t
*insn_arcs_array
)
6426 ainsn_t cyclic_insn_list
;
6429 gcc_assert (insn_arcs_array
[ainsn
->insn_reserv_decl
->insn_num
]);
6431 /* New class of ainsns which are not equivalent to given ainsn. */
6432 cyclic_insn_list
= NULL
;
6435 next_insn
= curr_insn
->next_equiv_class_insn
;
6436 arc
= insn_arcs_array
[curr_insn
->insn_reserv_decl
->insn_num
];
6438 || (insn_arcs_array
[ainsn
->insn_reserv_decl
->insn_num
]->to_state
6441 delete_ainsn_from_equiv_class (curr_insn
);
6442 cyclic_insn_list
= insert_ainsn_into_equiv_class (curr_insn
,
6445 curr_insn
= next_insn
;
6447 while (curr_insn
!= ainsn
);
6450 /* The function processes STATE in order to find equivalent ainsns. */
6452 process_state_for_insn_equiv_partition (state_t state
)
6455 arc_t
*insn_arcs_array
= XCNEWVEC (arc_t
, description
->insns_num
);
6457 /* Process insns of the arcs. */
6458 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
6459 insn_arcs_array
[arc
->insn
->insn_reserv_decl
->insn_num
] = arc
;
6460 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
6461 process_insn_equiv_class (arc
->insn
, insn_arcs_array
);
6463 free (insn_arcs_array
);
6466 /* The function searches for equivalent ainsns of AUTOMATON. */
6468 set_insn_equiv_classes (automaton_t automaton
)
6473 ainsn_t cyclic_insn_list
;
6474 ainsn_t insn_with_same_reservs
;
6475 int equiv_classes_num
;
6477 /* All insns are included in one equivalence class. */
6478 cyclic_insn_list
= NULL
;
6479 for (ainsn
= automaton
->ainsn_list
; ainsn
!= NULL
; ainsn
= ainsn
->next_ainsn
)
6480 if (ainsn
->first_insn_with_same_reservs
)
6481 cyclic_insn_list
= insert_ainsn_into_equiv_class (ainsn
,
6483 /* Process insns in order to make equivalence partition. */
6484 pass_states (automaton
, process_state_for_insn_equiv_partition
);
6485 /* Enumerate equiv classes. */
6486 for (ainsn
= automaton
->ainsn_list
; ainsn
!= NULL
; ainsn
= ainsn
->next_ainsn
)
6487 /* Set undefined value. */
6488 ainsn
->insn_equiv_class_num
= -1;
6489 equiv_classes_num
= 0;
6490 for (ainsn
= automaton
->ainsn_list
; ainsn
!= NULL
; ainsn
= ainsn
->next_ainsn
)
6491 if (ainsn
->insn_equiv_class_num
< 0)
6494 gcc_assert (first_insn
->first_insn_with_same_reservs
);
6495 first_insn
->first_ainsn_with_given_equivalence_num
= 1;
6496 curr_insn
= first_insn
;
6499 for (insn_with_same_reservs
= curr_insn
;
6500 insn_with_same_reservs
!= NULL
;
6501 insn_with_same_reservs
6502 = insn_with_same_reservs
->next_same_reservs_insn
)
6503 insn_with_same_reservs
->insn_equiv_class_num
= equiv_classes_num
;
6504 curr_insn
= curr_insn
->next_equiv_class_insn
;
6506 while (curr_insn
!= first_insn
);
6507 equiv_classes_num
++;
6509 automaton
->insn_equiv_classes_num
= equiv_classes_num
;
6514 /* This page contains code for creating DFA(s) and calls functions
6518 /* The following value is used to prevent floating point overflow for
6519 estimating an automaton bound. The value should be less DBL_MAX on
6520 the host machine. We use here approximate minimum of maximal
6521 double floating point value required by ANSI C standard. It
6522 will work for non ANSI sun compiler too. */
6524 #define MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND 1.0E37
6526 /* The function estimate size of the single DFA used by PHR (pipeline
6527 hazards recognizer). */
6529 estimate_one_automaton_bound (void)
6532 double one_automaton_estimation_bound
;
6536 one_automaton_estimation_bound
= 1.0;
6537 for (i
= 0; i
< description
->decls_num
; i
++)
6539 decl
= description
->decls
[i
];
6540 if (decl
->mode
== dm_unit
)
6542 root_value
= exp (log (DECL_UNIT (decl
)->max_occ_cycle_num
6543 - DECL_UNIT (decl
)->min_occ_cycle_num
+ 1.0)
6545 if (MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND
/ root_value
6546 > one_automaton_estimation_bound
)
6547 one_automaton_estimation_bound
*= root_value
;
6550 return one_automaton_estimation_bound
;
6553 /* The function compares unit declarations according to their maximal
6554 cycle in reservations. */
6556 compare_max_occ_cycle_nums (const void *unit_decl_1
,
6557 const void *unit_decl_2
)
6559 if ((DECL_UNIT (*(const_decl_t
const*) unit_decl_1
)->max_occ_cycle_num
)
6560 < (DECL_UNIT (*(const_decl_t
const*) unit_decl_2
)->max_occ_cycle_num
))
6562 else if ((DECL_UNIT (*(const_decl_t
const*) unit_decl_1
)->max_occ_cycle_num
)
6563 == (DECL_UNIT (*(const_decl_t
const*) unit_decl_2
)->max_occ_cycle_num
))
6569 /* The function makes heuristic assigning automata to units. Actually
6570 efficacy of the algorithm has been checked yet??? */
6573 units_to_automata_heuristic_distr (void)
6575 double estimation_bound
;
6579 unit_decl_t
*unit_decls
;
6582 if (description
->units_num
== 0)
6584 estimation_bound
= estimate_one_automaton_bound ();
6585 unit_decls
= XNEWVEC (unit_decl_t
, description
->units_num
);
6587 for (i
= 0, j
= 0; i
< description
->decls_num
; i
++)
6588 if (description
->decls
[i
]->mode
== dm_unit
)
6589 unit_decls
[j
++] = DECL_UNIT (description
->decls
[i
]);
6590 gcc_assert (j
== description
->units_num
);
6592 qsort (unit_decls
, description
->units_num
,
6593 sizeof (unit_decl_t
), compare_max_occ_cycle_nums
);
6596 bound_value
= unit_decls
[0]->max_occ_cycle_num
;
6597 unit_decls
[0]->corresponding_automaton_num
= automaton_num
;
6599 for (i
= 1; i
< description
->units_num
; i
++)
6601 rest_units_num
= description
->units_num
- i
+ 1;
6602 gcc_assert (automata_num
- automaton_num
- 1 <= rest_units_num
);
6603 if (automaton_num
< automata_num
- 1
6604 && ((automata_num
- automaton_num
- 1 == rest_units_num
)
6607 / unit_decls
[i
]->max_occ_cycle_num
))))
6609 bound_value
= unit_decls
[i
]->max_occ_cycle_num
;
6613 bound_value
*= unit_decls
[i
]->max_occ_cycle_num
;
6614 unit_decls
[i
]->corresponding_automaton_num
= automaton_num
;
6616 gcc_assert (automaton_num
== automata_num
- 1);
6620 /* The functions creates automaton insns for each automata. Automaton
6621 insn is simply insn for given automaton which makes reservation
6622 only of units of the automaton. */
6624 create_ainsns (automaton_t automaton
)
6627 ainsn_t first_ainsn
;
6634 for (i
= 0; i
< description
->decls_num
; i
++)
6636 decl
= description
->decls
[i
];
6637 if (decl
->mode
== dm_insn_reserv
)
6639 curr_ainsn
= XCREATENODE (struct ainsn
);
6640 curr_ainsn
->insn_reserv_decl
= DECL_INSN_RESERV (decl
);
6641 curr_ainsn
->important_p
= false;
6642 curr_ainsn
->next_ainsn
= NULL
;
6643 if (prev_ainsn
== NULL
)
6644 first_ainsn
= curr_ainsn
;
6646 prev_ainsn
->next_ainsn
= curr_ainsn
;
6647 if (decl
== advance_cycle_insn_decl
)
6648 automaton
->advance_ainsn
= curr_ainsn
;
6649 else if (decl
== collapse_ndfa_insn_decl
)
6650 automaton
->collapse_ainsn
= curr_ainsn
;
6651 prev_ainsn
= curr_ainsn
;
6654 automaton
->ainsn_list
= first_ainsn
;
6657 /* The function assigns automata to units according to constructions
6658 `define_automaton' in the description. */
6660 units_to_automata_distr (void)
6665 for (i
= 0; i
< description
->decls_num
; i
++)
6667 decl
= description
->decls
[i
];
6668 if (decl
->mode
== dm_unit
)
6670 if (DECL_UNIT (decl
)->automaton_decl
== NULL
6671 || (DECL_UNIT (decl
)->automaton_decl
->corresponding_automaton
6673 /* Distribute to the first automaton. */
6674 DECL_UNIT (decl
)->corresponding_automaton_num
= 0;
6676 DECL_UNIT (decl
)->corresponding_automaton_num
6677 = (DECL_UNIT (decl
)->automaton_decl
6678 ->corresponding_automaton
->automaton_order_num
);
6683 /* The function creates DFA(s) for fast pipeline hazards recognition
6684 after checking and simplifying IR of the description. */
6686 create_automata (void)
6688 automaton_t curr_automaton
;
6689 automaton_t prev_automaton
;
6691 int curr_automaton_num
;
6694 if (automata_num
!= 0)
6696 units_to_automata_heuristic_distr ();
6697 for (prev_automaton
= NULL
, curr_automaton_num
= 0;
6698 curr_automaton_num
< automata_num
;
6699 curr_automaton_num
++, prev_automaton
= curr_automaton
)
6701 curr_automaton
= XCREATENODE (struct automaton
);
6702 create_ainsns (curr_automaton
);
6703 curr_automaton
->corresponding_automaton_decl
= NULL
;
6704 curr_automaton
->next_automaton
= NULL
;
6705 curr_automaton
->automaton_order_num
= curr_automaton_num
;
6706 if (prev_automaton
== NULL
)
6707 description
->first_automaton
= curr_automaton
;
6709 prev_automaton
->next_automaton
= curr_automaton
;
6714 curr_automaton_num
= 0;
6715 prev_automaton
= NULL
;
6716 for (i
= 0; i
< description
->decls_num
; i
++)
6718 decl
= description
->decls
[i
];
6719 if (decl
->mode
== dm_automaton
6720 && DECL_AUTOMATON (decl
)->automaton_is_used
)
6722 curr_automaton
= XCREATENODE (struct automaton
);
6723 create_ainsns (curr_automaton
);
6724 curr_automaton
->corresponding_automaton_decl
6725 = DECL_AUTOMATON (decl
);
6726 curr_automaton
->next_automaton
= NULL
;
6727 DECL_AUTOMATON (decl
)->corresponding_automaton
= curr_automaton
;
6728 curr_automaton
->automaton_order_num
= curr_automaton_num
;
6729 if (prev_automaton
== NULL
)
6730 description
->first_automaton
= curr_automaton
;
6732 prev_automaton
->next_automaton
= curr_automaton
;
6733 curr_automaton_num
++;
6734 prev_automaton
= curr_automaton
;
6737 if (curr_automaton_num
== 0)
6739 curr_automaton
= XCREATENODE (struct automaton
);
6740 create_ainsns (curr_automaton
);
6741 curr_automaton
->corresponding_automaton_decl
= NULL
;
6742 curr_automaton
->next_automaton
= NULL
;
6743 description
->first_automaton
= curr_automaton
;
6745 units_to_automata_distr ();
6747 NDFA_time
= create_ticker ();
6748 ticker_off (&NDFA_time
);
6749 NDFA_to_DFA_time
= create_ticker ();
6750 ticker_off (&NDFA_to_DFA_time
);
6751 minimize_time
= create_ticker ();
6752 ticker_off (&minimize_time
);
6753 equiv_time
= create_ticker ();
6754 ticker_off (&equiv_time
);
6755 for (curr_automaton
= description
->first_automaton
;
6756 curr_automaton
!= NULL
;
6757 curr_automaton
= curr_automaton
->next_automaton
)
6761 if (curr_automaton
->corresponding_automaton_decl
== NULL
)
6762 fprintf (stderr
, "Prepare anonymous automaton creation ... ");
6764 fprintf (stderr
, "Prepare automaton `%s' creation...",
6765 curr_automaton
->corresponding_automaton_decl
->name
);
6767 create_alt_states (curr_automaton
);
6768 form_ainsn_with_same_reservs (curr_automaton
);
6770 fprintf (stderr
, "done\n");
6771 build_automaton (curr_automaton
);
6772 enumerate_states (curr_automaton
);
6773 ticker_on (&equiv_time
);
6774 set_insn_equiv_classes (curr_automaton
);
6775 ticker_off (&equiv_time
);
6781 /* This page contains code for forming string representation of
6782 regexp. The representation is formed on IR obstack. So you should
6783 not work with IR obstack between regexp_representation and
6784 finish_regexp_representation calls. */
6786 /* This recursive function forms string representation of regexp
6787 (without trailing '\0'). */
6789 form_regexp (regexp_t regexp
)
6793 switch (regexp
->mode
)
6795 case rm_unit
: case rm_reserv
:
6797 const char *name
= (regexp
->mode
== rm_unit
6798 ? REGEXP_UNIT (regexp
)->name
6799 : REGEXP_RESERV (regexp
)->name
);
6801 obstack_grow (&irp
, name
, strlen (name
));
6806 for (i
= 0; i
< REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
6809 obstack_1grow (&irp
, ',');
6810 form_regexp (REGEXP_SEQUENCE (regexp
)->regexps
[i
]);
6815 obstack_1grow (&irp
, '(');
6816 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
6819 obstack_1grow (&irp
, '+');
6820 if (REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
== rm_sequence
6821 || REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
== rm_oneof
)
6822 obstack_1grow (&irp
, '(');
6823 form_regexp (REGEXP_ALLOF (regexp
)->regexps
[i
]);
6824 if (REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
== rm_sequence
6825 || REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
== rm_oneof
)
6826 obstack_1grow (&irp
, ')');
6828 obstack_1grow (&irp
, ')');
6832 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
6835 obstack_1grow (&irp
, '|');
6836 if (REGEXP_ONEOF (regexp
)->regexps
[i
]->mode
== rm_sequence
)
6837 obstack_1grow (&irp
, '(');
6838 form_regexp (REGEXP_ONEOF (regexp
)->regexps
[i
]);
6839 if (REGEXP_ONEOF (regexp
)->regexps
[i
]->mode
== rm_sequence
)
6840 obstack_1grow (&irp
, ')');
6848 if (REGEXP_REPEAT (regexp
)->regexp
->mode
== rm_sequence
6849 || REGEXP_REPEAT (regexp
)->regexp
->mode
== rm_allof
6850 || REGEXP_REPEAT (regexp
)->regexp
->mode
== rm_oneof
)
6851 obstack_1grow (&irp
, '(');
6852 form_regexp (REGEXP_REPEAT (regexp
)->regexp
);
6853 if (REGEXP_REPEAT (regexp
)->regexp
->mode
== rm_sequence
6854 || REGEXP_REPEAT (regexp
)->regexp
->mode
== rm_allof
6855 || REGEXP_REPEAT (regexp
)->regexp
->mode
== rm_oneof
)
6856 obstack_1grow (&irp
, ')');
6857 sprintf (digits
, "*%d", REGEXP_REPEAT (regexp
)->repeat_num
);
6858 obstack_grow (&irp
, digits
, strlen (digits
));
6863 obstack_grow (&irp
, NOTHING_NAME
, strlen (NOTHING_NAME
));
6871 /* The function returns string representation of REGEXP on IR
6874 regexp_representation (regexp_t regexp
)
6876 form_regexp (regexp
);
6877 obstack_1grow (&irp
, '\0');
6878 return (char *) obstack_base (&irp
);
6881 /* The function frees memory allocated for last formed string
6882 representation of regexp. */
6884 finish_regexp_representation (void)
6886 int length
= obstack_object_size (&irp
);
6888 obstack_blank_fast (&irp
, -length
);
6893 /* This page contains code for output PHR (pipeline hazards recognizer). */
6895 /* The function outputs minimal C type which is sufficient for
6896 representation numbers in range min_range_value and
6897 max_range_value. Because host machine and build machine may be
6898 different, we use here minimal values required by ANSI C standard
6899 instead of UCHAR_MAX, SHRT_MAX, SHRT_MIN, etc. This is a good
6903 output_range_type (FILE *f
, long int min_range_value
,
6904 long int max_range_value
)
6906 if (min_range_value
>= 0 && max_range_value
<= 255)
6907 fprintf (f
, "unsigned char");
6908 else if (min_range_value
>= -127 && max_range_value
<= 127)
6909 fprintf (f
, "signed char");
6910 else if (min_range_value
>= 0 && max_range_value
<= 65535)
6911 fprintf (f
, "unsigned short");
6912 else if (min_range_value
>= -32767 && max_range_value
<= 32767)
6913 fprintf (f
, "short");
6918 /* The function outputs all initialization values of VECT. */
6920 output_vect (vla_hwint_t vect
)
6923 size_t vect_length
= vect
.length ();
6927 if (vect_length
== 0)
6928 fputs ("0 /* This is dummy el because the vect is empty */", output_file
);
6930 for (i
= 0; i
< vect_length
; i
++)
6932 fprintf (output_file
, "%5ld", (long) vect
[i
]);
6933 if (els_on_line
== 10)
6936 fputs (",\n", output_file
);
6938 else if (i
< vect_length
-1)
6939 fputs (", ", output_file
);
6944 /* The following is name of the structure which represents DFA(s) for
6946 #define CHIP_NAME "DFA_chip"
6948 /* The following is name of member which represents state of a DFA for
6951 output_chip_member_name (FILE *f
, automaton_t automaton
)
6953 if (automaton
->corresponding_automaton_decl
== NULL
)
6954 fprintf (f
, "automaton_state_%d", automaton
->automaton_order_num
);
6956 fprintf (f
, "%s_automaton_state",
6957 automaton
->corresponding_automaton_decl
->name
);
6960 /* The following is name of temporary variable which stores state of a
6963 output_temp_chip_member_name (FILE *f
, automaton_t automaton
)
6966 output_chip_member_name (f
, automaton
);
6969 /* This is name of macro value which is code of pseudo_insns
6970 representing advancing cpu cycle and collapsing the NDFA.
6971 Its value is used as internal code unknown insn. */
6972 #define ADVANCE_CYCLE_VALUE_NAME "DFA__ADVANCE_CYCLE"
6973 #define COLLAPSE_NDFA_VALUE_NAME "NDFA__COLLAPSE"
6975 /* Output name of translate vector for given automaton. */
6977 output_translate_vect_name (FILE *f
, automaton_t automaton
)
6979 if (automaton
->corresponding_automaton_decl
== NULL
)
6980 fprintf (f
, "translate_%d", automaton
->automaton_order_num
);
6982 fprintf (f
, "%s_translate", automaton
->corresponding_automaton_decl
->name
);
6985 /* Output name for simple transition table representation. */
6987 output_trans_full_vect_name (FILE *f
, automaton_t automaton
)
6989 if (automaton
->corresponding_automaton_decl
== NULL
)
6990 fprintf (f
, "transitions_%d", automaton
->automaton_order_num
);
6992 fprintf (f
, "%s_transitions",
6993 automaton
->corresponding_automaton_decl
->name
);
6996 /* Output name of comb vector of the transition table for given
6999 output_trans_comb_vect_name (FILE *f
, automaton_t automaton
)
7001 if (automaton
->corresponding_automaton_decl
== NULL
)
7002 fprintf (f
, "transitions_%d", automaton
->automaton_order_num
);
7004 fprintf (f
, "%s_transitions",
7005 automaton
->corresponding_automaton_decl
->name
);
7008 /* Output name of check vector of the transition table for given
7011 output_trans_check_vect_name (FILE *f
, automaton_t automaton
)
7013 if (automaton
->corresponding_automaton_decl
== NULL
)
7014 fprintf (f
, "check_%d", automaton
->automaton_order_num
);
7016 fprintf (f
, "%s_check", automaton
->corresponding_automaton_decl
->name
);
7019 /* Output name of base vector of the transition table for given
7022 output_trans_base_vect_name (FILE *f
, automaton_t automaton
)
7024 if (automaton
->corresponding_automaton_decl
== NULL
)
7025 fprintf (f
, "base_%d", automaton
->automaton_order_num
);
7027 fprintf (f
, "%s_base", automaton
->corresponding_automaton_decl
->name
);
7030 /* Output name of simple min issue delay table representation. */
7032 output_min_issue_delay_vect_name (FILE *f
, automaton_t automaton
)
7034 if (automaton
->corresponding_automaton_decl
== NULL
)
7035 fprintf (f
, "min_issue_delay_%d", automaton
->automaton_order_num
);
7037 fprintf (f
, "%s_min_issue_delay",
7038 automaton
->corresponding_automaton_decl
->name
);
7041 /* Output name of deadlock vector for given automaton. */
7043 output_dead_lock_vect_name (FILE *f
, automaton_t automaton
)
7045 if (automaton
->corresponding_automaton_decl
== NULL
)
7046 fprintf (f
, "dead_lock_%d", automaton
->automaton_order_num
);
7048 fprintf (f
, "%s_dead_lock", automaton
->corresponding_automaton_decl
->name
);
7051 /* Output name of reserved units table for AUTOMATON into file F. */
7053 output_reserved_units_table_name (FILE *f
, automaton_t automaton
)
7055 if (automaton
->corresponding_automaton_decl
== NULL
)
7056 fprintf (f
, "reserved_units_%d", automaton
->automaton_order_num
);
7058 fprintf (f
, "%s_reserved_units",
7059 automaton
->corresponding_automaton_decl
->name
);
7062 /* Name of the PHR interface macro. */
7063 #define CPU_UNITS_QUERY_MACRO_NAME "CPU_UNITS_QUERY"
7065 /* Names of an internal functions: */
7066 #define INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME "internal_min_issue_delay"
7068 /* This is external type of DFA(s) state. */
7069 #define STATE_TYPE_NAME "state_t"
7071 #define INTERNAL_TRANSITION_FUNC_NAME "internal_state_transition"
7073 #define INTERNAL_RESET_FUNC_NAME "internal_reset"
7075 #define INTERNAL_DEAD_LOCK_FUNC_NAME "internal_state_dead_lock_p"
7077 #define INTERNAL_INSN_LATENCY_FUNC_NAME "internal_insn_latency"
7079 /* Name of cache of insn dfa codes. */
7080 #define DFA_INSN_CODES_VARIABLE_NAME "dfa_insn_codes"
7082 /* Name of length of cache of insn dfa codes. */
7083 #define DFA_INSN_CODES_LENGTH_VARIABLE_NAME "dfa_insn_codes_length"
7085 /* Names of the PHR interface functions: */
7086 #define SIZE_FUNC_NAME "state_size"
7088 #define TRANSITION_FUNC_NAME "state_transition"
7090 #define MIN_ISSUE_DELAY_FUNC_NAME "min_issue_delay"
7092 #define MIN_INSN_CONFLICT_DELAY_FUNC_NAME "min_insn_conflict_delay"
7094 #define DEAD_LOCK_FUNC_NAME "state_dead_lock_p"
7096 #define RESET_FUNC_NAME "state_reset"
7098 #define INSN_LATENCY_FUNC_NAME "insn_latency"
7100 #define PRINT_RESERVATION_FUNC_NAME "print_reservation"
7102 #define GET_CPU_UNIT_CODE_FUNC_NAME "get_cpu_unit_code"
7104 #define CPU_UNIT_RESERVATION_P_FUNC_NAME "cpu_unit_reservation_p"
7106 #define INSN_HAS_DFA_RESERVATION_P_FUNC_NAME "insn_has_dfa_reservation_p"
7108 #define DFA_CLEAN_INSN_CACHE_FUNC_NAME "dfa_clean_insn_cache"
7110 #define DFA_CLEAR_SINGLE_INSN_CACHE_FUNC_NAME "dfa_clear_single_insn_cache"
7112 #define DFA_START_FUNC_NAME "dfa_start"
7114 #define DFA_FINISH_FUNC_NAME "dfa_finish"
7116 /* Names of parameters of the PHR interface functions. */
7117 #define STATE_NAME "state"
7119 #define INSN_PARAMETER_NAME "insn"
7121 #define INSN2_PARAMETER_NAME "insn2"
7123 #define CHIP_PARAMETER_NAME "chip"
7125 #define FILE_PARAMETER_NAME "f"
7127 #define CPU_UNIT_NAME_PARAMETER_NAME "cpu_unit_name"
7129 #define CPU_CODE_PARAMETER_NAME "cpu_unit_code"
7131 /* Names of the variables whose values are internal insn code of rtx
7133 #define INTERNAL_INSN_CODE_NAME "insn_code"
7135 #define INTERNAL_INSN2_CODE_NAME "insn2_code"
7137 /* Names of temporary variables in some functions. */
7138 #define TEMPORARY_VARIABLE_NAME "temp"
7140 #define I_VARIABLE_NAME "i"
7142 /* Name of result variable in some functions. */
7143 #define RESULT_VARIABLE_NAME "res"
7145 /* Name of function (attribute) to translate insn into internal insn
7147 #define INTERNAL_DFA_INSN_CODE_FUNC_NAME "internal_dfa_insn_code"
7149 /* Name of function (attribute) to translate insn into internal insn
7150 code with caching. */
7151 #define DFA_INSN_CODE_FUNC_NAME "dfa_insn_code"
7153 /* Output C type which is used for representation of codes of states
7156 output_state_member_type (FILE *f
, automaton_t automaton
)
7158 output_range_type (f
, 0, automaton
->achieved_states_num
);
7161 /* Output definition of the structure representing current DFA(s)
7164 output_chip_definitions (void)
7166 automaton_t automaton
;
7168 fprintf (output_file
, "struct %s\n{\n", CHIP_NAME
);
7169 for (automaton
= description
->first_automaton
;
7171 automaton
= automaton
->next_automaton
)
7173 fprintf (output_file
, " ");
7174 output_state_member_type (output_file
, automaton
);
7175 fprintf (output_file
, " ");
7176 output_chip_member_name (output_file
, automaton
);
7177 fprintf (output_file
, ";\n");
7179 fprintf (output_file
, "};\n\n");
7181 fprintf (output_file
, "static struct %s %s;\n\n", CHIP_NAME
, CHIP_NAME
);
7186 /* The function outputs translate vector of internal insn code into
7187 insn equivalence class number. The equivalence class number is
7188 used to access to table and vectors representing DFA(s). */
7190 output_translate_vect (automaton_t automaton
)
7194 vla_hwint_t translate_vect
;
7196 translate_vect
.create (description
->insns_num
);
7198 for (insn_value
= 0; insn_value
< description
->insns_num
; insn_value
++)
7199 /* Undefined value */
7200 translate_vect
.quick_push (automaton
->insn_equiv_classes_num
);
7202 for (ainsn
= automaton
->ainsn_list
; ainsn
!= NULL
; ainsn
= ainsn
->next_ainsn
)
7203 translate_vect
[ainsn
->insn_reserv_decl
->insn_num
] =
7204 ainsn
->insn_equiv_class_num
;
7206 fprintf (output_file
,
7207 "/* Vector translating external insn codes to internal ones.*/\n");
7208 fprintf (output_file
, "static const ");
7209 output_range_type (output_file
, 0, automaton
->insn_equiv_classes_num
);
7210 fprintf (output_file
, " ");
7211 output_translate_vect_name (output_file
, automaton
);
7212 fprintf (output_file
, "[] ATTRIBUTE_UNUSED = {\n");
7213 output_vect (translate_vect
);
7214 fprintf (output_file
, "};\n\n");
7215 translate_vect
.release ();
7218 /* The value in a table state x ainsn -> something which represents
7220 static int undefined_vect_el_value
;
7222 /* The following function returns nonzero value if the best
7223 representation of the table is comb vector. */
7225 comb_vect_p (state_ainsn_table_t tab
)
7229 return (2 * tab
->full_vect
.length () > 5 * tab
->comb_vect
.length ());
7232 /* The following function creates new table for AUTOMATON. */
7233 static state_ainsn_table_t
7234 create_state_ainsn_table (automaton_t automaton
)
7236 state_ainsn_table_t tab
;
7237 int full_vect_length
;
7240 tab
= XCREATENODE (struct state_ainsn_table
);
7241 tab
->automaton
= automaton
;
7243 tab
->comb_vect
.create (10000);
7244 tab
->check_vect
.create (10000);
7246 tab
->base_vect
.create (0);
7247 tab
->base_vect
.safe_grow (automaton
->achieved_states_num
, true);
7249 full_vect_length
= (automaton
->insn_equiv_classes_num
7250 * automaton
->achieved_states_num
);
7251 tab
->full_vect
.create (full_vect_length
);
7252 for (i
= 0; i
< full_vect_length
; i
++)
7253 tab
->full_vect
.quick_push (undefined_vect_el_value
);
7255 tab
->min_base_vect_el_value
= 0;
7256 tab
->max_base_vect_el_value
= 0;
7257 tab
->min_comb_vect_el_value
= 0;
7258 tab
->max_comb_vect_el_value
= 0;
7262 /* The following function outputs the best C representation of the
7263 table TAB of given TABLE_NAME. */
7265 output_state_ainsn_table (state_ainsn_table_t tab
, const char *table_name
,
7266 void (*output_full_vect_name_func
) (FILE *, automaton_t
),
7267 void (*output_comb_vect_name_func
) (FILE *, automaton_t
),
7268 void (*output_check_vect_name_func
) (FILE *, automaton_t
),
7269 void (*output_base_vect_name_func
) (FILE *, automaton_t
))
7271 if (!comb_vect_p (tab
))
7273 fprintf (output_file
, "/* Vector for %s. */\n", table_name
);
7274 fprintf (output_file
, "static const ");
7275 output_range_type (output_file
, tab
->min_comb_vect_el_value
,
7276 tab
->max_comb_vect_el_value
);
7277 fprintf (output_file
, " ");
7278 (*output_full_vect_name_func
) (output_file
, tab
->automaton
);
7279 fprintf (output_file
, "[] ATTRIBUTE_UNUSED = {\n");
7280 output_vect (tab
->full_vect
);
7281 fprintf (output_file
, "};\n\n");
7285 fprintf (output_file
, "/* Comb vector for %s. */\n", table_name
);
7286 fprintf (output_file
, "static const ");
7287 output_range_type (output_file
, tab
->min_comb_vect_el_value
,
7288 tab
->max_comb_vect_el_value
);
7289 fprintf (output_file
, " ");
7290 (*output_comb_vect_name_func
) (output_file
, tab
->automaton
);
7291 fprintf (output_file
, "[] ATTRIBUTE_UNUSED = {\n");
7292 output_vect (tab
->comb_vect
);
7293 fprintf (output_file
, "};\n\n");
7294 fprintf (output_file
, "/* Check vector for %s. */\n", table_name
);
7295 fprintf (output_file
, "static const ");
7296 output_range_type (output_file
, 0, tab
->automaton
->achieved_states_num
);
7297 fprintf (output_file
, " ");
7298 (*output_check_vect_name_func
) (output_file
, tab
->automaton
);
7299 fprintf (output_file
, "[] = {\n");
7300 output_vect (tab
->check_vect
);
7301 fprintf (output_file
, "};\n\n");
7302 fprintf (output_file
, "/* Base vector for %s. */\n", table_name
);
7303 fprintf (output_file
, "static const ");
7304 output_range_type (output_file
, tab
->min_base_vect_el_value
,
7305 tab
->max_base_vect_el_value
);
7306 fprintf (output_file
, " ");
7307 (*output_base_vect_name_func
) (output_file
, tab
->automaton
);
7308 fprintf (output_file
, "[] = {\n");
7309 output_vect (tab
->base_vect
);
7310 fprintf (output_file
, "};\n\n");
7314 /* The following function adds vector VECT to table TAB as its line
7315 with number VECT_NUM. */
7317 add_vect (state_ainsn_table_t tab
, int vect_num
, vla_hwint_t vect
)
7320 size_t real_vect_length
;
7321 int comb_vect_index
;
7322 int comb_vect_els_num
;
7324 int first_unempty_vect_index
;
7325 int additional_els_num
;
7329 unsigned long vect_mask
, comb_vect_mask
;
7331 vect_length
= vect
.length ();
7332 gcc_assert (vect_length
);
7333 gcc_assert (vect
.last () != undefined_vect_el_value
);
7334 real_vect_length
= tab
->automaton
->insn_equiv_classes_num
;
7335 /* Form full vector in the table: */
7337 size_t full_base
= tab
->automaton
->insn_equiv_classes_num
* vect_num
;
7338 if (tab
->full_vect
.length () < full_base
+ vect_length
)
7339 tab
->full_vect
.safe_grow (full_base
+ vect_length
, true);
7340 for (i
= 0; i
< vect_length
; i
++)
7341 tab
->full_vect
[full_base
+ i
] = vect
[i
];
7344 /* The comb_vect min/max values are also used for the full vector, so
7345 compute them now. */
7346 for (vect_index
= 0; vect_index
< vect_length
; vect_index
++)
7347 if (vect
[vect_index
] != undefined_vect_el_value
)
7349 vect_el_t x
= vect
[vect_index
];
7350 gcc_assert (x
>= 0);
7351 if (tab
->max_comb_vect_el_value
< x
)
7352 tab
->max_comb_vect_el_value
= x
;
7353 if (tab
->min_comb_vect_el_value
> x
)
7354 tab
->min_comb_vect_el_value
= x
;
7359 /* Form comb vector in the table: */
7360 gcc_assert (tab
->comb_vect
.length () == tab
->check_vect
.length ());
7362 comb_vect_els_num
= tab
->comb_vect
.length ();
7363 for (first_unempty_vect_index
= 0;
7364 first_unempty_vect_index
< vect_length
;
7365 first_unempty_vect_index
++)
7366 if (vect
[first_unempty_vect_index
]
7367 != undefined_vect_el_value
)
7370 /* Search for the place in comb vect for the inserted vect. */
7373 if (vect_length
- first_unempty_vect_index
>= SIZEOF_LONG
* CHAR_BIT
)
7375 for (comb_vect_index
= 0;
7376 comb_vect_index
< comb_vect_els_num
;
7379 for (vect_index
= first_unempty_vect_index
;
7380 vect_index
< vect_length
7381 && vect_index
+ comb_vect_index
< comb_vect_els_num
;
7383 if (vect
[vect_index
]
7384 != undefined_vect_el_value
7385 && (tab
->comb_vect
[vect_index
+ comb_vect_index
]
7386 != undefined_vect_el_value
))
7388 if (vect_index
>= vect_length
7389 || vect_index
+ comb_vect_index
>= comb_vect_els_num
)
7397 for (vect_index
= first_unempty_vect_index
;
7398 vect_index
< vect_length
;
7401 vect_mask
= vect_mask
<< 1;
7402 if (vect
[vect_index
] != undefined_vect_el_value
)
7406 /* Search for the place in comb vect for the inserted vect. */
7407 comb_vect_index
= 0;
7408 if (comb_vect_els_num
== 0)
7412 for (vect_index
= first_unempty_vect_index
;
7413 vect_index
< vect_length
&& vect_index
< comb_vect_els_num
;
7416 comb_vect_mask
<<= 1;
7417 if (vect_index
+ comb_vect_index
< comb_vect_els_num
7418 && tab
->comb_vect
[vect_index
+ comb_vect_index
]
7419 != undefined_vect_el_value
)
7420 comb_vect_mask
|= 1;
7422 if ((vect_mask
& comb_vect_mask
) == 0)
7425 for (comb_vect_index
= 1, i
= vect_length
; i
< comb_vect_els_num
;
7426 comb_vect_index
++, i
++)
7428 comb_vect_mask
= (comb_vect_mask
<< 1) | 1;
7429 comb_vect_mask
^= (tab
->comb_vect
[i
]
7430 == undefined_vect_el_value
);
7431 if ((vect_mask
& comb_vect_mask
) == 0)
7434 for ( ; comb_vect_index
< comb_vect_els_num
; comb_vect_index
++)
7436 comb_vect_mask
<<= 1;
7437 if ((vect_mask
& comb_vect_mask
) == 0)
7442 /* Slot was found. */
7443 additional_els_num
= comb_vect_index
+ real_vect_length
- comb_vect_els_num
;
7444 if (additional_els_num
< 0)
7445 additional_els_num
= 0;
7446 /* Expand comb and check vectors. */
7447 vect_el
= undefined_vect_el_value
;
7448 no_state_value
= tab
->automaton
->achieved_states_num
;
7449 while (additional_els_num
> 0)
7451 tab
->comb_vect
.safe_push (vect_el
);
7452 tab
->check_vect
.safe_push (no_state_value
);
7453 additional_els_num
--;
7455 gcc_assert (tab
->comb_vect
.length ()
7456 >= comb_vect_index
+ real_vect_length
);
7457 /* Fill comb and check vectors. */
7458 for (vect_index
= 0; vect_index
< vect_length
; vect_index
++)
7459 if (vect
[vect_index
] != undefined_vect_el_value
)
7461 vect_el_t x
= vect
[vect_index
];
7462 gcc_assert (tab
->comb_vect
[comb_vect_index
+ vect_index
]
7463 == undefined_vect_el_value
);
7464 gcc_assert (x
>= 0);
7465 tab
->comb_vect
[comb_vect_index
+ vect_index
] = x
;
7466 tab
->check_vect
[comb_vect_index
+ vect_index
] = vect_num
;
7468 if (tab
->max_comb_vect_el_value
< undefined_vect_el_value
)
7469 tab
->max_comb_vect_el_value
= undefined_vect_el_value
;
7470 if (tab
->min_comb_vect_el_value
> undefined_vect_el_value
)
7471 tab
->min_comb_vect_el_value
= undefined_vect_el_value
;
7472 if (tab
->max_base_vect_el_value
< comb_vect_index
)
7473 tab
->max_base_vect_el_value
= comb_vect_index
;
7474 if (tab
->min_base_vect_el_value
> comb_vect_index
)
7475 tab
->min_base_vect_el_value
= comb_vect_index
;
7477 tab
->base_vect
[vect_num
] = comb_vect_index
;
7480 /* Return number of out arcs of STATE. */
7482 out_state_arcs_num (const_state_t state
)
7488 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
7490 gcc_assert (arc
->insn
);
7491 if (arc
->insn
->first_ainsn_with_given_equivalence_num
)
7497 /* Compare number of possible transitions from the states. */
7499 compare_transition_els_num (const void *state_ptr_1
,
7500 const void *state_ptr_2
)
7502 const int transition_els_num_1
7503 = out_state_arcs_num (*(const_state_t
const*) state_ptr_1
);
7504 const int transition_els_num_2
7505 = out_state_arcs_num (*(const_state_t
const*) state_ptr_2
);
7507 if (transition_els_num_1
< transition_els_num_2
)
7509 else if (transition_els_num_1
== transition_els_num_2
)
7515 /* The function adds element EL_VALUE to vector VECT for a table state
7518 add_vect_el (vla_hwint_t
&vect
, ainsn_t ainsn
, int el_value
)
7520 int equiv_class_num
;
7524 equiv_class_num
= ainsn
->insn_equiv_class_num
;
7525 for (vect_index
= vect
.length ();
7526 vect_index
<= equiv_class_num
;
7528 vect
.safe_push (undefined_vect_el_value
);
7529 vect
[equiv_class_num
] = el_value
;
7532 /* This is for forming vector of states of an automaton. */
7533 static vec
<state_t
> output_states_vect
;
7535 /* The function is called by function pass_states. The function adds
7536 STATE to `output_states_vect'. */
7538 add_states_vect_el (state_t state
)
7540 output_states_vect
.safe_push (state
);
7543 /* Form and output vectors (comb, check, base or full vector)
7544 representing transition table of AUTOMATON. */
7546 output_trans_table (automaton_t automaton
)
7550 vla_hwint_t transition_vect
= vla_hwint_t ();
7552 undefined_vect_el_value
= automaton
->achieved_states_num
;
7553 automaton
->trans_table
= create_state_ainsn_table (automaton
);
7554 /* Create vect of pointers to states ordered by num of transitions
7555 from the state (state with the maximum num is the first). */
7556 output_states_vect
.create (0);
7557 pass_states (automaton
, add_states_vect_el
);
7558 output_states_vect
.qsort (compare_transition_els_num
);
7560 for (i
= 0; i
< output_states_vect
.length (); i
++)
7562 transition_vect
.truncate (0);
7563 for (arc
= first_out_arc (output_states_vect
[i
]);
7565 arc
= next_out_arc (arc
))
7567 gcc_assert (arc
->insn
);
7568 if (arc
->insn
->first_ainsn_with_given_equivalence_num
)
7569 add_vect_el (transition_vect
, arc
->insn
,
7570 arc
->to_state
->order_state_num
);
7572 add_vect (automaton
->trans_table
,
7573 output_states_vect
[i
]->order_state_num
,
7576 output_state_ainsn_table
7577 (automaton
->trans_table
, "state transitions",
7578 output_trans_full_vect_name
, output_trans_comb_vect_name
,
7579 output_trans_check_vect_name
, output_trans_base_vect_name
);
7581 output_states_vect
.release ();
7582 transition_vect
.release ();
7585 /* Form and output vectors representing minimal issue delay table of
7586 AUTOMATON. The table is state x ainsn -> minimal issue delay of
7589 output_min_issue_delay_table (automaton_t automaton
)
7591 vla_hwint_t min_issue_delay_vect
;
7592 vla_hwint_t compressed_min_issue_delay_vect
;
7595 size_t min_issue_delay_len
, compressed_min_issue_delay_len
;
7599 /* Create vect of pointers to states ordered by num of transitions
7600 from the state (state with the maximum num is the first). */
7601 output_states_vect
.create (0);
7602 pass_states (automaton
, add_states_vect_el
);
7604 min_issue_delay_len
= (output_states_vect
.length ()
7605 * automaton
->insn_equiv_classes_num
);
7606 min_issue_delay_vect
.create (min_issue_delay_len
);
7607 for (i
= 0; i
< min_issue_delay_len
; i
++)
7608 min_issue_delay_vect
.quick_push (-1);
7610 automaton
->max_min_delay
= 0;
7618 for (state_no
= 0; state_no
< output_states_vect
.length ();
7621 state_t s
= output_states_vect
[state_no
];
7624 for (arc
= first_out_arc (s
); arc
; arc
= next_out_arc (arc
))
7628 size_t asn
= s
->order_state_num
7629 * automaton
->insn_equiv_classes_num
7630 + arc
->insn
->insn_equiv_class_num
;
7632 if (min_issue_delay_vect
[asn
])
7634 min_issue_delay_vect
[asn
] = (vect_el_t
) 0;
7638 for (k
= 0; k
< automaton
->insn_equiv_classes_num
; k
++)
7641 vect_el_t delay0
, delay1
;
7643 n0
= s
->order_state_num
7644 * automaton
->insn_equiv_classes_num
7646 n1
= arc
->to_state
->order_state_num
7647 * automaton
->insn_equiv_classes_num
7649 delay0
= min_issue_delay_vect
[n0
];
7650 delay1
= min_issue_delay_vect
[n1
];
7653 if (arc
->insn
->insn_reserv_decl
7654 == DECL_INSN_RESERV (advance_cycle_insn_decl
))
7656 if (delay1
< delay0
|| delay0
== -1)
7658 min_issue_delay_vect
[n0
] = delay1
;
7668 automaton
->max_min_delay
= 0;
7670 for (ainsn
= automaton
->ainsn_list
; ainsn
; ainsn
= ainsn
->next_ainsn
)
7671 if (ainsn
->first_ainsn_with_given_equivalence_num
)
7673 for (i
= 0; i
< output_states_vect
.length (); i
++)
7675 state_t s
= output_states_vect
[i
];
7676 size_t np
= s
->order_state_num
7677 * automaton
->insn_equiv_classes_num
7678 + ainsn
->insn_equiv_class_num
;
7679 vect_el_t x
= min_issue_delay_vect
[np
];
7681 if (automaton
->max_min_delay
< x
)
7682 automaton
->max_min_delay
= x
;
7684 min_issue_delay_vect
[np
] = (vect_el_t
) 0;
7688 fprintf (output_file
, "/* Vector of min issue delay of insns. */\n");
7689 fprintf (output_file
, "static const ");
7690 output_range_type (output_file
, 0, automaton
->max_min_delay
);
7691 fprintf (output_file
, " ");
7692 output_min_issue_delay_vect_name (output_file
, automaton
);
7693 fprintf (output_file
, "[] ATTRIBUTE_UNUSED = {\n");
7694 /* Compress the vector. */
7695 if (automaton
->max_min_delay
< 2)
7697 else if (automaton
->max_min_delay
< 4)
7699 else if (automaton
->max_min_delay
< 16)
7703 automaton
->min_issue_delay_table_compression_factor
= cfactor
;
7705 compressed_min_issue_delay_len
= (min_issue_delay_len
+cfactor
-1) / cfactor
;
7706 compressed_min_issue_delay_vect
.create (compressed_min_issue_delay_len
);
7708 for (i
= 0; i
< compressed_min_issue_delay_len
; i
++)
7709 compressed_min_issue_delay_vect
.quick_push (0);
7711 for (i
= 0; i
< min_issue_delay_len
; i
++)
7713 size_t ci
= i
/ cfactor
;
7714 vect_el_t x
= min_issue_delay_vect
[i
];
7715 vect_el_t cx
= compressed_min_issue_delay_vect
[ci
];
7717 cx
|= x
<< (8 - (i
% cfactor
+ 1) * (8 / cfactor
));
7718 compressed_min_issue_delay_vect
[ci
] = cx
;
7720 output_vect (compressed_min_issue_delay_vect
);
7721 fprintf (output_file
, "};\n\n");
7722 output_states_vect
.release ();
7723 min_issue_delay_vect
.release ();
7724 compressed_min_issue_delay_vect
.release ();
7727 /* Form and output vector representing the locked states of
7730 output_dead_lock_vect (automaton_t automaton
)
7734 vla_hwint_t dead_lock_vect
= vla_hwint_t ();
7736 /* Create vect of pointers to states ordered by num of
7737 transitions from the state (state with the maximum num is the
7739 automaton
->locked_states
= 0;
7740 output_states_vect
.create (0);
7741 pass_states (automaton
, add_states_vect_el
);
7743 dead_lock_vect
.safe_grow (output_states_vect
.length (), true);
7744 for (i
= 0; i
< output_states_vect
.length (); i
++)
7746 state_t s
= output_states_vect
[i
];
7747 arc
= first_out_arc (s
);
7749 if (next_out_arc (arc
) == NULL
7750 && (arc
->insn
->insn_reserv_decl
7751 == DECL_INSN_RESERV (advance_cycle_insn_decl
)))
7753 dead_lock_vect
[s
->order_state_num
] = 1;
7754 automaton
->locked_states
++;
7757 dead_lock_vect
[s
->order_state_num
] = (vect_el_t
) 0;
7759 if (automaton
->locked_states
== 0)
7762 fprintf (output_file
, "/* Vector for locked state flags. */\n");
7763 fprintf (output_file
, "static const ");
7764 output_range_type (output_file
, 0, 1);
7765 fprintf (output_file
, " ");
7766 output_dead_lock_vect_name (output_file
, automaton
);
7767 fprintf (output_file
, "[] = {\n");
7768 output_vect (dead_lock_vect
);
7769 fprintf (output_file
, "};\n\n");
7770 output_states_vect
.release ();
7771 dead_lock_vect
.release ();
7774 /* Form and output vector representing reserved units of the states of
7777 output_reserved_units_table (automaton_t automaton
)
7779 vla_hwint_t reserved_units_table
= vla_hwint_t ();
7780 int state_byte_size
;
7781 int reserved_units_size
;
7785 if (description
->query_units_num
== 0)
7788 /* Create vect of pointers to states. */
7789 output_states_vect
.create (0);
7790 pass_states (automaton
, add_states_vect_el
);
7791 /* Create vector. */
7792 state_byte_size
= (description
->query_units_num
+ 7) / 8;
7793 reserved_units_size
= (output_states_vect
.length ()
7796 reserved_units_table
.create (reserved_units_size
);
7798 for (i
= 0; i
< reserved_units_size
; i
++)
7799 reserved_units_table
.quick_push (0);
7800 for (n
= 0; n
< output_states_vect
.length (); n
++)
7802 state_t s
= output_states_vect
[n
];
7803 for (i
= 0; i
< description
->units_num
; i
++)
7804 if (units_array
[i
]->query_p
7805 && first_cycle_unit_presence (s
, i
))
7807 int ri
= (s
->order_state_num
* state_byte_size
7808 + units_array
[i
]->query_num
/ 8);
7809 vect_el_t x
= reserved_units_table
[ri
];
7811 x
+= 1 << (units_array
[i
]->query_num
% 8);
7812 reserved_units_table
[ri
] = x
;
7815 fprintf (output_file
, "\n#if %s\n", CPU_UNITS_QUERY_MACRO_NAME
);
7816 fprintf (output_file
, "/* Vector for reserved units of states. */\n");
7817 fprintf (output_file
, "static const ");
7818 output_range_type (output_file
, 0, 255);
7819 fprintf (output_file
, " ");
7820 output_reserved_units_table_name (output_file
, automaton
);
7821 fprintf (output_file
, "[] = {\n");
7822 output_vect (reserved_units_table
);
7823 fprintf (output_file
, "};\n#endif /* #if %s */\n\n",
7824 CPU_UNITS_QUERY_MACRO_NAME
);
7826 output_states_vect
.release ();
7827 reserved_units_table
.release ();
7830 /* The function outputs all tables representing DFA(s) used for fast
7831 pipeline hazards recognition. */
7833 output_tables (void)
7835 automaton_t automaton
;
7837 for (automaton
= description
->first_automaton
;
7839 automaton
= automaton
->next_automaton
)
7841 output_translate_vect (automaton
);
7842 output_trans_table (automaton
);
7843 output_min_issue_delay_table (automaton
);
7844 output_dead_lock_vect (automaton
);
7845 output_reserved_units_table (automaton
);
7847 fprintf (output_file
, "\n#define %s %d\n\n", ADVANCE_CYCLE_VALUE_NAME
,
7848 DECL_INSN_RESERV (advance_cycle_insn_decl
)->insn_num
);
7850 fprintf (output_file
, "\n#define %s %d\n\n", COLLAPSE_NDFA_VALUE_NAME
,
7851 DECL_INSN_RESERV (collapse_ndfa_insn_decl
)->insn_num
);
7854 /* The function outputs definition and value of PHR interface variable
7855 `max_insn_queue_index'. Its value is not less than maximal queue
7856 length needed for the insn scheduler. */
7858 output_max_insn_queue_index_def (void)
7860 int i
, max
, latency
;
7863 max
= description
->max_insn_reserv_cycles
;
7864 for (i
= 0; i
< description
->decls_num
; i
++)
7866 decl
= description
->decls
[i
];
7867 if (decl
->mode
== dm_insn_reserv
&& decl
!= advance_cycle_insn_decl
)
7869 latency
= DECL_INSN_RESERV (decl
)->default_latency
;
7873 else if (decl
->mode
== dm_bypass
)
7875 latency
= DECL_BYPASS (decl
)->latency
;
7880 for (i
= 0; (1 << i
) <= max
; i
++)
7882 gcc_assert (i
>= 0);
7883 fprintf (output_file
, "\nconst int max_insn_queue_index = %d;\n\n",
7887 /* The function outputs switch cases for insn reservations using
7888 function *output_automata_list_code. */
7890 output_insn_code_cases (void (*output_automata_list_code
)
7891 (automata_list_el_t
))
7896 for (i
= 0; i
< description
->decls_num
; i
++)
7898 decl
= description
->decls
[i
];
7899 if (decl
->mode
== dm_insn_reserv
)
7900 DECL_INSN_RESERV (decl
)->processed_p
= false;
7902 for (i
= 0; i
< description
->decls_num
; i
++)
7904 decl
= description
->decls
[i
];
7905 if (decl
->mode
== dm_insn_reserv
7906 && !DECL_INSN_RESERV (decl
)->processed_p
)
7908 for (j
= i
; j
< description
->decls_num
; j
++)
7910 decl2
= description
->decls
[j
];
7911 if (decl2
->mode
== dm_insn_reserv
7912 && (DECL_INSN_RESERV (decl2
)->important_automata_list
7913 == DECL_INSN_RESERV (decl
)->important_automata_list
))
7915 DECL_INSN_RESERV (decl2
)->processed_p
= true;
7916 fprintf (output_file
, " case %d: /* %s */\n",
7917 DECL_INSN_RESERV (decl2
)->insn_num
,
7918 DECL_INSN_RESERV (decl2
)->name
);
7921 (*output_automata_list_code
)
7922 (DECL_INSN_RESERV (decl
)->important_automata_list
);
7928 /* The function outputs a code for evaluation of a minimal delay of
7929 issue of insns which have reservations in given AUTOMATA_LIST. */
7931 output_automata_list_min_issue_delay_code (automata_list_el_t automata_list
)
7933 automata_list_el_t el
;
7934 automaton_t automaton
;
7936 for (el
= automata_list
; el
!= NULL
; el
= el
->next_automata_list_el
)
7938 automaton
= el
->automaton
;
7939 fprintf (output_file
, "\n %s = ", TEMPORARY_VARIABLE_NAME
);
7940 output_min_issue_delay_vect_name (output_file
, automaton
);
7941 fprintf (output_file
,
7942 (automaton
->min_issue_delay_table_compression_factor
!= 1
7944 output_translate_vect_name (output_file
, automaton
);
7945 fprintf (output_file
, " [%s] + ", INTERNAL_INSN_CODE_NAME
);
7946 fprintf (output_file
, "%s->", CHIP_PARAMETER_NAME
);
7947 output_chip_member_name (output_file
, automaton
);
7948 fprintf (output_file
, " * %d", automaton
->insn_equiv_classes_num
);
7949 if (automaton
->min_issue_delay_table_compression_factor
== 1)
7950 fprintf (output_file
, "];\n");
7953 fprintf (output_file
, ") / %d];\n",
7954 automaton
->min_issue_delay_table_compression_factor
);
7955 fprintf (output_file
, " %s = (%s >> (8 - ((",
7956 TEMPORARY_VARIABLE_NAME
, TEMPORARY_VARIABLE_NAME
);
7957 output_translate_vect_name (output_file
, automaton
);
7958 fprintf (output_file
, " [%s] + ", INTERNAL_INSN_CODE_NAME
);
7959 fprintf (output_file
, "%s->", CHIP_PARAMETER_NAME
);
7960 output_chip_member_name (output_file
, automaton
);
7961 fprintf (output_file
, " * %d)", automaton
->insn_equiv_classes_num
);
7963 (output_file
, " %% %d + 1) * %d)) & %d;\n",
7964 automaton
->min_issue_delay_table_compression_factor
,
7965 8 / automaton
->min_issue_delay_table_compression_factor
,
7966 (1 << (8 / automaton
->min_issue_delay_table_compression_factor
))
7969 if (el
== automata_list
)
7970 fprintf (output_file
, " %s = %s;\n",
7971 RESULT_VARIABLE_NAME
, TEMPORARY_VARIABLE_NAME
);
7974 fprintf (output_file
, " if (%s > %s)\n",
7975 TEMPORARY_VARIABLE_NAME
, RESULT_VARIABLE_NAME
);
7976 fprintf (output_file
, " %s = %s;\n",
7977 RESULT_VARIABLE_NAME
, TEMPORARY_VARIABLE_NAME
);
7980 fprintf (output_file
, " break;\n\n");
7983 /* Output function `internal_min_issue_delay'. */
7985 output_internal_min_issue_delay_func (void)
7987 fprintf (output_file
,
7988 "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
7989 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
7990 CHIP_NAME
, CHIP_PARAMETER_NAME
);
7991 fprintf (output_file
, "{\n int %s ATTRIBUTE_UNUSED;\n int %s = -1;\n",
7992 TEMPORARY_VARIABLE_NAME
, RESULT_VARIABLE_NAME
);
7993 fprintf (output_file
, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME
);
7994 output_insn_code_cases (output_automata_list_min_issue_delay_code
);
7995 fprintf (output_file
,
7996 "\n default:\n %s = -1;\n break;\n }\n",
7997 RESULT_VARIABLE_NAME
);
7998 fprintf (output_file
, " return %s;\n", RESULT_VARIABLE_NAME
);
7999 fprintf (output_file
, "}\n\n");
8002 /* The function outputs a code changing state after issue of insns
8003 which have reservations in given AUTOMATA_LIST. */
8005 output_automata_list_transition_code (automata_list_el_t automata_list
)
8007 automata_list_el_t el
, next_el
;
8009 fprintf (output_file
, " {\n");
8010 if (automata_list
!= NULL
&& automata_list
->next_automata_list_el
!= NULL
)
8011 for (el
= automata_list
;; el
= next_el
)
8013 next_el
= el
->next_automata_list_el
;
8014 if (next_el
== NULL
)
8016 fprintf (output_file
, " ");
8017 output_state_member_type (output_file
, el
->automaton
);
8018 fprintf (output_file
, " ");
8019 output_temp_chip_member_name (output_file
, el
->automaton
);
8020 fprintf (output_file
, ";\n");
8022 for (el
= automata_list
; el
!= NULL
; el
= el
->next_automata_list_el
)
8023 if (comb_vect_p (el
->automaton
->trans_table
))
8025 fprintf (output_file
, "\n %s = ", TEMPORARY_VARIABLE_NAME
);
8026 output_trans_base_vect_name (output_file
, el
->automaton
);
8027 fprintf (output_file
, " [%s->", CHIP_PARAMETER_NAME
);
8028 output_chip_member_name (output_file
, el
->automaton
);
8029 fprintf (output_file
, "] + ");
8030 output_translate_vect_name (output_file
, el
->automaton
);
8031 fprintf (output_file
, " [%s];\n", INTERNAL_INSN_CODE_NAME
);
8032 fprintf (output_file
, " if (");
8033 output_trans_check_vect_name (output_file
, el
->automaton
);
8034 fprintf (output_file
, " [%s] != %s->",
8035 TEMPORARY_VARIABLE_NAME
, CHIP_PARAMETER_NAME
);
8036 output_chip_member_name (output_file
, el
->automaton
);
8037 fprintf (output_file
, ")\n");
8038 fprintf (output_file
, " return %s (%s, %s);\n",
8039 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
8040 CHIP_PARAMETER_NAME
);
8041 fprintf (output_file
, " else\n");
8042 fprintf (output_file
, " ");
8043 if (el
->next_automata_list_el
!= NULL
)
8044 output_temp_chip_member_name (output_file
, el
->automaton
);
8047 fprintf (output_file
, "%s->", CHIP_PARAMETER_NAME
);
8048 output_chip_member_name (output_file
, el
->automaton
);
8050 fprintf (output_file
, " = ");
8051 output_trans_comb_vect_name (output_file
, el
->automaton
);
8052 fprintf (output_file
, " [%s];\n", TEMPORARY_VARIABLE_NAME
);
8056 fprintf (output_file
, "\n %s = ", TEMPORARY_VARIABLE_NAME
);
8057 output_trans_full_vect_name (output_file
, el
->automaton
);
8058 fprintf (output_file
, " [");
8059 output_translate_vect_name (output_file
, el
->automaton
);
8060 fprintf (output_file
, " [%s] + ", INTERNAL_INSN_CODE_NAME
);
8061 fprintf (output_file
, "%s->", CHIP_PARAMETER_NAME
);
8062 output_chip_member_name (output_file
, el
->automaton
);
8063 fprintf (output_file
, " * %d];\n",
8064 el
->automaton
->insn_equiv_classes_num
);
8065 fprintf (output_file
, " if (%s >= %d)\n",
8066 TEMPORARY_VARIABLE_NAME
, el
->automaton
->achieved_states_num
);
8067 fprintf (output_file
, " return %s (%s, %s);\n",
8068 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
8069 CHIP_PARAMETER_NAME
);
8070 fprintf (output_file
, " else\n ");
8071 if (el
->next_automata_list_el
!= NULL
)
8072 output_temp_chip_member_name (output_file
, el
->automaton
);
8075 fprintf (output_file
, "%s->", CHIP_PARAMETER_NAME
);
8076 output_chip_member_name (output_file
, el
->automaton
);
8078 fprintf (output_file
, " = %s;\n", TEMPORARY_VARIABLE_NAME
);
8080 if (automata_list
!= NULL
&& automata_list
->next_automata_list_el
!= NULL
)
8081 for (el
= automata_list
;; el
= next_el
)
8083 next_el
= el
->next_automata_list_el
;
8084 if (next_el
== NULL
)
8086 fprintf (output_file
, " %s->", CHIP_PARAMETER_NAME
);
8087 output_chip_member_name (output_file
, el
->automaton
);
8088 fprintf (output_file
, " = ");
8089 output_temp_chip_member_name (output_file
, el
->automaton
);
8090 fprintf (output_file
, ";\n");
8092 fprintf (output_file
, " return -1;\n");
8093 fprintf (output_file
, " }\n");
8096 /* Output function `internal_state_transition'. */
8098 output_internal_trans_func (void)
8100 fprintf (output_file
,
8101 "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
8102 INTERNAL_TRANSITION_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
8103 CHIP_NAME
, CHIP_PARAMETER_NAME
);
8104 fprintf (output_file
, "{\n int %s ATTRIBUTE_UNUSED;\n", TEMPORARY_VARIABLE_NAME
);
8105 fprintf (output_file
, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME
);
8106 output_insn_code_cases (output_automata_list_transition_code
);
8107 fprintf (output_file
, "\n default:\n return -1;\n }\n");
8108 fprintf (output_file
, "}\n\n");
8113 gcc_checking_assert (insn != 0);
8114 insn_code = dfa_insn_code (insn);
8115 if (insn_code >= DFA__ADVANCE_CYCLE)
8118 where insn denotes INSN_NAME, insn_code denotes INSN_CODE_NAME, and
8119 code denotes CODE. */
8121 output_internal_insn_code_evaluation (const char *insn_name
,
8122 const char *insn_code_name
,
8125 fprintf (output_file
, " gcc_checking_assert (%s != 0);\n"
8127 " if (%s >= %s)\n return %d;\n",
8129 insn_code_name
, DFA_INSN_CODE_FUNC_NAME
, insn_name
,
8130 insn_code_name
, ADVANCE_CYCLE_VALUE_NAME
, code
);
8134 /* This function outputs `dfa_insn_code' and its helper function
8135 `dfa_insn_code_enlarge'. */
8137 output_dfa_insn_code_func (void)
8139 /* Emacs c-mode gets really confused if there's a { or } in column 0
8140 inside a string, so don't do that. */
8141 fprintf (output_file
, "\
8143 dfa_insn_code_enlarge (int uid)\n\
8147 %s = XRESIZEVEC (int, %s,\n\
8149 for (; i < %s; i++)\n\
8150 %s[i] = -1;\n}\n\n",
8151 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
,
8152 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
,
8153 DFA_INSN_CODES_VARIABLE_NAME
, DFA_INSN_CODES_VARIABLE_NAME
,
8154 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
,
8155 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
,
8156 DFA_INSN_CODES_VARIABLE_NAME
);
8157 fprintf (output_file
, "\
8158 static inline int\n%s (rtx_insn *%s)\n\
8160 int uid = INSN_UID (%s);\n\
8162 DFA_INSN_CODE_FUNC_NAME
, INSN_PARAMETER_NAME
,
8163 INSN_PARAMETER_NAME
, INTERNAL_INSN_CODE_NAME
);
8165 fprintf (output_file
,
8166 " if (uid >= %s)\n dfa_insn_code_enlarge (uid);\n\n",
8167 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
);
8168 fprintf (output_file
, " %s = %s[uid];\n",
8169 INTERNAL_INSN_CODE_NAME
, DFA_INSN_CODES_VARIABLE_NAME
);
8170 fprintf (output_file
, "\
8176 INTERNAL_INSN_CODE_NAME
,
8177 INTERNAL_INSN_CODE_NAME
,
8178 INTERNAL_DFA_INSN_CODE_FUNC_NAME
, INSN_PARAMETER_NAME
,
8179 DFA_INSN_CODES_VARIABLE_NAME
, INTERNAL_INSN_CODE_NAME
);
8180 fprintf (output_file
, " return %s;\n}\n\n", INTERNAL_INSN_CODE_NAME
);
8183 /* The function outputs PHR interface function `state_transition'. */
8185 output_trans_func (void)
8187 fprintf (output_file
, "int\n%s (%s %s, rtx %s)\n",
8188 TRANSITION_FUNC_NAME
, STATE_TYPE_NAME
, STATE_NAME
,
8189 INSN_PARAMETER_NAME
);
8190 fprintf (output_file
, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME
);
8191 fprintf (output_file
, "\n if (%s == 0)\n", INSN_PARAMETER_NAME
);
8192 fprintf (output_file
, " %s = %s;\n",
8193 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
8196 fprintf (output_file
, " else if (%s == const0_rtx)\n",
8197 INSN_PARAMETER_NAME
);
8198 fprintf (output_file
, " %s = %s;\n",
8199 INTERNAL_INSN_CODE_NAME
, COLLAPSE_NDFA_VALUE_NAME
);
8201 fprintf (output_file
, " else\n {\n");
8202 fprintf (output_file
, " %s = %s (as_a <rtx_insn *> (%s));\n",
8203 INTERNAL_INSN_CODE_NAME
, DFA_INSN_CODE_FUNC_NAME
,
8204 INSN_PARAMETER_NAME
);
8205 fprintf (output_file
, " if (%s > %s)\n return -1;\n }\n",
8206 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
8207 fprintf (output_file
, " return %s (%s, (struct %s *) %s);\n}\n\n",
8208 INTERNAL_TRANSITION_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
, CHIP_NAME
, STATE_NAME
);
8211 /* Output function `min_issue_delay'. */
8213 output_min_issue_delay_func (void)
8215 fprintf (output_file
, "int\n%s (%s %s, rtx_insn *%s)\n",
8216 MIN_ISSUE_DELAY_FUNC_NAME
, STATE_TYPE_NAME
, STATE_NAME
,
8217 INSN_PARAMETER_NAME
);
8218 fprintf (output_file
, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME
);
8219 fprintf (output_file
, "\n if (%s != 0)\n {\n", INSN_PARAMETER_NAME
);
8220 fprintf (output_file
, " %s = %s (%s);\n", INTERNAL_INSN_CODE_NAME
,
8221 DFA_INSN_CODE_FUNC_NAME
, INSN_PARAMETER_NAME
);
8222 fprintf (output_file
, " if (%s > %s)\n return 0;\n",
8223 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
8224 fprintf (output_file
, " }\n else\n %s = %s;\n",
8225 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
8226 fprintf (output_file
, "\n return %s (%s, (struct %s *) %s);\n",
8227 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
8228 CHIP_NAME
, STATE_NAME
);
8229 fprintf (output_file
, "}\n\n");
8232 /* Output function `internal_dead_lock'. */
8234 output_internal_dead_lock_func (void)
8236 automaton_t automaton
;
8238 fprintf (output_file
, "static int\n%s (struct %s *ARG_UNUSED (%s))\n",
8239 INTERNAL_DEAD_LOCK_FUNC_NAME
, CHIP_NAME
, CHIP_PARAMETER_NAME
);
8240 fprintf (output_file
, "{\n");
8241 for (automaton
= description
->first_automaton
;
8243 automaton
= automaton
->next_automaton
)
8244 if (automaton
->locked_states
)
8246 fprintf (output_file
, " if (");
8247 output_dead_lock_vect_name (output_file
, automaton
);
8248 fprintf (output_file
, " [%s->", CHIP_PARAMETER_NAME
);
8249 output_chip_member_name (output_file
, automaton
);
8250 fprintf (output_file
, "])\n return 1 /* TRUE */;\n");
8252 fprintf (output_file
, " return 0 /* FALSE */;\n}\n\n");
8255 /* The function outputs PHR interface function `state_dead_lock_p'. */
8257 output_dead_lock_func (void)
8259 fprintf (output_file
, "int\n%s (%s %s)\n",
8260 DEAD_LOCK_FUNC_NAME
, STATE_TYPE_NAME
, STATE_NAME
);
8261 fprintf (output_file
, "{\n return %s ((struct %s *) %s);\n}\n\n",
8262 INTERNAL_DEAD_LOCK_FUNC_NAME
, CHIP_NAME
, STATE_NAME
);
8265 /* Output function `internal_reset'. */
8267 output_internal_reset_func (void)
8269 fprintf (output_file
, "static inline void\n%s (struct %s *%s)\n",
8270 INTERNAL_RESET_FUNC_NAME
, CHIP_NAME
, CHIP_PARAMETER_NAME
);
8271 fprintf (output_file
, "{\n memset (%s, 0, sizeof (struct %s));\n}\n\n",
8272 CHIP_PARAMETER_NAME
, CHIP_NAME
);
8275 /* The function outputs PHR interface function `state_size'. */
8277 output_size_func (void)
8279 fprintf (output_file
, "int\n%s (void)\n", SIZE_FUNC_NAME
);
8280 fprintf (output_file
, "{\n return sizeof (struct %s);\n}\n\n", CHIP_NAME
);
8283 /* The function outputs PHR interface function `state_reset'. */
8285 output_reset_func (void)
8287 fprintf (output_file
, "void\n%s (%s %s)\n",
8288 RESET_FUNC_NAME
, STATE_TYPE_NAME
, STATE_NAME
);
8289 fprintf (output_file
, "{\n %s ((struct %s *) %s);\n}\n\n", INTERNAL_RESET_FUNC_NAME
,
8290 CHIP_NAME
, STATE_NAME
);
8293 /* Output function `min_insn_conflict_delay'. */
8295 output_min_insn_conflict_delay_func (void)
8297 fprintf (output_file
,
8298 "int\n%s (%s %s, rtx_insn *%s, rtx_insn *%s)\n",
8299 MIN_INSN_CONFLICT_DELAY_FUNC_NAME
, STATE_TYPE_NAME
,
8300 STATE_NAME
, INSN_PARAMETER_NAME
, INSN2_PARAMETER_NAME
);
8301 fprintf (output_file
, "{\n struct %s %s;\n int %s, %s, transition;\n",
8302 CHIP_NAME
, CHIP_NAME
, INTERNAL_INSN_CODE_NAME
,
8303 INTERNAL_INSN2_CODE_NAME
);
8304 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME
,
8305 INTERNAL_INSN_CODE_NAME
, 0);
8306 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME
,
8307 INTERNAL_INSN2_CODE_NAME
, 0);
8308 fprintf (output_file
, " memcpy (&%s, %s, sizeof (%s));\n",
8309 CHIP_NAME
, STATE_NAME
, CHIP_NAME
);
8310 fprintf (output_file
, " %s (&%s);\n", INTERNAL_RESET_FUNC_NAME
, CHIP_NAME
);
8311 fprintf (output_file
, " transition = %s (%s, &%s);\n",
8312 INTERNAL_TRANSITION_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
, CHIP_NAME
);
8313 fprintf (output_file
, " gcc_assert (transition <= 0);\n");
8314 fprintf (output_file
, " return %s (%s, &%s);\n",
8315 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME
, INTERNAL_INSN2_CODE_NAME
,
8317 fprintf (output_file
, "}\n\n");
8320 /* Output the array holding default latency values. These are used in
8321 insn_latency and maximal_insn_latency function implementations. */
8323 output_default_latencies (void)
8327 const char *tabletype
= "unsigned char";
8329 /* Find the smallest integer type that can hold all the default
8331 for (i
= 0; i
< description
->decls_num
; i
++)
8332 if (description
->decls
[i
]->mode
== dm_insn_reserv
)
8334 decl
= description
->decls
[i
];
8335 if (DECL_INSN_RESERV (decl
)->default_latency
> UCHAR_MAX
8336 && tabletype
[0] != 'i') /* Don't shrink it. */
8337 tabletype
= "unsigned short";
8338 if (DECL_INSN_RESERV (decl
)->default_latency
> USHRT_MAX
)
8342 fprintf (output_file
, " static const %s default_latencies[] =\n {",
8345 for (i
= 0, j
= 0, col
= 7; i
< description
->normal_decls_num
; i
++)
8346 if (description
->decls
[i
]->mode
== dm_insn_reserv
)
8348 if ((col
= (col
+1) % 8) == 0)
8349 fputs ("\n ", output_file
);
8350 decl
= description
->decls
[i
];
8351 gcc_assert (j
++ == DECL_INSN_RESERV (decl
)->insn_num
);
8352 fprintf (output_file
, "% 4d,",
8353 DECL_INSN_RESERV (decl
)->default_latency
);
8355 gcc_assert (j
== description
->insns_num
- (collapse_flag
? 2 : 1));
8356 fputs ("\n };\n", output_file
);
8359 /* Output function `internal_insn_latency'. */
8361 output_internal_insn_latency_func (void)
8365 struct bypass_decl
*bypass
;
8367 fprintf (output_file
, "static int\n"
8368 "%s (int %s ATTRIBUTE_UNUSED, int %s ATTRIBUTE_UNUSED,\n"
8369 "\trtx_insn *%s ATTRIBUTE_UNUSED, rtx_insn *%s ATTRIBUTE_UNUSED)\n",
8370 INTERNAL_INSN_LATENCY_FUNC_NAME
,
8371 INTERNAL_INSN_CODE_NAME
, INTERNAL_INSN2_CODE_NAME
,
8372 INSN_PARAMETER_NAME
, INSN2_PARAMETER_NAME
);
8373 fprintf (output_file
, "{\n");
8375 if (DECL_INSN_RESERV (advance_cycle_insn_decl
)->insn_num
== 0)
8377 fputs (" return 0;\n}\n\n", output_file
);
8381 fprintf (output_file
, " switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME
);
8382 for (i
= 0; i
< description
->decls_num
; i
++)
8383 if (description
->decls
[i
]->mode
== dm_insn_reserv
8384 && DECL_INSN_RESERV (description
->decls
[i
])->bypass_list
)
8386 decl
= description
->decls
[i
];
8387 fprintf (output_file
,
8388 " case %d:\n switch (%s)\n {\n",
8389 DECL_INSN_RESERV (decl
)->insn_num
,
8390 INTERNAL_INSN2_CODE_NAME
);
8391 for (bypass
= DECL_INSN_RESERV (decl
)->bypass_list
;
8393 bypass
= bypass
->next
)
8395 gcc_assert (bypass
->in_insn_reserv
->insn_num
8396 != (DECL_INSN_RESERV
8397 (advance_cycle_insn_decl
)->insn_num
));
8398 fprintf (output_file
, " case %d:\n",
8399 bypass
->in_insn_reserv
->insn_num
);
8402 if (bypass
->bypass_guard_name
== NULL
)
8404 gcc_assert (bypass
->next
== NULL
8405 || (bypass
->in_insn_reserv
8406 != bypass
->next
->in_insn_reserv
));
8407 fprintf (output_file
, " return %d;\n",
8412 fprintf (output_file
,
8413 " if (%s (%s, %s))\n",
8414 bypass
->bypass_guard_name
, INSN_PARAMETER_NAME
,
8415 INSN2_PARAMETER_NAME
);
8416 fprintf (output_file
, " return %d;\n",
8419 if (bypass
->next
== NULL
8420 || bypass
->in_insn_reserv
!= bypass
->next
->in_insn_reserv
)
8422 bypass
= bypass
->next
;
8424 if (bypass
->bypass_guard_name
!= NULL
)
8425 fprintf (output_file
, " break;\n");
8427 fputs (" }\n break;\n", output_file
);
8430 fprintf (output_file
, " }\n return default_latencies[%s];\n}\n\n",
8431 INTERNAL_INSN_CODE_NAME
);
8434 /* Output function `internal_maximum_insn_latency'. */
8436 output_internal_maximal_insn_latency_func (void)
8439 struct bypass_decl
*bypass
;
8443 fprintf (output_file
, "static int\n%s (int %s ATTRIBUTE_UNUSED)\n",
8444 "internal_maximal_insn_latency", INTERNAL_INSN_CODE_NAME
);
8445 fprintf (output_file
, "{\n");
8447 if (DECL_INSN_RESERV (advance_cycle_insn_decl
)->insn_num
== 0)
8449 fputs (" return 0;\n}\n\n", output_file
);
8453 fprintf (output_file
, " switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME
);
8454 for (i
= 0; i
< description
->decls_num
; i
++)
8455 if (description
->decls
[i
]->mode
== dm_insn_reserv
8456 && DECL_INSN_RESERV (description
->decls
[i
])->bypass_list
)
8458 decl
= description
->decls
[i
];
8459 max
= DECL_INSN_RESERV (decl
)->default_latency
;
8460 fprintf (output_file
,
8462 DECL_INSN_RESERV (decl
)->insn_num
);
8463 for (bypass
= DECL_INSN_RESERV (decl
)->bypass_list
;
8465 bypass
= bypass
->next
)
8467 if (bypass
->latency
> max
)
8468 max
= bypass
->latency
;
8470 fprintf (output_file
, " return %d; }\n break;\n", max
);
8473 fprintf (output_file
, " }\n return default_latencies[%s];\n}\n\n",
8474 INTERNAL_INSN_CODE_NAME
);
8477 /* The function outputs PHR interface function `insn_latency'. */
8479 output_insn_latency_func (void)
8481 fprintf (output_file
, "int\n%s (rtx_insn *%s, rtx_insn *%s)\n",
8482 INSN_LATENCY_FUNC_NAME
, INSN_PARAMETER_NAME
, INSN2_PARAMETER_NAME
);
8483 fprintf (output_file
, "{\n int %s, %s;\n",
8484 INTERNAL_INSN_CODE_NAME
, INTERNAL_INSN2_CODE_NAME
);
8485 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME
,
8486 INTERNAL_INSN_CODE_NAME
, 0);
8487 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME
,
8488 INTERNAL_INSN2_CODE_NAME
, 0);
8489 fprintf (output_file
, " return %s (%s, %s, %s, %s);\n}\n\n",
8490 INTERNAL_INSN_LATENCY_FUNC_NAME
,
8491 INTERNAL_INSN_CODE_NAME
, INTERNAL_INSN2_CODE_NAME
,
8492 INSN_PARAMETER_NAME
, INSN2_PARAMETER_NAME
);
8495 /* The function outputs PHR interface function `maximal_insn_latency'. */
8497 output_maximal_insn_latency_func (void)
8499 fprintf (output_file
, "int\n%s (rtx_insn *%s)\n",
8500 "maximal_insn_latency", INSN_PARAMETER_NAME
);
8501 fprintf (output_file
, "{\n int %s;\n",
8502 INTERNAL_INSN_CODE_NAME
);
8503 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME
,
8504 INTERNAL_INSN_CODE_NAME
, 0);
8505 fprintf (output_file
, " return %s (%s);\n}\n\n",
8506 "internal_maximal_insn_latency", INTERNAL_INSN_CODE_NAME
);
8509 /* The function outputs PHR interface function `print_reservation'. */
8511 output_print_reservation_func (void)
8516 fprintf (output_file
,
8517 "void\n%s (FILE *%s, rtx_insn *%s ATTRIBUTE_UNUSED)\n{\n",
8518 PRINT_RESERVATION_FUNC_NAME
, FILE_PARAMETER_NAME
,
8519 INSN_PARAMETER_NAME
);
8521 if (DECL_INSN_RESERV (advance_cycle_insn_decl
)->insn_num
== 0)
8523 fprintf (output_file
, " fputs (\"%s\", %s);\n}\n\n",
8524 NOTHING_NAME
, FILE_PARAMETER_NAME
);
8529 fputs (" static const char *const reservation_names[] =\n {",
8532 for (i
= 0, j
= 0; i
< description
->normal_decls_num
; i
++)
8534 decl
= description
->decls
[i
];
8535 if (decl
->mode
== dm_insn_reserv
)
8537 gcc_assert (j
== DECL_INSN_RESERV (decl
)->insn_num
);
8540 fprintf (output_file
, "\n \"%s\",",
8541 regexp_representation (DECL_INSN_RESERV (decl
)->regexp
));
8542 finish_regexp_representation ();
8545 gcc_assert (j
== description
->insns_num
- (collapse_flag
? 2 : 1));
8547 fprintf (output_file
, "\n \"%s\"\n };\n int %s;\n\n",
8548 NOTHING_NAME
, INTERNAL_INSN_CODE_NAME
);
8550 fprintf (output_file
, " if (%s == 0)\n %s = %s;\n",
8551 INSN_PARAMETER_NAME
,
8552 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
8553 fprintf (output_file
, " else\n\
8559 INTERNAL_INSN_CODE_NAME
, DFA_INSN_CODE_FUNC_NAME
,
8560 INSN_PARAMETER_NAME
,
8561 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
,
8562 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
8564 fprintf (output_file
, " fputs (reservation_names[%s], %s);\n}\n\n",
8565 INTERNAL_INSN_CODE_NAME
, FILE_PARAMETER_NAME
);
8568 /* The following function is used to sort unit declaration by their
8571 units_cmp (const void *unit1
, const void *unit2
)
8573 const_unit_decl_t
const u1
= *(const_unit_decl_t
const*) unit1
;
8574 const_unit_decl_t
const u2
= *(const_unit_decl_t
const*) unit2
;
8576 return strcmp (u1
->name
, u2
->name
);
8579 /* The following macro value is name of struct containing unit name
8581 #define NAME_CODE_STRUCT_NAME "name_code"
8583 /* The following macro value is name of table of struct name_code. */
8584 #define NAME_CODE_TABLE_NAME "name_code_table"
8586 /* The following macro values are member names for struct name_code. */
8587 #define NAME_MEMBER_NAME "name"
8588 #define CODE_MEMBER_NAME "code"
8590 /* The following macro values are local variable names for function
8591 `get_cpu_unit_code'. */
8592 #define CMP_VARIABLE_NAME "cmp"
8593 #define LOW_VARIABLE_NAME "l"
8594 #define MIDDLE_VARIABLE_NAME "m"
8595 #define HIGH_VARIABLE_NAME "h"
8597 /* The following function outputs function to obtain internal cpu unit
8598 code by the cpu unit name. */
8600 output_get_cpu_unit_code_func (void)
8605 fprintf (output_file
, "int\n%s (const char *%s)\n",
8606 GET_CPU_UNIT_CODE_FUNC_NAME
, CPU_UNIT_NAME_PARAMETER_NAME
);
8607 fprintf (output_file
, "{\n struct %s {const char *%s; int %s;};\n",
8608 NAME_CODE_STRUCT_NAME
, NAME_MEMBER_NAME
, CODE_MEMBER_NAME
);
8609 fprintf (output_file
, " int %s, %s, %s, %s;\n", CMP_VARIABLE_NAME
,
8610 LOW_VARIABLE_NAME
, MIDDLE_VARIABLE_NAME
, HIGH_VARIABLE_NAME
);
8611 fprintf (output_file
, " static struct %s %s [] =\n {\n",
8612 NAME_CODE_STRUCT_NAME
, NAME_CODE_TABLE_NAME
);
8613 units
= XNEWVEC (unit_decl_t
, description
->units_num
);
8614 memcpy (units
, units_array
, sizeof (unit_decl_t
) * description
->units_num
);
8615 qsort (units
, description
->units_num
, sizeof (unit_decl_t
), units_cmp
);
8616 for (i
= 0; i
< description
->units_num
; i
++)
8617 if (units
[i
]->query_p
)
8618 fprintf (output_file
, " {\"%s\", %d},\n",
8619 units
[i
]->name
, units
[i
]->query_num
);
8620 fprintf (output_file
, " };\n\n");
8621 fprintf (output_file
, " /* The following is binary search: */\n");
8622 fprintf (output_file
, " %s = 0;\n", LOW_VARIABLE_NAME
);
8623 fprintf (output_file
, " %s = sizeof (%s) / sizeof (struct %s) - 1;\n",
8624 HIGH_VARIABLE_NAME
, NAME_CODE_TABLE_NAME
, NAME_CODE_STRUCT_NAME
);
8625 fprintf (output_file
, " while (%s <= %s)\n {\n",
8626 LOW_VARIABLE_NAME
, HIGH_VARIABLE_NAME
);
8627 fprintf (output_file
, " %s = (%s + %s) / 2;\n",
8628 MIDDLE_VARIABLE_NAME
, LOW_VARIABLE_NAME
, HIGH_VARIABLE_NAME
);
8629 fprintf (output_file
, " %s = strcmp (%s, %s [%s].%s);\n",
8630 CMP_VARIABLE_NAME
, CPU_UNIT_NAME_PARAMETER_NAME
,
8631 NAME_CODE_TABLE_NAME
, MIDDLE_VARIABLE_NAME
, NAME_MEMBER_NAME
);
8632 fprintf (output_file
, " if (%s < 0)\n", CMP_VARIABLE_NAME
);
8633 fprintf (output_file
, " %s = %s - 1;\n",
8634 HIGH_VARIABLE_NAME
, MIDDLE_VARIABLE_NAME
);
8635 fprintf (output_file
, " else if (%s > 0)\n", CMP_VARIABLE_NAME
);
8636 fprintf (output_file
, " %s = %s + 1;\n",
8637 LOW_VARIABLE_NAME
, MIDDLE_VARIABLE_NAME
);
8638 fprintf (output_file
, " else\n");
8639 fprintf (output_file
, " return %s [%s].%s;\n }\n",
8640 NAME_CODE_TABLE_NAME
, MIDDLE_VARIABLE_NAME
, CODE_MEMBER_NAME
);
8641 fprintf (output_file
, " return -1;\n}\n\n");
8645 /* The following function outputs function to check reservation of cpu
8646 unit (its internal code will be passed as the function argument) in
8649 output_cpu_unit_reservation_p (void)
8651 automaton_t automaton
;
8653 fprintf (output_file
, "int\n%s (%s %s, int %s)\n",
8654 CPU_UNIT_RESERVATION_P_FUNC_NAME
,
8655 STATE_TYPE_NAME
, STATE_NAME
,
8656 CPU_CODE_PARAMETER_NAME
);
8657 fprintf (output_file
, "{\n gcc_assert (%s >= 0 && %s < %d);\n",
8658 CPU_CODE_PARAMETER_NAME
, CPU_CODE_PARAMETER_NAME
,
8659 description
->query_units_num
);
8660 if (description
->query_units_num
> 0)
8661 for (automaton
= description
->first_automaton
;
8663 automaton
= automaton
->next_automaton
)
8665 fprintf (output_file
, " if ((");
8666 output_reserved_units_table_name (output_file
, automaton
);
8667 fprintf (output_file
, " [((struct %s *) %s)->", CHIP_NAME
, STATE_NAME
);
8668 output_chip_member_name (output_file
, automaton
);
8669 fprintf (output_file
, " * %d + %s / 8] >> (%s %% 8)) & 1)\n",
8670 (description
->query_units_num
+ 7) / 8,
8671 CPU_CODE_PARAMETER_NAME
, CPU_CODE_PARAMETER_NAME
);
8672 fprintf (output_file
, " return 1;\n");
8674 fprintf (output_file
, " return 0;\n}\n\n");
8677 /* The following function outputs a function to check if insn
8678 has a dfa reservation. */
8680 output_insn_has_dfa_reservation_p (void)
8682 fprintf (output_file
,
8683 "bool\n%s (rtx_insn *%s ATTRIBUTE_UNUSED)\n{\n",
8684 INSN_HAS_DFA_RESERVATION_P_FUNC_NAME
,
8685 INSN_PARAMETER_NAME
);
8687 if (DECL_INSN_RESERV (advance_cycle_insn_decl
)->insn_num
== 0)
8689 fprintf (output_file
, " return false;\n}\n\n");
8693 fprintf (output_file
, " int %s;\n\n", INTERNAL_INSN_CODE_NAME
);
8695 fprintf (output_file
, " if (%s == 0)\n %s = %s;\n",
8696 INSN_PARAMETER_NAME
,
8697 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
8698 fprintf (output_file
, " else\n\
8704 INTERNAL_INSN_CODE_NAME
, DFA_INSN_CODE_FUNC_NAME
,
8705 INSN_PARAMETER_NAME
,
8706 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
,
8707 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
8709 fprintf (output_file
, " return %s != %s;\n}\n\n",
8710 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
8713 /* The function outputs PHR interface functions `dfa_clean_insn_cache'
8714 and 'dfa_clear_single_insn_cache'. */
8716 output_dfa_clean_insn_cache_func (void)
8718 fprintf (output_file
,
8719 "void\n%s (void)\n{\n int %s;\n\n",
8720 DFA_CLEAN_INSN_CACHE_FUNC_NAME
, I_VARIABLE_NAME
);
8721 fprintf (output_file
,
8722 " for (%s = 0; %s < %s; %s++)\n %s [%s] = -1;\n}\n\n",
8723 I_VARIABLE_NAME
, I_VARIABLE_NAME
,
8724 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
, I_VARIABLE_NAME
,
8725 DFA_INSN_CODES_VARIABLE_NAME
, I_VARIABLE_NAME
);
8727 fprintf (output_file
,
8728 "void\n%s (rtx_insn *%s)\n{\n int %s;\n\n",
8729 DFA_CLEAR_SINGLE_INSN_CACHE_FUNC_NAME
, INSN_PARAMETER_NAME
,
8731 fprintf (output_file
,
8732 " %s = INSN_UID (%s);\n if (%s < %s)\n %s [%s] = -1;\n}\n\n",
8733 I_VARIABLE_NAME
, INSN_PARAMETER_NAME
, I_VARIABLE_NAME
,
8734 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
, DFA_INSN_CODES_VARIABLE_NAME
,
8738 /* The function outputs PHR interface function `dfa_start'. */
8740 output_dfa_start_func (void)
8742 fprintf (output_file
,
8743 "void\n%s (void)\n{\n %s = get_max_uid ();\n",
8744 DFA_START_FUNC_NAME
, DFA_INSN_CODES_LENGTH_VARIABLE_NAME
);
8745 fprintf (output_file
, " %s = XNEWVEC (int, %s);\n",
8746 DFA_INSN_CODES_VARIABLE_NAME
, DFA_INSN_CODES_LENGTH_VARIABLE_NAME
);
8747 fprintf (output_file
, " %s ();\n}\n\n", DFA_CLEAN_INSN_CACHE_FUNC_NAME
);
8750 /* The function outputs PHR interface function `dfa_finish'. */
8752 output_dfa_finish_func (void)
8754 fprintf (output_file
, "void\n%s (void)\n{\n free (%s);\n}\n\n",
8755 DFA_FINISH_FUNC_NAME
, DFA_INSN_CODES_VARIABLE_NAME
);
8760 /* The page contains code for output description file (readable
8761 representation of original description and generated DFA(s). */
8763 /* The function outputs string representation of IR reservation. */
8765 output_regexp (regexp_t regexp
)
8767 fprintf (output_description_file
, "%s", regexp_representation (regexp
));
8768 finish_regexp_representation ();
8771 /* Output names of units in LIST separated by comma. */
8773 output_unit_set_el_list (unit_set_el_t list
)
8777 for (el
= list
; el
!= NULL
; el
= el
->next_unit_set_el
)
8780 fprintf (output_description_file
, ", ");
8781 fprintf (output_description_file
, "%s", el
->unit_decl
->name
);
8785 /* Output patterns in LIST separated by comma. */
8787 output_pattern_set_el_list (pattern_set_el_t list
)
8789 pattern_set_el_t el
;
8792 for (el
= list
; el
!= NULL
; el
= el
->next_pattern_set_el
)
8795 fprintf (output_description_file
, ", ");
8796 for (i
= 0; i
< el
->units_num
; i
++)
8797 fprintf (output_description_file
, (i
== 0 ? "%s" : " %s"),
8798 el
->unit_decls
[i
]->name
);
8802 /* The function outputs string representation of IR define_reservation
8803 and define_insn_reservation. */
8805 output_description (void)
8810 for (i
= 0; i
< description
->decls_num
; i
++)
8812 decl
= description
->decls
[i
];
8813 if (decl
->mode
== dm_unit
)
8815 if (DECL_UNIT (decl
)->excl_list
!= NULL
)
8817 fprintf (output_description_file
, "unit %s exclusion_set: ",
8818 DECL_UNIT (decl
)->name
);
8819 output_unit_set_el_list (DECL_UNIT (decl
)->excl_list
);
8820 fprintf (output_description_file
, "\n");
8822 if (DECL_UNIT (decl
)->presence_list
!= NULL
)
8824 fprintf (output_description_file
, "unit %s presence_set: ",
8825 DECL_UNIT (decl
)->name
);
8826 output_pattern_set_el_list (DECL_UNIT (decl
)->presence_list
);
8827 fprintf (output_description_file
, "\n");
8829 if (DECL_UNIT (decl
)->final_presence_list
!= NULL
)
8831 fprintf (output_description_file
, "unit %s final_presence_set: ",
8832 DECL_UNIT (decl
)->name
);
8833 output_pattern_set_el_list
8834 (DECL_UNIT (decl
)->final_presence_list
);
8835 fprintf (output_description_file
, "\n");
8837 if (DECL_UNIT (decl
)->absence_list
!= NULL
)
8839 fprintf (output_description_file
, "unit %s absence_set: ",
8840 DECL_UNIT (decl
)->name
);
8841 output_pattern_set_el_list (DECL_UNIT (decl
)->absence_list
);
8842 fprintf (output_description_file
, "\n");
8844 if (DECL_UNIT (decl
)->final_absence_list
!= NULL
)
8846 fprintf (output_description_file
, "unit %s final_absence_set: ",
8847 DECL_UNIT (decl
)->name
);
8848 output_pattern_set_el_list
8849 (DECL_UNIT (decl
)->final_absence_list
);
8850 fprintf (output_description_file
, "\n");
8854 fprintf (output_description_file
, "\n");
8855 for (i
= 0; i
< description
->normal_decls_num
; i
++)
8857 decl
= description
->decls
[i
];
8858 if (decl
->mode
== dm_reserv
)
8860 fprintf (output_description_file
, "reservation %s: ",
8861 DECL_RESERV (decl
)->name
);
8862 output_regexp (DECL_RESERV (decl
)->regexp
);
8863 fprintf (output_description_file
, "\n");
8865 else if (decl
->mode
== dm_insn_reserv
)
8867 fprintf (output_description_file
, "insn reservation %s ",
8868 DECL_INSN_RESERV (decl
)->name
);
8869 print_rtl (output_description_file
,
8870 DECL_INSN_RESERV (decl
)->condexp
);
8871 fprintf (output_description_file
, ": ");
8872 output_regexp (DECL_INSN_RESERV (decl
)->regexp
);
8873 fprintf (output_description_file
, "\n");
8875 else if (decl
->mode
== dm_bypass
)
8876 fprintf (output_description_file
, "bypass %d %s %s\n",
8877 DECL_BYPASS (decl
)->latency
,
8878 DECL_BYPASS (decl
)->out_pattern
,
8879 DECL_BYPASS (decl
)->in_pattern
);
8881 fprintf (output_description_file
, "\n\f\n");
8884 /* The function outputs name of AUTOMATON. */
8886 output_automaton_name (FILE *f
, automaton_t automaton
)
8888 if (automaton
->corresponding_automaton_decl
== NULL
)
8889 fprintf (f
, "#%d", automaton
->automaton_order_num
);
8891 fprintf (f
, "`%s'", automaton
->corresponding_automaton_decl
->name
);
8894 /* Maximal length of line for pretty printing into description
8896 #define MAX_LINE_LENGTH 70
8898 /* The function outputs units name belonging to AUTOMATON. */
8900 output_automaton_units (automaton_t automaton
)
8904 int curr_line_length
;
8905 int there_is_an_automaton_unit
;
8908 fprintf (output_description_file
, "\n Corresponding units:\n");
8909 fprintf (output_description_file
, " ");
8910 curr_line_length
= 4;
8911 there_is_an_automaton_unit
= 0;
8912 for (i
= 0; i
< description
->decls_num
; i
++)
8914 decl
= description
->decls
[i
];
8915 if (decl
->mode
== dm_unit
8916 && (DECL_UNIT (decl
)->corresponding_automaton_num
8917 == automaton
->automaton_order_num
))
8919 there_is_an_automaton_unit
= 1;
8920 name
= DECL_UNIT (decl
)->name
;
8921 if (curr_line_length
+ strlen (name
) + 1 > MAX_LINE_LENGTH
)
8923 curr_line_length
= strlen (name
) + 4;
8924 fprintf (output_description_file
, "\n ");
8928 curr_line_length
+= strlen (name
) + 1;
8929 fprintf (output_description_file
, " ");
8931 fprintf (output_description_file
, "%s", name
);
8934 if (!there_is_an_automaton_unit
)
8935 fprintf (output_description_file
, "<None>");
8936 fprintf (output_description_file
, "\n\n");
8939 /* The following variable is used for forming array of all possible cpu unit
8940 reservations described by the current DFA state. */
8941 static vec
<reserv_sets_t
> state_reservs
;
8943 /* The function forms `state_reservs' for STATE. */
8945 add_state_reservs (state_t state
)
8947 alt_state_t curr_alt_state
;
8949 if (state
->component_states
!= NULL
)
8950 for (curr_alt_state
= state
->component_states
;
8951 curr_alt_state
!= NULL
;
8952 curr_alt_state
= curr_alt_state
->next_sorted_alt_state
)
8953 add_state_reservs (curr_alt_state
->state
);
8955 state_reservs
.safe_push (state
->reservs
);
8958 /* The function outputs readable representation of all out arcs of
8961 output_state_arcs (state_t state
)
8965 const char *insn_name
;
8966 int curr_line_length
;
8968 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
8971 gcc_assert (ainsn
->first_insn_with_same_reservs
);
8972 fprintf (output_description_file
, " ");
8973 curr_line_length
= 7;
8974 fprintf (output_description_file
, "%2d: ", ainsn
->insn_equiv_class_num
);
8977 insn_name
= ainsn
->insn_reserv_decl
->name
;
8978 if (curr_line_length
+ strlen (insn_name
) > MAX_LINE_LENGTH
)
8980 if (ainsn
!= arc
->insn
)
8982 fprintf (output_description_file
, ",\n ");
8983 curr_line_length
= strlen (insn_name
) + 6;
8986 curr_line_length
+= strlen (insn_name
);
8990 curr_line_length
+= strlen (insn_name
);
8991 if (ainsn
!= arc
->insn
)
8993 curr_line_length
+= 2;
8994 fprintf (output_description_file
, ", ");
8997 fprintf (output_description_file
, "%s", insn_name
);
8998 ainsn
= ainsn
->next_same_reservs_insn
;
9000 while (ainsn
!= NULL
);
9001 fprintf (output_description_file
, " %d \n",
9002 arc
->to_state
->order_state_num
);
9004 fprintf (output_description_file
, "\n");
9007 /* The following function is used for sorting possible cpu unit
9008 reservation of a DFA state. */
9010 state_reservs_cmp (const void *reservs_ptr_1
, const void *reservs_ptr_2
)
9012 return reserv_sets_cmp (*(const_reserv_sets_t
const*) reservs_ptr_1
,
9013 *(const_reserv_sets_t
const*) reservs_ptr_2
);
9016 /* The following function is used for sorting possible cpu unit
9017 reservation of a DFA state. */
9019 remove_state_duplicate_reservs (void)
9023 for (i
= 1, j
= 0; i
< state_reservs
.length (); i
++)
9024 if (reserv_sets_cmp (state_reservs
[j
], state_reservs
[i
]))
9027 state_reservs
[j
] = state_reservs
[i
];
9029 state_reservs
.truncate (j
+ 1);
9032 /* The following function output readable representation of DFA(s)
9033 state used for fast recognition of pipeline hazards. State is
9034 described by possible (current and scheduled) cpu unit
9037 output_state (state_t state
)
9041 state_reservs
.create (0);
9043 fprintf (output_description_file
, " State #%d", state
->order_state_num
);
9044 fprintf (output_description_file
,
9045 state
->new_cycle_p
? " (new cycle)\n" : "\n");
9046 add_state_reservs (state
);
9047 state_reservs
.qsort (state_reservs_cmp
);
9048 remove_state_duplicate_reservs ();
9049 for (i
= 0; i
< state_reservs
.length (); i
++)
9051 fprintf (output_description_file
, " ");
9052 output_reserv_sets (output_description_file
, state_reservs
[i
]);
9053 fprintf (output_description_file
, "\n");
9055 fprintf (output_description_file
, "\n");
9056 output_state_arcs (state
);
9057 state_reservs
.release ();
9060 /* The following function output readable representation of
9061 DFAs used for fast recognition of pipeline hazards. */
9063 output_automaton_descriptions (void)
9065 automaton_t automaton
;
9067 for (automaton
= description
->first_automaton
;
9069 automaton
= automaton
->next_automaton
)
9071 fprintf (output_description_file
, "\nAutomaton ");
9072 output_automaton_name (output_description_file
, automaton
);
9073 fprintf (output_description_file
, "\n");
9074 output_automaton_units (automaton
);
9075 pass_states (automaton
, output_state
);
9081 /* The page contains top level function for generation DFA(s) used for
9084 /* The function outputs statistics about work of different phases of
9087 output_statistics (FILE *f
)
9089 automaton_t automaton
;
9092 int transition_comb_vect_els
= 0;
9093 int transition_full_vect_els
= 0;
9094 int min_issue_delay_vect_els
= 0;
9095 int locked_states
= 0;
9098 for (automaton
= description
->first_automaton
;
9100 automaton
= automaton
->next_automaton
)
9102 fprintf (f
, "\nAutomaton ");
9103 output_automaton_name (f
, automaton
);
9104 fprintf (f
, "\n %5d NDFA states, %5d NDFA arcs\n",
9105 automaton
->NDFA_states_num
, automaton
->NDFA_arcs_num
);
9106 fprintf (f
, " %5d DFA states, %5d DFA arcs\n",
9107 automaton
->DFA_states_num
, automaton
->DFA_arcs_num
);
9108 states_num
= automaton
->DFA_states_num
;
9109 if (!no_minimization_flag
)
9111 fprintf (f
, " %5d minimal DFA states, %5d minimal DFA arcs\n",
9112 automaton
->minimal_DFA_states_num
,
9113 automaton
->minimal_DFA_arcs_num
);
9114 states_num
= automaton
->minimal_DFA_states_num
;
9116 fprintf (f
, " %5d all insns %5d insn equivalence classes\n",
9117 description
->insns_num
, automaton
->insn_equiv_classes_num
);
9118 fprintf (f
, " %d locked states\n", automaton
->locked_states
);
9121 (f
, "%5ld transition comb vector els, %5ld trans table els: %s\n",
9122 (long) automaton
->trans_table
->comb_vect
.length (),
9123 (long) automaton
->trans_table
->full_vect
.length (),
9124 (comb_vect_p (automaton
->trans_table
)
9125 ? "use comb vect" : "use simple vect"));
9127 (f
, "%5ld min delay table els, compression factor %d\n",
9128 (long) states_num
* automaton
->insn_equiv_classes_num
,
9129 automaton
->min_issue_delay_table_compression_factor
);
9130 transition_comb_vect_els
9131 += automaton
->trans_table
->comb_vect
.length ();
9132 transition_full_vect_els
9133 += automaton
->trans_table
->full_vect
.length ();
9134 min_issue_delay_vect_els
9135 += states_num
* automaton
->insn_equiv_classes_num
;
9137 += automaton
->locked_states
;
9141 fprintf (f
, "\n%5d all allocated states, %5d all allocated arcs\n",
9142 allocated_states_num
, allocated_arcs_num
);
9143 fprintf (f
, "%5d all allocated alternative states\n",
9144 allocated_alt_states_num
);
9145 fprintf (f
, "%5d all transition comb vector els, %5d all trans table els\n",
9146 transition_comb_vect_els
, transition_full_vect_els
);
9147 fprintf (f
, "%5d all min delay table els\n", min_issue_delay_vect_els
);
9148 fprintf (f
, "%5d all locked states\n", locked_states
);
9152 /* The function output times of work of different phases of DFA
9155 output_time_statistics (FILE *f
)
9157 fprintf (f
, "\n transformation: ");
9158 print_active_time (f
, transform_time
);
9159 fprintf (f
, (!ndfa_flag
? ", building DFA: " : ", building NDFA: "));
9160 print_active_time (f
, NDFA_time
);
9163 fprintf (f
, ", NDFA -> DFA: ");
9164 print_active_time (f
, NDFA_to_DFA_time
);
9166 fprintf (f
, "\n DFA minimization: ");
9167 print_active_time (f
, minimize_time
);
9168 fprintf (f
, ", making insn equivalence: ");
9169 print_active_time (f
, equiv_time
);
9170 fprintf (f
, "\n all automaton generation: ");
9171 print_active_time (f
, automaton_generation_time
);
9172 fprintf (f
, ", output: ");
9173 print_active_time (f
, output_time
);
9177 /* The function generates DFA (deterministic finite state automaton)
9178 for fast recognition of pipeline hazards. No errors during
9179 checking must be fixed before this function call. */
9183 automata_num
= split_argument
;
9184 if (description
->units_num
< automata_num
)
9185 automata_num
= description
->units_num
;
9188 initiate_automata_lists ();
9189 initiate_pass_states ();
9190 initiate_excl_sets ();
9191 initiate_presence_absence_pattern_sets ();
9192 automaton_generation_time
= create_ticker ();
9194 ticker_off (&automaton_generation_time
);
9199 /* This page mainly contains top level functions of pipeline hazards
9200 description translator. */
9202 /* The following macro value is suffix of name of description file of
9203 pipeline hazards description translator. */
9204 #define STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX ".dfa"
9206 /* The function returns suffix of given file name. The returned
9207 string cannot be changed. */
9209 file_name_suffix (const char *file_name
)
9211 const char *last_period
;
9213 for (last_period
= NULL
; *file_name
!= '\0'; file_name
++)
9214 if (*file_name
== '.')
9215 last_period
= file_name
;
9216 return (last_period
== NULL
? file_name
: last_period
);
9219 /* The function returns base name of given file name, i.e. pointer to
9220 first char after last `/' (or `\' for WIN32) in given file name,
9221 given file name itself if the directory name is absent. The
9222 returned string cannot be changed. */
9224 base_file_name (const char *file_name
)
9226 int directory_name_length
;
9228 directory_name_length
= strlen (file_name
);
9230 while (directory_name_length
>= 0 && file_name
[directory_name_length
] != '/'
9231 && file_name
[directory_name_length
] != '\\')
9233 while (directory_name_length
>= 0 && file_name
[directory_name_length
] != '/')
9235 directory_name_length
--;
9236 return file_name
+ directory_name_length
+ 1;
9239 /* A function passed as argument to init_rtx_reader_args_cb. It parses the
9240 options available for genautomata. Returns true if the option was
9243 parse_automata_opt (const char *str
)
9245 if (strcmp (str
, NO_MINIMIZATION_OPTION
) == 0)
9246 no_minimization_flag
= 1;
9247 else if (strcmp (str
, TIME_OPTION
) == 0)
9249 else if (strcmp (str
, STATS_OPTION
) == 0)
9251 else if (strcmp (str
, V_OPTION
) == 0)
9253 else if (strcmp (str
, W_OPTION
) == 0)
9255 else if (strcmp (str
, NDFA_OPTION
) == 0)
9257 else if (strcmp (str
, COLLAPSE_OPTION
) == 0)
9259 else if (strcmp (str
, PROGRESS_OPTION
) == 0)
9261 else if (strcmp (str
, "-split") == 0)
9263 fatal ("option `-split' has not been implemented yet\n");
9264 /* split_argument = atoi (argument_vect [i + 1]); */
9272 /* The following is top level function to initialize the work of
9273 pipeline hazards description translator. */
9275 initiate_automaton_gen (const char **argv
)
9277 const char *base_name
;
9279 /* Initialize IR storage. */
9280 obstack_init (&irp
);
9281 initiate_automaton_decl_table ();
9282 initiate_insn_decl_table ();
9283 initiate_decl_table ();
9284 output_file
= stdout
;
9285 output_description_file
= NULL
;
9286 base_name
= base_file_name (argv
[1]);
9287 obstack_grow (&irp
, base_name
,
9288 strlen (base_name
) - strlen (file_name_suffix (base_name
)));
9289 obstack_grow (&irp
, STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX
,
9290 strlen (STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX
) + 1);
9291 obstack_1grow (&irp
, '\0');
9292 output_description_file_name
= (char *) obstack_base (&irp
);
9293 obstack_finish (&irp
);
9296 /* The following function checks existence at least one arc marked by
9299 check_automata_insn_issues (void)
9301 automaton_t automaton
;
9302 ainsn_t ainsn
, reserv_ainsn
;
9304 for (automaton
= description
->first_automaton
;
9306 automaton
= automaton
->next_automaton
)
9308 for (ainsn
= automaton
->ainsn_list
;
9310 ainsn
= ainsn
->next_ainsn
)
9311 if (ainsn
->first_insn_with_same_reservs
&& !ainsn
->arc_exists_p
9312 && ainsn
!= automaton
->collapse_ainsn
)
9314 for (reserv_ainsn
= ainsn
;
9315 reserv_ainsn
!= NULL
;
9316 reserv_ainsn
= reserv_ainsn
->next_same_reservs_insn
)
9317 if (automaton
->corresponding_automaton_decl
!= NULL
)
9320 error ("Automaton `%s': Insn `%s' will never be issued",
9321 automaton
->corresponding_automaton_decl
->name
,
9322 reserv_ainsn
->insn_reserv_decl
->name
);
9324 warning ("Automaton `%s': Insn `%s' will never be issued",
9325 automaton
->corresponding_automaton_decl
->name
,
9326 reserv_ainsn
->insn_reserv_decl
->name
);
9331 error ("Insn `%s' will never be issued",
9332 reserv_ainsn
->insn_reserv_decl
->name
);
9334 warning ("Insn `%s' will never be issued",
9335 reserv_ainsn
->insn_reserv_decl
->name
);
9341 /* The following vla is used for storing pointers to all achieved
9343 static vec
<state_t
> automaton_states
;
9345 /* This function is called by function pass_states to add an achieved
9348 add_automaton_state (state_t state
)
9350 automaton_states
.safe_push (state
);
9353 /* The following function forms list of important automata (whose
9354 states may be changed after the insn issue) for each insn. */
9356 form_important_insn_automata_lists (void)
9358 automaton_t automaton
;
9365 automaton_states
.create (0);
9366 /* Mark important ainsns. */
9367 for (automaton
= description
->first_automaton
;
9369 automaton
= automaton
->next_automaton
)
9371 automaton_states
.truncate (0);
9372 pass_states (automaton
, add_automaton_state
);
9373 for (n
= 0; n
< automaton_states
.length (); n
++)
9375 state_t s
= automaton_states
[n
];
9376 for (arc
= first_out_arc (s
);
9378 arc
= next_out_arc (arc
))
9379 if (arc
->to_state
!= s
)
9381 gcc_assert (arc
->insn
->first_insn_with_same_reservs
);
9382 for (ainsn
= arc
->insn
;
9384 ainsn
= ainsn
->next_same_reservs_insn
)
9385 ainsn
->important_p
= true;
9389 automaton_states
.release ();
9391 /* Create automata sets for the insns. */
9392 for (i
= 0; i
< description
->decls_num
; i
++)
9394 decl
= description
->decls
[i
];
9395 if (decl
->mode
== dm_insn_reserv
)
9397 automata_list_start ();
9398 for (automaton
= description
->first_automaton
;
9400 automaton
= automaton
->next_automaton
)
9401 for (ainsn
= automaton
->ainsn_list
;
9403 ainsn
= ainsn
->next_ainsn
)
9404 if (ainsn
->important_p
9405 && ainsn
->insn_reserv_decl
== DECL_INSN_RESERV (decl
))
9407 automata_list_add (automaton
);
9410 DECL_INSN_RESERV (decl
)->important_automata_list
9411 = automata_list_finish ();
9417 /* The following is top level function to generate automat(a,on) for
9418 fast recognition of pipeline hazards. */
9420 expand_automata (void)
9424 description
= XCREATENODEVAR (struct description
,
9425 sizeof (struct description
)
9426 /* Two entries for special insns. */
9427 + sizeof (decl_t
) * (decls
.length () + 1));
9428 description
->decls_num
= decls
.length ();
9429 description
->normal_decls_num
= description
->decls_num
;
9430 description
->query_units_num
= 0;
9431 for (i
= 0; i
< description
->decls_num
; i
++)
9433 description
->decls
[i
] = decls
[i
];
9434 if (description
->decls
[i
]->mode
== dm_unit
9435 && DECL_UNIT (description
->decls
[i
])->query_p
)
9436 DECL_UNIT (description
->decls
[i
])->query_num
9437 = description
->query_units_num
++;
9439 all_time
= create_ticker ();
9440 check_time
= create_ticker ();
9442 fprintf (stderr
, "Check description...");
9443 check_all_description ();
9445 fprintf (stderr
, "done\n");
9446 ticker_off (&check_time
);
9447 generation_time
= create_ticker ();
9450 transform_insn_regexps ();
9451 check_unit_distributions_to_automata ();
9456 check_automata_insn_issues ();
9460 form_important_insn_automata_lists ();
9462 ticker_off (&generation_time
);
9465 /* The following is top level function to output PHR and to finish
9466 work with pipeline description translator. */
9468 write_automata (void)
9470 output_time
= create_ticker ();
9472 fprintf (stderr
, "Forming and outputting automata tables...");
9476 fprintf (stderr
, "done\n");
9477 fprintf (stderr
, "Output functions to work with automata...");
9479 output_chip_definitions ();
9480 output_max_insn_queue_index_def ();
9481 output_internal_min_issue_delay_func ();
9482 output_internal_trans_func ();
9483 /* Cache of insn dfa codes: */
9484 fprintf (output_file
, "\nstatic int *%s;\n", DFA_INSN_CODES_VARIABLE_NAME
);
9485 fprintf (output_file
, "\nstatic int %s;\n\n",
9486 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
);
9487 output_dfa_insn_code_func ();
9488 output_trans_func ();
9489 output_min_issue_delay_func ();
9490 output_internal_dead_lock_func ();
9491 output_dead_lock_func ();
9492 output_size_func ();
9493 output_internal_reset_func ();
9494 output_reset_func ();
9495 output_min_insn_conflict_delay_func ();
9496 output_default_latencies ();
9497 output_internal_insn_latency_func ();
9498 output_insn_latency_func ();
9499 output_internal_maximal_insn_latency_func ();
9500 output_maximal_insn_latency_func ();
9501 output_print_reservation_func ();
9502 /* Output function get_cpu_unit_code. */
9503 fprintf (output_file
, "\n#if %s\n\n", CPU_UNITS_QUERY_MACRO_NAME
);
9504 output_get_cpu_unit_code_func ();
9505 output_cpu_unit_reservation_p ();
9506 fprintf (output_file
, "\n#endif /* #if %s */\n\n",
9507 CPU_UNITS_QUERY_MACRO_NAME
);
9508 output_insn_has_dfa_reservation_p ();
9509 output_dfa_clean_insn_cache_func ();
9510 output_dfa_start_func ();
9511 output_dfa_finish_func ();
9513 fprintf (stderr
, "done\n");
9516 output_description_file
= fopen (output_description_file_name
, "w");
9517 if (output_description_file
== NULL
)
9519 perror (output_description_file_name
);
9520 exit (FATAL_EXIT_CODE
);
9523 fprintf (stderr
, "Output automata description...");
9524 output_description ();
9525 output_automaton_descriptions ();
9527 fprintf (stderr
, "done\n");
9528 output_statistics (output_description_file
);
9531 output_statistics (stderr
);
9532 ticker_off (&output_time
);
9534 output_time_statistics (stderr
);
9537 finish_automata_lists ();
9540 fprintf (stderr
, "Summary:\n");
9541 fprintf (stderr
, " check time ");
9542 print_active_time (stderr
, check_time
);
9543 fprintf (stderr
, ", generation time ");
9544 print_active_time (stderr
, generation_time
);
9545 fprintf (stderr
, ", all time ");
9546 print_active_time (stderr
, all_time
);
9547 fprintf (stderr
, "\n");
9549 /* Finish all work. */
9550 if (output_description_file
!= NULL
)
9552 fflush (output_description_file
);
9553 if (ferror (stdout
) != 0)
9554 fatal ("Error in writing DFA description file %s: %s",
9555 output_description_file_name
, xstrerror (errno
));
9556 fclose (output_description_file
);
9558 finish_automaton_decl_table ();
9559 finish_insn_decl_table ();
9560 finish_decl_table ();
9561 obstack_free (&irp
, NULL
);
9562 if (have_error
&& output_description_file
!= NULL
)
9563 remove (output_description_file_name
);
9567 main (int argc
, const char **argv
)
9569 progname
= "genautomata";
9571 if (!init_rtx_reader_args_cb (argc
, argv
, parse_automata_opt
))
9572 return (FATAL_EXIT_CODE
);
9574 initiate_automaton_gen (argv
);
9576 while (read_md_rtx (&info
))
9577 switch (GET_CODE (info
.def
))
9579 case DEFINE_CPU_UNIT
:
9580 gen_cpu_unit (&info
);
9583 case DEFINE_QUERY_CPU_UNIT
:
9584 gen_query_cpu_unit (&info
);
9592 gen_excl_set (&info
);
9596 gen_presence_set (&info
);
9599 case FINAL_PRESENCE_SET
:
9600 gen_final_presence_set (&info
);
9604 gen_absence_set (&info
);
9607 case FINAL_ABSENCE_SET
:
9608 gen_final_absence_set (&info
);
9611 case DEFINE_AUTOMATON
:
9612 gen_automaton (&info
);
9615 case AUTOMATA_OPTION
:
9616 gen_automata_option (&info
);
9619 case DEFINE_RESERVATION
:
9623 case DEFINE_INSN_RESERVATION
:
9624 gen_insn_reserv (&info
);
9632 return FATAL_EXIT_CODE
;
9634 if (decls
.length () > 0)
9639 puts ("/* Generated automatically by the program `genautomata'\n"
9640 " from the machine description file `md'. */\n\n"
9641 "#define IN_TARGET_CODE 1\n"
9642 "#include \"config.h\"\n"
9643 "#include \"system.h\"\n"
9644 "#include \"coretypes.h\"\n"
9645 "#include \"tm.h\"\n"
9646 "#include \"alias.h\"\n"
9647 "#include \"tree.h\"\n"
9648 "#include \"varasm.h\"\n"
9649 "#include \"stor-layout.h\"\n"
9650 "#include \"calls.h\"\n"
9651 "#include \"rtl.h\"\n"
9652 "#include \"memmodel.h\"\n"
9653 "#include \"tm_p.h\"\n"
9654 "#include \"insn-config.h\"\n"
9655 "#include \"recog.h\"\n"
9656 "#include \"regs.h\"\n"
9657 "#include \"output.h\"\n"
9658 "#include \"insn-attr.h\"\n"
9659 "#include \"diagnostic-core.h\"\n"
9660 "#include \"flags.h\"\n"
9661 "#include \"function.h\"\n"
9662 "#include \"emit-rtl.h\"\n");
9663 /* FIXME: emit-rtl.h can go away once crtl is in rtl.h. */
9670 puts ("/* Generated automatically by the program `genautomata'\n"
9671 " from the machine description file `md'. */\n\n"
9672 "/* There is no automaton, but ISO C forbids empty\n"
9673 " translation units, so include a header file with some\n"
9674 " declarations, and its pre-requisite header file. */\n"
9675 "#include \"config.h\"\n"
9676 "#include \"system.h\"\n");
9680 return (ferror (stdout
) != 0 || have_error
9681 ? FATAL_EXIT_CODE
: SUCCESS_EXIT_CODE
);