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: */
216 DEF_VEC_P(alt_state_t
);
217 DEF_VEC_ALLOC_P(alt_state_t
, heap
);
219 DEF_VEC_ALLOC_P(ainsn_t
, heap
);
221 DEF_VEC_ALLOC_P(state_t
, heap
);
223 DEF_VEC_ALLOC_P(decl_t
, heap
);
224 DEF_VEC_P(reserv_sets_t
);
225 DEF_VEC_ALLOC_P(reserv_sets_t
, heap
);
227 DEF_VEC_I(vect_el_t
);
228 DEF_VEC_ALLOC_I(vect_el_t
, heap
);
229 typedef VEC(vect_el_t
, heap
) *vla_hwint_t
;
231 /* Forward declarations of functions used before their definitions, only. */
232 static regexp_t
gen_regexp_sequence (const char *);
233 static void reserv_sets_or (reserv_sets_t
, reserv_sets_t
,
235 static reserv_sets_t
get_excl_set (reserv_sets_t
);
236 static int check_presence_pattern_sets (reserv_sets_t
,
238 static int check_absence_pattern_sets (reserv_sets_t
, reserv_sets_t
,
240 static arc_t
first_out_arc (const_state_t
);
241 static arc_t
next_out_arc (arc_t
);
245 /* Options with the following names can be set up in automata_option
246 construction. Because the strings occur more one time we use the
249 #define NO_MINIMIZATION_OPTION "-no-minimization"
250 #define TIME_OPTION "-time"
251 #define STATS_OPTION "-stats"
252 #define V_OPTION "-v"
253 #define W_OPTION "-w"
254 #define NDFA_OPTION "-ndfa"
255 #define COLLAPSE_OPTION "-collapse-ndfa"
256 #define NO_COMB_OPTION "-no-comb-vect"
257 #define PROGRESS_OPTION "-progress"
259 /* The following flags are set up by function `initiate_automaton_gen'. */
261 /* Make automata with nondeterministic reservation by insns (`-ndfa'). */
262 static int ndfa_flag
;
264 /* When making an NDFA, produce additional transitions that collapse
265 NDFA state into a deterministic one suitable for querying CPU units.
266 Provide avance-state transitions only for deterministic states. */
267 static int collapse_flag
;
269 /* Do not make minimization of DFA (`-no-minimization'). */
270 static int no_minimization_flag
;
272 /* Do not try to generate a comb vector (`-no-comb-vect'). */
273 static int no_comb_flag
;
275 /* Value of this variable is number of automata being generated. The
276 actual number of automata may be less this value if there is not
277 sufficient number of units. This value is defined by argument of
278 option `-split' or by constructions automaton if the value is zero
279 (it is default value of the argument). */
280 static int split_argument
;
282 /* Flag of output time statistics (`-time'). */
283 static int time_flag
;
285 /* Flag of automata statistics (`-stats'). */
286 static int stats_flag
;
288 /* Flag of creation of description file which contains description of
289 result automaton and statistics information (`-v'). */
292 /* Flag of output of a progress bar showing how many states were
293 generated so far for automaton being processed (`-progress'). */
294 static int progress_flag
;
296 /* Flag of generating warning instead of error for non-critical errors
301 /* Output file for pipeline hazard recognizer (PHR) being generated.
302 The value is NULL if the file is not defined. */
303 static FILE *output_file
;
305 /* Description file of PHR. The value is NULL if the file is not
307 static FILE *output_description_file
;
309 /* PHR description file name. */
310 static char *output_description_file_name
;
312 /* Value of the following variable is node representing description
313 being processed. This is start point of IR. */
314 static struct description
*description
;
318 /* This page contains description of IR structure (nodes). */
332 /* This describes define_cpu_unit and define_query_cpu_unit (see file
337 /* NULL if the automaton name is absent. */
338 const char *automaton_name
;
339 /* If the following value is not zero, the cpu unit reservation is
340 described in define_query_cpu_unit. */
343 /* The following fields are defined by checker. */
345 /* The following field value is nonzero if the unit is used in an
349 /* The following field value is order number (0, 1, ...) of given
352 /* The following field value is corresponding declaration of
353 automaton which was given in description. If the field value is
354 NULL then automaton in the unit declaration was absent. */
355 struct automaton_decl
*automaton_decl
;
356 /* The following field value is maximal cycle number (1, ...) on
357 which given unit occurs in insns. Zero value means that given
358 unit is not used in insns. */
359 int max_occ_cycle_num
;
360 /* The following field value is minimal cycle number (0, ...) on
361 which given unit occurs in insns. -1 value means that given
362 unit is not used in insns. */
363 int min_occ_cycle_num
;
364 /* The following list contains units which conflict with given
366 unit_set_el_t excl_list
;
367 /* The following list contains patterns which are required to
368 reservation of given unit. */
369 pattern_set_el_t presence_list
;
370 pattern_set_el_t final_presence_list
;
371 /* The following list contains patterns which should be not present
372 in reservation for given unit. */
373 pattern_set_el_t absence_list
;
374 pattern_set_el_t final_absence_list
;
375 /* The following is used only when `query_p' has nonzero value.
376 This is query number for the unit. */
378 /* The following is the last cycle on which the unit was checked for
379 correct distributions of units to automata in a regexp. */
380 int last_distribution_check_cycle
;
382 /* The following fields are defined by automaton generator. */
384 /* The following field value is number of the automaton to which
385 given unit belongs. */
386 int corresponding_automaton_num
;
387 /* If the following value is not zero, the cpu unit is present in a
388 `exclusion_set' or in right part of a `presence_set',
389 `final_presence_set', `absence_set', and
390 `final_absence_set'define_query_cpu_unit. */
394 /* This describes define_bypass (see file rtl.def). */
398 const char *out_pattern
;
399 const char *in_pattern
;
400 const char *bypass_guard_name
;
402 /* The following fields are defined by checker. */
404 /* output and input insns of given bypass. */
405 struct insn_reserv_decl
*out_insn_reserv
;
406 struct insn_reserv_decl
*in_insn_reserv
;
407 /* The next bypass for given output insn. */
408 struct bypass_decl
*next
;
411 /* This describes define_automaton (see file rtl.def). */
412 struct automaton_decl
416 /* The following fields are defined by automaton generator. */
418 /* The following field value is nonzero if the automaton is used in
419 an regexp definition. */
420 char automaton_is_used
;
422 /* The following fields are defined by checker. */
424 /* The following field value is the corresponding automaton. This
425 field is not NULL only if the automaton is present in unit
426 declarations and the automatic partition on automata is not
428 automaton_t corresponding_automaton
;
431 /* This describes exclusion relations: exclusion_set (see file
436 int first_list_length
;
440 /* This describes unit relations: [final_]presence_set or
441 [final_]absence_set (see file rtl.def). */
442 struct unit_pattern_rel_decl
451 /* This describes define_reservation (see file rtl.def). */
457 /* The following fields are defined by checker. */
459 /* The following field value is nonzero if the unit is used in an
462 /* The following field is used to check up cycle in expression
467 /* This describes define_insn_reservation (see file rtl.def). */
468 struct insn_reserv_decl
475 /* The following fields are defined by checker. */
477 /* The following field value is order number (0, 1, ...) of given
480 /* The following field value is list of bypasses in which given insn
481 is output insn. Bypasses with the same input insn stay one after
482 another in the list in the same order as their occurrences in the
483 description but the bypass without a guard stays always the last
484 in a row of bypasses with the same input insn. */
485 struct bypass_decl
*bypass_list
;
487 /* The following fields are defined by automaton generator. */
489 /* The following field is the insn regexp transformed that
490 the regexp has not optional regexp, repetition regexp, and an
491 reservation name (i.e. reservation identifiers are changed by the
492 corresponding regexp) and all alternations are the top level
493 of the regexp. The value can be NULL only if it is special
494 insn `cycle advancing'. */
495 regexp_t transformed_regexp
;
496 /* The following field value is list of arcs marked given
497 insn. The field is used in transformation NDFA -> DFA. */
498 arc_t arcs_marked_by_insn
;
499 /* The two following fields are used during minimization of a finite state
501 /* The field value is number of equivalence class of state into
502 which arc marked by given insn enters from a state (fixed during
503 an automaton minimization). */
505 /* The following member value is the list to automata which can be
506 changed by the insn issue. */
507 automata_list_el_t important_automata_list
;
508 /* The following member is used to process insn once for output. */
512 /* This contains a declaration mentioned above. */
515 /* What node in the union? */
520 struct unit_decl unit
;
521 struct bypass_decl bypass
;
522 struct automaton_decl automaton
;
523 struct excl_rel_decl excl
;
524 struct unit_pattern_rel_decl presence
;
525 struct unit_pattern_rel_decl absence
;
526 struct reserv_decl reserv
;
527 struct insn_reserv_decl insn_reserv
;
531 /* The following structures represent parsed reservation strings. */
543 /* Cpu unit in reservation. */
547 unit_decl_t unit_decl
;
550 /* Define_reservation in a reservation. */
554 struct reserv_decl
*reserv_decl
;
557 /* Absence of reservation (represented by string `nothing'). */
558 struct nothing_regexp
560 /* This used to be empty but ISO C doesn't allow that. */
564 /* Representation of reservations separated by ',' (see file
566 struct sequence_regexp
569 regexp_t regexps
[1];
572 /* Representation of construction `repeat' (see file rtl.def). */
579 /* Representation of reservations separated by '+' (see file
584 regexp_t regexps
[1];
587 /* Representation of reservations separated by '|' (see file
592 regexp_t regexps
[1];
595 /* Representation of a reservation string. */
598 /* What node in the union? */
599 enum regexp_mode mode
;
603 struct unit_regexp unit
;
604 struct reserv_regexp reserv
;
605 struct nothing_regexp nothing
;
606 struct sequence_regexp sequence
;
607 struct repeat_regexp repeat
;
608 struct allof_regexp allof
;
609 struct oneof_regexp oneof
;
613 /* Represents description of pipeline hazard description based on
617 int decls_num
, normal_decls_num
;
619 /* The following fields are defined by checker. */
621 /* The following fields values are correspondingly number of all
622 units, query units, and insns in the description. */
626 /* The following field value is max length (in cycles) of
627 reservations of insns. The field value is defined only for
629 int max_insn_reserv_cycles
;
631 /* The following fields are defined by automaton generator. */
633 /* The following field value is the first automaton. */
634 automaton_t first_automaton
;
636 /* The following field is created by pipeline hazard parser and
637 contains all declarations. We allocate additional entries for
638 two special insns which are added by the automaton generator. */
643 /* The following nodes are created in automaton checker. */
645 /* The following nodes represent exclusion set for cpu units. Each
646 element is accessed through only one excl_list. */
649 unit_decl_t unit_decl
;
650 unit_set_el_t next_unit_set_el
;
653 /* The following nodes represent presence or absence pattern for cpu
654 units. Each element is accessed through only one presence_list or
656 struct pattern_set_el
658 /* The number of units in unit_decls. */
660 /* The units forming the pattern. */
661 struct unit_decl
**unit_decls
;
662 pattern_set_el_t next_pattern_set_el
;
666 /* The following nodes are created in automaton generator. */
669 /* The following nodes represent presence or absence pattern for cpu
670 units. Each element is accessed through only one element of
671 unit_presence_set_table or unit_absence_set_table. */
672 struct pattern_reserv
674 reserv_sets_t reserv
;
675 pattern_reserv_t next_pattern_reserv
;
678 /* The following node type describes state automaton. The state may
679 be deterministic or non-deterministic. Non-deterministic state has
680 several component states which represent alternative cpu units
681 reservations. The state also is used for describing a
682 deterministic reservation of automaton insn. */
685 /* The following member value is nonzero if there is a transition by
688 /* The following field is list of processor unit reservations on
690 reserv_sets_t reservs
;
691 /* The following field is unique number of given state between other
694 /* The following field value is automaton to which given state
696 automaton_t automaton
;
697 /* The following field value is the first arc output from given
700 unsigned int num_out_arcs
;
701 /* The following field is used to form NDFA. */
702 char it_was_placed_in_stack_for_NDFA_forming
;
703 /* The following field is used to form DFA. */
704 char it_was_placed_in_stack_for_DFA_forming
;
705 /* The following field is used to transform NDFA to DFA and DFA
706 minimization. The field value is not NULL if the state is a
707 compound state. In this case the value of field `unit_sets_list'
708 is NULL. All states in the list are in the hash table. The list
709 is formed through field `next_sorted_alt_state'. We should
710 support only one level of nesting state. */
711 alt_state_t component_states
;
712 /* The following field is used for passing graph of states. */
714 /* The list of states belonging to one equivalence class is formed
715 with the aid of the following field. */
716 state_t next_equiv_class_state
;
717 /* The two following fields are used during minimization of a finite
719 int equiv_class_num_1
, equiv_class_num_2
;
720 /* The following field is used during minimization of a finite state
721 automaton. The field value is state corresponding to equivalence
722 class to which given state belongs. */
723 state_t equiv_class_state
;
724 unsigned int *presence_signature
;
725 /* The following field value is the order number of given state.
726 The states in final DFA is enumerated with the aid of the
729 /* This member is used for passing states for searching minimal
732 /* The following member is used to evaluate min issue delay of insn
734 int min_insn_issue_delay
;
740 /* The following field refers for the state into which given arc
743 /* The following field describes that the insn issue (with cycle
744 advancing for special insn `cycle advancing' and without cycle
745 advancing for others) makes transition from given state to
746 another given state. */
748 /* The following field value is the next arc output from the same
751 /* List of arcs marked given insn is formed with the following
752 field. The field is used in transformation NDFA -> DFA. */
753 arc_t next_arc_marked_by_insn
;
756 /* The following node type describes a deterministic alternative in
757 non-deterministic state which characterizes cpu unit reservations
758 of automaton insn or which is part of NDFA. */
761 /* The following field is a deterministic state which characterizes
762 unit reservations of the instruction. */
764 /* The following field refers to the next state which characterizes
765 unit reservations of the instruction. */
766 alt_state_t next_alt_state
;
767 /* The following field refers to the next state in sorted list. */
768 alt_state_t next_sorted_alt_state
;
771 /* The following node type describes insn of automaton. They are
772 labels of FA arcs. */
775 /* The following field value is the corresponding insn declaration
777 struct insn_reserv_decl
*insn_reserv_decl
;
778 /* The following field value is the next insn declaration for an
781 /* The following field is states which characterize automaton unit
782 reservations of the instruction. The value can be NULL only if it
783 is special insn `cycle advancing'. */
784 alt_state_t alt_states
;
785 /* The following field is sorted list of states which characterize
786 automaton unit reservations of the instruction. The value can be
787 NULL only if it is special insn `cycle advancing'. */
788 alt_state_t sorted_alt_states
;
789 /* The following field refers the next automaton insn with
790 the same reservations. */
791 ainsn_t next_same_reservs_insn
;
792 /* The following field is flag of the first automaton insn with the
793 same reservations in the declaration list. Only arcs marked such
794 insn is present in the automaton. This significantly decreases
795 memory requirements especially when several automata are
797 char first_insn_with_same_reservs
;
798 /* The following member has nonzero value if there is arc from state of
799 the automaton marked by the ainsn. */
801 /* Cyclic list of insns of an equivalence class is formed with the
802 aid of the following field. */
803 ainsn_t next_equiv_class_insn
;
804 /* The following field value is nonzero if the insn declaration is
805 the first insn declaration with given equivalence number. */
806 char first_ainsn_with_given_equivalence_num
;
807 /* The following field is number of class of equivalence of insns.
808 It is necessary because many insns may be equivalent with the
809 point of view of pipeline hazards. */
810 int insn_equiv_class_num
;
811 /* The following member value is TRUE if there is an arc in the
812 automaton marked by the insn into another state. In other
813 words, the insn can change the state of the automaton. */
817 /* The following describes an automaton for PHR. */
820 /* The following field value is the list of insn declarations for
823 /* Pointers to the ainsns corresponding to the special reservations. */
824 ainsn_t advance_ainsn
, collapse_ainsn
;
826 /* The following field value is the corresponding automaton
827 declaration. This field is not NULL only if the automatic
828 partition on automata is not used. */
829 struct automaton_decl
*corresponding_automaton_decl
;
830 /* The following field value is the next automaton. */
831 automaton_t next_automaton
;
832 /* The following field is start state of FA. There are not unit
833 reservations in the state. */
835 /* The following field value is number of equivalence classes of
836 insns (see field `insn_equiv_class_num' in
837 `insn_reserv_decl'). */
838 int insn_equiv_classes_num
;
839 /* The following field value is number of states of final DFA. */
840 int achieved_states_num
;
841 /* The following field value is the order number (0, 1, ...) of
843 int automaton_order_num
;
844 /* The following fields contain statistics information about
845 building automaton. */
846 int NDFA_states_num
, DFA_states_num
;
847 /* The following field value is defined only if minimization of DFA
849 int minimal_DFA_states_num
;
850 int NDFA_arcs_num
, DFA_arcs_num
;
851 /* The following field value is defined only if minimization of DFA
853 int minimal_DFA_arcs_num
;
854 /* The following member refers for two table state x ainsn -> int.
855 ??? Above sentence is incomprehensible. */
856 state_ainsn_table_t trans_table
;
857 /* The following member value is maximal value of min issue delay
858 for insns of the automaton. */
860 /* Usually min issue delay is small and we can place several (2, 4,
861 8) elements in one vector element. So the compression factor can
862 be 1 (no compression), 2, 4, 8. */
863 int min_issue_delay_table_compression_factor
;
864 /* Total number of locked states in this automaton. */
868 /* The following is the element of the list of automata. */
869 struct automata_list_el
871 /* The automaton itself. */
872 automaton_t automaton
;
873 /* The next automata set element. */
874 automata_list_el_t next_automata_list_el
;
877 /* The following structure describes a table state X ainsn -> int(>= 0). */
878 struct state_ainsn_table
880 /* Automaton to which given table belongs. */
881 automaton_t automaton
;
882 /* The following tree vectors for comb vector implementation of the
884 vla_hwint_t comb_vect
;
885 vla_hwint_t check_vect
;
886 vla_hwint_t base_vect
;
887 /* This is simple implementation of the table. */
888 vla_hwint_t full_vect
;
889 /* Minimal and maximal values of the previous vectors. */
890 int min_comb_vect_el_value
, max_comb_vect_el_value
;
891 int min_base_vect_el_value
, max_base_vect_el_value
;
894 /* Macros to access members of unions. Use only them for access to
895 union members of declarations and regexps. */
897 #if defined ENABLE_CHECKING && (GCC_VERSION >= 2007)
899 #define DECL_UNIT(d) __extension__ \
900 (({ __typeof (d) const _decl = (d); \
901 if (_decl->mode != dm_unit) \
902 decl_mode_check_failed (_decl->mode, "dm_unit", \
903 __FILE__, __LINE__, __FUNCTION__); \
904 &(_decl)->decl.unit; }))
906 #define DECL_BYPASS(d) __extension__ \
907 (({ __typeof (d) const _decl = (d); \
908 if (_decl->mode != dm_bypass) \
909 decl_mode_check_failed (_decl->mode, "dm_bypass", \
910 __FILE__, __LINE__, __FUNCTION__); \
911 &(_decl)->decl.bypass; }))
913 #define DECL_AUTOMATON(d) __extension__ \
914 (({ __typeof (d) const _decl = (d); \
915 if (_decl->mode != dm_automaton) \
916 decl_mode_check_failed (_decl->mode, "dm_automaton", \
917 __FILE__, __LINE__, __FUNCTION__); \
918 &(_decl)->decl.automaton; }))
920 #define DECL_EXCL(d) __extension__ \
921 (({ __typeof (d) const _decl = (d); \
922 if (_decl->mode != dm_excl) \
923 decl_mode_check_failed (_decl->mode, "dm_excl", \
924 __FILE__, __LINE__, __FUNCTION__); \
925 &(_decl)->decl.excl; }))
927 #define DECL_PRESENCE(d) __extension__ \
928 (({ __typeof (d) const _decl = (d); \
929 if (_decl->mode != dm_presence) \
930 decl_mode_check_failed (_decl->mode, "dm_presence", \
931 __FILE__, __LINE__, __FUNCTION__); \
932 &(_decl)->decl.presence; }))
934 #define DECL_ABSENCE(d) __extension__ \
935 (({ __typeof (d) const _decl = (d); \
936 if (_decl->mode != dm_absence) \
937 decl_mode_check_failed (_decl->mode, "dm_absence", \
938 __FILE__, __LINE__, __FUNCTION__); \
939 &(_decl)->decl.absence; }))
941 #define DECL_RESERV(d) __extension__ \
942 (({ __typeof (d) const _decl = (d); \
943 if (_decl->mode != dm_reserv) \
944 decl_mode_check_failed (_decl->mode, "dm_reserv", \
945 __FILE__, __LINE__, __FUNCTION__); \
946 &(_decl)->decl.reserv; }))
948 #define DECL_INSN_RESERV(d) __extension__ \
949 (({ __typeof (d) const _decl = (d); \
950 if (_decl->mode != dm_insn_reserv) \
951 decl_mode_check_failed (_decl->mode, "dm_insn_reserv", \
952 __FILE__, __LINE__, __FUNCTION__); \
953 &(_decl)->decl.insn_reserv; }))
955 static const char *decl_name (enum decl_mode
);
956 static void decl_mode_check_failed (enum decl_mode
, const char *,
957 const char *, int, const char *)
960 /* Return string representation of declaration mode MODE. */
962 decl_name (enum decl_mode mode
)
964 static char str
[100];
968 else if (mode
== dm_bypass
)
970 else if (mode
== dm_automaton
)
971 return "dm_automaton";
972 else if (mode
== dm_excl
)
974 else if (mode
== dm_presence
)
975 return "dm_presence";
976 else if (mode
== dm_absence
)
978 else if (mode
== dm_reserv
)
980 else if (mode
== dm_insn_reserv
)
981 return "dm_insn_reserv";
983 sprintf (str
, "unknown (%d)", (int) mode
);
987 /* The function prints message about unexpected declaration and finish
990 decl_mode_check_failed (enum decl_mode mode
, const char *expected_mode_str
,
991 const char *file
, int line
, const char *func
)
995 "\n%s: %d: error in %s: DECL check: expected decl %s, have %s\n",
996 file
, line
, func
, expected_mode_str
, decl_name (mode
));
1001 #define REGEXP_UNIT(r) __extension__ \
1002 (({ struct regexp *const _regexp = (r); \
1003 if (_regexp->mode != rm_unit) \
1004 regexp_mode_check_failed (_regexp->mode, "rm_unit", \
1005 __FILE__, __LINE__, __FUNCTION__); \
1006 &(_regexp)->regexp.unit; }))
1008 #define REGEXP_RESERV(r) __extension__ \
1009 (({ struct regexp *const _regexp = (r); \
1010 if (_regexp->mode != rm_reserv) \
1011 regexp_mode_check_failed (_regexp->mode, "rm_reserv", \
1012 __FILE__, __LINE__, __FUNCTION__); \
1013 &(_regexp)->regexp.reserv; }))
1015 #define REGEXP_SEQUENCE(r) __extension__ \
1016 (({ struct regexp *const _regexp = (r); \
1017 if (_regexp->mode != rm_sequence) \
1018 regexp_mode_check_failed (_regexp->mode, "rm_sequence", \
1019 __FILE__, __LINE__, __FUNCTION__); \
1020 &(_regexp)->regexp.sequence; }))
1022 #define REGEXP_REPEAT(r) __extension__ \
1023 (({ struct regexp *const _regexp = (r); \
1024 if (_regexp->mode != rm_repeat) \
1025 regexp_mode_check_failed (_regexp->mode, "rm_repeat", \
1026 __FILE__, __LINE__, __FUNCTION__); \
1027 &(_regexp)->regexp.repeat; }))
1029 #define REGEXP_ALLOF(r) __extension__ \
1030 (({ struct regexp *const _regexp = (r); \
1031 if (_regexp->mode != rm_allof) \
1032 regexp_mode_check_failed (_regexp->mode, "rm_allof", \
1033 __FILE__, __LINE__, __FUNCTION__); \
1034 &(_regexp)->regexp.allof; }))
1036 #define REGEXP_ONEOF(r) __extension__ \
1037 (({ struct regexp *const _regexp = (r); \
1038 if (_regexp->mode != rm_oneof) \
1039 regexp_mode_check_failed (_regexp->mode, "rm_oneof", \
1040 __FILE__, __LINE__, __FUNCTION__); \
1041 &(_regexp)->regexp.oneof; }))
1043 static const char *regexp_name (enum regexp_mode
);
1044 static void regexp_mode_check_failed (enum regexp_mode
, const char *,
1046 const char *) ATTRIBUTE_NORETURN
;
1049 /* Return string representation of regexp mode MODE. */
1051 regexp_name (enum regexp_mode mode
)
1060 return "rm_nothing";
1062 return "rm_sequence";
1074 /* The function prints message about unexpected regexp and finish the
1077 regexp_mode_check_failed (enum regexp_mode mode
,
1078 const char *expected_mode_str
,
1079 const char *file
, int line
, const char *func
)
1083 "\n%s: %d: error in %s: REGEXP check: expected decl %s, have %s\n",
1084 file
, line
, func
, expected_mode_str
, regexp_name (mode
));
1088 #else /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */
1090 #define DECL_UNIT(d) (&(d)->decl.unit)
1091 #define DECL_BYPASS(d) (&(d)->decl.bypass)
1092 #define DECL_AUTOMATON(d) (&(d)->decl.automaton)
1093 #define DECL_EXCL(d) (&(d)->decl.excl)
1094 #define DECL_PRESENCE(d) (&(d)->decl.presence)
1095 #define DECL_ABSENCE(d) (&(d)->decl.absence)
1096 #define DECL_RESERV(d) (&(d)->decl.reserv)
1097 #define DECL_INSN_RESERV(d) (&(d)->decl.insn_reserv)
1099 #define REGEXP_UNIT(r) (&(r)->regexp.unit)
1100 #define REGEXP_RESERV(r) (&(r)->regexp.reserv)
1101 #define REGEXP_SEQUENCE(r) (&(r)->regexp.sequence)
1102 #define REGEXP_REPEAT(r) (&(r)->regexp.repeat)
1103 #define REGEXP_ALLOF(r) (&(r)->regexp.allof)
1104 #define REGEXP_ONEOF(r) (&(r)->regexp.oneof)
1106 #endif /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */
1108 #define XCREATENODE(T) ((T *) create_node (sizeof (T)))
1109 #define XCREATENODEVEC(T, N) ((T *) create_node (sizeof (T) * (N)))
1110 #define XCREATENODEVAR(T, S) ((T *) create_node ((S)))
1112 #define XCOPYNODE(T, P) ((T *) copy_node ((P), sizeof (T)))
1113 #define XCOPYNODEVEC(T, P, N) ((T *) copy_node ((P), sizeof (T) * (N)))
1114 #define XCOPYNODEVAR(T, P, S) ((T *) copy_node ((P), (S)))
1116 /* Create IR structure (node). */
1118 create_node (size_t size
)
1122 obstack_blank (&irp
, size
);
1123 result
= obstack_base (&irp
);
1124 obstack_finish (&irp
);
1125 /* Default values of members are NULL and zero. */
1126 memset (result
, 0, size
);
1130 /* Copy IR structure (node). */
1132 copy_node (const void *from
, size_t size
)
1134 void *const result
= create_node (size
);
1135 memcpy (result
, from
, size
);
1139 /* The function checks that NAME does not contain quotes (`"'). */
1141 check_name (const char * name
, pos_t pos ATTRIBUTE_UNUSED
)
1145 for (str
= name
; *str
!= '\0'; str
++)
1147 error ("Name `%s' contains quotes", name
);
1151 /* Pointers to all declarations during IR generation are stored in the
1153 static VEC(decl_t
, heap
) *decls
;
1155 /* Given a pointer to a (char *) and a separator, return an alloc'ed
1156 string containing the next separated element, taking parentheses
1157 into account if PAR_FLAG has nonzero value. Advance the pointer to
1158 after the string scanned, or the end-of-string. Return NULL if at
1161 next_sep_el (const char **pstr
, int sep
, int par_flag
)
1168 /* Remove leading whitespaces. */
1169 while (ISSPACE ((int) **pstr
))
1176 for (pars_num
= 0, p
= *pstr
; *p
!= '\0'; p
++)
1178 if (par_flag
&& *p
== '(')
1180 else if (par_flag
&& *p
== ')')
1182 else if (pars_num
== 0 && *p
== sep
)
1184 if (pars_num
== 0 && ISSPACE ((int) *p
))
1188 for (; n_spaces
!= 0; n_spaces
--)
1189 obstack_1grow (&irp
, p
[-n_spaces
]);
1190 obstack_1grow (&irp
, *p
);
1193 obstack_1grow (&irp
, '\0');
1194 out_str
= obstack_base (&irp
);
1195 obstack_finish (&irp
);
1204 /* Given a string and a separator, return the number of separated
1205 elements in it, taking parentheses into account if PAR_FLAG has
1206 nonzero value. Return 0 for the null string, -1 if parentheses is
1209 n_sep_els (const char *s
, int sep
, int par_flag
)
1217 for (pars_num
= 0, n
= 1; *s
; s
++)
1218 if (par_flag
&& *s
== '(')
1220 else if (par_flag
&& *s
== ')')
1222 else if (pars_num
== 0 && *s
== sep
)
1225 return (pars_num
!= 0 ? -1 : n
);
1228 /* Given a string and a separator, return vector of strings which are
1229 elements in the string and number of elements through els_num.
1230 Take parentheses into account if PAREN_P has nonzero value. The
1231 function also inserts the end marker NULL at the end of vector.
1232 Return 0 for the null string, -1 if parentheses are not balanced. */
1234 get_str_vect (const char *str
, int *els_num
, int sep
, int paren_p
)
1241 *els_num
= n_sep_els (str
, sep
, paren_p
);
1244 obstack_blank (&irp
, sizeof (char *) * (*els_num
+ 1));
1245 vect
= (char **) obstack_base (&irp
);
1246 obstack_finish (&irp
);
1248 for (i
= 0; i
< *els_num
; i
++)
1249 vect
[i
] = next_sep_el (pstr
, sep
, paren_p
);
1250 trail
= next_sep_el (pstr
, sep
, paren_p
);
1251 gcc_assert (!trail
);
1256 /* Process a DEFINE_CPU_UNIT.
1258 This gives information about a unit contained in CPU. We fill a
1259 struct unit_decl with information used later by `expand_automata'. */
1261 gen_cpu_unit (rtx def
)
1264 char **str_cpu_units
;
1268 str_cpu_units
= get_str_vect (XSTR (def
, 0), &vect_length
, ',', FALSE
);
1269 if (str_cpu_units
== NULL
)
1270 fatal ("invalid string `%s' in define_cpu_unit", XSTR (def
, 0));
1271 for (i
= 0; i
< vect_length
; i
++)
1273 decl
= XCREATENODE (struct decl
);
1274 decl
->mode
= dm_unit
;
1276 DECL_UNIT (decl
)->name
= check_name (str_cpu_units
[i
], decl
->pos
);
1277 DECL_UNIT (decl
)->automaton_name
= XSTR (def
, 1);
1278 DECL_UNIT (decl
)->query_p
= 0;
1279 DECL_UNIT (decl
)->min_occ_cycle_num
= -1;
1280 DECL_UNIT (decl
)->in_set_p
= 0;
1281 VEC_safe_push (decl_t
, heap
, decls
, decl
);
1285 /* Process a DEFINE_QUERY_CPU_UNIT.
1287 This gives information about a unit contained in CPU. We fill a
1288 struct unit_decl with information used later by `expand_automata'. */
1290 gen_query_cpu_unit (rtx def
)
1293 char **str_cpu_units
;
1297 str_cpu_units
= get_str_vect (XSTR (def
, 0), &vect_length
, ',',
1299 if (str_cpu_units
== NULL
)
1300 fatal ("invalid string `%s' in define_query_cpu_unit", XSTR (def
, 0));
1301 for (i
= 0; i
< vect_length
; i
++)
1303 decl
= XCREATENODE (struct decl
);
1304 decl
->mode
= dm_unit
;
1306 DECL_UNIT (decl
)->name
= check_name (str_cpu_units
[i
], decl
->pos
);
1307 DECL_UNIT (decl
)->automaton_name
= XSTR (def
, 1);
1308 DECL_UNIT (decl
)->query_p
= 1;
1309 VEC_safe_push (decl_t
, heap
, decls
, decl
);
1313 /* Process a DEFINE_BYPASS.
1315 This gives information about a unit contained in the CPU. We fill
1316 in a struct bypass_decl with information used later by
1317 `expand_automata'. */
1319 gen_bypass (rtx def
)
1322 char **out_patterns
;
1328 out_patterns
= get_str_vect (XSTR (def
, 1), &out_length
, ',', FALSE
);
1329 if (out_patterns
== NULL
)
1330 fatal ("invalid string `%s' in define_bypass", XSTR (def
, 1));
1331 in_patterns
= get_str_vect (XSTR (def
, 2), &in_length
, ',', FALSE
);
1332 if (in_patterns
== NULL
)
1333 fatal ("invalid string `%s' in define_bypass", XSTR (def
, 2));
1334 for (i
= 0; i
< out_length
; i
++)
1335 for (j
= 0; j
< in_length
; j
++)
1337 decl
= XCREATENODE (struct decl
);
1338 decl
->mode
= dm_bypass
;
1340 DECL_BYPASS (decl
)->latency
= XINT (def
, 0);
1341 DECL_BYPASS (decl
)->out_pattern
= out_patterns
[i
];
1342 DECL_BYPASS (decl
)->in_pattern
= in_patterns
[j
];
1343 DECL_BYPASS (decl
)->bypass_guard_name
= XSTR (def
, 3);
1344 VEC_safe_push (decl_t
, heap
, decls
, decl
);
1348 /* Process an EXCLUSION_SET.
1350 This gives information about a cpu unit conflicts. We fill a
1351 struct excl_rel_decl (excl) with information used later by
1352 `expand_automata'. */
1354 gen_excl_set (rtx def
)
1357 char **first_str_cpu_units
;
1358 char **second_str_cpu_units
;
1359 int first_vect_length
;
1364 = get_str_vect (XSTR (def
, 0), &first_vect_length
, ',', FALSE
);
1365 if (first_str_cpu_units
== NULL
)
1366 fatal ("invalid first string `%s' in exclusion_set", XSTR (def
, 0));
1367 second_str_cpu_units
= get_str_vect (XSTR (def
, 1), &length
, ',',
1369 if (second_str_cpu_units
== NULL
)
1370 fatal ("invalid second string `%s' in exclusion_set", XSTR (def
, 1));
1371 length
+= first_vect_length
;
1372 decl
= XCREATENODEVAR (struct decl
, sizeof (struct decl
) + (length
- 1) * sizeof (char *));
1373 decl
->mode
= dm_excl
;
1375 DECL_EXCL (decl
)->all_names_num
= length
;
1376 DECL_EXCL (decl
)->first_list_length
= first_vect_length
;
1377 for (i
= 0; i
< length
; i
++)
1378 if (i
< first_vect_length
)
1379 DECL_EXCL (decl
)->names
[i
] = first_str_cpu_units
[i
];
1381 DECL_EXCL (decl
)->names
[i
]
1382 = second_str_cpu_units
[i
- first_vect_length
];
1383 VEC_safe_push (decl_t
, heap
, decls
, decl
);
1386 /* Process a PRESENCE_SET, a FINAL_PRESENCE_SET, an ABSENCE_SET,
1387 FINAL_ABSENCE_SET (it is depended on PRESENCE_P and FINAL_P).
1389 This gives information about a cpu unit reservation requirements.
1390 We fill a struct unit_pattern_rel_decl with information used later
1391 by `expand_automata'. */
1393 gen_presence_absence_set (rtx def
, int presence_p
, int final_p
)
1396 char **str_cpu_units
;
1397 char **str_pattern_lists
;
1398 char ***str_patterns
;
1399 int cpu_units_length
;
1401 int patterns_length
;
1404 str_cpu_units
= get_str_vect (XSTR (def
, 0), &cpu_units_length
, ',',
1406 if (str_cpu_units
== NULL
)
1409 ? "invalid first string `%s' in final_presence_set"
1410 : "invalid first string `%s' in presence_set")
1412 ? "invalid first string `%s' in final_absence_set"
1413 : "invalid first string `%s' in absence_set")),
1415 str_pattern_lists
= get_str_vect (XSTR (def
, 1),
1416 &patterns_length
, ',', FALSE
);
1417 if (str_pattern_lists
== NULL
)
1420 ? "invalid second string `%s' in final_presence_set"
1421 : "invalid second string `%s' in presence_set")
1423 ? "invalid second string `%s' in final_absence_set"
1424 : "invalid second string `%s' in absence_set")), XSTR (def
, 1));
1425 str_patterns
= XOBNEWVEC (&irp
, char **, patterns_length
);
1426 for (i
= 0; i
< patterns_length
; i
++)
1428 str_patterns
[i
] = get_str_vect (str_pattern_lists
[i
],
1429 &length
, ' ', FALSE
);
1430 gcc_assert (str_patterns
[i
]);
1432 decl
= XCREATENODE (struct decl
);
1436 decl
->mode
= dm_presence
;
1437 DECL_PRESENCE (decl
)->names_num
= cpu_units_length
;
1438 DECL_PRESENCE (decl
)->names
= str_cpu_units
;
1439 DECL_PRESENCE (decl
)->patterns
= str_patterns
;
1440 DECL_PRESENCE (decl
)->patterns_num
= patterns_length
;
1441 DECL_PRESENCE (decl
)->final_p
= final_p
;
1445 decl
->mode
= dm_absence
;
1446 DECL_ABSENCE (decl
)->names_num
= cpu_units_length
;
1447 DECL_ABSENCE (decl
)->names
= str_cpu_units
;
1448 DECL_ABSENCE (decl
)->patterns
= str_patterns
;
1449 DECL_ABSENCE (decl
)->patterns_num
= patterns_length
;
1450 DECL_ABSENCE (decl
)->final_p
= final_p
;
1452 VEC_safe_push (decl_t
, heap
, decls
, decl
);
1455 /* Process a PRESENCE_SET.
1457 This gives information about a cpu unit reservation requirements.
1458 We fill a struct unit_pattern_rel_decl (presence) with information
1459 used later by `expand_automata'. */
1461 gen_presence_set (rtx def
)
1463 gen_presence_absence_set (def
, TRUE
, FALSE
);
1466 /* Process a FINAL_PRESENCE_SET.
1468 This gives information about a cpu unit reservation requirements.
1469 We fill a struct unit_pattern_rel_decl (presence) with information
1470 used later by `expand_automata'. */
1472 gen_final_presence_set (rtx def
)
1474 gen_presence_absence_set (def
, TRUE
, TRUE
);
1477 /* Process an ABSENCE_SET.
1479 This gives information about a cpu unit reservation requirements.
1480 We fill a struct unit_pattern_rel_decl (absence) with information
1481 used later by `expand_automata'. */
1483 gen_absence_set (rtx def
)
1485 gen_presence_absence_set (def
, FALSE
, FALSE
);
1488 /* Process a FINAL_ABSENCE_SET.
1490 This gives information about a cpu unit reservation requirements.
1491 We fill a struct unit_pattern_rel_decl (absence) with information
1492 used later by `expand_automata'. */
1494 gen_final_absence_set (rtx def
)
1496 gen_presence_absence_set (def
, FALSE
, TRUE
);
1499 /* Process a DEFINE_AUTOMATON.
1501 This gives information about a finite state automaton used for
1502 recognizing pipeline hazards. We fill a struct automaton_decl
1503 with information used later by `expand_automata'. */
1505 gen_automaton (rtx def
)
1508 char **str_automata
;
1512 str_automata
= get_str_vect (XSTR (def
, 0), &vect_length
, ',', FALSE
);
1513 if (str_automata
== NULL
)
1514 fatal ("invalid string `%s' in define_automaton", XSTR (def
, 0));
1515 for (i
= 0; i
< vect_length
; i
++)
1517 decl
= XCREATENODE (struct decl
);
1518 decl
->mode
= dm_automaton
;
1520 DECL_AUTOMATON (decl
)->name
= check_name (str_automata
[i
], decl
->pos
);
1521 VEC_safe_push (decl_t
, heap
, decls
, decl
);
1525 /* Process an AUTOMATA_OPTION.
1527 This gives information how to generate finite state automaton used
1528 for recognizing pipeline hazards. */
1530 gen_automata_option (rtx def
)
1532 if (strcmp (XSTR (def
, 0), NO_MINIMIZATION_OPTION
+ 1) == 0)
1533 no_minimization_flag
= 1;
1534 else if (strcmp (XSTR (def
, 0), TIME_OPTION
+ 1) == 0)
1536 else if (strcmp (XSTR (def
, 0), STATS_OPTION
+ 1) == 0)
1538 else if (strcmp (XSTR (def
, 0), V_OPTION
+ 1) == 0)
1540 else if (strcmp (XSTR (def
, 0), W_OPTION
+ 1) == 0)
1542 else if (strcmp (XSTR (def
, 0), NDFA_OPTION
+ 1) == 0)
1544 else if (strcmp (XSTR (def
, 0), COLLAPSE_OPTION
+ 1) == 0)
1546 else if (strcmp (XSTR (def
, 0), NO_COMB_OPTION
+ 1) == 0)
1548 else if (strcmp (XSTR (def
, 0), PROGRESS_OPTION
+ 1) == 0)
1551 fatal ("invalid option `%s' in automata_option", XSTR (def
, 0));
1554 /* Name in reservation to denote absence reservation. */
1555 #define NOTHING_NAME "nothing"
1557 /* The following string contains original reservation string being
1559 static const char *reserv_str
;
1561 /* Parse an element in STR. */
1563 gen_regexp_el (const char *str
)
1572 if (str
[len
- 1] != ')')
1573 fatal ("garbage after ) in reservation `%s'", reserv_str
);
1574 dstr
= XALLOCAVAR (char, len
- 1);
1575 memcpy (dstr
, str
+ 1, len
- 2);
1576 dstr
[len
-2] = '\0';
1577 regexp
= gen_regexp_sequence (dstr
);
1579 else if (strcmp (str
, NOTHING_NAME
) == 0)
1581 regexp
= XCREATENODE (struct regexp
);
1582 regexp
->mode
= rm_nothing
;
1586 regexp
= XCREATENODE (struct regexp
);
1587 regexp
->mode
= rm_unit
;
1588 REGEXP_UNIT (regexp
)->name
= str
;
1593 /* Parse construction `repeat' in STR. */
1595 gen_regexp_repeat (const char *str
)
1603 repeat_vect
= get_str_vect (str
, &els_num
, '*', TRUE
);
1604 if (repeat_vect
== NULL
)
1605 fatal ("invalid `%s' in reservation `%s'", str
, reserv_str
);
1608 regexp
= gen_regexp_el (repeat_vect
[0]);
1609 for (i
= 1; i
< els_num
; i
++)
1611 repeat
= XCREATENODE (struct regexp
);
1612 repeat
->mode
= rm_repeat
;
1613 REGEXP_REPEAT (repeat
)->regexp
= regexp
;
1614 REGEXP_REPEAT (repeat
)->repeat_num
= atoi (repeat_vect
[i
]);
1615 if (REGEXP_REPEAT (repeat
)->repeat_num
<= 1)
1616 fatal ("repetition `%s' <= 1 in reservation `%s'",
1623 return gen_regexp_el (repeat_vect
[0]);
1626 /* Parse reservation STR which possibly contains separator '+'. */
1628 gen_regexp_allof (const char *str
)
1635 allof_vect
= get_str_vect (str
, &els_num
, '+', TRUE
);
1636 if (allof_vect
== NULL
)
1637 fatal ("invalid `%s' in reservation `%s'", str
, reserv_str
);
1640 allof
= XCREATENODEVAR (struct regexp
, sizeof (struct regexp
)
1641 + sizeof (regexp_t
) * (els_num
- 1));
1642 allof
->mode
= rm_allof
;
1643 REGEXP_ALLOF (allof
)->regexps_num
= els_num
;
1644 for (i
= 0; i
< els_num
; i
++)
1645 REGEXP_ALLOF (allof
)->regexps
[i
] = gen_regexp_repeat (allof_vect
[i
]);
1649 return gen_regexp_repeat (allof_vect
[0]);
1652 /* Parse reservation STR which possibly contains separator '|'. */
1654 gen_regexp_oneof (const char *str
)
1661 oneof_vect
= get_str_vect (str
, &els_num
, '|', TRUE
);
1662 if (oneof_vect
== NULL
)
1663 fatal ("invalid `%s' in reservation `%s'", str
, reserv_str
);
1666 oneof
= XCREATENODEVAR (struct regexp
, sizeof (struct regexp
)
1667 + sizeof (regexp_t
) * (els_num
- 1));
1668 oneof
->mode
= rm_oneof
;
1669 REGEXP_ONEOF (oneof
)->regexps_num
= els_num
;
1670 for (i
= 0; i
< els_num
; i
++)
1671 REGEXP_ONEOF (oneof
)->regexps
[i
] = gen_regexp_allof (oneof_vect
[i
]);
1675 return gen_regexp_allof (oneof_vect
[0]);
1678 /* Parse reservation STR which possibly contains separator ','. */
1680 gen_regexp_sequence (const char *str
)
1683 char **sequence_vect
;
1687 sequence_vect
= get_str_vect (str
, &els_num
, ',', TRUE
);
1690 sequence
= XCREATENODEVAR (struct regexp
, sizeof (struct regexp
)
1691 + sizeof (regexp_t
) * (els_num
- 1));
1692 sequence
->mode
= rm_sequence
;
1693 REGEXP_SEQUENCE (sequence
)->regexps_num
= els_num
;
1694 for (i
= 0; i
< els_num
; i
++)
1695 REGEXP_SEQUENCE (sequence
)->regexps
[i
]
1696 = gen_regexp_oneof (sequence_vect
[i
]);
1700 return gen_regexp_oneof (sequence_vect
[0]);
1703 /* Parse construction reservation STR. */
1705 gen_regexp (const char *str
)
1708 return gen_regexp_sequence (str
);
1711 /* Process a DEFINE_RESERVATION.
1713 This gives information about a reservation of cpu units. We fill
1714 in a struct reserv_decl with information used later by
1715 `expand_automata'. */
1717 gen_reserv (rtx def
)
1721 decl
= XCREATENODE (struct decl
);
1722 decl
->mode
= dm_reserv
;
1724 DECL_RESERV (decl
)->name
= check_name (XSTR (def
, 0), decl
->pos
);
1725 DECL_RESERV (decl
)->regexp
= gen_regexp (XSTR (def
, 1));
1726 VEC_safe_push (decl_t
, heap
, decls
, decl
);
1729 /* Process a DEFINE_INSN_RESERVATION.
1731 This gives information about the reservation of cpu units by an
1732 insn. We fill a struct insn_reserv_decl with information used
1733 later by `expand_automata'. */
1735 gen_insn_reserv (rtx def
)
1739 decl
= XCREATENODE (struct decl
);
1740 decl
->mode
= dm_insn_reserv
;
1742 DECL_INSN_RESERV (decl
)->name
1743 = check_name (XSTR (def
, 0), decl
->pos
);
1744 DECL_INSN_RESERV (decl
)->default_latency
= XINT (def
, 1);
1745 DECL_INSN_RESERV (decl
)->condexp
= XEXP (def
, 2);
1746 DECL_INSN_RESERV (decl
)->regexp
= gen_regexp (XSTR (def
, 3));
1747 VEC_safe_push (decl_t
, heap
, decls
, decl
);
1752 /* The function evaluates hash value (0..UINT_MAX) of string. */
1754 string_hash (const char *string
)
1758 for (result
= i
= 0;*string
++ != '\0'; i
++)
1759 result
+= ((unsigned char) *string
<< (i
% CHAR_BIT
));
1765 /* This page contains abstract data `table of automaton declarations'.
1766 Elements of the table is nodes representing automaton declarations.
1767 Key of the table elements is name of given automaton. Remember
1768 that automaton names have own space. */
1770 /* The function evaluates hash value of an automaton declaration. The
1771 function is used by abstract data `hashtab'. The function returns
1772 hash value (0..UINT_MAX) of given automaton declaration. */
1774 automaton_decl_hash (const void *automaton_decl
)
1776 const_decl_t
const decl
= (const_decl_t
) automaton_decl
;
1778 gcc_assert (decl
->mode
!= dm_automaton
1779 || DECL_AUTOMATON (decl
)->name
);
1780 return string_hash (DECL_AUTOMATON (decl
)->name
);
1783 /* The function tests automaton declarations on equality of their
1784 keys. The function is used by abstract data `hashtab'. The
1785 function returns 1 if the declarations have the same key, 0
1788 automaton_decl_eq_p (const void* automaton_decl_1
,
1789 const void* automaton_decl_2
)
1791 const_decl_t
const decl1
= (const_decl_t
) automaton_decl_1
;
1792 const_decl_t
const decl2
= (const_decl_t
) automaton_decl_2
;
1794 gcc_assert (decl1
->mode
== dm_automaton
1795 && DECL_AUTOMATON (decl1
)->name
1796 && decl2
->mode
== dm_automaton
1797 && DECL_AUTOMATON (decl2
)->name
);
1798 return strcmp (DECL_AUTOMATON (decl1
)->name
,
1799 DECL_AUTOMATON (decl2
)->name
) == 0;
1802 /* The automaton declaration table itself is represented by the
1803 following variable. */
1804 static htab_t automaton_decl_table
;
1806 /* The function inserts automaton declaration into the table. The
1807 function does nothing if an automaton declaration with the same key
1808 exists already in the table. The function returns automaton
1809 declaration node in the table with the same key as given automaton
1810 declaration node. */
1812 insert_automaton_decl (decl_t automaton_decl
)
1816 entry_ptr
= htab_find_slot (automaton_decl_table
, automaton_decl
, INSERT
);
1817 if (*entry_ptr
== NULL
)
1818 *entry_ptr
= (void *) automaton_decl
;
1819 return (decl_t
) *entry_ptr
;
1822 /* The following variable value is node representing automaton
1823 declaration. The node used for searching automaton declaration
1825 static struct decl work_automaton_decl
;
1827 /* The function searches for automaton declaration in the table with
1828 the same key as node representing name of the automaton
1829 declaration. The function returns node found in the table, NULL if
1830 such node does not exist in the table. */
1832 find_automaton_decl (const char *name
)
1836 work_automaton_decl
.mode
= dm_automaton
;
1837 DECL_AUTOMATON (&work_automaton_decl
)->name
= name
;
1838 entry
= htab_find (automaton_decl_table
, &work_automaton_decl
);
1839 return (decl_t
) entry
;
1842 /* The function creates empty automaton declaration table and node
1843 representing automaton declaration and used for searching automaton
1844 declaration with given name. The function must be called only once
1845 before any work with the automaton declaration table. */
1847 initiate_automaton_decl_table (void)
1849 work_automaton_decl
.mode
= dm_automaton
;
1850 automaton_decl_table
= htab_create (10, automaton_decl_hash
,
1851 automaton_decl_eq_p
, (htab_del
) 0);
1854 /* The function deletes the automaton declaration table. Only call of
1855 function `initiate_automaton_decl_table' is possible immediately
1856 after this function call. */
1858 finish_automaton_decl_table (void)
1860 htab_delete (automaton_decl_table
);
1865 /* This page contains abstract data `table of insn declarations'.
1866 Elements of the table is nodes representing insn declarations. Key
1867 of the table elements is name of given insn (in corresponding
1868 define_insn_reservation). Remember that insn names have own
1871 /* The function evaluates hash value of an insn declaration. The
1872 function is used by abstract data `hashtab'. The function returns
1873 hash value (0..UINT_MAX) of given insn declaration. */
1875 insn_decl_hash (const void *insn_decl
)
1877 const_decl_t
const decl
= (const_decl_t
) insn_decl
;
1879 gcc_assert (decl
->mode
== dm_insn_reserv
1880 && DECL_INSN_RESERV (decl
)->name
);
1881 return string_hash (DECL_INSN_RESERV (decl
)->name
);
1884 /* The function tests insn declarations on equality of their keys.
1885 The function is used by abstract data `hashtab'. The function
1886 returns 1 if declarations have the same key, 0 otherwise. */
1888 insn_decl_eq_p (const void *insn_decl_1
, const void *insn_decl_2
)
1890 const_decl_t
const decl1
= (const_decl_t
) insn_decl_1
;
1891 const_decl_t
const decl2
= (const_decl_t
) insn_decl_2
;
1893 gcc_assert (decl1
->mode
== dm_insn_reserv
1894 && DECL_INSN_RESERV (decl1
)->name
1895 && decl2
->mode
== dm_insn_reserv
1896 && DECL_INSN_RESERV (decl2
)->name
);
1897 return strcmp (DECL_INSN_RESERV (decl1
)->name
,
1898 DECL_INSN_RESERV (decl2
)->name
) == 0;
1901 /* The insn declaration table itself is represented by the following
1902 variable. The table does not contain insn reservation
1904 static htab_t insn_decl_table
;
1906 /* The function inserts insn declaration into the table. The function
1907 does nothing if an insn declaration with the same key exists
1908 already in the table. The function returns insn declaration node
1909 in the table with the same key as given insn declaration node. */
1911 insert_insn_decl (decl_t insn_decl
)
1915 entry_ptr
= htab_find_slot (insn_decl_table
, insn_decl
, INSERT
);
1916 if (*entry_ptr
== NULL
)
1917 *entry_ptr
= (void *) insn_decl
;
1918 return (decl_t
) *entry_ptr
;
1921 /* The following variable value is node representing insn reservation
1922 declaration. The node used for searching insn reservation
1923 declaration with given name. */
1924 static struct decl work_insn_decl
;
1926 /* The function searches for insn reservation declaration in the table
1927 with the same key as node representing name of the insn reservation
1928 declaration. The function returns node found in the table, NULL if
1929 such node does not exist in the table. */
1931 find_insn_decl (const char *name
)
1935 work_insn_decl
.mode
= dm_insn_reserv
;
1936 DECL_INSN_RESERV (&work_insn_decl
)->name
= name
;
1937 entry
= htab_find (insn_decl_table
, &work_insn_decl
);
1938 return (decl_t
) entry
;
1941 /* The function creates empty insn declaration table and node
1942 representing insn declaration and used for searching insn
1943 declaration with given name. The function must be called only once
1944 before any work with the insn declaration table. */
1946 initiate_insn_decl_table (void)
1948 work_insn_decl
.mode
= dm_insn_reserv
;
1949 insn_decl_table
= htab_create (10, insn_decl_hash
, insn_decl_eq_p
,
1953 /* The function deletes the insn declaration table. Only call of
1954 function `initiate_insn_decl_table' is possible immediately after
1955 this function call. */
1957 finish_insn_decl_table (void)
1959 htab_delete (insn_decl_table
);
1964 /* This page contains abstract data `table of declarations'. Elements
1965 of the table is nodes representing declarations (of units and
1966 reservations). Key of the table elements is names of given
1969 /* The function evaluates hash value of a declaration. The function
1970 is used by abstract data `hashtab'. The function returns hash
1971 value (0..UINT_MAX) of given declaration. */
1973 decl_hash (const void *decl
)
1975 const_decl_t
const d
= (const_decl_t
) decl
;
1977 gcc_assert ((d
->mode
== dm_unit
&& DECL_UNIT (d
)->name
)
1978 || (d
->mode
== dm_reserv
&& DECL_RESERV (d
)->name
));
1979 return string_hash (d
->mode
== dm_unit
1980 ? DECL_UNIT (d
)->name
: DECL_RESERV (d
)->name
);
1983 /* The function tests declarations on equality of their keys. The
1984 function is used by abstract data 'hashtab'. The function
1985 returns 1 if the declarations have the same key, 0 otherwise. */
1987 decl_eq_p (const void *decl_1
, const void *decl_2
)
1989 const_decl_t
const d1
= (const_decl_t
) decl_1
;
1990 const_decl_t
const d2
= (const_decl_t
) decl_2
;
1992 gcc_assert ((d1
->mode
== dm_unit
&& DECL_UNIT (d1
)->name
)
1993 || (d1
->mode
== dm_reserv
&& DECL_RESERV (d1
)->name
));
1994 gcc_assert ((d2
->mode
== dm_unit
&& DECL_UNIT (d2
)->name
)
1995 || (d2
->mode
== dm_reserv
&& DECL_RESERV (d2
)->name
));
1996 return strcmp ((d1
->mode
== dm_unit
1997 ? DECL_UNIT (d1
)->name
: DECL_RESERV (d1
)->name
),
1998 (d2
->mode
== dm_unit
1999 ? DECL_UNIT (d2
)->name
: DECL_RESERV (d2
)->name
)) == 0;
2002 /* The declaration table itself is represented by the following
2004 static htab_t decl_table
;
2006 /* The function inserts declaration into the table. The function does
2007 nothing if a declaration with the same key exists already in the
2008 table. The function returns declaration node in the table with the
2009 same key as given declaration node. */
2012 insert_decl (decl_t decl
)
2016 entry_ptr
= htab_find_slot (decl_table
, decl
, INSERT
);
2017 if (*entry_ptr
== NULL
)
2018 *entry_ptr
= (void *) decl
;
2019 return (decl_t
) *entry_ptr
;
2022 /* The following variable value is node representing declaration. The
2023 node used for searching declaration with given name. */
2024 static struct decl work_decl
;
2026 /* The function searches for declaration in the table with the same
2027 key as node representing name of the declaration. The function
2028 returns node found in the table, NULL if such node does not exist
2031 find_decl (const char *name
)
2035 work_decl
.mode
= dm_unit
;
2036 DECL_UNIT (&work_decl
)->name
= name
;
2037 entry
= htab_find (decl_table
, &work_decl
);
2038 return (decl_t
) entry
;
2041 /* The function creates empty declaration table and node representing
2042 declaration and used for searching declaration with given name.
2043 The function must be called only once before any work with the
2044 declaration table. */
2046 initiate_decl_table (void)
2048 work_decl
.mode
= dm_unit
;
2049 decl_table
= htab_create (10, decl_hash
, decl_eq_p
, (htab_del
) 0);
2052 /* The function deletes the declaration table. Only call of function
2053 `initiate_declaration_table' is possible immediately after this
2056 finish_decl_table (void)
2058 htab_delete (decl_table
);
2063 /* This page contains checker of pipeline hazard description. */
2065 /* Checking NAMES in an exclusion clause vector and returning formed
2066 unit_set_el_list. */
2067 static unit_set_el_t
2068 process_excls (char **names
, int num
, pos_t excl_pos ATTRIBUTE_UNUSED
)
2070 unit_set_el_t el_list
;
2071 unit_set_el_t last_el
;
2072 unit_set_el_t new_el
;
2073 decl_t decl_in_table
;
2078 for (i
= 0; i
< num
; i
++)
2080 decl_in_table
= find_decl (names
[i
]);
2081 if (decl_in_table
== NULL
)
2082 error ("unit `%s' in exclusion is not declared", names
[i
]);
2083 else if (decl_in_table
->mode
!= dm_unit
)
2084 error ("`%s' in exclusion is not unit", names
[i
]);
2087 new_el
= XCREATENODE (struct unit_set_el
);
2088 new_el
->unit_decl
= DECL_UNIT (decl_in_table
);
2089 new_el
->next_unit_set_el
= NULL
;
2090 if (last_el
== NULL
)
2091 el_list
= last_el
= new_el
;
2094 last_el
->next_unit_set_el
= new_el
;
2095 last_el
= last_el
->next_unit_set_el
;
2102 /* The function adds each element from SOURCE_LIST to the exclusion
2103 list of the each element from DEST_LIST. Checking situation "unit
2104 excludes itself". */
2106 add_excls (unit_set_el_t dest_list
, unit_set_el_t source_list
,
2107 pos_t excl_pos ATTRIBUTE_UNUSED
)
2111 unit_set_el_t curr_el
;
2112 unit_set_el_t prev_el
;
2115 for (dst
= dest_list
; dst
!= NULL
; dst
= dst
->next_unit_set_el
)
2116 for (src
= source_list
; src
!= NULL
; src
= src
->next_unit_set_el
)
2118 if (dst
->unit_decl
== src
->unit_decl
)
2120 error ("unit `%s' excludes itself", src
->unit_decl
->name
);
2123 if (dst
->unit_decl
->automaton_name
!= NULL
2124 && src
->unit_decl
->automaton_name
!= NULL
2125 && strcmp (dst
->unit_decl
->automaton_name
,
2126 src
->unit_decl
->automaton_name
) != 0)
2128 error ("units `%s' and `%s' in exclusion set belong to different automata",
2129 src
->unit_decl
->name
, dst
->unit_decl
->name
);
2132 for (curr_el
= dst
->unit_decl
->excl_list
, prev_el
= NULL
;
2134 prev_el
= curr_el
, curr_el
= curr_el
->next_unit_set_el
)
2135 if (curr_el
->unit_decl
== src
->unit_decl
)
2137 if (curr_el
== NULL
)
2139 /* Element not found - insert. */
2140 copy
= XCOPYNODE (struct unit_set_el
, src
);
2141 copy
->next_unit_set_el
= NULL
;
2142 if (prev_el
== NULL
)
2143 dst
->unit_decl
->excl_list
= copy
;
2145 prev_el
->next_unit_set_el
= copy
;
2150 /* Checking NAMES in presence/absence clause and returning the
2151 formed unit_set_el_list. The function is called only after
2152 processing all exclusion sets. */
2153 static unit_set_el_t
2154 process_presence_absence_names (char **names
, int num
,
2155 pos_t req_pos ATTRIBUTE_UNUSED
,
2156 int presence_p
, int final_p
)
2158 unit_set_el_t el_list
;
2159 unit_set_el_t last_el
;
2160 unit_set_el_t new_el
;
2161 decl_t decl_in_table
;
2166 for (i
= 0; i
< num
; i
++)
2168 decl_in_table
= find_decl (names
[i
]);
2169 if (decl_in_table
== NULL
)
2172 ? "unit `%s' in final presence set is not declared"
2173 : "unit `%s' in presence set is not declared")
2175 ? "unit `%s' in final absence set is not declared"
2176 : "unit `%s' in absence set is not declared")), names
[i
]);
2177 else if (decl_in_table
->mode
!= dm_unit
)
2180 ? "`%s' in final presence set is not unit"
2181 : "`%s' in presence set is not unit")
2183 ? "`%s' in final absence set is not unit"
2184 : "`%s' in absence set is not unit")), names
[i
]);
2187 new_el
= XCREATENODE (struct unit_set_el
);
2188 new_el
->unit_decl
= DECL_UNIT (decl_in_table
);
2189 new_el
->next_unit_set_el
= NULL
;
2190 if (last_el
== NULL
)
2191 el_list
= last_el
= new_el
;
2194 last_el
->next_unit_set_el
= new_el
;
2195 last_el
= last_el
->next_unit_set_el
;
2202 /* Checking NAMES in patterns of a presence/absence clause and
2203 returning the formed pattern_set_el_list. The function is called
2204 only after processing all exclusion sets. */
2205 static pattern_set_el_t
2206 process_presence_absence_patterns (char ***patterns
, int num
,
2207 pos_t req_pos ATTRIBUTE_UNUSED
,
2208 int presence_p
, int final_p
)
2210 pattern_set_el_t el_list
;
2211 pattern_set_el_t last_el
;
2212 pattern_set_el_t new_el
;
2213 decl_t decl_in_table
;
2218 for (i
= 0; i
< num
; i
++)
2220 for (j
= 0; patterns
[i
] [j
] != NULL
; j
++)
2222 new_el
= XCREATENODEVAR (struct pattern_set_el
,
2223 sizeof (struct pattern_set_el
)
2224 + sizeof (struct unit_decl
*) * j
);
2226 = (struct unit_decl
**) ((char *) new_el
2227 + sizeof (struct pattern_set_el
));
2228 new_el
->next_pattern_set_el
= NULL
;
2229 if (last_el
== NULL
)
2230 el_list
= last_el
= new_el
;
2233 last_el
->next_pattern_set_el
= new_el
;
2234 last_el
= last_el
->next_pattern_set_el
;
2236 new_el
->units_num
= 0;
2237 for (j
= 0; patterns
[i
] [j
] != NULL
; j
++)
2239 decl_in_table
= find_decl (patterns
[i
] [j
]);
2240 if (decl_in_table
== NULL
)
2243 ? "unit `%s' in final presence set is not declared"
2244 : "unit `%s' in presence set is not declared")
2246 ? "unit `%s' in final absence set is not declared"
2247 : "unit `%s' in absence set is not declared")),
2249 else if (decl_in_table
->mode
!= dm_unit
)
2252 ? "`%s' in final presence set is not unit"
2253 : "`%s' in presence set is not unit")
2255 ? "`%s' in final absence set is not unit"
2256 : "`%s' in absence set is not unit")),
2260 new_el
->unit_decls
[new_el
->units_num
]
2261 = DECL_UNIT (decl_in_table
);
2262 new_el
->units_num
++;
2269 /* The function adds each element from PATTERN_LIST to presence (if
2270 PRESENCE_P) or absence list of the each element from DEST_LIST.
2271 Checking situations "unit requires own absence", and "unit excludes
2272 and requires presence of ...", "unit requires absence and presence
2273 of ...", "units in (final) presence set belong to different
2274 automata", and "units in (final) absence set belong to different
2275 automata". Remember that we process absence sets only after all
2278 add_presence_absence (unit_set_el_t dest_list
,
2279 pattern_set_el_t pattern_list
,
2280 pos_t req_pos ATTRIBUTE_UNUSED
,
2281 int presence_p
, int final_p
)
2284 pattern_set_el_t pat
;
2285 struct unit_decl
*unit
;
2286 unit_set_el_t curr_excl_el
;
2287 pattern_set_el_t curr_pat_el
;
2288 pattern_set_el_t prev_el
;
2289 pattern_set_el_t copy
;
2293 for (dst
= dest_list
; dst
!= NULL
; dst
= dst
->next_unit_set_el
)
2294 for (pat
= pattern_list
; pat
!= NULL
; pat
= pat
->next_pattern_set_el
)
2296 for (i
= 0; i
< pat
->units_num
; i
++)
2298 unit
= pat
->unit_decls
[i
];
2299 if (dst
->unit_decl
== unit
&& pat
->units_num
== 1 && !presence_p
)
2301 error ("unit `%s' requires own absence", unit
->name
);
2304 if (dst
->unit_decl
->automaton_name
!= NULL
2305 && unit
->automaton_name
!= NULL
2306 && strcmp (dst
->unit_decl
->automaton_name
,
2307 unit
->automaton_name
) != 0)
2311 ? "units `%s' and `%s' in final presence set belong to different automata"
2312 : "units `%s' and `%s' in presence set belong to different automata")
2314 ? "units `%s' and `%s' in final absence set belong to different automata"
2315 : "units `%s' and `%s' in absence set belong to different automata")),
2316 unit
->name
, dst
->unit_decl
->name
);
2321 for (curr_excl_el
= dst
->unit_decl
->excl_list
;
2322 curr_excl_el
!= NULL
;
2323 curr_excl_el
= curr_excl_el
->next_unit_set_el
)
2325 if (unit
== curr_excl_el
->unit_decl
&& pat
->units_num
== 1)
2329 error ("unit `%s' excludes and requires presence of `%s'",
2330 dst
->unit_decl
->name
, unit
->name
);
2334 warning ("unit `%s' excludes and requires presence of `%s'",
2335 dst
->unit_decl
->name
, unit
->name
);
2338 else if (pat
->units_num
== 1)
2339 for (curr_pat_el
= dst
->unit_decl
->presence_list
;
2340 curr_pat_el
!= NULL
;
2341 curr_pat_el
= curr_pat_el
->next_pattern_set_el
)
2342 if (curr_pat_el
->units_num
== 1
2343 && unit
== curr_pat_el
->unit_decls
[0])
2347 error ("unit `%s' requires absence and presence of `%s'",
2348 dst
->unit_decl
->name
, unit
->name
);
2352 warning ("unit `%s' requires absence and presence of `%s'",
2353 dst
->unit_decl
->name
, unit
->name
);
2357 for (prev_el
= (presence_p
2359 ? dst
->unit_decl
->final_presence_list
2360 : dst
->unit_decl
->final_presence_list
)
2362 ? dst
->unit_decl
->final_absence_list
2363 : dst
->unit_decl
->absence_list
));
2364 prev_el
!= NULL
&& prev_el
->next_pattern_set_el
!= NULL
;
2365 prev_el
= prev_el
->next_pattern_set_el
)
2367 copy
= XCOPYNODE (struct pattern_set_el
, pat
);
2368 copy
->next_pattern_set_el
= NULL
;
2369 if (prev_el
== NULL
)
2374 dst
->unit_decl
->final_presence_list
= copy
;
2376 dst
->unit_decl
->presence_list
= copy
;
2379 dst
->unit_decl
->final_absence_list
= copy
;
2381 dst
->unit_decl
->absence_list
= copy
;
2384 prev_el
->next_pattern_set_el
= copy
;
2391 /* The function inserts BYPASS in the list of bypasses of the
2392 corresponding output insn. The order of bypasses in the list is
2393 decribed in a comment for member `bypass_list' (see above). If
2394 there is already the same bypass in the list the function reports
2395 this and does nothing. */
2397 insert_bypass (struct bypass_decl
*bypass
)
2399 struct bypass_decl
*curr
, *last
;
2400 struct insn_reserv_decl
*out_insn_reserv
= bypass
->out_insn_reserv
;
2401 struct insn_reserv_decl
*in_insn_reserv
= bypass
->in_insn_reserv
;
2403 for (curr
= out_insn_reserv
->bypass_list
, last
= NULL
;
2405 last
= curr
, curr
= curr
->next
)
2406 if (curr
->in_insn_reserv
== in_insn_reserv
)
2408 if ((bypass
->bypass_guard_name
!= NULL
2409 && curr
->bypass_guard_name
!= NULL
2410 && ! strcmp (bypass
->bypass_guard_name
, curr
->bypass_guard_name
))
2411 || bypass
->bypass_guard_name
== curr
->bypass_guard_name
)
2413 if (bypass
->bypass_guard_name
== NULL
)
2416 error ("the same bypass `%s - %s' is already defined",
2417 bypass
->out_pattern
, bypass
->in_pattern
);
2419 warning ("the same bypass `%s - %s' is already defined",
2420 bypass
->out_pattern
, bypass
->in_pattern
);
2423 error ("the same bypass `%s - %s' (guard %s) is already defined",
2424 bypass
->out_pattern
, bypass
->in_pattern
,
2425 bypass
->bypass_guard_name
);
2428 ("the same bypass `%s - %s' (guard %s) is already defined",
2429 bypass
->out_pattern
, bypass
->in_pattern
,
2430 bypass
->bypass_guard_name
);
2433 if (curr
->bypass_guard_name
== NULL
)
2435 if (curr
->next
== NULL
|| curr
->next
->in_insn_reserv
!= in_insn_reserv
)
2444 bypass
->next
= out_insn_reserv
->bypass_list
;
2445 out_insn_reserv
->bypass_list
= bypass
;
2449 bypass
->next
= last
->next
;
2450 last
->next
= bypass
;
2454 /* BYPASS is a define_bypass decl that includes glob pattern PATTERN.
2455 Call FN (BYPASS, INSN, DATA) for each matching instruction INSN. */
2458 for_each_matching_insn (decl_t bypass
, const char *pattern
,
2459 void (*fn
) (decl_t
, decl_t
, void *), void *data
)
2466 if (strpbrk (pattern
, "*?["))
2467 for (i
= 0; i
< description
->decls_num
; i
++)
2469 insn_reserv
= description
->decls
[i
];
2470 if (insn_reserv
->mode
== dm_insn_reserv
2471 && fnmatch (pattern
, DECL_INSN_RESERV (insn_reserv
)->name
, 0) == 0)
2473 fn (bypass
, insn_reserv
, data
);
2479 insn_reserv
= find_insn_decl (pattern
);
2482 fn (bypass
, insn_reserv
, data
);
2487 error ("there is no insn reservation that matches `%s'", pattern
);
2490 /* A subroutine of process_bypass that is called for each pair
2491 of matching instructions. OUT_INSN_RESERV is the output
2492 instruction and DATA is the input instruction. */
2495 process_bypass_2 (decl_t model
, decl_t out_insn_reserv
, void *data
)
2497 struct bypass_decl
*bypass
;
2498 decl_t in_insn_reserv
;
2500 in_insn_reserv
= (decl_t
) data
;
2501 if (strcmp (DECL_INSN_RESERV (in_insn_reserv
)->name
,
2502 DECL_BYPASS (model
)->in_pattern
) == 0
2503 && strcmp (DECL_INSN_RESERV (out_insn_reserv
)->name
,
2504 DECL_BYPASS (model
)->out_pattern
) == 0)
2505 bypass
= DECL_BYPASS (model
);
2508 bypass
= XCNEW (struct bypass_decl
);
2509 bypass
->latency
= DECL_BYPASS (model
)->latency
;
2510 bypass
->out_pattern
= DECL_INSN_RESERV (out_insn_reserv
)->name
;
2511 bypass
->in_pattern
= DECL_INSN_RESERV (in_insn_reserv
)->name
;
2512 bypass
->bypass_guard_name
= DECL_BYPASS (model
)->bypass_guard_name
;
2514 bypass
->out_insn_reserv
= DECL_INSN_RESERV (out_insn_reserv
);
2515 bypass
->in_insn_reserv
= DECL_INSN_RESERV (in_insn_reserv
);
2516 insert_bypass (bypass
);
2519 /* A subroutine of process_bypass that is called for each input
2520 instruction IN_INSN_RESERV. */
2523 process_bypass_1 (decl_t bypass
, decl_t in_insn_reserv
,
2524 void *data ATTRIBUTE_UNUSED
)
2526 for_each_matching_insn (bypass
, DECL_BYPASS (bypass
)->out_pattern
,
2527 process_bypass_2
, in_insn_reserv
);
2530 /* Process define_bypass decl BYPASS, inserting a bypass for each specific
2531 pair of insn reservations. */
2534 process_bypass (decl_t bypass
)
2536 for_each_matching_insn (bypass
, DECL_BYPASS (bypass
)->in_pattern
,
2537 process_bypass_1
, NULL
);
2540 /* The function processes pipeline description declarations, checks
2541 their correctness, and forms exclusion/presence/absence sets. */
2543 process_decls (void)
2546 decl_t automaton_decl
;
2547 decl_t decl_in_table
;
2548 int automaton_presence
;
2551 /* Checking repeated automata declarations. */
2552 automaton_presence
= 0;
2553 for (i
= 0; i
< description
->decls_num
; i
++)
2555 decl
= description
->decls
[i
];
2556 if (decl
->mode
== dm_automaton
)
2558 automaton_presence
= 1;
2559 decl_in_table
= insert_automaton_decl (decl
);
2560 if (decl_in_table
!= decl
)
2563 error ("repeated declaration of automaton `%s'",
2564 DECL_AUTOMATON (decl
)->name
);
2566 warning ("repeated declaration of automaton `%s'",
2567 DECL_AUTOMATON (decl
)->name
);
2571 /* Checking undeclared automata, repeated declarations (except for
2572 automata) and correctness of their attributes (insn latency times
2574 for (i
= 0; i
< description
->decls_num
; i
++)
2576 decl
= description
->decls
[i
];
2577 if (decl
->mode
== dm_insn_reserv
)
2579 if (DECL_INSN_RESERV (decl
)->default_latency
< 0)
2580 error ("define_insn_reservation `%s' has negative latency time",
2581 DECL_INSN_RESERV (decl
)->name
);
2582 DECL_INSN_RESERV (decl
)->insn_num
= description
->insns_num
;
2583 description
->insns_num
++;
2584 decl_in_table
= insert_insn_decl (decl
);
2585 if (decl_in_table
!= decl
)
2586 error ("`%s' is already used as insn reservation name",
2587 DECL_INSN_RESERV (decl
)->name
);
2589 else if (decl
->mode
== dm_bypass
)
2591 if (DECL_BYPASS (decl
)->latency
< 0)
2592 error ("define_bypass `%s - %s' has negative latency time",
2593 DECL_BYPASS (decl
)->out_pattern
,
2594 DECL_BYPASS (decl
)->in_pattern
);
2596 else if (decl
->mode
== dm_unit
|| decl
->mode
== dm_reserv
)
2598 if (decl
->mode
== dm_unit
)
2600 DECL_UNIT (decl
)->automaton_decl
= NULL
;
2601 if (DECL_UNIT (decl
)->automaton_name
!= NULL
)
2604 = find_automaton_decl (DECL_UNIT (decl
)->automaton_name
);
2605 if (automaton_decl
== NULL
)
2606 error ("automaton `%s' is not declared",
2607 DECL_UNIT (decl
)->automaton_name
);
2610 DECL_AUTOMATON (automaton_decl
)->automaton_is_used
= 1;
2611 DECL_UNIT (decl
)->automaton_decl
2612 = DECL_AUTOMATON (automaton_decl
);
2615 else if (automaton_presence
)
2616 error ("define_unit `%s' without automaton when one defined",
2617 DECL_UNIT (decl
)->name
);
2618 DECL_UNIT (decl
)->unit_num
= description
->units_num
;
2619 description
->units_num
++;
2620 if (strcmp (DECL_UNIT (decl
)->name
, NOTHING_NAME
) == 0)
2622 error ("`%s' is declared as cpu unit", NOTHING_NAME
);
2625 decl_in_table
= find_decl (DECL_UNIT (decl
)->name
);
2629 if (strcmp (DECL_RESERV (decl
)->name
, NOTHING_NAME
) == 0)
2631 error ("`%s' is declared as cpu reservation", NOTHING_NAME
);
2634 decl_in_table
= find_decl (DECL_RESERV (decl
)->name
);
2636 if (decl_in_table
== NULL
)
2637 decl_in_table
= insert_decl (decl
);
2640 if (decl
->mode
== dm_unit
)
2641 error ("repeated declaration of unit `%s'",
2642 DECL_UNIT (decl
)->name
);
2644 error ("repeated declaration of reservation `%s'",
2645 DECL_RESERV (decl
)->name
);
2649 /* Check bypasses and form list of bypasses for each (output)
2651 for (i
= 0; i
< description
->decls_num
; i
++)
2653 decl
= description
->decls
[i
];
2654 if (decl
->mode
== dm_bypass
)
2655 process_bypass (decl
);
2658 /* Check exclusion set declarations and form exclusion sets. */
2659 for (i
= 0; i
< description
->decls_num
; i
++)
2661 decl
= description
->decls
[i
];
2662 if (decl
->mode
== dm_excl
)
2664 unit_set_el_t unit_set_el_list
;
2665 unit_set_el_t unit_set_el_list_2
;
2668 = process_excls (DECL_EXCL (decl
)->names
,
2669 DECL_EXCL (decl
)->first_list_length
, decl
->pos
);
2671 = process_excls (&DECL_EXCL (decl
)->names
2672 [DECL_EXCL (decl
)->first_list_length
],
2673 DECL_EXCL (decl
)->all_names_num
2674 - DECL_EXCL (decl
)->first_list_length
,
2676 add_excls (unit_set_el_list
, unit_set_el_list_2
, decl
->pos
);
2677 add_excls (unit_set_el_list_2
, unit_set_el_list
, decl
->pos
);
2681 /* Check presence set declarations and form presence sets. */
2682 for (i
= 0; i
< description
->decls_num
; i
++)
2684 decl
= description
->decls
[i
];
2685 if (decl
->mode
== dm_presence
)
2687 unit_set_el_t unit_set_el_list
;
2688 pattern_set_el_t pattern_set_el_list
;
2691 = process_presence_absence_names
2692 (DECL_PRESENCE (decl
)->names
, DECL_PRESENCE (decl
)->names_num
,
2693 decl
->pos
, TRUE
, DECL_PRESENCE (decl
)->final_p
);
2695 = process_presence_absence_patterns
2696 (DECL_PRESENCE (decl
)->patterns
,
2697 DECL_PRESENCE (decl
)->patterns_num
,
2698 decl
->pos
, TRUE
, DECL_PRESENCE (decl
)->final_p
);
2699 add_presence_absence (unit_set_el_list
, pattern_set_el_list
,
2701 DECL_PRESENCE (decl
)->final_p
);
2705 /* Check absence set declarations and form absence sets. */
2706 for (i
= 0; i
< description
->decls_num
; i
++)
2708 decl
= description
->decls
[i
];
2709 if (decl
->mode
== dm_absence
)
2711 unit_set_el_t unit_set_el_list
;
2712 pattern_set_el_t pattern_set_el_list
;
2715 = process_presence_absence_names
2716 (DECL_ABSENCE (decl
)->names
, DECL_ABSENCE (decl
)->names_num
,
2717 decl
->pos
, FALSE
, DECL_ABSENCE (decl
)->final_p
);
2719 = process_presence_absence_patterns
2720 (DECL_ABSENCE (decl
)->patterns
,
2721 DECL_ABSENCE (decl
)->patterns_num
,
2722 decl
->pos
, FALSE
, DECL_ABSENCE (decl
)->final_p
);
2723 add_presence_absence (unit_set_el_list
, pattern_set_el_list
,
2725 DECL_ABSENCE (decl
)->final_p
);
2730 /* The following function checks that declared automaton is used. If
2731 the automaton is not used, the function fixes error/warning. The
2732 following function must be called only after `process_decls'. */
2734 check_automaton_usage (void)
2739 for (i
= 0; i
< description
->decls_num
; i
++)
2741 decl
= description
->decls
[i
];
2742 if (decl
->mode
== dm_automaton
2743 && !DECL_AUTOMATON (decl
)->automaton_is_used
)
2746 error ("automaton `%s' is not used", DECL_AUTOMATON (decl
)->name
);
2748 warning ("automaton `%s' is not used",
2749 DECL_AUTOMATON (decl
)->name
);
2754 /* The following recursive function processes all regexp in order to
2755 fix usage of units or reservations and to fix errors of undeclared
2756 name. The function may change unit_regexp onto reserv_regexp.
2757 Remember that reserv_regexp does not exist before the function
2760 process_regexp (regexp_t regexp
)
2762 decl_t decl_in_table
;
2763 regexp_t new_regexp
;
2766 switch (regexp
->mode
)
2769 decl_in_table
= find_decl (REGEXP_UNIT (regexp
)->name
);
2770 if (decl_in_table
== NULL
)
2771 error ("undeclared unit or reservation `%s'",
2772 REGEXP_UNIT (regexp
)->name
);
2774 switch (decl_in_table
->mode
)
2777 DECL_UNIT (decl_in_table
)->unit_is_used
= 1;
2778 REGEXP_UNIT (regexp
)->unit_decl
= DECL_UNIT (decl_in_table
);
2782 DECL_RESERV (decl_in_table
)->reserv_is_used
= 1;
2783 new_regexp
= XCREATENODE (struct regexp
);
2784 new_regexp
->mode
= rm_reserv
;
2785 new_regexp
->pos
= regexp
->pos
;
2786 REGEXP_RESERV (new_regexp
)->name
= REGEXP_UNIT (regexp
)->name
;
2787 REGEXP_RESERV (new_regexp
)->reserv_decl
2788 = DECL_RESERV (decl_in_table
);
2789 regexp
= new_regexp
;
2797 for (i
= 0; i
<REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
2798 REGEXP_SEQUENCE (regexp
)->regexps
[i
]
2799 = process_regexp (REGEXP_SEQUENCE (regexp
)->regexps
[i
]);
2802 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
2803 REGEXP_ALLOF (regexp
)->regexps
[i
]
2804 = process_regexp (REGEXP_ALLOF (regexp
)->regexps
[i
]);
2807 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
2808 REGEXP_ONEOF (regexp
)->regexps
[i
]
2809 = process_regexp (REGEXP_ONEOF (regexp
)->regexps
[i
]);
2812 REGEXP_REPEAT (regexp
)->regexp
2813 = process_regexp (REGEXP_REPEAT (regexp
)->regexp
);
2823 /* The following function processes regexp of define_reservation and
2824 define_insn_reservation with the aid of function
2825 `process_regexp'. */
2827 process_regexp_decls (void)
2832 for (i
= 0; i
< description
->decls_num
; i
++)
2834 decl
= description
->decls
[i
];
2835 if (decl
->mode
== dm_reserv
)
2836 DECL_RESERV (decl
)->regexp
2837 = process_regexp (DECL_RESERV (decl
)->regexp
);
2838 else if (decl
->mode
== dm_insn_reserv
)
2839 DECL_INSN_RESERV (decl
)->regexp
2840 = process_regexp (DECL_INSN_RESERV (decl
)->regexp
);
2844 /* The following function checks that declared unit is used. If the
2845 unit is not used, the function fixes errors/warnings. The
2846 following function must be called only after `process_decls',
2847 `process_regexp_decls'. */
2854 for (i
= 0; i
< description
->decls_num
; i
++)
2856 decl
= description
->decls
[i
];
2857 if (decl
->mode
== dm_unit
&& !DECL_UNIT (decl
)->unit_is_used
)
2860 error ("unit `%s' is not used", DECL_UNIT (decl
)->name
);
2862 warning ("unit `%s' is not used", DECL_UNIT (decl
)->name
);
2864 else if (decl
->mode
== dm_reserv
&& !DECL_RESERV (decl
)->reserv_is_used
)
2867 error ("reservation `%s' is not used", DECL_RESERV (decl
)->name
);
2869 warning ("reservation `%s' is not used", DECL_RESERV (decl
)->name
);
2874 /* The following variable value is number of reservation being
2875 processed on loop recognition. */
2876 static int curr_loop_pass_num
;
2878 /* The following recursive function returns nonzero value if REGEXP
2879 contains given decl or reservations in given regexp refers for
2882 loop_in_regexp (regexp_t regexp
, decl_t start_decl
)
2888 switch (regexp
->mode
)
2894 if (start_decl
->mode
== dm_reserv
2895 && REGEXP_RESERV (regexp
)->reserv_decl
== DECL_RESERV (start_decl
))
2897 else if (REGEXP_RESERV (regexp
)->reserv_decl
->loop_pass_num
2898 == curr_loop_pass_num
)
2899 /* declaration has been processed. */
2903 REGEXP_RESERV (regexp
)->reserv_decl
->loop_pass_num
2904 = curr_loop_pass_num
;
2905 return loop_in_regexp (REGEXP_RESERV (regexp
)->reserv_decl
->regexp
,
2910 for (i
= 0; i
<REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
2911 if (loop_in_regexp (REGEXP_SEQUENCE (regexp
)->regexps
[i
], start_decl
))
2916 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
2917 if (loop_in_regexp (REGEXP_ALLOF (regexp
)->regexps
[i
], start_decl
))
2922 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
2923 if (loop_in_regexp (REGEXP_ONEOF (regexp
)->regexps
[i
], start_decl
))
2928 return loop_in_regexp (REGEXP_REPEAT (regexp
)->regexp
, start_decl
);
2938 /* The following function fixes errors "cycle in definition ...". The
2939 function uses function `loop_in_regexp' for that. */
2941 check_loops_in_regexps (void)
2946 for (i
= 0; i
< description
->decls_num
; i
++)
2948 decl
= description
->decls
[i
];
2949 if (decl
->mode
== dm_reserv
)
2950 DECL_RESERV (decl
)->loop_pass_num
= 0;
2952 for (i
= 0; i
< description
->decls_num
; i
++)
2954 decl
= description
->decls
[i
];
2955 curr_loop_pass_num
= i
;
2957 if (decl
->mode
== dm_reserv
)
2959 DECL_RESERV (decl
)->loop_pass_num
= curr_loop_pass_num
;
2960 if (loop_in_regexp (DECL_RESERV (decl
)->regexp
, decl
))
2962 gcc_assert (DECL_RESERV (decl
)->regexp
);
2963 error ("cycle in definition of reservation `%s'",
2964 DECL_RESERV (decl
)->name
);
2970 /* The function recursively processes IR of reservation and defines
2971 max and min cycle for reservation of unit. */
2973 process_regexp_cycles (regexp_t regexp
, int max_start_cycle
,
2974 int min_start_cycle
, int *max_finish_cycle
,
2975 int *min_finish_cycle
)
2979 switch (regexp
->mode
)
2982 if (REGEXP_UNIT (regexp
)->unit_decl
->max_occ_cycle_num
< max_start_cycle
)
2983 REGEXP_UNIT (regexp
)->unit_decl
->max_occ_cycle_num
= max_start_cycle
;
2984 if (REGEXP_UNIT (regexp
)->unit_decl
->min_occ_cycle_num
> min_start_cycle
2985 || REGEXP_UNIT (regexp
)->unit_decl
->min_occ_cycle_num
== -1)
2986 REGEXP_UNIT (regexp
)->unit_decl
->min_occ_cycle_num
= min_start_cycle
;
2987 *max_finish_cycle
= max_start_cycle
;
2988 *min_finish_cycle
= min_start_cycle
;
2992 process_regexp_cycles (REGEXP_RESERV (regexp
)->reserv_decl
->regexp
,
2993 max_start_cycle
, min_start_cycle
,
2994 max_finish_cycle
, min_finish_cycle
);
2998 for (i
= 0; i
< REGEXP_REPEAT (regexp
)->repeat_num
; i
++)
3000 process_regexp_cycles (REGEXP_REPEAT (regexp
)->regexp
,
3001 max_start_cycle
, min_start_cycle
,
3002 max_finish_cycle
, min_finish_cycle
);
3003 max_start_cycle
= *max_finish_cycle
+ 1;
3004 min_start_cycle
= *min_finish_cycle
+ 1;
3009 for (i
= 0; i
<REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
3011 process_regexp_cycles (REGEXP_SEQUENCE (regexp
)->regexps
[i
],
3012 max_start_cycle
, min_start_cycle
,
3013 max_finish_cycle
, min_finish_cycle
);
3014 max_start_cycle
= *max_finish_cycle
+ 1;
3015 min_start_cycle
= *min_finish_cycle
+ 1;
3024 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
3026 process_regexp_cycles (REGEXP_ALLOF (regexp
)->regexps
[i
],
3027 max_start_cycle
, min_start_cycle
,
3028 max_finish_cycle
, min_finish_cycle
);
3029 if (max_cycle
< *max_finish_cycle
)
3030 max_cycle
= *max_finish_cycle
;
3031 if (i
== 0 || min_cycle
> *min_finish_cycle
)
3032 min_cycle
= *min_finish_cycle
;
3034 *max_finish_cycle
= max_cycle
;
3035 *min_finish_cycle
= min_cycle
;
3044 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
3046 process_regexp_cycles (REGEXP_ONEOF (regexp
)->regexps
[i
],
3047 max_start_cycle
, min_start_cycle
,
3048 max_finish_cycle
, min_finish_cycle
);
3049 if (max_cycle
< *max_finish_cycle
)
3050 max_cycle
= *max_finish_cycle
;
3051 if (i
== 0 || min_cycle
> *min_finish_cycle
)
3052 min_cycle
= *min_finish_cycle
;
3054 *max_finish_cycle
= max_cycle
;
3055 *min_finish_cycle
= min_cycle
;
3060 *max_finish_cycle
= max_start_cycle
;
3061 *min_finish_cycle
= min_start_cycle
;
3069 /* The following function is called only for correct program. The
3070 function defines max reservation of insns in cycles. */
3072 evaluate_max_reserv_cycles (void)
3074 int max_insn_cycles_num
;
3075 int min_insn_cycles_num
;
3079 description
->max_insn_reserv_cycles
= 0;
3080 for (i
= 0; i
< description
->decls_num
; i
++)
3082 decl
= description
->decls
[i
];
3083 if (decl
->mode
== dm_insn_reserv
)
3085 process_regexp_cycles (DECL_INSN_RESERV (decl
)->regexp
, 0, 0,
3086 &max_insn_cycles_num
, &min_insn_cycles_num
);
3087 if (description
->max_insn_reserv_cycles
< max_insn_cycles_num
)
3088 description
->max_insn_reserv_cycles
= max_insn_cycles_num
;
3091 description
->max_insn_reserv_cycles
++;
3094 /* The following function calls functions for checking all
3097 check_all_description (void)
3100 check_automaton_usage ();
3101 process_regexp_decls ();
3103 check_loops_in_regexps ();
3105 evaluate_max_reserv_cycles ();
3110 /* The page contains abstract data `ticker'. This data is used to
3111 report time of different phases of building automata. It is
3112 possibly to write a description for which automata will be built
3113 during several minutes even on fast machine. */
3115 /* The following function creates ticker and makes it active. */
3117 create_ticker (void)
3121 ticker
.modified_creation_time
= get_run_time ();
3122 ticker
.incremented_off_time
= 0;
3126 /* The following function switches off given ticker. */
3128 ticker_off (ticker_t
*ticker
)
3130 if (ticker
->incremented_off_time
== 0)
3131 ticker
->incremented_off_time
= get_run_time () + 1;
3134 /* The following function switches on given ticker. */
3136 ticker_on (ticker_t
*ticker
)
3138 if (ticker
->incremented_off_time
!= 0)
3140 ticker
->modified_creation_time
3141 += get_run_time () - ticker
->incremented_off_time
+ 1;
3142 ticker
->incremented_off_time
= 0;
3146 /* The following function returns current time in milliseconds since
3147 the moment when given ticker was created. */
3149 active_time (ticker_t ticker
)
3151 if (ticker
.incremented_off_time
!= 0)
3152 return ticker
.incremented_off_time
- 1 - ticker
.modified_creation_time
;
3154 return get_run_time () - ticker
.modified_creation_time
;
3157 /* The following function returns string representation of active time
3158 of given ticker. The result is string representation of seconds
3159 with accuracy of 1/100 second. Only result of the last call of the
3160 function exists. Therefore the following code is not correct
3162 printf ("parser time: %s\ngeneration time: %s\n",
3163 active_time_string (parser_ticker),
3164 active_time_string (generation_ticker));
3166 Correct code has to be the following
3168 printf ("parser time: %s\n", active_time_string (parser_ticker));
3169 printf ("generation time: %s\n",
3170 active_time_string (generation_ticker));
3174 print_active_time (FILE *f
, ticker_t ticker
)
3178 msecs
= active_time (ticker
);
3179 fprintf (f
, "%d.%06d", msecs
/ 1000000, msecs
% 1000000);
3184 /* The following variable value is number of automaton which are
3185 really being created. This value is defined on the base of
3186 argument of option `-split'. If the variable has zero value the
3187 number of automata is defined by the constructions `%automaton'.
3188 This case occurs when option `-split' is absent or has zero
3189 argument. If constructions `define_automaton' is absent only one
3190 automaton is created. */
3191 static int automata_num
;
3193 /* The following variable values are times of
3194 o transformation of regular expressions
3195 o building NDFA (DFA if !ndfa_flag)
3196 o NDFA -> DFA (simply the same automaton if !ndfa_flag)
3198 o building insn equivalence classes
3201 static ticker_t transform_time
;
3202 static ticker_t NDFA_time
;
3203 static ticker_t NDFA_to_DFA_time
;
3204 static ticker_t minimize_time
;
3205 static ticker_t equiv_time
;
3206 static ticker_t automaton_generation_time
;
3207 static ticker_t output_time
;
3209 /* The following variable values are times of
3212 all pipeline hazard translator work */
3213 static ticker_t check_time
;
3214 static ticker_t generation_time
;
3215 static ticker_t all_time
;
3219 /* Pseudo insn decl which denotes advancing cycle. */
3220 static decl_t advance_cycle_insn_decl
;
3221 /* Pseudo insn decl which denotes collapsing the NDFA state. */
3222 static decl_t collapse_ndfa_insn_decl
;
3224 /* Create and record a decl for the special advance-cycle transition. */
3226 add_advance_cycle_insn_decl (void)
3228 advance_cycle_insn_decl
= XCREATENODE (struct decl
);
3229 advance_cycle_insn_decl
->mode
= dm_insn_reserv
;
3230 advance_cycle_insn_decl
->pos
= no_pos
;
3231 DECL_INSN_RESERV (advance_cycle_insn_decl
)->regexp
= NULL
;
3232 DECL_INSN_RESERV (advance_cycle_insn_decl
)->name
= "$advance_cycle";
3233 DECL_INSN_RESERV (advance_cycle_insn_decl
)->insn_num
3234 = description
->insns_num
;
3235 description
->decls
[description
->decls_num
] = advance_cycle_insn_decl
;
3236 description
->decls_num
++;
3237 description
->insns_num
++;
3240 /* Create and record a decl for the special collapse-NDFA transition. */
3242 add_collapse_ndfa_insn_decl (void)
3244 collapse_ndfa_insn_decl
= XCREATENODE (struct decl
);
3245 collapse_ndfa_insn_decl
->mode
= dm_insn_reserv
;
3246 collapse_ndfa_insn_decl
->pos
= no_pos
;
3247 DECL_INSN_RESERV (collapse_ndfa_insn_decl
)->regexp
= NULL
;
3248 DECL_INSN_RESERV (collapse_ndfa_insn_decl
)->name
= "$collapse_ndfa";
3249 DECL_INSN_RESERV (collapse_ndfa_insn_decl
)->insn_num
3250 = description
->insns_num
;
3251 description
->decls
[description
->decls_num
] = collapse_ndfa_insn_decl
;
3252 description
->decls_num
++;
3253 description
->insns_num
++;
3256 /* True if DECL is either of the two special decls we created. */
3258 special_decl_p (struct insn_reserv_decl
*decl
)
3260 return (decl
== DECL_INSN_RESERV (advance_cycle_insn_decl
)
3262 && decl
== DECL_INSN_RESERV (collapse_ndfa_insn_decl
)));
3266 /* Abstract data `alternative states' which represents
3267 nondeterministic nature of the description (see comments for
3268 structures alt_state and state). */
3270 /* List of free states. */
3271 static alt_state_t first_free_alt_state
;
3274 /* The following variables is maximal number of allocated nodes
3276 static int allocated_alt_states_num
= 0;
3279 /* The following function returns free node alt_state. It may be new
3280 allocated node or node freed earlier. */
3282 get_free_alt_state (void)
3286 if (first_free_alt_state
!= NULL
)
3288 result
= first_free_alt_state
;
3289 first_free_alt_state
= first_free_alt_state
->next_alt_state
;
3294 allocated_alt_states_num
++;
3296 result
= XCREATENODE (struct alt_state
);
3298 result
->state
= NULL
;
3299 result
->next_alt_state
= NULL
;
3300 result
->next_sorted_alt_state
= NULL
;
3304 /* The function frees node ALT_STATE. */
3306 free_alt_state (alt_state_t alt_state
)
3308 if (alt_state
== NULL
)
3310 alt_state
->next_alt_state
= first_free_alt_state
;
3311 first_free_alt_state
= alt_state
;
3314 /* The function frees list started with node ALT_STATE_LIST. */
3316 free_alt_states (alt_state_t alt_states_list
)
3318 alt_state_t curr_alt_state
;
3319 alt_state_t next_alt_state
;
3321 for (curr_alt_state
= alt_states_list
;
3322 curr_alt_state
!= NULL
;
3323 curr_alt_state
= next_alt_state
)
3325 next_alt_state
= curr_alt_state
->next_alt_state
;
3326 free_alt_state (curr_alt_state
);
3330 /* The function compares unique numbers of alt states. */
3332 alt_state_cmp (const void *alt_state_ptr_1
, const void *alt_state_ptr_2
)
3334 if ((*(const alt_state_t
*) alt_state_ptr_1
)->state
->unique_num
3335 == (*(const alt_state_t
*) alt_state_ptr_2
)->state
->unique_num
)
3337 else if ((*(const alt_state_t
*) alt_state_ptr_1
)->state
->unique_num
3338 < (*(const alt_state_t
*) alt_state_ptr_2
)->state
->unique_num
)
3344 /* The function sorts ALT_STATES_LIST and removes duplicated alt
3345 states from the list. The comparison key is alt state unique
3349 uniq_sort_alt_states (alt_state_t alt_states_list
)
3351 alt_state_t curr_alt_state
;
3352 VEC(alt_state_t
, heap
) *alt_states
;
3354 size_t prev_unique_state_ind
;
3357 if (alt_states_list
== 0)
3359 if (alt_states_list
->next_alt_state
== 0)
3360 return alt_states_list
;
3362 alt_states
= VEC_alloc (alt_state_t
, heap
, 150);
3363 for (curr_alt_state
= alt_states_list
;
3364 curr_alt_state
!= NULL
;
3365 curr_alt_state
= curr_alt_state
->next_alt_state
)
3366 VEC_safe_push (alt_state_t
, heap
, alt_states
, curr_alt_state
);
3368 VEC_qsort (alt_state_t
, alt_states
, alt_state_cmp
);
3370 prev_unique_state_ind
= 0;
3371 for (i
= 1; i
< VEC_length (alt_state_t
, alt_states
); i
++)
3372 if (VEC_index (alt_state_t
, alt_states
, prev_unique_state_ind
)->state
3373 != VEC_index (alt_state_t
, alt_states
, i
)->state
)
3375 prev_unique_state_ind
++;
3376 VEC_replace (alt_state_t
, alt_states
, prev_unique_state_ind
,
3377 VEC_index (alt_state_t
, alt_states
, i
));
3379 VEC_truncate (alt_state_t
, alt_states
, prev_unique_state_ind
+ 1);
3381 for (i
= 1; i
< VEC_length (alt_state_t
, alt_states
); i
++)
3382 VEC_index (alt_state_t
, alt_states
, i
-1)->next_sorted_alt_state
3383 = VEC_index (alt_state_t
, alt_states
, i
);
3384 VEC_last (alt_state_t
, alt_states
)->next_sorted_alt_state
= 0;
3386 result
= VEC_index (alt_state_t
, alt_states
, 0);
3388 VEC_free (alt_state_t
, heap
, alt_states
);
3392 /* The function checks equality of alt state lists. Remember that the
3393 lists must be already sorted by the previous function. */
3395 alt_states_eq (alt_state_t alt_states_1
, alt_state_t alt_states_2
)
3397 while (alt_states_1
!= NULL
&& alt_states_2
!= NULL
3398 && alt_state_cmp (&alt_states_1
, &alt_states_2
) == 0)
3400 alt_states_1
= alt_states_1
->next_sorted_alt_state
;
3401 alt_states_2
= alt_states_2
->next_sorted_alt_state
;
3403 return alt_states_1
== alt_states_2
;
3406 /* Initialization of the abstract data. */
3408 initiate_alt_states (void)
3410 first_free_alt_state
= NULL
;
3413 /* Finishing work with the abstract data. */
3415 finish_alt_states (void)
3421 /* The page contains macros for work with bits strings. We could use
3422 standard gcc bitmap or sbitmap but it would result in difficulties
3423 of building canadian cross. */
3425 /* Set bit number bitno in the bit string. The macro is not side
3427 #define SET_BIT(bitstring, bitno) \
3428 ((bitstring)[(bitno) / (sizeof (*(bitstring)) * CHAR_BIT)] |= \
3429 (HOST_WIDE_INT)1 << (bitno) % (sizeof (*(bitstring)) * CHAR_BIT))
3431 #define CLEAR_BIT(bitstring, bitno) \
3432 ((bitstring)[(bitno) / (sizeof (*(bitstring)) * CHAR_BIT)] &= \
3433 ~((HOST_WIDE_INT)1 << (bitno) % (sizeof (*(bitstring)) * CHAR_BIT)))
3435 /* Test if bit number bitno in the bitstring is set. The macro is not
3436 side effect proof. */
3437 #define TEST_BIT(bitstring, bitno) \
3438 ((bitstring)[(bitno) / (sizeof (*(bitstring)) * CHAR_BIT)] >> \
3439 (bitno) % (sizeof (*(bitstring)) * CHAR_BIT) & 1)
3443 /* This page contains abstract data `state'. */
3445 /* Maximal length of reservations in cycles (>= 1). */
3446 static int max_cycles_num
;
3448 /* Number of set elements (see type set_el_t) needed for
3449 representation of one cycle reservation. It is depended on units
3451 static int els_in_cycle_reserv
;
3453 /* Number of set elements (see type set_el_t) needed for
3454 representation of maximal length reservation. Deterministic
3455 reservation is stored as set (bit string) of length equal to the
3456 variable value * number of bits in set_el_t. */
3457 static int els_in_reservs
;
3459 /* Array of pointers to unit declarations. */
3460 static unit_decl_t
*units_array
;
3462 /* Temporary reservation of maximal length. */
3463 static reserv_sets_t temp_reserv
;
3465 /* The state table itself is represented by the following variable. */
3466 static htab_t state_table
;
3468 /* Linked list of free 'state' structures to be recycled. The
3469 next_equiv_class_state pointer is borrowed for a free list. */
3470 static state_t first_free_state
;
3472 static int curr_unique_state_num
;
3475 /* The following variables is maximal number of allocated nodes
3477 static int allocated_states_num
= 0;
3480 /* Allocate new reservation set. */
3481 static reserv_sets_t
3482 alloc_empty_reserv_sets (void)
3484 reserv_sets_t result
;
3486 obstack_blank (&irp
, els_in_reservs
* sizeof (set_el_t
));
3487 result
= (reserv_sets_t
) obstack_base (&irp
);
3488 obstack_finish (&irp
);
3489 memset (result
, 0, els_in_reservs
* sizeof (set_el_t
));
3493 /* Hash value of reservation set. */
3495 reserv_sets_hash_value (reserv_sets_t reservs
)
3497 set_el_t hash_value
;
3500 set_el_t
*reserv_ptr
;
3503 reservs_num
= els_in_reservs
;
3504 reserv_ptr
= reservs
;
3506 while (reservs_num
!= 0)
3509 hash_value
+= ((*reserv_ptr
>> i
)
3510 | (*reserv_ptr
<< (sizeof (set_el_t
) * CHAR_BIT
- i
)));
3512 if (i
== sizeof (set_el_t
) * CHAR_BIT
)
3516 if (sizeof (set_el_t
) <= sizeof (unsigned))
3519 for (i
= sizeof (set_el_t
); i
> 0; i
-= sizeof (unsigned) - 1)
3521 result
+= (unsigned) hash_value
;
3522 hash_value
>>= (sizeof (unsigned) - 1) * CHAR_BIT
;
3527 /* Comparison of given reservation sets. */
3529 reserv_sets_cmp (const_reserv_sets_t reservs_1
, const_reserv_sets_t reservs_2
)
3532 const set_el_t
*reserv_ptr_1
;
3533 const set_el_t
*reserv_ptr_2
;
3535 gcc_assert (reservs_1
&& reservs_2
);
3536 reservs_num
= els_in_reservs
;
3537 reserv_ptr_1
= reservs_1
;
3538 reserv_ptr_2
= reservs_2
;
3539 while (reservs_num
!= 0 && *reserv_ptr_1
== *reserv_ptr_2
)
3545 if (reservs_num
== 0)
3547 else if (*reserv_ptr_1
< *reserv_ptr_2
)
3553 /* The function checks equality of the reservation sets. */
3555 reserv_sets_eq (const_reserv_sets_t reservs_1
, const_reserv_sets_t reservs_2
)
3557 return reserv_sets_cmp (reservs_1
, reservs_2
) == 0;
3560 /* Set up in the reservation set that unit with UNIT_NUM is used on
3563 set_unit_reserv (reserv_sets_t reservs
, int cycle_num
, int unit_num
)
3565 gcc_assert (cycle_num
< max_cycles_num
);
3566 SET_BIT (reservs
, cycle_num
* els_in_cycle_reserv
3567 * sizeof (set_el_t
) * CHAR_BIT
+ unit_num
);
3570 /* Set up in the reservation set RESERVS that unit with UNIT_NUM is
3571 used on CYCLE_NUM. */
3573 test_unit_reserv (reserv_sets_t reservs
, int cycle_num
, int unit_num
)
3575 gcc_assert (cycle_num
< max_cycles_num
);
3576 return TEST_BIT (reservs
, cycle_num
* els_in_cycle_reserv
3577 * sizeof (set_el_t
) * CHAR_BIT
+ unit_num
);
3580 /* The function checks that the reservation sets are intersected,
3581 i.e. there is a unit reservation on a cycle in both reservation
3584 reserv_sets_are_intersected (reserv_sets_t operand_1
,
3585 reserv_sets_t operand_2
)
3589 set_el_t
*cycle_ptr_1
;
3590 set_el_t
*cycle_ptr_2
;
3592 gcc_assert (operand_1
&& operand_2
);
3593 for (el_ptr_1
= operand_1
, el_ptr_2
= operand_2
;
3594 el_ptr_1
< operand_1
+ els_in_reservs
;
3595 el_ptr_1
++, el_ptr_2
++)
3596 if (*el_ptr_1
& *el_ptr_2
)
3598 reserv_sets_or (temp_reserv
, operand_1
, operand_2
);
3599 for (cycle_ptr_1
= operand_1
, cycle_ptr_2
= operand_2
;
3600 cycle_ptr_1
< operand_1
+ els_in_reservs
;
3601 cycle_ptr_1
+= els_in_cycle_reserv
, cycle_ptr_2
+= els_in_cycle_reserv
)
3603 for (el_ptr_1
= cycle_ptr_1
, el_ptr_2
= get_excl_set (cycle_ptr_2
);
3604 el_ptr_1
< cycle_ptr_1
+ els_in_cycle_reserv
;
3605 el_ptr_1
++, el_ptr_2
++)
3606 if (*el_ptr_1
& *el_ptr_2
)
3608 if (!check_presence_pattern_sets (cycle_ptr_1
, cycle_ptr_2
, FALSE
))
3610 if (!check_presence_pattern_sets (temp_reserv
+ (cycle_ptr_2
3614 if (!check_absence_pattern_sets (cycle_ptr_1
, cycle_ptr_2
, FALSE
))
3616 if (!check_absence_pattern_sets (temp_reserv
+ (cycle_ptr_2
- operand_2
),
3623 /* The function sets up RESULT bits by bits of OPERAND shifted on one
3624 cpu cycle. The remaining bits of OPERAND (representing the last
3625 cycle unit reservations) are not changed. */
3627 reserv_sets_shift (reserv_sets_t result
, reserv_sets_t operand
)
3631 gcc_assert (result
&& operand
&& result
!= operand
);
3632 for (i
= els_in_cycle_reserv
; i
< els_in_reservs
; i
++)
3633 result
[i
- els_in_cycle_reserv
] = operand
[i
];
3636 /* OR of the reservation sets. */
3638 reserv_sets_or (reserv_sets_t result
, reserv_sets_t operand_1
,
3639 reserv_sets_t operand_2
)
3643 set_el_t
*result_set_el_ptr
;
3645 gcc_assert (result
&& operand_1
&& operand_2
);
3646 for (el_ptr_1
= operand_1
, el_ptr_2
= operand_2
, result_set_el_ptr
= result
;
3647 el_ptr_1
< operand_1
+ els_in_reservs
;
3648 el_ptr_1
++, el_ptr_2
++, result_set_el_ptr
++)
3649 *result_set_el_ptr
= *el_ptr_1
| *el_ptr_2
;
3652 /* AND of the reservation sets. */
3654 reserv_sets_and (reserv_sets_t result
, reserv_sets_t operand_1
,
3655 reserv_sets_t operand_2
)
3659 set_el_t
*result_set_el_ptr
;
3661 gcc_assert (result
&& operand_1
&& operand_2
);
3662 for (el_ptr_1
= operand_1
, el_ptr_2
= operand_2
, result_set_el_ptr
= result
;
3663 el_ptr_1
< operand_1
+ els_in_reservs
;
3664 el_ptr_1
++, el_ptr_2
++, result_set_el_ptr
++)
3665 *result_set_el_ptr
= *el_ptr_1
& *el_ptr_2
;
3668 /* The function outputs string representation of units reservation on
3669 cycle START_CYCLE in the reservation set. The function uses repeat
3670 construction if REPETITION_NUM > 1. */
3672 output_cycle_reservs (FILE *f
, reserv_sets_t reservs
, int start_cycle
,
3676 int reserved_units_num
;
3678 reserved_units_num
= 0;
3679 for (unit_num
= 0; unit_num
< description
->units_num
; unit_num
++)
3680 if (TEST_BIT (reservs
, start_cycle
* els_in_cycle_reserv
3681 * sizeof (set_el_t
) * CHAR_BIT
+ unit_num
))
3682 reserved_units_num
++;
3683 gcc_assert (repetition_num
> 0);
3684 if (repetition_num
!= 1 && reserved_units_num
> 1)
3686 reserved_units_num
= 0;
3688 unit_num
< description
->units_num
;
3690 if (TEST_BIT (reservs
, start_cycle
* els_in_cycle_reserv
3691 * sizeof (set_el_t
) * CHAR_BIT
+ unit_num
))
3693 if (reserved_units_num
!= 0)
3695 reserved_units_num
++;
3696 fprintf (f
, "%s", units_array
[unit_num
]->name
);
3698 if (reserved_units_num
== 0)
3699 fprintf (f
, NOTHING_NAME
);
3700 gcc_assert (repetition_num
> 0);
3701 if (repetition_num
!= 1 && reserved_units_num
> 1)
3703 if (repetition_num
!= 1)
3704 fprintf (f
, "*%d", repetition_num
);
3707 /* The function outputs string representation of units reservation in
3708 the reservation set. */
3710 output_reserv_sets (FILE *f
, reserv_sets_t reservs
)
3712 int start_cycle
= 0;
3717 for (cycle
= 0; cycle
< max_cycles_num
; cycle
++)
3718 if (repetition_num
== 0)
3721 start_cycle
= cycle
;
3724 ((char *) reservs
+ start_cycle
* els_in_cycle_reserv
3725 * sizeof (set_el_t
),
3726 (char *) reservs
+ cycle
* els_in_cycle_reserv
3727 * sizeof (set_el_t
),
3728 els_in_cycle_reserv
* sizeof (set_el_t
)) == 0)
3732 if (start_cycle
!= 0)
3734 output_cycle_reservs (f
, reservs
, start_cycle
, repetition_num
);
3736 start_cycle
= cycle
;
3738 if (start_cycle
< max_cycles_num
)
3740 if (start_cycle
!= 0)
3742 output_cycle_reservs (f
, reservs
, start_cycle
, repetition_num
);
3746 /* The following function returns free node state for AUTOMATON. It
3747 may be new allocated node or node freed earlier. The function also
3748 allocates reservation set if WITH_RESERVS has nonzero value. */
3750 get_free_state (int with_reservs
, automaton_t automaton
)
3754 gcc_assert (max_cycles_num
> 0 && automaton
);
3755 if (first_free_state
)
3757 result
= first_free_state
;
3758 first_free_state
= result
->next_equiv_class_state
;
3760 result
->next_equiv_class_state
= NULL
;
3761 result
->automaton
= automaton
;
3762 result
->first_out_arc
= NULL
;
3763 result
->it_was_placed_in_stack_for_NDFA_forming
= 0;
3764 result
->it_was_placed_in_stack_for_DFA_forming
= 0;
3765 result
->component_states
= NULL
;
3770 allocated_states_num
++;
3772 result
= XCREATENODE (struct state
);
3773 result
->automaton
= automaton
;
3774 result
->first_out_arc
= NULL
;
3775 result
->unique_num
= curr_unique_state_num
;
3776 curr_unique_state_num
++;
3780 if (result
->reservs
== NULL
)
3781 result
->reservs
= alloc_empty_reserv_sets ();
3783 memset (result
->reservs
, 0, els_in_reservs
* sizeof (set_el_t
));
3788 /* The function frees node STATE. */
3790 free_state (state_t state
)
3792 free_alt_states (state
->component_states
);
3793 state
->next_equiv_class_state
= first_free_state
;
3794 first_free_state
= state
;
3797 /* Hash value of STATE. If STATE represents deterministic state it is
3798 simply hash value of the corresponding reservation set. Otherwise
3799 it is formed from hash values of the component deterministic
3800 states. One more key is order number of state automaton. */
3802 state_hash (const void *state
)
3804 unsigned int hash_value
;
3805 alt_state_t alt_state
;
3807 if (((const_state_t
) state
)->component_states
== NULL
)
3808 hash_value
= reserv_sets_hash_value (((const_state_t
) state
)->reservs
);
3812 for (alt_state
= ((const_state_t
) state
)->component_states
;
3814 alt_state
= alt_state
->next_sorted_alt_state
)
3815 hash_value
= (((hash_value
>> (sizeof (unsigned) - 1) * CHAR_BIT
)
3816 | (hash_value
<< CHAR_BIT
))
3817 + alt_state
->state
->unique_num
);
3819 hash_value
= (((hash_value
>> (sizeof (unsigned) - 1) * CHAR_BIT
)
3820 | (hash_value
<< CHAR_BIT
))
3821 + ((const_state_t
) state
)->automaton
->automaton_order_num
);
3825 /* Return nonzero value if the states are the same. */
3827 state_eq_p (const void *state_1
, const void *state_2
)
3829 alt_state_t alt_state_1
;
3830 alt_state_t alt_state_2
;
3832 if (((const_state_t
) state_1
)->automaton
!= ((const_state_t
) state_2
)->automaton
)
3834 else if (((const_state_t
) state_1
)->component_states
== NULL
3835 && ((const_state_t
) state_2
)->component_states
== NULL
)
3836 return reserv_sets_eq (((const_state_t
) state_1
)->reservs
,
3837 ((const_state_t
) state_2
)->reservs
);
3838 else if (((const_state_t
) state_1
)->component_states
!= NULL
3839 && ((const_state_t
) state_2
)->component_states
!= NULL
)
3841 for (alt_state_1
= ((const_state_t
) state_1
)->component_states
,
3842 alt_state_2
= ((const_state_t
) state_2
)->component_states
;
3843 alt_state_1
!= NULL
&& alt_state_2
!= NULL
;
3844 alt_state_1
= alt_state_1
->next_sorted_alt_state
,
3845 alt_state_2
= alt_state_2
->next_sorted_alt_state
)
3846 /* All state in the list must be already in the hash table.
3847 Also the lists must be sorted. */
3848 if (alt_state_1
->state
!= alt_state_2
->state
)
3850 return alt_state_1
== alt_state_2
;
3856 /* Insert STATE into the state table. */
3858 insert_state (state_t state
)
3862 entry_ptr
= htab_find_slot (state_table
, (void *) state
, INSERT
);
3863 if (*entry_ptr
== NULL
)
3864 *entry_ptr
= (void *) state
;
3865 return (state_t
) *entry_ptr
;
3868 /* Add reservation of unit with UNIT_NUM on cycle CYCLE_NUM to
3869 deterministic STATE. */
3871 set_state_reserv (state_t state
, int cycle_num
, int unit_num
)
3873 set_unit_reserv (state
->reservs
, cycle_num
, unit_num
);
3876 /* Return nonzero value if the deterministic states contains a
3877 reservation of the same cpu unit on the same cpu cycle. */
3879 intersected_state_reservs_p (state_t state1
, state_t state2
)
3881 gcc_assert (state1
->automaton
== state2
->automaton
);
3882 return reserv_sets_are_intersected (state1
->reservs
, state2
->reservs
);
3885 /* Return deterministic state (inserted into the table) which
3886 representing the automaton state which is union of reservations of
3887 the deterministic states masked by RESERVS. */
3889 states_union (state_t state1
, state_t state2
, reserv_sets_t reservs
)
3892 state_t state_in_table
;
3894 gcc_assert (state1
->automaton
== state2
->automaton
);
3895 result
= get_free_state (1, state1
->automaton
);
3896 reserv_sets_or (result
->reservs
, state1
->reservs
, state2
->reservs
);
3897 reserv_sets_and (result
->reservs
, result
->reservs
, reservs
);
3898 state_in_table
= insert_state (result
);
3899 if (result
!= state_in_table
)
3901 free_state (result
);
3902 result
= state_in_table
;
3907 /* Return deterministic state (inserted into the table) which
3908 represent the automaton state is obtained from deterministic STATE
3909 by advancing cpu cycle and masking by RESERVS. */
3911 state_shift (state_t state
, reserv_sets_t reservs
)
3914 state_t state_in_table
;
3916 result
= get_free_state (1, state
->automaton
);
3917 reserv_sets_shift (result
->reservs
, state
->reservs
);
3918 reserv_sets_and (result
->reservs
, result
->reservs
, reservs
);
3919 state_in_table
= insert_state (result
);
3920 if (result
!= state_in_table
)
3922 free_state (result
);
3923 result
= state_in_table
;
3928 /* Initialization of the abstract data. */
3930 initiate_states (void)
3935 if (description
->units_num
)
3936 units_array
= XNEWVEC (unit_decl_t
, description
->units_num
);
3940 for (i
= 0; i
< description
->decls_num
; i
++)
3942 decl
= description
->decls
[i
];
3943 if (decl
->mode
== dm_unit
)
3944 units_array
[DECL_UNIT (decl
)->unit_num
] = DECL_UNIT (decl
);
3946 max_cycles_num
= description
->max_insn_reserv_cycles
;
3948 = ((description
->units_num
+ sizeof (set_el_t
) * CHAR_BIT
- 1)
3949 / (sizeof (set_el_t
) * CHAR_BIT
));
3950 els_in_reservs
= els_in_cycle_reserv
* max_cycles_num
;
3951 curr_unique_state_num
= 0;
3952 initiate_alt_states ();
3953 state_table
= htab_create (1500, state_hash
, state_eq_p
, (htab_del
) 0);
3954 temp_reserv
= alloc_empty_reserv_sets ();
3957 /* Finishing work with the abstract data. */
3959 finish_states (void)
3963 htab_delete (state_table
);
3964 first_free_state
= NULL
;
3965 finish_alt_states ();
3970 /* Abstract data `arcs'. */
3972 /* List of free arcs. */
3973 static arc_t first_free_arc
;
3976 /* The following variables is maximal number of allocated nodes
3978 static int allocated_arcs_num
= 0;
3981 /* The function frees node ARC. */
3983 free_arc (arc_t arc
)
3985 arc
->next_out_arc
= first_free_arc
;
3986 first_free_arc
= arc
;
3989 /* The function removes and frees ARC staring from FROM_STATE. */
3991 remove_arc (state_t from_state
, arc_t arc
)
3997 for (prev_arc
= NULL
, curr_arc
= from_state
->first_out_arc
;
3999 prev_arc
= curr_arc
, curr_arc
= curr_arc
->next_out_arc
)
4000 if (curr_arc
== arc
)
4002 gcc_assert (curr_arc
);
4003 if (prev_arc
== NULL
)
4004 from_state
->first_out_arc
= arc
->next_out_arc
;
4006 prev_arc
->next_out_arc
= arc
->next_out_arc
;
4007 from_state
->num_out_arcs
--;
4011 /* The functions returns arc with given characteristics (or NULL if
4012 the arc does not exist). */
4014 find_arc (state_t from_state
, state_t to_state
, ainsn_t insn
)
4018 for (arc
= first_out_arc (from_state
); arc
!= NULL
; arc
= next_out_arc (arc
))
4019 if (arc
->insn
== insn
4020 && (arc
->to_state
== to_state
4022 /* Any arc is good enough for a collapse-ndfa transition. */
4023 && (insn
->insn_reserv_decl
4024 == DECL_INSN_RESERV (collapse_ndfa_insn_decl
)))))
4029 /* The function adds arc from FROM_STATE to TO_STATE marked by AINSN,
4030 unless such an arc already exists. */
4032 add_arc (state_t from_state
, state_t to_state
, ainsn_t ainsn
)
4036 new_arc
= find_arc (from_state
, to_state
, ainsn
);
4037 if (new_arc
!= NULL
)
4039 if (first_free_arc
== NULL
)
4042 allocated_arcs_num
++;
4044 new_arc
= XCREATENODE (struct arc
);
4045 new_arc
->to_state
= NULL
;
4046 new_arc
->insn
= NULL
;
4047 new_arc
->next_out_arc
= NULL
;
4051 new_arc
= first_free_arc
;
4052 first_free_arc
= first_free_arc
->next_out_arc
;
4054 new_arc
->to_state
= to_state
;
4055 new_arc
->insn
= ainsn
;
4056 ainsn
->arc_exists_p
= 1;
4057 new_arc
->next_out_arc
= from_state
->first_out_arc
;
4058 from_state
->first_out_arc
= new_arc
;
4059 from_state
->num_out_arcs
++;
4060 new_arc
->next_arc_marked_by_insn
= NULL
;
4063 /* The function returns the first arc starting from STATE. */
4065 first_out_arc (const_state_t state
)
4067 return state
->first_out_arc
;
4070 /* The function returns next out arc after ARC. */
4072 next_out_arc (arc_t arc
)
4074 return arc
->next_out_arc
;
4077 /* Initialization of the abstract data. */
4079 initiate_arcs (void)
4081 first_free_arc
= NULL
;
4084 /* Finishing work with the abstract data. */
4092 /* Abstract data `automata lists'. */
4094 /* List of free states. */
4095 static automata_list_el_t first_free_automata_list_el
;
4097 /* The list being formed. */
4098 static automata_list_el_t current_automata_list
;
4100 /* Hash table of automata lists. */
4101 static htab_t automata_list_table
;
4103 /* The following function returns free automata list el. It may be
4104 new allocated node or node freed earlier. */
4105 static automata_list_el_t
4106 get_free_automata_list_el (void)
4108 automata_list_el_t result
;
4110 if (first_free_automata_list_el
!= NULL
)
4112 result
= first_free_automata_list_el
;
4113 first_free_automata_list_el
4114 = first_free_automata_list_el
->next_automata_list_el
;
4117 result
= XCREATENODE (struct automata_list_el
);
4118 result
->automaton
= NULL
;
4119 result
->next_automata_list_el
= NULL
;
4123 /* The function frees node AUTOMATA_LIST_EL. */
4125 free_automata_list_el (automata_list_el_t automata_list_el
)
4127 if (automata_list_el
== NULL
)
4129 automata_list_el
->next_automata_list_el
= first_free_automata_list_el
;
4130 first_free_automata_list_el
= automata_list_el
;
4133 /* The function frees list AUTOMATA_LIST. */
4135 free_automata_list (automata_list_el_t automata_list
)
4137 automata_list_el_t curr_automata_list_el
;
4138 automata_list_el_t next_automata_list_el
;
4140 for (curr_automata_list_el
= automata_list
;
4141 curr_automata_list_el
!= NULL
;
4142 curr_automata_list_el
= next_automata_list_el
)
4144 next_automata_list_el
= curr_automata_list_el
->next_automata_list_el
;
4145 free_automata_list_el (curr_automata_list_el
);
4149 /* Hash value of AUTOMATA_LIST. */
4151 automata_list_hash (const void *automata_list
)
4153 unsigned int hash_value
;
4154 const_automata_list_el_t curr_automata_list_el
;
4157 for (curr_automata_list_el
= (const_automata_list_el_t
) automata_list
;
4158 curr_automata_list_el
!= NULL
;
4159 curr_automata_list_el
= curr_automata_list_el
->next_automata_list_el
)
4160 hash_value
= (((hash_value
>> (sizeof (unsigned) - 1) * CHAR_BIT
)
4161 | (hash_value
<< CHAR_BIT
))
4162 + curr_automata_list_el
->automaton
->automaton_order_num
);
4166 /* Return nonzero value if the automata_lists are the same. */
4168 automata_list_eq_p (const void *automata_list_1
, const void *automata_list_2
)
4170 const_automata_list_el_t automata_list_el_1
;
4171 const_automata_list_el_t automata_list_el_2
;
4173 for (automata_list_el_1
= (const_automata_list_el_t
) automata_list_1
,
4174 automata_list_el_2
= (const_automata_list_el_t
) automata_list_2
;
4175 automata_list_el_1
!= NULL
&& automata_list_el_2
!= NULL
;
4176 automata_list_el_1
= automata_list_el_1
->next_automata_list_el
,
4177 automata_list_el_2
= automata_list_el_2
->next_automata_list_el
)
4178 if (automata_list_el_1
->automaton
!= automata_list_el_2
->automaton
)
4180 return automata_list_el_1
== automata_list_el_2
;
4183 /* Initialization of the abstract data. */
4185 initiate_automata_lists (void)
4187 first_free_automata_list_el
= NULL
;
4188 automata_list_table
= htab_create (1500, automata_list_hash
,
4189 automata_list_eq_p
, (htab_del
) 0);
4192 /* The following function starts new automata list and makes it the
4195 automata_list_start (void)
4197 current_automata_list
= NULL
;
4200 /* The following function adds AUTOMATON to the current list. */
4202 automata_list_add (automaton_t automaton
)
4204 automata_list_el_t el
;
4206 el
= get_free_automata_list_el ();
4207 el
->automaton
= automaton
;
4208 el
->next_automata_list_el
= current_automata_list
;
4209 current_automata_list
= el
;
4212 /* The following function finishes forming the current list, inserts
4213 it into the table and returns it. */
4214 static automata_list_el_t
4215 automata_list_finish (void)
4219 if (current_automata_list
== NULL
)
4221 entry_ptr
= htab_find_slot (automata_list_table
,
4222 (void *) current_automata_list
, INSERT
);
4223 if (*entry_ptr
== NULL
)
4224 *entry_ptr
= (void *) current_automata_list
;
4226 free_automata_list (current_automata_list
);
4227 current_automata_list
= NULL
;
4228 return (automata_list_el_t
) *entry_ptr
;
4231 /* Finishing work with the abstract data. */
4233 finish_automata_lists (void)
4235 htab_delete (automata_list_table
);
4240 /* The page contains abstract data for work with exclusion sets (see
4241 exclusion_set in file rtl.def). */
4243 /* The following variable refers to an exclusion set returned by
4244 get_excl_set. This is bit string of length equal to cpu units
4245 number. If exclusion set for given unit contains 1 for a unit,
4246 then simultaneous reservation of the units is prohibited. */
4247 static reserv_sets_t excl_set
;
4249 /* The array contains exclusion sets for each unit. */
4250 static reserv_sets_t
*unit_excl_set_table
;
4252 /* The following function forms the array containing exclusion sets
4255 initiate_excl_sets (void)
4258 reserv_sets_t unit_excl_set
;
4262 obstack_blank (&irp
, els_in_cycle_reserv
* sizeof (set_el_t
));
4263 excl_set
= (reserv_sets_t
) obstack_base (&irp
);
4264 obstack_finish (&irp
);
4265 obstack_blank (&irp
, description
->units_num
* sizeof (reserv_sets_t
));
4266 unit_excl_set_table
= (reserv_sets_t
*) obstack_base (&irp
);
4267 obstack_finish (&irp
);
4268 /* Evaluate unit exclusion sets. */
4269 for (i
= 0; i
< description
->decls_num
; i
++)
4271 decl
= description
->decls
[i
];
4272 if (decl
->mode
== dm_unit
)
4274 obstack_blank (&irp
, els_in_cycle_reserv
* sizeof (set_el_t
));
4275 unit_excl_set
= (reserv_sets_t
) obstack_base (&irp
);
4276 obstack_finish (&irp
);
4277 memset (unit_excl_set
, 0, els_in_cycle_reserv
* sizeof (set_el_t
));
4278 for (el
= DECL_UNIT (decl
)->excl_list
;
4280 el
= el
->next_unit_set_el
)
4282 SET_BIT (unit_excl_set
, el
->unit_decl
->unit_num
);
4283 el
->unit_decl
->in_set_p
= TRUE
;
4285 unit_excl_set_table
[DECL_UNIT (decl
)->unit_num
] = unit_excl_set
;
4290 /* The function sets up and return EXCL_SET which is union of
4291 exclusion sets for each unit in IN_SET. */
4292 static reserv_sets_t
4293 get_excl_set (reserv_sets_t in_set
)
4300 memset (excl_set
, 0, els_in_cycle_reserv
* sizeof (set_el_t
));
4301 for (el
= 0; el
< els_in_cycle_reserv
; el
++)
4303 for (i
= 0; i
< CHAR_BIT
* sizeof (set_el_t
); i
++)
4304 if ((in_set
[el
] >> i
) & 1)
4306 start_unit_num
= el
* CHAR_BIT
* sizeof (set_el_t
) + i
;
4307 if (start_unit_num
>= description
->units_num
)
4309 for (unit_num
= 0; unit_num
< els_in_cycle_reserv
; unit_num
++)
4312 |= unit_excl_set_table
[start_unit_num
] [unit_num
];
4320 /* The page contains abstract data for work with presence/absence
4321 pattern sets (see presence_set/absence_set in file rtl.def). */
4323 /* The following arrays contain correspondingly presence, final
4324 presence, absence, and final absence patterns for each unit. */
4325 static pattern_reserv_t
*unit_presence_set_table
;
4326 static pattern_reserv_t
*unit_final_presence_set_table
;
4327 static pattern_reserv_t
*unit_absence_set_table
;
4328 static pattern_reserv_t
*unit_final_absence_set_table
;
4330 /* The following function forms list of reservation sets for given
4332 static pattern_reserv_t
4333 form_reserv_sets_list (pattern_set_el_t pattern_list
)
4335 pattern_set_el_t el
;
4336 pattern_reserv_t first
, curr
, prev
;
4339 prev
= first
= NULL
;
4340 for (el
= pattern_list
; el
!= NULL
; el
= el
->next_pattern_set_el
)
4342 curr
= XCREATENODE (struct pattern_reserv
);
4343 curr
->reserv
= alloc_empty_reserv_sets ();
4344 curr
->next_pattern_reserv
= NULL
;
4345 for (i
= 0; i
< el
->units_num
; i
++)
4347 SET_BIT (curr
->reserv
, el
->unit_decls
[i
]->unit_num
);
4348 el
->unit_decls
[i
]->in_set_p
= TRUE
;
4351 prev
->next_pattern_reserv
= curr
;
4359 /* The following function forms the array containing presence and
4360 absence pattern sets for each unit. */
4362 initiate_presence_absence_pattern_sets (void)
4367 obstack_blank (&irp
, description
->units_num
* sizeof (pattern_reserv_t
));
4368 unit_presence_set_table
= (pattern_reserv_t
*) obstack_base (&irp
);
4369 obstack_finish (&irp
);
4370 obstack_blank (&irp
, description
->units_num
* sizeof (pattern_reserv_t
));
4371 unit_final_presence_set_table
= (pattern_reserv_t
*) obstack_base (&irp
);
4372 obstack_finish (&irp
);
4373 obstack_blank (&irp
, description
->units_num
* sizeof (pattern_reserv_t
));
4374 unit_absence_set_table
= (pattern_reserv_t
*) obstack_base (&irp
);
4375 obstack_finish (&irp
);
4376 obstack_blank (&irp
, description
->units_num
* sizeof (pattern_reserv_t
));
4377 unit_final_absence_set_table
= (pattern_reserv_t
*) obstack_base (&irp
);
4378 obstack_finish (&irp
);
4379 /* Evaluate unit presence/absence sets. */
4380 for (i
= 0; i
< description
->decls_num
; i
++)
4382 decl
= description
->decls
[i
];
4383 if (decl
->mode
== dm_unit
)
4385 unit_presence_set_table
[DECL_UNIT (decl
)->unit_num
]
4386 = form_reserv_sets_list (DECL_UNIT (decl
)->presence_list
);
4387 unit_final_presence_set_table
[DECL_UNIT (decl
)->unit_num
]
4388 = form_reserv_sets_list (DECL_UNIT (decl
)->final_presence_list
);
4389 unit_absence_set_table
[DECL_UNIT (decl
)->unit_num
]
4390 = form_reserv_sets_list (DECL_UNIT (decl
)->absence_list
);
4391 unit_final_absence_set_table
[DECL_UNIT (decl
)->unit_num
]
4392 = form_reserv_sets_list (DECL_UNIT (decl
)->final_absence_list
);
4397 /* The function checks that CHECKED_SET satisfies all presence pattern
4398 sets for units in ORIGINAL_SET. The function returns TRUE if it
4401 check_presence_pattern_sets (reserv_sets_t checked_set
,
4402 reserv_sets_t original_set
,
4410 pattern_reserv_t pat_reserv
;
4412 for (el
= 0; el
< els_in_cycle_reserv
; el
++)
4413 if (original_set
[el
])
4414 for (i
= 0; i
< CHAR_BIT
* sizeof (set_el_t
); i
++)
4415 if ((original_set
[el
] >> i
) & 1)
4417 start_unit_num
= el
* CHAR_BIT
* sizeof (set_el_t
) + i
;
4418 if (start_unit_num
>= description
->units_num
)
4421 && unit_final_presence_set_table
[start_unit_num
] == NULL
)
4423 && unit_presence_set_table
[start_unit_num
] == NULL
))
4426 for (pat_reserv
= (final_p
4427 ? unit_final_presence_set_table
[start_unit_num
]
4428 : unit_presence_set_table
[start_unit_num
]);
4430 pat_reserv
= pat_reserv
->next_pattern_reserv
)
4432 for (unit_num
= 0; unit_num
< els_in_cycle_reserv
; unit_num
++)
4433 if ((checked_set
[unit_num
] & pat_reserv
->reserv
[unit_num
])
4434 != pat_reserv
->reserv
[unit_num
])
4436 presence_p
= presence_p
|| unit_num
>= els_in_cycle_reserv
;
4444 /* The function checks that CHECKED_SET satisfies all absence pattern
4445 sets for units in ORIGINAL_SET. The function returns TRUE if it
4448 check_absence_pattern_sets (reserv_sets_t checked_set
,
4449 reserv_sets_t original_set
,
4456 pattern_reserv_t pat_reserv
;
4458 for (el
= 0; el
< els_in_cycle_reserv
; el
++)
4459 if (original_set
[el
])
4460 for (i
= 0; i
< CHAR_BIT
* sizeof (set_el_t
); i
++)
4461 if ((original_set
[el
] >> i
) & 1)
4463 start_unit_num
= el
* CHAR_BIT
* sizeof (set_el_t
) + i
;
4464 if (start_unit_num
>= description
->units_num
)
4466 for (pat_reserv
= (final_p
4467 ? unit_final_absence_set_table
[start_unit_num
]
4468 : unit_absence_set_table
[start_unit_num
]);
4470 pat_reserv
= pat_reserv
->next_pattern_reserv
)
4472 for (unit_num
= 0; unit_num
< els_in_cycle_reserv
; unit_num
++)
4473 if ((checked_set
[unit_num
] & pat_reserv
->reserv
[unit_num
])
4474 != pat_reserv
->reserv
[unit_num
]
4475 && pat_reserv
->reserv
[unit_num
])
4477 if (unit_num
>= els_in_cycle_reserv
)
4486 /* This page contains code for transformation of original reservations
4487 described in .md file. The main goal of transformations is
4488 simplifying reservation and lifting up all `|' on the top of IR
4489 reservation representation. */
4492 /* The following function makes copy of IR representation of
4493 reservation. The function also substitutes all reservations
4494 defined by define_reservation by corresponding value during making
4497 copy_insn_regexp (regexp_t regexp
)
4502 switch (regexp
->mode
)
4505 result
= copy_insn_regexp (REGEXP_RESERV (regexp
)->reserv_decl
->regexp
);
4509 result
= XCOPYNODE (struct regexp
, regexp
);
4513 result
= XCOPYNODE (struct regexp
, regexp
);
4514 REGEXP_REPEAT (result
)->regexp
4515 = copy_insn_regexp (REGEXP_REPEAT (regexp
)->regexp
);
4519 result
= XCOPYNODEVAR (struct regexp
, regexp
,
4520 sizeof (struct regexp
) + sizeof (regexp_t
)
4521 * (REGEXP_SEQUENCE (regexp
)->regexps_num
- 1));
4522 for (i
= 0; i
<REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
4523 REGEXP_SEQUENCE (result
)->regexps
[i
]
4524 = copy_insn_regexp (REGEXP_SEQUENCE (regexp
)->regexps
[i
]);
4528 result
= XCOPYNODEVAR (struct regexp
, regexp
,
4529 sizeof (struct regexp
) + sizeof (regexp_t
)
4530 * (REGEXP_ALLOF (regexp
)->regexps_num
- 1));
4531 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
4532 REGEXP_ALLOF (result
)->regexps
[i
]
4533 = copy_insn_regexp (REGEXP_ALLOF (regexp
)->regexps
[i
]);
4537 result
= XCOPYNODEVAR (struct regexp
, regexp
,
4538 sizeof (struct regexp
) + sizeof (regexp_t
)
4539 * (REGEXP_ONEOF (regexp
)->regexps_num
- 1));
4540 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
4541 REGEXP_ONEOF (result
)->regexps
[i
]
4542 = copy_insn_regexp (REGEXP_ONEOF (regexp
)->regexps
[i
]);
4546 result
= XCOPYNODE (struct regexp
, regexp
);
4555 /* The following variable is set up 1 if a transformation has been
4557 static int regexp_transformed_p
;
4559 /* The function makes transformation
4562 transform_1 (regexp_t regexp
)
4569 if (regexp
->mode
== rm_repeat
)
4571 repeat_num
= REGEXP_REPEAT (regexp
)->repeat_num
;
4572 gcc_assert (repeat_num
> 1);
4573 operand
= REGEXP_REPEAT (regexp
)->regexp
;
4575 regexp
= XCREATENODEVAR (struct regexp
, sizeof (struct regexp
)
4576 + sizeof (regexp_t
) * (repeat_num
- 1));
4577 regexp
->mode
= rm_sequence
;
4579 REGEXP_SEQUENCE (regexp
)->regexps_num
= repeat_num
;
4580 for (i
= 0; i
< repeat_num
; i
++)
4581 REGEXP_SEQUENCE (regexp
)->regexps
[i
] = copy_insn_regexp (operand
);
4582 regexp_transformed_p
= 1;
4587 /* The function makes transformations
4588 ...,(A,B,...),C,... -> ...,A,B,...,C,...
4589 ...+(A+B+...)+C+... -> ...+A+B+...+C+...
4590 ...|(A|B|...)|C|... -> ...|A|B|...|C|... */
4592 transform_2 (regexp_t regexp
)
4594 if (regexp
->mode
== rm_sequence
)
4596 regexp_t sequence
= NULL
;
4598 int sequence_index
= 0;
4601 for (i
= 0; i
< REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
4602 if (REGEXP_SEQUENCE (regexp
)->regexps
[i
]->mode
== rm_sequence
)
4605 sequence
= REGEXP_SEQUENCE (regexp
)->regexps
[i
];
4608 if (i
< REGEXP_SEQUENCE (regexp
)->regexps_num
)
4610 gcc_assert (REGEXP_SEQUENCE (sequence
)->regexps_num
> 1
4611 && REGEXP_SEQUENCE (regexp
)->regexps_num
> 1);
4612 result
= XCREATENODEVAR (struct regexp
, sizeof (struct regexp
)
4614 * (REGEXP_SEQUENCE (regexp
)->regexps_num
4615 + REGEXP_SEQUENCE (sequence
)->regexps_num
4617 result
->mode
= rm_sequence
;
4618 result
->pos
= regexp
->pos
;
4619 REGEXP_SEQUENCE (result
)->regexps_num
4620 = (REGEXP_SEQUENCE (regexp
)->regexps_num
4621 + REGEXP_SEQUENCE (sequence
)->regexps_num
- 1);
4622 for (i
= 0; i
< REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
4623 if (i
< sequence_index
)
4624 REGEXP_SEQUENCE (result
)->regexps
[i
]
4625 = copy_insn_regexp (REGEXP_SEQUENCE (regexp
)->regexps
[i
]);
4626 else if (i
> sequence_index
)
4627 REGEXP_SEQUENCE (result
)->regexps
4628 [i
+ REGEXP_SEQUENCE (sequence
)->regexps_num
- 1]
4629 = copy_insn_regexp (REGEXP_SEQUENCE (regexp
)->regexps
[i
]);
4631 for (j
= 0; j
< REGEXP_SEQUENCE (sequence
)->regexps_num
; j
++)
4632 REGEXP_SEQUENCE (result
)->regexps
[i
+ j
]
4633 = copy_insn_regexp (REGEXP_SEQUENCE (sequence
)->regexps
[j
]);
4634 regexp_transformed_p
= 1;
4638 else if (regexp
->mode
== rm_allof
)
4640 regexp_t allof
= NULL
;
4642 int allof_index
= 0;
4645 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
4646 if (REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
== rm_allof
)
4649 allof
= REGEXP_ALLOF (regexp
)->regexps
[i
];
4652 if (i
< REGEXP_ALLOF (regexp
)->regexps_num
)
4654 gcc_assert (REGEXP_ALLOF (allof
)->regexps_num
> 1
4655 && REGEXP_ALLOF (regexp
)->regexps_num
> 1);
4656 result
= XCREATENODEVAR (struct regexp
, sizeof (struct regexp
)
4658 * (REGEXP_ALLOF (regexp
)->regexps_num
4659 + REGEXP_ALLOF (allof
)->regexps_num
- 2));
4660 result
->mode
= rm_allof
;
4661 result
->pos
= regexp
->pos
;
4662 REGEXP_ALLOF (result
)->regexps_num
4663 = (REGEXP_ALLOF (regexp
)->regexps_num
4664 + REGEXP_ALLOF (allof
)->regexps_num
- 1);
4665 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
4666 if (i
< allof_index
)
4667 REGEXP_ALLOF (result
)->regexps
[i
]
4668 = copy_insn_regexp (REGEXP_ALLOF (regexp
)->regexps
[i
]);
4669 else if (i
> allof_index
)
4670 REGEXP_ALLOF (result
)->regexps
4671 [i
+ REGEXP_ALLOF (allof
)->regexps_num
- 1]
4672 = copy_insn_regexp (REGEXP_ALLOF (regexp
)->regexps
[i
]);
4674 for (j
= 0; j
< REGEXP_ALLOF (allof
)->regexps_num
; j
++)
4675 REGEXP_ALLOF (result
)->regexps
[i
+ j
]
4676 = copy_insn_regexp (REGEXP_ALLOF (allof
)->regexps
[j
]);
4677 regexp_transformed_p
= 1;
4681 else if (regexp
->mode
== rm_oneof
)
4683 regexp_t oneof
= NULL
;
4685 int oneof_index
= 0;
4688 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
4689 if (REGEXP_ONEOF (regexp
)->regexps
[i
]->mode
== rm_oneof
)
4692 oneof
= REGEXP_ONEOF (regexp
)->regexps
[i
];
4695 if (i
< REGEXP_ONEOF (regexp
)->regexps_num
)
4697 gcc_assert (REGEXP_ONEOF (oneof
)->regexps_num
> 1
4698 && REGEXP_ONEOF (regexp
)->regexps_num
> 1);
4699 result
= XCREATENODEVAR (struct regexp
, sizeof (struct regexp
)
4701 * (REGEXP_ONEOF (regexp
)->regexps_num
4702 + REGEXP_ONEOF (oneof
)->regexps_num
- 2));
4703 result
->mode
= rm_oneof
;
4704 result
->pos
= regexp
->pos
;
4705 REGEXP_ONEOF (result
)->regexps_num
4706 = (REGEXP_ONEOF (regexp
)->regexps_num
4707 + REGEXP_ONEOF (oneof
)->regexps_num
- 1);
4708 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
4709 if (i
< oneof_index
)
4710 REGEXP_ONEOF (result
)->regexps
[i
]
4711 = copy_insn_regexp (REGEXP_ONEOF (regexp
)->regexps
[i
]);
4712 else if (i
> oneof_index
)
4713 REGEXP_ONEOF (result
)->regexps
4714 [i
+ REGEXP_ONEOF (oneof
)->regexps_num
- 1]
4715 = copy_insn_regexp (REGEXP_ONEOF (regexp
)->regexps
[i
]);
4717 for (j
= 0; j
< REGEXP_ONEOF (oneof
)->regexps_num
; j
++)
4718 REGEXP_ONEOF (result
)->regexps
[i
+ j
]
4719 = copy_insn_regexp (REGEXP_ONEOF (oneof
)->regexps
[j
]);
4720 regexp_transformed_p
= 1;
4727 /* The function makes transformations
4728 ...,A|B|...,C,... -> (...,A,C,...)|(...,B,C,...)|...
4729 ...+(A|B|...)+C+... -> (...+A+C+...)|(...+B+C+...)|...
4730 ...+(A,B,...)+C+... -> (...+A+C+...),B,...
4731 ...+(A,B,...)+(C,D,...) -> (A+C),(B+D),... */
4733 transform_3 (regexp_t regexp
)
4735 if (regexp
->mode
== rm_sequence
)
4737 regexp_t oneof
= NULL
;
4738 int oneof_index
= 0;
4743 for (i
= 0; i
<REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
4744 if (REGEXP_SEQUENCE (regexp
)->regexps
[i
]->mode
== rm_oneof
)
4747 oneof
= REGEXP_SEQUENCE (regexp
)->regexps
[i
];
4750 if (i
< REGEXP_SEQUENCE (regexp
)->regexps_num
)
4752 gcc_assert (REGEXP_ONEOF (oneof
)->regexps_num
> 1
4753 && REGEXP_SEQUENCE (regexp
)->regexps_num
> 1);
4754 result
= XCREATENODEVAR (struct regexp
, sizeof (struct regexp
)
4756 * (REGEXP_ONEOF (oneof
)->regexps_num
- 1));
4757 result
->mode
= rm_oneof
;
4758 result
->pos
= regexp
->pos
;
4759 REGEXP_ONEOF (result
)->regexps_num
4760 = REGEXP_ONEOF (oneof
)->regexps_num
;
4761 for (i
= 0; i
< REGEXP_ONEOF (result
)->regexps_num
; i
++)
4764 = XCREATENODEVAR (struct regexp
, sizeof (struct regexp
)
4766 * (REGEXP_SEQUENCE (regexp
)->regexps_num
- 1));
4767 sequence
->mode
= rm_sequence
;
4768 sequence
->pos
= regexp
->pos
;
4769 REGEXP_SEQUENCE (sequence
)->regexps_num
4770 = REGEXP_SEQUENCE (regexp
)->regexps_num
;
4771 REGEXP_ONEOF (result
)->regexps
[i
] = sequence
;
4772 for (j
= 0; j
< REGEXP_SEQUENCE (sequence
)->regexps_num
; j
++)
4773 if (j
!= oneof_index
)
4774 REGEXP_SEQUENCE (sequence
)->regexps
[j
]
4775 = copy_insn_regexp (REGEXP_SEQUENCE (regexp
)->regexps
[j
]);
4777 REGEXP_SEQUENCE (sequence
)->regexps
[j
]
4778 = copy_insn_regexp (REGEXP_ONEOF (oneof
)->regexps
[i
]);
4780 regexp_transformed_p
= 1;
4784 else if (regexp
->mode
== rm_allof
)
4786 regexp_t oneof
= NULL
;
4788 int oneof_index
= 0;
4789 int max_seq_length
, allof_length
;
4791 regexp_t allof
= NULL
;
4792 regexp_t allof_op
= NULL
;
4795 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
4796 if (REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
== rm_oneof
)
4799 oneof
= REGEXP_ALLOF (regexp
)->regexps
[i
];
4802 if (i
< REGEXP_ALLOF (regexp
)->regexps_num
)
4804 gcc_assert (REGEXP_ONEOF (oneof
)->regexps_num
> 1
4805 && REGEXP_ALLOF (regexp
)->regexps_num
> 1);
4806 result
= XCREATENODEVAR (struct regexp
, sizeof (struct regexp
)
4808 * (REGEXP_ONEOF (oneof
)->regexps_num
- 1));
4809 result
->mode
= rm_oneof
;
4810 result
->pos
= regexp
->pos
;
4811 REGEXP_ONEOF (result
)->regexps_num
4812 = REGEXP_ONEOF (oneof
)->regexps_num
;
4813 for (i
= 0; i
< REGEXP_ONEOF (result
)->regexps_num
; i
++)
4816 = XCREATENODEVAR (struct regexp
, sizeof (struct regexp
)
4818 * (REGEXP_ALLOF (regexp
)->regexps_num
- 1));
4819 allof
->mode
= rm_allof
;
4820 allof
->pos
= regexp
->pos
;
4821 REGEXP_ALLOF (allof
)->regexps_num
4822 = REGEXP_ALLOF (regexp
)->regexps_num
;
4823 REGEXP_ONEOF (result
)->regexps
[i
] = allof
;
4824 for (j
= 0; j
< REGEXP_ALLOF (allof
)->regexps_num
; j
++)
4825 if (j
!= oneof_index
)
4826 REGEXP_ALLOF (allof
)->regexps
[j
]
4827 = copy_insn_regexp (REGEXP_ALLOF (regexp
)->regexps
[j
]);
4829 REGEXP_ALLOF (allof
)->regexps
[j
]
4830 = copy_insn_regexp (REGEXP_ONEOF (oneof
)->regexps
[i
]);
4832 regexp_transformed_p
= 1;
4836 if (regexp
->mode
== rm_allof
)
4837 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
4839 switch (REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
)
4842 seq
= REGEXP_ALLOF (regexp
)->regexps
[i
];
4843 if (max_seq_length
< REGEXP_SEQUENCE (seq
)->regexps_num
)
4844 max_seq_length
= REGEXP_SEQUENCE (seq
)->regexps_num
;
4857 if (max_seq_length
!= 0)
4859 gcc_assert (max_seq_length
!= 1
4860 && REGEXP_ALLOF (regexp
)->regexps_num
> 1);
4861 result
= XCREATENODEVAR (struct regexp
, sizeof (struct regexp
)
4862 + sizeof (regexp_t
) * (max_seq_length
- 1));
4863 result
->mode
= rm_sequence
;
4864 result
->pos
= regexp
->pos
;
4865 REGEXP_SEQUENCE (result
)->regexps_num
= max_seq_length
;
4866 for (i
= 0; i
< max_seq_length
; i
++)
4869 for (j
= 0; j
< REGEXP_ALLOF (regexp
)->regexps_num
; j
++)
4870 switch (REGEXP_ALLOF (regexp
)->regexps
[j
]->mode
)
4873 if (i
< (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp
)
4874 ->regexps
[j
])->regexps_num
))
4877 = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp
)
4887 allof_op
= REGEXP_ALLOF (regexp
)->regexps
[j
];
4895 if (allof_length
== 1)
4896 REGEXP_SEQUENCE (result
)->regexps
[i
] = allof_op
;
4899 allof
= XCREATENODEVAR (struct regexp
, sizeof (struct regexp
)
4901 * (allof_length
- 1));
4902 allof
->mode
= rm_allof
;
4903 allof
->pos
= regexp
->pos
;
4904 REGEXP_ALLOF (allof
)->regexps_num
= allof_length
;
4905 REGEXP_SEQUENCE (result
)->regexps
[i
] = allof
;
4907 for (j
= 0; j
< REGEXP_ALLOF (regexp
)->regexps_num
; j
++)
4908 if (REGEXP_ALLOF (regexp
)->regexps
[j
]->mode
== rm_sequence
4910 (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp
)
4911 ->regexps
[j
])->regexps_num
)))
4913 allof_op
= (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp
)
4916 REGEXP_ALLOF (allof
)->regexps
[allof_length
]
4921 && (REGEXP_ALLOF (regexp
)->regexps
[j
]->mode
4923 || (REGEXP_ALLOF (regexp
)->regexps
[j
]->mode
4926 allof_op
= REGEXP_ALLOF (regexp
)->regexps
[j
];
4927 REGEXP_ALLOF (allof
)->regexps
[allof_length
]
4933 regexp_transformed_p
= 1;
4940 /* The function traverses IR of reservation and applies transformations
4941 implemented by FUNC. */
4943 regexp_transform_func (regexp_t regexp
, regexp_t (*func
) (regexp_t regexp
))
4947 switch (regexp
->mode
)
4950 for (i
= 0; i
< REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
4951 REGEXP_SEQUENCE (regexp
)->regexps
[i
]
4952 = regexp_transform_func (REGEXP_SEQUENCE (regexp
)->regexps
[i
],
4957 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
4958 REGEXP_ALLOF (regexp
)->regexps
[i
]
4959 = regexp_transform_func (REGEXP_ALLOF (regexp
)->regexps
[i
], func
);
4963 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
4964 REGEXP_ONEOF (regexp
)->regexps
[i
]
4965 = regexp_transform_func (REGEXP_ONEOF (regexp
)->regexps
[i
], func
);
4969 REGEXP_REPEAT (regexp
)->regexp
4970 = regexp_transform_func (REGEXP_REPEAT (regexp
)->regexp
, func
);
4980 return (*func
) (regexp
);
4983 /* The function applies all transformations for IR representation of
4984 reservation REGEXP. */
4986 transform_regexp (regexp_t regexp
)
4988 regexp
= regexp_transform_func (regexp
, transform_1
);
4991 regexp_transformed_p
= 0;
4992 regexp
= regexp_transform_func (regexp
, transform_2
);
4993 regexp
= regexp_transform_func (regexp
, transform_3
);
4995 while (regexp_transformed_p
);
4999 /* The function applies all transformations for reservations of all
5000 insn declarations. */
5002 transform_insn_regexps (void)
5007 transform_time
= create_ticker ();
5008 add_advance_cycle_insn_decl ();
5010 add_collapse_ndfa_insn_decl ();
5012 fprintf (stderr
, "Reservation transformation...");
5013 for (i
= 0; i
< description
->normal_decls_num
; i
++)
5015 decl
= description
->decls
[i
];
5016 if (decl
->mode
== dm_insn_reserv
)
5017 DECL_INSN_RESERV (decl
)->transformed_regexp
5018 = transform_regexp (copy_insn_regexp
5019 (DECL_INSN_RESERV (decl
)->regexp
));
5022 fprintf (stderr
, "done\n");
5023 ticker_off (&transform_time
);
5028 /* The following variable value is TRUE if the first annotated message
5029 about units to automata distribution has been output. */
5030 static int annotation_message_reported_p
;
5032 /* The vector contains all decls which are automata. */
5033 static VEC(decl_t
, heap
) *automaton_decls
;
5035 /* The following structure describes usage of a unit in a reservation. */
5038 unit_decl_t unit_decl
;
5039 /* The following forms a list of units used on the same cycle in the
5040 same alternative. The list is ordered by the correspdoning unit
5041 declarations and there is no unit declaration duplication in the
5043 struct unit_usage
*next
;
5045 typedef struct unit_usage
*unit_usage_t
;
5047 DEF_VEC_P(unit_usage_t
);
5048 DEF_VEC_ALLOC_P(unit_usage_t
, heap
);
5050 /* Obstack for unit_usage structures. */
5051 static struct obstack unit_usages
;
5053 /* VLA for representation of array of pointers to unit usage
5054 structures. There is an element for each combination of
5055 (alternative number, cycle). Unit usages on given cycle in
5056 alternative with given number are referred through element with
5057 index equals to the cycle * number of all alternatives in the
5058 regexp + the alternative number. */
5059 static VEC(unit_usage_t
, heap
) *cycle_alt_unit_usages
;
5061 /* The following function creates the structure unit_usage for UNIT on
5062 CYCLE in REGEXP alternative with ALT_NUM. The structure is made
5063 accessed through cycle_alt_unit_usages. */
5065 store_alt_unit_usage (regexp_t regexp
, regexp_t unit
, int cycle
,
5069 unit_decl_t unit_decl
;
5070 unit_usage_t unit_usage_ptr
, curr
, prev
;
5073 gcc_assert (regexp
&& regexp
->mode
== rm_oneof
5074 && alt_num
< REGEXP_ONEOF (regexp
)->regexps_num
);
5075 unit_decl
= REGEXP_UNIT (unit
)->unit_decl
;
5077 length
= (cycle
+ 1) * REGEXP_ONEOF (regexp
)->regexps_num
;
5078 while (VEC_length (unit_usage_t
, cycle_alt_unit_usages
) < length
)
5079 VEC_safe_push (unit_usage_t
, heap
, cycle_alt_unit_usages
, 0);
5081 index
= cycle
* REGEXP_ONEOF (regexp
)->regexps_num
+ alt_num
;
5083 for (curr
= VEC_index (unit_usage_t
, cycle_alt_unit_usages
, index
);
5085 prev
= curr
, curr
= curr
->next
)
5086 if (curr
->unit_decl
>= unit_decl
)
5088 if (curr
!= NULL
&& curr
->unit_decl
== unit_decl
)
5090 obstack_blank (&unit_usages
, sizeof (struct unit_usage
));
5091 unit_usage_ptr
= (struct unit_usage
*) obstack_base (&unit_usages
);
5092 obstack_finish (&unit_usages
);
5093 unit_usage_ptr
->unit_decl
= unit_decl
;
5094 unit_decl
->last_distribution_check_cycle
= -1; /* undefined */
5095 unit_usage_ptr
->next
= curr
;
5097 VEC_replace (unit_usage_t
, cycle_alt_unit_usages
, index
, unit_usage_ptr
);
5099 prev
->next
= unit_usage_ptr
;
5102 /* Return true if unit UNIT_DECL is present on the LIST. */
5104 unit_present_on_list_p (unit_usage_t list
, unit_decl_t unit_decl
)
5106 while (list
!= NULL
)
5108 if (list
->unit_decl
== unit_decl
)
5115 /* The function returns true if reservations of alternatives ALT1 and
5116 ALT2 are equal after excluding reservations of units of
5117 EXCLUDED_AUTOMATON_DECL. */
5119 equal_alternatives_p (int alt1
, int alt2
, int n_alts
,
5120 struct automaton_decl
*excluded_automaton_decl
)
5123 unit_usage_t list1
, list2
;
5126 i
< (int) VEC_length (unit_usage_t
, cycle_alt_unit_usages
);
5129 for (list1
= VEC_index (unit_usage_t
, cycle_alt_unit_usages
, i
+ alt1
),
5130 list2
= VEC_index (unit_usage_t
, cycle_alt_unit_usages
, i
+ alt2
);;
5131 list1
= list1
->next
, list2
= list2
->next
)
5133 while (list1
!= NULL
5134 && list1
->unit_decl
->automaton_decl
== excluded_automaton_decl
)
5135 list1
= list1
->next
;
5136 while (list2
!= NULL
5137 && list2
->unit_decl
->automaton_decl
== excluded_automaton_decl
)
5138 list2
= list2
->next
;
5139 if (list1
== NULL
|| list2
== NULL
)
5146 if (list1
->unit_decl
!= list2
->unit_decl
)
5154 DEF_VEC_ALLOC_I(int, heap
);
5156 /* The function processes given REGEXP to find units with the wrong
5159 check_regexp_units_distribution (const char *insn_reserv_name
,
5162 int i
, j
, k
, cycle
, start
, n_alts
, alt
, alt2
;
5163 bool annotation_reservation_message_reported_p
;
5164 regexp_t seq
, allof
, unit
;
5165 struct unit_usage
*unit_usage_ptr
;
5166 VEC(int, heap
) *marked
;
5168 if (regexp
== NULL
|| regexp
->mode
!= rm_oneof
)
5170 /* Store all unit usages in the regexp: */
5171 obstack_init (&unit_usages
);
5172 cycle_alt_unit_usages
= VEC_alloc (unit_usage_t
, heap
, 10);
5174 for (i
= REGEXP_ONEOF (regexp
)->regexps_num
- 1; i
>= 0; i
--)
5176 seq
= REGEXP_ONEOF (regexp
)->regexps
[i
];
5180 for (j
= 0; j
< REGEXP_SEQUENCE (seq
)->regexps_num
; j
++)
5182 allof
= REGEXP_SEQUENCE (seq
)->regexps
[j
];
5183 switch (allof
->mode
)
5186 for (k
= 0; k
< REGEXP_ALLOF (allof
)->regexps_num
; k
++)
5188 unit
= REGEXP_ALLOF (allof
)->regexps
[k
];
5189 if (unit
->mode
== rm_unit
)
5190 store_alt_unit_usage (regexp
, unit
, j
, i
);
5192 gcc_assert (unit
->mode
== rm_nothing
);
5197 store_alt_unit_usage (regexp
, allof
, j
, i
);
5210 for (k
= 0; k
< REGEXP_ALLOF (seq
)->regexps_num
; k
++)
5212 unit
= REGEXP_ALLOF (seq
)->regexps
[k
];
5216 store_alt_unit_usage (regexp
, unit
, 0, i
);
5229 store_alt_unit_usage (regexp
, seq
, 0, i
);
5239 /* Check distribution: */
5240 for (i
= 0; i
< (int) VEC_length (unit_usage_t
, cycle_alt_unit_usages
); i
++)
5241 for (unit_usage_ptr
= VEC_index (unit_usage_t
, cycle_alt_unit_usages
, i
);
5242 unit_usage_ptr
!= NULL
;
5243 unit_usage_ptr
= unit_usage_ptr
->next
)
5244 unit_usage_ptr
->unit_decl
->last_distribution_check_cycle
= -1;
5245 n_alts
= REGEXP_ONEOF (regexp
)->regexps_num
;
5246 marked
= VEC_alloc (int, heap
, n_alts
);
5247 for (i
= 0; i
< n_alts
; i
++)
5248 VEC_safe_push (int, heap
, marked
, 0);
5249 annotation_reservation_message_reported_p
= false;
5250 for (i
= 0; i
< (int) VEC_length (unit_usage_t
, cycle_alt_unit_usages
); i
++)
5253 start
= cycle
* n_alts
;
5254 for (unit_usage_ptr
= VEC_index (unit_usage_t
, cycle_alt_unit_usages
, i
);
5255 unit_usage_ptr
!= NULL
;
5256 unit_usage_ptr
= unit_usage_ptr
->next
)
5258 if (unit_usage_ptr
->unit_decl
->last_distribution_check_cycle
== cycle
)
5260 unit_usage_ptr
->unit_decl
->last_distribution_check_cycle
= cycle
;
5261 for (alt
= 0; alt
< n_alts
; alt
++)
5262 if (! unit_present_on_list_p (VEC_index (unit_usage_t
,
5263 cycle_alt_unit_usages
,
5265 unit_usage_ptr
->unit_decl
))
5269 memset (VEC_address (int, marked
), 0, n_alts
* sizeof (int));
5270 for (alt
= 0; alt
< n_alts
; alt
++)
5272 if (! unit_present_on_list_p (VEC_index (unit_usage_t
,
5273 cycle_alt_unit_usages
,
5275 unit_usage_ptr
->unit_decl
))
5278 j
< (int) VEC_length (unit_usage_t
, cycle_alt_unit_usages
);
5282 if (! unit_present_on_list_p
5283 (VEC_index (unit_usage_t
, cycle_alt_unit_usages
,
5285 unit_usage_ptr
->unit_decl
)
5286 && equal_alternatives_p (alt
, alt2
, n_alts
,
5288 ->unit_decl
->automaton_decl
))
5290 VEC_replace (int, marked
, alt
, 1);
5291 VEC_replace (int, marked
, alt2
, 1);
5295 for (alt
= 0; alt
< n_alts
&& VEC_index (int, marked
, alt
); alt
++)
5297 if (alt
< n_alts
&& 0)
5299 if (! annotation_message_reported_p
)
5301 fprintf (stderr
, "\n");
5302 error ("The following units do not satisfy units-automata distribution rule");
5303 error ("(Unit presence on one alt and its absence on other alt\n");
5304 error (" result in different other automata reservations)");
5305 annotation_message_reported_p
= TRUE
;
5307 if (! annotation_reservation_message_reported_p
)
5309 error ("Reserv %s:", insn_reserv_name
);
5310 annotation_reservation_message_reported_p
= true;
5312 error (" Unit %s, cycle %d, alt %d, another alt %d",
5313 unit_usage_ptr
->unit_decl
->name
, cycle
, i
% n_alts
, alt
);
5317 VEC_free (int, heap
, marked
);
5318 VEC_free (unit_usage_t
, heap
, cycle_alt_unit_usages
);
5319 obstack_free (&unit_usages
, NULL
);
5322 /* The function finds units which violates units to automata
5323 distribution rule. If the units exist, report about them. */
5325 check_unit_distributions_to_automata (void)
5331 fprintf (stderr
, "Check unit distributions to automata...");
5332 automaton_decls
= NULL
;
5333 for (i
= 0; i
< description
->decls_num
; i
++)
5335 decl
= description
->decls
[i
];
5336 if (decl
->mode
== dm_automaton
)
5337 VEC_safe_push (decl_t
, heap
, automaton_decls
, decl
);
5339 if (VEC_length (decl_t
, automaton_decls
) > 1)
5341 annotation_message_reported_p
= FALSE
;
5342 for (i
= 0; i
< description
->decls_num
; i
++)
5344 decl
= description
->decls
[i
];
5345 if (decl
->mode
== dm_insn_reserv
)
5346 check_regexp_units_distribution
5347 (DECL_INSN_RESERV (decl
)->name
,
5348 DECL_INSN_RESERV (decl
)->transformed_regexp
);
5351 VEC_free (decl_t
, heap
, automaton_decls
);
5353 fprintf (stderr
, "done\n");
5358 /* The page contains code for building alt_states (see comments for
5359 IR) describing all possible insns reservations of an automaton. */
5361 /* Current state being formed for which the current alt_state
5363 static state_t state_being_formed
;
5365 /* Current alt_state being formed. */
5366 static alt_state_t alt_state_being_formed
;
5368 /* This recursive function processes `,' and units in reservation
5369 REGEXP for forming alt_states of AUTOMATON. It is believed that
5370 CURR_CYCLE is start cycle of all reservation REGEXP. */
5372 process_seq_for_forming_states (regexp_t regexp
, automaton_t automaton
,
5380 switch (regexp
->mode
)
5383 if (REGEXP_UNIT (regexp
)->unit_decl
->corresponding_automaton_num
5384 == automaton
->automaton_order_num
)
5385 set_state_reserv (state_being_formed
, curr_cycle
,
5386 REGEXP_UNIT (regexp
)->unit_decl
->unit_num
);
5390 for (i
= 0; i
< REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
5392 = process_seq_for_forming_states
5393 (REGEXP_SEQUENCE (regexp
)->regexps
[i
], automaton
, curr_cycle
) + 1;
5398 int finish_cycle
= 0;
5401 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
5403 cycle
= process_seq_for_forming_states (REGEXP_ALLOF (regexp
)
5405 automaton
, curr_cycle
);
5406 if (finish_cycle
< cycle
)
5407 finish_cycle
= cycle
;
5409 return finish_cycle
;
5420 /* This recursive function finishes forming ALT_STATE of AUTOMATON and
5421 inserts alt_state into the table. */
5423 finish_forming_alt_state (alt_state_t alt_state
,
5424 automaton_t automaton ATTRIBUTE_UNUSED
)
5426 state_t state_in_table
;
5427 state_t corresponding_state
;
5429 corresponding_state
= alt_state
->state
;
5430 state_in_table
= insert_state (corresponding_state
);
5431 if (state_in_table
!= corresponding_state
)
5433 free_state (corresponding_state
);
5434 alt_state
->state
= state_in_table
;
5438 /* The following variable value is current automaton insn for whose
5439 reservation the alt states are created. */
5440 static ainsn_t curr_ainsn
;
5442 /* This recursive function processes `|' in reservation REGEXP for
5443 forming alt_states of AUTOMATON. List of the alt states should
5444 have the same order as in the description. */
5446 process_alts_for_forming_states (regexp_t regexp
, automaton_t automaton
,
5451 if (regexp
->mode
!= rm_oneof
)
5453 alt_state_being_formed
= get_free_alt_state ();
5454 state_being_formed
= get_free_state (1, automaton
);
5455 alt_state_being_formed
->state
= state_being_formed
;
5456 /* We inserts in reverse order but we process alternatives also
5457 in reverse order. So we have the same order of alternative
5458 as in the description. */
5459 alt_state_being_formed
->next_alt_state
= curr_ainsn
->alt_states
;
5460 curr_ainsn
->alt_states
= alt_state_being_formed
;
5461 (void) process_seq_for_forming_states (regexp
, automaton
, 0);
5462 finish_forming_alt_state (alt_state_being_formed
, automaton
);
5466 gcc_assert (!inside_oneof_p
);
5467 /* We processes it in reverse order to get list with the same
5468 order as in the description. See also the previous
5470 for (i
= REGEXP_ONEOF (regexp
)->regexps_num
- 1; i
>= 0; i
--)
5471 process_alts_for_forming_states (REGEXP_ONEOF (regexp
)->regexps
[i
],
5476 /* Create nodes alt_state for all AUTOMATON insns. */
5478 create_alt_states (automaton_t automaton
)
5480 struct insn_reserv_decl
*reserv_decl
;
5482 for (curr_ainsn
= automaton
->ainsn_list
;
5484 curr_ainsn
= curr_ainsn
->next_ainsn
)
5486 reserv_decl
= curr_ainsn
->insn_reserv_decl
;
5487 if (!special_decl_p (reserv_decl
))
5489 curr_ainsn
->alt_states
= NULL
;
5490 process_alts_for_forming_states (reserv_decl
->transformed_regexp
,
5492 curr_ainsn
->sorted_alt_states
5493 = uniq_sort_alt_states (curr_ainsn
->alt_states
);
5500 /* The page contains major code for building DFA(s) for fast pipeline
5501 hazards recognition. */
5503 /* The function forms list of ainsns of AUTOMATON with the same
5507 form_ainsn_with_same_reservs (automaton_t automaton
)
5511 VEC(ainsn_t
, heap
) *last_insns
= VEC_alloc (ainsn_t
, heap
, 150);
5513 for (curr_ainsn
= automaton
->ainsn_list
;
5515 curr_ainsn
= curr_ainsn
->next_ainsn
)
5516 if (special_decl_p (curr_ainsn
->insn_reserv_decl
))
5518 curr_ainsn
->next_same_reservs_insn
= NULL
;
5519 curr_ainsn
->first_insn_with_same_reservs
= 1;
5523 for (i
= 0; i
< VEC_length (ainsn_t
, last_insns
); i
++)
5525 (curr_ainsn
->sorted_alt_states
,
5526 VEC_index (ainsn_t
, last_insns
, i
)->sorted_alt_states
))
5528 curr_ainsn
->next_same_reservs_insn
= NULL
;
5529 if (i
< VEC_length (ainsn_t
, last_insns
))
5531 curr_ainsn
->first_insn_with_same_reservs
= 0;
5532 VEC_index (ainsn_t
, last_insns
, i
)->next_same_reservs_insn
5534 VEC_replace (ainsn_t
, last_insns
, i
, curr_ainsn
);
5538 VEC_safe_push (ainsn_t
, heap
, last_insns
, curr_ainsn
);
5539 curr_ainsn
->first_insn_with_same_reservs
= 1;
5542 VEC_free (ainsn_t
, heap
, last_insns
);
5545 /* Forming unit reservations which can affect creating the automaton
5546 states achieved from a given state. It permits to build smaller
5547 automata in many cases. We would have the same automata after
5548 the minimization without such optimization, but the automaton
5549 right after the building could be huge. So in other words, usage
5550 of reservs_matter means some minimization during building the
5552 static reserv_sets_t
5553 form_reservs_matter (automaton_t automaton
)
5556 reserv_sets_t reservs_matter
= alloc_empty_reserv_sets();
5558 for (cycle
= 0; cycle
< max_cycles_num
; cycle
++)
5559 for (unit
= 0; unit
< description
->units_num
; unit
++)
5560 if (units_array
[unit
]->automaton_decl
5561 == automaton
->corresponding_automaton_decl
5562 && (cycle
>= units_array
[unit
]->min_occ_cycle_num
5563 /* We can not remove queried unit from reservations. */
5564 || units_array
[unit
]->query_p
5565 /* We can not remove units which are used
5566 `exclusion_set', `presence_set',
5567 `final_presence_set', `absence_set', and
5568 `final_absence_set'. */
5569 || units_array
[unit
]->in_set_p
))
5570 set_unit_reserv (reservs_matter
, cycle
, unit
);
5571 return reservs_matter
;
5574 /* The following function creates all states of nondeterministic AUTOMATON. */
5576 make_automaton (automaton_t automaton
)
5579 struct insn_reserv_decl
*insn_reserv_decl
;
5580 alt_state_t alt_state
;
5582 state_t start_state
;
5584 VEC(state_t
, heap
) *state_stack
= VEC_alloc(state_t
, heap
, 150);
5586 reserv_sets_t reservs_matter
= form_reservs_matter (automaton
);
5588 /* Create the start state (empty state). */
5589 start_state
= insert_state (get_free_state (1, automaton
));
5590 automaton
->start_state
= start_state
;
5591 start_state
->it_was_placed_in_stack_for_NDFA_forming
= 1;
5592 VEC_safe_push (state_t
, heap
, state_stack
, start_state
);
5594 while (VEC_length (state_t
, state_stack
) != 0)
5596 state
= VEC_pop (state_t
, state_stack
);
5597 for (ainsn
= automaton
->ainsn_list
;
5599 ainsn
= ainsn
->next_ainsn
)
5600 if (ainsn
->first_insn_with_same_reservs
)
5602 insn_reserv_decl
= ainsn
->insn_reserv_decl
;
5603 if (!special_decl_p (insn_reserv_decl
))
5605 /* We process alt_states in the same order as they are
5606 present in the description. */
5607 for (alt_state
= ainsn
->alt_states
;
5609 alt_state
= alt_state
->next_alt_state
)
5611 state2
= alt_state
->state
;
5612 if (!intersected_state_reservs_p (state
, state2
))
5614 state2
= states_union (state
, state2
, reservs_matter
);
5615 if (!state2
->it_was_placed_in_stack_for_NDFA_forming
)
5617 state2
->it_was_placed_in_stack_for_NDFA_forming
5619 VEC_safe_push (state_t
, heap
, state_stack
, state2
);
5621 if (progress_flag
&& states_n
% 100 == 0)
5622 fprintf (stderr
, ".");
5624 add_arc (state
, state2
, ainsn
);
5631 /* Add transition to advance cycle. */
5632 state2
= state_shift (state
, reservs_matter
);
5633 if (!state2
->it_was_placed_in_stack_for_NDFA_forming
)
5635 state2
->it_was_placed_in_stack_for_NDFA_forming
= 1;
5636 VEC_safe_push (state_t
, heap
, state_stack
, state2
);
5638 if (progress_flag
&& states_n
% 100 == 0)
5639 fprintf (stderr
, ".");
5641 add_arc (state
, state2
, automaton
->advance_ainsn
);
5643 VEC_free (state_t
, heap
, state_stack
);
5646 /* Form lists of all arcs of STATE marked by the same ainsn. */
5648 form_arcs_marked_by_insn (state_t state
)
5654 for (i
= 0; i
< description
->decls_num
; i
++)
5656 decl
= description
->decls
[i
];
5657 if (decl
->mode
== dm_insn_reserv
)
5658 DECL_INSN_RESERV (decl
)->arcs_marked_by_insn
= NULL
;
5660 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
5662 gcc_assert (arc
->insn
);
5663 arc
->next_arc_marked_by_insn
5664 = arc
->insn
->insn_reserv_decl
->arcs_marked_by_insn
;
5665 arc
->insn
->insn_reserv_decl
->arcs_marked_by_insn
= arc
;
5669 /* The function creates composed state (see comments for IR) from
5670 ORIGINAL_STATE and list of arcs ARCS_MARKED_BY_INSN marked by the
5671 same insn. If the composed state is not in STATE_STACK yet, it is
5672 pushed into STATE_STACK. */
5675 create_composed_state (state_t original_state
, arc_t arcs_marked_by_insn
,
5676 VEC(state_t
, heap
) **state_stack
)
5679 alt_state_t alt_state
, curr_alt_state
;
5680 alt_state_t new_alt_state
;
5683 state_t state_in_table
;
5685 alt_state_t canonical_alt_states_list
;
5687 int new_state_p
= 0;
5689 if (arcs_marked_by_insn
== NULL
)
5691 if (arcs_marked_by_insn
->next_arc_marked_by_insn
== NULL
)
5692 state
= arcs_marked_by_insn
->to_state
;
5695 gcc_assert (ndfa_flag
);
5696 /* Create composed state. */
5697 state
= get_free_state (0, arcs_marked_by_insn
->to_state
->automaton
);
5698 curr_alt_state
= NULL
;
5699 for (curr_arc
= arcs_marked_by_insn
;
5701 curr_arc
= curr_arc
->next_arc_marked_by_insn
)
5702 if (curr_arc
->to_state
->component_states
== NULL
)
5704 new_alt_state
= get_free_alt_state ();
5705 new_alt_state
->next_alt_state
= curr_alt_state
;
5706 new_alt_state
->state
= curr_arc
->to_state
;
5707 curr_alt_state
= new_alt_state
;
5710 for (alt_state
= curr_arc
->to_state
->component_states
;
5712 alt_state
= alt_state
->next_sorted_alt_state
)
5714 new_alt_state
= get_free_alt_state ();
5715 new_alt_state
->next_alt_state
= curr_alt_state
;
5716 new_alt_state
->state
= alt_state
->state
;
5717 gcc_assert (!alt_state
->state
->component_states
);
5718 curr_alt_state
= new_alt_state
;
5720 /* There are not identical sets in the alt state list. */
5721 canonical_alt_states_list
= uniq_sort_alt_states (curr_alt_state
);
5722 if (canonical_alt_states_list
->next_sorted_alt_state
== NULL
)
5725 state
= canonical_alt_states_list
->state
;
5726 free_state (temp_state
);
5730 state
->component_states
= canonical_alt_states_list
;
5731 state_in_table
= insert_state (state
);
5732 if (state_in_table
!= state
)
5735 (state_in_table
->it_was_placed_in_stack_for_DFA_forming
);
5737 state
= state_in_table
;
5741 gcc_assert (!state
->it_was_placed_in_stack_for_DFA_forming
);
5743 for (curr_alt_state
= state
->component_states
;
5744 curr_alt_state
!= NULL
;
5745 curr_alt_state
= curr_alt_state
->next_sorted_alt_state
)
5746 for (curr_arc
= first_out_arc (curr_alt_state
->state
);
5748 curr_arc
= next_out_arc (curr_arc
))
5750 /* When producing collapse-NDFA transitions, we
5751 only add advance-cycle transitions to the
5752 collapsed states. */
5753 || (curr_arc
->insn
->insn_reserv_decl
5754 != DECL_INSN_RESERV (advance_cycle_insn_decl
)))
5755 add_arc (state
, curr_arc
->to_state
, curr_arc
->insn
);
5757 arcs_marked_by_insn
->to_state
= state
;
5758 for (alts_number
= 0,
5759 curr_arc
= arcs_marked_by_insn
->next_arc_marked_by_insn
;
5761 curr_arc
= next_arc
)
5763 next_arc
= curr_arc
->next_arc_marked_by_insn
;
5764 remove_arc (original_state
, curr_arc
);
5769 if (!state
->it_was_placed_in_stack_for_DFA_forming
)
5771 state
->it_was_placed_in_stack_for_DFA_forming
= 1;
5772 VEC_safe_push (state_t
, heap
, *state_stack
, state
);
5777 /* The function transforms nondeterministic AUTOMATON into
5781 NDFA_to_DFA (automaton_t automaton
)
5783 state_t start_state
;
5786 VEC(state_t
, heap
) *state_stack
;
5790 state_stack
= VEC_alloc (state_t
, heap
, 0);
5792 /* Create the start state (empty state). */
5793 start_state
= automaton
->start_state
;
5794 start_state
->it_was_placed_in_stack_for_DFA_forming
= 1;
5795 VEC_safe_push (state_t
, heap
, state_stack
, start_state
);
5797 while (VEC_length (state_t
, state_stack
) != 0)
5799 state
= VEC_pop (state_t
, state_stack
);
5800 form_arcs_marked_by_insn (state
);
5801 for (i
= 0; i
< description
->decls_num
; i
++)
5803 decl
= description
->decls
[i
];
5804 if (decl
->mode
== dm_insn_reserv
5805 && decl
!= collapse_ndfa_insn_decl
5806 && create_composed_state
5807 (state
, DECL_INSN_RESERV (decl
)->arcs_marked_by_insn
,
5811 if (progress_flag
&& states_n
% 100 == 0)
5812 fprintf (stderr
, ".");
5815 /* Add a transition to collapse the NDFA. */
5818 if (state
->component_states
!= NULL
)
5820 state_t state2
= state
->component_states
->state
;
5821 if (!state2
->it_was_placed_in_stack_for_DFA_forming
)
5823 state2
->it_was_placed_in_stack_for_DFA_forming
= 1;
5824 VEC_safe_push (state_t
, heap
, state_stack
, state2
);
5826 add_arc (state
, state2
, automaton
->collapse_ainsn
);
5829 add_arc (state
, state
, automaton
->collapse_ainsn
);
5832 VEC_free (state_t
, heap
, state_stack
);
5835 /* The following variable value is current number (1, 2, ...) of passing
5837 static int curr_state_graph_pass_num
;
5839 /* This recursive function passes all states achieved from START_STATE
5840 and applies APPLIED_FUNC to them. */
5842 pass_state_graph (state_t start_state
, void (*applied_func
) (state_t state
))
5846 if (start_state
->pass_num
== curr_state_graph_pass_num
)
5848 start_state
->pass_num
= curr_state_graph_pass_num
;
5849 (*applied_func
) (start_state
);
5850 for (arc
= first_out_arc (start_state
);
5852 arc
= next_out_arc (arc
))
5853 pass_state_graph (arc
->to_state
, applied_func
);
5856 /* This recursive function passes all states of AUTOMATON and applies
5857 APPLIED_FUNC to them. */
5859 pass_states (automaton_t automaton
, void (*applied_func
) (state_t state
))
5861 curr_state_graph_pass_num
++;
5862 pass_state_graph (automaton
->start_state
, applied_func
);
5865 /* The function initializes code for passing of all states. */
5867 initiate_pass_states (void)
5869 curr_state_graph_pass_num
= 0;
5872 /* The following vla is used for storing pointers to all achieved
5874 static VEC(state_t
, heap
) *all_achieved_states
;
5876 /* This function is called by function pass_states to add an achieved
5879 add_achieved_state (state_t state
)
5881 VEC_safe_push (state_t
, heap
, all_achieved_states
, state
);
5884 /* The function sets up equivalence numbers of insns which mark all
5885 out arcs of STATE by equiv_class_num_1 (if ODD_ITERATION_FLAG has
5886 nonzero value) or by equiv_class_num_2 of the destination state. */
5888 set_out_arc_insns_equiv_num (state_t state
, int odd_iteration_flag
)
5892 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
5894 gcc_assert (!arc
->insn
->insn_reserv_decl
->equiv_class_num
);
5895 arc
->insn
->insn_reserv_decl
->equiv_class_num
5896 = (odd_iteration_flag
5897 ? arc
->to_state
->equiv_class_num_1
5898 : arc
->to_state
->equiv_class_num_2
);
5899 gcc_assert (arc
->insn
->insn_reserv_decl
->equiv_class_num
);
5903 /* The function clears equivalence numbers and alt_states in all insns
5904 which mark all out arcs of STATE. */
5906 clear_arc_insns_equiv_num (state_t state
)
5910 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
5911 arc
->insn
->insn_reserv_decl
->equiv_class_num
= 0;
5915 /* The following function returns TRUE if STATE reserves the unit with
5916 UNIT_NUM on the first cycle. */
5918 first_cycle_unit_presence (state_t state
, int unit_num
)
5920 alt_state_t alt_state
;
5922 if (state
->component_states
== NULL
)
5923 return test_unit_reserv (state
->reservs
, 0, unit_num
);
5926 for (alt_state
= state
->component_states
;
5928 alt_state
= alt_state
->next_sorted_alt_state
)
5929 if (test_unit_reserv (alt_state
->state
->reservs
, 0, unit_num
))
5935 /* This fills in the presence_signature[] member of STATE. */
5937 cache_presence (state_t state
)
5941 sz
= (description
->query_units_num
+ sizeof (int) * CHAR_BIT
- 1)
5942 / (sizeof (int) * CHAR_BIT
);
5944 state
->presence_signature
= XCREATENODEVEC (unsigned int, sz
);
5945 for (i
= 0; i
< description
->units_num
; i
++)
5946 if (units_array
[i
]->query_p
)
5948 int presence1_p
= first_cycle_unit_presence (state
, i
);
5949 state
->presence_signature
[num
/ (sizeof (int) * CHAR_BIT
)]
5950 |= (!!presence1_p
) << (num
% (sizeof (int) * CHAR_BIT
));
5955 /* The function returns nonzero value if STATE is not equivalent to
5956 ANOTHER_STATE from the same current partition on equivalence
5957 classes. Another state has ANOTHER_STATE_OUT_ARCS_NUM number of
5958 output arcs. Iteration of making equivalence partition is defined
5959 by ODD_ITERATION_FLAG. */
5961 state_is_differed (state_t state
, state_t another_state
,
5962 int odd_iteration_flag
)
5965 unsigned int sz
, si
;
5967 gcc_assert (state
->num_out_arcs
== another_state
->num_out_arcs
);
5969 sz
= (description
->query_units_num
+ sizeof (int) * CHAR_BIT
- 1)
5970 / (sizeof (int) * CHAR_BIT
);
5972 for (si
= 0; si
< sz
; si
++)
5973 gcc_assert (state
->presence_signature
[si
]
5974 == another_state
->presence_signature
[si
]);
5976 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
5978 if ((odd_iteration_flag
5979 ? arc
->to_state
->equiv_class_num_1
5980 : arc
->to_state
->equiv_class_num_2
)
5981 != arc
->insn
->insn_reserv_decl
->equiv_class_num
)
5988 /* Compares two states pointed to by STATE_PTR_1 and STATE_PTR_2
5989 and return -1, 0 or 1. This function can be used as predicate for
5990 qsort(). It requires the member presence_signature[] of both
5991 states be filled. */
5993 compare_states_for_equiv (const void *state_ptr_1
,
5994 const void *state_ptr_2
)
5996 const_state_t
const s1
= *(const_state_t
const*)state_ptr_1
;
5997 const_state_t
const s2
= *(const_state_t
const*)state_ptr_2
;
5998 unsigned int sz
, si
;
5999 if (s1
->num_out_arcs
< s2
->num_out_arcs
)
6001 else if (s1
->num_out_arcs
> s2
->num_out_arcs
)
6004 sz
= (description
->query_units_num
+ sizeof (int) * CHAR_BIT
- 1)
6005 / (sizeof (int) * CHAR_BIT
);
6007 for (si
= 0; si
< sz
; si
++)
6008 if (s1
->presence_signature
[si
] < s2
->presence_signature
[si
])
6010 else if (s1
->presence_signature
[si
] > s2
->presence_signature
[si
])
6015 /* The function makes initial partition of STATES on equivalent
6016 classes and saves it into *CLASSES. This function requires the input
6017 to be sorted via compare_states_for_equiv(). */
6019 init_equiv_class (VEC(state_t
, heap
) *states
, VEC (state_t
, heap
) **classes
)
6025 *classes
= VEC_alloc (state_t
, heap
, 150);
6026 for (i
= 0; i
< VEC_length (state_t
, states
); i
++)
6028 state_t state
= VEC_index (state_t
, states
, i
);
6031 if (compare_states_for_equiv (&prev
, &state
) != 0)
6033 VEC_safe_push (state_t
, heap
, *classes
, prev
);
6038 state
->equiv_class_num_1
= class_num
;
6039 state
->next_equiv_class_state
= prev
;
6043 VEC_safe_push (state_t
, heap
, *classes
, prev
);
6047 /* The function copies pointers to equivalent states from vla FROM
6050 copy_equiv_class (VEC(state_t
, heap
) **to
, VEC(state_t
, heap
) *from
)
6052 VEC_free (state_t
, heap
, *to
);
6053 *to
= VEC_copy (state_t
, heap
, from
);
6056 /* The function processes equivalence class given by its first state,
6057 FIRST_STATE, on odd iteration if ODD_ITERATION_FLAG. If there
6058 are not equivalent states, the function partitions the class
6059 removing nonequivalent states and placing them in
6060 *NEXT_ITERATION_CLASSES, increments *NEW_EQUIV_CLASS_NUM_PTR ans
6061 assigns it to the state equivalence number. If the class has been
6062 partitioned, the function returns nonzero value. */
6064 partition_equiv_class (state_t first_state
, int odd_iteration_flag
,
6065 VEC(state_t
, heap
) **next_iteration_classes
,
6066 int *new_equiv_class_num_ptr
)
6068 state_t new_equiv_class
;
6076 while (first_state
!= NULL
)
6078 new_equiv_class
= NULL
;
6079 if (first_state
->next_equiv_class_state
!= NULL
)
6081 /* There are more one states in the class equivalence. */
6082 set_out_arc_insns_equiv_num (first_state
, odd_iteration_flag
);
6083 for (prev_state
= first_state
,
6084 curr_state
= first_state
->next_equiv_class_state
;
6086 curr_state
= next_state
)
6088 next_state
= curr_state
->next_equiv_class_state
;
6089 if (state_is_differed (curr_state
, first_state
,
6090 odd_iteration_flag
))
6092 /* Remove curr state from the class equivalence. */
6093 prev_state
->next_equiv_class_state
= next_state
;
6094 /* Add curr state to the new class equivalence. */
6095 curr_state
->next_equiv_class_state
= new_equiv_class
;
6096 if (new_equiv_class
== NULL
)
6097 (*new_equiv_class_num_ptr
)++;
6098 if (odd_iteration_flag
)
6099 curr_state
->equiv_class_num_2
= *new_equiv_class_num_ptr
;
6101 curr_state
->equiv_class_num_1
= *new_equiv_class_num_ptr
;
6102 new_equiv_class
= curr_state
;
6106 prev_state
= curr_state
;
6108 clear_arc_insns_equiv_num (first_state
);
6110 if (new_equiv_class
!= NULL
)
6111 VEC_safe_push (state_t
, heap
, *next_iteration_classes
, new_equiv_class
);
6112 first_state
= new_equiv_class
;
6117 /* The function finds equivalent states of AUTOMATON. */
6119 evaluate_equiv_classes (automaton_t automaton
,
6120 VEC(state_t
, heap
) **equiv_classes
)
6122 int new_equiv_class_num
;
6123 int odd_iteration_flag
;
6125 VEC (state_t
, heap
) *next_iteration_classes
;
6128 all_achieved_states
= VEC_alloc (state_t
, heap
, 1500);
6129 pass_states (automaton
, add_achieved_state
);
6130 pass_states (automaton
, cache_presence
);
6131 VEC_qsort (state_t
, all_achieved_states
, compare_states_for_equiv
);
6133 odd_iteration_flag
= 0;
6134 new_equiv_class_num
= init_equiv_class (all_achieved_states
,
6135 &next_iteration_classes
);
6139 odd_iteration_flag
= !odd_iteration_flag
;
6141 copy_equiv_class (equiv_classes
, next_iteration_classes
);
6143 /* Transfer equiv numbers for the next iteration. */
6144 for (i
= 0; i
< VEC_length (state_t
, all_achieved_states
); i
++)
6145 if (odd_iteration_flag
)
6146 VEC_index (state_t
, all_achieved_states
, i
)->equiv_class_num_2
6147 = VEC_index (state_t
, all_achieved_states
, i
)->equiv_class_num_1
;
6149 VEC_index (state_t
, all_achieved_states
, i
)->equiv_class_num_1
6150 = VEC_index (state_t
, all_achieved_states
, i
)->equiv_class_num_2
;
6152 for (i
= 0; i
< VEC_length (state_t
, *equiv_classes
); i
++)
6153 if (partition_equiv_class (VEC_index (state_t
, *equiv_classes
, i
),
6155 &next_iteration_classes
,
6156 &new_equiv_class_num
))
6159 while (!finish_flag
);
6160 VEC_free (state_t
, heap
, next_iteration_classes
);
6161 VEC_free (state_t
, heap
, all_achieved_states
);
6164 /* The function merges equivalent states of AUTOMATON. */
6166 merge_states (automaton_t automaton
, VEC(state_t
, heap
) *equiv_classes
)
6170 state_t first_class_state
;
6171 alt_state_t alt_states
;
6172 alt_state_t alt_state
, new_alt_state
;
6177 /* Create states corresponding to equivalence classes containing two
6179 for (i
= 0; i
< VEC_length (state_t
, equiv_classes
); i
++)
6181 curr_state
= VEC_index (state_t
, equiv_classes
, i
);
6182 if (curr_state
->next_equiv_class_state
!= NULL
)
6184 /* There are more one states in the class equivalence. */
6185 /* Create new compound state. */
6186 new_state
= get_free_state (0, automaton
);
6188 first_class_state
= curr_state
;
6189 for (curr_state
= first_class_state
;
6191 curr_state
= curr_state
->next_equiv_class_state
)
6193 curr_state
->equiv_class_state
= new_state
;
6194 if (curr_state
->component_states
== NULL
)
6196 new_alt_state
= get_free_alt_state ();
6197 new_alt_state
->state
= curr_state
;
6198 new_alt_state
->next_alt_state
= alt_states
;
6199 alt_states
= new_alt_state
;
6202 for (alt_state
= curr_state
->component_states
;
6204 alt_state
= alt_state
->next_sorted_alt_state
)
6206 new_alt_state
= get_free_alt_state ();
6207 new_alt_state
->state
= alt_state
->state
;
6208 new_alt_state
->next_alt_state
= alt_states
;
6209 alt_states
= new_alt_state
;
6212 /* Its is important that alt states were sorted before and
6213 after merging to have the same querying results. */
6214 new_state
->component_states
= uniq_sort_alt_states (alt_states
);
6217 curr_state
->equiv_class_state
= curr_state
;
6220 for (i
= 0; i
< VEC_length (state_t
, equiv_classes
); i
++)
6222 curr_state
= VEC_index (state_t
, equiv_classes
, i
);
6223 if (curr_state
->next_equiv_class_state
!= NULL
)
6225 first_class_state
= curr_state
;
6226 /* Create new arcs output from the state corresponding to
6228 for (curr_arc
= first_out_arc (first_class_state
);
6230 curr_arc
= next_out_arc (curr_arc
))
6231 add_arc (first_class_state
->equiv_class_state
,
6232 curr_arc
->to_state
->equiv_class_state
,
6234 /* Delete output arcs from states of given class equivalence. */
6235 for (curr_state
= first_class_state
;
6237 curr_state
= curr_state
->next_equiv_class_state
)
6239 if (automaton
->start_state
== curr_state
)
6240 automaton
->start_state
= curr_state
->equiv_class_state
;
6241 /* Delete the state and its output arcs. */
6242 for (curr_arc
= first_out_arc (curr_state
);
6244 curr_arc
= next_arc
)
6246 next_arc
= next_out_arc (curr_arc
);
6247 free_arc (curr_arc
);
6253 /* Change `to_state' of arcs output from the state of given
6254 equivalence class. */
6255 for (curr_arc
= first_out_arc (curr_state
);
6257 curr_arc
= next_out_arc (curr_arc
))
6258 curr_arc
->to_state
= curr_arc
->to_state
->equiv_class_state
;
6263 /* The function sets up new_cycle_p for states if there is arc to the
6264 state marked by advance_cycle_insn_decl. */
6266 set_new_cycle_flags (state_t state
)
6270 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
6271 if (arc
->insn
->insn_reserv_decl
6272 == DECL_INSN_RESERV (advance_cycle_insn_decl
))
6273 arc
->to_state
->new_cycle_p
= 1;
6276 /* The top level function for minimization of deterministic
6279 minimize_DFA (automaton_t automaton
)
6281 VEC(state_t
, heap
) *equiv_classes
= 0;
6283 evaluate_equiv_classes (automaton
, &equiv_classes
);
6284 merge_states (automaton
, equiv_classes
);
6285 pass_states (automaton
, set_new_cycle_flags
);
6287 VEC_free (state_t
, heap
, equiv_classes
);
6290 /* Values of two variables are counted number of states and arcs in an
6292 static int curr_counted_states_num
;
6293 static int curr_counted_arcs_num
;
6295 /* The function is called by function `pass_states' to count states
6296 and arcs of an automaton. */
6298 incr_states_and_arcs_nums (state_t state
)
6302 curr_counted_states_num
++;
6303 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
6304 curr_counted_arcs_num
++;
6307 /* The function counts states and arcs of AUTOMATON. */
6309 count_states_and_arcs (automaton_t automaton
, int *states_num
,
6312 curr_counted_states_num
= 0;
6313 curr_counted_arcs_num
= 0;
6314 pass_states (automaton
, incr_states_and_arcs_nums
);
6315 *states_num
= curr_counted_states_num
;
6316 *arcs_num
= curr_counted_arcs_num
;
6319 /* The function builds one DFA AUTOMATON for fast pipeline hazards
6320 recognition after checking and simplifying IR of the
6323 build_automaton (automaton_t automaton
)
6328 ticker_on (&NDFA_time
);
6331 if (automaton
->corresponding_automaton_decl
== NULL
)
6332 fprintf (stderr
, "Create anonymous automaton");
6334 fprintf (stderr
, "Create automaton `%s'",
6335 automaton
->corresponding_automaton_decl
->name
);
6336 fprintf (stderr
, " (1 dot is 100 new states):");
6338 make_automaton (automaton
);
6340 fprintf (stderr
, " done\n");
6341 ticker_off (&NDFA_time
);
6342 count_states_and_arcs (automaton
, &states_num
, &arcs_num
);
6343 automaton
->NDFA_states_num
= states_num
;
6344 automaton
->NDFA_arcs_num
= arcs_num
;
6345 ticker_on (&NDFA_to_DFA_time
);
6348 if (automaton
->corresponding_automaton_decl
== NULL
)
6349 fprintf (stderr
, "Make anonymous DFA");
6351 fprintf (stderr
, "Make DFA `%s'",
6352 automaton
->corresponding_automaton_decl
->name
);
6353 fprintf (stderr
, " (1 dot is 100 new states):");
6355 NDFA_to_DFA (automaton
);
6357 fprintf (stderr
, " done\n");
6358 ticker_off (&NDFA_to_DFA_time
);
6359 count_states_and_arcs (automaton
, &states_num
, &arcs_num
);
6360 automaton
->DFA_states_num
= states_num
;
6361 automaton
->DFA_arcs_num
= arcs_num
;
6362 if (!no_minimization_flag
)
6364 ticker_on (&minimize_time
);
6367 if (automaton
->corresponding_automaton_decl
== NULL
)
6368 fprintf (stderr
, "Minimize anonymous DFA...");
6370 fprintf (stderr
, "Minimize DFA `%s'...",
6371 automaton
->corresponding_automaton_decl
->name
);
6373 minimize_DFA (automaton
);
6375 fprintf (stderr
, "done\n");
6376 ticker_off (&minimize_time
);
6377 count_states_and_arcs (automaton
, &states_num
, &arcs_num
);
6378 automaton
->minimal_DFA_states_num
= states_num
;
6379 automaton
->minimal_DFA_arcs_num
= arcs_num
;
6385 /* The page contains code for enumeration of all states of an automaton. */
6387 /* Variable used for enumeration of all states of an automaton. Its
6388 value is current number of automaton states. */
6389 static int curr_state_order_num
;
6391 /* The function is called by function `pass_states' for enumerating
6394 set_order_state_num (state_t state
)
6396 state
->order_state_num
= curr_state_order_num
;
6397 curr_state_order_num
++;
6400 /* The function enumerates all states of AUTOMATON. */
6402 enumerate_states (automaton_t automaton
)
6404 curr_state_order_num
= 0;
6405 pass_states (automaton
, set_order_state_num
);
6406 automaton
->achieved_states_num
= curr_state_order_num
;
6411 /* The page contains code for finding equivalent automaton insns
6414 /* The function inserts AINSN into cyclic list
6415 CYCLIC_EQUIV_CLASS_INSN_LIST of ainsns. */
6417 insert_ainsn_into_equiv_class (ainsn_t ainsn
,
6418 ainsn_t cyclic_equiv_class_insn_list
)
6420 if (cyclic_equiv_class_insn_list
== NULL
)
6421 ainsn
->next_equiv_class_insn
= ainsn
;
6424 ainsn
->next_equiv_class_insn
6425 = cyclic_equiv_class_insn_list
->next_equiv_class_insn
;
6426 cyclic_equiv_class_insn_list
->next_equiv_class_insn
= ainsn
;
6431 /* The function deletes equiv_class_insn into cyclic list of
6432 equivalent ainsns. */
6434 delete_ainsn_from_equiv_class (ainsn_t equiv_class_insn
)
6436 ainsn_t curr_equiv_class_insn
;
6437 ainsn_t prev_equiv_class_insn
;
6439 prev_equiv_class_insn
= equiv_class_insn
;
6440 for (curr_equiv_class_insn
= equiv_class_insn
->next_equiv_class_insn
;
6441 curr_equiv_class_insn
!= equiv_class_insn
;
6442 curr_equiv_class_insn
= curr_equiv_class_insn
->next_equiv_class_insn
)
6443 prev_equiv_class_insn
= curr_equiv_class_insn
;
6444 if (prev_equiv_class_insn
!= equiv_class_insn
)
6445 prev_equiv_class_insn
->next_equiv_class_insn
6446 = equiv_class_insn
->next_equiv_class_insn
;
6449 /* The function processes AINSN of a state in order to find equivalent
6450 ainsns. INSN_ARCS_ARRAY is table: code of insn -> out arc of the
6453 process_insn_equiv_class (ainsn_t ainsn
, arc_t
*insn_arcs_array
)
6457 ainsn_t cyclic_insn_list
;
6460 gcc_assert (insn_arcs_array
[ainsn
->insn_reserv_decl
->insn_num
]);
6462 /* New class of ainsns which are not equivalent to given ainsn. */
6463 cyclic_insn_list
= NULL
;
6466 next_insn
= curr_insn
->next_equiv_class_insn
;
6467 arc
= insn_arcs_array
[curr_insn
->insn_reserv_decl
->insn_num
];
6469 || (insn_arcs_array
[ainsn
->insn_reserv_decl
->insn_num
]->to_state
6472 delete_ainsn_from_equiv_class (curr_insn
);
6473 cyclic_insn_list
= insert_ainsn_into_equiv_class (curr_insn
,
6476 curr_insn
= next_insn
;
6478 while (curr_insn
!= ainsn
);
6481 /* The function processes STATE in order to find equivalent ainsns. */
6483 process_state_for_insn_equiv_partition (state_t state
)
6486 arc_t
*insn_arcs_array
= XCNEWVEC (arc_t
, description
->insns_num
);
6488 /* Process insns of the arcs. */
6489 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
6490 insn_arcs_array
[arc
->insn
->insn_reserv_decl
->insn_num
] = arc
;
6491 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
6492 process_insn_equiv_class (arc
->insn
, insn_arcs_array
);
6494 free (insn_arcs_array
);
6497 /* The function searches for equivalent ainsns of AUTOMATON. */
6499 set_insn_equiv_classes (automaton_t automaton
)
6504 ainsn_t cyclic_insn_list
;
6505 ainsn_t insn_with_same_reservs
;
6506 int equiv_classes_num
;
6508 /* All insns are included in one equivalence class. */
6509 cyclic_insn_list
= NULL
;
6510 for (ainsn
= automaton
->ainsn_list
; ainsn
!= NULL
; ainsn
= ainsn
->next_ainsn
)
6511 if (ainsn
->first_insn_with_same_reservs
)
6512 cyclic_insn_list
= insert_ainsn_into_equiv_class (ainsn
,
6514 /* Process insns in order to make equivalence partition. */
6515 pass_states (automaton
, process_state_for_insn_equiv_partition
);
6516 /* Enumerate equiv classes. */
6517 for (ainsn
= automaton
->ainsn_list
; ainsn
!= NULL
; ainsn
= ainsn
->next_ainsn
)
6518 /* Set undefined value. */
6519 ainsn
->insn_equiv_class_num
= -1;
6520 equiv_classes_num
= 0;
6521 for (ainsn
= automaton
->ainsn_list
; ainsn
!= NULL
; ainsn
= ainsn
->next_ainsn
)
6522 if (ainsn
->insn_equiv_class_num
< 0)
6525 gcc_assert (first_insn
->first_insn_with_same_reservs
);
6526 first_insn
->first_ainsn_with_given_equivalence_num
= 1;
6527 curr_insn
= first_insn
;
6530 for (insn_with_same_reservs
= curr_insn
;
6531 insn_with_same_reservs
!= NULL
;
6532 insn_with_same_reservs
6533 = insn_with_same_reservs
->next_same_reservs_insn
)
6534 insn_with_same_reservs
->insn_equiv_class_num
= equiv_classes_num
;
6535 curr_insn
= curr_insn
->next_equiv_class_insn
;
6537 while (curr_insn
!= first_insn
);
6538 equiv_classes_num
++;
6540 automaton
->insn_equiv_classes_num
= equiv_classes_num
;
6545 /* This page contains code for creating DFA(s) and calls functions
6549 /* The following value is used to prevent floating point overflow for
6550 estimating an automaton bound. The value should be less DBL_MAX on
6551 the host machine. We use here approximate minimum of maximal
6552 double floating point value required by ANSI C standard. It
6553 will work for non ANSI sun compiler too. */
6555 #define MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND 1.0E37
6557 /* The function estimate size of the single DFA used by PHR (pipeline
6558 hazards recognizer). */
6560 estimate_one_automaton_bound (void)
6563 double one_automaton_estimation_bound
;
6567 one_automaton_estimation_bound
= 1.0;
6568 for (i
= 0; i
< description
->decls_num
; i
++)
6570 decl
= description
->decls
[i
];
6571 if (decl
->mode
== dm_unit
)
6573 root_value
= exp (log (DECL_UNIT (decl
)->max_occ_cycle_num
6574 - DECL_UNIT (decl
)->min_occ_cycle_num
+ 1.0)
6576 if (MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND
/ root_value
6577 > one_automaton_estimation_bound
)
6578 one_automaton_estimation_bound
*= root_value
;
6581 return one_automaton_estimation_bound
;
6584 /* The function compares unit declarations according to their maximal
6585 cycle in reservations. */
6587 compare_max_occ_cycle_nums (const void *unit_decl_1
,
6588 const void *unit_decl_2
)
6590 if ((DECL_UNIT (*(const_decl_t
const*) unit_decl_1
)->max_occ_cycle_num
)
6591 < (DECL_UNIT (*(const_decl_t
const*) unit_decl_2
)->max_occ_cycle_num
))
6593 else if ((DECL_UNIT (*(const_decl_t
const*) unit_decl_1
)->max_occ_cycle_num
)
6594 == (DECL_UNIT (*(const_decl_t
const*) unit_decl_2
)->max_occ_cycle_num
))
6600 /* The function makes heuristic assigning automata to units. Actually
6601 efficacy of the algorithm has been checked yet??? */
6604 units_to_automata_heuristic_distr (void)
6606 double estimation_bound
;
6610 unit_decl_t
*unit_decls
;
6613 if (description
->units_num
== 0)
6615 estimation_bound
= estimate_one_automaton_bound ();
6616 unit_decls
= XNEWVEC (unit_decl_t
, description
->units_num
);
6618 for (i
= 0, j
= 0; i
< description
->decls_num
; i
++)
6619 if (description
->decls
[i
]->mode
== dm_unit
)
6620 unit_decls
[j
++] = DECL_UNIT (description
->decls
[i
]);
6621 gcc_assert (j
== description
->units_num
);
6623 qsort (unit_decls
, description
->units_num
,
6624 sizeof (unit_decl_t
), compare_max_occ_cycle_nums
);
6627 bound_value
= unit_decls
[0]->max_occ_cycle_num
;
6628 unit_decls
[0]->corresponding_automaton_num
= automaton_num
;
6630 for (i
= 1; i
< description
->units_num
; i
++)
6632 rest_units_num
= description
->units_num
- i
+ 1;
6633 gcc_assert (automata_num
- automaton_num
- 1 <= rest_units_num
);
6634 if (automaton_num
< automata_num
- 1
6635 && ((automata_num
- automaton_num
- 1 == rest_units_num
)
6638 / unit_decls
[i
]->max_occ_cycle_num
))))
6640 bound_value
= unit_decls
[i
]->max_occ_cycle_num
;
6644 bound_value
*= unit_decls
[i
]->max_occ_cycle_num
;
6645 unit_decls
[i
]->corresponding_automaton_num
= automaton_num
;
6647 gcc_assert (automaton_num
== automata_num
- 1);
6651 /* The functions creates automaton insns for each automata. Automaton
6652 insn is simply insn for given automaton which makes reservation
6653 only of units of the automaton. */
6655 create_ainsns (automaton_t automaton
)
6658 ainsn_t first_ainsn
;
6665 for (i
= 0; i
< description
->decls_num
; i
++)
6667 decl
= description
->decls
[i
];
6668 if (decl
->mode
== dm_insn_reserv
)
6670 curr_ainsn
= XCREATENODE (struct ainsn
);
6671 curr_ainsn
->insn_reserv_decl
= DECL_INSN_RESERV (decl
);
6672 curr_ainsn
->important_p
= FALSE
;
6673 curr_ainsn
->next_ainsn
= NULL
;
6674 if (prev_ainsn
== NULL
)
6675 first_ainsn
= curr_ainsn
;
6677 prev_ainsn
->next_ainsn
= curr_ainsn
;
6678 if (decl
== advance_cycle_insn_decl
)
6679 automaton
->advance_ainsn
= curr_ainsn
;
6680 else if (decl
== collapse_ndfa_insn_decl
)
6681 automaton
->collapse_ainsn
= curr_ainsn
;
6682 prev_ainsn
= curr_ainsn
;
6685 automaton
->ainsn_list
= first_ainsn
;
6688 /* The function assigns automata to units according to constructions
6689 `define_automaton' in the description. */
6691 units_to_automata_distr (void)
6696 for (i
= 0; i
< description
->decls_num
; i
++)
6698 decl
= description
->decls
[i
];
6699 if (decl
->mode
== dm_unit
)
6701 if (DECL_UNIT (decl
)->automaton_decl
== NULL
6702 || (DECL_UNIT (decl
)->automaton_decl
->corresponding_automaton
6704 /* Distribute to the first automaton. */
6705 DECL_UNIT (decl
)->corresponding_automaton_num
= 0;
6707 DECL_UNIT (decl
)->corresponding_automaton_num
6708 = (DECL_UNIT (decl
)->automaton_decl
6709 ->corresponding_automaton
->automaton_order_num
);
6714 /* The function creates DFA(s) for fast pipeline hazards recognition
6715 after checking and simplifying IR of the description. */
6717 create_automata (void)
6719 automaton_t curr_automaton
;
6720 automaton_t prev_automaton
;
6722 int curr_automaton_num
;
6725 if (automata_num
!= 0)
6727 units_to_automata_heuristic_distr ();
6728 for (prev_automaton
= NULL
, curr_automaton_num
= 0;
6729 curr_automaton_num
< automata_num
;
6730 curr_automaton_num
++, prev_automaton
= curr_automaton
)
6732 curr_automaton
= XCREATENODE (struct automaton
);
6733 create_ainsns (curr_automaton
);
6734 curr_automaton
->corresponding_automaton_decl
= NULL
;
6735 curr_automaton
->next_automaton
= NULL
;
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
;
6745 curr_automaton_num
= 0;
6746 prev_automaton
= NULL
;
6747 for (i
= 0; i
< description
->decls_num
; i
++)
6749 decl
= description
->decls
[i
];
6750 if (decl
->mode
== dm_automaton
6751 && DECL_AUTOMATON (decl
)->automaton_is_used
)
6753 curr_automaton
= XCREATENODE (struct automaton
);
6754 create_ainsns (curr_automaton
);
6755 curr_automaton
->corresponding_automaton_decl
6756 = DECL_AUTOMATON (decl
);
6757 curr_automaton
->next_automaton
= NULL
;
6758 DECL_AUTOMATON (decl
)->corresponding_automaton
= curr_automaton
;
6759 curr_automaton
->automaton_order_num
= curr_automaton_num
;
6760 if (prev_automaton
== NULL
)
6761 description
->first_automaton
= curr_automaton
;
6763 prev_automaton
->next_automaton
= curr_automaton
;
6764 curr_automaton_num
++;
6765 prev_automaton
= curr_automaton
;
6768 if (curr_automaton_num
== 0)
6770 curr_automaton
= XCREATENODE (struct automaton
);
6771 create_ainsns (curr_automaton
);
6772 curr_automaton
->corresponding_automaton_decl
= NULL
;
6773 curr_automaton
->next_automaton
= NULL
;
6774 description
->first_automaton
= curr_automaton
;
6776 units_to_automata_distr ();
6778 NDFA_time
= create_ticker ();
6779 ticker_off (&NDFA_time
);
6780 NDFA_to_DFA_time
= create_ticker ();
6781 ticker_off (&NDFA_to_DFA_time
);
6782 minimize_time
= create_ticker ();
6783 ticker_off (&minimize_time
);
6784 equiv_time
= create_ticker ();
6785 ticker_off (&equiv_time
);
6786 for (curr_automaton
= description
->first_automaton
;
6787 curr_automaton
!= NULL
;
6788 curr_automaton
= curr_automaton
->next_automaton
)
6792 if (curr_automaton
->corresponding_automaton_decl
== NULL
)
6793 fprintf (stderr
, "Prepare anonymous automaton creation ... ");
6795 fprintf (stderr
, "Prepare automaton `%s' creation...",
6796 curr_automaton
->corresponding_automaton_decl
->name
);
6798 create_alt_states (curr_automaton
);
6799 form_ainsn_with_same_reservs (curr_automaton
);
6801 fprintf (stderr
, "done\n");
6802 build_automaton (curr_automaton
);
6803 enumerate_states (curr_automaton
);
6804 ticker_on (&equiv_time
);
6805 set_insn_equiv_classes (curr_automaton
);
6806 ticker_off (&equiv_time
);
6812 /* This page contains code for forming string representation of
6813 regexp. The representation is formed on IR obstack. So you should
6814 not work with IR obstack between regexp_representation and
6815 finish_regexp_representation calls. */
6817 /* This recursive function forms string representation of regexp
6818 (without tailing '\0'). */
6820 form_regexp (regexp_t regexp
)
6824 switch (regexp
->mode
)
6826 case rm_unit
: case rm_reserv
:
6828 const char *name
= (regexp
->mode
== rm_unit
6829 ? REGEXP_UNIT (regexp
)->name
6830 : REGEXP_RESERV (regexp
)->name
);
6832 obstack_grow (&irp
, name
, strlen (name
));
6837 for (i
= 0; i
< REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
6840 obstack_1grow (&irp
, ',');
6841 form_regexp (REGEXP_SEQUENCE (regexp
)->regexps
[i
]);
6846 obstack_1grow (&irp
, '(');
6847 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
6850 obstack_1grow (&irp
, '+');
6851 if (REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
== rm_sequence
6852 || REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
== rm_oneof
)
6853 obstack_1grow (&irp
, '(');
6854 form_regexp (REGEXP_ALLOF (regexp
)->regexps
[i
]);
6855 if (REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
== rm_sequence
6856 || REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
== rm_oneof
)
6857 obstack_1grow (&irp
, ')');
6859 obstack_1grow (&irp
, ')');
6863 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
6866 obstack_1grow (&irp
, '|');
6867 if (REGEXP_ONEOF (regexp
)->regexps
[i
]->mode
== rm_sequence
)
6868 obstack_1grow (&irp
, '(');
6869 form_regexp (REGEXP_ONEOF (regexp
)->regexps
[i
]);
6870 if (REGEXP_ONEOF (regexp
)->regexps
[i
]->mode
== rm_sequence
)
6871 obstack_1grow (&irp
, ')');
6879 if (REGEXP_REPEAT (regexp
)->regexp
->mode
== rm_sequence
6880 || REGEXP_REPEAT (regexp
)->regexp
->mode
== rm_allof
6881 || REGEXP_REPEAT (regexp
)->regexp
->mode
== rm_oneof
)
6882 obstack_1grow (&irp
, '(');
6883 form_regexp (REGEXP_REPEAT (regexp
)->regexp
);
6884 if (REGEXP_REPEAT (regexp
)->regexp
->mode
== rm_sequence
6885 || REGEXP_REPEAT (regexp
)->regexp
->mode
== rm_allof
6886 || REGEXP_REPEAT (regexp
)->regexp
->mode
== rm_oneof
)
6887 obstack_1grow (&irp
, ')');
6888 sprintf (digits
, "*%d", REGEXP_REPEAT (regexp
)->repeat_num
);
6889 obstack_grow (&irp
, digits
, strlen (digits
));
6894 obstack_grow (&irp
, NOTHING_NAME
, strlen (NOTHING_NAME
));
6902 /* The function returns string representation of REGEXP on IR
6905 regexp_representation (regexp_t regexp
)
6907 form_regexp (regexp
);
6908 obstack_1grow (&irp
, '\0');
6909 return obstack_base (&irp
);
6912 /* The function frees memory allocated for last formed string
6913 representation of regexp. */
6915 finish_regexp_representation (void)
6917 int length
= obstack_object_size (&irp
);
6919 obstack_blank_fast (&irp
, -length
);
6924 /* This page contains code for output PHR (pipeline hazards recognizer). */
6926 /* The function outputs minimal C type which is sufficient for
6927 representation numbers in range min_range_value and
6928 max_range_value. Because host machine and build machine may be
6929 different, we use here minimal values required by ANSI C standard
6930 instead of UCHAR_MAX, SHRT_MAX, SHRT_MIN, etc. This is a good
6934 output_range_type (FILE *f
, long int min_range_value
,
6935 long int max_range_value
)
6937 if (min_range_value
>= 0 && max_range_value
<= 255)
6938 fprintf (f
, "unsigned char");
6939 else if (min_range_value
>= -127 && max_range_value
<= 127)
6940 fprintf (f
, "signed char");
6941 else if (min_range_value
>= 0 && max_range_value
<= 65535)
6942 fprintf (f
, "unsigned short");
6943 else if (min_range_value
>= -32767 && max_range_value
<= 32767)
6944 fprintf (f
, "short");
6949 /* The function outputs all initialization values of VECT. */
6951 output_vect (vla_hwint_t vect
)
6954 size_t vect_length
= VEC_length (vect_el_t
, vect
);
6958 if (vect_length
== 0)
6959 fputs ("0 /* This is dummy el because the vect is empty */", output_file
);
6961 for (i
= 0; i
< vect_length
; i
++)
6963 fprintf (output_file
, "%5ld", (long) VEC_index (vect_el_t
, vect
, i
));
6964 if (els_on_line
== 10)
6967 fputs (",\n", output_file
);
6969 else if (i
< vect_length
-1)
6970 fputs (", ", output_file
);
6975 /* The following is name of the structure which represents DFA(s) for
6977 #define CHIP_NAME "DFA_chip"
6979 /* The following is name of member which represents state of a DFA for
6982 output_chip_member_name (FILE *f
, automaton_t automaton
)
6984 if (automaton
->corresponding_automaton_decl
== NULL
)
6985 fprintf (f
, "automaton_state_%d", automaton
->automaton_order_num
);
6987 fprintf (f
, "%s_automaton_state",
6988 automaton
->corresponding_automaton_decl
->name
);
6991 /* The following is name of temporary variable which stores state of a
6994 output_temp_chip_member_name (FILE *f
, automaton_t automaton
)
6997 output_chip_member_name (f
, automaton
);
7000 /* This is name of macro value which is code of pseudo_insns
7001 representing advancing cpu cycle and collapsing the NDFA.
7002 Its value is used as internal code unknown insn. */
7003 #define ADVANCE_CYCLE_VALUE_NAME "DFA__ADVANCE_CYCLE"
7004 #define COLLAPSE_NDFA_VALUE_NAME "NDFA__COLLAPSE"
7006 /* Output name of translate vector for given automaton. */
7008 output_translate_vect_name (FILE *f
, automaton_t automaton
)
7010 if (automaton
->corresponding_automaton_decl
== NULL
)
7011 fprintf (f
, "translate_%d", automaton
->automaton_order_num
);
7013 fprintf (f
, "%s_translate", automaton
->corresponding_automaton_decl
->name
);
7016 /* Output name for simple transition table representation. */
7018 output_trans_full_vect_name (FILE *f
, automaton_t automaton
)
7020 if (automaton
->corresponding_automaton_decl
== NULL
)
7021 fprintf (f
, "transitions_%d", automaton
->automaton_order_num
);
7023 fprintf (f
, "%s_transitions",
7024 automaton
->corresponding_automaton_decl
->name
);
7027 /* Output name of comb vector of the transition table for given
7030 output_trans_comb_vect_name (FILE *f
, automaton_t automaton
)
7032 if (automaton
->corresponding_automaton_decl
== NULL
)
7033 fprintf (f
, "transitions_%d", automaton
->automaton_order_num
);
7035 fprintf (f
, "%s_transitions",
7036 automaton
->corresponding_automaton_decl
->name
);
7039 /* Output name of check vector of the transition table for given
7042 output_trans_check_vect_name (FILE *f
, automaton_t automaton
)
7044 if (automaton
->corresponding_automaton_decl
== NULL
)
7045 fprintf (f
, "check_%d", automaton
->automaton_order_num
);
7047 fprintf (f
, "%s_check", automaton
->corresponding_automaton_decl
->name
);
7050 /* Output name of base vector of the transition table for given
7053 output_trans_base_vect_name (FILE *f
, automaton_t automaton
)
7055 if (automaton
->corresponding_automaton_decl
== NULL
)
7056 fprintf (f
, "base_%d", automaton
->automaton_order_num
);
7058 fprintf (f
, "%s_base", automaton
->corresponding_automaton_decl
->name
);
7061 /* Output name of simple min issue delay table representation. */
7063 output_min_issue_delay_vect_name (FILE *f
, automaton_t automaton
)
7065 if (automaton
->corresponding_automaton_decl
== NULL
)
7066 fprintf (f
, "min_issue_delay_%d", automaton
->automaton_order_num
);
7068 fprintf (f
, "%s_min_issue_delay",
7069 automaton
->corresponding_automaton_decl
->name
);
7072 /* Output name of deadlock vector for given automaton. */
7074 output_dead_lock_vect_name (FILE *f
, automaton_t automaton
)
7076 if (automaton
->corresponding_automaton_decl
== NULL
)
7077 fprintf (f
, "dead_lock_%d", automaton
->automaton_order_num
);
7079 fprintf (f
, "%s_dead_lock", automaton
->corresponding_automaton_decl
->name
);
7082 /* Output name of reserved units table for AUTOMATON into file F. */
7084 output_reserved_units_table_name (FILE *f
, automaton_t automaton
)
7086 if (automaton
->corresponding_automaton_decl
== NULL
)
7087 fprintf (f
, "reserved_units_%d", automaton
->automaton_order_num
);
7089 fprintf (f
, "%s_reserved_units",
7090 automaton
->corresponding_automaton_decl
->name
);
7093 /* Name of the PHR interface macro. */
7094 #define CPU_UNITS_QUERY_MACRO_NAME "CPU_UNITS_QUERY"
7096 /* Names of an internal functions: */
7097 #define INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME "internal_min_issue_delay"
7099 /* This is external type of DFA(s) state. */
7100 #define STATE_TYPE_NAME "state_t"
7102 #define INTERNAL_TRANSITION_FUNC_NAME "internal_state_transition"
7104 #define INTERNAL_RESET_FUNC_NAME "internal_reset"
7106 #define INTERNAL_DEAD_LOCK_FUNC_NAME "internal_state_dead_lock_p"
7108 #define INTERNAL_INSN_LATENCY_FUNC_NAME "internal_insn_latency"
7110 /* Name of cache of insn dfa codes. */
7111 #define DFA_INSN_CODES_VARIABLE_NAME "dfa_insn_codes"
7113 /* Name of length of cache of insn dfa codes. */
7114 #define DFA_INSN_CODES_LENGTH_VARIABLE_NAME "dfa_insn_codes_length"
7116 /* Names of the PHR interface functions: */
7117 #define SIZE_FUNC_NAME "state_size"
7119 #define TRANSITION_FUNC_NAME "state_transition"
7121 #define MIN_ISSUE_DELAY_FUNC_NAME "min_issue_delay"
7123 #define MIN_INSN_CONFLICT_DELAY_FUNC_NAME "min_insn_conflict_delay"
7125 #define DEAD_LOCK_FUNC_NAME "state_dead_lock_p"
7127 #define RESET_FUNC_NAME "state_reset"
7129 #define INSN_LATENCY_FUNC_NAME "insn_latency"
7131 #define PRINT_RESERVATION_FUNC_NAME "print_reservation"
7133 #define GET_CPU_UNIT_CODE_FUNC_NAME "get_cpu_unit_code"
7135 #define CPU_UNIT_RESERVATION_P_FUNC_NAME "cpu_unit_reservation_p"
7137 #define INSN_HAS_DFA_RESERVATION_P_FUNC_NAME "insn_has_dfa_reservation_p"
7139 #define DFA_CLEAN_INSN_CACHE_FUNC_NAME "dfa_clean_insn_cache"
7141 #define DFA_CLEAR_SINGLE_INSN_CACHE_FUNC_NAME "dfa_clear_single_insn_cache"
7143 #define DFA_START_FUNC_NAME "dfa_start"
7145 #define DFA_FINISH_FUNC_NAME "dfa_finish"
7147 /* Names of parameters of the PHR interface functions. */
7148 #define STATE_NAME "state"
7150 #define INSN_PARAMETER_NAME "insn"
7152 #define INSN2_PARAMETER_NAME "insn2"
7154 #define CHIP_PARAMETER_NAME "chip"
7156 #define FILE_PARAMETER_NAME "f"
7158 #define CPU_UNIT_NAME_PARAMETER_NAME "cpu_unit_name"
7160 #define CPU_CODE_PARAMETER_NAME "cpu_unit_code"
7162 /* Names of the variables whose values are internal insn code of rtx
7164 #define INTERNAL_INSN_CODE_NAME "insn_code"
7166 #define INTERNAL_INSN2_CODE_NAME "insn2_code"
7168 /* Names of temporary variables in some functions. */
7169 #define TEMPORARY_VARIABLE_NAME "temp"
7171 #define I_VARIABLE_NAME "i"
7173 /* Name of result variable in some functions. */
7174 #define RESULT_VARIABLE_NAME "res"
7176 /* Name of function (attribute) to translate insn into internal insn
7178 #define INTERNAL_DFA_INSN_CODE_FUNC_NAME "internal_dfa_insn_code"
7180 /* Name of function (attribute) to translate insn into internal insn
7181 code with caching. */
7182 #define DFA_INSN_CODE_FUNC_NAME "dfa_insn_code"
7184 /* Output C type which is used for representation of codes of states
7187 output_state_member_type (FILE *f
, automaton_t automaton
)
7189 output_range_type (f
, 0, automaton
->achieved_states_num
);
7192 /* Output definition of the structure representing current DFA(s)
7195 output_chip_definitions (void)
7197 automaton_t automaton
;
7199 fprintf (output_file
, "struct %s\n{\n", CHIP_NAME
);
7200 for (automaton
= description
->first_automaton
;
7202 automaton
= automaton
->next_automaton
)
7204 fprintf (output_file
, " ");
7205 output_state_member_type (output_file
, automaton
);
7206 fprintf (output_file
, " ");
7207 output_chip_member_name (output_file
, automaton
);
7208 fprintf (output_file
, ";\n");
7210 fprintf (output_file
, "};\n\n");
7212 fprintf (output_file
, "static struct %s %s;\n\n", CHIP_NAME
, CHIP_NAME
);
7217 /* The function outputs translate vector of internal insn code into
7218 insn equivalence class number. The equivalence class number is
7219 used to access to table and vectors representing DFA(s). */
7221 output_translate_vect (automaton_t automaton
)
7225 vla_hwint_t translate_vect
;
7227 translate_vect
= VEC_alloc (vect_el_t
, heap
, description
->insns_num
);
7229 for (insn_value
= 0; insn_value
< description
->insns_num
; insn_value
++)
7230 /* Undefined value */
7231 VEC_quick_push (vect_el_t
, translate_vect
,
7232 automaton
->insn_equiv_classes_num
);
7234 for (ainsn
= automaton
->ainsn_list
; ainsn
!= NULL
; ainsn
= ainsn
->next_ainsn
)
7235 VEC_replace (vect_el_t
, translate_vect
,
7236 ainsn
->insn_reserv_decl
->insn_num
,
7237 ainsn
->insn_equiv_class_num
);
7239 fprintf (output_file
,
7240 "/* Vector translating external insn codes to internal ones.*/\n");
7241 fprintf (output_file
, "static const ");
7242 output_range_type (output_file
, 0, automaton
->insn_equiv_classes_num
);
7243 fprintf (output_file
, " ");
7244 output_translate_vect_name (output_file
, automaton
);
7245 fprintf (output_file
, "[] ATTRIBUTE_UNUSED = {\n");
7246 output_vect (translate_vect
);
7247 fprintf (output_file
, "};\n\n");
7248 VEC_free (vect_el_t
, heap
, translate_vect
);
7251 /* The value in a table state x ainsn -> something which represents
7253 static int undefined_vect_el_value
;
7255 /* The following function returns nonzero value if the best
7256 representation of the table is comb vector. */
7258 comb_vect_p (state_ainsn_table_t tab
)
7262 return (2 * VEC_length (vect_el_t
, tab
->full_vect
)
7263 > 5 * VEC_length (vect_el_t
, tab
->comb_vect
));
7266 /* The following function creates new table for AUTOMATON. */
7267 static state_ainsn_table_t
7268 create_state_ainsn_table (automaton_t automaton
)
7270 state_ainsn_table_t tab
;
7271 int full_vect_length
;
7274 tab
= XCREATENODE (struct state_ainsn_table
);
7275 tab
->automaton
= automaton
;
7277 tab
->comb_vect
= VEC_alloc (vect_el_t
, heap
, 10000);
7278 tab
->check_vect
= VEC_alloc (vect_el_t
, heap
, 10000);
7281 VEC_safe_grow (vect_el_t
, heap
, tab
->base_vect
,
7282 automaton
->achieved_states_num
);
7284 full_vect_length
= (automaton
->insn_equiv_classes_num
7285 * automaton
->achieved_states_num
);
7286 tab
->full_vect
= VEC_alloc (vect_el_t
, heap
, full_vect_length
);
7287 for (i
= 0; i
< full_vect_length
; i
++)
7288 VEC_quick_push (vect_el_t
, tab
->full_vect
, undefined_vect_el_value
);
7290 tab
->min_base_vect_el_value
= 0;
7291 tab
->max_base_vect_el_value
= 0;
7292 tab
->min_comb_vect_el_value
= 0;
7293 tab
->max_comb_vect_el_value
= 0;
7297 /* The following function outputs the best C representation of the
7298 table TAB of given TABLE_NAME. */
7300 output_state_ainsn_table (state_ainsn_table_t tab
, const char *table_name
,
7301 void (*output_full_vect_name_func
) (FILE *, automaton_t
),
7302 void (*output_comb_vect_name_func
) (FILE *, automaton_t
),
7303 void (*output_check_vect_name_func
) (FILE *, automaton_t
),
7304 void (*output_base_vect_name_func
) (FILE *, automaton_t
))
7306 if (!comb_vect_p (tab
))
7308 fprintf (output_file
, "/* Vector for %s. */\n", table_name
);
7309 fprintf (output_file
, "static const ");
7310 output_range_type (output_file
, tab
->min_comb_vect_el_value
,
7311 tab
->max_comb_vect_el_value
);
7312 fprintf (output_file
, " ");
7313 (*output_full_vect_name_func
) (output_file
, tab
->automaton
);
7314 fprintf (output_file
, "[] ATTRIBUTE_UNUSED = {\n");
7315 output_vect (tab
->full_vect
);
7316 fprintf (output_file
, "};\n\n");
7320 fprintf (output_file
, "/* Comb vector for %s. */\n", table_name
);
7321 fprintf (output_file
, "static const ");
7322 output_range_type (output_file
, tab
->min_comb_vect_el_value
,
7323 tab
->max_comb_vect_el_value
);
7324 fprintf (output_file
, " ");
7325 (*output_comb_vect_name_func
) (output_file
, tab
->automaton
);
7326 fprintf (output_file
, "[] ATTRIBUTE_UNUSED = {\n");
7327 output_vect (tab
->comb_vect
);
7328 fprintf (output_file
, "};\n\n");
7329 fprintf (output_file
, "/* Check vector for %s. */\n", table_name
);
7330 fprintf (output_file
, "static const ");
7331 output_range_type (output_file
, 0, tab
->automaton
->achieved_states_num
);
7332 fprintf (output_file
, " ");
7333 (*output_check_vect_name_func
) (output_file
, tab
->automaton
);
7334 fprintf (output_file
, "[] = {\n");
7335 output_vect (tab
->check_vect
);
7336 fprintf (output_file
, "};\n\n");
7337 fprintf (output_file
, "/* Base vector for %s. */\n", table_name
);
7338 fprintf (output_file
, "static const ");
7339 output_range_type (output_file
, tab
->min_base_vect_el_value
,
7340 tab
->max_base_vect_el_value
);
7341 fprintf (output_file
, " ");
7342 (*output_base_vect_name_func
) (output_file
, tab
->automaton
);
7343 fprintf (output_file
, "[] = {\n");
7344 output_vect (tab
->base_vect
);
7345 fprintf (output_file
, "};\n\n");
7349 /* The following function adds vector VECT to table TAB as its line
7350 with number VECT_NUM. */
7352 add_vect (state_ainsn_table_t tab
, int vect_num
, vla_hwint_t vect
)
7355 size_t real_vect_length
;
7356 int comb_vect_index
;
7357 int comb_vect_els_num
;
7359 int first_unempty_vect_index
;
7360 int additional_els_num
;
7364 unsigned long vect_mask
, comb_vect_mask
;
7366 vect_length
= VEC_length (vect_el_t
, vect
);
7367 gcc_assert (vect_length
);
7368 gcc_assert (VEC_last (vect_el_t
, vect
) != undefined_vect_el_value
);
7369 real_vect_length
= tab
->automaton
->insn_equiv_classes_num
;
7370 /* Form full vector in the table: */
7372 size_t full_base
= tab
->automaton
->insn_equiv_classes_num
* vect_num
;
7373 if (VEC_length (vect_el_t
, tab
->full_vect
) < full_base
+ vect_length
)
7374 VEC_safe_grow (vect_el_t
, heap
, tab
->full_vect
,
7375 full_base
+ vect_length
);
7376 for (i
= 0; i
< vect_length
; i
++)
7377 VEC_replace (vect_el_t
, tab
->full_vect
, full_base
+ i
,
7378 VEC_index (vect_el_t
, vect
, i
));
7381 /* The comb_vect min/max values are also used for the full vector, so
7382 compute them now. */
7383 for (vect_index
= 0; vect_index
< vect_length
; vect_index
++)
7384 if (VEC_index (vect_el_t
, vect
, vect_index
) != undefined_vect_el_value
)
7386 vect_el_t x
= VEC_index (vect_el_t
, vect
, vect_index
);
7387 gcc_assert (x
>= 0);
7388 if (tab
->max_comb_vect_el_value
< x
)
7389 tab
->max_comb_vect_el_value
= x
;
7390 if (tab
->min_comb_vect_el_value
> x
)
7391 tab
->min_comb_vect_el_value
= x
;
7396 /* Form comb vector in the table: */
7397 gcc_assert (VEC_length (vect_el_t
, tab
->comb_vect
)
7398 == VEC_length (vect_el_t
, tab
->check_vect
));
7400 comb_vect_els_num
= VEC_length (vect_el_t
, tab
->comb_vect
);
7401 for (first_unempty_vect_index
= 0;
7402 first_unempty_vect_index
< vect_length
;
7403 first_unempty_vect_index
++)
7404 if (VEC_index (vect_el_t
, vect
, first_unempty_vect_index
)
7405 != undefined_vect_el_value
)
7408 /* Search for the place in comb vect for the inserted vect. */
7411 if (vect_length
- first_unempty_vect_index
>= SIZEOF_LONG
* CHAR_BIT
)
7413 for (comb_vect_index
= 0;
7414 comb_vect_index
< comb_vect_els_num
;
7417 for (vect_index
= first_unempty_vect_index
;
7418 vect_index
< vect_length
7419 && vect_index
+ comb_vect_index
< comb_vect_els_num
;
7421 if (VEC_index (vect_el_t
, vect
, vect_index
)
7422 != undefined_vect_el_value
7423 && (VEC_index (vect_el_t
, tab
->comb_vect
,
7424 vect_index
+ comb_vect_index
)
7425 != undefined_vect_el_value
))
7427 if (vect_index
>= vect_length
7428 || vect_index
+ comb_vect_index
>= comb_vect_els_num
)
7436 for (vect_index
= first_unempty_vect_index
;
7437 vect_index
< vect_length
;
7440 vect_mask
= vect_mask
<< 1;
7441 if (VEC_index (vect_el_t
, vect
, vect_index
) != undefined_vect_el_value
)
7445 /* Search for the place in comb vect for the inserted vect. */
7446 comb_vect_index
= 0;
7447 if (comb_vect_els_num
== 0)
7451 for (vect_index
= first_unempty_vect_index
;
7452 vect_index
< vect_length
&& vect_index
< comb_vect_els_num
;
7455 comb_vect_mask
<<= 1;
7456 if (vect_index
+ comb_vect_index
< comb_vect_els_num
7457 && VEC_index (vect_el_t
, tab
->comb_vect
, vect_index
+ comb_vect_index
)
7458 != undefined_vect_el_value
)
7459 comb_vect_mask
|= 1;
7461 if ((vect_mask
& comb_vect_mask
) == 0)
7464 for (comb_vect_index
= 1, i
= vect_length
; i
< comb_vect_els_num
;
7465 comb_vect_index
++, i
++)
7467 comb_vect_mask
= (comb_vect_mask
<< 1) | 1;
7468 comb_vect_mask
^= (VEC_index (vect_el_t
, tab
->comb_vect
, i
)
7469 == undefined_vect_el_value
);
7470 if ((vect_mask
& comb_vect_mask
) == 0)
7473 for ( ; comb_vect_index
< comb_vect_els_num
; comb_vect_index
++)
7475 comb_vect_mask
<<= 1;
7476 if ((vect_mask
& comb_vect_mask
) == 0)
7481 /* Slot was found. */
7482 additional_els_num
= comb_vect_index
+ real_vect_length
- comb_vect_els_num
;
7483 if (additional_els_num
< 0)
7484 additional_els_num
= 0;
7485 /* Expand comb and check vectors. */
7486 vect_el
= undefined_vect_el_value
;
7487 no_state_value
= tab
->automaton
->achieved_states_num
;
7488 while (additional_els_num
> 0)
7490 VEC_safe_push (vect_el_t
, heap
, tab
->comb_vect
, vect_el
);
7491 VEC_safe_push (vect_el_t
, heap
, tab
->check_vect
, no_state_value
);
7492 additional_els_num
--;
7494 gcc_assert (VEC_length (vect_el_t
, tab
->comb_vect
)
7495 >= comb_vect_index
+ real_vect_length
);
7496 /* Fill comb and check vectors. */
7497 for (vect_index
= 0; vect_index
< vect_length
; vect_index
++)
7498 if (VEC_index (vect_el_t
, vect
, vect_index
) != undefined_vect_el_value
)
7500 vect_el_t x
= VEC_index (vect_el_t
, vect
, vect_index
);
7501 gcc_assert (VEC_index (vect_el_t
, tab
->comb_vect
,
7502 comb_vect_index
+ vect_index
)
7503 == undefined_vect_el_value
);
7504 gcc_assert (x
>= 0);
7505 VEC_replace (vect_el_t
, tab
->comb_vect
,
7506 comb_vect_index
+ vect_index
, x
);
7507 VEC_replace (vect_el_t
, tab
->check_vect
,
7508 comb_vect_index
+ vect_index
, vect_num
);
7510 if (tab
->max_comb_vect_el_value
< undefined_vect_el_value
)
7511 tab
->max_comb_vect_el_value
= undefined_vect_el_value
;
7512 if (tab
->min_comb_vect_el_value
> undefined_vect_el_value
)
7513 tab
->min_comb_vect_el_value
= undefined_vect_el_value
;
7514 if (tab
->max_base_vect_el_value
< comb_vect_index
)
7515 tab
->max_base_vect_el_value
= comb_vect_index
;
7516 if (tab
->min_base_vect_el_value
> comb_vect_index
)
7517 tab
->min_base_vect_el_value
= comb_vect_index
;
7519 VEC_replace (vect_el_t
, tab
->base_vect
, vect_num
, comb_vect_index
);
7522 /* Return number of out arcs of STATE. */
7524 out_state_arcs_num (const_state_t state
)
7530 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
7532 gcc_assert (arc
->insn
);
7533 if (arc
->insn
->first_ainsn_with_given_equivalence_num
)
7539 /* Compare number of possible transitions from the states. */
7541 compare_transition_els_num (const void *state_ptr_1
,
7542 const void *state_ptr_2
)
7544 const int transition_els_num_1
7545 = out_state_arcs_num (*(const_state_t
const*) state_ptr_1
);
7546 const int transition_els_num_2
7547 = out_state_arcs_num (*(const_state_t
const*) state_ptr_2
);
7549 if (transition_els_num_1
< transition_els_num_2
)
7551 else if (transition_els_num_1
== transition_els_num_2
)
7557 /* The function adds element EL_VALUE to vector VECT for a table state
7560 add_vect_el (vla_hwint_t
*vect
, ainsn_t ainsn
, int el_value
)
7562 int equiv_class_num
;
7566 equiv_class_num
= ainsn
->insn_equiv_class_num
;
7567 for (vect_index
= VEC_length (vect_el_t
, *vect
);
7568 vect_index
<= equiv_class_num
;
7570 VEC_safe_push (vect_el_t
, heap
, *vect
, undefined_vect_el_value
);
7571 VEC_replace (vect_el_t
, *vect
, equiv_class_num
, el_value
);
7574 /* This is for forming vector of states of an automaton. */
7575 static VEC(state_t
, heap
) *output_states_vect
;
7577 /* The function is called by function pass_states. The function adds
7578 STATE to `output_states_vect'. */
7580 add_states_vect_el (state_t state
)
7582 VEC_safe_push (state_t
, heap
, output_states_vect
, state
);
7585 /* Form and output vectors (comb, check, base or full vector)
7586 representing transition table of AUTOMATON. */
7588 output_trans_table (automaton_t automaton
)
7592 vla_hwint_t transition_vect
= 0;
7594 undefined_vect_el_value
= automaton
->achieved_states_num
;
7595 automaton
->trans_table
= create_state_ainsn_table (automaton
);
7596 /* Create vect of pointers to states ordered by num of transitions
7597 from the state (state with the maximum num is the first). */
7598 output_states_vect
= 0;
7599 pass_states (automaton
, add_states_vect_el
);
7600 VEC_qsort (state_t
, output_states_vect
, compare_transition_els_num
);
7602 for (i
= 0; i
< VEC_length (state_t
, output_states_vect
); i
++)
7604 VEC_truncate (vect_el_t
, transition_vect
, 0);
7605 for (arc
= first_out_arc (VEC_index (state_t
, output_states_vect
, i
));
7607 arc
= next_out_arc (arc
))
7609 gcc_assert (arc
->insn
);
7610 if (arc
->insn
->first_ainsn_with_given_equivalence_num
)
7611 add_vect_el (&transition_vect
, arc
->insn
,
7612 arc
->to_state
->order_state_num
);
7614 add_vect (automaton
->trans_table
,
7615 VEC_index (state_t
, output_states_vect
, i
)->order_state_num
,
7618 output_state_ainsn_table
7619 (automaton
->trans_table
, "state transitions",
7620 output_trans_full_vect_name
, output_trans_comb_vect_name
,
7621 output_trans_check_vect_name
, output_trans_base_vect_name
);
7623 VEC_free (state_t
, heap
, output_states_vect
);
7624 VEC_free (vect_el_t
, heap
, transition_vect
);
7627 /* Form and output vectors representing minimal issue delay table of
7628 AUTOMATON. The table is state x ainsn -> minimal issue delay of
7631 output_min_issue_delay_table (automaton_t automaton
)
7633 vla_hwint_t min_issue_delay_vect
;
7634 vla_hwint_t compressed_min_issue_delay_vect
;
7637 size_t min_issue_delay_len
, compressed_min_issue_delay_len
;
7641 /* Create vect of pointers to states ordered by num of transitions
7642 from the state (state with the maximum num is the first). */
7643 output_states_vect
= 0;
7644 pass_states (automaton
, add_states_vect_el
);
7646 min_issue_delay_len
= (VEC_length (state_t
, output_states_vect
)
7647 * automaton
->insn_equiv_classes_num
);
7648 min_issue_delay_vect
= VEC_alloc (vect_el_t
, heap
, min_issue_delay_len
);
7649 for (i
= 0; i
< min_issue_delay_len
; i
++)
7650 VEC_quick_push (vect_el_t
, min_issue_delay_vect
, -1);
7652 automaton
->max_min_delay
= 0;
7660 for (state_no
= 0; state_no
< VEC_length (state_t
, output_states_vect
);
7663 state_t s
= VEC_index (state_t
, output_states_vect
, state_no
);
7666 for (arc
= first_out_arc (s
); arc
; arc
= next_out_arc (arc
))
7670 size_t asn
= s
->order_state_num
7671 * automaton
->insn_equiv_classes_num
7672 + arc
->insn
->insn_equiv_class_num
;
7674 if (VEC_index (vect_el_t
, min_issue_delay_vect
, asn
))
7676 VEC_replace (vect_el_t
, min_issue_delay_vect
, asn
, 0);
7680 for (k
= 0; k
< automaton
->insn_equiv_classes_num
; k
++)
7683 vect_el_t delay0
, delay1
;
7685 n0
= s
->order_state_num
7686 * automaton
->insn_equiv_classes_num
7688 n1
= arc
->to_state
->order_state_num
7689 * automaton
->insn_equiv_classes_num
7691 delay0
= VEC_index (vect_el_t
, min_issue_delay_vect
, n0
);
7692 delay1
= VEC_index (vect_el_t
, min_issue_delay_vect
, n1
);
7695 if (arc
->insn
->insn_reserv_decl
7696 == DECL_INSN_RESERV (advance_cycle_insn_decl
))
7698 if (delay1
< delay0
|| delay0
== -1)
7700 VEC_replace (vect_el_t
, min_issue_delay_vect
, n0
, delay1
);
7710 automaton
->max_min_delay
= 0;
7712 for (ainsn
= automaton
->ainsn_list
; ainsn
; ainsn
= ainsn
->next_ainsn
)
7713 if (ainsn
->first_ainsn_with_given_equivalence_num
)
7715 for (i
= 0; i
< VEC_length (state_t
, output_states_vect
); i
++)
7717 state_t s
= VEC_index (state_t
, output_states_vect
, i
);
7718 size_t np
= s
->order_state_num
7719 * automaton
->insn_equiv_classes_num
7720 + ainsn
->insn_equiv_class_num
;
7721 vect_el_t x
= VEC_index (vect_el_t
, min_issue_delay_vect
, np
);
7723 if (automaton
->max_min_delay
< x
)
7724 automaton
->max_min_delay
= x
;
7726 VEC_replace (vect_el_t
, min_issue_delay_vect
, np
, 0);
7730 fprintf (output_file
, "/* Vector of min issue delay of insns. */\n");
7731 fprintf (output_file
, "static const ");
7732 output_range_type (output_file
, 0, automaton
->max_min_delay
);
7733 fprintf (output_file
, " ");
7734 output_min_issue_delay_vect_name (output_file
, automaton
);
7735 fprintf (output_file
, "[] ATTRIBUTE_UNUSED = {\n");
7736 /* Compress the vector. */
7737 if (automaton
->max_min_delay
< 2)
7739 else if (automaton
->max_min_delay
< 4)
7741 else if (automaton
->max_min_delay
< 16)
7745 automaton
->min_issue_delay_table_compression_factor
= cfactor
;
7747 compressed_min_issue_delay_len
= (min_issue_delay_len
+cfactor
-1) / cfactor
;
7748 compressed_min_issue_delay_vect
7749 = VEC_alloc (vect_el_t
, heap
, compressed_min_issue_delay_len
);
7751 for (i
= 0; i
< compressed_min_issue_delay_len
; i
++)
7752 VEC_quick_push (vect_el_t
, compressed_min_issue_delay_vect
, 0);
7754 for (i
= 0; i
< min_issue_delay_len
; i
++)
7756 size_t ci
= i
/ cfactor
;
7757 vect_el_t x
= VEC_index (vect_el_t
, min_issue_delay_vect
, i
);
7758 vect_el_t cx
= VEC_index (vect_el_t
, compressed_min_issue_delay_vect
, ci
);
7760 cx
|= x
<< (8 - (i
% cfactor
+ 1) * (8 / cfactor
));
7761 VEC_replace (vect_el_t
, compressed_min_issue_delay_vect
, ci
, cx
);
7763 output_vect (compressed_min_issue_delay_vect
);
7764 fprintf (output_file
, "};\n\n");
7765 VEC_free (state_t
, heap
, output_states_vect
);
7766 VEC_free (vect_el_t
, heap
, min_issue_delay_vect
);
7767 VEC_free (vect_el_t
, heap
, compressed_min_issue_delay_vect
);
7770 /* Form and output vector representing the locked states of
7773 output_dead_lock_vect (automaton_t automaton
)
7777 vla_hwint_t dead_lock_vect
= 0;
7779 /* Create vect of pointers to states ordered by num of
7780 transitions from the state (state with the maximum num is the
7782 automaton
->locked_states
= 0;
7783 output_states_vect
= 0;
7784 pass_states (automaton
, add_states_vect_el
);
7786 VEC_safe_grow (vect_el_t
, heap
, dead_lock_vect
,
7787 VEC_length (state_t
, output_states_vect
));
7788 for (i
= 0; i
< VEC_length (state_t
, output_states_vect
); i
++)
7790 state_t s
= VEC_index (state_t
, output_states_vect
, i
);
7791 arc
= first_out_arc (s
);
7793 if (next_out_arc (arc
) == NULL
7794 && (arc
->insn
->insn_reserv_decl
7795 == DECL_INSN_RESERV (advance_cycle_insn_decl
)))
7797 VEC_replace (vect_el_t
, dead_lock_vect
, s
->order_state_num
, 1);
7798 automaton
->locked_states
++;
7801 VEC_replace (vect_el_t
, dead_lock_vect
, s
->order_state_num
, 0);
7803 if (automaton
->locked_states
== 0)
7806 fprintf (output_file
, "/* Vector for locked state flags. */\n");
7807 fprintf (output_file
, "static const ");
7808 output_range_type (output_file
, 0, 1);
7809 fprintf (output_file
, " ");
7810 output_dead_lock_vect_name (output_file
, automaton
);
7811 fprintf (output_file
, "[] = {\n");
7812 output_vect (dead_lock_vect
);
7813 fprintf (output_file
, "};\n\n");
7814 VEC_free (state_t
, heap
, output_states_vect
);
7815 VEC_free (vect_el_t
, heap
, dead_lock_vect
);
7818 /* Form and output vector representing reserved units of the states of
7821 output_reserved_units_table (automaton_t automaton
)
7823 vla_hwint_t reserved_units_table
= 0;
7824 int state_byte_size
;
7825 int reserved_units_size
;
7829 if (description
->query_units_num
== 0)
7832 /* Create vect of pointers to states. */
7833 output_states_vect
= 0;
7834 pass_states (automaton
, add_states_vect_el
);
7835 /* Create vector. */
7836 state_byte_size
= (description
->query_units_num
+ 7) / 8;
7837 reserved_units_size
= (VEC_length (state_t
, output_states_vect
)
7840 reserved_units_table
= VEC_alloc (vect_el_t
, heap
, reserved_units_size
);
7842 for (i
= 0; i
< reserved_units_size
; i
++)
7843 VEC_quick_push (vect_el_t
, reserved_units_table
, 0);
7844 for (n
= 0; n
< VEC_length (state_t
, output_states_vect
); n
++)
7846 state_t s
= VEC_index (state_t
, output_states_vect
, n
);
7847 for (i
= 0; i
< description
->units_num
; i
++)
7848 if (units_array
[i
]->query_p
7849 && first_cycle_unit_presence (s
, i
))
7851 int ri
= (s
->order_state_num
* state_byte_size
7852 + units_array
[i
]->query_num
/ 8);
7853 vect_el_t x
= VEC_index (vect_el_t
, reserved_units_table
, ri
);
7855 x
+= 1 << (units_array
[i
]->query_num
% 8);
7856 VEC_replace (vect_el_t
, reserved_units_table
, ri
, x
);
7859 fprintf (output_file
, "\n#if %s\n", CPU_UNITS_QUERY_MACRO_NAME
);
7860 fprintf (output_file
, "/* Vector for reserved units of states. */\n");
7861 fprintf (output_file
, "static const ");
7862 output_range_type (output_file
, 0, 255);
7863 fprintf (output_file
, " ");
7864 output_reserved_units_table_name (output_file
, automaton
);
7865 fprintf (output_file
, "[] = {\n");
7866 output_vect (reserved_units_table
);
7867 fprintf (output_file
, "};\n#endif /* #if %s */\n\n",
7868 CPU_UNITS_QUERY_MACRO_NAME
);
7870 VEC_free (state_t
, heap
, output_states_vect
);
7871 VEC_free (vect_el_t
, heap
, reserved_units_table
);
7874 /* The function outputs all tables representing DFA(s) used for fast
7875 pipeline hazards recognition. */
7877 output_tables (void)
7879 automaton_t automaton
;
7881 for (automaton
= description
->first_automaton
;
7883 automaton
= automaton
->next_automaton
)
7885 output_translate_vect (automaton
);
7886 output_trans_table (automaton
);
7887 output_min_issue_delay_table (automaton
);
7888 output_dead_lock_vect (automaton
);
7889 output_reserved_units_table (automaton
);
7891 fprintf (output_file
, "\n#define %s %d\n\n", ADVANCE_CYCLE_VALUE_NAME
,
7892 DECL_INSN_RESERV (advance_cycle_insn_decl
)->insn_num
);
7894 fprintf (output_file
, "\n#define %s %d\n\n", COLLAPSE_NDFA_VALUE_NAME
,
7895 DECL_INSN_RESERV (collapse_ndfa_insn_decl
)->insn_num
);
7898 /* The function outputs definition and value of PHR interface variable
7899 `max_insn_queue_index'. Its value is not less than maximal queue
7900 length needed for the insn scheduler. */
7902 output_max_insn_queue_index_def (void)
7904 int i
, max
, latency
;
7907 max
= description
->max_insn_reserv_cycles
;
7908 for (i
= 0; i
< description
->decls_num
; i
++)
7910 decl
= description
->decls
[i
];
7911 if (decl
->mode
== dm_insn_reserv
&& decl
!= advance_cycle_insn_decl
)
7913 latency
= DECL_INSN_RESERV (decl
)->default_latency
;
7917 else if (decl
->mode
== dm_bypass
)
7919 latency
= DECL_BYPASS (decl
)->latency
;
7924 for (i
= 0; (1 << i
) <= max
; i
++)
7926 gcc_assert (i
>= 0);
7927 fprintf (output_file
, "\nconst int max_insn_queue_index = %d;\n\n",
7931 /* The function outputs switch cases for insn reservations using
7932 function *output_automata_list_code. */
7934 output_insn_code_cases (void (*output_automata_list_code
)
7935 (automata_list_el_t
))
7940 for (i
= 0; i
< description
->decls_num
; i
++)
7942 decl
= description
->decls
[i
];
7943 if (decl
->mode
== dm_insn_reserv
)
7944 DECL_INSN_RESERV (decl
)->processed_p
= FALSE
;
7946 for (i
= 0; i
< description
->decls_num
; i
++)
7948 decl
= description
->decls
[i
];
7949 if (decl
->mode
== dm_insn_reserv
7950 && !DECL_INSN_RESERV (decl
)->processed_p
)
7952 for (j
= i
; j
< description
->decls_num
; j
++)
7954 decl2
= description
->decls
[j
];
7955 if (decl2
->mode
== dm_insn_reserv
7956 && (DECL_INSN_RESERV (decl2
)->important_automata_list
7957 == DECL_INSN_RESERV (decl
)->important_automata_list
))
7959 DECL_INSN_RESERV (decl2
)->processed_p
= TRUE
;
7960 fprintf (output_file
, " case %d: /* %s */\n",
7961 DECL_INSN_RESERV (decl2
)->insn_num
,
7962 DECL_INSN_RESERV (decl2
)->name
);
7965 (*output_automata_list_code
)
7966 (DECL_INSN_RESERV (decl
)->important_automata_list
);
7972 /* The function outputs a code for evaluation of a minimal delay of
7973 issue of insns which have reservations in given AUTOMATA_LIST. */
7975 output_automata_list_min_issue_delay_code (automata_list_el_t automata_list
)
7977 automata_list_el_t el
;
7978 automaton_t automaton
;
7980 for (el
= automata_list
; el
!= NULL
; el
= el
->next_automata_list_el
)
7982 automaton
= el
->automaton
;
7983 fprintf (output_file
, "\n %s = ", TEMPORARY_VARIABLE_NAME
);
7984 output_min_issue_delay_vect_name (output_file
, automaton
);
7985 fprintf (output_file
,
7986 (automaton
->min_issue_delay_table_compression_factor
!= 1
7988 output_translate_vect_name (output_file
, automaton
);
7989 fprintf (output_file
, " [%s] + ", INTERNAL_INSN_CODE_NAME
);
7990 fprintf (output_file
, "%s->", CHIP_PARAMETER_NAME
);
7991 output_chip_member_name (output_file
, automaton
);
7992 fprintf (output_file
, " * %d", automaton
->insn_equiv_classes_num
);
7993 if (automaton
->min_issue_delay_table_compression_factor
== 1)
7994 fprintf (output_file
, "];\n");
7997 fprintf (output_file
, ") / %d];\n",
7998 automaton
->min_issue_delay_table_compression_factor
);
7999 fprintf (output_file
, " %s = (%s >> (8 - ((",
8000 TEMPORARY_VARIABLE_NAME
, TEMPORARY_VARIABLE_NAME
);
8001 output_translate_vect_name (output_file
, automaton
);
8002 fprintf (output_file
, " [%s] + ", INTERNAL_INSN_CODE_NAME
);
8003 fprintf (output_file
, "%s->", CHIP_PARAMETER_NAME
);
8004 output_chip_member_name (output_file
, automaton
);
8005 fprintf (output_file
, " * %d)", automaton
->insn_equiv_classes_num
);
8007 (output_file
, " %% %d + 1) * %d)) & %d;\n",
8008 automaton
->min_issue_delay_table_compression_factor
,
8009 8 / automaton
->min_issue_delay_table_compression_factor
,
8010 (1 << (8 / automaton
->min_issue_delay_table_compression_factor
))
8013 if (el
== automata_list
)
8014 fprintf (output_file
, " %s = %s;\n",
8015 RESULT_VARIABLE_NAME
, TEMPORARY_VARIABLE_NAME
);
8018 fprintf (output_file
, " if (%s > %s)\n",
8019 TEMPORARY_VARIABLE_NAME
, RESULT_VARIABLE_NAME
);
8020 fprintf (output_file
, " %s = %s;\n",
8021 RESULT_VARIABLE_NAME
, TEMPORARY_VARIABLE_NAME
);
8024 fprintf (output_file
, " break;\n\n");
8027 /* Output function `internal_min_issue_delay'. */
8029 output_internal_min_issue_delay_func (void)
8031 fprintf (output_file
,
8032 "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
8033 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
8034 CHIP_NAME
, CHIP_PARAMETER_NAME
);
8035 fprintf (output_file
, "{\n int %s ATTRIBUTE_UNUSED;\n int %s = -1;\n",
8036 TEMPORARY_VARIABLE_NAME
, RESULT_VARIABLE_NAME
);
8037 fprintf (output_file
, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME
);
8038 output_insn_code_cases (output_automata_list_min_issue_delay_code
);
8039 fprintf (output_file
,
8040 "\n default:\n %s = -1;\n break;\n }\n",
8041 RESULT_VARIABLE_NAME
);
8042 fprintf (output_file
, " return %s;\n", RESULT_VARIABLE_NAME
);
8043 fprintf (output_file
, "}\n\n");
8046 /* The function outputs a code changing state after issue of insns
8047 which have reservations in given AUTOMATA_LIST. */
8049 output_automata_list_transition_code (automata_list_el_t automata_list
)
8051 automata_list_el_t el
, next_el
;
8053 fprintf (output_file
, " {\n");
8054 if (automata_list
!= NULL
&& automata_list
->next_automata_list_el
!= NULL
)
8055 for (el
= automata_list
;; el
= next_el
)
8057 next_el
= el
->next_automata_list_el
;
8058 if (next_el
== NULL
)
8060 fprintf (output_file
, " ");
8061 output_state_member_type (output_file
, el
->automaton
);
8062 fprintf (output_file
, " ");
8063 output_temp_chip_member_name (output_file
, el
->automaton
);
8064 fprintf (output_file
, ";\n");
8066 for (el
= automata_list
; el
!= NULL
; el
= el
->next_automata_list_el
)
8067 if (comb_vect_p (el
->automaton
->trans_table
))
8069 fprintf (output_file
, "\n %s = ", TEMPORARY_VARIABLE_NAME
);
8070 output_trans_base_vect_name (output_file
, el
->automaton
);
8071 fprintf (output_file
, " [%s->", CHIP_PARAMETER_NAME
);
8072 output_chip_member_name (output_file
, el
->automaton
);
8073 fprintf (output_file
, "] + ");
8074 output_translate_vect_name (output_file
, el
->automaton
);
8075 fprintf (output_file
, " [%s];\n", INTERNAL_INSN_CODE_NAME
);
8076 fprintf (output_file
, " if (");
8077 output_trans_check_vect_name (output_file
, el
->automaton
);
8078 fprintf (output_file
, " [%s] != %s->",
8079 TEMPORARY_VARIABLE_NAME
, CHIP_PARAMETER_NAME
);
8080 output_chip_member_name (output_file
, el
->automaton
);
8081 fprintf (output_file
, ")\n");
8082 fprintf (output_file
, " return %s (%s, %s);\n",
8083 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
8084 CHIP_PARAMETER_NAME
);
8085 fprintf (output_file
, " else\n");
8086 fprintf (output_file
, " ");
8087 if (el
->next_automata_list_el
!= NULL
)
8088 output_temp_chip_member_name (output_file
, el
->automaton
);
8091 fprintf (output_file
, "%s->", CHIP_PARAMETER_NAME
);
8092 output_chip_member_name (output_file
, el
->automaton
);
8094 fprintf (output_file
, " = ");
8095 output_trans_comb_vect_name (output_file
, el
->automaton
);
8096 fprintf (output_file
, " [%s];\n", TEMPORARY_VARIABLE_NAME
);
8100 fprintf (output_file
, "\n %s = ", TEMPORARY_VARIABLE_NAME
);
8101 output_trans_full_vect_name (output_file
, el
->automaton
);
8102 fprintf (output_file
, " [");
8103 output_translate_vect_name (output_file
, el
->automaton
);
8104 fprintf (output_file
, " [%s] + ", INTERNAL_INSN_CODE_NAME
);
8105 fprintf (output_file
, "%s->", CHIP_PARAMETER_NAME
);
8106 output_chip_member_name (output_file
, el
->automaton
);
8107 fprintf (output_file
, " * %d];\n",
8108 el
->automaton
->insn_equiv_classes_num
);
8109 fprintf (output_file
, " if (%s >= %d)\n",
8110 TEMPORARY_VARIABLE_NAME
, el
->automaton
->achieved_states_num
);
8111 fprintf (output_file
, " return %s (%s, %s);\n",
8112 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
8113 CHIP_PARAMETER_NAME
);
8114 fprintf (output_file
, " else\n ");
8115 if (el
->next_automata_list_el
!= NULL
)
8116 output_temp_chip_member_name (output_file
, el
->automaton
);
8119 fprintf (output_file
, "%s->", CHIP_PARAMETER_NAME
);
8120 output_chip_member_name (output_file
, el
->automaton
);
8122 fprintf (output_file
, " = %s;\n", TEMPORARY_VARIABLE_NAME
);
8124 if (automata_list
!= NULL
&& automata_list
->next_automata_list_el
!= NULL
)
8125 for (el
= automata_list
;; el
= next_el
)
8127 next_el
= el
->next_automata_list_el
;
8128 if (next_el
== NULL
)
8130 fprintf (output_file
, " %s->", CHIP_PARAMETER_NAME
);
8131 output_chip_member_name (output_file
, el
->automaton
);
8132 fprintf (output_file
, " = ");
8133 output_temp_chip_member_name (output_file
, el
->automaton
);
8134 fprintf (output_file
, ";\n");
8136 fprintf (output_file
, " return -1;\n");
8137 fprintf (output_file
, " }\n");
8140 /* Output function `internal_state_transition'. */
8142 output_internal_trans_func (void)
8144 fprintf (output_file
,
8145 "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
8146 INTERNAL_TRANSITION_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
8147 CHIP_NAME
, CHIP_PARAMETER_NAME
);
8148 fprintf (output_file
, "{\n int %s ATTRIBUTE_UNUSED;\n", TEMPORARY_VARIABLE_NAME
);
8149 fprintf (output_file
, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME
);
8150 output_insn_code_cases (output_automata_list_transition_code
);
8151 fprintf (output_file
, "\n default:\n return -1;\n }\n");
8152 fprintf (output_file
, "}\n\n");
8159 insn_code = dfa_insn_code (insn);
8160 if (insn_code > DFA__ADVANCE_CYCLE)
8164 insn_code = DFA__ADVANCE_CYCLE;
8166 where insn denotes INSN_NAME, insn_code denotes INSN_CODE_NAME, and
8167 code denotes CODE. */
8169 output_internal_insn_code_evaluation (const char *insn_name
,
8170 const char *insn_code_name
,
8173 fprintf (output_file
, "\n if (%s == 0)\n", insn_name
);
8174 fprintf (output_file
, " %s = %s;\n\n",
8175 insn_code_name
, ADVANCE_CYCLE_VALUE_NAME
);
8178 fprintf (output_file
, "\n else if (%s == const0_rtx)\n", insn_name
);
8179 fprintf (output_file
, " %s = %s;\n\n",
8180 insn_code_name
, COLLAPSE_NDFA_VALUE_NAME
);
8182 fprintf (output_file
, "\n else\n {\n");
8183 fprintf (output_file
, " %s = %s (%s);\n", insn_code_name
,
8184 DFA_INSN_CODE_FUNC_NAME
, insn_name
);
8185 fprintf (output_file
, " if (%s > %s)\n return %d;\n }\n",
8186 insn_code_name
, ADVANCE_CYCLE_VALUE_NAME
, code
);
8190 /* This function outputs `dfa_insn_code' and its helper function
8191 `dfa_insn_code_enlarge'. */
8193 output_dfa_insn_code_func (void)
8195 /* Emacs c-mode gets really confused if there's a { or } in column 0
8196 inside a string, so don't do that. */
8197 fprintf (output_file
, "\
8199 dfa_insn_code_enlarge (int uid)\n\
8203 %s = XRESIZEVEC (int, %s,\n\
8205 for (; i < %s; i++)\n\
8206 %s[i] = -1;\n}\n\n",
8207 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
,
8208 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
,
8209 DFA_INSN_CODES_VARIABLE_NAME
, DFA_INSN_CODES_VARIABLE_NAME
,
8210 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
,
8211 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
,
8212 DFA_INSN_CODES_VARIABLE_NAME
);
8213 fprintf (output_file
, "\
8214 static inline int\n%s (rtx %s)\n\
8216 int uid = INSN_UID (%s);\n\
8218 DFA_INSN_CODE_FUNC_NAME
, INSN_PARAMETER_NAME
,
8219 INSN_PARAMETER_NAME
, INTERNAL_INSN_CODE_NAME
);
8221 fprintf (output_file
,
8222 " if (uid >= %s)\n dfa_insn_code_enlarge (uid);\n\n",
8223 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
);
8224 fprintf (output_file
, " %s = %s[uid];\n",
8225 INTERNAL_INSN_CODE_NAME
, DFA_INSN_CODES_VARIABLE_NAME
);
8226 fprintf (output_file
, "\
8232 INTERNAL_INSN_CODE_NAME
,
8233 INTERNAL_INSN_CODE_NAME
,
8234 INTERNAL_DFA_INSN_CODE_FUNC_NAME
, INSN_PARAMETER_NAME
,
8235 DFA_INSN_CODES_VARIABLE_NAME
, INTERNAL_INSN_CODE_NAME
);
8236 fprintf (output_file
, " return %s;\n}\n\n", INTERNAL_INSN_CODE_NAME
);
8239 /* The function outputs PHR interface function `state_transition'. */
8241 output_trans_func (void)
8243 fprintf (output_file
, "int\n%s (%s %s, rtx %s)\n",
8244 TRANSITION_FUNC_NAME
, STATE_TYPE_NAME
, STATE_NAME
,
8245 INSN_PARAMETER_NAME
);
8246 fprintf (output_file
, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME
);
8247 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME
,
8248 INTERNAL_INSN_CODE_NAME
, -1);
8249 fprintf (output_file
, " return %s (%s, (struct %s *) %s);\n}\n\n",
8250 INTERNAL_TRANSITION_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
, CHIP_NAME
, STATE_NAME
);
8253 /* Output function `min_issue_delay'. */
8255 output_min_issue_delay_func (void)
8257 fprintf (output_file
, "int\n%s (%s %s, rtx %s)\n",
8258 MIN_ISSUE_DELAY_FUNC_NAME
, STATE_TYPE_NAME
, STATE_NAME
,
8259 INSN_PARAMETER_NAME
);
8260 fprintf (output_file
, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME
);
8261 fprintf (output_file
, "\n if (%s != 0)\n {\n", INSN_PARAMETER_NAME
);
8262 fprintf (output_file
, " %s = %s (%s);\n", INTERNAL_INSN_CODE_NAME
,
8263 DFA_INSN_CODE_FUNC_NAME
, INSN_PARAMETER_NAME
);
8264 fprintf (output_file
, " if (%s > %s)\n return 0;\n",
8265 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
8266 fprintf (output_file
, " }\n else\n %s = %s;\n",
8267 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
8268 fprintf (output_file
, "\n return %s (%s, (struct %s *) %s);\n",
8269 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
8270 CHIP_NAME
, STATE_NAME
);
8271 fprintf (output_file
, "}\n\n");
8274 /* Output function `internal_dead_lock'. */
8276 output_internal_dead_lock_func (void)
8278 automaton_t automaton
;
8280 fprintf (output_file
, "static int\n%s (struct %s *ARG_UNUSED (%s))\n",
8281 INTERNAL_DEAD_LOCK_FUNC_NAME
, CHIP_NAME
, CHIP_PARAMETER_NAME
);
8282 fprintf (output_file
, "{\n");
8283 for (automaton
= description
->first_automaton
;
8285 automaton
= automaton
->next_automaton
)
8286 if (automaton
->locked_states
)
8288 fprintf (output_file
, " if (");
8289 output_dead_lock_vect_name (output_file
, automaton
);
8290 fprintf (output_file
, " [%s->", CHIP_PARAMETER_NAME
);
8291 output_chip_member_name (output_file
, automaton
);
8292 fprintf (output_file
, "])\n return 1/* TRUE */;\n");
8294 fprintf (output_file
, " return 0/* FALSE */;\n}\n\n");
8297 /* The function outputs PHR interface function `state_dead_lock_p'. */
8299 output_dead_lock_func (void)
8301 fprintf (output_file
, "int\n%s (%s %s)\n",
8302 DEAD_LOCK_FUNC_NAME
, STATE_TYPE_NAME
, STATE_NAME
);
8303 fprintf (output_file
, "{\n return %s ((struct %s *) %s);\n}\n\n",
8304 INTERNAL_DEAD_LOCK_FUNC_NAME
, CHIP_NAME
, STATE_NAME
);
8307 /* Output function `internal_reset'. */
8309 output_internal_reset_func (void)
8311 fprintf (output_file
, "static inline void\n%s (struct %s *%s)\n",
8312 INTERNAL_RESET_FUNC_NAME
, CHIP_NAME
, CHIP_PARAMETER_NAME
);
8313 fprintf (output_file
, "{\n memset (%s, 0, sizeof (struct %s));\n}\n\n",
8314 CHIP_PARAMETER_NAME
, CHIP_NAME
);
8317 /* The function outputs PHR interface function `state_size'. */
8319 output_size_func (void)
8321 fprintf (output_file
, "int\n%s (void)\n", SIZE_FUNC_NAME
);
8322 fprintf (output_file
, "{\n return sizeof (struct %s);\n}\n\n", CHIP_NAME
);
8325 /* The function outputs PHR interface function `state_reset'. */
8327 output_reset_func (void)
8329 fprintf (output_file
, "void\n%s (%s %s)\n",
8330 RESET_FUNC_NAME
, STATE_TYPE_NAME
, STATE_NAME
);
8331 fprintf (output_file
, "{\n %s ((struct %s *) %s);\n}\n\n", INTERNAL_RESET_FUNC_NAME
,
8332 CHIP_NAME
, STATE_NAME
);
8335 /* Output function `min_insn_conflict_delay'. */
8337 output_min_insn_conflict_delay_func (void)
8339 fprintf (output_file
,
8340 "int\n%s (%s %s, rtx %s, rtx %s)\n",
8341 MIN_INSN_CONFLICT_DELAY_FUNC_NAME
, STATE_TYPE_NAME
,
8342 STATE_NAME
, INSN_PARAMETER_NAME
, INSN2_PARAMETER_NAME
);
8343 fprintf (output_file
, "{\n struct %s %s;\n int %s, %s, transition;\n",
8344 CHIP_NAME
, CHIP_NAME
, INTERNAL_INSN_CODE_NAME
,
8345 INTERNAL_INSN2_CODE_NAME
);
8346 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME
,
8347 INTERNAL_INSN_CODE_NAME
, 0);
8348 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME
,
8349 INTERNAL_INSN2_CODE_NAME
, 0);
8350 fprintf (output_file
, " memcpy (&%s, %s, sizeof (%s));\n",
8351 CHIP_NAME
, STATE_NAME
, CHIP_NAME
);
8352 fprintf (output_file
, " %s (&%s);\n", INTERNAL_RESET_FUNC_NAME
, CHIP_NAME
);
8353 fprintf (output_file
, " transition = %s (%s, &%s);\n",
8354 INTERNAL_TRANSITION_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
, CHIP_NAME
);
8355 fprintf (output_file
, " gcc_assert (transition <= 0);\n");
8356 fprintf (output_file
, " return %s (%s, &%s);\n",
8357 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME
, INTERNAL_INSN2_CODE_NAME
,
8359 fprintf (output_file
, "}\n\n");
8362 /* Output the array holding default latency values. These are used in
8363 insn_latency and maximal_insn_latency function implementations. */
8365 output_default_latencies (void)
8369 const char *tabletype
= "unsigned char";
8371 /* Find the smallest integer type that can hold all the default
8373 for (i
= 0; i
< description
->decls_num
; i
++)
8374 if (description
->decls
[i
]->mode
== dm_insn_reserv
)
8376 decl
= description
->decls
[i
];
8377 if (DECL_INSN_RESERV (decl
)->default_latency
> UCHAR_MAX
8378 && tabletype
[0] != 'i') /* Don't shrink it. */
8379 tabletype
= "unsigned short";
8380 if (DECL_INSN_RESERV (decl
)->default_latency
> USHRT_MAX
)
8384 fprintf (output_file
, " static const %s default_latencies[] =\n {",
8387 for (i
= 0, j
= 0, col
= 7; i
< description
->normal_decls_num
; i
++)
8388 if (description
->decls
[i
]->mode
== dm_insn_reserv
)
8390 if ((col
= (col
+1) % 8) == 0)
8391 fputs ("\n ", output_file
);
8392 decl
= description
->decls
[i
];
8393 gcc_assert (j
++ == DECL_INSN_RESERV (decl
)->insn_num
);
8394 fprintf (output_file
, "% 4d,",
8395 DECL_INSN_RESERV (decl
)->default_latency
);
8397 gcc_assert (j
== description
->insns_num
- (collapse_flag
? 2 : 1));
8398 fputs ("\n };\n", output_file
);
8401 /* Output function `internal_insn_latency'. */
8403 output_internal_insn_latency_func (void)
8407 struct bypass_decl
*bypass
;
8409 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",
8410 INTERNAL_INSN_LATENCY_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
8411 INTERNAL_INSN2_CODE_NAME
, INSN_PARAMETER_NAME
,
8412 INSN2_PARAMETER_NAME
);
8413 fprintf (output_file
, "{\n");
8415 if (DECL_INSN_RESERV (advance_cycle_insn_decl
)->insn_num
== 0)
8417 fputs (" return 0;\n}\n\n", output_file
);
8421 fprintf (output_file
, " if (%s >= %s || %s >= %s)\n return 0;\n",
8422 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
,
8423 INTERNAL_INSN2_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
8425 fprintf (output_file
, " switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME
);
8426 for (i
= 0; i
< description
->decls_num
; i
++)
8427 if (description
->decls
[i
]->mode
== dm_insn_reserv
8428 && DECL_INSN_RESERV (description
->decls
[i
])->bypass_list
)
8430 decl
= description
->decls
[i
];
8431 fprintf (output_file
,
8432 " case %d:\n switch (%s)\n {\n",
8433 DECL_INSN_RESERV (decl
)->insn_num
,
8434 INTERNAL_INSN2_CODE_NAME
);
8435 for (bypass
= DECL_INSN_RESERV (decl
)->bypass_list
;
8437 bypass
= bypass
->next
)
8439 gcc_assert (bypass
->in_insn_reserv
->insn_num
8440 != (DECL_INSN_RESERV
8441 (advance_cycle_insn_decl
)->insn_num
));
8442 fprintf (output_file
, " case %d:\n",
8443 bypass
->in_insn_reserv
->insn_num
);
8446 if (bypass
->bypass_guard_name
== NULL
)
8448 gcc_assert (bypass
->next
== NULL
8449 || (bypass
->in_insn_reserv
8450 != bypass
->next
->in_insn_reserv
));
8451 fprintf (output_file
, " return %d;\n",
8456 fprintf (output_file
,
8457 " if (%s (%s, %s))\n",
8458 bypass
->bypass_guard_name
, INSN_PARAMETER_NAME
,
8459 INSN2_PARAMETER_NAME
);
8460 fprintf (output_file
, " return %d;\n",
8463 if (bypass
->next
== NULL
8464 || bypass
->in_insn_reserv
!= bypass
->next
->in_insn_reserv
)
8466 bypass
= bypass
->next
;
8468 if (bypass
->bypass_guard_name
!= NULL
)
8469 fprintf (output_file
, " break;\n");
8471 fputs (" }\n break;\n", output_file
);
8474 fprintf (output_file
, " }\n return default_latencies[%s];\n}\n\n",
8475 INTERNAL_INSN_CODE_NAME
);
8478 /* Output function `internal_maximum_insn_latency'. */
8480 output_internal_maximal_insn_latency_func (void)
8483 struct bypass_decl
*bypass
;
8487 fprintf (output_file
, "static int\n%s (int %s ATTRIBUTE_UNUSED,\n\trtx %s ATTRIBUTE_UNUSED)\n",
8488 "internal_maximal_insn_latency", INTERNAL_INSN_CODE_NAME
,
8489 INSN_PARAMETER_NAME
);
8490 fprintf (output_file
, "{\n");
8492 if (DECL_INSN_RESERV (advance_cycle_insn_decl
)->insn_num
== 0)
8494 fputs (" return 0;\n}\n\n", output_file
);
8498 fprintf (output_file
, " switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME
);
8499 for (i
= 0; i
< description
->decls_num
; i
++)
8500 if (description
->decls
[i
]->mode
== dm_insn_reserv
8501 && DECL_INSN_RESERV (description
->decls
[i
])->bypass_list
)
8503 decl
= description
->decls
[i
];
8504 max
= DECL_INSN_RESERV (decl
)->default_latency
;
8505 fprintf (output_file
,
8507 DECL_INSN_RESERV (decl
)->insn_num
);
8508 for (bypass
= DECL_INSN_RESERV (decl
)->bypass_list
;
8510 bypass
= bypass
->next
)
8512 if (bypass
->latency
> max
)
8513 max
= bypass
->latency
;
8515 fprintf (output_file
, " return %d; }\n break;\n", max
);
8518 fprintf (output_file
, " }\n return default_latencies[%s];\n}\n\n",
8519 INTERNAL_INSN_CODE_NAME
);
8522 /* The function outputs PHR interface function `insn_latency'. */
8524 output_insn_latency_func (void)
8526 fprintf (output_file
, "int\n%s (rtx %s, rtx %s)\n",
8527 INSN_LATENCY_FUNC_NAME
, INSN_PARAMETER_NAME
, INSN2_PARAMETER_NAME
);
8528 fprintf (output_file
, "{\n int %s, %s;\n",
8529 INTERNAL_INSN_CODE_NAME
, INTERNAL_INSN2_CODE_NAME
);
8530 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME
,
8531 INTERNAL_INSN_CODE_NAME
, 0);
8532 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME
,
8533 INTERNAL_INSN2_CODE_NAME
, 0);
8534 fprintf (output_file
, " return %s (%s, %s, %s, %s);\n}\n\n",
8535 INTERNAL_INSN_LATENCY_FUNC_NAME
,
8536 INTERNAL_INSN_CODE_NAME
, INTERNAL_INSN2_CODE_NAME
,
8537 INSN_PARAMETER_NAME
, INSN2_PARAMETER_NAME
);
8540 /* The function outputs PHR interface function `maximal_insn_latency'. */
8542 output_maximal_insn_latency_func (void)
8544 fprintf (output_file
, "int\n%s (rtx %s)\n",
8545 "maximal_insn_latency", INSN_PARAMETER_NAME
);
8546 fprintf (output_file
, "{\n int %s;\n",
8547 INTERNAL_INSN_CODE_NAME
);
8548 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME
,
8549 INTERNAL_INSN_CODE_NAME
, 0);
8550 fprintf (output_file
, " return %s (%s, %s);\n}\n\n",
8551 "internal_maximal_insn_latency",
8552 INTERNAL_INSN_CODE_NAME
, INSN_PARAMETER_NAME
);
8555 /* The function outputs PHR interface function `print_reservation'. */
8557 output_print_reservation_func (void)
8562 fprintf (output_file
,
8563 "void\n%s (FILE *%s, rtx %s ATTRIBUTE_UNUSED)\n{\n",
8564 PRINT_RESERVATION_FUNC_NAME
, FILE_PARAMETER_NAME
,
8565 INSN_PARAMETER_NAME
);
8567 if (DECL_INSN_RESERV (advance_cycle_insn_decl
)->insn_num
== 0)
8569 fprintf (output_file
, " fputs (\"%s\", %s);\n}\n\n",
8570 NOTHING_NAME
, FILE_PARAMETER_NAME
);
8575 fputs (" static const char *const reservation_names[] =\n {",
8578 for (i
= 0, j
= 0; i
< description
->normal_decls_num
; i
++)
8580 decl
= description
->decls
[i
];
8581 if (decl
->mode
== dm_insn_reserv
)
8583 gcc_assert (j
== DECL_INSN_RESERV (decl
)->insn_num
);
8586 fprintf (output_file
, "\n \"%s\",",
8587 regexp_representation (DECL_INSN_RESERV (decl
)->regexp
));
8588 finish_regexp_representation ();
8591 gcc_assert (j
== description
->insns_num
- (collapse_flag
? 2 : 1));
8593 fprintf (output_file
, "\n \"%s\"\n };\n int %s;\n\n",
8594 NOTHING_NAME
, INTERNAL_INSN_CODE_NAME
);
8596 fprintf (output_file
, " if (%s == 0)\n %s = %s;\n",
8597 INSN_PARAMETER_NAME
,
8598 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
8599 fprintf (output_file
, " else\n\
8605 INTERNAL_INSN_CODE_NAME
, DFA_INSN_CODE_FUNC_NAME
,
8606 INSN_PARAMETER_NAME
,
8607 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
,
8608 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
8610 fprintf (output_file
, " fputs (reservation_names[%s], %s);\n}\n\n",
8611 INTERNAL_INSN_CODE_NAME
, FILE_PARAMETER_NAME
);
8614 /* The following function is used to sort unit declaration by their
8617 units_cmp (const void *unit1
, const void *unit2
)
8619 const_unit_decl_t
const u1
= *(const_unit_decl_t
const*) unit1
;
8620 const_unit_decl_t
const u2
= *(const_unit_decl_t
const*) unit2
;
8622 return strcmp (u1
->name
, u2
->name
);
8625 /* The following macro value is name of struct containing unit name
8627 #define NAME_CODE_STRUCT_NAME "name_code"
8629 /* The following macro value is name of table of struct name_code. */
8630 #define NAME_CODE_TABLE_NAME "name_code_table"
8632 /* The following macro values are member names for struct name_code. */
8633 #define NAME_MEMBER_NAME "name"
8634 #define CODE_MEMBER_NAME "code"
8636 /* The following macro values are local variable names for function
8637 `get_cpu_unit_code'. */
8638 #define CMP_VARIABLE_NAME "cmp"
8639 #define LOW_VARIABLE_NAME "l"
8640 #define MIDDLE_VARIABLE_NAME "m"
8641 #define HIGH_VARIABLE_NAME "h"
8643 /* The following function outputs function to obtain internal cpu unit
8644 code by the cpu unit name. */
8646 output_get_cpu_unit_code_func (void)
8651 fprintf (output_file
, "int\n%s (const char *%s)\n",
8652 GET_CPU_UNIT_CODE_FUNC_NAME
, CPU_UNIT_NAME_PARAMETER_NAME
);
8653 fprintf (output_file
, "{\n struct %s {const char *%s; int %s;};\n",
8654 NAME_CODE_STRUCT_NAME
, NAME_MEMBER_NAME
, CODE_MEMBER_NAME
);
8655 fprintf (output_file
, " int %s, %s, %s, %s;\n", CMP_VARIABLE_NAME
,
8656 LOW_VARIABLE_NAME
, MIDDLE_VARIABLE_NAME
, HIGH_VARIABLE_NAME
);
8657 fprintf (output_file
, " static struct %s %s [] =\n {\n",
8658 NAME_CODE_STRUCT_NAME
, NAME_CODE_TABLE_NAME
);
8659 units
= XNEWVEC (unit_decl_t
, description
->units_num
);
8660 memcpy (units
, units_array
, sizeof (unit_decl_t
) * description
->units_num
);
8661 qsort (units
, description
->units_num
, sizeof (unit_decl_t
), units_cmp
);
8662 for (i
= 0; i
< description
->units_num
; i
++)
8663 if (units
[i
]->query_p
)
8664 fprintf (output_file
, " {\"%s\", %d},\n",
8665 units
[i
]->name
, units
[i
]->query_num
);
8666 fprintf (output_file
, " };\n\n");
8667 fprintf (output_file
, " /* The following is binary search: */\n");
8668 fprintf (output_file
, " %s = 0;\n", LOW_VARIABLE_NAME
);
8669 fprintf (output_file
, " %s = sizeof (%s) / sizeof (struct %s) - 1;\n",
8670 HIGH_VARIABLE_NAME
, NAME_CODE_TABLE_NAME
, NAME_CODE_STRUCT_NAME
);
8671 fprintf (output_file
, " while (%s <= %s)\n {\n",
8672 LOW_VARIABLE_NAME
, HIGH_VARIABLE_NAME
);
8673 fprintf (output_file
, " %s = (%s + %s) / 2;\n",
8674 MIDDLE_VARIABLE_NAME
, LOW_VARIABLE_NAME
, HIGH_VARIABLE_NAME
);
8675 fprintf (output_file
, " %s = strcmp (%s, %s [%s].%s);\n",
8676 CMP_VARIABLE_NAME
, CPU_UNIT_NAME_PARAMETER_NAME
,
8677 NAME_CODE_TABLE_NAME
, MIDDLE_VARIABLE_NAME
, NAME_MEMBER_NAME
);
8678 fprintf (output_file
, " if (%s < 0)\n", CMP_VARIABLE_NAME
);
8679 fprintf (output_file
, " %s = %s - 1;\n",
8680 HIGH_VARIABLE_NAME
, MIDDLE_VARIABLE_NAME
);
8681 fprintf (output_file
, " else if (%s > 0)\n", CMP_VARIABLE_NAME
);
8682 fprintf (output_file
, " %s = %s + 1;\n",
8683 LOW_VARIABLE_NAME
, MIDDLE_VARIABLE_NAME
);
8684 fprintf (output_file
, " else\n");
8685 fprintf (output_file
, " return %s [%s].%s;\n }\n",
8686 NAME_CODE_TABLE_NAME
, MIDDLE_VARIABLE_NAME
, CODE_MEMBER_NAME
);
8687 fprintf (output_file
, " return -1;\n}\n\n");
8691 /* The following function outputs function to check reservation of cpu
8692 unit (its internal code will be passed as the function argument) in
8695 output_cpu_unit_reservation_p (void)
8697 automaton_t automaton
;
8699 fprintf (output_file
, "int\n%s (%s %s, int %s)\n",
8700 CPU_UNIT_RESERVATION_P_FUNC_NAME
,
8701 STATE_TYPE_NAME
, STATE_NAME
,
8702 CPU_CODE_PARAMETER_NAME
);
8703 fprintf (output_file
, "{\n gcc_assert (%s >= 0 && %s < %d);\n",
8704 CPU_CODE_PARAMETER_NAME
, CPU_CODE_PARAMETER_NAME
,
8705 description
->query_units_num
);
8706 if (description
->query_units_num
> 0)
8707 for (automaton
= description
->first_automaton
;
8709 automaton
= automaton
->next_automaton
)
8711 fprintf (output_file
, " if ((");
8712 output_reserved_units_table_name (output_file
, automaton
);
8713 fprintf (output_file
, " [((struct %s *) %s)->", CHIP_NAME
, STATE_NAME
);
8714 output_chip_member_name (output_file
, automaton
);
8715 fprintf (output_file
, " * %d + %s / 8] >> (%s %% 8)) & 1)\n",
8716 (description
->query_units_num
+ 7) / 8,
8717 CPU_CODE_PARAMETER_NAME
, CPU_CODE_PARAMETER_NAME
);
8718 fprintf (output_file
, " return 1;\n");
8720 fprintf (output_file
, " return 0;\n}\n\n");
8723 /* The following function outputs a function to check if insn
8724 has a dfa reservation. */
8726 output_insn_has_dfa_reservation_p (void)
8728 fprintf (output_file
,
8729 "bool\n%s (rtx %s ATTRIBUTE_UNUSED)\n{\n",
8730 INSN_HAS_DFA_RESERVATION_P_FUNC_NAME
,
8731 INSN_PARAMETER_NAME
);
8733 if (DECL_INSN_RESERV (advance_cycle_insn_decl
)->insn_num
== 0)
8735 fprintf (output_file
, " return false;\n}\n\n");
8739 fprintf (output_file
, " int %s;\n\n", INTERNAL_INSN_CODE_NAME
);
8741 fprintf (output_file
, " if (%s == 0)\n %s = %s;\n",
8742 INSN_PARAMETER_NAME
,
8743 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
8744 fprintf (output_file
, " else\n\
8750 INTERNAL_INSN_CODE_NAME
, DFA_INSN_CODE_FUNC_NAME
,
8751 INSN_PARAMETER_NAME
,
8752 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
,
8753 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
8755 fprintf (output_file
, " return %s != %s;\n}\n\n",
8756 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
8759 /* The function outputs PHR interface functions `dfa_clean_insn_cache'
8760 and 'dfa_clear_single_insn_cache'. */
8762 output_dfa_clean_insn_cache_func (void)
8764 fprintf (output_file
,
8765 "void\n%s (void)\n{\n int %s;\n\n",
8766 DFA_CLEAN_INSN_CACHE_FUNC_NAME
, I_VARIABLE_NAME
);
8767 fprintf (output_file
,
8768 " for (%s = 0; %s < %s; %s++)\n %s [%s] = -1;\n}\n\n",
8769 I_VARIABLE_NAME
, I_VARIABLE_NAME
,
8770 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
, I_VARIABLE_NAME
,
8771 DFA_INSN_CODES_VARIABLE_NAME
, I_VARIABLE_NAME
);
8773 fprintf (output_file
,
8774 "void\n%s (rtx %s)\n{\n int %s;\n\n",
8775 DFA_CLEAR_SINGLE_INSN_CACHE_FUNC_NAME
, INSN_PARAMETER_NAME
,
8777 fprintf (output_file
,
8778 " %s = INSN_UID (%s);\n if (%s < %s)\n %s [%s] = -1;\n}\n\n",
8779 I_VARIABLE_NAME
, INSN_PARAMETER_NAME
, I_VARIABLE_NAME
,
8780 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
, DFA_INSN_CODES_VARIABLE_NAME
,
8784 /* The function outputs PHR interface function `dfa_start'. */
8786 output_dfa_start_func (void)
8788 fprintf (output_file
,
8789 "void\n%s (void)\n{\n %s = get_max_uid ();\n",
8790 DFA_START_FUNC_NAME
, DFA_INSN_CODES_LENGTH_VARIABLE_NAME
);
8791 fprintf (output_file
, " %s = XNEWVEC (int, %s);\n",
8792 DFA_INSN_CODES_VARIABLE_NAME
, DFA_INSN_CODES_LENGTH_VARIABLE_NAME
);
8793 fprintf (output_file
, " %s ();\n}\n\n", DFA_CLEAN_INSN_CACHE_FUNC_NAME
);
8796 /* The function outputs PHR interface function `dfa_finish'. */
8798 output_dfa_finish_func (void)
8800 fprintf (output_file
, "void\n%s (void)\n{\n free (%s);\n}\n\n",
8801 DFA_FINISH_FUNC_NAME
, DFA_INSN_CODES_VARIABLE_NAME
);
8806 /* The page contains code for output description file (readable
8807 representation of original description and generated DFA(s). */
8809 /* The function outputs string representation of IR reservation. */
8811 output_regexp (regexp_t regexp
)
8813 fprintf (output_description_file
, "%s", regexp_representation (regexp
));
8814 finish_regexp_representation ();
8817 /* Output names of units in LIST separated by comma. */
8819 output_unit_set_el_list (unit_set_el_t list
)
8823 for (el
= list
; el
!= NULL
; el
= el
->next_unit_set_el
)
8826 fprintf (output_description_file
, ", ");
8827 fprintf (output_description_file
, "%s", el
->unit_decl
->name
);
8831 /* Output patterns in LIST separated by comma. */
8833 output_pattern_set_el_list (pattern_set_el_t list
)
8835 pattern_set_el_t el
;
8838 for (el
= list
; el
!= NULL
; el
= el
->next_pattern_set_el
)
8841 fprintf (output_description_file
, ", ");
8842 for (i
= 0; i
< el
->units_num
; i
++)
8843 fprintf (output_description_file
, (i
== 0 ? "%s" : " %s"),
8844 el
->unit_decls
[i
]->name
);
8848 /* The function outputs string representation of IR define_reservation
8849 and define_insn_reservation. */
8851 output_description (void)
8856 for (i
= 0; i
< description
->decls_num
; i
++)
8858 decl
= description
->decls
[i
];
8859 if (decl
->mode
== dm_unit
)
8861 if (DECL_UNIT (decl
)->excl_list
!= NULL
)
8863 fprintf (output_description_file
, "unit %s exclusion_set: ",
8864 DECL_UNIT (decl
)->name
);
8865 output_unit_set_el_list (DECL_UNIT (decl
)->excl_list
);
8866 fprintf (output_description_file
, "\n");
8868 if (DECL_UNIT (decl
)->presence_list
!= NULL
)
8870 fprintf (output_description_file
, "unit %s presence_set: ",
8871 DECL_UNIT (decl
)->name
);
8872 output_pattern_set_el_list (DECL_UNIT (decl
)->presence_list
);
8873 fprintf (output_description_file
, "\n");
8875 if (DECL_UNIT (decl
)->final_presence_list
!= NULL
)
8877 fprintf (output_description_file
, "unit %s final_presence_set: ",
8878 DECL_UNIT (decl
)->name
);
8879 output_pattern_set_el_list
8880 (DECL_UNIT (decl
)->final_presence_list
);
8881 fprintf (output_description_file
, "\n");
8883 if (DECL_UNIT (decl
)->absence_list
!= NULL
)
8885 fprintf (output_description_file
, "unit %s absence_set: ",
8886 DECL_UNIT (decl
)->name
);
8887 output_pattern_set_el_list (DECL_UNIT (decl
)->absence_list
);
8888 fprintf (output_description_file
, "\n");
8890 if (DECL_UNIT (decl
)->final_absence_list
!= NULL
)
8892 fprintf (output_description_file
, "unit %s final_absence_set: ",
8893 DECL_UNIT (decl
)->name
);
8894 output_pattern_set_el_list
8895 (DECL_UNIT (decl
)->final_absence_list
);
8896 fprintf (output_description_file
, "\n");
8900 fprintf (output_description_file
, "\n");
8901 for (i
= 0; i
< description
->normal_decls_num
; i
++)
8903 decl
= description
->decls
[i
];
8904 if (decl
->mode
== dm_reserv
)
8906 fprintf (output_description_file
, "reservation %s: ",
8907 DECL_RESERV (decl
)->name
);
8908 output_regexp (DECL_RESERV (decl
)->regexp
);
8909 fprintf (output_description_file
, "\n");
8911 else if (decl
->mode
== dm_insn_reserv
)
8913 fprintf (output_description_file
, "insn reservation %s ",
8914 DECL_INSN_RESERV (decl
)->name
);
8915 print_rtl (output_description_file
,
8916 DECL_INSN_RESERV (decl
)->condexp
);
8917 fprintf (output_description_file
, ": ");
8918 output_regexp (DECL_INSN_RESERV (decl
)->regexp
);
8919 fprintf (output_description_file
, "\n");
8921 else if (decl
->mode
== dm_bypass
)
8922 fprintf (output_description_file
, "bypass %d %s %s\n",
8923 DECL_BYPASS (decl
)->latency
,
8924 DECL_BYPASS (decl
)->out_pattern
,
8925 DECL_BYPASS (decl
)->in_pattern
);
8927 fprintf (output_description_file
, "\n\f\n");
8930 /* The function outputs name of AUTOMATON. */
8932 output_automaton_name (FILE *f
, automaton_t automaton
)
8934 if (automaton
->corresponding_automaton_decl
== NULL
)
8935 fprintf (f
, "#%d", automaton
->automaton_order_num
);
8937 fprintf (f
, "`%s'", automaton
->corresponding_automaton_decl
->name
);
8940 /* Maximal length of line for pretty printing into description
8942 #define MAX_LINE_LENGTH 70
8944 /* The function outputs units name belonging to AUTOMATON. */
8946 output_automaton_units (automaton_t automaton
)
8950 int curr_line_length
;
8951 int there_is_an_automaton_unit
;
8954 fprintf (output_description_file
, "\n Corresponding units:\n");
8955 fprintf (output_description_file
, " ");
8956 curr_line_length
= 4;
8957 there_is_an_automaton_unit
= 0;
8958 for (i
= 0; i
< description
->decls_num
; i
++)
8960 decl
= description
->decls
[i
];
8961 if (decl
->mode
== dm_unit
8962 && (DECL_UNIT (decl
)->corresponding_automaton_num
8963 == automaton
->automaton_order_num
))
8965 there_is_an_automaton_unit
= 1;
8966 name
= DECL_UNIT (decl
)->name
;
8967 if (curr_line_length
+ strlen (name
) + 1 > MAX_LINE_LENGTH
)
8969 curr_line_length
= strlen (name
) + 4;
8970 fprintf (output_description_file
, "\n ");
8974 curr_line_length
+= strlen (name
) + 1;
8975 fprintf (output_description_file
, " ");
8977 fprintf (output_description_file
, "%s", name
);
8980 if (!there_is_an_automaton_unit
)
8981 fprintf (output_description_file
, "<None>");
8982 fprintf (output_description_file
, "\n\n");
8985 /* The following variable is used for forming array of all possible cpu unit
8986 reservations described by the current DFA state. */
8987 static VEC(reserv_sets_t
, heap
) *state_reservs
;
8989 /* The function forms `state_reservs' for STATE. */
8991 add_state_reservs (state_t state
)
8993 alt_state_t curr_alt_state
;
8995 if (state
->component_states
!= NULL
)
8996 for (curr_alt_state
= state
->component_states
;
8997 curr_alt_state
!= NULL
;
8998 curr_alt_state
= curr_alt_state
->next_sorted_alt_state
)
8999 add_state_reservs (curr_alt_state
->state
);
9001 VEC_safe_push (reserv_sets_t
, heap
, state_reservs
, state
->reservs
);
9004 /* The function outputs readable representation of all out arcs of
9007 output_state_arcs (state_t state
)
9011 const char *insn_name
;
9012 int curr_line_length
;
9014 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
9017 gcc_assert (ainsn
->first_insn_with_same_reservs
);
9018 fprintf (output_description_file
, " ");
9019 curr_line_length
= 7;
9020 fprintf (output_description_file
, "%2d: ", ainsn
->insn_equiv_class_num
);
9023 insn_name
= ainsn
->insn_reserv_decl
->name
;
9024 if (curr_line_length
+ strlen (insn_name
) > MAX_LINE_LENGTH
)
9026 if (ainsn
!= arc
->insn
)
9028 fprintf (output_description_file
, ",\n ");
9029 curr_line_length
= strlen (insn_name
) + 6;
9032 curr_line_length
+= strlen (insn_name
);
9036 curr_line_length
+= strlen (insn_name
);
9037 if (ainsn
!= arc
->insn
)
9039 curr_line_length
+= 2;
9040 fprintf (output_description_file
, ", ");
9043 fprintf (output_description_file
, "%s", insn_name
);
9044 ainsn
= ainsn
->next_same_reservs_insn
;
9046 while (ainsn
!= NULL
);
9047 fprintf (output_description_file
, " %d \n",
9048 arc
->to_state
->order_state_num
);
9050 fprintf (output_description_file
, "\n");
9053 /* The following function is used for sorting possible cpu unit
9054 reservation of a DFA state. */
9056 state_reservs_cmp (const void *reservs_ptr_1
, const void *reservs_ptr_2
)
9058 return reserv_sets_cmp (*(const_reserv_sets_t
const*) reservs_ptr_1
,
9059 *(const_reserv_sets_t
const*) reservs_ptr_2
);
9062 /* The following function is used for sorting possible cpu unit
9063 reservation of a DFA state. */
9065 remove_state_duplicate_reservs (void)
9069 for (i
= 1, j
= 0; i
< VEC_length (reserv_sets_t
, state_reservs
); i
++)
9070 if (reserv_sets_cmp (VEC_index (reserv_sets_t
, state_reservs
, j
),
9071 VEC_index (reserv_sets_t
, state_reservs
, i
)))
9074 VEC_replace (reserv_sets_t
, state_reservs
, j
,
9075 VEC_index (reserv_sets_t
, state_reservs
, i
));
9077 VEC_truncate (reserv_sets_t
, state_reservs
, j
+ 1);
9080 /* The following function output readable representation of DFA(s)
9081 state used for fast recognition of pipeline hazards. State is
9082 described by possible (current and scheduled) cpu unit
9085 output_state (state_t state
)
9091 fprintf (output_description_file
, " State #%d", state
->order_state_num
);
9092 fprintf (output_description_file
,
9093 state
->new_cycle_p
? " (new cycle)\n" : "\n");
9094 add_state_reservs (state
);
9095 VEC_qsort (reserv_sets_t
, state_reservs
, state_reservs_cmp
);
9096 remove_state_duplicate_reservs ();
9097 for (i
= 0; i
< VEC_length (reserv_sets_t
, state_reservs
); i
++)
9099 fprintf (output_description_file
, " ");
9100 output_reserv_sets (output_description_file
,
9101 VEC_index (reserv_sets_t
, state_reservs
, i
));
9102 fprintf (output_description_file
, "\n");
9104 fprintf (output_description_file
, "\n");
9105 output_state_arcs (state
);
9106 VEC_free (reserv_sets_t
, heap
, state_reservs
);
9109 /* The following function output readable representation of
9110 DFAs used for fast recognition of pipeline hazards. */
9112 output_automaton_descriptions (void)
9114 automaton_t automaton
;
9116 for (automaton
= description
->first_automaton
;
9118 automaton
= automaton
->next_automaton
)
9120 fprintf (output_description_file
, "\nAutomaton ");
9121 output_automaton_name (output_description_file
, automaton
);
9122 fprintf (output_description_file
, "\n");
9123 output_automaton_units (automaton
);
9124 pass_states (automaton
, output_state
);
9130 /* The page contains top level function for generation DFA(s) used for
9133 /* The function outputs statistics about work of different phases of
9136 output_statistics (FILE *f
)
9138 automaton_t automaton
;
9141 int transition_comb_vect_els
= 0;
9142 int transition_full_vect_els
= 0;
9143 int min_issue_delay_vect_els
= 0;
9144 int locked_states
= 0;
9147 for (automaton
= description
->first_automaton
;
9149 automaton
= automaton
->next_automaton
)
9151 fprintf (f
, "\nAutomaton ");
9152 output_automaton_name (f
, automaton
);
9153 fprintf (f
, "\n %5d NDFA states, %5d NDFA arcs\n",
9154 automaton
->NDFA_states_num
, automaton
->NDFA_arcs_num
);
9155 fprintf (f
, " %5d DFA states, %5d DFA arcs\n",
9156 automaton
->DFA_states_num
, automaton
->DFA_arcs_num
);
9157 states_num
= automaton
->DFA_states_num
;
9158 if (!no_minimization_flag
)
9160 fprintf (f
, " %5d minimal DFA states, %5d minimal DFA arcs\n",
9161 automaton
->minimal_DFA_states_num
,
9162 automaton
->minimal_DFA_arcs_num
);
9163 states_num
= automaton
->minimal_DFA_states_num
;
9165 fprintf (f
, " %5d all insns %5d insn equivalence classes\n",
9166 description
->insns_num
, automaton
->insn_equiv_classes_num
);
9167 fprintf (f
, " %d locked states\n", automaton
->locked_states
);
9170 (f
, "%5ld transition comb vector els, %5ld trans table els: %s\n",
9171 (long) VEC_length (vect_el_t
, automaton
->trans_table
->comb_vect
),
9172 (long) VEC_length (vect_el_t
, automaton
->trans_table
->full_vect
),
9173 (comb_vect_p (automaton
->trans_table
)
9174 ? "use comb vect" : "use simple vect"));
9176 (f
, "%5ld min delay table els, compression factor %d\n",
9177 (long) states_num
* automaton
->insn_equiv_classes_num
,
9178 automaton
->min_issue_delay_table_compression_factor
);
9179 transition_comb_vect_els
9180 += VEC_length (vect_el_t
, automaton
->trans_table
->comb_vect
);
9181 transition_full_vect_els
9182 += VEC_length (vect_el_t
, automaton
->trans_table
->full_vect
);
9183 min_issue_delay_vect_els
9184 += states_num
* automaton
->insn_equiv_classes_num
;
9186 += automaton
->locked_states
;
9190 fprintf (f
, "\n%5d all allocated states, %5d all allocated arcs\n",
9191 allocated_states_num
, allocated_arcs_num
);
9192 fprintf (f
, "%5d all allocated alternative states\n",
9193 allocated_alt_states_num
);
9194 fprintf (f
, "%5d all transition comb vector els, %5d all trans table els\n",
9195 transition_comb_vect_els
, transition_full_vect_els
);
9196 fprintf (f
, "%5d all min delay table els\n", min_issue_delay_vect_els
);
9197 fprintf (f
, "%5d all locked states\n", locked_states
);
9201 /* The function output times of work of different phases of DFA
9204 output_time_statistics (FILE *f
)
9206 fprintf (f
, "\n transformation: ");
9207 print_active_time (f
, transform_time
);
9208 fprintf (f
, (!ndfa_flag
? ", building DFA: " : ", building NDFA: "));
9209 print_active_time (f
, NDFA_time
);
9212 fprintf (f
, ", NDFA -> DFA: ");
9213 print_active_time (f
, NDFA_to_DFA_time
);
9215 fprintf (f
, "\n DFA minimization: ");
9216 print_active_time (f
, minimize_time
);
9217 fprintf (f
, ", making insn equivalence: ");
9218 print_active_time (f
, equiv_time
);
9219 fprintf (f
, "\n all automaton generation: ");
9220 print_active_time (f
, automaton_generation_time
);
9221 fprintf (f
, ", output: ");
9222 print_active_time (f
, output_time
);
9226 /* The function generates DFA (deterministic finite state automaton)
9227 for fast recognition of pipeline hazards. No errors during
9228 checking must be fixed before this function call. */
9232 automata_num
= split_argument
;
9233 if (description
->units_num
< automata_num
)
9234 automata_num
= description
->units_num
;
9237 initiate_automata_lists ();
9238 initiate_pass_states ();
9239 initiate_excl_sets ();
9240 initiate_presence_absence_pattern_sets ();
9241 automaton_generation_time
= create_ticker ();
9243 ticker_off (&automaton_generation_time
);
9248 /* This page mainly contains top level functions of pipeline hazards
9249 description translator. */
9251 /* The following macro value is suffix of name of description file of
9252 pipeline hazards description translator. */
9253 #define STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX ".dfa"
9255 /* The function returns suffix of given file name. The returned
9256 string can not be changed. */
9258 file_name_suffix (const char *file_name
)
9260 const char *last_period
;
9262 for (last_period
= NULL
; *file_name
!= '\0'; file_name
++)
9263 if (*file_name
== '.')
9264 last_period
= file_name
;
9265 return (last_period
== NULL
? file_name
: last_period
);
9268 /* The function returns base name of given file name, i.e. pointer to
9269 first char after last `/' (or `\' for WIN32) in given file name,
9270 given file name itself if the directory name is absent. The
9271 returned string can not be changed. */
9273 base_file_name (const char *file_name
)
9275 int directory_name_length
;
9277 directory_name_length
= strlen (file_name
);
9279 while (directory_name_length
>= 0 && file_name
[directory_name_length
] != '/'
9280 && file_name
[directory_name_length
] != '\\')
9282 while (directory_name_length
>= 0 && file_name
[directory_name_length
] != '/')
9284 directory_name_length
--;
9285 return file_name
+ directory_name_length
+ 1;
9288 /* The following is top level function to initialize the work of
9289 pipeline hazards description translator. */
9291 initiate_automaton_gen (int argc
, char **argv
)
9293 const char *base_name
;
9297 split_argument
= 0; /* default value */
9298 no_minimization_flag
= 0;
9304 for (i
= 2; i
< argc
; i
++)
9305 if (strcmp (argv
[i
], NO_MINIMIZATION_OPTION
) == 0)
9306 no_minimization_flag
= 1;
9307 else if (strcmp (argv
[i
], TIME_OPTION
) == 0)
9309 else if (strcmp (argv
[i
], STATS_OPTION
) == 0)
9311 else if (strcmp (argv
[i
], V_OPTION
) == 0)
9313 else if (strcmp (argv
[i
], W_OPTION
) == 0)
9315 else if (strcmp (argv
[i
], NDFA_OPTION
) == 0)
9317 else if (strcmp (argv
[i
], COLLAPSE_OPTION
) == 0)
9319 else if (strcmp (argv
[i
], PROGRESS_OPTION
) == 0)
9321 else if (strcmp (argv
[i
], "-split") == 0)
9324 fatal ("-split has no argument.");
9325 fatal ("option `-split' has not been implemented yet\n");
9326 /* split_argument = atoi (argument_vect [i + 1]); */
9329 /* Initialize IR storage. */
9330 obstack_init (&irp
);
9331 initiate_automaton_decl_table ();
9332 initiate_insn_decl_table ();
9333 initiate_decl_table ();
9334 output_file
= stdout
;
9335 output_description_file
= NULL
;
9336 base_name
= base_file_name (argv
[1]);
9337 obstack_grow (&irp
, base_name
,
9338 strlen (base_name
) - strlen (file_name_suffix (base_name
)));
9339 obstack_grow (&irp
, STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX
,
9340 strlen (STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX
) + 1);
9341 obstack_1grow (&irp
, '\0');
9342 output_description_file_name
= obstack_base (&irp
);
9343 obstack_finish (&irp
);
9346 /* The following function checks existence at least one arc marked by
9349 check_automata_insn_issues (void)
9351 automaton_t automaton
;
9352 ainsn_t ainsn
, reserv_ainsn
;
9354 for (automaton
= description
->first_automaton
;
9356 automaton
= automaton
->next_automaton
)
9358 for (ainsn
= automaton
->ainsn_list
;
9360 ainsn
= ainsn
->next_ainsn
)
9361 if (ainsn
->first_insn_with_same_reservs
&& !ainsn
->arc_exists_p
9362 && ainsn
!= automaton
->collapse_ainsn
)
9364 for (reserv_ainsn
= ainsn
;
9365 reserv_ainsn
!= NULL
;
9366 reserv_ainsn
= reserv_ainsn
->next_same_reservs_insn
)
9367 if (automaton
->corresponding_automaton_decl
!= NULL
)
9370 error ("Automaton `%s': Insn `%s' will never be issued",
9371 automaton
->corresponding_automaton_decl
->name
,
9372 reserv_ainsn
->insn_reserv_decl
->name
);
9374 warning ("Automaton `%s': Insn `%s' will never be issued",
9375 automaton
->corresponding_automaton_decl
->name
,
9376 reserv_ainsn
->insn_reserv_decl
->name
);
9381 error ("Insn `%s' will never be issued",
9382 reserv_ainsn
->insn_reserv_decl
->name
);
9384 warning ("Insn `%s' will never be issued",
9385 reserv_ainsn
->insn_reserv_decl
->name
);
9391 /* The following vla is used for storing pointers to all achieved
9393 static VEC(state_t
, heap
) *automaton_states
;
9395 /* This function is called by function pass_states to add an achieved
9398 add_automaton_state (state_t state
)
9400 VEC_safe_push (state_t
, heap
, automaton_states
, state
);
9403 /* The following function forms list of important automata (whose
9404 states may be changed after the insn issue) for each insn. */
9406 form_important_insn_automata_lists (void)
9408 automaton_t automaton
;
9415 automaton_states
= 0;
9416 /* Mark important ainsns. */
9417 for (automaton
= description
->first_automaton
;
9419 automaton
= automaton
->next_automaton
)
9421 VEC_truncate (state_t
, automaton_states
, 0);
9422 pass_states (automaton
, add_automaton_state
);
9423 for (n
= 0; n
< VEC_length (state_t
, automaton_states
); n
++)
9425 state_t s
= VEC_index (state_t
, automaton_states
, n
);
9426 for (arc
= first_out_arc (s
);
9428 arc
= next_out_arc (arc
))
9429 if (arc
->to_state
!= s
)
9431 gcc_assert (arc
->insn
->first_insn_with_same_reservs
);
9432 for (ainsn
= arc
->insn
;
9434 ainsn
= ainsn
->next_same_reservs_insn
)
9435 ainsn
->important_p
= TRUE
;
9439 VEC_free (state_t
, heap
, automaton_states
);
9441 /* Create automata sets for the insns. */
9442 for (i
= 0; i
< description
->decls_num
; i
++)
9444 decl
= description
->decls
[i
];
9445 if (decl
->mode
== dm_insn_reserv
)
9447 automata_list_start ();
9448 for (automaton
= description
->first_automaton
;
9450 automaton
= automaton
->next_automaton
)
9451 for (ainsn
= automaton
->ainsn_list
;
9453 ainsn
= ainsn
->next_ainsn
)
9454 if (ainsn
->important_p
9455 && ainsn
->insn_reserv_decl
== DECL_INSN_RESERV (decl
))
9457 automata_list_add (automaton
);
9460 DECL_INSN_RESERV (decl
)->important_automata_list
9461 = automata_list_finish ();
9467 /* The following is top level function to generate automat(a,on) for
9468 fast recognition of pipeline hazards. */
9470 expand_automata (void)
9474 description
= XCREATENODEVAR (struct description
,
9475 sizeof (struct description
)
9476 /* Two entries for special insns. */
9477 + sizeof (decl_t
) * (VEC_length (decl_t
, decls
) + 1));
9478 description
->decls_num
= VEC_length (decl_t
, decls
);
9479 description
->normal_decls_num
= description
->decls_num
;
9480 description
->query_units_num
= 0;
9481 for (i
= 0; i
< description
->decls_num
; i
++)
9483 description
->decls
[i
] = VEC_index (decl_t
, decls
, i
);
9484 if (description
->decls
[i
]->mode
== dm_unit
9485 && DECL_UNIT (description
->decls
[i
])->query_p
)
9486 DECL_UNIT (description
->decls
[i
])->query_num
9487 = description
->query_units_num
++;
9489 all_time
= create_ticker ();
9490 check_time
= create_ticker ();
9492 fprintf (stderr
, "Check description...");
9493 check_all_description ();
9495 fprintf (stderr
, "done\n");
9496 ticker_off (&check_time
);
9497 generation_time
= create_ticker ();
9500 transform_insn_regexps ();
9501 check_unit_distributions_to_automata ();
9506 check_automata_insn_issues ();
9510 form_important_insn_automata_lists ();
9512 ticker_off (&generation_time
);
9515 /* The following is top level function to output PHR and to finish
9516 work with pipeline description translator. */
9518 write_automata (void)
9520 output_time
= create_ticker ();
9522 fprintf (stderr
, "Forming and outputting automata tables...");
9526 fprintf (stderr
, "done\n");
9527 fprintf (stderr
, "Output functions to work with automata...");
9529 output_chip_definitions ();
9530 output_max_insn_queue_index_def ();
9531 output_internal_min_issue_delay_func ();
9532 output_internal_trans_func ();
9533 /* Cache of insn dfa codes: */
9534 fprintf (output_file
, "\nstatic int *%s;\n", DFA_INSN_CODES_VARIABLE_NAME
);
9535 fprintf (output_file
, "\nstatic int %s;\n\n",
9536 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
);
9537 output_dfa_insn_code_func ();
9538 output_trans_func ();
9539 output_min_issue_delay_func ();
9540 output_internal_dead_lock_func ();
9541 output_dead_lock_func ();
9542 output_size_func ();
9543 output_internal_reset_func ();
9544 output_reset_func ();
9545 output_min_insn_conflict_delay_func ();
9546 output_default_latencies ();
9547 output_internal_insn_latency_func ();
9548 output_insn_latency_func ();
9549 output_internal_maximal_insn_latency_func ();
9550 output_maximal_insn_latency_func ();
9551 output_print_reservation_func ();
9552 /* Output function get_cpu_unit_code. */
9553 fprintf (output_file
, "\n#if %s\n\n", CPU_UNITS_QUERY_MACRO_NAME
);
9554 output_get_cpu_unit_code_func ();
9555 output_cpu_unit_reservation_p ();
9556 output_insn_has_dfa_reservation_p ();
9557 fprintf (output_file
, "\n#endif /* #if %s */\n\n",
9558 CPU_UNITS_QUERY_MACRO_NAME
);
9559 output_dfa_clean_insn_cache_func ();
9560 output_dfa_start_func ();
9561 output_dfa_finish_func ();
9563 fprintf (stderr
, "done\n");
9566 output_description_file
= fopen (output_description_file_name
, "w");
9567 if (output_description_file
== NULL
)
9569 perror (output_description_file_name
);
9570 exit (FATAL_EXIT_CODE
);
9573 fprintf (stderr
, "Output automata description...");
9574 output_description ();
9575 output_automaton_descriptions ();
9577 fprintf (stderr
, "done\n");
9578 output_statistics (output_description_file
);
9581 output_statistics (stderr
);
9582 ticker_off (&output_time
);
9584 output_time_statistics (stderr
);
9587 finish_automata_lists ();
9590 fprintf (stderr
, "Summary:\n");
9591 fprintf (stderr
, " check time ");
9592 print_active_time (stderr
, check_time
);
9593 fprintf (stderr
, ", generation time ");
9594 print_active_time (stderr
, generation_time
);
9595 fprintf (stderr
, ", all time ");
9596 print_active_time (stderr
, all_time
);
9597 fprintf (stderr
, "\n");
9599 /* Finish all work. */
9600 if (output_description_file
!= NULL
)
9602 fflush (output_description_file
);
9603 if (ferror (stdout
) != 0)
9604 fatal ("Error in writing DFA description file %s: %s",
9605 output_description_file_name
, xstrerror (errno
));
9606 fclose (output_description_file
);
9608 finish_automaton_decl_table ();
9609 finish_insn_decl_table ();
9610 finish_decl_table ();
9611 obstack_free (&irp
, NULL
);
9612 if (have_error
&& output_description_file
!= NULL
)
9613 remove (output_description_file_name
);
9617 main (int argc
, char **argv
)
9621 progname
= "genautomata";
9623 if (!init_rtx_reader_args (argc
, argv
))
9624 return (FATAL_EXIT_CODE
);
9626 initiate_automaton_gen (argc
, argv
);
9630 int insn_code_number
;
9632 desc
= read_md_rtx (&lineno
, &insn_code_number
);
9636 switch (GET_CODE (desc
))
9638 case DEFINE_CPU_UNIT
:
9639 gen_cpu_unit (desc
);
9642 case DEFINE_QUERY_CPU_UNIT
:
9643 gen_query_cpu_unit (desc
);
9651 gen_excl_set (desc
);
9655 gen_presence_set (desc
);
9658 case FINAL_PRESENCE_SET
:
9659 gen_final_presence_set (desc
);
9663 gen_absence_set (desc
);
9666 case FINAL_ABSENCE_SET
:
9667 gen_final_absence_set (desc
);
9670 case DEFINE_AUTOMATON
:
9671 gen_automaton (desc
);
9674 case AUTOMATA_OPTION
:
9675 gen_automata_option (desc
);
9678 case DEFINE_RESERVATION
:
9682 case DEFINE_INSN_RESERVATION
:
9683 gen_insn_reserv (desc
);
9692 return FATAL_EXIT_CODE
;
9694 if (VEC_length (decl_t
, decls
) > 0)
9699 puts ("/* Generated automatically by the program `genautomata'\n"
9700 " from the machine description file `md'. */\n\n"
9701 "#include \"config.h\"\n"
9702 "#include \"system.h\"\n"
9703 "#include \"coretypes.h\"\n"
9704 "#include \"tm.h\"\n"
9705 "#include \"rtl.h\"\n"
9706 "#include \"tm_p.h\"\n"
9707 "#include \"insn-config.h\"\n"
9708 "#include \"recog.h\"\n"
9709 "#include \"regs.h\"\n"
9710 "#include \"output.h\"\n"
9711 "#include \"insn-attr.h\"\n"
9712 "#include \"diagnostic-core.h\"\n"
9713 "#include \"flags.h\"\n"
9714 "#include \"function.h\"\n"
9715 "#include \"emit-rtl.h\"\n");
9716 /* FIXME: emit-rtl.h can go away once crtl is in rtl.h. */
9723 puts ("/* Generated automatically by the program `genautomata'\n"
9724 " from the machine description file `md'. */\n\n"
9725 "/* There is no automaton, but ISO C forbids empty\n"
9726 " translation units, so include a header file with some\n"
9727 " declarations, and its pre-requisite header file. */\n"
9728 "#include \"config.h\"\n"
9729 "#include \"system.h\"\n");
9733 return (ferror (stdout
) != 0 || have_error
9734 ? FATAL_EXIT_CODE
: SUCCESS_EXIT_CODE
);