1 /* Pipeline hazard description translator.
2 Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010
3 Free Software Foundation, Inc.
5 Written by Vladimir Makarov <vmakarov@redhat.com>
7 This file is part of GCC.
9 GCC is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by the
11 Free Software Foundation; either version 3, or (at your option) any
14 GCC is distributed in the hope that it will be useful, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING3. If not see
21 <http://www.gnu.org/licenses/>. */
25 1. The finite state automaton based pipeline hazard recognizer and
26 instruction scheduler in GCC. V. Makarov. Proceedings of GCC
29 2. Detecting pipeline structural hazards quickly. T. Proebsting,
30 C. Fraser. Proceedings of ACM SIGPLAN-SIGACT Symposium on
31 Principles of Programming Languages, pages 280--286, 1994.
33 This article is a good start point to understand usage of finite
34 state automata for pipeline hazard recognizers. But I'd
35 recommend the 1st and 3rd article for more deep understanding.
37 3. Efficient Instruction Scheduling Using Finite State Automata:
38 V. Bala and N. Rubin, Proceedings of MICRO-28. This is the best
39 article about usage of finite state automata for pipeline hazard
42 The current implementation is described in the 1st article and it
43 is different from the 3rd article in the following:
45 1. New operator `|' (alternative) is permitted in functional unit
46 reservation which can be treated deterministically and
47 non-deterministically.
49 2. Possibility of usage of nondeterministic automata too.
51 3. Possibility to query functional unit reservations for given
54 4. Several constructions to describe impossible reservations
55 (`exclusion_set', `presence_set', `final_presence_set',
56 `absence_set', and `final_absence_set').
58 5. No reverse automata are generated. Trace instruction scheduling
59 requires this. It can be easily added in the future if we
62 6. Union of automaton states are not generated yet. It is planned
63 to be implemented. Such feature is needed to make more accurate
64 interlock insn scheduling to get state describing functional
65 unit reservation in a joint CFG point. */
67 /* This file code processes constructions of machine description file
68 which describes automaton used for recognition of processor pipeline
69 hazards by insn scheduler and can be used for other tasks (such as
72 The translator functions `gen_cpu_unit', `gen_query_cpu_unit',
73 `gen_bypass', `gen_excl_set', `gen_presence_set',
74 `gen_final_presence_set', `gen_absence_set',
75 `gen_final_absence_set', `gen_automaton', `gen_automata_option',
76 `gen_reserv', `gen_insn_reserv' are called from file
77 `genattrtab.c'. They transform RTL constructions describing
78 automata in .md file into internal representation convenient for
81 The translator major function `expand_automata' processes the
82 description internal representation into finite state automaton.
85 o checking correctness of the automaton pipeline description
86 (major function is `check_all_description').
88 o generating automaton (automata) from the description (major
89 function is `make_automaton').
91 o optional transformation of nondeterministic finite state
92 automata into deterministic ones if the alternative operator
93 `|' is treated nondeterministically in the description (major
94 function is NDFA_to_DFA).
96 o optional minimization of the finite state automata by merging
97 equivalent automaton states (major function is `minimize_DFA').
99 o forming tables (some as comb vectors) and attributes
100 representing the automata (functions output_..._table).
102 Function `write_automata' outputs the created finite state
103 automaton as different tables and functions which works with the
104 automata to inquire automaton state and to change its state. These
105 function are used by gcc instruction scheduler and may be some
110 #include "coretypes.h"
115 #include "gensupport.h"
126 /* Positions in machine description file. Now they are not used. But
127 they could be used in the future for better diagnostic messages. */
130 /* The following is element of vector of current (and planned in the
131 future) functional unit reservations. */
132 typedef unsigned HOST_WIDE_INT set_el_t
;
134 /* Reservations of function units are represented by value of the following
136 typedef set_el_t
*reserv_sets_t
;
137 typedef const set_el_t
*const_reserv_sets_t
;
139 /* The following structure describes a ticker. */
142 /* The following member value is time of the ticker creation with
143 taking into account time when the ticker is off. Active time of
144 the ticker is current time minus the value. */
145 int modified_creation_time
;
146 /* The following member value is time (incremented by one) when the
147 ticker was off. Zero value means that now the ticker is on. */
148 int incremented_off_time
;
151 /* The ticker is represented by the following type. */
152 typedef struct ticker ticker_t
;
154 /* The following type describes elements of output vectors. */
155 typedef HOST_WIDE_INT vect_el_t
;
157 /* Forward declaration of structures of internal representation of
158 pipeline description based on NDFA. */
163 struct automaton_decl
;
164 struct unit_pattern_rel_decl
;
166 struct insn_reserv_decl
;
169 struct result_regexp
;
170 struct reserv_regexp
;
171 struct nothing_regexp
;
172 struct sequence_regexp
;
173 struct repeat_regexp
;
179 struct pattern_set_el
;
180 struct pattern_reserv
;
186 struct state_ainsn_table
;
188 /* The following typedefs are for brevity. */
189 typedef struct unit_decl
*unit_decl_t
;
190 typedef const struct unit_decl
*const_unit_decl_t
;
191 typedef struct decl
*decl_t
;
192 typedef const struct decl
*const_decl_t
;
193 typedef struct regexp
*regexp_t
;
194 typedef struct unit_set_el
*unit_set_el_t
;
195 typedef struct pattern_set_el
*pattern_set_el_t
;
196 typedef struct pattern_reserv
*pattern_reserv_t
;
197 typedef struct alt_state
*alt_state_t
;
198 typedef struct state
*state_t
;
199 typedef const struct state
*const_state_t
;
200 typedef struct arc
*arc_t
;
201 typedef struct ainsn
*ainsn_t
;
202 typedef struct automaton
*automaton_t
;
203 typedef struct automata_list_el
*automata_list_el_t
;
204 typedef const struct automata_list_el
*const_automata_list_el_t
;
205 typedef struct state_ainsn_table
*state_ainsn_table_t
;
207 /* Undefined position. */
208 static pos_t no_pos
= 0;
210 /* All IR is stored in the following obstack. */
211 static struct obstack irp
;
214 /* Declare vector types for various data structures: */
217 typedef vec
<vect_el_t
> vla_hwint_t
;
219 /* Forward declarations of functions used before their definitions, only. */
220 static regexp_t
gen_regexp_sequence (const char *);
221 static void reserv_sets_or (reserv_sets_t
, reserv_sets_t
,
223 static reserv_sets_t
get_excl_set (reserv_sets_t
);
224 static int check_presence_pattern_sets (reserv_sets_t
,
226 static int check_absence_pattern_sets (reserv_sets_t
, reserv_sets_t
,
228 static arc_t
first_out_arc (const_state_t
);
229 static arc_t
next_out_arc (arc_t
);
233 /* Options with the following names can be set up in automata_option
234 construction. Because the strings occur more one time we use the
237 #define NO_MINIMIZATION_OPTION "-no-minimization"
238 #define TIME_OPTION "-time"
239 #define STATS_OPTION "-stats"
240 #define V_OPTION "-v"
241 #define W_OPTION "-w"
242 #define NDFA_OPTION "-ndfa"
243 #define COLLAPSE_OPTION "-collapse-ndfa"
244 #define NO_COMB_OPTION "-no-comb-vect"
245 #define PROGRESS_OPTION "-progress"
247 /* The following flags are set up by function `initiate_automaton_gen'. */
249 /* Make automata with nondeterministic reservation by insns (`-ndfa'). */
250 static int ndfa_flag
;
252 /* When making an NDFA, produce additional transitions that collapse
253 NDFA state into a deterministic one suitable for querying CPU units.
254 Provide avance-state transitions only for deterministic states. */
255 static int collapse_flag
;
257 /* Do not make minimization of DFA (`-no-minimization'). */
258 static int no_minimization_flag
;
260 /* Do not try to generate a comb vector (`-no-comb-vect'). */
261 static int no_comb_flag
;
263 /* Value of this variable is number of automata being generated. The
264 actual number of automata may be less this value if there is not
265 sufficient number of units. This value is defined by argument of
266 option `-split' or by constructions automaton if the value is zero
267 (it is default value of the argument). */
268 static int split_argument
;
270 /* Flag of output time statistics (`-time'). */
271 static int time_flag
;
273 /* Flag of automata statistics (`-stats'). */
274 static int stats_flag
;
276 /* Flag of creation of description file which contains description of
277 result automaton and statistics information (`-v'). */
280 /* Flag of output of a progress bar showing how many states were
281 generated so far for automaton being processed (`-progress'). */
282 static int progress_flag
;
284 /* Flag of generating warning instead of error for non-critical errors
289 /* Output file for pipeline hazard recognizer (PHR) being generated.
290 The value is NULL if the file is not defined. */
291 static FILE *output_file
;
293 /* Description file of PHR. The value is NULL if the file is not
295 static FILE *output_description_file
;
297 /* PHR description file name. */
298 static char *output_description_file_name
;
300 /* Value of the following variable is node representing description
301 being processed. This is start point of IR. */
302 static struct description
*description
;
306 /* This page contains description of IR structure (nodes). */
320 /* This describes define_cpu_unit and define_query_cpu_unit (see file
325 /* NULL if the automaton name is absent. */
326 const char *automaton_name
;
327 /* If the following value is not zero, the cpu unit reservation is
328 described in define_query_cpu_unit. */
331 /* The following fields are defined by checker. */
333 /* The following field value is nonzero if the unit is used in an
337 /* The following field value is order number (0, 1, ...) of given
340 /* The following field value is corresponding declaration of
341 automaton which was given in description. If the field value is
342 NULL then automaton in the unit declaration was absent. */
343 struct automaton_decl
*automaton_decl
;
344 /* The following field value is maximal cycle number (1, ...) on
345 which given unit occurs in insns. Zero value means that given
346 unit is not used in insns. */
347 int max_occ_cycle_num
;
348 /* The following field value is minimal cycle number (0, ...) on
349 which given unit occurs in insns. -1 value means that given
350 unit is not used in insns. */
351 int min_occ_cycle_num
;
352 /* The following list contains units which conflict with given
354 unit_set_el_t excl_list
;
355 /* The following list contains patterns which are required to
356 reservation of given unit. */
357 pattern_set_el_t presence_list
;
358 pattern_set_el_t final_presence_list
;
359 /* The following list contains patterns which should be not present
360 in reservation for given unit. */
361 pattern_set_el_t absence_list
;
362 pattern_set_el_t final_absence_list
;
363 /* The following is used only when `query_p' has nonzero value.
364 This is query number for the unit. */
366 /* The following is the last cycle on which the unit was checked for
367 correct distributions of units to automata in a regexp. */
368 int last_distribution_check_cycle
;
370 /* The following fields are defined by automaton generator. */
372 /* The following field value is number of the automaton to which
373 given unit belongs. */
374 int corresponding_automaton_num
;
375 /* If the following value is not zero, the cpu unit is present in a
376 `exclusion_set' or in right part of a `presence_set',
377 `final_presence_set', `absence_set', and
378 `final_absence_set'define_query_cpu_unit. */
382 /* This describes define_bypass (see file rtl.def). */
386 const char *out_pattern
;
387 const char *in_pattern
;
388 const char *bypass_guard_name
;
390 /* The following fields are defined by checker. */
392 /* output and input insns of given bypass. */
393 struct insn_reserv_decl
*out_insn_reserv
;
394 struct insn_reserv_decl
*in_insn_reserv
;
395 /* The next bypass for given output insn. */
396 struct bypass_decl
*next
;
399 /* This describes define_automaton (see file rtl.def). */
400 struct automaton_decl
404 /* The following fields are defined by automaton generator. */
406 /* The following field value is nonzero if the automaton is used in
407 an regexp definition. */
408 char automaton_is_used
;
410 /* The following fields are defined by checker. */
412 /* The following field value is the corresponding automaton. This
413 field is not NULL only if the automaton is present in unit
414 declarations and the automatic partition on automata is not
416 automaton_t corresponding_automaton
;
419 /* This describes exclusion relations: exclusion_set (see file
424 int first_list_length
;
428 /* This describes unit relations: [final_]presence_set or
429 [final_]absence_set (see file rtl.def). */
430 struct unit_pattern_rel_decl
439 /* This describes define_reservation (see file rtl.def). */
445 /* The following fields are defined by checker. */
447 /* The following field value is nonzero if the unit is used in an
450 /* The following field is used to check up cycle in expression
455 /* This describes define_insn_reservation (see file rtl.def). */
456 struct insn_reserv_decl
463 /* The following fields are defined by checker. */
465 /* The following field value is order number (0, 1, ...) of given
468 /* The following field value is list of bypasses in which given insn
469 is output insn. Bypasses with the same input insn stay one after
470 another in the list in the same order as their occurrences in the
471 description but the bypass without a guard stays always the last
472 in a row of bypasses with the same input insn. */
473 struct bypass_decl
*bypass_list
;
475 /* The following fields are defined by automaton generator. */
477 /* The following field is the insn regexp transformed that
478 the regexp has not optional regexp, repetition regexp, and an
479 reservation name (i.e. reservation identifiers are changed by the
480 corresponding regexp) and all alternations are the top level
481 of the regexp. The value can be NULL only if it is special
482 insn `cycle advancing'. */
483 regexp_t transformed_regexp
;
484 /* The following field value is list of arcs marked given
485 insn. The field is used in transformation NDFA -> DFA. */
486 arc_t arcs_marked_by_insn
;
487 /* The two following fields are used during minimization of a finite state
489 /* The field value is number of equivalence class of state into
490 which arc marked by given insn enters from a state (fixed during
491 an automaton minimization). */
493 /* The following member value is the list to automata which can be
494 changed by the insn issue. */
495 automata_list_el_t important_automata_list
;
496 /* The following member is used to process insn once for output. */
500 /* This contains a declaration mentioned above. */
503 /* What node in the union? */
508 struct unit_decl unit
;
509 struct bypass_decl bypass
;
510 struct automaton_decl automaton
;
511 struct excl_rel_decl excl
;
512 struct unit_pattern_rel_decl presence
;
513 struct unit_pattern_rel_decl absence
;
514 struct reserv_decl reserv
;
515 struct insn_reserv_decl insn_reserv
;
519 /* The following structures represent parsed reservation strings. */
531 /* Cpu unit in reservation. */
535 unit_decl_t unit_decl
;
538 /* Define_reservation in a reservation. */
542 struct reserv_decl
*reserv_decl
;
545 /* Absence of reservation (represented by string `nothing'). */
546 struct nothing_regexp
548 /* This used to be empty but ISO C doesn't allow that. */
552 /* Representation of reservations separated by ',' (see file
554 struct sequence_regexp
557 regexp_t regexps
[1];
560 /* Representation of construction `repeat' (see file rtl.def). */
567 /* Representation of reservations separated by '+' (see file
572 regexp_t regexps
[1];
575 /* Representation of reservations separated by '|' (see file
580 regexp_t regexps
[1];
583 /* Representation of a reservation string. */
586 /* What node in the union? */
587 enum regexp_mode mode
;
591 struct unit_regexp unit
;
592 struct reserv_regexp reserv
;
593 struct nothing_regexp nothing
;
594 struct sequence_regexp sequence
;
595 struct repeat_regexp repeat
;
596 struct allof_regexp allof
;
597 struct oneof_regexp oneof
;
601 /* Represents description of pipeline hazard description based on
605 int decls_num
, normal_decls_num
;
607 /* The following fields are defined by checker. */
609 /* The following fields values are correspondingly number of all
610 units, query units, and insns in the description. */
614 /* The following field value is max length (in cycles) of
615 reservations of insns. The field value is defined only for
617 int max_insn_reserv_cycles
;
619 /* The following fields are defined by automaton generator. */
621 /* The following field value is the first automaton. */
622 automaton_t first_automaton
;
624 /* The following field is created by pipeline hazard parser and
625 contains all declarations. We allocate additional entries for
626 two special insns which are added by the automaton generator. */
631 /* The following nodes are created in automaton checker. */
633 /* The following nodes represent exclusion set for cpu units. Each
634 element is accessed through only one excl_list. */
637 unit_decl_t unit_decl
;
638 unit_set_el_t next_unit_set_el
;
641 /* The following nodes represent presence or absence pattern for cpu
642 units. Each element is accessed through only one presence_list or
644 struct pattern_set_el
646 /* The number of units in unit_decls. */
648 /* The units forming the pattern. */
649 struct unit_decl
**unit_decls
;
650 pattern_set_el_t next_pattern_set_el
;
654 /* The following nodes are created in automaton generator. */
657 /* The following nodes represent presence or absence pattern for cpu
658 units. Each element is accessed through only one element of
659 unit_presence_set_table or unit_absence_set_table. */
660 struct pattern_reserv
662 reserv_sets_t reserv
;
663 pattern_reserv_t next_pattern_reserv
;
666 /* The following node type describes state automaton. The state may
667 be deterministic or non-deterministic. Non-deterministic state has
668 several component states which represent alternative cpu units
669 reservations. The state also is used for describing a
670 deterministic reservation of automaton insn. */
673 /* The following member value is nonzero if there is a transition by
676 /* The following field is list of processor unit reservations on
678 reserv_sets_t reservs
;
679 /* The following field is unique number of given state between other
682 /* The following field value is automaton to which given state
684 automaton_t automaton
;
685 /* The following field value is the first arc output from given
688 unsigned int num_out_arcs
;
689 /* The following field is used to form NDFA. */
690 char it_was_placed_in_stack_for_NDFA_forming
;
691 /* The following field is used to form DFA. */
692 char it_was_placed_in_stack_for_DFA_forming
;
693 /* The following field is used to transform NDFA to DFA and DFA
694 minimization. The field value is not NULL if the state is a
695 compound state. In this case the value of field `unit_sets_list'
696 is NULL. All states in the list are in the hash table. The list
697 is formed through field `next_sorted_alt_state'. We should
698 support only one level of nesting state. */
699 alt_state_t component_states
;
700 /* The following field is used for passing graph of states. */
702 /* The list of states belonging to one equivalence class is formed
703 with the aid of the following field. */
704 state_t next_equiv_class_state
;
705 /* The two following fields are used during minimization of a finite
707 int equiv_class_num_1
, equiv_class_num_2
;
708 /* The following field is used during minimization of a finite state
709 automaton. The field value is state corresponding to equivalence
710 class to which given state belongs. */
711 state_t equiv_class_state
;
712 unsigned int *presence_signature
;
713 /* The following field value is the order number of given state.
714 The states in final DFA is enumerated with the aid of the
717 /* This member is used for passing states for searching minimal
720 /* The following member is used to evaluate min issue delay of insn
722 int min_insn_issue_delay
;
728 /* The following field refers for the state into which given arc
731 /* The following field describes that the insn issue (with cycle
732 advancing for special insn `cycle advancing' and without cycle
733 advancing for others) makes transition from given state to
734 another given state. */
736 /* The following field value is the next arc output from the same
739 /* List of arcs marked given insn is formed with the following
740 field. The field is used in transformation NDFA -> DFA. */
741 arc_t next_arc_marked_by_insn
;
744 /* The following node type describes a deterministic alternative in
745 non-deterministic state which characterizes cpu unit reservations
746 of automaton insn or which is part of NDFA. */
749 /* The following field is a deterministic state which characterizes
750 unit reservations of the instruction. */
752 /* The following field refers to the next state which characterizes
753 unit reservations of the instruction. */
754 alt_state_t next_alt_state
;
755 /* The following field refers to the next state in sorted list. */
756 alt_state_t next_sorted_alt_state
;
759 /* The following node type describes insn of automaton. They are
760 labels of FA arcs. */
763 /* The following field value is the corresponding insn declaration
765 struct insn_reserv_decl
*insn_reserv_decl
;
766 /* The following field value is the next insn declaration for an
769 /* The following field is states which characterize automaton unit
770 reservations of the instruction. The value can be NULL only if it
771 is special insn `cycle advancing'. */
772 alt_state_t alt_states
;
773 /* The following field is sorted list of states which characterize
774 automaton unit reservations of the instruction. The value can be
775 NULL only if it is special insn `cycle advancing'. */
776 alt_state_t sorted_alt_states
;
777 /* The following field refers the next automaton insn with
778 the same reservations. */
779 ainsn_t next_same_reservs_insn
;
780 /* The following field is flag of the first automaton insn with the
781 same reservations in the declaration list. Only arcs marked such
782 insn is present in the automaton. This significantly decreases
783 memory requirements especially when several automata are
785 char first_insn_with_same_reservs
;
786 /* The following member has nonzero value if there is arc from state of
787 the automaton marked by the ainsn. */
789 /* Cyclic list of insns of an equivalence class is formed with the
790 aid of the following field. */
791 ainsn_t next_equiv_class_insn
;
792 /* The following field value is nonzero if the insn declaration is
793 the first insn declaration with given equivalence number. */
794 char first_ainsn_with_given_equivalence_num
;
795 /* The following field is number of class of equivalence of insns.
796 It is necessary because many insns may be equivalent with the
797 point of view of pipeline hazards. */
798 int insn_equiv_class_num
;
799 /* The following member value is TRUE if there is an arc in the
800 automaton marked by the insn into another state. In other
801 words, the insn can change the state of the automaton. */
805 /* The following describes an automaton for PHR. */
808 /* The following field value is the list of insn declarations for
811 /* Pointers to the ainsns corresponding to the special reservations. */
812 ainsn_t advance_ainsn
, collapse_ainsn
;
814 /* The following field value is the corresponding automaton
815 declaration. This field is not NULL only if the automatic
816 partition on automata is not used. */
817 struct automaton_decl
*corresponding_automaton_decl
;
818 /* The following field value is the next automaton. */
819 automaton_t next_automaton
;
820 /* The following field is start state of FA. There are not unit
821 reservations in the state. */
823 /* The following field value is number of equivalence classes of
824 insns (see field `insn_equiv_class_num' in
825 `insn_reserv_decl'). */
826 int insn_equiv_classes_num
;
827 /* The following field value is number of states of final DFA. */
828 int achieved_states_num
;
829 /* The following field value is the order number (0, 1, ...) of
831 int automaton_order_num
;
832 /* The following fields contain statistics information about
833 building automaton. */
834 int NDFA_states_num
, DFA_states_num
;
835 /* The following field value is defined only if minimization of DFA
837 int minimal_DFA_states_num
;
838 int NDFA_arcs_num
, DFA_arcs_num
;
839 /* The following field value is defined only if minimization of DFA
841 int minimal_DFA_arcs_num
;
842 /* The following member refers for two table state x ainsn -> int.
843 ??? Above sentence is incomprehensible. */
844 state_ainsn_table_t trans_table
;
845 /* The following member value is maximal value of min issue delay
846 for insns of the automaton. */
848 /* Usually min issue delay is small and we can place several (2, 4,
849 8) elements in one vector element. So the compression factor can
850 be 1 (no compression), 2, 4, 8. */
851 int min_issue_delay_table_compression_factor
;
852 /* Total number of locked states in this automaton. */
856 /* The following is the element of the list of automata. */
857 struct automata_list_el
859 /* The automaton itself. */
860 automaton_t automaton
;
861 /* The next automata set element. */
862 automata_list_el_t next_automata_list_el
;
865 /* The following structure describes a table state X ainsn -> int(>= 0). */
866 struct state_ainsn_table
868 /* Automaton to which given table belongs. */
869 automaton_t automaton
;
870 /* The following tree vectors for comb vector implementation of the
872 vla_hwint_t comb_vect
;
873 vla_hwint_t check_vect
;
874 vla_hwint_t base_vect
;
875 /* This is simple implementation of the table. */
876 vla_hwint_t full_vect
;
877 /* Minimal and maximal values of the previous vectors. */
878 int min_comb_vect_el_value
, max_comb_vect_el_value
;
879 int min_base_vect_el_value
, max_base_vect_el_value
;
882 /* Macros to access members of unions. Use only them for access to
883 union members of declarations and regexps. */
885 #if defined ENABLE_CHECKING && (GCC_VERSION >= 2007)
887 #define DECL_UNIT(d) __extension__ \
888 (({ __typeof (d) const _decl = (d); \
889 if (_decl->mode != dm_unit) \
890 decl_mode_check_failed (_decl->mode, "dm_unit", \
891 __FILE__, __LINE__, __FUNCTION__); \
892 &(_decl)->decl.unit; }))
894 #define DECL_BYPASS(d) __extension__ \
895 (({ __typeof (d) const _decl = (d); \
896 if (_decl->mode != dm_bypass) \
897 decl_mode_check_failed (_decl->mode, "dm_bypass", \
898 __FILE__, __LINE__, __FUNCTION__); \
899 &(_decl)->decl.bypass; }))
901 #define DECL_AUTOMATON(d) __extension__ \
902 (({ __typeof (d) const _decl = (d); \
903 if (_decl->mode != dm_automaton) \
904 decl_mode_check_failed (_decl->mode, "dm_automaton", \
905 __FILE__, __LINE__, __FUNCTION__); \
906 &(_decl)->decl.automaton; }))
908 #define DECL_EXCL(d) __extension__ \
909 (({ __typeof (d) const _decl = (d); \
910 if (_decl->mode != dm_excl) \
911 decl_mode_check_failed (_decl->mode, "dm_excl", \
912 __FILE__, __LINE__, __FUNCTION__); \
913 &(_decl)->decl.excl; }))
915 #define DECL_PRESENCE(d) __extension__ \
916 (({ __typeof (d) const _decl = (d); \
917 if (_decl->mode != dm_presence) \
918 decl_mode_check_failed (_decl->mode, "dm_presence", \
919 __FILE__, __LINE__, __FUNCTION__); \
920 &(_decl)->decl.presence; }))
922 #define DECL_ABSENCE(d) __extension__ \
923 (({ __typeof (d) const _decl = (d); \
924 if (_decl->mode != dm_absence) \
925 decl_mode_check_failed (_decl->mode, "dm_absence", \
926 __FILE__, __LINE__, __FUNCTION__); \
927 &(_decl)->decl.absence; }))
929 #define DECL_RESERV(d) __extension__ \
930 (({ __typeof (d) const _decl = (d); \
931 if (_decl->mode != dm_reserv) \
932 decl_mode_check_failed (_decl->mode, "dm_reserv", \
933 __FILE__, __LINE__, __FUNCTION__); \
934 &(_decl)->decl.reserv; }))
936 #define DECL_INSN_RESERV(d) __extension__ \
937 (({ __typeof (d) const _decl = (d); \
938 if (_decl->mode != dm_insn_reserv) \
939 decl_mode_check_failed (_decl->mode, "dm_insn_reserv", \
940 __FILE__, __LINE__, __FUNCTION__); \
941 &(_decl)->decl.insn_reserv; }))
943 static const char *decl_name (enum decl_mode
);
944 static void decl_mode_check_failed (enum decl_mode
, const char *,
945 const char *, int, const char *)
948 /* Return string representation of declaration mode MODE. */
950 decl_name (enum decl_mode mode
)
952 static char str
[100];
956 else if (mode
== dm_bypass
)
958 else if (mode
== dm_automaton
)
959 return "dm_automaton";
960 else if (mode
== dm_excl
)
962 else if (mode
== dm_presence
)
963 return "dm_presence";
964 else if (mode
== dm_absence
)
966 else if (mode
== dm_reserv
)
968 else if (mode
== dm_insn_reserv
)
969 return "dm_insn_reserv";
971 sprintf (str
, "unknown (%d)", (int) mode
);
975 /* The function prints message about unexpected declaration and finish
978 decl_mode_check_failed (enum decl_mode mode
, const char *expected_mode_str
,
979 const char *file
, int line
, const char *func
)
983 "\n%s: %d: error in %s: DECL check: expected decl %s, have %s\n",
984 file
, line
, func
, expected_mode_str
, decl_name (mode
));
989 #define REGEXP_UNIT(r) __extension__ \
990 (({ struct regexp *const _regexp = (r); \
991 if (_regexp->mode != rm_unit) \
992 regexp_mode_check_failed (_regexp->mode, "rm_unit", \
993 __FILE__, __LINE__, __FUNCTION__); \
994 &(_regexp)->regexp.unit; }))
996 #define REGEXP_RESERV(r) __extension__ \
997 (({ struct regexp *const _regexp = (r); \
998 if (_regexp->mode != rm_reserv) \
999 regexp_mode_check_failed (_regexp->mode, "rm_reserv", \
1000 __FILE__, __LINE__, __FUNCTION__); \
1001 &(_regexp)->regexp.reserv; }))
1003 #define REGEXP_SEQUENCE(r) __extension__ \
1004 (({ struct regexp *const _regexp = (r); \
1005 if (_regexp->mode != rm_sequence) \
1006 regexp_mode_check_failed (_regexp->mode, "rm_sequence", \
1007 __FILE__, __LINE__, __FUNCTION__); \
1008 &(_regexp)->regexp.sequence; }))
1010 #define REGEXP_REPEAT(r) __extension__ \
1011 (({ struct regexp *const _regexp = (r); \
1012 if (_regexp->mode != rm_repeat) \
1013 regexp_mode_check_failed (_regexp->mode, "rm_repeat", \
1014 __FILE__, __LINE__, __FUNCTION__); \
1015 &(_regexp)->regexp.repeat; }))
1017 #define REGEXP_ALLOF(r) __extension__ \
1018 (({ struct regexp *const _regexp = (r); \
1019 if (_regexp->mode != rm_allof) \
1020 regexp_mode_check_failed (_regexp->mode, "rm_allof", \
1021 __FILE__, __LINE__, __FUNCTION__); \
1022 &(_regexp)->regexp.allof; }))
1024 #define REGEXP_ONEOF(r) __extension__ \
1025 (({ struct regexp *const _regexp = (r); \
1026 if (_regexp->mode != rm_oneof) \
1027 regexp_mode_check_failed (_regexp->mode, "rm_oneof", \
1028 __FILE__, __LINE__, __FUNCTION__); \
1029 &(_regexp)->regexp.oneof; }))
1031 static const char *regexp_name (enum regexp_mode
);
1032 static void regexp_mode_check_failed (enum regexp_mode
, const char *,
1034 const char *) ATTRIBUTE_NORETURN
;
1037 /* Return string representation of regexp mode MODE. */
1039 regexp_name (enum regexp_mode mode
)
1048 return "rm_nothing";
1050 return "rm_sequence";
1062 /* The function prints message about unexpected regexp and finish the
1065 regexp_mode_check_failed (enum regexp_mode mode
,
1066 const char *expected_mode_str
,
1067 const char *file
, int line
, const char *func
)
1071 "\n%s: %d: error in %s: REGEXP check: expected decl %s, have %s\n",
1072 file
, line
, func
, expected_mode_str
, regexp_name (mode
));
1076 #else /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */
1078 #define DECL_UNIT(d) (&(d)->decl.unit)
1079 #define DECL_BYPASS(d) (&(d)->decl.bypass)
1080 #define DECL_AUTOMATON(d) (&(d)->decl.automaton)
1081 #define DECL_EXCL(d) (&(d)->decl.excl)
1082 #define DECL_PRESENCE(d) (&(d)->decl.presence)
1083 #define DECL_ABSENCE(d) (&(d)->decl.absence)
1084 #define DECL_RESERV(d) (&(d)->decl.reserv)
1085 #define DECL_INSN_RESERV(d) (&(d)->decl.insn_reserv)
1087 #define REGEXP_UNIT(r) (&(r)->regexp.unit)
1088 #define REGEXP_RESERV(r) (&(r)->regexp.reserv)
1089 #define REGEXP_SEQUENCE(r) (&(r)->regexp.sequence)
1090 #define REGEXP_REPEAT(r) (&(r)->regexp.repeat)
1091 #define REGEXP_ALLOF(r) (&(r)->regexp.allof)
1092 #define REGEXP_ONEOF(r) (&(r)->regexp.oneof)
1094 #endif /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */
1096 #define XCREATENODE(T) ((T *) create_node (sizeof (T)))
1097 #define XCREATENODEVEC(T, N) ((T *) create_node (sizeof (T) * (N)))
1098 #define XCREATENODEVAR(T, S) ((T *) create_node ((S)))
1100 #define XCOPYNODE(T, P) ((T *) copy_node ((P), sizeof (T)))
1101 #define XCOPYNODEVEC(T, P, N) ((T *) copy_node ((P), sizeof (T) * (N)))
1102 #define XCOPYNODEVAR(T, P, S) ((T *) copy_node ((P), (S)))
1104 /* Create IR structure (node). */
1106 create_node (size_t size
)
1110 obstack_blank (&irp
, size
);
1111 result
= obstack_base (&irp
);
1112 obstack_finish (&irp
);
1113 /* Default values of members are NULL and zero. */
1114 memset (result
, 0, size
);
1118 /* Copy IR structure (node). */
1120 copy_node (const void *from
, size_t size
)
1122 void *const result
= create_node (size
);
1123 memcpy (result
, from
, size
);
1127 /* The function checks that NAME does not contain quotes (`"'). */
1129 check_name (const char * name
, pos_t pos ATTRIBUTE_UNUSED
)
1133 for (str
= name
; *str
!= '\0'; str
++)
1135 error ("Name `%s' contains quotes", name
);
1139 /* Pointers to all declarations during IR generation are stored in the
1141 static vec
<decl_t
> decls
;
1143 /* Given a pointer to a (char *) and a separator, return an alloc'ed
1144 string containing the next separated element, taking parentheses
1145 into account if PAR_FLAG has nonzero value. Advance the pointer to
1146 after the string scanned, or the end-of-string. Return NULL if at
1149 next_sep_el (const char **pstr
, int sep
, int par_flag
)
1156 /* Remove leading whitespaces. */
1157 while (ISSPACE ((int) **pstr
))
1164 for (pars_num
= 0, p
= *pstr
; *p
!= '\0'; p
++)
1166 if (par_flag
&& *p
== '(')
1168 else if (par_flag
&& *p
== ')')
1170 else if (pars_num
== 0 && *p
== sep
)
1172 if (pars_num
== 0 && ISSPACE ((int) *p
))
1176 for (; n_spaces
!= 0; n_spaces
--)
1177 obstack_1grow (&irp
, p
[-n_spaces
]);
1178 obstack_1grow (&irp
, *p
);
1181 obstack_1grow (&irp
, '\0');
1182 out_str
= obstack_base (&irp
);
1183 obstack_finish (&irp
);
1192 /* Given a string and a separator, return the number of separated
1193 elements in it, taking parentheses into account if PAR_FLAG has
1194 nonzero value. Return 0 for the null string, -1 if parentheses is
1197 n_sep_els (const char *s
, int sep
, int par_flag
)
1205 for (pars_num
= 0, n
= 1; *s
; s
++)
1206 if (par_flag
&& *s
== '(')
1208 else if (par_flag
&& *s
== ')')
1210 else if (pars_num
== 0 && *s
== sep
)
1213 return (pars_num
!= 0 ? -1 : n
);
1216 /* Given a string and a separator, return vector of strings which are
1217 elements in the string and number of elements through els_num.
1218 Take parentheses into account if PAREN_P has nonzero value. The
1219 function also inserts the end marker NULL at the end of vector.
1220 Return 0 for the null string, -1 if parentheses are not balanced. */
1222 get_str_vect (const char *str
, int *els_num
, int sep
, int paren_p
)
1229 *els_num
= n_sep_els (str
, sep
, paren_p
);
1232 obstack_blank (&irp
, sizeof (char *) * (*els_num
+ 1));
1233 vect
= (char **) obstack_base (&irp
);
1234 obstack_finish (&irp
);
1236 for (i
= 0; i
< *els_num
; i
++)
1237 vect
[i
] = next_sep_el (pstr
, sep
, paren_p
);
1238 trail
= next_sep_el (pstr
, sep
, paren_p
);
1239 gcc_assert (!trail
);
1244 /* Process a DEFINE_CPU_UNIT.
1246 This gives information about a unit contained in CPU. We fill a
1247 struct unit_decl with information used later by `expand_automata'. */
1249 gen_cpu_unit (rtx def
)
1252 char **str_cpu_units
;
1256 str_cpu_units
= get_str_vect (XSTR (def
, 0), &vect_length
, ',', FALSE
);
1257 if (str_cpu_units
== NULL
)
1258 fatal ("invalid string `%s' in define_cpu_unit", XSTR (def
, 0));
1259 for (i
= 0; i
< vect_length
; i
++)
1261 decl
= XCREATENODE (struct decl
);
1262 decl
->mode
= dm_unit
;
1264 DECL_UNIT (decl
)->name
= check_name (str_cpu_units
[i
], decl
->pos
);
1265 DECL_UNIT (decl
)->automaton_name
= XSTR (def
, 1);
1266 DECL_UNIT (decl
)->query_p
= 0;
1267 DECL_UNIT (decl
)->min_occ_cycle_num
= -1;
1268 DECL_UNIT (decl
)->in_set_p
= 0;
1269 decls
.safe_push (decl
);
1273 /* Process a DEFINE_QUERY_CPU_UNIT.
1275 This gives information about a unit contained in CPU. We fill a
1276 struct unit_decl with information used later by `expand_automata'. */
1278 gen_query_cpu_unit (rtx def
)
1281 char **str_cpu_units
;
1285 str_cpu_units
= get_str_vect (XSTR (def
, 0), &vect_length
, ',',
1287 if (str_cpu_units
== NULL
)
1288 fatal ("invalid string `%s' in define_query_cpu_unit", XSTR (def
, 0));
1289 for (i
= 0; i
< vect_length
; i
++)
1291 decl
= XCREATENODE (struct decl
);
1292 decl
->mode
= dm_unit
;
1294 DECL_UNIT (decl
)->name
= check_name (str_cpu_units
[i
], decl
->pos
);
1295 DECL_UNIT (decl
)->automaton_name
= XSTR (def
, 1);
1296 DECL_UNIT (decl
)->query_p
= 1;
1297 decls
.safe_push (decl
);
1301 /* Process a DEFINE_BYPASS.
1303 This gives information about a unit contained in the CPU. We fill
1304 in a struct bypass_decl with information used later by
1305 `expand_automata'. */
1307 gen_bypass (rtx def
)
1310 char **out_patterns
;
1316 out_patterns
= get_str_vect (XSTR (def
, 1), &out_length
, ',', FALSE
);
1317 if (out_patterns
== NULL
)
1318 fatal ("invalid string `%s' in define_bypass", XSTR (def
, 1));
1319 in_patterns
= get_str_vect (XSTR (def
, 2), &in_length
, ',', FALSE
);
1320 if (in_patterns
== NULL
)
1321 fatal ("invalid string `%s' in define_bypass", XSTR (def
, 2));
1322 for (i
= 0; i
< out_length
; i
++)
1323 for (j
= 0; j
< in_length
; j
++)
1325 decl
= XCREATENODE (struct decl
);
1326 decl
->mode
= dm_bypass
;
1328 DECL_BYPASS (decl
)->latency
= XINT (def
, 0);
1329 DECL_BYPASS (decl
)->out_pattern
= out_patterns
[i
];
1330 DECL_BYPASS (decl
)->in_pattern
= in_patterns
[j
];
1331 DECL_BYPASS (decl
)->bypass_guard_name
= XSTR (def
, 3);
1332 decls
.safe_push (decl
);
1336 /* Process an EXCLUSION_SET.
1338 This gives information about a cpu unit conflicts. We fill a
1339 struct excl_rel_decl (excl) with information used later by
1340 `expand_automata'. */
1342 gen_excl_set (rtx def
)
1345 char **first_str_cpu_units
;
1346 char **second_str_cpu_units
;
1347 int first_vect_length
;
1352 = get_str_vect (XSTR (def
, 0), &first_vect_length
, ',', FALSE
);
1353 if (first_str_cpu_units
== NULL
)
1354 fatal ("invalid first string `%s' in exclusion_set", XSTR (def
, 0));
1355 second_str_cpu_units
= get_str_vect (XSTR (def
, 1), &length
, ',',
1357 if (second_str_cpu_units
== NULL
)
1358 fatal ("invalid second string `%s' in exclusion_set", XSTR (def
, 1));
1359 length
+= first_vect_length
;
1360 decl
= XCREATENODEVAR (struct decl
, sizeof (struct decl
) + (length
- 1) * sizeof (char *));
1361 decl
->mode
= dm_excl
;
1363 DECL_EXCL (decl
)->all_names_num
= length
;
1364 DECL_EXCL (decl
)->first_list_length
= first_vect_length
;
1365 for (i
= 0; i
< length
; i
++)
1366 if (i
< first_vect_length
)
1367 DECL_EXCL (decl
)->names
[i
] = first_str_cpu_units
[i
];
1369 DECL_EXCL (decl
)->names
[i
]
1370 = second_str_cpu_units
[i
- first_vect_length
];
1371 decls
.safe_push (decl
);
1374 /* Process a PRESENCE_SET, a FINAL_PRESENCE_SET, an ABSENCE_SET,
1375 FINAL_ABSENCE_SET (it is depended on PRESENCE_P and FINAL_P).
1377 This gives information about a cpu unit reservation requirements.
1378 We fill a struct unit_pattern_rel_decl with information used later
1379 by `expand_automata'. */
1381 gen_presence_absence_set (rtx def
, int presence_p
, int final_p
)
1384 char **str_cpu_units
;
1385 char **str_pattern_lists
;
1386 char ***str_patterns
;
1387 int cpu_units_length
;
1389 int patterns_length
;
1392 str_cpu_units
= get_str_vect (XSTR (def
, 0), &cpu_units_length
, ',',
1394 if (str_cpu_units
== NULL
)
1397 ? "invalid first string `%s' in final_presence_set"
1398 : "invalid first string `%s' in presence_set")
1400 ? "invalid first string `%s' in final_absence_set"
1401 : "invalid first string `%s' in absence_set")),
1403 str_pattern_lists
= get_str_vect (XSTR (def
, 1),
1404 &patterns_length
, ',', FALSE
);
1405 if (str_pattern_lists
== NULL
)
1408 ? "invalid second string `%s' in final_presence_set"
1409 : "invalid second string `%s' in presence_set")
1411 ? "invalid second string `%s' in final_absence_set"
1412 : "invalid second string `%s' in absence_set")), XSTR (def
, 1));
1413 str_patterns
= XOBNEWVEC (&irp
, char **, patterns_length
);
1414 for (i
= 0; i
< patterns_length
; i
++)
1416 str_patterns
[i
] = get_str_vect (str_pattern_lists
[i
],
1417 &length
, ' ', FALSE
);
1418 gcc_assert (str_patterns
[i
]);
1420 decl
= XCREATENODE (struct decl
);
1424 decl
->mode
= dm_presence
;
1425 DECL_PRESENCE (decl
)->names_num
= cpu_units_length
;
1426 DECL_PRESENCE (decl
)->names
= str_cpu_units
;
1427 DECL_PRESENCE (decl
)->patterns
= str_patterns
;
1428 DECL_PRESENCE (decl
)->patterns_num
= patterns_length
;
1429 DECL_PRESENCE (decl
)->final_p
= final_p
;
1433 decl
->mode
= dm_absence
;
1434 DECL_ABSENCE (decl
)->names_num
= cpu_units_length
;
1435 DECL_ABSENCE (decl
)->names
= str_cpu_units
;
1436 DECL_ABSENCE (decl
)->patterns
= str_patterns
;
1437 DECL_ABSENCE (decl
)->patterns_num
= patterns_length
;
1438 DECL_ABSENCE (decl
)->final_p
= final_p
;
1440 decls
.safe_push (decl
);
1443 /* Process a PRESENCE_SET.
1445 This gives information about a cpu unit reservation requirements.
1446 We fill a struct unit_pattern_rel_decl (presence) with information
1447 used later by `expand_automata'. */
1449 gen_presence_set (rtx def
)
1451 gen_presence_absence_set (def
, TRUE
, FALSE
);
1454 /* Process a FINAL_PRESENCE_SET.
1456 This gives information about a cpu unit reservation requirements.
1457 We fill a struct unit_pattern_rel_decl (presence) with information
1458 used later by `expand_automata'. */
1460 gen_final_presence_set (rtx def
)
1462 gen_presence_absence_set (def
, TRUE
, TRUE
);
1465 /* Process an ABSENCE_SET.
1467 This gives information about a cpu unit reservation requirements.
1468 We fill a struct unit_pattern_rel_decl (absence) with information
1469 used later by `expand_automata'. */
1471 gen_absence_set (rtx def
)
1473 gen_presence_absence_set (def
, FALSE
, FALSE
);
1476 /* Process a FINAL_ABSENCE_SET.
1478 This gives information about a cpu unit reservation requirements.
1479 We fill a struct unit_pattern_rel_decl (absence) with information
1480 used later by `expand_automata'. */
1482 gen_final_absence_set (rtx def
)
1484 gen_presence_absence_set (def
, FALSE
, TRUE
);
1487 /* Process a DEFINE_AUTOMATON.
1489 This gives information about a finite state automaton used for
1490 recognizing pipeline hazards. We fill a struct automaton_decl
1491 with information used later by `expand_automata'. */
1493 gen_automaton (rtx def
)
1496 char **str_automata
;
1500 str_automata
= get_str_vect (XSTR (def
, 0), &vect_length
, ',', FALSE
);
1501 if (str_automata
== NULL
)
1502 fatal ("invalid string `%s' in define_automaton", XSTR (def
, 0));
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 (rtx def
)
1520 if (strcmp (XSTR (def
, 0), NO_MINIMIZATION_OPTION
+ 1) == 0)
1521 no_minimization_flag
= 1;
1522 else if (strcmp (XSTR (def
, 0), TIME_OPTION
+ 1) == 0)
1524 else if (strcmp (XSTR (def
, 0), STATS_OPTION
+ 1) == 0)
1526 else if (strcmp (XSTR (def
, 0), V_OPTION
+ 1) == 0)
1528 else if (strcmp (XSTR (def
, 0), W_OPTION
+ 1) == 0)
1530 else if (strcmp (XSTR (def
, 0), NDFA_OPTION
+ 1) == 0)
1532 else if (strcmp (XSTR (def
, 0), COLLAPSE_OPTION
+ 1) == 0)
1534 else if (strcmp (XSTR (def
, 0), NO_COMB_OPTION
+ 1) == 0)
1536 else if (strcmp (XSTR (def
, 0), PROGRESS_OPTION
+ 1) == 0)
1539 fatal ("invalid option `%s' in automata_option", XSTR (def
, 0));
1542 /* Name in reservation to denote absence reservation. */
1543 #define NOTHING_NAME "nothing"
1545 /* The following string contains original reservation string being
1547 static const char *reserv_str
;
1549 /* Parse an element in STR. */
1551 gen_regexp_el (const char *str
)
1560 if (str
[len
- 1] != ')')
1561 fatal ("garbage after ) in reservation `%s'", reserv_str
);
1562 dstr
= XALLOCAVAR (char, len
- 1);
1563 memcpy (dstr
, str
+ 1, len
- 2);
1564 dstr
[len
-2] = '\0';
1565 regexp
= gen_regexp_sequence (dstr
);
1567 else if (strcmp (str
, NOTHING_NAME
) == 0)
1569 regexp
= XCREATENODE (struct regexp
);
1570 regexp
->mode
= rm_nothing
;
1574 regexp
= XCREATENODE (struct regexp
);
1575 regexp
->mode
= rm_unit
;
1576 REGEXP_UNIT (regexp
)->name
= str
;
1581 /* Parse construction `repeat' in STR. */
1583 gen_regexp_repeat (const char *str
)
1591 repeat_vect
= get_str_vect (str
, &els_num
, '*', TRUE
);
1592 if (repeat_vect
== NULL
)
1593 fatal ("invalid `%s' in reservation `%s'", str
, reserv_str
);
1596 regexp
= gen_regexp_el (repeat_vect
[0]);
1597 for (i
= 1; i
< els_num
; i
++)
1599 repeat
= XCREATENODE (struct regexp
);
1600 repeat
->mode
= rm_repeat
;
1601 REGEXP_REPEAT (repeat
)->regexp
= regexp
;
1602 REGEXP_REPEAT (repeat
)->repeat_num
= atoi (repeat_vect
[i
]);
1603 if (REGEXP_REPEAT (repeat
)->repeat_num
<= 1)
1604 fatal ("repetition `%s' <= 1 in reservation `%s'",
1611 return gen_regexp_el (repeat_vect
[0]);
1614 /* Parse reservation STR which possibly contains separator '+'. */
1616 gen_regexp_allof (const char *str
)
1623 allof_vect
= get_str_vect (str
, &els_num
, '+', TRUE
);
1624 if (allof_vect
== NULL
)
1625 fatal ("invalid `%s' in reservation `%s'", str
, reserv_str
);
1628 allof
= XCREATENODEVAR (struct regexp
, sizeof (struct regexp
)
1629 + sizeof (regexp_t
) * (els_num
- 1));
1630 allof
->mode
= rm_allof
;
1631 REGEXP_ALLOF (allof
)->regexps_num
= els_num
;
1632 for (i
= 0; i
< els_num
; i
++)
1633 REGEXP_ALLOF (allof
)->regexps
[i
] = gen_regexp_repeat (allof_vect
[i
]);
1637 return gen_regexp_repeat (allof_vect
[0]);
1640 /* Parse reservation STR which possibly contains separator '|'. */
1642 gen_regexp_oneof (const char *str
)
1649 oneof_vect
= get_str_vect (str
, &els_num
, '|', TRUE
);
1650 if (oneof_vect
== NULL
)
1651 fatal ("invalid `%s' in reservation `%s'", str
, reserv_str
);
1654 oneof
= XCREATENODEVAR (struct regexp
, sizeof (struct regexp
)
1655 + sizeof (regexp_t
) * (els_num
- 1));
1656 oneof
->mode
= rm_oneof
;
1657 REGEXP_ONEOF (oneof
)->regexps_num
= els_num
;
1658 for (i
= 0; i
< els_num
; i
++)
1659 REGEXP_ONEOF (oneof
)->regexps
[i
] = gen_regexp_allof (oneof_vect
[i
]);
1663 return gen_regexp_allof (oneof_vect
[0]);
1666 /* Parse reservation STR which possibly contains separator ','. */
1668 gen_regexp_sequence (const char *str
)
1671 char **sequence_vect
;
1675 sequence_vect
= get_str_vect (str
, &els_num
, ',', TRUE
);
1678 sequence
= XCREATENODEVAR (struct regexp
, sizeof (struct regexp
)
1679 + sizeof (regexp_t
) * (els_num
- 1));
1680 sequence
->mode
= rm_sequence
;
1681 REGEXP_SEQUENCE (sequence
)->regexps_num
= els_num
;
1682 for (i
= 0; i
< els_num
; i
++)
1683 REGEXP_SEQUENCE (sequence
)->regexps
[i
]
1684 = gen_regexp_oneof (sequence_vect
[i
]);
1688 return gen_regexp_oneof (sequence_vect
[0]);
1691 /* Parse construction reservation STR. */
1693 gen_regexp (const char *str
)
1696 return gen_regexp_sequence (str
);
1699 /* Process a DEFINE_RESERVATION.
1701 This gives information about a reservation of cpu units. We fill
1702 in a struct reserv_decl with information used later by
1703 `expand_automata'. */
1705 gen_reserv (rtx def
)
1709 decl
= XCREATENODE (struct decl
);
1710 decl
->mode
= dm_reserv
;
1712 DECL_RESERV (decl
)->name
= check_name (XSTR (def
, 0), decl
->pos
);
1713 DECL_RESERV (decl
)->regexp
= gen_regexp (XSTR (def
, 1));
1714 decls
.safe_push (decl
);
1717 /* Process a DEFINE_INSN_RESERVATION.
1719 This gives information about the reservation of cpu units by an
1720 insn. We fill a struct insn_reserv_decl with information used
1721 later by `expand_automata'. */
1723 gen_insn_reserv (rtx def
)
1727 decl
= XCREATENODE (struct decl
);
1728 decl
->mode
= dm_insn_reserv
;
1730 DECL_INSN_RESERV (decl
)->name
1731 = check_name (XSTR (def
, 0), decl
->pos
);
1732 DECL_INSN_RESERV (decl
)->default_latency
= XINT (def
, 1);
1733 DECL_INSN_RESERV (decl
)->condexp
= XEXP (def
, 2);
1734 DECL_INSN_RESERV (decl
)->regexp
= gen_regexp (XSTR (def
, 3));
1735 decls
.safe_push (decl
);
1740 /* The function evaluates hash value (0..UINT_MAX) of string. */
1742 string_hash (const char *string
)
1746 for (result
= i
= 0;*string
++ != '\0'; i
++)
1747 result
+= ((unsigned char) *string
<< (i
% CHAR_BIT
));
1753 /* This page contains abstract data `table of automaton declarations'.
1754 Elements of the table is nodes representing automaton declarations.
1755 Key of the table elements is name of given automaton. Remember
1756 that automaton names have own space. */
1758 /* The function evaluates hash value of an automaton declaration. The
1759 function is used by abstract data `hashtab'. The function returns
1760 hash value (0..UINT_MAX) of given automaton declaration. */
1762 automaton_decl_hash (const void *automaton_decl
)
1764 const_decl_t
const decl
= (const_decl_t
) automaton_decl
;
1766 gcc_assert (decl
->mode
!= dm_automaton
1767 || DECL_AUTOMATON (decl
)->name
);
1768 return string_hash (DECL_AUTOMATON (decl
)->name
);
1771 /* The function tests automaton declarations on equality of their
1772 keys. The function is used by abstract data `hashtab'. The
1773 function returns 1 if the declarations have the same key, 0
1776 automaton_decl_eq_p (const void* automaton_decl_1
,
1777 const void* automaton_decl_2
)
1779 const_decl_t
const decl1
= (const_decl_t
) automaton_decl_1
;
1780 const_decl_t
const decl2
= (const_decl_t
) automaton_decl_2
;
1782 gcc_assert (decl1
->mode
== dm_automaton
1783 && DECL_AUTOMATON (decl1
)->name
1784 && decl2
->mode
== dm_automaton
1785 && DECL_AUTOMATON (decl2
)->name
);
1786 return strcmp (DECL_AUTOMATON (decl1
)->name
,
1787 DECL_AUTOMATON (decl2
)->name
) == 0;
1790 /* The automaton declaration table itself is represented by the
1791 following variable. */
1792 static htab_t automaton_decl_table
;
1794 /* The function inserts automaton declaration into the table. The
1795 function does nothing if an automaton declaration with the same key
1796 exists already in the table. The function returns automaton
1797 declaration node in the table with the same key as given automaton
1798 declaration node. */
1800 insert_automaton_decl (decl_t automaton_decl
)
1804 entry_ptr
= htab_find_slot (automaton_decl_table
, automaton_decl
, INSERT
);
1805 if (*entry_ptr
== NULL
)
1806 *entry_ptr
= (void *) automaton_decl
;
1807 return (decl_t
) *entry_ptr
;
1810 /* The following variable value is node representing automaton
1811 declaration. The node used for searching automaton declaration
1813 static struct decl work_automaton_decl
;
1815 /* The function searches for automaton declaration in the table with
1816 the same key as node representing name of the automaton
1817 declaration. The function returns node found in the table, NULL if
1818 such node does not exist in the table. */
1820 find_automaton_decl (const char *name
)
1824 work_automaton_decl
.mode
= dm_automaton
;
1825 DECL_AUTOMATON (&work_automaton_decl
)->name
= name
;
1826 entry
= htab_find (automaton_decl_table
, &work_automaton_decl
);
1827 return (decl_t
) entry
;
1830 /* The function creates empty automaton declaration table and node
1831 representing automaton declaration and used for searching automaton
1832 declaration with given name. The function must be called only once
1833 before any work with the automaton declaration table. */
1835 initiate_automaton_decl_table (void)
1837 work_automaton_decl
.mode
= dm_automaton
;
1838 automaton_decl_table
= htab_create (10, automaton_decl_hash
,
1839 automaton_decl_eq_p
, (htab_del
) 0);
1842 /* The function deletes the automaton declaration table. Only call of
1843 function `initiate_automaton_decl_table' is possible immediately
1844 after this function call. */
1846 finish_automaton_decl_table (void)
1848 htab_delete (automaton_decl_table
);
1853 /* This page contains abstract data `table of insn declarations'.
1854 Elements of the table is nodes representing insn declarations. Key
1855 of the table elements is name of given insn (in corresponding
1856 define_insn_reservation). Remember that insn names have own
1859 /* The function evaluates hash value of an insn declaration. The
1860 function is used by abstract data `hashtab'. The function returns
1861 hash value (0..UINT_MAX) of given insn declaration. */
1863 insn_decl_hash (const void *insn_decl
)
1865 const_decl_t
const decl
= (const_decl_t
) insn_decl
;
1867 gcc_assert (decl
->mode
== dm_insn_reserv
1868 && DECL_INSN_RESERV (decl
)->name
);
1869 return string_hash (DECL_INSN_RESERV (decl
)->name
);
1872 /* The function tests insn declarations on equality of their keys.
1873 The function is used by abstract data `hashtab'. The function
1874 returns 1 if declarations have the same key, 0 otherwise. */
1876 insn_decl_eq_p (const void *insn_decl_1
, const void *insn_decl_2
)
1878 const_decl_t
const decl1
= (const_decl_t
) insn_decl_1
;
1879 const_decl_t
const decl2
= (const_decl_t
) insn_decl_2
;
1881 gcc_assert (decl1
->mode
== dm_insn_reserv
1882 && DECL_INSN_RESERV (decl1
)->name
1883 && decl2
->mode
== dm_insn_reserv
1884 && DECL_INSN_RESERV (decl2
)->name
);
1885 return strcmp (DECL_INSN_RESERV (decl1
)->name
,
1886 DECL_INSN_RESERV (decl2
)->name
) == 0;
1889 /* The insn declaration table itself is represented by the following
1890 variable. The table does not contain insn reservation
1892 static htab_t insn_decl_table
;
1894 /* The function inserts insn declaration into the table. The function
1895 does nothing if an insn declaration with the same key exists
1896 already in the table. The function returns insn declaration node
1897 in the table with the same key as given insn declaration node. */
1899 insert_insn_decl (decl_t insn_decl
)
1903 entry_ptr
= htab_find_slot (insn_decl_table
, insn_decl
, INSERT
);
1904 if (*entry_ptr
== NULL
)
1905 *entry_ptr
= (void *) insn_decl
;
1906 return (decl_t
) *entry_ptr
;
1909 /* The following variable value is node representing insn reservation
1910 declaration. The node used for searching insn reservation
1911 declaration with given name. */
1912 static struct decl work_insn_decl
;
1914 /* The function searches for insn reservation declaration in the table
1915 with the same key as node representing name of the insn reservation
1916 declaration. The function returns node found in the table, NULL if
1917 such node does not exist in the table. */
1919 find_insn_decl (const char *name
)
1923 work_insn_decl
.mode
= dm_insn_reserv
;
1924 DECL_INSN_RESERV (&work_insn_decl
)->name
= name
;
1925 entry
= htab_find (insn_decl_table
, &work_insn_decl
);
1926 return (decl_t
) entry
;
1929 /* The function creates empty insn declaration table and node
1930 representing insn declaration and used for searching insn
1931 declaration with given name. The function must be called only once
1932 before any work with the insn declaration table. */
1934 initiate_insn_decl_table (void)
1936 work_insn_decl
.mode
= dm_insn_reserv
;
1937 insn_decl_table
= htab_create (10, insn_decl_hash
, insn_decl_eq_p
,
1941 /* The function deletes the insn declaration table. Only call of
1942 function `initiate_insn_decl_table' is possible immediately after
1943 this function call. */
1945 finish_insn_decl_table (void)
1947 htab_delete (insn_decl_table
);
1952 /* This page contains abstract data `table of declarations'. Elements
1953 of the table is nodes representing declarations (of units and
1954 reservations). Key of the table elements is names of given
1957 /* The function evaluates hash value of a declaration. The function
1958 is used by abstract data `hashtab'. The function returns hash
1959 value (0..UINT_MAX) of given declaration. */
1961 decl_hash (const void *decl
)
1963 const_decl_t
const d
= (const_decl_t
) decl
;
1965 gcc_assert ((d
->mode
== dm_unit
&& DECL_UNIT (d
)->name
)
1966 || (d
->mode
== dm_reserv
&& DECL_RESERV (d
)->name
));
1967 return string_hash (d
->mode
== dm_unit
1968 ? DECL_UNIT (d
)->name
: DECL_RESERV (d
)->name
);
1971 /* The function tests declarations on equality of their keys. The
1972 function is used by abstract data 'hashtab'. The function
1973 returns 1 if the declarations have the same key, 0 otherwise. */
1975 decl_eq_p (const void *decl_1
, const void *decl_2
)
1977 const_decl_t
const d1
= (const_decl_t
) decl_1
;
1978 const_decl_t
const d2
= (const_decl_t
) decl_2
;
1980 gcc_assert ((d1
->mode
== dm_unit
&& DECL_UNIT (d1
)->name
)
1981 || (d1
->mode
== dm_reserv
&& DECL_RESERV (d1
)->name
));
1982 gcc_assert ((d2
->mode
== dm_unit
&& DECL_UNIT (d2
)->name
)
1983 || (d2
->mode
== dm_reserv
&& DECL_RESERV (d2
)->name
));
1984 return strcmp ((d1
->mode
== dm_unit
1985 ? DECL_UNIT (d1
)->name
: DECL_RESERV (d1
)->name
),
1986 (d2
->mode
== dm_unit
1987 ? DECL_UNIT (d2
)->name
: DECL_RESERV (d2
)->name
)) == 0;
1990 /* The declaration table itself is represented by the following
1992 static htab_t decl_table
;
1994 /* The function inserts declaration into the table. The function does
1995 nothing if a declaration with the same key exists already in the
1996 table. The function returns declaration node in the table with the
1997 same key as given declaration node. */
2000 insert_decl (decl_t decl
)
2004 entry_ptr
= htab_find_slot (decl_table
, decl
, INSERT
);
2005 if (*entry_ptr
== NULL
)
2006 *entry_ptr
= (void *) decl
;
2007 return (decl_t
) *entry_ptr
;
2010 /* The following variable value is node representing declaration. The
2011 node used for searching declaration with given name. */
2012 static struct decl work_decl
;
2014 /* The function searches for declaration in the table with the same
2015 key as node representing name of the declaration. The function
2016 returns node found in the table, NULL if such node does not exist
2019 find_decl (const char *name
)
2023 work_decl
.mode
= dm_unit
;
2024 DECL_UNIT (&work_decl
)->name
= name
;
2025 entry
= htab_find (decl_table
, &work_decl
);
2026 return (decl_t
) entry
;
2029 /* The function creates empty declaration table and node representing
2030 declaration and used for searching declaration with given name.
2031 The function must be called only once before any work with the
2032 declaration table. */
2034 initiate_decl_table (void)
2036 work_decl
.mode
= dm_unit
;
2037 decl_table
= htab_create (10, decl_hash
, decl_eq_p
, (htab_del
) 0);
2040 /* The function deletes the declaration table. Only call of function
2041 `initiate_declaration_table' is possible immediately after this
2044 finish_decl_table (void)
2046 htab_delete (decl_table
);
2051 /* This page contains checker of pipeline hazard description. */
2053 /* Checking NAMES in an exclusion clause vector and returning formed
2054 unit_set_el_list. */
2055 static unit_set_el_t
2056 process_excls (char **names
, int num
, pos_t excl_pos ATTRIBUTE_UNUSED
)
2058 unit_set_el_t el_list
;
2059 unit_set_el_t last_el
;
2060 unit_set_el_t new_el
;
2061 decl_t decl_in_table
;
2066 for (i
= 0; i
< num
; i
++)
2068 decl_in_table
= find_decl (names
[i
]);
2069 if (decl_in_table
== NULL
)
2070 error ("unit `%s' in exclusion is not declared", names
[i
]);
2071 else if (decl_in_table
->mode
!= dm_unit
)
2072 error ("`%s' in exclusion is not unit", names
[i
]);
2075 new_el
= XCREATENODE (struct unit_set_el
);
2076 new_el
->unit_decl
= DECL_UNIT (decl_in_table
);
2077 new_el
->next_unit_set_el
= NULL
;
2078 if (last_el
== NULL
)
2079 el_list
= last_el
= new_el
;
2082 last_el
->next_unit_set_el
= new_el
;
2083 last_el
= last_el
->next_unit_set_el
;
2090 /* The function adds each element from SOURCE_LIST to the exclusion
2091 list of the each element from DEST_LIST. Checking situation "unit
2092 excludes itself". */
2094 add_excls (unit_set_el_t dest_list
, unit_set_el_t source_list
,
2095 pos_t excl_pos ATTRIBUTE_UNUSED
)
2099 unit_set_el_t curr_el
;
2100 unit_set_el_t prev_el
;
2103 for (dst
= dest_list
; dst
!= NULL
; dst
= dst
->next_unit_set_el
)
2104 for (src
= source_list
; src
!= NULL
; src
= src
->next_unit_set_el
)
2106 if (dst
->unit_decl
== src
->unit_decl
)
2108 error ("unit `%s' excludes itself", src
->unit_decl
->name
);
2111 if (dst
->unit_decl
->automaton_name
!= NULL
2112 && src
->unit_decl
->automaton_name
!= NULL
2113 && strcmp (dst
->unit_decl
->automaton_name
,
2114 src
->unit_decl
->automaton_name
) != 0)
2116 error ("units `%s' and `%s' in exclusion set belong to different automata",
2117 src
->unit_decl
->name
, dst
->unit_decl
->name
);
2120 for (curr_el
= dst
->unit_decl
->excl_list
, prev_el
= NULL
;
2122 prev_el
= curr_el
, curr_el
= curr_el
->next_unit_set_el
)
2123 if (curr_el
->unit_decl
== src
->unit_decl
)
2125 if (curr_el
== NULL
)
2127 /* Element not found - insert. */
2128 copy
= XCOPYNODE (struct unit_set_el
, src
);
2129 copy
->next_unit_set_el
= NULL
;
2130 if (prev_el
== NULL
)
2131 dst
->unit_decl
->excl_list
= copy
;
2133 prev_el
->next_unit_set_el
= copy
;
2138 /* Checking NAMES in presence/absence clause and returning the
2139 formed unit_set_el_list. The function is called only after
2140 processing all exclusion sets. */
2141 static unit_set_el_t
2142 process_presence_absence_names (char **names
, int num
,
2143 pos_t req_pos ATTRIBUTE_UNUSED
,
2144 int presence_p
, int final_p
)
2146 unit_set_el_t el_list
;
2147 unit_set_el_t last_el
;
2148 unit_set_el_t new_el
;
2149 decl_t decl_in_table
;
2154 for (i
= 0; i
< num
; i
++)
2156 decl_in_table
= find_decl (names
[i
]);
2157 if (decl_in_table
== NULL
)
2160 ? "unit `%s' in final presence set is not declared"
2161 : "unit `%s' in presence set is not declared")
2163 ? "unit `%s' in final absence set is not declared"
2164 : "unit `%s' in absence set is not declared")), names
[i
]);
2165 else if (decl_in_table
->mode
!= dm_unit
)
2168 ? "`%s' in final presence set is not unit"
2169 : "`%s' in presence set is not unit")
2171 ? "`%s' in final absence set is not unit"
2172 : "`%s' in absence set is not unit")), names
[i
]);
2175 new_el
= XCREATENODE (struct unit_set_el
);
2176 new_el
->unit_decl
= DECL_UNIT (decl_in_table
);
2177 new_el
->next_unit_set_el
= NULL
;
2178 if (last_el
== NULL
)
2179 el_list
= last_el
= new_el
;
2182 last_el
->next_unit_set_el
= new_el
;
2183 last_el
= last_el
->next_unit_set_el
;
2190 /* Checking NAMES in patterns of a presence/absence clause and
2191 returning the formed pattern_set_el_list. The function is called
2192 only after processing all exclusion sets. */
2193 static pattern_set_el_t
2194 process_presence_absence_patterns (char ***patterns
, int num
,
2195 pos_t req_pos ATTRIBUTE_UNUSED
,
2196 int presence_p
, int final_p
)
2198 pattern_set_el_t el_list
;
2199 pattern_set_el_t last_el
;
2200 pattern_set_el_t new_el
;
2201 decl_t decl_in_table
;
2206 for (i
= 0; i
< num
; i
++)
2208 for (j
= 0; patterns
[i
] [j
] != NULL
; j
++)
2210 new_el
= XCREATENODEVAR (struct pattern_set_el
,
2211 sizeof (struct pattern_set_el
)
2212 + sizeof (struct unit_decl
*) * j
);
2214 = (struct unit_decl
**) ((char *) new_el
2215 + sizeof (struct pattern_set_el
));
2216 new_el
->next_pattern_set_el
= NULL
;
2217 if (last_el
== NULL
)
2218 el_list
= last_el
= new_el
;
2221 last_el
->next_pattern_set_el
= new_el
;
2222 last_el
= last_el
->next_pattern_set_el
;
2224 new_el
->units_num
= 0;
2225 for (j
= 0; patterns
[i
] [j
] != NULL
; j
++)
2227 decl_in_table
= find_decl (patterns
[i
] [j
]);
2228 if (decl_in_table
== NULL
)
2231 ? "unit `%s' in final presence set is not declared"
2232 : "unit `%s' in presence set is not declared")
2234 ? "unit `%s' in final absence set is not declared"
2235 : "unit `%s' in absence set is not declared")),
2237 else if (decl_in_table
->mode
!= dm_unit
)
2240 ? "`%s' in final presence set is not unit"
2241 : "`%s' in presence set is not unit")
2243 ? "`%s' in final absence set is not unit"
2244 : "`%s' in absence set is not unit")),
2248 new_el
->unit_decls
[new_el
->units_num
]
2249 = DECL_UNIT (decl_in_table
);
2250 new_el
->units_num
++;
2257 /* The function adds each element from PATTERN_LIST to presence (if
2258 PRESENCE_P) or absence list of the each element from DEST_LIST.
2259 Checking situations "unit requires own absence", and "unit excludes
2260 and requires presence of ...", "unit requires absence and presence
2261 of ...", "units in (final) presence set belong to different
2262 automata", and "units in (final) absence set belong to different
2263 automata". Remember that we process absence sets only after all
2266 add_presence_absence (unit_set_el_t dest_list
,
2267 pattern_set_el_t pattern_list
,
2268 pos_t req_pos ATTRIBUTE_UNUSED
,
2269 int presence_p
, int final_p
)
2272 pattern_set_el_t pat
;
2273 struct unit_decl
*unit
;
2274 unit_set_el_t curr_excl_el
;
2275 pattern_set_el_t curr_pat_el
;
2276 pattern_set_el_t prev_el
;
2277 pattern_set_el_t copy
;
2281 for (dst
= dest_list
; dst
!= NULL
; dst
= dst
->next_unit_set_el
)
2282 for (pat
= pattern_list
; pat
!= NULL
; pat
= pat
->next_pattern_set_el
)
2284 for (i
= 0; i
< pat
->units_num
; i
++)
2286 unit
= pat
->unit_decls
[i
];
2287 if (dst
->unit_decl
== unit
&& pat
->units_num
== 1 && !presence_p
)
2289 error ("unit `%s' requires own absence", unit
->name
);
2292 if (dst
->unit_decl
->automaton_name
!= NULL
2293 && unit
->automaton_name
!= NULL
2294 && strcmp (dst
->unit_decl
->automaton_name
,
2295 unit
->automaton_name
) != 0)
2299 ? "units `%s' and `%s' in final presence set belong to different automata"
2300 : "units `%s' and `%s' in presence set belong to different automata")
2302 ? "units `%s' and `%s' in final absence set belong to different automata"
2303 : "units `%s' and `%s' in absence set belong to different automata")),
2304 unit
->name
, dst
->unit_decl
->name
);
2309 for (curr_excl_el
= dst
->unit_decl
->excl_list
;
2310 curr_excl_el
!= NULL
;
2311 curr_excl_el
= curr_excl_el
->next_unit_set_el
)
2313 if (unit
== curr_excl_el
->unit_decl
&& pat
->units_num
== 1)
2317 error ("unit `%s' excludes and requires presence of `%s'",
2318 dst
->unit_decl
->name
, unit
->name
);
2322 warning ("unit `%s' excludes and requires presence of `%s'",
2323 dst
->unit_decl
->name
, unit
->name
);
2326 else if (pat
->units_num
== 1)
2327 for (curr_pat_el
= dst
->unit_decl
->presence_list
;
2328 curr_pat_el
!= NULL
;
2329 curr_pat_el
= curr_pat_el
->next_pattern_set_el
)
2330 if (curr_pat_el
->units_num
== 1
2331 && unit
== curr_pat_el
->unit_decls
[0])
2335 error ("unit `%s' requires absence and presence of `%s'",
2336 dst
->unit_decl
->name
, unit
->name
);
2340 warning ("unit `%s' requires absence and presence of `%s'",
2341 dst
->unit_decl
->name
, unit
->name
);
2345 for (prev_el
= (presence_p
2347 ? dst
->unit_decl
->final_presence_list
2348 : dst
->unit_decl
->final_presence_list
)
2350 ? dst
->unit_decl
->final_absence_list
2351 : dst
->unit_decl
->absence_list
));
2352 prev_el
!= NULL
&& prev_el
->next_pattern_set_el
!= NULL
;
2353 prev_el
= prev_el
->next_pattern_set_el
)
2355 copy
= XCOPYNODE (struct pattern_set_el
, pat
);
2356 copy
->next_pattern_set_el
= NULL
;
2357 if (prev_el
== NULL
)
2362 dst
->unit_decl
->final_presence_list
= copy
;
2364 dst
->unit_decl
->presence_list
= copy
;
2367 dst
->unit_decl
->final_absence_list
= copy
;
2369 dst
->unit_decl
->absence_list
= copy
;
2372 prev_el
->next_pattern_set_el
= copy
;
2379 /* The function inserts BYPASS in the list of bypasses of the
2380 corresponding output insn. The order of bypasses in the list is
2381 described in a comment for member `bypass_list' (see above). If
2382 there is already the same bypass in the list the function reports
2383 this and does nothing. */
2385 insert_bypass (struct bypass_decl
*bypass
)
2387 struct bypass_decl
*curr
, *last
;
2388 struct insn_reserv_decl
*out_insn_reserv
= bypass
->out_insn_reserv
;
2389 struct insn_reserv_decl
*in_insn_reserv
= bypass
->in_insn_reserv
;
2391 for (curr
= out_insn_reserv
->bypass_list
, last
= NULL
;
2393 last
= curr
, curr
= curr
->next
)
2394 if (curr
->in_insn_reserv
== in_insn_reserv
)
2396 if ((bypass
->bypass_guard_name
!= NULL
2397 && curr
->bypass_guard_name
!= NULL
2398 && ! strcmp (bypass
->bypass_guard_name
, curr
->bypass_guard_name
))
2399 || bypass
->bypass_guard_name
== curr
->bypass_guard_name
)
2401 if (bypass
->bypass_guard_name
== NULL
)
2404 error ("the same bypass `%s - %s' is already defined",
2405 bypass
->out_pattern
, bypass
->in_pattern
);
2407 warning ("the same bypass `%s - %s' is already defined",
2408 bypass
->out_pattern
, bypass
->in_pattern
);
2411 error ("the same bypass `%s - %s' (guard %s) is already defined",
2412 bypass
->out_pattern
, bypass
->in_pattern
,
2413 bypass
->bypass_guard_name
);
2416 ("the same bypass `%s - %s' (guard %s) is already defined",
2417 bypass
->out_pattern
, bypass
->in_pattern
,
2418 bypass
->bypass_guard_name
);
2421 if (curr
->bypass_guard_name
== NULL
)
2423 if (curr
->next
== NULL
|| curr
->next
->in_insn_reserv
!= in_insn_reserv
)
2432 bypass
->next
= out_insn_reserv
->bypass_list
;
2433 out_insn_reserv
->bypass_list
= bypass
;
2437 bypass
->next
= last
->next
;
2438 last
->next
= bypass
;
2442 /* BYPASS is a define_bypass decl that includes glob pattern PATTERN.
2443 Call FN (BYPASS, INSN, DATA) for each matching instruction INSN. */
2446 for_each_matching_insn (decl_t bypass
, const char *pattern
,
2447 void (*fn
) (decl_t
, decl_t
, void *), void *data
)
2454 if (strpbrk (pattern
, "*?["))
2455 for (i
= 0; i
< description
->decls_num
; i
++)
2457 insn_reserv
= description
->decls
[i
];
2458 if (insn_reserv
->mode
== dm_insn_reserv
2459 && fnmatch (pattern
, DECL_INSN_RESERV (insn_reserv
)->name
, 0) == 0)
2461 fn (bypass
, insn_reserv
, data
);
2467 insn_reserv
= find_insn_decl (pattern
);
2470 fn (bypass
, insn_reserv
, data
);
2475 error ("there is no insn reservation that matches `%s'", pattern
);
2478 /* A subroutine of process_bypass that is called for each pair
2479 of matching instructions. OUT_INSN_RESERV is the output
2480 instruction and DATA is the input instruction. */
2483 process_bypass_2 (decl_t model
, decl_t out_insn_reserv
, void *data
)
2485 struct bypass_decl
*bypass
;
2486 decl_t in_insn_reserv
;
2488 in_insn_reserv
= (decl_t
) data
;
2489 if (strcmp (DECL_INSN_RESERV (in_insn_reserv
)->name
,
2490 DECL_BYPASS (model
)->in_pattern
) == 0
2491 && strcmp (DECL_INSN_RESERV (out_insn_reserv
)->name
,
2492 DECL_BYPASS (model
)->out_pattern
) == 0)
2493 bypass
= DECL_BYPASS (model
);
2496 bypass
= XCNEW (struct bypass_decl
);
2497 bypass
->latency
= DECL_BYPASS (model
)->latency
;
2498 bypass
->out_pattern
= DECL_INSN_RESERV (out_insn_reserv
)->name
;
2499 bypass
->in_pattern
= DECL_INSN_RESERV (in_insn_reserv
)->name
;
2500 bypass
->bypass_guard_name
= DECL_BYPASS (model
)->bypass_guard_name
;
2502 bypass
->out_insn_reserv
= DECL_INSN_RESERV (out_insn_reserv
);
2503 bypass
->in_insn_reserv
= DECL_INSN_RESERV (in_insn_reserv
);
2504 insert_bypass (bypass
);
2507 /* A subroutine of process_bypass that is called for each input
2508 instruction IN_INSN_RESERV. */
2511 process_bypass_1 (decl_t bypass
, decl_t in_insn_reserv
,
2512 void *data ATTRIBUTE_UNUSED
)
2514 for_each_matching_insn (bypass
, DECL_BYPASS (bypass
)->out_pattern
,
2515 process_bypass_2
, in_insn_reserv
);
2518 /* Process define_bypass decl BYPASS, inserting a bypass for each specific
2519 pair of insn reservations. */
2522 process_bypass (decl_t bypass
)
2524 for_each_matching_insn (bypass
, DECL_BYPASS (bypass
)->in_pattern
,
2525 process_bypass_1
, NULL
);
2528 /* The function processes pipeline description declarations, checks
2529 their correctness, and forms exclusion/presence/absence sets. */
2531 process_decls (void)
2534 decl_t automaton_decl
;
2535 decl_t decl_in_table
;
2536 int automaton_presence
;
2539 /* Checking repeated automata declarations. */
2540 automaton_presence
= 0;
2541 for (i
= 0; i
< description
->decls_num
; i
++)
2543 decl
= description
->decls
[i
];
2544 if (decl
->mode
== dm_automaton
)
2546 automaton_presence
= 1;
2547 decl_in_table
= insert_automaton_decl (decl
);
2548 if (decl_in_table
!= decl
)
2551 error ("repeated declaration of automaton `%s'",
2552 DECL_AUTOMATON (decl
)->name
);
2554 warning ("repeated declaration of automaton `%s'",
2555 DECL_AUTOMATON (decl
)->name
);
2559 /* Checking undeclared automata, repeated declarations (except for
2560 automata) and correctness of their attributes (insn latency times
2562 for (i
= 0; i
< description
->decls_num
; i
++)
2564 decl
= description
->decls
[i
];
2565 if (decl
->mode
== dm_insn_reserv
)
2567 if (DECL_INSN_RESERV (decl
)->default_latency
< 0)
2568 error ("define_insn_reservation `%s' has negative latency time",
2569 DECL_INSN_RESERV (decl
)->name
);
2570 DECL_INSN_RESERV (decl
)->insn_num
= description
->insns_num
;
2571 description
->insns_num
++;
2572 decl_in_table
= insert_insn_decl (decl
);
2573 if (decl_in_table
!= decl
)
2574 error ("`%s' is already used as insn reservation name",
2575 DECL_INSN_RESERV (decl
)->name
);
2577 else if (decl
->mode
== dm_bypass
)
2579 if (DECL_BYPASS (decl
)->latency
< 0)
2580 error ("define_bypass `%s - %s' has negative latency time",
2581 DECL_BYPASS (decl
)->out_pattern
,
2582 DECL_BYPASS (decl
)->in_pattern
);
2584 else if (decl
->mode
== dm_unit
|| decl
->mode
== dm_reserv
)
2586 if (decl
->mode
== dm_unit
)
2588 DECL_UNIT (decl
)->automaton_decl
= NULL
;
2589 if (DECL_UNIT (decl
)->automaton_name
!= NULL
)
2592 = find_automaton_decl (DECL_UNIT (decl
)->automaton_name
);
2593 if (automaton_decl
== NULL
)
2594 error ("automaton `%s' is not declared",
2595 DECL_UNIT (decl
)->automaton_name
);
2598 DECL_AUTOMATON (automaton_decl
)->automaton_is_used
= 1;
2599 DECL_UNIT (decl
)->automaton_decl
2600 = DECL_AUTOMATON (automaton_decl
);
2603 else if (automaton_presence
)
2604 error ("define_unit `%s' without automaton when one defined",
2605 DECL_UNIT (decl
)->name
);
2606 DECL_UNIT (decl
)->unit_num
= description
->units_num
;
2607 description
->units_num
++;
2608 if (strcmp (DECL_UNIT (decl
)->name
, NOTHING_NAME
) == 0)
2610 error ("`%s' is declared as cpu unit", NOTHING_NAME
);
2613 decl_in_table
= find_decl (DECL_UNIT (decl
)->name
);
2617 if (strcmp (DECL_RESERV (decl
)->name
, NOTHING_NAME
) == 0)
2619 error ("`%s' is declared as cpu reservation", NOTHING_NAME
);
2622 decl_in_table
= find_decl (DECL_RESERV (decl
)->name
);
2624 if (decl_in_table
== NULL
)
2625 decl_in_table
= insert_decl (decl
);
2628 if (decl
->mode
== dm_unit
)
2629 error ("repeated declaration of unit `%s'",
2630 DECL_UNIT (decl
)->name
);
2632 error ("repeated declaration of reservation `%s'",
2633 DECL_RESERV (decl
)->name
);
2637 /* Check bypasses and form list of bypasses for each (output)
2639 for (i
= 0; i
< description
->decls_num
; i
++)
2641 decl
= description
->decls
[i
];
2642 if (decl
->mode
== dm_bypass
)
2643 process_bypass (decl
);
2646 /* Check exclusion set declarations and form exclusion sets. */
2647 for (i
= 0; i
< description
->decls_num
; i
++)
2649 decl
= description
->decls
[i
];
2650 if (decl
->mode
== dm_excl
)
2652 unit_set_el_t unit_set_el_list
;
2653 unit_set_el_t unit_set_el_list_2
;
2656 = process_excls (DECL_EXCL (decl
)->names
,
2657 DECL_EXCL (decl
)->first_list_length
, decl
->pos
);
2659 = process_excls (&DECL_EXCL (decl
)->names
2660 [DECL_EXCL (decl
)->first_list_length
],
2661 DECL_EXCL (decl
)->all_names_num
2662 - DECL_EXCL (decl
)->first_list_length
,
2664 add_excls (unit_set_el_list
, unit_set_el_list_2
, decl
->pos
);
2665 add_excls (unit_set_el_list_2
, unit_set_el_list
, decl
->pos
);
2669 /* Check presence set declarations and form presence sets. */
2670 for (i
= 0; i
< description
->decls_num
; i
++)
2672 decl
= description
->decls
[i
];
2673 if (decl
->mode
== dm_presence
)
2675 unit_set_el_t unit_set_el_list
;
2676 pattern_set_el_t pattern_set_el_list
;
2679 = process_presence_absence_names
2680 (DECL_PRESENCE (decl
)->names
, DECL_PRESENCE (decl
)->names_num
,
2681 decl
->pos
, TRUE
, DECL_PRESENCE (decl
)->final_p
);
2683 = process_presence_absence_patterns
2684 (DECL_PRESENCE (decl
)->patterns
,
2685 DECL_PRESENCE (decl
)->patterns_num
,
2686 decl
->pos
, TRUE
, DECL_PRESENCE (decl
)->final_p
);
2687 add_presence_absence (unit_set_el_list
, pattern_set_el_list
,
2689 DECL_PRESENCE (decl
)->final_p
);
2693 /* Check absence set declarations and form absence sets. */
2694 for (i
= 0; i
< description
->decls_num
; i
++)
2696 decl
= description
->decls
[i
];
2697 if (decl
->mode
== dm_absence
)
2699 unit_set_el_t unit_set_el_list
;
2700 pattern_set_el_t pattern_set_el_list
;
2703 = process_presence_absence_names
2704 (DECL_ABSENCE (decl
)->names
, DECL_ABSENCE (decl
)->names_num
,
2705 decl
->pos
, FALSE
, DECL_ABSENCE (decl
)->final_p
);
2707 = process_presence_absence_patterns
2708 (DECL_ABSENCE (decl
)->patterns
,
2709 DECL_ABSENCE (decl
)->patterns_num
,
2710 decl
->pos
, FALSE
, DECL_ABSENCE (decl
)->final_p
);
2711 add_presence_absence (unit_set_el_list
, pattern_set_el_list
,
2713 DECL_ABSENCE (decl
)->final_p
);
2718 /* The following function checks that declared automaton is used. If
2719 the automaton is not used, the function fixes error/warning. The
2720 following function must be called only after `process_decls'. */
2722 check_automaton_usage (void)
2727 for (i
= 0; i
< description
->decls_num
; i
++)
2729 decl
= description
->decls
[i
];
2730 if (decl
->mode
== dm_automaton
2731 && !DECL_AUTOMATON (decl
)->automaton_is_used
)
2734 error ("automaton `%s' is not used", DECL_AUTOMATON (decl
)->name
);
2736 warning ("automaton `%s' is not used",
2737 DECL_AUTOMATON (decl
)->name
);
2742 /* The following recursive function processes all regexp in order to
2743 fix usage of units or reservations and to fix errors of undeclared
2744 name. The function may change unit_regexp onto reserv_regexp.
2745 Remember that reserv_regexp does not exist before the function
2748 process_regexp (regexp_t regexp
)
2750 decl_t decl_in_table
;
2751 regexp_t new_regexp
;
2754 switch (regexp
->mode
)
2757 decl_in_table
= find_decl (REGEXP_UNIT (regexp
)->name
);
2758 if (decl_in_table
== NULL
)
2759 error ("undeclared unit or reservation `%s'",
2760 REGEXP_UNIT (regexp
)->name
);
2762 switch (decl_in_table
->mode
)
2765 DECL_UNIT (decl_in_table
)->unit_is_used
= 1;
2766 REGEXP_UNIT (regexp
)->unit_decl
= DECL_UNIT (decl_in_table
);
2770 DECL_RESERV (decl_in_table
)->reserv_is_used
= 1;
2771 new_regexp
= XCREATENODE (struct regexp
);
2772 new_regexp
->mode
= rm_reserv
;
2773 new_regexp
->pos
= regexp
->pos
;
2774 REGEXP_RESERV (new_regexp
)->name
= REGEXP_UNIT (regexp
)->name
;
2775 REGEXP_RESERV (new_regexp
)->reserv_decl
2776 = DECL_RESERV (decl_in_table
);
2777 regexp
= new_regexp
;
2785 for (i
= 0; i
<REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
2786 REGEXP_SEQUENCE (regexp
)->regexps
[i
]
2787 = process_regexp (REGEXP_SEQUENCE (regexp
)->regexps
[i
]);
2790 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
2791 REGEXP_ALLOF (regexp
)->regexps
[i
]
2792 = process_regexp (REGEXP_ALLOF (regexp
)->regexps
[i
]);
2795 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
2796 REGEXP_ONEOF (regexp
)->regexps
[i
]
2797 = process_regexp (REGEXP_ONEOF (regexp
)->regexps
[i
]);
2800 REGEXP_REPEAT (regexp
)->regexp
2801 = process_regexp (REGEXP_REPEAT (regexp
)->regexp
);
2811 /* The following function processes regexp of define_reservation and
2812 define_insn_reservation with the aid of function
2813 `process_regexp'. */
2815 process_regexp_decls (void)
2820 for (i
= 0; i
< description
->decls_num
; i
++)
2822 decl
= description
->decls
[i
];
2823 if (decl
->mode
== dm_reserv
)
2824 DECL_RESERV (decl
)->regexp
2825 = process_regexp (DECL_RESERV (decl
)->regexp
);
2826 else if (decl
->mode
== dm_insn_reserv
)
2827 DECL_INSN_RESERV (decl
)->regexp
2828 = process_regexp (DECL_INSN_RESERV (decl
)->regexp
);
2832 /* The following function checks that declared unit is used. If the
2833 unit is not used, the function fixes errors/warnings. The
2834 following function must be called only after `process_decls',
2835 `process_regexp_decls'. */
2842 for (i
= 0; i
< description
->decls_num
; i
++)
2844 decl
= description
->decls
[i
];
2845 if (decl
->mode
== dm_unit
&& !DECL_UNIT (decl
)->unit_is_used
)
2848 error ("unit `%s' is not used", DECL_UNIT (decl
)->name
);
2850 warning ("unit `%s' is not used", DECL_UNIT (decl
)->name
);
2852 else if (decl
->mode
== dm_reserv
&& !DECL_RESERV (decl
)->reserv_is_used
)
2855 error ("reservation `%s' is not used", DECL_RESERV (decl
)->name
);
2857 warning ("reservation `%s' is not used", DECL_RESERV (decl
)->name
);
2862 /* The following variable value is number of reservation being
2863 processed on loop recognition. */
2864 static int curr_loop_pass_num
;
2866 /* The following recursive function returns nonzero value if REGEXP
2867 contains given decl or reservations in given regexp refers for
2870 loop_in_regexp (regexp_t regexp
, decl_t start_decl
)
2876 switch (regexp
->mode
)
2882 if (start_decl
->mode
== dm_reserv
2883 && REGEXP_RESERV (regexp
)->reserv_decl
== DECL_RESERV (start_decl
))
2885 else if (REGEXP_RESERV (regexp
)->reserv_decl
->loop_pass_num
2886 == curr_loop_pass_num
)
2887 /* declaration has been processed. */
2891 REGEXP_RESERV (regexp
)->reserv_decl
->loop_pass_num
2892 = curr_loop_pass_num
;
2893 return loop_in_regexp (REGEXP_RESERV (regexp
)->reserv_decl
->regexp
,
2898 for (i
= 0; i
<REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
2899 if (loop_in_regexp (REGEXP_SEQUENCE (regexp
)->regexps
[i
], start_decl
))
2904 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
2905 if (loop_in_regexp (REGEXP_ALLOF (regexp
)->regexps
[i
], start_decl
))
2910 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
2911 if (loop_in_regexp (REGEXP_ONEOF (regexp
)->regexps
[i
], start_decl
))
2916 return loop_in_regexp (REGEXP_REPEAT (regexp
)->regexp
, start_decl
);
2926 /* The following function fixes errors "cycle in definition ...". The
2927 function uses function `loop_in_regexp' for that. */
2929 check_loops_in_regexps (void)
2934 for (i
= 0; i
< description
->decls_num
; i
++)
2936 decl
= description
->decls
[i
];
2937 if (decl
->mode
== dm_reserv
)
2938 DECL_RESERV (decl
)->loop_pass_num
= 0;
2940 for (i
= 0; i
< description
->decls_num
; i
++)
2942 decl
= description
->decls
[i
];
2943 curr_loop_pass_num
= i
;
2945 if (decl
->mode
== dm_reserv
)
2947 DECL_RESERV (decl
)->loop_pass_num
= curr_loop_pass_num
;
2948 if (loop_in_regexp (DECL_RESERV (decl
)->regexp
, decl
))
2950 gcc_assert (DECL_RESERV (decl
)->regexp
);
2951 error ("cycle in definition of reservation `%s'",
2952 DECL_RESERV (decl
)->name
);
2958 /* The function recursively processes IR of reservation and defines
2959 max and min cycle for reservation of unit. */
2961 process_regexp_cycles (regexp_t regexp
, int max_start_cycle
,
2962 int min_start_cycle
, int *max_finish_cycle
,
2963 int *min_finish_cycle
)
2967 switch (regexp
->mode
)
2970 if (REGEXP_UNIT (regexp
)->unit_decl
->max_occ_cycle_num
< max_start_cycle
)
2971 REGEXP_UNIT (regexp
)->unit_decl
->max_occ_cycle_num
= max_start_cycle
;
2972 if (REGEXP_UNIT (regexp
)->unit_decl
->min_occ_cycle_num
> min_start_cycle
2973 || REGEXP_UNIT (regexp
)->unit_decl
->min_occ_cycle_num
== -1)
2974 REGEXP_UNIT (regexp
)->unit_decl
->min_occ_cycle_num
= min_start_cycle
;
2975 *max_finish_cycle
= max_start_cycle
;
2976 *min_finish_cycle
= min_start_cycle
;
2980 process_regexp_cycles (REGEXP_RESERV (regexp
)->reserv_decl
->regexp
,
2981 max_start_cycle
, min_start_cycle
,
2982 max_finish_cycle
, min_finish_cycle
);
2986 for (i
= 0; i
< REGEXP_REPEAT (regexp
)->repeat_num
; i
++)
2988 process_regexp_cycles (REGEXP_REPEAT (regexp
)->regexp
,
2989 max_start_cycle
, min_start_cycle
,
2990 max_finish_cycle
, min_finish_cycle
);
2991 max_start_cycle
= *max_finish_cycle
+ 1;
2992 min_start_cycle
= *min_finish_cycle
+ 1;
2997 for (i
= 0; i
<REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
2999 process_regexp_cycles (REGEXP_SEQUENCE (regexp
)->regexps
[i
],
3000 max_start_cycle
, min_start_cycle
,
3001 max_finish_cycle
, min_finish_cycle
);
3002 max_start_cycle
= *max_finish_cycle
+ 1;
3003 min_start_cycle
= *min_finish_cycle
+ 1;
3012 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
3014 process_regexp_cycles (REGEXP_ALLOF (regexp
)->regexps
[i
],
3015 max_start_cycle
, min_start_cycle
,
3016 max_finish_cycle
, min_finish_cycle
);
3017 if (max_cycle
< *max_finish_cycle
)
3018 max_cycle
= *max_finish_cycle
;
3019 if (i
== 0 || min_cycle
> *min_finish_cycle
)
3020 min_cycle
= *min_finish_cycle
;
3022 *max_finish_cycle
= max_cycle
;
3023 *min_finish_cycle
= min_cycle
;
3032 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
3034 process_regexp_cycles (REGEXP_ONEOF (regexp
)->regexps
[i
],
3035 max_start_cycle
, min_start_cycle
,
3036 max_finish_cycle
, min_finish_cycle
);
3037 if (max_cycle
< *max_finish_cycle
)
3038 max_cycle
= *max_finish_cycle
;
3039 if (i
== 0 || min_cycle
> *min_finish_cycle
)
3040 min_cycle
= *min_finish_cycle
;
3042 *max_finish_cycle
= max_cycle
;
3043 *min_finish_cycle
= min_cycle
;
3048 *max_finish_cycle
= max_start_cycle
;
3049 *min_finish_cycle
= min_start_cycle
;
3057 /* The following function is called only for correct program. The
3058 function defines max reservation of insns in cycles. */
3060 evaluate_max_reserv_cycles (void)
3062 int max_insn_cycles_num
;
3063 int min_insn_cycles_num
;
3067 description
->max_insn_reserv_cycles
= 0;
3068 for (i
= 0; i
< description
->decls_num
; i
++)
3070 decl
= description
->decls
[i
];
3071 if (decl
->mode
== dm_insn_reserv
)
3073 process_regexp_cycles (DECL_INSN_RESERV (decl
)->regexp
, 0, 0,
3074 &max_insn_cycles_num
, &min_insn_cycles_num
);
3075 if (description
->max_insn_reserv_cycles
< max_insn_cycles_num
)
3076 description
->max_insn_reserv_cycles
= max_insn_cycles_num
;
3079 description
->max_insn_reserv_cycles
++;
3082 /* The following function calls functions for checking all
3085 check_all_description (void)
3088 check_automaton_usage ();
3089 process_regexp_decls ();
3091 check_loops_in_regexps ();
3093 evaluate_max_reserv_cycles ();
3098 /* The page contains abstract data `ticker'. This data is used to
3099 report time of different phases of building automata. It is
3100 possibly to write a description for which automata will be built
3101 during several minutes even on fast machine. */
3103 /* The following function creates ticker and makes it active. */
3105 create_ticker (void)
3109 ticker
.modified_creation_time
= get_run_time ();
3110 ticker
.incremented_off_time
= 0;
3114 /* The following function switches off given ticker. */
3116 ticker_off (ticker_t
*ticker
)
3118 if (ticker
->incremented_off_time
== 0)
3119 ticker
->incremented_off_time
= get_run_time () + 1;
3122 /* The following function switches on given ticker. */
3124 ticker_on (ticker_t
*ticker
)
3126 if (ticker
->incremented_off_time
!= 0)
3128 ticker
->modified_creation_time
3129 += get_run_time () - ticker
->incremented_off_time
+ 1;
3130 ticker
->incremented_off_time
= 0;
3134 /* The following function returns current time in milliseconds since
3135 the moment when given ticker was created. */
3137 active_time (ticker_t ticker
)
3139 if (ticker
.incremented_off_time
!= 0)
3140 return ticker
.incremented_off_time
- 1 - ticker
.modified_creation_time
;
3142 return get_run_time () - ticker
.modified_creation_time
;
3145 /* The following function returns string representation of active time
3146 of given ticker. The result is string representation of seconds
3147 with accuracy of 1/100 second. Only result of the last call of the
3148 function exists. Therefore the following code is not correct
3150 printf ("parser time: %s\ngeneration time: %s\n",
3151 active_time_string (parser_ticker),
3152 active_time_string (generation_ticker));
3154 Correct code has to be the following
3156 printf ("parser time: %s\n", active_time_string (parser_ticker));
3157 printf ("generation time: %s\n",
3158 active_time_string (generation_ticker));
3162 print_active_time (FILE *f
, ticker_t ticker
)
3166 msecs
= active_time (ticker
);
3167 fprintf (f
, "%d.%06d", msecs
/ 1000000, msecs
% 1000000);
3172 /* The following variable value is number of automaton which are
3173 really being created. This value is defined on the base of
3174 argument of option `-split'. If the variable has zero value the
3175 number of automata is defined by the constructions `%automaton'.
3176 This case occurs when option `-split' is absent or has zero
3177 argument. If constructions `define_automaton' is absent only one
3178 automaton is created. */
3179 static int automata_num
;
3181 /* The following variable values are times of
3182 o transformation of regular expressions
3183 o building NDFA (DFA if !ndfa_flag)
3184 o NDFA -> DFA (simply the same automaton if !ndfa_flag)
3186 o building insn equivalence classes
3189 static ticker_t transform_time
;
3190 static ticker_t NDFA_time
;
3191 static ticker_t NDFA_to_DFA_time
;
3192 static ticker_t minimize_time
;
3193 static ticker_t equiv_time
;
3194 static ticker_t automaton_generation_time
;
3195 static ticker_t output_time
;
3197 /* The following variable values are times of
3200 all pipeline hazard translator work */
3201 static ticker_t check_time
;
3202 static ticker_t generation_time
;
3203 static ticker_t all_time
;
3207 /* Pseudo insn decl which denotes advancing cycle. */
3208 static decl_t advance_cycle_insn_decl
;
3209 /* Pseudo insn decl which denotes collapsing the NDFA state. */
3210 static decl_t collapse_ndfa_insn_decl
;
3212 /* Create and record a decl for the special advance-cycle transition. */
3214 add_advance_cycle_insn_decl (void)
3216 advance_cycle_insn_decl
= XCREATENODE (struct decl
);
3217 advance_cycle_insn_decl
->mode
= dm_insn_reserv
;
3218 advance_cycle_insn_decl
->pos
= no_pos
;
3219 DECL_INSN_RESERV (advance_cycle_insn_decl
)->regexp
= NULL
;
3220 DECL_INSN_RESERV (advance_cycle_insn_decl
)->name
= "$advance_cycle";
3221 DECL_INSN_RESERV (advance_cycle_insn_decl
)->insn_num
3222 = description
->insns_num
;
3223 description
->decls
[description
->decls_num
] = advance_cycle_insn_decl
;
3224 description
->decls_num
++;
3225 description
->insns_num
++;
3228 /* Create and record a decl for the special collapse-NDFA transition. */
3230 add_collapse_ndfa_insn_decl (void)
3232 collapse_ndfa_insn_decl
= XCREATENODE (struct decl
);
3233 collapse_ndfa_insn_decl
->mode
= dm_insn_reserv
;
3234 collapse_ndfa_insn_decl
->pos
= no_pos
;
3235 DECL_INSN_RESERV (collapse_ndfa_insn_decl
)->regexp
= NULL
;
3236 DECL_INSN_RESERV (collapse_ndfa_insn_decl
)->name
= "$collapse_ndfa";
3237 DECL_INSN_RESERV (collapse_ndfa_insn_decl
)->insn_num
3238 = description
->insns_num
;
3239 description
->decls
[description
->decls_num
] = collapse_ndfa_insn_decl
;
3240 description
->decls_num
++;
3241 description
->insns_num
++;
3244 /* True if DECL is either of the two special decls we created. */
3246 special_decl_p (struct insn_reserv_decl
*decl
)
3248 return (decl
== DECL_INSN_RESERV (advance_cycle_insn_decl
)
3250 && decl
== DECL_INSN_RESERV (collapse_ndfa_insn_decl
)));
3254 /* Abstract data `alternative states' which represents
3255 nondeterministic nature of the description (see comments for
3256 structures alt_state and state). */
3258 /* List of free states. */
3259 static alt_state_t first_free_alt_state
;
3262 /* The following variables is maximal number of allocated nodes
3264 static int allocated_alt_states_num
= 0;
3267 /* The following function returns free node alt_state. It may be new
3268 allocated node or node freed earlier. */
3270 get_free_alt_state (void)
3274 if (first_free_alt_state
!= NULL
)
3276 result
= first_free_alt_state
;
3277 first_free_alt_state
= first_free_alt_state
->next_alt_state
;
3282 allocated_alt_states_num
++;
3284 result
= XCREATENODE (struct alt_state
);
3286 result
->state
= NULL
;
3287 result
->next_alt_state
= NULL
;
3288 result
->next_sorted_alt_state
= NULL
;
3292 /* The function frees node ALT_STATE. */
3294 free_alt_state (alt_state_t alt_state
)
3296 if (alt_state
== NULL
)
3298 alt_state
->next_alt_state
= first_free_alt_state
;
3299 first_free_alt_state
= alt_state
;
3302 /* The function frees list started with node ALT_STATE_LIST. */
3304 free_alt_states (alt_state_t alt_states_list
)
3306 alt_state_t curr_alt_state
;
3307 alt_state_t next_alt_state
;
3309 for (curr_alt_state
= alt_states_list
;
3310 curr_alt_state
!= NULL
;
3311 curr_alt_state
= next_alt_state
)
3313 next_alt_state
= curr_alt_state
->next_alt_state
;
3314 free_alt_state (curr_alt_state
);
3318 /* The function compares unique numbers of alt states. */
3320 alt_state_cmp (const void *alt_state_ptr_1
, const void *alt_state_ptr_2
)
3322 if ((*(const alt_state_t
*) alt_state_ptr_1
)->state
->unique_num
3323 == (*(const alt_state_t
*) alt_state_ptr_2
)->state
->unique_num
)
3325 else if ((*(const alt_state_t
*) alt_state_ptr_1
)->state
->unique_num
3326 < (*(const alt_state_t
*) alt_state_ptr_2
)->state
->unique_num
)
3332 /* The function sorts ALT_STATES_LIST and removes duplicated alt
3333 states from the list. The comparison key is alt state unique
3337 uniq_sort_alt_states (alt_state_t alt_states_list
)
3339 alt_state_t curr_alt_state
;
3340 vec
<alt_state_t
> alt_states
;
3342 size_t prev_unique_state_ind
;
3345 if (alt_states_list
== 0)
3347 if (alt_states_list
->next_alt_state
== 0)
3348 return alt_states_list
;
3350 alt_states
.create (150);
3351 for (curr_alt_state
= alt_states_list
;
3352 curr_alt_state
!= NULL
;
3353 curr_alt_state
= curr_alt_state
->next_alt_state
)
3354 alt_states
.safe_push (curr_alt_state
);
3356 alt_states
.qsort (alt_state_cmp
);
3358 prev_unique_state_ind
= 0;
3359 for (i
= 1; i
< alt_states
.length (); i
++)
3360 if (alt_states
[prev_unique_state_ind
]->state
!= alt_states
[i
]->state
)
3362 prev_unique_state_ind
++;
3363 alt_states
[prev_unique_state_ind
] = alt_states
[i
];
3365 alt_states
.truncate (prev_unique_state_ind
+ 1);
3367 for (i
= 1; i
< alt_states
.length (); i
++)
3368 alt_states
[i
-1]->next_sorted_alt_state
3370 alt_states
.last ()->next_sorted_alt_state
= 0;
3372 result
= alt_states
[0];
3374 alt_states
.release ();
3378 /* The function checks equality of alt state lists. Remember that the
3379 lists must be already sorted by the previous function. */
3381 alt_states_eq (alt_state_t alt_states_1
, alt_state_t alt_states_2
)
3383 while (alt_states_1
!= NULL
&& alt_states_2
!= NULL
3384 && alt_state_cmp (&alt_states_1
, &alt_states_2
) == 0)
3386 alt_states_1
= alt_states_1
->next_sorted_alt_state
;
3387 alt_states_2
= alt_states_2
->next_sorted_alt_state
;
3389 return alt_states_1
== alt_states_2
;
3392 /* Initialization of the abstract data. */
3394 initiate_alt_states (void)
3396 first_free_alt_state
= NULL
;
3399 /* Finishing work with the abstract data. */
3401 finish_alt_states (void)
3407 /* The page contains macros for work with bits strings. We could use
3408 standard gcc bitmap or sbitmap but it would result in difficulties
3409 of building canadian cross. */
3411 /* Set bit number bitno in the bit string. The macro is not side
3413 #define bitmap_set_bit(bitstring, bitno) \
3414 ((bitstring)[(bitno) / (sizeof (*(bitstring)) * CHAR_BIT)] |= \
3415 (HOST_WIDE_INT)1 << (bitno) % (sizeof (*(bitstring)) * CHAR_BIT))
3417 #define CLEAR_BIT(bitstring, bitno) \
3418 ((bitstring)[(bitno) / (sizeof (*(bitstring)) * CHAR_BIT)] &= \
3419 ~((HOST_WIDE_INT)1 << (bitno) % (sizeof (*(bitstring)) * CHAR_BIT)))
3421 /* Test if bit number bitno in the bitstring is set. The macro is not
3422 side effect proof. */
3423 #define bitmap_bit_p(bitstring, bitno) \
3424 ((bitstring)[(bitno) / (sizeof (*(bitstring)) * CHAR_BIT)] >> \
3425 (bitno) % (sizeof (*(bitstring)) * CHAR_BIT) & 1)
3429 /* This page contains abstract data `state'. */
3431 /* Maximal length of reservations in cycles (>= 1). */
3432 static int max_cycles_num
;
3434 /* Number of set elements (see type set_el_t) needed for
3435 representation of one cycle reservation. It is depended on units
3437 static int els_in_cycle_reserv
;
3439 /* Number of set elements (see type set_el_t) needed for
3440 representation of maximal length reservation. Deterministic
3441 reservation is stored as set (bit string) of length equal to the
3442 variable value * number of bits in set_el_t. */
3443 static int els_in_reservs
;
3445 /* Array of pointers to unit declarations. */
3446 static unit_decl_t
*units_array
;
3448 /* Temporary reservation of maximal length. */
3449 static reserv_sets_t temp_reserv
;
3451 /* The state table itself is represented by the following variable. */
3452 static htab_t state_table
;
3454 /* Linked list of free 'state' structures to be recycled. The
3455 next_equiv_class_state pointer is borrowed for a free list. */
3456 static state_t first_free_state
;
3458 static int curr_unique_state_num
;
3461 /* The following variables is maximal number of allocated nodes
3463 static int allocated_states_num
= 0;
3466 /* Allocate new reservation set. */
3467 static reserv_sets_t
3468 alloc_empty_reserv_sets (void)
3470 reserv_sets_t result
;
3472 obstack_blank (&irp
, els_in_reservs
* sizeof (set_el_t
));
3473 result
= (reserv_sets_t
) obstack_base (&irp
);
3474 obstack_finish (&irp
);
3475 memset (result
, 0, els_in_reservs
* sizeof (set_el_t
));
3479 /* Hash value of reservation set. */
3481 reserv_sets_hash_value (reserv_sets_t reservs
)
3483 set_el_t hash_value
;
3486 set_el_t
*reserv_ptr
;
3489 reservs_num
= els_in_reservs
;
3490 reserv_ptr
= reservs
;
3492 while (reservs_num
!= 0)
3495 hash_value
+= ((*reserv_ptr
>> i
)
3496 | (*reserv_ptr
<< (sizeof (set_el_t
) * CHAR_BIT
- i
)));
3498 if (i
== sizeof (set_el_t
) * CHAR_BIT
)
3502 if (sizeof (set_el_t
) <= sizeof (unsigned))
3505 for (i
= sizeof (set_el_t
); i
> 0; i
-= sizeof (unsigned) - 1)
3507 result
+= (unsigned) hash_value
;
3508 hash_value
>>= (sizeof (unsigned) - 1) * CHAR_BIT
;
3513 /* Comparison of given reservation sets. */
3515 reserv_sets_cmp (const_reserv_sets_t reservs_1
, const_reserv_sets_t reservs_2
)
3518 const set_el_t
*reserv_ptr_1
;
3519 const set_el_t
*reserv_ptr_2
;
3521 gcc_assert (reservs_1
&& reservs_2
);
3522 reservs_num
= els_in_reservs
;
3523 reserv_ptr_1
= reservs_1
;
3524 reserv_ptr_2
= reservs_2
;
3525 while (reservs_num
!= 0 && *reserv_ptr_1
== *reserv_ptr_2
)
3531 if (reservs_num
== 0)
3533 else if (*reserv_ptr_1
< *reserv_ptr_2
)
3539 /* The function checks equality of the reservation sets. */
3541 reserv_sets_eq (const_reserv_sets_t reservs_1
, const_reserv_sets_t reservs_2
)
3543 return reserv_sets_cmp (reservs_1
, reservs_2
) == 0;
3546 /* Set up in the reservation set that unit with UNIT_NUM is used on
3549 set_unit_reserv (reserv_sets_t reservs
, int cycle_num
, int unit_num
)
3551 gcc_assert (cycle_num
< max_cycles_num
);
3552 bitmap_set_bit (reservs
, cycle_num
* els_in_cycle_reserv
3553 * sizeof (set_el_t
) * CHAR_BIT
+ unit_num
);
3556 /* Set up in the reservation set RESERVS that unit with UNIT_NUM is
3557 used on CYCLE_NUM. */
3559 test_unit_reserv (reserv_sets_t reservs
, int cycle_num
, int unit_num
)
3561 gcc_assert (cycle_num
< max_cycles_num
);
3562 return bitmap_bit_p (reservs
, cycle_num
* els_in_cycle_reserv
3563 * sizeof (set_el_t
) * CHAR_BIT
+ unit_num
);
3566 /* The function checks that the reservation sets are intersected,
3567 i.e. there is a unit reservation on a cycle in both reservation
3570 reserv_sets_are_intersected (reserv_sets_t operand_1
,
3571 reserv_sets_t operand_2
)
3575 set_el_t
*cycle_ptr_1
;
3576 set_el_t
*cycle_ptr_2
;
3578 gcc_assert (operand_1
&& operand_2
);
3579 for (el_ptr_1
= operand_1
, el_ptr_2
= operand_2
;
3580 el_ptr_1
< operand_1
+ els_in_reservs
;
3581 el_ptr_1
++, el_ptr_2
++)
3582 if (*el_ptr_1
& *el_ptr_2
)
3584 reserv_sets_or (temp_reserv
, operand_1
, operand_2
);
3585 for (cycle_ptr_1
= operand_1
, cycle_ptr_2
= operand_2
;
3586 cycle_ptr_1
< operand_1
+ els_in_reservs
;
3587 cycle_ptr_1
+= els_in_cycle_reserv
, cycle_ptr_2
+= els_in_cycle_reserv
)
3589 for (el_ptr_1
= cycle_ptr_1
, el_ptr_2
= get_excl_set (cycle_ptr_2
);
3590 el_ptr_1
< cycle_ptr_1
+ els_in_cycle_reserv
;
3591 el_ptr_1
++, el_ptr_2
++)
3592 if (*el_ptr_1
& *el_ptr_2
)
3594 if (!check_presence_pattern_sets (cycle_ptr_1
, cycle_ptr_2
, FALSE
))
3596 if (!check_presence_pattern_sets (temp_reserv
+ (cycle_ptr_2
3600 if (!check_absence_pattern_sets (cycle_ptr_1
, cycle_ptr_2
, FALSE
))
3602 if (!check_absence_pattern_sets (temp_reserv
+ (cycle_ptr_2
- operand_2
),
3609 /* The function sets up RESULT bits by bits of OPERAND shifted on one
3610 cpu cycle. The remaining bits of OPERAND (representing the last
3611 cycle unit reservations) are not changed. */
3613 reserv_sets_shift (reserv_sets_t result
, reserv_sets_t operand
)
3617 gcc_assert (result
&& operand
&& result
!= operand
);
3618 for (i
= els_in_cycle_reserv
; i
< els_in_reservs
; i
++)
3619 result
[i
- els_in_cycle_reserv
] = operand
[i
];
3622 /* OR of the reservation sets. */
3624 reserv_sets_or (reserv_sets_t result
, reserv_sets_t operand_1
,
3625 reserv_sets_t operand_2
)
3629 set_el_t
*result_set_el_ptr
;
3631 gcc_assert (result
&& operand_1
&& operand_2
);
3632 for (el_ptr_1
= operand_1
, el_ptr_2
= operand_2
, result_set_el_ptr
= result
;
3633 el_ptr_1
< operand_1
+ els_in_reservs
;
3634 el_ptr_1
++, el_ptr_2
++, result_set_el_ptr
++)
3635 *result_set_el_ptr
= *el_ptr_1
| *el_ptr_2
;
3638 /* AND of the reservation sets. */
3640 reserv_sets_and (reserv_sets_t result
, reserv_sets_t operand_1
,
3641 reserv_sets_t operand_2
)
3645 set_el_t
*result_set_el_ptr
;
3647 gcc_assert (result
&& operand_1
&& operand_2
);
3648 for (el_ptr_1
= operand_1
, el_ptr_2
= operand_2
, result_set_el_ptr
= result
;
3649 el_ptr_1
< operand_1
+ els_in_reservs
;
3650 el_ptr_1
++, el_ptr_2
++, result_set_el_ptr
++)
3651 *result_set_el_ptr
= *el_ptr_1
& *el_ptr_2
;
3654 /* The function outputs string representation of units reservation on
3655 cycle START_CYCLE in the reservation set. The function uses repeat
3656 construction if REPETITION_NUM > 1. */
3658 output_cycle_reservs (FILE *f
, reserv_sets_t reservs
, int start_cycle
,
3662 int reserved_units_num
;
3664 reserved_units_num
= 0;
3665 for (unit_num
= 0; unit_num
< description
->units_num
; unit_num
++)
3666 if (bitmap_bit_p (reservs
, start_cycle
* els_in_cycle_reserv
3667 * sizeof (set_el_t
) * CHAR_BIT
+ unit_num
))
3668 reserved_units_num
++;
3669 gcc_assert (repetition_num
> 0);
3670 if (repetition_num
!= 1 && reserved_units_num
> 1)
3672 reserved_units_num
= 0;
3674 unit_num
< description
->units_num
;
3676 if (bitmap_bit_p (reservs
, start_cycle
* els_in_cycle_reserv
3677 * sizeof (set_el_t
) * CHAR_BIT
+ unit_num
))
3679 if (reserved_units_num
!= 0)
3681 reserved_units_num
++;
3682 fprintf (f
, "%s", units_array
[unit_num
]->name
);
3684 if (reserved_units_num
== 0)
3685 fprintf (f
, NOTHING_NAME
);
3686 gcc_assert (repetition_num
> 0);
3687 if (repetition_num
!= 1 && reserved_units_num
> 1)
3689 if (repetition_num
!= 1)
3690 fprintf (f
, "*%d", repetition_num
);
3693 /* The function outputs string representation of units reservation in
3694 the reservation set. */
3696 output_reserv_sets (FILE *f
, reserv_sets_t reservs
)
3698 int start_cycle
= 0;
3703 for (cycle
= 0; cycle
< max_cycles_num
; cycle
++)
3704 if (repetition_num
== 0)
3707 start_cycle
= cycle
;
3710 ((char *) reservs
+ start_cycle
* els_in_cycle_reserv
3711 * sizeof (set_el_t
),
3712 (char *) reservs
+ cycle
* els_in_cycle_reserv
3713 * sizeof (set_el_t
),
3714 els_in_cycle_reserv
* sizeof (set_el_t
)) == 0)
3718 if (start_cycle
!= 0)
3720 output_cycle_reservs (f
, reservs
, start_cycle
, repetition_num
);
3722 start_cycle
= cycle
;
3724 if (start_cycle
< max_cycles_num
)
3726 if (start_cycle
!= 0)
3728 output_cycle_reservs (f
, reservs
, start_cycle
, repetition_num
);
3732 /* The following function returns free node state for AUTOMATON. It
3733 may be new allocated node or node freed earlier. The function also
3734 allocates reservation set if WITH_RESERVS has nonzero value. */
3736 get_free_state (int with_reservs
, automaton_t automaton
)
3740 gcc_assert (max_cycles_num
> 0 && automaton
);
3741 if (first_free_state
)
3743 result
= first_free_state
;
3744 first_free_state
= result
->next_equiv_class_state
;
3746 result
->next_equiv_class_state
= NULL
;
3747 result
->automaton
= automaton
;
3748 result
->first_out_arc
= NULL
;
3749 result
->it_was_placed_in_stack_for_NDFA_forming
= 0;
3750 result
->it_was_placed_in_stack_for_DFA_forming
= 0;
3751 result
->component_states
= NULL
;
3756 allocated_states_num
++;
3758 result
= XCREATENODE (struct state
);
3759 result
->automaton
= automaton
;
3760 result
->first_out_arc
= NULL
;
3761 result
->unique_num
= curr_unique_state_num
;
3762 curr_unique_state_num
++;
3766 if (result
->reservs
== NULL
)
3767 result
->reservs
= alloc_empty_reserv_sets ();
3769 memset (result
->reservs
, 0, els_in_reservs
* sizeof (set_el_t
));
3774 /* The function frees node STATE. */
3776 free_state (state_t state
)
3778 free_alt_states (state
->component_states
);
3779 state
->next_equiv_class_state
= first_free_state
;
3780 first_free_state
= state
;
3783 /* Hash value of STATE. If STATE represents deterministic state it is
3784 simply hash value of the corresponding reservation set. Otherwise
3785 it is formed from hash values of the component deterministic
3786 states. One more key is order number of state automaton. */
3788 state_hash (const void *state
)
3790 unsigned int hash_value
;
3791 alt_state_t alt_state
;
3793 if (((const_state_t
) state
)->component_states
== NULL
)
3794 hash_value
= reserv_sets_hash_value (((const_state_t
) state
)->reservs
);
3798 for (alt_state
= ((const_state_t
) state
)->component_states
;
3800 alt_state
= alt_state
->next_sorted_alt_state
)
3801 hash_value
= (((hash_value
>> (sizeof (unsigned) - 1) * CHAR_BIT
)
3802 | (hash_value
<< CHAR_BIT
))
3803 + alt_state
->state
->unique_num
);
3805 hash_value
= (((hash_value
>> (sizeof (unsigned) - 1) * CHAR_BIT
)
3806 | (hash_value
<< CHAR_BIT
))
3807 + ((const_state_t
) state
)->automaton
->automaton_order_num
);
3811 /* Return nonzero value if the states are the same. */
3813 state_eq_p (const void *state_1
, const void *state_2
)
3815 alt_state_t alt_state_1
;
3816 alt_state_t alt_state_2
;
3818 if (((const_state_t
) state_1
)->automaton
!= ((const_state_t
) state_2
)->automaton
)
3820 else if (((const_state_t
) state_1
)->component_states
== NULL
3821 && ((const_state_t
) state_2
)->component_states
== NULL
)
3822 return reserv_sets_eq (((const_state_t
) state_1
)->reservs
,
3823 ((const_state_t
) state_2
)->reservs
);
3824 else if (((const_state_t
) state_1
)->component_states
!= NULL
3825 && ((const_state_t
) state_2
)->component_states
!= NULL
)
3827 for (alt_state_1
= ((const_state_t
) state_1
)->component_states
,
3828 alt_state_2
= ((const_state_t
) state_2
)->component_states
;
3829 alt_state_1
!= NULL
&& alt_state_2
!= NULL
;
3830 alt_state_1
= alt_state_1
->next_sorted_alt_state
,
3831 alt_state_2
= alt_state_2
->next_sorted_alt_state
)
3832 /* All state in the list must be already in the hash table.
3833 Also the lists must be sorted. */
3834 if (alt_state_1
->state
!= alt_state_2
->state
)
3836 return alt_state_1
== alt_state_2
;
3842 /* Insert STATE into the state table. */
3844 insert_state (state_t state
)
3848 entry_ptr
= htab_find_slot (state_table
, (void *) state
, INSERT
);
3849 if (*entry_ptr
== NULL
)
3850 *entry_ptr
= (void *) state
;
3851 return (state_t
) *entry_ptr
;
3854 /* Add reservation of unit with UNIT_NUM on cycle CYCLE_NUM to
3855 deterministic STATE. */
3857 set_state_reserv (state_t state
, int cycle_num
, int unit_num
)
3859 set_unit_reserv (state
->reservs
, cycle_num
, unit_num
);
3862 /* Return nonzero value if the deterministic states contains a
3863 reservation of the same cpu unit on the same cpu cycle. */
3865 intersected_state_reservs_p (state_t state1
, state_t state2
)
3867 gcc_assert (state1
->automaton
== state2
->automaton
);
3868 return reserv_sets_are_intersected (state1
->reservs
, state2
->reservs
);
3871 /* Return deterministic state (inserted into the table) which
3872 representing the automaton state which is union of reservations of
3873 the deterministic states masked by RESERVS. */
3875 states_union (state_t state1
, state_t state2
, reserv_sets_t reservs
)
3878 state_t state_in_table
;
3880 gcc_assert (state1
->automaton
== state2
->automaton
);
3881 result
= get_free_state (1, state1
->automaton
);
3882 reserv_sets_or (result
->reservs
, state1
->reservs
, state2
->reservs
);
3883 reserv_sets_and (result
->reservs
, result
->reservs
, reservs
);
3884 state_in_table
= insert_state (result
);
3885 if (result
!= state_in_table
)
3887 free_state (result
);
3888 result
= state_in_table
;
3893 /* Return deterministic state (inserted into the table) which
3894 represent the automaton state is obtained from deterministic STATE
3895 by advancing cpu cycle and masking by RESERVS. */
3897 state_shift (state_t state
, reserv_sets_t reservs
)
3900 state_t state_in_table
;
3902 result
= get_free_state (1, state
->automaton
);
3903 reserv_sets_shift (result
->reservs
, state
->reservs
);
3904 reserv_sets_and (result
->reservs
, result
->reservs
, reservs
);
3905 state_in_table
= insert_state (result
);
3906 if (result
!= state_in_table
)
3908 free_state (result
);
3909 result
= state_in_table
;
3914 /* Initialization of the abstract data. */
3916 initiate_states (void)
3921 if (description
->units_num
)
3922 units_array
= XNEWVEC (unit_decl_t
, description
->units_num
);
3926 for (i
= 0; i
< description
->decls_num
; i
++)
3928 decl
= description
->decls
[i
];
3929 if (decl
->mode
== dm_unit
)
3930 units_array
[DECL_UNIT (decl
)->unit_num
] = DECL_UNIT (decl
);
3932 max_cycles_num
= description
->max_insn_reserv_cycles
;
3934 = ((description
->units_num
+ sizeof (set_el_t
) * CHAR_BIT
- 1)
3935 / (sizeof (set_el_t
) * CHAR_BIT
));
3936 els_in_reservs
= els_in_cycle_reserv
* max_cycles_num
;
3937 curr_unique_state_num
= 0;
3938 initiate_alt_states ();
3939 state_table
= htab_create (1500, state_hash
, state_eq_p
, (htab_del
) 0);
3940 temp_reserv
= alloc_empty_reserv_sets ();
3943 /* Finishing work with the abstract data. */
3945 finish_states (void)
3949 htab_delete (state_table
);
3950 first_free_state
= NULL
;
3951 finish_alt_states ();
3956 /* Abstract data `arcs'. */
3958 /* List of free arcs. */
3959 static arc_t first_free_arc
;
3962 /* The following variables is maximal number of allocated nodes
3964 static int allocated_arcs_num
= 0;
3967 /* The function frees node ARC. */
3969 free_arc (arc_t arc
)
3971 arc
->next_out_arc
= first_free_arc
;
3972 first_free_arc
= arc
;
3975 /* The function removes and frees ARC staring from FROM_STATE. */
3977 remove_arc (state_t from_state
, arc_t arc
)
3983 for (prev_arc
= NULL
, curr_arc
= from_state
->first_out_arc
;
3985 prev_arc
= curr_arc
, curr_arc
= curr_arc
->next_out_arc
)
3986 if (curr_arc
== arc
)
3988 gcc_assert (curr_arc
);
3989 if (prev_arc
== NULL
)
3990 from_state
->first_out_arc
= arc
->next_out_arc
;
3992 prev_arc
->next_out_arc
= arc
->next_out_arc
;
3993 from_state
->num_out_arcs
--;
3997 /* The functions returns arc with given characteristics (or NULL if
3998 the arc does not exist). */
4000 find_arc (state_t from_state
, state_t to_state
, ainsn_t insn
)
4004 for (arc
= first_out_arc (from_state
); arc
!= NULL
; arc
= next_out_arc (arc
))
4005 if (arc
->insn
== insn
4006 && (arc
->to_state
== to_state
4008 /* Any arc is good enough for a collapse-ndfa transition. */
4009 && (insn
->insn_reserv_decl
4010 == DECL_INSN_RESERV (collapse_ndfa_insn_decl
)))))
4015 /* The function adds arc from FROM_STATE to TO_STATE marked by AINSN,
4016 unless such an arc already exists. */
4018 add_arc (state_t from_state
, state_t to_state
, ainsn_t ainsn
)
4022 new_arc
= find_arc (from_state
, to_state
, ainsn
);
4023 if (new_arc
!= NULL
)
4025 if (first_free_arc
== NULL
)
4028 allocated_arcs_num
++;
4030 new_arc
= XCREATENODE (struct arc
);
4031 new_arc
->to_state
= NULL
;
4032 new_arc
->insn
= NULL
;
4033 new_arc
->next_out_arc
= NULL
;
4037 new_arc
= first_free_arc
;
4038 first_free_arc
= first_free_arc
->next_out_arc
;
4040 new_arc
->to_state
= to_state
;
4041 new_arc
->insn
= ainsn
;
4042 ainsn
->arc_exists_p
= 1;
4043 new_arc
->next_out_arc
= from_state
->first_out_arc
;
4044 from_state
->first_out_arc
= new_arc
;
4045 from_state
->num_out_arcs
++;
4046 new_arc
->next_arc_marked_by_insn
= NULL
;
4049 /* The function returns the first arc starting from STATE. */
4051 first_out_arc (const_state_t state
)
4053 return state
->first_out_arc
;
4056 /* The function returns next out arc after ARC. */
4058 next_out_arc (arc_t arc
)
4060 return arc
->next_out_arc
;
4063 /* Initialization of the abstract data. */
4065 initiate_arcs (void)
4067 first_free_arc
= NULL
;
4070 /* Finishing work with the abstract data. */
4078 /* Abstract data `automata lists'. */
4080 /* List of free states. */
4081 static automata_list_el_t first_free_automata_list_el
;
4083 /* The list being formed. */
4084 static automata_list_el_t current_automata_list
;
4086 /* Hash table of automata lists. */
4087 static htab_t automata_list_table
;
4089 /* The following function returns free automata list el. It may be
4090 new allocated node or node freed earlier. */
4091 static automata_list_el_t
4092 get_free_automata_list_el (void)
4094 automata_list_el_t result
;
4096 if (first_free_automata_list_el
!= NULL
)
4098 result
= first_free_automata_list_el
;
4099 first_free_automata_list_el
4100 = first_free_automata_list_el
->next_automata_list_el
;
4103 result
= XCREATENODE (struct automata_list_el
);
4104 result
->automaton
= NULL
;
4105 result
->next_automata_list_el
= NULL
;
4109 /* The function frees node AUTOMATA_LIST_EL. */
4111 free_automata_list_el (automata_list_el_t automata_list_el
)
4113 if (automata_list_el
== NULL
)
4115 automata_list_el
->next_automata_list_el
= first_free_automata_list_el
;
4116 first_free_automata_list_el
= automata_list_el
;
4119 /* The function frees list AUTOMATA_LIST. */
4121 free_automata_list (automata_list_el_t automata_list
)
4123 automata_list_el_t curr_automata_list_el
;
4124 automata_list_el_t next_automata_list_el
;
4126 for (curr_automata_list_el
= automata_list
;
4127 curr_automata_list_el
!= NULL
;
4128 curr_automata_list_el
= next_automata_list_el
)
4130 next_automata_list_el
= curr_automata_list_el
->next_automata_list_el
;
4131 free_automata_list_el (curr_automata_list_el
);
4135 /* Hash value of AUTOMATA_LIST. */
4137 automata_list_hash (const void *automata_list
)
4139 unsigned int hash_value
;
4140 const_automata_list_el_t curr_automata_list_el
;
4143 for (curr_automata_list_el
= (const_automata_list_el_t
) automata_list
;
4144 curr_automata_list_el
!= NULL
;
4145 curr_automata_list_el
= curr_automata_list_el
->next_automata_list_el
)
4146 hash_value
= (((hash_value
>> (sizeof (unsigned) - 1) * CHAR_BIT
)
4147 | (hash_value
<< CHAR_BIT
))
4148 + curr_automata_list_el
->automaton
->automaton_order_num
);
4152 /* Return nonzero value if the automata_lists are the same. */
4154 automata_list_eq_p (const void *automata_list_1
, const void *automata_list_2
)
4156 const_automata_list_el_t automata_list_el_1
;
4157 const_automata_list_el_t automata_list_el_2
;
4159 for (automata_list_el_1
= (const_automata_list_el_t
) automata_list_1
,
4160 automata_list_el_2
= (const_automata_list_el_t
) automata_list_2
;
4161 automata_list_el_1
!= NULL
&& automata_list_el_2
!= NULL
;
4162 automata_list_el_1
= automata_list_el_1
->next_automata_list_el
,
4163 automata_list_el_2
= automata_list_el_2
->next_automata_list_el
)
4164 if (automata_list_el_1
->automaton
!= automata_list_el_2
->automaton
)
4166 return automata_list_el_1
== automata_list_el_2
;
4169 /* Initialization of the abstract data. */
4171 initiate_automata_lists (void)
4173 first_free_automata_list_el
= NULL
;
4174 automata_list_table
= htab_create (1500, automata_list_hash
,
4175 automata_list_eq_p
, (htab_del
) 0);
4178 /* The following function starts new automata list and makes it the
4181 automata_list_start (void)
4183 current_automata_list
= NULL
;
4186 /* The following function adds AUTOMATON to the current list. */
4188 automata_list_add (automaton_t automaton
)
4190 automata_list_el_t el
;
4192 el
= get_free_automata_list_el ();
4193 el
->automaton
= automaton
;
4194 el
->next_automata_list_el
= current_automata_list
;
4195 current_automata_list
= el
;
4198 /* The following function finishes forming the current list, inserts
4199 it into the table and returns it. */
4200 static automata_list_el_t
4201 automata_list_finish (void)
4205 if (current_automata_list
== NULL
)
4207 entry_ptr
= htab_find_slot (automata_list_table
,
4208 (void *) current_automata_list
, INSERT
);
4209 if (*entry_ptr
== NULL
)
4210 *entry_ptr
= (void *) current_automata_list
;
4212 free_automata_list (current_automata_list
);
4213 current_automata_list
= NULL
;
4214 return (automata_list_el_t
) *entry_ptr
;
4217 /* Finishing work with the abstract data. */
4219 finish_automata_lists (void)
4221 htab_delete (automata_list_table
);
4226 /* The page contains abstract data for work with exclusion sets (see
4227 exclusion_set in file rtl.def). */
4229 /* The following variable refers to an exclusion set returned by
4230 get_excl_set. This is bit string of length equal to cpu units
4231 number. If exclusion set for given unit contains 1 for a unit,
4232 then simultaneous reservation of the units is prohibited. */
4233 static reserv_sets_t excl_set
;
4235 /* The array contains exclusion sets for each unit. */
4236 static reserv_sets_t
*unit_excl_set_table
;
4238 /* The following function forms the array containing exclusion sets
4241 initiate_excl_sets (void)
4244 reserv_sets_t unit_excl_set
;
4248 obstack_blank (&irp
, els_in_cycle_reserv
* sizeof (set_el_t
));
4249 excl_set
= (reserv_sets_t
) obstack_base (&irp
);
4250 obstack_finish (&irp
);
4251 obstack_blank (&irp
, description
->units_num
* sizeof (reserv_sets_t
));
4252 unit_excl_set_table
= (reserv_sets_t
*) obstack_base (&irp
);
4253 obstack_finish (&irp
);
4254 /* Evaluate unit exclusion sets. */
4255 for (i
= 0; i
< description
->decls_num
; i
++)
4257 decl
= description
->decls
[i
];
4258 if (decl
->mode
== dm_unit
)
4260 obstack_blank (&irp
, els_in_cycle_reserv
* sizeof (set_el_t
));
4261 unit_excl_set
= (reserv_sets_t
) obstack_base (&irp
);
4262 obstack_finish (&irp
);
4263 memset (unit_excl_set
, 0, els_in_cycle_reserv
* sizeof (set_el_t
));
4264 for (el
= DECL_UNIT (decl
)->excl_list
;
4266 el
= el
->next_unit_set_el
)
4268 bitmap_set_bit (unit_excl_set
, el
->unit_decl
->unit_num
);
4269 el
->unit_decl
->in_set_p
= TRUE
;
4271 unit_excl_set_table
[DECL_UNIT (decl
)->unit_num
] = unit_excl_set
;
4276 /* The function sets up and return EXCL_SET which is union of
4277 exclusion sets for each unit in IN_SET. */
4278 static reserv_sets_t
4279 get_excl_set (reserv_sets_t in_set
)
4286 memset (excl_set
, 0, els_in_cycle_reserv
* sizeof (set_el_t
));
4287 for (el
= 0; el
< els_in_cycle_reserv
; el
++)
4289 for (i
= 0; i
< CHAR_BIT
* sizeof (set_el_t
); i
++)
4290 if ((in_set
[el
] >> i
) & 1)
4292 start_unit_num
= el
* CHAR_BIT
* sizeof (set_el_t
) + i
;
4293 if (start_unit_num
>= description
->units_num
)
4295 for (unit_num
= 0; unit_num
< els_in_cycle_reserv
; unit_num
++)
4298 |= unit_excl_set_table
[start_unit_num
] [unit_num
];
4306 /* The page contains abstract data for work with presence/absence
4307 pattern sets (see presence_set/absence_set in file rtl.def). */
4309 /* The following arrays contain correspondingly presence, final
4310 presence, absence, and final absence patterns for each unit. */
4311 static pattern_reserv_t
*unit_presence_set_table
;
4312 static pattern_reserv_t
*unit_final_presence_set_table
;
4313 static pattern_reserv_t
*unit_absence_set_table
;
4314 static pattern_reserv_t
*unit_final_absence_set_table
;
4316 /* The following function forms list of reservation sets for given
4318 static pattern_reserv_t
4319 form_reserv_sets_list (pattern_set_el_t pattern_list
)
4321 pattern_set_el_t el
;
4322 pattern_reserv_t first
, curr
, prev
;
4325 prev
= first
= NULL
;
4326 for (el
= pattern_list
; el
!= NULL
; el
= el
->next_pattern_set_el
)
4328 curr
= XCREATENODE (struct pattern_reserv
);
4329 curr
->reserv
= alloc_empty_reserv_sets ();
4330 curr
->next_pattern_reserv
= NULL
;
4331 for (i
= 0; i
< el
->units_num
; i
++)
4333 bitmap_set_bit (curr
->reserv
, el
->unit_decls
[i
]->unit_num
);
4334 el
->unit_decls
[i
]->in_set_p
= TRUE
;
4337 prev
->next_pattern_reserv
= curr
;
4345 /* The following function forms the array containing presence and
4346 absence pattern sets for each unit. */
4348 initiate_presence_absence_pattern_sets (void)
4353 obstack_blank (&irp
, description
->units_num
* sizeof (pattern_reserv_t
));
4354 unit_presence_set_table
= (pattern_reserv_t
*) obstack_base (&irp
);
4355 obstack_finish (&irp
);
4356 obstack_blank (&irp
, description
->units_num
* sizeof (pattern_reserv_t
));
4357 unit_final_presence_set_table
= (pattern_reserv_t
*) obstack_base (&irp
);
4358 obstack_finish (&irp
);
4359 obstack_blank (&irp
, description
->units_num
* sizeof (pattern_reserv_t
));
4360 unit_absence_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_absence_set_table
= (pattern_reserv_t
*) obstack_base (&irp
);
4364 obstack_finish (&irp
);
4365 /* Evaluate unit presence/absence sets. */
4366 for (i
= 0; i
< description
->decls_num
; i
++)
4368 decl
= description
->decls
[i
];
4369 if (decl
->mode
== dm_unit
)
4371 unit_presence_set_table
[DECL_UNIT (decl
)->unit_num
]
4372 = form_reserv_sets_list (DECL_UNIT (decl
)->presence_list
);
4373 unit_final_presence_set_table
[DECL_UNIT (decl
)->unit_num
]
4374 = form_reserv_sets_list (DECL_UNIT (decl
)->final_presence_list
);
4375 unit_absence_set_table
[DECL_UNIT (decl
)->unit_num
]
4376 = form_reserv_sets_list (DECL_UNIT (decl
)->absence_list
);
4377 unit_final_absence_set_table
[DECL_UNIT (decl
)->unit_num
]
4378 = form_reserv_sets_list (DECL_UNIT (decl
)->final_absence_list
);
4383 /* The function checks that CHECKED_SET satisfies all presence pattern
4384 sets for units in ORIGINAL_SET. The function returns TRUE if it
4387 check_presence_pattern_sets (reserv_sets_t checked_set
,
4388 reserv_sets_t original_set
,
4396 pattern_reserv_t pat_reserv
;
4398 for (el
= 0; el
< els_in_cycle_reserv
; el
++)
4399 if (original_set
[el
])
4400 for (i
= 0; i
< CHAR_BIT
* sizeof (set_el_t
); i
++)
4401 if ((original_set
[el
] >> i
) & 1)
4403 start_unit_num
= el
* CHAR_BIT
* sizeof (set_el_t
) + i
;
4404 if (start_unit_num
>= description
->units_num
)
4407 && unit_final_presence_set_table
[start_unit_num
] == NULL
)
4409 && unit_presence_set_table
[start_unit_num
] == NULL
))
4412 for (pat_reserv
= (final_p
4413 ? unit_final_presence_set_table
[start_unit_num
]
4414 : unit_presence_set_table
[start_unit_num
]);
4416 pat_reserv
= pat_reserv
->next_pattern_reserv
)
4418 for (unit_num
= 0; unit_num
< els_in_cycle_reserv
; unit_num
++)
4419 if ((checked_set
[unit_num
] & pat_reserv
->reserv
[unit_num
])
4420 != pat_reserv
->reserv
[unit_num
])
4422 presence_p
= presence_p
|| unit_num
>= els_in_cycle_reserv
;
4430 /* The function checks that CHECKED_SET satisfies all absence pattern
4431 sets for units in ORIGINAL_SET. The function returns TRUE if it
4434 check_absence_pattern_sets (reserv_sets_t checked_set
,
4435 reserv_sets_t original_set
,
4442 pattern_reserv_t pat_reserv
;
4444 for (el
= 0; el
< els_in_cycle_reserv
; el
++)
4445 if (original_set
[el
])
4446 for (i
= 0; i
< CHAR_BIT
* sizeof (set_el_t
); i
++)
4447 if ((original_set
[el
] >> i
) & 1)
4449 start_unit_num
= el
* CHAR_BIT
* sizeof (set_el_t
) + i
;
4450 if (start_unit_num
>= description
->units_num
)
4452 for (pat_reserv
= (final_p
4453 ? unit_final_absence_set_table
[start_unit_num
]
4454 : unit_absence_set_table
[start_unit_num
]);
4456 pat_reserv
= pat_reserv
->next_pattern_reserv
)
4458 for (unit_num
= 0; unit_num
< els_in_cycle_reserv
; unit_num
++)
4459 if ((checked_set
[unit_num
] & pat_reserv
->reserv
[unit_num
])
4460 != pat_reserv
->reserv
[unit_num
]
4461 && pat_reserv
->reserv
[unit_num
])
4463 if (unit_num
>= els_in_cycle_reserv
)
4472 /* This page contains code for transformation of original reservations
4473 described in .md file. The main goal of transformations is
4474 simplifying reservation and lifting up all `|' on the top of IR
4475 reservation representation. */
4478 /* The following function makes copy of IR representation of
4479 reservation. The function also substitutes all reservations
4480 defined by define_reservation by corresponding value during making
4483 copy_insn_regexp (regexp_t regexp
)
4488 switch (regexp
->mode
)
4491 result
= copy_insn_regexp (REGEXP_RESERV (regexp
)->reserv_decl
->regexp
);
4495 result
= XCOPYNODE (struct regexp
, regexp
);
4499 result
= XCOPYNODE (struct regexp
, regexp
);
4500 REGEXP_REPEAT (result
)->regexp
4501 = copy_insn_regexp (REGEXP_REPEAT (regexp
)->regexp
);
4505 result
= XCOPYNODEVAR (struct regexp
, regexp
,
4506 sizeof (struct regexp
) + sizeof (regexp_t
)
4507 * (REGEXP_SEQUENCE (regexp
)->regexps_num
- 1));
4508 for (i
= 0; i
<REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
4509 REGEXP_SEQUENCE (result
)->regexps
[i
]
4510 = copy_insn_regexp (REGEXP_SEQUENCE (regexp
)->regexps
[i
]);
4514 result
= XCOPYNODEVAR (struct regexp
, regexp
,
4515 sizeof (struct regexp
) + sizeof (regexp_t
)
4516 * (REGEXP_ALLOF (regexp
)->regexps_num
- 1));
4517 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
4518 REGEXP_ALLOF (result
)->regexps
[i
]
4519 = copy_insn_regexp (REGEXP_ALLOF (regexp
)->regexps
[i
]);
4523 result
= XCOPYNODEVAR (struct regexp
, regexp
,
4524 sizeof (struct regexp
) + sizeof (regexp_t
)
4525 * (REGEXP_ONEOF (regexp
)->regexps_num
- 1));
4526 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
4527 REGEXP_ONEOF (result
)->regexps
[i
]
4528 = copy_insn_regexp (REGEXP_ONEOF (regexp
)->regexps
[i
]);
4532 result
= XCOPYNODE (struct regexp
, regexp
);
4541 /* The following variable is set up 1 if a transformation has been
4543 static int regexp_transformed_p
;
4545 /* The function makes transformation
4548 transform_1 (regexp_t regexp
)
4555 if (regexp
->mode
== rm_repeat
)
4557 repeat_num
= REGEXP_REPEAT (regexp
)->repeat_num
;
4558 gcc_assert (repeat_num
> 1);
4559 operand
= REGEXP_REPEAT (regexp
)->regexp
;
4561 regexp
= XCREATENODEVAR (struct regexp
, sizeof (struct regexp
)
4562 + sizeof (regexp_t
) * (repeat_num
- 1));
4563 regexp
->mode
= rm_sequence
;
4565 REGEXP_SEQUENCE (regexp
)->regexps_num
= repeat_num
;
4566 for (i
= 0; i
< repeat_num
; i
++)
4567 REGEXP_SEQUENCE (regexp
)->regexps
[i
] = copy_insn_regexp (operand
);
4568 regexp_transformed_p
= 1;
4573 /* The function makes transformations
4574 ...,(A,B,...),C,... -> ...,A,B,...,C,...
4575 ...+(A+B+...)+C+... -> ...+A+B+...+C+...
4576 ...|(A|B|...)|C|... -> ...|A|B|...|C|... */
4578 transform_2 (regexp_t regexp
)
4580 if (regexp
->mode
== rm_sequence
)
4582 regexp_t sequence
= NULL
;
4584 int sequence_index
= 0;
4587 for (i
= 0; i
< REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
4588 if (REGEXP_SEQUENCE (regexp
)->regexps
[i
]->mode
== rm_sequence
)
4591 sequence
= REGEXP_SEQUENCE (regexp
)->regexps
[i
];
4594 if (i
< REGEXP_SEQUENCE (regexp
)->regexps_num
)
4596 gcc_assert (REGEXP_SEQUENCE (sequence
)->regexps_num
> 1
4597 && REGEXP_SEQUENCE (regexp
)->regexps_num
> 1);
4598 result
= XCREATENODEVAR (struct regexp
, sizeof (struct regexp
)
4600 * (REGEXP_SEQUENCE (regexp
)->regexps_num
4601 + REGEXP_SEQUENCE (sequence
)->regexps_num
4603 result
->mode
= rm_sequence
;
4604 result
->pos
= regexp
->pos
;
4605 REGEXP_SEQUENCE (result
)->regexps_num
4606 = (REGEXP_SEQUENCE (regexp
)->regexps_num
4607 + REGEXP_SEQUENCE (sequence
)->regexps_num
- 1);
4608 for (i
= 0; i
< REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
4609 if (i
< sequence_index
)
4610 REGEXP_SEQUENCE (result
)->regexps
[i
]
4611 = copy_insn_regexp (REGEXP_SEQUENCE (regexp
)->regexps
[i
]);
4612 else if (i
> sequence_index
)
4613 REGEXP_SEQUENCE (result
)->regexps
4614 [i
+ REGEXP_SEQUENCE (sequence
)->regexps_num
- 1]
4615 = copy_insn_regexp (REGEXP_SEQUENCE (regexp
)->regexps
[i
]);
4617 for (j
= 0; j
< REGEXP_SEQUENCE (sequence
)->regexps_num
; j
++)
4618 REGEXP_SEQUENCE (result
)->regexps
[i
+ j
]
4619 = copy_insn_regexp (REGEXP_SEQUENCE (sequence
)->regexps
[j
]);
4620 regexp_transformed_p
= 1;
4624 else if (regexp
->mode
== rm_allof
)
4626 regexp_t allof
= NULL
;
4628 int allof_index
= 0;
4631 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
4632 if (REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
== rm_allof
)
4635 allof
= REGEXP_ALLOF (regexp
)->regexps
[i
];
4638 if (i
< REGEXP_ALLOF (regexp
)->regexps_num
)
4640 gcc_assert (REGEXP_ALLOF (allof
)->regexps_num
> 1
4641 && REGEXP_ALLOF (regexp
)->regexps_num
> 1);
4642 result
= XCREATENODEVAR (struct regexp
, sizeof (struct regexp
)
4644 * (REGEXP_ALLOF (regexp
)->regexps_num
4645 + REGEXP_ALLOF (allof
)->regexps_num
- 2));
4646 result
->mode
= rm_allof
;
4647 result
->pos
= regexp
->pos
;
4648 REGEXP_ALLOF (result
)->regexps_num
4649 = (REGEXP_ALLOF (regexp
)->regexps_num
4650 + REGEXP_ALLOF (allof
)->regexps_num
- 1);
4651 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
4652 if (i
< allof_index
)
4653 REGEXP_ALLOF (result
)->regexps
[i
]
4654 = copy_insn_regexp (REGEXP_ALLOF (regexp
)->regexps
[i
]);
4655 else if (i
> allof_index
)
4656 REGEXP_ALLOF (result
)->regexps
4657 [i
+ REGEXP_ALLOF (allof
)->regexps_num
- 1]
4658 = copy_insn_regexp (REGEXP_ALLOF (regexp
)->regexps
[i
]);
4660 for (j
= 0; j
< REGEXP_ALLOF (allof
)->regexps_num
; j
++)
4661 REGEXP_ALLOF (result
)->regexps
[i
+ j
]
4662 = copy_insn_regexp (REGEXP_ALLOF (allof
)->regexps
[j
]);
4663 regexp_transformed_p
= 1;
4667 else if (regexp
->mode
== rm_oneof
)
4669 regexp_t oneof
= NULL
;
4671 int oneof_index
= 0;
4674 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
4675 if (REGEXP_ONEOF (regexp
)->regexps
[i
]->mode
== rm_oneof
)
4678 oneof
= REGEXP_ONEOF (regexp
)->regexps
[i
];
4681 if (i
< REGEXP_ONEOF (regexp
)->regexps_num
)
4683 gcc_assert (REGEXP_ONEOF (oneof
)->regexps_num
> 1
4684 && REGEXP_ONEOF (regexp
)->regexps_num
> 1);
4685 result
= XCREATENODEVAR (struct regexp
, sizeof (struct regexp
)
4687 * (REGEXP_ONEOF (regexp
)->regexps_num
4688 + REGEXP_ONEOF (oneof
)->regexps_num
- 2));
4689 result
->mode
= rm_oneof
;
4690 result
->pos
= regexp
->pos
;
4691 REGEXP_ONEOF (result
)->regexps_num
4692 = (REGEXP_ONEOF (regexp
)->regexps_num
4693 + REGEXP_ONEOF (oneof
)->regexps_num
- 1);
4694 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
4695 if (i
< oneof_index
)
4696 REGEXP_ONEOF (result
)->regexps
[i
]
4697 = copy_insn_regexp (REGEXP_ONEOF (regexp
)->regexps
[i
]);
4698 else if (i
> oneof_index
)
4699 REGEXP_ONEOF (result
)->regexps
4700 [i
+ REGEXP_ONEOF (oneof
)->regexps_num
- 1]
4701 = copy_insn_regexp (REGEXP_ONEOF (regexp
)->regexps
[i
]);
4703 for (j
= 0; j
< REGEXP_ONEOF (oneof
)->regexps_num
; j
++)
4704 REGEXP_ONEOF (result
)->regexps
[i
+ j
]
4705 = copy_insn_regexp (REGEXP_ONEOF (oneof
)->regexps
[j
]);
4706 regexp_transformed_p
= 1;
4713 /* The function makes transformations
4714 ...,A|B|...,C,... -> (...,A,C,...)|(...,B,C,...)|...
4715 ...+(A|B|...)+C+... -> (...+A+C+...)|(...+B+C+...)|...
4716 ...+(A,B,...)+C+... -> (...+A+C+...),B,...
4717 ...+(A,B,...)+(C,D,...) -> (A+C),(B+D),... */
4719 transform_3 (regexp_t regexp
)
4721 if (regexp
->mode
== rm_sequence
)
4723 regexp_t oneof
= NULL
;
4724 int oneof_index
= 0;
4729 for (i
= 0; i
<REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
4730 if (REGEXP_SEQUENCE (regexp
)->regexps
[i
]->mode
== rm_oneof
)
4733 oneof
= REGEXP_SEQUENCE (regexp
)->regexps
[i
];
4736 if (i
< REGEXP_SEQUENCE (regexp
)->regexps_num
)
4738 gcc_assert (REGEXP_ONEOF (oneof
)->regexps_num
> 1
4739 && REGEXP_SEQUENCE (regexp
)->regexps_num
> 1);
4740 result
= XCREATENODEVAR (struct regexp
, sizeof (struct regexp
)
4742 * (REGEXP_ONEOF (oneof
)->regexps_num
- 1));
4743 result
->mode
= rm_oneof
;
4744 result
->pos
= regexp
->pos
;
4745 REGEXP_ONEOF (result
)->regexps_num
4746 = REGEXP_ONEOF (oneof
)->regexps_num
;
4747 for (i
= 0; i
< REGEXP_ONEOF (result
)->regexps_num
; i
++)
4750 = XCREATENODEVAR (struct regexp
, sizeof (struct regexp
)
4752 * (REGEXP_SEQUENCE (regexp
)->regexps_num
- 1));
4753 sequence
->mode
= rm_sequence
;
4754 sequence
->pos
= regexp
->pos
;
4755 REGEXP_SEQUENCE (sequence
)->regexps_num
4756 = REGEXP_SEQUENCE (regexp
)->regexps_num
;
4757 REGEXP_ONEOF (result
)->regexps
[i
] = sequence
;
4758 for (j
= 0; j
< REGEXP_SEQUENCE (sequence
)->regexps_num
; j
++)
4759 if (j
!= oneof_index
)
4760 REGEXP_SEQUENCE (sequence
)->regexps
[j
]
4761 = copy_insn_regexp (REGEXP_SEQUENCE (regexp
)->regexps
[j
]);
4763 REGEXP_SEQUENCE (sequence
)->regexps
[j
]
4764 = copy_insn_regexp (REGEXP_ONEOF (oneof
)->regexps
[i
]);
4766 regexp_transformed_p
= 1;
4770 else if (regexp
->mode
== rm_allof
)
4772 regexp_t oneof
= NULL
;
4774 int oneof_index
= 0;
4775 int max_seq_length
, allof_length
;
4777 regexp_t allof
= NULL
;
4778 regexp_t allof_op
= NULL
;
4781 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
4782 if (REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
== rm_oneof
)
4785 oneof
= REGEXP_ALLOF (regexp
)->regexps
[i
];
4788 if (i
< REGEXP_ALLOF (regexp
)->regexps_num
)
4790 gcc_assert (REGEXP_ONEOF (oneof
)->regexps_num
> 1
4791 && REGEXP_ALLOF (regexp
)->regexps_num
> 1);
4792 result
= XCREATENODEVAR (struct regexp
, sizeof (struct regexp
)
4794 * (REGEXP_ONEOF (oneof
)->regexps_num
- 1));
4795 result
->mode
= rm_oneof
;
4796 result
->pos
= regexp
->pos
;
4797 REGEXP_ONEOF (result
)->regexps_num
4798 = REGEXP_ONEOF (oneof
)->regexps_num
;
4799 for (i
= 0; i
< REGEXP_ONEOF (result
)->regexps_num
; i
++)
4802 = XCREATENODEVAR (struct regexp
, sizeof (struct regexp
)
4804 * (REGEXP_ALLOF (regexp
)->regexps_num
- 1));
4805 allof
->mode
= rm_allof
;
4806 allof
->pos
= regexp
->pos
;
4807 REGEXP_ALLOF (allof
)->regexps_num
4808 = REGEXP_ALLOF (regexp
)->regexps_num
;
4809 REGEXP_ONEOF (result
)->regexps
[i
] = allof
;
4810 for (j
= 0; j
< REGEXP_ALLOF (allof
)->regexps_num
; j
++)
4811 if (j
!= oneof_index
)
4812 REGEXP_ALLOF (allof
)->regexps
[j
]
4813 = copy_insn_regexp (REGEXP_ALLOF (regexp
)->regexps
[j
]);
4815 REGEXP_ALLOF (allof
)->regexps
[j
]
4816 = copy_insn_regexp (REGEXP_ONEOF (oneof
)->regexps
[i
]);
4818 regexp_transformed_p
= 1;
4822 if (regexp
->mode
== rm_allof
)
4823 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
4825 switch (REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
)
4828 seq
= REGEXP_ALLOF (regexp
)->regexps
[i
];
4829 if (max_seq_length
< REGEXP_SEQUENCE (seq
)->regexps_num
)
4830 max_seq_length
= REGEXP_SEQUENCE (seq
)->regexps_num
;
4843 if (max_seq_length
!= 0)
4845 gcc_assert (max_seq_length
!= 1
4846 && REGEXP_ALLOF (regexp
)->regexps_num
> 1);
4847 result
= XCREATENODEVAR (struct regexp
, sizeof (struct regexp
)
4848 + sizeof (regexp_t
) * (max_seq_length
- 1));
4849 result
->mode
= rm_sequence
;
4850 result
->pos
= regexp
->pos
;
4851 REGEXP_SEQUENCE (result
)->regexps_num
= max_seq_length
;
4852 for (i
= 0; i
< max_seq_length
; i
++)
4855 for (j
= 0; j
< REGEXP_ALLOF (regexp
)->regexps_num
; j
++)
4856 switch (REGEXP_ALLOF (regexp
)->regexps
[j
]->mode
)
4859 if (i
< (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp
)
4860 ->regexps
[j
])->regexps_num
))
4863 = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp
)
4873 allof_op
= REGEXP_ALLOF (regexp
)->regexps
[j
];
4881 if (allof_length
== 1)
4882 REGEXP_SEQUENCE (result
)->regexps
[i
] = allof_op
;
4885 allof
= XCREATENODEVAR (struct regexp
, sizeof (struct regexp
)
4887 * (allof_length
- 1));
4888 allof
->mode
= rm_allof
;
4889 allof
->pos
= regexp
->pos
;
4890 REGEXP_ALLOF (allof
)->regexps_num
= allof_length
;
4891 REGEXP_SEQUENCE (result
)->regexps
[i
] = allof
;
4893 for (j
= 0; j
< REGEXP_ALLOF (regexp
)->regexps_num
; j
++)
4894 if (REGEXP_ALLOF (regexp
)->regexps
[j
]->mode
== rm_sequence
4896 (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp
)
4897 ->regexps
[j
])->regexps_num
)))
4899 allof_op
= (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp
)
4902 REGEXP_ALLOF (allof
)->regexps
[allof_length
]
4907 && (REGEXP_ALLOF (regexp
)->regexps
[j
]->mode
4909 || (REGEXP_ALLOF (regexp
)->regexps
[j
]->mode
4912 allof_op
= REGEXP_ALLOF (regexp
)->regexps
[j
];
4913 REGEXP_ALLOF (allof
)->regexps
[allof_length
]
4919 regexp_transformed_p
= 1;
4926 /* The function traverses IR of reservation and applies transformations
4927 implemented by FUNC. */
4929 regexp_transform_func (regexp_t regexp
, regexp_t (*func
) (regexp_t regexp
))
4933 switch (regexp
->mode
)
4936 for (i
= 0; i
< REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
4937 REGEXP_SEQUENCE (regexp
)->regexps
[i
]
4938 = regexp_transform_func (REGEXP_SEQUENCE (regexp
)->regexps
[i
],
4943 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
4944 REGEXP_ALLOF (regexp
)->regexps
[i
]
4945 = regexp_transform_func (REGEXP_ALLOF (regexp
)->regexps
[i
], func
);
4949 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
4950 REGEXP_ONEOF (regexp
)->regexps
[i
]
4951 = regexp_transform_func (REGEXP_ONEOF (regexp
)->regexps
[i
], func
);
4955 REGEXP_REPEAT (regexp
)->regexp
4956 = regexp_transform_func (REGEXP_REPEAT (regexp
)->regexp
, func
);
4966 return (*func
) (regexp
);
4969 /* The function applies all transformations for IR representation of
4970 reservation REGEXP. */
4972 transform_regexp (regexp_t regexp
)
4974 regexp
= regexp_transform_func (regexp
, transform_1
);
4977 regexp_transformed_p
= 0;
4978 regexp
= regexp_transform_func (regexp
, transform_2
);
4979 regexp
= regexp_transform_func (regexp
, transform_3
);
4981 while (regexp_transformed_p
);
4985 /* The function applies all transformations for reservations of all
4986 insn declarations. */
4988 transform_insn_regexps (void)
4993 transform_time
= create_ticker ();
4994 add_advance_cycle_insn_decl ();
4996 add_collapse_ndfa_insn_decl ();
4998 fprintf (stderr
, "Reservation transformation...");
4999 for (i
= 0; i
< description
->normal_decls_num
; i
++)
5001 decl
= description
->decls
[i
];
5002 if (decl
->mode
== dm_insn_reserv
)
5003 DECL_INSN_RESERV (decl
)->transformed_regexp
5004 = transform_regexp (copy_insn_regexp
5005 (DECL_INSN_RESERV (decl
)->regexp
));
5008 fprintf (stderr
, "done\n");
5009 ticker_off (&transform_time
);
5014 /* The following variable value is TRUE if the first annotated message
5015 about units to automata distribution has been output. */
5016 static int annotation_message_reported_p
;
5018 /* The vector contains all decls which are automata. */
5019 static vec
<decl_t
> automaton_decls
;
5021 /* The following structure describes usage of a unit in a reservation. */
5024 unit_decl_t unit_decl
;
5025 /* The following forms a list of units used on the same cycle in the
5026 same alternative. The list is ordered by the correspdoning unit
5027 declarations and there is no unit declaration duplication in the
5029 struct unit_usage
*next
;
5031 typedef struct unit_usage
*unit_usage_t
;
5034 /* Obstack for unit_usage structures. */
5035 static struct obstack unit_usages
;
5037 /* VLA for representation of array of pointers to unit usage
5038 structures. There is an element for each combination of
5039 (alternative number, cycle). Unit usages on given cycle in
5040 alternative with given number are referred through element with
5041 index equals to the cycle * number of all alternatives in the
5042 regexp + the alternative number. */
5043 static vec
<unit_usage_t
> cycle_alt_unit_usages
;
5045 /* The following function creates the structure unit_usage for UNIT on
5046 CYCLE in REGEXP alternative with ALT_NUM. The structure is made
5047 accessed through cycle_alt_unit_usages. */
5049 store_alt_unit_usage (regexp_t regexp
, regexp_t unit
, int cycle
,
5053 unit_decl_t unit_decl
;
5054 unit_usage_t unit_usage_ptr
, curr
, prev
;
5057 gcc_assert (regexp
&& regexp
->mode
== rm_oneof
5058 && alt_num
< REGEXP_ONEOF (regexp
)->regexps_num
);
5059 unit_decl
= REGEXP_UNIT (unit
)->unit_decl
;
5061 length
= (cycle
+ 1) * REGEXP_ONEOF (regexp
)->regexps_num
;
5062 while (cycle_alt_unit_usages
.length () < length
)
5063 cycle_alt_unit_usages
.safe_push (NULL
);
5065 index
= cycle
* REGEXP_ONEOF (regexp
)->regexps_num
+ alt_num
;
5067 for (curr
= cycle_alt_unit_usages
[index
];
5069 prev
= curr
, curr
= curr
->next
)
5070 if (curr
->unit_decl
>= unit_decl
)
5072 if (curr
!= NULL
&& curr
->unit_decl
== unit_decl
)
5074 obstack_blank (&unit_usages
, sizeof (struct unit_usage
));
5075 unit_usage_ptr
= (struct unit_usage
*) obstack_base (&unit_usages
);
5076 obstack_finish (&unit_usages
);
5077 unit_usage_ptr
->unit_decl
= unit_decl
;
5078 unit_decl
->last_distribution_check_cycle
= -1; /* undefined */
5079 unit_usage_ptr
->next
= curr
;
5081 cycle_alt_unit_usages
[index
] = unit_usage_ptr
;
5083 prev
->next
= unit_usage_ptr
;
5086 /* Return true if unit UNIT_DECL is present on the LIST. */
5088 unit_present_on_list_p (unit_usage_t list
, unit_decl_t unit_decl
)
5090 while (list
!= NULL
)
5092 if (list
->unit_decl
== unit_decl
)
5099 /* The function returns true if reservations of alternatives ALT1 and
5100 ALT2 are equal after excluding reservations of units of
5101 EXCLUDED_AUTOMATON_DECL. */
5103 equal_alternatives_p (int alt1
, int alt2
, int n_alts
,
5104 struct automaton_decl
*excluded_automaton_decl
)
5107 unit_usage_t list1
, list2
;
5110 i
< (int) cycle_alt_unit_usages
.length ();
5113 for (list1
= cycle_alt_unit_usages
[i
+ alt1
],
5114 list2
= cycle_alt_unit_usages
[i
+ alt2
];;
5115 list1
= list1
->next
, list2
= list2
->next
)
5117 while (list1
!= NULL
5118 && list1
->unit_decl
->automaton_decl
== excluded_automaton_decl
)
5119 list1
= list1
->next
;
5120 while (list2
!= NULL
5121 && list2
->unit_decl
->automaton_decl
== excluded_automaton_decl
)
5122 list2
= list2
->next
;
5123 if (list1
== NULL
|| list2
== NULL
)
5130 if (list1
->unit_decl
!= list2
->unit_decl
)
5138 /* The function processes given REGEXP to find units with the wrong
5141 check_regexp_units_distribution (const char *insn_reserv_name
,
5144 int i
, j
, k
, cycle
, start
, n_alts
, alt
, alt2
;
5145 bool annotation_reservation_message_reported_p
;
5146 regexp_t seq
, allof
, unit
;
5147 struct unit_usage
*unit_usage_ptr
;
5150 if (regexp
== NULL
|| regexp
->mode
!= rm_oneof
)
5152 /* Store all unit usages in the regexp: */
5153 obstack_init (&unit_usages
);
5154 cycle_alt_unit_usages
.create (10);
5156 for (i
= REGEXP_ONEOF (regexp
)->regexps_num
- 1; i
>= 0; i
--)
5158 seq
= REGEXP_ONEOF (regexp
)->regexps
[i
];
5162 for (j
= 0; j
< REGEXP_SEQUENCE (seq
)->regexps_num
; j
++)
5164 allof
= REGEXP_SEQUENCE (seq
)->regexps
[j
];
5165 switch (allof
->mode
)
5168 for (k
= 0; k
< REGEXP_ALLOF (allof
)->regexps_num
; k
++)
5170 unit
= REGEXP_ALLOF (allof
)->regexps
[k
];
5171 if (unit
->mode
== rm_unit
)
5172 store_alt_unit_usage (regexp
, unit
, j
, i
);
5174 gcc_assert (unit
->mode
== rm_nothing
);
5179 store_alt_unit_usage (regexp
, allof
, j
, i
);
5192 for (k
= 0; k
< REGEXP_ALLOF (seq
)->regexps_num
; k
++)
5194 unit
= REGEXP_ALLOF (seq
)->regexps
[k
];
5198 store_alt_unit_usage (regexp
, unit
, 0, i
);
5211 store_alt_unit_usage (regexp
, seq
, 0, i
);
5221 /* Check distribution: */
5222 for (i
= 0; i
< (int) cycle_alt_unit_usages
.length (); i
++)
5223 for (unit_usage_ptr
= cycle_alt_unit_usages
[i
];
5224 unit_usage_ptr
!= NULL
;
5225 unit_usage_ptr
= unit_usage_ptr
->next
)
5226 unit_usage_ptr
->unit_decl
->last_distribution_check_cycle
= -1;
5227 n_alts
= REGEXP_ONEOF (regexp
)->regexps_num
;
5228 marked
.create (n_alts
);
5229 for (i
= 0; i
< n_alts
; i
++)
5230 marked
.safe_push (0);
5231 annotation_reservation_message_reported_p
= false;
5232 for (i
= 0; i
< (int) cycle_alt_unit_usages
.length (); i
++)
5235 start
= cycle
* n_alts
;
5236 for (unit_usage_ptr
= cycle_alt_unit_usages
[i
];
5237 unit_usage_ptr
!= NULL
;
5238 unit_usage_ptr
= unit_usage_ptr
->next
)
5240 if (unit_usage_ptr
->unit_decl
->last_distribution_check_cycle
== cycle
)
5242 unit_usage_ptr
->unit_decl
->last_distribution_check_cycle
= cycle
;
5243 for (alt
= 0; alt
< n_alts
; alt
++)
5244 if (! unit_present_on_list_p (cycle_alt_unit_usages
[start
+ alt
],
5245 unit_usage_ptr
->unit_decl
))
5249 memset (marked
.address (), 0, n_alts
* sizeof (int));
5250 for (alt
= 0; alt
< n_alts
; alt
++)
5252 if (! unit_present_on_list_p (cycle_alt_unit_usages
[start
+ alt
],
5253 unit_usage_ptr
->unit_decl
))
5256 j
< (int) cycle_alt_unit_usages
.length ();
5260 if (! unit_present_on_list_p
5261 (cycle_alt_unit_usages
[start
+ alt2
],
5262 unit_usage_ptr
->unit_decl
)
5263 && equal_alternatives_p (alt
, alt2
, n_alts
,
5265 ->unit_decl
->automaton_decl
))
5272 for (alt
= 0; alt
< n_alts
&& marked
[alt
]; alt
++)
5274 if (alt
< n_alts
&& 0)
5276 if (! annotation_message_reported_p
)
5278 fprintf (stderr
, "\n");
5279 error ("The following units do not satisfy units-automata distribution rule");
5280 error ("(Unit presence on one alt and its absence on other alt\n");
5281 error (" result in different other automata reservations)");
5282 annotation_message_reported_p
= TRUE
;
5284 if (! annotation_reservation_message_reported_p
)
5286 error ("Reserv %s:", insn_reserv_name
);
5287 annotation_reservation_message_reported_p
= true;
5289 error (" Unit %s, cycle %d, alt %d, another alt %d",
5290 unit_usage_ptr
->unit_decl
->name
, cycle
, i
% n_alts
, alt
);
5295 cycle_alt_unit_usages
.release ();
5296 obstack_free (&unit_usages
, NULL
);
5299 /* The function finds units which violates units to automata
5300 distribution rule. If the units exist, report about them. */
5302 check_unit_distributions_to_automata (void)
5308 fprintf (stderr
, "Check unit distributions to automata...");
5309 automaton_decls
.create (0);
5310 for (i
= 0; i
< description
->decls_num
; i
++)
5312 decl
= description
->decls
[i
];
5313 if (decl
->mode
== dm_automaton
)
5314 automaton_decls
.safe_push (decl
);
5316 if (automaton_decls
.length () > 1)
5318 annotation_message_reported_p
= FALSE
;
5319 for (i
= 0; i
< description
->decls_num
; i
++)
5321 decl
= description
->decls
[i
];
5322 if (decl
->mode
== dm_insn_reserv
)
5323 check_regexp_units_distribution
5324 (DECL_INSN_RESERV (decl
)->name
,
5325 DECL_INSN_RESERV (decl
)->transformed_regexp
);
5328 automaton_decls
.release ();
5330 fprintf (stderr
, "done\n");
5335 /* The page contains code for building alt_states (see comments for
5336 IR) describing all possible insns reservations of an automaton. */
5338 /* Current state being formed for which the current alt_state
5340 static state_t state_being_formed
;
5342 /* Current alt_state being formed. */
5343 static alt_state_t alt_state_being_formed
;
5345 /* This recursive function processes `,' and units in reservation
5346 REGEXP for forming alt_states of AUTOMATON. It is believed that
5347 CURR_CYCLE is start cycle of all reservation REGEXP. */
5349 process_seq_for_forming_states (regexp_t regexp
, automaton_t automaton
,
5357 switch (regexp
->mode
)
5360 if (REGEXP_UNIT (regexp
)->unit_decl
->corresponding_automaton_num
5361 == automaton
->automaton_order_num
)
5362 set_state_reserv (state_being_formed
, curr_cycle
,
5363 REGEXP_UNIT (regexp
)->unit_decl
->unit_num
);
5367 for (i
= 0; i
< REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
5369 = process_seq_for_forming_states
5370 (REGEXP_SEQUENCE (regexp
)->regexps
[i
], automaton
, curr_cycle
) + 1;
5375 int finish_cycle
= 0;
5378 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
5380 cycle
= process_seq_for_forming_states (REGEXP_ALLOF (regexp
)
5382 automaton
, curr_cycle
);
5383 if (finish_cycle
< cycle
)
5384 finish_cycle
= cycle
;
5386 return finish_cycle
;
5397 /* This recursive function finishes forming ALT_STATE of AUTOMATON and
5398 inserts alt_state into the table. */
5400 finish_forming_alt_state (alt_state_t alt_state
,
5401 automaton_t automaton ATTRIBUTE_UNUSED
)
5403 state_t state_in_table
;
5404 state_t corresponding_state
;
5406 corresponding_state
= alt_state
->state
;
5407 state_in_table
= insert_state (corresponding_state
);
5408 if (state_in_table
!= corresponding_state
)
5410 free_state (corresponding_state
);
5411 alt_state
->state
= state_in_table
;
5415 /* The following variable value is current automaton insn for whose
5416 reservation the alt states are created. */
5417 static ainsn_t curr_ainsn
;
5419 /* This recursive function processes `|' in reservation REGEXP for
5420 forming alt_states of AUTOMATON. List of the alt states should
5421 have the same order as in the description. */
5423 process_alts_for_forming_states (regexp_t regexp
, automaton_t automaton
,
5428 if (regexp
->mode
!= rm_oneof
)
5430 alt_state_being_formed
= get_free_alt_state ();
5431 state_being_formed
= get_free_state (1, automaton
);
5432 alt_state_being_formed
->state
= state_being_formed
;
5433 /* We inserts in reverse order but we process alternatives also
5434 in reverse order. So we have the same order of alternative
5435 as in the description. */
5436 alt_state_being_formed
->next_alt_state
= curr_ainsn
->alt_states
;
5437 curr_ainsn
->alt_states
= alt_state_being_formed
;
5438 (void) process_seq_for_forming_states (regexp
, automaton
, 0);
5439 finish_forming_alt_state (alt_state_being_formed
, automaton
);
5443 gcc_assert (!inside_oneof_p
);
5444 /* We processes it in reverse order to get list with the same
5445 order as in the description. See also the previous
5447 for (i
= REGEXP_ONEOF (regexp
)->regexps_num
- 1; i
>= 0; i
--)
5448 process_alts_for_forming_states (REGEXP_ONEOF (regexp
)->regexps
[i
],
5453 /* Create nodes alt_state for all AUTOMATON insns. */
5455 create_alt_states (automaton_t automaton
)
5457 struct insn_reserv_decl
*reserv_decl
;
5459 for (curr_ainsn
= automaton
->ainsn_list
;
5461 curr_ainsn
= curr_ainsn
->next_ainsn
)
5463 reserv_decl
= curr_ainsn
->insn_reserv_decl
;
5464 if (!special_decl_p (reserv_decl
))
5466 curr_ainsn
->alt_states
= NULL
;
5467 process_alts_for_forming_states (reserv_decl
->transformed_regexp
,
5469 curr_ainsn
->sorted_alt_states
5470 = uniq_sort_alt_states (curr_ainsn
->alt_states
);
5477 /* The page contains major code for building DFA(s) for fast pipeline
5478 hazards recognition. */
5480 /* The function forms list of ainsns of AUTOMATON with the same
5484 form_ainsn_with_same_reservs (automaton_t automaton
)
5488 vec
<ainsn_t
> last_insns
;
5489 last_insns
.create (150);
5491 for (curr_ainsn
= automaton
->ainsn_list
;
5493 curr_ainsn
= curr_ainsn
->next_ainsn
)
5494 if (special_decl_p (curr_ainsn
->insn_reserv_decl
))
5496 curr_ainsn
->next_same_reservs_insn
= NULL
;
5497 curr_ainsn
->first_insn_with_same_reservs
= 1;
5501 for (i
= 0; i
< last_insns
.length (); i
++)
5503 (curr_ainsn
->sorted_alt_states
,
5504 last_insns
[i
]->sorted_alt_states
))
5506 curr_ainsn
->next_same_reservs_insn
= NULL
;
5507 if (i
< last_insns
.length ())
5509 curr_ainsn
->first_insn_with_same_reservs
= 0;
5510 last_insns
[i
]->next_same_reservs_insn
= curr_ainsn
;
5511 last_insns
[i
] = curr_ainsn
;
5515 last_insns
.safe_push (curr_ainsn
);
5516 curr_ainsn
->first_insn_with_same_reservs
= 1;
5519 last_insns
.release ();
5522 /* Forming unit reservations which can affect creating the automaton
5523 states achieved from a given state. It permits to build smaller
5524 automata in many cases. We would have the same automata after
5525 the minimization without such optimization, but the automaton
5526 right after the building could be huge. So in other words, usage
5527 of reservs_matter means some minimization during building the
5529 static reserv_sets_t
5530 form_reservs_matter (automaton_t automaton
)
5533 reserv_sets_t reservs_matter
= alloc_empty_reserv_sets();
5535 for (cycle
= 0; cycle
< max_cycles_num
; cycle
++)
5536 for (unit
= 0; unit
< description
->units_num
; unit
++)
5537 if (units_array
[unit
]->automaton_decl
5538 == automaton
->corresponding_automaton_decl
5539 && (cycle
>= units_array
[unit
]->min_occ_cycle_num
5540 /* We can not remove queried unit from reservations. */
5541 || units_array
[unit
]->query_p
5542 /* We can not remove units which are used
5543 `exclusion_set', `presence_set',
5544 `final_presence_set', `absence_set', and
5545 `final_absence_set'. */
5546 || units_array
[unit
]->in_set_p
))
5547 set_unit_reserv (reservs_matter
, cycle
, unit
);
5548 return reservs_matter
;
5551 /* The following function creates all states of nondeterministic AUTOMATON. */
5553 make_automaton (automaton_t automaton
)
5556 struct insn_reserv_decl
*insn_reserv_decl
;
5557 alt_state_t alt_state
;
5559 state_t start_state
;
5561 vec
<state_t
> state_stack
;
5562 state_stack
.create (150);
5564 reserv_sets_t reservs_matter
= form_reservs_matter (automaton
);
5566 /* Create the start state (empty state). */
5567 start_state
= insert_state (get_free_state (1, automaton
));
5568 automaton
->start_state
= start_state
;
5569 start_state
->it_was_placed_in_stack_for_NDFA_forming
= 1;
5570 state_stack
.safe_push (start_state
);
5572 while (state_stack
.length () != 0)
5574 state
= state_stack
.pop ();
5575 for (ainsn
= automaton
->ainsn_list
;
5577 ainsn
= ainsn
->next_ainsn
)
5578 if (ainsn
->first_insn_with_same_reservs
)
5580 insn_reserv_decl
= ainsn
->insn_reserv_decl
;
5581 if (!special_decl_p (insn_reserv_decl
))
5583 /* We process alt_states in the same order as they are
5584 present in the description. */
5585 for (alt_state
= ainsn
->alt_states
;
5587 alt_state
= alt_state
->next_alt_state
)
5589 state2
= alt_state
->state
;
5590 if (!intersected_state_reservs_p (state
, state2
))
5592 state2
= states_union (state
, state2
, reservs_matter
);
5593 if (!state2
->it_was_placed_in_stack_for_NDFA_forming
)
5595 state2
->it_was_placed_in_stack_for_NDFA_forming
5597 state_stack
.safe_push (state2
);
5599 if (progress_flag
&& states_n
% 100 == 0)
5600 fprintf (stderr
, ".");
5602 add_arc (state
, state2
, ainsn
);
5609 /* Add transition to advance cycle. */
5610 state2
= state_shift (state
, reservs_matter
);
5611 if (!state2
->it_was_placed_in_stack_for_NDFA_forming
)
5613 state2
->it_was_placed_in_stack_for_NDFA_forming
= 1;
5614 state_stack
.safe_push (state2
);
5616 if (progress_flag
&& states_n
% 100 == 0)
5617 fprintf (stderr
, ".");
5619 add_arc (state
, state2
, automaton
->advance_ainsn
);
5621 state_stack
.release ();
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
;
5665 int new_state_p
= 0;
5667 if (arcs_marked_by_insn
== NULL
)
5669 if (arcs_marked_by_insn
->next_arc_marked_by_insn
== NULL
)
5670 state
= arcs_marked_by_insn
->to_state
;
5673 gcc_assert (ndfa_flag
);
5674 /* Create composed state. */
5675 state
= get_free_state (0, arcs_marked_by_insn
->to_state
->automaton
);
5676 curr_alt_state
= NULL
;
5677 for (curr_arc
= arcs_marked_by_insn
;
5679 curr_arc
= curr_arc
->next_arc_marked_by_insn
)
5680 if (curr_arc
->to_state
->component_states
== NULL
)
5682 new_alt_state
= get_free_alt_state ();
5683 new_alt_state
->next_alt_state
= curr_alt_state
;
5684 new_alt_state
->state
= curr_arc
->to_state
;
5685 curr_alt_state
= new_alt_state
;
5688 for (alt_state
= curr_arc
->to_state
->component_states
;
5690 alt_state
= alt_state
->next_sorted_alt_state
)
5692 new_alt_state
= get_free_alt_state ();
5693 new_alt_state
->next_alt_state
= curr_alt_state
;
5694 new_alt_state
->state
= alt_state
->state
;
5695 gcc_assert (!alt_state
->state
->component_states
);
5696 curr_alt_state
= new_alt_state
;
5698 /* There are not identical sets in the alt state list. */
5699 canonical_alt_states_list
= uniq_sort_alt_states (curr_alt_state
);
5700 if (canonical_alt_states_list
->next_sorted_alt_state
== NULL
)
5703 state
= canonical_alt_states_list
->state
;
5704 free_state (temp_state
);
5708 state
->component_states
= canonical_alt_states_list
;
5709 state_in_table
= insert_state (state
);
5710 if (state_in_table
!= state
)
5713 (state_in_table
->it_was_placed_in_stack_for_DFA_forming
);
5715 state
= state_in_table
;
5719 gcc_assert (!state
->it_was_placed_in_stack_for_DFA_forming
);
5721 for (curr_alt_state
= state
->component_states
;
5722 curr_alt_state
!= NULL
;
5723 curr_alt_state
= curr_alt_state
->next_sorted_alt_state
)
5724 for (curr_arc
= first_out_arc (curr_alt_state
->state
);
5726 curr_arc
= next_out_arc (curr_arc
))
5728 /* When producing collapse-NDFA transitions, we
5729 only add advance-cycle transitions to the
5730 collapsed states. */
5731 || (curr_arc
->insn
->insn_reserv_decl
5732 != DECL_INSN_RESERV (advance_cycle_insn_decl
)))
5733 add_arc (state
, curr_arc
->to_state
, curr_arc
->insn
);
5735 arcs_marked_by_insn
->to_state
= state
;
5736 for (alts_number
= 0,
5737 curr_arc
= arcs_marked_by_insn
->next_arc_marked_by_insn
;
5739 curr_arc
= next_arc
)
5741 next_arc
= curr_arc
->next_arc_marked_by_insn
;
5742 remove_arc (original_state
, curr_arc
);
5747 if (!state
->it_was_placed_in_stack_for_DFA_forming
)
5749 state
->it_was_placed_in_stack_for_DFA_forming
= 1;
5750 state_stack
->safe_push (state
);
5755 /* The function transforms nondeterministic AUTOMATON into
5759 NDFA_to_DFA (automaton_t automaton
)
5761 state_t start_state
;
5764 vec
<state_t
> state_stack
;
5768 state_stack
.create (0);
5770 /* Create the start state (empty state). */
5771 start_state
= automaton
->start_state
;
5772 start_state
->it_was_placed_in_stack_for_DFA_forming
= 1;
5773 state_stack
.safe_push (start_state
);
5775 while (state_stack
.length () != 0)
5777 state
= state_stack
.pop ();
5778 form_arcs_marked_by_insn (state
);
5779 for (i
= 0; i
< description
->decls_num
; i
++)
5781 decl
= description
->decls
[i
];
5782 if (decl
->mode
== dm_insn_reserv
5783 && decl
!= collapse_ndfa_insn_decl
5784 && create_composed_state
5785 (state
, DECL_INSN_RESERV (decl
)->arcs_marked_by_insn
,
5789 if (progress_flag
&& states_n
% 100 == 0)
5790 fprintf (stderr
, ".");
5793 /* Add a transition to collapse the NDFA. */
5796 if (state
->component_states
!= NULL
)
5798 state_t state2
= state
->component_states
->state
;
5799 if (!state2
->it_was_placed_in_stack_for_DFA_forming
)
5801 state2
->it_was_placed_in_stack_for_DFA_forming
= 1;
5802 state_stack
.safe_push (state2
);
5804 add_arc (state
, state2
, automaton
->collapse_ainsn
);
5807 add_arc (state
, state
, automaton
->collapse_ainsn
);
5810 state_stack
.release ();
5813 /* The following variable value is current number (1, 2, ...) of passing
5815 static int curr_state_graph_pass_num
;
5817 /* This recursive function passes all states achieved from START_STATE
5818 and applies APPLIED_FUNC to them. */
5820 pass_state_graph (state_t start_state
, void (*applied_func
) (state_t state
))
5824 if (start_state
->pass_num
== curr_state_graph_pass_num
)
5826 start_state
->pass_num
= curr_state_graph_pass_num
;
5827 (*applied_func
) (start_state
);
5828 for (arc
= first_out_arc (start_state
);
5830 arc
= next_out_arc (arc
))
5831 pass_state_graph (arc
->to_state
, applied_func
);
5834 /* This recursive function passes all states of AUTOMATON and applies
5835 APPLIED_FUNC to them. */
5837 pass_states (automaton_t automaton
, void (*applied_func
) (state_t state
))
5839 curr_state_graph_pass_num
++;
5840 pass_state_graph (automaton
->start_state
, applied_func
);
5843 /* The function initializes code for passing of all states. */
5845 initiate_pass_states (void)
5847 curr_state_graph_pass_num
= 0;
5850 /* The following vla is used for storing pointers to all achieved
5852 static vec
<state_t
> all_achieved_states
;
5854 /* This function is called by function pass_states to add an achieved
5857 add_achieved_state (state_t state
)
5859 all_achieved_states
.safe_push (state
);
5862 /* The function sets up equivalence numbers of insns which mark all
5863 out arcs of STATE by equiv_class_num_1 (if ODD_ITERATION_FLAG has
5864 nonzero value) or by equiv_class_num_2 of the destination state. */
5866 set_out_arc_insns_equiv_num (state_t state
, int odd_iteration_flag
)
5870 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
5872 gcc_assert (!arc
->insn
->insn_reserv_decl
->equiv_class_num
);
5873 arc
->insn
->insn_reserv_decl
->equiv_class_num
5874 = (odd_iteration_flag
5875 ? arc
->to_state
->equiv_class_num_1
5876 : arc
->to_state
->equiv_class_num_2
);
5877 gcc_assert (arc
->insn
->insn_reserv_decl
->equiv_class_num
);
5881 /* The function clears equivalence numbers and alt_states in all insns
5882 which mark all out arcs of STATE. */
5884 clear_arc_insns_equiv_num (state_t state
)
5888 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
5889 arc
->insn
->insn_reserv_decl
->equiv_class_num
= 0;
5893 /* The following function returns TRUE if STATE reserves the unit with
5894 UNIT_NUM on the first cycle. */
5896 first_cycle_unit_presence (state_t state
, int unit_num
)
5898 alt_state_t alt_state
;
5900 if (state
->component_states
== NULL
)
5901 return test_unit_reserv (state
->reservs
, 0, unit_num
);
5904 for (alt_state
= state
->component_states
;
5906 alt_state
= alt_state
->next_sorted_alt_state
)
5907 if (test_unit_reserv (alt_state
->state
->reservs
, 0, unit_num
))
5913 /* This fills in the presence_signature[] member of STATE. */
5915 cache_presence (state_t state
)
5919 sz
= (description
->query_units_num
+ sizeof (int) * CHAR_BIT
- 1)
5920 / (sizeof (int) * CHAR_BIT
);
5922 state
->presence_signature
= XCREATENODEVEC (unsigned int, sz
);
5923 for (i
= 0; i
< description
->units_num
; i
++)
5924 if (units_array
[i
]->query_p
)
5926 int presence1_p
= first_cycle_unit_presence (state
, i
);
5927 state
->presence_signature
[num
/ (sizeof (int) * CHAR_BIT
)]
5928 |= (!!presence1_p
) << (num
% (sizeof (int) * CHAR_BIT
));
5933 /* The function returns nonzero value if STATE is not equivalent to
5934 ANOTHER_STATE from the same current partition on equivalence
5935 classes. Another state has ANOTHER_STATE_OUT_ARCS_NUM number of
5936 output arcs. Iteration of making equivalence partition is defined
5937 by ODD_ITERATION_FLAG. */
5939 state_is_differed (state_t state
, state_t another_state
,
5940 int odd_iteration_flag
)
5943 unsigned int sz
, si
;
5945 gcc_assert (state
->num_out_arcs
== another_state
->num_out_arcs
);
5947 sz
= (description
->query_units_num
+ sizeof (int) * CHAR_BIT
- 1)
5948 / (sizeof (int) * CHAR_BIT
);
5950 for (si
= 0; si
< sz
; si
++)
5951 gcc_assert (state
->presence_signature
[si
]
5952 == another_state
->presence_signature
[si
]);
5954 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
5956 if ((odd_iteration_flag
5957 ? arc
->to_state
->equiv_class_num_1
5958 : arc
->to_state
->equiv_class_num_2
)
5959 != arc
->insn
->insn_reserv_decl
->equiv_class_num
)
5966 /* Compares two states pointed to by STATE_PTR_1 and STATE_PTR_2
5967 and return -1, 0 or 1. This function can be used as predicate for
5968 qsort(). It requires the member presence_signature[] of both
5969 states be filled. */
5971 compare_states_for_equiv (const void *state_ptr_1
,
5972 const void *state_ptr_2
)
5974 const_state_t
const s1
= *(const_state_t
const*)state_ptr_1
;
5975 const_state_t
const s2
= *(const_state_t
const*)state_ptr_2
;
5976 unsigned int sz
, si
;
5977 if (s1
->num_out_arcs
< s2
->num_out_arcs
)
5979 else if (s1
->num_out_arcs
> s2
->num_out_arcs
)
5982 sz
= (description
->query_units_num
+ sizeof (int) * CHAR_BIT
- 1)
5983 / (sizeof (int) * CHAR_BIT
);
5985 for (si
= 0; si
< sz
; si
++)
5986 if (s1
->presence_signature
[si
] < s2
->presence_signature
[si
])
5988 else if (s1
->presence_signature
[si
] > s2
->presence_signature
[si
])
5993 /* The function makes initial partition of STATES on equivalent
5994 classes and saves it into CLASSES. This function requires the input
5995 to be sorted via compare_states_for_equiv(). */
5997 init_equiv_class (vec
<state_t
> states
, vec
<state_t
> *classes
)
6003 classes
->create (150);
6004 for (i
= 0; i
< states
.length (); i
++)
6006 state_t state
= states
[i
];
6009 if (compare_states_for_equiv (&prev
, &state
) != 0)
6011 classes
->safe_push (prev
);
6016 state
->equiv_class_num_1
= class_num
;
6017 state
->next_equiv_class_state
= prev
;
6021 classes
->safe_push (prev
);
6025 /* The function copies pointers to equivalent states from vla FROM
6028 copy_equiv_class (vec
<state_t
> *to
, vec
<state_t
> from
)
6034 /* The function processes equivalence class given by its first state,
6035 FIRST_STATE, on odd iteration if ODD_ITERATION_FLAG. If there
6036 are not equivalent states, the function partitions the class
6037 removing nonequivalent states and placing them in
6038 *NEXT_ITERATION_CLASSES, increments *NEW_EQUIV_CLASS_NUM_PTR ans
6039 assigns it to the state equivalence number. If the class has been
6040 partitioned, the function returns nonzero value. */
6042 partition_equiv_class (state_t first_state
, int odd_iteration_flag
,
6043 vec
<state_t
> *next_iteration_classes
,
6044 int *new_equiv_class_num_ptr
)
6046 state_t new_equiv_class
;
6054 while (first_state
!= NULL
)
6056 new_equiv_class
= NULL
;
6057 if (first_state
->next_equiv_class_state
!= NULL
)
6059 /* There are more one states in the class equivalence. */
6060 set_out_arc_insns_equiv_num (first_state
, odd_iteration_flag
);
6061 for (prev_state
= first_state
,
6062 curr_state
= first_state
->next_equiv_class_state
;
6064 curr_state
= next_state
)
6066 next_state
= curr_state
->next_equiv_class_state
;
6067 if (state_is_differed (curr_state
, first_state
,
6068 odd_iteration_flag
))
6070 /* Remove curr state from the class equivalence. */
6071 prev_state
->next_equiv_class_state
= next_state
;
6072 /* Add curr state to the new class equivalence. */
6073 curr_state
->next_equiv_class_state
= new_equiv_class
;
6074 if (new_equiv_class
== NULL
)
6075 (*new_equiv_class_num_ptr
)++;
6076 if (odd_iteration_flag
)
6077 curr_state
->equiv_class_num_2
= *new_equiv_class_num_ptr
;
6079 curr_state
->equiv_class_num_1
= *new_equiv_class_num_ptr
;
6080 new_equiv_class
= curr_state
;
6084 prev_state
= curr_state
;
6086 clear_arc_insns_equiv_num (first_state
);
6088 if (new_equiv_class
!= NULL
)
6089 next_iteration_classes
->safe_push (new_equiv_class
);
6090 first_state
= new_equiv_class
;
6095 /* The function finds equivalent states of AUTOMATON. */
6097 evaluate_equiv_classes (automaton_t automaton
, vec
<state_t
> *equiv_classes
)
6099 int new_equiv_class_num
;
6100 int odd_iteration_flag
;
6102 vec
<state_t
> next_iteration_classes
;
6105 all_achieved_states
.create (1500);
6106 pass_states (automaton
, add_achieved_state
);
6107 pass_states (automaton
, cache_presence
);
6108 all_achieved_states
.qsort (compare_states_for_equiv
);
6110 odd_iteration_flag
= 0;
6111 new_equiv_class_num
= init_equiv_class (all_achieved_states
,
6112 &next_iteration_classes
);
6116 odd_iteration_flag
= !odd_iteration_flag
;
6118 copy_equiv_class (equiv_classes
, next_iteration_classes
);
6120 /* Transfer equiv numbers for the next iteration. */
6121 for (i
= 0; i
< all_achieved_states
.length (); i
++)
6122 if (odd_iteration_flag
)
6123 all_achieved_states
[i
]->equiv_class_num_2
6124 = all_achieved_states
[i
]->equiv_class_num_1
;
6126 all_achieved_states
[i
]->equiv_class_num_1
6127 = all_achieved_states
[i
]->equiv_class_num_2
;
6129 for (i
= 0; i
< equiv_classes
->length (); i
++)
6130 if (partition_equiv_class ((*equiv_classes
)[i
],
6132 &next_iteration_classes
,
6133 &new_equiv_class_num
))
6136 while (!finish_flag
);
6137 next_iteration_classes
.release ();
6138 all_achieved_states
.release ();
6141 /* The function merges equivalent states of AUTOMATON. */
6143 merge_states (automaton_t automaton
, vec
<state_t
> equiv_classes
)
6147 state_t first_class_state
;
6148 alt_state_t alt_states
;
6149 alt_state_t alt_state
, new_alt_state
;
6154 /* Create states corresponding to equivalence classes containing two
6156 for (i
= 0; i
< equiv_classes
.length (); i
++)
6158 curr_state
= equiv_classes
[i
];
6159 if (curr_state
->next_equiv_class_state
!= NULL
)
6161 /* There are more one states in the class equivalence. */
6162 /* Create new compound state. */
6163 new_state
= get_free_state (0, automaton
);
6165 first_class_state
= curr_state
;
6166 for (curr_state
= first_class_state
;
6168 curr_state
= curr_state
->next_equiv_class_state
)
6170 curr_state
->equiv_class_state
= new_state
;
6171 if (curr_state
->component_states
== NULL
)
6173 new_alt_state
= get_free_alt_state ();
6174 new_alt_state
->state
= curr_state
;
6175 new_alt_state
->next_alt_state
= alt_states
;
6176 alt_states
= new_alt_state
;
6179 for (alt_state
= curr_state
->component_states
;
6181 alt_state
= alt_state
->next_sorted_alt_state
)
6183 new_alt_state
= get_free_alt_state ();
6184 new_alt_state
->state
= alt_state
->state
;
6185 new_alt_state
->next_alt_state
= alt_states
;
6186 alt_states
= new_alt_state
;
6189 /* Its is important that alt states were sorted before and
6190 after merging to have the same querying results. */
6191 new_state
->component_states
= uniq_sort_alt_states (alt_states
);
6194 curr_state
->equiv_class_state
= curr_state
;
6197 for (i
= 0; i
< equiv_classes
.length (); i
++)
6199 curr_state
= equiv_classes
[i
];
6200 if (curr_state
->next_equiv_class_state
!= NULL
)
6202 first_class_state
= curr_state
;
6203 /* Create new arcs output from the state corresponding to
6205 for (curr_arc
= first_out_arc (first_class_state
);
6207 curr_arc
= next_out_arc (curr_arc
))
6208 add_arc (first_class_state
->equiv_class_state
,
6209 curr_arc
->to_state
->equiv_class_state
,
6211 /* Delete output arcs from states of given class equivalence. */
6212 for (curr_state
= first_class_state
;
6214 curr_state
= curr_state
->next_equiv_class_state
)
6216 if (automaton
->start_state
== curr_state
)
6217 automaton
->start_state
= curr_state
->equiv_class_state
;
6218 /* Delete the state and its output arcs. */
6219 for (curr_arc
= first_out_arc (curr_state
);
6221 curr_arc
= next_arc
)
6223 next_arc
= next_out_arc (curr_arc
);
6224 free_arc (curr_arc
);
6230 /* Change `to_state' of arcs output from the state of given
6231 equivalence class. */
6232 for (curr_arc
= first_out_arc (curr_state
);
6234 curr_arc
= next_out_arc (curr_arc
))
6235 curr_arc
->to_state
= curr_arc
->to_state
->equiv_class_state
;
6240 /* The function sets up new_cycle_p for states if there is arc to the
6241 state marked by advance_cycle_insn_decl. */
6243 set_new_cycle_flags (state_t state
)
6247 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
6248 if (arc
->insn
->insn_reserv_decl
6249 == DECL_INSN_RESERV (advance_cycle_insn_decl
))
6250 arc
->to_state
->new_cycle_p
= 1;
6253 /* The top level function for minimization of deterministic
6256 minimize_DFA (automaton_t automaton
)
6258 vec
<state_t
> equiv_classes
= vNULL
;
6260 evaluate_equiv_classes (automaton
, &equiv_classes
);
6261 merge_states (automaton
, equiv_classes
);
6262 pass_states (automaton
, set_new_cycle_flags
);
6264 equiv_classes
.release ();
6267 /* Values of two variables are counted number of states and arcs in an
6269 static int curr_counted_states_num
;
6270 static int curr_counted_arcs_num
;
6272 /* The function is called by function `pass_states' to count states
6273 and arcs of an automaton. */
6275 incr_states_and_arcs_nums (state_t state
)
6279 curr_counted_states_num
++;
6280 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
6281 curr_counted_arcs_num
++;
6284 /* The function counts states and arcs of AUTOMATON. */
6286 count_states_and_arcs (automaton_t automaton
, int *states_num
,
6289 curr_counted_states_num
= 0;
6290 curr_counted_arcs_num
= 0;
6291 pass_states (automaton
, incr_states_and_arcs_nums
);
6292 *states_num
= curr_counted_states_num
;
6293 *arcs_num
= curr_counted_arcs_num
;
6296 /* The function builds one DFA AUTOMATON for fast pipeline hazards
6297 recognition after checking and simplifying IR of the
6300 build_automaton (automaton_t automaton
)
6305 ticker_on (&NDFA_time
);
6308 if (automaton
->corresponding_automaton_decl
== NULL
)
6309 fprintf (stderr
, "Create anonymous automaton");
6311 fprintf (stderr
, "Create automaton `%s'",
6312 automaton
->corresponding_automaton_decl
->name
);
6313 fprintf (stderr
, " (1 dot is 100 new states):");
6315 make_automaton (automaton
);
6317 fprintf (stderr
, " done\n");
6318 ticker_off (&NDFA_time
);
6319 count_states_and_arcs (automaton
, &states_num
, &arcs_num
);
6320 automaton
->NDFA_states_num
= states_num
;
6321 automaton
->NDFA_arcs_num
= arcs_num
;
6322 ticker_on (&NDFA_to_DFA_time
);
6325 if (automaton
->corresponding_automaton_decl
== NULL
)
6326 fprintf (stderr
, "Make anonymous DFA");
6328 fprintf (stderr
, "Make DFA `%s'",
6329 automaton
->corresponding_automaton_decl
->name
);
6330 fprintf (stderr
, " (1 dot is 100 new states):");
6332 NDFA_to_DFA (automaton
);
6334 fprintf (stderr
, " done\n");
6335 ticker_off (&NDFA_to_DFA_time
);
6336 count_states_and_arcs (automaton
, &states_num
, &arcs_num
);
6337 automaton
->DFA_states_num
= states_num
;
6338 automaton
->DFA_arcs_num
= arcs_num
;
6339 if (!no_minimization_flag
)
6341 ticker_on (&minimize_time
);
6344 if (automaton
->corresponding_automaton_decl
== NULL
)
6345 fprintf (stderr
, "Minimize anonymous DFA...");
6347 fprintf (stderr
, "Minimize DFA `%s'...",
6348 automaton
->corresponding_automaton_decl
->name
);
6350 minimize_DFA (automaton
);
6352 fprintf (stderr
, "done\n");
6353 ticker_off (&minimize_time
);
6354 count_states_and_arcs (automaton
, &states_num
, &arcs_num
);
6355 automaton
->minimal_DFA_states_num
= states_num
;
6356 automaton
->minimal_DFA_arcs_num
= arcs_num
;
6362 /* The page contains code for enumeration of all states of an automaton. */
6364 /* Variable used for enumeration of all states of an automaton. Its
6365 value is current number of automaton states. */
6366 static int curr_state_order_num
;
6368 /* The function is called by function `pass_states' for enumerating
6371 set_order_state_num (state_t state
)
6373 state
->order_state_num
= curr_state_order_num
;
6374 curr_state_order_num
++;
6377 /* The function enumerates all states of AUTOMATON. */
6379 enumerate_states (automaton_t automaton
)
6381 curr_state_order_num
= 0;
6382 pass_states (automaton
, set_order_state_num
);
6383 automaton
->achieved_states_num
= curr_state_order_num
;
6388 /* The page contains code for finding equivalent automaton insns
6391 /* The function inserts AINSN into cyclic list
6392 CYCLIC_EQUIV_CLASS_INSN_LIST of ainsns. */
6394 insert_ainsn_into_equiv_class (ainsn_t ainsn
,
6395 ainsn_t cyclic_equiv_class_insn_list
)
6397 if (cyclic_equiv_class_insn_list
== NULL
)
6398 ainsn
->next_equiv_class_insn
= ainsn
;
6401 ainsn
->next_equiv_class_insn
6402 = cyclic_equiv_class_insn_list
->next_equiv_class_insn
;
6403 cyclic_equiv_class_insn_list
->next_equiv_class_insn
= ainsn
;
6408 /* The function deletes equiv_class_insn into cyclic list of
6409 equivalent ainsns. */
6411 delete_ainsn_from_equiv_class (ainsn_t equiv_class_insn
)
6413 ainsn_t curr_equiv_class_insn
;
6414 ainsn_t prev_equiv_class_insn
;
6416 prev_equiv_class_insn
= equiv_class_insn
;
6417 for (curr_equiv_class_insn
= equiv_class_insn
->next_equiv_class_insn
;
6418 curr_equiv_class_insn
!= equiv_class_insn
;
6419 curr_equiv_class_insn
= curr_equiv_class_insn
->next_equiv_class_insn
)
6420 prev_equiv_class_insn
= curr_equiv_class_insn
;
6421 if (prev_equiv_class_insn
!= equiv_class_insn
)
6422 prev_equiv_class_insn
->next_equiv_class_insn
6423 = equiv_class_insn
->next_equiv_class_insn
;
6426 /* The function processes AINSN of a state in order to find equivalent
6427 ainsns. INSN_ARCS_ARRAY is table: code of insn -> out arc of the
6430 process_insn_equiv_class (ainsn_t ainsn
, arc_t
*insn_arcs_array
)
6434 ainsn_t cyclic_insn_list
;
6437 gcc_assert (insn_arcs_array
[ainsn
->insn_reserv_decl
->insn_num
]);
6439 /* New class of ainsns which are not equivalent to given ainsn. */
6440 cyclic_insn_list
= NULL
;
6443 next_insn
= curr_insn
->next_equiv_class_insn
;
6444 arc
= insn_arcs_array
[curr_insn
->insn_reserv_decl
->insn_num
];
6446 || (insn_arcs_array
[ainsn
->insn_reserv_decl
->insn_num
]->to_state
6449 delete_ainsn_from_equiv_class (curr_insn
);
6450 cyclic_insn_list
= insert_ainsn_into_equiv_class (curr_insn
,
6453 curr_insn
= next_insn
;
6455 while (curr_insn
!= ainsn
);
6458 /* The function processes STATE in order to find equivalent ainsns. */
6460 process_state_for_insn_equiv_partition (state_t state
)
6463 arc_t
*insn_arcs_array
= XCNEWVEC (arc_t
, description
->insns_num
);
6465 /* Process insns of the arcs. */
6466 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
6467 insn_arcs_array
[arc
->insn
->insn_reserv_decl
->insn_num
] = arc
;
6468 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
6469 process_insn_equiv_class (arc
->insn
, insn_arcs_array
);
6471 free (insn_arcs_array
);
6474 /* The function searches for equivalent ainsns of AUTOMATON. */
6476 set_insn_equiv_classes (automaton_t automaton
)
6481 ainsn_t cyclic_insn_list
;
6482 ainsn_t insn_with_same_reservs
;
6483 int equiv_classes_num
;
6485 /* All insns are included in one equivalence class. */
6486 cyclic_insn_list
= NULL
;
6487 for (ainsn
= automaton
->ainsn_list
; ainsn
!= NULL
; ainsn
= ainsn
->next_ainsn
)
6488 if (ainsn
->first_insn_with_same_reservs
)
6489 cyclic_insn_list
= insert_ainsn_into_equiv_class (ainsn
,
6491 /* Process insns in order to make equivalence partition. */
6492 pass_states (automaton
, process_state_for_insn_equiv_partition
);
6493 /* Enumerate equiv classes. */
6494 for (ainsn
= automaton
->ainsn_list
; ainsn
!= NULL
; ainsn
= ainsn
->next_ainsn
)
6495 /* Set undefined value. */
6496 ainsn
->insn_equiv_class_num
= -1;
6497 equiv_classes_num
= 0;
6498 for (ainsn
= automaton
->ainsn_list
; ainsn
!= NULL
; ainsn
= ainsn
->next_ainsn
)
6499 if (ainsn
->insn_equiv_class_num
< 0)
6502 gcc_assert (first_insn
->first_insn_with_same_reservs
);
6503 first_insn
->first_ainsn_with_given_equivalence_num
= 1;
6504 curr_insn
= first_insn
;
6507 for (insn_with_same_reservs
= curr_insn
;
6508 insn_with_same_reservs
!= NULL
;
6509 insn_with_same_reservs
6510 = insn_with_same_reservs
->next_same_reservs_insn
)
6511 insn_with_same_reservs
->insn_equiv_class_num
= equiv_classes_num
;
6512 curr_insn
= curr_insn
->next_equiv_class_insn
;
6514 while (curr_insn
!= first_insn
);
6515 equiv_classes_num
++;
6517 automaton
->insn_equiv_classes_num
= equiv_classes_num
;
6522 /* This page contains code for creating DFA(s) and calls functions
6526 /* The following value is used to prevent floating point overflow for
6527 estimating an automaton bound. The value should be less DBL_MAX on
6528 the host machine. We use here approximate minimum of maximal
6529 double floating point value required by ANSI C standard. It
6530 will work for non ANSI sun compiler too. */
6532 #define MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND 1.0E37
6534 /* The function estimate size of the single DFA used by PHR (pipeline
6535 hazards recognizer). */
6537 estimate_one_automaton_bound (void)
6540 double one_automaton_estimation_bound
;
6544 one_automaton_estimation_bound
= 1.0;
6545 for (i
= 0; i
< description
->decls_num
; i
++)
6547 decl
= description
->decls
[i
];
6548 if (decl
->mode
== dm_unit
)
6550 root_value
= exp (log (DECL_UNIT (decl
)->max_occ_cycle_num
6551 - DECL_UNIT (decl
)->min_occ_cycle_num
+ 1.0)
6553 if (MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND
/ root_value
6554 > one_automaton_estimation_bound
)
6555 one_automaton_estimation_bound
*= root_value
;
6558 return one_automaton_estimation_bound
;
6561 /* The function compares unit declarations according to their maximal
6562 cycle in reservations. */
6564 compare_max_occ_cycle_nums (const void *unit_decl_1
,
6565 const void *unit_decl_2
)
6567 if ((DECL_UNIT (*(const_decl_t
const*) unit_decl_1
)->max_occ_cycle_num
)
6568 < (DECL_UNIT (*(const_decl_t
const*) unit_decl_2
)->max_occ_cycle_num
))
6570 else if ((DECL_UNIT (*(const_decl_t
const*) unit_decl_1
)->max_occ_cycle_num
)
6571 == (DECL_UNIT (*(const_decl_t
const*) unit_decl_2
)->max_occ_cycle_num
))
6577 /* The function makes heuristic assigning automata to units. Actually
6578 efficacy of the algorithm has been checked yet??? */
6581 units_to_automata_heuristic_distr (void)
6583 double estimation_bound
;
6587 unit_decl_t
*unit_decls
;
6590 if (description
->units_num
== 0)
6592 estimation_bound
= estimate_one_automaton_bound ();
6593 unit_decls
= XNEWVEC (unit_decl_t
, description
->units_num
);
6595 for (i
= 0, j
= 0; i
< description
->decls_num
; i
++)
6596 if (description
->decls
[i
]->mode
== dm_unit
)
6597 unit_decls
[j
++] = DECL_UNIT (description
->decls
[i
]);
6598 gcc_assert (j
== description
->units_num
);
6600 qsort (unit_decls
, description
->units_num
,
6601 sizeof (unit_decl_t
), compare_max_occ_cycle_nums
);
6604 bound_value
= unit_decls
[0]->max_occ_cycle_num
;
6605 unit_decls
[0]->corresponding_automaton_num
= automaton_num
;
6607 for (i
= 1; i
< description
->units_num
; i
++)
6609 rest_units_num
= description
->units_num
- i
+ 1;
6610 gcc_assert (automata_num
- automaton_num
- 1 <= rest_units_num
);
6611 if (automaton_num
< automata_num
- 1
6612 && ((automata_num
- automaton_num
- 1 == rest_units_num
)
6615 / unit_decls
[i
]->max_occ_cycle_num
))))
6617 bound_value
= unit_decls
[i
]->max_occ_cycle_num
;
6621 bound_value
*= unit_decls
[i
]->max_occ_cycle_num
;
6622 unit_decls
[i
]->corresponding_automaton_num
= automaton_num
;
6624 gcc_assert (automaton_num
== automata_num
- 1);
6628 /* The functions creates automaton insns for each automata. Automaton
6629 insn is simply insn for given automaton which makes reservation
6630 only of units of the automaton. */
6632 create_ainsns (automaton_t automaton
)
6635 ainsn_t first_ainsn
;
6642 for (i
= 0; i
< description
->decls_num
; i
++)
6644 decl
= description
->decls
[i
];
6645 if (decl
->mode
== dm_insn_reserv
)
6647 curr_ainsn
= XCREATENODE (struct ainsn
);
6648 curr_ainsn
->insn_reserv_decl
= DECL_INSN_RESERV (decl
);
6649 curr_ainsn
->important_p
= FALSE
;
6650 curr_ainsn
->next_ainsn
= NULL
;
6651 if (prev_ainsn
== NULL
)
6652 first_ainsn
= curr_ainsn
;
6654 prev_ainsn
->next_ainsn
= curr_ainsn
;
6655 if (decl
== advance_cycle_insn_decl
)
6656 automaton
->advance_ainsn
= curr_ainsn
;
6657 else if (decl
== collapse_ndfa_insn_decl
)
6658 automaton
->collapse_ainsn
= curr_ainsn
;
6659 prev_ainsn
= curr_ainsn
;
6662 automaton
->ainsn_list
= first_ainsn
;
6665 /* The function assigns automata to units according to constructions
6666 `define_automaton' in the description. */
6668 units_to_automata_distr (void)
6673 for (i
= 0; i
< description
->decls_num
; i
++)
6675 decl
= description
->decls
[i
];
6676 if (decl
->mode
== dm_unit
)
6678 if (DECL_UNIT (decl
)->automaton_decl
== NULL
6679 || (DECL_UNIT (decl
)->automaton_decl
->corresponding_automaton
6681 /* Distribute to the first automaton. */
6682 DECL_UNIT (decl
)->corresponding_automaton_num
= 0;
6684 DECL_UNIT (decl
)->corresponding_automaton_num
6685 = (DECL_UNIT (decl
)->automaton_decl
6686 ->corresponding_automaton
->automaton_order_num
);
6691 /* The function creates DFA(s) for fast pipeline hazards recognition
6692 after checking and simplifying IR of the description. */
6694 create_automata (void)
6696 automaton_t curr_automaton
;
6697 automaton_t prev_automaton
;
6699 int curr_automaton_num
;
6702 if (automata_num
!= 0)
6704 units_to_automata_heuristic_distr ();
6705 for (prev_automaton
= NULL
, curr_automaton_num
= 0;
6706 curr_automaton_num
< automata_num
;
6707 curr_automaton_num
++, prev_automaton
= curr_automaton
)
6709 curr_automaton
= XCREATENODE (struct automaton
);
6710 create_ainsns (curr_automaton
);
6711 curr_automaton
->corresponding_automaton_decl
= NULL
;
6712 curr_automaton
->next_automaton
= NULL
;
6713 curr_automaton
->automaton_order_num
= curr_automaton_num
;
6714 if (prev_automaton
== NULL
)
6715 description
->first_automaton
= curr_automaton
;
6717 prev_automaton
->next_automaton
= curr_automaton
;
6722 curr_automaton_num
= 0;
6723 prev_automaton
= NULL
;
6724 for (i
= 0; i
< description
->decls_num
; i
++)
6726 decl
= description
->decls
[i
];
6727 if (decl
->mode
== dm_automaton
6728 && DECL_AUTOMATON (decl
)->automaton_is_used
)
6730 curr_automaton
= XCREATENODE (struct automaton
);
6731 create_ainsns (curr_automaton
);
6732 curr_automaton
->corresponding_automaton_decl
6733 = DECL_AUTOMATON (decl
);
6734 curr_automaton
->next_automaton
= NULL
;
6735 DECL_AUTOMATON (decl
)->corresponding_automaton
= curr_automaton
;
6736 curr_automaton
->automaton_order_num
= curr_automaton_num
;
6737 if (prev_automaton
== NULL
)
6738 description
->first_automaton
= curr_automaton
;
6740 prev_automaton
->next_automaton
= curr_automaton
;
6741 curr_automaton_num
++;
6742 prev_automaton
= curr_automaton
;
6745 if (curr_automaton_num
== 0)
6747 curr_automaton
= XCREATENODE (struct automaton
);
6748 create_ainsns (curr_automaton
);
6749 curr_automaton
->corresponding_automaton_decl
= NULL
;
6750 curr_automaton
->next_automaton
= NULL
;
6751 description
->first_automaton
= curr_automaton
;
6753 units_to_automata_distr ();
6755 NDFA_time
= create_ticker ();
6756 ticker_off (&NDFA_time
);
6757 NDFA_to_DFA_time
= create_ticker ();
6758 ticker_off (&NDFA_to_DFA_time
);
6759 minimize_time
= create_ticker ();
6760 ticker_off (&minimize_time
);
6761 equiv_time
= create_ticker ();
6762 ticker_off (&equiv_time
);
6763 for (curr_automaton
= description
->first_automaton
;
6764 curr_automaton
!= NULL
;
6765 curr_automaton
= curr_automaton
->next_automaton
)
6769 if (curr_automaton
->corresponding_automaton_decl
== NULL
)
6770 fprintf (stderr
, "Prepare anonymous automaton creation ... ");
6772 fprintf (stderr
, "Prepare automaton `%s' creation...",
6773 curr_automaton
->corresponding_automaton_decl
->name
);
6775 create_alt_states (curr_automaton
);
6776 form_ainsn_with_same_reservs (curr_automaton
);
6778 fprintf (stderr
, "done\n");
6779 build_automaton (curr_automaton
);
6780 enumerate_states (curr_automaton
);
6781 ticker_on (&equiv_time
);
6782 set_insn_equiv_classes (curr_automaton
);
6783 ticker_off (&equiv_time
);
6789 /* This page contains code for forming string representation of
6790 regexp. The representation is formed on IR obstack. So you should
6791 not work with IR obstack between regexp_representation and
6792 finish_regexp_representation calls. */
6794 /* This recursive function forms string representation of regexp
6795 (without tailing '\0'). */
6797 form_regexp (regexp_t regexp
)
6801 switch (regexp
->mode
)
6803 case rm_unit
: case rm_reserv
:
6805 const char *name
= (regexp
->mode
== rm_unit
6806 ? REGEXP_UNIT (regexp
)->name
6807 : REGEXP_RESERV (regexp
)->name
);
6809 obstack_grow (&irp
, name
, strlen (name
));
6814 for (i
= 0; i
< REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
6817 obstack_1grow (&irp
, ',');
6818 form_regexp (REGEXP_SEQUENCE (regexp
)->regexps
[i
]);
6823 obstack_1grow (&irp
, '(');
6824 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
6827 obstack_1grow (&irp
, '+');
6828 if (REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
== rm_sequence
6829 || REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
== rm_oneof
)
6830 obstack_1grow (&irp
, '(');
6831 form_regexp (REGEXP_ALLOF (regexp
)->regexps
[i
]);
6832 if (REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
== rm_sequence
6833 || REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
== rm_oneof
)
6834 obstack_1grow (&irp
, ')');
6836 obstack_1grow (&irp
, ')');
6840 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
6843 obstack_1grow (&irp
, '|');
6844 if (REGEXP_ONEOF (regexp
)->regexps
[i
]->mode
== rm_sequence
)
6845 obstack_1grow (&irp
, '(');
6846 form_regexp (REGEXP_ONEOF (regexp
)->regexps
[i
]);
6847 if (REGEXP_ONEOF (regexp
)->regexps
[i
]->mode
== rm_sequence
)
6848 obstack_1grow (&irp
, ')');
6856 if (REGEXP_REPEAT (regexp
)->regexp
->mode
== rm_sequence
6857 || REGEXP_REPEAT (regexp
)->regexp
->mode
== rm_allof
6858 || REGEXP_REPEAT (regexp
)->regexp
->mode
== rm_oneof
)
6859 obstack_1grow (&irp
, '(');
6860 form_regexp (REGEXP_REPEAT (regexp
)->regexp
);
6861 if (REGEXP_REPEAT (regexp
)->regexp
->mode
== rm_sequence
6862 || REGEXP_REPEAT (regexp
)->regexp
->mode
== rm_allof
6863 || REGEXP_REPEAT (regexp
)->regexp
->mode
== rm_oneof
)
6864 obstack_1grow (&irp
, ')');
6865 sprintf (digits
, "*%d", REGEXP_REPEAT (regexp
)->repeat_num
);
6866 obstack_grow (&irp
, digits
, strlen (digits
));
6871 obstack_grow (&irp
, NOTHING_NAME
, strlen (NOTHING_NAME
));
6879 /* The function returns string representation of REGEXP on IR
6882 regexp_representation (regexp_t regexp
)
6884 form_regexp (regexp
);
6885 obstack_1grow (&irp
, '\0');
6886 return obstack_base (&irp
);
6889 /* The function frees memory allocated for last formed string
6890 representation of regexp. */
6892 finish_regexp_representation (void)
6894 int length
= obstack_object_size (&irp
);
6896 obstack_blank_fast (&irp
, -length
);
6901 /* This page contains code for output PHR (pipeline hazards recognizer). */
6903 /* The function outputs minimal C type which is sufficient for
6904 representation numbers in range min_range_value and
6905 max_range_value. Because host machine and build machine may be
6906 different, we use here minimal values required by ANSI C standard
6907 instead of UCHAR_MAX, SHRT_MAX, SHRT_MIN, etc. This is a good
6911 output_range_type (FILE *f
, long int min_range_value
,
6912 long int max_range_value
)
6914 if (min_range_value
>= 0 && max_range_value
<= 255)
6915 fprintf (f
, "unsigned char");
6916 else if (min_range_value
>= -127 && max_range_value
<= 127)
6917 fprintf (f
, "signed char");
6918 else if (min_range_value
>= 0 && max_range_value
<= 65535)
6919 fprintf (f
, "unsigned short");
6920 else if (min_range_value
>= -32767 && max_range_value
<= 32767)
6921 fprintf (f
, "short");
6926 /* The function outputs all initialization values of VECT. */
6928 output_vect (vla_hwint_t vect
)
6931 size_t vect_length
= vect
.length ();
6935 if (vect_length
== 0)
6936 fputs ("0 /* This is dummy el because the vect is empty */", output_file
);
6938 for (i
= 0; i
< vect_length
; i
++)
6940 fprintf (output_file
, "%5ld", (long) vect
[i
]);
6941 if (els_on_line
== 10)
6944 fputs (",\n", output_file
);
6946 else if (i
< vect_length
-1)
6947 fputs (", ", output_file
);
6952 /* The following is name of the structure which represents DFA(s) for
6954 #define CHIP_NAME "DFA_chip"
6956 /* The following is name of member which represents state of a DFA for
6959 output_chip_member_name (FILE *f
, automaton_t automaton
)
6961 if (automaton
->corresponding_automaton_decl
== NULL
)
6962 fprintf (f
, "automaton_state_%d", automaton
->automaton_order_num
);
6964 fprintf (f
, "%s_automaton_state",
6965 automaton
->corresponding_automaton_decl
->name
);
6968 /* The following is name of temporary variable which stores state of a
6971 output_temp_chip_member_name (FILE *f
, automaton_t automaton
)
6974 output_chip_member_name (f
, automaton
);
6977 /* This is name of macro value which is code of pseudo_insns
6978 representing advancing cpu cycle and collapsing the NDFA.
6979 Its value is used as internal code unknown insn. */
6980 #define ADVANCE_CYCLE_VALUE_NAME "DFA__ADVANCE_CYCLE"
6981 #define COLLAPSE_NDFA_VALUE_NAME "NDFA__COLLAPSE"
6983 /* Output name of translate vector for given automaton. */
6985 output_translate_vect_name (FILE *f
, automaton_t automaton
)
6987 if (automaton
->corresponding_automaton_decl
== NULL
)
6988 fprintf (f
, "translate_%d", automaton
->automaton_order_num
);
6990 fprintf (f
, "%s_translate", automaton
->corresponding_automaton_decl
->name
);
6993 /* Output name for simple transition table representation. */
6995 output_trans_full_vect_name (FILE *f
, automaton_t automaton
)
6997 if (automaton
->corresponding_automaton_decl
== NULL
)
6998 fprintf (f
, "transitions_%d", automaton
->automaton_order_num
);
7000 fprintf (f
, "%s_transitions",
7001 automaton
->corresponding_automaton_decl
->name
);
7004 /* Output name of comb vector of the transition table for given
7007 output_trans_comb_vect_name (FILE *f
, automaton_t automaton
)
7009 if (automaton
->corresponding_automaton_decl
== NULL
)
7010 fprintf (f
, "transitions_%d", automaton
->automaton_order_num
);
7012 fprintf (f
, "%s_transitions",
7013 automaton
->corresponding_automaton_decl
->name
);
7016 /* Output name of check vector of the transition table for given
7019 output_trans_check_vect_name (FILE *f
, automaton_t automaton
)
7021 if (automaton
->corresponding_automaton_decl
== NULL
)
7022 fprintf (f
, "check_%d", automaton
->automaton_order_num
);
7024 fprintf (f
, "%s_check", automaton
->corresponding_automaton_decl
->name
);
7027 /* Output name of base vector of the transition table for given
7030 output_trans_base_vect_name (FILE *f
, automaton_t automaton
)
7032 if (automaton
->corresponding_automaton_decl
== NULL
)
7033 fprintf (f
, "base_%d", automaton
->automaton_order_num
);
7035 fprintf (f
, "%s_base", automaton
->corresponding_automaton_decl
->name
);
7038 /* Output name of simple min issue delay table representation. */
7040 output_min_issue_delay_vect_name (FILE *f
, automaton_t automaton
)
7042 if (automaton
->corresponding_automaton_decl
== NULL
)
7043 fprintf (f
, "min_issue_delay_%d", automaton
->automaton_order_num
);
7045 fprintf (f
, "%s_min_issue_delay",
7046 automaton
->corresponding_automaton_decl
->name
);
7049 /* Output name of deadlock vector for given automaton. */
7051 output_dead_lock_vect_name (FILE *f
, automaton_t automaton
)
7053 if (automaton
->corresponding_automaton_decl
== NULL
)
7054 fprintf (f
, "dead_lock_%d", automaton
->automaton_order_num
);
7056 fprintf (f
, "%s_dead_lock", automaton
->corresponding_automaton_decl
->name
);
7059 /* Output name of reserved units table for AUTOMATON into file F. */
7061 output_reserved_units_table_name (FILE *f
, automaton_t automaton
)
7063 if (automaton
->corresponding_automaton_decl
== NULL
)
7064 fprintf (f
, "reserved_units_%d", automaton
->automaton_order_num
);
7066 fprintf (f
, "%s_reserved_units",
7067 automaton
->corresponding_automaton_decl
->name
);
7070 /* Name of the PHR interface macro. */
7071 #define CPU_UNITS_QUERY_MACRO_NAME "CPU_UNITS_QUERY"
7073 /* Names of an internal functions: */
7074 #define INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME "internal_min_issue_delay"
7076 /* This is external type of DFA(s) state. */
7077 #define STATE_TYPE_NAME "state_t"
7079 #define INTERNAL_TRANSITION_FUNC_NAME "internal_state_transition"
7081 #define INTERNAL_RESET_FUNC_NAME "internal_reset"
7083 #define INTERNAL_DEAD_LOCK_FUNC_NAME "internal_state_dead_lock_p"
7085 #define INTERNAL_INSN_LATENCY_FUNC_NAME "internal_insn_latency"
7087 /* Name of cache of insn dfa codes. */
7088 #define DFA_INSN_CODES_VARIABLE_NAME "dfa_insn_codes"
7090 /* Name of length of cache of insn dfa codes. */
7091 #define DFA_INSN_CODES_LENGTH_VARIABLE_NAME "dfa_insn_codes_length"
7093 /* Names of the PHR interface functions: */
7094 #define SIZE_FUNC_NAME "state_size"
7096 #define TRANSITION_FUNC_NAME "state_transition"
7098 #define MIN_ISSUE_DELAY_FUNC_NAME "min_issue_delay"
7100 #define MIN_INSN_CONFLICT_DELAY_FUNC_NAME "min_insn_conflict_delay"
7102 #define DEAD_LOCK_FUNC_NAME "state_dead_lock_p"
7104 #define RESET_FUNC_NAME "state_reset"
7106 #define INSN_LATENCY_FUNC_NAME "insn_latency"
7108 #define PRINT_RESERVATION_FUNC_NAME "print_reservation"
7110 #define GET_CPU_UNIT_CODE_FUNC_NAME "get_cpu_unit_code"
7112 #define CPU_UNIT_RESERVATION_P_FUNC_NAME "cpu_unit_reservation_p"
7114 #define INSN_HAS_DFA_RESERVATION_P_FUNC_NAME "insn_has_dfa_reservation_p"
7116 #define DFA_CLEAN_INSN_CACHE_FUNC_NAME "dfa_clean_insn_cache"
7118 #define DFA_CLEAR_SINGLE_INSN_CACHE_FUNC_NAME "dfa_clear_single_insn_cache"
7120 #define DFA_START_FUNC_NAME "dfa_start"
7122 #define DFA_FINISH_FUNC_NAME "dfa_finish"
7124 /* Names of parameters of the PHR interface functions. */
7125 #define STATE_NAME "state"
7127 #define INSN_PARAMETER_NAME "insn"
7129 #define INSN2_PARAMETER_NAME "insn2"
7131 #define CHIP_PARAMETER_NAME "chip"
7133 #define FILE_PARAMETER_NAME "f"
7135 #define CPU_UNIT_NAME_PARAMETER_NAME "cpu_unit_name"
7137 #define CPU_CODE_PARAMETER_NAME "cpu_unit_code"
7139 /* Names of the variables whose values are internal insn code of rtx
7141 #define INTERNAL_INSN_CODE_NAME "insn_code"
7143 #define INTERNAL_INSN2_CODE_NAME "insn2_code"
7145 /* Names of temporary variables in some functions. */
7146 #define TEMPORARY_VARIABLE_NAME "temp"
7148 #define I_VARIABLE_NAME "i"
7150 /* Name of result variable in some functions. */
7151 #define RESULT_VARIABLE_NAME "res"
7153 /* Name of function (attribute) to translate insn into internal insn
7155 #define INTERNAL_DFA_INSN_CODE_FUNC_NAME "internal_dfa_insn_code"
7157 /* Name of function (attribute) to translate insn into internal insn
7158 code with caching. */
7159 #define DFA_INSN_CODE_FUNC_NAME "dfa_insn_code"
7161 /* Output C type which is used for representation of codes of states
7164 output_state_member_type (FILE *f
, automaton_t automaton
)
7166 output_range_type (f
, 0, automaton
->achieved_states_num
);
7169 /* Output definition of the structure representing current DFA(s)
7172 output_chip_definitions (void)
7174 automaton_t automaton
;
7176 fprintf (output_file
, "struct %s\n{\n", CHIP_NAME
);
7177 for (automaton
= description
->first_automaton
;
7179 automaton
= automaton
->next_automaton
)
7181 fprintf (output_file
, " ");
7182 output_state_member_type (output_file
, automaton
);
7183 fprintf (output_file
, " ");
7184 output_chip_member_name (output_file
, automaton
);
7185 fprintf (output_file
, ";\n");
7187 fprintf (output_file
, "};\n\n");
7189 fprintf (output_file
, "static struct %s %s;\n\n", CHIP_NAME
, CHIP_NAME
);
7194 /* The function outputs translate vector of internal insn code into
7195 insn equivalence class number. The equivalence class number is
7196 used to access to table and vectors representing DFA(s). */
7198 output_translate_vect (automaton_t automaton
)
7202 vla_hwint_t translate_vect
;
7204 translate_vect
.create (description
->insns_num
);
7206 for (insn_value
= 0; insn_value
< description
->insns_num
; insn_value
++)
7207 /* Undefined value */
7208 translate_vect
.quick_push (automaton
->insn_equiv_classes_num
);
7210 for (ainsn
= automaton
->ainsn_list
; ainsn
!= NULL
; ainsn
= ainsn
->next_ainsn
)
7211 translate_vect
[ainsn
->insn_reserv_decl
->insn_num
] =
7212 ainsn
->insn_equiv_class_num
;
7214 fprintf (output_file
,
7215 "/* Vector translating external insn codes to internal ones.*/\n");
7216 fprintf (output_file
, "static const ");
7217 output_range_type (output_file
, 0, automaton
->insn_equiv_classes_num
);
7218 fprintf (output_file
, " ");
7219 output_translate_vect_name (output_file
, automaton
);
7220 fprintf (output_file
, "[] ATTRIBUTE_UNUSED = {\n");
7221 output_vect (translate_vect
);
7222 fprintf (output_file
, "};\n\n");
7223 translate_vect
.release ();
7226 /* The value in a table state x ainsn -> something which represents
7228 static int undefined_vect_el_value
;
7230 /* The following function returns nonzero value if the best
7231 representation of the table is comb vector. */
7233 comb_vect_p (state_ainsn_table_t tab
)
7237 return (2 * tab
->full_vect
.length () > 5 * tab
->comb_vect
.length ());
7240 /* The following function creates new table for AUTOMATON. */
7241 static state_ainsn_table_t
7242 create_state_ainsn_table (automaton_t automaton
)
7244 state_ainsn_table_t tab
;
7245 int full_vect_length
;
7248 tab
= XCREATENODE (struct state_ainsn_table
);
7249 tab
->automaton
= automaton
;
7251 tab
->comb_vect
.create (10000);
7252 tab
->check_vect
.create (10000);
7254 tab
->base_vect
.create (0);
7255 tab
->base_vect
.safe_grow (automaton
->achieved_states_num
);
7257 full_vect_length
= (automaton
->insn_equiv_classes_num
7258 * automaton
->achieved_states_num
);
7259 tab
->full_vect
.create (full_vect_length
);
7260 for (i
= 0; i
< full_vect_length
; i
++)
7261 tab
->full_vect
.quick_push (undefined_vect_el_value
);
7263 tab
->min_base_vect_el_value
= 0;
7264 tab
->max_base_vect_el_value
= 0;
7265 tab
->min_comb_vect_el_value
= 0;
7266 tab
->max_comb_vect_el_value
= 0;
7270 /* The following function outputs the best C representation of the
7271 table TAB of given TABLE_NAME. */
7273 output_state_ainsn_table (state_ainsn_table_t tab
, const char *table_name
,
7274 void (*output_full_vect_name_func
) (FILE *, automaton_t
),
7275 void (*output_comb_vect_name_func
) (FILE *, automaton_t
),
7276 void (*output_check_vect_name_func
) (FILE *, automaton_t
),
7277 void (*output_base_vect_name_func
) (FILE *, automaton_t
))
7279 if (!comb_vect_p (tab
))
7281 fprintf (output_file
, "/* Vector for %s. */\n", table_name
);
7282 fprintf (output_file
, "static const ");
7283 output_range_type (output_file
, tab
->min_comb_vect_el_value
,
7284 tab
->max_comb_vect_el_value
);
7285 fprintf (output_file
, " ");
7286 (*output_full_vect_name_func
) (output_file
, tab
->automaton
);
7287 fprintf (output_file
, "[] ATTRIBUTE_UNUSED = {\n");
7288 output_vect (tab
->full_vect
);
7289 fprintf (output_file
, "};\n\n");
7293 fprintf (output_file
, "/* Comb vector for %s. */\n", table_name
);
7294 fprintf (output_file
, "static const ");
7295 output_range_type (output_file
, tab
->min_comb_vect_el_value
,
7296 tab
->max_comb_vect_el_value
);
7297 fprintf (output_file
, " ");
7298 (*output_comb_vect_name_func
) (output_file
, tab
->automaton
);
7299 fprintf (output_file
, "[] ATTRIBUTE_UNUSED = {\n");
7300 output_vect (tab
->comb_vect
);
7301 fprintf (output_file
, "};\n\n");
7302 fprintf (output_file
, "/* Check vector for %s. */\n", table_name
);
7303 fprintf (output_file
, "static const ");
7304 output_range_type (output_file
, 0, tab
->automaton
->achieved_states_num
);
7305 fprintf (output_file
, " ");
7306 (*output_check_vect_name_func
) (output_file
, tab
->automaton
);
7307 fprintf (output_file
, "[] = {\n");
7308 output_vect (tab
->check_vect
);
7309 fprintf (output_file
, "};\n\n");
7310 fprintf (output_file
, "/* Base vector for %s. */\n", table_name
);
7311 fprintf (output_file
, "static const ");
7312 output_range_type (output_file
, tab
->min_base_vect_el_value
,
7313 tab
->max_base_vect_el_value
);
7314 fprintf (output_file
, " ");
7315 (*output_base_vect_name_func
) (output_file
, tab
->automaton
);
7316 fprintf (output_file
, "[] = {\n");
7317 output_vect (tab
->base_vect
);
7318 fprintf (output_file
, "};\n\n");
7322 /* The following function adds vector VECT to table TAB as its line
7323 with number VECT_NUM. */
7325 add_vect (state_ainsn_table_t tab
, int vect_num
, vla_hwint_t vect
)
7328 size_t real_vect_length
;
7329 int comb_vect_index
;
7330 int comb_vect_els_num
;
7332 int first_unempty_vect_index
;
7333 int additional_els_num
;
7337 unsigned long vect_mask
, comb_vect_mask
;
7339 vect_length
= vect
.length ();
7340 gcc_assert (vect_length
);
7341 gcc_assert (vect
.last () != undefined_vect_el_value
);
7342 real_vect_length
= tab
->automaton
->insn_equiv_classes_num
;
7343 /* Form full vector in the table: */
7345 size_t full_base
= tab
->automaton
->insn_equiv_classes_num
* vect_num
;
7346 if (tab
->full_vect
.length () < full_base
+ vect_length
)
7347 tab
->full_vect
.safe_grow (full_base
+ vect_length
);
7348 for (i
= 0; i
< vect_length
; i
++)
7349 tab
->full_vect
[full_base
+ i
] = vect
[i
];
7352 /* The comb_vect min/max values are also used for the full vector, so
7353 compute them now. */
7354 for (vect_index
= 0; vect_index
< vect_length
; vect_index
++)
7355 if (vect
[vect_index
] != undefined_vect_el_value
)
7357 vect_el_t x
= vect
[vect_index
];
7358 gcc_assert (x
>= 0);
7359 if (tab
->max_comb_vect_el_value
< x
)
7360 tab
->max_comb_vect_el_value
= x
;
7361 if (tab
->min_comb_vect_el_value
> x
)
7362 tab
->min_comb_vect_el_value
= x
;
7367 /* Form comb vector in the table: */
7368 gcc_assert (tab
->comb_vect
.length () == tab
->check_vect
.length ());
7370 comb_vect_els_num
= tab
->comb_vect
.length ();
7371 for (first_unempty_vect_index
= 0;
7372 first_unempty_vect_index
< vect_length
;
7373 first_unempty_vect_index
++)
7374 if (vect
[first_unempty_vect_index
]
7375 != undefined_vect_el_value
)
7378 /* Search for the place in comb vect for the inserted vect. */
7381 if (vect_length
- first_unempty_vect_index
>= SIZEOF_LONG
* CHAR_BIT
)
7383 for (comb_vect_index
= 0;
7384 comb_vect_index
< comb_vect_els_num
;
7387 for (vect_index
= first_unempty_vect_index
;
7388 vect_index
< vect_length
7389 && vect_index
+ comb_vect_index
< comb_vect_els_num
;
7391 if (vect
[vect_index
]
7392 != undefined_vect_el_value
7393 && (tab
->comb_vect
[vect_index
+ comb_vect_index
]
7394 != undefined_vect_el_value
))
7396 if (vect_index
>= vect_length
7397 || vect_index
+ comb_vect_index
>= comb_vect_els_num
)
7405 for (vect_index
= first_unempty_vect_index
;
7406 vect_index
< vect_length
;
7409 vect_mask
= vect_mask
<< 1;
7410 if (vect
[vect_index
] != undefined_vect_el_value
)
7414 /* Search for the place in comb vect for the inserted vect. */
7415 comb_vect_index
= 0;
7416 if (comb_vect_els_num
== 0)
7420 for (vect_index
= first_unempty_vect_index
;
7421 vect_index
< vect_length
&& vect_index
< comb_vect_els_num
;
7424 comb_vect_mask
<<= 1;
7425 if (vect_index
+ comb_vect_index
< comb_vect_els_num
7426 && tab
->comb_vect
[vect_index
+ comb_vect_index
]
7427 != undefined_vect_el_value
)
7428 comb_vect_mask
|= 1;
7430 if ((vect_mask
& comb_vect_mask
) == 0)
7433 for (comb_vect_index
= 1, i
= vect_length
; i
< comb_vect_els_num
;
7434 comb_vect_index
++, i
++)
7436 comb_vect_mask
= (comb_vect_mask
<< 1) | 1;
7437 comb_vect_mask
^= (tab
->comb_vect
[i
]
7438 == undefined_vect_el_value
);
7439 if ((vect_mask
& comb_vect_mask
) == 0)
7442 for ( ; comb_vect_index
< comb_vect_els_num
; comb_vect_index
++)
7444 comb_vect_mask
<<= 1;
7445 if ((vect_mask
& comb_vect_mask
) == 0)
7450 /* Slot was found. */
7451 additional_els_num
= comb_vect_index
+ real_vect_length
- comb_vect_els_num
;
7452 if (additional_els_num
< 0)
7453 additional_els_num
= 0;
7454 /* Expand comb and check vectors. */
7455 vect_el
= undefined_vect_el_value
;
7456 no_state_value
= tab
->automaton
->achieved_states_num
;
7457 while (additional_els_num
> 0)
7459 tab
->comb_vect
.safe_push (vect_el
);
7460 tab
->check_vect
.safe_push (no_state_value
);
7461 additional_els_num
--;
7463 gcc_assert (tab
->comb_vect
.length ()
7464 >= comb_vect_index
+ real_vect_length
);
7465 /* Fill comb and check vectors. */
7466 for (vect_index
= 0; vect_index
< vect_length
; vect_index
++)
7467 if (vect
[vect_index
] != undefined_vect_el_value
)
7469 vect_el_t x
= vect
[vect_index
];
7470 gcc_assert (tab
->comb_vect
[comb_vect_index
+ vect_index
]
7471 == undefined_vect_el_value
);
7472 gcc_assert (x
>= 0);
7473 tab
->comb_vect
[comb_vect_index
+ vect_index
] = x
;
7474 tab
->check_vect
[comb_vect_index
+ vect_index
] = vect_num
;
7476 if (tab
->max_comb_vect_el_value
< undefined_vect_el_value
)
7477 tab
->max_comb_vect_el_value
= undefined_vect_el_value
;
7478 if (tab
->min_comb_vect_el_value
> undefined_vect_el_value
)
7479 tab
->min_comb_vect_el_value
= undefined_vect_el_value
;
7480 if (tab
->max_base_vect_el_value
< comb_vect_index
)
7481 tab
->max_base_vect_el_value
= comb_vect_index
;
7482 if (tab
->min_base_vect_el_value
> comb_vect_index
)
7483 tab
->min_base_vect_el_value
= comb_vect_index
;
7485 tab
->base_vect
[vect_num
] = comb_vect_index
;
7488 /* Return number of out arcs of STATE. */
7490 out_state_arcs_num (const_state_t state
)
7496 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
7498 gcc_assert (arc
->insn
);
7499 if (arc
->insn
->first_ainsn_with_given_equivalence_num
)
7505 /* Compare number of possible transitions from the states. */
7507 compare_transition_els_num (const void *state_ptr_1
,
7508 const void *state_ptr_2
)
7510 const int transition_els_num_1
7511 = out_state_arcs_num (*(const_state_t
const*) state_ptr_1
);
7512 const int transition_els_num_2
7513 = out_state_arcs_num (*(const_state_t
const*) state_ptr_2
);
7515 if (transition_els_num_1
< transition_els_num_2
)
7517 else if (transition_els_num_1
== transition_els_num_2
)
7523 /* The function adds element EL_VALUE to vector VECT for a table state
7526 add_vect_el (vla_hwint_t
&vect
, ainsn_t ainsn
, int el_value
)
7528 int equiv_class_num
;
7532 equiv_class_num
= ainsn
->insn_equiv_class_num
;
7533 for (vect_index
= vect
.length ();
7534 vect_index
<= equiv_class_num
;
7536 vect
.safe_push (undefined_vect_el_value
);
7537 vect
[equiv_class_num
] = el_value
;
7540 /* This is for forming vector of states of an automaton. */
7541 static vec
<state_t
> output_states_vect
;
7543 /* The function is called by function pass_states. The function adds
7544 STATE to `output_states_vect'. */
7546 add_states_vect_el (state_t state
)
7548 output_states_vect
.safe_push (state
);
7551 /* Form and output vectors (comb, check, base or full vector)
7552 representing transition table of AUTOMATON. */
7554 output_trans_table (automaton_t automaton
)
7558 vla_hwint_t transition_vect
= vla_hwint_t();
7560 undefined_vect_el_value
= automaton
->achieved_states_num
;
7561 automaton
->trans_table
= create_state_ainsn_table (automaton
);
7562 /* Create vect of pointers to states ordered by num of transitions
7563 from the state (state with the maximum num is the first). */
7564 output_states_vect
.create (0);
7565 pass_states (automaton
, add_states_vect_el
);
7566 output_states_vect
.qsort (compare_transition_els_num
);
7568 for (i
= 0; i
< output_states_vect
.length (); i
++)
7570 transition_vect
.truncate (0);
7571 for (arc
= first_out_arc (output_states_vect
[i
]);
7573 arc
= next_out_arc (arc
))
7575 gcc_assert (arc
->insn
);
7576 if (arc
->insn
->first_ainsn_with_given_equivalence_num
)
7577 add_vect_el (transition_vect
, arc
->insn
,
7578 arc
->to_state
->order_state_num
);
7580 add_vect (automaton
->trans_table
,
7581 output_states_vect
[i
]->order_state_num
,
7584 output_state_ainsn_table
7585 (automaton
->trans_table
, "state transitions",
7586 output_trans_full_vect_name
, output_trans_comb_vect_name
,
7587 output_trans_check_vect_name
, output_trans_base_vect_name
);
7589 output_states_vect
.release ();
7590 transition_vect
.release ();
7593 /* Form and output vectors representing minimal issue delay table of
7594 AUTOMATON. The table is state x ainsn -> minimal issue delay of
7597 output_min_issue_delay_table (automaton_t automaton
)
7599 vla_hwint_t min_issue_delay_vect
;
7600 vla_hwint_t compressed_min_issue_delay_vect
;
7603 size_t min_issue_delay_len
, compressed_min_issue_delay_len
;
7607 /* Create vect of pointers to states ordered by num of transitions
7608 from the state (state with the maximum num is the first). */
7609 output_states_vect
.create (0);
7610 pass_states (automaton
, add_states_vect_el
);
7612 min_issue_delay_len
= (output_states_vect
.length ()
7613 * automaton
->insn_equiv_classes_num
);
7614 min_issue_delay_vect
.create (min_issue_delay_len
);
7615 for (i
= 0; i
< min_issue_delay_len
; i
++)
7616 min_issue_delay_vect
.quick_push (-1);
7618 automaton
->max_min_delay
= 0;
7626 for (state_no
= 0; state_no
< output_states_vect
.length ();
7629 state_t s
= output_states_vect
[state_no
];
7632 for (arc
= first_out_arc (s
); arc
; arc
= next_out_arc (arc
))
7636 size_t asn
= s
->order_state_num
7637 * automaton
->insn_equiv_classes_num
7638 + arc
->insn
->insn_equiv_class_num
;
7640 if (min_issue_delay_vect
[asn
])
7642 min_issue_delay_vect
[asn
] = (vect_el_t
) 0;
7646 for (k
= 0; k
< automaton
->insn_equiv_classes_num
; k
++)
7649 vect_el_t delay0
, delay1
;
7651 n0
= s
->order_state_num
7652 * automaton
->insn_equiv_classes_num
7654 n1
= arc
->to_state
->order_state_num
7655 * automaton
->insn_equiv_classes_num
7657 delay0
= min_issue_delay_vect
[n0
];
7658 delay1
= min_issue_delay_vect
[n1
];
7661 if (arc
->insn
->insn_reserv_decl
7662 == DECL_INSN_RESERV (advance_cycle_insn_decl
))
7664 if (delay1
< delay0
|| delay0
== -1)
7666 min_issue_delay_vect
[n0
] = delay1
;
7676 automaton
->max_min_delay
= 0;
7678 for (ainsn
= automaton
->ainsn_list
; ainsn
; ainsn
= ainsn
->next_ainsn
)
7679 if (ainsn
->first_ainsn_with_given_equivalence_num
)
7681 for (i
= 0; i
< output_states_vect
.length (); i
++)
7683 state_t s
= output_states_vect
[i
];
7684 size_t np
= s
->order_state_num
7685 * automaton
->insn_equiv_classes_num
7686 + ainsn
->insn_equiv_class_num
;
7687 vect_el_t x
= min_issue_delay_vect
[np
];
7689 if (automaton
->max_min_delay
< x
)
7690 automaton
->max_min_delay
= x
;
7692 min_issue_delay_vect
[np
] = (vect_el_t
) 0;
7696 fprintf (output_file
, "/* Vector of min issue delay of insns. */\n");
7697 fprintf (output_file
, "static const ");
7698 output_range_type (output_file
, 0, automaton
->max_min_delay
);
7699 fprintf (output_file
, " ");
7700 output_min_issue_delay_vect_name (output_file
, automaton
);
7701 fprintf (output_file
, "[] ATTRIBUTE_UNUSED = {\n");
7702 /* Compress the vector. */
7703 if (automaton
->max_min_delay
< 2)
7705 else if (automaton
->max_min_delay
< 4)
7707 else if (automaton
->max_min_delay
< 16)
7711 automaton
->min_issue_delay_table_compression_factor
= cfactor
;
7713 compressed_min_issue_delay_len
= (min_issue_delay_len
+cfactor
-1) / cfactor
;
7714 compressed_min_issue_delay_vect
.create (compressed_min_issue_delay_len
);
7716 for (i
= 0; i
< compressed_min_issue_delay_len
; i
++)
7717 compressed_min_issue_delay_vect
.quick_push (0);
7719 for (i
= 0; i
< min_issue_delay_len
; i
++)
7721 size_t ci
= i
/ cfactor
;
7722 vect_el_t x
= min_issue_delay_vect
[i
];
7723 vect_el_t cx
= compressed_min_issue_delay_vect
[ci
];
7725 cx
|= x
<< (8 - (i
% cfactor
+ 1) * (8 / cfactor
));
7726 compressed_min_issue_delay_vect
[ci
] = cx
;
7728 output_vect (compressed_min_issue_delay_vect
);
7729 fprintf (output_file
, "};\n\n");
7730 output_states_vect
.release ();
7731 min_issue_delay_vect
.release ();
7732 compressed_min_issue_delay_vect
.release ();
7735 /* Form and output vector representing the locked states of
7738 output_dead_lock_vect (automaton_t automaton
)
7742 vla_hwint_t dead_lock_vect
= vla_hwint_t();
7744 /* Create vect of pointers to states ordered by num of
7745 transitions from the state (state with the maximum num is the
7747 automaton
->locked_states
= 0;
7748 output_states_vect
.create (0);
7749 pass_states (automaton
, add_states_vect_el
);
7751 dead_lock_vect
.safe_grow (output_states_vect
.length ());
7752 for (i
= 0; i
< output_states_vect
.length (); i
++)
7754 state_t s
= output_states_vect
[i
];
7755 arc
= first_out_arc (s
);
7757 if (next_out_arc (arc
) == NULL
7758 && (arc
->insn
->insn_reserv_decl
7759 == DECL_INSN_RESERV (advance_cycle_insn_decl
)))
7761 dead_lock_vect
[s
->order_state_num
] = 1;
7762 automaton
->locked_states
++;
7765 dead_lock_vect
[s
->order_state_num
] = (vect_el_t
) 0;
7767 if (automaton
->locked_states
== 0)
7770 fprintf (output_file
, "/* Vector for locked state flags. */\n");
7771 fprintf (output_file
, "static const ");
7772 output_range_type (output_file
, 0, 1);
7773 fprintf (output_file
, " ");
7774 output_dead_lock_vect_name (output_file
, automaton
);
7775 fprintf (output_file
, "[] = {\n");
7776 output_vect (dead_lock_vect
);
7777 fprintf (output_file
, "};\n\n");
7778 output_states_vect
.release ();
7779 dead_lock_vect
.release ();
7782 /* Form and output vector representing reserved units of the states of
7785 output_reserved_units_table (automaton_t automaton
)
7787 vla_hwint_t reserved_units_table
= vla_hwint_t();
7788 int state_byte_size
;
7789 int reserved_units_size
;
7793 if (description
->query_units_num
== 0)
7796 /* Create vect of pointers to states. */
7797 output_states_vect
.create (0);
7798 pass_states (automaton
, add_states_vect_el
);
7799 /* Create vector. */
7800 state_byte_size
= (description
->query_units_num
+ 7) / 8;
7801 reserved_units_size
= (output_states_vect
.length ()
7804 reserved_units_table
.create (reserved_units_size
);
7806 for (i
= 0; i
< reserved_units_size
; i
++)
7807 reserved_units_table
.quick_push (0);
7808 for (n
= 0; n
< output_states_vect
.length (); n
++)
7810 state_t s
= output_states_vect
[n
];
7811 for (i
= 0; i
< description
->units_num
; i
++)
7812 if (units_array
[i
]->query_p
7813 && first_cycle_unit_presence (s
, i
))
7815 int ri
= (s
->order_state_num
* state_byte_size
7816 + units_array
[i
]->query_num
/ 8);
7817 vect_el_t x
= reserved_units_table
[ri
];
7819 x
+= 1 << (units_array
[i
]->query_num
% 8);
7820 reserved_units_table
[ri
] = x
;
7823 fprintf (output_file
, "\n#if %s\n", CPU_UNITS_QUERY_MACRO_NAME
);
7824 fprintf (output_file
, "/* Vector for reserved units of states. */\n");
7825 fprintf (output_file
, "static const ");
7826 output_range_type (output_file
, 0, 255);
7827 fprintf (output_file
, " ");
7828 output_reserved_units_table_name (output_file
, automaton
);
7829 fprintf (output_file
, "[] = {\n");
7830 output_vect (reserved_units_table
);
7831 fprintf (output_file
, "};\n#endif /* #if %s */\n\n",
7832 CPU_UNITS_QUERY_MACRO_NAME
);
7834 output_states_vect
.release ();
7835 reserved_units_table
.release ();
7838 /* The function outputs all tables representing DFA(s) used for fast
7839 pipeline hazards recognition. */
7841 output_tables (void)
7843 automaton_t automaton
;
7845 for (automaton
= description
->first_automaton
;
7847 automaton
= automaton
->next_automaton
)
7849 output_translate_vect (automaton
);
7850 output_trans_table (automaton
);
7851 output_min_issue_delay_table (automaton
);
7852 output_dead_lock_vect (automaton
);
7853 output_reserved_units_table (automaton
);
7855 fprintf (output_file
, "\n#define %s %d\n\n", ADVANCE_CYCLE_VALUE_NAME
,
7856 DECL_INSN_RESERV (advance_cycle_insn_decl
)->insn_num
);
7858 fprintf (output_file
, "\n#define %s %d\n\n", COLLAPSE_NDFA_VALUE_NAME
,
7859 DECL_INSN_RESERV (collapse_ndfa_insn_decl
)->insn_num
);
7862 /* The function outputs definition and value of PHR interface variable
7863 `max_insn_queue_index'. Its value is not less than maximal queue
7864 length needed for the insn scheduler. */
7866 output_max_insn_queue_index_def (void)
7868 int i
, max
, latency
;
7871 max
= description
->max_insn_reserv_cycles
;
7872 for (i
= 0; i
< description
->decls_num
; i
++)
7874 decl
= description
->decls
[i
];
7875 if (decl
->mode
== dm_insn_reserv
&& decl
!= advance_cycle_insn_decl
)
7877 latency
= DECL_INSN_RESERV (decl
)->default_latency
;
7881 else if (decl
->mode
== dm_bypass
)
7883 latency
= DECL_BYPASS (decl
)->latency
;
7888 for (i
= 0; (1 << i
) <= max
; i
++)
7890 gcc_assert (i
>= 0);
7891 fprintf (output_file
, "\nconst int max_insn_queue_index = %d;\n\n",
7895 /* The function outputs switch cases for insn reservations using
7896 function *output_automata_list_code. */
7898 output_insn_code_cases (void (*output_automata_list_code
)
7899 (automata_list_el_t
))
7904 for (i
= 0; i
< description
->decls_num
; i
++)
7906 decl
= description
->decls
[i
];
7907 if (decl
->mode
== dm_insn_reserv
)
7908 DECL_INSN_RESERV (decl
)->processed_p
= FALSE
;
7910 for (i
= 0; i
< description
->decls_num
; i
++)
7912 decl
= description
->decls
[i
];
7913 if (decl
->mode
== dm_insn_reserv
7914 && !DECL_INSN_RESERV (decl
)->processed_p
)
7916 for (j
= i
; j
< description
->decls_num
; j
++)
7918 decl2
= description
->decls
[j
];
7919 if (decl2
->mode
== dm_insn_reserv
7920 && (DECL_INSN_RESERV (decl2
)->important_automata_list
7921 == DECL_INSN_RESERV (decl
)->important_automata_list
))
7923 DECL_INSN_RESERV (decl2
)->processed_p
= TRUE
;
7924 fprintf (output_file
, " case %d: /* %s */\n",
7925 DECL_INSN_RESERV (decl2
)->insn_num
,
7926 DECL_INSN_RESERV (decl2
)->name
);
7929 (*output_automata_list_code
)
7930 (DECL_INSN_RESERV (decl
)->important_automata_list
);
7936 /* The function outputs a code for evaluation of a minimal delay of
7937 issue of insns which have reservations in given AUTOMATA_LIST. */
7939 output_automata_list_min_issue_delay_code (automata_list_el_t automata_list
)
7941 automata_list_el_t el
;
7942 automaton_t automaton
;
7944 for (el
= automata_list
; el
!= NULL
; el
= el
->next_automata_list_el
)
7946 automaton
= el
->automaton
;
7947 fprintf (output_file
, "\n %s = ", TEMPORARY_VARIABLE_NAME
);
7948 output_min_issue_delay_vect_name (output_file
, automaton
);
7949 fprintf (output_file
,
7950 (automaton
->min_issue_delay_table_compression_factor
!= 1
7952 output_translate_vect_name (output_file
, automaton
);
7953 fprintf (output_file
, " [%s] + ", INTERNAL_INSN_CODE_NAME
);
7954 fprintf (output_file
, "%s->", CHIP_PARAMETER_NAME
);
7955 output_chip_member_name (output_file
, automaton
);
7956 fprintf (output_file
, " * %d", automaton
->insn_equiv_classes_num
);
7957 if (automaton
->min_issue_delay_table_compression_factor
== 1)
7958 fprintf (output_file
, "];\n");
7961 fprintf (output_file
, ") / %d];\n",
7962 automaton
->min_issue_delay_table_compression_factor
);
7963 fprintf (output_file
, " %s = (%s >> (8 - ((",
7964 TEMPORARY_VARIABLE_NAME
, TEMPORARY_VARIABLE_NAME
);
7965 output_translate_vect_name (output_file
, automaton
);
7966 fprintf (output_file
, " [%s] + ", INTERNAL_INSN_CODE_NAME
);
7967 fprintf (output_file
, "%s->", CHIP_PARAMETER_NAME
);
7968 output_chip_member_name (output_file
, automaton
);
7969 fprintf (output_file
, " * %d)", automaton
->insn_equiv_classes_num
);
7971 (output_file
, " %% %d + 1) * %d)) & %d;\n",
7972 automaton
->min_issue_delay_table_compression_factor
,
7973 8 / automaton
->min_issue_delay_table_compression_factor
,
7974 (1 << (8 / automaton
->min_issue_delay_table_compression_factor
))
7977 if (el
== automata_list
)
7978 fprintf (output_file
, " %s = %s;\n",
7979 RESULT_VARIABLE_NAME
, TEMPORARY_VARIABLE_NAME
);
7982 fprintf (output_file
, " if (%s > %s)\n",
7983 TEMPORARY_VARIABLE_NAME
, RESULT_VARIABLE_NAME
);
7984 fprintf (output_file
, " %s = %s;\n",
7985 RESULT_VARIABLE_NAME
, TEMPORARY_VARIABLE_NAME
);
7988 fprintf (output_file
, " break;\n\n");
7991 /* Output function `internal_min_issue_delay'. */
7993 output_internal_min_issue_delay_func (void)
7995 fprintf (output_file
,
7996 "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
7997 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
7998 CHIP_NAME
, CHIP_PARAMETER_NAME
);
7999 fprintf (output_file
, "{\n int %s ATTRIBUTE_UNUSED;\n int %s = -1;\n",
8000 TEMPORARY_VARIABLE_NAME
, RESULT_VARIABLE_NAME
);
8001 fprintf (output_file
, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME
);
8002 output_insn_code_cases (output_automata_list_min_issue_delay_code
);
8003 fprintf (output_file
,
8004 "\n default:\n %s = -1;\n break;\n }\n",
8005 RESULT_VARIABLE_NAME
);
8006 fprintf (output_file
, " return %s;\n", RESULT_VARIABLE_NAME
);
8007 fprintf (output_file
, "}\n\n");
8010 /* The function outputs a code changing state after issue of insns
8011 which have reservations in given AUTOMATA_LIST. */
8013 output_automata_list_transition_code (automata_list_el_t automata_list
)
8015 automata_list_el_t el
, next_el
;
8017 fprintf (output_file
, " {\n");
8018 if (automata_list
!= NULL
&& automata_list
->next_automata_list_el
!= NULL
)
8019 for (el
= automata_list
;; el
= next_el
)
8021 next_el
= el
->next_automata_list_el
;
8022 if (next_el
== NULL
)
8024 fprintf (output_file
, " ");
8025 output_state_member_type (output_file
, el
->automaton
);
8026 fprintf (output_file
, " ");
8027 output_temp_chip_member_name (output_file
, el
->automaton
);
8028 fprintf (output_file
, ";\n");
8030 for (el
= automata_list
; el
!= NULL
; el
= el
->next_automata_list_el
)
8031 if (comb_vect_p (el
->automaton
->trans_table
))
8033 fprintf (output_file
, "\n %s = ", TEMPORARY_VARIABLE_NAME
);
8034 output_trans_base_vect_name (output_file
, el
->automaton
);
8035 fprintf (output_file
, " [%s->", CHIP_PARAMETER_NAME
);
8036 output_chip_member_name (output_file
, el
->automaton
);
8037 fprintf (output_file
, "] + ");
8038 output_translate_vect_name (output_file
, el
->automaton
);
8039 fprintf (output_file
, " [%s];\n", INTERNAL_INSN_CODE_NAME
);
8040 fprintf (output_file
, " if (");
8041 output_trans_check_vect_name (output_file
, el
->automaton
);
8042 fprintf (output_file
, " [%s] != %s->",
8043 TEMPORARY_VARIABLE_NAME
, CHIP_PARAMETER_NAME
);
8044 output_chip_member_name (output_file
, el
->automaton
);
8045 fprintf (output_file
, ")\n");
8046 fprintf (output_file
, " return %s (%s, %s);\n",
8047 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
8048 CHIP_PARAMETER_NAME
);
8049 fprintf (output_file
, " else\n");
8050 fprintf (output_file
, " ");
8051 if (el
->next_automata_list_el
!= NULL
)
8052 output_temp_chip_member_name (output_file
, el
->automaton
);
8055 fprintf (output_file
, "%s->", CHIP_PARAMETER_NAME
);
8056 output_chip_member_name (output_file
, el
->automaton
);
8058 fprintf (output_file
, " = ");
8059 output_trans_comb_vect_name (output_file
, el
->automaton
);
8060 fprintf (output_file
, " [%s];\n", TEMPORARY_VARIABLE_NAME
);
8064 fprintf (output_file
, "\n %s = ", TEMPORARY_VARIABLE_NAME
);
8065 output_trans_full_vect_name (output_file
, el
->automaton
);
8066 fprintf (output_file
, " [");
8067 output_translate_vect_name (output_file
, el
->automaton
);
8068 fprintf (output_file
, " [%s] + ", INTERNAL_INSN_CODE_NAME
);
8069 fprintf (output_file
, "%s->", CHIP_PARAMETER_NAME
);
8070 output_chip_member_name (output_file
, el
->automaton
);
8071 fprintf (output_file
, " * %d];\n",
8072 el
->automaton
->insn_equiv_classes_num
);
8073 fprintf (output_file
, " if (%s >= %d)\n",
8074 TEMPORARY_VARIABLE_NAME
, el
->automaton
->achieved_states_num
);
8075 fprintf (output_file
, " return %s (%s, %s);\n",
8076 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
8077 CHIP_PARAMETER_NAME
);
8078 fprintf (output_file
, " else\n ");
8079 if (el
->next_automata_list_el
!= NULL
)
8080 output_temp_chip_member_name (output_file
, el
->automaton
);
8083 fprintf (output_file
, "%s->", CHIP_PARAMETER_NAME
);
8084 output_chip_member_name (output_file
, el
->automaton
);
8086 fprintf (output_file
, " = %s;\n", TEMPORARY_VARIABLE_NAME
);
8088 if (automata_list
!= NULL
&& automata_list
->next_automata_list_el
!= NULL
)
8089 for (el
= automata_list
;; el
= next_el
)
8091 next_el
= el
->next_automata_list_el
;
8092 if (next_el
== NULL
)
8094 fprintf (output_file
, " %s->", CHIP_PARAMETER_NAME
);
8095 output_chip_member_name (output_file
, el
->automaton
);
8096 fprintf (output_file
, " = ");
8097 output_temp_chip_member_name (output_file
, el
->automaton
);
8098 fprintf (output_file
, ";\n");
8100 fprintf (output_file
, " return -1;\n");
8101 fprintf (output_file
, " }\n");
8104 /* Output function `internal_state_transition'. */
8106 output_internal_trans_func (void)
8108 fprintf (output_file
,
8109 "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
8110 INTERNAL_TRANSITION_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
8111 CHIP_NAME
, CHIP_PARAMETER_NAME
);
8112 fprintf (output_file
, "{\n int %s ATTRIBUTE_UNUSED;\n", TEMPORARY_VARIABLE_NAME
);
8113 fprintf (output_file
, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME
);
8114 output_insn_code_cases (output_automata_list_transition_code
);
8115 fprintf (output_file
, "\n default:\n return -1;\n }\n");
8116 fprintf (output_file
, "}\n\n");
8123 insn_code = dfa_insn_code (insn);
8124 if (insn_code > DFA__ADVANCE_CYCLE)
8128 insn_code = DFA__ADVANCE_CYCLE;
8130 where insn denotes INSN_NAME, insn_code denotes INSN_CODE_NAME, and
8131 code denotes CODE. */
8133 output_internal_insn_code_evaluation (const char *insn_name
,
8134 const char *insn_code_name
,
8137 fprintf (output_file
, "\n if (%s == 0)\n", insn_name
);
8138 fprintf (output_file
, " %s = %s;\n\n",
8139 insn_code_name
, ADVANCE_CYCLE_VALUE_NAME
);
8142 fprintf (output_file
, "\n else if (%s == const0_rtx)\n", insn_name
);
8143 fprintf (output_file
, " %s = %s;\n\n",
8144 insn_code_name
, COLLAPSE_NDFA_VALUE_NAME
);
8146 fprintf (output_file
, "\n else\n {\n");
8147 fprintf (output_file
, " %s = %s (%s);\n", insn_code_name
,
8148 DFA_INSN_CODE_FUNC_NAME
, insn_name
);
8149 fprintf (output_file
, " if (%s > %s)\n return %d;\n }\n",
8150 insn_code_name
, ADVANCE_CYCLE_VALUE_NAME
, code
);
8154 /* This function outputs `dfa_insn_code' and its helper function
8155 `dfa_insn_code_enlarge'. */
8157 output_dfa_insn_code_func (void)
8159 /* Emacs c-mode gets really confused if there's a { or } in column 0
8160 inside a string, so don't do that. */
8161 fprintf (output_file
, "\
8163 dfa_insn_code_enlarge (int uid)\n\
8167 %s = XRESIZEVEC (int, %s,\n\
8169 for (; i < %s; i++)\n\
8170 %s[i] = -1;\n}\n\n",
8171 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
,
8172 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
,
8173 DFA_INSN_CODES_VARIABLE_NAME
, DFA_INSN_CODES_VARIABLE_NAME
,
8174 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
,
8175 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
,
8176 DFA_INSN_CODES_VARIABLE_NAME
);
8177 fprintf (output_file
, "\
8178 static inline int\n%s (rtx %s)\n\
8180 int uid = INSN_UID (%s);\n\
8182 DFA_INSN_CODE_FUNC_NAME
, INSN_PARAMETER_NAME
,
8183 INSN_PARAMETER_NAME
, INTERNAL_INSN_CODE_NAME
);
8185 fprintf (output_file
,
8186 " if (uid >= %s)\n dfa_insn_code_enlarge (uid);\n\n",
8187 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
);
8188 fprintf (output_file
, " %s = %s[uid];\n",
8189 INTERNAL_INSN_CODE_NAME
, DFA_INSN_CODES_VARIABLE_NAME
);
8190 fprintf (output_file
, "\
8196 INTERNAL_INSN_CODE_NAME
,
8197 INTERNAL_INSN_CODE_NAME
,
8198 INTERNAL_DFA_INSN_CODE_FUNC_NAME
, INSN_PARAMETER_NAME
,
8199 DFA_INSN_CODES_VARIABLE_NAME
, INTERNAL_INSN_CODE_NAME
);
8200 fprintf (output_file
, " return %s;\n}\n\n", INTERNAL_INSN_CODE_NAME
);
8203 /* The function outputs PHR interface function `state_transition'. */
8205 output_trans_func (void)
8207 fprintf (output_file
, "int\n%s (%s %s, rtx %s)\n",
8208 TRANSITION_FUNC_NAME
, STATE_TYPE_NAME
, STATE_NAME
,
8209 INSN_PARAMETER_NAME
);
8210 fprintf (output_file
, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME
);
8211 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME
,
8212 INTERNAL_INSN_CODE_NAME
, -1);
8213 fprintf (output_file
, " return %s (%s, (struct %s *) %s);\n}\n\n",
8214 INTERNAL_TRANSITION_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
, CHIP_NAME
, STATE_NAME
);
8217 /* Output function `min_issue_delay'. */
8219 output_min_issue_delay_func (void)
8221 fprintf (output_file
, "int\n%s (%s %s, rtx %s)\n",
8222 MIN_ISSUE_DELAY_FUNC_NAME
, STATE_TYPE_NAME
, STATE_NAME
,
8223 INSN_PARAMETER_NAME
);
8224 fprintf (output_file
, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME
);
8225 fprintf (output_file
, "\n if (%s != 0)\n {\n", INSN_PARAMETER_NAME
);
8226 fprintf (output_file
, " %s = %s (%s);\n", INTERNAL_INSN_CODE_NAME
,
8227 DFA_INSN_CODE_FUNC_NAME
, INSN_PARAMETER_NAME
);
8228 fprintf (output_file
, " if (%s > %s)\n return 0;\n",
8229 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
8230 fprintf (output_file
, " }\n else\n %s = %s;\n",
8231 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
8232 fprintf (output_file
, "\n return %s (%s, (struct %s *) %s);\n",
8233 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
8234 CHIP_NAME
, STATE_NAME
);
8235 fprintf (output_file
, "}\n\n");
8238 /* Output function `internal_dead_lock'. */
8240 output_internal_dead_lock_func (void)
8242 automaton_t automaton
;
8244 fprintf (output_file
, "static int\n%s (struct %s *ARG_UNUSED (%s))\n",
8245 INTERNAL_DEAD_LOCK_FUNC_NAME
, CHIP_NAME
, CHIP_PARAMETER_NAME
);
8246 fprintf (output_file
, "{\n");
8247 for (automaton
= description
->first_automaton
;
8249 automaton
= automaton
->next_automaton
)
8250 if (automaton
->locked_states
)
8252 fprintf (output_file
, " if (");
8253 output_dead_lock_vect_name (output_file
, automaton
);
8254 fprintf (output_file
, " [%s->", CHIP_PARAMETER_NAME
);
8255 output_chip_member_name (output_file
, automaton
);
8256 fprintf (output_file
, "])\n return 1/* TRUE */;\n");
8258 fprintf (output_file
, " return 0/* FALSE */;\n}\n\n");
8261 /* The function outputs PHR interface function `state_dead_lock_p'. */
8263 output_dead_lock_func (void)
8265 fprintf (output_file
, "int\n%s (%s %s)\n",
8266 DEAD_LOCK_FUNC_NAME
, STATE_TYPE_NAME
, STATE_NAME
);
8267 fprintf (output_file
, "{\n return %s ((struct %s *) %s);\n}\n\n",
8268 INTERNAL_DEAD_LOCK_FUNC_NAME
, CHIP_NAME
, STATE_NAME
);
8271 /* Output function `internal_reset'. */
8273 output_internal_reset_func (void)
8275 fprintf (output_file
, "static inline void\n%s (struct %s *%s)\n",
8276 INTERNAL_RESET_FUNC_NAME
, CHIP_NAME
, CHIP_PARAMETER_NAME
);
8277 fprintf (output_file
, "{\n memset (%s, 0, sizeof (struct %s));\n}\n\n",
8278 CHIP_PARAMETER_NAME
, CHIP_NAME
);
8281 /* The function outputs PHR interface function `state_size'. */
8283 output_size_func (void)
8285 fprintf (output_file
, "int\n%s (void)\n", SIZE_FUNC_NAME
);
8286 fprintf (output_file
, "{\n return sizeof (struct %s);\n}\n\n", CHIP_NAME
);
8289 /* The function outputs PHR interface function `state_reset'. */
8291 output_reset_func (void)
8293 fprintf (output_file
, "void\n%s (%s %s)\n",
8294 RESET_FUNC_NAME
, STATE_TYPE_NAME
, STATE_NAME
);
8295 fprintf (output_file
, "{\n %s ((struct %s *) %s);\n}\n\n", INTERNAL_RESET_FUNC_NAME
,
8296 CHIP_NAME
, STATE_NAME
);
8299 /* Output function `min_insn_conflict_delay'. */
8301 output_min_insn_conflict_delay_func (void)
8303 fprintf (output_file
,
8304 "int\n%s (%s %s, rtx %s, rtx %s)\n",
8305 MIN_INSN_CONFLICT_DELAY_FUNC_NAME
, STATE_TYPE_NAME
,
8306 STATE_NAME
, INSN_PARAMETER_NAME
, INSN2_PARAMETER_NAME
);
8307 fprintf (output_file
, "{\n struct %s %s;\n int %s, %s, transition;\n",
8308 CHIP_NAME
, CHIP_NAME
, INTERNAL_INSN_CODE_NAME
,
8309 INTERNAL_INSN2_CODE_NAME
);
8310 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME
,
8311 INTERNAL_INSN_CODE_NAME
, 0);
8312 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME
,
8313 INTERNAL_INSN2_CODE_NAME
, 0);
8314 fprintf (output_file
, " memcpy (&%s, %s, sizeof (%s));\n",
8315 CHIP_NAME
, STATE_NAME
, CHIP_NAME
);
8316 fprintf (output_file
, " %s (&%s);\n", INTERNAL_RESET_FUNC_NAME
, CHIP_NAME
);
8317 fprintf (output_file
, " transition = %s (%s, &%s);\n",
8318 INTERNAL_TRANSITION_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
, CHIP_NAME
);
8319 fprintf (output_file
, " gcc_assert (transition <= 0);\n");
8320 fprintf (output_file
, " return %s (%s, &%s);\n",
8321 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME
, INTERNAL_INSN2_CODE_NAME
,
8323 fprintf (output_file
, "}\n\n");
8326 /* Output the array holding default latency values. These are used in
8327 insn_latency and maximal_insn_latency function implementations. */
8329 output_default_latencies (void)
8333 const char *tabletype
= "unsigned char";
8335 /* Find the smallest integer type that can hold all the default
8337 for (i
= 0; i
< description
->decls_num
; i
++)
8338 if (description
->decls
[i
]->mode
== dm_insn_reserv
)
8340 decl
= description
->decls
[i
];
8341 if (DECL_INSN_RESERV (decl
)->default_latency
> UCHAR_MAX
8342 && tabletype
[0] != 'i') /* Don't shrink it. */
8343 tabletype
= "unsigned short";
8344 if (DECL_INSN_RESERV (decl
)->default_latency
> USHRT_MAX
)
8348 fprintf (output_file
, " static const %s default_latencies[] =\n {",
8351 for (i
= 0, j
= 0, col
= 7; i
< description
->normal_decls_num
; i
++)
8352 if (description
->decls
[i
]->mode
== dm_insn_reserv
)
8354 if ((col
= (col
+1) % 8) == 0)
8355 fputs ("\n ", output_file
);
8356 decl
= description
->decls
[i
];
8357 gcc_assert (j
++ == DECL_INSN_RESERV (decl
)->insn_num
);
8358 fprintf (output_file
, "% 4d,",
8359 DECL_INSN_RESERV (decl
)->default_latency
);
8361 gcc_assert (j
== description
->insns_num
- (collapse_flag
? 2 : 1));
8362 fputs ("\n };\n", output_file
);
8365 /* Output function `internal_insn_latency'. */
8367 output_internal_insn_latency_func (void)
8371 struct bypass_decl
*bypass
;
8373 fprintf (output_file
, "static int\n%s (int %s ATTRIBUTE_UNUSED,\n\tint %s ATTRIBUTE_UNUSED,\n\trtx %s ATTRIBUTE_UNUSED,\n\trtx %s ATTRIBUTE_UNUSED)\n",
8374 INTERNAL_INSN_LATENCY_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
8375 INTERNAL_INSN2_CODE_NAME
, INSN_PARAMETER_NAME
,
8376 INSN2_PARAMETER_NAME
);
8377 fprintf (output_file
, "{\n");
8379 if (DECL_INSN_RESERV (advance_cycle_insn_decl
)->insn_num
== 0)
8381 fputs (" return 0;\n}\n\n", output_file
);
8385 fprintf (output_file
, " if (%s >= %s || %s >= %s)\n return 0;\n",
8386 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
,
8387 INTERNAL_INSN2_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
8389 fprintf (output_file
, " switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME
);
8390 for (i
= 0; i
< description
->decls_num
; i
++)
8391 if (description
->decls
[i
]->mode
== dm_insn_reserv
8392 && DECL_INSN_RESERV (description
->decls
[i
])->bypass_list
)
8394 decl
= description
->decls
[i
];
8395 fprintf (output_file
,
8396 " case %d:\n switch (%s)\n {\n",
8397 DECL_INSN_RESERV (decl
)->insn_num
,
8398 INTERNAL_INSN2_CODE_NAME
);
8399 for (bypass
= DECL_INSN_RESERV (decl
)->bypass_list
;
8401 bypass
= bypass
->next
)
8403 gcc_assert (bypass
->in_insn_reserv
->insn_num
8404 != (DECL_INSN_RESERV
8405 (advance_cycle_insn_decl
)->insn_num
));
8406 fprintf (output_file
, " case %d:\n",
8407 bypass
->in_insn_reserv
->insn_num
);
8410 if (bypass
->bypass_guard_name
== NULL
)
8412 gcc_assert (bypass
->next
== NULL
8413 || (bypass
->in_insn_reserv
8414 != bypass
->next
->in_insn_reserv
));
8415 fprintf (output_file
, " return %d;\n",
8420 fprintf (output_file
,
8421 " if (%s (%s, %s))\n",
8422 bypass
->bypass_guard_name
, INSN_PARAMETER_NAME
,
8423 INSN2_PARAMETER_NAME
);
8424 fprintf (output_file
, " return %d;\n",
8427 if (bypass
->next
== NULL
8428 || bypass
->in_insn_reserv
!= bypass
->next
->in_insn_reserv
)
8430 bypass
= bypass
->next
;
8432 if (bypass
->bypass_guard_name
!= NULL
)
8433 fprintf (output_file
, " break;\n");
8435 fputs (" }\n break;\n", output_file
);
8438 fprintf (output_file
, " }\n return default_latencies[%s];\n}\n\n",
8439 INTERNAL_INSN_CODE_NAME
);
8442 /* Output function `internal_maximum_insn_latency'. */
8444 output_internal_maximal_insn_latency_func (void)
8447 struct bypass_decl
*bypass
;
8451 fprintf (output_file
, "static int\n%s (int %s ATTRIBUTE_UNUSED,\n\trtx %s ATTRIBUTE_UNUSED)\n",
8452 "internal_maximal_insn_latency", INTERNAL_INSN_CODE_NAME
,
8453 INSN_PARAMETER_NAME
);
8454 fprintf (output_file
, "{\n");
8456 if (DECL_INSN_RESERV (advance_cycle_insn_decl
)->insn_num
== 0)
8458 fputs (" return 0;\n}\n\n", output_file
);
8462 fprintf (output_file
, " switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME
);
8463 for (i
= 0; i
< description
->decls_num
; i
++)
8464 if (description
->decls
[i
]->mode
== dm_insn_reserv
8465 && DECL_INSN_RESERV (description
->decls
[i
])->bypass_list
)
8467 decl
= description
->decls
[i
];
8468 max
= DECL_INSN_RESERV (decl
)->default_latency
;
8469 fprintf (output_file
,
8471 DECL_INSN_RESERV (decl
)->insn_num
);
8472 for (bypass
= DECL_INSN_RESERV (decl
)->bypass_list
;
8474 bypass
= bypass
->next
)
8476 if (bypass
->latency
> max
)
8477 max
= bypass
->latency
;
8479 fprintf (output_file
, " return %d; }\n break;\n", max
);
8482 fprintf (output_file
, " }\n return default_latencies[%s];\n}\n\n",
8483 INTERNAL_INSN_CODE_NAME
);
8486 /* The function outputs PHR interface function `insn_latency'. */
8488 output_insn_latency_func (void)
8490 fprintf (output_file
, "int\n%s (rtx %s, rtx %s)\n",
8491 INSN_LATENCY_FUNC_NAME
, INSN_PARAMETER_NAME
, INSN2_PARAMETER_NAME
);
8492 fprintf (output_file
, "{\n int %s, %s;\n",
8493 INTERNAL_INSN_CODE_NAME
, INTERNAL_INSN2_CODE_NAME
);
8494 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME
,
8495 INTERNAL_INSN_CODE_NAME
, 0);
8496 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME
,
8497 INTERNAL_INSN2_CODE_NAME
, 0);
8498 fprintf (output_file
, " return %s (%s, %s, %s, %s);\n}\n\n",
8499 INTERNAL_INSN_LATENCY_FUNC_NAME
,
8500 INTERNAL_INSN_CODE_NAME
, INTERNAL_INSN2_CODE_NAME
,
8501 INSN_PARAMETER_NAME
, INSN2_PARAMETER_NAME
);
8504 /* The function outputs PHR interface function `maximal_insn_latency'. */
8506 output_maximal_insn_latency_func (void)
8508 fprintf (output_file
, "int\n%s (rtx %s)\n",
8509 "maximal_insn_latency", INSN_PARAMETER_NAME
);
8510 fprintf (output_file
, "{\n int %s;\n",
8511 INTERNAL_INSN_CODE_NAME
);
8512 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME
,
8513 INTERNAL_INSN_CODE_NAME
, 0);
8514 fprintf (output_file
, " return %s (%s, %s);\n}\n\n",
8515 "internal_maximal_insn_latency",
8516 INTERNAL_INSN_CODE_NAME
, INSN_PARAMETER_NAME
);
8519 /* The function outputs PHR interface function `print_reservation'. */
8521 output_print_reservation_func (void)
8526 fprintf (output_file
,
8527 "void\n%s (FILE *%s, rtx %s ATTRIBUTE_UNUSED)\n{\n",
8528 PRINT_RESERVATION_FUNC_NAME
, FILE_PARAMETER_NAME
,
8529 INSN_PARAMETER_NAME
);
8531 if (DECL_INSN_RESERV (advance_cycle_insn_decl
)->insn_num
== 0)
8533 fprintf (output_file
, " fputs (\"%s\", %s);\n}\n\n",
8534 NOTHING_NAME
, FILE_PARAMETER_NAME
);
8539 fputs (" static const char *const reservation_names[] =\n {",
8542 for (i
= 0, j
= 0; i
< description
->normal_decls_num
; i
++)
8544 decl
= description
->decls
[i
];
8545 if (decl
->mode
== dm_insn_reserv
)
8547 gcc_assert (j
== DECL_INSN_RESERV (decl
)->insn_num
);
8550 fprintf (output_file
, "\n \"%s\",",
8551 regexp_representation (DECL_INSN_RESERV (decl
)->regexp
));
8552 finish_regexp_representation ();
8555 gcc_assert (j
== description
->insns_num
- (collapse_flag
? 2 : 1));
8557 fprintf (output_file
, "\n \"%s\"\n };\n int %s;\n\n",
8558 NOTHING_NAME
, INTERNAL_INSN_CODE_NAME
);
8560 fprintf (output_file
, " if (%s == 0)\n %s = %s;\n",
8561 INSN_PARAMETER_NAME
,
8562 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
8563 fprintf (output_file
, " else\n\
8569 INTERNAL_INSN_CODE_NAME
, DFA_INSN_CODE_FUNC_NAME
,
8570 INSN_PARAMETER_NAME
,
8571 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
,
8572 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
8574 fprintf (output_file
, " fputs (reservation_names[%s], %s);\n}\n\n",
8575 INTERNAL_INSN_CODE_NAME
, FILE_PARAMETER_NAME
);
8578 /* The following function is used to sort unit declaration by their
8581 units_cmp (const void *unit1
, const void *unit2
)
8583 const_unit_decl_t
const u1
= *(const_unit_decl_t
const*) unit1
;
8584 const_unit_decl_t
const u2
= *(const_unit_decl_t
const*) unit2
;
8586 return strcmp (u1
->name
, u2
->name
);
8589 /* The following macro value is name of struct containing unit name
8591 #define NAME_CODE_STRUCT_NAME "name_code"
8593 /* The following macro value is name of table of struct name_code. */
8594 #define NAME_CODE_TABLE_NAME "name_code_table"
8596 /* The following macro values are member names for struct name_code. */
8597 #define NAME_MEMBER_NAME "name"
8598 #define CODE_MEMBER_NAME "code"
8600 /* The following macro values are local variable names for function
8601 `get_cpu_unit_code'. */
8602 #define CMP_VARIABLE_NAME "cmp"
8603 #define LOW_VARIABLE_NAME "l"
8604 #define MIDDLE_VARIABLE_NAME "m"
8605 #define HIGH_VARIABLE_NAME "h"
8607 /* The following function outputs function to obtain internal cpu unit
8608 code by the cpu unit name. */
8610 output_get_cpu_unit_code_func (void)
8615 fprintf (output_file
, "int\n%s (const char *%s)\n",
8616 GET_CPU_UNIT_CODE_FUNC_NAME
, CPU_UNIT_NAME_PARAMETER_NAME
);
8617 fprintf (output_file
, "{\n struct %s {const char *%s; int %s;};\n",
8618 NAME_CODE_STRUCT_NAME
, NAME_MEMBER_NAME
, CODE_MEMBER_NAME
);
8619 fprintf (output_file
, " int %s, %s, %s, %s;\n", CMP_VARIABLE_NAME
,
8620 LOW_VARIABLE_NAME
, MIDDLE_VARIABLE_NAME
, HIGH_VARIABLE_NAME
);
8621 fprintf (output_file
, " static struct %s %s [] =\n {\n",
8622 NAME_CODE_STRUCT_NAME
, NAME_CODE_TABLE_NAME
);
8623 units
= XNEWVEC (unit_decl_t
, description
->units_num
);
8624 memcpy (units
, units_array
, sizeof (unit_decl_t
) * description
->units_num
);
8625 qsort (units
, description
->units_num
, sizeof (unit_decl_t
), units_cmp
);
8626 for (i
= 0; i
< description
->units_num
; i
++)
8627 if (units
[i
]->query_p
)
8628 fprintf (output_file
, " {\"%s\", %d},\n",
8629 units
[i
]->name
, units
[i
]->query_num
);
8630 fprintf (output_file
, " };\n\n");
8631 fprintf (output_file
, " /* The following is binary search: */\n");
8632 fprintf (output_file
, " %s = 0;\n", LOW_VARIABLE_NAME
);
8633 fprintf (output_file
, " %s = sizeof (%s) / sizeof (struct %s) - 1;\n",
8634 HIGH_VARIABLE_NAME
, NAME_CODE_TABLE_NAME
, NAME_CODE_STRUCT_NAME
);
8635 fprintf (output_file
, " while (%s <= %s)\n {\n",
8636 LOW_VARIABLE_NAME
, HIGH_VARIABLE_NAME
);
8637 fprintf (output_file
, " %s = (%s + %s) / 2;\n",
8638 MIDDLE_VARIABLE_NAME
, LOW_VARIABLE_NAME
, HIGH_VARIABLE_NAME
);
8639 fprintf (output_file
, " %s = strcmp (%s, %s [%s].%s);\n",
8640 CMP_VARIABLE_NAME
, CPU_UNIT_NAME_PARAMETER_NAME
,
8641 NAME_CODE_TABLE_NAME
, MIDDLE_VARIABLE_NAME
, NAME_MEMBER_NAME
);
8642 fprintf (output_file
, " if (%s < 0)\n", CMP_VARIABLE_NAME
);
8643 fprintf (output_file
, " %s = %s - 1;\n",
8644 HIGH_VARIABLE_NAME
, MIDDLE_VARIABLE_NAME
);
8645 fprintf (output_file
, " else if (%s > 0)\n", CMP_VARIABLE_NAME
);
8646 fprintf (output_file
, " %s = %s + 1;\n",
8647 LOW_VARIABLE_NAME
, MIDDLE_VARIABLE_NAME
);
8648 fprintf (output_file
, " else\n");
8649 fprintf (output_file
, " return %s [%s].%s;\n }\n",
8650 NAME_CODE_TABLE_NAME
, MIDDLE_VARIABLE_NAME
, CODE_MEMBER_NAME
);
8651 fprintf (output_file
, " return -1;\n}\n\n");
8655 /* The following function outputs function to check reservation of cpu
8656 unit (its internal code will be passed as the function argument) in
8659 output_cpu_unit_reservation_p (void)
8661 automaton_t automaton
;
8663 fprintf (output_file
, "int\n%s (%s %s, int %s)\n",
8664 CPU_UNIT_RESERVATION_P_FUNC_NAME
,
8665 STATE_TYPE_NAME
, STATE_NAME
,
8666 CPU_CODE_PARAMETER_NAME
);
8667 fprintf (output_file
, "{\n gcc_assert (%s >= 0 && %s < %d);\n",
8668 CPU_CODE_PARAMETER_NAME
, CPU_CODE_PARAMETER_NAME
,
8669 description
->query_units_num
);
8670 if (description
->query_units_num
> 0)
8671 for (automaton
= description
->first_automaton
;
8673 automaton
= automaton
->next_automaton
)
8675 fprintf (output_file
, " if ((");
8676 output_reserved_units_table_name (output_file
, automaton
);
8677 fprintf (output_file
, " [((struct %s *) %s)->", CHIP_NAME
, STATE_NAME
);
8678 output_chip_member_name (output_file
, automaton
);
8679 fprintf (output_file
, " * %d + %s / 8] >> (%s %% 8)) & 1)\n",
8680 (description
->query_units_num
+ 7) / 8,
8681 CPU_CODE_PARAMETER_NAME
, CPU_CODE_PARAMETER_NAME
);
8682 fprintf (output_file
, " return 1;\n");
8684 fprintf (output_file
, " return 0;\n}\n\n");
8687 /* The following function outputs a function to check if insn
8688 has a dfa reservation. */
8690 output_insn_has_dfa_reservation_p (void)
8692 fprintf (output_file
,
8693 "bool\n%s (rtx %s ATTRIBUTE_UNUSED)\n{\n",
8694 INSN_HAS_DFA_RESERVATION_P_FUNC_NAME
,
8695 INSN_PARAMETER_NAME
);
8697 if (DECL_INSN_RESERV (advance_cycle_insn_decl
)->insn_num
== 0)
8699 fprintf (output_file
, " return false;\n}\n\n");
8703 fprintf (output_file
, " int %s;\n\n", INTERNAL_INSN_CODE_NAME
);
8705 fprintf (output_file
, " if (%s == 0)\n %s = %s;\n",
8706 INSN_PARAMETER_NAME
,
8707 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
8708 fprintf (output_file
, " else\n\
8714 INTERNAL_INSN_CODE_NAME
, DFA_INSN_CODE_FUNC_NAME
,
8715 INSN_PARAMETER_NAME
,
8716 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
,
8717 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
8719 fprintf (output_file
, " return %s != %s;\n}\n\n",
8720 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
8723 /* The function outputs PHR interface functions `dfa_clean_insn_cache'
8724 and 'dfa_clear_single_insn_cache'. */
8726 output_dfa_clean_insn_cache_func (void)
8728 fprintf (output_file
,
8729 "void\n%s (void)\n{\n int %s;\n\n",
8730 DFA_CLEAN_INSN_CACHE_FUNC_NAME
, I_VARIABLE_NAME
);
8731 fprintf (output_file
,
8732 " for (%s = 0; %s < %s; %s++)\n %s [%s] = -1;\n}\n\n",
8733 I_VARIABLE_NAME
, I_VARIABLE_NAME
,
8734 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
, I_VARIABLE_NAME
,
8735 DFA_INSN_CODES_VARIABLE_NAME
, I_VARIABLE_NAME
);
8737 fprintf (output_file
,
8738 "void\n%s (rtx %s)\n{\n int %s;\n\n",
8739 DFA_CLEAR_SINGLE_INSN_CACHE_FUNC_NAME
, INSN_PARAMETER_NAME
,
8741 fprintf (output_file
,
8742 " %s = INSN_UID (%s);\n if (%s < %s)\n %s [%s] = -1;\n}\n\n",
8743 I_VARIABLE_NAME
, INSN_PARAMETER_NAME
, I_VARIABLE_NAME
,
8744 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
, DFA_INSN_CODES_VARIABLE_NAME
,
8748 /* The function outputs PHR interface function `dfa_start'. */
8750 output_dfa_start_func (void)
8752 fprintf (output_file
,
8753 "void\n%s (void)\n{\n %s = get_max_uid ();\n",
8754 DFA_START_FUNC_NAME
, DFA_INSN_CODES_LENGTH_VARIABLE_NAME
);
8755 fprintf (output_file
, " %s = XNEWVEC (int, %s);\n",
8756 DFA_INSN_CODES_VARIABLE_NAME
, DFA_INSN_CODES_LENGTH_VARIABLE_NAME
);
8757 fprintf (output_file
, " %s ();\n}\n\n", DFA_CLEAN_INSN_CACHE_FUNC_NAME
);
8760 /* The function outputs PHR interface function `dfa_finish'. */
8762 output_dfa_finish_func (void)
8764 fprintf (output_file
, "void\n%s (void)\n{\n free (%s);\n}\n\n",
8765 DFA_FINISH_FUNC_NAME
, DFA_INSN_CODES_VARIABLE_NAME
);
8770 /* The page contains code for output description file (readable
8771 representation of original description and generated DFA(s). */
8773 /* The function outputs string representation of IR reservation. */
8775 output_regexp (regexp_t regexp
)
8777 fprintf (output_description_file
, "%s", regexp_representation (regexp
));
8778 finish_regexp_representation ();
8781 /* Output names of units in LIST separated by comma. */
8783 output_unit_set_el_list (unit_set_el_t list
)
8787 for (el
= list
; el
!= NULL
; el
= el
->next_unit_set_el
)
8790 fprintf (output_description_file
, ", ");
8791 fprintf (output_description_file
, "%s", el
->unit_decl
->name
);
8795 /* Output patterns in LIST separated by comma. */
8797 output_pattern_set_el_list (pattern_set_el_t list
)
8799 pattern_set_el_t el
;
8802 for (el
= list
; el
!= NULL
; el
= el
->next_pattern_set_el
)
8805 fprintf (output_description_file
, ", ");
8806 for (i
= 0; i
< el
->units_num
; i
++)
8807 fprintf (output_description_file
, (i
== 0 ? "%s" : " %s"),
8808 el
->unit_decls
[i
]->name
);
8812 /* The function outputs string representation of IR define_reservation
8813 and define_insn_reservation. */
8815 output_description (void)
8820 for (i
= 0; i
< description
->decls_num
; i
++)
8822 decl
= description
->decls
[i
];
8823 if (decl
->mode
== dm_unit
)
8825 if (DECL_UNIT (decl
)->excl_list
!= NULL
)
8827 fprintf (output_description_file
, "unit %s exclusion_set: ",
8828 DECL_UNIT (decl
)->name
);
8829 output_unit_set_el_list (DECL_UNIT (decl
)->excl_list
);
8830 fprintf (output_description_file
, "\n");
8832 if (DECL_UNIT (decl
)->presence_list
!= NULL
)
8834 fprintf (output_description_file
, "unit %s presence_set: ",
8835 DECL_UNIT (decl
)->name
);
8836 output_pattern_set_el_list (DECL_UNIT (decl
)->presence_list
);
8837 fprintf (output_description_file
, "\n");
8839 if (DECL_UNIT (decl
)->final_presence_list
!= NULL
)
8841 fprintf (output_description_file
, "unit %s final_presence_set: ",
8842 DECL_UNIT (decl
)->name
);
8843 output_pattern_set_el_list
8844 (DECL_UNIT (decl
)->final_presence_list
);
8845 fprintf (output_description_file
, "\n");
8847 if (DECL_UNIT (decl
)->absence_list
!= NULL
)
8849 fprintf (output_description_file
, "unit %s absence_set: ",
8850 DECL_UNIT (decl
)->name
);
8851 output_pattern_set_el_list (DECL_UNIT (decl
)->absence_list
);
8852 fprintf (output_description_file
, "\n");
8854 if (DECL_UNIT (decl
)->final_absence_list
!= NULL
)
8856 fprintf (output_description_file
, "unit %s final_absence_set: ",
8857 DECL_UNIT (decl
)->name
);
8858 output_pattern_set_el_list
8859 (DECL_UNIT (decl
)->final_absence_list
);
8860 fprintf (output_description_file
, "\n");
8864 fprintf (output_description_file
, "\n");
8865 for (i
= 0; i
< description
->normal_decls_num
; i
++)
8867 decl
= description
->decls
[i
];
8868 if (decl
->mode
== dm_reserv
)
8870 fprintf (output_description_file
, "reservation %s: ",
8871 DECL_RESERV (decl
)->name
);
8872 output_regexp (DECL_RESERV (decl
)->regexp
);
8873 fprintf (output_description_file
, "\n");
8875 else if (decl
->mode
== dm_insn_reserv
)
8877 fprintf (output_description_file
, "insn reservation %s ",
8878 DECL_INSN_RESERV (decl
)->name
);
8879 print_rtl (output_description_file
,
8880 DECL_INSN_RESERV (decl
)->condexp
);
8881 fprintf (output_description_file
, ": ");
8882 output_regexp (DECL_INSN_RESERV (decl
)->regexp
);
8883 fprintf (output_description_file
, "\n");
8885 else if (decl
->mode
== dm_bypass
)
8886 fprintf (output_description_file
, "bypass %d %s %s\n",
8887 DECL_BYPASS (decl
)->latency
,
8888 DECL_BYPASS (decl
)->out_pattern
,
8889 DECL_BYPASS (decl
)->in_pattern
);
8891 fprintf (output_description_file
, "\n\f\n");
8894 /* The function outputs name of AUTOMATON. */
8896 output_automaton_name (FILE *f
, automaton_t automaton
)
8898 if (automaton
->corresponding_automaton_decl
== NULL
)
8899 fprintf (f
, "#%d", automaton
->automaton_order_num
);
8901 fprintf (f
, "`%s'", automaton
->corresponding_automaton_decl
->name
);
8904 /* Maximal length of line for pretty printing into description
8906 #define MAX_LINE_LENGTH 70
8908 /* The function outputs units name belonging to AUTOMATON. */
8910 output_automaton_units (automaton_t automaton
)
8914 int curr_line_length
;
8915 int there_is_an_automaton_unit
;
8918 fprintf (output_description_file
, "\n Corresponding units:\n");
8919 fprintf (output_description_file
, " ");
8920 curr_line_length
= 4;
8921 there_is_an_automaton_unit
= 0;
8922 for (i
= 0; i
< description
->decls_num
; i
++)
8924 decl
= description
->decls
[i
];
8925 if (decl
->mode
== dm_unit
8926 && (DECL_UNIT (decl
)->corresponding_automaton_num
8927 == automaton
->automaton_order_num
))
8929 there_is_an_automaton_unit
= 1;
8930 name
= DECL_UNIT (decl
)->name
;
8931 if (curr_line_length
+ strlen (name
) + 1 > MAX_LINE_LENGTH
)
8933 curr_line_length
= strlen (name
) + 4;
8934 fprintf (output_description_file
, "\n ");
8938 curr_line_length
+= strlen (name
) + 1;
8939 fprintf (output_description_file
, " ");
8941 fprintf (output_description_file
, "%s", name
);
8944 if (!there_is_an_automaton_unit
)
8945 fprintf (output_description_file
, "<None>");
8946 fprintf (output_description_file
, "\n\n");
8949 /* The following variable is used for forming array of all possible cpu unit
8950 reservations described by the current DFA state. */
8951 static vec
<reserv_sets_t
> state_reservs
;
8953 /* The function forms `state_reservs' for STATE. */
8955 add_state_reservs (state_t state
)
8957 alt_state_t curr_alt_state
;
8959 if (state
->component_states
!= NULL
)
8960 for (curr_alt_state
= state
->component_states
;
8961 curr_alt_state
!= NULL
;
8962 curr_alt_state
= curr_alt_state
->next_sorted_alt_state
)
8963 add_state_reservs (curr_alt_state
->state
);
8965 state_reservs
.safe_push (state
->reservs
);
8968 /* The function outputs readable representation of all out arcs of
8971 output_state_arcs (state_t state
)
8975 const char *insn_name
;
8976 int curr_line_length
;
8978 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
8981 gcc_assert (ainsn
->first_insn_with_same_reservs
);
8982 fprintf (output_description_file
, " ");
8983 curr_line_length
= 7;
8984 fprintf (output_description_file
, "%2d: ", ainsn
->insn_equiv_class_num
);
8987 insn_name
= ainsn
->insn_reserv_decl
->name
;
8988 if (curr_line_length
+ strlen (insn_name
) > MAX_LINE_LENGTH
)
8990 if (ainsn
!= arc
->insn
)
8992 fprintf (output_description_file
, ",\n ");
8993 curr_line_length
= strlen (insn_name
) + 6;
8996 curr_line_length
+= strlen (insn_name
);
9000 curr_line_length
+= strlen (insn_name
);
9001 if (ainsn
!= arc
->insn
)
9003 curr_line_length
+= 2;
9004 fprintf (output_description_file
, ", ");
9007 fprintf (output_description_file
, "%s", insn_name
);
9008 ainsn
= ainsn
->next_same_reservs_insn
;
9010 while (ainsn
!= NULL
);
9011 fprintf (output_description_file
, " %d \n",
9012 arc
->to_state
->order_state_num
);
9014 fprintf (output_description_file
, "\n");
9017 /* The following function is used for sorting possible cpu unit
9018 reservation of a DFA state. */
9020 state_reservs_cmp (const void *reservs_ptr_1
, const void *reservs_ptr_2
)
9022 return reserv_sets_cmp (*(const_reserv_sets_t
const*) reservs_ptr_1
,
9023 *(const_reserv_sets_t
const*) reservs_ptr_2
);
9026 /* The following function is used for sorting possible cpu unit
9027 reservation of a DFA state. */
9029 remove_state_duplicate_reservs (void)
9033 for (i
= 1, j
= 0; i
< state_reservs
.length (); i
++)
9034 if (reserv_sets_cmp (state_reservs
[j
], state_reservs
[i
]))
9037 state_reservs
[j
] = state_reservs
[i
];
9039 state_reservs
.truncate (j
+ 1);
9042 /* The following function output readable representation of DFA(s)
9043 state used for fast recognition of pipeline hazards. State is
9044 described by possible (current and scheduled) cpu unit
9047 output_state (state_t state
)
9051 state_reservs
.create (0);
9053 fprintf (output_description_file
, " State #%d", state
->order_state_num
);
9054 fprintf (output_description_file
,
9055 state
->new_cycle_p
? " (new cycle)\n" : "\n");
9056 add_state_reservs (state
);
9057 state_reservs
.qsort (state_reservs_cmp
);
9058 remove_state_duplicate_reservs ();
9059 for (i
= 0; i
< state_reservs
.length (); i
++)
9061 fprintf (output_description_file
, " ");
9062 output_reserv_sets (output_description_file
, state_reservs
[i
]);
9063 fprintf (output_description_file
, "\n");
9065 fprintf (output_description_file
, "\n");
9066 output_state_arcs (state
);
9067 state_reservs
.release ();
9070 /* The following function output readable representation of
9071 DFAs used for fast recognition of pipeline hazards. */
9073 output_automaton_descriptions (void)
9075 automaton_t automaton
;
9077 for (automaton
= description
->first_automaton
;
9079 automaton
= automaton
->next_automaton
)
9081 fprintf (output_description_file
, "\nAutomaton ");
9082 output_automaton_name (output_description_file
, automaton
);
9083 fprintf (output_description_file
, "\n");
9084 output_automaton_units (automaton
);
9085 pass_states (automaton
, output_state
);
9091 /* The page contains top level function for generation DFA(s) used for
9094 /* The function outputs statistics about work of different phases of
9097 output_statistics (FILE *f
)
9099 automaton_t automaton
;
9102 int transition_comb_vect_els
= 0;
9103 int transition_full_vect_els
= 0;
9104 int min_issue_delay_vect_els
= 0;
9105 int locked_states
= 0;
9108 for (automaton
= description
->first_automaton
;
9110 automaton
= automaton
->next_automaton
)
9112 fprintf (f
, "\nAutomaton ");
9113 output_automaton_name (f
, automaton
);
9114 fprintf (f
, "\n %5d NDFA states, %5d NDFA arcs\n",
9115 automaton
->NDFA_states_num
, automaton
->NDFA_arcs_num
);
9116 fprintf (f
, " %5d DFA states, %5d DFA arcs\n",
9117 automaton
->DFA_states_num
, automaton
->DFA_arcs_num
);
9118 states_num
= automaton
->DFA_states_num
;
9119 if (!no_minimization_flag
)
9121 fprintf (f
, " %5d minimal DFA states, %5d minimal DFA arcs\n",
9122 automaton
->minimal_DFA_states_num
,
9123 automaton
->minimal_DFA_arcs_num
);
9124 states_num
= automaton
->minimal_DFA_states_num
;
9126 fprintf (f
, " %5d all insns %5d insn equivalence classes\n",
9127 description
->insns_num
, automaton
->insn_equiv_classes_num
);
9128 fprintf (f
, " %d locked states\n", automaton
->locked_states
);
9131 (f
, "%5ld transition comb vector els, %5ld trans table els: %s\n",
9132 (long) automaton
->trans_table
->comb_vect
.length (),
9133 (long) automaton
->trans_table
->full_vect
.length (),
9134 (comb_vect_p (automaton
->trans_table
)
9135 ? "use comb vect" : "use simple vect"));
9137 (f
, "%5ld min delay table els, compression factor %d\n",
9138 (long) states_num
* automaton
->insn_equiv_classes_num
,
9139 automaton
->min_issue_delay_table_compression_factor
);
9140 transition_comb_vect_els
9141 += automaton
->trans_table
->comb_vect
.length ();
9142 transition_full_vect_els
9143 += automaton
->trans_table
->full_vect
.length ();
9144 min_issue_delay_vect_els
9145 += states_num
* automaton
->insn_equiv_classes_num
;
9147 += automaton
->locked_states
;
9151 fprintf (f
, "\n%5d all allocated states, %5d all allocated arcs\n",
9152 allocated_states_num
, allocated_arcs_num
);
9153 fprintf (f
, "%5d all allocated alternative states\n",
9154 allocated_alt_states_num
);
9155 fprintf (f
, "%5d all transition comb vector els, %5d all trans table els\n",
9156 transition_comb_vect_els
, transition_full_vect_els
);
9157 fprintf (f
, "%5d all min delay table els\n", min_issue_delay_vect_els
);
9158 fprintf (f
, "%5d all locked states\n", locked_states
);
9162 /* The function output times of work of different phases of DFA
9165 output_time_statistics (FILE *f
)
9167 fprintf (f
, "\n transformation: ");
9168 print_active_time (f
, transform_time
);
9169 fprintf (f
, (!ndfa_flag
? ", building DFA: " : ", building NDFA: "));
9170 print_active_time (f
, NDFA_time
);
9173 fprintf (f
, ", NDFA -> DFA: ");
9174 print_active_time (f
, NDFA_to_DFA_time
);
9176 fprintf (f
, "\n DFA minimization: ");
9177 print_active_time (f
, minimize_time
);
9178 fprintf (f
, ", making insn equivalence: ");
9179 print_active_time (f
, equiv_time
);
9180 fprintf (f
, "\n all automaton generation: ");
9181 print_active_time (f
, automaton_generation_time
);
9182 fprintf (f
, ", output: ");
9183 print_active_time (f
, output_time
);
9187 /* The function generates DFA (deterministic finite state automaton)
9188 for fast recognition of pipeline hazards. No errors during
9189 checking must be fixed before this function call. */
9193 automata_num
= split_argument
;
9194 if (description
->units_num
< automata_num
)
9195 automata_num
= description
->units_num
;
9198 initiate_automata_lists ();
9199 initiate_pass_states ();
9200 initiate_excl_sets ();
9201 initiate_presence_absence_pattern_sets ();
9202 automaton_generation_time
= create_ticker ();
9204 ticker_off (&automaton_generation_time
);
9209 /* This page mainly contains top level functions of pipeline hazards
9210 description translator. */
9212 /* The following macro value is suffix of name of description file of
9213 pipeline hazards description translator. */
9214 #define STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX ".dfa"
9216 /* The function returns suffix of given file name. The returned
9217 string can not be changed. */
9219 file_name_suffix (const char *file_name
)
9221 const char *last_period
;
9223 for (last_period
= NULL
; *file_name
!= '\0'; file_name
++)
9224 if (*file_name
== '.')
9225 last_period
= file_name
;
9226 return (last_period
== NULL
? file_name
: last_period
);
9229 /* The function returns base name of given file name, i.e. pointer to
9230 first char after last `/' (or `\' for WIN32) in given file name,
9231 given file name itself if the directory name is absent. The
9232 returned string can not be changed. */
9234 base_file_name (const char *file_name
)
9236 int directory_name_length
;
9238 directory_name_length
= strlen (file_name
);
9240 while (directory_name_length
>= 0 && file_name
[directory_name_length
] != '/'
9241 && file_name
[directory_name_length
] != '\\')
9243 while (directory_name_length
>= 0 && file_name
[directory_name_length
] != '/')
9245 directory_name_length
--;
9246 return file_name
+ directory_name_length
+ 1;
9249 /* A function passed as argument to init_rtx_reader_args_cb. It parses the
9250 options available for genautomata. Returns true if the option was
9253 parse_automata_opt (const char *str
)
9255 if (strcmp (str
, NO_MINIMIZATION_OPTION
) == 0)
9256 no_minimization_flag
= 1;
9257 else if (strcmp (str
, TIME_OPTION
) == 0)
9259 else if (strcmp (str
, STATS_OPTION
) == 0)
9261 else if (strcmp (str
, V_OPTION
) == 0)
9263 else if (strcmp (str
, W_OPTION
) == 0)
9265 else if (strcmp (str
, NDFA_OPTION
) == 0)
9267 else if (strcmp (str
, COLLAPSE_OPTION
) == 0)
9269 else if (strcmp (str
, PROGRESS_OPTION
) == 0)
9271 else if (strcmp (str
, "-split") == 0)
9273 fatal ("option `-split' has not been implemented yet\n");
9274 /* split_argument = atoi (argument_vect [i + 1]); */
9282 /* The following is top level function to initialize the work of
9283 pipeline hazards description translator. */
9285 initiate_automaton_gen (char **argv
)
9287 const char *base_name
;
9289 /* Initialize IR storage. */
9290 obstack_init (&irp
);
9291 initiate_automaton_decl_table ();
9292 initiate_insn_decl_table ();
9293 initiate_decl_table ();
9294 output_file
= stdout
;
9295 output_description_file
= NULL
;
9296 base_name
= base_file_name (argv
[1]);
9297 obstack_grow (&irp
, base_name
,
9298 strlen (base_name
) - strlen (file_name_suffix (base_name
)));
9299 obstack_grow (&irp
, STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX
,
9300 strlen (STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX
) + 1);
9301 obstack_1grow (&irp
, '\0');
9302 output_description_file_name
= obstack_base (&irp
);
9303 obstack_finish (&irp
);
9306 /* The following function checks existence at least one arc marked by
9309 check_automata_insn_issues (void)
9311 automaton_t automaton
;
9312 ainsn_t ainsn
, reserv_ainsn
;
9314 for (automaton
= description
->first_automaton
;
9316 automaton
= automaton
->next_automaton
)
9318 for (ainsn
= automaton
->ainsn_list
;
9320 ainsn
= ainsn
->next_ainsn
)
9321 if (ainsn
->first_insn_with_same_reservs
&& !ainsn
->arc_exists_p
9322 && ainsn
!= automaton
->collapse_ainsn
)
9324 for (reserv_ainsn
= ainsn
;
9325 reserv_ainsn
!= NULL
;
9326 reserv_ainsn
= reserv_ainsn
->next_same_reservs_insn
)
9327 if (automaton
->corresponding_automaton_decl
!= NULL
)
9330 error ("Automaton `%s': Insn `%s' will never be issued",
9331 automaton
->corresponding_automaton_decl
->name
,
9332 reserv_ainsn
->insn_reserv_decl
->name
);
9334 warning ("Automaton `%s': Insn `%s' will never be issued",
9335 automaton
->corresponding_automaton_decl
->name
,
9336 reserv_ainsn
->insn_reserv_decl
->name
);
9341 error ("Insn `%s' will never be issued",
9342 reserv_ainsn
->insn_reserv_decl
->name
);
9344 warning ("Insn `%s' will never be issued",
9345 reserv_ainsn
->insn_reserv_decl
->name
);
9351 /* The following vla is used for storing pointers to all achieved
9353 static vec
<state_t
> automaton_states
;
9355 /* This function is called by function pass_states to add an achieved
9358 add_automaton_state (state_t state
)
9360 automaton_states
.safe_push (state
);
9363 /* The following function forms list of important automata (whose
9364 states may be changed after the insn issue) for each insn. */
9366 form_important_insn_automata_lists (void)
9368 automaton_t automaton
;
9375 automaton_states
.create (0);
9376 /* Mark important ainsns. */
9377 for (automaton
= description
->first_automaton
;
9379 automaton
= automaton
->next_automaton
)
9381 automaton_states
.truncate (0);
9382 pass_states (automaton
, add_automaton_state
);
9383 for (n
= 0; n
< automaton_states
.length (); n
++)
9385 state_t s
= automaton_states
[n
];
9386 for (arc
= first_out_arc (s
);
9388 arc
= next_out_arc (arc
))
9389 if (arc
->to_state
!= s
)
9391 gcc_assert (arc
->insn
->first_insn_with_same_reservs
);
9392 for (ainsn
= arc
->insn
;
9394 ainsn
= ainsn
->next_same_reservs_insn
)
9395 ainsn
->important_p
= TRUE
;
9399 automaton_states
.release ();
9401 /* Create automata sets for the insns. */
9402 for (i
= 0; i
< description
->decls_num
; i
++)
9404 decl
= description
->decls
[i
];
9405 if (decl
->mode
== dm_insn_reserv
)
9407 automata_list_start ();
9408 for (automaton
= description
->first_automaton
;
9410 automaton
= automaton
->next_automaton
)
9411 for (ainsn
= automaton
->ainsn_list
;
9413 ainsn
= ainsn
->next_ainsn
)
9414 if (ainsn
->important_p
9415 && ainsn
->insn_reserv_decl
== DECL_INSN_RESERV (decl
))
9417 automata_list_add (automaton
);
9420 DECL_INSN_RESERV (decl
)->important_automata_list
9421 = automata_list_finish ();
9427 /* The following is top level function to generate automat(a,on) for
9428 fast recognition of pipeline hazards. */
9430 expand_automata (void)
9434 description
= XCREATENODEVAR (struct description
,
9435 sizeof (struct description
)
9436 /* Two entries for special insns. */
9437 + sizeof (decl_t
) * (decls
.length () + 1));
9438 description
->decls_num
= decls
.length ();
9439 description
->normal_decls_num
= description
->decls_num
;
9440 description
->query_units_num
= 0;
9441 for (i
= 0; i
< description
->decls_num
; i
++)
9443 description
->decls
[i
] = decls
[i
];
9444 if (description
->decls
[i
]->mode
== dm_unit
9445 && DECL_UNIT (description
->decls
[i
])->query_p
)
9446 DECL_UNIT (description
->decls
[i
])->query_num
9447 = description
->query_units_num
++;
9449 all_time
= create_ticker ();
9450 check_time
= create_ticker ();
9452 fprintf (stderr
, "Check description...");
9453 check_all_description ();
9455 fprintf (stderr
, "done\n");
9456 ticker_off (&check_time
);
9457 generation_time
= create_ticker ();
9460 transform_insn_regexps ();
9461 check_unit_distributions_to_automata ();
9466 check_automata_insn_issues ();
9470 form_important_insn_automata_lists ();
9472 ticker_off (&generation_time
);
9475 /* The following is top level function to output PHR and to finish
9476 work with pipeline description translator. */
9478 write_automata (void)
9480 output_time
= create_ticker ();
9482 fprintf (stderr
, "Forming and outputting automata tables...");
9486 fprintf (stderr
, "done\n");
9487 fprintf (stderr
, "Output functions to work with automata...");
9489 output_chip_definitions ();
9490 output_max_insn_queue_index_def ();
9491 output_internal_min_issue_delay_func ();
9492 output_internal_trans_func ();
9493 /* Cache of insn dfa codes: */
9494 fprintf (output_file
, "\nstatic int *%s;\n", DFA_INSN_CODES_VARIABLE_NAME
);
9495 fprintf (output_file
, "\nstatic int %s;\n\n",
9496 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
);
9497 output_dfa_insn_code_func ();
9498 output_trans_func ();
9499 output_min_issue_delay_func ();
9500 output_internal_dead_lock_func ();
9501 output_dead_lock_func ();
9502 output_size_func ();
9503 output_internal_reset_func ();
9504 output_reset_func ();
9505 output_min_insn_conflict_delay_func ();
9506 output_default_latencies ();
9507 output_internal_insn_latency_func ();
9508 output_insn_latency_func ();
9509 output_internal_maximal_insn_latency_func ();
9510 output_maximal_insn_latency_func ();
9511 output_print_reservation_func ();
9512 /* Output function get_cpu_unit_code. */
9513 fprintf (output_file
, "\n#if %s\n\n", CPU_UNITS_QUERY_MACRO_NAME
);
9514 output_get_cpu_unit_code_func ();
9515 output_cpu_unit_reservation_p ();
9516 output_insn_has_dfa_reservation_p ();
9517 fprintf (output_file
, "\n#endif /* #if %s */\n\n",
9518 CPU_UNITS_QUERY_MACRO_NAME
);
9519 output_dfa_clean_insn_cache_func ();
9520 output_dfa_start_func ();
9521 output_dfa_finish_func ();
9523 fprintf (stderr
, "done\n");
9526 output_description_file
= fopen (output_description_file_name
, "w");
9527 if (output_description_file
== NULL
)
9529 perror (output_description_file_name
);
9530 exit (FATAL_EXIT_CODE
);
9533 fprintf (stderr
, "Output automata description...");
9534 output_description ();
9535 output_automaton_descriptions ();
9537 fprintf (stderr
, "done\n");
9538 output_statistics (output_description_file
);
9541 output_statistics (stderr
);
9542 ticker_off (&output_time
);
9544 output_time_statistics (stderr
);
9547 finish_automata_lists ();
9550 fprintf (stderr
, "Summary:\n");
9551 fprintf (stderr
, " check time ");
9552 print_active_time (stderr
, check_time
);
9553 fprintf (stderr
, ", generation time ");
9554 print_active_time (stderr
, generation_time
);
9555 fprintf (stderr
, ", all time ");
9556 print_active_time (stderr
, all_time
);
9557 fprintf (stderr
, "\n");
9559 /* Finish all work. */
9560 if (output_description_file
!= NULL
)
9562 fflush (output_description_file
);
9563 if (ferror (stdout
) != 0)
9564 fatal ("Error in writing DFA description file %s: %s",
9565 output_description_file_name
, xstrerror (errno
));
9566 fclose (output_description_file
);
9568 finish_automaton_decl_table ();
9569 finish_insn_decl_table ();
9570 finish_decl_table ();
9571 obstack_free (&irp
, NULL
);
9572 if (have_error
&& output_description_file
!= NULL
)
9573 remove (output_description_file_name
);
9577 main (int argc
, char **argv
)
9581 progname
= "genautomata";
9583 if (!init_rtx_reader_args_cb (argc
, argv
, parse_automata_opt
))
9584 return (FATAL_EXIT_CODE
);
9586 initiate_automaton_gen (argv
);
9590 int insn_code_number
;
9592 desc
= read_md_rtx (&lineno
, &insn_code_number
);
9596 switch (GET_CODE (desc
))
9598 case DEFINE_CPU_UNIT
:
9599 gen_cpu_unit (desc
);
9602 case DEFINE_QUERY_CPU_UNIT
:
9603 gen_query_cpu_unit (desc
);
9611 gen_excl_set (desc
);
9615 gen_presence_set (desc
);
9618 case FINAL_PRESENCE_SET
:
9619 gen_final_presence_set (desc
);
9623 gen_absence_set (desc
);
9626 case FINAL_ABSENCE_SET
:
9627 gen_final_absence_set (desc
);
9630 case DEFINE_AUTOMATON
:
9631 gen_automaton (desc
);
9634 case AUTOMATA_OPTION
:
9635 gen_automata_option (desc
);
9638 case DEFINE_RESERVATION
:
9642 case DEFINE_INSN_RESERVATION
:
9643 gen_insn_reserv (desc
);
9652 return FATAL_EXIT_CODE
;
9654 if (decls
.length () > 0)
9659 puts ("/* Generated automatically by the program `genautomata'\n"
9660 " from the machine description file `md'. */\n\n"
9661 "#include \"config.h\"\n"
9662 "#include \"system.h\"\n"
9663 "#include \"coretypes.h\"\n"
9664 "#include \"tm.h\"\n"
9665 "#include \"rtl.h\"\n"
9666 "#include \"tm_p.h\"\n"
9667 "#include \"insn-config.h\"\n"
9668 "#include \"recog.h\"\n"
9669 "#include \"regs.h\"\n"
9670 "#include \"output.h\"\n"
9671 "#include \"insn-attr.h\"\n"
9672 "#include \"diagnostic-core.h\"\n"
9673 "#include \"flags.h\"\n"
9674 "#include \"function.h\"\n"
9675 "#include \"emit-rtl.h\"\n");
9676 /* FIXME: emit-rtl.h can go away once crtl is in rtl.h. */
9683 puts ("/* Generated automatically by the program `genautomata'\n"
9684 " from the machine description file `md'. */\n\n"
9685 "/* There is no automaton, but ISO C forbids empty\n"
9686 " translation units, so include a header file with some\n"
9687 " declarations, and its pre-requisite header file. */\n"
9688 "#include \"config.h\"\n"
9689 "#include \"system.h\"\n");
9693 return (ferror (stdout
) != 0 || have_error
9694 ? FATAL_EXIT_CODE
: SUCCESS_EXIT_CODE
);