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 described 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 bitmap_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 bitmap_bit_p(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 bitmap_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 bitmap_bit_p (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 (bitmap_bit_p (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 (bitmap_bit_p (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 bitmap_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 bitmap_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
,
5080 (unit_usage_t
) NULL
);
5082 index
= cycle
* REGEXP_ONEOF (regexp
)->regexps_num
+ alt_num
;
5084 for (curr
= VEC_index (unit_usage_t
, cycle_alt_unit_usages
, index
);
5086 prev
= curr
, curr
= curr
->next
)
5087 if (curr
->unit_decl
>= unit_decl
)
5089 if (curr
!= NULL
&& curr
->unit_decl
== unit_decl
)
5091 obstack_blank (&unit_usages
, sizeof (struct unit_usage
));
5092 unit_usage_ptr
= (struct unit_usage
*) obstack_base (&unit_usages
);
5093 obstack_finish (&unit_usages
);
5094 unit_usage_ptr
->unit_decl
= unit_decl
;
5095 unit_decl
->last_distribution_check_cycle
= -1; /* undefined */
5096 unit_usage_ptr
->next
= curr
;
5098 VEC_replace (unit_usage_t
, cycle_alt_unit_usages
, index
, unit_usage_ptr
);
5100 prev
->next
= unit_usage_ptr
;
5103 /* Return true if unit UNIT_DECL is present on the LIST. */
5105 unit_present_on_list_p (unit_usage_t list
, unit_decl_t unit_decl
)
5107 while (list
!= NULL
)
5109 if (list
->unit_decl
== unit_decl
)
5116 /* The function returns true if reservations of alternatives ALT1 and
5117 ALT2 are equal after excluding reservations of units of
5118 EXCLUDED_AUTOMATON_DECL. */
5120 equal_alternatives_p (int alt1
, int alt2
, int n_alts
,
5121 struct automaton_decl
*excluded_automaton_decl
)
5124 unit_usage_t list1
, list2
;
5127 i
< (int) VEC_length (unit_usage_t
, cycle_alt_unit_usages
);
5130 for (list1
= VEC_index (unit_usage_t
, cycle_alt_unit_usages
, i
+ alt1
),
5131 list2
= VEC_index (unit_usage_t
, cycle_alt_unit_usages
, i
+ alt2
);;
5132 list1
= list1
->next
, list2
= list2
->next
)
5134 while (list1
!= NULL
5135 && list1
->unit_decl
->automaton_decl
== excluded_automaton_decl
)
5136 list1
= list1
->next
;
5137 while (list2
!= NULL
5138 && list2
->unit_decl
->automaton_decl
== excluded_automaton_decl
)
5139 list2
= list2
->next
;
5140 if (list1
== NULL
|| list2
== NULL
)
5147 if (list1
->unit_decl
!= list2
->unit_decl
)
5155 DEF_VEC_ALLOC_I(int, heap
);
5157 /* The function processes given REGEXP to find units with the wrong
5160 check_regexp_units_distribution (const char *insn_reserv_name
,
5163 int i
, j
, k
, cycle
, start
, n_alts
, alt
, alt2
;
5164 bool annotation_reservation_message_reported_p
;
5165 regexp_t seq
, allof
, unit
;
5166 struct unit_usage
*unit_usage_ptr
;
5167 VEC(int, heap
) *marked
;
5169 if (regexp
== NULL
|| regexp
->mode
!= rm_oneof
)
5171 /* Store all unit usages in the regexp: */
5172 obstack_init (&unit_usages
);
5173 cycle_alt_unit_usages
= VEC_alloc (unit_usage_t
, heap
, 10);
5175 for (i
= REGEXP_ONEOF (regexp
)->regexps_num
- 1; i
>= 0; i
--)
5177 seq
= REGEXP_ONEOF (regexp
)->regexps
[i
];
5181 for (j
= 0; j
< REGEXP_SEQUENCE (seq
)->regexps_num
; j
++)
5183 allof
= REGEXP_SEQUENCE (seq
)->regexps
[j
];
5184 switch (allof
->mode
)
5187 for (k
= 0; k
< REGEXP_ALLOF (allof
)->regexps_num
; k
++)
5189 unit
= REGEXP_ALLOF (allof
)->regexps
[k
];
5190 if (unit
->mode
== rm_unit
)
5191 store_alt_unit_usage (regexp
, unit
, j
, i
);
5193 gcc_assert (unit
->mode
== rm_nothing
);
5198 store_alt_unit_usage (regexp
, allof
, j
, i
);
5211 for (k
= 0; k
< REGEXP_ALLOF (seq
)->regexps_num
; k
++)
5213 unit
= REGEXP_ALLOF (seq
)->regexps
[k
];
5217 store_alt_unit_usage (regexp
, unit
, 0, i
);
5230 store_alt_unit_usage (regexp
, seq
, 0, i
);
5240 /* Check distribution: */
5241 for (i
= 0; i
< (int) VEC_length (unit_usage_t
, cycle_alt_unit_usages
); i
++)
5242 for (unit_usage_ptr
= VEC_index (unit_usage_t
, cycle_alt_unit_usages
, i
);
5243 unit_usage_ptr
!= NULL
;
5244 unit_usage_ptr
= unit_usage_ptr
->next
)
5245 unit_usage_ptr
->unit_decl
->last_distribution_check_cycle
= -1;
5246 n_alts
= REGEXP_ONEOF (regexp
)->regexps_num
;
5247 marked
= VEC_alloc (int, heap
, n_alts
);
5248 for (i
= 0; i
< n_alts
; i
++)
5249 VEC_safe_push (int, heap
, marked
, 0);
5250 annotation_reservation_message_reported_p
= false;
5251 for (i
= 0; i
< (int) VEC_length (unit_usage_t
, cycle_alt_unit_usages
); i
++)
5254 start
= cycle
* n_alts
;
5255 for (unit_usage_ptr
= VEC_index (unit_usage_t
, cycle_alt_unit_usages
, i
);
5256 unit_usage_ptr
!= NULL
;
5257 unit_usage_ptr
= unit_usage_ptr
->next
)
5259 if (unit_usage_ptr
->unit_decl
->last_distribution_check_cycle
== cycle
)
5261 unit_usage_ptr
->unit_decl
->last_distribution_check_cycle
= cycle
;
5262 for (alt
= 0; alt
< n_alts
; alt
++)
5263 if (! unit_present_on_list_p (VEC_index (unit_usage_t
,
5264 cycle_alt_unit_usages
,
5266 unit_usage_ptr
->unit_decl
))
5270 memset (VEC_address (int, marked
), 0, n_alts
* sizeof (int));
5271 for (alt
= 0; alt
< n_alts
; alt
++)
5273 if (! unit_present_on_list_p (VEC_index (unit_usage_t
,
5274 cycle_alt_unit_usages
,
5276 unit_usage_ptr
->unit_decl
))
5279 j
< (int) VEC_length (unit_usage_t
, cycle_alt_unit_usages
);
5283 if (! unit_present_on_list_p
5284 (VEC_index (unit_usage_t
, cycle_alt_unit_usages
,
5286 unit_usage_ptr
->unit_decl
)
5287 && equal_alternatives_p (alt
, alt2
, n_alts
,
5289 ->unit_decl
->automaton_decl
))
5291 VEC_replace (int, marked
, alt
, 1);
5292 VEC_replace (int, marked
, alt2
, 1);
5296 for (alt
= 0; alt
< n_alts
&& VEC_index (int, marked
, alt
); alt
++)
5298 if (alt
< n_alts
&& 0)
5300 if (! annotation_message_reported_p
)
5302 fprintf (stderr
, "\n");
5303 error ("The following units do not satisfy units-automata distribution rule");
5304 error ("(Unit presence on one alt and its absence on other alt\n");
5305 error (" result in different other automata reservations)");
5306 annotation_message_reported_p
= TRUE
;
5308 if (! annotation_reservation_message_reported_p
)
5310 error ("Reserv %s:", insn_reserv_name
);
5311 annotation_reservation_message_reported_p
= true;
5313 error (" Unit %s, cycle %d, alt %d, another alt %d",
5314 unit_usage_ptr
->unit_decl
->name
, cycle
, i
% n_alts
, alt
);
5318 VEC_free (int, heap
, marked
);
5319 VEC_free (unit_usage_t
, heap
, cycle_alt_unit_usages
);
5320 obstack_free (&unit_usages
, NULL
);
5323 /* The function finds units which violates units to automata
5324 distribution rule. If the units exist, report about them. */
5326 check_unit_distributions_to_automata (void)
5332 fprintf (stderr
, "Check unit distributions to automata...");
5333 automaton_decls
= NULL
;
5334 for (i
= 0; i
< description
->decls_num
; i
++)
5336 decl
= description
->decls
[i
];
5337 if (decl
->mode
== dm_automaton
)
5338 VEC_safe_push (decl_t
, heap
, automaton_decls
, decl
);
5340 if (VEC_length (decl_t
, automaton_decls
) > 1)
5342 annotation_message_reported_p
= FALSE
;
5343 for (i
= 0; i
< description
->decls_num
; i
++)
5345 decl
= description
->decls
[i
];
5346 if (decl
->mode
== dm_insn_reserv
)
5347 check_regexp_units_distribution
5348 (DECL_INSN_RESERV (decl
)->name
,
5349 DECL_INSN_RESERV (decl
)->transformed_regexp
);
5352 VEC_free (decl_t
, heap
, automaton_decls
);
5354 fprintf (stderr
, "done\n");
5359 /* The page contains code for building alt_states (see comments for
5360 IR) describing all possible insns reservations of an automaton. */
5362 /* Current state being formed for which the current alt_state
5364 static state_t state_being_formed
;
5366 /* Current alt_state being formed. */
5367 static alt_state_t alt_state_being_formed
;
5369 /* This recursive function processes `,' and units in reservation
5370 REGEXP for forming alt_states of AUTOMATON. It is believed that
5371 CURR_CYCLE is start cycle of all reservation REGEXP. */
5373 process_seq_for_forming_states (regexp_t regexp
, automaton_t automaton
,
5381 switch (regexp
->mode
)
5384 if (REGEXP_UNIT (regexp
)->unit_decl
->corresponding_automaton_num
5385 == automaton
->automaton_order_num
)
5386 set_state_reserv (state_being_formed
, curr_cycle
,
5387 REGEXP_UNIT (regexp
)->unit_decl
->unit_num
);
5391 for (i
= 0; i
< REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
5393 = process_seq_for_forming_states
5394 (REGEXP_SEQUENCE (regexp
)->regexps
[i
], automaton
, curr_cycle
) + 1;
5399 int finish_cycle
= 0;
5402 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
5404 cycle
= process_seq_for_forming_states (REGEXP_ALLOF (regexp
)
5406 automaton
, curr_cycle
);
5407 if (finish_cycle
< cycle
)
5408 finish_cycle
= cycle
;
5410 return finish_cycle
;
5421 /* This recursive function finishes forming ALT_STATE of AUTOMATON and
5422 inserts alt_state into the table. */
5424 finish_forming_alt_state (alt_state_t alt_state
,
5425 automaton_t automaton ATTRIBUTE_UNUSED
)
5427 state_t state_in_table
;
5428 state_t corresponding_state
;
5430 corresponding_state
= alt_state
->state
;
5431 state_in_table
= insert_state (corresponding_state
);
5432 if (state_in_table
!= corresponding_state
)
5434 free_state (corresponding_state
);
5435 alt_state
->state
= state_in_table
;
5439 /* The following variable value is current automaton insn for whose
5440 reservation the alt states are created. */
5441 static ainsn_t curr_ainsn
;
5443 /* This recursive function processes `|' in reservation REGEXP for
5444 forming alt_states of AUTOMATON. List of the alt states should
5445 have the same order as in the description. */
5447 process_alts_for_forming_states (regexp_t regexp
, automaton_t automaton
,
5452 if (regexp
->mode
!= rm_oneof
)
5454 alt_state_being_formed
= get_free_alt_state ();
5455 state_being_formed
= get_free_state (1, automaton
);
5456 alt_state_being_formed
->state
= state_being_formed
;
5457 /* We inserts in reverse order but we process alternatives also
5458 in reverse order. So we have the same order of alternative
5459 as in the description. */
5460 alt_state_being_formed
->next_alt_state
= curr_ainsn
->alt_states
;
5461 curr_ainsn
->alt_states
= alt_state_being_formed
;
5462 (void) process_seq_for_forming_states (regexp
, automaton
, 0);
5463 finish_forming_alt_state (alt_state_being_formed
, automaton
);
5467 gcc_assert (!inside_oneof_p
);
5468 /* We processes it in reverse order to get list with the same
5469 order as in the description. See also the previous
5471 for (i
= REGEXP_ONEOF (regexp
)->regexps_num
- 1; i
>= 0; i
--)
5472 process_alts_for_forming_states (REGEXP_ONEOF (regexp
)->regexps
[i
],
5477 /* Create nodes alt_state for all AUTOMATON insns. */
5479 create_alt_states (automaton_t automaton
)
5481 struct insn_reserv_decl
*reserv_decl
;
5483 for (curr_ainsn
= automaton
->ainsn_list
;
5485 curr_ainsn
= curr_ainsn
->next_ainsn
)
5487 reserv_decl
= curr_ainsn
->insn_reserv_decl
;
5488 if (!special_decl_p (reserv_decl
))
5490 curr_ainsn
->alt_states
= NULL
;
5491 process_alts_for_forming_states (reserv_decl
->transformed_regexp
,
5493 curr_ainsn
->sorted_alt_states
5494 = uniq_sort_alt_states (curr_ainsn
->alt_states
);
5501 /* The page contains major code for building DFA(s) for fast pipeline
5502 hazards recognition. */
5504 /* The function forms list of ainsns of AUTOMATON with the same
5508 form_ainsn_with_same_reservs (automaton_t automaton
)
5512 VEC(ainsn_t
, heap
) *last_insns
= VEC_alloc (ainsn_t
, heap
, 150);
5514 for (curr_ainsn
= automaton
->ainsn_list
;
5516 curr_ainsn
= curr_ainsn
->next_ainsn
)
5517 if (special_decl_p (curr_ainsn
->insn_reserv_decl
))
5519 curr_ainsn
->next_same_reservs_insn
= NULL
;
5520 curr_ainsn
->first_insn_with_same_reservs
= 1;
5524 for (i
= 0; i
< VEC_length (ainsn_t
, last_insns
); i
++)
5526 (curr_ainsn
->sorted_alt_states
,
5527 VEC_index (ainsn_t
, last_insns
, i
)->sorted_alt_states
))
5529 curr_ainsn
->next_same_reservs_insn
= NULL
;
5530 if (i
< VEC_length (ainsn_t
, last_insns
))
5532 curr_ainsn
->first_insn_with_same_reservs
= 0;
5533 VEC_index (ainsn_t
, last_insns
, i
)->next_same_reservs_insn
5535 VEC_replace (ainsn_t
, last_insns
, i
, curr_ainsn
);
5539 VEC_safe_push (ainsn_t
, heap
, last_insns
, curr_ainsn
);
5540 curr_ainsn
->first_insn_with_same_reservs
= 1;
5543 VEC_free (ainsn_t
, heap
, last_insns
);
5546 /* Forming unit reservations which can affect creating the automaton
5547 states achieved from a given state. It permits to build smaller
5548 automata in many cases. We would have the same automata after
5549 the minimization without such optimization, but the automaton
5550 right after the building could be huge. So in other words, usage
5551 of reservs_matter means some minimization during building the
5553 static reserv_sets_t
5554 form_reservs_matter (automaton_t automaton
)
5557 reserv_sets_t reservs_matter
= alloc_empty_reserv_sets();
5559 for (cycle
= 0; cycle
< max_cycles_num
; cycle
++)
5560 for (unit
= 0; unit
< description
->units_num
; unit
++)
5561 if (units_array
[unit
]->automaton_decl
5562 == automaton
->corresponding_automaton_decl
5563 && (cycle
>= units_array
[unit
]->min_occ_cycle_num
5564 /* We can not remove queried unit from reservations. */
5565 || units_array
[unit
]->query_p
5566 /* We can not remove units which are used
5567 `exclusion_set', `presence_set',
5568 `final_presence_set', `absence_set', and
5569 `final_absence_set'. */
5570 || units_array
[unit
]->in_set_p
))
5571 set_unit_reserv (reservs_matter
, cycle
, unit
);
5572 return reservs_matter
;
5575 /* The following function creates all states of nondeterministic AUTOMATON. */
5577 make_automaton (automaton_t automaton
)
5580 struct insn_reserv_decl
*insn_reserv_decl
;
5581 alt_state_t alt_state
;
5583 state_t start_state
;
5585 VEC(state_t
, heap
) *state_stack
= VEC_alloc(state_t
, heap
, 150);
5587 reserv_sets_t reservs_matter
= form_reservs_matter (automaton
);
5589 /* Create the start state (empty state). */
5590 start_state
= insert_state (get_free_state (1, automaton
));
5591 automaton
->start_state
= start_state
;
5592 start_state
->it_was_placed_in_stack_for_NDFA_forming
= 1;
5593 VEC_safe_push (state_t
, heap
, state_stack
, start_state
);
5595 while (VEC_length (state_t
, state_stack
) != 0)
5597 state
= VEC_pop (state_t
, state_stack
);
5598 for (ainsn
= automaton
->ainsn_list
;
5600 ainsn
= ainsn
->next_ainsn
)
5601 if (ainsn
->first_insn_with_same_reservs
)
5603 insn_reserv_decl
= ainsn
->insn_reserv_decl
;
5604 if (!special_decl_p (insn_reserv_decl
))
5606 /* We process alt_states in the same order as they are
5607 present in the description. */
5608 for (alt_state
= ainsn
->alt_states
;
5610 alt_state
= alt_state
->next_alt_state
)
5612 state2
= alt_state
->state
;
5613 if (!intersected_state_reservs_p (state
, state2
))
5615 state2
= states_union (state
, state2
, reservs_matter
);
5616 if (!state2
->it_was_placed_in_stack_for_NDFA_forming
)
5618 state2
->it_was_placed_in_stack_for_NDFA_forming
5620 VEC_safe_push (state_t
, heap
, state_stack
, state2
);
5622 if (progress_flag
&& states_n
% 100 == 0)
5623 fprintf (stderr
, ".");
5625 add_arc (state
, state2
, ainsn
);
5632 /* Add transition to advance cycle. */
5633 state2
= state_shift (state
, reservs_matter
);
5634 if (!state2
->it_was_placed_in_stack_for_NDFA_forming
)
5636 state2
->it_was_placed_in_stack_for_NDFA_forming
= 1;
5637 VEC_safe_push (state_t
, heap
, state_stack
, state2
);
5639 if (progress_flag
&& states_n
% 100 == 0)
5640 fprintf (stderr
, ".");
5642 add_arc (state
, state2
, automaton
->advance_ainsn
);
5644 VEC_free (state_t
, heap
, state_stack
);
5647 /* Form lists of all arcs of STATE marked by the same ainsn. */
5649 form_arcs_marked_by_insn (state_t state
)
5655 for (i
= 0; i
< description
->decls_num
; i
++)
5657 decl
= description
->decls
[i
];
5658 if (decl
->mode
== dm_insn_reserv
)
5659 DECL_INSN_RESERV (decl
)->arcs_marked_by_insn
= NULL
;
5661 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
5663 gcc_assert (arc
->insn
);
5664 arc
->next_arc_marked_by_insn
5665 = arc
->insn
->insn_reserv_decl
->arcs_marked_by_insn
;
5666 arc
->insn
->insn_reserv_decl
->arcs_marked_by_insn
= arc
;
5670 /* The function creates composed state (see comments for IR) from
5671 ORIGINAL_STATE and list of arcs ARCS_MARKED_BY_INSN marked by the
5672 same insn. If the composed state is not in STATE_STACK yet, it is
5673 pushed into STATE_STACK. */
5676 create_composed_state (state_t original_state
, arc_t arcs_marked_by_insn
,
5677 VEC(state_t
, heap
) **state_stack
)
5680 alt_state_t alt_state
, curr_alt_state
;
5681 alt_state_t new_alt_state
;
5684 state_t state_in_table
;
5686 alt_state_t canonical_alt_states_list
;
5688 int new_state_p
= 0;
5690 if (arcs_marked_by_insn
== NULL
)
5692 if (arcs_marked_by_insn
->next_arc_marked_by_insn
== NULL
)
5693 state
= arcs_marked_by_insn
->to_state
;
5696 gcc_assert (ndfa_flag
);
5697 /* Create composed state. */
5698 state
= get_free_state (0, arcs_marked_by_insn
->to_state
->automaton
);
5699 curr_alt_state
= NULL
;
5700 for (curr_arc
= arcs_marked_by_insn
;
5702 curr_arc
= curr_arc
->next_arc_marked_by_insn
)
5703 if (curr_arc
->to_state
->component_states
== NULL
)
5705 new_alt_state
= get_free_alt_state ();
5706 new_alt_state
->next_alt_state
= curr_alt_state
;
5707 new_alt_state
->state
= curr_arc
->to_state
;
5708 curr_alt_state
= new_alt_state
;
5711 for (alt_state
= curr_arc
->to_state
->component_states
;
5713 alt_state
= alt_state
->next_sorted_alt_state
)
5715 new_alt_state
= get_free_alt_state ();
5716 new_alt_state
->next_alt_state
= curr_alt_state
;
5717 new_alt_state
->state
= alt_state
->state
;
5718 gcc_assert (!alt_state
->state
->component_states
);
5719 curr_alt_state
= new_alt_state
;
5721 /* There are not identical sets in the alt state list. */
5722 canonical_alt_states_list
= uniq_sort_alt_states (curr_alt_state
);
5723 if (canonical_alt_states_list
->next_sorted_alt_state
== NULL
)
5726 state
= canonical_alt_states_list
->state
;
5727 free_state (temp_state
);
5731 state
->component_states
= canonical_alt_states_list
;
5732 state_in_table
= insert_state (state
);
5733 if (state_in_table
!= state
)
5736 (state_in_table
->it_was_placed_in_stack_for_DFA_forming
);
5738 state
= state_in_table
;
5742 gcc_assert (!state
->it_was_placed_in_stack_for_DFA_forming
);
5744 for (curr_alt_state
= state
->component_states
;
5745 curr_alt_state
!= NULL
;
5746 curr_alt_state
= curr_alt_state
->next_sorted_alt_state
)
5747 for (curr_arc
= first_out_arc (curr_alt_state
->state
);
5749 curr_arc
= next_out_arc (curr_arc
))
5751 /* When producing collapse-NDFA transitions, we
5752 only add advance-cycle transitions to the
5753 collapsed states. */
5754 || (curr_arc
->insn
->insn_reserv_decl
5755 != DECL_INSN_RESERV (advance_cycle_insn_decl
)))
5756 add_arc (state
, curr_arc
->to_state
, curr_arc
->insn
);
5758 arcs_marked_by_insn
->to_state
= state
;
5759 for (alts_number
= 0,
5760 curr_arc
= arcs_marked_by_insn
->next_arc_marked_by_insn
;
5762 curr_arc
= next_arc
)
5764 next_arc
= curr_arc
->next_arc_marked_by_insn
;
5765 remove_arc (original_state
, curr_arc
);
5770 if (!state
->it_was_placed_in_stack_for_DFA_forming
)
5772 state
->it_was_placed_in_stack_for_DFA_forming
= 1;
5773 VEC_safe_push (state_t
, heap
, *state_stack
, state
);
5778 /* The function transforms nondeterministic AUTOMATON into
5782 NDFA_to_DFA (automaton_t automaton
)
5784 state_t start_state
;
5787 VEC(state_t
, heap
) *state_stack
;
5791 state_stack
= VEC_alloc (state_t
, heap
, 0);
5793 /* Create the start state (empty state). */
5794 start_state
= automaton
->start_state
;
5795 start_state
->it_was_placed_in_stack_for_DFA_forming
= 1;
5796 VEC_safe_push (state_t
, heap
, state_stack
, start_state
);
5798 while (VEC_length (state_t
, state_stack
) != 0)
5800 state
= VEC_pop (state_t
, state_stack
);
5801 form_arcs_marked_by_insn (state
);
5802 for (i
= 0; i
< description
->decls_num
; i
++)
5804 decl
= description
->decls
[i
];
5805 if (decl
->mode
== dm_insn_reserv
5806 && decl
!= collapse_ndfa_insn_decl
5807 && create_composed_state
5808 (state
, DECL_INSN_RESERV (decl
)->arcs_marked_by_insn
,
5812 if (progress_flag
&& states_n
% 100 == 0)
5813 fprintf (stderr
, ".");
5816 /* Add a transition to collapse the NDFA. */
5819 if (state
->component_states
!= NULL
)
5821 state_t state2
= state
->component_states
->state
;
5822 if (!state2
->it_was_placed_in_stack_for_DFA_forming
)
5824 state2
->it_was_placed_in_stack_for_DFA_forming
= 1;
5825 VEC_safe_push (state_t
, heap
, state_stack
, state2
);
5827 add_arc (state
, state2
, automaton
->collapse_ainsn
);
5830 add_arc (state
, state
, automaton
->collapse_ainsn
);
5833 VEC_free (state_t
, heap
, state_stack
);
5836 /* The following variable value is current number (1, 2, ...) of passing
5838 static int curr_state_graph_pass_num
;
5840 /* This recursive function passes all states achieved from START_STATE
5841 and applies APPLIED_FUNC to them. */
5843 pass_state_graph (state_t start_state
, void (*applied_func
) (state_t state
))
5847 if (start_state
->pass_num
== curr_state_graph_pass_num
)
5849 start_state
->pass_num
= curr_state_graph_pass_num
;
5850 (*applied_func
) (start_state
);
5851 for (arc
= first_out_arc (start_state
);
5853 arc
= next_out_arc (arc
))
5854 pass_state_graph (arc
->to_state
, applied_func
);
5857 /* This recursive function passes all states of AUTOMATON and applies
5858 APPLIED_FUNC to them. */
5860 pass_states (automaton_t automaton
, void (*applied_func
) (state_t state
))
5862 curr_state_graph_pass_num
++;
5863 pass_state_graph (automaton
->start_state
, applied_func
);
5866 /* The function initializes code for passing of all states. */
5868 initiate_pass_states (void)
5870 curr_state_graph_pass_num
= 0;
5873 /* The following vla is used for storing pointers to all achieved
5875 static VEC(state_t
, heap
) *all_achieved_states
;
5877 /* This function is called by function pass_states to add an achieved
5880 add_achieved_state (state_t state
)
5882 VEC_safe_push (state_t
, heap
, all_achieved_states
, state
);
5885 /* The function sets up equivalence numbers of insns which mark all
5886 out arcs of STATE by equiv_class_num_1 (if ODD_ITERATION_FLAG has
5887 nonzero value) or by equiv_class_num_2 of the destination state. */
5889 set_out_arc_insns_equiv_num (state_t state
, int odd_iteration_flag
)
5893 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
5895 gcc_assert (!arc
->insn
->insn_reserv_decl
->equiv_class_num
);
5896 arc
->insn
->insn_reserv_decl
->equiv_class_num
5897 = (odd_iteration_flag
5898 ? arc
->to_state
->equiv_class_num_1
5899 : arc
->to_state
->equiv_class_num_2
);
5900 gcc_assert (arc
->insn
->insn_reserv_decl
->equiv_class_num
);
5904 /* The function clears equivalence numbers and alt_states in all insns
5905 which mark all out arcs of STATE. */
5907 clear_arc_insns_equiv_num (state_t state
)
5911 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
5912 arc
->insn
->insn_reserv_decl
->equiv_class_num
= 0;
5916 /* The following function returns TRUE if STATE reserves the unit with
5917 UNIT_NUM on the first cycle. */
5919 first_cycle_unit_presence (state_t state
, int unit_num
)
5921 alt_state_t alt_state
;
5923 if (state
->component_states
== NULL
)
5924 return test_unit_reserv (state
->reservs
, 0, unit_num
);
5927 for (alt_state
= state
->component_states
;
5929 alt_state
= alt_state
->next_sorted_alt_state
)
5930 if (test_unit_reserv (alt_state
->state
->reservs
, 0, unit_num
))
5936 /* This fills in the presence_signature[] member of STATE. */
5938 cache_presence (state_t state
)
5942 sz
= (description
->query_units_num
+ sizeof (int) * CHAR_BIT
- 1)
5943 / (sizeof (int) * CHAR_BIT
);
5945 state
->presence_signature
= XCREATENODEVEC (unsigned int, sz
);
5946 for (i
= 0; i
< description
->units_num
; i
++)
5947 if (units_array
[i
]->query_p
)
5949 int presence1_p
= first_cycle_unit_presence (state
, i
);
5950 state
->presence_signature
[num
/ (sizeof (int) * CHAR_BIT
)]
5951 |= (!!presence1_p
) << (num
% (sizeof (int) * CHAR_BIT
));
5956 /* The function returns nonzero value if STATE is not equivalent to
5957 ANOTHER_STATE from the same current partition on equivalence
5958 classes. Another state has ANOTHER_STATE_OUT_ARCS_NUM number of
5959 output arcs. Iteration of making equivalence partition is defined
5960 by ODD_ITERATION_FLAG. */
5962 state_is_differed (state_t state
, state_t another_state
,
5963 int odd_iteration_flag
)
5966 unsigned int sz
, si
;
5968 gcc_assert (state
->num_out_arcs
== another_state
->num_out_arcs
);
5970 sz
= (description
->query_units_num
+ sizeof (int) * CHAR_BIT
- 1)
5971 / (sizeof (int) * CHAR_BIT
);
5973 for (si
= 0; si
< sz
; si
++)
5974 gcc_assert (state
->presence_signature
[si
]
5975 == another_state
->presence_signature
[si
]);
5977 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
5979 if ((odd_iteration_flag
5980 ? arc
->to_state
->equiv_class_num_1
5981 : arc
->to_state
->equiv_class_num_2
)
5982 != arc
->insn
->insn_reserv_decl
->equiv_class_num
)
5989 /* Compares two states pointed to by STATE_PTR_1 and STATE_PTR_2
5990 and return -1, 0 or 1. This function can be used as predicate for
5991 qsort(). It requires the member presence_signature[] of both
5992 states be filled. */
5994 compare_states_for_equiv (const void *state_ptr_1
,
5995 const void *state_ptr_2
)
5997 const_state_t
const s1
= *(const_state_t
const*)state_ptr_1
;
5998 const_state_t
const s2
= *(const_state_t
const*)state_ptr_2
;
5999 unsigned int sz
, si
;
6000 if (s1
->num_out_arcs
< s2
->num_out_arcs
)
6002 else if (s1
->num_out_arcs
> s2
->num_out_arcs
)
6005 sz
= (description
->query_units_num
+ sizeof (int) * CHAR_BIT
- 1)
6006 / (sizeof (int) * CHAR_BIT
);
6008 for (si
= 0; si
< sz
; si
++)
6009 if (s1
->presence_signature
[si
] < s2
->presence_signature
[si
])
6011 else if (s1
->presence_signature
[si
] > s2
->presence_signature
[si
])
6016 /* The function makes initial partition of STATES on equivalent
6017 classes and saves it into *CLASSES. This function requires the input
6018 to be sorted via compare_states_for_equiv(). */
6020 init_equiv_class (VEC(state_t
, heap
) *states
, VEC (state_t
, heap
) **classes
)
6026 *classes
= VEC_alloc (state_t
, heap
, 150);
6027 for (i
= 0; i
< VEC_length (state_t
, states
); i
++)
6029 state_t state
= VEC_index (state_t
, states
, i
);
6032 if (compare_states_for_equiv (&prev
, &state
) != 0)
6034 VEC_safe_push (state_t
, heap
, *classes
, prev
);
6039 state
->equiv_class_num_1
= class_num
;
6040 state
->next_equiv_class_state
= prev
;
6044 VEC_safe_push (state_t
, heap
, *classes
, prev
);
6048 /* The function copies pointers to equivalent states from vla FROM
6051 copy_equiv_class (VEC(state_t
, heap
) **to
, VEC(state_t
, heap
) *from
)
6053 VEC_free (state_t
, heap
, *to
);
6054 *to
= VEC_copy (state_t
, heap
, from
);
6057 /* The function processes equivalence class given by its first state,
6058 FIRST_STATE, on odd iteration if ODD_ITERATION_FLAG. If there
6059 are not equivalent states, the function partitions the class
6060 removing nonequivalent states and placing them in
6061 *NEXT_ITERATION_CLASSES, increments *NEW_EQUIV_CLASS_NUM_PTR ans
6062 assigns it to the state equivalence number. If the class has been
6063 partitioned, the function returns nonzero value. */
6065 partition_equiv_class (state_t first_state
, int odd_iteration_flag
,
6066 VEC(state_t
, heap
) **next_iteration_classes
,
6067 int *new_equiv_class_num_ptr
)
6069 state_t new_equiv_class
;
6077 while (first_state
!= NULL
)
6079 new_equiv_class
= NULL
;
6080 if (first_state
->next_equiv_class_state
!= NULL
)
6082 /* There are more one states in the class equivalence. */
6083 set_out_arc_insns_equiv_num (first_state
, odd_iteration_flag
);
6084 for (prev_state
= first_state
,
6085 curr_state
= first_state
->next_equiv_class_state
;
6087 curr_state
= next_state
)
6089 next_state
= curr_state
->next_equiv_class_state
;
6090 if (state_is_differed (curr_state
, first_state
,
6091 odd_iteration_flag
))
6093 /* Remove curr state from the class equivalence. */
6094 prev_state
->next_equiv_class_state
= next_state
;
6095 /* Add curr state to the new class equivalence. */
6096 curr_state
->next_equiv_class_state
= new_equiv_class
;
6097 if (new_equiv_class
== NULL
)
6098 (*new_equiv_class_num_ptr
)++;
6099 if (odd_iteration_flag
)
6100 curr_state
->equiv_class_num_2
= *new_equiv_class_num_ptr
;
6102 curr_state
->equiv_class_num_1
= *new_equiv_class_num_ptr
;
6103 new_equiv_class
= curr_state
;
6107 prev_state
= curr_state
;
6109 clear_arc_insns_equiv_num (first_state
);
6111 if (new_equiv_class
!= NULL
)
6112 VEC_safe_push (state_t
, heap
, *next_iteration_classes
, new_equiv_class
);
6113 first_state
= new_equiv_class
;
6118 /* The function finds equivalent states of AUTOMATON. */
6120 evaluate_equiv_classes (automaton_t automaton
,
6121 VEC(state_t
, heap
) **equiv_classes
)
6123 int new_equiv_class_num
;
6124 int odd_iteration_flag
;
6126 VEC (state_t
, heap
) *next_iteration_classes
;
6129 all_achieved_states
= VEC_alloc (state_t
, heap
, 1500);
6130 pass_states (automaton
, add_achieved_state
);
6131 pass_states (automaton
, cache_presence
);
6132 VEC_qsort (state_t
, all_achieved_states
, compare_states_for_equiv
);
6134 odd_iteration_flag
= 0;
6135 new_equiv_class_num
= init_equiv_class (all_achieved_states
,
6136 &next_iteration_classes
);
6140 odd_iteration_flag
= !odd_iteration_flag
;
6142 copy_equiv_class (equiv_classes
, next_iteration_classes
);
6144 /* Transfer equiv numbers for the next iteration. */
6145 for (i
= 0; i
< VEC_length (state_t
, all_achieved_states
); i
++)
6146 if (odd_iteration_flag
)
6147 VEC_index (state_t
, all_achieved_states
, i
)->equiv_class_num_2
6148 = VEC_index (state_t
, all_achieved_states
, i
)->equiv_class_num_1
;
6150 VEC_index (state_t
, all_achieved_states
, i
)->equiv_class_num_1
6151 = VEC_index (state_t
, all_achieved_states
, i
)->equiv_class_num_2
;
6153 for (i
= 0; i
< VEC_length (state_t
, *equiv_classes
); i
++)
6154 if (partition_equiv_class (VEC_index (state_t
, *equiv_classes
, i
),
6156 &next_iteration_classes
,
6157 &new_equiv_class_num
))
6160 while (!finish_flag
);
6161 VEC_free (state_t
, heap
, next_iteration_classes
);
6162 VEC_free (state_t
, heap
, all_achieved_states
);
6165 /* The function merges equivalent states of AUTOMATON. */
6167 merge_states (automaton_t automaton
, VEC(state_t
, heap
) *equiv_classes
)
6171 state_t first_class_state
;
6172 alt_state_t alt_states
;
6173 alt_state_t alt_state
, new_alt_state
;
6178 /* Create states corresponding to equivalence classes containing two
6180 for (i
= 0; i
< VEC_length (state_t
, equiv_classes
); i
++)
6182 curr_state
= VEC_index (state_t
, equiv_classes
, i
);
6183 if (curr_state
->next_equiv_class_state
!= NULL
)
6185 /* There are more one states in the class equivalence. */
6186 /* Create new compound state. */
6187 new_state
= get_free_state (0, automaton
);
6189 first_class_state
= curr_state
;
6190 for (curr_state
= first_class_state
;
6192 curr_state
= curr_state
->next_equiv_class_state
)
6194 curr_state
->equiv_class_state
= new_state
;
6195 if (curr_state
->component_states
== NULL
)
6197 new_alt_state
= get_free_alt_state ();
6198 new_alt_state
->state
= curr_state
;
6199 new_alt_state
->next_alt_state
= alt_states
;
6200 alt_states
= new_alt_state
;
6203 for (alt_state
= curr_state
->component_states
;
6205 alt_state
= alt_state
->next_sorted_alt_state
)
6207 new_alt_state
= get_free_alt_state ();
6208 new_alt_state
->state
= alt_state
->state
;
6209 new_alt_state
->next_alt_state
= alt_states
;
6210 alt_states
= new_alt_state
;
6213 /* Its is important that alt states were sorted before and
6214 after merging to have the same querying results. */
6215 new_state
->component_states
= uniq_sort_alt_states (alt_states
);
6218 curr_state
->equiv_class_state
= curr_state
;
6221 for (i
= 0; i
< VEC_length (state_t
, equiv_classes
); i
++)
6223 curr_state
= VEC_index (state_t
, equiv_classes
, i
);
6224 if (curr_state
->next_equiv_class_state
!= NULL
)
6226 first_class_state
= curr_state
;
6227 /* Create new arcs output from the state corresponding to
6229 for (curr_arc
= first_out_arc (first_class_state
);
6231 curr_arc
= next_out_arc (curr_arc
))
6232 add_arc (first_class_state
->equiv_class_state
,
6233 curr_arc
->to_state
->equiv_class_state
,
6235 /* Delete output arcs from states of given class equivalence. */
6236 for (curr_state
= first_class_state
;
6238 curr_state
= curr_state
->next_equiv_class_state
)
6240 if (automaton
->start_state
== curr_state
)
6241 automaton
->start_state
= curr_state
->equiv_class_state
;
6242 /* Delete the state and its output arcs. */
6243 for (curr_arc
= first_out_arc (curr_state
);
6245 curr_arc
= next_arc
)
6247 next_arc
= next_out_arc (curr_arc
);
6248 free_arc (curr_arc
);
6254 /* Change `to_state' of arcs output from the state of given
6255 equivalence class. */
6256 for (curr_arc
= first_out_arc (curr_state
);
6258 curr_arc
= next_out_arc (curr_arc
))
6259 curr_arc
->to_state
= curr_arc
->to_state
->equiv_class_state
;
6264 /* The function sets up new_cycle_p for states if there is arc to the
6265 state marked by advance_cycle_insn_decl. */
6267 set_new_cycle_flags (state_t state
)
6271 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
6272 if (arc
->insn
->insn_reserv_decl
6273 == DECL_INSN_RESERV (advance_cycle_insn_decl
))
6274 arc
->to_state
->new_cycle_p
= 1;
6277 /* The top level function for minimization of deterministic
6280 minimize_DFA (automaton_t automaton
)
6282 VEC(state_t
, heap
) *equiv_classes
= 0;
6284 evaluate_equiv_classes (automaton
, &equiv_classes
);
6285 merge_states (automaton
, equiv_classes
);
6286 pass_states (automaton
, set_new_cycle_flags
);
6288 VEC_free (state_t
, heap
, equiv_classes
);
6291 /* Values of two variables are counted number of states and arcs in an
6293 static int curr_counted_states_num
;
6294 static int curr_counted_arcs_num
;
6296 /* The function is called by function `pass_states' to count states
6297 and arcs of an automaton. */
6299 incr_states_and_arcs_nums (state_t state
)
6303 curr_counted_states_num
++;
6304 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
6305 curr_counted_arcs_num
++;
6308 /* The function counts states and arcs of AUTOMATON. */
6310 count_states_and_arcs (automaton_t automaton
, int *states_num
,
6313 curr_counted_states_num
= 0;
6314 curr_counted_arcs_num
= 0;
6315 pass_states (automaton
, incr_states_and_arcs_nums
);
6316 *states_num
= curr_counted_states_num
;
6317 *arcs_num
= curr_counted_arcs_num
;
6320 /* The function builds one DFA AUTOMATON for fast pipeline hazards
6321 recognition after checking and simplifying IR of the
6324 build_automaton (automaton_t automaton
)
6329 ticker_on (&NDFA_time
);
6332 if (automaton
->corresponding_automaton_decl
== NULL
)
6333 fprintf (stderr
, "Create anonymous automaton");
6335 fprintf (stderr
, "Create automaton `%s'",
6336 automaton
->corresponding_automaton_decl
->name
);
6337 fprintf (stderr
, " (1 dot is 100 new states):");
6339 make_automaton (automaton
);
6341 fprintf (stderr
, " done\n");
6342 ticker_off (&NDFA_time
);
6343 count_states_and_arcs (automaton
, &states_num
, &arcs_num
);
6344 automaton
->NDFA_states_num
= states_num
;
6345 automaton
->NDFA_arcs_num
= arcs_num
;
6346 ticker_on (&NDFA_to_DFA_time
);
6349 if (automaton
->corresponding_automaton_decl
== NULL
)
6350 fprintf (stderr
, "Make anonymous DFA");
6352 fprintf (stderr
, "Make DFA `%s'",
6353 automaton
->corresponding_automaton_decl
->name
);
6354 fprintf (stderr
, " (1 dot is 100 new states):");
6356 NDFA_to_DFA (automaton
);
6358 fprintf (stderr
, " done\n");
6359 ticker_off (&NDFA_to_DFA_time
);
6360 count_states_and_arcs (automaton
, &states_num
, &arcs_num
);
6361 automaton
->DFA_states_num
= states_num
;
6362 automaton
->DFA_arcs_num
= arcs_num
;
6363 if (!no_minimization_flag
)
6365 ticker_on (&minimize_time
);
6368 if (automaton
->corresponding_automaton_decl
== NULL
)
6369 fprintf (stderr
, "Minimize anonymous DFA...");
6371 fprintf (stderr
, "Minimize DFA `%s'...",
6372 automaton
->corresponding_automaton_decl
->name
);
6374 minimize_DFA (automaton
);
6376 fprintf (stderr
, "done\n");
6377 ticker_off (&minimize_time
);
6378 count_states_and_arcs (automaton
, &states_num
, &arcs_num
);
6379 automaton
->minimal_DFA_states_num
= states_num
;
6380 automaton
->minimal_DFA_arcs_num
= arcs_num
;
6386 /* The page contains code for enumeration of all states of an automaton. */
6388 /* Variable used for enumeration of all states of an automaton. Its
6389 value is current number of automaton states. */
6390 static int curr_state_order_num
;
6392 /* The function is called by function `pass_states' for enumerating
6395 set_order_state_num (state_t state
)
6397 state
->order_state_num
= curr_state_order_num
;
6398 curr_state_order_num
++;
6401 /* The function enumerates all states of AUTOMATON. */
6403 enumerate_states (automaton_t automaton
)
6405 curr_state_order_num
= 0;
6406 pass_states (automaton
, set_order_state_num
);
6407 automaton
->achieved_states_num
= curr_state_order_num
;
6412 /* The page contains code for finding equivalent automaton insns
6415 /* The function inserts AINSN into cyclic list
6416 CYCLIC_EQUIV_CLASS_INSN_LIST of ainsns. */
6418 insert_ainsn_into_equiv_class (ainsn_t ainsn
,
6419 ainsn_t cyclic_equiv_class_insn_list
)
6421 if (cyclic_equiv_class_insn_list
== NULL
)
6422 ainsn
->next_equiv_class_insn
= ainsn
;
6425 ainsn
->next_equiv_class_insn
6426 = cyclic_equiv_class_insn_list
->next_equiv_class_insn
;
6427 cyclic_equiv_class_insn_list
->next_equiv_class_insn
= ainsn
;
6432 /* The function deletes equiv_class_insn into cyclic list of
6433 equivalent ainsns. */
6435 delete_ainsn_from_equiv_class (ainsn_t equiv_class_insn
)
6437 ainsn_t curr_equiv_class_insn
;
6438 ainsn_t prev_equiv_class_insn
;
6440 prev_equiv_class_insn
= equiv_class_insn
;
6441 for (curr_equiv_class_insn
= equiv_class_insn
->next_equiv_class_insn
;
6442 curr_equiv_class_insn
!= equiv_class_insn
;
6443 curr_equiv_class_insn
= curr_equiv_class_insn
->next_equiv_class_insn
)
6444 prev_equiv_class_insn
= curr_equiv_class_insn
;
6445 if (prev_equiv_class_insn
!= equiv_class_insn
)
6446 prev_equiv_class_insn
->next_equiv_class_insn
6447 = equiv_class_insn
->next_equiv_class_insn
;
6450 /* The function processes AINSN of a state in order to find equivalent
6451 ainsns. INSN_ARCS_ARRAY is table: code of insn -> out arc of the
6454 process_insn_equiv_class (ainsn_t ainsn
, arc_t
*insn_arcs_array
)
6458 ainsn_t cyclic_insn_list
;
6461 gcc_assert (insn_arcs_array
[ainsn
->insn_reserv_decl
->insn_num
]);
6463 /* New class of ainsns which are not equivalent to given ainsn. */
6464 cyclic_insn_list
= NULL
;
6467 next_insn
= curr_insn
->next_equiv_class_insn
;
6468 arc
= insn_arcs_array
[curr_insn
->insn_reserv_decl
->insn_num
];
6470 || (insn_arcs_array
[ainsn
->insn_reserv_decl
->insn_num
]->to_state
6473 delete_ainsn_from_equiv_class (curr_insn
);
6474 cyclic_insn_list
= insert_ainsn_into_equiv_class (curr_insn
,
6477 curr_insn
= next_insn
;
6479 while (curr_insn
!= ainsn
);
6482 /* The function processes STATE in order to find equivalent ainsns. */
6484 process_state_for_insn_equiv_partition (state_t state
)
6487 arc_t
*insn_arcs_array
= XCNEWVEC (arc_t
, description
->insns_num
);
6489 /* Process insns of the arcs. */
6490 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
6491 insn_arcs_array
[arc
->insn
->insn_reserv_decl
->insn_num
] = arc
;
6492 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
6493 process_insn_equiv_class (arc
->insn
, insn_arcs_array
);
6495 free (insn_arcs_array
);
6498 /* The function searches for equivalent ainsns of AUTOMATON. */
6500 set_insn_equiv_classes (automaton_t automaton
)
6505 ainsn_t cyclic_insn_list
;
6506 ainsn_t insn_with_same_reservs
;
6507 int equiv_classes_num
;
6509 /* All insns are included in one equivalence class. */
6510 cyclic_insn_list
= NULL
;
6511 for (ainsn
= automaton
->ainsn_list
; ainsn
!= NULL
; ainsn
= ainsn
->next_ainsn
)
6512 if (ainsn
->first_insn_with_same_reservs
)
6513 cyclic_insn_list
= insert_ainsn_into_equiv_class (ainsn
,
6515 /* Process insns in order to make equivalence partition. */
6516 pass_states (automaton
, process_state_for_insn_equiv_partition
);
6517 /* Enumerate equiv classes. */
6518 for (ainsn
= automaton
->ainsn_list
; ainsn
!= NULL
; ainsn
= ainsn
->next_ainsn
)
6519 /* Set undefined value. */
6520 ainsn
->insn_equiv_class_num
= -1;
6521 equiv_classes_num
= 0;
6522 for (ainsn
= automaton
->ainsn_list
; ainsn
!= NULL
; ainsn
= ainsn
->next_ainsn
)
6523 if (ainsn
->insn_equiv_class_num
< 0)
6526 gcc_assert (first_insn
->first_insn_with_same_reservs
);
6527 first_insn
->first_ainsn_with_given_equivalence_num
= 1;
6528 curr_insn
= first_insn
;
6531 for (insn_with_same_reservs
= curr_insn
;
6532 insn_with_same_reservs
!= NULL
;
6533 insn_with_same_reservs
6534 = insn_with_same_reservs
->next_same_reservs_insn
)
6535 insn_with_same_reservs
->insn_equiv_class_num
= equiv_classes_num
;
6536 curr_insn
= curr_insn
->next_equiv_class_insn
;
6538 while (curr_insn
!= first_insn
);
6539 equiv_classes_num
++;
6541 automaton
->insn_equiv_classes_num
= equiv_classes_num
;
6546 /* This page contains code for creating DFA(s) and calls functions
6550 /* The following value is used to prevent floating point overflow for
6551 estimating an automaton bound. The value should be less DBL_MAX on
6552 the host machine. We use here approximate minimum of maximal
6553 double floating point value required by ANSI C standard. It
6554 will work for non ANSI sun compiler too. */
6556 #define MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND 1.0E37
6558 /* The function estimate size of the single DFA used by PHR (pipeline
6559 hazards recognizer). */
6561 estimate_one_automaton_bound (void)
6564 double one_automaton_estimation_bound
;
6568 one_automaton_estimation_bound
= 1.0;
6569 for (i
= 0; i
< description
->decls_num
; i
++)
6571 decl
= description
->decls
[i
];
6572 if (decl
->mode
== dm_unit
)
6574 root_value
= exp (log (DECL_UNIT (decl
)->max_occ_cycle_num
6575 - DECL_UNIT (decl
)->min_occ_cycle_num
+ 1.0)
6577 if (MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND
/ root_value
6578 > one_automaton_estimation_bound
)
6579 one_automaton_estimation_bound
*= root_value
;
6582 return one_automaton_estimation_bound
;
6585 /* The function compares unit declarations according to their maximal
6586 cycle in reservations. */
6588 compare_max_occ_cycle_nums (const void *unit_decl_1
,
6589 const void *unit_decl_2
)
6591 if ((DECL_UNIT (*(const_decl_t
const*) unit_decl_1
)->max_occ_cycle_num
)
6592 < (DECL_UNIT (*(const_decl_t
const*) unit_decl_2
)->max_occ_cycle_num
))
6594 else if ((DECL_UNIT (*(const_decl_t
const*) unit_decl_1
)->max_occ_cycle_num
)
6595 == (DECL_UNIT (*(const_decl_t
const*) unit_decl_2
)->max_occ_cycle_num
))
6601 /* The function makes heuristic assigning automata to units. Actually
6602 efficacy of the algorithm has been checked yet??? */
6605 units_to_automata_heuristic_distr (void)
6607 double estimation_bound
;
6611 unit_decl_t
*unit_decls
;
6614 if (description
->units_num
== 0)
6616 estimation_bound
= estimate_one_automaton_bound ();
6617 unit_decls
= XNEWVEC (unit_decl_t
, description
->units_num
);
6619 for (i
= 0, j
= 0; i
< description
->decls_num
; i
++)
6620 if (description
->decls
[i
]->mode
== dm_unit
)
6621 unit_decls
[j
++] = DECL_UNIT (description
->decls
[i
]);
6622 gcc_assert (j
== description
->units_num
);
6624 qsort (unit_decls
, description
->units_num
,
6625 sizeof (unit_decl_t
), compare_max_occ_cycle_nums
);
6628 bound_value
= unit_decls
[0]->max_occ_cycle_num
;
6629 unit_decls
[0]->corresponding_automaton_num
= automaton_num
;
6631 for (i
= 1; i
< description
->units_num
; i
++)
6633 rest_units_num
= description
->units_num
- i
+ 1;
6634 gcc_assert (automata_num
- automaton_num
- 1 <= rest_units_num
);
6635 if (automaton_num
< automata_num
- 1
6636 && ((automata_num
- automaton_num
- 1 == rest_units_num
)
6639 / unit_decls
[i
]->max_occ_cycle_num
))))
6641 bound_value
= unit_decls
[i
]->max_occ_cycle_num
;
6645 bound_value
*= unit_decls
[i
]->max_occ_cycle_num
;
6646 unit_decls
[i
]->corresponding_automaton_num
= automaton_num
;
6648 gcc_assert (automaton_num
== automata_num
- 1);
6652 /* The functions creates automaton insns for each automata. Automaton
6653 insn is simply insn for given automaton which makes reservation
6654 only of units of the automaton. */
6656 create_ainsns (automaton_t automaton
)
6659 ainsn_t first_ainsn
;
6666 for (i
= 0; i
< description
->decls_num
; i
++)
6668 decl
= description
->decls
[i
];
6669 if (decl
->mode
== dm_insn_reserv
)
6671 curr_ainsn
= XCREATENODE (struct ainsn
);
6672 curr_ainsn
->insn_reserv_decl
= DECL_INSN_RESERV (decl
);
6673 curr_ainsn
->important_p
= FALSE
;
6674 curr_ainsn
->next_ainsn
= NULL
;
6675 if (prev_ainsn
== NULL
)
6676 first_ainsn
= curr_ainsn
;
6678 prev_ainsn
->next_ainsn
= curr_ainsn
;
6679 if (decl
== advance_cycle_insn_decl
)
6680 automaton
->advance_ainsn
= curr_ainsn
;
6681 else if (decl
== collapse_ndfa_insn_decl
)
6682 automaton
->collapse_ainsn
= curr_ainsn
;
6683 prev_ainsn
= curr_ainsn
;
6686 automaton
->ainsn_list
= first_ainsn
;
6689 /* The function assigns automata to units according to constructions
6690 `define_automaton' in the description. */
6692 units_to_automata_distr (void)
6697 for (i
= 0; i
< description
->decls_num
; i
++)
6699 decl
= description
->decls
[i
];
6700 if (decl
->mode
== dm_unit
)
6702 if (DECL_UNIT (decl
)->automaton_decl
== NULL
6703 || (DECL_UNIT (decl
)->automaton_decl
->corresponding_automaton
6705 /* Distribute to the first automaton. */
6706 DECL_UNIT (decl
)->corresponding_automaton_num
= 0;
6708 DECL_UNIT (decl
)->corresponding_automaton_num
6709 = (DECL_UNIT (decl
)->automaton_decl
6710 ->corresponding_automaton
->automaton_order_num
);
6715 /* The function creates DFA(s) for fast pipeline hazards recognition
6716 after checking and simplifying IR of the description. */
6718 create_automata (void)
6720 automaton_t curr_automaton
;
6721 automaton_t prev_automaton
;
6723 int curr_automaton_num
;
6726 if (automata_num
!= 0)
6728 units_to_automata_heuristic_distr ();
6729 for (prev_automaton
= NULL
, curr_automaton_num
= 0;
6730 curr_automaton_num
< automata_num
;
6731 curr_automaton_num
++, prev_automaton
= curr_automaton
)
6733 curr_automaton
= XCREATENODE (struct automaton
);
6734 create_ainsns (curr_automaton
);
6735 curr_automaton
->corresponding_automaton_decl
= NULL
;
6736 curr_automaton
->next_automaton
= NULL
;
6737 curr_automaton
->automaton_order_num
= curr_automaton_num
;
6738 if (prev_automaton
== NULL
)
6739 description
->first_automaton
= curr_automaton
;
6741 prev_automaton
->next_automaton
= curr_automaton
;
6746 curr_automaton_num
= 0;
6747 prev_automaton
= NULL
;
6748 for (i
= 0; i
< description
->decls_num
; i
++)
6750 decl
= description
->decls
[i
];
6751 if (decl
->mode
== dm_automaton
6752 && DECL_AUTOMATON (decl
)->automaton_is_used
)
6754 curr_automaton
= XCREATENODE (struct automaton
);
6755 create_ainsns (curr_automaton
);
6756 curr_automaton
->corresponding_automaton_decl
6757 = DECL_AUTOMATON (decl
);
6758 curr_automaton
->next_automaton
= NULL
;
6759 DECL_AUTOMATON (decl
)->corresponding_automaton
= curr_automaton
;
6760 curr_automaton
->automaton_order_num
= curr_automaton_num
;
6761 if (prev_automaton
== NULL
)
6762 description
->first_automaton
= curr_automaton
;
6764 prev_automaton
->next_automaton
= curr_automaton
;
6765 curr_automaton_num
++;
6766 prev_automaton
= curr_automaton
;
6769 if (curr_automaton_num
== 0)
6771 curr_automaton
= XCREATENODE (struct automaton
);
6772 create_ainsns (curr_automaton
);
6773 curr_automaton
->corresponding_automaton_decl
= NULL
;
6774 curr_automaton
->next_automaton
= NULL
;
6775 description
->first_automaton
= curr_automaton
;
6777 units_to_automata_distr ();
6779 NDFA_time
= create_ticker ();
6780 ticker_off (&NDFA_time
);
6781 NDFA_to_DFA_time
= create_ticker ();
6782 ticker_off (&NDFA_to_DFA_time
);
6783 minimize_time
= create_ticker ();
6784 ticker_off (&minimize_time
);
6785 equiv_time
= create_ticker ();
6786 ticker_off (&equiv_time
);
6787 for (curr_automaton
= description
->first_automaton
;
6788 curr_automaton
!= NULL
;
6789 curr_automaton
= curr_automaton
->next_automaton
)
6793 if (curr_automaton
->corresponding_automaton_decl
== NULL
)
6794 fprintf (stderr
, "Prepare anonymous automaton creation ... ");
6796 fprintf (stderr
, "Prepare automaton `%s' creation...",
6797 curr_automaton
->corresponding_automaton_decl
->name
);
6799 create_alt_states (curr_automaton
);
6800 form_ainsn_with_same_reservs (curr_automaton
);
6802 fprintf (stderr
, "done\n");
6803 build_automaton (curr_automaton
);
6804 enumerate_states (curr_automaton
);
6805 ticker_on (&equiv_time
);
6806 set_insn_equiv_classes (curr_automaton
);
6807 ticker_off (&equiv_time
);
6813 /* This page contains code for forming string representation of
6814 regexp. The representation is formed on IR obstack. So you should
6815 not work with IR obstack between regexp_representation and
6816 finish_regexp_representation calls. */
6818 /* This recursive function forms string representation of regexp
6819 (without tailing '\0'). */
6821 form_regexp (regexp_t regexp
)
6825 switch (regexp
->mode
)
6827 case rm_unit
: case rm_reserv
:
6829 const char *name
= (regexp
->mode
== rm_unit
6830 ? REGEXP_UNIT (regexp
)->name
6831 : REGEXP_RESERV (regexp
)->name
);
6833 obstack_grow (&irp
, name
, strlen (name
));
6838 for (i
= 0; i
< REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
6841 obstack_1grow (&irp
, ',');
6842 form_regexp (REGEXP_SEQUENCE (regexp
)->regexps
[i
]);
6847 obstack_1grow (&irp
, '(');
6848 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
6851 obstack_1grow (&irp
, '+');
6852 if (REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
== rm_sequence
6853 || REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
== rm_oneof
)
6854 obstack_1grow (&irp
, '(');
6855 form_regexp (REGEXP_ALLOF (regexp
)->regexps
[i
]);
6856 if (REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
== rm_sequence
6857 || REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
== rm_oneof
)
6858 obstack_1grow (&irp
, ')');
6860 obstack_1grow (&irp
, ')');
6864 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
6867 obstack_1grow (&irp
, '|');
6868 if (REGEXP_ONEOF (regexp
)->regexps
[i
]->mode
== rm_sequence
)
6869 obstack_1grow (&irp
, '(');
6870 form_regexp (REGEXP_ONEOF (regexp
)->regexps
[i
]);
6871 if (REGEXP_ONEOF (regexp
)->regexps
[i
]->mode
== rm_sequence
)
6872 obstack_1grow (&irp
, ')');
6880 if (REGEXP_REPEAT (regexp
)->regexp
->mode
== rm_sequence
6881 || REGEXP_REPEAT (regexp
)->regexp
->mode
== rm_allof
6882 || REGEXP_REPEAT (regexp
)->regexp
->mode
== rm_oneof
)
6883 obstack_1grow (&irp
, '(');
6884 form_regexp (REGEXP_REPEAT (regexp
)->regexp
);
6885 if (REGEXP_REPEAT (regexp
)->regexp
->mode
== rm_sequence
6886 || REGEXP_REPEAT (regexp
)->regexp
->mode
== rm_allof
6887 || REGEXP_REPEAT (regexp
)->regexp
->mode
== rm_oneof
)
6888 obstack_1grow (&irp
, ')');
6889 sprintf (digits
, "*%d", REGEXP_REPEAT (regexp
)->repeat_num
);
6890 obstack_grow (&irp
, digits
, strlen (digits
));
6895 obstack_grow (&irp
, NOTHING_NAME
, strlen (NOTHING_NAME
));
6903 /* The function returns string representation of REGEXP on IR
6906 regexp_representation (regexp_t regexp
)
6908 form_regexp (regexp
);
6909 obstack_1grow (&irp
, '\0');
6910 return obstack_base (&irp
);
6913 /* The function frees memory allocated for last formed string
6914 representation of regexp. */
6916 finish_regexp_representation (void)
6918 int length
= obstack_object_size (&irp
);
6920 obstack_blank_fast (&irp
, -length
);
6925 /* This page contains code for output PHR (pipeline hazards recognizer). */
6927 /* The function outputs minimal C type which is sufficient for
6928 representation numbers in range min_range_value and
6929 max_range_value. Because host machine and build machine may be
6930 different, we use here minimal values required by ANSI C standard
6931 instead of UCHAR_MAX, SHRT_MAX, SHRT_MIN, etc. This is a good
6935 output_range_type (FILE *f
, long int min_range_value
,
6936 long int max_range_value
)
6938 if (min_range_value
>= 0 && max_range_value
<= 255)
6939 fprintf (f
, "unsigned char");
6940 else if (min_range_value
>= -127 && max_range_value
<= 127)
6941 fprintf (f
, "signed char");
6942 else if (min_range_value
>= 0 && max_range_value
<= 65535)
6943 fprintf (f
, "unsigned short");
6944 else if (min_range_value
>= -32767 && max_range_value
<= 32767)
6945 fprintf (f
, "short");
6950 /* The function outputs all initialization values of VECT. */
6952 output_vect (vla_hwint_t vect
)
6955 size_t vect_length
= VEC_length (vect_el_t
, vect
);
6959 if (vect_length
== 0)
6960 fputs ("0 /* This is dummy el because the vect is empty */", output_file
);
6962 for (i
= 0; i
< vect_length
; i
++)
6964 fprintf (output_file
, "%5ld", (long) VEC_index (vect_el_t
, vect
, i
));
6965 if (els_on_line
== 10)
6968 fputs (",\n", output_file
);
6970 else if (i
< vect_length
-1)
6971 fputs (", ", output_file
);
6976 /* The following is name of the structure which represents DFA(s) for
6978 #define CHIP_NAME "DFA_chip"
6980 /* The following is name of member which represents state of a DFA for
6983 output_chip_member_name (FILE *f
, automaton_t automaton
)
6985 if (automaton
->corresponding_automaton_decl
== NULL
)
6986 fprintf (f
, "automaton_state_%d", automaton
->automaton_order_num
);
6988 fprintf (f
, "%s_automaton_state",
6989 automaton
->corresponding_automaton_decl
->name
);
6992 /* The following is name of temporary variable which stores state of a
6995 output_temp_chip_member_name (FILE *f
, automaton_t automaton
)
6998 output_chip_member_name (f
, automaton
);
7001 /* This is name of macro value which is code of pseudo_insns
7002 representing advancing cpu cycle and collapsing the NDFA.
7003 Its value is used as internal code unknown insn. */
7004 #define ADVANCE_CYCLE_VALUE_NAME "DFA__ADVANCE_CYCLE"
7005 #define COLLAPSE_NDFA_VALUE_NAME "NDFA__COLLAPSE"
7007 /* Output name of translate vector for given automaton. */
7009 output_translate_vect_name (FILE *f
, automaton_t automaton
)
7011 if (automaton
->corresponding_automaton_decl
== NULL
)
7012 fprintf (f
, "translate_%d", automaton
->automaton_order_num
);
7014 fprintf (f
, "%s_translate", automaton
->corresponding_automaton_decl
->name
);
7017 /* Output name for simple transition table representation. */
7019 output_trans_full_vect_name (FILE *f
, automaton_t automaton
)
7021 if (automaton
->corresponding_automaton_decl
== NULL
)
7022 fprintf (f
, "transitions_%d", automaton
->automaton_order_num
);
7024 fprintf (f
, "%s_transitions",
7025 automaton
->corresponding_automaton_decl
->name
);
7028 /* Output name of comb vector of the transition table for given
7031 output_trans_comb_vect_name (FILE *f
, automaton_t automaton
)
7033 if (automaton
->corresponding_automaton_decl
== NULL
)
7034 fprintf (f
, "transitions_%d", automaton
->automaton_order_num
);
7036 fprintf (f
, "%s_transitions",
7037 automaton
->corresponding_automaton_decl
->name
);
7040 /* Output name of check vector of the transition table for given
7043 output_trans_check_vect_name (FILE *f
, automaton_t automaton
)
7045 if (automaton
->corresponding_automaton_decl
== NULL
)
7046 fprintf (f
, "check_%d", automaton
->automaton_order_num
);
7048 fprintf (f
, "%s_check", automaton
->corresponding_automaton_decl
->name
);
7051 /* Output name of base vector of the transition table for given
7054 output_trans_base_vect_name (FILE *f
, automaton_t automaton
)
7056 if (automaton
->corresponding_automaton_decl
== NULL
)
7057 fprintf (f
, "base_%d", automaton
->automaton_order_num
);
7059 fprintf (f
, "%s_base", automaton
->corresponding_automaton_decl
->name
);
7062 /* Output name of simple min issue delay table representation. */
7064 output_min_issue_delay_vect_name (FILE *f
, automaton_t automaton
)
7066 if (automaton
->corresponding_automaton_decl
== NULL
)
7067 fprintf (f
, "min_issue_delay_%d", automaton
->automaton_order_num
);
7069 fprintf (f
, "%s_min_issue_delay",
7070 automaton
->corresponding_automaton_decl
->name
);
7073 /* Output name of deadlock vector for given automaton. */
7075 output_dead_lock_vect_name (FILE *f
, automaton_t automaton
)
7077 if (automaton
->corresponding_automaton_decl
== NULL
)
7078 fprintf (f
, "dead_lock_%d", automaton
->automaton_order_num
);
7080 fprintf (f
, "%s_dead_lock", automaton
->corresponding_automaton_decl
->name
);
7083 /* Output name of reserved units table for AUTOMATON into file F. */
7085 output_reserved_units_table_name (FILE *f
, automaton_t automaton
)
7087 if (automaton
->corresponding_automaton_decl
== NULL
)
7088 fprintf (f
, "reserved_units_%d", automaton
->automaton_order_num
);
7090 fprintf (f
, "%s_reserved_units",
7091 automaton
->corresponding_automaton_decl
->name
);
7094 /* Name of the PHR interface macro. */
7095 #define CPU_UNITS_QUERY_MACRO_NAME "CPU_UNITS_QUERY"
7097 /* Names of an internal functions: */
7098 #define INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME "internal_min_issue_delay"
7100 /* This is external type of DFA(s) state. */
7101 #define STATE_TYPE_NAME "state_t"
7103 #define INTERNAL_TRANSITION_FUNC_NAME "internal_state_transition"
7105 #define INTERNAL_RESET_FUNC_NAME "internal_reset"
7107 #define INTERNAL_DEAD_LOCK_FUNC_NAME "internal_state_dead_lock_p"
7109 #define INTERNAL_INSN_LATENCY_FUNC_NAME "internal_insn_latency"
7111 /* Name of cache of insn dfa codes. */
7112 #define DFA_INSN_CODES_VARIABLE_NAME "dfa_insn_codes"
7114 /* Name of length of cache of insn dfa codes. */
7115 #define DFA_INSN_CODES_LENGTH_VARIABLE_NAME "dfa_insn_codes_length"
7117 /* Names of the PHR interface functions: */
7118 #define SIZE_FUNC_NAME "state_size"
7120 #define TRANSITION_FUNC_NAME "state_transition"
7122 #define MIN_ISSUE_DELAY_FUNC_NAME "min_issue_delay"
7124 #define MIN_INSN_CONFLICT_DELAY_FUNC_NAME "min_insn_conflict_delay"
7126 #define DEAD_LOCK_FUNC_NAME "state_dead_lock_p"
7128 #define RESET_FUNC_NAME "state_reset"
7130 #define INSN_LATENCY_FUNC_NAME "insn_latency"
7132 #define PRINT_RESERVATION_FUNC_NAME "print_reservation"
7134 #define GET_CPU_UNIT_CODE_FUNC_NAME "get_cpu_unit_code"
7136 #define CPU_UNIT_RESERVATION_P_FUNC_NAME "cpu_unit_reservation_p"
7138 #define INSN_HAS_DFA_RESERVATION_P_FUNC_NAME "insn_has_dfa_reservation_p"
7140 #define DFA_CLEAN_INSN_CACHE_FUNC_NAME "dfa_clean_insn_cache"
7142 #define DFA_CLEAR_SINGLE_INSN_CACHE_FUNC_NAME "dfa_clear_single_insn_cache"
7144 #define DFA_START_FUNC_NAME "dfa_start"
7146 #define DFA_FINISH_FUNC_NAME "dfa_finish"
7148 /* Names of parameters of the PHR interface functions. */
7149 #define STATE_NAME "state"
7151 #define INSN_PARAMETER_NAME "insn"
7153 #define INSN2_PARAMETER_NAME "insn2"
7155 #define CHIP_PARAMETER_NAME "chip"
7157 #define FILE_PARAMETER_NAME "f"
7159 #define CPU_UNIT_NAME_PARAMETER_NAME "cpu_unit_name"
7161 #define CPU_CODE_PARAMETER_NAME "cpu_unit_code"
7163 /* Names of the variables whose values are internal insn code of rtx
7165 #define INTERNAL_INSN_CODE_NAME "insn_code"
7167 #define INTERNAL_INSN2_CODE_NAME "insn2_code"
7169 /* Names of temporary variables in some functions. */
7170 #define TEMPORARY_VARIABLE_NAME "temp"
7172 #define I_VARIABLE_NAME "i"
7174 /* Name of result variable in some functions. */
7175 #define RESULT_VARIABLE_NAME "res"
7177 /* Name of function (attribute) to translate insn into internal insn
7179 #define INTERNAL_DFA_INSN_CODE_FUNC_NAME "internal_dfa_insn_code"
7181 /* Name of function (attribute) to translate insn into internal insn
7182 code with caching. */
7183 #define DFA_INSN_CODE_FUNC_NAME "dfa_insn_code"
7185 /* Output C type which is used for representation of codes of states
7188 output_state_member_type (FILE *f
, automaton_t automaton
)
7190 output_range_type (f
, 0, automaton
->achieved_states_num
);
7193 /* Output definition of the structure representing current DFA(s)
7196 output_chip_definitions (void)
7198 automaton_t automaton
;
7200 fprintf (output_file
, "struct %s\n{\n", CHIP_NAME
);
7201 for (automaton
= description
->first_automaton
;
7203 automaton
= automaton
->next_automaton
)
7205 fprintf (output_file
, " ");
7206 output_state_member_type (output_file
, automaton
);
7207 fprintf (output_file
, " ");
7208 output_chip_member_name (output_file
, automaton
);
7209 fprintf (output_file
, ";\n");
7211 fprintf (output_file
, "};\n\n");
7213 fprintf (output_file
, "static struct %s %s;\n\n", CHIP_NAME
, CHIP_NAME
);
7218 /* The function outputs translate vector of internal insn code into
7219 insn equivalence class number. The equivalence class number is
7220 used to access to table and vectors representing DFA(s). */
7222 output_translate_vect (automaton_t automaton
)
7226 vla_hwint_t translate_vect
;
7228 translate_vect
= VEC_alloc (vect_el_t
, heap
, description
->insns_num
);
7230 for (insn_value
= 0; insn_value
< description
->insns_num
; insn_value
++)
7231 /* Undefined value */
7232 VEC_quick_push (vect_el_t
, translate_vect
,
7233 automaton
->insn_equiv_classes_num
);
7235 for (ainsn
= automaton
->ainsn_list
; ainsn
!= NULL
; ainsn
= ainsn
->next_ainsn
)
7236 VEC_replace (vect_el_t
, translate_vect
,
7237 ainsn
->insn_reserv_decl
->insn_num
,
7238 ainsn
->insn_equiv_class_num
);
7240 fprintf (output_file
,
7241 "/* Vector translating external insn codes to internal ones.*/\n");
7242 fprintf (output_file
, "static const ");
7243 output_range_type (output_file
, 0, automaton
->insn_equiv_classes_num
);
7244 fprintf (output_file
, " ");
7245 output_translate_vect_name (output_file
, automaton
);
7246 fprintf (output_file
, "[] ATTRIBUTE_UNUSED = {\n");
7247 output_vect (translate_vect
);
7248 fprintf (output_file
, "};\n\n");
7249 VEC_free (vect_el_t
, heap
, translate_vect
);
7252 /* The value in a table state x ainsn -> something which represents
7254 static int undefined_vect_el_value
;
7256 /* The following function returns nonzero value if the best
7257 representation of the table is comb vector. */
7259 comb_vect_p (state_ainsn_table_t tab
)
7263 return (2 * VEC_length (vect_el_t
, tab
->full_vect
)
7264 > 5 * VEC_length (vect_el_t
, tab
->comb_vect
));
7267 /* The following function creates new table for AUTOMATON. */
7268 static state_ainsn_table_t
7269 create_state_ainsn_table (automaton_t automaton
)
7271 state_ainsn_table_t tab
;
7272 int full_vect_length
;
7275 tab
= XCREATENODE (struct state_ainsn_table
);
7276 tab
->automaton
= automaton
;
7278 tab
->comb_vect
= VEC_alloc (vect_el_t
, heap
, 10000);
7279 tab
->check_vect
= VEC_alloc (vect_el_t
, heap
, 10000);
7282 VEC_safe_grow (vect_el_t
, heap
, tab
->base_vect
,
7283 automaton
->achieved_states_num
);
7285 full_vect_length
= (automaton
->insn_equiv_classes_num
7286 * automaton
->achieved_states_num
);
7287 tab
->full_vect
= VEC_alloc (vect_el_t
, heap
, full_vect_length
);
7288 for (i
= 0; i
< full_vect_length
; i
++)
7289 VEC_quick_push (vect_el_t
, tab
->full_vect
, undefined_vect_el_value
);
7291 tab
->min_base_vect_el_value
= 0;
7292 tab
->max_base_vect_el_value
= 0;
7293 tab
->min_comb_vect_el_value
= 0;
7294 tab
->max_comb_vect_el_value
= 0;
7298 /* The following function outputs the best C representation of the
7299 table TAB of given TABLE_NAME. */
7301 output_state_ainsn_table (state_ainsn_table_t tab
, const char *table_name
,
7302 void (*output_full_vect_name_func
) (FILE *, automaton_t
),
7303 void (*output_comb_vect_name_func
) (FILE *, automaton_t
),
7304 void (*output_check_vect_name_func
) (FILE *, automaton_t
),
7305 void (*output_base_vect_name_func
) (FILE *, automaton_t
))
7307 if (!comb_vect_p (tab
))
7309 fprintf (output_file
, "/* Vector for %s. */\n", table_name
);
7310 fprintf (output_file
, "static const ");
7311 output_range_type (output_file
, tab
->min_comb_vect_el_value
,
7312 tab
->max_comb_vect_el_value
);
7313 fprintf (output_file
, " ");
7314 (*output_full_vect_name_func
) (output_file
, tab
->automaton
);
7315 fprintf (output_file
, "[] ATTRIBUTE_UNUSED = {\n");
7316 output_vect (tab
->full_vect
);
7317 fprintf (output_file
, "};\n\n");
7321 fprintf (output_file
, "/* Comb vector for %s. */\n", table_name
);
7322 fprintf (output_file
, "static const ");
7323 output_range_type (output_file
, tab
->min_comb_vect_el_value
,
7324 tab
->max_comb_vect_el_value
);
7325 fprintf (output_file
, " ");
7326 (*output_comb_vect_name_func
) (output_file
, tab
->automaton
);
7327 fprintf (output_file
, "[] ATTRIBUTE_UNUSED = {\n");
7328 output_vect (tab
->comb_vect
);
7329 fprintf (output_file
, "};\n\n");
7330 fprintf (output_file
, "/* Check vector for %s. */\n", table_name
);
7331 fprintf (output_file
, "static const ");
7332 output_range_type (output_file
, 0, tab
->automaton
->achieved_states_num
);
7333 fprintf (output_file
, " ");
7334 (*output_check_vect_name_func
) (output_file
, tab
->automaton
);
7335 fprintf (output_file
, "[] = {\n");
7336 output_vect (tab
->check_vect
);
7337 fprintf (output_file
, "};\n\n");
7338 fprintf (output_file
, "/* Base vector for %s. */\n", table_name
);
7339 fprintf (output_file
, "static const ");
7340 output_range_type (output_file
, tab
->min_base_vect_el_value
,
7341 tab
->max_base_vect_el_value
);
7342 fprintf (output_file
, " ");
7343 (*output_base_vect_name_func
) (output_file
, tab
->automaton
);
7344 fprintf (output_file
, "[] = {\n");
7345 output_vect (tab
->base_vect
);
7346 fprintf (output_file
, "};\n\n");
7350 /* The following function adds vector VECT to table TAB as its line
7351 with number VECT_NUM. */
7353 add_vect (state_ainsn_table_t tab
, int vect_num
, vla_hwint_t vect
)
7356 size_t real_vect_length
;
7357 int comb_vect_index
;
7358 int comb_vect_els_num
;
7360 int first_unempty_vect_index
;
7361 int additional_els_num
;
7365 unsigned long vect_mask
, comb_vect_mask
;
7367 vect_length
= VEC_length (vect_el_t
, vect
);
7368 gcc_assert (vect_length
);
7369 gcc_assert (VEC_last (vect_el_t
, vect
) != undefined_vect_el_value
);
7370 real_vect_length
= tab
->automaton
->insn_equiv_classes_num
;
7371 /* Form full vector in the table: */
7373 size_t full_base
= tab
->automaton
->insn_equiv_classes_num
* vect_num
;
7374 if (VEC_length (vect_el_t
, tab
->full_vect
) < full_base
+ vect_length
)
7375 VEC_safe_grow (vect_el_t
, heap
, tab
->full_vect
,
7376 full_base
+ vect_length
);
7377 for (i
= 0; i
< vect_length
; i
++)
7378 VEC_replace (vect_el_t
, tab
->full_vect
, full_base
+ i
,
7379 VEC_index (vect_el_t
, vect
, i
));
7382 /* The comb_vect min/max values are also used for the full vector, so
7383 compute them now. */
7384 for (vect_index
= 0; vect_index
< vect_length
; vect_index
++)
7385 if (VEC_index (vect_el_t
, vect
, vect_index
) != undefined_vect_el_value
)
7387 vect_el_t x
= VEC_index (vect_el_t
, vect
, vect_index
);
7388 gcc_assert (x
>= 0);
7389 if (tab
->max_comb_vect_el_value
< x
)
7390 tab
->max_comb_vect_el_value
= x
;
7391 if (tab
->min_comb_vect_el_value
> x
)
7392 tab
->min_comb_vect_el_value
= x
;
7397 /* Form comb vector in the table: */
7398 gcc_assert (VEC_length (vect_el_t
, tab
->comb_vect
)
7399 == VEC_length (vect_el_t
, tab
->check_vect
));
7401 comb_vect_els_num
= VEC_length (vect_el_t
, tab
->comb_vect
);
7402 for (first_unempty_vect_index
= 0;
7403 first_unempty_vect_index
< vect_length
;
7404 first_unempty_vect_index
++)
7405 if (VEC_index (vect_el_t
, vect
, first_unempty_vect_index
)
7406 != undefined_vect_el_value
)
7409 /* Search for the place in comb vect for the inserted vect. */
7412 if (vect_length
- first_unempty_vect_index
>= SIZEOF_LONG
* CHAR_BIT
)
7414 for (comb_vect_index
= 0;
7415 comb_vect_index
< comb_vect_els_num
;
7418 for (vect_index
= first_unempty_vect_index
;
7419 vect_index
< vect_length
7420 && vect_index
+ comb_vect_index
< comb_vect_els_num
;
7422 if (VEC_index (vect_el_t
, vect
, vect_index
)
7423 != undefined_vect_el_value
7424 && (VEC_index (vect_el_t
, tab
->comb_vect
,
7425 vect_index
+ comb_vect_index
)
7426 != undefined_vect_el_value
))
7428 if (vect_index
>= vect_length
7429 || vect_index
+ comb_vect_index
>= comb_vect_els_num
)
7437 for (vect_index
= first_unempty_vect_index
;
7438 vect_index
< vect_length
;
7441 vect_mask
= vect_mask
<< 1;
7442 if (VEC_index (vect_el_t
, vect
, vect_index
) != undefined_vect_el_value
)
7446 /* Search for the place in comb vect for the inserted vect. */
7447 comb_vect_index
= 0;
7448 if (comb_vect_els_num
== 0)
7452 for (vect_index
= first_unempty_vect_index
;
7453 vect_index
< vect_length
&& vect_index
< comb_vect_els_num
;
7456 comb_vect_mask
<<= 1;
7457 if (vect_index
+ comb_vect_index
< comb_vect_els_num
7458 && VEC_index (vect_el_t
, tab
->comb_vect
, vect_index
+ comb_vect_index
)
7459 != undefined_vect_el_value
)
7460 comb_vect_mask
|= 1;
7462 if ((vect_mask
& comb_vect_mask
) == 0)
7465 for (comb_vect_index
= 1, i
= vect_length
; i
< comb_vect_els_num
;
7466 comb_vect_index
++, i
++)
7468 comb_vect_mask
= (comb_vect_mask
<< 1) | 1;
7469 comb_vect_mask
^= (VEC_index (vect_el_t
, tab
->comb_vect
, i
)
7470 == undefined_vect_el_value
);
7471 if ((vect_mask
& comb_vect_mask
) == 0)
7474 for ( ; comb_vect_index
< comb_vect_els_num
; comb_vect_index
++)
7476 comb_vect_mask
<<= 1;
7477 if ((vect_mask
& comb_vect_mask
) == 0)
7482 /* Slot was found. */
7483 additional_els_num
= comb_vect_index
+ real_vect_length
- comb_vect_els_num
;
7484 if (additional_els_num
< 0)
7485 additional_els_num
= 0;
7486 /* Expand comb and check vectors. */
7487 vect_el
= undefined_vect_el_value
;
7488 no_state_value
= tab
->automaton
->achieved_states_num
;
7489 while (additional_els_num
> 0)
7491 VEC_safe_push (vect_el_t
, heap
, tab
->comb_vect
, vect_el
);
7492 VEC_safe_push (vect_el_t
, heap
, tab
->check_vect
, no_state_value
);
7493 additional_els_num
--;
7495 gcc_assert (VEC_length (vect_el_t
, tab
->comb_vect
)
7496 >= comb_vect_index
+ real_vect_length
);
7497 /* Fill comb and check vectors. */
7498 for (vect_index
= 0; vect_index
< vect_length
; vect_index
++)
7499 if (VEC_index (vect_el_t
, vect
, vect_index
) != undefined_vect_el_value
)
7501 vect_el_t x
= VEC_index (vect_el_t
, vect
, vect_index
);
7502 gcc_assert (VEC_index (vect_el_t
, tab
->comb_vect
,
7503 comb_vect_index
+ vect_index
)
7504 == undefined_vect_el_value
);
7505 gcc_assert (x
>= 0);
7506 VEC_replace (vect_el_t
, tab
->comb_vect
,
7507 comb_vect_index
+ vect_index
, x
);
7508 VEC_replace (vect_el_t
, tab
->check_vect
,
7509 comb_vect_index
+ vect_index
, vect_num
);
7511 if (tab
->max_comb_vect_el_value
< undefined_vect_el_value
)
7512 tab
->max_comb_vect_el_value
= undefined_vect_el_value
;
7513 if (tab
->min_comb_vect_el_value
> undefined_vect_el_value
)
7514 tab
->min_comb_vect_el_value
= undefined_vect_el_value
;
7515 if (tab
->max_base_vect_el_value
< comb_vect_index
)
7516 tab
->max_base_vect_el_value
= comb_vect_index
;
7517 if (tab
->min_base_vect_el_value
> comb_vect_index
)
7518 tab
->min_base_vect_el_value
= comb_vect_index
;
7520 VEC_replace (vect_el_t
, tab
->base_vect
, vect_num
, comb_vect_index
);
7523 /* Return number of out arcs of STATE. */
7525 out_state_arcs_num (const_state_t state
)
7531 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
7533 gcc_assert (arc
->insn
);
7534 if (arc
->insn
->first_ainsn_with_given_equivalence_num
)
7540 /* Compare number of possible transitions from the states. */
7542 compare_transition_els_num (const void *state_ptr_1
,
7543 const void *state_ptr_2
)
7545 const int transition_els_num_1
7546 = out_state_arcs_num (*(const_state_t
const*) state_ptr_1
);
7547 const int transition_els_num_2
7548 = out_state_arcs_num (*(const_state_t
const*) state_ptr_2
);
7550 if (transition_els_num_1
< transition_els_num_2
)
7552 else if (transition_els_num_1
== transition_els_num_2
)
7558 /* The function adds element EL_VALUE to vector VECT for a table state
7561 add_vect_el (vla_hwint_t
*vect
, ainsn_t ainsn
, int el_value
)
7563 int equiv_class_num
;
7567 equiv_class_num
= ainsn
->insn_equiv_class_num
;
7568 for (vect_index
= VEC_length (vect_el_t
, *vect
);
7569 vect_index
<= equiv_class_num
;
7571 VEC_safe_push (vect_el_t
, heap
, *vect
, undefined_vect_el_value
);
7572 VEC_replace (vect_el_t
, *vect
, equiv_class_num
, el_value
);
7575 /* This is for forming vector of states of an automaton. */
7576 static VEC(state_t
, heap
) *output_states_vect
;
7578 /* The function is called by function pass_states. The function adds
7579 STATE to `output_states_vect'. */
7581 add_states_vect_el (state_t state
)
7583 VEC_safe_push (state_t
, heap
, output_states_vect
, state
);
7586 /* Form and output vectors (comb, check, base or full vector)
7587 representing transition table of AUTOMATON. */
7589 output_trans_table (automaton_t automaton
)
7593 vla_hwint_t transition_vect
= 0;
7595 undefined_vect_el_value
= automaton
->achieved_states_num
;
7596 automaton
->trans_table
= create_state_ainsn_table (automaton
);
7597 /* Create vect of pointers to states ordered by num of transitions
7598 from the state (state with the maximum num is the first). */
7599 output_states_vect
= 0;
7600 pass_states (automaton
, add_states_vect_el
);
7601 VEC_qsort (state_t
, output_states_vect
, compare_transition_els_num
);
7603 for (i
= 0; i
< VEC_length (state_t
, output_states_vect
); i
++)
7605 VEC_truncate (vect_el_t
, transition_vect
, 0);
7606 for (arc
= first_out_arc (VEC_index (state_t
, output_states_vect
, i
));
7608 arc
= next_out_arc (arc
))
7610 gcc_assert (arc
->insn
);
7611 if (arc
->insn
->first_ainsn_with_given_equivalence_num
)
7612 add_vect_el (&transition_vect
, arc
->insn
,
7613 arc
->to_state
->order_state_num
);
7615 add_vect (automaton
->trans_table
,
7616 VEC_index (state_t
, output_states_vect
, i
)->order_state_num
,
7619 output_state_ainsn_table
7620 (automaton
->trans_table
, "state transitions",
7621 output_trans_full_vect_name
, output_trans_comb_vect_name
,
7622 output_trans_check_vect_name
, output_trans_base_vect_name
);
7624 VEC_free (state_t
, heap
, output_states_vect
);
7625 VEC_free (vect_el_t
, heap
, transition_vect
);
7628 /* Form and output vectors representing minimal issue delay table of
7629 AUTOMATON. The table is state x ainsn -> minimal issue delay of
7632 output_min_issue_delay_table (automaton_t automaton
)
7634 vla_hwint_t min_issue_delay_vect
;
7635 vla_hwint_t compressed_min_issue_delay_vect
;
7638 size_t min_issue_delay_len
, compressed_min_issue_delay_len
;
7642 /* Create vect of pointers to states ordered by num of transitions
7643 from the state (state with the maximum num is the first). */
7644 output_states_vect
= 0;
7645 pass_states (automaton
, add_states_vect_el
);
7647 min_issue_delay_len
= (VEC_length (state_t
, output_states_vect
)
7648 * automaton
->insn_equiv_classes_num
);
7649 min_issue_delay_vect
= VEC_alloc (vect_el_t
, heap
, min_issue_delay_len
);
7650 for (i
= 0; i
< min_issue_delay_len
; i
++)
7651 VEC_quick_push (vect_el_t
, min_issue_delay_vect
, -1);
7653 automaton
->max_min_delay
= 0;
7661 for (state_no
= 0; state_no
< VEC_length (state_t
, output_states_vect
);
7664 state_t s
= VEC_index (state_t
, output_states_vect
, state_no
);
7667 for (arc
= first_out_arc (s
); arc
; arc
= next_out_arc (arc
))
7671 size_t asn
= s
->order_state_num
7672 * automaton
->insn_equiv_classes_num
7673 + arc
->insn
->insn_equiv_class_num
;
7675 if (VEC_index (vect_el_t
, min_issue_delay_vect
, asn
))
7677 VEC_replace (vect_el_t
, min_issue_delay_vect
, asn
,
7682 for (k
= 0; k
< automaton
->insn_equiv_classes_num
; k
++)
7685 vect_el_t delay0
, delay1
;
7687 n0
= s
->order_state_num
7688 * automaton
->insn_equiv_classes_num
7690 n1
= arc
->to_state
->order_state_num
7691 * automaton
->insn_equiv_classes_num
7693 delay0
= VEC_index (vect_el_t
, min_issue_delay_vect
, n0
);
7694 delay1
= VEC_index (vect_el_t
, min_issue_delay_vect
, n1
);
7697 if (arc
->insn
->insn_reserv_decl
7698 == DECL_INSN_RESERV (advance_cycle_insn_decl
))
7700 if (delay1
< delay0
|| delay0
== -1)
7702 VEC_replace (vect_el_t
, min_issue_delay_vect
, n0
, delay1
);
7712 automaton
->max_min_delay
= 0;
7714 for (ainsn
= automaton
->ainsn_list
; ainsn
; ainsn
= ainsn
->next_ainsn
)
7715 if (ainsn
->first_ainsn_with_given_equivalence_num
)
7717 for (i
= 0; i
< VEC_length (state_t
, output_states_vect
); i
++)
7719 state_t s
= VEC_index (state_t
, output_states_vect
, i
);
7720 size_t np
= s
->order_state_num
7721 * automaton
->insn_equiv_classes_num
7722 + ainsn
->insn_equiv_class_num
;
7723 vect_el_t x
= VEC_index (vect_el_t
, min_issue_delay_vect
, np
);
7725 if (automaton
->max_min_delay
< x
)
7726 automaton
->max_min_delay
= x
;
7728 VEC_replace (vect_el_t
, min_issue_delay_vect
, np
,
7733 fprintf (output_file
, "/* Vector of min issue delay of insns. */\n");
7734 fprintf (output_file
, "static const ");
7735 output_range_type (output_file
, 0, automaton
->max_min_delay
);
7736 fprintf (output_file
, " ");
7737 output_min_issue_delay_vect_name (output_file
, automaton
);
7738 fprintf (output_file
, "[] ATTRIBUTE_UNUSED = {\n");
7739 /* Compress the vector. */
7740 if (automaton
->max_min_delay
< 2)
7742 else if (automaton
->max_min_delay
< 4)
7744 else if (automaton
->max_min_delay
< 16)
7748 automaton
->min_issue_delay_table_compression_factor
= cfactor
;
7750 compressed_min_issue_delay_len
= (min_issue_delay_len
+cfactor
-1) / cfactor
;
7751 compressed_min_issue_delay_vect
7752 = VEC_alloc (vect_el_t
, heap
, compressed_min_issue_delay_len
);
7754 for (i
= 0; i
< compressed_min_issue_delay_len
; i
++)
7755 VEC_quick_push (vect_el_t
, compressed_min_issue_delay_vect
, 0);
7757 for (i
= 0; i
< min_issue_delay_len
; i
++)
7759 size_t ci
= i
/ cfactor
;
7760 vect_el_t x
= VEC_index (vect_el_t
, min_issue_delay_vect
, i
);
7761 vect_el_t cx
= VEC_index (vect_el_t
, compressed_min_issue_delay_vect
, ci
);
7763 cx
|= x
<< (8 - (i
% cfactor
+ 1) * (8 / cfactor
));
7764 VEC_replace (vect_el_t
, compressed_min_issue_delay_vect
, ci
, cx
);
7766 output_vect (compressed_min_issue_delay_vect
);
7767 fprintf (output_file
, "};\n\n");
7768 VEC_free (state_t
, heap
, output_states_vect
);
7769 VEC_free (vect_el_t
, heap
, min_issue_delay_vect
);
7770 VEC_free (vect_el_t
, heap
, compressed_min_issue_delay_vect
);
7773 /* Form and output vector representing the locked states of
7776 output_dead_lock_vect (automaton_t automaton
)
7780 vla_hwint_t dead_lock_vect
= 0;
7782 /* Create vect of pointers to states ordered by num of
7783 transitions from the state (state with the maximum num is the
7785 automaton
->locked_states
= 0;
7786 output_states_vect
= 0;
7787 pass_states (automaton
, add_states_vect_el
);
7789 VEC_safe_grow (vect_el_t
, heap
, dead_lock_vect
,
7790 VEC_length (state_t
, output_states_vect
));
7791 for (i
= 0; i
< VEC_length (state_t
, output_states_vect
); i
++)
7793 state_t s
= VEC_index (state_t
, output_states_vect
, i
);
7794 arc
= first_out_arc (s
);
7796 if (next_out_arc (arc
) == NULL
7797 && (arc
->insn
->insn_reserv_decl
7798 == DECL_INSN_RESERV (advance_cycle_insn_decl
)))
7800 VEC_replace (vect_el_t
, dead_lock_vect
, s
->order_state_num
, 1);
7801 automaton
->locked_states
++;
7804 VEC_replace (vect_el_t
, dead_lock_vect
, s
->order_state_num
,
7807 if (automaton
->locked_states
== 0)
7810 fprintf (output_file
, "/* Vector for locked state flags. */\n");
7811 fprintf (output_file
, "static const ");
7812 output_range_type (output_file
, 0, 1);
7813 fprintf (output_file
, " ");
7814 output_dead_lock_vect_name (output_file
, automaton
);
7815 fprintf (output_file
, "[] = {\n");
7816 output_vect (dead_lock_vect
);
7817 fprintf (output_file
, "};\n\n");
7818 VEC_free (state_t
, heap
, output_states_vect
);
7819 VEC_free (vect_el_t
, heap
, dead_lock_vect
);
7822 /* Form and output vector representing reserved units of the states of
7825 output_reserved_units_table (automaton_t automaton
)
7827 vla_hwint_t reserved_units_table
= 0;
7828 int state_byte_size
;
7829 int reserved_units_size
;
7833 if (description
->query_units_num
== 0)
7836 /* Create vect of pointers to states. */
7837 output_states_vect
= 0;
7838 pass_states (automaton
, add_states_vect_el
);
7839 /* Create vector. */
7840 state_byte_size
= (description
->query_units_num
+ 7) / 8;
7841 reserved_units_size
= (VEC_length (state_t
, output_states_vect
)
7844 reserved_units_table
= VEC_alloc (vect_el_t
, heap
, reserved_units_size
);
7846 for (i
= 0; i
< reserved_units_size
; i
++)
7847 VEC_quick_push (vect_el_t
, reserved_units_table
, 0);
7848 for (n
= 0; n
< VEC_length (state_t
, output_states_vect
); n
++)
7850 state_t s
= VEC_index (state_t
, output_states_vect
, n
);
7851 for (i
= 0; i
< description
->units_num
; i
++)
7852 if (units_array
[i
]->query_p
7853 && first_cycle_unit_presence (s
, i
))
7855 int ri
= (s
->order_state_num
* state_byte_size
7856 + units_array
[i
]->query_num
/ 8);
7857 vect_el_t x
= VEC_index (vect_el_t
, reserved_units_table
, ri
);
7859 x
+= 1 << (units_array
[i
]->query_num
% 8);
7860 VEC_replace (vect_el_t
, reserved_units_table
, ri
, x
);
7863 fprintf (output_file
, "\n#if %s\n", CPU_UNITS_QUERY_MACRO_NAME
);
7864 fprintf (output_file
, "/* Vector for reserved units of states. */\n");
7865 fprintf (output_file
, "static const ");
7866 output_range_type (output_file
, 0, 255);
7867 fprintf (output_file
, " ");
7868 output_reserved_units_table_name (output_file
, automaton
);
7869 fprintf (output_file
, "[] = {\n");
7870 output_vect (reserved_units_table
);
7871 fprintf (output_file
, "};\n#endif /* #if %s */\n\n",
7872 CPU_UNITS_QUERY_MACRO_NAME
);
7874 VEC_free (state_t
, heap
, output_states_vect
);
7875 VEC_free (vect_el_t
, heap
, reserved_units_table
);
7878 /* The function outputs all tables representing DFA(s) used for fast
7879 pipeline hazards recognition. */
7881 output_tables (void)
7883 automaton_t automaton
;
7885 for (automaton
= description
->first_automaton
;
7887 automaton
= automaton
->next_automaton
)
7889 output_translate_vect (automaton
);
7890 output_trans_table (automaton
);
7891 output_min_issue_delay_table (automaton
);
7892 output_dead_lock_vect (automaton
);
7893 output_reserved_units_table (automaton
);
7895 fprintf (output_file
, "\n#define %s %d\n\n", ADVANCE_CYCLE_VALUE_NAME
,
7896 DECL_INSN_RESERV (advance_cycle_insn_decl
)->insn_num
);
7898 fprintf (output_file
, "\n#define %s %d\n\n", COLLAPSE_NDFA_VALUE_NAME
,
7899 DECL_INSN_RESERV (collapse_ndfa_insn_decl
)->insn_num
);
7902 /* The function outputs definition and value of PHR interface variable
7903 `max_insn_queue_index'. Its value is not less than maximal queue
7904 length needed for the insn scheduler. */
7906 output_max_insn_queue_index_def (void)
7908 int i
, max
, latency
;
7911 max
= description
->max_insn_reserv_cycles
;
7912 for (i
= 0; i
< description
->decls_num
; i
++)
7914 decl
= description
->decls
[i
];
7915 if (decl
->mode
== dm_insn_reserv
&& decl
!= advance_cycle_insn_decl
)
7917 latency
= DECL_INSN_RESERV (decl
)->default_latency
;
7921 else if (decl
->mode
== dm_bypass
)
7923 latency
= DECL_BYPASS (decl
)->latency
;
7928 for (i
= 0; (1 << i
) <= max
; i
++)
7930 gcc_assert (i
>= 0);
7931 fprintf (output_file
, "\nconst int max_insn_queue_index = %d;\n\n",
7935 /* The function outputs switch cases for insn reservations using
7936 function *output_automata_list_code. */
7938 output_insn_code_cases (void (*output_automata_list_code
)
7939 (automata_list_el_t
))
7944 for (i
= 0; i
< description
->decls_num
; i
++)
7946 decl
= description
->decls
[i
];
7947 if (decl
->mode
== dm_insn_reserv
)
7948 DECL_INSN_RESERV (decl
)->processed_p
= FALSE
;
7950 for (i
= 0; i
< description
->decls_num
; i
++)
7952 decl
= description
->decls
[i
];
7953 if (decl
->mode
== dm_insn_reserv
7954 && !DECL_INSN_RESERV (decl
)->processed_p
)
7956 for (j
= i
; j
< description
->decls_num
; j
++)
7958 decl2
= description
->decls
[j
];
7959 if (decl2
->mode
== dm_insn_reserv
7960 && (DECL_INSN_RESERV (decl2
)->important_automata_list
7961 == DECL_INSN_RESERV (decl
)->important_automata_list
))
7963 DECL_INSN_RESERV (decl2
)->processed_p
= TRUE
;
7964 fprintf (output_file
, " case %d: /* %s */\n",
7965 DECL_INSN_RESERV (decl2
)->insn_num
,
7966 DECL_INSN_RESERV (decl2
)->name
);
7969 (*output_automata_list_code
)
7970 (DECL_INSN_RESERV (decl
)->important_automata_list
);
7976 /* The function outputs a code for evaluation of a minimal delay of
7977 issue of insns which have reservations in given AUTOMATA_LIST. */
7979 output_automata_list_min_issue_delay_code (automata_list_el_t automata_list
)
7981 automata_list_el_t el
;
7982 automaton_t automaton
;
7984 for (el
= automata_list
; el
!= NULL
; el
= el
->next_automata_list_el
)
7986 automaton
= el
->automaton
;
7987 fprintf (output_file
, "\n %s = ", TEMPORARY_VARIABLE_NAME
);
7988 output_min_issue_delay_vect_name (output_file
, automaton
);
7989 fprintf (output_file
,
7990 (automaton
->min_issue_delay_table_compression_factor
!= 1
7992 output_translate_vect_name (output_file
, automaton
);
7993 fprintf (output_file
, " [%s] + ", INTERNAL_INSN_CODE_NAME
);
7994 fprintf (output_file
, "%s->", CHIP_PARAMETER_NAME
);
7995 output_chip_member_name (output_file
, automaton
);
7996 fprintf (output_file
, " * %d", automaton
->insn_equiv_classes_num
);
7997 if (automaton
->min_issue_delay_table_compression_factor
== 1)
7998 fprintf (output_file
, "];\n");
8001 fprintf (output_file
, ") / %d];\n",
8002 automaton
->min_issue_delay_table_compression_factor
);
8003 fprintf (output_file
, " %s = (%s >> (8 - ((",
8004 TEMPORARY_VARIABLE_NAME
, TEMPORARY_VARIABLE_NAME
);
8005 output_translate_vect_name (output_file
, automaton
);
8006 fprintf (output_file
, " [%s] + ", INTERNAL_INSN_CODE_NAME
);
8007 fprintf (output_file
, "%s->", CHIP_PARAMETER_NAME
);
8008 output_chip_member_name (output_file
, automaton
);
8009 fprintf (output_file
, " * %d)", automaton
->insn_equiv_classes_num
);
8011 (output_file
, " %% %d + 1) * %d)) & %d;\n",
8012 automaton
->min_issue_delay_table_compression_factor
,
8013 8 / automaton
->min_issue_delay_table_compression_factor
,
8014 (1 << (8 / automaton
->min_issue_delay_table_compression_factor
))
8017 if (el
== automata_list
)
8018 fprintf (output_file
, " %s = %s;\n",
8019 RESULT_VARIABLE_NAME
, TEMPORARY_VARIABLE_NAME
);
8022 fprintf (output_file
, " if (%s > %s)\n",
8023 TEMPORARY_VARIABLE_NAME
, RESULT_VARIABLE_NAME
);
8024 fprintf (output_file
, " %s = %s;\n",
8025 RESULT_VARIABLE_NAME
, TEMPORARY_VARIABLE_NAME
);
8028 fprintf (output_file
, " break;\n\n");
8031 /* Output function `internal_min_issue_delay'. */
8033 output_internal_min_issue_delay_func (void)
8035 fprintf (output_file
,
8036 "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
8037 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
8038 CHIP_NAME
, CHIP_PARAMETER_NAME
);
8039 fprintf (output_file
, "{\n int %s ATTRIBUTE_UNUSED;\n int %s = -1;\n",
8040 TEMPORARY_VARIABLE_NAME
, RESULT_VARIABLE_NAME
);
8041 fprintf (output_file
, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME
);
8042 output_insn_code_cases (output_automata_list_min_issue_delay_code
);
8043 fprintf (output_file
,
8044 "\n default:\n %s = -1;\n break;\n }\n",
8045 RESULT_VARIABLE_NAME
);
8046 fprintf (output_file
, " return %s;\n", RESULT_VARIABLE_NAME
);
8047 fprintf (output_file
, "}\n\n");
8050 /* The function outputs a code changing state after issue of insns
8051 which have reservations in given AUTOMATA_LIST. */
8053 output_automata_list_transition_code (automata_list_el_t automata_list
)
8055 automata_list_el_t el
, next_el
;
8057 fprintf (output_file
, " {\n");
8058 if (automata_list
!= NULL
&& automata_list
->next_automata_list_el
!= NULL
)
8059 for (el
= automata_list
;; el
= next_el
)
8061 next_el
= el
->next_automata_list_el
;
8062 if (next_el
== NULL
)
8064 fprintf (output_file
, " ");
8065 output_state_member_type (output_file
, el
->automaton
);
8066 fprintf (output_file
, " ");
8067 output_temp_chip_member_name (output_file
, el
->automaton
);
8068 fprintf (output_file
, ";\n");
8070 for (el
= automata_list
; el
!= NULL
; el
= el
->next_automata_list_el
)
8071 if (comb_vect_p (el
->automaton
->trans_table
))
8073 fprintf (output_file
, "\n %s = ", TEMPORARY_VARIABLE_NAME
);
8074 output_trans_base_vect_name (output_file
, el
->automaton
);
8075 fprintf (output_file
, " [%s->", CHIP_PARAMETER_NAME
);
8076 output_chip_member_name (output_file
, el
->automaton
);
8077 fprintf (output_file
, "] + ");
8078 output_translate_vect_name (output_file
, el
->automaton
);
8079 fprintf (output_file
, " [%s];\n", INTERNAL_INSN_CODE_NAME
);
8080 fprintf (output_file
, " if (");
8081 output_trans_check_vect_name (output_file
, el
->automaton
);
8082 fprintf (output_file
, " [%s] != %s->",
8083 TEMPORARY_VARIABLE_NAME
, CHIP_PARAMETER_NAME
);
8084 output_chip_member_name (output_file
, el
->automaton
);
8085 fprintf (output_file
, ")\n");
8086 fprintf (output_file
, " return %s (%s, %s);\n",
8087 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
8088 CHIP_PARAMETER_NAME
);
8089 fprintf (output_file
, " else\n");
8090 fprintf (output_file
, " ");
8091 if (el
->next_automata_list_el
!= NULL
)
8092 output_temp_chip_member_name (output_file
, el
->automaton
);
8095 fprintf (output_file
, "%s->", CHIP_PARAMETER_NAME
);
8096 output_chip_member_name (output_file
, el
->automaton
);
8098 fprintf (output_file
, " = ");
8099 output_trans_comb_vect_name (output_file
, el
->automaton
);
8100 fprintf (output_file
, " [%s];\n", TEMPORARY_VARIABLE_NAME
);
8104 fprintf (output_file
, "\n %s = ", TEMPORARY_VARIABLE_NAME
);
8105 output_trans_full_vect_name (output_file
, el
->automaton
);
8106 fprintf (output_file
, " [");
8107 output_translate_vect_name (output_file
, el
->automaton
);
8108 fprintf (output_file
, " [%s] + ", INTERNAL_INSN_CODE_NAME
);
8109 fprintf (output_file
, "%s->", CHIP_PARAMETER_NAME
);
8110 output_chip_member_name (output_file
, el
->automaton
);
8111 fprintf (output_file
, " * %d];\n",
8112 el
->automaton
->insn_equiv_classes_num
);
8113 fprintf (output_file
, " if (%s >= %d)\n",
8114 TEMPORARY_VARIABLE_NAME
, el
->automaton
->achieved_states_num
);
8115 fprintf (output_file
, " return %s (%s, %s);\n",
8116 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
8117 CHIP_PARAMETER_NAME
);
8118 fprintf (output_file
, " else\n ");
8119 if (el
->next_automata_list_el
!= NULL
)
8120 output_temp_chip_member_name (output_file
, el
->automaton
);
8123 fprintf (output_file
, "%s->", CHIP_PARAMETER_NAME
);
8124 output_chip_member_name (output_file
, el
->automaton
);
8126 fprintf (output_file
, " = %s;\n", TEMPORARY_VARIABLE_NAME
);
8128 if (automata_list
!= NULL
&& automata_list
->next_automata_list_el
!= NULL
)
8129 for (el
= automata_list
;; el
= next_el
)
8131 next_el
= el
->next_automata_list_el
;
8132 if (next_el
== NULL
)
8134 fprintf (output_file
, " %s->", CHIP_PARAMETER_NAME
);
8135 output_chip_member_name (output_file
, el
->automaton
);
8136 fprintf (output_file
, " = ");
8137 output_temp_chip_member_name (output_file
, el
->automaton
);
8138 fprintf (output_file
, ";\n");
8140 fprintf (output_file
, " return -1;\n");
8141 fprintf (output_file
, " }\n");
8144 /* Output function `internal_state_transition'. */
8146 output_internal_trans_func (void)
8148 fprintf (output_file
,
8149 "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
8150 INTERNAL_TRANSITION_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
8151 CHIP_NAME
, CHIP_PARAMETER_NAME
);
8152 fprintf (output_file
, "{\n int %s ATTRIBUTE_UNUSED;\n", TEMPORARY_VARIABLE_NAME
);
8153 fprintf (output_file
, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME
);
8154 output_insn_code_cases (output_automata_list_transition_code
);
8155 fprintf (output_file
, "\n default:\n return -1;\n }\n");
8156 fprintf (output_file
, "}\n\n");
8163 insn_code = dfa_insn_code (insn);
8164 if (insn_code > DFA__ADVANCE_CYCLE)
8168 insn_code = DFA__ADVANCE_CYCLE;
8170 where insn denotes INSN_NAME, insn_code denotes INSN_CODE_NAME, and
8171 code denotes CODE. */
8173 output_internal_insn_code_evaluation (const char *insn_name
,
8174 const char *insn_code_name
,
8177 fprintf (output_file
, "\n if (%s == 0)\n", insn_name
);
8178 fprintf (output_file
, " %s = %s;\n\n",
8179 insn_code_name
, ADVANCE_CYCLE_VALUE_NAME
);
8182 fprintf (output_file
, "\n else if (%s == const0_rtx)\n", insn_name
);
8183 fprintf (output_file
, " %s = %s;\n\n",
8184 insn_code_name
, COLLAPSE_NDFA_VALUE_NAME
);
8186 fprintf (output_file
, "\n else\n {\n");
8187 fprintf (output_file
, " %s = %s (%s);\n", insn_code_name
,
8188 DFA_INSN_CODE_FUNC_NAME
, insn_name
);
8189 fprintf (output_file
, " if (%s > %s)\n return %d;\n }\n",
8190 insn_code_name
, ADVANCE_CYCLE_VALUE_NAME
, code
);
8194 /* This function outputs `dfa_insn_code' and its helper function
8195 `dfa_insn_code_enlarge'. */
8197 output_dfa_insn_code_func (void)
8199 /* Emacs c-mode gets really confused if there's a { or } in column 0
8200 inside a string, so don't do that. */
8201 fprintf (output_file
, "\
8203 dfa_insn_code_enlarge (int uid)\n\
8207 %s = XRESIZEVEC (int, %s,\n\
8209 for (; i < %s; i++)\n\
8210 %s[i] = -1;\n}\n\n",
8211 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
,
8212 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
,
8213 DFA_INSN_CODES_VARIABLE_NAME
, DFA_INSN_CODES_VARIABLE_NAME
,
8214 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
,
8215 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
,
8216 DFA_INSN_CODES_VARIABLE_NAME
);
8217 fprintf (output_file
, "\
8218 static inline int\n%s (rtx %s)\n\
8220 int uid = INSN_UID (%s);\n\
8222 DFA_INSN_CODE_FUNC_NAME
, INSN_PARAMETER_NAME
,
8223 INSN_PARAMETER_NAME
, INTERNAL_INSN_CODE_NAME
);
8225 fprintf (output_file
,
8226 " if (uid >= %s)\n dfa_insn_code_enlarge (uid);\n\n",
8227 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
);
8228 fprintf (output_file
, " %s = %s[uid];\n",
8229 INTERNAL_INSN_CODE_NAME
, DFA_INSN_CODES_VARIABLE_NAME
);
8230 fprintf (output_file
, "\
8236 INTERNAL_INSN_CODE_NAME
,
8237 INTERNAL_INSN_CODE_NAME
,
8238 INTERNAL_DFA_INSN_CODE_FUNC_NAME
, INSN_PARAMETER_NAME
,
8239 DFA_INSN_CODES_VARIABLE_NAME
, INTERNAL_INSN_CODE_NAME
);
8240 fprintf (output_file
, " return %s;\n}\n\n", INTERNAL_INSN_CODE_NAME
);
8243 /* The function outputs PHR interface function `state_transition'. */
8245 output_trans_func (void)
8247 fprintf (output_file
, "int\n%s (%s %s, rtx %s)\n",
8248 TRANSITION_FUNC_NAME
, STATE_TYPE_NAME
, STATE_NAME
,
8249 INSN_PARAMETER_NAME
);
8250 fprintf (output_file
, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME
);
8251 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME
,
8252 INTERNAL_INSN_CODE_NAME
, -1);
8253 fprintf (output_file
, " return %s (%s, (struct %s *) %s);\n}\n\n",
8254 INTERNAL_TRANSITION_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
, CHIP_NAME
, STATE_NAME
);
8257 /* Output function `min_issue_delay'. */
8259 output_min_issue_delay_func (void)
8261 fprintf (output_file
, "int\n%s (%s %s, rtx %s)\n",
8262 MIN_ISSUE_DELAY_FUNC_NAME
, STATE_TYPE_NAME
, STATE_NAME
,
8263 INSN_PARAMETER_NAME
);
8264 fprintf (output_file
, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME
);
8265 fprintf (output_file
, "\n if (%s != 0)\n {\n", INSN_PARAMETER_NAME
);
8266 fprintf (output_file
, " %s = %s (%s);\n", INTERNAL_INSN_CODE_NAME
,
8267 DFA_INSN_CODE_FUNC_NAME
, INSN_PARAMETER_NAME
);
8268 fprintf (output_file
, " if (%s > %s)\n return 0;\n",
8269 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
8270 fprintf (output_file
, " }\n else\n %s = %s;\n",
8271 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
8272 fprintf (output_file
, "\n return %s (%s, (struct %s *) %s);\n",
8273 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
8274 CHIP_NAME
, STATE_NAME
);
8275 fprintf (output_file
, "}\n\n");
8278 /* Output function `internal_dead_lock'. */
8280 output_internal_dead_lock_func (void)
8282 automaton_t automaton
;
8284 fprintf (output_file
, "static int\n%s (struct %s *ARG_UNUSED (%s))\n",
8285 INTERNAL_DEAD_LOCK_FUNC_NAME
, CHIP_NAME
, CHIP_PARAMETER_NAME
);
8286 fprintf (output_file
, "{\n");
8287 for (automaton
= description
->first_automaton
;
8289 automaton
= automaton
->next_automaton
)
8290 if (automaton
->locked_states
)
8292 fprintf (output_file
, " if (");
8293 output_dead_lock_vect_name (output_file
, automaton
);
8294 fprintf (output_file
, " [%s->", CHIP_PARAMETER_NAME
);
8295 output_chip_member_name (output_file
, automaton
);
8296 fprintf (output_file
, "])\n return 1/* TRUE */;\n");
8298 fprintf (output_file
, " return 0/* FALSE */;\n}\n\n");
8301 /* The function outputs PHR interface function `state_dead_lock_p'. */
8303 output_dead_lock_func (void)
8305 fprintf (output_file
, "int\n%s (%s %s)\n",
8306 DEAD_LOCK_FUNC_NAME
, STATE_TYPE_NAME
, STATE_NAME
);
8307 fprintf (output_file
, "{\n return %s ((struct %s *) %s);\n}\n\n",
8308 INTERNAL_DEAD_LOCK_FUNC_NAME
, CHIP_NAME
, STATE_NAME
);
8311 /* Output function `internal_reset'. */
8313 output_internal_reset_func (void)
8315 fprintf (output_file
, "static inline void\n%s (struct %s *%s)\n",
8316 INTERNAL_RESET_FUNC_NAME
, CHIP_NAME
, CHIP_PARAMETER_NAME
);
8317 fprintf (output_file
, "{\n memset (%s, 0, sizeof (struct %s));\n}\n\n",
8318 CHIP_PARAMETER_NAME
, CHIP_NAME
);
8321 /* The function outputs PHR interface function `state_size'. */
8323 output_size_func (void)
8325 fprintf (output_file
, "int\n%s (void)\n", SIZE_FUNC_NAME
);
8326 fprintf (output_file
, "{\n return sizeof (struct %s);\n}\n\n", CHIP_NAME
);
8329 /* The function outputs PHR interface function `state_reset'. */
8331 output_reset_func (void)
8333 fprintf (output_file
, "void\n%s (%s %s)\n",
8334 RESET_FUNC_NAME
, STATE_TYPE_NAME
, STATE_NAME
);
8335 fprintf (output_file
, "{\n %s ((struct %s *) %s);\n}\n\n", INTERNAL_RESET_FUNC_NAME
,
8336 CHIP_NAME
, STATE_NAME
);
8339 /* Output function `min_insn_conflict_delay'. */
8341 output_min_insn_conflict_delay_func (void)
8343 fprintf (output_file
,
8344 "int\n%s (%s %s, rtx %s, rtx %s)\n",
8345 MIN_INSN_CONFLICT_DELAY_FUNC_NAME
, STATE_TYPE_NAME
,
8346 STATE_NAME
, INSN_PARAMETER_NAME
, INSN2_PARAMETER_NAME
);
8347 fprintf (output_file
, "{\n struct %s %s;\n int %s, %s, transition;\n",
8348 CHIP_NAME
, CHIP_NAME
, INTERNAL_INSN_CODE_NAME
,
8349 INTERNAL_INSN2_CODE_NAME
);
8350 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME
,
8351 INTERNAL_INSN_CODE_NAME
, 0);
8352 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME
,
8353 INTERNAL_INSN2_CODE_NAME
, 0);
8354 fprintf (output_file
, " memcpy (&%s, %s, sizeof (%s));\n",
8355 CHIP_NAME
, STATE_NAME
, CHIP_NAME
);
8356 fprintf (output_file
, " %s (&%s);\n", INTERNAL_RESET_FUNC_NAME
, CHIP_NAME
);
8357 fprintf (output_file
, " transition = %s (%s, &%s);\n",
8358 INTERNAL_TRANSITION_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
, CHIP_NAME
);
8359 fprintf (output_file
, " gcc_assert (transition <= 0);\n");
8360 fprintf (output_file
, " return %s (%s, &%s);\n",
8361 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME
, INTERNAL_INSN2_CODE_NAME
,
8363 fprintf (output_file
, "}\n\n");
8366 /* Output the array holding default latency values. These are used in
8367 insn_latency and maximal_insn_latency function implementations. */
8369 output_default_latencies (void)
8373 const char *tabletype
= "unsigned char";
8375 /* Find the smallest integer type that can hold all the default
8377 for (i
= 0; i
< description
->decls_num
; i
++)
8378 if (description
->decls
[i
]->mode
== dm_insn_reserv
)
8380 decl
= description
->decls
[i
];
8381 if (DECL_INSN_RESERV (decl
)->default_latency
> UCHAR_MAX
8382 && tabletype
[0] != 'i') /* Don't shrink it. */
8383 tabletype
= "unsigned short";
8384 if (DECL_INSN_RESERV (decl
)->default_latency
> USHRT_MAX
)
8388 fprintf (output_file
, " static const %s default_latencies[] =\n {",
8391 for (i
= 0, j
= 0, col
= 7; i
< description
->normal_decls_num
; i
++)
8392 if (description
->decls
[i
]->mode
== dm_insn_reserv
)
8394 if ((col
= (col
+1) % 8) == 0)
8395 fputs ("\n ", output_file
);
8396 decl
= description
->decls
[i
];
8397 gcc_assert (j
++ == DECL_INSN_RESERV (decl
)->insn_num
);
8398 fprintf (output_file
, "% 4d,",
8399 DECL_INSN_RESERV (decl
)->default_latency
);
8401 gcc_assert (j
== description
->insns_num
- (collapse_flag
? 2 : 1));
8402 fputs ("\n };\n", output_file
);
8405 /* Output function `internal_insn_latency'. */
8407 output_internal_insn_latency_func (void)
8411 struct bypass_decl
*bypass
;
8413 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",
8414 INTERNAL_INSN_LATENCY_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
8415 INTERNAL_INSN2_CODE_NAME
, INSN_PARAMETER_NAME
,
8416 INSN2_PARAMETER_NAME
);
8417 fprintf (output_file
, "{\n");
8419 if (DECL_INSN_RESERV (advance_cycle_insn_decl
)->insn_num
== 0)
8421 fputs (" return 0;\n}\n\n", output_file
);
8425 fprintf (output_file
, " if (%s >= %s || %s >= %s)\n return 0;\n",
8426 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
,
8427 INTERNAL_INSN2_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
8429 fprintf (output_file
, " switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME
);
8430 for (i
= 0; i
< description
->decls_num
; i
++)
8431 if (description
->decls
[i
]->mode
== dm_insn_reserv
8432 && DECL_INSN_RESERV (description
->decls
[i
])->bypass_list
)
8434 decl
= description
->decls
[i
];
8435 fprintf (output_file
,
8436 " case %d:\n switch (%s)\n {\n",
8437 DECL_INSN_RESERV (decl
)->insn_num
,
8438 INTERNAL_INSN2_CODE_NAME
);
8439 for (bypass
= DECL_INSN_RESERV (decl
)->bypass_list
;
8441 bypass
= bypass
->next
)
8443 gcc_assert (bypass
->in_insn_reserv
->insn_num
8444 != (DECL_INSN_RESERV
8445 (advance_cycle_insn_decl
)->insn_num
));
8446 fprintf (output_file
, " case %d:\n",
8447 bypass
->in_insn_reserv
->insn_num
);
8450 if (bypass
->bypass_guard_name
== NULL
)
8452 gcc_assert (bypass
->next
== NULL
8453 || (bypass
->in_insn_reserv
8454 != bypass
->next
->in_insn_reserv
));
8455 fprintf (output_file
, " return %d;\n",
8460 fprintf (output_file
,
8461 " if (%s (%s, %s))\n",
8462 bypass
->bypass_guard_name
, INSN_PARAMETER_NAME
,
8463 INSN2_PARAMETER_NAME
);
8464 fprintf (output_file
, " return %d;\n",
8467 if (bypass
->next
== NULL
8468 || bypass
->in_insn_reserv
!= bypass
->next
->in_insn_reserv
)
8470 bypass
= bypass
->next
;
8472 if (bypass
->bypass_guard_name
!= NULL
)
8473 fprintf (output_file
, " break;\n");
8475 fputs (" }\n break;\n", output_file
);
8478 fprintf (output_file
, " }\n return default_latencies[%s];\n}\n\n",
8479 INTERNAL_INSN_CODE_NAME
);
8482 /* Output function `internal_maximum_insn_latency'. */
8484 output_internal_maximal_insn_latency_func (void)
8487 struct bypass_decl
*bypass
;
8491 fprintf (output_file
, "static int\n%s (int %s ATTRIBUTE_UNUSED,\n\trtx %s ATTRIBUTE_UNUSED)\n",
8492 "internal_maximal_insn_latency", INTERNAL_INSN_CODE_NAME
,
8493 INSN_PARAMETER_NAME
);
8494 fprintf (output_file
, "{\n");
8496 if (DECL_INSN_RESERV (advance_cycle_insn_decl
)->insn_num
== 0)
8498 fputs (" return 0;\n}\n\n", output_file
);
8502 fprintf (output_file
, " switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME
);
8503 for (i
= 0; i
< description
->decls_num
; i
++)
8504 if (description
->decls
[i
]->mode
== dm_insn_reserv
8505 && DECL_INSN_RESERV (description
->decls
[i
])->bypass_list
)
8507 decl
= description
->decls
[i
];
8508 max
= DECL_INSN_RESERV (decl
)->default_latency
;
8509 fprintf (output_file
,
8511 DECL_INSN_RESERV (decl
)->insn_num
);
8512 for (bypass
= DECL_INSN_RESERV (decl
)->bypass_list
;
8514 bypass
= bypass
->next
)
8516 if (bypass
->latency
> max
)
8517 max
= bypass
->latency
;
8519 fprintf (output_file
, " return %d; }\n break;\n", max
);
8522 fprintf (output_file
, " }\n return default_latencies[%s];\n}\n\n",
8523 INTERNAL_INSN_CODE_NAME
);
8526 /* The function outputs PHR interface function `insn_latency'. */
8528 output_insn_latency_func (void)
8530 fprintf (output_file
, "int\n%s (rtx %s, rtx %s)\n",
8531 INSN_LATENCY_FUNC_NAME
, INSN_PARAMETER_NAME
, INSN2_PARAMETER_NAME
);
8532 fprintf (output_file
, "{\n int %s, %s;\n",
8533 INTERNAL_INSN_CODE_NAME
, INTERNAL_INSN2_CODE_NAME
);
8534 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME
,
8535 INTERNAL_INSN_CODE_NAME
, 0);
8536 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME
,
8537 INTERNAL_INSN2_CODE_NAME
, 0);
8538 fprintf (output_file
, " return %s (%s, %s, %s, %s);\n}\n\n",
8539 INTERNAL_INSN_LATENCY_FUNC_NAME
,
8540 INTERNAL_INSN_CODE_NAME
, INTERNAL_INSN2_CODE_NAME
,
8541 INSN_PARAMETER_NAME
, INSN2_PARAMETER_NAME
);
8544 /* The function outputs PHR interface function `maximal_insn_latency'. */
8546 output_maximal_insn_latency_func (void)
8548 fprintf (output_file
, "int\n%s (rtx %s)\n",
8549 "maximal_insn_latency", INSN_PARAMETER_NAME
);
8550 fprintf (output_file
, "{\n int %s;\n",
8551 INTERNAL_INSN_CODE_NAME
);
8552 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME
,
8553 INTERNAL_INSN_CODE_NAME
, 0);
8554 fprintf (output_file
, " return %s (%s, %s);\n}\n\n",
8555 "internal_maximal_insn_latency",
8556 INTERNAL_INSN_CODE_NAME
, INSN_PARAMETER_NAME
);
8559 /* The function outputs PHR interface function `print_reservation'. */
8561 output_print_reservation_func (void)
8566 fprintf (output_file
,
8567 "void\n%s (FILE *%s, rtx %s ATTRIBUTE_UNUSED)\n{\n",
8568 PRINT_RESERVATION_FUNC_NAME
, FILE_PARAMETER_NAME
,
8569 INSN_PARAMETER_NAME
);
8571 if (DECL_INSN_RESERV (advance_cycle_insn_decl
)->insn_num
== 0)
8573 fprintf (output_file
, " fputs (\"%s\", %s);\n}\n\n",
8574 NOTHING_NAME
, FILE_PARAMETER_NAME
);
8579 fputs (" static const char *const reservation_names[] =\n {",
8582 for (i
= 0, j
= 0; i
< description
->normal_decls_num
; i
++)
8584 decl
= description
->decls
[i
];
8585 if (decl
->mode
== dm_insn_reserv
)
8587 gcc_assert (j
== DECL_INSN_RESERV (decl
)->insn_num
);
8590 fprintf (output_file
, "\n \"%s\",",
8591 regexp_representation (DECL_INSN_RESERV (decl
)->regexp
));
8592 finish_regexp_representation ();
8595 gcc_assert (j
== description
->insns_num
- (collapse_flag
? 2 : 1));
8597 fprintf (output_file
, "\n \"%s\"\n };\n int %s;\n\n",
8598 NOTHING_NAME
, INTERNAL_INSN_CODE_NAME
);
8600 fprintf (output_file
, " if (%s == 0)\n %s = %s;\n",
8601 INSN_PARAMETER_NAME
,
8602 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
8603 fprintf (output_file
, " else\n\
8609 INTERNAL_INSN_CODE_NAME
, DFA_INSN_CODE_FUNC_NAME
,
8610 INSN_PARAMETER_NAME
,
8611 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
,
8612 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
8614 fprintf (output_file
, " fputs (reservation_names[%s], %s);\n}\n\n",
8615 INTERNAL_INSN_CODE_NAME
, FILE_PARAMETER_NAME
);
8618 /* The following function is used to sort unit declaration by their
8621 units_cmp (const void *unit1
, const void *unit2
)
8623 const_unit_decl_t
const u1
= *(const_unit_decl_t
const*) unit1
;
8624 const_unit_decl_t
const u2
= *(const_unit_decl_t
const*) unit2
;
8626 return strcmp (u1
->name
, u2
->name
);
8629 /* The following macro value is name of struct containing unit name
8631 #define NAME_CODE_STRUCT_NAME "name_code"
8633 /* The following macro value is name of table of struct name_code. */
8634 #define NAME_CODE_TABLE_NAME "name_code_table"
8636 /* The following macro values are member names for struct name_code. */
8637 #define NAME_MEMBER_NAME "name"
8638 #define CODE_MEMBER_NAME "code"
8640 /* The following macro values are local variable names for function
8641 `get_cpu_unit_code'. */
8642 #define CMP_VARIABLE_NAME "cmp"
8643 #define LOW_VARIABLE_NAME "l"
8644 #define MIDDLE_VARIABLE_NAME "m"
8645 #define HIGH_VARIABLE_NAME "h"
8647 /* The following function outputs function to obtain internal cpu unit
8648 code by the cpu unit name. */
8650 output_get_cpu_unit_code_func (void)
8655 fprintf (output_file
, "int\n%s (const char *%s)\n",
8656 GET_CPU_UNIT_CODE_FUNC_NAME
, CPU_UNIT_NAME_PARAMETER_NAME
);
8657 fprintf (output_file
, "{\n struct %s {const char *%s; int %s;};\n",
8658 NAME_CODE_STRUCT_NAME
, NAME_MEMBER_NAME
, CODE_MEMBER_NAME
);
8659 fprintf (output_file
, " int %s, %s, %s, %s;\n", CMP_VARIABLE_NAME
,
8660 LOW_VARIABLE_NAME
, MIDDLE_VARIABLE_NAME
, HIGH_VARIABLE_NAME
);
8661 fprintf (output_file
, " static struct %s %s [] =\n {\n",
8662 NAME_CODE_STRUCT_NAME
, NAME_CODE_TABLE_NAME
);
8663 units
= XNEWVEC (unit_decl_t
, description
->units_num
);
8664 memcpy (units
, units_array
, sizeof (unit_decl_t
) * description
->units_num
);
8665 qsort (units
, description
->units_num
, sizeof (unit_decl_t
), units_cmp
);
8666 for (i
= 0; i
< description
->units_num
; i
++)
8667 if (units
[i
]->query_p
)
8668 fprintf (output_file
, " {\"%s\", %d},\n",
8669 units
[i
]->name
, units
[i
]->query_num
);
8670 fprintf (output_file
, " };\n\n");
8671 fprintf (output_file
, " /* The following is binary search: */\n");
8672 fprintf (output_file
, " %s = 0;\n", LOW_VARIABLE_NAME
);
8673 fprintf (output_file
, " %s = sizeof (%s) / sizeof (struct %s) - 1;\n",
8674 HIGH_VARIABLE_NAME
, NAME_CODE_TABLE_NAME
, NAME_CODE_STRUCT_NAME
);
8675 fprintf (output_file
, " while (%s <= %s)\n {\n",
8676 LOW_VARIABLE_NAME
, HIGH_VARIABLE_NAME
);
8677 fprintf (output_file
, " %s = (%s + %s) / 2;\n",
8678 MIDDLE_VARIABLE_NAME
, LOW_VARIABLE_NAME
, HIGH_VARIABLE_NAME
);
8679 fprintf (output_file
, " %s = strcmp (%s, %s [%s].%s);\n",
8680 CMP_VARIABLE_NAME
, CPU_UNIT_NAME_PARAMETER_NAME
,
8681 NAME_CODE_TABLE_NAME
, MIDDLE_VARIABLE_NAME
, NAME_MEMBER_NAME
);
8682 fprintf (output_file
, " if (%s < 0)\n", CMP_VARIABLE_NAME
);
8683 fprintf (output_file
, " %s = %s - 1;\n",
8684 HIGH_VARIABLE_NAME
, MIDDLE_VARIABLE_NAME
);
8685 fprintf (output_file
, " else if (%s > 0)\n", CMP_VARIABLE_NAME
);
8686 fprintf (output_file
, " %s = %s + 1;\n",
8687 LOW_VARIABLE_NAME
, MIDDLE_VARIABLE_NAME
);
8688 fprintf (output_file
, " else\n");
8689 fprintf (output_file
, " return %s [%s].%s;\n }\n",
8690 NAME_CODE_TABLE_NAME
, MIDDLE_VARIABLE_NAME
, CODE_MEMBER_NAME
);
8691 fprintf (output_file
, " return -1;\n}\n\n");
8695 /* The following function outputs function to check reservation of cpu
8696 unit (its internal code will be passed as the function argument) in
8699 output_cpu_unit_reservation_p (void)
8701 automaton_t automaton
;
8703 fprintf (output_file
, "int\n%s (%s %s, int %s)\n",
8704 CPU_UNIT_RESERVATION_P_FUNC_NAME
,
8705 STATE_TYPE_NAME
, STATE_NAME
,
8706 CPU_CODE_PARAMETER_NAME
);
8707 fprintf (output_file
, "{\n gcc_assert (%s >= 0 && %s < %d);\n",
8708 CPU_CODE_PARAMETER_NAME
, CPU_CODE_PARAMETER_NAME
,
8709 description
->query_units_num
);
8710 if (description
->query_units_num
> 0)
8711 for (automaton
= description
->first_automaton
;
8713 automaton
= automaton
->next_automaton
)
8715 fprintf (output_file
, " if ((");
8716 output_reserved_units_table_name (output_file
, automaton
);
8717 fprintf (output_file
, " [((struct %s *) %s)->", CHIP_NAME
, STATE_NAME
);
8718 output_chip_member_name (output_file
, automaton
);
8719 fprintf (output_file
, " * %d + %s / 8] >> (%s %% 8)) & 1)\n",
8720 (description
->query_units_num
+ 7) / 8,
8721 CPU_CODE_PARAMETER_NAME
, CPU_CODE_PARAMETER_NAME
);
8722 fprintf (output_file
, " return 1;\n");
8724 fprintf (output_file
, " return 0;\n}\n\n");
8727 /* The following function outputs a function to check if insn
8728 has a dfa reservation. */
8730 output_insn_has_dfa_reservation_p (void)
8732 fprintf (output_file
,
8733 "bool\n%s (rtx %s ATTRIBUTE_UNUSED)\n{\n",
8734 INSN_HAS_DFA_RESERVATION_P_FUNC_NAME
,
8735 INSN_PARAMETER_NAME
);
8737 if (DECL_INSN_RESERV (advance_cycle_insn_decl
)->insn_num
== 0)
8739 fprintf (output_file
, " return false;\n}\n\n");
8743 fprintf (output_file
, " int %s;\n\n", INTERNAL_INSN_CODE_NAME
);
8745 fprintf (output_file
, " if (%s == 0)\n %s = %s;\n",
8746 INSN_PARAMETER_NAME
,
8747 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
8748 fprintf (output_file
, " else\n\
8754 INTERNAL_INSN_CODE_NAME
, DFA_INSN_CODE_FUNC_NAME
,
8755 INSN_PARAMETER_NAME
,
8756 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
,
8757 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
8759 fprintf (output_file
, " return %s != %s;\n}\n\n",
8760 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
8763 /* The function outputs PHR interface functions `dfa_clean_insn_cache'
8764 and 'dfa_clear_single_insn_cache'. */
8766 output_dfa_clean_insn_cache_func (void)
8768 fprintf (output_file
,
8769 "void\n%s (void)\n{\n int %s;\n\n",
8770 DFA_CLEAN_INSN_CACHE_FUNC_NAME
, I_VARIABLE_NAME
);
8771 fprintf (output_file
,
8772 " for (%s = 0; %s < %s; %s++)\n %s [%s] = -1;\n}\n\n",
8773 I_VARIABLE_NAME
, I_VARIABLE_NAME
,
8774 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
, I_VARIABLE_NAME
,
8775 DFA_INSN_CODES_VARIABLE_NAME
, I_VARIABLE_NAME
);
8777 fprintf (output_file
,
8778 "void\n%s (rtx %s)\n{\n int %s;\n\n",
8779 DFA_CLEAR_SINGLE_INSN_CACHE_FUNC_NAME
, INSN_PARAMETER_NAME
,
8781 fprintf (output_file
,
8782 " %s = INSN_UID (%s);\n if (%s < %s)\n %s [%s] = -1;\n}\n\n",
8783 I_VARIABLE_NAME
, INSN_PARAMETER_NAME
, I_VARIABLE_NAME
,
8784 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
, DFA_INSN_CODES_VARIABLE_NAME
,
8788 /* The function outputs PHR interface function `dfa_start'. */
8790 output_dfa_start_func (void)
8792 fprintf (output_file
,
8793 "void\n%s (void)\n{\n %s = get_max_uid ();\n",
8794 DFA_START_FUNC_NAME
, DFA_INSN_CODES_LENGTH_VARIABLE_NAME
);
8795 fprintf (output_file
, " %s = XNEWVEC (int, %s);\n",
8796 DFA_INSN_CODES_VARIABLE_NAME
, DFA_INSN_CODES_LENGTH_VARIABLE_NAME
);
8797 fprintf (output_file
, " %s ();\n}\n\n", DFA_CLEAN_INSN_CACHE_FUNC_NAME
);
8800 /* The function outputs PHR interface function `dfa_finish'. */
8802 output_dfa_finish_func (void)
8804 fprintf (output_file
, "void\n%s (void)\n{\n free (%s);\n}\n\n",
8805 DFA_FINISH_FUNC_NAME
, DFA_INSN_CODES_VARIABLE_NAME
);
8810 /* The page contains code for output description file (readable
8811 representation of original description and generated DFA(s). */
8813 /* The function outputs string representation of IR reservation. */
8815 output_regexp (regexp_t regexp
)
8817 fprintf (output_description_file
, "%s", regexp_representation (regexp
));
8818 finish_regexp_representation ();
8821 /* Output names of units in LIST separated by comma. */
8823 output_unit_set_el_list (unit_set_el_t list
)
8827 for (el
= list
; el
!= NULL
; el
= el
->next_unit_set_el
)
8830 fprintf (output_description_file
, ", ");
8831 fprintf (output_description_file
, "%s", el
->unit_decl
->name
);
8835 /* Output patterns in LIST separated by comma. */
8837 output_pattern_set_el_list (pattern_set_el_t list
)
8839 pattern_set_el_t el
;
8842 for (el
= list
; el
!= NULL
; el
= el
->next_pattern_set_el
)
8845 fprintf (output_description_file
, ", ");
8846 for (i
= 0; i
< el
->units_num
; i
++)
8847 fprintf (output_description_file
, (i
== 0 ? "%s" : " %s"),
8848 el
->unit_decls
[i
]->name
);
8852 /* The function outputs string representation of IR define_reservation
8853 and define_insn_reservation. */
8855 output_description (void)
8860 for (i
= 0; i
< description
->decls_num
; i
++)
8862 decl
= description
->decls
[i
];
8863 if (decl
->mode
== dm_unit
)
8865 if (DECL_UNIT (decl
)->excl_list
!= NULL
)
8867 fprintf (output_description_file
, "unit %s exclusion_set: ",
8868 DECL_UNIT (decl
)->name
);
8869 output_unit_set_el_list (DECL_UNIT (decl
)->excl_list
);
8870 fprintf (output_description_file
, "\n");
8872 if (DECL_UNIT (decl
)->presence_list
!= NULL
)
8874 fprintf (output_description_file
, "unit %s presence_set: ",
8875 DECL_UNIT (decl
)->name
);
8876 output_pattern_set_el_list (DECL_UNIT (decl
)->presence_list
);
8877 fprintf (output_description_file
, "\n");
8879 if (DECL_UNIT (decl
)->final_presence_list
!= NULL
)
8881 fprintf (output_description_file
, "unit %s final_presence_set: ",
8882 DECL_UNIT (decl
)->name
);
8883 output_pattern_set_el_list
8884 (DECL_UNIT (decl
)->final_presence_list
);
8885 fprintf (output_description_file
, "\n");
8887 if (DECL_UNIT (decl
)->absence_list
!= NULL
)
8889 fprintf (output_description_file
, "unit %s absence_set: ",
8890 DECL_UNIT (decl
)->name
);
8891 output_pattern_set_el_list (DECL_UNIT (decl
)->absence_list
);
8892 fprintf (output_description_file
, "\n");
8894 if (DECL_UNIT (decl
)->final_absence_list
!= NULL
)
8896 fprintf (output_description_file
, "unit %s final_absence_set: ",
8897 DECL_UNIT (decl
)->name
);
8898 output_pattern_set_el_list
8899 (DECL_UNIT (decl
)->final_absence_list
);
8900 fprintf (output_description_file
, "\n");
8904 fprintf (output_description_file
, "\n");
8905 for (i
= 0; i
< description
->normal_decls_num
; i
++)
8907 decl
= description
->decls
[i
];
8908 if (decl
->mode
== dm_reserv
)
8910 fprintf (output_description_file
, "reservation %s: ",
8911 DECL_RESERV (decl
)->name
);
8912 output_regexp (DECL_RESERV (decl
)->regexp
);
8913 fprintf (output_description_file
, "\n");
8915 else if (decl
->mode
== dm_insn_reserv
)
8917 fprintf (output_description_file
, "insn reservation %s ",
8918 DECL_INSN_RESERV (decl
)->name
);
8919 print_rtl (output_description_file
,
8920 DECL_INSN_RESERV (decl
)->condexp
);
8921 fprintf (output_description_file
, ": ");
8922 output_regexp (DECL_INSN_RESERV (decl
)->regexp
);
8923 fprintf (output_description_file
, "\n");
8925 else if (decl
->mode
== dm_bypass
)
8926 fprintf (output_description_file
, "bypass %d %s %s\n",
8927 DECL_BYPASS (decl
)->latency
,
8928 DECL_BYPASS (decl
)->out_pattern
,
8929 DECL_BYPASS (decl
)->in_pattern
);
8931 fprintf (output_description_file
, "\n\f\n");
8934 /* The function outputs name of AUTOMATON. */
8936 output_automaton_name (FILE *f
, automaton_t automaton
)
8938 if (automaton
->corresponding_automaton_decl
== NULL
)
8939 fprintf (f
, "#%d", automaton
->automaton_order_num
);
8941 fprintf (f
, "`%s'", automaton
->corresponding_automaton_decl
->name
);
8944 /* Maximal length of line for pretty printing into description
8946 #define MAX_LINE_LENGTH 70
8948 /* The function outputs units name belonging to AUTOMATON. */
8950 output_automaton_units (automaton_t automaton
)
8954 int curr_line_length
;
8955 int there_is_an_automaton_unit
;
8958 fprintf (output_description_file
, "\n Corresponding units:\n");
8959 fprintf (output_description_file
, " ");
8960 curr_line_length
= 4;
8961 there_is_an_automaton_unit
= 0;
8962 for (i
= 0; i
< description
->decls_num
; i
++)
8964 decl
= description
->decls
[i
];
8965 if (decl
->mode
== dm_unit
8966 && (DECL_UNIT (decl
)->corresponding_automaton_num
8967 == automaton
->automaton_order_num
))
8969 there_is_an_automaton_unit
= 1;
8970 name
= DECL_UNIT (decl
)->name
;
8971 if (curr_line_length
+ strlen (name
) + 1 > MAX_LINE_LENGTH
)
8973 curr_line_length
= strlen (name
) + 4;
8974 fprintf (output_description_file
, "\n ");
8978 curr_line_length
+= strlen (name
) + 1;
8979 fprintf (output_description_file
, " ");
8981 fprintf (output_description_file
, "%s", name
);
8984 if (!there_is_an_automaton_unit
)
8985 fprintf (output_description_file
, "<None>");
8986 fprintf (output_description_file
, "\n\n");
8989 /* The following variable is used for forming array of all possible cpu unit
8990 reservations described by the current DFA state. */
8991 static VEC(reserv_sets_t
, heap
) *state_reservs
;
8993 /* The function forms `state_reservs' for STATE. */
8995 add_state_reservs (state_t state
)
8997 alt_state_t curr_alt_state
;
8999 if (state
->component_states
!= NULL
)
9000 for (curr_alt_state
= state
->component_states
;
9001 curr_alt_state
!= NULL
;
9002 curr_alt_state
= curr_alt_state
->next_sorted_alt_state
)
9003 add_state_reservs (curr_alt_state
->state
);
9005 VEC_safe_push (reserv_sets_t
, heap
, state_reservs
, state
->reservs
);
9008 /* The function outputs readable representation of all out arcs of
9011 output_state_arcs (state_t state
)
9015 const char *insn_name
;
9016 int curr_line_length
;
9018 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
9021 gcc_assert (ainsn
->first_insn_with_same_reservs
);
9022 fprintf (output_description_file
, " ");
9023 curr_line_length
= 7;
9024 fprintf (output_description_file
, "%2d: ", ainsn
->insn_equiv_class_num
);
9027 insn_name
= ainsn
->insn_reserv_decl
->name
;
9028 if (curr_line_length
+ strlen (insn_name
) > MAX_LINE_LENGTH
)
9030 if (ainsn
!= arc
->insn
)
9032 fprintf (output_description_file
, ",\n ");
9033 curr_line_length
= strlen (insn_name
) + 6;
9036 curr_line_length
+= strlen (insn_name
);
9040 curr_line_length
+= strlen (insn_name
);
9041 if (ainsn
!= arc
->insn
)
9043 curr_line_length
+= 2;
9044 fprintf (output_description_file
, ", ");
9047 fprintf (output_description_file
, "%s", insn_name
);
9048 ainsn
= ainsn
->next_same_reservs_insn
;
9050 while (ainsn
!= NULL
);
9051 fprintf (output_description_file
, " %d \n",
9052 arc
->to_state
->order_state_num
);
9054 fprintf (output_description_file
, "\n");
9057 /* The following function is used for sorting possible cpu unit
9058 reservation of a DFA state. */
9060 state_reservs_cmp (const void *reservs_ptr_1
, const void *reservs_ptr_2
)
9062 return reserv_sets_cmp (*(const_reserv_sets_t
const*) reservs_ptr_1
,
9063 *(const_reserv_sets_t
const*) reservs_ptr_2
);
9066 /* The following function is used for sorting possible cpu unit
9067 reservation of a DFA state. */
9069 remove_state_duplicate_reservs (void)
9073 for (i
= 1, j
= 0; i
< VEC_length (reserv_sets_t
, state_reservs
); i
++)
9074 if (reserv_sets_cmp (VEC_index (reserv_sets_t
, state_reservs
, j
),
9075 VEC_index (reserv_sets_t
, state_reservs
, i
)))
9078 VEC_replace (reserv_sets_t
, state_reservs
, j
,
9079 VEC_index (reserv_sets_t
, state_reservs
, i
));
9081 VEC_truncate (reserv_sets_t
, state_reservs
, j
+ 1);
9084 /* The following function output readable representation of DFA(s)
9085 state used for fast recognition of pipeline hazards. State is
9086 described by possible (current and scheduled) cpu unit
9089 output_state (state_t state
)
9095 fprintf (output_description_file
, " State #%d", state
->order_state_num
);
9096 fprintf (output_description_file
,
9097 state
->new_cycle_p
? " (new cycle)\n" : "\n");
9098 add_state_reservs (state
);
9099 VEC_qsort (reserv_sets_t
, state_reservs
, state_reservs_cmp
);
9100 remove_state_duplicate_reservs ();
9101 for (i
= 0; i
< VEC_length (reserv_sets_t
, state_reservs
); i
++)
9103 fprintf (output_description_file
, " ");
9104 output_reserv_sets (output_description_file
,
9105 VEC_index (reserv_sets_t
, state_reservs
, i
));
9106 fprintf (output_description_file
, "\n");
9108 fprintf (output_description_file
, "\n");
9109 output_state_arcs (state
);
9110 VEC_free (reserv_sets_t
, heap
, state_reservs
);
9113 /* The following function output readable representation of
9114 DFAs used for fast recognition of pipeline hazards. */
9116 output_automaton_descriptions (void)
9118 automaton_t automaton
;
9120 for (automaton
= description
->first_automaton
;
9122 automaton
= automaton
->next_automaton
)
9124 fprintf (output_description_file
, "\nAutomaton ");
9125 output_automaton_name (output_description_file
, automaton
);
9126 fprintf (output_description_file
, "\n");
9127 output_automaton_units (automaton
);
9128 pass_states (automaton
, output_state
);
9134 /* The page contains top level function for generation DFA(s) used for
9137 /* The function outputs statistics about work of different phases of
9140 output_statistics (FILE *f
)
9142 automaton_t automaton
;
9145 int transition_comb_vect_els
= 0;
9146 int transition_full_vect_els
= 0;
9147 int min_issue_delay_vect_els
= 0;
9148 int locked_states
= 0;
9151 for (automaton
= description
->first_automaton
;
9153 automaton
= automaton
->next_automaton
)
9155 fprintf (f
, "\nAutomaton ");
9156 output_automaton_name (f
, automaton
);
9157 fprintf (f
, "\n %5d NDFA states, %5d NDFA arcs\n",
9158 automaton
->NDFA_states_num
, automaton
->NDFA_arcs_num
);
9159 fprintf (f
, " %5d DFA states, %5d DFA arcs\n",
9160 automaton
->DFA_states_num
, automaton
->DFA_arcs_num
);
9161 states_num
= automaton
->DFA_states_num
;
9162 if (!no_minimization_flag
)
9164 fprintf (f
, " %5d minimal DFA states, %5d minimal DFA arcs\n",
9165 automaton
->minimal_DFA_states_num
,
9166 automaton
->minimal_DFA_arcs_num
);
9167 states_num
= automaton
->minimal_DFA_states_num
;
9169 fprintf (f
, " %5d all insns %5d insn equivalence classes\n",
9170 description
->insns_num
, automaton
->insn_equiv_classes_num
);
9171 fprintf (f
, " %d locked states\n", automaton
->locked_states
);
9174 (f
, "%5ld transition comb vector els, %5ld trans table els: %s\n",
9175 (long) VEC_length (vect_el_t
, automaton
->trans_table
->comb_vect
),
9176 (long) VEC_length (vect_el_t
, automaton
->trans_table
->full_vect
),
9177 (comb_vect_p (automaton
->trans_table
)
9178 ? "use comb vect" : "use simple vect"));
9180 (f
, "%5ld min delay table els, compression factor %d\n",
9181 (long) states_num
* automaton
->insn_equiv_classes_num
,
9182 automaton
->min_issue_delay_table_compression_factor
);
9183 transition_comb_vect_els
9184 += VEC_length (vect_el_t
, automaton
->trans_table
->comb_vect
);
9185 transition_full_vect_els
9186 += VEC_length (vect_el_t
, automaton
->trans_table
->full_vect
);
9187 min_issue_delay_vect_els
9188 += states_num
* automaton
->insn_equiv_classes_num
;
9190 += automaton
->locked_states
;
9194 fprintf (f
, "\n%5d all allocated states, %5d all allocated arcs\n",
9195 allocated_states_num
, allocated_arcs_num
);
9196 fprintf (f
, "%5d all allocated alternative states\n",
9197 allocated_alt_states_num
);
9198 fprintf (f
, "%5d all transition comb vector els, %5d all trans table els\n",
9199 transition_comb_vect_els
, transition_full_vect_els
);
9200 fprintf (f
, "%5d all min delay table els\n", min_issue_delay_vect_els
);
9201 fprintf (f
, "%5d all locked states\n", locked_states
);
9205 /* The function output times of work of different phases of DFA
9208 output_time_statistics (FILE *f
)
9210 fprintf (f
, "\n transformation: ");
9211 print_active_time (f
, transform_time
);
9212 fprintf (f
, (!ndfa_flag
? ", building DFA: " : ", building NDFA: "));
9213 print_active_time (f
, NDFA_time
);
9216 fprintf (f
, ", NDFA -> DFA: ");
9217 print_active_time (f
, NDFA_to_DFA_time
);
9219 fprintf (f
, "\n DFA minimization: ");
9220 print_active_time (f
, minimize_time
);
9221 fprintf (f
, ", making insn equivalence: ");
9222 print_active_time (f
, equiv_time
);
9223 fprintf (f
, "\n all automaton generation: ");
9224 print_active_time (f
, automaton_generation_time
);
9225 fprintf (f
, ", output: ");
9226 print_active_time (f
, output_time
);
9230 /* The function generates DFA (deterministic finite state automaton)
9231 for fast recognition of pipeline hazards. No errors during
9232 checking must be fixed before this function call. */
9236 automata_num
= split_argument
;
9237 if (description
->units_num
< automata_num
)
9238 automata_num
= description
->units_num
;
9241 initiate_automata_lists ();
9242 initiate_pass_states ();
9243 initiate_excl_sets ();
9244 initiate_presence_absence_pattern_sets ();
9245 automaton_generation_time
= create_ticker ();
9247 ticker_off (&automaton_generation_time
);
9252 /* This page mainly contains top level functions of pipeline hazards
9253 description translator. */
9255 /* The following macro value is suffix of name of description file of
9256 pipeline hazards description translator. */
9257 #define STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX ".dfa"
9259 /* The function returns suffix of given file name. The returned
9260 string can not be changed. */
9262 file_name_suffix (const char *file_name
)
9264 const char *last_period
;
9266 for (last_period
= NULL
; *file_name
!= '\0'; file_name
++)
9267 if (*file_name
== '.')
9268 last_period
= file_name
;
9269 return (last_period
== NULL
? file_name
: last_period
);
9272 /* The function returns base name of given file name, i.e. pointer to
9273 first char after last `/' (or `\' for WIN32) in given file name,
9274 given file name itself if the directory name is absent. The
9275 returned string can not be changed. */
9277 base_file_name (const char *file_name
)
9279 int directory_name_length
;
9281 directory_name_length
= strlen (file_name
);
9283 while (directory_name_length
>= 0 && file_name
[directory_name_length
] != '/'
9284 && file_name
[directory_name_length
] != '\\')
9286 while (directory_name_length
>= 0 && file_name
[directory_name_length
] != '/')
9288 directory_name_length
--;
9289 return file_name
+ directory_name_length
+ 1;
9292 /* A function passed as argument to init_rtx_reader_args_cb. It parses the
9293 options available for genautomata. Returns true if the option was
9296 parse_automata_opt (const char *str
)
9298 if (strcmp (str
, NO_MINIMIZATION_OPTION
) == 0)
9299 no_minimization_flag
= 1;
9300 else if (strcmp (str
, TIME_OPTION
) == 0)
9302 else if (strcmp (str
, STATS_OPTION
) == 0)
9304 else if (strcmp (str
, V_OPTION
) == 0)
9306 else if (strcmp (str
, W_OPTION
) == 0)
9308 else if (strcmp (str
, NDFA_OPTION
) == 0)
9310 else if (strcmp (str
, COLLAPSE_OPTION
) == 0)
9312 else if (strcmp (str
, PROGRESS_OPTION
) == 0)
9314 else if (strcmp (str
, "-split") == 0)
9316 fatal ("option `-split' has not been implemented yet\n");
9317 /* split_argument = atoi (argument_vect [i + 1]); */
9325 /* The following is top level function to initialize the work of
9326 pipeline hazards description translator. */
9328 initiate_automaton_gen (char **argv
)
9330 const char *base_name
;
9332 /* Initialize IR storage. */
9333 obstack_init (&irp
);
9334 initiate_automaton_decl_table ();
9335 initiate_insn_decl_table ();
9336 initiate_decl_table ();
9337 output_file
= stdout
;
9338 output_description_file
= NULL
;
9339 base_name
= base_file_name (argv
[1]);
9340 obstack_grow (&irp
, base_name
,
9341 strlen (base_name
) - strlen (file_name_suffix (base_name
)));
9342 obstack_grow (&irp
, STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX
,
9343 strlen (STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX
) + 1);
9344 obstack_1grow (&irp
, '\0');
9345 output_description_file_name
= obstack_base (&irp
);
9346 obstack_finish (&irp
);
9349 /* The following function checks existence at least one arc marked by
9352 check_automata_insn_issues (void)
9354 automaton_t automaton
;
9355 ainsn_t ainsn
, reserv_ainsn
;
9357 for (automaton
= description
->first_automaton
;
9359 automaton
= automaton
->next_automaton
)
9361 for (ainsn
= automaton
->ainsn_list
;
9363 ainsn
= ainsn
->next_ainsn
)
9364 if (ainsn
->first_insn_with_same_reservs
&& !ainsn
->arc_exists_p
9365 && ainsn
!= automaton
->collapse_ainsn
)
9367 for (reserv_ainsn
= ainsn
;
9368 reserv_ainsn
!= NULL
;
9369 reserv_ainsn
= reserv_ainsn
->next_same_reservs_insn
)
9370 if (automaton
->corresponding_automaton_decl
!= NULL
)
9373 error ("Automaton `%s': Insn `%s' will never be issued",
9374 automaton
->corresponding_automaton_decl
->name
,
9375 reserv_ainsn
->insn_reserv_decl
->name
);
9377 warning ("Automaton `%s': Insn `%s' will never be issued",
9378 automaton
->corresponding_automaton_decl
->name
,
9379 reserv_ainsn
->insn_reserv_decl
->name
);
9384 error ("Insn `%s' will never be issued",
9385 reserv_ainsn
->insn_reserv_decl
->name
);
9387 warning ("Insn `%s' will never be issued",
9388 reserv_ainsn
->insn_reserv_decl
->name
);
9394 /* The following vla is used for storing pointers to all achieved
9396 static VEC(state_t
, heap
) *automaton_states
;
9398 /* This function is called by function pass_states to add an achieved
9401 add_automaton_state (state_t state
)
9403 VEC_safe_push (state_t
, heap
, automaton_states
, state
);
9406 /* The following function forms list of important automata (whose
9407 states may be changed after the insn issue) for each insn. */
9409 form_important_insn_automata_lists (void)
9411 automaton_t automaton
;
9418 automaton_states
= 0;
9419 /* Mark important ainsns. */
9420 for (automaton
= description
->first_automaton
;
9422 automaton
= automaton
->next_automaton
)
9424 VEC_truncate (state_t
, automaton_states
, 0);
9425 pass_states (automaton
, add_automaton_state
);
9426 for (n
= 0; n
< VEC_length (state_t
, automaton_states
); n
++)
9428 state_t s
= VEC_index (state_t
, automaton_states
, n
);
9429 for (arc
= first_out_arc (s
);
9431 arc
= next_out_arc (arc
))
9432 if (arc
->to_state
!= s
)
9434 gcc_assert (arc
->insn
->first_insn_with_same_reservs
);
9435 for (ainsn
= arc
->insn
;
9437 ainsn
= ainsn
->next_same_reservs_insn
)
9438 ainsn
->important_p
= TRUE
;
9442 VEC_free (state_t
, heap
, automaton_states
);
9444 /* Create automata sets for the insns. */
9445 for (i
= 0; i
< description
->decls_num
; i
++)
9447 decl
= description
->decls
[i
];
9448 if (decl
->mode
== dm_insn_reserv
)
9450 automata_list_start ();
9451 for (automaton
= description
->first_automaton
;
9453 automaton
= automaton
->next_automaton
)
9454 for (ainsn
= automaton
->ainsn_list
;
9456 ainsn
= ainsn
->next_ainsn
)
9457 if (ainsn
->important_p
9458 && ainsn
->insn_reserv_decl
== DECL_INSN_RESERV (decl
))
9460 automata_list_add (automaton
);
9463 DECL_INSN_RESERV (decl
)->important_automata_list
9464 = automata_list_finish ();
9470 /* The following is top level function to generate automat(a,on) for
9471 fast recognition of pipeline hazards. */
9473 expand_automata (void)
9477 description
= XCREATENODEVAR (struct description
,
9478 sizeof (struct description
)
9479 /* Two entries for special insns. */
9480 + sizeof (decl_t
) * (VEC_length (decl_t
, decls
) + 1));
9481 description
->decls_num
= VEC_length (decl_t
, decls
);
9482 description
->normal_decls_num
= description
->decls_num
;
9483 description
->query_units_num
= 0;
9484 for (i
= 0; i
< description
->decls_num
; i
++)
9486 description
->decls
[i
] = VEC_index (decl_t
, decls
, i
);
9487 if (description
->decls
[i
]->mode
== dm_unit
9488 && DECL_UNIT (description
->decls
[i
])->query_p
)
9489 DECL_UNIT (description
->decls
[i
])->query_num
9490 = description
->query_units_num
++;
9492 all_time
= create_ticker ();
9493 check_time
= create_ticker ();
9495 fprintf (stderr
, "Check description...");
9496 check_all_description ();
9498 fprintf (stderr
, "done\n");
9499 ticker_off (&check_time
);
9500 generation_time
= create_ticker ();
9503 transform_insn_regexps ();
9504 check_unit_distributions_to_automata ();
9509 check_automata_insn_issues ();
9513 form_important_insn_automata_lists ();
9515 ticker_off (&generation_time
);
9518 /* The following is top level function to output PHR and to finish
9519 work with pipeline description translator. */
9521 write_automata (void)
9523 output_time
= create_ticker ();
9525 fprintf (stderr
, "Forming and outputting automata tables...");
9529 fprintf (stderr
, "done\n");
9530 fprintf (stderr
, "Output functions to work with automata...");
9532 output_chip_definitions ();
9533 output_max_insn_queue_index_def ();
9534 output_internal_min_issue_delay_func ();
9535 output_internal_trans_func ();
9536 /* Cache of insn dfa codes: */
9537 fprintf (output_file
, "\nstatic int *%s;\n", DFA_INSN_CODES_VARIABLE_NAME
);
9538 fprintf (output_file
, "\nstatic int %s;\n\n",
9539 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
);
9540 output_dfa_insn_code_func ();
9541 output_trans_func ();
9542 output_min_issue_delay_func ();
9543 output_internal_dead_lock_func ();
9544 output_dead_lock_func ();
9545 output_size_func ();
9546 output_internal_reset_func ();
9547 output_reset_func ();
9548 output_min_insn_conflict_delay_func ();
9549 output_default_latencies ();
9550 output_internal_insn_latency_func ();
9551 output_insn_latency_func ();
9552 output_internal_maximal_insn_latency_func ();
9553 output_maximal_insn_latency_func ();
9554 output_print_reservation_func ();
9555 /* Output function get_cpu_unit_code. */
9556 fprintf (output_file
, "\n#if %s\n\n", CPU_UNITS_QUERY_MACRO_NAME
);
9557 output_get_cpu_unit_code_func ();
9558 output_cpu_unit_reservation_p ();
9559 output_insn_has_dfa_reservation_p ();
9560 fprintf (output_file
, "\n#endif /* #if %s */\n\n",
9561 CPU_UNITS_QUERY_MACRO_NAME
);
9562 output_dfa_clean_insn_cache_func ();
9563 output_dfa_start_func ();
9564 output_dfa_finish_func ();
9566 fprintf (stderr
, "done\n");
9569 output_description_file
= fopen (output_description_file_name
, "w");
9570 if (output_description_file
== NULL
)
9572 perror (output_description_file_name
);
9573 exit (FATAL_EXIT_CODE
);
9576 fprintf (stderr
, "Output automata description...");
9577 output_description ();
9578 output_automaton_descriptions ();
9580 fprintf (stderr
, "done\n");
9581 output_statistics (output_description_file
);
9584 output_statistics (stderr
);
9585 ticker_off (&output_time
);
9587 output_time_statistics (stderr
);
9590 finish_automata_lists ();
9593 fprintf (stderr
, "Summary:\n");
9594 fprintf (stderr
, " check time ");
9595 print_active_time (stderr
, check_time
);
9596 fprintf (stderr
, ", generation time ");
9597 print_active_time (stderr
, generation_time
);
9598 fprintf (stderr
, ", all time ");
9599 print_active_time (stderr
, all_time
);
9600 fprintf (stderr
, "\n");
9602 /* Finish all work. */
9603 if (output_description_file
!= NULL
)
9605 fflush (output_description_file
);
9606 if (ferror (stdout
) != 0)
9607 fatal ("Error in writing DFA description file %s: %s",
9608 output_description_file_name
, xstrerror (errno
));
9609 fclose (output_description_file
);
9611 finish_automaton_decl_table ();
9612 finish_insn_decl_table ();
9613 finish_decl_table ();
9614 obstack_free (&irp
, NULL
);
9615 if (have_error
&& output_description_file
!= NULL
)
9616 remove (output_description_file_name
);
9620 main (int argc
, char **argv
)
9624 progname
= "genautomata";
9626 if (!init_rtx_reader_args_cb (argc
, argv
, parse_automata_opt
))
9627 return (FATAL_EXIT_CODE
);
9629 initiate_automaton_gen (argv
);
9633 int insn_code_number
;
9635 desc
= read_md_rtx (&lineno
, &insn_code_number
);
9639 switch (GET_CODE (desc
))
9641 case DEFINE_CPU_UNIT
:
9642 gen_cpu_unit (desc
);
9645 case DEFINE_QUERY_CPU_UNIT
:
9646 gen_query_cpu_unit (desc
);
9654 gen_excl_set (desc
);
9658 gen_presence_set (desc
);
9661 case FINAL_PRESENCE_SET
:
9662 gen_final_presence_set (desc
);
9666 gen_absence_set (desc
);
9669 case FINAL_ABSENCE_SET
:
9670 gen_final_absence_set (desc
);
9673 case DEFINE_AUTOMATON
:
9674 gen_automaton (desc
);
9677 case AUTOMATA_OPTION
:
9678 gen_automata_option (desc
);
9681 case DEFINE_RESERVATION
:
9685 case DEFINE_INSN_RESERVATION
:
9686 gen_insn_reserv (desc
);
9695 return FATAL_EXIT_CODE
;
9697 if (VEC_length (decl_t
, decls
) > 0)
9702 puts ("/* Generated automatically by the program `genautomata'\n"
9703 " from the machine description file `md'. */\n\n"
9704 "#include \"config.h\"\n"
9705 "#include \"system.h\"\n"
9706 "#include \"coretypes.h\"\n"
9707 "#include \"tm.h\"\n"
9708 "#include \"rtl.h\"\n"
9709 "#include \"tm_p.h\"\n"
9710 "#include \"insn-config.h\"\n"
9711 "#include \"recog.h\"\n"
9712 "#include \"regs.h\"\n"
9713 "#include \"output.h\"\n"
9714 "#include \"insn-attr.h\"\n"
9715 "#include \"diagnostic-core.h\"\n"
9716 "#include \"flags.h\"\n"
9717 "#include \"function.h\"\n"
9718 "#include \"emit-rtl.h\"\n");
9719 /* FIXME: emit-rtl.h can go away once crtl is in rtl.h. */
9726 puts ("/* Generated automatically by the program `genautomata'\n"
9727 " from the machine description file `md'. */\n\n"
9728 "/* There is no automaton, but ISO C forbids empty\n"
9729 " translation units, so include a header file with some\n"
9730 " declarations, and its pre-requisite header file. */\n"
9731 "#include \"config.h\"\n"
9732 "#include \"system.h\"\n");
9736 return (ferror (stdout
) != 0 || have_error
9737 ? FATAL_EXIT_CODE
: SUCCESS_EXIT_CODE
);