1 /* Pipeline hazard description translator.
2 Copyright (C) 2000-2013 Free Software Foundation, Inc.
4 Written by Vladimir Makarov <vmakarov@redhat.com>
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 3, or (at your option) any
13 GCC is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. */
24 1. The finite state automaton based pipeline hazard recognizer and
25 instruction scheduler in GCC. V. Makarov. Proceedings of GCC
28 2. Detecting pipeline structural hazards quickly. T. Proebsting,
29 C. Fraser. Proceedings of ACM SIGPLAN-SIGACT Symposium on
30 Principles of Programming Languages, pages 280--286, 1994.
32 This article is a good start point to understand usage of finite
33 state automata for pipeline hazard recognizers. But I'd
34 recommend the 1st and 3rd article for more deep understanding.
36 3. Efficient Instruction Scheduling Using Finite State Automata:
37 V. Bala and N. Rubin, Proceedings of MICRO-28. This is the best
38 article about usage of finite state automata for pipeline hazard
41 The current implementation is described in the 1st article and it
42 is different from the 3rd article in the following:
44 1. New operator `|' (alternative) is permitted in functional unit
45 reservation which can be treated deterministically and
46 non-deterministically.
48 2. Possibility of usage of nondeterministic automata too.
50 3. Possibility to query functional unit reservations for given
53 4. Several constructions to describe impossible reservations
54 (`exclusion_set', `presence_set', `final_presence_set',
55 `absence_set', and `final_absence_set').
57 5. No reverse automata are generated. Trace instruction scheduling
58 requires this. It can be easily added in the future if we
61 6. Union of automaton states are not generated yet. It is planned
62 to be implemented. Such feature is needed to make more accurate
63 interlock insn scheduling to get state describing functional
64 unit reservation in a joint CFG point. */
66 /* This file code processes constructions of machine description file
67 which describes automaton used for recognition of processor pipeline
68 hazards by insn scheduler and can be used for other tasks (such as
71 The translator functions `gen_cpu_unit', `gen_query_cpu_unit',
72 `gen_bypass', `gen_excl_set', `gen_presence_set',
73 `gen_final_presence_set', `gen_absence_set',
74 `gen_final_absence_set', `gen_automaton', `gen_automata_option',
75 `gen_reserv', `gen_insn_reserv' are called from file
76 `genattrtab.c'. They transform RTL constructions describing
77 automata in .md file into internal representation convenient for
80 The translator major function `expand_automata' processes the
81 description internal representation into finite state automaton.
84 o checking correctness of the automaton pipeline description
85 (major function is `check_all_description').
87 o generating automaton (automata) from the description (major
88 function is `make_automaton').
90 o optional transformation of nondeterministic finite state
91 automata into deterministic ones if the alternative operator
92 `|' is treated nondeterministically in the description (major
93 function is NDFA_to_DFA).
95 o optional minimization of the finite state automata by merging
96 equivalent automaton states (major function is `minimize_DFA').
98 o forming tables (some as comb vectors) and attributes
99 representing the automata (functions output_..._table).
101 Function `write_automata' outputs the created finite state
102 automaton as different tables and functions which works with the
103 automata to inquire automaton state and to change its state. These
104 function are used by gcc instruction scheduler and may be some
109 #include "coretypes.h"
114 #include "gensupport.h"
125 /* Positions in machine description file. Now they are not used. But
126 they could be used in the future for better diagnostic messages. */
129 /* The following is element of vector of current (and planned in the
130 future) functional unit reservations. */
131 typedef unsigned HOST_WIDE_INT set_el_t
;
133 /* Reservations of function units are represented by value of the following
135 typedef set_el_t
*reserv_sets_t
;
136 typedef const set_el_t
*const_reserv_sets_t
;
138 /* The following structure describes a ticker. */
141 /* The following member value is time of the ticker creation with
142 taking into account time when the ticker is off. Active time of
143 the ticker is current time minus the value. */
144 int modified_creation_time
;
145 /* The following member value is time (incremented by one) when the
146 ticker was off. Zero value means that now the ticker is on. */
147 int incremented_off_time
;
150 /* The ticker is represented by the following type. */
151 typedef struct ticker ticker_t
;
153 /* The following type describes elements of output vectors. */
154 typedef HOST_WIDE_INT vect_el_t
;
156 /* Forward declaration of structures of internal representation of
157 pipeline description based on NDFA. */
162 struct automaton_decl
;
163 struct unit_pattern_rel_decl
;
165 struct insn_reserv_decl
;
168 struct result_regexp
;
169 struct reserv_regexp
;
170 struct nothing_regexp
;
171 struct sequence_regexp
;
172 struct repeat_regexp
;
178 struct pattern_set_el
;
179 struct pattern_reserv
;
185 struct state_ainsn_table
;
187 /* The following typedefs are for brevity. */
188 typedef struct unit_decl
*unit_decl_t
;
189 typedef const struct unit_decl
*const_unit_decl_t
;
190 typedef struct decl
*decl_t
;
191 typedef const struct decl
*const_decl_t
;
192 typedef struct regexp
*regexp_t
;
193 typedef struct unit_set_el
*unit_set_el_t
;
194 typedef struct pattern_set_el
*pattern_set_el_t
;
195 typedef struct pattern_reserv
*pattern_reserv_t
;
196 typedef struct alt_state
*alt_state_t
;
197 typedef struct state
*state_t
;
198 typedef const struct state
*const_state_t
;
199 typedef struct arc
*arc_t
;
200 typedef struct ainsn
*ainsn_t
;
201 typedef struct automaton
*automaton_t
;
202 typedef struct automata_list_el
*automata_list_el_t
;
203 typedef const struct automata_list_el
*const_automata_list_el_t
;
204 typedef struct state_ainsn_table
*state_ainsn_table_t
;
206 /* Undefined position. */
207 static pos_t no_pos
= 0;
209 /* All IR is stored in the following obstack. */
210 static struct obstack irp
;
213 /* Declare vector types for various data structures: */
216 typedef vec
<vect_el_t
> vla_hwint_t
;
218 /* Forward declarations of functions used before their definitions, only. */
219 static regexp_t
gen_regexp_sequence (const char *);
220 static void reserv_sets_or (reserv_sets_t
, reserv_sets_t
,
222 static reserv_sets_t
get_excl_set (reserv_sets_t
);
223 static int check_presence_pattern_sets (reserv_sets_t
,
225 static int check_absence_pattern_sets (reserv_sets_t
, reserv_sets_t
,
227 static arc_t
first_out_arc (const_state_t
);
228 static arc_t
next_out_arc (arc_t
);
232 /* Options with the following names can be set up in automata_option
233 construction. Because the strings occur more one time we use the
236 #define NO_MINIMIZATION_OPTION "-no-minimization"
237 #define TIME_OPTION "-time"
238 #define STATS_OPTION "-stats"
239 #define V_OPTION "-v"
240 #define W_OPTION "-w"
241 #define NDFA_OPTION "-ndfa"
242 #define COLLAPSE_OPTION "-collapse-ndfa"
243 #define NO_COMB_OPTION "-no-comb-vect"
244 #define PROGRESS_OPTION "-progress"
246 /* The following flags are set up by function `initiate_automaton_gen'. */
248 /* Make automata with nondeterministic reservation by insns (`-ndfa'). */
249 static int ndfa_flag
;
251 /* When making an NDFA, produce additional transitions that collapse
252 NDFA state into a deterministic one suitable for querying CPU units.
253 Provide avance-state transitions only for deterministic states. */
254 static int collapse_flag
;
256 /* Do not make minimization of DFA (`-no-minimization'). */
257 static int no_minimization_flag
;
259 /* Do not try to generate a comb vector (`-no-comb-vect'). */
260 static int no_comb_flag
;
262 /* Value of this variable is number of automata being generated. The
263 actual number of automata may be less this value if there is not
264 sufficient number of units. This value is defined by argument of
265 option `-split' or by constructions automaton if the value is zero
266 (it is default value of the argument). */
267 static int split_argument
;
269 /* Flag of output time statistics (`-time'). */
270 static int time_flag
;
272 /* Flag of automata statistics (`-stats'). */
273 static int stats_flag
;
275 /* Flag of creation of description file which contains description of
276 result automaton and statistics information (`-v'). */
279 /* Flag of output of a progress bar showing how many states were
280 generated so far for automaton being processed (`-progress'). */
281 static int progress_flag
;
283 /* Flag of generating warning instead of error for non-critical errors
288 /* Output file for pipeline hazard recognizer (PHR) being generated.
289 The value is NULL if the file is not defined. */
290 static FILE *output_file
;
292 /* Description file of PHR. The value is NULL if the file is not
294 static FILE *output_description_file
;
296 /* PHR description file name. */
297 static char *output_description_file_name
;
299 /* Value of the following variable is node representing description
300 being processed. This is start point of IR. */
301 static struct description
*description
;
305 /* This page contains description of IR structure (nodes). */
319 /* This describes define_cpu_unit and define_query_cpu_unit (see file
324 /* NULL if the automaton name is absent. */
325 const char *automaton_name
;
326 /* If the following value is not zero, the cpu unit reservation is
327 described in define_query_cpu_unit. */
330 /* The following fields are defined by checker. */
332 /* The following field value is nonzero if the unit is used in an
336 /* The following field value is order number (0, 1, ...) of given
339 /* The following field value is corresponding declaration of
340 automaton which was given in description. If the field value is
341 NULL then automaton in the unit declaration was absent. */
342 struct automaton_decl
*automaton_decl
;
343 /* The following field value is maximal cycle number (1, ...) on
344 which given unit occurs in insns. Zero value means that given
345 unit is not used in insns. */
346 int max_occ_cycle_num
;
347 /* The following field value is minimal cycle number (0, ...) on
348 which given unit occurs in insns. -1 value means that given
349 unit is not used in insns. */
350 int min_occ_cycle_num
;
351 /* The following list contains units which conflict with given
353 unit_set_el_t excl_list
;
354 /* The following list contains patterns which are required to
355 reservation of given unit. */
356 pattern_set_el_t presence_list
;
357 pattern_set_el_t final_presence_list
;
358 /* The following list contains patterns which should be not present
359 in reservation for given unit. */
360 pattern_set_el_t absence_list
;
361 pattern_set_el_t final_absence_list
;
362 /* The following is used only when `query_p' has nonzero value.
363 This is query number for the unit. */
365 /* The following is the last cycle on which the unit was checked for
366 correct distributions of units to automata in a regexp. */
367 int last_distribution_check_cycle
;
369 /* The following fields are defined by automaton generator. */
371 /* The following field value is number of the automaton to which
372 given unit belongs. */
373 int corresponding_automaton_num
;
374 /* If the following value is not zero, the cpu unit is present in a
375 `exclusion_set' or in right part of a `presence_set',
376 `final_presence_set', `absence_set', and
377 `final_absence_set'define_query_cpu_unit. */
381 /* This describes define_bypass (see file rtl.def). */
385 const char *out_pattern
;
386 const char *in_pattern
;
387 const char *bypass_guard_name
;
389 /* The following fields are defined by checker. */
391 /* output and input insns of given bypass. */
392 struct insn_reserv_decl
*out_insn_reserv
;
393 struct insn_reserv_decl
*in_insn_reserv
;
394 /* The next bypass for given output insn. */
395 struct bypass_decl
*next
;
398 /* This describes define_automaton (see file rtl.def). */
399 struct automaton_decl
403 /* The following fields are defined by automaton generator. */
405 /* The following field value is nonzero if the automaton is used in
406 an regexp definition. */
407 char automaton_is_used
;
409 /* The following fields are defined by checker. */
411 /* The following field value is the corresponding automaton. This
412 field is not NULL only if the automaton is present in unit
413 declarations and the automatic partition on automata is not
415 automaton_t corresponding_automaton
;
418 /* This describes exclusion relations: exclusion_set (see file
423 int first_list_length
;
427 /* This describes unit relations: [final_]presence_set or
428 [final_]absence_set (see file rtl.def). */
429 struct unit_pattern_rel_decl
438 /* This describes define_reservation (see file rtl.def). */
444 /* The following fields are defined by checker. */
446 /* The following field value is nonzero if the unit is used in an
449 /* The following field is used to check up cycle in expression
454 /* This describes define_insn_reservation (see file rtl.def). */
455 struct insn_reserv_decl
462 /* The following fields are defined by checker. */
464 /* The following field value is order number (0, 1, ...) of given
467 /* The following field value is list of bypasses in which given insn
468 is output insn. Bypasses with the same input insn stay one after
469 another in the list in the same order as their occurrences in the
470 description but the bypass without a guard stays always the last
471 in a row of bypasses with the same input insn. */
472 struct bypass_decl
*bypass_list
;
474 /* The following fields are defined by automaton generator. */
476 /* The following field is the insn regexp transformed that
477 the regexp has not optional regexp, repetition regexp, and an
478 reservation name (i.e. reservation identifiers are changed by the
479 corresponding regexp) and all alternations are the top level
480 of the regexp. The value can be NULL only if it is special
481 insn `cycle advancing'. */
482 regexp_t transformed_regexp
;
483 /* The following field value is list of arcs marked given
484 insn. The field is used in transformation NDFA -> DFA. */
485 arc_t arcs_marked_by_insn
;
486 /* The two following fields are used during minimization of a finite state
488 /* The field value is number of equivalence class of state into
489 which arc marked by given insn enters from a state (fixed during
490 an automaton minimization). */
492 /* The following member value is the list to automata which can be
493 changed by the insn issue. */
494 automata_list_el_t important_automata_list
;
495 /* The following member is used to process insn once for output. */
499 /* This contains a declaration mentioned above. */
502 /* What node in the union? */
507 struct unit_decl unit
;
508 struct bypass_decl bypass
;
509 struct automaton_decl automaton
;
510 struct excl_rel_decl excl
;
511 struct unit_pattern_rel_decl presence
;
512 struct unit_pattern_rel_decl absence
;
513 struct reserv_decl reserv
;
514 struct insn_reserv_decl insn_reserv
;
518 /* The following structures represent parsed reservation strings. */
530 /* Cpu unit in reservation. */
534 unit_decl_t unit_decl
;
537 /* Define_reservation in a reservation. */
541 struct reserv_decl
*reserv_decl
;
544 /* Absence of reservation (represented by string `nothing'). */
545 struct nothing_regexp
547 /* This used to be empty but ISO C doesn't allow that. */
551 /* Representation of reservations separated by ',' (see file
553 struct sequence_regexp
556 regexp_t regexps
[1];
559 /* Representation of construction `repeat' (see file rtl.def). */
566 /* Representation of reservations separated by '+' (see file
571 regexp_t regexps
[1];
574 /* Representation of reservations separated by '|' (see file
579 regexp_t regexps
[1];
582 /* Representation of a reservation string. */
585 /* What node in the union? */
586 enum regexp_mode mode
;
590 struct unit_regexp unit
;
591 struct reserv_regexp reserv
;
592 struct nothing_regexp nothing
;
593 struct sequence_regexp sequence
;
594 struct repeat_regexp repeat
;
595 struct allof_regexp allof
;
596 struct oneof_regexp oneof
;
600 /* Represents description of pipeline hazard description based on
604 int decls_num
, normal_decls_num
;
606 /* The following fields are defined by checker. */
608 /* The following fields values are correspondingly number of all
609 units, query units, and insns in the description. */
613 /* The following field value is max length (in cycles) of
614 reservations of insns. The field value is defined only for
616 int max_insn_reserv_cycles
;
618 /* The following fields are defined by automaton generator. */
620 /* The following field value is the first automaton. */
621 automaton_t first_automaton
;
623 /* The following field is created by pipeline hazard parser and
624 contains all declarations. We allocate additional entries for
625 two special insns which are added by the automaton generator. */
630 /* The following nodes are created in automaton checker. */
632 /* The following nodes represent exclusion set for cpu units. Each
633 element is accessed through only one excl_list. */
636 unit_decl_t unit_decl
;
637 unit_set_el_t next_unit_set_el
;
640 /* The following nodes represent presence or absence pattern for cpu
641 units. Each element is accessed through only one presence_list or
643 struct pattern_set_el
645 /* The number of units in unit_decls. */
647 /* The units forming the pattern. */
648 struct unit_decl
**unit_decls
;
649 pattern_set_el_t next_pattern_set_el
;
653 /* The following nodes are created in automaton generator. */
656 /* The following nodes represent presence or absence pattern for cpu
657 units. Each element is accessed through only one element of
658 unit_presence_set_table or unit_absence_set_table. */
659 struct pattern_reserv
661 reserv_sets_t reserv
;
662 pattern_reserv_t next_pattern_reserv
;
665 /* The following node type describes state automaton. The state may
666 be deterministic or non-deterministic. Non-deterministic state has
667 several component states which represent alternative cpu units
668 reservations. The state also is used for describing a
669 deterministic reservation of automaton insn. */
672 /* The following member value is nonzero if there is a transition by
675 /* The following field is list of processor unit reservations on
677 reserv_sets_t reservs
;
678 /* The following field is unique number of given state between other
681 /* The following field value is automaton to which given state
683 automaton_t automaton
;
684 /* The following field value is the first arc output from given
687 unsigned int num_out_arcs
;
688 /* The following field is used to form NDFA. */
689 char it_was_placed_in_stack_for_NDFA_forming
;
690 /* The following field is used to form DFA. */
691 char it_was_placed_in_stack_for_DFA_forming
;
692 /* The following field is used to transform NDFA to DFA and DFA
693 minimization. The field value is not NULL if the state is a
694 compound state. In this case the value of field `unit_sets_list'
695 is NULL. All states in the list are in the hash table. The list
696 is formed through field `next_sorted_alt_state'. We should
697 support only one level of nesting state. */
698 alt_state_t component_states
;
699 /* The following field is used for passing graph of states. */
701 /* The list of states belonging to one equivalence class is formed
702 with the aid of the following field. */
703 state_t next_equiv_class_state
;
704 /* The two following fields are used during minimization of a finite
706 int equiv_class_num_1
, equiv_class_num_2
;
707 /* The following field is used during minimization of a finite state
708 automaton. The field value is state corresponding to equivalence
709 class to which given state belongs. */
710 state_t equiv_class_state
;
711 unsigned int *presence_signature
;
712 /* The following field value is the order number of given state.
713 The states in final DFA is enumerated with the aid of the
716 /* This member is used for passing states for searching minimal
719 /* The following member is used to evaluate min issue delay of insn
721 int min_insn_issue_delay
;
727 /* The following field refers for the state into which given arc
730 /* The following field describes that the insn issue (with cycle
731 advancing for special insn `cycle advancing' and without cycle
732 advancing for others) makes transition from given state to
733 another given state. */
735 /* The following field value is the next arc output from the same
738 /* List of arcs marked given insn is formed with the following
739 field. The field is used in transformation NDFA -> DFA. */
740 arc_t next_arc_marked_by_insn
;
743 /* The following node type describes a deterministic alternative in
744 non-deterministic state which characterizes cpu unit reservations
745 of automaton insn or which is part of NDFA. */
748 /* The following field is a deterministic state which characterizes
749 unit reservations of the instruction. */
751 /* The following field refers to the next state which characterizes
752 unit reservations of the instruction. */
753 alt_state_t next_alt_state
;
754 /* The following field refers to the next state in sorted list. */
755 alt_state_t next_sorted_alt_state
;
758 /* The following node type describes insn of automaton. They are
759 labels of FA arcs. */
762 /* The following field value is the corresponding insn declaration
764 struct insn_reserv_decl
*insn_reserv_decl
;
765 /* The following field value is the next insn declaration for an
768 /* The following field is states which characterize automaton unit
769 reservations of the instruction. The value can be NULL only if it
770 is special insn `cycle advancing'. */
771 alt_state_t alt_states
;
772 /* The following field is sorted list of states which characterize
773 automaton unit reservations of the instruction. The value can be
774 NULL only if it is special insn `cycle advancing'. */
775 alt_state_t sorted_alt_states
;
776 /* The following field refers the next automaton insn with
777 the same reservations. */
778 ainsn_t next_same_reservs_insn
;
779 /* The following field is flag of the first automaton insn with the
780 same reservations in the declaration list. Only arcs marked such
781 insn is present in the automaton. This significantly decreases
782 memory requirements especially when several automata are
784 char first_insn_with_same_reservs
;
785 /* The following member has nonzero value if there is arc from state of
786 the automaton marked by the ainsn. */
788 /* Cyclic list of insns of an equivalence class is formed with the
789 aid of the following field. */
790 ainsn_t next_equiv_class_insn
;
791 /* The following field value is nonzero if the insn declaration is
792 the first insn declaration with given equivalence number. */
793 char first_ainsn_with_given_equivalence_num
;
794 /* The following field is number of class of equivalence of insns.
795 It is necessary because many insns may be equivalent with the
796 point of view of pipeline hazards. */
797 int insn_equiv_class_num
;
798 /* The following member value is TRUE if there is an arc in the
799 automaton marked by the insn into another state. In other
800 words, the insn can change the state of the automaton. */
804 /* The following describes an automaton for PHR. */
807 /* The following field value is the list of insn declarations for
810 /* Pointers to the ainsns corresponding to the special reservations. */
811 ainsn_t advance_ainsn
, collapse_ainsn
;
813 /* The following field value is the corresponding automaton
814 declaration. This field is not NULL only if the automatic
815 partition on automata is not used. */
816 struct automaton_decl
*corresponding_automaton_decl
;
817 /* The following field value is the next automaton. */
818 automaton_t next_automaton
;
819 /* The following field is start state of FA. There are not unit
820 reservations in the state. */
822 /* The following field value is number of equivalence classes of
823 insns (see field `insn_equiv_class_num' in
824 `insn_reserv_decl'). */
825 int insn_equiv_classes_num
;
826 /* The following field value is number of states of final DFA. */
827 int achieved_states_num
;
828 /* The following field value is the order number (0, 1, ...) of
830 int automaton_order_num
;
831 /* The following fields contain statistics information about
832 building automaton. */
833 int NDFA_states_num
, DFA_states_num
;
834 /* The following field value is defined only if minimization of DFA
836 int minimal_DFA_states_num
;
837 int NDFA_arcs_num
, DFA_arcs_num
;
838 /* The following field value is defined only if minimization of DFA
840 int minimal_DFA_arcs_num
;
841 /* The following member refers for two table state x ainsn -> int.
842 ??? Above sentence is incomprehensible. */
843 state_ainsn_table_t trans_table
;
844 /* The following member value is maximal value of min issue delay
845 for insns of the automaton. */
847 /* Usually min issue delay is small and we can place several (2, 4,
848 8) elements in one vector element. So the compression factor can
849 be 1 (no compression), 2, 4, 8. */
850 int min_issue_delay_table_compression_factor
;
851 /* Total number of locked states in this automaton. */
855 /* The following is the element of the list of automata. */
856 struct automata_list_el
858 /* The automaton itself. */
859 automaton_t automaton
;
860 /* The next automata set element. */
861 automata_list_el_t next_automata_list_el
;
864 /* The following structure describes a table state X ainsn -> int(>= 0). */
865 struct state_ainsn_table
867 /* Automaton to which given table belongs. */
868 automaton_t automaton
;
869 /* The following tree vectors for comb vector implementation of the
871 vla_hwint_t comb_vect
;
872 vla_hwint_t check_vect
;
873 vla_hwint_t base_vect
;
874 /* This is simple implementation of the table. */
875 vla_hwint_t full_vect
;
876 /* Minimal and maximal values of the previous vectors. */
877 int min_comb_vect_el_value
, max_comb_vect_el_value
;
878 int min_base_vect_el_value
, max_base_vect_el_value
;
881 /* Macros to access members of unions. Use only them for access to
882 union members of declarations and regexps. */
884 #if defined ENABLE_CHECKING && (GCC_VERSION >= 2007)
886 #define DECL_UNIT(d) __extension__ \
887 (({ __typeof (d) const _decl = (d); \
888 if (_decl->mode != dm_unit) \
889 decl_mode_check_failed (_decl->mode, "dm_unit", \
890 __FILE__, __LINE__, __FUNCTION__); \
891 &(_decl)->decl.unit; }))
893 #define DECL_BYPASS(d) __extension__ \
894 (({ __typeof (d) const _decl = (d); \
895 if (_decl->mode != dm_bypass) \
896 decl_mode_check_failed (_decl->mode, "dm_bypass", \
897 __FILE__, __LINE__, __FUNCTION__); \
898 &(_decl)->decl.bypass; }))
900 #define DECL_AUTOMATON(d) __extension__ \
901 (({ __typeof (d) const _decl = (d); \
902 if (_decl->mode != dm_automaton) \
903 decl_mode_check_failed (_decl->mode, "dm_automaton", \
904 __FILE__, __LINE__, __FUNCTION__); \
905 &(_decl)->decl.automaton; }))
907 #define DECL_EXCL(d) __extension__ \
908 (({ __typeof (d) const _decl = (d); \
909 if (_decl->mode != dm_excl) \
910 decl_mode_check_failed (_decl->mode, "dm_excl", \
911 __FILE__, __LINE__, __FUNCTION__); \
912 &(_decl)->decl.excl; }))
914 #define DECL_PRESENCE(d) __extension__ \
915 (({ __typeof (d) const _decl = (d); \
916 if (_decl->mode != dm_presence) \
917 decl_mode_check_failed (_decl->mode, "dm_presence", \
918 __FILE__, __LINE__, __FUNCTION__); \
919 &(_decl)->decl.presence; }))
921 #define DECL_ABSENCE(d) __extension__ \
922 (({ __typeof (d) const _decl = (d); \
923 if (_decl->mode != dm_absence) \
924 decl_mode_check_failed (_decl->mode, "dm_absence", \
925 __FILE__, __LINE__, __FUNCTION__); \
926 &(_decl)->decl.absence; }))
928 #define DECL_RESERV(d) __extension__ \
929 (({ __typeof (d) const _decl = (d); \
930 if (_decl->mode != dm_reserv) \
931 decl_mode_check_failed (_decl->mode, "dm_reserv", \
932 __FILE__, __LINE__, __FUNCTION__); \
933 &(_decl)->decl.reserv; }))
935 #define DECL_INSN_RESERV(d) __extension__ \
936 (({ __typeof (d) const _decl = (d); \
937 if (_decl->mode != dm_insn_reserv) \
938 decl_mode_check_failed (_decl->mode, "dm_insn_reserv", \
939 __FILE__, __LINE__, __FUNCTION__); \
940 &(_decl)->decl.insn_reserv; }))
942 static const char *decl_name (enum decl_mode
);
943 static void decl_mode_check_failed (enum decl_mode
, const char *,
944 const char *, int, const char *)
947 /* Return string representation of declaration mode MODE. */
949 decl_name (enum decl_mode mode
)
951 static char str
[100];
955 else if (mode
== dm_bypass
)
957 else if (mode
== dm_automaton
)
958 return "dm_automaton";
959 else if (mode
== dm_excl
)
961 else if (mode
== dm_presence
)
962 return "dm_presence";
963 else if (mode
== dm_absence
)
965 else if (mode
== dm_reserv
)
967 else if (mode
== dm_insn_reserv
)
968 return "dm_insn_reserv";
970 sprintf (str
, "unknown (%d)", (int) mode
);
974 /* The function prints message about unexpected declaration and finish
977 decl_mode_check_failed (enum decl_mode mode
, const char *expected_mode_str
,
978 const char *file
, int line
, const char *func
)
982 "\n%s: %d: error in %s: DECL check: expected decl %s, have %s\n",
983 file
, line
, func
, expected_mode_str
, decl_name (mode
));
988 #define REGEXP_UNIT(r) __extension__ \
989 (({ struct regexp *const _regexp = (r); \
990 if (_regexp->mode != rm_unit) \
991 regexp_mode_check_failed (_regexp->mode, "rm_unit", \
992 __FILE__, __LINE__, __FUNCTION__); \
993 &(_regexp)->regexp.unit; }))
995 #define REGEXP_RESERV(r) __extension__ \
996 (({ struct regexp *const _regexp = (r); \
997 if (_regexp->mode != rm_reserv) \
998 regexp_mode_check_failed (_regexp->mode, "rm_reserv", \
999 __FILE__, __LINE__, __FUNCTION__); \
1000 &(_regexp)->regexp.reserv; }))
1002 #define REGEXP_SEQUENCE(r) __extension__ \
1003 (({ struct regexp *const _regexp = (r); \
1004 if (_regexp->mode != rm_sequence) \
1005 regexp_mode_check_failed (_regexp->mode, "rm_sequence", \
1006 __FILE__, __LINE__, __FUNCTION__); \
1007 &(_regexp)->regexp.sequence; }))
1009 #define REGEXP_REPEAT(r) __extension__ \
1010 (({ struct regexp *const _regexp = (r); \
1011 if (_regexp->mode != rm_repeat) \
1012 regexp_mode_check_failed (_regexp->mode, "rm_repeat", \
1013 __FILE__, __LINE__, __FUNCTION__); \
1014 &(_regexp)->regexp.repeat; }))
1016 #define REGEXP_ALLOF(r) __extension__ \
1017 (({ struct regexp *const _regexp = (r); \
1018 if (_regexp->mode != rm_allof) \
1019 regexp_mode_check_failed (_regexp->mode, "rm_allof", \
1020 __FILE__, __LINE__, __FUNCTION__); \
1021 &(_regexp)->regexp.allof; }))
1023 #define REGEXP_ONEOF(r) __extension__ \
1024 (({ struct regexp *const _regexp = (r); \
1025 if (_regexp->mode != rm_oneof) \
1026 regexp_mode_check_failed (_regexp->mode, "rm_oneof", \
1027 __FILE__, __LINE__, __FUNCTION__); \
1028 &(_regexp)->regexp.oneof; }))
1030 static const char *regexp_name (enum regexp_mode
);
1031 static void regexp_mode_check_failed (enum regexp_mode
, const char *,
1033 const char *) ATTRIBUTE_NORETURN
;
1036 /* Return string representation of regexp mode MODE. */
1038 regexp_name (enum regexp_mode mode
)
1047 return "rm_nothing";
1049 return "rm_sequence";
1061 /* The function prints message about unexpected regexp and finish the
1064 regexp_mode_check_failed (enum regexp_mode mode
,
1065 const char *expected_mode_str
,
1066 const char *file
, int line
, const char *func
)
1070 "\n%s: %d: error in %s: REGEXP check: expected decl %s, have %s\n",
1071 file
, line
, func
, expected_mode_str
, regexp_name (mode
));
1075 #else /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */
1077 #define DECL_UNIT(d) (&(d)->decl.unit)
1078 #define DECL_BYPASS(d) (&(d)->decl.bypass)
1079 #define DECL_AUTOMATON(d) (&(d)->decl.automaton)
1080 #define DECL_EXCL(d) (&(d)->decl.excl)
1081 #define DECL_PRESENCE(d) (&(d)->decl.presence)
1082 #define DECL_ABSENCE(d) (&(d)->decl.absence)
1083 #define DECL_RESERV(d) (&(d)->decl.reserv)
1084 #define DECL_INSN_RESERV(d) (&(d)->decl.insn_reserv)
1086 #define REGEXP_UNIT(r) (&(r)->regexp.unit)
1087 #define REGEXP_RESERV(r) (&(r)->regexp.reserv)
1088 #define REGEXP_SEQUENCE(r) (&(r)->regexp.sequence)
1089 #define REGEXP_REPEAT(r) (&(r)->regexp.repeat)
1090 #define REGEXP_ALLOF(r) (&(r)->regexp.allof)
1091 #define REGEXP_ONEOF(r) (&(r)->regexp.oneof)
1093 #endif /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */
1095 #define XCREATENODE(T) ((T *) create_node (sizeof (T)))
1096 #define XCREATENODEVEC(T, N) ((T *) create_node (sizeof (T) * (N)))
1097 #define XCREATENODEVAR(T, S) ((T *) create_node ((S)))
1099 #define XCOPYNODE(T, P) ((T *) copy_node ((P), sizeof (T)))
1100 #define XCOPYNODEVEC(T, P, N) ((T *) copy_node ((P), sizeof (T) * (N)))
1101 #define XCOPYNODEVAR(T, P, S) ((T *) copy_node ((P), (S)))
1103 /* Create IR structure (node). */
1105 create_node (size_t size
)
1109 obstack_blank (&irp
, size
);
1110 result
= obstack_base (&irp
);
1111 obstack_finish (&irp
);
1112 /* Default values of members are NULL and zero. */
1113 memset (result
, 0, size
);
1117 /* Copy IR structure (node). */
1119 copy_node (const void *from
, size_t size
)
1121 void *const result
= create_node (size
);
1122 memcpy (result
, from
, size
);
1126 /* The function checks that NAME does not contain quotes (`"'). */
1128 check_name (const char * name
, pos_t pos ATTRIBUTE_UNUSED
)
1132 for (str
= name
; *str
!= '\0'; str
++)
1134 error ("Name `%s' contains quotes", name
);
1138 /* Pointers to all declarations during IR generation are stored in the
1140 static vec
<decl_t
> decls
;
1142 /* Given a pointer to a (char *) and a separator, return an alloc'ed
1143 string containing the next separated element, taking parentheses
1144 into account if PAR_FLAG has nonzero value. Advance the pointer to
1145 after the string scanned, or the end-of-string. Return NULL if at
1148 next_sep_el (const char **pstr
, int sep
, int par_flag
)
1155 /* Remove leading whitespaces. */
1156 while (ISSPACE ((int) **pstr
))
1163 for (pars_num
= 0, p
= *pstr
; *p
!= '\0'; p
++)
1165 if (par_flag
&& *p
== '(')
1167 else if (par_flag
&& *p
== ')')
1169 else if (pars_num
== 0 && *p
== sep
)
1171 if (pars_num
== 0 && ISSPACE ((int) *p
))
1175 for (; n_spaces
!= 0; n_spaces
--)
1176 obstack_1grow (&irp
, p
[-n_spaces
]);
1177 obstack_1grow (&irp
, *p
);
1180 obstack_1grow (&irp
, '\0');
1181 out_str
= obstack_base (&irp
);
1182 obstack_finish (&irp
);
1191 /* Given a string and a separator, return the number of separated
1192 elements in it, taking parentheses into account if PAR_FLAG has
1193 nonzero value. Return 0 for the null string, -1 if parentheses is
1196 n_sep_els (const char *s
, int sep
, int par_flag
)
1204 for (pars_num
= 0, n
= 1; *s
; s
++)
1205 if (par_flag
&& *s
== '(')
1207 else if (par_flag
&& *s
== ')')
1209 else if (pars_num
== 0 && *s
== sep
)
1212 return (pars_num
!= 0 ? -1 : n
);
1215 /* Given a string and a separator, return vector of strings which are
1216 elements in the string and number of elements through els_num.
1217 Take parentheses into account if PAREN_P has nonzero value. The
1218 function also inserts the end marker NULL at the end of vector.
1219 Return 0 for the null string, -1 if parentheses are not balanced. */
1221 get_str_vect (const char *str
, int *els_num
, int sep
, int paren_p
)
1228 *els_num
= n_sep_els (str
, sep
, paren_p
);
1231 obstack_blank (&irp
, sizeof (char *) * (*els_num
+ 1));
1232 vect
= (char **) obstack_base (&irp
);
1233 obstack_finish (&irp
);
1235 for (i
= 0; i
< *els_num
; i
++)
1236 vect
[i
] = next_sep_el (pstr
, sep
, paren_p
);
1237 trail
= next_sep_el (pstr
, sep
, paren_p
);
1238 gcc_assert (!trail
);
1243 /* Process a DEFINE_CPU_UNIT.
1245 This gives information about a unit contained in CPU. We fill a
1246 struct unit_decl with information used later by `expand_automata'. */
1248 gen_cpu_unit (rtx def
)
1251 char **str_cpu_units
;
1255 str_cpu_units
= get_str_vect (XSTR (def
, 0), &vect_length
, ',', FALSE
);
1256 if (str_cpu_units
== NULL
)
1257 fatal ("invalid string `%s' in define_cpu_unit", XSTR (def
, 0));
1258 for (i
= 0; i
< vect_length
; i
++)
1260 decl
= XCREATENODE (struct decl
);
1261 decl
->mode
= dm_unit
;
1263 DECL_UNIT (decl
)->name
= check_name (str_cpu_units
[i
], decl
->pos
);
1264 DECL_UNIT (decl
)->automaton_name
= XSTR (def
, 1);
1265 DECL_UNIT (decl
)->query_p
= 0;
1266 DECL_UNIT (decl
)->min_occ_cycle_num
= -1;
1267 DECL_UNIT (decl
)->in_set_p
= 0;
1268 decls
.safe_push (decl
);
1272 /* Process a DEFINE_QUERY_CPU_UNIT.
1274 This gives information about a unit contained in CPU. We fill a
1275 struct unit_decl with information used later by `expand_automata'. */
1277 gen_query_cpu_unit (rtx def
)
1280 char **str_cpu_units
;
1284 str_cpu_units
= get_str_vect (XSTR (def
, 0), &vect_length
, ',',
1286 if (str_cpu_units
== NULL
)
1287 fatal ("invalid string `%s' in define_query_cpu_unit", XSTR (def
, 0));
1288 for (i
= 0; i
< vect_length
; i
++)
1290 decl
= XCREATENODE (struct decl
);
1291 decl
->mode
= dm_unit
;
1293 DECL_UNIT (decl
)->name
= check_name (str_cpu_units
[i
], decl
->pos
);
1294 DECL_UNIT (decl
)->automaton_name
= XSTR (def
, 1);
1295 DECL_UNIT (decl
)->query_p
= 1;
1296 decls
.safe_push (decl
);
1300 /* Process a DEFINE_BYPASS.
1302 This gives information about a unit contained in the CPU. We fill
1303 in a struct bypass_decl with information used later by
1304 `expand_automata'. */
1306 gen_bypass (rtx def
)
1309 char **out_patterns
;
1315 out_patterns
= get_str_vect (XSTR (def
, 1), &out_length
, ',', FALSE
);
1316 if (out_patterns
== NULL
)
1317 fatal ("invalid string `%s' in define_bypass", XSTR (def
, 1));
1318 in_patterns
= get_str_vect (XSTR (def
, 2), &in_length
, ',', FALSE
);
1319 if (in_patterns
== NULL
)
1320 fatal ("invalid string `%s' in define_bypass", XSTR (def
, 2));
1321 for (i
= 0; i
< out_length
; i
++)
1322 for (j
= 0; j
< in_length
; j
++)
1324 decl
= XCREATENODE (struct decl
);
1325 decl
->mode
= dm_bypass
;
1327 DECL_BYPASS (decl
)->latency
= XINT (def
, 0);
1328 DECL_BYPASS (decl
)->out_pattern
= out_patterns
[i
];
1329 DECL_BYPASS (decl
)->in_pattern
= in_patterns
[j
];
1330 DECL_BYPASS (decl
)->bypass_guard_name
= XSTR (def
, 3);
1331 decls
.safe_push (decl
);
1335 /* Process an EXCLUSION_SET.
1337 This gives information about a cpu unit conflicts. We fill a
1338 struct excl_rel_decl (excl) with information used later by
1339 `expand_automata'. */
1341 gen_excl_set (rtx def
)
1344 char **first_str_cpu_units
;
1345 char **second_str_cpu_units
;
1346 int first_vect_length
;
1351 = get_str_vect (XSTR (def
, 0), &first_vect_length
, ',', FALSE
);
1352 if (first_str_cpu_units
== NULL
)
1353 fatal ("invalid first string `%s' in exclusion_set", XSTR (def
, 0));
1354 second_str_cpu_units
= get_str_vect (XSTR (def
, 1), &length
, ',',
1356 if (second_str_cpu_units
== NULL
)
1357 fatal ("invalid second string `%s' in exclusion_set", XSTR (def
, 1));
1358 length
+= first_vect_length
;
1359 decl
= XCREATENODEVAR (struct decl
, sizeof (struct decl
) + (length
- 1) * sizeof (char *));
1360 decl
->mode
= dm_excl
;
1362 DECL_EXCL (decl
)->all_names_num
= length
;
1363 DECL_EXCL (decl
)->first_list_length
= first_vect_length
;
1364 for (i
= 0; i
< length
; i
++)
1365 if (i
< first_vect_length
)
1366 DECL_EXCL (decl
)->names
[i
] = first_str_cpu_units
[i
];
1368 DECL_EXCL (decl
)->names
[i
]
1369 = second_str_cpu_units
[i
- first_vect_length
];
1370 decls
.safe_push (decl
);
1373 /* Process a PRESENCE_SET, a FINAL_PRESENCE_SET, an ABSENCE_SET,
1374 FINAL_ABSENCE_SET (it is depended on PRESENCE_P and FINAL_P).
1376 This gives information about a cpu unit reservation requirements.
1377 We fill a struct unit_pattern_rel_decl with information used later
1378 by `expand_automata'. */
1380 gen_presence_absence_set (rtx def
, int presence_p
, int final_p
)
1383 char **str_cpu_units
;
1384 char **str_pattern_lists
;
1385 char ***str_patterns
;
1386 int cpu_units_length
;
1388 int patterns_length
;
1391 str_cpu_units
= get_str_vect (XSTR (def
, 0), &cpu_units_length
, ',',
1393 if (str_cpu_units
== NULL
)
1396 ? "invalid first string `%s' in final_presence_set"
1397 : "invalid first string `%s' in presence_set")
1399 ? "invalid first string `%s' in final_absence_set"
1400 : "invalid first string `%s' in absence_set")),
1402 str_pattern_lists
= get_str_vect (XSTR (def
, 1),
1403 &patterns_length
, ',', FALSE
);
1404 if (str_pattern_lists
== NULL
)
1407 ? "invalid second string `%s' in final_presence_set"
1408 : "invalid second string `%s' in presence_set")
1410 ? "invalid second string `%s' in final_absence_set"
1411 : "invalid second string `%s' in absence_set")), XSTR (def
, 1));
1412 str_patterns
= XOBNEWVEC (&irp
, char **, patterns_length
);
1413 for (i
= 0; i
< patterns_length
; i
++)
1415 str_patterns
[i
] = get_str_vect (str_pattern_lists
[i
],
1416 &length
, ' ', FALSE
);
1417 gcc_assert (str_patterns
[i
]);
1419 decl
= XCREATENODE (struct decl
);
1423 decl
->mode
= dm_presence
;
1424 DECL_PRESENCE (decl
)->names_num
= cpu_units_length
;
1425 DECL_PRESENCE (decl
)->names
= str_cpu_units
;
1426 DECL_PRESENCE (decl
)->patterns
= str_patterns
;
1427 DECL_PRESENCE (decl
)->patterns_num
= patterns_length
;
1428 DECL_PRESENCE (decl
)->final_p
= final_p
;
1432 decl
->mode
= dm_absence
;
1433 DECL_ABSENCE (decl
)->names_num
= cpu_units_length
;
1434 DECL_ABSENCE (decl
)->names
= str_cpu_units
;
1435 DECL_ABSENCE (decl
)->patterns
= str_patterns
;
1436 DECL_ABSENCE (decl
)->patterns_num
= patterns_length
;
1437 DECL_ABSENCE (decl
)->final_p
= final_p
;
1439 decls
.safe_push (decl
);
1442 /* Process a PRESENCE_SET.
1444 This gives information about a cpu unit reservation requirements.
1445 We fill a struct unit_pattern_rel_decl (presence) with information
1446 used later by `expand_automata'. */
1448 gen_presence_set (rtx def
)
1450 gen_presence_absence_set (def
, TRUE
, FALSE
);
1453 /* Process a FINAL_PRESENCE_SET.
1455 This gives information about a cpu unit reservation requirements.
1456 We fill a struct unit_pattern_rel_decl (presence) with information
1457 used later by `expand_automata'. */
1459 gen_final_presence_set (rtx def
)
1461 gen_presence_absence_set (def
, TRUE
, TRUE
);
1464 /* Process an ABSENCE_SET.
1466 This gives information about a cpu unit reservation requirements.
1467 We fill a struct unit_pattern_rel_decl (absence) with information
1468 used later by `expand_automata'. */
1470 gen_absence_set (rtx def
)
1472 gen_presence_absence_set (def
, FALSE
, FALSE
);
1475 /* Process a FINAL_ABSENCE_SET.
1477 This gives information about a cpu unit reservation requirements.
1478 We fill a struct unit_pattern_rel_decl (absence) with information
1479 used later by `expand_automata'. */
1481 gen_final_absence_set (rtx def
)
1483 gen_presence_absence_set (def
, FALSE
, TRUE
);
1486 /* Process a DEFINE_AUTOMATON.
1488 This gives information about a finite state automaton used for
1489 recognizing pipeline hazards. We fill a struct automaton_decl
1490 with information used later by `expand_automata'. */
1492 gen_automaton (rtx def
)
1495 char **str_automata
;
1499 str_automata
= get_str_vect (XSTR (def
, 0), &vect_length
, ',', FALSE
);
1500 if (str_automata
== NULL
)
1501 fatal ("invalid string `%s' in define_automaton", XSTR (def
, 0));
1502 for (i
= 0; i
< vect_length
; i
++)
1504 decl
= XCREATENODE (struct decl
);
1505 decl
->mode
= dm_automaton
;
1507 DECL_AUTOMATON (decl
)->name
= check_name (str_automata
[i
], decl
->pos
);
1508 decls
.safe_push (decl
);
1512 /* Process an AUTOMATA_OPTION.
1514 This gives information how to generate finite state automaton used
1515 for recognizing pipeline hazards. */
1517 gen_automata_option (rtx def
)
1519 if (strcmp (XSTR (def
, 0), NO_MINIMIZATION_OPTION
+ 1) == 0)
1520 no_minimization_flag
= 1;
1521 else if (strcmp (XSTR (def
, 0), TIME_OPTION
+ 1) == 0)
1523 else if (strcmp (XSTR (def
, 0), STATS_OPTION
+ 1) == 0)
1525 else if (strcmp (XSTR (def
, 0), V_OPTION
+ 1) == 0)
1527 else if (strcmp (XSTR (def
, 0), W_OPTION
+ 1) == 0)
1529 else if (strcmp (XSTR (def
, 0), NDFA_OPTION
+ 1) == 0)
1531 else if (strcmp (XSTR (def
, 0), COLLAPSE_OPTION
+ 1) == 0)
1533 else if (strcmp (XSTR (def
, 0), NO_COMB_OPTION
+ 1) == 0)
1535 else if (strcmp (XSTR (def
, 0), PROGRESS_OPTION
+ 1) == 0)
1538 fatal ("invalid option `%s' in automata_option", XSTR (def
, 0));
1541 /* Name in reservation to denote absence reservation. */
1542 #define NOTHING_NAME "nothing"
1544 /* The following string contains original reservation string being
1546 static const char *reserv_str
;
1548 /* Parse an element in STR. */
1550 gen_regexp_el (const char *str
)
1559 if (str
[len
- 1] != ')')
1560 fatal ("garbage after ) in reservation `%s'", reserv_str
);
1561 dstr
= XALLOCAVAR (char, len
- 1);
1562 memcpy (dstr
, str
+ 1, len
- 2);
1563 dstr
[len
-2] = '\0';
1564 regexp
= gen_regexp_sequence (dstr
);
1566 else if (strcmp (str
, NOTHING_NAME
) == 0)
1568 regexp
= XCREATENODE (struct regexp
);
1569 regexp
->mode
= rm_nothing
;
1573 regexp
= XCREATENODE (struct regexp
);
1574 regexp
->mode
= rm_unit
;
1575 REGEXP_UNIT (regexp
)->name
= str
;
1580 /* Parse construction `repeat' in STR. */
1582 gen_regexp_repeat (const char *str
)
1590 repeat_vect
= get_str_vect (str
, &els_num
, '*', TRUE
);
1591 if (repeat_vect
== NULL
)
1592 fatal ("invalid `%s' in reservation `%s'", str
, reserv_str
);
1595 regexp
= gen_regexp_el (repeat_vect
[0]);
1596 for (i
= 1; i
< els_num
; i
++)
1598 repeat
= XCREATENODE (struct regexp
);
1599 repeat
->mode
= rm_repeat
;
1600 REGEXP_REPEAT (repeat
)->regexp
= regexp
;
1601 REGEXP_REPEAT (repeat
)->repeat_num
= atoi (repeat_vect
[i
]);
1602 if (REGEXP_REPEAT (repeat
)->repeat_num
<= 1)
1603 fatal ("repetition `%s' <= 1 in reservation `%s'",
1610 return gen_regexp_el (repeat_vect
[0]);
1613 /* Parse reservation STR which possibly contains separator '+'. */
1615 gen_regexp_allof (const char *str
)
1622 allof_vect
= get_str_vect (str
, &els_num
, '+', TRUE
);
1623 if (allof_vect
== NULL
)
1624 fatal ("invalid `%s' in reservation `%s'", str
, reserv_str
);
1627 allof
= XCREATENODEVAR (struct regexp
, sizeof (struct regexp
)
1628 + sizeof (regexp_t
) * (els_num
- 1));
1629 allof
->mode
= rm_allof
;
1630 REGEXP_ALLOF (allof
)->regexps_num
= els_num
;
1631 for (i
= 0; i
< els_num
; i
++)
1632 REGEXP_ALLOF (allof
)->regexps
[i
] = gen_regexp_repeat (allof_vect
[i
]);
1636 return gen_regexp_repeat (allof_vect
[0]);
1639 /* Parse reservation STR which possibly contains separator '|'. */
1641 gen_regexp_oneof (const char *str
)
1648 oneof_vect
= get_str_vect (str
, &els_num
, '|', TRUE
);
1649 if (oneof_vect
== NULL
)
1650 fatal ("invalid `%s' in reservation `%s'", str
, reserv_str
);
1653 oneof
= XCREATENODEVAR (struct regexp
, sizeof (struct regexp
)
1654 + sizeof (regexp_t
) * (els_num
- 1));
1655 oneof
->mode
= rm_oneof
;
1656 REGEXP_ONEOF (oneof
)->regexps_num
= els_num
;
1657 for (i
= 0; i
< els_num
; i
++)
1658 REGEXP_ONEOF (oneof
)->regexps
[i
] = gen_regexp_allof (oneof_vect
[i
]);
1662 return gen_regexp_allof (oneof_vect
[0]);
1665 /* Parse reservation STR which possibly contains separator ','. */
1667 gen_regexp_sequence (const char *str
)
1670 char **sequence_vect
;
1674 sequence_vect
= get_str_vect (str
, &els_num
, ',', TRUE
);
1676 fatal ("unbalanced parentheses in reservation `%s'", str
);
1677 if (sequence_vect
== NULL
)
1678 fatal ("invalid reservation `%s'", str
);
1681 sequence
= XCREATENODEVAR (struct regexp
, sizeof (struct regexp
)
1682 + sizeof (regexp_t
) * (els_num
- 1));
1683 sequence
->mode
= rm_sequence
;
1684 REGEXP_SEQUENCE (sequence
)->regexps_num
= els_num
;
1685 for (i
= 0; i
< els_num
; i
++)
1686 REGEXP_SEQUENCE (sequence
)->regexps
[i
]
1687 = gen_regexp_oneof (sequence_vect
[i
]);
1691 return gen_regexp_oneof (sequence_vect
[0]);
1694 /* Parse construction reservation STR. */
1696 gen_regexp (const char *str
)
1699 return gen_regexp_sequence (str
);
1702 /* Process a DEFINE_RESERVATION.
1704 This gives information about a reservation of cpu units. We fill
1705 in a struct reserv_decl with information used later by
1706 `expand_automata'. */
1708 gen_reserv (rtx def
)
1712 decl
= XCREATENODE (struct decl
);
1713 decl
->mode
= dm_reserv
;
1715 DECL_RESERV (decl
)->name
= check_name (XSTR (def
, 0), decl
->pos
);
1716 DECL_RESERV (decl
)->regexp
= gen_regexp (XSTR (def
, 1));
1717 decls
.safe_push (decl
);
1720 /* Process a DEFINE_INSN_RESERVATION.
1722 This gives information about the reservation of cpu units by an
1723 insn. We fill a struct insn_reserv_decl with information used
1724 later by `expand_automata'. */
1726 gen_insn_reserv (rtx def
)
1730 decl
= XCREATENODE (struct decl
);
1731 decl
->mode
= dm_insn_reserv
;
1733 DECL_INSN_RESERV (decl
)->name
1734 = check_name (XSTR (def
, 0), decl
->pos
);
1735 DECL_INSN_RESERV (decl
)->default_latency
= XINT (def
, 1);
1736 DECL_INSN_RESERV (decl
)->condexp
= XEXP (def
, 2);
1737 DECL_INSN_RESERV (decl
)->regexp
= gen_regexp (XSTR (def
, 3));
1738 decls
.safe_push (decl
);
1743 /* The function evaluates hash value (0..UINT_MAX) of string. */
1745 string_hash (const char *string
)
1749 for (result
= i
= 0;*string
++ != '\0'; i
++)
1750 result
+= ((unsigned char) *string
<< (i
% CHAR_BIT
));
1756 /* This page contains abstract data `table of automaton declarations'.
1757 Elements of the table is nodes representing automaton declarations.
1758 Key of the table elements is name of given automaton. Remember
1759 that automaton names have own space. */
1761 /* The function evaluates hash value of an automaton declaration. The
1762 function is used by abstract data `hashtab'. The function returns
1763 hash value (0..UINT_MAX) of given automaton declaration. */
1765 automaton_decl_hash (const void *automaton_decl
)
1767 const_decl_t
const decl
= (const_decl_t
) automaton_decl
;
1769 gcc_assert (decl
->mode
!= dm_automaton
1770 || DECL_AUTOMATON (decl
)->name
);
1771 return string_hash (DECL_AUTOMATON (decl
)->name
);
1774 /* The function tests automaton declarations on equality of their
1775 keys. The function is used by abstract data `hashtab'. The
1776 function returns 1 if the declarations have the same key, 0
1779 automaton_decl_eq_p (const void* automaton_decl_1
,
1780 const void* automaton_decl_2
)
1782 const_decl_t
const decl1
= (const_decl_t
) automaton_decl_1
;
1783 const_decl_t
const decl2
= (const_decl_t
) automaton_decl_2
;
1785 gcc_assert (decl1
->mode
== dm_automaton
1786 && DECL_AUTOMATON (decl1
)->name
1787 && decl2
->mode
== dm_automaton
1788 && DECL_AUTOMATON (decl2
)->name
);
1789 return strcmp (DECL_AUTOMATON (decl1
)->name
,
1790 DECL_AUTOMATON (decl2
)->name
) == 0;
1793 /* The automaton declaration table itself is represented by the
1794 following variable. */
1795 static htab_t automaton_decl_table
;
1797 /* The function inserts automaton declaration into the table. The
1798 function does nothing if an automaton declaration with the same key
1799 exists already in the table. The function returns automaton
1800 declaration node in the table with the same key as given automaton
1801 declaration node. */
1803 insert_automaton_decl (decl_t automaton_decl
)
1807 entry_ptr
= htab_find_slot (automaton_decl_table
, automaton_decl
, INSERT
);
1808 if (*entry_ptr
== NULL
)
1809 *entry_ptr
= (void *) automaton_decl
;
1810 return (decl_t
) *entry_ptr
;
1813 /* The following variable value is node representing automaton
1814 declaration. The node used for searching automaton declaration
1816 static struct decl work_automaton_decl
;
1818 /* The function searches for automaton declaration in the table with
1819 the same key as node representing name of the automaton
1820 declaration. The function returns node found in the table, NULL if
1821 such node does not exist in the table. */
1823 find_automaton_decl (const char *name
)
1827 work_automaton_decl
.mode
= dm_automaton
;
1828 DECL_AUTOMATON (&work_automaton_decl
)->name
= name
;
1829 entry
= htab_find (automaton_decl_table
, &work_automaton_decl
);
1830 return (decl_t
) entry
;
1833 /* The function creates empty automaton declaration table and node
1834 representing automaton declaration and used for searching automaton
1835 declaration with given name. The function must be called only once
1836 before any work with the automaton declaration table. */
1838 initiate_automaton_decl_table (void)
1840 work_automaton_decl
.mode
= dm_automaton
;
1841 automaton_decl_table
= htab_create (10, automaton_decl_hash
,
1842 automaton_decl_eq_p
, (htab_del
) 0);
1845 /* The function deletes the automaton declaration table. Only call of
1846 function `initiate_automaton_decl_table' is possible immediately
1847 after this function call. */
1849 finish_automaton_decl_table (void)
1851 htab_delete (automaton_decl_table
);
1856 /* This page contains abstract data `table of insn declarations'.
1857 Elements of the table is nodes representing insn declarations. Key
1858 of the table elements is name of given insn (in corresponding
1859 define_insn_reservation). Remember that insn names have own
1862 /* The function evaluates hash value of an insn declaration. The
1863 function is used by abstract data `hashtab'. The function returns
1864 hash value (0..UINT_MAX) of given insn declaration. */
1866 insn_decl_hash (const void *insn_decl
)
1868 const_decl_t
const decl
= (const_decl_t
) insn_decl
;
1870 gcc_assert (decl
->mode
== dm_insn_reserv
1871 && DECL_INSN_RESERV (decl
)->name
);
1872 return string_hash (DECL_INSN_RESERV (decl
)->name
);
1875 /* The function tests insn declarations on equality of their keys.
1876 The function is used by abstract data `hashtab'. The function
1877 returns 1 if declarations have the same key, 0 otherwise. */
1879 insn_decl_eq_p (const void *insn_decl_1
, const void *insn_decl_2
)
1881 const_decl_t
const decl1
= (const_decl_t
) insn_decl_1
;
1882 const_decl_t
const decl2
= (const_decl_t
) insn_decl_2
;
1884 gcc_assert (decl1
->mode
== dm_insn_reserv
1885 && DECL_INSN_RESERV (decl1
)->name
1886 && decl2
->mode
== dm_insn_reserv
1887 && DECL_INSN_RESERV (decl2
)->name
);
1888 return strcmp (DECL_INSN_RESERV (decl1
)->name
,
1889 DECL_INSN_RESERV (decl2
)->name
) == 0;
1892 /* The insn declaration table itself is represented by the following
1893 variable. The table does not contain insn reservation
1895 static htab_t insn_decl_table
;
1897 /* The function inserts insn declaration into the table. The function
1898 does nothing if an insn declaration with the same key exists
1899 already in the table. The function returns insn declaration node
1900 in the table with the same key as given insn declaration node. */
1902 insert_insn_decl (decl_t insn_decl
)
1906 entry_ptr
= htab_find_slot (insn_decl_table
, insn_decl
, INSERT
);
1907 if (*entry_ptr
== NULL
)
1908 *entry_ptr
= (void *) insn_decl
;
1909 return (decl_t
) *entry_ptr
;
1912 /* The following variable value is node representing insn reservation
1913 declaration. The node used for searching insn reservation
1914 declaration with given name. */
1915 static struct decl work_insn_decl
;
1917 /* The function searches for insn reservation declaration in the table
1918 with the same key as node representing name of the insn reservation
1919 declaration. The function returns node found in the table, NULL if
1920 such node does not exist in the table. */
1922 find_insn_decl (const char *name
)
1926 work_insn_decl
.mode
= dm_insn_reserv
;
1927 DECL_INSN_RESERV (&work_insn_decl
)->name
= name
;
1928 entry
= htab_find (insn_decl_table
, &work_insn_decl
);
1929 return (decl_t
) entry
;
1932 /* The function creates empty insn declaration table and node
1933 representing insn declaration and used for searching insn
1934 declaration with given name. The function must be called only once
1935 before any work with the insn declaration table. */
1937 initiate_insn_decl_table (void)
1939 work_insn_decl
.mode
= dm_insn_reserv
;
1940 insn_decl_table
= htab_create (10, insn_decl_hash
, insn_decl_eq_p
,
1944 /* The function deletes the insn declaration table. Only call of
1945 function `initiate_insn_decl_table' is possible immediately after
1946 this function call. */
1948 finish_insn_decl_table (void)
1950 htab_delete (insn_decl_table
);
1955 /* This page contains abstract data `table of declarations'. Elements
1956 of the table is nodes representing declarations (of units and
1957 reservations). Key of the table elements is names of given
1960 /* The function evaluates hash value of a declaration. The function
1961 is used by abstract data `hashtab'. The function returns hash
1962 value (0..UINT_MAX) of given declaration. */
1964 decl_hash (const void *decl
)
1966 const_decl_t
const d
= (const_decl_t
) decl
;
1968 gcc_assert ((d
->mode
== dm_unit
&& DECL_UNIT (d
)->name
)
1969 || (d
->mode
== dm_reserv
&& DECL_RESERV (d
)->name
));
1970 return string_hash (d
->mode
== dm_unit
1971 ? DECL_UNIT (d
)->name
: DECL_RESERV (d
)->name
);
1974 /* The function tests declarations on equality of their keys. The
1975 function is used by abstract data 'hashtab'. The function
1976 returns 1 if the declarations have the same key, 0 otherwise. */
1978 decl_eq_p (const void *decl_1
, const void *decl_2
)
1980 const_decl_t
const d1
= (const_decl_t
) decl_1
;
1981 const_decl_t
const d2
= (const_decl_t
) decl_2
;
1983 gcc_assert ((d1
->mode
== dm_unit
&& DECL_UNIT (d1
)->name
)
1984 || (d1
->mode
== dm_reserv
&& DECL_RESERV (d1
)->name
));
1985 gcc_assert ((d2
->mode
== dm_unit
&& DECL_UNIT (d2
)->name
)
1986 || (d2
->mode
== dm_reserv
&& DECL_RESERV (d2
)->name
));
1987 return strcmp ((d1
->mode
== dm_unit
1988 ? DECL_UNIT (d1
)->name
: DECL_RESERV (d1
)->name
),
1989 (d2
->mode
== dm_unit
1990 ? DECL_UNIT (d2
)->name
: DECL_RESERV (d2
)->name
)) == 0;
1993 /* The declaration table itself is represented by the following
1995 static htab_t decl_table
;
1997 /* The function inserts declaration into the table. The function does
1998 nothing if a declaration with the same key exists already in the
1999 table. The function returns declaration node in the table with the
2000 same key as given declaration node. */
2003 insert_decl (decl_t decl
)
2007 entry_ptr
= htab_find_slot (decl_table
, decl
, INSERT
);
2008 if (*entry_ptr
== NULL
)
2009 *entry_ptr
= (void *) decl
;
2010 return (decl_t
) *entry_ptr
;
2013 /* The following variable value is node representing declaration. The
2014 node used for searching declaration with given name. */
2015 static struct decl work_decl
;
2017 /* The function searches for declaration in the table with the same
2018 key as node representing name of the declaration. The function
2019 returns node found in the table, NULL if such node does not exist
2022 find_decl (const char *name
)
2026 work_decl
.mode
= dm_unit
;
2027 DECL_UNIT (&work_decl
)->name
= name
;
2028 entry
= htab_find (decl_table
, &work_decl
);
2029 return (decl_t
) entry
;
2032 /* The function creates empty declaration table and node representing
2033 declaration and used for searching declaration with given name.
2034 The function must be called only once before any work with the
2035 declaration table. */
2037 initiate_decl_table (void)
2039 work_decl
.mode
= dm_unit
;
2040 decl_table
= htab_create (10, decl_hash
, decl_eq_p
, (htab_del
) 0);
2043 /* The function deletes the declaration table. Only call of function
2044 `initiate_declaration_table' is possible immediately after this
2047 finish_decl_table (void)
2049 htab_delete (decl_table
);
2054 /* This page contains checker of pipeline hazard description. */
2056 /* Checking NAMES in an exclusion clause vector and returning formed
2057 unit_set_el_list. */
2058 static unit_set_el_t
2059 process_excls (char **names
, int num
, pos_t excl_pos ATTRIBUTE_UNUSED
)
2061 unit_set_el_t el_list
;
2062 unit_set_el_t last_el
;
2063 unit_set_el_t new_el
;
2064 decl_t decl_in_table
;
2069 for (i
= 0; i
< num
; i
++)
2071 decl_in_table
= find_decl (names
[i
]);
2072 if (decl_in_table
== NULL
)
2073 error ("unit `%s' in exclusion is not declared", names
[i
]);
2074 else if (decl_in_table
->mode
!= dm_unit
)
2075 error ("`%s' in exclusion is not unit", names
[i
]);
2078 new_el
= XCREATENODE (struct unit_set_el
);
2079 new_el
->unit_decl
= DECL_UNIT (decl_in_table
);
2080 new_el
->next_unit_set_el
= NULL
;
2081 if (last_el
== NULL
)
2082 el_list
= last_el
= new_el
;
2085 last_el
->next_unit_set_el
= new_el
;
2086 last_el
= last_el
->next_unit_set_el
;
2093 /* The function adds each element from SOURCE_LIST to the exclusion
2094 list of the each element from DEST_LIST. Checking situation "unit
2095 excludes itself". */
2097 add_excls (unit_set_el_t dest_list
, unit_set_el_t source_list
,
2098 pos_t excl_pos ATTRIBUTE_UNUSED
)
2102 unit_set_el_t curr_el
;
2103 unit_set_el_t prev_el
;
2106 for (dst
= dest_list
; dst
!= NULL
; dst
= dst
->next_unit_set_el
)
2107 for (src
= source_list
; src
!= NULL
; src
= src
->next_unit_set_el
)
2109 if (dst
->unit_decl
== src
->unit_decl
)
2111 error ("unit `%s' excludes itself", src
->unit_decl
->name
);
2114 if (dst
->unit_decl
->automaton_name
!= NULL
2115 && src
->unit_decl
->automaton_name
!= NULL
2116 && strcmp (dst
->unit_decl
->automaton_name
,
2117 src
->unit_decl
->automaton_name
) != 0)
2119 error ("units `%s' and `%s' in exclusion set belong to different automata",
2120 src
->unit_decl
->name
, dst
->unit_decl
->name
);
2123 for (curr_el
= dst
->unit_decl
->excl_list
, prev_el
= NULL
;
2125 prev_el
= curr_el
, curr_el
= curr_el
->next_unit_set_el
)
2126 if (curr_el
->unit_decl
== src
->unit_decl
)
2128 if (curr_el
== NULL
)
2130 /* Element not found - insert. */
2131 copy
= XCOPYNODE (struct unit_set_el
, src
);
2132 copy
->next_unit_set_el
= NULL
;
2133 if (prev_el
== NULL
)
2134 dst
->unit_decl
->excl_list
= copy
;
2136 prev_el
->next_unit_set_el
= copy
;
2141 /* Checking NAMES in presence/absence clause and returning the
2142 formed unit_set_el_list. The function is called only after
2143 processing all exclusion sets. */
2144 static unit_set_el_t
2145 process_presence_absence_names (char **names
, int num
,
2146 pos_t req_pos ATTRIBUTE_UNUSED
,
2147 int presence_p
, int final_p
)
2149 unit_set_el_t el_list
;
2150 unit_set_el_t last_el
;
2151 unit_set_el_t new_el
;
2152 decl_t decl_in_table
;
2157 for (i
= 0; i
< num
; i
++)
2159 decl_in_table
= find_decl (names
[i
]);
2160 if (decl_in_table
== NULL
)
2163 ? "unit `%s' in final presence set is not declared"
2164 : "unit `%s' in presence set is not declared")
2166 ? "unit `%s' in final absence set is not declared"
2167 : "unit `%s' in absence set is not declared")), names
[i
]);
2168 else if (decl_in_table
->mode
!= dm_unit
)
2171 ? "`%s' in final presence set is not unit"
2172 : "`%s' in presence set is not unit")
2174 ? "`%s' in final absence set is not unit"
2175 : "`%s' in absence set is not unit")), names
[i
]);
2178 new_el
= XCREATENODE (struct unit_set_el
);
2179 new_el
->unit_decl
= DECL_UNIT (decl_in_table
);
2180 new_el
->next_unit_set_el
= NULL
;
2181 if (last_el
== NULL
)
2182 el_list
= last_el
= new_el
;
2185 last_el
->next_unit_set_el
= new_el
;
2186 last_el
= last_el
->next_unit_set_el
;
2193 /* Checking NAMES in patterns of a presence/absence clause and
2194 returning the formed pattern_set_el_list. The function is called
2195 only after processing all exclusion sets. */
2196 static pattern_set_el_t
2197 process_presence_absence_patterns (char ***patterns
, int num
,
2198 pos_t req_pos ATTRIBUTE_UNUSED
,
2199 int presence_p
, int final_p
)
2201 pattern_set_el_t el_list
;
2202 pattern_set_el_t last_el
;
2203 pattern_set_el_t new_el
;
2204 decl_t decl_in_table
;
2209 for (i
= 0; i
< num
; i
++)
2211 for (j
= 0; patterns
[i
] [j
] != NULL
; j
++)
2213 new_el
= XCREATENODEVAR (struct pattern_set_el
,
2214 sizeof (struct pattern_set_el
)
2215 + sizeof (struct unit_decl
*) * j
);
2217 = (struct unit_decl
**) ((char *) new_el
2218 + sizeof (struct pattern_set_el
));
2219 new_el
->next_pattern_set_el
= NULL
;
2220 if (last_el
== NULL
)
2221 el_list
= last_el
= new_el
;
2224 last_el
->next_pattern_set_el
= new_el
;
2225 last_el
= last_el
->next_pattern_set_el
;
2227 new_el
->units_num
= 0;
2228 for (j
= 0; patterns
[i
] [j
] != NULL
; j
++)
2230 decl_in_table
= find_decl (patterns
[i
] [j
]);
2231 if (decl_in_table
== NULL
)
2234 ? "unit `%s' in final presence set is not declared"
2235 : "unit `%s' in presence set is not declared")
2237 ? "unit `%s' in final absence set is not declared"
2238 : "unit `%s' in absence set is not declared")),
2240 else if (decl_in_table
->mode
!= dm_unit
)
2243 ? "`%s' in final presence set is not unit"
2244 : "`%s' in presence set is not unit")
2246 ? "`%s' in final absence set is not unit"
2247 : "`%s' in absence set is not unit")),
2251 new_el
->unit_decls
[new_el
->units_num
]
2252 = DECL_UNIT (decl_in_table
);
2253 new_el
->units_num
++;
2260 /* The function adds each element from PATTERN_LIST to presence (if
2261 PRESENCE_P) or absence list of the each element from DEST_LIST.
2262 Checking situations "unit requires own absence", and "unit excludes
2263 and requires presence of ...", "unit requires absence and presence
2264 of ...", "units in (final) presence set belong to different
2265 automata", and "units in (final) absence set belong to different
2266 automata". Remember that we process absence sets only after all
2269 add_presence_absence (unit_set_el_t dest_list
,
2270 pattern_set_el_t pattern_list
,
2271 pos_t req_pos ATTRIBUTE_UNUSED
,
2272 int presence_p
, int final_p
)
2275 pattern_set_el_t pat
;
2276 struct unit_decl
*unit
;
2277 unit_set_el_t curr_excl_el
;
2278 pattern_set_el_t curr_pat_el
;
2279 pattern_set_el_t prev_el
;
2280 pattern_set_el_t copy
;
2284 for (dst
= dest_list
; dst
!= NULL
; dst
= dst
->next_unit_set_el
)
2285 for (pat
= pattern_list
; pat
!= NULL
; pat
= pat
->next_pattern_set_el
)
2287 for (i
= 0; i
< pat
->units_num
; i
++)
2289 unit
= pat
->unit_decls
[i
];
2290 if (dst
->unit_decl
== unit
&& pat
->units_num
== 1 && !presence_p
)
2292 error ("unit `%s' requires own absence", unit
->name
);
2295 if (dst
->unit_decl
->automaton_name
!= NULL
2296 && unit
->automaton_name
!= NULL
2297 && strcmp (dst
->unit_decl
->automaton_name
,
2298 unit
->automaton_name
) != 0)
2302 ? "units `%s' and `%s' in final presence set belong to different automata"
2303 : "units `%s' and `%s' in presence set belong to different automata")
2305 ? "units `%s' and `%s' in final absence set belong to different automata"
2306 : "units `%s' and `%s' in absence set belong to different automata")),
2307 unit
->name
, dst
->unit_decl
->name
);
2312 for (curr_excl_el
= dst
->unit_decl
->excl_list
;
2313 curr_excl_el
!= NULL
;
2314 curr_excl_el
= curr_excl_el
->next_unit_set_el
)
2316 if (unit
== curr_excl_el
->unit_decl
&& pat
->units_num
== 1)
2320 error ("unit `%s' excludes and requires presence of `%s'",
2321 dst
->unit_decl
->name
, unit
->name
);
2325 warning ("unit `%s' excludes and requires presence of `%s'",
2326 dst
->unit_decl
->name
, unit
->name
);
2329 else if (pat
->units_num
== 1)
2330 for (curr_pat_el
= dst
->unit_decl
->presence_list
;
2331 curr_pat_el
!= NULL
;
2332 curr_pat_el
= curr_pat_el
->next_pattern_set_el
)
2333 if (curr_pat_el
->units_num
== 1
2334 && unit
== curr_pat_el
->unit_decls
[0])
2338 error ("unit `%s' requires absence and presence of `%s'",
2339 dst
->unit_decl
->name
, unit
->name
);
2343 warning ("unit `%s' requires absence and presence of `%s'",
2344 dst
->unit_decl
->name
, unit
->name
);
2348 for (prev_el
= (presence_p
2350 ? dst
->unit_decl
->final_presence_list
2351 : dst
->unit_decl
->final_presence_list
)
2353 ? dst
->unit_decl
->final_absence_list
2354 : dst
->unit_decl
->absence_list
));
2355 prev_el
!= NULL
&& prev_el
->next_pattern_set_el
!= NULL
;
2356 prev_el
= prev_el
->next_pattern_set_el
)
2358 copy
= XCOPYNODE (struct pattern_set_el
, pat
);
2359 copy
->next_pattern_set_el
= NULL
;
2360 if (prev_el
== NULL
)
2365 dst
->unit_decl
->final_presence_list
= copy
;
2367 dst
->unit_decl
->presence_list
= copy
;
2370 dst
->unit_decl
->final_absence_list
= copy
;
2372 dst
->unit_decl
->absence_list
= copy
;
2375 prev_el
->next_pattern_set_el
= copy
;
2382 /* The function inserts BYPASS in the list of bypasses of the
2383 corresponding output insn. The order of bypasses in the list is
2384 described in a comment for member `bypass_list' (see above). If
2385 there is already the same bypass in the list the function reports
2386 this and does nothing. */
2388 insert_bypass (struct bypass_decl
*bypass
)
2390 struct bypass_decl
*curr
, *last
;
2391 struct insn_reserv_decl
*out_insn_reserv
= bypass
->out_insn_reserv
;
2392 struct insn_reserv_decl
*in_insn_reserv
= bypass
->in_insn_reserv
;
2394 for (curr
= out_insn_reserv
->bypass_list
, last
= NULL
;
2396 last
= curr
, curr
= curr
->next
)
2397 if (curr
->in_insn_reserv
== in_insn_reserv
)
2399 if ((bypass
->bypass_guard_name
!= NULL
2400 && curr
->bypass_guard_name
!= NULL
2401 && ! strcmp (bypass
->bypass_guard_name
, curr
->bypass_guard_name
))
2402 || bypass
->bypass_guard_name
== curr
->bypass_guard_name
)
2404 if (bypass
->bypass_guard_name
== NULL
)
2407 error ("the same bypass `%s - %s' is already defined",
2408 bypass
->out_pattern
, bypass
->in_pattern
);
2410 warning ("the same bypass `%s - %s' is already defined",
2411 bypass
->out_pattern
, bypass
->in_pattern
);
2414 error ("the same bypass `%s - %s' (guard %s) is already defined",
2415 bypass
->out_pattern
, bypass
->in_pattern
,
2416 bypass
->bypass_guard_name
);
2419 ("the same bypass `%s - %s' (guard %s) is already defined",
2420 bypass
->out_pattern
, bypass
->in_pattern
,
2421 bypass
->bypass_guard_name
);
2424 if (curr
->bypass_guard_name
== NULL
)
2426 if (curr
->next
== NULL
|| curr
->next
->in_insn_reserv
!= in_insn_reserv
)
2435 bypass
->next
= out_insn_reserv
->bypass_list
;
2436 out_insn_reserv
->bypass_list
= bypass
;
2440 bypass
->next
= last
->next
;
2441 last
->next
= bypass
;
2445 /* BYPASS is a define_bypass decl that includes glob pattern PATTERN.
2446 Call FN (BYPASS, INSN, DATA) for each matching instruction INSN. */
2449 for_each_matching_insn (decl_t bypass
, const char *pattern
,
2450 void (*fn
) (decl_t
, decl_t
, void *), void *data
)
2457 if (strpbrk (pattern
, "*?["))
2458 for (i
= 0; i
< description
->decls_num
; i
++)
2460 insn_reserv
= description
->decls
[i
];
2461 if (insn_reserv
->mode
== dm_insn_reserv
2462 && fnmatch (pattern
, DECL_INSN_RESERV (insn_reserv
)->name
, 0) == 0)
2464 fn (bypass
, insn_reserv
, data
);
2470 insn_reserv
= find_insn_decl (pattern
);
2473 fn (bypass
, insn_reserv
, data
);
2478 error ("there is no insn reservation that matches `%s'", pattern
);
2481 /* A subroutine of process_bypass that is called for each pair
2482 of matching instructions. OUT_INSN_RESERV is the output
2483 instruction and DATA is the input instruction. */
2486 process_bypass_2 (decl_t model
, decl_t out_insn_reserv
, void *data
)
2488 struct bypass_decl
*bypass
;
2489 decl_t in_insn_reserv
;
2491 in_insn_reserv
= (decl_t
) data
;
2492 if (strcmp (DECL_INSN_RESERV (in_insn_reserv
)->name
,
2493 DECL_BYPASS (model
)->in_pattern
) == 0
2494 && strcmp (DECL_INSN_RESERV (out_insn_reserv
)->name
,
2495 DECL_BYPASS (model
)->out_pattern
) == 0)
2496 bypass
= DECL_BYPASS (model
);
2499 bypass
= XCNEW (struct bypass_decl
);
2500 bypass
->latency
= DECL_BYPASS (model
)->latency
;
2501 bypass
->out_pattern
= DECL_INSN_RESERV (out_insn_reserv
)->name
;
2502 bypass
->in_pattern
= DECL_INSN_RESERV (in_insn_reserv
)->name
;
2503 bypass
->bypass_guard_name
= DECL_BYPASS (model
)->bypass_guard_name
;
2505 bypass
->out_insn_reserv
= DECL_INSN_RESERV (out_insn_reserv
);
2506 bypass
->in_insn_reserv
= DECL_INSN_RESERV (in_insn_reserv
);
2507 insert_bypass (bypass
);
2510 /* A subroutine of process_bypass that is called for each input
2511 instruction IN_INSN_RESERV. */
2514 process_bypass_1 (decl_t bypass
, decl_t in_insn_reserv
,
2515 void *data ATTRIBUTE_UNUSED
)
2517 for_each_matching_insn (bypass
, DECL_BYPASS (bypass
)->out_pattern
,
2518 process_bypass_2
, in_insn_reserv
);
2521 /* Process define_bypass decl BYPASS, inserting a bypass for each specific
2522 pair of insn reservations. */
2525 process_bypass (decl_t bypass
)
2527 for_each_matching_insn (bypass
, DECL_BYPASS (bypass
)->in_pattern
,
2528 process_bypass_1
, NULL
);
2531 /* The function processes pipeline description declarations, checks
2532 their correctness, and forms exclusion/presence/absence sets. */
2534 process_decls (void)
2537 decl_t automaton_decl
;
2538 decl_t decl_in_table
;
2539 int automaton_presence
;
2542 /* Checking repeated automata declarations. */
2543 automaton_presence
= 0;
2544 for (i
= 0; i
< description
->decls_num
; i
++)
2546 decl
= description
->decls
[i
];
2547 if (decl
->mode
== dm_automaton
)
2549 automaton_presence
= 1;
2550 decl_in_table
= insert_automaton_decl (decl
);
2551 if (decl_in_table
!= decl
)
2554 error ("repeated declaration of automaton `%s'",
2555 DECL_AUTOMATON (decl
)->name
);
2557 warning ("repeated declaration of automaton `%s'",
2558 DECL_AUTOMATON (decl
)->name
);
2562 /* Checking undeclared automata, repeated declarations (except for
2563 automata) and correctness of their attributes (insn latency times
2565 for (i
= 0; i
< description
->decls_num
; i
++)
2567 decl
= description
->decls
[i
];
2568 if (decl
->mode
== dm_insn_reserv
)
2570 if (DECL_INSN_RESERV (decl
)->default_latency
< 0)
2571 error ("define_insn_reservation `%s' has negative latency time",
2572 DECL_INSN_RESERV (decl
)->name
);
2573 DECL_INSN_RESERV (decl
)->insn_num
= description
->insns_num
;
2574 description
->insns_num
++;
2575 decl_in_table
= insert_insn_decl (decl
);
2576 if (decl_in_table
!= decl
)
2577 error ("`%s' is already used as insn reservation name",
2578 DECL_INSN_RESERV (decl
)->name
);
2580 else if (decl
->mode
== dm_bypass
)
2582 if (DECL_BYPASS (decl
)->latency
< 0)
2583 error ("define_bypass `%s - %s' has negative latency time",
2584 DECL_BYPASS (decl
)->out_pattern
,
2585 DECL_BYPASS (decl
)->in_pattern
);
2587 else if (decl
->mode
== dm_unit
|| decl
->mode
== dm_reserv
)
2589 if (decl
->mode
== dm_unit
)
2591 DECL_UNIT (decl
)->automaton_decl
= NULL
;
2592 if (DECL_UNIT (decl
)->automaton_name
!= NULL
)
2595 = find_automaton_decl (DECL_UNIT (decl
)->automaton_name
);
2596 if (automaton_decl
== NULL
)
2597 error ("automaton `%s' is not declared",
2598 DECL_UNIT (decl
)->automaton_name
);
2601 DECL_AUTOMATON (automaton_decl
)->automaton_is_used
= 1;
2602 DECL_UNIT (decl
)->automaton_decl
2603 = DECL_AUTOMATON (automaton_decl
);
2606 else if (automaton_presence
)
2607 error ("define_unit `%s' without automaton when one defined",
2608 DECL_UNIT (decl
)->name
);
2609 DECL_UNIT (decl
)->unit_num
= description
->units_num
;
2610 description
->units_num
++;
2611 if (strcmp (DECL_UNIT (decl
)->name
, NOTHING_NAME
) == 0)
2613 error ("`%s' is declared as cpu unit", NOTHING_NAME
);
2616 decl_in_table
= find_decl (DECL_UNIT (decl
)->name
);
2620 if (strcmp (DECL_RESERV (decl
)->name
, NOTHING_NAME
) == 0)
2622 error ("`%s' is declared as cpu reservation", NOTHING_NAME
);
2625 decl_in_table
= find_decl (DECL_RESERV (decl
)->name
);
2627 if (decl_in_table
== NULL
)
2628 decl_in_table
= insert_decl (decl
);
2631 if (decl
->mode
== dm_unit
)
2632 error ("repeated declaration of unit `%s'",
2633 DECL_UNIT (decl
)->name
);
2635 error ("repeated declaration of reservation `%s'",
2636 DECL_RESERV (decl
)->name
);
2640 /* Check bypasses and form list of bypasses for each (output)
2642 for (i
= 0; i
< description
->decls_num
; i
++)
2644 decl
= description
->decls
[i
];
2645 if (decl
->mode
== dm_bypass
)
2646 process_bypass (decl
);
2649 /* Check exclusion set declarations and form exclusion sets. */
2650 for (i
= 0; i
< description
->decls_num
; i
++)
2652 decl
= description
->decls
[i
];
2653 if (decl
->mode
== dm_excl
)
2655 unit_set_el_t unit_set_el_list
;
2656 unit_set_el_t unit_set_el_list_2
;
2659 = process_excls (DECL_EXCL (decl
)->names
,
2660 DECL_EXCL (decl
)->first_list_length
, decl
->pos
);
2662 = process_excls (&DECL_EXCL (decl
)->names
2663 [DECL_EXCL (decl
)->first_list_length
],
2664 DECL_EXCL (decl
)->all_names_num
2665 - DECL_EXCL (decl
)->first_list_length
,
2667 add_excls (unit_set_el_list
, unit_set_el_list_2
, decl
->pos
);
2668 add_excls (unit_set_el_list_2
, unit_set_el_list
, decl
->pos
);
2672 /* Check presence set declarations and form presence sets. */
2673 for (i
= 0; i
< description
->decls_num
; i
++)
2675 decl
= description
->decls
[i
];
2676 if (decl
->mode
== dm_presence
)
2678 unit_set_el_t unit_set_el_list
;
2679 pattern_set_el_t pattern_set_el_list
;
2682 = process_presence_absence_names
2683 (DECL_PRESENCE (decl
)->names
, DECL_PRESENCE (decl
)->names_num
,
2684 decl
->pos
, TRUE
, DECL_PRESENCE (decl
)->final_p
);
2686 = process_presence_absence_patterns
2687 (DECL_PRESENCE (decl
)->patterns
,
2688 DECL_PRESENCE (decl
)->patterns_num
,
2689 decl
->pos
, TRUE
, DECL_PRESENCE (decl
)->final_p
);
2690 add_presence_absence (unit_set_el_list
, pattern_set_el_list
,
2692 DECL_PRESENCE (decl
)->final_p
);
2696 /* Check absence set declarations and form absence sets. */
2697 for (i
= 0; i
< description
->decls_num
; i
++)
2699 decl
= description
->decls
[i
];
2700 if (decl
->mode
== dm_absence
)
2702 unit_set_el_t unit_set_el_list
;
2703 pattern_set_el_t pattern_set_el_list
;
2706 = process_presence_absence_names
2707 (DECL_ABSENCE (decl
)->names
, DECL_ABSENCE (decl
)->names_num
,
2708 decl
->pos
, FALSE
, DECL_ABSENCE (decl
)->final_p
);
2710 = process_presence_absence_patterns
2711 (DECL_ABSENCE (decl
)->patterns
,
2712 DECL_ABSENCE (decl
)->patterns_num
,
2713 decl
->pos
, FALSE
, DECL_ABSENCE (decl
)->final_p
);
2714 add_presence_absence (unit_set_el_list
, pattern_set_el_list
,
2716 DECL_ABSENCE (decl
)->final_p
);
2721 /* The following function checks that declared automaton is used. If
2722 the automaton is not used, the function fixes error/warning. The
2723 following function must be called only after `process_decls'. */
2725 check_automaton_usage (void)
2730 for (i
= 0; i
< description
->decls_num
; i
++)
2732 decl
= description
->decls
[i
];
2733 if (decl
->mode
== dm_automaton
2734 && !DECL_AUTOMATON (decl
)->automaton_is_used
)
2737 error ("automaton `%s' is not used", DECL_AUTOMATON (decl
)->name
);
2739 warning ("automaton `%s' is not used",
2740 DECL_AUTOMATON (decl
)->name
);
2745 /* The following recursive function processes all regexp in order to
2746 fix usage of units or reservations and to fix errors of undeclared
2747 name. The function may change unit_regexp onto reserv_regexp.
2748 Remember that reserv_regexp does not exist before the function
2751 process_regexp (regexp_t regexp
)
2753 decl_t decl_in_table
;
2754 regexp_t new_regexp
;
2757 switch (regexp
->mode
)
2760 decl_in_table
= find_decl (REGEXP_UNIT (regexp
)->name
);
2761 if (decl_in_table
== NULL
)
2762 error ("undeclared unit or reservation `%s'",
2763 REGEXP_UNIT (regexp
)->name
);
2765 switch (decl_in_table
->mode
)
2768 DECL_UNIT (decl_in_table
)->unit_is_used
= 1;
2769 REGEXP_UNIT (regexp
)->unit_decl
= DECL_UNIT (decl_in_table
);
2773 DECL_RESERV (decl_in_table
)->reserv_is_used
= 1;
2774 new_regexp
= XCREATENODE (struct regexp
);
2775 new_regexp
->mode
= rm_reserv
;
2776 new_regexp
->pos
= regexp
->pos
;
2777 REGEXP_RESERV (new_regexp
)->name
= REGEXP_UNIT (regexp
)->name
;
2778 REGEXP_RESERV (new_regexp
)->reserv_decl
2779 = DECL_RESERV (decl_in_table
);
2780 regexp
= new_regexp
;
2788 for (i
= 0; i
<REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
2789 REGEXP_SEQUENCE (regexp
)->regexps
[i
]
2790 = process_regexp (REGEXP_SEQUENCE (regexp
)->regexps
[i
]);
2793 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
2794 REGEXP_ALLOF (regexp
)->regexps
[i
]
2795 = process_regexp (REGEXP_ALLOF (regexp
)->regexps
[i
]);
2798 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
2799 REGEXP_ONEOF (regexp
)->regexps
[i
]
2800 = process_regexp (REGEXP_ONEOF (regexp
)->regexps
[i
]);
2803 REGEXP_REPEAT (regexp
)->regexp
2804 = process_regexp (REGEXP_REPEAT (regexp
)->regexp
);
2814 /* The following function processes regexp of define_reservation and
2815 define_insn_reservation with the aid of function
2816 `process_regexp'. */
2818 process_regexp_decls (void)
2823 for (i
= 0; i
< description
->decls_num
; i
++)
2825 decl
= description
->decls
[i
];
2826 if (decl
->mode
== dm_reserv
)
2827 DECL_RESERV (decl
)->regexp
2828 = process_regexp (DECL_RESERV (decl
)->regexp
);
2829 else if (decl
->mode
== dm_insn_reserv
)
2830 DECL_INSN_RESERV (decl
)->regexp
2831 = process_regexp (DECL_INSN_RESERV (decl
)->regexp
);
2835 /* The following function checks that declared unit is used. If the
2836 unit is not used, the function fixes errors/warnings. The
2837 following function must be called only after `process_decls',
2838 `process_regexp_decls'. */
2845 for (i
= 0; i
< description
->decls_num
; i
++)
2847 decl
= description
->decls
[i
];
2848 if (decl
->mode
== dm_unit
&& !DECL_UNIT (decl
)->unit_is_used
)
2851 error ("unit `%s' is not used", DECL_UNIT (decl
)->name
);
2853 warning ("unit `%s' is not used", DECL_UNIT (decl
)->name
);
2855 else if (decl
->mode
== dm_reserv
&& !DECL_RESERV (decl
)->reserv_is_used
)
2858 error ("reservation `%s' is not used", DECL_RESERV (decl
)->name
);
2860 warning ("reservation `%s' is not used", DECL_RESERV (decl
)->name
);
2865 /* The following variable value is number of reservation being
2866 processed on loop recognition. */
2867 static int curr_loop_pass_num
;
2869 /* The following recursive function returns nonzero value if REGEXP
2870 contains given decl or reservations in given regexp refers for
2873 loop_in_regexp (regexp_t regexp
, decl_t start_decl
)
2879 switch (regexp
->mode
)
2885 if (start_decl
->mode
== dm_reserv
2886 && REGEXP_RESERV (regexp
)->reserv_decl
== DECL_RESERV (start_decl
))
2888 else if (REGEXP_RESERV (regexp
)->reserv_decl
->loop_pass_num
2889 == curr_loop_pass_num
)
2890 /* declaration has been processed. */
2894 REGEXP_RESERV (regexp
)->reserv_decl
->loop_pass_num
2895 = curr_loop_pass_num
;
2896 return loop_in_regexp (REGEXP_RESERV (regexp
)->reserv_decl
->regexp
,
2901 for (i
= 0; i
<REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
2902 if (loop_in_regexp (REGEXP_SEQUENCE (regexp
)->regexps
[i
], start_decl
))
2907 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
2908 if (loop_in_regexp (REGEXP_ALLOF (regexp
)->regexps
[i
], start_decl
))
2913 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
2914 if (loop_in_regexp (REGEXP_ONEOF (regexp
)->regexps
[i
], start_decl
))
2919 return loop_in_regexp (REGEXP_REPEAT (regexp
)->regexp
, start_decl
);
2929 /* The following function fixes errors "cycle in definition ...". The
2930 function uses function `loop_in_regexp' for that. */
2932 check_loops_in_regexps (void)
2937 for (i
= 0; i
< description
->decls_num
; i
++)
2939 decl
= description
->decls
[i
];
2940 if (decl
->mode
== dm_reserv
)
2941 DECL_RESERV (decl
)->loop_pass_num
= 0;
2943 for (i
= 0; i
< description
->decls_num
; i
++)
2945 decl
= description
->decls
[i
];
2946 curr_loop_pass_num
= i
;
2948 if (decl
->mode
== dm_reserv
)
2950 DECL_RESERV (decl
)->loop_pass_num
= curr_loop_pass_num
;
2951 if (loop_in_regexp (DECL_RESERV (decl
)->regexp
, decl
))
2953 gcc_assert (DECL_RESERV (decl
)->regexp
);
2954 error ("cycle in definition of reservation `%s'",
2955 DECL_RESERV (decl
)->name
);
2961 /* The function recursively processes IR of reservation and defines
2962 max and min cycle for reservation of unit. */
2964 process_regexp_cycles (regexp_t regexp
, int max_start_cycle
,
2965 int min_start_cycle
, int *max_finish_cycle
,
2966 int *min_finish_cycle
)
2970 switch (regexp
->mode
)
2973 if (REGEXP_UNIT (regexp
)->unit_decl
->max_occ_cycle_num
< max_start_cycle
)
2974 REGEXP_UNIT (regexp
)->unit_decl
->max_occ_cycle_num
= max_start_cycle
;
2975 if (REGEXP_UNIT (regexp
)->unit_decl
->min_occ_cycle_num
> min_start_cycle
2976 || REGEXP_UNIT (regexp
)->unit_decl
->min_occ_cycle_num
== -1)
2977 REGEXP_UNIT (regexp
)->unit_decl
->min_occ_cycle_num
= min_start_cycle
;
2978 *max_finish_cycle
= max_start_cycle
;
2979 *min_finish_cycle
= min_start_cycle
;
2983 process_regexp_cycles (REGEXP_RESERV (regexp
)->reserv_decl
->regexp
,
2984 max_start_cycle
, min_start_cycle
,
2985 max_finish_cycle
, min_finish_cycle
);
2989 for (i
= 0; i
< REGEXP_REPEAT (regexp
)->repeat_num
; i
++)
2991 process_regexp_cycles (REGEXP_REPEAT (regexp
)->regexp
,
2992 max_start_cycle
, min_start_cycle
,
2993 max_finish_cycle
, min_finish_cycle
);
2994 max_start_cycle
= *max_finish_cycle
+ 1;
2995 min_start_cycle
= *min_finish_cycle
+ 1;
3000 for (i
= 0; i
<REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
3002 process_regexp_cycles (REGEXP_SEQUENCE (regexp
)->regexps
[i
],
3003 max_start_cycle
, min_start_cycle
,
3004 max_finish_cycle
, min_finish_cycle
);
3005 max_start_cycle
= *max_finish_cycle
+ 1;
3006 min_start_cycle
= *min_finish_cycle
+ 1;
3015 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
3017 process_regexp_cycles (REGEXP_ALLOF (regexp
)->regexps
[i
],
3018 max_start_cycle
, min_start_cycle
,
3019 max_finish_cycle
, min_finish_cycle
);
3020 if (max_cycle
< *max_finish_cycle
)
3021 max_cycle
= *max_finish_cycle
;
3022 if (i
== 0 || min_cycle
> *min_finish_cycle
)
3023 min_cycle
= *min_finish_cycle
;
3025 *max_finish_cycle
= max_cycle
;
3026 *min_finish_cycle
= min_cycle
;
3035 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
3037 process_regexp_cycles (REGEXP_ONEOF (regexp
)->regexps
[i
],
3038 max_start_cycle
, min_start_cycle
,
3039 max_finish_cycle
, min_finish_cycle
);
3040 if (max_cycle
< *max_finish_cycle
)
3041 max_cycle
= *max_finish_cycle
;
3042 if (i
== 0 || min_cycle
> *min_finish_cycle
)
3043 min_cycle
= *min_finish_cycle
;
3045 *max_finish_cycle
= max_cycle
;
3046 *min_finish_cycle
= min_cycle
;
3051 *max_finish_cycle
= max_start_cycle
;
3052 *min_finish_cycle
= min_start_cycle
;
3060 /* The following function is called only for correct program. The
3061 function defines max reservation of insns in cycles. */
3063 evaluate_max_reserv_cycles (void)
3065 int max_insn_cycles_num
;
3066 int min_insn_cycles_num
;
3070 description
->max_insn_reserv_cycles
= 0;
3071 for (i
= 0; i
< description
->decls_num
; i
++)
3073 decl
= description
->decls
[i
];
3074 if (decl
->mode
== dm_insn_reserv
)
3076 process_regexp_cycles (DECL_INSN_RESERV (decl
)->regexp
, 0, 0,
3077 &max_insn_cycles_num
, &min_insn_cycles_num
);
3078 if (description
->max_insn_reserv_cycles
< max_insn_cycles_num
)
3079 description
->max_insn_reserv_cycles
= max_insn_cycles_num
;
3082 description
->max_insn_reserv_cycles
++;
3085 /* The following function calls functions for checking all
3088 check_all_description (void)
3091 check_automaton_usage ();
3092 process_regexp_decls ();
3094 check_loops_in_regexps ();
3096 evaluate_max_reserv_cycles ();
3101 /* The page contains abstract data `ticker'. This data is used to
3102 report time of different phases of building automata. It is
3103 possibly to write a description for which automata will be built
3104 during several minutes even on fast machine. */
3106 /* The following function creates ticker and makes it active. */
3108 create_ticker (void)
3112 ticker
.modified_creation_time
= get_run_time ();
3113 ticker
.incremented_off_time
= 0;
3117 /* The following function switches off given ticker. */
3119 ticker_off (ticker_t
*ticker
)
3121 if (ticker
->incremented_off_time
== 0)
3122 ticker
->incremented_off_time
= get_run_time () + 1;
3125 /* The following function switches on given ticker. */
3127 ticker_on (ticker_t
*ticker
)
3129 if (ticker
->incremented_off_time
!= 0)
3131 ticker
->modified_creation_time
3132 += get_run_time () - ticker
->incremented_off_time
+ 1;
3133 ticker
->incremented_off_time
= 0;
3137 /* The following function returns current time in milliseconds since
3138 the moment when given ticker was created. */
3140 active_time (ticker_t ticker
)
3142 if (ticker
.incremented_off_time
!= 0)
3143 return ticker
.incremented_off_time
- 1 - ticker
.modified_creation_time
;
3145 return get_run_time () - ticker
.modified_creation_time
;
3148 /* The following function returns string representation of active time
3149 of given ticker. The result is string representation of seconds
3150 with accuracy of 1/100 second. Only result of the last call of the
3151 function exists. Therefore the following code is not correct
3153 printf ("parser time: %s\ngeneration time: %s\n",
3154 active_time_string (parser_ticker),
3155 active_time_string (generation_ticker));
3157 Correct code has to be the following
3159 printf ("parser time: %s\n", active_time_string (parser_ticker));
3160 printf ("generation time: %s\n",
3161 active_time_string (generation_ticker));
3165 print_active_time (FILE *f
, ticker_t ticker
)
3169 msecs
= active_time (ticker
);
3170 fprintf (f
, "%d.%06d", msecs
/ 1000000, msecs
% 1000000);
3175 /* The following variable value is number of automaton which are
3176 really being created. This value is defined on the base of
3177 argument of option `-split'. If the variable has zero value the
3178 number of automata is defined by the constructions `%automaton'.
3179 This case occurs when option `-split' is absent or has zero
3180 argument. If constructions `define_automaton' is absent only one
3181 automaton is created. */
3182 static int automata_num
;
3184 /* The following variable values are times of
3185 o transformation of regular expressions
3186 o building NDFA (DFA if !ndfa_flag)
3187 o NDFA -> DFA (simply the same automaton if !ndfa_flag)
3189 o building insn equivalence classes
3192 static ticker_t transform_time
;
3193 static ticker_t NDFA_time
;
3194 static ticker_t NDFA_to_DFA_time
;
3195 static ticker_t minimize_time
;
3196 static ticker_t equiv_time
;
3197 static ticker_t automaton_generation_time
;
3198 static ticker_t output_time
;
3200 /* The following variable values are times of
3203 all pipeline hazard translator work */
3204 static ticker_t check_time
;
3205 static ticker_t generation_time
;
3206 static ticker_t all_time
;
3210 /* Pseudo insn decl which denotes advancing cycle. */
3211 static decl_t advance_cycle_insn_decl
;
3212 /* Pseudo insn decl which denotes collapsing the NDFA state. */
3213 static decl_t collapse_ndfa_insn_decl
;
3215 /* Create and record a decl for the special advance-cycle transition. */
3217 add_advance_cycle_insn_decl (void)
3219 advance_cycle_insn_decl
= XCREATENODE (struct decl
);
3220 advance_cycle_insn_decl
->mode
= dm_insn_reserv
;
3221 advance_cycle_insn_decl
->pos
= no_pos
;
3222 DECL_INSN_RESERV (advance_cycle_insn_decl
)->regexp
= NULL
;
3223 DECL_INSN_RESERV (advance_cycle_insn_decl
)->name
= "$advance_cycle";
3224 DECL_INSN_RESERV (advance_cycle_insn_decl
)->insn_num
3225 = description
->insns_num
;
3226 description
->decls
[description
->decls_num
] = advance_cycle_insn_decl
;
3227 description
->decls_num
++;
3228 description
->insns_num
++;
3231 /* Create and record a decl for the special collapse-NDFA transition. */
3233 add_collapse_ndfa_insn_decl (void)
3235 collapse_ndfa_insn_decl
= XCREATENODE (struct decl
);
3236 collapse_ndfa_insn_decl
->mode
= dm_insn_reserv
;
3237 collapse_ndfa_insn_decl
->pos
= no_pos
;
3238 DECL_INSN_RESERV (collapse_ndfa_insn_decl
)->regexp
= NULL
;
3239 DECL_INSN_RESERV (collapse_ndfa_insn_decl
)->name
= "$collapse_ndfa";
3240 DECL_INSN_RESERV (collapse_ndfa_insn_decl
)->insn_num
3241 = description
->insns_num
;
3242 description
->decls
[description
->decls_num
] = collapse_ndfa_insn_decl
;
3243 description
->decls_num
++;
3244 description
->insns_num
++;
3247 /* True if DECL is either of the two special decls we created. */
3249 special_decl_p (struct insn_reserv_decl
*decl
)
3251 return (decl
== DECL_INSN_RESERV (advance_cycle_insn_decl
)
3253 && decl
== DECL_INSN_RESERV (collapse_ndfa_insn_decl
)));
3257 /* Abstract data `alternative states' which represents
3258 nondeterministic nature of the description (see comments for
3259 structures alt_state and state). */
3261 /* List of free states. */
3262 static alt_state_t first_free_alt_state
;
3265 /* The following variables is maximal number of allocated nodes
3267 static int allocated_alt_states_num
= 0;
3270 /* The following function returns free node alt_state. It may be new
3271 allocated node or node freed earlier. */
3273 get_free_alt_state (void)
3277 if (first_free_alt_state
!= NULL
)
3279 result
= first_free_alt_state
;
3280 first_free_alt_state
= first_free_alt_state
->next_alt_state
;
3285 allocated_alt_states_num
++;
3287 result
= XCREATENODE (struct alt_state
);
3289 result
->state
= NULL
;
3290 result
->next_alt_state
= NULL
;
3291 result
->next_sorted_alt_state
= NULL
;
3295 /* The function frees node ALT_STATE. */
3297 free_alt_state (alt_state_t alt_state
)
3299 if (alt_state
== NULL
)
3301 alt_state
->next_alt_state
= first_free_alt_state
;
3302 first_free_alt_state
= alt_state
;
3305 /* The function frees list started with node ALT_STATE_LIST. */
3307 free_alt_states (alt_state_t alt_states_list
)
3309 alt_state_t curr_alt_state
;
3310 alt_state_t next_alt_state
;
3312 for (curr_alt_state
= alt_states_list
;
3313 curr_alt_state
!= NULL
;
3314 curr_alt_state
= next_alt_state
)
3316 next_alt_state
= curr_alt_state
->next_alt_state
;
3317 free_alt_state (curr_alt_state
);
3321 /* The function compares unique numbers of alt states. */
3323 alt_state_cmp (const void *alt_state_ptr_1
, const void *alt_state_ptr_2
)
3325 if ((*(const alt_state_t
*) alt_state_ptr_1
)->state
->unique_num
3326 == (*(const alt_state_t
*) alt_state_ptr_2
)->state
->unique_num
)
3328 else if ((*(const alt_state_t
*) alt_state_ptr_1
)->state
->unique_num
3329 < (*(const alt_state_t
*) alt_state_ptr_2
)->state
->unique_num
)
3335 /* The function sorts ALT_STATES_LIST and removes duplicated alt
3336 states from the list. The comparison key is alt state unique
3340 uniq_sort_alt_states (alt_state_t alt_states_list
)
3342 alt_state_t curr_alt_state
;
3343 vec
<alt_state_t
> alt_states
;
3345 size_t prev_unique_state_ind
;
3348 if (alt_states_list
== 0)
3350 if (alt_states_list
->next_alt_state
== 0)
3351 return alt_states_list
;
3353 alt_states
.create (150);
3354 for (curr_alt_state
= alt_states_list
;
3355 curr_alt_state
!= NULL
;
3356 curr_alt_state
= curr_alt_state
->next_alt_state
)
3357 alt_states
.safe_push (curr_alt_state
);
3359 alt_states
.qsort (alt_state_cmp
);
3361 prev_unique_state_ind
= 0;
3362 for (i
= 1; i
< alt_states
.length (); i
++)
3363 if (alt_states
[prev_unique_state_ind
]->state
!= alt_states
[i
]->state
)
3365 prev_unique_state_ind
++;
3366 alt_states
[prev_unique_state_ind
] = alt_states
[i
];
3368 alt_states
.truncate (prev_unique_state_ind
+ 1);
3370 for (i
= 1; i
< alt_states
.length (); i
++)
3371 alt_states
[i
-1]->next_sorted_alt_state
3373 alt_states
.last ()->next_sorted_alt_state
= 0;
3375 result
= alt_states
[0];
3377 alt_states
.release ();
3381 /* The function checks equality of alt state lists. Remember that the
3382 lists must be already sorted by the previous function. */
3384 alt_states_eq (alt_state_t alt_states_1
, alt_state_t alt_states_2
)
3386 while (alt_states_1
!= NULL
&& alt_states_2
!= NULL
3387 && alt_state_cmp (&alt_states_1
, &alt_states_2
) == 0)
3389 alt_states_1
= alt_states_1
->next_sorted_alt_state
;
3390 alt_states_2
= alt_states_2
->next_sorted_alt_state
;
3392 return alt_states_1
== alt_states_2
;
3395 /* Initialization of the abstract data. */
3397 initiate_alt_states (void)
3399 first_free_alt_state
= NULL
;
3402 /* Finishing work with the abstract data. */
3404 finish_alt_states (void)
3410 /* The page contains macros for work with bits strings. We could use
3411 standard gcc bitmap or sbitmap but it would result in difficulties
3412 of building canadian cross. */
3414 /* Set bit number bitno in the bit string. The macro is not side
3416 #define bitmap_set_bit(bitstring, bitno) \
3417 ((bitstring)[(bitno) / (sizeof (*(bitstring)) * CHAR_BIT)] |= \
3418 (HOST_WIDE_INT)1 << (bitno) % (sizeof (*(bitstring)) * CHAR_BIT))
3420 #define CLEAR_BIT(bitstring, bitno) \
3421 ((bitstring)[(bitno) / (sizeof (*(bitstring)) * CHAR_BIT)] &= \
3422 ~((HOST_WIDE_INT)1 << (bitno) % (sizeof (*(bitstring)) * CHAR_BIT)))
3424 /* Test if bit number bitno in the bitstring is set. The macro is not
3425 side effect proof. */
3426 #define bitmap_bit_p(bitstring, bitno) \
3427 ((bitstring)[(bitno) / (sizeof (*(bitstring)) * CHAR_BIT)] >> \
3428 (bitno) % (sizeof (*(bitstring)) * CHAR_BIT) & 1)
3432 /* This page contains abstract data `state'. */
3434 /* Maximal length of reservations in cycles (>= 1). */
3435 static int max_cycles_num
;
3437 /* Number of set elements (see type set_el_t) needed for
3438 representation of one cycle reservation. It is depended on units
3440 static int els_in_cycle_reserv
;
3442 /* Number of set elements (see type set_el_t) needed for
3443 representation of maximal length reservation. Deterministic
3444 reservation is stored as set (bit string) of length equal to the
3445 variable value * number of bits in set_el_t. */
3446 static int els_in_reservs
;
3448 /* Array of pointers to unit declarations. */
3449 static unit_decl_t
*units_array
;
3451 /* Temporary reservation of maximal length. */
3452 static reserv_sets_t temp_reserv
;
3454 /* The state table itself is represented by the following variable. */
3455 static htab_t state_table
;
3457 /* Linked list of free 'state' structures to be recycled. The
3458 next_equiv_class_state pointer is borrowed for a free list. */
3459 static state_t first_free_state
;
3461 static int curr_unique_state_num
;
3464 /* The following variables is maximal number of allocated nodes
3466 static int allocated_states_num
= 0;
3469 /* Allocate new reservation set. */
3470 static reserv_sets_t
3471 alloc_empty_reserv_sets (void)
3473 reserv_sets_t result
;
3475 obstack_blank (&irp
, els_in_reservs
* sizeof (set_el_t
));
3476 result
= (reserv_sets_t
) obstack_base (&irp
);
3477 obstack_finish (&irp
);
3478 memset (result
, 0, els_in_reservs
* sizeof (set_el_t
));
3482 /* Hash value of reservation set. */
3484 reserv_sets_hash_value (reserv_sets_t reservs
)
3486 set_el_t hash_value
;
3489 set_el_t
*reserv_ptr
;
3492 reservs_num
= els_in_reservs
;
3493 reserv_ptr
= reservs
;
3495 while (reservs_num
!= 0)
3498 hash_value
+= ((*reserv_ptr
>> i
)
3499 | (*reserv_ptr
<< (sizeof (set_el_t
) * CHAR_BIT
- i
)));
3501 if (i
== sizeof (set_el_t
) * CHAR_BIT
)
3505 if (sizeof (set_el_t
) <= sizeof (unsigned))
3508 for (i
= sizeof (set_el_t
); i
> 0; i
-= sizeof (unsigned) - 1)
3510 result
+= (unsigned) hash_value
;
3511 hash_value
>>= (sizeof (unsigned) - 1) * CHAR_BIT
;
3516 /* Comparison of given reservation sets. */
3518 reserv_sets_cmp (const_reserv_sets_t reservs_1
, const_reserv_sets_t reservs_2
)
3521 const set_el_t
*reserv_ptr_1
;
3522 const set_el_t
*reserv_ptr_2
;
3524 gcc_assert (reservs_1
&& reservs_2
);
3525 reservs_num
= els_in_reservs
;
3526 reserv_ptr_1
= reservs_1
;
3527 reserv_ptr_2
= reservs_2
;
3528 while (reservs_num
!= 0 && *reserv_ptr_1
== *reserv_ptr_2
)
3534 if (reservs_num
== 0)
3536 else if (*reserv_ptr_1
< *reserv_ptr_2
)
3542 /* The function checks equality of the reservation sets. */
3544 reserv_sets_eq (const_reserv_sets_t reservs_1
, const_reserv_sets_t reservs_2
)
3546 return reserv_sets_cmp (reservs_1
, reservs_2
) == 0;
3549 /* Set up in the reservation set that unit with UNIT_NUM is used on
3552 set_unit_reserv (reserv_sets_t reservs
, int cycle_num
, int unit_num
)
3554 gcc_assert (cycle_num
< max_cycles_num
);
3555 bitmap_set_bit (reservs
, cycle_num
* els_in_cycle_reserv
3556 * sizeof (set_el_t
) * CHAR_BIT
+ unit_num
);
3559 /* Set up in the reservation set RESERVS that unit with UNIT_NUM is
3560 used on CYCLE_NUM. */
3562 test_unit_reserv (reserv_sets_t reservs
, int cycle_num
, int unit_num
)
3564 gcc_assert (cycle_num
< max_cycles_num
);
3565 return bitmap_bit_p (reservs
, cycle_num
* els_in_cycle_reserv
3566 * sizeof (set_el_t
) * CHAR_BIT
+ unit_num
);
3569 /* The function checks that the reservation sets are intersected,
3570 i.e. there is a unit reservation on a cycle in both reservation
3573 reserv_sets_are_intersected (reserv_sets_t operand_1
,
3574 reserv_sets_t operand_2
)
3578 set_el_t
*cycle_ptr_1
;
3579 set_el_t
*cycle_ptr_2
;
3581 gcc_assert (operand_1
&& operand_2
);
3582 for (el_ptr_1
= operand_1
, el_ptr_2
= operand_2
;
3583 el_ptr_1
< operand_1
+ els_in_reservs
;
3584 el_ptr_1
++, el_ptr_2
++)
3585 if (*el_ptr_1
& *el_ptr_2
)
3587 reserv_sets_or (temp_reserv
, operand_1
, operand_2
);
3588 for (cycle_ptr_1
= operand_1
, cycle_ptr_2
= operand_2
;
3589 cycle_ptr_1
< operand_1
+ els_in_reservs
;
3590 cycle_ptr_1
+= els_in_cycle_reserv
, cycle_ptr_2
+= els_in_cycle_reserv
)
3592 for (el_ptr_1
= cycle_ptr_1
, el_ptr_2
= get_excl_set (cycle_ptr_2
);
3593 el_ptr_1
< cycle_ptr_1
+ els_in_cycle_reserv
;
3594 el_ptr_1
++, el_ptr_2
++)
3595 if (*el_ptr_1
& *el_ptr_2
)
3597 if (!check_presence_pattern_sets (cycle_ptr_1
, cycle_ptr_2
, FALSE
))
3599 if (!check_presence_pattern_sets (temp_reserv
+ (cycle_ptr_2
3603 if (!check_absence_pattern_sets (cycle_ptr_1
, cycle_ptr_2
, FALSE
))
3605 if (!check_absence_pattern_sets (temp_reserv
+ (cycle_ptr_2
- operand_2
),
3612 /* The function sets up RESULT bits by bits of OPERAND shifted on one
3613 cpu cycle. The remaining bits of OPERAND (representing the last
3614 cycle unit reservations) are not changed. */
3616 reserv_sets_shift (reserv_sets_t result
, reserv_sets_t operand
)
3620 gcc_assert (result
&& operand
&& result
!= operand
);
3621 for (i
= els_in_cycle_reserv
; i
< els_in_reservs
; i
++)
3622 result
[i
- els_in_cycle_reserv
] = operand
[i
];
3625 /* OR of the reservation sets. */
3627 reserv_sets_or (reserv_sets_t result
, reserv_sets_t operand_1
,
3628 reserv_sets_t operand_2
)
3632 set_el_t
*result_set_el_ptr
;
3634 gcc_assert (result
&& operand_1
&& operand_2
);
3635 for (el_ptr_1
= operand_1
, el_ptr_2
= operand_2
, result_set_el_ptr
= result
;
3636 el_ptr_1
< operand_1
+ els_in_reservs
;
3637 el_ptr_1
++, el_ptr_2
++, result_set_el_ptr
++)
3638 *result_set_el_ptr
= *el_ptr_1
| *el_ptr_2
;
3641 /* AND of the reservation sets. */
3643 reserv_sets_and (reserv_sets_t result
, reserv_sets_t operand_1
,
3644 reserv_sets_t operand_2
)
3648 set_el_t
*result_set_el_ptr
;
3650 gcc_assert (result
&& operand_1
&& operand_2
);
3651 for (el_ptr_1
= operand_1
, el_ptr_2
= operand_2
, result_set_el_ptr
= result
;
3652 el_ptr_1
< operand_1
+ els_in_reservs
;
3653 el_ptr_1
++, el_ptr_2
++, result_set_el_ptr
++)
3654 *result_set_el_ptr
= *el_ptr_1
& *el_ptr_2
;
3657 /* The function outputs string representation of units reservation on
3658 cycle START_CYCLE in the reservation set. The function uses repeat
3659 construction if REPETITION_NUM > 1. */
3661 output_cycle_reservs (FILE *f
, reserv_sets_t reservs
, int start_cycle
,
3665 int reserved_units_num
;
3667 reserved_units_num
= 0;
3668 for (unit_num
= 0; unit_num
< description
->units_num
; unit_num
++)
3669 if (bitmap_bit_p (reservs
, start_cycle
* els_in_cycle_reserv
3670 * sizeof (set_el_t
) * CHAR_BIT
+ unit_num
))
3671 reserved_units_num
++;
3672 gcc_assert (repetition_num
> 0);
3673 if (repetition_num
!= 1 && reserved_units_num
> 1)
3675 reserved_units_num
= 0;
3677 unit_num
< description
->units_num
;
3679 if (bitmap_bit_p (reservs
, start_cycle
* els_in_cycle_reserv
3680 * sizeof (set_el_t
) * CHAR_BIT
+ unit_num
))
3682 if (reserved_units_num
!= 0)
3684 reserved_units_num
++;
3685 fprintf (f
, "%s", units_array
[unit_num
]->name
);
3687 if (reserved_units_num
== 0)
3688 fprintf (f
, NOTHING_NAME
);
3689 gcc_assert (repetition_num
> 0);
3690 if (repetition_num
!= 1 && reserved_units_num
> 1)
3692 if (repetition_num
!= 1)
3693 fprintf (f
, "*%d", repetition_num
);
3696 /* The function outputs string representation of units reservation in
3697 the reservation set. */
3699 output_reserv_sets (FILE *f
, reserv_sets_t reservs
)
3701 int start_cycle
= 0;
3706 for (cycle
= 0; cycle
< max_cycles_num
; cycle
++)
3707 if (repetition_num
== 0)
3710 start_cycle
= cycle
;
3713 ((char *) reservs
+ start_cycle
* els_in_cycle_reserv
3714 * sizeof (set_el_t
),
3715 (char *) reservs
+ cycle
* els_in_cycle_reserv
3716 * sizeof (set_el_t
),
3717 els_in_cycle_reserv
* sizeof (set_el_t
)) == 0)
3721 if (start_cycle
!= 0)
3723 output_cycle_reservs (f
, reservs
, start_cycle
, repetition_num
);
3725 start_cycle
= cycle
;
3727 if (start_cycle
< max_cycles_num
)
3729 if (start_cycle
!= 0)
3731 output_cycle_reservs (f
, reservs
, start_cycle
, repetition_num
);
3735 /* The following function returns free node state for AUTOMATON. It
3736 may be new allocated node or node freed earlier. The function also
3737 allocates reservation set if WITH_RESERVS has nonzero value. */
3739 get_free_state (int with_reservs
, automaton_t automaton
)
3743 gcc_assert (max_cycles_num
> 0 && automaton
);
3744 if (first_free_state
)
3746 result
= first_free_state
;
3747 first_free_state
= result
->next_equiv_class_state
;
3749 result
->next_equiv_class_state
= NULL
;
3750 result
->automaton
= automaton
;
3751 result
->first_out_arc
= NULL
;
3752 result
->it_was_placed_in_stack_for_NDFA_forming
= 0;
3753 result
->it_was_placed_in_stack_for_DFA_forming
= 0;
3754 result
->component_states
= NULL
;
3759 allocated_states_num
++;
3761 result
= XCREATENODE (struct state
);
3762 result
->automaton
= automaton
;
3763 result
->first_out_arc
= NULL
;
3764 result
->unique_num
= curr_unique_state_num
;
3765 curr_unique_state_num
++;
3769 if (result
->reservs
== NULL
)
3770 result
->reservs
= alloc_empty_reserv_sets ();
3772 memset (result
->reservs
, 0, els_in_reservs
* sizeof (set_el_t
));
3777 /* The function frees node STATE. */
3779 free_state (state_t state
)
3781 free_alt_states (state
->component_states
);
3782 state
->next_equiv_class_state
= first_free_state
;
3783 first_free_state
= state
;
3786 /* Hash value of STATE. If STATE represents deterministic state it is
3787 simply hash value of the corresponding reservation set. Otherwise
3788 it is formed from hash values of the component deterministic
3789 states. One more key is order number of state automaton. */
3791 state_hash (const void *state
)
3793 unsigned int hash_value
;
3794 alt_state_t alt_state
;
3796 if (((const_state_t
) state
)->component_states
== NULL
)
3797 hash_value
= reserv_sets_hash_value (((const_state_t
) state
)->reservs
);
3801 for (alt_state
= ((const_state_t
) state
)->component_states
;
3803 alt_state
= alt_state
->next_sorted_alt_state
)
3804 hash_value
= (((hash_value
>> (sizeof (unsigned) - 1) * CHAR_BIT
)
3805 | (hash_value
<< CHAR_BIT
))
3806 + alt_state
->state
->unique_num
);
3808 hash_value
= (((hash_value
>> (sizeof (unsigned) - 1) * CHAR_BIT
)
3809 | (hash_value
<< CHAR_BIT
))
3810 + ((const_state_t
) state
)->automaton
->automaton_order_num
);
3814 /* Return nonzero value if the states are the same. */
3816 state_eq_p (const void *state_1
, const void *state_2
)
3818 alt_state_t alt_state_1
;
3819 alt_state_t alt_state_2
;
3821 if (((const_state_t
) state_1
)->automaton
!= ((const_state_t
) state_2
)->automaton
)
3823 else if (((const_state_t
) state_1
)->component_states
== NULL
3824 && ((const_state_t
) state_2
)->component_states
== NULL
)
3825 return reserv_sets_eq (((const_state_t
) state_1
)->reservs
,
3826 ((const_state_t
) state_2
)->reservs
);
3827 else if (((const_state_t
) state_1
)->component_states
!= NULL
3828 && ((const_state_t
) state_2
)->component_states
!= NULL
)
3830 for (alt_state_1
= ((const_state_t
) state_1
)->component_states
,
3831 alt_state_2
= ((const_state_t
) state_2
)->component_states
;
3832 alt_state_1
!= NULL
&& alt_state_2
!= NULL
;
3833 alt_state_1
= alt_state_1
->next_sorted_alt_state
,
3834 alt_state_2
= alt_state_2
->next_sorted_alt_state
)
3835 /* All state in the list must be already in the hash table.
3836 Also the lists must be sorted. */
3837 if (alt_state_1
->state
!= alt_state_2
->state
)
3839 return alt_state_1
== alt_state_2
;
3845 /* Insert STATE into the state table. */
3847 insert_state (state_t state
)
3851 entry_ptr
= htab_find_slot (state_table
, (void *) state
, INSERT
);
3852 if (*entry_ptr
== NULL
)
3853 *entry_ptr
= (void *) state
;
3854 return (state_t
) *entry_ptr
;
3857 /* Add reservation of unit with UNIT_NUM on cycle CYCLE_NUM to
3858 deterministic STATE. */
3860 set_state_reserv (state_t state
, int cycle_num
, int unit_num
)
3862 set_unit_reserv (state
->reservs
, cycle_num
, unit_num
);
3865 /* Return nonzero value if the deterministic states contains a
3866 reservation of the same cpu unit on the same cpu cycle. */
3868 intersected_state_reservs_p (state_t state1
, state_t state2
)
3870 gcc_assert (state1
->automaton
== state2
->automaton
);
3871 return reserv_sets_are_intersected (state1
->reservs
, state2
->reservs
);
3874 /* Return deterministic state (inserted into the table) which
3875 representing the automaton state which is union of reservations of
3876 the deterministic states masked by RESERVS. */
3878 states_union (state_t state1
, state_t state2
, reserv_sets_t reservs
)
3881 state_t state_in_table
;
3883 gcc_assert (state1
->automaton
== state2
->automaton
);
3884 result
= get_free_state (1, state1
->automaton
);
3885 reserv_sets_or (result
->reservs
, state1
->reservs
, state2
->reservs
);
3886 reserv_sets_and (result
->reservs
, result
->reservs
, reservs
);
3887 state_in_table
= insert_state (result
);
3888 if (result
!= state_in_table
)
3890 free_state (result
);
3891 result
= state_in_table
;
3896 /* Return deterministic state (inserted into the table) which
3897 represent the automaton state is obtained from deterministic STATE
3898 by advancing cpu cycle and masking by RESERVS. */
3900 state_shift (state_t state
, reserv_sets_t reservs
)
3903 state_t state_in_table
;
3905 result
= get_free_state (1, state
->automaton
);
3906 reserv_sets_shift (result
->reservs
, state
->reservs
);
3907 reserv_sets_and (result
->reservs
, result
->reservs
, reservs
);
3908 state_in_table
= insert_state (result
);
3909 if (result
!= state_in_table
)
3911 free_state (result
);
3912 result
= state_in_table
;
3917 /* Initialization of the abstract data. */
3919 initiate_states (void)
3924 if (description
->units_num
)
3925 units_array
= XNEWVEC (unit_decl_t
, description
->units_num
);
3929 for (i
= 0; i
< description
->decls_num
; i
++)
3931 decl
= description
->decls
[i
];
3932 if (decl
->mode
== dm_unit
)
3933 units_array
[DECL_UNIT (decl
)->unit_num
] = DECL_UNIT (decl
);
3935 max_cycles_num
= description
->max_insn_reserv_cycles
;
3937 = ((description
->units_num
+ sizeof (set_el_t
) * CHAR_BIT
- 1)
3938 / (sizeof (set_el_t
) * CHAR_BIT
));
3939 els_in_reservs
= els_in_cycle_reserv
* max_cycles_num
;
3940 curr_unique_state_num
= 0;
3941 initiate_alt_states ();
3942 state_table
= htab_create (1500, state_hash
, state_eq_p
, (htab_del
) 0);
3943 temp_reserv
= alloc_empty_reserv_sets ();
3946 /* Finishing work with the abstract data. */
3948 finish_states (void)
3952 htab_delete (state_table
);
3953 first_free_state
= NULL
;
3954 finish_alt_states ();
3959 /* Abstract data `arcs'. */
3961 /* List of free arcs. */
3962 static arc_t first_free_arc
;
3965 /* The following variables is maximal number of allocated nodes
3967 static int allocated_arcs_num
= 0;
3970 /* The function frees node ARC. */
3972 free_arc (arc_t arc
)
3974 arc
->next_out_arc
= first_free_arc
;
3975 first_free_arc
= arc
;
3978 /* The function removes and frees ARC staring from FROM_STATE. */
3980 remove_arc (state_t from_state
, arc_t arc
)
3986 for (prev_arc
= NULL
, curr_arc
= from_state
->first_out_arc
;
3988 prev_arc
= curr_arc
, curr_arc
= curr_arc
->next_out_arc
)
3989 if (curr_arc
== arc
)
3991 gcc_assert (curr_arc
);
3992 if (prev_arc
== NULL
)
3993 from_state
->first_out_arc
= arc
->next_out_arc
;
3995 prev_arc
->next_out_arc
= arc
->next_out_arc
;
3996 from_state
->num_out_arcs
--;
4000 /* The functions returns arc with given characteristics (or NULL if
4001 the arc does not exist). */
4003 find_arc (state_t from_state
, state_t to_state
, ainsn_t insn
)
4007 for (arc
= first_out_arc (from_state
); arc
!= NULL
; arc
= next_out_arc (arc
))
4008 if (arc
->insn
== insn
4009 && (arc
->to_state
== to_state
4011 /* Any arc is good enough for a collapse-ndfa transition. */
4012 && (insn
->insn_reserv_decl
4013 == DECL_INSN_RESERV (collapse_ndfa_insn_decl
)))))
4018 /* The function adds arc from FROM_STATE to TO_STATE marked by AINSN,
4019 unless such an arc already exists. */
4021 add_arc (state_t from_state
, state_t to_state
, ainsn_t ainsn
)
4025 new_arc
= find_arc (from_state
, to_state
, ainsn
);
4026 if (new_arc
!= NULL
)
4028 if (first_free_arc
== NULL
)
4031 allocated_arcs_num
++;
4033 new_arc
= XCREATENODE (struct arc
);
4034 new_arc
->to_state
= NULL
;
4035 new_arc
->insn
= NULL
;
4036 new_arc
->next_out_arc
= NULL
;
4040 new_arc
= first_free_arc
;
4041 first_free_arc
= first_free_arc
->next_out_arc
;
4043 new_arc
->to_state
= to_state
;
4044 new_arc
->insn
= ainsn
;
4045 ainsn
->arc_exists_p
= 1;
4046 new_arc
->next_out_arc
= from_state
->first_out_arc
;
4047 from_state
->first_out_arc
= new_arc
;
4048 from_state
->num_out_arcs
++;
4049 new_arc
->next_arc_marked_by_insn
= NULL
;
4052 /* The function returns the first arc starting from STATE. */
4054 first_out_arc (const_state_t state
)
4056 return state
->first_out_arc
;
4059 /* The function returns next out arc after ARC. */
4061 next_out_arc (arc_t arc
)
4063 return arc
->next_out_arc
;
4066 /* Initialization of the abstract data. */
4068 initiate_arcs (void)
4070 first_free_arc
= NULL
;
4073 /* Finishing work with the abstract data. */
4081 /* Abstract data `automata lists'. */
4083 /* List of free states. */
4084 static automata_list_el_t first_free_automata_list_el
;
4086 /* The list being formed. */
4087 static automata_list_el_t current_automata_list
;
4089 /* Hash table of automata lists. */
4090 static htab_t automata_list_table
;
4092 /* The following function returns free automata list el. It may be
4093 new allocated node or node freed earlier. */
4094 static automata_list_el_t
4095 get_free_automata_list_el (void)
4097 automata_list_el_t result
;
4099 if (first_free_automata_list_el
!= NULL
)
4101 result
= first_free_automata_list_el
;
4102 first_free_automata_list_el
4103 = first_free_automata_list_el
->next_automata_list_el
;
4106 result
= XCREATENODE (struct automata_list_el
);
4107 result
->automaton
= NULL
;
4108 result
->next_automata_list_el
= NULL
;
4112 /* The function frees node AUTOMATA_LIST_EL. */
4114 free_automata_list_el (automata_list_el_t automata_list_el
)
4116 if (automata_list_el
== NULL
)
4118 automata_list_el
->next_automata_list_el
= first_free_automata_list_el
;
4119 first_free_automata_list_el
= automata_list_el
;
4122 /* The function frees list AUTOMATA_LIST. */
4124 free_automata_list (automata_list_el_t automata_list
)
4126 automata_list_el_t curr_automata_list_el
;
4127 automata_list_el_t next_automata_list_el
;
4129 for (curr_automata_list_el
= automata_list
;
4130 curr_automata_list_el
!= NULL
;
4131 curr_automata_list_el
= next_automata_list_el
)
4133 next_automata_list_el
= curr_automata_list_el
->next_automata_list_el
;
4134 free_automata_list_el (curr_automata_list_el
);
4138 /* Hash value of AUTOMATA_LIST. */
4140 automata_list_hash (const void *automata_list
)
4142 unsigned int hash_value
;
4143 const_automata_list_el_t curr_automata_list_el
;
4146 for (curr_automata_list_el
= (const_automata_list_el_t
) automata_list
;
4147 curr_automata_list_el
!= NULL
;
4148 curr_automata_list_el
= curr_automata_list_el
->next_automata_list_el
)
4149 hash_value
= (((hash_value
>> (sizeof (unsigned) - 1) * CHAR_BIT
)
4150 | (hash_value
<< CHAR_BIT
))
4151 + curr_automata_list_el
->automaton
->automaton_order_num
);
4155 /* Return nonzero value if the automata_lists are the same. */
4157 automata_list_eq_p (const void *automata_list_1
, const void *automata_list_2
)
4159 const_automata_list_el_t automata_list_el_1
;
4160 const_automata_list_el_t automata_list_el_2
;
4162 for (automata_list_el_1
= (const_automata_list_el_t
) automata_list_1
,
4163 automata_list_el_2
= (const_automata_list_el_t
) automata_list_2
;
4164 automata_list_el_1
!= NULL
&& automata_list_el_2
!= NULL
;
4165 automata_list_el_1
= automata_list_el_1
->next_automata_list_el
,
4166 automata_list_el_2
= automata_list_el_2
->next_automata_list_el
)
4167 if (automata_list_el_1
->automaton
!= automata_list_el_2
->automaton
)
4169 return automata_list_el_1
== automata_list_el_2
;
4172 /* Initialization of the abstract data. */
4174 initiate_automata_lists (void)
4176 first_free_automata_list_el
= NULL
;
4177 automata_list_table
= htab_create (1500, automata_list_hash
,
4178 automata_list_eq_p
, (htab_del
) 0);
4181 /* The following function starts new automata list and makes it the
4184 automata_list_start (void)
4186 current_automata_list
= NULL
;
4189 /* The following function adds AUTOMATON to the current list. */
4191 automata_list_add (automaton_t automaton
)
4193 automata_list_el_t el
;
4195 el
= get_free_automata_list_el ();
4196 el
->automaton
= automaton
;
4197 el
->next_automata_list_el
= current_automata_list
;
4198 current_automata_list
= el
;
4201 /* The following function finishes forming the current list, inserts
4202 it into the table and returns it. */
4203 static automata_list_el_t
4204 automata_list_finish (void)
4208 if (current_automata_list
== NULL
)
4210 entry_ptr
= htab_find_slot (automata_list_table
,
4211 (void *) current_automata_list
, INSERT
);
4212 if (*entry_ptr
== NULL
)
4213 *entry_ptr
= (void *) current_automata_list
;
4215 free_automata_list (current_automata_list
);
4216 current_automata_list
= NULL
;
4217 return (automata_list_el_t
) *entry_ptr
;
4220 /* Finishing work with the abstract data. */
4222 finish_automata_lists (void)
4224 htab_delete (automata_list_table
);
4229 /* The page contains abstract data for work with exclusion sets (see
4230 exclusion_set in file rtl.def). */
4232 /* The following variable refers to an exclusion set returned by
4233 get_excl_set. This is bit string of length equal to cpu units
4234 number. If exclusion set for given unit contains 1 for a unit,
4235 then simultaneous reservation of the units is prohibited. */
4236 static reserv_sets_t excl_set
;
4238 /* The array contains exclusion sets for each unit. */
4239 static reserv_sets_t
*unit_excl_set_table
;
4241 /* The following function forms the array containing exclusion sets
4244 initiate_excl_sets (void)
4247 reserv_sets_t unit_excl_set
;
4251 obstack_blank (&irp
, els_in_cycle_reserv
* sizeof (set_el_t
));
4252 excl_set
= (reserv_sets_t
) obstack_base (&irp
);
4253 obstack_finish (&irp
);
4254 obstack_blank (&irp
, description
->units_num
* sizeof (reserv_sets_t
));
4255 unit_excl_set_table
= (reserv_sets_t
*) obstack_base (&irp
);
4256 obstack_finish (&irp
);
4257 /* Evaluate unit exclusion sets. */
4258 for (i
= 0; i
< description
->decls_num
; i
++)
4260 decl
= description
->decls
[i
];
4261 if (decl
->mode
== dm_unit
)
4263 obstack_blank (&irp
, els_in_cycle_reserv
* sizeof (set_el_t
));
4264 unit_excl_set
= (reserv_sets_t
) obstack_base (&irp
);
4265 obstack_finish (&irp
);
4266 memset (unit_excl_set
, 0, els_in_cycle_reserv
* sizeof (set_el_t
));
4267 for (el
= DECL_UNIT (decl
)->excl_list
;
4269 el
= el
->next_unit_set_el
)
4271 bitmap_set_bit (unit_excl_set
, el
->unit_decl
->unit_num
);
4272 el
->unit_decl
->in_set_p
= TRUE
;
4274 unit_excl_set_table
[DECL_UNIT (decl
)->unit_num
] = unit_excl_set
;
4279 /* The function sets up and return EXCL_SET which is union of
4280 exclusion sets for each unit in IN_SET. */
4281 static reserv_sets_t
4282 get_excl_set (reserv_sets_t in_set
)
4289 memset (excl_set
, 0, els_in_cycle_reserv
* sizeof (set_el_t
));
4290 for (el
= 0; el
< els_in_cycle_reserv
; el
++)
4292 for (i
= 0; i
< CHAR_BIT
* sizeof (set_el_t
); i
++)
4293 if ((in_set
[el
] >> i
) & 1)
4295 start_unit_num
= el
* CHAR_BIT
* sizeof (set_el_t
) + i
;
4296 if (start_unit_num
>= description
->units_num
)
4298 for (unit_num
= 0; unit_num
< els_in_cycle_reserv
; unit_num
++)
4301 |= unit_excl_set_table
[start_unit_num
] [unit_num
];
4309 /* The page contains abstract data for work with presence/absence
4310 pattern sets (see presence_set/absence_set in file rtl.def). */
4312 /* The following arrays contain correspondingly presence, final
4313 presence, absence, and final absence patterns for each unit. */
4314 static pattern_reserv_t
*unit_presence_set_table
;
4315 static pattern_reserv_t
*unit_final_presence_set_table
;
4316 static pattern_reserv_t
*unit_absence_set_table
;
4317 static pattern_reserv_t
*unit_final_absence_set_table
;
4319 /* The following function forms list of reservation sets for given
4321 static pattern_reserv_t
4322 form_reserv_sets_list (pattern_set_el_t pattern_list
)
4324 pattern_set_el_t el
;
4325 pattern_reserv_t first
, curr
, prev
;
4328 prev
= first
= NULL
;
4329 for (el
= pattern_list
; el
!= NULL
; el
= el
->next_pattern_set_el
)
4331 curr
= XCREATENODE (struct pattern_reserv
);
4332 curr
->reserv
= alloc_empty_reserv_sets ();
4333 curr
->next_pattern_reserv
= NULL
;
4334 for (i
= 0; i
< el
->units_num
; i
++)
4336 bitmap_set_bit (curr
->reserv
, el
->unit_decls
[i
]->unit_num
);
4337 el
->unit_decls
[i
]->in_set_p
= TRUE
;
4340 prev
->next_pattern_reserv
= curr
;
4348 /* The following function forms the array containing presence and
4349 absence pattern sets for each unit. */
4351 initiate_presence_absence_pattern_sets (void)
4356 obstack_blank (&irp
, description
->units_num
* sizeof (pattern_reserv_t
));
4357 unit_presence_set_table
= (pattern_reserv_t
*) obstack_base (&irp
);
4358 obstack_finish (&irp
);
4359 obstack_blank (&irp
, description
->units_num
* sizeof (pattern_reserv_t
));
4360 unit_final_presence_set_table
= (pattern_reserv_t
*) obstack_base (&irp
);
4361 obstack_finish (&irp
);
4362 obstack_blank (&irp
, description
->units_num
* sizeof (pattern_reserv_t
));
4363 unit_absence_set_table
= (pattern_reserv_t
*) obstack_base (&irp
);
4364 obstack_finish (&irp
);
4365 obstack_blank (&irp
, description
->units_num
* sizeof (pattern_reserv_t
));
4366 unit_final_absence_set_table
= (pattern_reserv_t
*) obstack_base (&irp
);
4367 obstack_finish (&irp
);
4368 /* Evaluate unit presence/absence sets. */
4369 for (i
= 0; i
< description
->decls_num
; i
++)
4371 decl
= description
->decls
[i
];
4372 if (decl
->mode
== dm_unit
)
4374 unit_presence_set_table
[DECL_UNIT (decl
)->unit_num
]
4375 = form_reserv_sets_list (DECL_UNIT (decl
)->presence_list
);
4376 unit_final_presence_set_table
[DECL_UNIT (decl
)->unit_num
]
4377 = form_reserv_sets_list (DECL_UNIT (decl
)->final_presence_list
);
4378 unit_absence_set_table
[DECL_UNIT (decl
)->unit_num
]
4379 = form_reserv_sets_list (DECL_UNIT (decl
)->absence_list
);
4380 unit_final_absence_set_table
[DECL_UNIT (decl
)->unit_num
]
4381 = form_reserv_sets_list (DECL_UNIT (decl
)->final_absence_list
);
4386 /* The function checks that CHECKED_SET satisfies all presence pattern
4387 sets for units in ORIGINAL_SET. The function returns TRUE if it
4390 check_presence_pattern_sets (reserv_sets_t checked_set
,
4391 reserv_sets_t original_set
,
4399 pattern_reserv_t pat_reserv
;
4401 for (el
= 0; el
< els_in_cycle_reserv
; el
++)
4402 if (original_set
[el
])
4403 for (i
= 0; i
< CHAR_BIT
* sizeof (set_el_t
); i
++)
4404 if ((original_set
[el
] >> i
) & 1)
4406 start_unit_num
= el
* CHAR_BIT
* sizeof (set_el_t
) + i
;
4407 if (start_unit_num
>= description
->units_num
)
4410 && unit_final_presence_set_table
[start_unit_num
] == NULL
)
4412 && unit_presence_set_table
[start_unit_num
] == NULL
))
4415 for (pat_reserv
= (final_p
4416 ? unit_final_presence_set_table
[start_unit_num
]
4417 : unit_presence_set_table
[start_unit_num
]);
4419 pat_reserv
= pat_reserv
->next_pattern_reserv
)
4421 for (unit_num
= 0; unit_num
< els_in_cycle_reserv
; unit_num
++)
4422 if ((checked_set
[unit_num
] & pat_reserv
->reserv
[unit_num
])
4423 != pat_reserv
->reserv
[unit_num
])
4425 presence_p
= presence_p
|| unit_num
>= els_in_cycle_reserv
;
4433 /* The function checks that CHECKED_SET satisfies all absence pattern
4434 sets for units in ORIGINAL_SET. The function returns TRUE if it
4437 check_absence_pattern_sets (reserv_sets_t checked_set
,
4438 reserv_sets_t original_set
,
4445 pattern_reserv_t pat_reserv
;
4447 for (el
= 0; el
< els_in_cycle_reserv
; el
++)
4448 if (original_set
[el
])
4449 for (i
= 0; i
< CHAR_BIT
* sizeof (set_el_t
); i
++)
4450 if ((original_set
[el
] >> i
) & 1)
4452 start_unit_num
= el
* CHAR_BIT
* sizeof (set_el_t
) + i
;
4453 if (start_unit_num
>= description
->units_num
)
4455 for (pat_reserv
= (final_p
4456 ? unit_final_absence_set_table
[start_unit_num
]
4457 : unit_absence_set_table
[start_unit_num
]);
4459 pat_reserv
= pat_reserv
->next_pattern_reserv
)
4461 for (unit_num
= 0; unit_num
< els_in_cycle_reserv
; unit_num
++)
4462 if ((checked_set
[unit_num
] & pat_reserv
->reserv
[unit_num
])
4463 != pat_reserv
->reserv
[unit_num
]
4464 && pat_reserv
->reserv
[unit_num
])
4466 if (unit_num
>= els_in_cycle_reserv
)
4475 /* This page contains code for transformation of original reservations
4476 described in .md file. The main goal of transformations is
4477 simplifying reservation and lifting up all `|' on the top of IR
4478 reservation representation. */
4481 /* The following function makes copy of IR representation of
4482 reservation. The function also substitutes all reservations
4483 defined by define_reservation by corresponding value during making
4486 copy_insn_regexp (regexp_t regexp
)
4491 switch (regexp
->mode
)
4494 result
= copy_insn_regexp (REGEXP_RESERV (regexp
)->reserv_decl
->regexp
);
4498 result
= XCOPYNODE (struct regexp
, regexp
);
4502 result
= XCOPYNODE (struct regexp
, regexp
);
4503 REGEXP_REPEAT (result
)->regexp
4504 = copy_insn_regexp (REGEXP_REPEAT (regexp
)->regexp
);
4508 result
= XCOPYNODEVAR (struct regexp
, regexp
,
4509 sizeof (struct regexp
) + sizeof (regexp_t
)
4510 * (REGEXP_SEQUENCE (regexp
)->regexps_num
- 1));
4511 for (i
= 0; i
<REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
4512 REGEXP_SEQUENCE (result
)->regexps
[i
]
4513 = copy_insn_regexp (REGEXP_SEQUENCE (regexp
)->regexps
[i
]);
4517 result
= XCOPYNODEVAR (struct regexp
, regexp
,
4518 sizeof (struct regexp
) + sizeof (regexp_t
)
4519 * (REGEXP_ALLOF (regexp
)->regexps_num
- 1));
4520 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
4521 REGEXP_ALLOF (result
)->regexps
[i
]
4522 = copy_insn_regexp (REGEXP_ALLOF (regexp
)->regexps
[i
]);
4526 result
= XCOPYNODEVAR (struct regexp
, regexp
,
4527 sizeof (struct regexp
) + sizeof (regexp_t
)
4528 * (REGEXP_ONEOF (regexp
)->regexps_num
- 1));
4529 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
4530 REGEXP_ONEOF (result
)->regexps
[i
]
4531 = copy_insn_regexp (REGEXP_ONEOF (regexp
)->regexps
[i
]);
4535 result
= XCOPYNODE (struct regexp
, regexp
);
4544 /* The following variable is set up 1 if a transformation has been
4546 static int regexp_transformed_p
;
4548 /* The function makes transformation
4551 transform_1 (regexp_t regexp
)
4558 if (regexp
->mode
== rm_repeat
)
4560 repeat_num
= REGEXP_REPEAT (regexp
)->repeat_num
;
4561 gcc_assert (repeat_num
> 1);
4562 operand
= REGEXP_REPEAT (regexp
)->regexp
;
4564 regexp
= XCREATENODEVAR (struct regexp
, sizeof (struct regexp
)
4565 + sizeof (regexp_t
) * (repeat_num
- 1));
4566 regexp
->mode
= rm_sequence
;
4568 REGEXP_SEQUENCE (regexp
)->regexps_num
= repeat_num
;
4569 for (i
= 0; i
< repeat_num
; i
++)
4570 REGEXP_SEQUENCE (regexp
)->regexps
[i
] = copy_insn_regexp (operand
);
4571 regexp_transformed_p
= 1;
4576 /* The function makes transformations
4577 ...,(A,B,...),C,... -> ...,A,B,...,C,...
4578 ...+(A+B+...)+C+... -> ...+A+B+...+C+...
4579 ...|(A|B|...)|C|... -> ...|A|B|...|C|... */
4581 transform_2 (regexp_t regexp
)
4583 if (regexp
->mode
== rm_sequence
)
4585 regexp_t sequence
= NULL
;
4587 int sequence_index
= 0;
4590 for (i
= 0; i
< REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
4591 if (REGEXP_SEQUENCE (regexp
)->regexps
[i
]->mode
== rm_sequence
)
4594 sequence
= REGEXP_SEQUENCE (regexp
)->regexps
[i
];
4597 if (i
< REGEXP_SEQUENCE (regexp
)->regexps_num
)
4599 gcc_assert (REGEXP_SEQUENCE (sequence
)->regexps_num
> 1
4600 && REGEXP_SEQUENCE (regexp
)->regexps_num
> 1);
4601 result
= XCREATENODEVAR (struct regexp
, sizeof (struct regexp
)
4603 * (REGEXP_SEQUENCE (regexp
)->regexps_num
4604 + REGEXP_SEQUENCE (sequence
)->regexps_num
4606 result
->mode
= rm_sequence
;
4607 result
->pos
= regexp
->pos
;
4608 REGEXP_SEQUENCE (result
)->regexps_num
4609 = (REGEXP_SEQUENCE (regexp
)->regexps_num
4610 + REGEXP_SEQUENCE (sequence
)->regexps_num
- 1);
4611 for (i
= 0; i
< REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
4612 if (i
< sequence_index
)
4613 REGEXP_SEQUENCE (result
)->regexps
[i
]
4614 = copy_insn_regexp (REGEXP_SEQUENCE (regexp
)->regexps
[i
]);
4615 else if (i
> sequence_index
)
4616 REGEXP_SEQUENCE (result
)->regexps
4617 [i
+ REGEXP_SEQUENCE (sequence
)->regexps_num
- 1]
4618 = copy_insn_regexp (REGEXP_SEQUENCE (regexp
)->regexps
[i
]);
4620 for (j
= 0; j
< REGEXP_SEQUENCE (sequence
)->regexps_num
; j
++)
4621 REGEXP_SEQUENCE (result
)->regexps
[i
+ j
]
4622 = copy_insn_regexp (REGEXP_SEQUENCE (sequence
)->regexps
[j
]);
4623 regexp_transformed_p
= 1;
4627 else if (regexp
->mode
== rm_allof
)
4629 regexp_t allof
= NULL
;
4631 int allof_index
= 0;
4634 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
4635 if (REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
== rm_allof
)
4638 allof
= REGEXP_ALLOF (regexp
)->regexps
[i
];
4641 if (i
< REGEXP_ALLOF (regexp
)->regexps_num
)
4643 gcc_assert (REGEXP_ALLOF (allof
)->regexps_num
> 1
4644 && REGEXP_ALLOF (regexp
)->regexps_num
> 1);
4645 result
= XCREATENODEVAR (struct regexp
, sizeof (struct regexp
)
4647 * (REGEXP_ALLOF (regexp
)->regexps_num
4648 + REGEXP_ALLOF (allof
)->regexps_num
- 2));
4649 result
->mode
= rm_allof
;
4650 result
->pos
= regexp
->pos
;
4651 REGEXP_ALLOF (result
)->regexps_num
4652 = (REGEXP_ALLOF (regexp
)->regexps_num
4653 + REGEXP_ALLOF (allof
)->regexps_num
- 1);
4654 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
4655 if (i
< allof_index
)
4656 REGEXP_ALLOF (result
)->regexps
[i
]
4657 = copy_insn_regexp (REGEXP_ALLOF (regexp
)->regexps
[i
]);
4658 else if (i
> allof_index
)
4659 REGEXP_ALLOF (result
)->regexps
4660 [i
+ REGEXP_ALLOF (allof
)->regexps_num
- 1]
4661 = copy_insn_regexp (REGEXP_ALLOF (regexp
)->regexps
[i
]);
4663 for (j
= 0; j
< REGEXP_ALLOF (allof
)->regexps_num
; j
++)
4664 REGEXP_ALLOF (result
)->regexps
[i
+ j
]
4665 = copy_insn_regexp (REGEXP_ALLOF (allof
)->regexps
[j
]);
4666 regexp_transformed_p
= 1;
4670 else if (regexp
->mode
== rm_oneof
)
4672 regexp_t oneof
= NULL
;
4674 int oneof_index
= 0;
4677 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
4678 if (REGEXP_ONEOF (regexp
)->regexps
[i
]->mode
== rm_oneof
)
4681 oneof
= REGEXP_ONEOF (regexp
)->regexps
[i
];
4684 if (i
< REGEXP_ONEOF (regexp
)->regexps_num
)
4686 gcc_assert (REGEXP_ONEOF (oneof
)->regexps_num
> 1
4687 && REGEXP_ONEOF (regexp
)->regexps_num
> 1);
4688 result
= XCREATENODEVAR (struct regexp
, sizeof (struct regexp
)
4690 * (REGEXP_ONEOF (regexp
)->regexps_num
4691 + REGEXP_ONEOF (oneof
)->regexps_num
- 2));
4692 result
->mode
= rm_oneof
;
4693 result
->pos
= regexp
->pos
;
4694 REGEXP_ONEOF (result
)->regexps_num
4695 = (REGEXP_ONEOF (regexp
)->regexps_num
4696 + REGEXP_ONEOF (oneof
)->regexps_num
- 1);
4697 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
4698 if (i
< oneof_index
)
4699 REGEXP_ONEOF (result
)->regexps
[i
]
4700 = copy_insn_regexp (REGEXP_ONEOF (regexp
)->regexps
[i
]);
4701 else if (i
> oneof_index
)
4702 REGEXP_ONEOF (result
)->regexps
4703 [i
+ REGEXP_ONEOF (oneof
)->regexps_num
- 1]
4704 = copy_insn_regexp (REGEXP_ONEOF (regexp
)->regexps
[i
]);
4706 for (j
= 0; j
< REGEXP_ONEOF (oneof
)->regexps_num
; j
++)
4707 REGEXP_ONEOF (result
)->regexps
[i
+ j
]
4708 = copy_insn_regexp (REGEXP_ONEOF (oneof
)->regexps
[j
]);
4709 regexp_transformed_p
= 1;
4716 /* The function makes transformations
4717 ...,A|B|...,C,... -> (...,A,C,...)|(...,B,C,...)|...
4718 ...+(A|B|...)+C+... -> (...+A+C+...)|(...+B+C+...)|...
4719 ...+(A,B,...)+C+... -> (...+A+C+...),B,...
4720 ...+(A,B,...)+(C,D,...) -> (A+C),(B+D),... */
4722 transform_3 (regexp_t regexp
)
4724 if (regexp
->mode
== rm_sequence
)
4726 regexp_t oneof
= NULL
;
4727 int oneof_index
= 0;
4732 for (i
= 0; i
<REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
4733 if (REGEXP_SEQUENCE (regexp
)->regexps
[i
]->mode
== rm_oneof
)
4736 oneof
= REGEXP_SEQUENCE (regexp
)->regexps
[i
];
4739 if (i
< REGEXP_SEQUENCE (regexp
)->regexps_num
)
4741 gcc_assert (REGEXP_ONEOF (oneof
)->regexps_num
> 1
4742 && REGEXP_SEQUENCE (regexp
)->regexps_num
> 1);
4743 result
= XCREATENODEVAR (struct regexp
, sizeof (struct regexp
)
4745 * (REGEXP_ONEOF (oneof
)->regexps_num
- 1));
4746 result
->mode
= rm_oneof
;
4747 result
->pos
= regexp
->pos
;
4748 REGEXP_ONEOF (result
)->regexps_num
4749 = REGEXP_ONEOF (oneof
)->regexps_num
;
4750 for (i
= 0; i
< REGEXP_ONEOF (result
)->regexps_num
; i
++)
4753 = XCREATENODEVAR (struct regexp
, sizeof (struct regexp
)
4755 * (REGEXP_SEQUENCE (regexp
)->regexps_num
- 1));
4756 sequence
->mode
= rm_sequence
;
4757 sequence
->pos
= regexp
->pos
;
4758 REGEXP_SEQUENCE (sequence
)->regexps_num
4759 = REGEXP_SEQUENCE (regexp
)->regexps_num
;
4760 REGEXP_ONEOF (result
)->regexps
[i
] = sequence
;
4761 for (j
= 0; j
< REGEXP_SEQUENCE (sequence
)->regexps_num
; j
++)
4762 if (j
!= oneof_index
)
4763 REGEXP_SEQUENCE (sequence
)->regexps
[j
]
4764 = copy_insn_regexp (REGEXP_SEQUENCE (regexp
)->regexps
[j
]);
4766 REGEXP_SEQUENCE (sequence
)->regexps
[j
]
4767 = copy_insn_regexp (REGEXP_ONEOF (oneof
)->regexps
[i
]);
4769 regexp_transformed_p
= 1;
4773 else if (regexp
->mode
== rm_allof
)
4775 regexp_t oneof
= NULL
;
4777 int oneof_index
= 0;
4778 int max_seq_length
, allof_length
;
4780 regexp_t allof
= NULL
;
4781 regexp_t allof_op
= NULL
;
4784 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
4785 if (REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
== rm_oneof
)
4788 oneof
= REGEXP_ALLOF (regexp
)->regexps
[i
];
4791 if (i
< REGEXP_ALLOF (regexp
)->regexps_num
)
4793 gcc_assert (REGEXP_ONEOF (oneof
)->regexps_num
> 1
4794 && REGEXP_ALLOF (regexp
)->regexps_num
> 1);
4795 result
= XCREATENODEVAR (struct regexp
, sizeof (struct regexp
)
4797 * (REGEXP_ONEOF (oneof
)->regexps_num
- 1));
4798 result
->mode
= rm_oneof
;
4799 result
->pos
= regexp
->pos
;
4800 REGEXP_ONEOF (result
)->regexps_num
4801 = REGEXP_ONEOF (oneof
)->regexps_num
;
4802 for (i
= 0; i
< REGEXP_ONEOF (result
)->regexps_num
; i
++)
4805 = XCREATENODEVAR (struct regexp
, sizeof (struct regexp
)
4807 * (REGEXP_ALLOF (regexp
)->regexps_num
- 1));
4808 allof
->mode
= rm_allof
;
4809 allof
->pos
= regexp
->pos
;
4810 REGEXP_ALLOF (allof
)->regexps_num
4811 = REGEXP_ALLOF (regexp
)->regexps_num
;
4812 REGEXP_ONEOF (result
)->regexps
[i
] = allof
;
4813 for (j
= 0; j
< REGEXP_ALLOF (allof
)->regexps_num
; j
++)
4814 if (j
!= oneof_index
)
4815 REGEXP_ALLOF (allof
)->regexps
[j
]
4816 = copy_insn_regexp (REGEXP_ALLOF (regexp
)->regexps
[j
]);
4818 REGEXP_ALLOF (allof
)->regexps
[j
]
4819 = copy_insn_regexp (REGEXP_ONEOF (oneof
)->regexps
[i
]);
4821 regexp_transformed_p
= 1;
4825 if (regexp
->mode
== rm_allof
)
4826 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
4828 switch (REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
)
4831 seq
= REGEXP_ALLOF (regexp
)->regexps
[i
];
4832 if (max_seq_length
< REGEXP_SEQUENCE (seq
)->regexps_num
)
4833 max_seq_length
= REGEXP_SEQUENCE (seq
)->regexps_num
;
4846 if (max_seq_length
!= 0)
4848 gcc_assert (max_seq_length
!= 1
4849 && REGEXP_ALLOF (regexp
)->regexps_num
> 1);
4850 result
= XCREATENODEVAR (struct regexp
, sizeof (struct regexp
)
4851 + sizeof (regexp_t
) * (max_seq_length
- 1));
4852 result
->mode
= rm_sequence
;
4853 result
->pos
= regexp
->pos
;
4854 REGEXP_SEQUENCE (result
)->regexps_num
= max_seq_length
;
4855 for (i
= 0; i
< max_seq_length
; i
++)
4858 for (j
= 0; j
< REGEXP_ALLOF (regexp
)->regexps_num
; j
++)
4859 switch (REGEXP_ALLOF (regexp
)->regexps
[j
]->mode
)
4862 if (i
< (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp
)
4863 ->regexps
[j
])->regexps_num
))
4866 = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp
)
4876 allof_op
= REGEXP_ALLOF (regexp
)->regexps
[j
];
4884 if (allof_length
== 1)
4885 REGEXP_SEQUENCE (result
)->regexps
[i
] = allof_op
;
4888 allof
= XCREATENODEVAR (struct regexp
, sizeof (struct regexp
)
4890 * (allof_length
- 1));
4891 allof
->mode
= rm_allof
;
4892 allof
->pos
= regexp
->pos
;
4893 REGEXP_ALLOF (allof
)->regexps_num
= allof_length
;
4894 REGEXP_SEQUENCE (result
)->regexps
[i
] = allof
;
4896 for (j
= 0; j
< REGEXP_ALLOF (regexp
)->regexps_num
; j
++)
4897 if (REGEXP_ALLOF (regexp
)->regexps
[j
]->mode
== rm_sequence
4899 (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp
)
4900 ->regexps
[j
])->regexps_num
)))
4902 allof_op
= (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp
)
4905 REGEXP_ALLOF (allof
)->regexps
[allof_length
]
4910 && (REGEXP_ALLOF (regexp
)->regexps
[j
]->mode
4912 || (REGEXP_ALLOF (regexp
)->regexps
[j
]->mode
4915 allof_op
= REGEXP_ALLOF (regexp
)->regexps
[j
];
4916 REGEXP_ALLOF (allof
)->regexps
[allof_length
]
4922 regexp_transformed_p
= 1;
4929 /* The function traverses IR of reservation and applies transformations
4930 implemented by FUNC. */
4932 regexp_transform_func (regexp_t regexp
, regexp_t (*func
) (regexp_t regexp
))
4936 switch (regexp
->mode
)
4939 for (i
= 0; i
< REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
4940 REGEXP_SEQUENCE (regexp
)->regexps
[i
]
4941 = regexp_transform_func (REGEXP_SEQUENCE (regexp
)->regexps
[i
],
4946 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
4947 REGEXP_ALLOF (regexp
)->regexps
[i
]
4948 = regexp_transform_func (REGEXP_ALLOF (regexp
)->regexps
[i
], func
);
4952 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
4953 REGEXP_ONEOF (regexp
)->regexps
[i
]
4954 = regexp_transform_func (REGEXP_ONEOF (regexp
)->regexps
[i
], func
);
4958 REGEXP_REPEAT (regexp
)->regexp
4959 = regexp_transform_func (REGEXP_REPEAT (regexp
)->regexp
, func
);
4969 return (*func
) (regexp
);
4972 /* The function applies all transformations for IR representation of
4973 reservation REGEXP. */
4975 transform_regexp (regexp_t regexp
)
4977 regexp
= regexp_transform_func (regexp
, transform_1
);
4980 regexp_transformed_p
= 0;
4981 regexp
= regexp_transform_func (regexp
, transform_2
);
4982 regexp
= regexp_transform_func (regexp
, transform_3
);
4984 while (regexp_transformed_p
);
4988 /* The function applies all transformations for reservations of all
4989 insn declarations. */
4991 transform_insn_regexps (void)
4996 transform_time
= create_ticker ();
4997 add_advance_cycle_insn_decl ();
4999 add_collapse_ndfa_insn_decl ();
5001 fprintf (stderr
, "Reservation transformation...");
5002 for (i
= 0; i
< description
->normal_decls_num
; i
++)
5004 decl
= description
->decls
[i
];
5005 if (decl
->mode
== dm_insn_reserv
)
5006 DECL_INSN_RESERV (decl
)->transformed_regexp
5007 = transform_regexp (copy_insn_regexp
5008 (DECL_INSN_RESERV (decl
)->regexp
));
5011 fprintf (stderr
, "done\n");
5012 ticker_off (&transform_time
);
5017 /* The following variable value is TRUE if the first annotated message
5018 about units to automata distribution has been output. */
5019 static int annotation_message_reported_p
;
5021 /* The vector contains all decls which are automata. */
5022 static vec
<decl_t
> automaton_decls
;
5024 /* The following structure describes usage of a unit in a reservation. */
5027 unit_decl_t unit_decl
;
5028 /* The following forms a list of units used on the same cycle in the
5029 same alternative. The list is ordered by the correspdoning unit
5030 declarations and there is no unit declaration duplication in the
5032 struct unit_usage
*next
;
5034 typedef struct unit_usage
*unit_usage_t
;
5037 /* Obstack for unit_usage structures. */
5038 static struct obstack unit_usages
;
5040 /* VLA for representation of array of pointers to unit usage
5041 structures. There is an element for each combination of
5042 (alternative number, cycle). Unit usages on given cycle in
5043 alternative with given number are referred through element with
5044 index equals to the cycle * number of all alternatives in the
5045 regexp + the alternative number. */
5046 static vec
<unit_usage_t
> cycle_alt_unit_usages
;
5048 /* The following function creates the structure unit_usage for UNIT on
5049 CYCLE in REGEXP alternative with ALT_NUM. The structure is made
5050 accessed through cycle_alt_unit_usages. */
5052 store_alt_unit_usage (regexp_t regexp
, regexp_t unit
, int cycle
,
5056 unit_decl_t unit_decl
;
5057 unit_usage_t unit_usage_ptr
, curr
, prev
;
5060 gcc_assert (regexp
&& regexp
->mode
== rm_oneof
5061 && alt_num
< REGEXP_ONEOF (regexp
)->regexps_num
);
5062 unit_decl
= REGEXP_UNIT (unit
)->unit_decl
;
5064 length
= (cycle
+ 1) * REGEXP_ONEOF (regexp
)->regexps_num
;
5065 while (cycle_alt_unit_usages
.length () < length
)
5066 cycle_alt_unit_usages
.safe_push (NULL
);
5068 index
= cycle
* REGEXP_ONEOF (regexp
)->regexps_num
+ alt_num
;
5070 for (curr
= cycle_alt_unit_usages
[index
];
5072 prev
= curr
, curr
= curr
->next
)
5073 if (curr
->unit_decl
>= unit_decl
)
5075 if (curr
!= NULL
&& curr
->unit_decl
== unit_decl
)
5077 obstack_blank (&unit_usages
, sizeof (struct unit_usage
));
5078 unit_usage_ptr
= (struct unit_usage
*) obstack_base (&unit_usages
);
5079 obstack_finish (&unit_usages
);
5080 unit_usage_ptr
->unit_decl
= unit_decl
;
5081 unit_decl
->last_distribution_check_cycle
= -1; /* undefined */
5082 unit_usage_ptr
->next
= curr
;
5084 cycle_alt_unit_usages
[index
] = unit_usage_ptr
;
5086 prev
->next
= unit_usage_ptr
;
5089 /* Return true if unit UNIT_DECL is present on the LIST. */
5091 unit_present_on_list_p (unit_usage_t list
, unit_decl_t unit_decl
)
5093 while (list
!= NULL
)
5095 if (list
->unit_decl
== unit_decl
)
5102 /* The function returns true if reservations of alternatives ALT1 and
5103 ALT2 are equal after excluding reservations of units of
5104 EXCLUDED_AUTOMATON_DECL. */
5106 equal_alternatives_p (int alt1
, int alt2
, int n_alts
,
5107 struct automaton_decl
*excluded_automaton_decl
)
5110 unit_usage_t list1
, list2
;
5113 i
< (int) cycle_alt_unit_usages
.length ();
5116 for (list1
= cycle_alt_unit_usages
[i
+ alt1
],
5117 list2
= cycle_alt_unit_usages
[i
+ alt2
];;
5118 list1
= list1
->next
, list2
= list2
->next
)
5120 while (list1
!= NULL
5121 && list1
->unit_decl
->automaton_decl
== excluded_automaton_decl
)
5122 list1
= list1
->next
;
5123 while (list2
!= NULL
5124 && list2
->unit_decl
->automaton_decl
== excluded_automaton_decl
)
5125 list2
= list2
->next
;
5126 if (list1
== NULL
|| list2
== NULL
)
5133 if (list1
->unit_decl
!= list2
->unit_decl
)
5141 /* The function processes given REGEXP to find units with the wrong
5144 check_regexp_units_distribution (const char *insn_reserv_name
,
5147 int i
, j
, k
, cycle
, start
, n_alts
, alt
, alt2
;
5148 bool annotation_reservation_message_reported_p
;
5149 regexp_t seq
, allof
, unit
;
5150 struct unit_usage
*unit_usage_ptr
;
5153 if (regexp
== NULL
|| regexp
->mode
!= rm_oneof
)
5155 /* Store all unit usages in the regexp: */
5156 obstack_init (&unit_usages
);
5157 cycle_alt_unit_usages
.create (10);
5159 for (i
= REGEXP_ONEOF (regexp
)->regexps_num
- 1; i
>= 0; i
--)
5161 seq
= REGEXP_ONEOF (regexp
)->regexps
[i
];
5165 for (j
= 0; j
< REGEXP_SEQUENCE (seq
)->regexps_num
; j
++)
5167 allof
= REGEXP_SEQUENCE (seq
)->regexps
[j
];
5168 switch (allof
->mode
)
5171 for (k
= 0; k
< REGEXP_ALLOF (allof
)->regexps_num
; k
++)
5173 unit
= REGEXP_ALLOF (allof
)->regexps
[k
];
5174 if (unit
->mode
== rm_unit
)
5175 store_alt_unit_usage (regexp
, unit
, j
, i
);
5177 gcc_assert (unit
->mode
== rm_nothing
);
5182 store_alt_unit_usage (regexp
, allof
, j
, i
);
5195 for (k
= 0; k
< REGEXP_ALLOF (seq
)->regexps_num
; k
++)
5197 unit
= REGEXP_ALLOF (seq
)->regexps
[k
];
5201 store_alt_unit_usage (regexp
, unit
, 0, i
);
5214 store_alt_unit_usage (regexp
, seq
, 0, i
);
5224 /* Check distribution: */
5225 for (i
= 0; i
< (int) cycle_alt_unit_usages
.length (); i
++)
5226 for (unit_usage_ptr
= cycle_alt_unit_usages
[i
];
5227 unit_usage_ptr
!= NULL
;
5228 unit_usage_ptr
= unit_usage_ptr
->next
)
5229 unit_usage_ptr
->unit_decl
->last_distribution_check_cycle
= -1;
5230 n_alts
= REGEXP_ONEOF (regexp
)->regexps_num
;
5231 marked
.create (n_alts
);
5232 for (i
= 0; i
< n_alts
; i
++)
5233 marked
.safe_push (0);
5234 annotation_reservation_message_reported_p
= false;
5235 for (i
= 0; i
< (int) cycle_alt_unit_usages
.length (); i
++)
5238 start
= cycle
* n_alts
;
5239 for (unit_usage_ptr
= cycle_alt_unit_usages
[i
];
5240 unit_usage_ptr
!= NULL
;
5241 unit_usage_ptr
= unit_usage_ptr
->next
)
5243 if (unit_usage_ptr
->unit_decl
->last_distribution_check_cycle
== cycle
)
5245 unit_usage_ptr
->unit_decl
->last_distribution_check_cycle
= cycle
;
5246 for (alt
= 0; alt
< n_alts
; alt
++)
5247 if (! unit_present_on_list_p (cycle_alt_unit_usages
[start
+ alt
],
5248 unit_usage_ptr
->unit_decl
))
5252 memset (marked
.address (), 0, n_alts
* sizeof (int));
5253 for (alt
= 0; alt
< n_alts
; alt
++)
5255 if (! unit_present_on_list_p (cycle_alt_unit_usages
[start
+ alt
],
5256 unit_usage_ptr
->unit_decl
))
5259 j
< (int) cycle_alt_unit_usages
.length ();
5263 if (! unit_present_on_list_p
5264 (cycle_alt_unit_usages
[start
+ alt2
],
5265 unit_usage_ptr
->unit_decl
)
5266 && equal_alternatives_p (alt
, alt2
, n_alts
,
5268 ->unit_decl
->automaton_decl
))
5275 for (alt
= 0; alt
< n_alts
&& marked
[alt
]; alt
++)
5277 if (alt
< n_alts
&& 0)
5279 if (! annotation_message_reported_p
)
5281 fprintf (stderr
, "\n");
5282 error ("The following units do not satisfy units-automata distribution rule");
5283 error ("(Unit presence on one alt and its absence on other alt\n");
5284 error (" result in different other automata reservations)");
5285 annotation_message_reported_p
= TRUE
;
5287 if (! annotation_reservation_message_reported_p
)
5289 error ("Reserv %s:", insn_reserv_name
);
5290 annotation_reservation_message_reported_p
= true;
5292 error (" Unit %s, cycle %d, alt %d, another alt %d",
5293 unit_usage_ptr
->unit_decl
->name
, cycle
, i
% n_alts
, alt
);
5298 cycle_alt_unit_usages
.release ();
5299 obstack_free (&unit_usages
, NULL
);
5302 /* The function finds units which violates units to automata
5303 distribution rule. If the units exist, report about them. */
5305 check_unit_distributions_to_automata (void)
5311 fprintf (stderr
, "Check unit distributions to automata...");
5312 automaton_decls
.create (0);
5313 for (i
= 0; i
< description
->decls_num
; i
++)
5315 decl
= description
->decls
[i
];
5316 if (decl
->mode
== dm_automaton
)
5317 automaton_decls
.safe_push (decl
);
5319 if (automaton_decls
.length () > 1)
5321 annotation_message_reported_p
= FALSE
;
5322 for (i
= 0; i
< description
->decls_num
; i
++)
5324 decl
= description
->decls
[i
];
5325 if (decl
->mode
== dm_insn_reserv
)
5326 check_regexp_units_distribution
5327 (DECL_INSN_RESERV (decl
)->name
,
5328 DECL_INSN_RESERV (decl
)->transformed_regexp
);
5331 automaton_decls
.release ();
5333 fprintf (stderr
, "done\n");
5338 /* The page contains code for building alt_states (see comments for
5339 IR) describing all possible insns reservations of an automaton. */
5341 /* Current state being formed for which the current alt_state
5343 static state_t state_being_formed
;
5345 /* Current alt_state being formed. */
5346 static alt_state_t alt_state_being_formed
;
5348 /* This recursive function processes `,' and units in reservation
5349 REGEXP for forming alt_states of AUTOMATON. It is believed that
5350 CURR_CYCLE is start cycle of all reservation REGEXP. */
5352 process_seq_for_forming_states (regexp_t regexp
, automaton_t automaton
,
5360 switch (regexp
->mode
)
5363 if (REGEXP_UNIT (regexp
)->unit_decl
->corresponding_automaton_num
5364 == automaton
->automaton_order_num
)
5365 set_state_reserv (state_being_formed
, curr_cycle
,
5366 REGEXP_UNIT (regexp
)->unit_decl
->unit_num
);
5370 for (i
= 0; i
< REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
5372 = process_seq_for_forming_states
5373 (REGEXP_SEQUENCE (regexp
)->regexps
[i
], automaton
, curr_cycle
) + 1;
5378 int finish_cycle
= 0;
5381 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
5383 cycle
= process_seq_for_forming_states (REGEXP_ALLOF (regexp
)
5385 automaton
, curr_cycle
);
5386 if (finish_cycle
< cycle
)
5387 finish_cycle
= cycle
;
5389 return finish_cycle
;
5400 /* This recursive function finishes forming ALT_STATE of AUTOMATON and
5401 inserts alt_state into the table. */
5403 finish_forming_alt_state (alt_state_t alt_state
,
5404 automaton_t automaton ATTRIBUTE_UNUSED
)
5406 state_t state_in_table
;
5407 state_t corresponding_state
;
5409 corresponding_state
= alt_state
->state
;
5410 state_in_table
= insert_state (corresponding_state
);
5411 if (state_in_table
!= corresponding_state
)
5413 free_state (corresponding_state
);
5414 alt_state
->state
= state_in_table
;
5418 /* The following variable value is current automaton insn for whose
5419 reservation the alt states are created. */
5420 static ainsn_t curr_ainsn
;
5422 /* This recursive function processes `|' in reservation REGEXP for
5423 forming alt_states of AUTOMATON. List of the alt states should
5424 have the same order as in the description. */
5426 process_alts_for_forming_states (regexp_t regexp
, automaton_t automaton
,
5431 if (regexp
->mode
!= rm_oneof
)
5433 alt_state_being_formed
= get_free_alt_state ();
5434 state_being_formed
= get_free_state (1, automaton
);
5435 alt_state_being_formed
->state
= state_being_formed
;
5436 /* We inserts in reverse order but we process alternatives also
5437 in reverse order. So we have the same order of alternative
5438 as in the description. */
5439 alt_state_being_formed
->next_alt_state
= curr_ainsn
->alt_states
;
5440 curr_ainsn
->alt_states
= alt_state_being_formed
;
5441 (void) process_seq_for_forming_states (regexp
, automaton
, 0);
5442 finish_forming_alt_state (alt_state_being_formed
, automaton
);
5446 gcc_assert (!inside_oneof_p
);
5447 /* We processes it in reverse order to get list with the same
5448 order as in the description. See also the previous
5450 for (i
= REGEXP_ONEOF (regexp
)->regexps_num
- 1; i
>= 0; i
--)
5451 process_alts_for_forming_states (REGEXP_ONEOF (regexp
)->regexps
[i
],
5456 /* Create nodes alt_state for all AUTOMATON insns. */
5458 create_alt_states (automaton_t automaton
)
5460 struct insn_reserv_decl
*reserv_decl
;
5462 for (curr_ainsn
= automaton
->ainsn_list
;
5464 curr_ainsn
= curr_ainsn
->next_ainsn
)
5466 reserv_decl
= curr_ainsn
->insn_reserv_decl
;
5467 if (!special_decl_p (reserv_decl
))
5469 curr_ainsn
->alt_states
= NULL
;
5470 process_alts_for_forming_states (reserv_decl
->transformed_regexp
,
5472 curr_ainsn
->sorted_alt_states
5473 = uniq_sort_alt_states (curr_ainsn
->alt_states
);
5480 /* The page contains major code for building DFA(s) for fast pipeline
5481 hazards recognition. */
5483 /* The function forms list of ainsns of AUTOMATON with the same
5487 form_ainsn_with_same_reservs (automaton_t automaton
)
5491 vec
<ainsn_t
> last_insns
;
5492 last_insns
.create (150);
5494 for (curr_ainsn
= automaton
->ainsn_list
;
5496 curr_ainsn
= curr_ainsn
->next_ainsn
)
5497 if (special_decl_p (curr_ainsn
->insn_reserv_decl
))
5499 curr_ainsn
->next_same_reservs_insn
= NULL
;
5500 curr_ainsn
->first_insn_with_same_reservs
= 1;
5504 for (i
= 0; i
< last_insns
.length (); i
++)
5506 (curr_ainsn
->sorted_alt_states
,
5507 last_insns
[i
]->sorted_alt_states
))
5509 curr_ainsn
->next_same_reservs_insn
= NULL
;
5510 if (i
< last_insns
.length ())
5512 curr_ainsn
->first_insn_with_same_reservs
= 0;
5513 last_insns
[i
]->next_same_reservs_insn
= curr_ainsn
;
5514 last_insns
[i
] = curr_ainsn
;
5518 last_insns
.safe_push (curr_ainsn
);
5519 curr_ainsn
->first_insn_with_same_reservs
= 1;
5522 last_insns
.release ();
5525 /* Forming unit reservations which can affect creating the automaton
5526 states achieved from a given state. It permits to build smaller
5527 automata in many cases. We would have the same automata after
5528 the minimization without such optimization, but the automaton
5529 right after the building could be huge. So in other words, usage
5530 of reservs_matter means some minimization during building the
5532 static reserv_sets_t
5533 form_reservs_matter (automaton_t automaton
)
5536 reserv_sets_t reservs_matter
= alloc_empty_reserv_sets();
5538 for (cycle
= 0; cycle
< max_cycles_num
; cycle
++)
5539 for (unit
= 0; unit
< description
->units_num
; unit
++)
5540 if (units_array
[unit
]->automaton_decl
5541 == automaton
->corresponding_automaton_decl
5542 && (cycle
>= units_array
[unit
]->min_occ_cycle_num
5543 /* We can not remove queried unit from reservations. */
5544 || units_array
[unit
]->query_p
5545 /* We can not remove units which are used
5546 `exclusion_set', `presence_set',
5547 `final_presence_set', `absence_set', and
5548 `final_absence_set'. */
5549 || units_array
[unit
]->in_set_p
))
5550 set_unit_reserv (reservs_matter
, cycle
, unit
);
5551 return reservs_matter
;
5554 /* The following function creates all states of nondeterministic AUTOMATON. */
5556 make_automaton (automaton_t automaton
)
5559 struct insn_reserv_decl
*insn_reserv_decl
;
5560 alt_state_t alt_state
;
5562 state_t start_state
;
5564 vec
<state_t
> state_stack
;
5565 state_stack
.create (150);
5567 reserv_sets_t reservs_matter
= form_reservs_matter (automaton
);
5569 /* Create the start state (empty state). */
5570 start_state
= insert_state (get_free_state (1, automaton
));
5571 automaton
->start_state
= start_state
;
5572 start_state
->it_was_placed_in_stack_for_NDFA_forming
= 1;
5573 state_stack
.safe_push (start_state
);
5575 while (state_stack
.length () != 0)
5577 state
= state_stack
.pop ();
5578 for (ainsn
= automaton
->ainsn_list
;
5580 ainsn
= ainsn
->next_ainsn
)
5581 if (ainsn
->first_insn_with_same_reservs
)
5583 insn_reserv_decl
= ainsn
->insn_reserv_decl
;
5584 if (!special_decl_p (insn_reserv_decl
))
5586 /* We process alt_states in the same order as they are
5587 present in the description. */
5588 for (alt_state
= ainsn
->alt_states
;
5590 alt_state
= alt_state
->next_alt_state
)
5592 state2
= alt_state
->state
;
5593 if (!intersected_state_reservs_p (state
, state2
))
5595 state2
= states_union (state
, state2
, reservs_matter
);
5596 if (!state2
->it_was_placed_in_stack_for_NDFA_forming
)
5598 state2
->it_was_placed_in_stack_for_NDFA_forming
5600 state_stack
.safe_push (state2
);
5602 if (progress_flag
&& states_n
% 100 == 0)
5603 fprintf (stderr
, ".");
5605 add_arc (state
, state2
, ainsn
);
5612 /* Add transition to advance cycle. */
5613 state2
= state_shift (state
, reservs_matter
);
5614 if (!state2
->it_was_placed_in_stack_for_NDFA_forming
)
5616 state2
->it_was_placed_in_stack_for_NDFA_forming
= 1;
5617 state_stack
.safe_push (state2
);
5619 if (progress_flag
&& states_n
% 100 == 0)
5620 fprintf (stderr
, ".");
5622 add_arc (state
, state2
, automaton
->advance_ainsn
);
5624 state_stack
.release ();
5627 /* Form lists of all arcs of STATE marked by the same ainsn. */
5629 form_arcs_marked_by_insn (state_t state
)
5635 for (i
= 0; i
< description
->decls_num
; i
++)
5637 decl
= description
->decls
[i
];
5638 if (decl
->mode
== dm_insn_reserv
)
5639 DECL_INSN_RESERV (decl
)->arcs_marked_by_insn
= NULL
;
5641 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
5643 gcc_assert (arc
->insn
);
5644 arc
->next_arc_marked_by_insn
5645 = arc
->insn
->insn_reserv_decl
->arcs_marked_by_insn
;
5646 arc
->insn
->insn_reserv_decl
->arcs_marked_by_insn
= arc
;
5650 /* The function creates composed state (see comments for IR) from
5651 ORIGINAL_STATE and list of arcs ARCS_MARKED_BY_INSN marked by the
5652 same insn. If the composed state is not in STATE_STACK yet, it is
5653 pushed into STATE_STACK. */
5656 create_composed_state (state_t original_state
, arc_t arcs_marked_by_insn
,
5657 vec
<state_t
> *state_stack
)
5660 alt_state_t alt_state
, curr_alt_state
;
5661 alt_state_t new_alt_state
;
5664 state_t state_in_table
;
5666 alt_state_t canonical_alt_states_list
;
5668 int new_state_p
= 0;
5670 if (arcs_marked_by_insn
== NULL
)
5672 if (arcs_marked_by_insn
->next_arc_marked_by_insn
== NULL
)
5673 state
= arcs_marked_by_insn
->to_state
;
5676 gcc_assert (ndfa_flag
);
5677 /* Create composed state. */
5678 state
= get_free_state (0, arcs_marked_by_insn
->to_state
->automaton
);
5679 curr_alt_state
= NULL
;
5680 for (curr_arc
= arcs_marked_by_insn
;
5682 curr_arc
= curr_arc
->next_arc_marked_by_insn
)
5683 if (curr_arc
->to_state
->component_states
== NULL
)
5685 new_alt_state
= get_free_alt_state ();
5686 new_alt_state
->next_alt_state
= curr_alt_state
;
5687 new_alt_state
->state
= curr_arc
->to_state
;
5688 curr_alt_state
= new_alt_state
;
5691 for (alt_state
= curr_arc
->to_state
->component_states
;
5693 alt_state
= alt_state
->next_sorted_alt_state
)
5695 new_alt_state
= get_free_alt_state ();
5696 new_alt_state
->next_alt_state
= curr_alt_state
;
5697 new_alt_state
->state
= alt_state
->state
;
5698 gcc_assert (!alt_state
->state
->component_states
);
5699 curr_alt_state
= new_alt_state
;
5701 /* There are not identical sets in the alt state list. */
5702 canonical_alt_states_list
= uniq_sort_alt_states (curr_alt_state
);
5703 if (canonical_alt_states_list
->next_sorted_alt_state
== NULL
)
5706 state
= canonical_alt_states_list
->state
;
5707 free_state (temp_state
);
5711 state
->component_states
= canonical_alt_states_list
;
5712 state_in_table
= insert_state (state
);
5713 if (state_in_table
!= state
)
5716 (state_in_table
->it_was_placed_in_stack_for_DFA_forming
);
5718 state
= state_in_table
;
5722 gcc_assert (!state
->it_was_placed_in_stack_for_DFA_forming
);
5724 for (curr_alt_state
= state
->component_states
;
5725 curr_alt_state
!= NULL
;
5726 curr_alt_state
= curr_alt_state
->next_sorted_alt_state
)
5727 for (curr_arc
= first_out_arc (curr_alt_state
->state
);
5729 curr_arc
= next_out_arc (curr_arc
))
5731 /* When producing collapse-NDFA transitions, we
5732 only add advance-cycle transitions to the
5733 collapsed states. */
5734 || (curr_arc
->insn
->insn_reserv_decl
5735 != DECL_INSN_RESERV (advance_cycle_insn_decl
)))
5736 add_arc (state
, curr_arc
->to_state
, curr_arc
->insn
);
5738 arcs_marked_by_insn
->to_state
= state
;
5739 for (alts_number
= 0,
5740 curr_arc
= arcs_marked_by_insn
->next_arc_marked_by_insn
;
5742 curr_arc
= next_arc
)
5744 next_arc
= curr_arc
->next_arc_marked_by_insn
;
5745 remove_arc (original_state
, curr_arc
);
5750 if (!state
->it_was_placed_in_stack_for_DFA_forming
)
5752 state
->it_was_placed_in_stack_for_DFA_forming
= 1;
5753 state_stack
->safe_push (state
);
5758 /* The function transforms nondeterministic AUTOMATON into
5762 NDFA_to_DFA (automaton_t automaton
)
5764 state_t start_state
;
5767 vec
<state_t
> state_stack
;
5771 state_stack
.create (0);
5773 /* Create the start state (empty state). */
5774 start_state
= automaton
->start_state
;
5775 start_state
->it_was_placed_in_stack_for_DFA_forming
= 1;
5776 state_stack
.safe_push (start_state
);
5778 while (state_stack
.length () != 0)
5780 state
= state_stack
.pop ();
5781 form_arcs_marked_by_insn (state
);
5782 for (i
= 0; i
< description
->decls_num
; i
++)
5784 decl
= description
->decls
[i
];
5785 if (decl
->mode
== dm_insn_reserv
5786 && decl
!= collapse_ndfa_insn_decl
5787 && create_composed_state
5788 (state
, DECL_INSN_RESERV (decl
)->arcs_marked_by_insn
,
5792 if (progress_flag
&& states_n
% 100 == 0)
5793 fprintf (stderr
, ".");
5796 /* Add a transition to collapse the NDFA. */
5799 if (state
->component_states
!= NULL
)
5801 state_t state2
= state
->component_states
->state
;
5802 if (!state2
->it_was_placed_in_stack_for_DFA_forming
)
5804 state2
->it_was_placed_in_stack_for_DFA_forming
= 1;
5805 state_stack
.safe_push (state2
);
5807 add_arc (state
, state2
, automaton
->collapse_ainsn
);
5810 add_arc (state
, state
, automaton
->collapse_ainsn
);
5813 state_stack
.release ();
5816 /* The following variable value is current number (1, 2, ...) of passing
5818 static int curr_state_graph_pass_num
;
5820 /* This recursive function passes all states achieved from START_STATE
5821 and applies APPLIED_FUNC to them. */
5823 pass_state_graph (state_t start_state
, void (*applied_func
) (state_t state
))
5827 if (start_state
->pass_num
== curr_state_graph_pass_num
)
5829 start_state
->pass_num
= curr_state_graph_pass_num
;
5830 (*applied_func
) (start_state
);
5831 for (arc
= first_out_arc (start_state
);
5833 arc
= next_out_arc (arc
))
5834 pass_state_graph (arc
->to_state
, applied_func
);
5837 /* This recursive function passes all states of AUTOMATON and applies
5838 APPLIED_FUNC to them. */
5840 pass_states (automaton_t automaton
, void (*applied_func
) (state_t state
))
5842 curr_state_graph_pass_num
++;
5843 pass_state_graph (automaton
->start_state
, applied_func
);
5846 /* The function initializes code for passing of all states. */
5848 initiate_pass_states (void)
5850 curr_state_graph_pass_num
= 0;
5853 /* The following vla is used for storing pointers to all achieved
5855 static vec
<state_t
> all_achieved_states
;
5857 /* This function is called by function pass_states to add an achieved
5860 add_achieved_state (state_t state
)
5862 all_achieved_states
.safe_push (state
);
5865 /* The function sets up equivalence numbers of insns which mark all
5866 out arcs of STATE by equiv_class_num_1 (if ODD_ITERATION_FLAG has
5867 nonzero value) or by equiv_class_num_2 of the destination state. */
5869 set_out_arc_insns_equiv_num (state_t state
, int odd_iteration_flag
)
5873 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
5875 gcc_assert (!arc
->insn
->insn_reserv_decl
->equiv_class_num
);
5876 arc
->insn
->insn_reserv_decl
->equiv_class_num
5877 = (odd_iteration_flag
5878 ? arc
->to_state
->equiv_class_num_1
5879 : arc
->to_state
->equiv_class_num_2
);
5880 gcc_assert (arc
->insn
->insn_reserv_decl
->equiv_class_num
);
5884 /* The function clears equivalence numbers and alt_states in all insns
5885 which mark all out arcs of STATE. */
5887 clear_arc_insns_equiv_num (state_t state
)
5891 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
5892 arc
->insn
->insn_reserv_decl
->equiv_class_num
= 0;
5896 /* The following function returns TRUE if STATE reserves the unit with
5897 UNIT_NUM on the first cycle. */
5899 first_cycle_unit_presence (state_t state
, int unit_num
)
5901 alt_state_t alt_state
;
5903 if (state
->component_states
== NULL
)
5904 return test_unit_reserv (state
->reservs
, 0, unit_num
);
5907 for (alt_state
= state
->component_states
;
5909 alt_state
= alt_state
->next_sorted_alt_state
)
5910 if (test_unit_reserv (alt_state
->state
->reservs
, 0, unit_num
))
5916 /* This fills in the presence_signature[] member of STATE. */
5918 cache_presence (state_t state
)
5922 sz
= (description
->query_units_num
+ sizeof (int) * CHAR_BIT
- 1)
5923 / (sizeof (int) * CHAR_BIT
);
5925 state
->presence_signature
= XCREATENODEVEC (unsigned int, sz
);
5926 for (i
= 0; i
< description
->units_num
; i
++)
5927 if (units_array
[i
]->query_p
)
5929 int presence1_p
= first_cycle_unit_presence (state
, i
);
5930 state
->presence_signature
[num
/ (sizeof (int) * CHAR_BIT
)]
5931 |= (!!presence1_p
) << (num
% (sizeof (int) * CHAR_BIT
));
5936 /* The function returns nonzero value if STATE is not equivalent to
5937 ANOTHER_STATE from the same current partition on equivalence
5938 classes. Another state has ANOTHER_STATE_OUT_ARCS_NUM number of
5939 output arcs. Iteration of making equivalence partition is defined
5940 by ODD_ITERATION_FLAG. */
5942 state_is_differed (state_t state
, state_t another_state
,
5943 int odd_iteration_flag
)
5946 unsigned int sz
, si
;
5948 gcc_assert (state
->num_out_arcs
== another_state
->num_out_arcs
);
5950 sz
= (description
->query_units_num
+ sizeof (int) * CHAR_BIT
- 1)
5951 / (sizeof (int) * CHAR_BIT
);
5953 for (si
= 0; si
< sz
; si
++)
5954 gcc_assert (state
->presence_signature
[si
]
5955 == another_state
->presence_signature
[si
]);
5957 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
5959 if ((odd_iteration_flag
5960 ? arc
->to_state
->equiv_class_num_1
5961 : arc
->to_state
->equiv_class_num_2
)
5962 != arc
->insn
->insn_reserv_decl
->equiv_class_num
)
5969 /* Compares two states pointed to by STATE_PTR_1 and STATE_PTR_2
5970 and return -1, 0 or 1. This function can be used as predicate for
5971 qsort(). It requires the member presence_signature[] of both
5972 states be filled. */
5974 compare_states_for_equiv (const void *state_ptr_1
,
5975 const void *state_ptr_2
)
5977 const_state_t
const s1
= *(const_state_t
const*)state_ptr_1
;
5978 const_state_t
const s2
= *(const_state_t
const*)state_ptr_2
;
5979 unsigned int sz
, si
;
5980 if (s1
->num_out_arcs
< s2
->num_out_arcs
)
5982 else if (s1
->num_out_arcs
> s2
->num_out_arcs
)
5985 sz
= (description
->query_units_num
+ sizeof (int) * CHAR_BIT
- 1)
5986 / (sizeof (int) * CHAR_BIT
);
5988 for (si
= 0; si
< sz
; si
++)
5989 if (s1
->presence_signature
[si
] < s2
->presence_signature
[si
])
5991 else if (s1
->presence_signature
[si
] > s2
->presence_signature
[si
])
5996 /* The function makes initial partition of STATES on equivalent
5997 classes and saves it into CLASSES. This function requires the input
5998 to be sorted via compare_states_for_equiv(). */
6000 init_equiv_class (vec
<state_t
> states
, vec
<state_t
> *classes
)
6006 classes
->create (150);
6007 for (i
= 0; i
< states
.length (); i
++)
6009 state_t state
= states
[i
];
6012 if (compare_states_for_equiv (&prev
, &state
) != 0)
6014 classes
->safe_push (prev
);
6019 state
->equiv_class_num_1
= class_num
;
6020 state
->next_equiv_class_state
= prev
;
6024 classes
->safe_push (prev
);
6028 /* The function copies pointers to equivalent states from vla FROM
6031 copy_equiv_class (vec
<state_t
> *to
, vec
<state_t
> from
)
6037 /* The function processes equivalence class given by its first state,
6038 FIRST_STATE, on odd iteration if ODD_ITERATION_FLAG. If there
6039 are not equivalent states, the function partitions the class
6040 removing nonequivalent states and placing them in
6041 *NEXT_ITERATION_CLASSES, increments *NEW_EQUIV_CLASS_NUM_PTR ans
6042 assigns it to the state equivalence number. If the class has been
6043 partitioned, the function returns nonzero value. */
6045 partition_equiv_class (state_t first_state
, int odd_iteration_flag
,
6046 vec
<state_t
> *next_iteration_classes
,
6047 int *new_equiv_class_num_ptr
)
6049 state_t new_equiv_class
;
6057 while (first_state
!= NULL
)
6059 new_equiv_class
= NULL
;
6060 if (first_state
->next_equiv_class_state
!= NULL
)
6062 /* There are more one states in the class equivalence. */
6063 set_out_arc_insns_equiv_num (first_state
, odd_iteration_flag
);
6064 for (prev_state
= first_state
,
6065 curr_state
= first_state
->next_equiv_class_state
;
6067 curr_state
= next_state
)
6069 next_state
= curr_state
->next_equiv_class_state
;
6070 if (state_is_differed (curr_state
, first_state
,
6071 odd_iteration_flag
))
6073 /* Remove curr state from the class equivalence. */
6074 prev_state
->next_equiv_class_state
= next_state
;
6075 /* Add curr state to the new class equivalence. */
6076 curr_state
->next_equiv_class_state
= new_equiv_class
;
6077 if (new_equiv_class
== NULL
)
6078 (*new_equiv_class_num_ptr
)++;
6079 if (odd_iteration_flag
)
6080 curr_state
->equiv_class_num_2
= *new_equiv_class_num_ptr
;
6082 curr_state
->equiv_class_num_1
= *new_equiv_class_num_ptr
;
6083 new_equiv_class
= curr_state
;
6087 prev_state
= curr_state
;
6089 clear_arc_insns_equiv_num (first_state
);
6091 if (new_equiv_class
!= NULL
)
6092 next_iteration_classes
->safe_push (new_equiv_class
);
6093 first_state
= new_equiv_class
;
6098 /* The function finds equivalent states of AUTOMATON. */
6100 evaluate_equiv_classes (automaton_t automaton
, vec
<state_t
> *equiv_classes
)
6102 int new_equiv_class_num
;
6103 int odd_iteration_flag
;
6105 vec
<state_t
> next_iteration_classes
;
6108 all_achieved_states
.create (1500);
6109 pass_states (automaton
, add_achieved_state
);
6110 pass_states (automaton
, cache_presence
);
6111 all_achieved_states
.qsort (compare_states_for_equiv
);
6113 odd_iteration_flag
= 0;
6114 new_equiv_class_num
= init_equiv_class (all_achieved_states
,
6115 &next_iteration_classes
);
6119 odd_iteration_flag
= !odd_iteration_flag
;
6121 copy_equiv_class (equiv_classes
, next_iteration_classes
);
6123 /* Transfer equiv numbers for the next iteration. */
6124 for (i
= 0; i
< all_achieved_states
.length (); i
++)
6125 if (odd_iteration_flag
)
6126 all_achieved_states
[i
]->equiv_class_num_2
6127 = all_achieved_states
[i
]->equiv_class_num_1
;
6129 all_achieved_states
[i
]->equiv_class_num_1
6130 = all_achieved_states
[i
]->equiv_class_num_2
;
6132 for (i
= 0; i
< equiv_classes
->length (); i
++)
6133 if (partition_equiv_class ((*equiv_classes
)[i
],
6135 &next_iteration_classes
,
6136 &new_equiv_class_num
))
6139 while (!finish_flag
);
6140 next_iteration_classes
.release ();
6141 all_achieved_states
.release ();
6144 /* The function merges equivalent states of AUTOMATON. */
6146 merge_states (automaton_t automaton
, vec
<state_t
> equiv_classes
)
6150 state_t first_class_state
;
6151 alt_state_t alt_states
;
6152 alt_state_t alt_state
, new_alt_state
;
6157 /* Create states corresponding to equivalence classes containing two
6159 for (i
= 0; i
< equiv_classes
.length (); i
++)
6161 curr_state
= equiv_classes
[i
];
6162 if (curr_state
->next_equiv_class_state
!= NULL
)
6164 /* There are more one states in the class equivalence. */
6165 /* Create new compound state. */
6166 new_state
= get_free_state (0, automaton
);
6168 first_class_state
= curr_state
;
6169 for (curr_state
= first_class_state
;
6171 curr_state
= curr_state
->next_equiv_class_state
)
6173 curr_state
->equiv_class_state
= new_state
;
6174 if (curr_state
->component_states
== NULL
)
6176 new_alt_state
= get_free_alt_state ();
6177 new_alt_state
->state
= curr_state
;
6178 new_alt_state
->next_alt_state
= alt_states
;
6179 alt_states
= new_alt_state
;
6182 for (alt_state
= curr_state
->component_states
;
6184 alt_state
= alt_state
->next_sorted_alt_state
)
6186 new_alt_state
= get_free_alt_state ();
6187 new_alt_state
->state
= alt_state
->state
;
6188 new_alt_state
->next_alt_state
= alt_states
;
6189 alt_states
= new_alt_state
;
6192 /* Its is important that alt states were sorted before and
6193 after merging to have the same querying results. */
6194 new_state
->component_states
= uniq_sort_alt_states (alt_states
);
6197 curr_state
->equiv_class_state
= curr_state
;
6200 for (i
= 0; i
< equiv_classes
.length (); i
++)
6202 curr_state
= equiv_classes
[i
];
6203 if (curr_state
->next_equiv_class_state
!= NULL
)
6205 first_class_state
= curr_state
;
6206 /* Create new arcs output from the state corresponding to
6208 for (curr_arc
= first_out_arc (first_class_state
);
6210 curr_arc
= next_out_arc (curr_arc
))
6211 add_arc (first_class_state
->equiv_class_state
,
6212 curr_arc
->to_state
->equiv_class_state
,
6214 /* Delete output arcs from states of given class equivalence. */
6215 for (curr_state
= first_class_state
;
6217 curr_state
= curr_state
->next_equiv_class_state
)
6219 if (automaton
->start_state
== curr_state
)
6220 automaton
->start_state
= curr_state
->equiv_class_state
;
6221 /* Delete the state and its output arcs. */
6222 for (curr_arc
= first_out_arc (curr_state
);
6224 curr_arc
= next_arc
)
6226 next_arc
= next_out_arc (curr_arc
);
6227 free_arc (curr_arc
);
6233 /* Change `to_state' of arcs output from the state of given
6234 equivalence class. */
6235 for (curr_arc
= first_out_arc (curr_state
);
6237 curr_arc
= next_out_arc (curr_arc
))
6238 curr_arc
->to_state
= curr_arc
->to_state
->equiv_class_state
;
6243 /* The function sets up new_cycle_p for states if there is arc to the
6244 state marked by advance_cycle_insn_decl. */
6246 set_new_cycle_flags (state_t state
)
6250 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
6251 if (arc
->insn
->insn_reserv_decl
6252 == DECL_INSN_RESERV (advance_cycle_insn_decl
))
6253 arc
->to_state
->new_cycle_p
= 1;
6256 /* The top level function for minimization of deterministic
6259 minimize_DFA (automaton_t automaton
)
6261 vec
<state_t
> equiv_classes
= vNULL
;
6263 evaluate_equiv_classes (automaton
, &equiv_classes
);
6264 merge_states (automaton
, equiv_classes
);
6265 pass_states (automaton
, set_new_cycle_flags
);
6267 equiv_classes
.release ();
6270 /* Values of two variables are counted number of states and arcs in an
6272 static int curr_counted_states_num
;
6273 static int curr_counted_arcs_num
;
6275 /* The function is called by function `pass_states' to count states
6276 and arcs of an automaton. */
6278 incr_states_and_arcs_nums (state_t state
)
6282 curr_counted_states_num
++;
6283 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
6284 curr_counted_arcs_num
++;
6287 /* The function counts states and arcs of AUTOMATON. */
6289 count_states_and_arcs (automaton_t automaton
, int *states_num
,
6292 curr_counted_states_num
= 0;
6293 curr_counted_arcs_num
= 0;
6294 pass_states (automaton
, incr_states_and_arcs_nums
);
6295 *states_num
= curr_counted_states_num
;
6296 *arcs_num
= curr_counted_arcs_num
;
6299 /* The function builds one DFA AUTOMATON for fast pipeline hazards
6300 recognition after checking and simplifying IR of the
6303 build_automaton (automaton_t automaton
)
6308 ticker_on (&NDFA_time
);
6311 if (automaton
->corresponding_automaton_decl
== NULL
)
6312 fprintf (stderr
, "Create anonymous automaton");
6314 fprintf (stderr
, "Create automaton `%s'",
6315 automaton
->corresponding_automaton_decl
->name
);
6316 fprintf (stderr
, " (1 dot is 100 new states):");
6318 make_automaton (automaton
);
6320 fprintf (stderr
, " done\n");
6321 ticker_off (&NDFA_time
);
6322 count_states_and_arcs (automaton
, &states_num
, &arcs_num
);
6323 automaton
->NDFA_states_num
= states_num
;
6324 automaton
->NDFA_arcs_num
= arcs_num
;
6325 ticker_on (&NDFA_to_DFA_time
);
6328 if (automaton
->corresponding_automaton_decl
== NULL
)
6329 fprintf (stderr
, "Make anonymous DFA");
6331 fprintf (stderr
, "Make DFA `%s'",
6332 automaton
->corresponding_automaton_decl
->name
);
6333 fprintf (stderr
, " (1 dot is 100 new states):");
6335 NDFA_to_DFA (automaton
);
6337 fprintf (stderr
, " done\n");
6338 ticker_off (&NDFA_to_DFA_time
);
6339 count_states_and_arcs (automaton
, &states_num
, &arcs_num
);
6340 automaton
->DFA_states_num
= states_num
;
6341 automaton
->DFA_arcs_num
= arcs_num
;
6342 if (!no_minimization_flag
)
6344 ticker_on (&minimize_time
);
6347 if (automaton
->corresponding_automaton_decl
== NULL
)
6348 fprintf (stderr
, "Minimize anonymous DFA...");
6350 fprintf (stderr
, "Minimize DFA `%s'...",
6351 automaton
->corresponding_automaton_decl
->name
);
6353 minimize_DFA (automaton
);
6355 fprintf (stderr
, "done\n");
6356 ticker_off (&minimize_time
);
6357 count_states_and_arcs (automaton
, &states_num
, &arcs_num
);
6358 automaton
->minimal_DFA_states_num
= states_num
;
6359 automaton
->minimal_DFA_arcs_num
= arcs_num
;
6365 /* The page contains code for enumeration of all states of an automaton. */
6367 /* Variable used for enumeration of all states of an automaton. Its
6368 value is current number of automaton states. */
6369 static int curr_state_order_num
;
6371 /* The function is called by function `pass_states' for enumerating
6374 set_order_state_num (state_t state
)
6376 state
->order_state_num
= curr_state_order_num
;
6377 curr_state_order_num
++;
6380 /* The function enumerates all states of AUTOMATON. */
6382 enumerate_states (automaton_t automaton
)
6384 curr_state_order_num
= 0;
6385 pass_states (automaton
, set_order_state_num
);
6386 automaton
->achieved_states_num
= curr_state_order_num
;
6391 /* The page contains code for finding equivalent automaton insns
6394 /* The function inserts AINSN into cyclic list
6395 CYCLIC_EQUIV_CLASS_INSN_LIST of ainsns. */
6397 insert_ainsn_into_equiv_class (ainsn_t ainsn
,
6398 ainsn_t cyclic_equiv_class_insn_list
)
6400 if (cyclic_equiv_class_insn_list
== NULL
)
6401 ainsn
->next_equiv_class_insn
= ainsn
;
6404 ainsn
->next_equiv_class_insn
6405 = cyclic_equiv_class_insn_list
->next_equiv_class_insn
;
6406 cyclic_equiv_class_insn_list
->next_equiv_class_insn
= ainsn
;
6411 /* The function deletes equiv_class_insn into cyclic list of
6412 equivalent ainsns. */
6414 delete_ainsn_from_equiv_class (ainsn_t equiv_class_insn
)
6416 ainsn_t curr_equiv_class_insn
;
6417 ainsn_t prev_equiv_class_insn
;
6419 prev_equiv_class_insn
= equiv_class_insn
;
6420 for (curr_equiv_class_insn
= equiv_class_insn
->next_equiv_class_insn
;
6421 curr_equiv_class_insn
!= equiv_class_insn
;
6422 curr_equiv_class_insn
= curr_equiv_class_insn
->next_equiv_class_insn
)
6423 prev_equiv_class_insn
= curr_equiv_class_insn
;
6424 if (prev_equiv_class_insn
!= equiv_class_insn
)
6425 prev_equiv_class_insn
->next_equiv_class_insn
6426 = equiv_class_insn
->next_equiv_class_insn
;
6429 /* The function processes AINSN of a state in order to find equivalent
6430 ainsns. INSN_ARCS_ARRAY is table: code of insn -> out arc of the
6433 process_insn_equiv_class (ainsn_t ainsn
, arc_t
*insn_arcs_array
)
6437 ainsn_t cyclic_insn_list
;
6440 gcc_assert (insn_arcs_array
[ainsn
->insn_reserv_decl
->insn_num
]);
6442 /* New class of ainsns which are not equivalent to given ainsn. */
6443 cyclic_insn_list
= NULL
;
6446 next_insn
= curr_insn
->next_equiv_class_insn
;
6447 arc
= insn_arcs_array
[curr_insn
->insn_reserv_decl
->insn_num
];
6449 || (insn_arcs_array
[ainsn
->insn_reserv_decl
->insn_num
]->to_state
6452 delete_ainsn_from_equiv_class (curr_insn
);
6453 cyclic_insn_list
= insert_ainsn_into_equiv_class (curr_insn
,
6456 curr_insn
= next_insn
;
6458 while (curr_insn
!= ainsn
);
6461 /* The function processes STATE in order to find equivalent ainsns. */
6463 process_state_for_insn_equiv_partition (state_t state
)
6466 arc_t
*insn_arcs_array
= XCNEWVEC (arc_t
, description
->insns_num
);
6468 /* Process insns of the arcs. */
6469 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
6470 insn_arcs_array
[arc
->insn
->insn_reserv_decl
->insn_num
] = arc
;
6471 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
6472 process_insn_equiv_class (arc
->insn
, insn_arcs_array
);
6474 free (insn_arcs_array
);
6477 /* The function searches for equivalent ainsns of AUTOMATON. */
6479 set_insn_equiv_classes (automaton_t automaton
)
6484 ainsn_t cyclic_insn_list
;
6485 ainsn_t insn_with_same_reservs
;
6486 int equiv_classes_num
;
6488 /* All insns are included in one equivalence class. */
6489 cyclic_insn_list
= NULL
;
6490 for (ainsn
= automaton
->ainsn_list
; ainsn
!= NULL
; ainsn
= ainsn
->next_ainsn
)
6491 if (ainsn
->first_insn_with_same_reservs
)
6492 cyclic_insn_list
= insert_ainsn_into_equiv_class (ainsn
,
6494 /* Process insns in order to make equivalence partition. */
6495 pass_states (automaton
, process_state_for_insn_equiv_partition
);
6496 /* Enumerate equiv classes. */
6497 for (ainsn
= automaton
->ainsn_list
; ainsn
!= NULL
; ainsn
= ainsn
->next_ainsn
)
6498 /* Set undefined value. */
6499 ainsn
->insn_equiv_class_num
= -1;
6500 equiv_classes_num
= 0;
6501 for (ainsn
= automaton
->ainsn_list
; ainsn
!= NULL
; ainsn
= ainsn
->next_ainsn
)
6502 if (ainsn
->insn_equiv_class_num
< 0)
6505 gcc_assert (first_insn
->first_insn_with_same_reservs
);
6506 first_insn
->first_ainsn_with_given_equivalence_num
= 1;
6507 curr_insn
= first_insn
;
6510 for (insn_with_same_reservs
= curr_insn
;
6511 insn_with_same_reservs
!= NULL
;
6512 insn_with_same_reservs
6513 = insn_with_same_reservs
->next_same_reservs_insn
)
6514 insn_with_same_reservs
->insn_equiv_class_num
= equiv_classes_num
;
6515 curr_insn
= curr_insn
->next_equiv_class_insn
;
6517 while (curr_insn
!= first_insn
);
6518 equiv_classes_num
++;
6520 automaton
->insn_equiv_classes_num
= equiv_classes_num
;
6525 /* This page contains code for creating DFA(s) and calls functions
6529 /* The following value is used to prevent floating point overflow for
6530 estimating an automaton bound. The value should be less DBL_MAX on
6531 the host machine. We use here approximate minimum of maximal
6532 double floating point value required by ANSI C standard. It
6533 will work for non ANSI sun compiler too. */
6535 #define MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND 1.0E37
6537 /* The function estimate size of the single DFA used by PHR (pipeline
6538 hazards recognizer). */
6540 estimate_one_automaton_bound (void)
6543 double one_automaton_estimation_bound
;
6547 one_automaton_estimation_bound
= 1.0;
6548 for (i
= 0; i
< description
->decls_num
; i
++)
6550 decl
= description
->decls
[i
];
6551 if (decl
->mode
== dm_unit
)
6553 root_value
= exp (log (DECL_UNIT (decl
)->max_occ_cycle_num
6554 - DECL_UNIT (decl
)->min_occ_cycle_num
+ 1.0)
6556 if (MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND
/ root_value
6557 > one_automaton_estimation_bound
)
6558 one_automaton_estimation_bound
*= root_value
;
6561 return one_automaton_estimation_bound
;
6564 /* The function compares unit declarations according to their maximal
6565 cycle in reservations. */
6567 compare_max_occ_cycle_nums (const void *unit_decl_1
,
6568 const void *unit_decl_2
)
6570 if ((DECL_UNIT (*(const_decl_t
const*) unit_decl_1
)->max_occ_cycle_num
)
6571 < (DECL_UNIT (*(const_decl_t
const*) unit_decl_2
)->max_occ_cycle_num
))
6573 else if ((DECL_UNIT (*(const_decl_t
const*) unit_decl_1
)->max_occ_cycle_num
)
6574 == (DECL_UNIT (*(const_decl_t
const*) unit_decl_2
)->max_occ_cycle_num
))
6580 /* The function makes heuristic assigning automata to units. Actually
6581 efficacy of the algorithm has been checked yet??? */
6584 units_to_automata_heuristic_distr (void)
6586 double estimation_bound
;
6590 unit_decl_t
*unit_decls
;
6593 if (description
->units_num
== 0)
6595 estimation_bound
= estimate_one_automaton_bound ();
6596 unit_decls
= XNEWVEC (unit_decl_t
, description
->units_num
);
6598 for (i
= 0, j
= 0; i
< description
->decls_num
; i
++)
6599 if (description
->decls
[i
]->mode
== dm_unit
)
6600 unit_decls
[j
++] = DECL_UNIT (description
->decls
[i
]);
6601 gcc_assert (j
== description
->units_num
);
6603 qsort (unit_decls
, description
->units_num
,
6604 sizeof (unit_decl_t
), compare_max_occ_cycle_nums
);
6607 bound_value
= unit_decls
[0]->max_occ_cycle_num
;
6608 unit_decls
[0]->corresponding_automaton_num
= automaton_num
;
6610 for (i
= 1; i
< description
->units_num
; i
++)
6612 rest_units_num
= description
->units_num
- i
+ 1;
6613 gcc_assert (automata_num
- automaton_num
- 1 <= rest_units_num
);
6614 if (automaton_num
< automata_num
- 1
6615 && ((automata_num
- automaton_num
- 1 == rest_units_num
)
6618 / unit_decls
[i
]->max_occ_cycle_num
))))
6620 bound_value
= unit_decls
[i
]->max_occ_cycle_num
;
6624 bound_value
*= unit_decls
[i
]->max_occ_cycle_num
;
6625 unit_decls
[i
]->corresponding_automaton_num
= automaton_num
;
6627 gcc_assert (automaton_num
== automata_num
- 1);
6631 /* The functions creates automaton insns for each automata. Automaton
6632 insn is simply insn for given automaton which makes reservation
6633 only of units of the automaton. */
6635 create_ainsns (automaton_t automaton
)
6638 ainsn_t first_ainsn
;
6645 for (i
= 0; i
< description
->decls_num
; i
++)
6647 decl
= description
->decls
[i
];
6648 if (decl
->mode
== dm_insn_reserv
)
6650 curr_ainsn
= XCREATENODE (struct ainsn
);
6651 curr_ainsn
->insn_reserv_decl
= DECL_INSN_RESERV (decl
);
6652 curr_ainsn
->important_p
= FALSE
;
6653 curr_ainsn
->next_ainsn
= NULL
;
6654 if (prev_ainsn
== NULL
)
6655 first_ainsn
= curr_ainsn
;
6657 prev_ainsn
->next_ainsn
= curr_ainsn
;
6658 if (decl
== advance_cycle_insn_decl
)
6659 automaton
->advance_ainsn
= curr_ainsn
;
6660 else if (decl
== collapse_ndfa_insn_decl
)
6661 automaton
->collapse_ainsn
= curr_ainsn
;
6662 prev_ainsn
= curr_ainsn
;
6665 automaton
->ainsn_list
= first_ainsn
;
6668 /* The function assigns automata to units according to constructions
6669 `define_automaton' in the description. */
6671 units_to_automata_distr (void)
6676 for (i
= 0; i
< description
->decls_num
; i
++)
6678 decl
= description
->decls
[i
];
6679 if (decl
->mode
== dm_unit
)
6681 if (DECL_UNIT (decl
)->automaton_decl
== NULL
6682 || (DECL_UNIT (decl
)->automaton_decl
->corresponding_automaton
6684 /* Distribute to the first automaton. */
6685 DECL_UNIT (decl
)->corresponding_automaton_num
= 0;
6687 DECL_UNIT (decl
)->corresponding_automaton_num
6688 = (DECL_UNIT (decl
)->automaton_decl
6689 ->corresponding_automaton
->automaton_order_num
);
6694 /* The function creates DFA(s) for fast pipeline hazards recognition
6695 after checking and simplifying IR of the description. */
6697 create_automata (void)
6699 automaton_t curr_automaton
;
6700 automaton_t prev_automaton
;
6702 int curr_automaton_num
;
6705 if (automata_num
!= 0)
6707 units_to_automata_heuristic_distr ();
6708 for (prev_automaton
= NULL
, curr_automaton_num
= 0;
6709 curr_automaton_num
< automata_num
;
6710 curr_automaton_num
++, prev_automaton
= curr_automaton
)
6712 curr_automaton
= XCREATENODE (struct automaton
);
6713 create_ainsns (curr_automaton
);
6714 curr_automaton
->corresponding_automaton_decl
= NULL
;
6715 curr_automaton
->next_automaton
= NULL
;
6716 curr_automaton
->automaton_order_num
= curr_automaton_num
;
6717 if (prev_automaton
== NULL
)
6718 description
->first_automaton
= curr_automaton
;
6720 prev_automaton
->next_automaton
= curr_automaton
;
6725 curr_automaton_num
= 0;
6726 prev_automaton
= NULL
;
6727 for (i
= 0; i
< description
->decls_num
; i
++)
6729 decl
= description
->decls
[i
];
6730 if (decl
->mode
== dm_automaton
6731 && DECL_AUTOMATON (decl
)->automaton_is_used
)
6733 curr_automaton
= XCREATENODE (struct automaton
);
6734 create_ainsns (curr_automaton
);
6735 curr_automaton
->corresponding_automaton_decl
6736 = DECL_AUTOMATON (decl
);
6737 curr_automaton
->next_automaton
= NULL
;
6738 DECL_AUTOMATON (decl
)->corresponding_automaton
= curr_automaton
;
6739 curr_automaton
->automaton_order_num
= curr_automaton_num
;
6740 if (prev_automaton
== NULL
)
6741 description
->first_automaton
= curr_automaton
;
6743 prev_automaton
->next_automaton
= curr_automaton
;
6744 curr_automaton_num
++;
6745 prev_automaton
= curr_automaton
;
6748 if (curr_automaton_num
== 0)
6750 curr_automaton
= XCREATENODE (struct automaton
);
6751 create_ainsns (curr_automaton
);
6752 curr_automaton
->corresponding_automaton_decl
= NULL
;
6753 curr_automaton
->next_automaton
= NULL
;
6754 description
->first_automaton
= curr_automaton
;
6756 units_to_automata_distr ();
6758 NDFA_time
= create_ticker ();
6759 ticker_off (&NDFA_time
);
6760 NDFA_to_DFA_time
= create_ticker ();
6761 ticker_off (&NDFA_to_DFA_time
);
6762 minimize_time
= create_ticker ();
6763 ticker_off (&minimize_time
);
6764 equiv_time
= create_ticker ();
6765 ticker_off (&equiv_time
);
6766 for (curr_automaton
= description
->first_automaton
;
6767 curr_automaton
!= NULL
;
6768 curr_automaton
= curr_automaton
->next_automaton
)
6772 if (curr_automaton
->corresponding_automaton_decl
== NULL
)
6773 fprintf (stderr
, "Prepare anonymous automaton creation ... ");
6775 fprintf (stderr
, "Prepare automaton `%s' creation...",
6776 curr_automaton
->corresponding_automaton_decl
->name
);
6778 create_alt_states (curr_automaton
);
6779 form_ainsn_with_same_reservs (curr_automaton
);
6781 fprintf (stderr
, "done\n");
6782 build_automaton (curr_automaton
);
6783 enumerate_states (curr_automaton
);
6784 ticker_on (&equiv_time
);
6785 set_insn_equiv_classes (curr_automaton
);
6786 ticker_off (&equiv_time
);
6792 /* This page contains code for forming string representation of
6793 regexp. The representation is formed on IR obstack. So you should
6794 not work with IR obstack between regexp_representation and
6795 finish_regexp_representation calls. */
6797 /* This recursive function forms string representation of regexp
6798 (without tailing '\0'). */
6800 form_regexp (regexp_t regexp
)
6804 switch (regexp
->mode
)
6806 case rm_unit
: case rm_reserv
:
6808 const char *name
= (regexp
->mode
== rm_unit
6809 ? REGEXP_UNIT (regexp
)->name
6810 : REGEXP_RESERV (regexp
)->name
);
6812 obstack_grow (&irp
, name
, strlen (name
));
6817 for (i
= 0; i
< REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
6820 obstack_1grow (&irp
, ',');
6821 form_regexp (REGEXP_SEQUENCE (regexp
)->regexps
[i
]);
6826 obstack_1grow (&irp
, '(');
6827 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
6830 obstack_1grow (&irp
, '+');
6831 if (REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
== rm_sequence
6832 || REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
== rm_oneof
)
6833 obstack_1grow (&irp
, '(');
6834 form_regexp (REGEXP_ALLOF (regexp
)->regexps
[i
]);
6835 if (REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
== rm_sequence
6836 || REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
== rm_oneof
)
6837 obstack_1grow (&irp
, ')');
6839 obstack_1grow (&irp
, ')');
6843 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
6846 obstack_1grow (&irp
, '|');
6847 if (REGEXP_ONEOF (regexp
)->regexps
[i
]->mode
== rm_sequence
)
6848 obstack_1grow (&irp
, '(');
6849 form_regexp (REGEXP_ONEOF (regexp
)->regexps
[i
]);
6850 if (REGEXP_ONEOF (regexp
)->regexps
[i
]->mode
== rm_sequence
)
6851 obstack_1grow (&irp
, ')');
6859 if (REGEXP_REPEAT (regexp
)->regexp
->mode
== rm_sequence
6860 || REGEXP_REPEAT (regexp
)->regexp
->mode
== rm_allof
6861 || REGEXP_REPEAT (regexp
)->regexp
->mode
== rm_oneof
)
6862 obstack_1grow (&irp
, '(');
6863 form_regexp (REGEXP_REPEAT (regexp
)->regexp
);
6864 if (REGEXP_REPEAT (regexp
)->regexp
->mode
== rm_sequence
6865 || REGEXP_REPEAT (regexp
)->regexp
->mode
== rm_allof
6866 || REGEXP_REPEAT (regexp
)->regexp
->mode
== rm_oneof
)
6867 obstack_1grow (&irp
, ')');
6868 sprintf (digits
, "*%d", REGEXP_REPEAT (regexp
)->repeat_num
);
6869 obstack_grow (&irp
, digits
, strlen (digits
));
6874 obstack_grow (&irp
, NOTHING_NAME
, strlen (NOTHING_NAME
));
6882 /* The function returns string representation of REGEXP on IR
6885 regexp_representation (regexp_t regexp
)
6887 form_regexp (regexp
);
6888 obstack_1grow (&irp
, '\0');
6889 return obstack_base (&irp
);
6892 /* The function frees memory allocated for last formed string
6893 representation of regexp. */
6895 finish_regexp_representation (void)
6897 int length
= obstack_object_size (&irp
);
6899 obstack_blank_fast (&irp
, -length
);
6904 /* This page contains code for output PHR (pipeline hazards recognizer). */
6906 /* The function outputs minimal C type which is sufficient for
6907 representation numbers in range min_range_value and
6908 max_range_value. Because host machine and build machine may be
6909 different, we use here minimal values required by ANSI C standard
6910 instead of UCHAR_MAX, SHRT_MAX, SHRT_MIN, etc. This is a good
6914 output_range_type (FILE *f
, long int min_range_value
,
6915 long int max_range_value
)
6917 if (min_range_value
>= 0 && max_range_value
<= 255)
6918 fprintf (f
, "unsigned char");
6919 else if (min_range_value
>= -127 && max_range_value
<= 127)
6920 fprintf (f
, "signed char");
6921 else if (min_range_value
>= 0 && max_range_value
<= 65535)
6922 fprintf (f
, "unsigned short");
6923 else if (min_range_value
>= -32767 && max_range_value
<= 32767)
6924 fprintf (f
, "short");
6929 /* The function outputs all initialization values of VECT. */
6931 output_vect (vla_hwint_t vect
)
6934 size_t vect_length
= vect
.length ();
6938 if (vect_length
== 0)
6939 fputs ("0 /* This is dummy el because the vect is empty */", output_file
);
6941 for (i
= 0; i
< vect_length
; i
++)
6943 fprintf (output_file
, "%5ld", (long) vect
[i
]);
6944 if (els_on_line
== 10)
6947 fputs (",\n", output_file
);
6949 else if (i
< vect_length
-1)
6950 fputs (", ", output_file
);
6955 /* The following is name of the structure which represents DFA(s) for
6957 #define CHIP_NAME "DFA_chip"
6959 /* The following is name of member which represents state of a DFA for
6962 output_chip_member_name (FILE *f
, automaton_t automaton
)
6964 if (automaton
->corresponding_automaton_decl
== NULL
)
6965 fprintf (f
, "automaton_state_%d", automaton
->automaton_order_num
);
6967 fprintf (f
, "%s_automaton_state",
6968 automaton
->corresponding_automaton_decl
->name
);
6971 /* The following is name of temporary variable which stores state of a
6974 output_temp_chip_member_name (FILE *f
, automaton_t automaton
)
6977 output_chip_member_name (f
, automaton
);
6980 /* This is name of macro value which is code of pseudo_insns
6981 representing advancing cpu cycle and collapsing the NDFA.
6982 Its value is used as internal code unknown insn. */
6983 #define ADVANCE_CYCLE_VALUE_NAME "DFA__ADVANCE_CYCLE"
6984 #define COLLAPSE_NDFA_VALUE_NAME "NDFA__COLLAPSE"
6986 /* Output name of translate vector for given automaton. */
6988 output_translate_vect_name (FILE *f
, automaton_t automaton
)
6990 if (automaton
->corresponding_automaton_decl
== NULL
)
6991 fprintf (f
, "translate_%d", automaton
->automaton_order_num
);
6993 fprintf (f
, "%s_translate", automaton
->corresponding_automaton_decl
->name
);
6996 /* Output name for simple transition table representation. */
6998 output_trans_full_vect_name (FILE *f
, automaton_t automaton
)
7000 if (automaton
->corresponding_automaton_decl
== NULL
)
7001 fprintf (f
, "transitions_%d", automaton
->automaton_order_num
);
7003 fprintf (f
, "%s_transitions",
7004 automaton
->corresponding_automaton_decl
->name
);
7007 /* Output name of comb vector of the transition table for given
7010 output_trans_comb_vect_name (FILE *f
, automaton_t automaton
)
7012 if (automaton
->corresponding_automaton_decl
== NULL
)
7013 fprintf (f
, "transitions_%d", automaton
->automaton_order_num
);
7015 fprintf (f
, "%s_transitions",
7016 automaton
->corresponding_automaton_decl
->name
);
7019 /* Output name of check vector of the transition table for given
7022 output_trans_check_vect_name (FILE *f
, automaton_t automaton
)
7024 if (automaton
->corresponding_automaton_decl
== NULL
)
7025 fprintf (f
, "check_%d", automaton
->automaton_order_num
);
7027 fprintf (f
, "%s_check", automaton
->corresponding_automaton_decl
->name
);
7030 /* Output name of base vector of the transition table for given
7033 output_trans_base_vect_name (FILE *f
, automaton_t automaton
)
7035 if (automaton
->corresponding_automaton_decl
== NULL
)
7036 fprintf (f
, "base_%d", automaton
->automaton_order_num
);
7038 fprintf (f
, "%s_base", automaton
->corresponding_automaton_decl
->name
);
7041 /* Output name of simple min issue delay table representation. */
7043 output_min_issue_delay_vect_name (FILE *f
, automaton_t automaton
)
7045 if (automaton
->corresponding_automaton_decl
== NULL
)
7046 fprintf (f
, "min_issue_delay_%d", automaton
->automaton_order_num
);
7048 fprintf (f
, "%s_min_issue_delay",
7049 automaton
->corresponding_automaton_decl
->name
);
7052 /* Output name of deadlock vector for given automaton. */
7054 output_dead_lock_vect_name (FILE *f
, automaton_t automaton
)
7056 if (automaton
->corresponding_automaton_decl
== NULL
)
7057 fprintf (f
, "dead_lock_%d", automaton
->automaton_order_num
);
7059 fprintf (f
, "%s_dead_lock", automaton
->corresponding_automaton_decl
->name
);
7062 /* Output name of reserved units table for AUTOMATON into file F. */
7064 output_reserved_units_table_name (FILE *f
, automaton_t automaton
)
7066 if (automaton
->corresponding_automaton_decl
== NULL
)
7067 fprintf (f
, "reserved_units_%d", automaton
->automaton_order_num
);
7069 fprintf (f
, "%s_reserved_units",
7070 automaton
->corresponding_automaton_decl
->name
);
7073 /* Name of the PHR interface macro. */
7074 #define CPU_UNITS_QUERY_MACRO_NAME "CPU_UNITS_QUERY"
7076 /* Names of an internal functions: */
7077 #define INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME "internal_min_issue_delay"
7079 /* This is external type of DFA(s) state. */
7080 #define STATE_TYPE_NAME "state_t"
7082 #define INTERNAL_TRANSITION_FUNC_NAME "internal_state_transition"
7084 #define INTERNAL_RESET_FUNC_NAME "internal_reset"
7086 #define INTERNAL_DEAD_LOCK_FUNC_NAME "internal_state_dead_lock_p"
7088 #define INTERNAL_INSN_LATENCY_FUNC_NAME "internal_insn_latency"
7090 /* Name of cache of insn dfa codes. */
7091 #define DFA_INSN_CODES_VARIABLE_NAME "dfa_insn_codes"
7093 /* Name of length of cache of insn dfa codes. */
7094 #define DFA_INSN_CODES_LENGTH_VARIABLE_NAME "dfa_insn_codes_length"
7096 /* Names of the PHR interface functions: */
7097 #define SIZE_FUNC_NAME "state_size"
7099 #define TRANSITION_FUNC_NAME "state_transition"
7101 #define MIN_ISSUE_DELAY_FUNC_NAME "min_issue_delay"
7103 #define MIN_INSN_CONFLICT_DELAY_FUNC_NAME "min_insn_conflict_delay"
7105 #define DEAD_LOCK_FUNC_NAME "state_dead_lock_p"
7107 #define RESET_FUNC_NAME "state_reset"
7109 #define INSN_LATENCY_FUNC_NAME "insn_latency"
7111 #define PRINT_RESERVATION_FUNC_NAME "print_reservation"
7113 #define GET_CPU_UNIT_CODE_FUNC_NAME "get_cpu_unit_code"
7115 #define CPU_UNIT_RESERVATION_P_FUNC_NAME "cpu_unit_reservation_p"
7117 #define INSN_HAS_DFA_RESERVATION_P_FUNC_NAME "insn_has_dfa_reservation_p"
7119 #define DFA_CLEAN_INSN_CACHE_FUNC_NAME "dfa_clean_insn_cache"
7121 #define DFA_CLEAR_SINGLE_INSN_CACHE_FUNC_NAME "dfa_clear_single_insn_cache"
7123 #define DFA_START_FUNC_NAME "dfa_start"
7125 #define DFA_FINISH_FUNC_NAME "dfa_finish"
7127 /* Names of parameters of the PHR interface functions. */
7128 #define STATE_NAME "state"
7130 #define INSN_PARAMETER_NAME "insn"
7132 #define INSN2_PARAMETER_NAME "insn2"
7134 #define CHIP_PARAMETER_NAME "chip"
7136 #define FILE_PARAMETER_NAME "f"
7138 #define CPU_UNIT_NAME_PARAMETER_NAME "cpu_unit_name"
7140 #define CPU_CODE_PARAMETER_NAME "cpu_unit_code"
7142 /* Names of the variables whose values are internal insn code of rtx
7144 #define INTERNAL_INSN_CODE_NAME "insn_code"
7146 #define INTERNAL_INSN2_CODE_NAME "insn2_code"
7148 /* Names of temporary variables in some functions. */
7149 #define TEMPORARY_VARIABLE_NAME "temp"
7151 #define I_VARIABLE_NAME "i"
7153 /* Name of result variable in some functions. */
7154 #define RESULT_VARIABLE_NAME "res"
7156 /* Name of function (attribute) to translate insn into internal insn
7158 #define INTERNAL_DFA_INSN_CODE_FUNC_NAME "internal_dfa_insn_code"
7160 /* Name of function (attribute) to translate insn into internal insn
7161 code with caching. */
7162 #define DFA_INSN_CODE_FUNC_NAME "dfa_insn_code"
7164 /* Output C type which is used for representation of codes of states
7167 output_state_member_type (FILE *f
, automaton_t automaton
)
7169 output_range_type (f
, 0, automaton
->achieved_states_num
);
7172 /* Output definition of the structure representing current DFA(s)
7175 output_chip_definitions (void)
7177 automaton_t automaton
;
7179 fprintf (output_file
, "struct %s\n{\n", CHIP_NAME
);
7180 for (automaton
= description
->first_automaton
;
7182 automaton
= automaton
->next_automaton
)
7184 fprintf (output_file
, " ");
7185 output_state_member_type (output_file
, automaton
);
7186 fprintf (output_file
, " ");
7187 output_chip_member_name (output_file
, automaton
);
7188 fprintf (output_file
, ";\n");
7190 fprintf (output_file
, "};\n\n");
7192 fprintf (output_file
, "static struct %s %s;\n\n", CHIP_NAME
, CHIP_NAME
);
7197 /* The function outputs translate vector of internal insn code into
7198 insn equivalence class number. The equivalence class number is
7199 used to access to table and vectors representing DFA(s). */
7201 output_translate_vect (automaton_t automaton
)
7205 vla_hwint_t translate_vect
;
7207 translate_vect
.create (description
->insns_num
);
7209 for (insn_value
= 0; insn_value
< description
->insns_num
; insn_value
++)
7210 /* Undefined value */
7211 translate_vect
.quick_push (automaton
->insn_equiv_classes_num
);
7213 for (ainsn
= automaton
->ainsn_list
; ainsn
!= NULL
; ainsn
= ainsn
->next_ainsn
)
7214 translate_vect
[ainsn
->insn_reserv_decl
->insn_num
] =
7215 ainsn
->insn_equiv_class_num
;
7217 fprintf (output_file
,
7218 "/* Vector translating external insn codes to internal ones.*/\n");
7219 fprintf (output_file
, "static const ");
7220 output_range_type (output_file
, 0, automaton
->insn_equiv_classes_num
);
7221 fprintf (output_file
, " ");
7222 output_translate_vect_name (output_file
, automaton
);
7223 fprintf (output_file
, "[] ATTRIBUTE_UNUSED = {\n");
7224 output_vect (translate_vect
);
7225 fprintf (output_file
, "};\n\n");
7226 translate_vect
.release ();
7229 /* The value in a table state x ainsn -> something which represents
7231 static int undefined_vect_el_value
;
7233 /* The following function returns nonzero value if the best
7234 representation of the table is comb vector. */
7236 comb_vect_p (state_ainsn_table_t tab
)
7240 return (2 * tab
->full_vect
.length () > 5 * tab
->comb_vect
.length ());
7243 /* The following function creates new table for AUTOMATON. */
7244 static state_ainsn_table_t
7245 create_state_ainsn_table (automaton_t automaton
)
7247 state_ainsn_table_t tab
;
7248 int full_vect_length
;
7251 tab
= XCREATENODE (struct state_ainsn_table
);
7252 tab
->automaton
= automaton
;
7254 tab
->comb_vect
.create (10000);
7255 tab
->check_vect
.create (10000);
7257 tab
->base_vect
.create (0);
7258 tab
->base_vect
.safe_grow (automaton
->achieved_states_num
);
7260 full_vect_length
= (automaton
->insn_equiv_classes_num
7261 * automaton
->achieved_states_num
);
7262 tab
->full_vect
.create (full_vect_length
);
7263 for (i
= 0; i
< full_vect_length
; i
++)
7264 tab
->full_vect
.quick_push (undefined_vect_el_value
);
7266 tab
->min_base_vect_el_value
= 0;
7267 tab
->max_base_vect_el_value
= 0;
7268 tab
->min_comb_vect_el_value
= 0;
7269 tab
->max_comb_vect_el_value
= 0;
7273 /* The following function outputs the best C representation of the
7274 table TAB of given TABLE_NAME. */
7276 output_state_ainsn_table (state_ainsn_table_t tab
, const char *table_name
,
7277 void (*output_full_vect_name_func
) (FILE *, automaton_t
),
7278 void (*output_comb_vect_name_func
) (FILE *, automaton_t
),
7279 void (*output_check_vect_name_func
) (FILE *, automaton_t
),
7280 void (*output_base_vect_name_func
) (FILE *, automaton_t
))
7282 if (!comb_vect_p (tab
))
7284 fprintf (output_file
, "/* Vector for %s. */\n", table_name
);
7285 fprintf (output_file
, "static const ");
7286 output_range_type (output_file
, tab
->min_comb_vect_el_value
,
7287 tab
->max_comb_vect_el_value
);
7288 fprintf (output_file
, " ");
7289 (*output_full_vect_name_func
) (output_file
, tab
->automaton
);
7290 fprintf (output_file
, "[] ATTRIBUTE_UNUSED = {\n");
7291 output_vect (tab
->full_vect
);
7292 fprintf (output_file
, "};\n\n");
7296 fprintf (output_file
, "/* Comb vector for %s. */\n", table_name
);
7297 fprintf (output_file
, "static const ");
7298 output_range_type (output_file
, tab
->min_comb_vect_el_value
,
7299 tab
->max_comb_vect_el_value
);
7300 fprintf (output_file
, " ");
7301 (*output_comb_vect_name_func
) (output_file
, tab
->automaton
);
7302 fprintf (output_file
, "[] ATTRIBUTE_UNUSED = {\n");
7303 output_vect (tab
->comb_vect
);
7304 fprintf (output_file
, "};\n\n");
7305 fprintf (output_file
, "/* Check vector for %s. */\n", table_name
);
7306 fprintf (output_file
, "static const ");
7307 output_range_type (output_file
, 0, tab
->automaton
->achieved_states_num
);
7308 fprintf (output_file
, " ");
7309 (*output_check_vect_name_func
) (output_file
, tab
->automaton
);
7310 fprintf (output_file
, "[] = {\n");
7311 output_vect (tab
->check_vect
);
7312 fprintf (output_file
, "};\n\n");
7313 fprintf (output_file
, "/* Base vector for %s. */\n", table_name
);
7314 fprintf (output_file
, "static const ");
7315 output_range_type (output_file
, tab
->min_base_vect_el_value
,
7316 tab
->max_base_vect_el_value
);
7317 fprintf (output_file
, " ");
7318 (*output_base_vect_name_func
) (output_file
, tab
->automaton
);
7319 fprintf (output_file
, "[] = {\n");
7320 output_vect (tab
->base_vect
);
7321 fprintf (output_file
, "};\n\n");
7325 /* The following function adds vector VECT to table TAB as its line
7326 with number VECT_NUM. */
7328 add_vect (state_ainsn_table_t tab
, int vect_num
, vla_hwint_t vect
)
7331 size_t real_vect_length
;
7332 int comb_vect_index
;
7333 int comb_vect_els_num
;
7335 int first_unempty_vect_index
;
7336 int additional_els_num
;
7340 unsigned long vect_mask
, comb_vect_mask
;
7342 vect_length
= vect
.length ();
7343 gcc_assert (vect_length
);
7344 gcc_assert (vect
.last () != undefined_vect_el_value
);
7345 real_vect_length
= tab
->automaton
->insn_equiv_classes_num
;
7346 /* Form full vector in the table: */
7348 size_t full_base
= tab
->automaton
->insn_equiv_classes_num
* vect_num
;
7349 if (tab
->full_vect
.length () < full_base
+ vect_length
)
7350 tab
->full_vect
.safe_grow (full_base
+ vect_length
);
7351 for (i
= 0; i
< vect_length
; i
++)
7352 tab
->full_vect
[full_base
+ i
] = vect
[i
];
7355 /* The comb_vect min/max values are also used for the full vector, so
7356 compute them now. */
7357 for (vect_index
= 0; vect_index
< vect_length
; vect_index
++)
7358 if (vect
[vect_index
] != undefined_vect_el_value
)
7360 vect_el_t x
= vect
[vect_index
];
7361 gcc_assert (x
>= 0);
7362 if (tab
->max_comb_vect_el_value
< x
)
7363 tab
->max_comb_vect_el_value
= x
;
7364 if (tab
->min_comb_vect_el_value
> x
)
7365 tab
->min_comb_vect_el_value
= x
;
7370 /* Form comb vector in the table: */
7371 gcc_assert (tab
->comb_vect
.length () == tab
->check_vect
.length ());
7373 comb_vect_els_num
= tab
->comb_vect
.length ();
7374 for (first_unempty_vect_index
= 0;
7375 first_unempty_vect_index
< vect_length
;
7376 first_unempty_vect_index
++)
7377 if (vect
[first_unempty_vect_index
]
7378 != undefined_vect_el_value
)
7381 /* Search for the place in comb vect for the inserted vect. */
7384 if (vect_length
- first_unempty_vect_index
>= SIZEOF_LONG
* CHAR_BIT
)
7386 for (comb_vect_index
= 0;
7387 comb_vect_index
< comb_vect_els_num
;
7390 for (vect_index
= first_unempty_vect_index
;
7391 vect_index
< vect_length
7392 && vect_index
+ comb_vect_index
< comb_vect_els_num
;
7394 if (vect
[vect_index
]
7395 != undefined_vect_el_value
7396 && (tab
->comb_vect
[vect_index
+ comb_vect_index
]
7397 != undefined_vect_el_value
))
7399 if (vect_index
>= vect_length
7400 || vect_index
+ comb_vect_index
>= comb_vect_els_num
)
7408 for (vect_index
= first_unempty_vect_index
;
7409 vect_index
< vect_length
;
7412 vect_mask
= vect_mask
<< 1;
7413 if (vect
[vect_index
] != undefined_vect_el_value
)
7417 /* Search for the place in comb vect for the inserted vect. */
7418 comb_vect_index
= 0;
7419 if (comb_vect_els_num
== 0)
7423 for (vect_index
= first_unempty_vect_index
;
7424 vect_index
< vect_length
&& vect_index
< comb_vect_els_num
;
7427 comb_vect_mask
<<= 1;
7428 if (vect_index
+ comb_vect_index
< comb_vect_els_num
7429 && tab
->comb_vect
[vect_index
+ comb_vect_index
]
7430 != undefined_vect_el_value
)
7431 comb_vect_mask
|= 1;
7433 if ((vect_mask
& comb_vect_mask
) == 0)
7436 for (comb_vect_index
= 1, i
= vect_length
; i
< comb_vect_els_num
;
7437 comb_vect_index
++, i
++)
7439 comb_vect_mask
= (comb_vect_mask
<< 1) | 1;
7440 comb_vect_mask
^= (tab
->comb_vect
[i
]
7441 == undefined_vect_el_value
);
7442 if ((vect_mask
& comb_vect_mask
) == 0)
7445 for ( ; comb_vect_index
< comb_vect_els_num
; comb_vect_index
++)
7447 comb_vect_mask
<<= 1;
7448 if ((vect_mask
& comb_vect_mask
) == 0)
7453 /* Slot was found. */
7454 additional_els_num
= comb_vect_index
+ real_vect_length
- comb_vect_els_num
;
7455 if (additional_els_num
< 0)
7456 additional_els_num
= 0;
7457 /* Expand comb and check vectors. */
7458 vect_el
= undefined_vect_el_value
;
7459 no_state_value
= tab
->automaton
->achieved_states_num
;
7460 while (additional_els_num
> 0)
7462 tab
->comb_vect
.safe_push (vect_el
);
7463 tab
->check_vect
.safe_push (no_state_value
);
7464 additional_els_num
--;
7466 gcc_assert (tab
->comb_vect
.length ()
7467 >= comb_vect_index
+ real_vect_length
);
7468 /* Fill comb and check vectors. */
7469 for (vect_index
= 0; vect_index
< vect_length
; vect_index
++)
7470 if (vect
[vect_index
] != undefined_vect_el_value
)
7472 vect_el_t x
= vect
[vect_index
];
7473 gcc_assert (tab
->comb_vect
[comb_vect_index
+ vect_index
]
7474 == undefined_vect_el_value
);
7475 gcc_assert (x
>= 0);
7476 tab
->comb_vect
[comb_vect_index
+ vect_index
] = x
;
7477 tab
->check_vect
[comb_vect_index
+ vect_index
] = vect_num
;
7479 if (tab
->max_comb_vect_el_value
< undefined_vect_el_value
)
7480 tab
->max_comb_vect_el_value
= undefined_vect_el_value
;
7481 if (tab
->min_comb_vect_el_value
> undefined_vect_el_value
)
7482 tab
->min_comb_vect_el_value
= undefined_vect_el_value
;
7483 if (tab
->max_base_vect_el_value
< comb_vect_index
)
7484 tab
->max_base_vect_el_value
= comb_vect_index
;
7485 if (tab
->min_base_vect_el_value
> comb_vect_index
)
7486 tab
->min_base_vect_el_value
= comb_vect_index
;
7488 tab
->base_vect
[vect_num
] = comb_vect_index
;
7491 /* Return number of out arcs of STATE. */
7493 out_state_arcs_num (const_state_t state
)
7499 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
7501 gcc_assert (arc
->insn
);
7502 if (arc
->insn
->first_ainsn_with_given_equivalence_num
)
7508 /* Compare number of possible transitions from the states. */
7510 compare_transition_els_num (const void *state_ptr_1
,
7511 const void *state_ptr_2
)
7513 const int transition_els_num_1
7514 = out_state_arcs_num (*(const_state_t
const*) state_ptr_1
);
7515 const int transition_els_num_2
7516 = out_state_arcs_num (*(const_state_t
const*) state_ptr_2
);
7518 if (transition_els_num_1
< transition_els_num_2
)
7520 else if (transition_els_num_1
== transition_els_num_2
)
7526 /* The function adds element EL_VALUE to vector VECT for a table state
7529 add_vect_el (vla_hwint_t
&vect
, ainsn_t ainsn
, int el_value
)
7531 int equiv_class_num
;
7535 equiv_class_num
= ainsn
->insn_equiv_class_num
;
7536 for (vect_index
= vect
.length ();
7537 vect_index
<= equiv_class_num
;
7539 vect
.safe_push (undefined_vect_el_value
);
7540 vect
[equiv_class_num
] = el_value
;
7543 /* This is for forming vector of states of an automaton. */
7544 static vec
<state_t
> output_states_vect
;
7546 /* The function is called by function pass_states. The function adds
7547 STATE to `output_states_vect'. */
7549 add_states_vect_el (state_t state
)
7551 output_states_vect
.safe_push (state
);
7554 /* Form and output vectors (comb, check, base or full vector)
7555 representing transition table of AUTOMATON. */
7557 output_trans_table (automaton_t automaton
)
7561 vla_hwint_t transition_vect
= vla_hwint_t();
7563 undefined_vect_el_value
= automaton
->achieved_states_num
;
7564 automaton
->trans_table
= create_state_ainsn_table (automaton
);
7565 /* Create vect of pointers to states ordered by num of transitions
7566 from the state (state with the maximum num is the first). */
7567 output_states_vect
.create (0);
7568 pass_states (automaton
, add_states_vect_el
);
7569 output_states_vect
.qsort (compare_transition_els_num
);
7571 for (i
= 0; i
< output_states_vect
.length (); i
++)
7573 transition_vect
.truncate (0);
7574 for (arc
= first_out_arc (output_states_vect
[i
]);
7576 arc
= next_out_arc (arc
))
7578 gcc_assert (arc
->insn
);
7579 if (arc
->insn
->first_ainsn_with_given_equivalence_num
)
7580 add_vect_el (transition_vect
, arc
->insn
,
7581 arc
->to_state
->order_state_num
);
7583 add_vect (automaton
->trans_table
,
7584 output_states_vect
[i
]->order_state_num
,
7587 output_state_ainsn_table
7588 (automaton
->trans_table
, "state transitions",
7589 output_trans_full_vect_name
, output_trans_comb_vect_name
,
7590 output_trans_check_vect_name
, output_trans_base_vect_name
);
7592 output_states_vect
.release ();
7593 transition_vect
.release ();
7596 /* Form and output vectors representing minimal issue delay table of
7597 AUTOMATON. The table is state x ainsn -> minimal issue delay of
7600 output_min_issue_delay_table (automaton_t automaton
)
7602 vla_hwint_t min_issue_delay_vect
;
7603 vla_hwint_t compressed_min_issue_delay_vect
;
7606 size_t min_issue_delay_len
, compressed_min_issue_delay_len
;
7610 /* Create vect of pointers to states ordered by num of transitions
7611 from the state (state with the maximum num is the first). */
7612 output_states_vect
.create (0);
7613 pass_states (automaton
, add_states_vect_el
);
7615 min_issue_delay_len
= (output_states_vect
.length ()
7616 * automaton
->insn_equiv_classes_num
);
7617 min_issue_delay_vect
.create (min_issue_delay_len
);
7618 for (i
= 0; i
< min_issue_delay_len
; i
++)
7619 min_issue_delay_vect
.quick_push (-1);
7621 automaton
->max_min_delay
= 0;
7629 for (state_no
= 0; state_no
< output_states_vect
.length ();
7632 state_t s
= output_states_vect
[state_no
];
7635 for (arc
= first_out_arc (s
); arc
; arc
= next_out_arc (arc
))
7639 size_t asn
= s
->order_state_num
7640 * automaton
->insn_equiv_classes_num
7641 + arc
->insn
->insn_equiv_class_num
;
7643 if (min_issue_delay_vect
[asn
])
7645 min_issue_delay_vect
[asn
] = (vect_el_t
) 0;
7649 for (k
= 0; k
< automaton
->insn_equiv_classes_num
; k
++)
7652 vect_el_t delay0
, delay1
;
7654 n0
= s
->order_state_num
7655 * automaton
->insn_equiv_classes_num
7657 n1
= arc
->to_state
->order_state_num
7658 * automaton
->insn_equiv_classes_num
7660 delay0
= min_issue_delay_vect
[n0
];
7661 delay1
= min_issue_delay_vect
[n1
];
7664 if (arc
->insn
->insn_reserv_decl
7665 == DECL_INSN_RESERV (advance_cycle_insn_decl
))
7667 if (delay1
< delay0
|| delay0
== -1)
7669 min_issue_delay_vect
[n0
] = delay1
;
7679 automaton
->max_min_delay
= 0;
7681 for (ainsn
= automaton
->ainsn_list
; ainsn
; ainsn
= ainsn
->next_ainsn
)
7682 if (ainsn
->first_ainsn_with_given_equivalence_num
)
7684 for (i
= 0; i
< output_states_vect
.length (); i
++)
7686 state_t s
= output_states_vect
[i
];
7687 size_t np
= s
->order_state_num
7688 * automaton
->insn_equiv_classes_num
7689 + ainsn
->insn_equiv_class_num
;
7690 vect_el_t x
= min_issue_delay_vect
[np
];
7692 if (automaton
->max_min_delay
< x
)
7693 automaton
->max_min_delay
= x
;
7695 min_issue_delay_vect
[np
] = (vect_el_t
) 0;
7699 fprintf (output_file
, "/* Vector of min issue delay of insns. */\n");
7700 fprintf (output_file
, "static const ");
7701 output_range_type (output_file
, 0, automaton
->max_min_delay
);
7702 fprintf (output_file
, " ");
7703 output_min_issue_delay_vect_name (output_file
, automaton
);
7704 fprintf (output_file
, "[] ATTRIBUTE_UNUSED = {\n");
7705 /* Compress the vector. */
7706 if (automaton
->max_min_delay
< 2)
7708 else if (automaton
->max_min_delay
< 4)
7710 else if (automaton
->max_min_delay
< 16)
7714 automaton
->min_issue_delay_table_compression_factor
= cfactor
;
7716 compressed_min_issue_delay_len
= (min_issue_delay_len
+cfactor
-1) / cfactor
;
7717 compressed_min_issue_delay_vect
.create (compressed_min_issue_delay_len
);
7719 for (i
= 0; i
< compressed_min_issue_delay_len
; i
++)
7720 compressed_min_issue_delay_vect
.quick_push (0);
7722 for (i
= 0; i
< min_issue_delay_len
; i
++)
7724 size_t ci
= i
/ cfactor
;
7725 vect_el_t x
= min_issue_delay_vect
[i
];
7726 vect_el_t cx
= compressed_min_issue_delay_vect
[ci
];
7728 cx
|= x
<< (8 - (i
% cfactor
+ 1) * (8 / cfactor
));
7729 compressed_min_issue_delay_vect
[ci
] = cx
;
7731 output_vect (compressed_min_issue_delay_vect
);
7732 fprintf (output_file
, "};\n\n");
7733 output_states_vect
.release ();
7734 min_issue_delay_vect
.release ();
7735 compressed_min_issue_delay_vect
.release ();
7738 /* Form and output vector representing the locked states of
7741 output_dead_lock_vect (automaton_t automaton
)
7745 vla_hwint_t dead_lock_vect
= vla_hwint_t();
7747 /* Create vect of pointers to states ordered by num of
7748 transitions from the state (state with the maximum num is the
7750 automaton
->locked_states
= 0;
7751 output_states_vect
.create (0);
7752 pass_states (automaton
, add_states_vect_el
);
7754 dead_lock_vect
.safe_grow (output_states_vect
.length ());
7755 for (i
= 0; i
< output_states_vect
.length (); i
++)
7757 state_t s
= output_states_vect
[i
];
7758 arc
= first_out_arc (s
);
7760 if (next_out_arc (arc
) == NULL
7761 && (arc
->insn
->insn_reserv_decl
7762 == DECL_INSN_RESERV (advance_cycle_insn_decl
)))
7764 dead_lock_vect
[s
->order_state_num
] = 1;
7765 automaton
->locked_states
++;
7768 dead_lock_vect
[s
->order_state_num
] = (vect_el_t
) 0;
7770 if (automaton
->locked_states
== 0)
7773 fprintf (output_file
, "/* Vector for locked state flags. */\n");
7774 fprintf (output_file
, "static const ");
7775 output_range_type (output_file
, 0, 1);
7776 fprintf (output_file
, " ");
7777 output_dead_lock_vect_name (output_file
, automaton
);
7778 fprintf (output_file
, "[] = {\n");
7779 output_vect (dead_lock_vect
);
7780 fprintf (output_file
, "};\n\n");
7781 output_states_vect
.release ();
7782 dead_lock_vect
.release ();
7785 /* Form and output vector representing reserved units of the states of
7788 output_reserved_units_table (automaton_t automaton
)
7790 vla_hwint_t reserved_units_table
= vla_hwint_t();
7791 int state_byte_size
;
7792 int reserved_units_size
;
7796 if (description
->query_units_num
== 0)
7799 /* Create vect of pointers to states. */
7800 output_states_vect
.create (0);
7801 pass_states (automaton
, add_states_vect_el
);
7802 /* Create vector. */
7803 state_byte_size
= (description
->query_units_num
+ 7) / 8;
7804 reserved_units_size
= (output_states_vect
.length ()
7807 reserved_units_table
.create (reserved_units_size
);
7809 for (i
= 0; i
< reserved_units_size
; i
++)
7810 reserved_units_table
.quick_push (0);
7811 for (n
= 0; n
< output_states_vect
.length (); n
++)
7813 state_t s
= output_states_vect
[n
];
7814 for (i
= 0; i
< description
->units_num
; i
++)
7815 if (units_array
[i
]->query_p
7816 && first_cycle_unit_presence (s
, i
))
7818 int ri
= (s
->order_state_num
* state_byte_size
7819 + units_array
[i
]->query_num
/ 8);
7820 vect_el_t x
= reserved_units_table
[ri
];
7822 x
+= 1 << (units_array
[i
]->query_num
% 8);
7823 reserved_units_table
[ri
] = x
;
7826 fprintf (output_file
, "\n#if %s\n", CPU_UNITS_QUERY_MACRO_NAME
);
7827 fprintf (output_file
, "/* Vector for reserved units of states. */\n");
7828 fprintf (output_file
, "static const ");
7829 output_range_type (output_file
, 0, 255);
7830 fprintf (output_file
, " ");
7831 output_reserved_units_table_name (output_file
, automaton
);
7832 fprintf (output_file
, "[] = {\n");
7833 output_vect (reserved_units_table
);
7834 fprintf (output_file
, "};\n#endif /* #if %s */\n\n",
7835 CPU_UNITS_QUERY_MACRO_NAME
);
7837 output_states_vect
.release ();
7838 reserved_units_table
.release ();
7841 /* The function outputs all tables representing DFA(s) used for fast
7842 pipeline hazards recognition. */
7844 output_tables (void)
7846 automaton_t automaton
;
7848 for (automaton
= description
->first_automaton
;
7850 automaton
= automaton
->next_automaton
)
7852 output_translate_vect (automaton
);
7853 output_trans_table (automaton
);
7854 output_min_issue_delay_table (automaton
);
7855 output_dead_lock_vect (automaton
);
7856 output_reserved_units_table (automaton
);
7858 fprintf (output_file
, "\n#define %s %d\n\n", ADVANCE_CYCLE_VALUE_NAME
,
7859 DECL_INSN_RESERV (advance_cycle_insn_decl
)->insn_num
);
7861 fprintf (output_file
, "\n#define %s %d\n\n", COLLAPSE_NDFA_VALUE_NAME
,
7862 DECL_INSN_RESERV (collapse_ndfa_insn_decl
)->insn_num
);
7865 /* The function outputs definition and value of PHR interface variable
7866 `max_insn_queue_index'. Its value is not less than maximal queue
7867 length needed for the insn scheduler. */
7869 output_max_insn_queue_index_def (void)
7871 int i
, max
, latency
;
7874 max
= description
->max_insn_reserv_cycles
;
7875 for (i
= 0; i
< description
->decls_num
; i
++)
7877 decl
= description
->decls
[i
];
7878 if (decl
->mode
== dm_insn_reserv
&& decl
!= advance_cycle_insn_decl
)
7880 latency
= DECL_INSN_RESERV (decl
)->default_latency
;
7884 else if (decl
->mode
== dm_bypass
)
7886 latency
= DECL_BYPASS (decl
)->latency
;
7891 for (i
= 0; (1 << i
) <= max
; i
++)
7893 gcc_assert (i
>= 0);
7894 fprintf (output_file
, "\nconst int max_insn_queue_index = %d;\n\n",
7898 /* The function outputs switch cases for insn reservations using
7899 function *output_automata_list_code. */
7901 output_insn_code_cases (void (*output_automata_list_code
)
7902 (automata_list_el_t
))
7907 for (i
= 0; i
< description
->decls_num
; i
++)
7909 decl
= description
->decls
[i
];
7910 if (decl
->mode
== dm_insn_reserv
)
7911 DECL_INSN_RESERV (decl
)->processed_p
= FALSE
;
7913 for (i
= 0; i
< description
->decls_num
; i
++)
7915 decl
= description
->decls
[i
];
7916 if (decl
->mode
== dm_insn_reserv
7917 && !DECL_INSN_RESERV (decl
)->processed_p
)
7919 for (j
= i
; j
< description
->decls_num
; j
++)
7921 decl2
= description
->decls
[j
];
7922 if (decl2
->mode
== dm_insn_reserv
7923 && (DECL_INSN_RESERV (decl2
)->important_automata_list
7924 == DECL_INSN_RESERV (decl
)->important_automata_list
))
7926 DECL_INSN_RESERV (decl2
)->processed_p
= TRUE
;
7927 fprintf (output_file
, " case %d: /* %s */\n",
7928 DECL_INSN_RESERV (decl2
)->insn_num
,
7929 DECL_INSN_RESERV (decl2
)->name
);
7932 (*output_automata_list_code
)
7933 (DECL_INSN_RESERV (decl
)->important_automata_list
);
7939 /* The function outputs a code for evaluation of a minimal delay of
7940 issue of insns which have reservations in given AUTOMATA_LIST. */
7942 output_automata_list_min_issue_delay_code (automata_list_el_t automata_list
)
7944 automata_list_el_t el
;
7945 automaton_t automaton
;
7947 for (el
= automata_list
; el
!= NULL
; el
= el
->next_automata_list_el
)
7949 automaton
= el
->automaton
;
7950 fprintf (output_file
, "\n %s = ", TEMPORARY_VARIABLE_NAME
);
7951 output_min_issue_delay_vect_name (output_file
, automaton
);
7952 fprintf (output_file
,
7953 (automaton
->min_issue_delay_table_compression_factor
!= 1
7955 output_translate_vect_name (output_file
, automaton
);
7956 fprintf (output_file
, " [%s] + ", INTERNAL_INSN_CODE_NAME
);
7957 fprintf (output_file
, "%s->", CHIP_PARAMETER_NAME
);
7958 output_chip_member_name (output_file
, automaton
);
7959 fprintf (output_file
, " * %d", automaton
->insn_equiv_classes_num
);
7960 if (automaton
->min_issue_delay_table_compression_factor
== 1)
7961 fprintf (output_file
, "];\n");
7964 fprintf (output_file
, ") / %d];\n",
7965 automaton
->min_issue_delay_table_compression_factor
);
7966 fprintf (output_file
, " %s = (%s >> (8 - ((",
7967 TEMPORARY_VARIABLE_NAME
, TEMPORARY_VARIABLE_NAME
);
7968 output_translate_vect_name (output_file
, automaton
);
7969 fprintf (output_file
, " [%s] + ", INTERNAL_INSN_CODE_NAME
);
7970 fprintf (output_file
, "%s->", CHIP_PARAMETER_NAME
);
7971 output_chip_member_name (output_file
, automaton
);
7972 fprintf (output_file
, " * %d)", automaton
->insn_equiv_classes_num
);
7974 (output_file
, " %% %d + 1) * %d)) & %d;\n",
7975 automaton
->min_issue_delay_table_compression_factor
,
7976 8 / automaton
->min_issue_delay_table_compression_factor
,
7977 (1 << (8 / automaton
->min_issue_delay_table_compression_factor
))
7980 if (el
== automata_list
)
7981 fprintf (output_file
, " %s = %s;\n",
7982 RESULT_VARIABLE_NAME
, TEMPORARY_VARIABLE_NAME
);
7985 fprintf (output_file
, " if (%s > %s)\n",
7986 TEMPORARY_VARIABLE_NAME
, RESULT_VARIABLE_NAME
);
7987 fprintf (output_file
, " %s = %s;\n",
7988 RESULT_VARIABLE_NAME
, TEMPORARY_VARIABLE_NAME
);
7991 fprintf (output_file
, " break;\n\n");
7994 /* Output function `internal_min_issue_delay'. */
7996 output_internal_min_issue_delay_func (void)
7998 fprintf (output_file
,
7999 "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
8000 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
8001 CHIP_NAME
, CHIP_PARAMETER_NAME
);
8002 fprintf (output_file
, "{\n int %s ATTRIBUTE_UNUSED;\n int %s = -1;\n",
8003 TEMPORARY_VARIABLE_NAME
, RESULT_VARIABLE_NAME
);
8004 fprintf (output_file
, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME
);
8005 output_insn_code_cases (output_automata_list_min_issue_delay_code
);
8006 fprintf (output_file
,
8007 "\n default:\n %s = -1;\n break;\n }\n",
8008 RESULT_VARIABLE_NAME
);
8009 fprintf (output_file
, " return %s;\n", RESULT_VARIABLE_NAME
);
8010 fprintf (output_file
, "}\n\n");
8013 /* The function outputs a code changing state after issue of insns
8014 which have reservations in given AUTOMATA_LIST. */
8016 output_automata_list_transition_code (automata_list_el_t automata_list
)
8018 automata_list_el_t el
, next_el
;
8020 fprintf (output_file
, " {\n");
8021 if (automata_list
!= NULL
&& automata_list
->next_automata_list_el
!= NULL
)
8022 for (el
= automata_list
;; el
= next_el
)
8024 next_el
= el
->next_automata_list_el
;
8025 if (next_el
== NULL
)
8027 fprintf (output_file
, " ");
8028 output_state_member_type (output_file
, el
->automaton
);
8029 fprintf (output_file
, " ");
8030 output_temp_chip_member_name (output_file
, el
->automaton
);
8031 fprintf (output_file
, ";\n");
8033 for (el
= automata_list
; el
!= NULL
; el
= el
->next_automata_list_el
)
8034 if (comb_vect_p (el
->automaton
->trans_table
))
8036 fprintf (output_file
, "\n %s = ", TEMPORARY_VARIABLE_NAME
);
8037 output_trans_base_vect_name (output_file
, el
->automaton
);
8038 fprintf (output_file
, " [%s->", CHIP_PARAMETER_NAME
);
8039 output_chip_member_name (output_file
, el
->automaton
);
8040 fprintf (output_file
, "] + ");
8041 output_translate_vect_name (output_file
, el
->automaton
);
8042 fprintf (output_file
, " [%s];\n", INTERNAL_INSN_CODE_NAME
);
8043 fprintf (output_file
, " if (");
8044 output_trans_check_vect_name (output_file
, el
->automaton
);
8045 fprintf (output_file
, " [%s] != %s->",
8046 TEMPORARY_VARIABLE_NAME
, CHIP_PARAMETER_NAME
);
8047 output_chip_member_name (output_file
, el
->automaton
);
8048 fprintf (output_file
, ")\n");
8049 fprintf (output_file
, " return %s (%s, %s);\n",
8050 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
8051 CHIP_PARAMETER_NAME
);
8052 fprintf (output_file
, " else\n");
8053 fprintf (output_file
, " ");
8054 if (el
->next_automata_list_el
!= NULL
)
8055 output_temp_chip_member_name (output_file
, el
->automaton
);
8058 fprintf (output_file
, "%s->", CHIP_PARAMETER_NAME
);
8059 output_chip_member_name (output_file
, el
->automaton
);
8061 fprintf (output_file
, " = ");
8062 output_trans_comb_vect_name (output_file
, el
->automaton
);
8063 fprintf (output_file
, " [%s];\n", TEMPORARY_VARIABLE_NAME
);
8067 fprintf (output_file
, "\n %s = ", TEMPORARY_VARIABLE_NAME
);
8068 output_trans_full_vect_name (output_file
, el
->automaton
);
8069 fprintf (output_file
, " [");
8070 output_translate_vect_name (output_file
, el
->automaton
);
8071 fprintf (output_file
, " [%s] + ", INTERNAL_INSN_CODE_NAME
);
8072 fprintf (output_file
, "%s->", CHIP_PARAMETER_NAME
);
8073 output_chip_member_name (output_file
, el
->automaton
);
8074 fprintf (output_file
, " * %d];\n",
8075 el
->automaton
->insn_equiv_classes_num
);
8076 fprintf (output_file
, " if (%s >= %d)\n",
8077 TEMPORARY_VARIABLE_NAME
, el
->automaton
->achieved_states_num
);
8078 fprintf (output_file
, " return %s (%s, %s);\n",
8079 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
8080 CHIP_PARAMETER_NAME
);
8081 fprintf (output_file
, " else\n ");
8082 if (el
->next_automata_list_el
!= NULL
)
8083 output_temp_chip_member_name (output_file
, el
->automaton
);
8086 fprintf (output_file
, "%s->", CHIP_PARAMETER_NAME
);
8087 output_chip_member_name (output_file
, el
->automaton
);
8089 fprintf (output_file
, " = %s;\n", TEMPORARY_VARIABLE_NAME
);
8091 if (automata_list
!= NULL
&& automata_list
->next_automata_list_el
!= NULL
)
8092 for (el
= automata_list
;; el
= next_el
)
8094 next_el
= el
->next_automata_list_el
;
8095 if (next_el
== NULL
)
8097 fprintf (output_file
, " %s->", CHIP_PARAMETER_NAME
);
8098 output_chip_member_name (output_file
, el
->automaton
);
8099 fprintf (output_file
, " = ");
8100 output_temp_chip_member_name (output_file
, el
->automaton
);
8101 fprintf (output_file
, ";\n");
8103 fprintf (output_file
, " return -1;\n");
8104 fprintf (output_file
, " }\n");
8107 /* Output function `internal_state_transition'. */
8109 output_internal_trans_func (void)
8111 fprintf (output_file
,
8112 "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
8113 INTERNAL_TRANSITION_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
8114 CHIP_NAME
, CHIP_PARAMETER_NAME
);
8115 fprintf (output_file
, "{\n int %s ATTRIBUTE_UNUSED;\n", TEMPORARY_VARIABLE_NAME
);
8116 fprintf (output_file
, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME
);
8117 output_insn_code_cases (output_automata_list_transition_code
);
8118 fprintf (output_file
, "\n default:\n return -1;\n }\n");
8119 fprintf (output_file
, "}\n\n");
8126 insn_code = dfa_insn_code (insn);
8127 if (insn_code > DFA__ADVANCE_CYCLE)
8131 insn_code = DFA__ADVANCE_CYCLE;
8133 where insn denotes INSN_NAME, insn_code denotes INSN_CODE_NAME, and
8134 code denotes CODE. */
8136 output_internal_insn_code_evaluation (const char *insn_name
,
8137 const char *insn_code_name
,
8140 fprintf (output_file
, "\n if (%s == 0)\n", insn_name
);
8141 fprintf (output_file
, " %s = %s;\n\n",
8142 insn_code_name
, ADVANCE_CYCLE_VALUE_NAME
);
8145 fprintf (output_file
, "\n else if (%s == const0_rtx)\n", insn_name
);
8146 fprintf (output_file
, " %s = %s;\n\n",
8147 insn_code_name
, COLLAPSE_NDFA_VALUE_NAME
);
8149 fprintf (output_file
, "\n else\n {\n");
8150 fprintf (output_file
, " %s = %s (%s);\n", insn_code_name
,
8151 DFA_INSN_CODE_FUNC_NAME
, insn_name
);
8152 fprintf (output_file
, " if (%s > %s)\n return %d;\n }\n",
8153 insn_code_name
, ADVANCE_CYCLE_VALUE_NAME
, code
);
8157 /* This function outputs `dfa_insn_code' and its helper function
8158 `dfa_insn_code_enlarge'. */
8160 output_dfa_insn_code_func (void)
8162 /* Emacs c-mode gets really confused if there's a { or } in column 0
8163 inside a string, so don't do that. */
8164 fprintf (output_file
, "\
8166 dfa_insn_code_enlarge (int uid)\n\
8170 %s = XRESIZEVEC (int, %s,\n\
8172 for (; i < %s; i++)\n\
8173 %s[i] = -1;\n}\n\n",
8174 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
,
8175 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
,
8176 DFA_INSN_CODES_VARIABLE_NAME
, DFA_INSN_CODES_VARIABLE_NAME
,
8177 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
,
8178 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
,
8179 DFA_INSN_CODES_VARIABLE_NAME
);
8180 fprintf (output_file
, "\
8181 static inline int\n%s (rtx %s)\n\
8183 int uid = INSN_UID (%s);\n\
8185 DFA_INSN_CODE_FUNC_NAME
, INSN_PARAMETER_NAME
,
8186 INSN_PARAMETER_NAME
, INTERNAL_INSN_CODE_NAME
);
8188 fprintf (output_file
,
8189 " if (uid >= %s)\n dfa_insn_code_enlarge (uid);\n\n",
8190 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
);
8191 fprintf (output_file
, " %s = %s[uid];\n",
8192 INTERNAL_INSN_CODE_NAME
, DFA_INSN_CODES_VARIABLE_NAME
);
8193 fprintf (output_file
, "\
8199 INTERNAL_INSN_CODE_NAME
,
8200 INTERNAL_INSN_CODE_NAME
,
8201 INTERNAL_DFA_INSN_CODE_FUNC_NAME
, INSN_PARAMETER_NAME
,
8202 DFA_INSN_CODES_VARIABLE_NAME
, INTERNAL_INSN_CODE_NAME
);
8203 fprintf (output_file
, " return %s;\n}\n\n", INTERNAL_INSN_CODE_NAME
);
8206 /* The function outputs PHR interface function `state_transition'. */
8208 output_trans_func (void)
8210 fprintf (output_file
, "int\n%s (%s %s, rtx %s)\n",
8211 TRANSITION_FUNC_NAME
, STATE_TYPE_NAME
, STATE_NAME
,
8212 INSN_PARAMETER_NAME
);
8213 fprintf (output_file
, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME
);
8214 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME
,
8215 INTERNAL_INSN_CODE_NAME
, -1);
8216 fprintf (output_file
, " return %s (%s, (struct %s *) %s);\n}\n\n",
8217 INTERNAL_TRANSITION_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
, CHIP_NAME
, STATE_NAME
);
8220 /* Output function `min_issue_delay'. */
8222 output_min_issue_delay_func (void)
8224 fprintf (output_file
, "int\n%s (%s %s, rtx %s)\n",
8225 MIN_ISSUE_DELAY_FUNC_NAME
, STATE_TYPE_NAME
, STATE_NAME
,
8226 INSN_PARAMETER_NAME
);
8227 fprintf (output_file
, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME
);
8228 fprintf (output_file
, "\n if (%s != 0)\n {\n", INSN_PARAMETER_NAME
);
8229 fprintf (output_file
, " %s = %s (%s);\n", INTERNAL_INSN_CODE_NAME
,
8230 DFA_INSN_CODE_FUNC_NAME
, INSN_PARAMETER_NAME
);
8231 fprintf (output_file
, " if (%s > %s)\n return 0;\n",
8232 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
8233 fprintf (output_file
, " }\n else\n %s = %s;\n",
8234 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
8235 fprintf (output_file
, "\n return %s (%s, (struct %s *) %s);\n",
8236 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
8237 CHIP_NAME
, STATE_NAME
);
8238 fprintf (output_file
, "}\n\n");
8241 /* Output function `internal_dead_lock'. */
8243 output_internal_dead_lock_func (void)
8245 automaton_t automaton
;
8247 fprintf (output_file
, "static int\n%s (struct %s *ARG_UNUSED (%s))\n",
8248 INTERNAL_DEAD_LOCK_FUNC_NAME
, CHIP_NAME
, CHIP_PARAMETER_NAME
);
8249 fprintf (output_file
, "{\n");
8250 for (automaton
= description
->first_automaton
;
8252 automaton
= automaton
->next_automaton
)
8253 if (automaton
->locked_states
)
8255 fprintf (output_file
, " if (");
8256 output_dead_lock_vect_name (output_file
, automaton
);
8257 fprintf (output_file
, " [%s->", CHIP_PARAMETER_NAME
);
8258 output_chip_member_name (output_file
, automaton
);
8259 fprintf (output_file
, "])\n return 1/* TRUE */;\n");
8261 fprintf (output_file
, " return 0/* FALSE */;\n}\n\n");
8264 /* The function outputs PHR interface function `state_dead_lock_p'. */
8266 output_dead_lock_func (void)
8268 fprintf (output_file
, "int\n%s (%s %s)\n",
8269 DEAD_LOCK_FUNC_NAME
, STATE_TYPE_NAME
, STATE_NAME
);
8270 fprintf (output_file
, "{\n return %s ((struct %s *) %s);\n}\n\n",
8271 INTERNAL_DEAD_LOCK_FUNC_NAME
, CHIP_NAME
, STATE_NAME
);
8274 /* Output function `internal_reset'. */
8276 output_internal_reset_func (void)
8278 fprintf (output_file
, "static inline void\n%s (struct %s *%s)\n",
8279 INTERNAL_RESET_FUNC_NAME
, CHIP_NAME
, CHIP_PARAMETER_NAME
);
8280 fprintf (output_file
, "{\n memset (%s, 0, sizeof (struct %s));\n}\n\n",
8281 CHIP_PARAMETER_NAME
, CHIP_NAME
);
8284 /* The function outputs PHR interface function `state_size'. */
8286 output_size_func (void)
8288 fprintf (output_file
, "int\n%s (void)\n", SIZE_FUNC_NAME
);
8289 fprintf (output_file
, "{\n return sizeof (struct %s);\n}\n\n", CHIP_NAME
);
8292 /* The function outputs PHR interface function `state_reset'. */
8294 output_reset_func (void)
8296 fprintf (output_file
, "void\n%s (%s %s)\n",
8297 RESET_FUNC_NAME
, STATE_TYPE_NAME
, STATE_NAME
);
8298 fprintf (output_file
, "{\n %s ((struct %s *) %s);\n}\n\n", INTERNAL_RESET_FUNC_NAME
,
8299 CHIP_NAME
, STATE_NAME
);
8302 /* Output function `min_insn_conflict_delay'. */
8304 output_min_insn_conflict_delay_func (void)
8306 fprintf (output_file
,
8307 "int\n%s (%s %s, rtx %s, rtx %s)\n",
8308 MIN_INSN_CONFLICT_DELAY_FUNC_NAME
, STATE_TYPE_NAME
,
8309 STATE_NAME
, INSN_PARAMETER_NAME
, INSN2_PARAMETER_NAME
);
8310 fprintf (output_file
, "{\n struct %s %s;\n int %s, %s, transition;\n",
8311 CHIP_NAME
, CHIP_NAME
, INTERNAL_INSN_CODE_NAME
,
8312 INTERNAL_INSN2_CODE_NAME
);
8313 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME
,
8314 INTERNAL_INSN_CODE_NAME
, 0);
8315 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME
,
8316 INTERNAL_INSN2_CODE_NAME
, 0);
8317 fprintf (output_file
, " memcpy (&%s, %s, sizeof (%s));\n",
8318 CHIP_NAME
, STATE_NAME
, CHIP_NAME
);
8319 fprintf (output_file
, " %s (&%s);\n", INTERNAL_RESET_FUNC_NAME
, CHIP_NAME
);
8320 fprintf (output_file
, " transition = %s (%s, &%s);\n",
8321 INTERNAL_TRANSITION_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
, CHIP_NAME
);
8322 fprintf (output_file
, " gcc_assert (transition <= 0);\n");
8323 fprintf (output_file
, " return %s (%s, &%s);\n",
8324 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME
, INTERNAL_INSN2_CODE_NAME
,
8326 fprintf (output_file
, "}\n\n");
8329 /* Output the array holding default latency values. These are used in
8330 insn_latency and maximal_insn_latency function implementations. */
8332 output_default_latencies (void)
8336 const char *tabletype
= "unsigned char";
8338 /* Find the smallest integer type that can hold all the default
8340 for (i
= 0; i
< description
->decls_num
; i
++)
8341 if (description
->decls
[i
]->mode
== dm_insn_reserv
)
8343 decl
= description
->decls
[i
];
8344 if (DECL_INSN_RESERV (decl
)->default_latency
> UCHAR_MAX
8345 && tabletype
[0] != 'i') /* Don't shrink it. */
8346 tabletype
= "unsigned short";
8347 if (DECL_INSN_RESERV (decl
)->default_latency
> USHRT_MAX
)
8351 fprintf (output_file
, " static const %s default_latencies[] =\n {",
8354 for (i
= 0, j
= 0, col
= 7; i
< description
->normal_decls_num
; i
++)
8355 if (description
->decls
[i
]->mode
== dm_insn_reserv
)
8357 if ((col
= (col
+1) % 8) == 0)
8358 fputs ("\n ", output_file
);
8359 decl
= description
->decls
[i
];
8360 gcc_assert (j
++ == DECL_INSN_RESERV (decl
)->insn_num
);
8361 fprintf (output_file
, "% 4d,",
8362 DECL_INSN_RESERV (decl
)->default_latency
);
8364 gcc_assert (j
== description
->insns_num
- (collapse_flag
? 2 : 1));
8365 fputs ("\n };\n", output_file
);
8368 /* Output function `internal_insn_latency'. */
8370 output_internal_insn_latency_func (void)
8374 struct bypass_decl
*bypass
;
8376 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",
8377 INTERNAL_INSN_LATENCY_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
8378 INTERNAL_INSN2_CODE_NAME
, INSN_PARAMETER_NAME
,
8379 INSN2_PARAMETER_NAME
);
8380 fprintf (output_file
, "{\n");
8382 if (DECL_INSN_RESERV (advance_cycle_insn_decl
)->insn_num
== 0)
8384 fputs (" return 0;\n}\n\n", output_file
);
8388 fprintf (output_file
, " if (%s >= %s || %s >= %s)\n return 0;\n",
8389 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
,
8390 INTERNAL_INSN2_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
8392 fprintf (output_file
, " switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME
);
8393 for (i
= 0; i
< description
->decls_num
; i
++)
8394 if (description
->decls
[i
]->mode
== dm_insn_reserv
8395 && DECL_INSN_RESERV (description
->decls
[i
])->bypass_list
)
8397 decl
= description
->decls
[i
];
8398 fprintf (output_file
,
8399 " case %d:\n switch (%s)\n {\n",
8400 DECL_INSN_RESERV (decl
)->insn_num
,
8401 INTERNAL_INSN2_CODE_NAME
);
8402 for (bypass
= DECL_INSN_RESERV (decl
)->bypass_list
;
8404 bypass
= bypass
->next
)
8406 gcc_assert (bypass
->in_insn_reserv
->insn_num
8407 != (DECL_INSN_RESERV
8408 (advance_cycle_insn_decl
)->insn_num
));
8409 fprintf (output_file
, " case %d:\n",
8410 bypass
->in_insn_reserv
->insn_num
);
8413 if (bypass
->bypass_guard_name
== NULL
)
8415 gcc_assert (bypass
->next
== NULL
8416 || (bypass
->in_insn_reserv
8417 != bypass
->next
->in_insn_reserv
));
8418 fprintf (output_file
, " return %d;\n",
8423 fprintf (output_file
,
8424 " if (%s (%s, %s))\n",
8425 bypass
->bypass_guard_name
, INSN_PARAMETER_NAME
,
8426 INSN2_PARAMETER_NAME
);
8427 fprintf (output_file
, " return %d;\n",
8430 if (bypass
->next
== NULL
8431 || bypass
->in_insn_reserv
!= bypass
->next
->in_insn_reserv
)
8433 bypass
= bypass
->next
;
8435 if (bypass
->bypass_guard_name
!= NULL
)
8436 fprintf (output_file
, " break;\n");
8438 fputs (" }\n break;\n", output_file
);
8441 fprintf (output_file
, " }\n return default_latencies[%s];\n}\n\n",
8442 INTERNAL_INSN_CODE_NAME
);
8445 /* Output function `internal_maximum_insn_latency'. */
8447 output_internal_maximal_insn_latency_func (void)
8450 struct bypass_decl
*bypass
;
8454 fprintf (output_file
, "static int\n%s (int %s ATTRIBUTE_UNUSED,\n\trtx %s ATTRIBUTE_UNUSED)\n",
8455 "internal_maximal_insn_latency", INTERNAL_INSN_CODE_NAME
,
8456 INSN_PARAMETER_NAME
);
8457 fprintf (output_file
, "{\n");
8459 if (DECL_INSN_RESERV (advance_cycle_insn_decl
)->insn_num
== 0)
8461 fputs (" return 0;\n}\n\n", output_file
);
8465 fprintf (output_file
, " switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME
);
8466 for (i
= 0; i
< description
->decls_num
; i
++)
8467 if (description
->decls
[i
]->mode
== dm_insn_reserv
8468 && DECL_INSN_RESERV (description
->decls
[i
])->bypass_list
)
8470 decl
= description
->decls
[i
];
8471 max
= DECL_INSN_RESERV (decl
)->default_latency
;
8472 fprintf (output_file
,
8474 DECL_INSN_RESERV (decl
)->insn_num
);
8475 for (bypass
= DECL_INSN_RESERV (decl
)->bypass_list
;
8477 bypass
= bypass
->next
)
8479 if (bypass
->latency
> max
)
8480 max
= bypass
->latency
;
8482 fprintf (output_file
, " return %d; }\n break;\n", max
);
8485 fprintf (output_file
, " }\n return default_latencies[%s];\n}\n\n",
8486 INTERNAL_INSN_CODE_NAME
);
8489 /* The function outputs PHR interface function `insn_latency'. */
8491 output_insn_latency_func (void)
8493 fprintf (output_file
, "int\n%s (rtx %s, rtx %s)\n",
8494 INSN_LATENCY_FUNC_NAME
, INSN_PARAMETER_NAME
, INSN2_PARAMETER_NAME
);
8495 fprintf (output_file
, "{\n int %s, %s;\n",
8496 INTERNAL_INSN_CODE_NAME
, INTERNAL_INSN2_CODE_NAME
);
8497 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME
,
8498 INTERNAL_INSN_CODE_NAME
, 0);
8499 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME
,
8500 INTERNAL_INSN2_CODE_NAME
, 0);
8501 fprintf (output_file
, " return %s (%s, %s, %s, %s);\n}\n\n",
8502 INTERNAL_INSN_LATENCY_FUNC_NAME
,
8503 INTERNAL_INSN_CODE_NAME
, INTERNAL_INSN2_CODE_NAME
,
8504 INSN_PARAMETER_NAME
, INSN2_PARAMETER_NAME
);
8507 /* The function outputs PHR interface function `maximal_insn_latency'. */
8509 output_maximal_insn_latency_func (void)
8511 fprintf (output_file
, "int\n%s (rtx %s)\n",
8512 "maximal_insn_latency", INSN_PARAMETER_NAME
);
8513 fprintf (output_file
, "{\n int %s;\n",
8514 INTERNAL_INSN_CODE_NAME
);
8515 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME
,
8516 INTERNAL_INSN_CODE_NAME
, 0);
8517 fprintf (output_file
, " return %s (%s, %s);\n}\n\n",
8518 "internal_maximal_insn_latency",
8519 INTERNAL_INSN_CODE_NAME
, INSN_PARAMETER_NAME
);
8522 /* The function outputs PHR interface function `print_reservation'. */
8524 output_print_reservation_func (void)
8529 fprintf (output_file
,
8530 "void\n%s (FILE *%s, rtx %s ATTRIBUTE_UNUSED)\n{\n",
8531 PRINT_RESERVATION_FUNC_NAME
, FILE_PARAMETER_NAME
,
8532 INSN_PARAMETER_NAME
);
8534 if (DECL_INSN_RESERV (advance_cycle_insn_decl
)->insn_num
== 0)
8536 fprintf (output_file
, " fputs (\"%s\", %s);\n}\n\n",
8537 NOTHING_NAME
, FILE_PARAMETER_NAME
);
8542 fputs (" static const char *const reservation_names[] =\n {",
8545 for (i
= 0, j
= 0; i
< description
->normal_decls_num
; i
++)
8547 decl
= description
->decls
[i
];
8548 if (decl
->mode
== dm_insn_reserv
)
8550 gcc_assert (j
== DECL_INSN_RESERV (decl
)->insn_num
);
8553 fprintf (output_file
, "\n \"%s\",",
8554 regexp_representation (DECL_INSN_RESERV (decl
)->regexp
));
8555 finish_regexp_representation ();
8558 gcc_assert (j
== description
->insns_num
- (collapse_flag
? 2 : 1));
8560 fprintf (output_file
, "\n \"%s\"\n };\n int %s;\n\n",
8561 NOTHING_NAME
, INTERNAL_INSN_CODE_NAME
);
8563 fprintf (output_file
, " if (%s == 0)\n %s = %s;\n",
8564 INSN_PARAMETER_NAME
,
8565 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
8566 fprintf (output_file
, " else\n\
8572 INTERNAL_INSN_CODE_NAME
, DFA_INSN_CODE_FUNC_NAME
,
8573 INSN_PARAMETER_NAME
,
8574 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
,
8575 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
8577 fprintf (output_file
, " fputs (reservation_names[%s], %s);\n}\n\n",
8578 INTERNAL_INSN_CODE_NAME
, FILE_PARAMETER_NAME
);
8581 /* The following function is used to sort unit declaration by their
8584 units_cmp (const void *unit1
, const void *unit2
)
8586 const_unit_decl_t
const u1
= *(const_unit_decl_t
const*) unit1
;
8587 const_unit_decl_t
const u2
= *(const_unit_decl_t
const*) unit2
;
8589 return strcmp (u1
->name
, u2
->name
);
8592 /* The following macro value is name of struct containing unit name
8594 #define NAME_CODE_STRUCT_NAME "name_code"
8596 /* The following macro value is name of table of struct name_code. */
8597 #define NAME_CODE_TABLE_NAME "name_code_table"
8599 /* The following macro values are member names for struct name_code. */
8600 #define NAME_MEMBER_NAME "name"
8601 #define CODE_MEMBER_NAME "code"
8603 /* The following macro values are local variable names for function
8604 `get_cpu_unit_code'. */
8605 #define CMP_VARIABLE_NAME "cmp"
8606 #define LOW_VARIABLE_NAME "l"
8607 #define MIDDLE_VARIABLE_NAME "m"
8608 #define HIGH_VARIABLE_NAME "h"
8610 /* The following function outputs function to obtain internal cpu unit
8611 code by the cpu unit name. */
8613 output_get_cpu_unit_code_func (void)
8618 fprintf (output_file
, "int\n%s (const char *%s)\n",
8619 GET_CPU_UNIT_CODE_FUNC_NAME
, CPU_UNIT_NAME_PARAMETER_NAME
);
8620 fprintf (output_file
, "{\n struct %s {const char *%s; int %s;};\n",
8621 NAME_CODE_STRUCT_NAME
, NAME_MEMBER_NAME
, CODE_MEMBER_NAME
);
8622 fprintf (output_file
, " int %s, %s, %s, %s;\n", CMP_VARIABLE_NAME
,
8623 LOW_VARIABLE_NAME
, MIDDLE_VARIABLE_NAME
, HIGH_VARIABLE_NAME
);
8624 fprintf (output_file
, " static struct %s %s [] =\n {\n",
8625 NAME_CODE_STRUCT_NAME
, NAME_CODE_TABLE_NAME
);
8626 units
= XNEWVEC (unit_decl_t
, description
->units_num
);
8627 memcpy (units
, units_array
, sizeof (unit_decl_t
) * description
->units_num
);
8628 qsort (units
, description
->units_num
, sizeof (unit_decl_t
), units_cmp
);
8629 for (i
= 0; i
< description
->units_num
; i
++)
8630 if (units
[i
]->query_p
)
8631 fprintf (output_file
, " {\"%s\", %d},\n",
8632 units
[i
]->name
, units
[i
]->query_num
);
8633 fprintf (output_file
, " };\n\n");
8634 fprintf (output_file
, " /* The following is binary search: */\n");
8635 fprintf (output_file
, " %s = 0;\n", LOW_VARIABLE_NAME
);
8636 fprintf (output_file
, " %s = sizeof (%s) / sizeof (struct %s) - 1;\n",
8637 HIGH_VARIABLE_NAME
, NAME_CODE_TABLE_NAME
, NAME_CODE_STRUCT_NAME
);
8638 fprintf (output_file
, " while (%s <= %s)\n {\n",
8639 LOW_VARIABLE_NAME
, HIGH_VARIABLE_NAME
);
8640 fprintf (output_file
, " %s = (%s + %s) / 2;\n",
8641 MIDDLE_VARIABLE_NAME
, LOW_VARIABLE_NAME
, HIGH_VARIABLE_NAME
);
8642 fprintf (output_file
, " %s = strcmp (%s, %s [%s].%s);\n",
8643 CMP_VARIABLE_NAME
, CPU_UNIT_NAME_PARAMETER_NAME
,
8644 NAME_CODE_TABLE_NAME
, MIDDLE_VARIABLE_NAME
, NAME_MEMBER_NAME
);
8645 fprintf (output_file
, " if (%s < 0)\n", CMP_VARIABLE_NAME
);
8646 fprintf (output_file
, " %s = %s - 1;\n",
8647 HIGH_VARIABLE_NAME
, MIDDLE_VARIABLE_NAME
);
8648 fprintf (output_file
, " else if (%s > 0)\n", CMP_VARIABLE_NAME
);
8649 fprintf (output_file
, " %s = %s + 1;\n",
8650 LOW_VARIABLE_NAME
, MIDDLE_VARIABLE_NAME
);
8651 fprintf (output_file
, " else\n");
8652 fprintf (output_file
, " return %s [%s].%s;\n }\n",
8653 NAME_CODE_TABLE_NAME
, MIDDLE_VARIABLE_NAME
, CODE_MEMBER_NAME
);
8654 fprintf (output_file
, " return -1;\n}\n\n");
8658 /* The following function outputs function to check reservation of cpu
8659 unit (its internal code will be passed as the function argument) in
8662 output_cpu_unit_reservation_p (void)
8664 automaton_t automaton
;
8666 fprintf (output_file
, "int\n%s (%s %s, int %s)\n",
8667 CPU_UNIT_RESERVATION_P_FUNC_NAME
,
8668 STATE_TYPE_NAME
, STATE_NAME
,
8669 CPU_CODE_PARAMETER_NAME
);
8670 fprintf (output_file
, "{\n gcc_assert (%s >= 0 && %s < %d);\n",
8671 CPU_CODE_PARAMETER_NAME
, CPU_CODE_PARAMETER_NAME
,
8672 description
->query_units_num
);
8673 if (description
->query_units_num
> 0)
8674 for (automaton
= description
->first_automaton
;
8676 automaton
= automaton
->next_automaton
)
8678 fprintf (output_file
, " if ((");
8679 output_reserved_units_table_name (output_file
, automaton
);
8680 fprintf (output_file
, " [((struct %s *) %s)->", CHIP_NAME
, STATE_NAME
);
8681 output_chip_member_name (output_file
, automaton
);
8682 fprintf (output_file
, " * %d + %s / 8] >> (%s %% 8)) & 1)\n",
8683 (description
->query_units_num
+ 7) / 8,
8684 CPU_CODE_PARAMETER_NAME
, CPU_CODE_PARAMETER_NAME
);
8685 fprintf (output_file
, " return 1;\n");
8687 fprintf (output_file
, " return 0;\n}\n\n");
8690 /* The following function outputs a function to check if insn
8691 has a dfa reservation. */
8693 output_insn_has_dfa_reservation_p (void)
8695 fprintf (output_file
,
8696 "bool\n%s (rtx %s ATTRIBUTE_UNUSED)\n{\n",
8697 INSN_HAS_DFA_RESERVATION_P_FUNC_NAME
,
8698 INSN_PARAMETER_NAME
);
8700 if (DECL_INSN_RESERV (advance_cycle_insn_decl
)->insn_num
== 0)
8702 fprintf (output_file
, " return false;\n}\n\n");
8706 fprintf (output_file
, " int %s;\n\n", INTERNAL_INSN_CODE_NAME
);
8708 fprintf (output_file
, " if (%s == 0)\n %s = %s;\n",
8709 INSN_PARAMETER_NAME
,
8710 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
8711 fprintf (output_file
, " else\n\
8717 INTERNAL_INSN_CODE_NAME
, DFA_INSN_CODE_FUNC_NAME
,
8718 INSN_PARAMETER_NAME
,
8719 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
,
8720 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
8722 fprintf (output_file
, " return %s != %s;\n}\n\n",
8723 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
8726 /* The function outputs PHR interface functions `dfa_clean_insn_cache'
8727 and 'dfa_clear_single_insn_cache'. */
8729 output_dfa_clean_insn_cache_func (void)
8731 fprintf (output_file
,
8732 "void\n%s (void)\n{\n int %s;\n\n",
8733 DFA_CLEAN_INSN_CACHE_FUNC_NAME
, I_VARIABLE_NAME
);
8734 fprintf (output_file
,
8735 " for (%s = 0; %s < %s; %s++)\n %s [%s] = -1;\n}\n\n",
8736 I_VARIABLE_NAME
, I_VARIABLE_NAME
,
8737 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
, I_VARIABLE_NAME
,
8738 DFA_INSN_CODES_VARIABLE_NAME
, I_VARIABLE_NAME
);
8740 fprintf (output_file
,
8741 "void\n%s (rtx %s)\n{\n int %s;\n\n",
8742 DFA_CLEAR_SINGLE_INSN_CACHE_FUNC_NAME
, INSN_PARAMETER_NAME
,
8744 fprintf (output_file
,
8745 " %s = INSN_UID (%s);\n if (%s < %s)\n %s [%s] = -1;\n}\n\n",
8746 I_VARIABLE_NAME
, INSN_PARAMETER_NAME
, I_VARIABLE_NAME
,
8747 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
, DFA_INSN_CODES_VARIABLE_NAME
,
8751 /* The function outputs PHR interface function `dfa_start'. */
8753 output_dfa_start_func (void)
8755 fprintf (output_file
,
8756 "void\n%s (void)\n{\n %s = get_max_uid ();\n",
8757 DFA_START_FUNC_NAME
, DFA_INSN_CODES_LENGTH_VARIABLE_NAME
);
8758 fprintf (output_file
, " %s = XNEWVEC (int, %s);\n",
8759 DFA_INSN_CODES_VARIABLE_NAME
, DFA_INSN_CODES_LENGTH_VARIABLE_NAME
);
8760 fprintf (output_file
, " %s ();\n}\n\n", DFA_CLEAN_INSN_CACHE_FUNC_NAME
);
8763 /* The function outputs PHR interface function `dfa_finish'. */
8765 output_dfa_finish_func (void)
8767 fprintf (output_file
, "void\n%s (void)\n{\n free (%s);\n}\n\n",
8768 DFA_FINISH_FUNC_NAME
, DFA_INSN_CODES_VARIABLE_NAME
);
8773 /* The page contains code for output description file (readable
8774 representation of original description and generated DFA(s). */
8776 /* The function outputs string representation of IR reservation. */
8778 output_regexp (regexp_t regexp
)
8780 fprintf (output_description_file
, "%s", regexp_representation (regexp
));
8781 finish_regexp_representation ();
8784 /* Output names of units in LIST separated by comma. */
8786 output_unit_set_el_list (unit_set_el_t list
)
8790 for (el
= list
; el
!= NULL
; el
= el
->next_unit_set_el
)
8793 fprintf (output_description_file
, ", ");
8794 fprintf (output_description_file
, "%s", el
->unit_decl
->name
);
8798 /* Output patterns in LIST separated by comma. */
8800 output_pattern_set_el_list (pattern_set_el_t list
)
8802 pattern_set_el_t el
;
8805 for (el
= list
; el
!= NULL
; el
= el
->next_pattern_set_el
)
8808 fprintf (output_description_file
, ", ");
8809 for (i
= 0; i
< el
->units_num
; i
++)
8810 fprintf (output_description_file
, (i
== 0 ? "%s" : " %s"),
8811 el
->unit_decls
[i
]->name
);
8815 /* The function outputs string representation of IR define_reservation
8816 and define_insn_reservation. */
8818 output_description (void)
8823 for (i
= 0; i
< description
->decls_num
; i
++)
8825 decl
= description
->decls
[i
];
8826 if (decl
->mode
== dm_unit
)
8828 if (DECL_UNIT (decl
)->excl_list
!= NULL
)
8830 fprintf (output_description_file
, "unit %s exclusion_set: ",
8831 DECL_UNIT (decl
)->name
);
8832 output_unit_set_el_list (DECL_UNIT (decl
)->excl_list
);
8833 fprintf (output_description_file
, "\n");
8835 if (DECL_UNIT (decl
)->presence_list
!= NULL
)
8837 fprintf (output_description_file
, "unit %s presence_set: ",
8838 DECL_UNIT (decl
)->name
);
8839 output_pattern_set_el_list (DECL_UNIT (decl
)->presence_list
);
8840 fprintf (output_description_file
, "\n");
8842 if (DECL_UNIT (decl
)->final_presence_list
!= NULL
)
8844 fprintf (output_description_file
, "unit %s final_presence_set: ",
8845 DECL_UNIT (decl
)->name
);
8846 output_pattern_set_el_list
8847 (DECL_UNIT (decl
)->final_presence_list
);
8848 fprintf (output_description_file
, "\n");
8850 if (DECL_UNIT (decl
)->absence_list
!= NULL
)
8852 fprintf (output_description_file
, "unit %s absence_set: ",
8853 DECL_UNIT (decl
)->name
);
8854 output_pattern_set_el_list (DECL_UNIT (decl
)->absence_list
);
8855 fprintf (output_description_file
, "\n");
8857 if (DECL_UNIT (decl
)->final_absence_list
!= NULL
)
8859 fprintf (output_description_file
, "unit %s final_absence_set: ",
8860 DECL_UNIT (decl
)->name
);
8861 output_pattern_set_el_list
8862 (DECL_UNIT (decl
)->final_absence_list
);
8863 fprintf (output_description_file
, "\n");
8867 fprintf (output_description_file
, "\n");
8868 for (i
= 0; i
< description
->normal_decls_num
; i
++)
8870 decl
= description
->decls
[i
];
8871 if (decl
->mode
== dm_reserv
)
8873 fprintf (output_description_file
, "reservation %s: ",
8874 DECL_RESERV (decl
)->name
);
8875 output_regexp (DECL_RESERV (decl
)->regexp
);
8876 fprintf (output_description_file
, "\n");
8878 else if (decl
->mode
== dm_insn_reserv
)
8880 fprintf (output_description_file
, "insn reservation %s ",
8881 DECL_INSN_RESERV (decl
)->name
);
8882 print_rtl (output_description_file
,
8883 DECL_INSN_RESERV (decl
)->condexp
);
8884 fprintf (output_description_file
, ": ");
8885 output_regexp (DECL_INSN_RESERV (decl
)->regexp
);
8886 fprintf (output_description_file
, "\n");
8888 else if (decl
->mode
== dm_bypass
)
8889 fprintf (output_description_file
, "bypass %d %s %s\n",
8890 DECL_BYPASS (decl
)->latency
,
8891 DECL_BYPASS (decl
)->out_pattern
,
8892 DECL_BYPASS (decl
)->in_pattern
);
8894 fprintf (output_description_file
, "\n\f\n");
8897 /* The function outputs name of AUTOMATON. */
8899 output_automaton_name (FILE *f
, automaton_t automaton
)
8901 if (automaton
->corresponding_automaton_decl
== NULL
)
8902 fprintf (f
, "#%d", automaton
->automaton_order_num
);
8904 fprintf (f
, "`%s'", automaton
->corresponding_automaton_decl
->name
);
8907 /* Maximal length of line for pretty printing into description
8909 #define MAX_LINE_LENGTH 70
8911 /* The function outputs units name belonging to AUTOMATON. */
8913 output_automaton_units (automaton_t automaton
)
8917 int curr_line_length
;
8918 int there_is_an_automaton_unit
;
8921 fprintf (output_description_file
, "\n Corresponding units:\n");
8922 fprintf (output_description_file
, " ");
8923 curr_line_length
= 4;
8924 there_is_an_automaton_unit
= 0;
8925 for (i
= 0; i
< description
->decls_num
; i
++)
8927 decl
= description
->decls
[i
];
8928 if (decl
->mode
== dm_unit
8929 && (DECL_UNIT (decl
)->corresponding_automaton_num
8930 == automaton
->automaton_order_num
))
8932 there_is_an_automaton_unit
= 1;
8933 name
= DECL_UNIT (decl
)->name
;
8934 if (curr_line_length
+ strlen (name
) + 1 > MAX_LINE_LENGTH
)
8936 curr_line_length
= strlen (name
) + 4;
8937 fprintf (output_description_file
, "\n ");
8941 curr_line_length
+= strlen (name
) + 1;
8942 fprintf (output_description_file
, " ");
8944 fprintf (output_description_file
, "%s", name
);
8947 if (!there_is_an_automaton_unit
)
8948 fprintf (output_description_file
, "<None>");
8949 fprintf (output_description_file
, "\n\n");
8952 /* The following variable is used for forming array of all possible cpu unit
8953 reservations described by the current DFA state. */
8954 static vec
<reserv_sets_t
> state_reservs
;
8956 /* The function forms `state_reservs' for STATE. */
8958 add_state_reservs (state_t state
)
8960 alt_state_t curr_alt_state
;
8962 if (state
->component_states
!= NULL
)
8963 for (curr_alt_state
= state
->component_states
;
8964 curr_alt_state
!= NULL
;
8965 curr_alt_state
= curr_alt_state
->next_sorted_alt_state
)
8966 add_state_reservs (curr_alt_state
->state
);
8968 state_reservs
.safe_push (state
->reservs
);
8971 /* The function outputs readable representation of all out arcs of
8974 output_state_arcs (state_t state
)
8978 const char *insn_name
;
8979 int curr_line_length
;
8981 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
8984 gcc_assert (ainsn
->first_insn_with_same_reservs
);
8985 fprintf (output_description_file
, " ");
8986 curr_line_length
= 7;
8987 fprintf (output_description_file
, "%2d: ", ainsn
->insn_equiv_class_num
);
8990 insn_name
= ainsn
->insn_reserv_decl
->name
;
8991 if (curr_line_length
+ strlen (insn_name
) > MAX_LINE_LENGTH
)
8993 if (ainsn
!= arc
->insn
)
8995 fprintf (output_description_file
, ",\n ");
8996 curr_line_length
= strlen (insn_name
) + 6;
8999 curr_line_length
+= strlen (insn_name
);
9003 curr_line_length
+= strlen (insn_name
);
9004 if (ainsn
!= arc
->insn
)
9006 curr_line_length
+= 2;
9007 fprintf (output_description_file
, ", ");
9010 fprintf (output_description_file
, "%s", insn_name
);
9011 ainsn
= ainsn
->next_same_reservs_insn
;
9013 while (ainsn
!= NULL
);
9014 fprintf (output_description_file
, " %d \n",
9015 arc
->to_state
->order_state_num
);
9017 fprintf (output_description_file
, "\n");
9020 /* The following function is used for sorting possible cpu unit
9021 reservation of a DFA state. */
9023 state_reservs_cmp (const void *reservs_ptr_1
, const void *reservs_ptr_2
)
9025 return reserv_sets_cmp (*(const_reserv_sets_t
const*) reservs_ptr_1
,
9026 *(const_reserv_sets_t
const*) reservs_ptr_2
);
9029 /* The following function is used for sorting possible cpu unit
9030 reservation of a DFA state. */
9032 remove_state_duplicate_reservs (void)
9036 for (i
= 1, j
= 0; i
< state_reservs
.length (); i
++)
9037 if (reserv_sets_cmp (state_reservs
[j
], state_reservs
[i
]))
9040 state_reservs
[j
] = state_reservs
[i
];
9042 state_reservs
.truncate (j
+ 1);
9045 /* The following function output readable representation of DFA(s)
9046 state used for fast recognition of pipeline hazards. State is
9047 described by possible (current and scheduled) cpu unit
9050 output_state (state_t state
)
9054 state_reservs
.create (0);
9056 fprintf (output_description_file
, " State #%d", state
->order_state_num
);
9057 fprintf (output_description_file
,
9058 state
->new_cycle_p
? " (new cycle)\n" : "\n");
9059 add_state_reservs (state
);
9060 state_reservs
.qsort (state_reservs_cmp
);
9061 remove_state_duplicate_reservs ();
9062 for (i
= 0; i
< state_reservs
.length (); i
++)
9064 fprintf (output_description_file
, " ");
9065 output_reserv_sets (output_description_file
, state_reservs
[i
]);
9066 fprintf (output_description_file
, "\n");
9068 fprintf (output_description_file
, "\n");
9069 output_state_arcs (state
);
9070 state_reservs
.release ();
9073 /* The following function output readable representation of
9074 DFAs used for fast recognition of pipeline hazards. */
9076 output_automaton_descriptions (void)
9078 automaton_t automaton
;
9080 for (automaton
= description
->first_automaton
;
9082 automaton
= automaton
->next_automaton
)
9084 fprintf (output_description_file
, "\nAutomaton ");
9085 output_automaton_name (output_description_file
, automaton
);
9086 fprintf (output_description_file
, "\n");
9087 output_automaton_units (automaton
);
9088 pass_states (automaton
, output_state
);
9094 /* The page contains top level function for generation DFA(s) used for
9097 /* The function outputs statistics about work of different phases of
9100 output_statistics (FILE *f
)
9102 automaton_t automaton
;
9105 int transition_comb_vect_els
= 0;
9106 int transition_full_vect_els
= 0;
9107 int min_issue_delay_vect_els
= 0;
9108 int locked_states
= 0;
9111 for (automaton
= description
->first_automaton
;
9113 automaton
= automaton
->next_automaton
)
9115 fprintf (f
, "\nAutomaton ");
9116 output_automaton_name (f
, automaton
);
9117 fprintf (f
, "\n %5d NDFA states, %5d NDFA arcs\n",
9118 automaton
->NDFA_states_num
, automaton
->NDFA_arcs_num
);
9119 fprintf (f
, " %5d DFA states, %5d DFA arcs\n",
9120 automaton
->DFA_states_num
, automaton
->DFA_arcs_num
);
9121 states_num
= automaton
->DFA_states_num
;
9122 if (!no_minimization_flag
)
9124 fprintf (f
, " %5d minimal DFA states, %5d minimal DFA arcs\n",
9125 automaton
->minimal_DFA_states_num
,
9126 automaton
->minimal_DFA_arcs_num
);
9127 states_num
= automaton
->minimal_DFA_states_num
;
9129 fprintf (f
, " %5d all insns %5d insn equivalence classes\n",
9130 description
->insns_num
, automaton
->insn_equiv_classes_num
);
9131 fprintf (f
, " %d locked states\n", automaton
->locked_states
);
9134 (f
, "%5ld transition comb vector els, %5ld trans table els: %s\n",
9135 (long) automaton
->trans_table
->comb_vect
.length (),
9136 (long) automaton
->trans_table
->full_vect
.length (),
9137 (comb_vect_p (automaton
->trans_table
)
9138 ? "use comb vect" : "use simple vect"));
9140 (f
, "%5ld min delay table els, compression factor %d\n",
9141 (long) states_num
* automaton
->insn_equiv_classes_num
,
9142 automaton
->min_issue_delay_table_compression_factor
);
9143 transition_comb_vect_els
9144 += automaton
->trans_table
->comb_vect
.length ();
9145 transition_full_vect_els
9146 += automaton
->trans_table
->full_vect
.length ();
9147 min_issue_delay_vect_els
9148 += states_num
* automaton
->insn_equiv_classes_num
;
9150 += automaton
->locked_states
;
9154 fprintf (f
, "\n%5d all allocated states, %5d all allocated arcs\n",
9155 allocated_states_num
, allocated_arcs_num
);
9156 fprintf (f
, "%5d all allocated alternative states\n",
9157 allocated_alt_states_num
);
9158 fprintf (f
, "%5d all transition comb vector els, %5d all trans table els\n",
9159 transition_comb_vect_els
, transition_full_vect_els
);
9160 fprintf (f
, "%5d all min delay table els\n", min_issue_delay_vect_els
);
9161 fprintf (f
, "%5d all locked states\n", locked_states
);
9165 /* The function output times of work of different phases of DFA
9168 output_time_statistics (FILE *f
)
9170 fprintf (f
, "\n transformation: ");
9171 print_active_time (f
, transform_time
);
9172 fprintf (f
, (!ndfa_flag
? ", building DFA: " : ", building NDFA: "));
9173 print_active_time (f
, NDFA_time
);
9176 fprintf (f
, ", NDFA -> DFA: ");
9177 print_active_time (f
, NDFA_to_DFA_time
);
9179 fprintf (f
, "\n DFA minimization: ");
9180 print_active_time (f
, minimize_time
);
9181 fprintf (f
, ", making insn equivalence: ");
9182 print_active_time (f
, equiv_time
);
9183 fprintf (f
, "\n all automaton generation: ");
9184 print_active_time (f
, automaton_generation_time
);
9185 fprintf (f
, ", output: ");
9186 print_active_time (f
, output_time
);
9190 /* The function generates DFA (deterministic finite state automaton)
9191 for fast recognition of pipeline hazards. No errors during
9192 checking must be fixed before this function call. */
9196 automata_num
= split_argument
;
9197 if (description
->units_num
< automata_num
)
9198 automata_num
= description
->units_num
;
9201 initiate_automata_lists ();
9202 initiate_pass_states ();
9203 initiate_excl_sets ();
9204 initiate_presence_absence_pattern_sets ();
9205 automaton_generation_time
= create_ticker ();
9207 ticker_off (&automaton_generation_time
);
9212 /* This page mainly contains top level functions of pipeline hazards
9213 description translator. */
9215 /* The following macro value is suffix of name of description file of
9216 pipeline hazards description translator. */
9217 #define STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX ".dfa"
9219 /* The function returns suffix of given file name. The returned
9220 string can not be changed. */
9222 file_name_suffix (const char *file_name
)
9224 const char *last_period
;
9226 for (last_period
= NULL
; *file_name
!= '\0'; file_name
++)
9227 if (*file_name
== '.')
9228 last_period
= file_name
;
9229 return (last_period
== NULL
? file_name
: last_period
);
9232 /* The function returns base name of given file name, i.e. pointer to
9233 first char after last `/' (or `\' for WIN32) in given file name,
9234 given file name itself if the directory name is absent. The
9235 returned string can not be changed. */
9237 base_file_name (const char *file_name
)
9239 int directory_name_length
;
9241 directory_name_length
= strlen (file_name
);
9243 while (directory_name_length
>= 0 && file_name
[directory_name_length
] != '/'
9244 && file_name
[directory_name_length
] != '\\')
9246 while (directory_name_length
>= 0 && file_name
[directory_name_length
] != '/')
9248 directory_name_length
--;
9249 return file_name
+ directory_name_length
+ 1;
9252 /* A function passed as argument to init_rtx_reader_args_cb. It parses the
9253 options available for genautomata. Returns true if the option was
9256 parse_automata_opt (const char *str
)
9258 if (strcmp (str
, NO_MINIMIZATION_OPTION
) == 0)
9259 no_minimization_flag
= 1;
9260 else if (strcmp (str
, TIME_OPTION
) == 0)
9262 else if (strcmp (str
, STATS_OPTION
) == 0)
9264 else if (strcmp (str
, V_OPTION
) == 0)
9266 else if (strcmp (str
, W_OPTION
) == 0)
9268 else if (strcmp (str
, NDFA_OPTION
) == 0)
9270 else if (strcmp (str
, COLLAPSE_OPTION
) == 0)
9272 else if (strcmp (str
, PROGRESS_OPTION
) == 0)
9274 else if (strcmp (str
, "-split") == 0)
9276 fatal ("option `-split' has not been implemented yet\n");
9277 /* split_argument = atoi (argument_vect [i + 1]); */
9285 /* The following is top level function to initialize the work of
9286 pipeline hazards description translator. */
9288 initiate_automaton_gen (char **argv
)
9290 const char *base_name
;
9292 /* Initialize IR storage. */
9293 obstack_init (&irp
);
9294 initiate_automaton_decl_table ();
9295 initiate_insn_decl_table ();
9296 initiate_decl_table ();
9297 output_file
= stdout
;
9298 output_description_file
= NULL
;
9299 base_name
= base_file_name (argv
[1]);
9300 obstack_grow (&irp
, base_name
,
9301 strlen (base_name
) - strlen (file_name_suffix (base_name
)));
9302 obstack_grow (&irp
, STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX
,
9303 strlen (STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX
) + 1);
9304 obstack_1grow (&irp
, '\0');
9305 output_description_file_name
= obstack_base (&irp
);
9306 obstack_finish (&irp
);
9309 /* The following function checks existence at least one arc marked by
9312 check_automata_insn_issues (void)
9314 automaton_t automaton
;
9315 ainsn_t ainsn
, reserv_ainsn
;
9317 for (automaton
= description
->first_automaton
;
9319 automaton
= automaton
->next_automaton
)
9321 for (ainsn
= automaton
->ainsn_list
;
9323 ainsn
= ainsn
->next_ainsn
)
9324 if (ainsn
->first_insn_with_same_reservs
&& !ainsn
->arc_exists_p
9325 && ainsn
!= automaton
->collapse_ainsn
)
9327 for (reserv_ainsn
= ainsn
;
9328 reserv_ainsn
!= NULL
;
9329 reserv_ainsn
= reserv_ainsn
->next_same_reservs_insn
)
9330 if (automaton
->corresponding_automaton_decl
!= NULL
)
9333 error ("Automaton `%s': Insn `%s' will never be issued",
9334 automaton
->corresponding_automaton_decl
->name
,
9335 reserv_ainsn
->insn_reserv_decl
->name
);
9337 warning ("Automaton `%s': Insn `%s' will never be issued",
9338 automaton
->corresponding_automaton_decl
->name
,
9339 reserv_ainsn
->insn_reserv_decl
->name
);
9344 error ("Insn `%s' will never be issued",
9345 reserv_ainsn
->insn_reserv_decl
->name
);
9347 warning ("Insn `%s' will never be issued",
9348 reserv_ainsn
->insn_reserv_decl
->name
);
9354 /* The following vla is used for storing pointers to all achieved
9356 static vec
<state_t
> automaton_states
;
9358 /* This function is called by function pass_states to add an achieved
9361 add_automaton_state (state_t state
)
9363 automaton_states
.safe_push (state
);
9366 /* The following function forms list of important automata (whose
9367 states may be changed after the insn issue) for each insn. */
9369 form_important_insn_automata_lists (void)
9371 automaton_t automaton
;
9378 automaton_states
.create (0);
9379 /* Mark important ainsns. */
9380 for (automaton
= description
->first_automaton
;
9382 automaton
= automaton
->next_automaton
)
9384 automaton_states
.truncate (0);
9385 pass_states (automaton
, add_automaton_state
);
9386 for (n
= 0; n
< automaton_states
.length (); n
++)
9388 state_t s
= automaton_states
[n
];
9389 for (arc
= first_out_arc (s
);
9391 arc
= next_out_arc (arc
))
9392 if (arc
->to_state
!= s
)
9394 gcc_assert (arc
->insn
->first_insn_with_same_reservs
);
9395 for (ainsn
= arc
->insn
;
9397 ainsn
= ainsn
->next_same_reservs_insn
)
9398 ainsn
->important_p
= TRUE
;
9402 automaton_states
.release ();
9404 /* Create automata sets for the insns. */
9405 for (i
= 0; i
< description
->decls_num
; i
++)
9407 decl
= description
->decls
[i
];
9408 if (decl
->mode
== dm_insn_reserv
)
9410 automata_list_start ();
9411 for (automaton
= description
->first_automaton
;
9413 automaton
= automaton
->next_automaton
)
9414 for (ainsn
= automaton
->ainsn_list
;
9416 ainsn
= ainsn
->next_ainsn
)
9417 if (ainsn
->important_p
9418 && ainsn
->insn_reserv_decl
== DECL_INSN_RESERV (decl
))
9420 automata_list_add (automaton
);
9423 DECL_INSN_RESERV (decl
)->important_automata_list
9424 = automata_list_finish ();
9430 /* The following is top level function to generate automat(a,on) for
9431 fast recognition of pipeline hazards. */
9433 expand_automata (void)
9437 description
= XCREATENODEVAR (struct description
,
9438 sizeof (struct description
)
9439 /* Two entries for special insns. */
9440 + sizeof (decl_t
) * (decls
.length () + 1));
9441 description
->decls_num
= decls
.length ();
9442 description
->normal_decls_num
= description
->decls_num
;
9443 description
->query_units_num
= 0;
9444 for (i
= 0; i
< description
->decls_num
; i
++)
9446 description
->decls
[i
] = decls
[i
];
9447 if (description
->decls
[i
]->mode
== dm_unit
9448 && DECL_UNIT (description
->decls
[i
])->query_p
)
9449 DECL_UNIT (description
->decls
[i
])->query_num
9450 = description
->query_units_num
++;
9452 all_time
= create_ticker ();
9453 check_time
= create_ticker ();
9455 fprintf (stderr
, "Check description...");
9456 check_all_description ();
9458 fprintf (stderr
, "done\n");
9459 ticker_off (&check_time
);
9460 generation_time
= create_ticker ();
9463 transform_insn_regexps ();
9464 check_unit_distributions_to_automata ();
9469 check_automata_insn_issues ();
9473 form_important_insn_automata_lists ();
9475 ticker_off (&generation_time
);
9478 /* The following is top level function to output PHR and to finish
9479 work with pipeline description translator. */
9481 write_automata (void)
9483 output_time
= create_ticker ();
9485 fprintf (stderr
, "Forming and outputting automata tables...");
9489 fprintf (stderr
, "done\n");
9490 fprintf (stderr
, "Output functions to work with automata...");
9492 output_chip_definitions ();
9493 output_max_insn_queue_index_def ();
9494 output_internal_min_issue_delay_func ();
9495 output_internal_trans_func ();
9496 /* Cache of insn dfa codes: */
9497 fprintf (output_file
, "\nstatic int *%s;\n", DFA_INSN_CODES_VARIABLE_NAME
);
9498 fprintf (output_file
, "\nstatic int %s;\n\n",
9499 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
);
9500 output_dfa_insn_code_func ();
9501 output_trans_func ();
9502 output_min_issue_delay_func ();
9503 output_internal_dead_lock_func ();
9504 output_dead_lock_func ();
9505 output_size_func ();
9506 output_internal_reset_func ();
9507 output_reset_func ();
9508 output_min_insn_conflict_delay_func ();
9509 output_default_latencies ();
9510 output_internal_insn_latency_func ();
9511 output_insn_latency_func ();
9512 output_internal_maximal_insn_latency_func ();
9513 output_maximal_insn_latency_func ();
9514 output_print_reservation_func ();
9515 /* Output function get_cpu_unit_code. */
9516 fprintf (output_file
, "\n#if %s\n\n", CPU_UNITS_QUERY_MACRO_NAME
);
9517 output_get_cpu_unit_code_func ();
9518 output_cpu_unit_reservation_p ();
9519 output_insn_has_dfa_reservation_p ();
9520 fprintf (output_file
, "\n#endif /* #if %s */\n\n",
9521 CPU_UNITS_QUERY_MACRO_NAME
);
9522 output_dfa_clean_insn_cache_func ();
9523 output_dfa_start_func ();
9524 output_dfa_finish_func ();
9526 fprintf (stderr
, "done\n");
9529 output_description_file
= fopen (output_description_file_name
, "w");
9530 if (output_description_file
== NULL
)
9532 perror (output_description_file_name
);
9533 exit (FATAL_EXIT_CODE
);
9536 fprintf (stderr
, "Output automata description...");
9537 output_description ();
9538 output_automaton_descriptions ();
9540 fprintf (stderr
, "done\n");
9541 output_statistics (output_description_file
);
9544 output_statistics (stderr
);
9545 ticker_off (&output_time
);
9547 output_time_statistics (stderr
);
9550 finish_automata_lists ();
9553 fprintf (stderr
, "Summary:\n");
9554 fprintf (stderr
, " check time ");
9555 print_active_time (stderr
, check_time
);
9556 fprintf (stderr
, ", generation time ");
9557 print_active_time (stderr
, generation_time
);
9558 fprintf (stderr
, ", all time ");
9559 print_active_time (stderr
, all_time
);
9560 fprintf (stderr
, "\n");
9562 /* Finish all work. */
9563 if (output_description_file
!= NULL
)
9565 fflush (output_description_file
);
9566 if (ferror (stdout
) != 0)
9567 fatal ("Error in writing DFA description file %s: %s",
9568 output_description_file_name
, xstrerror (errno
));
9569 fclose (output_description_file
);
9571 finish_automaton_decl_table ();
9572 finish_insn_decl_table ();
9573 finish_decl_table ();
9574 obstack_free (&irp
, NULL
);
9575 if (have_error
&& output_description_file
!= NULL
)
9576 remove (output_description_file_name
);
9580 main (int argc
, char **argv
)
9584 progname
= "genautomata";
9586 if (!init_rtx_reader_args_cb (argc
, argv
, parse_automata_opt
))
9587 return (FATAL_EXIT_CODE
);
9589 initiate_automaton_gen (argv
);
9593 int insn_code_number
;
9595 desc
= read_md_rtx (&lineno
, &insn_code_number
);
9599 switch (GET_CODE (desc
))
9601 case DEFINE_CPU_UNIT
:
9602 gen_cpu_unit (desc
);
9605 case DEFINE_QUERY_CPU_UNIT
:
9606 gen_query_cpu_unit (desc
);
9614 gen_excl_set (desc
);
9618 gen_presence_set (desc
);
9621 case FINAL_PRESENCE_SET
:
9622 gen_final_presence_set (desc
);
9626 gen_absence_set (desc
);
9629 case FINAL_ABSENCE_SET
:
9630 gen_final_absence_set (desc
);
9633 case DEFINE_AUTOMATON
:
9634 gen_automaton (desc
);
9637 case AUTOMATA_OPTION
:
9638 gen_automata_option (desc
);
9641 case DEFINE_RESERVATION
:
9645 case DEFINE_INSN_RESERVATION
:
9646 gen_insn_reserv (desc
);
9655 return FATAL_EXIT_CODE
;
9657 if (decls
.length () > 0)
9662 puts ("/* Generated automatically by the program `genautomata'\n"
9663 " from the machine description file `md'. */\n\n"
9664 "#include \"config.h\"\n"
9665 "#include \"system.h\"\n"
9666 "#include \"coretypes.h\"\n"
9667 "#include \"tm.h\"\n"
9668 "#include \"rtl.h\"\n"
9669 "#include \"tm_p.h\"\n"
9670 "#include \"insn-config.h\"\n"
9671 "#include \"recog.h\"\n"
9672 "#include \"regs.h\"\n"
9673 "#include \"output.h\"\n"
9674 "#include \"insn-attr.h\"\n"
9675 "#include \"diagnostic-core.h\"\n"
9676 "#include \"flags.h\"\n"
9677 "#include \"function.h\"\n"
9678 "#include \"emit-rtl.h\"\n");
9679 /* FIXME: emit-rtl.h can go away once crtl is in rtl.h. */
9686 puts ("/* Generated automatically by the program `genautomata'\n"
9687 " from the machine description file `md'. */\n\n"
9688 "/* There is no automaton, but ISO C forbids empty\n"
9689 " translation units, so include a header file with some\n"
9690 " declarations, and its pre-requisite header file. */\n"
9691 "#include \"config.h\"\n"
9692 "#include \"system.h\"\n");
9696 return (ferror (stdout
) != 0 || have_error
9697 ? FATAL_EXIT_CODE
: SUCCESS_EXIT_CODE
);