1 /* Pipeline hazard description translator.
2 Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007
3 Free Software Foundation, Inc.
5 Written by Vladimir Makarov <vmakarov@redhat.com>
7 This file is part of GCC.
9 GCC is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by the
11 Free Software Foundation; either version 2, or (at your option) any
14 GCC is distributed in the hope that it will be useful, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING. If not, write to the Free
21 Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
26 1. Detecting pipeline structural hazards quickly. T. Proebsting,
27 C. Fraser. Proceedings of ACM SIGPLAN-SIGACT Symposium on
28 Principles of Programming Languages, pages 280--286, 1994.
30 This article is a good start point to understand usage of finite
31 state automata for pipeline hazard recognizers. But I'd
32 recommend the 2nd article for more deep understanding.
34 2. Efficient Instruction Scheduling Using Finite State Automata:
35 V. Bala and N. Rubin, Proceedings of MICRO-28. This is the best
36 article about usage of finite state automata for pipeline hazard
39 The current implementation is different from the 2nd article in the
42 1. New operator `|' (alternative) is permitted in functional unit
43 reservation which can be treated deterministically and
44 non-deterministically.
46 2. Possibility of usage of nondeterministic automata too.
48 3. Possibility to query functional unit reservations for given
51 4. Several constructions to describe impossible reservations
52 (`exclusion_set', `presence_set', `final_presence_set',
53 `absence_set', and `final_absence_set').
55 5. No reverse automata are generated. Trace instruction scheduling
56 requires this. It can be easily added in the future if we
59 6. Union of automaton states are not generated yet. It is planned
60 to be implemented. Such feature is needed to make more accurate
61 interlock insn scheduling to get state describing functional
62 unit reservation in a joint CFG point. */
64 /* This file code processes constructions of machine description file
65 which describes automaton used for recognition of processor pipeline
66 hazards by insn scheduler and can be used for other tasks (such as
69 The translator functions `gen_cpu_unit', `gen_query_cpu_unit',
70 `gen_bypass', `gen_excl_set', `gen_presence_set',
71 `gen_final_presence_set', `gen_absence_set',
72 `gen_final_absence_set', `gen_automaton', `gen_automata_option',
73 `gen_reserv', `gen_insn_reserv' are called from file
74 `genattrtab.c'. They transform RTL constructions describing
75 automata in .md file into internal representation convenient for
78 The translator major function `expand_automata' processes the
79 description internal representation into finite state automaton.
82 o checking correctness of the automaton pipeline description
83 (major function is `check_all_description').
85 o generating automaton (automata) from the description (major
86 function is `make_automaton').
88 o optional transformation of nondeterministic finite state
89 automata into deterministic ones if the alternative operator
90 `|' is treated nondeterministically in the description (major
91 function is NDFA_to_DFA).
93 o optional minimization of the finite state automata by merging
94 equivalent automaton states (major function is `minimize_DFA').
96 o forming tables (some as comb vectors) and attributes
97 representing the automata (functions output_..._table).
99 Function `write_automata' outputs the created finite state
100 automaton as different tables and functions which works with the
101 automata to inquire automaton state and to change its state. These
102 function are used by gcc instruction scheduler and may be some
107 #include "coretypes.h"
112 #include "gensupport.h"
122 /* Positions in machine description file. Now they are not used. But
123 they could be used in the future for better diagnostic messages. */
126 /* The following is element of vector of current (and planned in the
127 future) functional unit reservations. */
128 typedef unsigned HOST_WIDE_INT set_el_t;
130 /* Reservations of function units are represented by value of the following
132 typedef set_el_t *reserv_sets_t;
133 typedef const set_el_t *const_reserv_sets_t;
135 /* The following structure describes a ticker. */
138 /* The following member value is time of the ticker creation with
139 taking into account time when the ticker is off. Active time of
140 the ticker is current time minus the value. */
141 int modified_creation_time;
142 /* The following member value is time (incremented by one) when the
143 ticker was off. Zero value means that now the ticker is on. */
144 int incremented_off_time;
147 /* The ticker is represented by the following type. */
148 typedef struct ticker ticker_t;
150 /* The following type describes elements of output vectors. */
151 typedef HOST_WIDE_INT vect_el_t;
153 /* Forward declaration of structures of internal representation of
154 pipeline description based on NDFA. */
159 struct automaton_decl;
160 struct unit_pattern_rel_decl;
162 struct insn_reserv_decl;
165 struct result_regexp;
166 struct reserv_regexp;
167 struct nothing_regexp;
168 struct sequence_regexp;
169 struct repeat_regexp;
175 struct pattern_set_el;
176 struct pattern_reserv;
182 struct state_ainsn_table;
184 /* The following typedefs are for brevity. */
185 typedef struct unit_decl *unit_decl_t;
186 typedef const struct unit_decl *const_unit_decl_t;
187 typedef struct decl *decl_t;
188 typedef const struct decl *const_decl_t;
189 typedef struct regexp *regexp_t;
190 typedef struct unit_set_el *unit_set_el_t;
191 typedef struct pattern_set_el *pattern_set_el_t;
192 typedef struct pattern_reserv *pattern_reserv_t;
193 typedef struct alt_state *alt_state_t;
194 typedef struct state *state_t;
195 typedef const struct state *const_state_t;
196 typedef struct arc *arc_t;
197 typedef struct ainsn *ainsn_t;
198 typedef struct automaton *automaton_t;
199 typedef struct automata_list_el *automata_list_el_t;
200 typedef const struct automata_list_el *const_automata_list_el_t;
201 typedef struct state_ainsn_table *state_ainsn_table_t;
203 /* Undefined position. */
204 static pos_t no_pos = 0;
206 /* All IR is stored in the following obstack. */
207 static struct obstack irp;
210 /* Declare vector types for various data structures: */
212 DEF_VEC_P(alt_state_t);
213 DEF_VEC_ALLOC_P(alt_state_t,heap);
215 DEF_VEC_ALLOC_P(ainsn_t,heap);
217 DEF_VEC_ALLOC_P(state_t,heap);
219 DEF_VEC_ALLOC_P(decl_t,heap);
220 DEF_VEC_P(reserv_sets_t);
221 DEF_VEC_ALLOC_P(reserv_sets_t,heap);
223 DEF_VEC_I(vect_el_t);
224 DEF_VEC_ALLOC_I(vect_el_t, heap);
225 typedef VEC(vect_el_t,heap) *vla_hwint_t;
227 /* Forward declarations of functions used before their definitions, only. */
228 static regexp_t gen_regexp_sequence (const char *);
229 static void reserv_sets_or (reserv_sets_t, reserv_sets_t,
231 static reserv_sets_t get_excl_set (reserv_sets_t);
232 static int check_presence_pattern_sets (reserv_sets_t,
234 static int check_absence_pattern_sets (reserv_sets_t, reserv_sets_t,
236 static arc_t first_out_arc (const_state_t);
237 static arc_t next_out_arc (arc_t);
241 /* Options with the following names can be set up in automata_option
242 construction. Because the strings occur more one time we use the
245 #define NO_MINIMIZATION_OPTION "-no-minimization"
246 #define TIME_OPTION "-time"
247 #define STATS_OPTION "-stats"
248 #define V_OPTION "-v"
249 #define W_OPTION "-w"
250 #define NDFA_OPTION "-ndfa"
251 #define PROGRESS_OPTION "-progress"
253 /* The following flags are set up by function `initiate_automaton_gen'. */
255 /* Make automata with nondeterministic reservation by insns (`-ndfa'). */
256 static int ndfa_flag;
258 /* Do not make minimization of DFA (`-no-minimization'). */
259 static int no_minimization_flag;
261 /* Value of this variable is number of automata being generated. The
262 actual number of automata may be less this value if there is not
263 sufficient number of units. This value is defined by argument of
264 option `-split' or by constructions automaton if the value is zero
265 (it is default value of the argument). */
266 static int split_argument;
268 /* Flag of output time statistics (`-time'). */
269 static int time_flag;
271 /* Flag of automata statistics (`-stats'). */
272 static int stats_flag;
274 /* Flag of creation of description file which contains description of
275 result automaton and statistics information (`-v'). */
278 /* Flag of output of a progress bar showing how many states were
279 generated so far for automaton being processed (`-progress'). */
280 static int progress_flag;
282 /* Flag of generating warning instead of error for non-critical errors
287 /* Output file for pipeline hazard recognizer (PHR) being generated.
288 The value is NULL if the file is not defined. */
289 static FILE *output_file;
291 /* Description file of PHR. The value is NULL if the file is not
293 static FILE *output_description_file;
295 /* PHR description file name. */
296 static char *output_description_file_name;
298 /* Value of the following variable is node representing description
299 being processed. This is start point of IR. */
300 static struct description *description;
304 /* This page contains description of IR structure (nodes). */
318 /* This describes define_cpu_unit and define_query_cpu_unit (see file
323 /* NULL if the automaton name is absent. */
324 const char *automaton_name;
325 /* If the following value is not zero, the cpu unit reservation is
326 described in define_query_cpu_unit. */
329 /* The following fields are defined by checker. */
331 /* The following field value is nonzero if the unit is used in an
335 /* The following field value is order number (0, 1, ...) of given
338 /* The following field value is corresponding declaration of
339 automaton which was given in description. If the field value is
340 NULL then automaton in the unit declaration was absent. */
341 struct automaton_decl *automaton_decl;
342 /* The following field value is maximal cycle number (1, ...) on
343 which given unit occurs in insns. Zero value means that given
344 unit is not used in insns. */
345 int max_occ_cycle_num;
346 /* The following field value is minimal cycle number (0, ...) on
347 which given unit occurs in insns. -1 value means that given
348 unit is not used in insns. */
349 int min_occ_cycle_num;
350 /* The following list contains units which conflict with given
352 unit_set_el_t excl_list;
353 /* The following list contains patterns which are required to
354 reservation of given unit. */
355 pattern_set_el_t presence_list;
356 pattern_set_el_t final_presence_list;
357 /* The following list contains patterns which should be not present
358 in reservation for given unit. */
359 pattern_set_el_t absence_list;
360 pattern_set_el_t final_absence_list;
361 /* The following is used only when `query_p' has nonzero value.
362 This is query number for the unit. */
364 /* The following is the last cycle on which the unit was checked for
365 correct distributions of units to automata in a regexp. */
366 int last_distribution_check_cycle;
368 /* The following fields are defined by automaton generator. */
370 /* The following field value is number of the automaton to which
371 given unit belongs. */
372 int corresponding_automaton_num;
373 /* If the following value is not zero, the cpu unit is present in a
374 `exclusion_set' or in right part of a `presence_set',
375 `final_presence_set', `absence_set', and
376 `final_absence_set'define_query_cpu_unit. */
380 /* This describes define_bypass (see file rtl.def). */
384 const char *out_insn_name;
385 const char *in_insn_name;
386 const char *bypass_guard_name;
388 /* The following fields are defined by checker. */
390 /* output and input insns of given bypass. */
391 struct insn_reserv_decl *out_insn_reserv;
392 struct insn_reserv_decl *in_insn_reserv;
393 /* The next bypass for given output insn. */
394 struct bypass_decl *next;
397 /* This describes define_automaton (see file rtl.def). */
398 struct automaton_decl
402 /* The following fields are defined by automaton generator. */
404 /* The following field value is nonzero if the automaton is used in
405 an regexp definition. */
406 char automaton_is_used;
408 /* The following fields are defined by checker. */
410 /* The following field value is the corresponding automaton. This
411 field is not NULL only if the automaton is present in unit
412 declarations and the automatic partition on automata is not
414 automaton_t corresponding_automaton;
417 /* This describes exclusion relations: exclusion_set (see file
422 int first_list_length;
426 /* This describes unit relations: [final_]presence_set or
427 [final_]absence_set (see file rtl.def). */
428 struct unit_pattern_rel_decl
437 /* This describes define_reservation (see file rtl.def). */
443 /* The following fields are defined by checker. */
445 /* The following field value is nonzero if the unit is used in an
448 /* The following field is used to check up cycle in expression
453 /* This describes define_insn_reservation (see file rtl.def). */
454 struct insn_reserv_decl
461 /* The following fields are defined by checker. */
463 /* The following field value is order number (0, 1, ...) of given
466 /* The following field value is list of bypasses in which given insn
468 struct bypass_decl *bypass_list;
470 /* The following fields are defined by automaton generator. */
472 /* The following field is the insn regexp transformed that
473 the regexp has not optional regexp, repetition regexp, and an
474 reservation name (i.e. reservation identifiers are changed by the
475 corresponding regexp) and all alternations are the topest level
476 of the regexp. The value can be NULL only if it is special
477 insn `cycle advancing'. */
478 regexp_t transformed_regexp;
479 /* The following field value is list of arcs marked given
480 insn. The field is used in transformation NDFA -> DFA. */
481 arc_t arcs_marked_by_insn;
482 /* The two following fields are used during minimization of a finite state
484 /* The field value is number of equivalence class of state into
485 which arc marked by given insn enters from a state (fixed during
486 an automaton minimization). */
488 /* The following member value is the list to automata which can be
489 changed by the insn issue. */
490 automata_list_el_t important_automata_list;
491 /* The following member is used to process insn once for output. */
495 /* This contains a declaration mentioned above. */
498 /* What node in the union? */
503 struct unit_decl unit;
504 struct bypass_decl bypass;
505 struct automaton_decl automaton;
506 struct excl_rel_decl excl;
507 struct unit_pattern_rel_decl presence;
508 struct unit_pattern_rel_decl absence;
509 struct reserv_decl reserv;
510 struct insn_reserv_decl insn_reserv;
514 /* The following structures represent parsed reservation strings. */
526 /* Cpu unit in reservation. */
530 unit_decl_t unit_decl;
533 /* Define_reservation in a reservation. */
537 struct reserv_decl *reserv_decl;
540 /* Absence of reservation (represented by string `nothing'). */
541 struct nothing_regexp
543 /* This used to be empty but ISO C doesn't allow that. */
547 /* Representation of reservations separated by ',' (see file
549 struct sequence_regexp
552 regexp_t regexps [1];
555 /* Representation of construction `repeat' (see file rtl.def). */
562 /* Representation of reservations separated by '+' (see file
567 regexp_t regexps [1];
570 /* Representation of reservations separated by '|' (see file
575 regexp_t regexps [1];
578 /* Representation of a reservation string. */
581 /* What node in the union? */
582 enum regexp_mode mode;
586 struct unit_regexp unit;
587 struct reserv_regexp reserv;
588 struct nothing_regexp nothing;
589 struct sequence_regexp sequence;
590 struct repeat_regexp repeat;
591 struct allof_regexp allof;
592 struct oneof_regexp oneof;
596 /* Represents description of pipeline hazard description based on
602 /* The following fields are defined by checker. */
604 /* The following fields values are correspondingly number of all
605 units, query units, and insns in the description. */
609 /* The following field value is max length (in cycles) of
610 reservations of insns. The field value is defined only for
612 int max_insn_reserv_cycles;
614 /* The following fields are defined by automaton generator. */
616 /* The following field value is the first automaton. */
617 automaton_t first_automaton;
619 /* The following field is created by pipeline hazard parser and
620 contains all declarations. We allocate additional entry for
621 special insn "cycle advancing" which is added by the automaton
627 /* The following nodes are created in automaton checker. */
629 /* The following nodes represent exclusion set for cpu units. Each
630 element is accessed through only one excl_list. */
633 unit_decl_t unit_decl;
634 unit_set_el_t next_unit_set_el;
637 /* The following nodes represent presence or absence pattern for cpu
638 units. Each element is accessed through only one presence_list or
640 struct pattern_set_el
642 /* The number of units in unit_decls. */
644 /* The units forming the pattern. */
645 struct unit_decl **unit_decls;
646 pattern_set_el_t next_pattern_set_el;
650 /* The following nodes are created in automaton generator. */
653 /* The following nodes represent presence or absence pattern for cpu
654 units. Each element is accessed through only one element of
655 unit_presence_set_table or unit_absence_set_table. */
656 struct pattern_reserv
658 reserv_sets_t reserv;
659 pattern_reserv_t next_pattern_reserv;
662 /* The following node type describes state automaton. The state may
663 be deterministic or non-deterministic. Non-deterministic state has
664 several component states which represent alternative cpu units
665 reservations. The state also is used for describing a
666 deterministic reservation of automaton insn. */
669 /* The following member value is nonzero if there is a transition by
672 /* The following field is list of processor unit reservations on
674 reserv_sets_t reservs;
675 /* The following field is unique number of given state between other
678 /* The following field value is automaton to which given state
680 automaton_t automaton;
681 /* The following field value is the first arc output from given
684 unsigned int num_out_arcs;
685 /* The following field is used to form NDFA. */
686 char it_was_placed_in_stack_for_NDFA_forming;
687 /* The following field is used to form DFA. */
688 char it_was_placed_in_stack_for_DFA_forming;
689 /* The following field is used to transform NDFA to DFA and DFA
690 minimization. The field value is not NULL if the state is a
691 compound state. In this case the value of field `unit_sets_list'
692 is NULL. All states in the list are in the hash table. The list
693 is formed through field `next_sorted_alt_state'. We should
694 support only one level of nesting state. */
695 alt_state_t component_states;
696 /* The following field is used for passing graph of states. */
698 /* The list of states belonging to one equivalence class is formed
699 with the aid of the following field. */
700 state_t next_equiv_class_state;
701 /* The two following fields are used during minimization of a finite
703 int equiv_class_num_1, equiv_class_num_2;
704 /* The following field is used during minimization of a finite state
705 automaton. The field value is state corresponding to equivalence
706 class to which given state belongs. */
707 state_t equiv_class_state;
708 unsigned int *presence_signature;
709 /* The following field value is the order number of given state.
710 The states in final DFA is enumerated with the aid of the
713 /* This member is used for passing states for searching minimal
716 /* The following member is used to evaluate min issue delay of insn
718 int min_insn_issue_delay;
724 /* The following field refers for the state into which given arc
727 /* The following field describes that the insn issue (with cycle
728 advancing for special insn `cycle advancing' and without cycle
729 advancing for others) makes transition from given state to
730 another given state. */
732 /* The following field value is the next arc output from the same
735 /* List of arcs marked given insn is formed with the following
736 field. The field is used in transformation NDFA -> DFA. */
737 arc_t next_arc_marked_by_insn;
740 /* The following node type describes a deterministic alternative in
741 non-deterministic state which characterizes cpu unit reservations
742 of automaton insn or which is part of NDFA. */
745 /* The following field is a deterministic state which characterizes
746 unit reservations of the instruction. */
748 /* The following field refers to the next state which characterizes
749 unit reservations of the instruction. */
750 alt_state_t next_alt_state;
751 /* The following field refers to the next state in sorted list. */
752 alt_state_t next_sorted_alt_state;
755 /* The following node type describes insn of automaton. They are
756 labels of FA arcs. */
759 /* The following field value is the corresponding insn declaration
761 struct insn_reserv_decl *insn_reserv_decl;
762 /* The following field value is the next insn declaration for an
765 /* The following field is states which characterize automaton unit
766 reservations of the instruction. The value can be NULL only if it
767 is special insn `cycle advancing'. */
768 alt_state_t alt_states;
769 /* The following field is sorted list of states which characterize
770 automaton unit reservations of the instruction. The value can be
771 NULL only if it is special insn `cycle advancing'. */
772 alt_state_t sorted_alt_states;
773 /* The following field refers the next automaton insn with
774 the same reservations. */
775 ainsn_t next_same_reservs_insn;
776 /* The following field is flag of the first automaton insn with the
777 same reservations in the declaration list. Only arcs marked such
778 insn is present in the automaton. This significantly decreases
779 memory requirements especially when several automata are
781 char first_insn_with_same_reservs;
782 /* The following member has nonzero value if there is arc from state of
783 the automaton marked by the ainsn. */
785 /* Cyclic list of insns of an equivalence class is formed with the
786 aid of the following field. */
787 ainsn_t next_equiv_class_insn;
788 /* The following field value is nonzero if the insn declaration is
789 the first insn declaration with given equivalence number. */
790 char first_ainsn_with_given_equivalence_num;
791 /* The following field is number of class of equivalence of insns.
792 It is necessary because many insns may be equivalent with the
793 point of view of pipeline hazards. */
794 int insn_equiv_class_num;
795 /* The following member value is TRUE if there is an arc in the
796 automaton marked by the insn into another state. In other
797 words, the insn can change the state of the automaton. */
801 /* The following describes an automaton for PHR. */
804 /* The following field value is the list of insn declarations for
807 /* The following field value is the corresponding automaton
808 declaration. This field is not NULL only if the automatic
809 partition on automata is not used. */
810 struct automaton_decl *corresponding_automaton_decl;
811 /* The following field value is the next automaton. */
812 automaton_t next_automaton;
813 /* The following field is start state of FA. There are not unit
814 reservations in the state. */
816 /* The following field value is number of equivalence classes of
817 insns (see field `insn_equiv_class_num' in
818 `insn_reserv_decl'). */
819 int insn_equiv_classes_num;
820 /* The following field value is number of states of final DFA. */
821 int achieved_states_num;
822 /* The following field value is the order number (0, 1, ...) of
824 int automaton_order_num;
825 /* The following fields contain statistics information about
826 building automaton. */
827 int NDFA_states_num, DFA_states_num;
828 /* The following field value is defined only if minimization of DFA
830 int minimal_DFA_states_num;
831 int NDFA_arcs_num, DFA_arcs_num;
832 /* The following field value is defined only if minimization of DFA
834 int minimal_DFA_arcs_num;
835 /* The following member refers for two table state x ainsn -> int.
836 ??? Above sentence is incomprehensible. */
837 state_ainsn_table_t trans_table;
838 /* The following member value is maximal value of min issue delay
839 for insns of the automaton. */
841 /* Usually min issue delay is small and we can place several (2, 4,
842 8) elements in one vector element. So the compression factor can
843 be 1 (no compression), 2, 4, 8. */
844 int min_issue_delay_table_compression_factor;
845 /* Total number of locked states in this automaton. */
849 /* The following is the element of the list of automata. */
850 struct automata_list_el
852 /* The automaton itself. */
853 automaton_t automaton;
854 /* The next automata set element. */
855 automata_list_el_t next_automata_list_el;
858 /* The following structure describes a table state X ainsn -> int(>= 0). */
859 struct state_ainsn_table
861 /* Automaton to which given table belongs. */
862 automaton_t automaton;
863 /* The following tree vectors for comb vector implementation of the
865 vla_hwint_t comb_vect;
866 vla_hwint_t check_vect;
867 vla_hwint_t base_vect;
868 /* This is simple implementation of the table. */
869 vla_hwint_t full_vect;
870 /* Minimal and maximal values of the previous vectors. */
871 int min_comb_vect_el_value, max_comb_vect_el_value;
872 int min_base_vect_el_value, max_base_vect_el_value;
875 /* Macros to access members of unions. Use only them for access to
876 union members of declarations and regexps. */
878 #if defined ENABLE_CHECKING && (GCC_VERSION >= 2007)
880 #define DECL_UNIT(d) __extension__ \
881 (({ __typeof (d) const _decl = (d); \
882 if (_decl->mode != dm_unit) \
883 decl_mode_check_failed (_decl->mode, "dm_unit", \
884 __FILE__, __LINE__, __FUNCTION__); \
885 &(_decl)->decl.unit; }))
887 #define DECL_BYPASS(d) __extension__ \
888 (({ __typeof (d) const _decl = (d); \
889 if (_decl->mode != dm_bypass) \
890 decl_mode_check_failed (_decl->mode, "dm_bypass", \
891 __FILE__, __LINE__, __FUNCTION__); \
892 &(_decl)->decl.bypass; }))
894 #define DECL_AUTOMATON(d) __extension__ \
895 (({ __typeof (d) const _decl = (d); \
896 if (_decl->mode != dm_automaton) \
897 decl_mode_check_failed (_decl->mode, "dm_automaton", \
898 __FILE__, __LINE__, __FUNCTION__); \
899 &(_decl)->decl.automaton; }))
901 #define DECL_EXCL(d) __extension__ \
902 (({ __typeof (d) const _decl = (d); \
903 if (_decl->mode != dm_excl) \
904 decl_mode_check_failed (_decl->mode, "dm_excl", \
905 __FILE__, __LINE__, __FUNCTION__); \
906 &(_decl)->decl.excl; }))
908 #define DECL_PRESENCE(d) __extension__ \
909 (({ __typeof (d) const _decl = (d); \
910 if (_decl->mode != dm_presence) \
911 decl_mode_check_failed (_decl->mode, "dm_presence", \
912 __FILE__, __LINE__, __FUNCTION__); \
913 &(_decl)->decl.presence; }))
915 #define DECL_ABSENCE(d) __extension__ \
916 (({ __typeof (d) const _decl = (d); \
917 if (_decl->mode != dm_absence) \
918 decl_mode_check_failed (_decl->mode, "dm_absence", \
919 __FILE__, __LINE__, __FUNCTION__); \
920 &(_decl)->decl.absence; }))
922 #define DECL_RESERV(d) __extension__ \
923 (({ __typeof (d) const _decl = (d); \
924 if (_decl->mode != dm_reserv) \
925 decl_mode_check_failed (_decl->mode, "dm_reserv", \
926 __FILE__, __LINE__, __FUNCTION__); \
927 &(_decl)->decl.reserv; }))
929 #define DECL_INSN_RESERV(d) __extension__ \
930 (({ __typeof (d) const _decl = (d); \
931 if (_decl->mode != dm_insn_reserv) \
932 decl_mode_check_failed (_decl->mode, "dm_insn_reserv", \
933 __FILE__, __LINE__, __FUNCTION__); \
934 &(_decl)->decl.insn_reserv; }))
936 static const char *decl_name (enum decl_mode);
937 static void decl_mode_check_failed (enum decl_mode, const char *,
938 const char *, int, const char *)
941 /* Return string representation of declaration mode MODE. */
943 decl_name (enum decl_mode mode)
945 static char str [100];
949 else if (mode == dm_bypass)
951 else if (mode == dm_automaton)
952 return "dm_automaton";
953 else if (mode == dm_excl)
955 else if (mode == dm_presence)
956 return "dm_presence";
957 else if (mode == dm_absence)
959 else if (mode == dm_reserv)
961 else if (mode == dm_insn_reserv)
962 return "dm_insn_reserv";
964 sprintf (str, "unknown (%d)", (int) mode);
968 /* The function prints message about unexpected declaration and finish
971 decl_mode_check_failed (enum decl_mode mode, const char *expected_mode_str,
972 const char *file, int line, const char *func)
976 "\n%s: %d: error in %s: DECL check: expected decl %s, have %s\n",
977 file, line, func, expected_mode_str, decl_name (mode));
982 #define REGEXP_UNIT(r) __extension__ \
983 (({ struct regexp *const _regexp = (r); \
984 if (_regexp->mode != rm_unit) \
985 regexp_mode_check_failed (_regexp->mode, "rm_unit", \
986 __FILE__, __LINE__, __FUNCTION__); \
987 &(_regexp)->regexp.unit; }))
989 #define REGEXP_RESERV(r) __extension__ \
990 (({ struct regexp *const _regexp = (r); \
991 if (_regexp->mode != rm_reserv) \
992 regexp_mode_check_failed (_regexp->mode, "rm_reserv", \
993 __FILE__, __LINE__, __FUNCTION__); \
994 &(_regexp)->regexp.reserv; }))
996 #define REGEXP_SEQUENCE(r) __extension__ \
997 (({ struct regexp *const _regexp = (r); \
998 if (_regexp->mode != rm_sequence) \
999 regexp_mode_check_failed (_regexp->mode, "rm_sequence", \
1000 __FILE__, __LINE__, __FUNCTION__); \
1001 &(_regexp)->regexp.sequence; }))
1003 #define REGEXP_REPEAT(r) __extension__ \
1004 (({ struct regexp *const _regexp = (r); \
1005 if (_regexp->mode != rm_repeat) \
1006 regexp_mode_check_failed (_regexp->mode, "rm_repeat", \
1007 __FILE__, __LINE__, __FUNCTION__); \
1008 &(_regexp)->regexp.repeat; }))
1010 #define REGEXP_ALLOF(r) __extension__ \
1011 (({ struct regexp *const _regexp = (r); \
1012 if (_regexp->mode != rm_allof) \
1013 regexp_mode_check_failed (_regexp->mode, "rm_allof", \
1014 __FILE__, __LINE__, __FUNCTION__); \
1015 &(_regexp)->regexp.allof; }))
1017 #define REGEXP_ONEOF(r) __extension__ \
1018 (({ struct regexp *const _regexp = (r); \
1019 if (_regexp->mode != rm_oneof) \
1020 regexp_mode_check_failed (_regexp->mode, "rm_oneof", \
1021 __FILE__, __LINE__, __FUNCTION__); \
1022 &(_regexp)->regexp.oneof; }))
1024 static const char *regexp_name (enum regexp_mode);
1025 static void regexp_mode_check_failed (enum regexp_mode, const char *,
1027 const char *) ATTRIBUTE_NORETURN;
1030 /* Return string representation of regexp mode MODE. */
1032 regexp_name (enum regexp_mode mode)
1041 return "rm_nothing";
1043 return "rm_sequence";
1055 /* The function prints message about unexpected regexp and finish the
1058 regexp_mode_check_failed (enum regexp_mode mode,
1059 const char *expected_mode_str,
1060 const char *file, int line, const char *func)
1064 "\n%s: %d: error in %s: REGEXP check: expected decl %s, have %s\n",
1065 file, line, func, expected_mode_str, regexp_name (mode));
1069 #else /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */
1071 #define DECL_UNIT(d) (&(d)->decl.unit)
1072 #define DECL_BYPASS(d) (&(d)->decl.bypass)
1073 #define DECL_AUTOMATON(d) (&(d)->decl.automaton)
1074 #define DECL_EXCL(d) (&(d)->decl.excl)
1075 #define DECL_PRESENCE(d) (&(d)->decl.presence)
1076 #define DECL_ABSENCE(d) (&(d)->decl.absence)
1077 #define DECL_RESERV(d) (&(d)->decl.reserv)
1078 #define DECL_INSN_RESERV(d) (&(d)->decl.insn_reserv)
1080 #define REGEXP_UNIT(r) (&(r)->regexp.unit)
1081 #define REGEXP_RESERV(r) (&(r)->regexp.reserv)
1082 #define REGEXP_SEQUENCE(r) (&(r)->regexp.sequence)
1083 #define REGEXP_REPEAT(r) (&(r)->regexp.repeat)
1084 #define REGEXP_ALLOF(r) (&(r)->regexp.allof)
1085 #define REGEXP_ONEOF(r) (&(r)->regexp.oneof)
1087 #endif /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */
1089 /* Create IR structure (node). */
1091 create_node (size_t size)
1095 obstack_blank (&irp, size);
1096 result = obstack_base (&irp);
1097 obstack_finish (&irp);
1098 /* Default values of members are NULL and zero. */
1099 memset (result, 0, size);
1103 /* Copy IR structure (node). */
1105 copy_node (const void *from, size_t size)
1107 void *const result = create_node (size);
1108 memcpy (result, from, size);
1112 /* The function checks that NAME does not contain quotes (`"'). */
1114 check_name (const char * name, pos_t pos ATTRIBUTE_UNUSED)
1118 for (str = name; *str != '\0'; str++)
1120 error ("Name `%s' contains quotes", name);
1124 /* Pointers to all declarations during IR generation are stored in the
1126 static VEC(decl_t,heap) *decls;
1128 /* Given a pointer to a (char *) and a separator, return an alloc'ed
1129 string containing the next separated element, taking parentheses
1130 into account if PAR_FLAG has nonzero value. Advance the pointer to
1131 after the string scanned, or the end-of-string. Return NULL if at
1134 next_sep_el (const char **pstr, int sep, int par_flag)
1141 /* Remove leading whitespaces. */
1142 while (ISSPACE ((int) **pstr))
1149 for (pars_num = 0, p = *pstr; *p != '\0'; p++)
1151 if (par_flag && *p == '(')
1153 else if (par_flag && *p == ')')
1155 else if (pars_num == 0 && *p == sep)
1157 if (pars_num == 0 && ISSPACE ((int) *p))
1161 for (; n_spaces != 0; n_spaces--)
1162 obstack_1grow (&irp, p [-n_spaces]);
1163 obstack_1grow (&irp, *p);
1166 obstack_1grow (&irp, '\0');
1167 out_str = obstack_base (&irp);
1168 obstack_finish (&irp);
1177 /* Given a string and a separator, return the number of separated
1178 elements in it, taking parentheses into account if PAR_FLAG has
1179 nonzero value. Return 0 for the null string, -1 if parentheses is
1182 n_sep_els (const char *s, int sep, int par_flag)
1190 for (pars_num = 0, n = 1; *s; s++)
1191 if (par_flag && *s == '(')
1193 else if (par_flag && *s == ')')
1195 else if (pars_num == 0 && *s == sep)
1198 return (pars_num != 0 ? -1 : n);
1201 /* Given a string and a separator, return vector of strings which are
1202 elements in the string and number of elements through els_num.
1203 Take parentheses into account if PAREN_P has nonzero value. The
1204 function also inserts the end marker NULL at the end of vector.
1205 Return 0 for the null string, -1 if parentheses are not balanced. */
1207 get_str_vect (const char *str, int *els_num, int sep, int paren_p)
1214 *els_num = n_sep_els (str, sep, paren_p);
1217 obstack_blank (&irp, sizeof (char *) * (*els_num + 1));
1218 vect = (char **) obstack_base (&irp);
1219 obstack_finish (&irp);
1221 for (i = 0; i < *els_num; i++)
1222 vect [i] = next_sep_el (pstr, sep, paren_p);
1223 trail = next_sep_el (pstr, sep, paren_p);
1224 gcc_assert (!trail);
1229 /* Process a DEFINE_CPU_UNIT.
1231 This gives information about a unit contained in CPU. We fill a
1232 struct unit_decl with information used later by `expand_automata'. */
1234 gen_cpu_unit (rtx def)
1237 char **str_cpu_units;
1241 str_cpu_units = get_str_vect (XSTR (def, 0), &vect_length, ',', FALSE);
1242 if (str_cpu_units == NULL)
1243 fatal ("invalid string `%s' in define_cpu_unit", XSTR (def, 0));
1244 for (i = 0; i < vect_length; i++)
1246 decl = create_node (sizeof (struct decl));
1247 decl->mode = dm_unit;
1249 DECL_UNIT (decl)->name = check_name (str_cpu_units [i], decl->pos);
1250 DECL_UNIT (decl)->automaton_name = XSTR (def, 1);
1251 DECL_UNIT (decl)->query_p = 0;
1252 DECL_UNIT (decl)->min_occ_cycle_num = -1;
1253 DECL_UNIT (decl)->in_set_p = 0;
1254 VEC_safe_push (decl_t,heap, decls, decl);
1258 /* Process a DEFINE_QUERY_CPU_UNIT.
1260 This gives information about a unit contained in CPU. We fill a
1261 struct unit_decl with information used later by `expand_automata'. */
1263 gen_query_cpu_unit (rtx def)
1266 char **str_cpu_units;
1270 str_cpu_units = get_str_vect (XSTR (def, 0), &vect_length, ',',
1272 if (str_cpu_units == NULL)
1273 fatal ("invalid string `%s' in define_query_cpu_unit", XSTR (def, 0));
1274 for (i = 0; i < vect_length; i++)
1276 decl = create_node (sizeof (struct decl));
1277 decl->mode = dm_unit;
1279 DECL_UNIT (decl)->name = check_name (str_cpu_units [i], decl->pos);
1280 DECL_UNIT (decl)->automaton_name = XSTR (def, 1);
1281 DECL_UNIT (decl)->query_p = 1;
1282 VEC_safe_push (decl_t,heap, decls, decl);
1286 /* Process a DEFINE_BYPASS.
1288 This gives information about a unit contained in the CPU. We fill
1289 in a struct bypass_decl with information used later by
1290 `expand_automata'. */
1292 gen_bypass (rtx def)
1301 out_insns = get_str_vect (XSTR (def, 1), &out_length, ',', FALSE);
1302 if (out_insns == NULL)
1303 fatal ("invalid string `%s' in define_bypass", XSTR (def, 1));
1304 in_insns = get_str_vect (XSTR (def, 2), &in_length, ',', FALSE);
1305 if (in_insns == NULL)
1306 fatal ("invalid string `%s' in define_bypass", XSTR (def, 2));
1307 for (i = 0; i < out_length; i++)
1308 for (j = 0; j < in_length; j++)
1310 decl = create_node (sizeof (struct decl));
1311 decl->mode = dm_bypass;
1313 DECL_BYPASS (decl)->latency = XINT (def, 0);
1314 DECL_BYPASS (decl)->out_insn_name = out_insns [i];
1315 DECL_BYPASS (decl)->in_insn_name = in_insns [j];
1316 DECL_BYPASS (decl)->bypass_guard_name = XSTR (def, 3);
1317 VEC_safe_push (decl_t,heap, decls, decl);
1321 /* Process an EXCLUSION_SET.
1323 This gives information about a cpu unit conflicts. We fill a
1324 struct excl_rel_decl (excl) with information used later by
1325 `expand_automata'. */
1327 gen_excl_set (rtx def)
1330 char **first_str_cpu_units;
1331 char **second_str_cpu_units;
1332 int first_vect_length;
1337 = get_str_vect (XSTR (def, 0), &first_vect_length, ',', FALSE);
1338 if (first_str_cpu_units == NULL)
1339 fatal ("invalid first string `%s' in exclusion_set", XSTR (def, 0));
1340 second_str_cpu_units = get_str_vect (XSTR (def, 1), &length, ',',
1342 if (second_str_cpu_units == NULL)
1343 fatal ("invalid second string `%s' in exclusion_set", XSTR (def, 1));
1344 length += first_vect_length;
1345 decl = create_node (sizeof (struct decl) + (length - 1) * sizeof (char *));
1346 decl->mode = dm_excl;
1348 DECL_EXCL (decl)->all_names_num = length;
1349 DECL_EXCL (decl)->first_list_length = first_vect_length;
1350 for (i = 0; i < length; i++)
1351 if (i < first_vect_length)
1352 DECL_EXCL (decl)->names [i] = first_str_cpu_units [i];
1354 DECL_EXCL (decl)->names [i]
1355 = second_str_cpu_units [i - first_vect_length];
1356 VEC_safe_push (decl_t,heap, decls, decl);
1359 /* Process a PRESENCE_SET, a FINAL_PRESENCE_SET, an ABSENCE_SET,
1360 FINAL_ABSENCE_SET (it is depended on PRESENCE_P and FINAL_P).
1362 This gives information about a cpu unit reservation requirements.
1363 We fill a struct unit_pattern_rel_decl with information used later
1364 by `expand_automata'. */
1366 gen_presence_absence_set (rtx def, int presence_p, int final_p)
1369 char **str_cpu_units;
1370 char **str_pattern_lists;
1371 char ***str_patterns;
1372 int cpu_units_length;
1374 int patterns_length;
1377 str_cpu_units = get_str_vect (XSTR (def, 0), &cpu_units_length, ',',
1379 if (str_cpu_units == NULL)
1382 ? "invalid first string `%s' in final_presence_set"
1383 : "invalid first string `%s' in presence_set")
1385 ? "invalid first string `%s' in final_absence_set"
1386 : "invalid first string `%s' in absence_set")),
1388 str_pattern_lists = get_str_vect (XSTR (def, 1),
1389 &patterns_length, ',', FALSE);
1390 if (str_pattern_lists == NULL)
1393 ? "invalid second string `%s' in final_presence_set"
1394 : "invalid second string `%s' in presence_set")
1396 ? "invalid second string `%s' in final_absence_set"
1397 : "invalid second string `%s' in absence_set")), XSTR (def, 1));
1398 str_patterns = obstack_alloc (&irp, patterns_length * sizeof (char **));
1399 for (i = 0; i < patterns_length; i++)
1401 str_patterns [i] = get_str_vect (str_pattern_lists [i],
1402 &length, ' ', FALSE);
1403 gcc_assert (str_patterns [i]);
1405 decl = create_node (sizeof (struct decl));
1409 decl->mode = dm_presence;
1410 DECL_PRESENCE (decl)->names_num = cpu_units_length;
1411 DECL_PRESENCE (decl)->names = str_cpu_units;
1412 DECL_PRESENCE (decl)->patterns = str_patterns;
1413 DECL_PRESENCE (decl)->patterns_num = patterns_length;
1414 DECL_PRESENCE (decl)->final_p = final_p;
1418 decl->mode = dm_absence;
1419 DECL_ABSENCE (decl)->names_num = cpu_units_length;
1420 DECL_ABSENCE (decl)->names = str_cpu_units;
1421 DECL_ABSENCE (decl)->patterns = str_patterns;
1422 DECL_ABSENCE (decl)->patterns_num = patterns_length;
1423 DECL_ABSENCE (decl)->final_p = final_p;
1425 VEC_safe_push (decl_t,heap, decls, decl);
1428 /* Process a PRESENCE_SET.
1430 This gives information about a cpu unit reservation requirements.
1431 We fill a struct unit_pattern_rel_decl (presence) with information
1432 used later by `expand_automata'. */
1434 gen_presence_set (rtx def)
1436 gen_presence_absence_set (def, TRUE, FALSE);
1439 /* Process a FINAL_PRESENCE_SET.
1441 This gives information about a cpu unit reservation requirements.
1442 We fill a struct unit_pattern_rel_decl (presence) with information
1443 used later by `expand_automata'. */
1445 gen_final_presence_set (rtx def)
1447 gen_presence_absence_set (def, TRUE, TRUE);
1450 /* Process an ABSENCE_SET.
1452 This gives information about a cpu unit reservation requirements.
1453 We fill a struct unit_pattern_rel_decl (absence) with information
1454 used later by `expand_automata'. */
1456 gen_absence_set (rtx def)
1458 gen_presence_absence_set (def, FALSE, FALSE);
1461 /* Process a FINAL_ABSENCE_SET.
1463 This gives information about a cpu unit reservation requirements.
1464 We fill a struct unit_pattern_rel_decl (absence) with information
1465 used later by `expand_automata'. */
1467 gen_final_absence_set (rtx def)
1469 gen_presence_absence_set (def, FALSE, TRUE);
1472 /* Process a DEFINE_AUTOMATON.
1474 This gives information about a finite state automaton used for
1475 recognizing pipeline hazards. We fill a struct automaton_decl
1476 with information used later by `expand_automata'. */
1478 gen_automaton (rtx def)
1481 char **str_automata;
1485 str_automata = get_str_vect (XSTR (def, 0), &vect_length, ',', FALSE);
1486 if (str_automata == NULL)
1487 fatal ("invalid string `%s' in define_automaton", XSTR (def, 0));
1488 for (i = 0; i < vect_length; i++)
1490 decl = create_node (sizeof (struct decl));
1491 decl->mode = dm_automaton;
1493 DECL_AUTOMATON (decl)->name = check_name (str_automata [i], decl->pos);
1494 VEC_safe_push (decl_t,heap, decls, decl);
1498 /* Process an AUTOMATA_OPTION.
1500 This gives information how to generate finite state automaton used
1501 for recognizing pipeline hazards. */
1503 gen_automata_option (rtx def)
1505 if (strcmp (XSTR (def, 0), NO_MINIMIZATION_OPTION + 1) == 0)
1506 no_minimization_flag = 1;
1507 else if (strcmp (XSTR (def, 0), TIME_OPTION + 1) == 0)
1509 else if (strcmp (XSTR (def, 0), STATS_OPTION + 1) == 0)
1511 else if (strcmp (XSTR (def, 0), V_OPTION + 1) == 0)
1513 else if (strcmp (XSTR (def, 0), W_OPTION + 1) == 0)
1515 else if (strcmp (XSTR (def, 0), NDFA_OPTION + 1) == 0)
1517 else if (strcmp (XSTR (def, 0), PROGRESS_OPTION + 1) == 0)
1520 fatal ("invalid option `%s' in automata_option", XSTR (def, 0));
1523 /* Name in reservation to denote absence reservation. */
1524 #define NOTHING_NAME "nothing"
1526 /* The following string contains original reservation string being
1528 static const char *reserv_str;
1530 /* Parse an element in STR. */
1532 gen_regexp_el (const char *str)
1541 if (str [len - 1] != ')')
1542 fatal ("garbage after ) in reservation `%s'", reserv_str);
1543 dstr = alloca (len - 1);
1544 memcpy (dstr, str + 1, len - 2);
1545 dstr [len-2] = '\0';
1546 regexp = gen_regexp_sequence (dstr);
1548 else if (strcmp (str, NOTHING_NAME) == 0)
1550 regexp = create_node (sizeof *regexp);
1551 regexp->mode = rm_nothing;
1555 regexp = create_node (sizeof *regexp);
1556 regexp->mode = rm_unit;
1557 REGEXP_UNIT (regexp)->name = str;
1562 /* Parse construction `repeat' in STR. */
1564 gen_regexp_repeat (const char *str)
1572 repeat_vect = get_str_vect (str, &els_num, '*', TRUE);
1573 if (repeat_vect == NULL)
1574 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1577 regexp = gen_regexp_el (repeat_vect [0]);
1578 for (i = 1; i < els_num; i++)
1580 repeat = create_node (sizeof (struct regexp));
1581 repeat->mode = rm_repeat;
1582 REGEXP_REPEAT (repeat)->regexp = regexp;
1583 REGEXP_REPEAT (repeat)->repeat_num = atoi (repeat_vect [i]);
1584 if (REGEXP_REPEAT (repeat)->repeat_num <= 1)
1585 fatal ("repetition `%s' <= 1 in reservation `%s'",
1592 return gen_regexp_el (str);
1595 /* Parse reservation STR which possibly contains separator '+'. */
1597 gen_regexp_allof (const char *str)
1604 allof_vect = get_str_vect (str, &els_num, '+', TRUE);
1605 if (allof_vect == NULL)
1606 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1609 allof = create_node (sizeof (struct regexp)
1610 + sizeof (regexp_t) * (els_num - 1));
1611 allof->mode = rm_allof;
1612 REGEXP_ALLOF (allof)->regexps_num = els_num;
1613 for (i = 0; i < els_num; i++)
1614 REGEXP_ALLOF (allof)->regexps [i] = gen_regexp_repeat (allof_vect [i]);
1618 return gen_regexp_repeat (str);
1621 /* Parse reservation STR which possibly contains separator '|'. */
1623 gen_regexp_oneof (const char *str)
1630 oneof_vect = get_str_vect (str, &els_num, '|', TRUE);
1631 if (oneof_vect == NULL)
1632 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1635 oneof = create_node (sizeof (struct regexp)
1636 + sizeof (regexp_t) * (els_num - 1));
1637 oneof->mode = rm_oneof;
1638 REGEXP_ONEOF (oneof)->regexps_num = els_num;
1639 for (i = 0; i < els_num; i++)
1640 REGEXP_ONEOF (oneof)->regexps [i] = gen_regexp_allof (oneof_vect [i]);
1644 return gen_regexp_allof (str);
1647 /* Parse reservation STR which possibly contains separator ','. */
1649 gen_regexp_sequence (const char *str)
1652 char **sequence_vect;
1656 sequence_vect = get_str_vect (str, &els_num, ',', TRUE);
1659 sequence = create_node (sizeof (struct regexp)
1660 + sizeof (regexp_t) * (els_num - 1));
1661 sequence->mode = rm_sequence;
1662 REGEXP_SEQUENCE (sequence)->regexps_num = els_num;
1663 for (i = 0; i < els_num; i++)
1664 REGEXP_SEQUENCE (sequence)->regexps [i]
1665 = gen_regexp_oneof (sequence_vect [i]);
1669 return gen_regexp_oneof (str);
1672 /* Parse construction reservation STR. */
1674 gen_regexp (const char *str)
1677 return gen_regexp_sequence (str);;
1680 /* Process a DEFINE_RESERVATION.
1682 This gives information about a reservation of cpu units. We fill
1683 in a struct reserv_decl with information used later by
1684 `expand_automata'. */
1686 gen_reserv (rtx def)
1690 decl = create_node (sizeof (struct decl));
1691 decl->mode = dm_reserv;
1693 DECL_RESERV (decl)->name = check_name (XSTR (def, 0), decl->pos);
1694 DECL_RESERV (decl)->regexp = gen_regexp (XSTR (def, 1));
1695 VEC_safe_push (decl_t,heap, decls, decl);
1698 /* Process a DEFINE_INSN_RESERVATION.
1700 This gives information about the reservation of cpu units by an
1701 insn. We fill a struct insn_reserv_decl with information used
1702 later by `expand_automata'. */
1704 gen_insn_reserv (rtx def)
1708 decl = create_node (sizeof (struct decl));
1709 decl->mode = dm_insn_reserv;
1711 DECL_INSN_RESERV (decl)->name
1712 = check_name (XSTR (def, 0), decl->pos);
1713 DECL_INSN_RESERV (decl)->default_latency = XINT (def, 1);
1714 DECL_INSN_RESERV (decl)->condexp = XEXP (def, 2);
1715 DECL_INSN_RESERV (decl)->regexp = gen_regexp (XSTR (def, 3));
1716 VEC_safe_push (decl_t,heap, decls, decl);
1721 /* The function evaluates hash value (0..UINT_MAX) of string. */
1723 string_hash (const char *string)
1727 for (result = i = 0;*string++ != '\0'; i++)
1728 result += ((unsigned char) *string << (i % CHAR_BIT));
1734 /* This page contains abstract data `table of automaton declarations'.
1735 Elements of the table is nodes representing automaton declarations.
1736 Key of the table elements is name of given automaton. Remember
1737 that automaton names have own space. */
1739 /* The function evaluates hash value of an automaton declaration. The
1740 function is used by abstract data `hashtab'. The function returns
1741 hash value (0..UINT_MAX) of given automaton declaration. */
1743 automaton_decl_hash (const void *automaton_decl)
1745 const_decl_t const decl = (const_decl_t) automaton_decl;
1747 gcc_assert (decl->mode != dm_automaton
1748 || DECL_AUTOMATON (decl)->name);
1749 return string_hash (DECL_AUTOMATON (decl)->name);
1752 /* The function tests automaton declarations on equality of their
1753 keys. The function is used by abstract data `hashtab'. The
1754 function returns 1 if the declarations have the same key, 0
1757 automaton_decl_eq_p (const void* automaton_decl_1,
1758 const void* automaton_decl_2)
1760 const_decl_t const decl1 = (const_decl_t) automaton_decl_1;
1761 const_decl_t const decl2 = (const_decl_t) automaton_decl_2;
1763 gcc_assert (decl1->mode == dm_automaton
1764 && DECL_AUTOMATON (decl1)->name
1765 && decl2->mode == dm_automaton
1766 && DECL_AUTOMATON (decl2)->name);
1767 return strcmp (DECL_AUTOMATON (decl1)->name,
1768 DECL_AUTOMATON (decl2)->name) == 0;
1771 /* The automaton declaration table itself is represented by the
1772 following variable. */
1773 static htab_t automaton_decl_table;
1775 /* The function inserts automaton declaration into the table. The
1776 function does nothing if an automaton declaration with the same key
1777 exists already in the table. The function returns automaton
1778 declaration node in the table with the same key as given automaton
1779 declaration node. */
1781 insert_automaton_decl (decl_t automaton_decl)
1785 entry_ptr = htab_find_slot (automaton_decl_table, automaton_decl, 1);
1786 if (*entry_ptr == NULL)
1787 *entry_ptr = (void *) automaton_decl;
1788 return (decl_t) *entry_ptr;
1791 /* The following variable value is node representing automaton
1792 declaration. The node used for searching automaton declaration
1794 static struct decl work_automaton_decl;
1796 /* The function searches for automaton declaration in the table with
1797 the same key as node representing name of the automaton
1798 declaration. The function returns node found in the table, NULL if
1799 such node does not exist in the table. */
1801 find_automaton_decl (const char *name)
1805 work_automaton_decl.mode = dm_automaton;
1806 DECL_AUTOMATON (&work_automaton_decl)->name = name;
1807 entry = htab_find (automaton_decl_table, &work_automaton_decl);
1808 return (decl_t) entry;
1811 /* The function creates empty automaton declaration table and node
1812 representing automaton declaration and used for searching automaton
1813 declaration with given name. The function must be called only once
1814 before any work with the automaton declaration table. */
1816 initiate_automaton_decl_table (void)
1818 work_automaton_decl.mode = dm_automaton;
1819 automaton_decl_table = htab_create (10, automaton_decl_hash,
1820 automaton_decl_eq_p, (htab_del) 0);
1823 /* The function deletes the automaton declaration table. Only call of
1824 function `initiate_automaton_decl_table' is possible immediately
1825 after this function call. */
1827 finish_automaton_decl_table (void)
1829 htab_delete (automaton_decl_table);
1834 /* This page contains abstract data `table of insn declarations'.
1835 Elements of the table is nodes representing insn declarations. Key
1836 of the table elements is name of given insn (in corresponding
1837 define_insn_reservation). Remember that insn names have own
1840 /* The function evaluates hash value of an insn declaration. The
1841 function is used by abstract data `hashtab'. The function returns
1842 hash value (0..UINT_MAX) of given insn declaration. */
1844 insn_decl_hash (const void *insn_decl)
1846 const_decl_t const decl = (const_decl_t) insn_decl;
1848 gcc_assert (decl->mode == dm_insn_reserv
1849 && DECL_INSN_RESERV (decl)->name);
1850 return string_hash (DECL_INSN_RESERV (decl)->name);
1853 /* The function tests insn declarations on equality of their keys.
1854 The function is used by abstract data `hashtab'. The function
1855 returns 1 if declarations have the same key, 0 otherwise. */
1857 insn_decl_eq_p (const void *insn_decl_1, const void *insn_decl_2)
1859 const_decl_t const decl1 = (const_decl_t) insn_decl_1;
1860 const_decl_t const decl2 = (const_decl_t) insn_decl_2;
1862 gcc_assert (decl1->mode == dm_insn_reserv
1863 && DECL_INSN_RESERV (decl1)->name
1864 && decl2->mode == dm_insn_reserv
1865 && DECL_INSN_RESERV (decl2)->name);
1866 return strcmp (DECL_INSN_RESERV (decl1)->name,
1867 DECL_INSN_RESERV (decl2)->name) == 0;
1870 /* The insn declaration table itself is represented by the following
1871 variable. The table does not contain insn reservation
1873 static htab_t insn_decl_table;
1875 /* The function inserts insn declaration into the table. The function
1876 does nothing if an insn declaration with the same key exists
1877 already in the table. The function returns insn declaration node
1878 in the table with the same key as given insn declaration node. */
1880 insert_insn_decl (decl_t insn_decl)
1884 entry_ptr = htab_find_slot (insn_decl_table, insn_decl, 1);
1885 if (*entry_ptr == NULL)
1886 *entry_ptr = (void *) insn_decl;
1887 return (decl_t) *entry_ptr;
1890 /* The following variable value is node representing insn reservation
1891 declaration. The node used for searching insn reservation
1892 declaration with given name. */
1893 static struct decl work_insn_decl;
1895 /* The function searches for insn reservation declaration in the table
1896 with the same key as node representing name of the insn reservation
1897 declaration. The function returns node found in the table, NULL if
1898 such node does not exist in the table. */
1900 find_insn_decl (const char *name)
1904 work_insn_decl.mode = dm_insn_reserv;
1905 DECL_INSN_RESERV (&work_insn_decl)->name = name;
1906 entry = htab_find (insn_decl_table, &work_insn_decl);
1907 return (decl_t) entry;
1910 /* The function creates empty insn declaration table and node
1911 representing insn declaration and used for searching insn
1912 declaration with given name. The function must be called only once
1913 before any work with the insn declaration table. */
1915 initiate_insn_decl_table (void)
1917 work_insn_decl.mode = dm_insn_reserv;
1918 insn_decl_table = htab_create (10, insn_decl_hash, insn_decl_eq_p,
1922 /* The function deletes the insn declaration table. Only call of
1923 function `initiate_insn_decl_table' is possible immediately after
1924 this function call. */
1926 finish_insn_decl_table (void)
1928 htab_delete (insn_decl_table);
1933 /* This page contains abstract data `table of declarations'. Elements
1934 of the table is nodes representing declarations (of units and
1935 reservations). Key of the table elements is names of given
1938 /* The function evaluates hash value of a declaration. The function
1939 is used by abstract data `hashtab'. The function returns hash
1940 value (0..UINT_MAX) of given declaration. */
1942 decl_hash (const void *decl)
1944 const_decl_t const d = (const_decl_t) decl;
1946 gcc_assert ((d->mode == dm_unit && DECL_UNIT (d)->name)
1947 || (d->mode == dm_reserv && DECL_RESERV (d)->name));
1948 return string_hash (d->mode == dm_unit
1949 ? DECL_UNIT (d)->name : DECL_RESERV (d)->name);
1952 /* The function tests declarations on equality of their keys. The
1953 function is used by abstract data 'hashtab'. The function
1954 returns 1 if the declarations have the same key, 0 otherwise. */
1956 decl_eq_p (const void *decl_1, const void *decl_2)
1958 const_decl_t const d1 = (const_decl_t) decl_1;
1959 const_decl_t const d2 = (const_decl_t) decl_2;
1961 gcc_assert ((d1->mode == dm_unit && DECL_UNIT (d1)->name)
1962 || (d1->mode == dm_reserv && DECL_RESERV (d1)->name));
1963 gcc_assert ((d2->mode == dm_unit && DECL_UNIT (d2)->name)
1964 || (d2->mode == dm_reserv && DECL_RESERV (d2)->name));
1965 return strcmp ((d1->mode == dm_unit
1966 ? DECL_UNIT (d1)->name : DECL_RESERV (d1)->name),
1967 (d2->mode == dm_unit
1968 ? DECL_UNIT (d2)->name : DECL_RESERV (d2)->name)) == 0;
1971 /* The declaration table itself is represented by the following
1973 static htab_t decl_table;
1975 /* The function inserts declaration into the table. The function does
1976 nothing if a declaration with the same key exists already in the
1977 table. The function returns declaration node in the table with the
1978 same key as given declaration node. */
1981 insert_decl (decl_t decl)
1985 entry_ptr = htab_find_slot (decl_table, decl, 1);
1986 if (*entry_ptr == NULL)
1987 *entry_ptr = (void *) decl;
1988 return (decl_t) *entry_ptr;
1991 /* The following variable value is node representing declaration. The
1992 node used for searching declaration with given name. */
1993 static struct decl work_decl;
1995 /* The function searches for declaration in the table with the same
1996 key as node representing name of the declaration. The function
1997 returns node found in the table, NULL if such node does not exist
2000 find_decl (const char *name)
2004 work_decl.mode = dm_unit;
2005 DECL_UNIT (&work_decl)->name = name;
2006 entry = htab_find (decl_table, &work_decl);
2007 return (decl_t) entry;
2010 /* The function creates empty declaration table and node representing
2011 declaration and used for searching declaration with given name.
2012 The function must be called only once before any work with the
2013 declaration table. */
2015 initiate_decl_table (void)
2017 work_decl.mode = dm_unit;
2018 decl_table = htab_create (10, decl_hash, decl_eq_p, (htab_del) 0);
2021 /* The function deletes the declaration table. Only call of function
2022 `initiate_declaration_table' is possible immediately after this
2025 finish_decl_table (void)
2027 htab_delete (decl_table);
2032 /* This page contains checker of pipeline hazard description. */
2034 /* Checking NAMES in an exclusion clause vector and returning formed
2035 unit_set_el_list. */
2036 static unit_set_el_t
2037 process_excls (char **names, int num, pos_t excl_pos ATTRIBUTE_UNUSED)
2039 unit_set_el_t el_list;
2040 unit_set_el_t last_el;
2041 unit_set_el_t new_el;
2042 decl_t decl_in_table;
2047 for (i = 0; i < num; i++)
2049 decl_in_table = find_decl (names [i]);
2050 if (decl_in_table == NULL)
2051 error ("unit `%s' in exclusion is not declared", names [i]);
2052 else if (decl_in_table->mode != dm_unit)
2053 error ("`%s' in exclusion is not unit", names [i]);
2056 new_el = create_node (sizeof (struct unit_set_el));
2057 new_el->unit_decl = DECL_UNIT (decl_in_table);
2058 new_el->next_unit_set_el = NULL;
2059 if (last_el == NULL)
2060 el_list = last_el = new_el;
2063 last_el->next_unit_set_el = new_el;
2064 last_el = last_el->next_unit_set_el;
2071 /* The function adds each element from SOURCE_LIST to the exclusion
2072 list of the each element from DEST_LIST. Checking situation "unit
2073 excludes itself". */
2075 add_excls (unit_set_el_t dest_list, unit_set_el_t source_list,
2076 pos_t excl_pos ATTRIBUTE_UNUSED)
2080 unit_set_el_t curr_el;
2081 unit_set_el_t prev_el;
2084 for (dst = dest_list; dst != NULL; dst = dst->next_unit_set_el)
2085 for (src = source_list; src != NULL; src = src->next_unit_set_el)
2087 if (dst->unit_decl == src->unit_decl)
2089 error ("unit `%s' excludes itself", src->unit_decl->name);
2092 if (dst->unit_decl->automaton_name != NULL
2093 && src->unit_decl->automaton_name != NULL
2094 && strcmp (dst->unit_decl->automaton_name,
2095 src->unit_decl->automaton_name) != 0)
2097 error ("units `%s' and `%s' in exclusion set belong to different automata",
2098 src->unit_decl->name, dst->unit_decl->name);
2101 for (curr_el = dst->unit_decl->excl_list, prev_el = NULL;
2103 prev_el = curr_el, curr_el = curr_el->next_unit_set_el)
2104 if (curr_el->unit_decl == src->unit_decl)
2106 if (curr_el == NULL)
2108 /* Element not found - insert. */
2109 copy = copy_node (src, sizeof (*src));
2110 copy->next_unit_set_el = NULL;
2111 if (prev_el == NULL)
2112 dst->unit_decl->excl_list = copy;
2114 prev_el->next_unit_set_el = copy;
2119 /* Checking NAMES in presence/absence clause and returning the
2120 formed unit_set_el_list. The function is called only after
2121 processing all exclusion sets. */
2122 static unit_set_el_t
2123 process_presence_absence_names (char **names, int num,
2124 pos_t req_pos ATTRIBUTE_UNUSED,
2125 int presence_p, int final_p)
2127 unit_set_el_t el_list;
2128 unit_set_el_t last_el;
2129 unit_set_el_t new_el;
2130 decl_t decl_in_table;
2135 for (i = 0; i < num; i++)
2137 decl_in_table = find_decl (names [i]);
2138 if (decl_in_table == NULL)
2141 ? "unit `%s' in final presence set is not declared"
2142 : "unit `%s' in presence set is not declared")
2144 ? "unit `%s' in final absence set is not declared"
2145 : "unit `%s' in absence set is not declared")), names [i]);
2146 else if (decl_in_table->mode != dm_unit)
2149 ? "`%s' in final presence set is not unit"
2150 : "`%s' in presence set is not unit")
2152 ? "`%s' in final absence set is not unit"
2153 : "`%s' in absence set is not unit")), names [i]);
2156 new_el = create_node (sizeof (struct unit_set_el));
2157 new_el->unit_decl = DECL_UNIT (decl_in_table);
2158 new_el->next_unit_set_el = NULL;
2159 if (last_el == NULL)
2160 el_list = last_el = new_el;
2163 last_el->next_unit_set_el = new_el;
2164 last_el = last_el->next_unit_set_el;
2171 /* Checking NAMES in patterns of a presence/absence clause and
2172 returning the formed pattern_set_el_list. The function is called
2173 only after processing all exclusion sets. */
2174 static pattern_set_el_t
2175 process_presence_absence_patterns (char ***patterns, int num,
2176 pos_t req_pos ATTRIBUTE_UNUSED,
2177 int presence_p, int final_p)
2179 pattern_set_el_t el_list;
2180 pattern_set_el_t last_el;
2181 pattern_set_el_t new_el;
2182 decl_t decl_in_table;
2187 for (i = 0; i < num; i++)
2189 for (j = 0; patterns [i] [j] != NULL; j++)
2191 new_el = create_node (sizeof (struct pattern_set_el)
2192 + sizeof (struct unit_decl *) * j);
2194 = (struct unit_decl **) ((char *) new_el
2195 + sizeof (struct pattern_set_el));
2196 new_el->next_pattern_set_el = NULL;
2197 if (last_el == NULL)
2198 el_list = last_el = new_el;
2201 last_el->next_pattern_set_el = new_el;
2202 last_el = last_el->next_pattern_set_el;
2204 new_el->units_num = 0;
2205 for (j = 0; patterns [i] [j] != NULL; j++)
2207 decl_in_table = find_decl (patterns [i] [j]);
2208 if (decl_in_table == NULL)
2211 ? "unit `%s' in final presence set is not declared"
2212 : "unit `%s' in presence set is not declared")
2214 ? "unit `%s' in final absence set is not declared"
2215 : "unit `%s' in absence set is not declared")),
2217 else if (decl_in_table->mode != dm_unit)
2220 ? "`%s' in final presence set is not unit"
2221 : "`%s' in presence set is not unit")
2223 ? "`%s' in final absence set is not unit"
2224 : "`%s' in absence set is not unit")),
2228 new_el->unit_decls [new_el->units_num]
2229 = DECL_UNIT (decl_in_table);
2230 new_el->units_num++;
2237 /* The function adds each element from PATTERN_LIST to presence (if
2238 PRESENCE_P) or absence list of the each element from DEST_LIST.
2239 Checking situations "unit requires own absence", and "unit excludes
2240 and requires presence of ...", "unit requires absence and presence
2241 of ...", "units in (final) presence set belong to different
2242 automata", and "units in (final) absence set belong to different
2243 automata". Remember that we process absence sets only after all
2246 add_presence_absence (unit_set_el_t dest_list,
2247 pattern_set_el_t pattern_list,
2248 pos_t req_pos ATTRIBUTE_UNUSED,
2249 int presence_p, int final_p)
2252 pattern_set_el_t pat;
2253 struct unit_decl *unit;
2254 unit_set_el_t curr_excl_el;
2255 pattern_set_el_t curr_pat_el;
2256 pattern_set_el_t prev_el;
2257 pattern_set_el_t copy;
2261 for (dst = dest_list; dst != NULL; dst = dst->next_unit_set_el)
2262 for (pat = pattern_list; pat != NULL; pat = pat->next_pattern_set_el)
2264 for (i = 0; i < pat->units_num; i++)
2266 unit = pat->unit_decls [i];
2267 if (dst->unit_decl == unit && pat->units_num == 1 && !presence_p)
2269 error ("unit `%s' requires own absence", unit->name);
2272 if (dst->unit_decl->automaton_name != NULL
2273 && unit->automaton_name != NULL
2274 && strcmp (dst->unit_decl->automaton_name,
2275 unit->automaton_name) != 0)
2279 ? "units `%s' and `%s' in final presence set belong to different automata"
2280 : "units `%s' and `%s' in presence set belong to different automata")
2282 ? "units `%s' and `%s' in final absence set belong to different automata"
2283 : "units `%s' and `%s' in absence set belong to different automata")),
2284 unit->name, dst->unit_decl->name);
2289 for (curr_excl_el = dst->unit_decl->excl_list;
2290 curr_excl_el != NULL;
2291 curr_excl_el = curr_excl_el->next_unit_set_el)
2293 if (unit == curr_excl_el->unit_decl && pat->units_num == 1)
2297 error ("unit `%s' excludes and requires presence of `%s'",
2298 dst->unit_decl->name, unit->name);
2303 (0, "unit `%s' excludes and requires presence of `%s'",
2304 dst->unit_decl->name, unit->name);
2307 else if (pat->units_num == 1)
2308 for (curr_pat_el = dst->unit_decl->presence_list;
2309 curr_pat_el != NULL;
2310 curr_pat_el = curr_pat_el->next_pattern_set_el)
2311 if (curr_pat_el->units_num == 1
2312 && unit == curr_pat_el->unit_decls [0])
2317 ("unit `%s' requires absence and presence of `%s'",
2318 dst->unit_decl->name, unit->name);
2323 (0, "unit `%s' requires absence and presence of `%s'",
2324 dst->unit_decl->name, unit->name);
2328 for (prev_el = (presence_p
2330 ? dst->unit_decl->final_presence_list
2331 : dst->unit_decl->final_presence_list)
2333 ? dst->unit_decl->final_absence_list
2334 : dst->unit_decl->absence_list));
2335 prev_el != NULL && prev_el->next_pattern_set_el != NULL;
2336 prev_el = prev_el->next_pattern_set_el)
2338 copy = copy_node (pat, sizeof (*pat));
2339 copy->next_pattern_set_el = NULL;
2340 if (prev_el == NULL)
2345 dst->unit_decl->final_presence_list = copy;
2347 dst->unit_decl->presence_list = copy;
2350 dst->unit_decl->final_absence_list = copy;
2352 dst->unit_decl->absence_list = copy;
2355 prev_el->next_pattern_set_el = copy;
2362 /* The function searches for bypass with given IN_INSN_RESERV in given
2364 static struct bypass_decl *
2365 find_bypass (struct bypass_decl *bypass_list,
2366 struct insn_reserv_decl *in_insn_reserv)
2368 struct bypass_decl *bypass;
2370 for (bypass = bypass_list; bypass != NULL; bypass = bypass->next)
2371 if (bypass->in_insn_reserv == in_insn_reserv)
2376 /* The function processes pipeline description declarations, checks
2377 their correctness, and forms exclusion/presence/absence sets. */
2379 process_decls (void)
2382 decl_t automaton_decl;
2383 decl_t decl_in_table;
2384 decl_t out_insn_reserv;
2385 decl_t in_insn_reserv;
2386 struct bypass_decl *bypass;
2387 int automaton_presence;
2390 /* Checking repeated automata declarations. */
2391 automaton_presence = 0;
2392 for (i = 0; i < description->decls_num; i++)
2394 decl = description->decls [i];
2395 if (decl->mode == dm_automaton)
2397 automaton_presence = 1;
2398 decl_in_table = insert_automaton_decl (decl);
2399 if (decl_in_table != decl)
2402 error ("repeated declaration of automaton `%s'",
2403 DECL_AUTOMATON (decl)->name);
2405 warning (0, "repeated declaration of automaton `%s'",
2406 DECL_AUTOMATON (decl)->name);
2410 /* Checking undeclared automata, repeated declarations (except for
2411 automata) and correctness of their attributes (insn latency times
2413 for (i = 0; i < description->decls_num; i++)
2415 decl = description->decls [i];
2416 if (decl->mode == dm_insn_reserv)
2418 if (DECL_INSN_RESERV (decl)->default_latency < 0)
2419 error ("define_insn_reservation `%s' has negative latency time",
2420 DECL_INSN_RESERV (decl)->name);
2421 DECL_INSN_RESERV (decl)->insn_num = description->insns_num;
2422 description->insns_num++;
2423 decl_in_table = insert_insn_decl (decl);
2424 if (decl_in_table != decl)
2425 error ("`%s' is already used as insn reservation name",
2426 DECL_INSN_RESERV (decl)->name);
2428 else if (decl->mode == dm_bypass)
2430 if (DECL_BYPASS (decl)->latency < 0)
2431 error ("define_bypass `%s - %s' has negative latency time",
2432 DECL_BYPASS (decl)->out_insn_name,
2433 DECL_BYPASS (decl)->in_insn_name);
2435 else if (decl->mode == dm_unit || decl->mode == dm_reserv)
2437 if (decl->mode == dm_unit)
2439 DECL_UNIT (decl)->automaton_decl = NULL;
2440 if (DECL_UNIT (decl)->automaton_name != NULL)
2443 = find_automaton_decl (DECL_UNIT (decl)->automaton_name);
2444 if (automaton_decl == NULL)
2445 error ("automaton `%s' is not declared",
2446 DECL_UNIT (decl)->automaton_name);
2449 DECL_AUTOMATON (automaton_decl)->automaton_is_used = 1;
2450 DECL_UNIT (decl)->automaton_decl
2451 = DECL_AUTOMATON (automaton_decl);
2454 else if (automaton_presence)
2455 error ("define_unit `%s' without automaton when one defined",
2456 DECL_UNIT (decl)->name);
2457 DECL_UNIT (decl)->unit_num = description->units_num;
2458 description->units_num++;
2459 if (strcmp (DECL_UNIT (decl)->name, NOTHING_NAME) == 0)
2461 error ("`%s' is declared as cpu unit", NOTHING_NAME);
2464 decl_in_table = find_decl (DECL_UNIT (decl)->name);
2468 if (strcmp (DECL_RESERV (decl)->name, NOTHING_NAME) == 0)
2470 error ("`%s' is declared as cpu reservation", NOTHING_NAME);
2473 decl_in_table = find_decl (DECL_RESERV (decl)->name);
2475 if (decl_in_table == NULL)
2476 decl_in_table = insert_decl (decl);
2479 if (decl->mode == dm_unit)
2480 error ("repeated declaration of unit `%s'",
2481 DECL_UNIT (decl)->name);
2483 error ("repeated declaration of reservation `%s'",
2484 DECL_RESERV (decl)->name);
2488 /* Check bypasses and form list of bypasses for each (output)
2490 for (i = 0; i < description->decls_num; i++)
2492 decl = description->decls [i];
2493 if (decl->mode == dm_bypass)
2495 out_insn_reserv = find_insn_decl (DECL_BYPASS (decl)->out_insn_name);
2496 in_insn_reserv = find_insn_decl (DECL_BYPASS (decl)->in_insn_name);
2497 if (out_insn_reserv == NULL)
2498 error ("there is no insn reservation `%s'",
2499 DECL_BYPASS (decl)->out_insn_name);
2500 else if (in_insn_reserv == NULL)
2501 error ("there is no insn reservation `%s'",
2502 DECL_BYPASS (decl)->in_insn_name);
2505 DECL_BYPASS (decl)->out_insn_reserv
2506 = DECL_INSN_RESERV (out_insn_reserv);
2507 DECL_BYPASS (decl)->in_insn_reserv
2508 = DECL_INSN_RESERV (in_insn_reserv);
2510 = find_bypass (DECL_INSN_RESERV (out_insn_reserv)->bypass_list,
2511 DECL_BYPASS (decl)->in_insn_reserv);
2514 if (DECL_BYPASS (decl)->latency == bypass->latency)
2518 ("the same bypass `%s - %s' is already defined",
2519 DECL_BYPASS (decl)->out_insn_name,
2520 DECL_BYPASS (decl)->in_insn_name);
2523 (0, "the same bypass `%s - %s' is already defined",
2524 DECL_BYPASS (decl)->out_insn_name,
2525 DECL_BYPASS (decl)->in_insn_name);
2528 error ("bypass `%s - %s' is already defined",
2529 DECL_BYPASS (decl)->out_insn_name,
2530 DECL_BYPASS (decl)->in_insn_name);
2534 DECL_BYPASS (decl)->next
2535 = DECL_INSN_RESERV (out_insn_reserv)->bypass_list;
2536 DECL_INSN_RESERV (out_insn_reserv)->bypass_list
2537 = DECL_BYPASS (decl);
2543 /* Check exclusion set declarations and form exclusion sets. */
2544 for (i = 0; i < description->decls_num; i++)
2546 decl = description->decls [i];
2547 if (decl->mode == dm_excl)
2549 unit_set_el_t unit_set_el_list;
2550 unit_set_el_t unit_set_el_list_2;
2553 = process_excls (DECL_EXCL (decl)->names,
2554 DECL_EXCL (decl)->first_list_length, decl->pos);
2556 = process_excls (&DECL_EXCL (decl)->names
2557 [DECL_EXCL (decl)->first_list_length],
2558 DECL_EXCL (decl)->all_names_num
2559 - DECL_EXCL (decl)->first_list_length,
2561 add_excls (unit_set_el_list, unit_set_el_list_2, decl->pos);
2562 add_excls (unit_set_el_list_2, unit_set_el_list, decl->pos);
2566 /* Check presence set declarations and form presence sets. */
2567 for (i = 0; i < description->decls_num; i++)
2569 decl = description->decls [i];
2570 if (decl->mode == dm_presence)
2572 unit_set_el_t unit_set_el_list;
2573 pattern_set_el_t pattern_set_el_list;
2576 = process_presence_absence_names
2577 (DECL_PRESENCE (decl)->names, DECL_PRESENCE (decl)->names_num,
2578 decl->pos, TRUE, DECL_PRESENCE (decl)->final_p);
2580 = process_presence_absence_patterns
2581 (DECL_PRESENCE (decl)->patterns,
2582 DECL_PRESENCE (decl)->patterns_num,
2583 decl->pos, TRUE, DECL_PRESENCE (decl)->final_p);
2584 add_presence_absence (unit_set_el_list, pattern_set_el_list,
2586 DECL_PRESENCE (decl)->final_p);
2590 /* Check absence set declarations and form absence sets. */
2591 for (i = 0; i < description->decls_num; i++)
2593 decl = description->decls [i];
2594 if (decl->mode == dm_absence)
2596 unit_set_el_t unit_set_el_list;
2597 pattern_set_el_t pattern_set_el_list;
2600 = process_presence_absence_names
2601 (DECL_ABSENCE (decl)->names, DECL_ABSENCE (decl)->names_num,
2602 decl->pos, FALSE, DECL_ABSENCE (decl)->final_p);
2604 = process_presence_absence_patterns
2605 (DECL_ABSENCE (decl)->patterns,
2606 DECL_ABSENCE (decl)->patterns_num,
2607 decl->pos, FALSE, DECL_ABSENCE (decl)->final_p);
2608 add_presence_absence (unit_set_el_list, pattern_set_el_list,
2610 DECL_ABSENCE (decl)->final_p);
2615 /* The following function checks that declared automaton is used. If
2616 the automaton is not used, the function fixes error/warning. The
2617 following function must be called only after `process_decls'. */
2619 check_automaton_usage (void)
2624 for (i = 0; i < description->decls_num; i++)
2626 decl = description->decls [i];
2627 if (decl->mode == dm_automaton
2628 && !DECL_AUTOMATON (decl)->automaton_is_used)
2631 error ("automaton `%s' is not used", DECL_AUTOMATON (decl)->name);
2633 warning (0, "automaton `%s' is not used",
2634 DECL_AUTOMATON (decl)->name);
2639 /* The following recursive function processes all regexp in order to
2640 fix usage of units or reservations and to fix errors of undeclared
2641 name. The function may change unit_regexp onto reserv_regexp.
2642 Remember that reserv_regexp does not exist before the function
2645 process_regexp (regexp_t regexp)
2647 decl_t decl_in_table;
2648 regexp_t new_regexp;
2651 switch (regexp->mode)
2654 decl_in_table = find_decl (REGEXP_UNIT (regexp)->name);
2655 if (decl_in_table == NULL)
2656 error ("undeclared unit or reservation `%s'",
2657 REGEXP_UNIT (regexp)->name);
2659 switch (decl_in_table->mode)
2662 DECL_UNIT (decl_in_table)->unit_is_used = 1;
2663 REGEXP_UNIT (regexp)->unit_decl = DECL_UNIT (decl_in_table);
2667 DECL_RESERV (decl_in_table)->reserv_is_used = 1;
2668 new_regexp = create_node (sizeof (struct regexp));
2669 new_regexp->mode = rm_reserv;
2670 new_regexp->pos = regexp->pos;
2671 REGEXP_RESERV (new_regexp)->name = REGEXP_UNIT (regexp)->name;
2672 REGEXP_RESERV (new_regexp)->reserv_decl
2673 = DECL_RESERV (decl_in_table);
2674 regexp = new_regexp;
2682 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
2683 REGEXP_SEQUENCE (regexp)->regexps [i]
2684 = process_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
2687 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
2688 REGEXP_ALLOF (regexp)->regexps [i]
2689 = process_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
2692 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
2693 REGEXP_ONEOF (regexp)->regexps [i]
2694 = process_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
2697 REGEXP_REPEAT (regexp)->regexp
2698 = process_regexp (REGEXP_REPEAT (regexp)->regexp);
2708 /* The following function processes regexp of define_reservation and
2709 define_insn_reservation with the aid of function
2710 `process_regexp'. */
2712 process_regexp_decls (void)
2717 for (i = 0; i < description->decls_num; i++)
2719 decl = description->decls [i];
2720 if (decl->mode == dm_reserv)
2721 DECL_RESERV (decl)->regexp
2722 = process_regexp (DECL_RESERV (decl)->regexp);
2723 else if (decl->mode == dm_insn_reserv)
2724 DECL_INSN_RESERV (decl)->regexp
2725 = process_regexp (DECL_INSN_RESERV (decl)->regexp);
2729 /* The following function checks that declared unit is used. If the
2730 unit is not used, the function fixes errors/warnings. The
2731 following function must be called only after `process_decls',
2732 `process_regexp_decls'. */
2739 for (i = 0; i < description->decls_num; i++)
2741 decl = description->decls [i];
2742 if (decl->mode == dm_unit && !DECL_UNIT (decl)->unit_is_used)
2745 error ("unit `%s' is not used", DECL_UNIT (decl)->name);
2747 warning (0, "unit `%s' is not used", DECL_UNIT (decl)->name);
2749 else if (decl->mode == dm_reserv && !DECL_RESERV (decl)->reserv_is_used)
2752 error ("reservation `%s' is not used", DECL_RESERV (decl)->name);
2754 warning (0, "reservation `%s' is not used", DECL_RESERV (decl)->name);
2759 /* The following variable value is number of reservation being
2760 processed on loop recognition. */
2761 static int curr_loop_pass_num;
2763 /* The following recursive function returns nonzero value if REGEXP
2764 contains given decl or reservations in given regexp refers for
2767 loop_in_regexp (regexp_t regexp, decl_t start_decl)
2773 switch (regexp->mode)
2779 if (start_decl->mode == dm_reserv
2780 && REGEXP_RESERV (regexp)->reserv_decl == DECL_RESERV (start_decl))
2782 else if (REGEXP_RESERV (regexp)->reserv_decl->loop_pass_num
2783 == curr_loop_pass_num)
2784 /* declaration has been processed. */
2788 REGEXP_RESERV (regexp)->reserv_decl->loop_pass_num
2789 = curr_loop_pass_num;
2790 return loop_in_regexp (REGEXP_RESERV (regexp)->reserv_decl->regexp,
2795 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
2796 if (loop_in_regexp (REGEXP_SEQUENCE (regexp)->regexps [i], start_decl))
2801 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
2802 if (loop_in_regexp (REGEXP_ALLOF (regexp)->regexps [i], start_decl))
2807 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
2808 if (loop_in_regexp (REGEXP_ONEOF (regexp)->regexps [i], start_decl))
2813 return loop_in_regexp (REGEXP_REPEAT (regexp)->regexp, start_decl);
2823 /* The following function fixes errors "cycle in definition ...". The
2824 function uses function `loop_in_regexp' for that. */
2826 check_loops_in_regexps (void)
2831 for (i = 0; i < description->decls_num; i++)
2833 decl = description->decls [i];
2834 if (decl->mode == dm_reserv)
2835 DECL_RESERV (decl)->loop_pass_num = 0;
2837 for (i = 0; i < description->decls_num; i++)
2839 decl = description->decls [i];
2840 curr_loop_pass_num = i;
2842 if (decl->mode == dm_reserv)
2844 DECL_RESERV (decl)->loop_pass_num = curr_loop_pass_num;
2845 if (loop_in_regexp (DECL_RESERV (decl)->regexp, decl))
2847 gcc_assert (DECL_RESERV (decl)->regexp);
2848 error ("cycle in definition of reservation `%s'",
2849 DECL_RESERV (decl)->name);
2855 /* The function recursively processes IR of reservation and defines
2856 max and min cycle for reservation of unit. */
2858 process_regexp_cycles (regexp_t regexp, int max_start_cycle,
2859 int min_start_cycle, int *max_finish_cycle,
2860 int *min_finish_cycle)
2864 switch (regexp->mode)
2867 if (REGEXP_UNIT (regexp)->unit_decl->max_occ_cycle_num < max_start_cycle)
2868 REGEXP_UNIT (regexp)->unit_decl->max_occ_cycle_num = max_start_cycle;
2869 if (REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num > min_start_cycle
2870 || REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num == -1)
2871 REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num = min_start_cycle;
2872 *max_finish_cycle = max_start_cycle;
2873 *min_finish_cycle = min_start_cycle;
2877 process_regexp_cycles (REGEXP_RESERV (regexp)->reserv_decl->regexp,
2878 max_start_cycle, min_start_cycle,
2879 max_finish_cycle, min_finish_cycle);
2883 for (i = 0; i < REGEXP_REPEAT (regexp)->repeat_num; i++)
2885 process_regexp_cycles (REGEXP_REPEAT (regexp)->regexp,
2886 max_start_cycle, min_start_cycle,
2887 max_finish_cycle, min_finish_cycle);
2888 max_start_cycle = *max_finish_cycle + 1;
2889 min_start_cycle = *min_finish_cycle + 1;
2894 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
2896 process_regexp_cycles (REGEXP_SEQUENCE (regexp)->regexps [i],
2897 max_start_cycle, min_start_cycle,
2898 max_finish_cycle, min_finish_cycle);
2899 max_start_cycle = *max_finish_cycle + 1;
2900 min_start_cycle = *min_finish_cycle + 1;
2909 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
2911 process_regexp_cycles (REGEXP_ALLOF (regexp)->regexps [i],
2912 max_start_cycle, min_start_cycle,
2913 max_finish_cycle, min_finish_cycle);
2914 if (max_cycle < *max_finish_cycle)
2915 max_cycle = *max_finish_cycle;
2916 if (i == 0 || min_cycle > *min_finish_cycle)
2917 min_cycle = *min_finish_cycle;
2919 *max_finish_cycle = max_cycle;
2920 *min_finish_cycle = min_cycle;
2929 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
2931 process_regexp_cycles (REGEXP_ONEOF (regexp)->regexps [i],
2932 max_start_cycle, min_start_cycle,
2933 max_finish_cycle, min_finish_cycle);
2934 if (max_cycle < *max_finish_cycle)
2935 max_cycle = *max_finish_cycle;
2936 if (i == 0 || min_cycle > *min_finish_cycle)
2937 min_cycle = *min_finish_cycle;
2939 *max_finish_cycle = max_cycle;
2940 *min_finish_cycle = min_cycle;
2945 *max_finish_cycle = max_start_cycle;
2946 *min_finish_cycle = min_start_cycle;
2954 /* The following function is called only for correct program. The
2955 function defines max reservation of insns in cycles. */
2957 evaluate_max_reserv_cycles (void)
2959 int max_insn_cycles_num;
2960 int min_insn_cycles_num;
2964 description->max_insn_reserv_cycles = 0;
2965 for (i = 0; i < description->decls_num; i++)
2967 decl = description->decls [i];
2968 if (decl->mode == dm_insn_reserv)
2970 process_regexp_cycles (DECL_INSN_RESERV (decl)->regexp, 0, 0,
2971 &max_insn_cycles_num, &min_insn_cycles_num);
2972 if (description->max_insn_reserv_cycles < max_insn_cycles_num)
2973 description->max_insn_reserv_cycles = max_insn_cycles_num;
2976 description->max_insn_reserv_cycles++;
2979 /* The following function calls functions for checking all
2982 check_all_description (void)
2985 check_automaton_usage ();
2986 process_regexp_decls ();
2988 check_loops_in_regexps ();
2990 evaluate_max_reserv_cycles ();
2995 /* The page contains abstract data `ticker'. This data is used to
2996 report time of different phases of building automata. It is
2997 possibly to write a description for which automata will be built
2998 during several minutes even on fast machine. */
3000 /* The following function creates ticker and makes it active. */
3002 create_ticker (void)
3006 ticker.modified_creation_time = get_run_time ();
3007 ticker.incremented_off_time = 0;
3011 /* The following function switches off given ticker. */
3013 ticker_off (ticker_t *ticker)
3015 if (ticker->incremented_off_time == 0)
3016 ticker->incremented_off_time = get_run_time () + 1;
3019 /* The following function switches on given ticker. */
3021 ticker_on (ticker_t *ticker)
3023 if (ticker->incremented_off_time != 0)
3025 ticker->modified_creation_time
3026 += get_run_time () - ticker->incremented_off_time + 1;
3027 ticker->incremented_off_time = 0;
3031 /* The following function returns current time in milliseconds since
3032 the moment when given ticker was created. */
3034 active_time (ticker_t ticker)
3036 if (ticker.incremented_off_time != 0)
3037 return ticker.incremented_off_time - 1 - ticker.modified_creation_time;
3039 return get_run_time () - ticker.modified_creation_time;
3042 /* The following function returns string representation of active time
3043 of given ticker. The result is string representation of seconds
3044 with accuracy of 1/100 second. Only result of the last call of the
3045 function exists. Therefore the following code is not correct
3047 printf ("parser time: %s\ngeneration time: %s\n",
3048 active_time_string (parser_ticker),
3049 active_time_string (generation_ticker));
3051 Correct code has to be the following
3053 printf ("parser time: %s\n", active_time_string (parser_ticker));
3054 printf ("generation time: %s\n",
3055 active_time_string (generation_ticker));
3059 print_active_time (FILE *f, ticker_t ticker)
3063 msecs = active_time (ticker);
3064 fprintf (f, "%d.%06d", msecs / 1000000, msecs % 1000000);
3069 /* The following variable value is number of automaton which are
3070 really being created. This value is defined on the base of
3071 argument of option `-split'. If the variable has zero value the
3072 number of automata is defined by the constructions `%automaton'.
3073 This case occurs when option `-split' is absent or has zero
3074 argument. If constructions `define_automaton' is absent only one
3075 automaton is created. */
3076 static int automata_num;
3078 /* The following variable values are times of
3079 o transformation of regular expressions
3080 o building NDFA (DFA if !ndfa_flag)
3081 o NDFA -> DFA (simply the same automaton if !ndfa_flag)
3083 o building insn equivalence classes
3086 static ticker_t transform_time;
3087 static ticker_t NDFA_time;
3088 static ticker_t NDFA_to_DFA_time;
3089 static ticker_t minimize_time;
3090 static ticker_t equiv_time;
3091 static ticker_t automaton_generation_time;
3092 static ticker_t output_time;
3094 /* The following variable values are times of
3097 all pipeline hazard translator work */
3098 static ticker_t check_time;
3099 static ticker_t generation_time;
3100 static ticker_t all_time;
3104 /* Pseudo insn decl which denotes advancing cycle. */
3105 static decl_t advance_cycle_insn_decl;
3107 add_advance_cycle_insn_decl (void)
3109 advance_cycle_insn_decl = create_node (sizeof (struct decl));
3110 advance_cycle_insn_decl->mode = dm_insn_reserv;
3111 advance_cycle_insn_decl->pos = no_pos;
3112 DECL_INSN_RESERV (advance_cycle_insn_decl)->regexp = NULL;
3113 DECL_INSN_RESERV (advance_cycle_insn_decl)->name = "$advance_cycle";
3114 DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num
3115 = description->insns_num;
3116 description->decls [description->decls_num] = advance_cycle_insn_decl;
3117 description->decls_num++;
3118 description->insns_num++;
3122 /* Abstract data `alternative states' which represents
3123 nondeterministic nature of the description (see comments for
3124 structures alt_state and state). */
3126 /* List of free states. */
3127 static alt_state_t first_free_alt_state;
3130 /* The following variables is maximal number of allocated nodes
3132 static int allocated_alt_states_num = 0;
3135 /* The following function returns free node alt_state. It may be new
3136 allocated node or node freed earlier. */
3138 get_free_alt_state (void)
3142 if (first_free_alt_state != NULL)
3144 result = first_free_alt_state;
3145 first_free_alt_state = first_free_alt_state->next_alt_state;
3150 allocated_alt_states_num++;
3152 result = create_node (sizeof (struct alt_state));
3154 result->state = NULL;
3155 result->next_alt_state = NULL;
3156 result->next_sorted_alt_state = NULL;
3160 /* The function frees node ALT_STATE. */
3162 free_alt_state (alt_state_t alt_state)
3164 if (alt_state == NULL)
3166 alt_state->next_alt_state = first_free_alt_state;
3167 first_free_alt_state = alt_state;
3170 /* The function frees list started with node ALT_STATE_LIST. */
3172 free_alt_states (alt_state_t alt_states_list)
3174 alt_state_t curr_alt_state;
3175 alt_state_t next_alt_state;
3177 for (curr_alt_state = alt_states_list;
3178 curr_alt_state != NULL;
3179 curr_alt_state = next_alt_state)
3181 next_alt_state = curr_alt_state->next_alt_state;
3182 free_alt_state (curr_alt_state);
3186 /* The function compares unique numbers of alt states. */
3188 alt_state_cmp (const void *alt_state_ptr_1, const void *alt_state_ptr_2)
3190 if ((*(const alt_state_t *) alt_state_ptr_1)->state->unique_num
3191 == (*(const alt_state_t *) alt_state_ptr_2)->state->unique_num)
3193 else if ((*(const alt_state_t *) alt_state_ptr_1)->state->unique_num
3194 < (*(const alt_state_t *) alt_state_ptr_2)->state->unique_num)
3200 /* The function sorts ALT_STATES_LIST and removes duplicated alt
3201 states from the list. The comparison key is alt state unique
3205 uniq_sort_alt_states (alt_state_t alt_states_list)
3207 alt_state_t curr_alt_state;
3208 VEC(alt_state_t,heap) *alt_states;
3210 size_t prev_unique_state_ind;
3213 if (alt_states_list == 0)
3215 if (alt_states_list->next_alt_state == 0)
3216 return alt_states_list;
3218 alt_states = VEC_alloc (alt_state_t,heap, 150);
3219 for (curr_alt_state = alt_states_list;
3220 curr_alt_state != NULL;
3221 curr_alt_state = curr_alt_state->next_alt_state)
3222 VEC_safe_push (alt_state_t,heap, alt_states, curr_alt_state);
3224 qsort (VEC_address (alt_state_t, alt_states),
3225 VEC_length (alt_state_t, alt_states),
3226 sizeof (alt_state_t), alt_state_cmp);
3228 prev_unique_state_ind = 0;
3229 for (i = 1; i < VEC_length (alt_state_t, alt_states); i++)
3230 if (VEC_index (alt_state_t, alt_states, prev_unique_state_ind)->state
3231 != VEC_index (alt_state_t, alt_states, i)->state)
3233 prev_unique_state_ind++;
3234 VEC_replace (alt_state_t, alt_states, prev_unique_state_ind,
3235 VEC_index (alt_state_t, alt_states, i));
3237 VEC_truncate (alt_state_t, alt_states, prev_unique_state_ind + 1);
3239 for (i = 1; i < VEC_length (alt_state_t, alt_states); i++)
3240 VEC_index (alt_state_t, alt_states, i-1)->next_sorted_alt_state
3241 = VEC_index (alt_state_t, alt_states, i);
3242 VEC_last (alt_state_t, alt_states)->next_sorted_alt_state = 0;
3244 result = VEC_index (alt_state_t, alt_states, 0);
3246 VEC_free (alt_state_t,heap, alt_states);
3250 /* The function checks equality of alt state lists. Remember that the
3251 lists must be already sorted by the previous function. */
3253 alt_states_eq (alt_state_t alt_states_1, alt_state_t alt_states_2)
3255 while (alt_states_1 != NULL && alt_states_2 != NULL
3256 && alt_state_cmp (&alt_states_1, &alt_states_2) == 0)
3258 alt_states_1 = alt_states_1->next_sorted_alt_state;
3259 alt_states_2 = alt_states_2->next_sorted_alt_state;
3261 return alt_states_1 == alt_states_2;
3264 /* Initialization of the abstract data. */
3266 initiate_alt_states (void)
3268 first_free_alt_state = NULL;
3271 /* Finishing work with the abstract data. */
3273 finish_alt_states (void)
3279 /* The page contains macros for work with bits strings. We could use
3280 standard gcc bitmap or sbitmap but it would result in difficulties
3281 of building canadian cross. */
3283 /* Set bit number bitno in the bit string. The macro is not side
3285 #define SET_BIT(bitstring, bitno) \
3286 (((char *) (bitstring)) [(bitno) / CHAR_BIT] |= 1 << (bitno) % CHAR_BIT)
3288 #define CLEAR_BIT(bitstring, bitno) \
3289 (((char *) (bitstring)) [(bitno) / CHAR_BIT] &= ~(1 << (bitno) % CHAR_BIT))
3291 /* Test if bit number bitno in the bitstring is set. The macro is not
3292 side effect proof. */
3293 #define TEST_BIT(bitstring, bitno) \
3294 (((char *) (bitstring)) [(bitno) / CHAR_BIT] >> (bitno) % CHAR_BIT & 1)
3298 /* This page contains abstract data `state'. */
3300 /* Maximal length of reservations in cycles (>= 1). */
3301 static int max_cycles_num;
3303 /* Number of set elements (see type set_el_t) needed for
3304 representation of one cycle reservation. It is depended on units
3306 static int els_in_cycle_reserv;
3308 /* Number of set elements (see type set_el_t) needed for
3309 representation of maximal length reservation. Deterministic
3310 reservation is stored as set (bit string) of length equal to the
3311 variable value * number of bits in set_el_t. */
3312 static int els_in_reservs;
3314 /* Array of pointers to unit declarations. */
3315 static unit_decl_t *units_array;
3317 /* Temporary reservation of maximal length. */
3318 static reserv_sets_t temp_reserv;
3320 /* The state table itself is represented by the following variable. */
3321 static htab_t state_table;
3323 /* Linked list of free 'state' structures to be recycled. The
3324 next_equiv_class_state pointer is borrowed for a free list. */
3325 static state_t first_free_state;
3327 static int curr_unique_state_num;
3330 /* The following variables is maximal number of allocated nodes
3332 static int allocated_states_num = 0;
3335 /* Allocate new reservation set. */
3336 static reserv_sets_t
3337 alloc_empty_reserv_sets (void)
3339 reserv_sets_t result;
3341 obstack_blank (&irp, els_in_reservs * sizeof (set_el_t));
3342 result = (reserv_sets_t) obstack_base (&irp);
3343 obstack_finish (&irp);
3344 memset (result, 0, els_in_reservs * sizeof (set_el_t));
3348 /* Hash value of reservation set. */
3350 reserv_sets_hash_value (reserv_sets_t reservs)
3352 set_el_t hash_value;
3355 set_el_t *reserv_ptr;
3358 reservs_num = els_in_reservs;
3359 reserv_ptr = reservs;
3361 while (reservs_num != 0)
3364 hash_value += ((*reserv_ptr >> i)
3365 | (*reserv_ptr << (sizeof (set_el_t) * CHAR_BIT - i)));
3367 if (i == sizeof (set_el_t) * CHAR_BIT)
3371 if (sizeof (set_el_t) <= sizeof (unsigned))
3374 for (i = sizeof (set_el_t); i > 0; i -= sizeof (unsigned) - 1)
3376 result += (unsigned) hash_value;
3377 hash_value >>= (sizeof (unsigned) - 1) * CHAR_BIT;
3382 /* Comparison of given reservation sets. */
3384 reserv_sets_cmp (const_reserv_sets_t reservs_1, const_reserv_sets_t reservs_2)
3387 const set_el_t *reserv_ptr_1;
3388 const set_el_t *reserv_ptr_2;
3390 gcc_assert (reservs_1 && reservs_2);
3391 reservs_num = els_in_reservs;
3392 reserv_ptr_1 = reservs_1;
3393 reserv_ptr_2 = reservs_2;
3394 while (reservs_num != 0 && *reserv_ptr_1 == *reserv_ptr_2)
3400 if (reservs_num == 0)
3402 else if (*reserv_ptr_1 < *reserv_ptr_2)
3408 /* The function checks equality of the reservation sets. */
3410 reserv_sets_eq (const_reserv_sets_t reservs_1, const_reserv_sets_t reservs_2)
3412 return reserv_sets_cmp (reservs_1, reservs_2) == 0;
3415 /* Set up in the reservation set that unit with UNIT_NUM is used on
3418 set_unit_reserv (reserv_sets_t reservs, int cycle_num, int unit_num)
3420 gcc_assert (cycle_num < max_cycles_num);
3421 SET_BIT (reservs, cycle_num * els_in_cycle_reserv
3422 * sizeof (set_el_t) * CHAR_BIT + unit_num);
3425 /* Set up in the reservation set RESERVS that unit with UNIT_NUM is
3426 used on CYCLE_NUM. */
3428 test_unit_reserv (reserv_sets_t reservs, int cycle_num, int unit_num)
3430 gcc_assert (cycle_num < max_cycles_num);
3431 return TEST_BIT (reservs, cycle_num * els_in_cycle_reserv
3432 * sizeof (set_el_t) * CHAR_BIT + unit_num);
3435 /* The function checks that the reservation sets are intersected,
3436 i.e. there is a unit reservation on a cycle in both reservation
3439 reserv_sets_are_intersected (reserv_sets_t operand_1,
3440 reserv_sets_t operand_2)
3444 set_el_t *cycle_ptr_1;
3445 set_el_t *cycle_ptr_2;
3447 gcc_assert (operand_1 && operand_2);
3448 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2;
3449 el_ptr_1 < operand_1 + els_in_reservs;
3450 el_ptr_1++, el_ptr_2++)
3451 if (*el_ptr_1 & *el_ptr_2)
3453 reserv_sets_or (temp_reserv, operand_1, operand_2);
3454 for (cycle_ptr_1 = operand_1, cycle_ptr_2 = operand_2;
3455 cycle_ptr_1 < operand_1 + els_in_reservs;
3456 cycle_ptr_1 += els_in_cycle_reserv, cycle_ptr_2 += els_in_cycle_reserv)
3458 for (el_ptr_1 = cycle_ptr_1, el_ptr_2 = get_excl_set (cycle_ptr_2);
3459 el_ptr_1 < cycle_ptr_1 + els_in_cycle_reserv;
3460 el_ptr_1++, el_ptr_2++)
3461 if (*el_ptr_1 & *el_ptr_2)
3463 if (!check_presence_pattern_sets (cycle_ptr_1, cycle_ptr_2, FALSE))
3465 if (!check_presence_pattern_sets (temp_reserv + (cycle_ptr_2
3469 if (!check_absence_pattern_sets (cycle_ptr_1, cycle_ptr_2, FALSE))
3471 if (!check_absence_pattern_sets (temp_reserv + (cycle_ptr_2 - operand_2),
3478 /* The function sets up RESULT bits by bits of OPERAND shifted on one
3479 cpu cycle. The remaining bits of OPERAND (representing the last
3480 cycle unit reservations) are not changed. */
3482 reserv_sets_shift (reserv_sets_t result, reserv_sets_t operand)
3486 gcc_assert (result && operand && result != operand);
3487 for (i = els_in_cycle_reserv; i < els_in_reservs; i++)
3488 result [i - els_in_cycle_reserv] = operand [i];
3491 /* OR of the reservation sets. */
3493 reserv_sets_or (reserv_sets_t result, reserv_sets_t operand_1,
3494 reserv_sets_t operand_2)
3498 set_el_t *result_set_el_ptr;
3500 gcc_assert (result && operand_1 && operand_2);
3501 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2, result_set_el_ptr = result;
3502 el_ptr_1 < operand_1 + els_in_reservs;
3503 el_ptr_1++, el_ptr_2++, result_set_el_ptr++)
3504 *result_set_el_ptr = *el_ptr_1 | *el_ptr_2;
3507 /* AND of the reservation sets. */
3509 reserv_sets_and (reserv_sets_t result, reserv_sets_t operand_1,
3510 reserv_sets_t operand_2)
3514 set_el_t *result_set_el_ptr;
3516 gcc_assert (result && operand_1 && operand_2);
3517 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2, result_set_el_ptr = result;
3518 el_ptr_1 < operand_1 + els_in_reservs;
3519 el_ptr_1++, el_ptr_2++, result_set_el_ptr++)
3520 *result_set_el_ptr = *el_ptr_1 & *el_ptr_2;
3523 /* The function outputs string representation of units reservation on
3524 cycle START_CYCLE in the reservation set. The function uses repeat
3525 construction if REPETITION_NUM > 1. */
3527 output_cycle_reservs (FILE *f, reserv_sets_t reservs, int start_cycle,
3531 int reserved_units_num;
3533 reserved_units_num = 0;
3534 for (unit_num = 0; unit_num < description->units_num; unit_num++)
3535 if (TEST_BIT (reservs, start_cycle * els_in_cycle_reserv
3536 * sizeof (set_el_t) * CHAR_BIT + unit_num))
3537 reserved_units_num++;
3538 gcc_assert (repetition_num > 0);
3539 if (repetition_num != 1 && reserved_units_num > 1)
3541 reserved_units_num = 0;
3543 unit_num < description->units_num;
3545 if (TEST_BIT (reservs, start_cycle * els_in_cycle_reserv
3546 * sizeof (set_el_t) * CHAR_BIT + unit_num))
3548 if (reserved_units_num != 0)
3550 reserved_units_num++;
3551 fprintf (f, "%s", units_array [unit_num]->name);
3553 if (reserved_units_num == 0)
3554 fprintf (f, NOTHING_NAME);
3555 gcc_assert (repetition_num > 0);
3556 if (repetition_num != 1 && reserved_units_num > 1)
3558 if (repetition_num != 1)
3559 fprintf (f, "*%d", repetition_num);
3562 /* The function outputs string representation of units reservation in
3563 the reservation set. */
3565 output_reserv_sets (FILE *f, reserv_sets_t reservs)
3567 int start_cycle = 0;
3572 for (cycle = 0; cycle < max_cycles_num; cycle++)
3573 if (repetition_num == 0)
3576 start_cycle = cycle;
3579 ((char *) reservs + start_cycle * els_in_cycle_reserv
3580 * sizeof (set_el_t),
3581 (char *) reservs + cycle * els_in_cycle_reserv
3582 * sizeof (set_el_t),
3583 els_in_cycle_reserv * sizeof (set_el_t)) == 0)
3587 if (start_cycle != 0)
3589 output_cycle_reservs (f, reservs, start_cycle, repetition_num);
3591 start_cycle = cycle;
3593 if (start_cycle < max_cycles_num)
3595 if (start_cycle != 0)
3597 output_cycle_reservs (f, reservs, start_cycle, repetition_num);
3601 /* The following function returns free node state for AUTOMATON. It
3602 may be new allocated node or node freed earlier. The function also
3603 allocates reservation set if WITH_RESERVS has nonzero value. */
3605 get_free_state (int with_reservs, automaton_t automaton)
3609 gcc_assert (max_cycles_num > 0 && automaton);
3610 if (first_free_state)
3612 result = first_free_state;
3613 first_free_state = result->next_equiv_class_state;
3615 result->next_equiv_class_state = NULL;
3616 result->automaton = automaton;
3617 result->first_out_arc = NULL;
3618 result->it_was_placed_in_stack_for_NDFA_forming = 0;
3619 result->it_was_placed_in_stack_for_DFA_forming = 0;
3620 result->component_states = NULL;
3625 allocated_states_num++;
3627 result = create_node (sizeof (struct state));
3628 result->automaton = automaton;
3629 result->first_out_arc = NULL;
3630 result->unique_num = curr_unique_state_num;
3631 curr_unique_state_num++;
3635 if (result->reservs == NULL)
3636 result->reservs = alloc_empty_reserv_sets ();
3638 memset (result->reservs, 0, els_in_reservs * sizeof (set_el_t));
3643 /* The function frees node STATE. */
3645 free_state (state_t state)
3647 free_alt_states (state->component_states);
3648 state->next_equiv_class_state = first_free_state;
3649 first_free_state = state;
3652 /* Hash value of STATE. If STATE represents deterministic state it is
3653 simply hash value of the corresponding reservation set. Otherwise
3654 it is formed from hash values of the component deterministic
3655 states. One more key is order number of state automaton. */
3657 state_hash (const void *state)
3659 unsigned int hash_value;
3660 alt_state_t alt_state;
3662 if (((const_state_t) state)->component_states == NULL)
3663 hash_value = reserv_sets_hash_value (((const_state_t) state)->reservs);
3667 for (alt_state = ((const_state_t) state)->component_states;
3669 alt_state = alt_state->next_sorted_alt_state)
3670 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
3671 | (hash_value << CHAR_BIT))
3672 + alt_state->state->unique_num);
3674 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
3675 | (hash_value << CHAR_BIT))
3676 + ((const_state_t) state)->automaton->automaton_order_num);
3680 /* Return nonzero value if the states are the same. */
3682 state_eq_p (const void *state_1, const void *state_2)
3684 alt_state_t alt_state_1;
3685 alt_state_t alt_state_2;
3687 if (((const_state_t) state_1)->automaton != ((const_state_t) state_2)->automaton)
3689 else if (((const_state_t) state_1)->component_states == NULL
3690 && ((const_state_t) state_2)->component_states == NULL)
3691 return reserv_sets_eq (((const_state_t) state_1)->reservs,
3692 ((const_state_t) state_2)->reservs);
3693 else if (((const_state_t) state_1)->component_states != NULL
3694 && ((const_state_t) state_2)->component_states != NULL)
3696 for (alt_state_1 = ((const_state_t) state_1)->component_states,
3697 alt_state_2 = ((const_state_t) state_2)->component_states;
3698 alt_state_1 != NULL && alt_state_2 != NULL;
3699 alt_state_1 = alt_state_1->next_sorted_alt_state,
3700 alt_state_2 = alt_state_2->next_sorted_alt_state)
3701 /* All state in the list must be already in the hash table.
3702 Also the lists must be sorted. */
3703 if (alt_state_1->state != alt_state_2->state)
3705 return alt_state_1 == alt_state_2;
3711 /* Insert STATE into the state table. */
3713 insert_state (state_t state)
3717 entry_ptr = htab_find_slot (state_table, (void *) state, 1);
3718 if (*entry_ptr == NULL)
3719 *entry_ptr = (void *) state;
3720 return (state_t) *entry_ptr;
3723 /* Add reservation of unit with UNIT_NUM on cycle CYCLE_NUM to
3724 deterministic STATE. */
3726 set_state_reserv (state_t state, int cycle_num, int unit_num)
3728 set_unit_reserv (state->reservs, cycle_num, unit_num);
3731 /* Return nonzero value if the deterministic states contains a
3732 reservation of the same cpu unit on the same cpu cycle. */
3734 intersected_state_reservs_p (state_t state1, state_t state2)
3736 gcc_assert (state1->automaton == state2->automaton);
3737 return reserv_sets_are_intersected (state1->reservs, state2->reservs);
3740 /* Return deterministic state (inserted into the table) which
3741 representing the automaton state which is union of reservations of
3742 the deterministic states masked by RESERVS. */
3744 states_union (state_t state1, state_t state2, reserv_sets_t reservs)
3747 state_t state_in_table;
3749 gcc_assert (state1->automaton == state2->automaton);
3750 result = get_free_state (1, state1->automaton);
3751 reserv_sets_or (result->reservs, state1->reservs, state2->reservs);
3752 reserv_sets_and (result->reservs, result->reservs, reservs);
3753 state_in_table = insert_state (result);
3754 if (result != state_in_table)
3756 free_state (result);
3757 result = state_in_table;
3762 /* Return deterministic state (inserted into the table) which
3763 represent the automaton state is obtained from deterministic STATE
3764 by advancing cpu cycle and masking by RESERVS. */
3766 state_shift (state_t state, reserv_sets_t reservs)
3769 state_t state_in_table;
3771 result = get_free_state (1, state->automaton);
3772 reserv_sets_shift (result->reservs, state->reservs);
3773 reserv_sets_and (result->reservs, result->reservs, reservs);
3774 state_in_table = insert_state (result);
3775 if (result != state_in_table)
3777 free_state (result);
3778 result = state_in_table;
3783 /* Initialization of the abstract data. */
3785 initiate_states (void)
3790 if (description->units_num)
3791 units_array = XNEWVEC (unit_decl_t, description->units_num);
3795 for (i = 0; i < description->decls_num; i++)
3797 decl = description->decls [i];
3798 if (decl->mode == dm_unit)
3799 units_array [DECL_UNIT (decl)->unit_num] = DECL_UNIT (decl);
3801 max_cycles_num = description->max_insn_reserv_cycles;
3803 = ((description->units_num + sizeof (set_el_t) * CHAR_BIT - 1)
3804 / (sizeof (set_el_t) * CHAR_BIT));
3805 els_in_reservs = els_in_cycle_reserv * max_cycles_num;
3806 curr_unique_state_num = 0;
3807 initiate_alt_states ();
3808 state_table = htab_create (1500, state_hash, state_eq_p, (htab_del) 0);
3809 temp_reserv = alloc_empty_reserv_sets ();
3812 /* Finishing work with the abstract data. */
3814 finish_states (void)
3818 htab_delete (state_table);
3819 first_free_state = NULL;
3820 finish_alt_states ();
3825 /* Abstract data `arcs'. */
3827 /* List of free arcs. */
3828 static arc_t first_free_arc;
3831 /* The following variables is maximal number of allocated nodes
3833 static int allocated_arcs_num = 0;
3836 /* The function frees node ARC. */
3838 free_arc (arc_t arc)
3840 arc->next_out_arc = first_free_arc;
3841 first_free_arc = arc;
3844 /* The function removes and frees ARC staring from FROM_STATE. */
3846 remove_arc (state_t from_state, arc_t arc)
3852 for (prev_arc = NULL, curr_arc = from_state->first_out_arc;
3854 prev_arc = curr_arc, curr_arc = curr_arc->next_out_arc)
3855 if (curr_arc == arc)
3857 gcc_assert (curr_arc);
3858 if (prev_arc == NULL)
3859 from_state->first_out_arc = arc->next_out_arc;
3861 prev_arc->next_out_arc = arc->next_out_arc;
3862 from_state->num_out_arcs--;
3866 /* The functions returns arc with given characteristics (or NULL if
3867 the arc does not exist). */
3869 find_arc (state_t from_state, state_t to_state, ainsn_t insn)
3873 for (arc = first_out_arc (from_state); arc != NULL; arc = next_out_arc (arc))
3874 if (arc->to_state == to_state && arc->insn == insn)
3879 /* The function adds arc from FROM_STATE to TO_STATE marked by AINSN.
3880 The function returns added arc (or already existing arc). */
3882 add_arc (state_t from_state, state_t to_state, ainsn_t ainsn)
3886 new_arc = find_arc (from_state, to_state, ainsn);
3887 if (new_arc != NULL)
3889 if (first_free_arc == NULL)
3892 allocated_arcs_num++;
3894 new_arc = create_node (sizeof (struct arc));
3895 new_arc->to_state = NULL;
3896 new_arc->insn = NULL;
3897 new_arc->next_out_arc = NULL;
3901 new_arc = first_free_arc;
3902 first_free_arc = first_free_arc->next_out_arc;
3904 new_arc->to_state = to_state;
3905 new_arc->insn = ainsn;
3906 ainsn->arc_exists_p = 1;
3907 new_arc->next_out_arc = from_state->first_out_arc;
3908 from_state->first_out_arc = new_arc;
3909 from_state->num_out_arcs++;
3910 new_arc->next_arc_marked_by_insn = NULL;
3914 /* The function returns the first arc starting from STATE. */
3916 first_out_arc (const_state_t state)
3918 return state->first_out_arc;
3921 /* The function returns next out arc after ARC. */
3923 next_out_arc (arc_t arc)
3925 return arc->next_out_arc;
3928 /* Initialization of the abstract data. */
3930 initiate_arcs (void)
3932 first_free_arc = NULL;
3935 /* Finishing work with the abstract data. */
3943 /* Abstract data `automata lists'. */
3945 /* List of free states. */
3946 static automata_list_el_t first_free_automata_list_el;
3948 /* The list being formed. */
3949 static automata_list_el_t current_automata_list;
3951 /* Hash table of automata lists. */
3952 static htab_t automata_list_table;
3954 /* The following function returns free automata list el. It may be
3955 new allocated node or node freed earlier. */
3956 static automata_list_el_t
3957 get_free_automata_list_el (void)
3959 automata_list_el_t result;
3961 if (first_free_automata_list_el != NULL)
3963 result = first_free_automata_list_el;
3964 first_free_automata_list_el
3965 = first_free_automata_list_el->next_automata_list_el;
3968 result = create_node (sizeof (struct automata_list_el));
3969 result->automaton = NULL;
3970 result->next_automata_list_el = NULL;
3974 /* The function frees node AUTOMATA_LIST_EL. */
3976 free_automata_list_el (automata_list_el_t automata_list_el)
3978 if (automata_list_el == NULL)
3980 automata_list_el->next_automata_list_el = first_free_automata_list_el;
3981 first_free_automata_list_el = automata_list_el;
3984 /* The function frees list AUTOMATA_LIST. */
3986 free_automata_list (automata_list_el_t automata_list)
3988 automata_list_el_t curr_automata_list_el;
3989 automata_list_el_t next_automata_list_el;
3991 for (curr_automata_list_el = automata_list;
3992 curr_automata_list_el != NULL;
3993 curr_automata_list_el = next_automata_list_el)
3995 next_automata_list_el = curr_automata_list_el->next_automata_list_el;
3996 free_automata_list_el (curr_automata_list_el);
4000 /* Hash value of AUTOMATA_LIST. */
4002 automata_list_hash (const void *automata_list)
4004 unsigned int hash_value;
4005 const_automata_list_el_t curr_automata_list_el;
4008 for (curr_automata_list_el = (const_automata_list_el_t) automata_list;
4009 curr_automata_list_el != NULL;
4010 curr_automata_list_el = curr_automata_list_el->next_automata_list_el)
4011 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
4012 | (hash_value << CHAR_BIT))
4013 + curr_automata_list_el->automaton->automaton_order_num);
4017 /* Return nonzero value if the automata_lists are the same. */
4019 automata_list_eq_p (const void *automata_list_1, const void *automata_list_2)
4021 const_automata_list_el_t automata_list_el_1;
4022 const_automata_list_el_t automata_list_el_2;
4024 for (automata_list_el_1 = (const_automata_list_el_t) automata_list_1,
4025 automata_list_el_2 = (const_automata_list_el_t) automata_list_2;
4026 automata_list_el_1 != NULL && automata_list_el_2 != NULL;
4027 automata_list_el_1 = automata_list_el_1->next_automata_list_el,
4028 automata_list_el_2 = automata_list_el_2->next_automata_list_el)
4029 if (automata_list_el_1->automaton != automata_list_el_2->automaton)
4031 return automata_list_el_1 == automata_list_el_2;
4034 /* Initialization of the abstract data. */
4036 initiate_automata_lists (void)
4038 first_free_automata_list_el = NULL;
4039 automata_list_table = htab_create (1500, automata_list_hash,
4040 automata_list_eq_p, (htab_del) 0);
4043 /* The following function starts new automata list and makes it the
4046 automata_list_start (void)
4048 current_automata_list = NULL;
4051 /* The following function adds AUTOMATON to the current list. */
4053 automata_list_add (automaton_t automaton)
4055 automata_list_el_t el;
4057 el = get_free_automata_list_el ();
4058 el->automaton = automaton;
4059 el->next_automata_list_el = current_automata_list;
4060 current_automata_list = el;
4063 /* The following function finishes forming the current list, inserts
4064 it into the table and returns it. */
4065 static automata_list_el_t
4066 automata_list_finish (void)
4070 if (current_automata_list == NULL)
4072 entry_ptr = htab_find_slot (automata_list_table,
4073 (void *) current_automata_list, 1);
4074 if (*entry_ptr == NULL)
4075 *entry_ptr = (void *) current_automata_list;
4077 free_automata_list (current_automata_list);
4078 current_automata_list = NULL;
4079 return (automata_list_el_t) *entry_ptr;
4082 /* Finishing work with the abstract data. */
4084 finish_automata_lists (void)
4086 htab_delete (automata_list_table);
4091 /* The page contains abstract data for work with exclusion sets (see
4092 exclusion_set in file rtl.def). */
4094 /* The following variable refers to an exclusion set returned by
4095 get_excl_set. This is bit string of length equal to cpu units
4096 number. If exclusion set for given unit contains 1 for a unit,
4097 then simultaneous reservation of the units is prohibited. */
4098 static reserv_sets_t excl_set;
4100 /* The array contains exclusion sets for each unit. */
4101 static reserv_sets_t *unit_excl_set_table;
4103 /* The following function forms the array containing exclusion sets
4106 initiate_excl_sets (void)
4109 reserv_sets_t unit_excl_set;
4113 obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4114 excl_set = (reserv_sets_t) obstack_base (&irp);
4115 obstack_finish (&irp);
4116 obstack_blank (&irp, description->units_num * sizeof (reserv_sets_t));
4117 unit_excl_set_table = (reserv_sets_t *) obstack_base (&irp);
4118 obstack_finish (&irp);
4119 /* Evaluate unit exclusion sets. */
4120 for (i = 0; i < description->decls_num; i++)
4122 decl = description->decls [i];
4123 if (decl->mode == dm_unit)
4125 obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4126 unit_excl_set = (reserv_sets_t) obstack_base (&irp);
4127 obstack_finish (&irp);
4128 memset (unit_excl_set, 0, els_in_cycle_reserv * sizeof (set_el_t));
4129 for (el = DECL_UNIT (decl)->excl_list;
4131 el = el->next_unit_set_el)
4133 SET_BIT (unit_excl_set, el->unit_decl->unit_num);
4134 el->unit_decl->in_set_p = TRUE;
4136 unit_excl_set_table [DECL_UNIT (decl)->unit_num] = unit_excl_set;
4141 /* The function sets up and return EXCL_SET which is union of
4142 exclusion sets for each unit in IN_SET. */
4143 static reserv_sets_t
4144 get_excl_set (reserv_sets_t in_set)
4152 chars_num = els_in_cycle_reserv * sizeof (set_el_t);
4153 memset (excl_set, 0, chars_num);
4154 for (excl_char_num = 0; excl_char_num < chars_num; excl_char_num++)
4155 if (((unsigned char *) in_set) [excl_char_num])
4156 for (i = CHAR_BIT - 1; i >= 0; i--)
4157 if ((((unsigned char *) in_set) [excl_char_num] >> i) & 1)
4159 start_unit_num = excl_char_num * CHAR_BIT + i;
4160 if (start_unit_num >= description->units_num)
4162 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4165 |= unit_excl_set_table [start_unit_num] [unit_num];
4173 /* The page contains abstract data for work with presence/absence
4174 pattern sets (see presence_set/absence_set in file rtl.def). */
4176 /* The following arrays contain correspondingly presence, final
4177 presence, absence, and final absence patterns for each unit. */
4178 static pattern_reserv_t *unit_presence_set_table;
4179 static pattern_reserv_t *unit_final_presence_set_table;
4180 static pattern_reserv_t *unit_absence_set_table;
4181 static pattern_reserv_t *unit_final_absence_set_table;
4183 /* The following function forms list of reservation sets for given
4185 static pattern_reserv_t
4186 form_reserv_sets_list (pattern_set_el_t pattern_list)
4188 pattern_set_el_t el;
4189 pattern_reserv_t first, curr, prev;
4192 prev = first = NULL;
4193 for (el = pattern_list; el != NULL; el = el->next_pattern_set_el)
4195 curr = create_node (sizeof (struct pattern_reserv));
4196 curr->reserv = alloc_empty_reserv_sets ();
4197 curr->next_pattern_reserv = NULL;
4198 for (i = 0; i < el->units_num; i++)
4200 SET_BIT (curr->reserv, el->unit_decls [i]->unit_num);
4201 el->unit_decls [i]->in_set_p = TRUE;
4204 prev->next_pattern_reserv = curr;
4212 /* The following function forms the array containing presence and
4213 absence pattern sets for each unit. */
4215 initiate_presence_absence_pattern_sets (void)
4220 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4221 unit_presence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4222 obstack_finish (&irp);
4223 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4224 unit_final_presence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4225 obstack_finish (&irp);
4226 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4227 unit_absence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4228 obstack_finish (&irp);
4229 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4230 unit_final_absence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4231 obstack_finish (&irp);
4232 /* Evaluate unit presence/absence sets. */
4233 for (i = 0; i < description->decls_num; i++)
4235 decl = description->decls [i];
4236 if (decl->mode == dm_unit)
4238 unit_presence_set_table [DECL_UNIT (decl)->unit_num]
4239 = form_reserv_sets_list (DECL_UNIT (decl)->presence_list);
4240 unit_final_presence_set_table [DECL_UNIT (decl)->unit_num]
4241 = form_reserv_sets_list (DECL_UNIT (decl)->final_presence_list);
4242 unit_absence_set_table [DECL_UNIT (decl)->unit_num]
4243 = form_reserv_sets_list (DECL_UNIT (decl)->absence_list);
4244 unit_final_absence_set_table [DECL_UNIT (decl)->unit_num]
4245 = form_reserv_sets_list (DECL_UNIT (decl)->final_absence_list);
4250 /* The function checks that CHECKED_SET satisfies all presence pattern
4251 sets for units in ORIGIONAL_SET. The function returns TRUE if it
4254 check_presence_pattern_sets (reserv_sets_t checked_set,
4255 reserv_sets_t origional_set,
4264 pattern_reserv_t pat_reserv;
4266 chars_num = els_in_cycle_reserv * sizeof (set_el_t);
4267 for (char_num = 0; char_num < chars_num; char_num++)
4268 if (((unsigned char *) origional_set) [char_num])
4269 for (i = CHAR_BIT - 1; i >= 0; i--)
4270 if ((((unsigned char *) origional_set) [char_num] >> i) & 1)
4272 start_unit_num = char_num * CHAR_BIT + i;
4273 if (start_unit_num >= description->units_num)
4276 && unit_final_presence_set_table [start_unit_num] == NULL)
4278 && unit_presence_set_table [start_unit_num] == NULL))
4281 for (pat_reserv = (final_p
4282 ? unit_final_presence_set_table [start_unit_num]
4283 : unit_presence_set_table [start_unit_num]);
4285 pat_reserv = pat_reserv->next_pattern_reserv)
4287 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4288 if ((checked_set [unit_num] & pat_reserv->reserv [unit_num])
4289 != pat_reserv->reserv [unit_num])
4291 presence_p = presence_p || unit_num >= els_in_cycle_reserv;
4299 /* The function checks that CHECKED_SET satisfies all absence pattern
4300 sets for units in ORIGIONAL_SET. The function returns TRUE if it
4303 check_absence_pattern_sets (reserv_sets_t checked_set,
4304 reserv_sets_t origional_set,
4312 pattern_reserv_t pat_reserv;
4314 chars_num = els_in_cycle_reserv * sizeof (set_el_t);
4315 for (char_num = 0; char_num < chars_num; char_num++)
4316 if (((unsigned char *) origional_set) [char_num])
4317 for (i = CHAR_BIT - 1; i >= 0; i--)
4318 if ((((unsigned char *) origional_set) [char_num] >> i) & 1)
4320 start_unit_num = char_num * CHAR_BIT + i;
4321 if (start_unit_num >= description->units_num)
4323 for (pat_reserv = (final_p
4324 ? unit_final_absence_set_table [start_unit_num]
4325 : unit_absence_set_table [start_unit_num]);
4327 pat_reserv = pat_reserv->next_pattern_reserv)
4329 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4330 if ((checked_set [unit_num] & pat_reserv->reserv [unit_num])
4331 != pat_reserv->reserv [unit_num]
4332 && pat_reserv->reserv [unit_num])
4334 if (unit_num >= els_in_cycle_reserv)
4343 /* This page contains code for transformation of original reservations
4344 described in .md file. The main goal of transformations is
4345 simplifying reservation and lifting up all `|' on the top of IR
4346 reservation representation. */
4349 /* The following function makes copy of IR representation of
4350 reservation. The function also substitutes all reservations
4351 defined by define_reservation by corresponding value during making
4354 copy_insn_regexp (regexp_t regexp)
4359 switch (regexp->mode)
4362 result = copy_insn_regexp (REGEXP_RESERV (regexp)->reserv_decl->regexp);
4366 result = copy_node (regexp, sizeof (struct regexp));
4370 result = copy_node (regexp, sizeof (struct regexp));
4371 REGEXP_REPEAT (result)->regexp
4372 = copy_insn_regexp (REGEXP_REPEAT (regexp)->regexp);
4376 result = copy_node (regexp,
4377 sizeof (struct regexp) + sizeof (regexp_t)
4378 * (REGEXP_SEQUENCE (regexp)->regexps_num - 1));
4379 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4380 REGEXP_SEQUENCE (result)->regexps [i]
4381 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4385 result = copy_node (regexp,
4386 sizeof (struct regexp) + sizeof (regexp_t)
4387 * (REGEXP_ALLOF (regexp)->regexps_num - 1));
4388 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4389 REGEXP_ALLOF (result)->regexps [i]
4390 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4394 result = copy_node (regexp,
4395 sizeof (struct regexp) + sizeof (regexp_t)
4396 * (REGEXP_ONEOF (regexp)->regexps_num - 1));
4397 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4398 REGEXP_ONEOF (result)->regexps [i]
4399 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4403 result = copy_node (regexp, sizeof (struct regexp));
4412 /* The following variable is set up 1 if a transformation has been
4414 static int regexp_transformed_p;
4416 /* The function makes transformation
4419 transform_1 (regexp_t regexp)
4426 if (regexp->mode == rm_repeat)
4428 repeat_num = REGEXP_REPEAT (regexp)->repeat_num;
4429 gcc_assert (repeat_num > 1);
4430 operand = REGEXP_REPEAT (regexp)->regexp;
4432 regexp = create_node (sizeof (struct regexp) + sizeof (regexp_t)
4433 * (repeat_num - 1));
4434 regexp->mode = rm_sequence;
4436 REGEXP_SEQUENCE (regexp)->regexps_num = repeat_num;
4437 for (i = 0; i < repeat_num; i++)
4438 REGEXP_SEQUENCE (regexp)->regexps [i] = copy_insn_regexp (operand);
4439 regexp_transformed_p = 1;
4444 /* The function makes transformations
4445 ...,(A,B,...),C,... -> ...,A,B,...,C,...
4446 ...+(A+B+...)+C+... -> ...+A+B+...+C+...
4447 ...|(A|B|...)|C|... -> ...|A|B|...|C|... */
4449 transform_2 (regexp_t regexp)
4451 if (regexp->mode == rm_sequence)
4453 regexp_t sequence = NULL;
4455 int sequence_index = 0;
4458 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4459 if (REGEXP_SEQUENCE (regexp)->regexps [i]->mode == rm_sequence)
4462 sequence = REGEXP_SEQUENCE (regexp)->regexps [i];
4465 if (i < REGEXP_SEQUENCE (regexp)->regexps_num)
4467 gcc_assert (REGEXP_SEQUENCE (sequence)->regexps_num > 1
4468 && REGEXP_SEQUENCE (regexp)->regexps_num > 1);
4469 result = create_node (sizeof (struct regexp)
4471 * (REGEXP_SEQUENCE (regexp)->regexps_num
4472 + REGEXP_SEQUENCE (sequence)->regexps_num
4474 result->mode = rm_sequence;
4475 result->pos = regexp->pos;
4476 REGEXP_SEQUENCE (result)->regexps_num
4477 = (REGEXP_SEQUENCE (regexp)->regexps_num
4478 + REGEXP_SEQUENCE (sequence)->regexps_num - 1);
4479 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4480 if (i < sequence_index)
4481 REGEXP_SEQUENCE (result)->regexps [i]
4482 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4483 else if (i > sequence_index)
4484 REGEXP_SEQUENCE (result)->regexps
4485 [i + REGEXP_SEQUENCE (sequence)->regexps_num - 1]
4486 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4488 for (j = 0; j < REGEXP_SEQUENCE (sequence)->regexps_num; j++)
4489 REGEXP_SEQUENCE (result)->regexps [i + j]
4490 = copy_insn_regexp (REGEXP_SEQUENCE (sequence)->regexps [j]);
4491 regexp_transformed_p = 1;
4495 else if (regexp->mode == rm_allof)
4497 regexp_t allof = NULL;
4499 int allof_index = 0;
4502 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4503 if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_allof)
4506 allof = REGEXP_ALLOF (regexp)->regexps [i];
4509 if (i < REGEXP_ALLOF (regexp)->regexps_num)
4511 gcc_assert (REGEXP_ALLOF (allof)->regexps_num > 1
4512 && REGEXP_ALLOF (regexp)->regexps_num > 1);
4513 result = create_node (sizeof (struct regexp)
4515 * (REGEXP_ALLOF (regexp)->regexps_num
4516 + REGEXP_ALLOF (allof)->regexps_num - 2));
4517 result->mode = rm_allof;
4518 result->pos = regexp->pos;
4519 REGEXP_ALLOF (result)->regexps_num
4520 = (REGEXP_ALLOF (regexp)->regexps_num
4521 + REGEXP_ALLOF (allof)->regexps_num - 1);
4522 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4523 if (i < allof_index)
4524 REGEXP_ALLOF (result)->regexps [i]
4525 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4526 else if (i > allof_index)
4527 REGEXP_ALLOF (result)->regexps
4528 [i + REGEXP_ALLOF (allof)->regexps_num - 1]
4529 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4531 for (j = 0; j < REGEXP_ALLOF (allof)->regexps_num; j++)
4532 REGEXP_ALLOF (result)->regexps [i + j]
4533 = copy_insn_regexp (REGEXP_ALLOF (allof)->regexps [j]);
4534 regexp_transformed_p = 1;
4538 else if (regexp->mode == rm_oneof)
4540 regexp_t oneof = NULL;
4542 int oneof_index = 0;
4545 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4546 if (REGEXP_ONEOF (regexp)->regexps [i]->mode == rm_oneof)
4549 oneof = REGEXP_ONEOF (regexp)->regexps [i];
4552 if (i < REGEXP_ONEOF (regexp)->regexps_num)
4554 gcc_assert (REGEXP_ONEOF (oneof)->regexps_num > 1
4555 && REGEXP_ONEOF (regexp)->regexps_num > 1);
4556 result = create_node (sizeof (struct regexp)
4558 * (REGEXP_ONEOF (regexp)->regexps_num
4559 + REGEXP_ONEOF (oneof)->regexps_num - 2));
4560 result->mode = rm_oneof;
4561 result->pos = regexp->pos;
4562 REGEXP_ONEOF (result)->regexps_num
4563 = (REGEXP_ONEOF (regexp)->regexps_num
4564 + REGEXP_ONEOF (oneof)->regexps_num - 1);
4565 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4566 if (i < oneof_index)
4567 REGEXP_ONEOF (result)->regexps [i]
4568 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4569 else if (i > oneof_index)
4570 REGEXP_ONEOF (result)->regexps
4571 [i + REGEXP_ONEOF (oneof)->regexps_num - 1]
4572 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4574 for (j = 0; j < REGEXP_ONEOF (oneof)->regexps_num; j++)
4575 REGEXP_ONEOF (result)->regexps [i + j]
4576 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [j]);
4577 regexp_transformed_p = 1;
4584 /* The function makes transformations
4585 ...,A|B|...,C,... -> (...,A,C,...)|(...,B,C,...)|...
4586 ...+(A|B|...)+C+... -> (...+A+C+...)|(...+B+C+...)|...
4587 ...+(A,B,...)+C+... -> (...+A+C+...),B,...
4588 ...+(A,B,...)+(C,D,...) -> (A+C),(B+D),... */
4590 transform_3 (regexp_t regexp)
4592 if (regexp->mode == rm_sequence)
4594 regexp_t oneof = NULL;
4595 int oneof_index = 0;
4600 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4601 if (REGEXP_SEQUENCE (regexp)->regexps [i]->mode == rm_oneof)
4604 oneof = REGEXP_SEQUENCE (regexp)->regexps [i];
4607 if (i < REGEXP_SEQUENCE (regexp)->regexps_num)
4609 gcc_assert (REGEXP_ONEOF (oneof)->regexps_num > 1
4610 && REGEXP_SEQUENCE (regexp)->regexps_num > 1);
4611 result = create_node (sizeof (struct regexp)
4613 * (REGEXP_ONEOF (oneof)->regexps_num - 1));
4614 result->mode = rm_oneof;
4615 result->pos = regexp->pos;
4616 REGEXP_ONEOF (result)->regexps_num
4617 = REGEXP_ONEOF (oneof)->regexps_num;
4618 for (i = 0; i < REGEXP_ONEOF (result)->regexps_num; i++)
4621 = create_node (sizeof (struct regexp)
4623 * (REGEXP_SEQUENCE (regexp)->regexps_num - 1));
4624 sequence->mode = rm_sequence;
4625 sequence->pos = regexp->pos;
4626 REGEXP_SEQUENCE (sequence)->regexps_num
4627 = REGEXP_SEQUENCE (regexp)->regexps_num;
4628 REGEXP_ONEOF (result)->regexps [i] = sequence;
4629 for (j = 0; j < REGEXP_SEQUENCE (sequence)->regexps_num; j++)
4630 if (j != oneof_index)
4631 REGEXP_SEQUENCE (sequence)->regexps [j]
4632 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [j]);
4634 REGEXP_SEQUENCE (sequence)->regexps [j]
4635 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [i]);
4637 regexp_transformed_p = 1;
4641 else if (regexp->mode == rm_allof)
4643 regexp_t oneof = NULL;
4645 int oneof_index = 0;
4646 int max_seq_length, allof_length;
4648 regexp_t allof = NULL;
4649 regexp_t allof_op = NULL;
4652 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4653 if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_oneof)
4656 oneof = REGEXP_ALLOF (regexp)->regexps [i];
4659 if (i < REGEXP_ALLOF (regexp)->regexps_num)
4661 gcc_assert (REGEXP_ONEOF (oneof)->regexps_num > 1
4662 && REGEXP_ALLOF (regexp)->regexps_num > 1);
4663 result = create_node (sizeof (struct regexp)
4665 * (REGEXP_ONEOF (oneof)->regexps_num - 1));
4666 result->mode = rm_oneof;
4667 result->pos = regexp->pos;
4668 REGEXP_ONEOF (result)->regexps_num
4669 = REGEXP_ONEOF (oneof)->regexps_num;
4670 for (i = 0; i < REGEXP_ONEOF (result)->regexps_num; i++)
4673 = create_node (sizeof (struct regexp)
4675 * (REGEXP_ALLOF (regexp)->regexps_num - 1));
4676 allof->mode = rm_allof;
4677 allof->pos = regexp->pos;
4678 REGEXP_ALLOF (allof)->regexps_num
4679 = REGEXP_ALLOF (regexp)->regexps_num;
4680 REGEXP_ONEOF (result)->regexps [i] = allof;
4681 for (j = 0; j < REGEXP_ALLOF (allof)->regexps_num; j++)
4682 if (j != oneof_index)
4683 REGEXP_ALLOF (allof)->regexps [j]
4684 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [j]);
4686 REGEXP_ALLOF (allof)->regexps [j]
4687 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [i]);
4689 regexp_transformed_p = 1;
4693 if (regexp->mode == rm_allof)
4694 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4696 switch (REGEXP_ALLOF (regexp)->regexps [i]->mode)
4699 seq = REGEXP_ALLOF (regexp)->regexps [i];
4700 if (max_seq_length < REGEXP_SEQUENCE (seq)->regexps_num)
4701 max_seq_length = REGEXP_SEQUENCE (seq)->regexps_num;
4714 if (max_seq_length != 0)
4716 gcc_assert (max_seq_length != 1
4717 && REGEXP_ALLOF (regexp)->regexps_num > 1);
4718 result = create_node (sizeof (struct regexp)
4719 + sizeof (regexp_t) * (max_seq_length - 1));
4720 result->mode = rm_sequence;
4721 result->pos = regexp->pos;
4722 REGEXP_SEQUENCE (result)->regexps_num = max_seq_length;
4723 for (i = 0; i < max_seq_length; i++)
4726 for (j = 0; j < REGEXP_ALLOF (regexp)->regexps_num; j++)
4727 switch (REGEXP_ALLOF (regexp)->regexps [j]->mode)
4730 if (i < (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4731 ->regexps [j])->regexps_num))
4734 = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4744 allof_op = REGEXP_ALLOF (regexp)->regexps [j];
4752 if (allof_length == 1)
4753 REGEXP_SEQUENCE (result)->regexps [i] = allof_op;
4756 allof = create_node (sizeof (struct regexp)
4758 * (allof_length - 1));
4759 allof->mode = rm_allof;
4760 allof->pos = regexp->pos;
4761 REGEXP_ALLOF (allof)->regexps_num = allof_length;
4762 REGEXP_SEQUENCE (result)->regexps [i] = allof;
4764 for (j = 0; j < REGEXP_ALLOF (regexp)->regexps_num; j++)
4765 if (REGEXP_ALLOF (regexp)->regexps [j]->mode == rm_sequence
4767 (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4768 ->regexps [j])->regexps_num)))
4770 allof_op = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4773 REGEXP_ALLOF (allof)->regexps [allof_length]
4778 && (REGEXP_ALLOF (regexp)->regexps [j]->mode
4780 || (REGEXP_ALLOF (regexp)->regexps [j]->mode
4783 allof_op = REGEXP_ALLOF (regexp)->regexps [j];
4784 REGEXP_ALLOF (allof)->regexps [allof_length]
4790 regexp_transformed_p = 1;
4797 /* The function traverses IR of reservation and applies transformations
4798 implemented by FUNC. */
4800 regexp_transform_func (regexp_t regexp, regexp_t (*func) (regexp_t regexp))
4804 switch (regexp->mode)
4807 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4808 REGEXP_SEQUENCE (regexp)->regexps [i]
4809 = regexp_transform_func (REGEXP_SEQUENCE (regexp)->regexps [i],
4814 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4815 REGEXP_ALLOF (regexp)->regexps [i]
4816 = regexp_transform_func (REGEXP_ALLOF (regexp)->regexps [i], func);
4820 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4821 REGEXP_ONEOF (regexp)->regexps [i]
4822 = regexp_transform_func (REGEXP_ONEOF (regexp)->regexps [i], func);
4826 REGEXP_REPEAT (regexp)->regexp
4827 = regexp_transform_func (REGEXP_REPEAT (regexp)->regexp, func);
4837 return (*func) (regexp);
4840 /* The function applies all transformations for IR representation of
4841 reservation REGEXP. */
4843 transform_regexp (regexp_t regexp)
4845 regexp = regexp_transform_func (regexp, transform_1);
4848 regexp_transformed_p = 0;
4849 regexp = regexp_transform_func (regexp, transform_2);
4850 regexp = regexp_transform_func (regexp, transform_3);
4852 while (regexp_transformed_p);
4856 /* The function applies all transformations for reservations of all
4857 insn declarations. */
4859 transform_insn_regexps (void)
4864 transform_time = create_ticker ();
4865 add_advance_cycle_insn_decl ();
4867 fprintf (stderr, "Reservation transformation...");
4868 for (i = 0; i < description->decls_num; i++)
4870 decl = description->decls [i];
4871 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
4872 DECL_INSN_RESERV (decl)->transformed_regexp
4873 = transform_regexp (copy_insn_regexp
4874 (DECL_INSN_RESERV (decl)->regexp));
4877 fprintf (stderr, "done\n");
4878 ticker_off (&transform_time);
4883 /* The following variable value is TRUE if the first annotated message
4884 about units to automata distribution has been output. */
4885 static int annotation_message_reported_p;
4887 /* The following structure describes usage of a unit in a reservation. */
4890 unit_decl_t unit_decl;
4891 /* The following forms a list of units used on the same cycle in the
4892 same alternative. */
4893 struct unit_usage *next;
4895 typedef struct unit_usage *unit_usage_t;
4897 DEF_VEC_P(unit_usage_t);
4898 DEF_VEC_ALLOC_P(unit_usage_t,heap);
4900 /* Obstack for unit_usage structures. */
4901 static struct obstack unit_usages;
4903 /* VLA for representation of array of pointers to unit usage
4904 structures. There is an element for each combination of
4905 (alternative number, cycle). Unit usages on given cycle in
4906 alternative with given number are referred through element with
4907 index equals to the cycle * number of all alternatives in the regexp
4908 + the alternative number. */
4909 static VEC(unit_usage_t,heap) *cycle_alt_unit_usages;
4911 /* The following function creates the structure unit_usage for UNIT on
4912 CYCLE in REGEXP alternative with ALT_NUM. The structure is made
4913 accessed through cycle_alt_unit_usages. */
4915 store_alt_unit_usage (regexp_t regexp, regexp_t unit, int cycle,
4919 unit_decl_t unit_decl;
4920 unit_usage_t unit_usage_ptr;
4923 gcc_assert (regexp && regexp->mode == rm_oneof
4924 && alt_num < REGEXP_ONEOF (regexp)->regexps_num);
4925 unit_decl = REGEXP_UNIT (unit)->unit_decl;
4927 length = (cycle + 1) * REGEXP_ONEOF (regexp)->regexps_num;
4928 while (VEC_length (unit_usage_t, cycle_alt_unit_usages) < length)
4929 VEC_safe_push (unit_usage_t,heap, cycle_alt_unit_usages, 0);
4931 obstack_blank (&unit_usages, sizeof (struct unit_usage));
4932 unit_usage_ptr = (struct unit_usage *) obstack_base (&unit_usages);
4933 obstack_finish (&unit_usages);
4934 unit_usage_ptr->unit_decl = unit_decl;
4935 index = cycle * REGEXP_ONEOF (regexp)->regexps_num + alt_num;
4936 unit_usage_ptr->next = VEC_index (unit_usage_t, cycle_alt_unit_usages, index);
4937 VEC_replace (unit_usage_t, cycle_alt_unit_usages, index, unit_usage_ptr);
4938 unit_decl->last_distribution_check_cycle = -1; /* undefined */
4941 /* The function processes given REGEXP to find units with the wrong
4944 check_regexp_units_distribution (const char *insn_reserv_name,
4948 regexp_t seq, allof, unit;
4949 struct unit_usage *unit_usage_ptr, *other_unit_usage_ptr;
4951 if (regexp == NULL || regexp->mode != rm_oneof)
4953 /* Store all unit usages in the regexp: */
4954 obstack_init (&unit_usages);
4955 cycle_alt_unit_usages = 0;
4957 for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
4959 seq = REGEXP_ONEOF (regexp)->regexps [i];
4963 for (j = 0; j < REGEXP_SEQUENCE (seq)->regexps_num; j++)
4965 allof = REGEXP_SEQUENCE (seq)->regexps [j];
4966 switch (allof->mode)
4969 for (k = 0; k < REGEXP_ALLOF (allof)->regexps_num; k++)
4971 unit = REGEXP_ALLOF (allof)->regexps [k];
4972 if (unit->mode == rm_unit)
4973 store_alt_unit_usage (regexp, unit, j, i);
4975 gcc_assert (unit->mode == rm_nothing);
4980 store_alt_unit_usage (regexp, allof, j, i);
4993 for (k = 0; k < REGEXP_ALLOF (seq)->regexps_num; k++)
4995 unit = REGEXP_ALLOF (seq)->regexps [k];
4999 store_alt_unit_usage (regexp, unit, 0, i);
5012 store_alt_unit_usage (regexp, seq, 0, i);
5022 /* Check distribution: */
5023 for (i = 0; i < (int) VEC_length (unit_usage_t, cycle_alt_unit_usages); i++)
5025 cycle = i / REGEXP_ONEOF (regexp)->regexps_num;
5026 for (unit_usage_ptr = VEC_index (unit_usage_t, cycle_alt_unit_usages, i);
5027 unit_usage_ptr != NULL;
5028 unit_usage_ptr = unit_usage_ptr->next)
5029 if (cycle != unit_usage_ptr->unit_decl->last_distribution_check_cycle)
5031 unit_usage_ptr->unit_decl->last_distribution_check_cycle = cycle;
5032 for (k = cycle * REGEXP_ONEOF (regexp)->regexps_num;
5033 k < (int) VEC_length (unit_usage_t, cycle_alt_unit_usages)
5034 && k == cycle * REGEXP_ONEOF (regexp)->regexps_num;
5037 for (other_unit_usage_ptr
5038 = VEC_index (unit_usage_t, cycle_alt_unit_usages, k);
5039 other_unit_usage_ptr != NULL;
5040 other_unit_usage_ptr = other_unit_usage_ptr->next)
5041 if (unit_usage_ptr->unit_decl->automaton_decl
5042 == other_unit_usage_ptr->unit_decl->automaton_decl)
5044 if (other_unit_usage_ptr == NULL
5045 && (VEC_index (unit_usage_t, cycle_alt_unit_usages, k)
5049 if (k < (int) VEC_length (unit_usage_t, cycle_alt_unit_usages)
5050 && k == cycle * REGEXP_ONEOF (regexp)->regexps_num)
5052 if (!annotation_message_reported_p)
5054 fprintf (stderr, "\n");
5055 error ("The following units do not satisfy units-automata distribution rule");
5056 error (" (A unit of given unit automaton should be on each reserv. altern.)");
5057 annotation_message_reported_p = TRUE;
5059 error ("Unit %s, reserv. %s, cycle %d",
5060 unit_usage_ptr->unit_decl->name, insn_reserv_name,
5065 VEC_free (unit_usage_t,heap, cycle_alt_unit_usages);
5066 obstack_free (&unit_usages, NULL);
5069 /* The function finds units which violates units to automata
5070 distribution rule. If the units exist, report about them. */
5072 check_unit_distributions_to_automata (void)
5078 fprintf (stderr, "Check unit distributions to automata...");
5079 annotation_message_reported_p = FALSE;
5080 for (i = 0; i < description->decls_num; i++)
5082 decl = description->decls [i];
5083 if (decl->mode == dm_insn_reserv)
5084 check_regexp_units_distribution
5085 (DECL_INSN_RESERV (decl)->name,
5086 DECL_INSN_RESERV (decl)->transformed_regexp);
5089 fprintf (stderr, "done\n");
5094 /* The page contains code for building alt_states (see comments for
5095 IR) describing all possible insns reservations of an automaton. */
5097 /* Current state being formed for which the current alt_state
5099 static state_t state_being_formed;
5101 /* Current alt_state being formed. */
5102 static alt_state_t alt_state_being_formed;
5104 /* This recursive function processes `,' and units in reservation
5105 REGEXP for forming alt_states of AUTOMATON. It is believed that
5106 CURR_CYCLE is start cycle of all reservation REGEXP. */
5108 process_seq_for_forming_states (regexp_t regexp, automaton_t automaton,
5116 switch (regexp->mode)
5119 if (REGEXP_UNIT (regexp)->unit_decl->corresponding_automaton_num
5120 == automaton->automaton_order_num)
5121 set_state_reserv (state_being_formed, curr_cycle,
5122 REGEXP_UNIT (regexp)->unit_decl->unit_num);
5126 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
5128 = process_seq_for_forming_states
5129 (REGEXP_SEQUENCE (regexp)->regexps [i], automaton, curr_cycle) + 1;
5134 int finish_cycle = 0;
5137 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
5139 cycle = process_seq_for_forming_states (REGEXP_ALLOF (regexp)
5141 automaton, curr_cycle);
5142 if (finish_cycle < cycle)
5143 finish_cycle = cycle;
5145 return finish_cycle;
5156 /* This recursive function finishes forming ALT_STATE of AUTOMATON and
5157 inserts alt_state into the table. */
5159 finish_forming_alt_state (alt_state_t alt_state,
5160 automaton_t automaton ATTRIBUTE_UNUSED)
5162 state_t state_in_table;
5163 state_t corresponding_state;
5165 corresponding_state = alt_state->state;
5166 state_in_table = insert_state (corresponding_state);
5167 if (state_in_table != corresponding_state)
5169 free_state (corresponding_state);
5170 alt_state->state = state_in_table;
5174 /* The following variable value is current automaton insn for whose
5175 reservation the alt states are created. */
5176 static ainsn_t curr_ainsn;
5178 /* This recursive function processes `|' in reservation REGEXP for
5179 forming alt_states of AUTOMATON. List of the alt states should
5180 have the same order as in the description. */
5182 process_alts_for_forming_states (regexp_t regexp, automaton_t automaton,
5187 if (regexp->mode != rm_oneof)
5189 alt_state_being_formed = get_free_alt_state ();
5190 state_being_formed = get_free_state (1, automaton);
5191 alt_state_being_formed->state = state_being_formed;
5192 /* We inserts in reverse order but we process alternatives also
5193 in reverse order. So we have the same order of alternative
5194 as in the description. */
5195 alt_state_being_formed->next_alt_state = curr_ainsn->alt_states;
5196 curr_ainsn->alt_states = alt_state_being_formed;
5197 (void) process_seq_for_forming_states (regexp, automaton, 0);
5198 finish_forming_alt_state (alt_state_being_formed, automaton);
5202 gcc_assert (!inside_oneof_p);
5203 /* We processes it in reverse order to get list with the same
5204 order as in the description. See also the previous
5206 for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
5207 process_alts_for_forming_states (REGEXP_ONEOF (regexp)->regexps [i],
5212 /* Create nodes alt_state for all AUTOMATON insns. */
5214 create_alt_states (automaton_t automaton)
5216 struct insn_reserv_decl *reserv_decl;
5218 for (curr_ainsn = automaton->ainsn_list;
5220 curr_ainsn = curr_ainsn->next_ainsn)
5222 reserv_decl = curr_ainsn->insn_reserv_decl;
5223 if (reserv_decl != DECL_INSN_RESERV (advance_cycle_insn_decl))
5225 curr_ainsn->alt_states = NULL;
5226 process_alts_for_forming_states (reserv_decl->transformed_regexp,
5228 curr_ainsn->sorted_alt_states
5229 = uniq_sort_alt_states (curr_ainsn->alt_states);
5236 /* The page contains major code for building DFA(s) for fast pipeline
5237 hazards recognition. */
5239 /* The function forms list of ainsns of AUTOMATON with the same
5243 form_ainsn_with_same_reservs (automaton_t automaton)
5247 VEC(ainsn_t,heap) *last_insns = VEC_alloc (ainsn_t,heap, 150);
5249 for (curr_ainsn = automaton->ainsn_list;
5251 curr_ainsn = curr_ainsn->next_ainsn)
5252 if (curr_ainsn->insn_reserv_decl
5253 == DECL_INSN_RESERV (advance_cycle_insn_decl))
5255 curr_ainsn->next_same_reservs_insn = NULL;
5256 curr_ainsn->first_insn_with_same_reservs = 1;
5260 for (i = 0; i < VEC_length (ainsn_t, last_insns); i++)
5262 (curr_ainsn->sorted_alt_states,
5263 VEC_index (ainsn_t, last_insns, i)->sorted_alt_states))
5265 curr_ainsn->next_same_reservs_insn = NULL;
5266 if (i < VEC_length (ainsn_t, last_insns))
5268 curr_ainsn->first_insn_with_same_reservs = 0;
5269 VEC_index (ainsn_t, last_insns, i)->next_same_reservs_insn
5271 VEC_replace (ainsn_t, last_insns, i, curr_ainsn);
5275 VEC_safe_push (ainsn_t, heap, last_insns, curr_ainsn);
5276 curr_ainsn->first_insn_with_same_reservs = 1;
5279 VEC_free (ainsn_t,heap, last_insns);
5282 /* Forming unit reservations which can affect creating the automaton
5283 states achieved from a given state. It permits to build smaller
5284 automata in many cases. We would have the same automata after
5285 the minimization without such optimization, but the automaton
5286 right after the building could be huge. So in other words, usage
5287 of reservs_matter means some minimization during building the
5289 static reserv_sets_t
5290 form_reservs_matter (automaton_t automaton)
5293 reserv_sets_t reservs_matter = alloc_empty_reserv_sets();
5295 for (cycle = 0; cycle < max_cycles_num; cycle++)
5296 for (unit = 0; unit < description->units_num; unit++)
5297 if (units_array [unit]->automaton_decl
5298 == automaton->corresponding_automaton_decl
5299 && (cycle >= units_array [unit]->min_occ_cycle_num
5300 /* We can not remove queried unit from reservations. */
5301 || units_array [unit]->query_p
5302 /* We can not remove units which are used
5303 `exclusion_set', `presence_set',
5304 `final_presence_set', `absence_set', and
5305 `final_absence_set'. */
5306 || units_array [unit]->in_set_p))
5307 set_unit_reserv (reservs_matter, cycle, unit);
5308 return reservs_matter;
5311 /* The following function creates all states of nondeterministic AUTOMATON. */
5313 make_automaton (automaton_t automaton)
5316 struct insn_reserv_decl *insn_reserv_decl;
5317 alt_state_t alt_state;
5319 state_t start_state;
5321 ainsn_t advance_cycle_ainsn;
5323 VEC(state_t,heap) *state_stack = VEC_alloc(state_t,heap, 150);
5325 reserv_sets_t reservs_matter = form_reservs_matter (automaton);
5327 /* Create the start state (empty state). */
5328 start_state = insert_state (get_free_state (1, automaton));
5329 automaton->start_state = start_state;
5330 start_state->it_was_placed_in_stack_for_NDFA_forming = 1;
5331 VEC_safe_push (state_t,heap, state_stack, start_state);
5333 while (VEC_length (state_t, state_stack) != 0)
5335 state = VEC_pop (state_t, state_stack);
5336 advance_cycle_ainsn = NULL;
5337 for (ainsn = automaton->ainsn_list;
5339 ainsn = ainsn->next_ainsn)
5340 if (ainsn->first_insn_with_same_reservs)
5342 insn_reserv_decl = ainsn->insn_reserv_decl;
5343 if (insn_reserv_decl != DECL_INSN_RESERV (advance_cycle_insn_decl))
5345 /* We process alt_states in the same order as they are
5346 present in the description. */
5348 for (alt_state = ainsn->alt_states;
5350 alt_state = alt_state->next_alt_state)
5352 state2 = alt_state->state;
5353 if (!intersected_state_reservs_p (state, state2))
5355 state2 = states_union (state, state2, reservs_matter);
5356 if (!state2->it_was_placed_in_stack_for_NDFA_forming)
5358 state2->it_was_placed_in_stack_for_NDFA_forming
5360 VEC_safe_push (state_t,heap, state_stack, state2);
5362 if (progress_flag && states_n % 100 == 0)
5363 fprintf (stderr, ".");
5365 added_arc = add_arc (state, state2, ainsn);
5370 if (!ndfa_flag && added_arc != NULL)
5372 for (alt_state = ainsn->alt_states;
5374 alt_state = alt_state->next_alt_state)
5375 state2 = alt_state->state;
5379 advance_cycle_ainsn = ainsn;
5381 /* Add transition to advance cycle. */
5382 state2 = state_shift (state, reservs_matter);
5383 if (!state2->it_was_placed_in_stack_for_NDFA_forming)
5385 state2->it_was_placed_in_stack_for_NDFA_forming = 1;
5386 VEC_safe_push (state_t,heap, state_stack, state2);
5388 if (progress_flag && states_n % 100 == 0)
5389 fprintf (stderr, ".");
5391 gcc_assert (advance_cycle_ainsn);
5392 add_arc (state, state2, advance_cycle_ainsn);
5394 VEC_free (state_t,heap, state_stack);
5397 /* Foms lists of all arcs of STATE marked by the same ainsn. */
5399 form_arcs_marked_by_insn (state_t state)
5405 for (i = 0; i < description->decls_num; i++)
5407 decl = description->decls [i];
5408 if (decl->mode == dm_insn_reserv)
5409 DECL_INSN_RESERV (decl)->arcs_marked_by_insn = NULL;
5411 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5413 gcc_assert (arc->insn);
5414 arc->next_arc_marked_by_insn
5415 = arc->insn->insn_reserv_decl->arcs_marked_by_insn;
5416 arc->insn->insn_reserv_decl->arcs_marked_by_insn = arc;
5420 /* The function creates composed state (see comments for IR) from
5421 ORIGINAL_STATE and list of arcs ARCS_MARKED_BY_INSN marked by the
5422 same insn. If the composed state is not in STATE_STACK yet, it is
5423 pushed into STATE_STACK. */
5426 create_composed_state (state_t original_state, arc_t arcs_marked_by_insn,
5427 VEC(state_t,heap) **state_stack)
5430 alt_state_t alt_state, curr_alt_state;
5431 alt_state_t new_alt_state;
5434 state_t state_in_table;
5436 alt_state_t canonical_alt_states_list;
5438 int new_state_p = 0;
5440 if (arcs_marked_by_insn == NULL)
5442 if (arcs_marked_by_insn->next_arc_marked_by_insn == NULL)
5443 state = arcs_marked_by_insn->to_state;
5446 gcc_assert (ndfa_flag);
5447 /* Create composed state. */
5448 state = get_free_state (0, arcs_marked_by_insn->to_state->automaton);
5449 curr_alt_state = NULL;
5450 for (curr_arc = arcs_marked_by_insn;
5452 curr_arc = curr_arc->next_arc_marked_by_insn)
5453 if (curr_arc->to_state->component_states == NULL)
5455 new_alt_state = get_free_alt_state ();
5456 new_alt_state->next_alt_state = curr_alt_state;
5457 new_alt_state->state = curr_arc->to_state;
5458 curr_alt_state = new_alt_state;
5461 for (alt_state = curr_arc->to_state->component_states;
5463 alt_state = alt_state->next_sorted_alt_state)
5465 new_alt_state = get_free_alt_state ();
5466 new_alt_state->next_alt_state = curr_alt_state;
5467 new_alt_state->state = alt_state->state;
5468 gcc_assert (!alt_state->state->component_states);
5469 curr_alt_state = new_alt_state;
5471 /* There are not identical sets in the alt state list. */
5472 canonical_alt_states_list = uniq_sort_alt_states (curr_alt_state);
5473 if (canonical_alt_states_list->next_sorted_alt_state == NULL)
5476 state = canonical_alt_states_list->state;
5477 free_state (temp_state);
5481 state->component_states = canonical_alt_states_list;
5482 state_in_table = insert_state (state);
5483 if (state_in_table != state)
5486 (state_in_table->it_was_placed_in_stack_for_DFA_forming);
5488 state = state_in_table;
5492 gcc_assert (!state->it_was_placed_in_stack_for_DFA_forming);
5494 for (curr_alt_state = state->component_states;
5495 curr_alt_state != NULL;
5496 curr_alt_state = curr_alt_state->next_sorted_alt_state)
5497 for (curr_arc = first_out_arc (curr_alt_state->state);
5499 curr_arc = next_out_arc (curr_arc))
5500 add_arc (state, curr_arc->to_state, curr_arc->insn);
5502 arcs_marked_by_insn->to_state = state;
5503 for (alts_number = 0,
5504 curr_arc = arcs_marked_by_insn->next_arc_marked_by_insn;
5506 curr_arc = next_arc)
5508 next_arc = curr_arc->next_arc_marked_by_insn;
5509 remove_arc (original_state, curr_arc);
5514 if (!state->it_was_placed_in_stack_for_DFA_forming)
5516 state->it_was_placed_in_stack_for_DFA_forming = 1;
5517 VEC_safe_push (state_t,heap, *state_stack, state);
5522 /* The function transforms nondeterministic AUTOMATON into
5526 NDFA_to_DFA (automaton_t automaton)
5528 state_t start_state;
5531 VEC(state_t,heap) *state_stack;
5535 state_stack = VEC_alloc (state_t,heap, 0);
5537 /* Create the start state (empty state). */
5538 start_state = automaton->start_state;
5539 start_state->it_was_placed_in_stack_for_DFA_forming = 1;
5540 VEC_safe_push (state_t,heap, state_stack, start_state);
5542 while (VEC_length (state_t, state_stack) != 0)
5544 state = VEC_pop (state_t, state_stack);
5545 form_arcs_marked_by_insn (state);
5546 for (i = 0; i < description->decls_num; i++)
5548 decl = description->decls [i];
5549 if (decl->mode == dm_insn_reserv
5550 && create_composed_state
5551 (state, DECL_INSN_RESERV (decl)->arcs_marked_by_insn,
5555 if (progress_flag && states_n % 100 == 0)
5556 fprintf (stderr, ".");
5560 VEC_free (state_t,heap, state_stack);
5563 /* The following variable value is current number (1, 2, ...) of passing
5565 static int curr_state_graph_pass_num;
5567 /* This recursive function passes all states achieved from START_STATE
5568 and applies APPLIED_FUNC to them. */
5570 pass_state_graph (state_t start_state, void (*applied_func) (state_t state))
5574 if (start_state->pass_num == curr_state_graph_pass_num)
5576 start_state->pass_num = curr_state_graph_pass_num;
5577 (*applied_func) (start_state);
5578 for (arc = first_out_arc (start_state);
5580 arc = next_out_arc (arc))
5581 pass_state_graph (arc->to_state, applied_func);
5584 /* This recursive function passes all states of AUTOMATON and applies
5585 APPLIED_FUNC to them. */
5587 pass_states (automaton_t automaton, void (*applied_func) (state_t state))
5589 curr_state_graph_pass_num++;
5590 pass_state_graph (automaton->start_state, applied_func);
5593 /* The function initializes code for passing of all states. */
5595 initiate_pass_states (void)
5597 curr_state_graph_pass_num = 0;
5600 /* The following vla is used for storing pointers to all achieved
5602 static VEC(state_t,heap) *all_achieved_states;
5604 /* This function is called by function pass_states to add an achieved
5607 add_achieved_state (state_t state)
5609 VEC_safe_push (state_t,heap, all_achieved_states, state);
5612 /* The function sets up equivalence numbers of insns which mark all
5613 out arcs of STATE by equiv_class_num_1 (if ODD_ITERATION_FLAG has
5614 nonzero value) or by equiv_class_num_2 of the destination state.
5615 The function returns number of out arcs of STATE. */
5617 set_out_arc_insns_equiv_num (state_t state, int odd_iteration_flag)
5621 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5623 gcc_assert (!arc->insn->insn_reserv_decl->equiv_class_num);
5624 arc->insn->insn_reserv_decl->equiv_class_num
5625 = (odd_iteration_flag
5626 ? arc->to_state->equiv_class_num_1
5627 : arc->to_state->equiv_class_num_2);
5628 gcc_assert (arc->insn->insn_reserv_decl->equiv_class_num);
5632 /* The function clears equivalence numbers and alt_states in all insns
5633 which mark all out arcs of STATE. */
5635 clear_arc_insns_equiv_num (state_t state)
5639 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5640 arc->insn->insn_reserv_decl->equiv_class_num = 0;
5644 /* The following function returns TRUE if STATE reserves the unit with
5645 UNIT_NUM on the first cycle. */
5647 first_cycle_unit_presence (state_t state, int unit_num)
5649 alt_state_t alt_state;
5651 if (state->component_states == NULL)
5652 return test_unit_reserv (state->reservs, 0, unit_num);
5655 for (alt_state = state->component_states;
5657 alt_state = alt_state->next_sorted_alt_state)
5658 if (test_unit_reserv (alt_state->state->reservs, 0, unit_num))
5664 /* This fills in the presence_signature[] member of STATE. */
5666 cache_presence (state_t state)
5670 sz = (description->query_units_num + sizeof (int) * CHAR_BIT - 1)
5671 / (sizeof (int) * CHAR_BIT);
5673 state->presence_signature = create_node (sz * sizeof (int));
5674 for (i = 0; i < description->units_num; i++)
5675 if (units_array [i]->query_p)
5677 int presence1_p = first_cycle_unit_presence (state, i);
5678 state->presence_signature[num / (sizeof (int) * CHAR_BIT)]
5679 |= (!!presence1_p) << (num % (sizeof (int) * CHAR_BIT));
5684 /* The function returns nonzero value if STATE is not equivalent to
5685 ANOTHER_STATE from the same current partition on equivalence
5686 classes. Another state has ANOTHER_STATE_OUT_ARCS_NUM number of
5687 output arcs. Iteration of making equivalence partition is defined
5688 by ODD_ITERATION_FLAG. */
5690 state_is_differed (state_t state, state_t another_state,
5691 int odd_iteration_flag)
5694 unsigned int sz, si;
5696 gcc_assert (state->num_out_arcs == another_state->num_out_arcs);
5698 sz = (description->query_units_num + sizeof (int) * CHAR_BIT - 1)
5699 / (sizeof (int) * CHAR_BIT);
5701 for (si = 0; si < sz; si++)
5702 gcc_assert (state->presence_signature[si]
5703 == another_state->presence_signature[si]);
5705 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5707 if ((odd_iteration_flag
5708 ? arc->to_state->equiv_class_num_1
5709 : arc->to_state->equiv_class_num_2)
5710 != arc->insn->insn_reserv_decl->equiv_class_num)
5717 /* Compares two states pointed to by STATE_PTR_1 and STATE_PTR_2
5718 and return -1, 0 or 1. This function can be used as predicate for
5719 qsort(). It requires the member presence_signature[] of both
5720 states be filled. */
5722 compare_states_for_equiv (const void *state_ptr_1,
5723 const void *state_ptr_2)
5725 const_state_t const s1 = *(const_state_t const*)state_ptr_1;
5726 const_state_t const s2 = *(const_state_t const*)state_ptr_2;
5727 unsigned int sz, si;
5728 if (s1->num_out_arcs < s2->num_out_arcs)
5730 else if (s1->num_out_arcs > s2->num_out_arcs)
5733 sz = (description->query_units_num + sizeof (int) * CHAR_BIT - 1)
5734 / (sizeof (int) * CHAR_BIT);
5736 for (si = 0; si < sz; si++)
5737 if (s1->presence_signature[si] < s2->presence_signature[si])
5739 else if (s1->presence_signature[si] > s2->presence_signature[si])
5744 /* The function makes initial partition of STATES on equivalent
5745 classes and saves it into *CLASSES. This function requires the input
5746 to be sorted via compare_states_for_equiv(). */
5748 init_equiv_class (VEC(state_t,heap) *states, VEC (state_t,heap) **classes)
5754 *classes = VEC_alloc (state_t,heap, 150);
5755 for (i = 0; i < VEC_length (state_t, states); i++)
5757 state_t state = VEC_index (state_t, states, i);
5760 if (compare_states_for_equiv (&prev, &state) != 0)
5762 VEC_safe_push (state_t,heap, *classes, prev);
5767 state->equiv_class_num_1 = class_num;
5768 state->next_equiv_class_state = prev;
5772 VEC_safe_push (state_t,heap, *classes, prev);
5776 /* The function copies pointers to equivalent states from vla FROM
5779 copy_equiv_class (VEC(state_t,heap) **to, VEC(state_t,heap) *from)
5781 VEC_free (state_t,heap, *to);
5782 *to = VEC_copy (state_t,heap, from);
5785 /* The function processes equivalence class given by its first state,
5786 FIRST_STATE, on odd iteration if ODD_ITERATION_FLAG. If there
5787 are not equivalent states, the function partitions the class
5788 removing nonequivalent states and placing them in
5789 *NEXT_ITERATION_CLASSES, increments *NEW_EQUIV_CLASS_NUM_PTR ans
5790 assigns it to the state equivalence number. If the class has been
5791 partitioned, the function returns nonzero value. */
5793 partition_equiv_class (state_t first_state, int odd_iteration_flag,
5794 VEC(state_t,heap) **next_iteration_classes,
5795 int *new_equiv_class_num_ptr)
5797 state_t new_equiv_class;
5805 while (first_state != NULL)
5807 new_equiv_class = NULL;
5808 if (first_state->next_equiv_class_state != NULL)
5810 /* There are more one states in the class equivalence. */
5811 set_out_arc_insns_equiv_num (first_state, odd_iteration_flag);
5812 for (prev_state = first_state,
5813 curr_state = first_state->next_equiv_class_state;
5815 curr_state = next_state)
5817 next_state = curr_state->next_equiv_class_state;
5818 if (state_is_differed (curr_state, first_state,
5819 odd_iteration_flag))
5821 /* Remove curr state from the class equivalence. */
5822 prev_state->next_equiv_class_state = next_state;
5823 /* Add curr state to the new class equivalence. */
5824 curr_state->next_equiv_class_state = new_equiv_class;
5825 if (new_equiv_class == NULL)
5826 (*new_equiv_class_num_ptr)++;
5827 if (odd_iteration_flag)
5828 curr_state->equiv_class_num_2 = *new_equiv_class_num_ptr;
5830 curr_state->equiv_class_num_1 = *new_equiv_class_num_ptr;
5831 new_equiv_class = curr_state;
5835 prev_state = curr_state;
5837 clear_arc_insns_equiv_num (first_state);
5839 if (new_equiv_class != NULL)
5840 VEC_safe_push (state_t,heap, *next_iteration_classes, new_equiv_class);
5841 first_state = new_equiv_class;
5846 /* The function finds equivalent states of AUTOMATON. */
5848 evaluate_equiv_classes (automaton_t automaton,
5849 VEC(state_t,heap) **equiv_classes)
5851 int new_equiv_class_num;
5852 int odd_iteration_flag;
5854 VEC (state_t,heap) *next_iteration_classes;
5857 all_achieved_states = VEC_alloc (state_t,heap, 1500);
5858 pass_states (automaton, add_achieved_state);
5859 pass_states (automaton, cache_presence);
5860 qsort (VEC_address (state_t, all_achieved_states),
5861 VEC_length (state_t, all_achieved_states),
5862 sizeof (state_t), compare_states_for_equiv);
5864 odd_iteration_flag = 0;
5865 new_equiv_class_num = init_equiv_class (all_achieved_states,
5866 &next_iteration_classes);
5870 odd_iteration_flag = !odd_iteration_flag;
5872 copy_equiv_class (equiv_classes, next_iteration_classes);
5874 /* Transfer equiv numbers for the next iteration. */
5875 for (i = 0; i < VEC_length (state_t, all_achieved_states); i++)
5876 if (odd_iteration_flag)
5877 VEC_index (state_t, all_achieved_states, i)->equiv_class_num_2
5878 = VEC_index (state_t, all_achieved_states, i)->equiv_class_num_1;
5880 VEC_index (state_t, all_achieved_states, i)->equiv_class_num_1
5881 = VEC_index (state_t, all_achieved_states, i)->equiv_class_num_2;
5883 for (i = 0; i < VEC_length (state_t, *equiv_classes); i++)
5884 if (partition_equiv_class (VEC_index (state_t, *equiv_classes, i),
5886 &next_iteration_classes,
5887 &new_equiv_class_num))
5890 while (!finish_flag);
5891 VEC_free (state_t,heap, next_iteration_classes);
5892 VEC_free (state_t,heap, all_achieved_states);
5895 /* The function merges equivalent states of AUTOMATON. */
5897 merge_states (automaton_t automaton, VEC(state_t,heap) *equiv_classes)
5901 state_t first_class_state;
5902 alt_state_t alt_states;
5903 alt_state_t alt_state, new_alt_state;
5908 /* Create states corresponding to equivalence classes containing two
5910 for (i = 0; i < VEC_length (state_t, equiv_classes); i++)
5912 curr_state = VEC_index (state_t, equiv_classes, i);
5913 if (curr_state->next_equiv_class_state != NULL)
5915 /* There are more one states in the class equivalence. */
5916 /* Create new compound state. */
5917 new_state = get_free_state (0, automaton);
5919 first_class_state = curr_state;
5920 for (curr_state = first_class_state;
5922 curr_state = curr_state->next_equiv_class_state)
5924 curr_state->equiv_class_state = new_state;
5925 if (curr_state->component_states == NULL)
5927 new_alt_state = get_free_alt_state ();
5928 new_alt_state->state = curr_state;
5929 new_alt_state->next_alt_state = alt_states;
5930 alt_states = new_alt_state;
5933 for (alt_state = curr_state->component_states;
5935 alt_state = alt_state->next_sorted_alt_state)
5937 new_alt_state = get_free_alt_state ();
5938 new_alt_state->state = alt_state->state;
5939 new_alt_state->next_alt_state = alt_states;
5940 alt_states = new_alt_state;
5943 /* Its is important that alt states were sorted before and
5944 after merging to have the same querying results. */
5945 new_state->component_states = uniq_sort_alt_states (alt_states);
5948 curr_state->equiv_class_state = curr_state;
5951 for (i = 0; i < VEC_length (state_t, equiv_classes); i++)
5953 curr_state = VEC_index (state_t, equiv_classes, i);
5954 if (curr_state->next_equiv_class_state != NULL)
5956 first_class_state = curr_state;
5957 /* Create new arcs output from the state corresponding to
5959 for (curr_arc = first_out_arc (first_class_state);
5961 curr_arc = next_out_arc (curr_arc))
5962 add_arc (first_class_state->equiv_class_state,
5963 curr_arc->to_state->equiv_class_state,
5965 /* Delete output arcs from states of given class equivalence. */
5966 for (curr_state = first_class_state;
5968 curr_state = curr_state->next_equiv_class_state)
5970 if (automaton->start_state == curr_state)
5971 automaton->start_state = curr_state->equiv_class_state;
5972 /* Delete the state and its output arcs. */
5973 for (curr_arc = first_out_arc (curr_state);
5975 curr_arc = next_arc)
5977 next_arc = next_out_arc (curr_arc);
5978 free_arc (curr_arc);
5984 /* Change `to_state' of arcs output from the state of given
5985 equivalence class. */
5986 for (curr_arc = first_out_arc (curr_state);
5988 curr_arc = next_out_arc (curr_arc))
5989 curr_arc->to_state = curr_arc->to_state->equiv_class_state;
5994 /* The function sets up new_cycle_p for states if there is arc to the
5995 state marked by advance_cycle_insn_decl. */
5997 set_new_cycle_flags (state_t state)
6001 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6002 if (arc->insn->insn_reserv_decl
6003 == DECL_INSN_RESERV (advance_cycle_insn_decl))
6004 arc->to_state->new_cycle_p = 1;
6007 /* The top level function for minimization of deterministic
6010 minimize_DFA (automaton_t automaton)
6012 VEC(state_t,heap) *equiv_classes = 0;
6014 evaluate_equiv_classes (automaton, &equiv_classes);
6015 merge_states (automaton, equiv_classes);
6016 pass_states (automaton, set_new_cycle_flags);
6018 VEC_free (state_t,heap, equiv_classes);
6021 /* Values of two variables are counted number of states and arcs in an
6023 static int curr_counted_states_num;
6024 static int curr_counted_arcs_num;
6026 /* The function is called by function `pass_states' to count states
6027 and arcs of an automaton. */
6029 incr_states_and_arcs_nums (state_t state)
6033 curr_counted_states_num++;
6034 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6035 curr_counted_arcs_num++;
6038 /* The function counts states and arcs of AUTOMATON. */
6040 count_states_and_arcs (automaton_t automaton, int *states_num,
6043 curr_counted_states_num = 0;
6044 curr_counted_arcs_num = 0;
6045 pass_states (automaton, incr_states_and_arcs_nums);
6046 *states_num = curr_counted_states_num;
6047 *arcs_num = curr_counted_arcs_num;
6050 /* The function builds one DFA AUTOMATON for fast pipeline hazards
6051 recognition after checking and simplifying IR of the
6054 build_automaton (automaton_t automaton)
6059 ticker_on (&NDFA_time);
6062 if (automaton->corresponding_automaton_decl == NULL)
6063 fprintf (stderr, "Create anonymous automaton");
6065 fprintf (stderr, "Create automaton `%s'",
6066 automaton->corresponding_automaton_decl->name);
6067 fprintf (stderr, " (1 dot is 100 new states):");
6069 make_automaton (automaton);
6071 fprintf (stderr, " done\n");
6072 ticker_off (&NDFA_time);
6073 count_states_and_arcs (automaton, &states_num, &arcs_num);
6074 automaton->NDFA_states_num = states_num;
6075 automaton->NDFA_arcs_num = arcs_num;
6076 ticker_on (&NDFA_to_DFA_time);
6079 if (automaton->corresponding_automaton_decl == NULL)
6080 fprintf (stderr, "Make anonymous DFA");
6082 fprintf (stderr, "Make DFA `%s'",
6083 automaton->corresponding_automaton_decl->name);
6084 fprintf (stderr, " (1 dot is 100 new states):");
6086 NDFA_to_DFA (automaton);
6088 fprintf (stderr, " done\n");
6089 ticker_off (&NDFA_to_DFA_time);
6090 count_states_and_arcs (automaton, &states_num, &arcs_num);
6091 automaton->DFA_states_num = states_num;
6092 automaton->DFA_arcs_num = arcs_num;
6093 if (!no_minimization_flag)
6095 ticker_on (&minimize_time);
6098 if (automaton->corresponding_automaton_decl == NULL)
6099 fprintf (stderr, "Minimize anonymous DFA...");
6101 fprintf (stderr, "Minimize DFA `%s'...",
6102 automaton->corresponding_automaton_decl->name);
6104 minimize_DFA (automaton);
6106 fprintf (stderr, "done\n");
6107 ticker_off (&minimize_time);
6108 count_states_and_arcs (automaton, &states_num, &arcs_num);
6109 automaton->minimal_DFA_states_num = states_num;
6110 automaton->minimal_DFA_arcs_num = arcs_num;
6116 /* The page contains code for enumeration of all states of an automaton. */
6118 /* Variable used for enumeration of all states of an automaton. Its
6119 value is current number of automaton states. */
6120 static int curr_state_order_num;
6122 /* The function is called by function `pass_states' for enumerating
6125 set_order_state_num (state_t state)
6127 state->order_state_num = curr_state_order_num;
6128 curr_state_order_num++;
6131 /* The function enumerates all states of AUTOMATON. */
6133 enumerate_states (automaton_t automaton)
6135 curr_state_order_num = 0;
6136 pass_states (automaton, set_order_state_num);
6137 automaton->achieved_states_num = curr_state_order_num;
6142 /* The page contains code for finding equivalent automaton insns
6145 /* The function inserts AINSN into cyclic list
6146 CYCLIC_EQUIV_CLASS_INSN_LIST of ainsns. */
6148 insert_ainsn_into_equiv_class (ainsn_t ainsn,
6149 ainsn_t cyclic_equiv_class_insn_list)
6151 if (cyclic_equiv_class_insn_list == NULL)
6152 ainsn->next_equiv_class_insn = ainsn;
6155 ainsn->next_equiv_class_insn
6156 = cyclic_equiv_class_insn_list->next_equiv_class_insn;
6157 cyclic_equiv_class_insn_list->next_equiv_class_insn = ainsn;
6162 /* The function deletes equiv_class_insn into cyclic list of
6163 equivalent ainsns. */
6165 delete_ainsn_from_equiv_class (ainsn_t equiv_class_insn)
6167 ainsn_t curr_equiv_class_insn;
6168 ainsn_t prev_equiv_class_insn;
6170 prev_equiv_class_insn = equiv_class_insn;
6171 for (curr_equiv_class_insn = equiv_class_insn->next_equiv_class_insn;
6172 curr_equiv_class_insn != equiv_class_insn;
6173 curr_equiv_class_insn = curr_equiv_class_insn->next_equiv_class_insn)
6174 prev_equiv_class_insn = curr_equiv_class_insn;
6175 if (prev_equiv_class_insn != equiv_class_insn)
6176 prev_equiv_class_insn->next_equiv_class_insn
6177 = equiv_class_insn->next_equiv_class_insn;
6180 /* The function processes AINSN of a state in order to find equivalent
6181 ainsns. INSN_ARCS_ARRAY is table: code of insn -> out arc of the
6184 process_insn_equiv_class (ainsn_t ainsn, arc_t *insn_arcs_array)
6188 ainsn_t cyclic_insn_list;
6191 gcc_assert (insn_arcs_array [ainsn->insn_reserv_decl->insn_num]);
6193 /* New class of ainsns which are not equivalent to given ainsn. */
6194 cyclic_insn_list = NULL;
6197 next_insn = curr_insn->next_equiv_class_insn;
6198 arc = insn_arcs_array [curr_insn->insn_reserv_decl->insn_num];
6200 || (insn_arcs_array [ainsn->insn_reserv_decl->insn_num]->to_state
6203 delete_ainsn_from_equiv_class (curr_insn);
6204 cyclic_insn_list = insert_ainsn_into_equiv_class (curr_insn,
6207 curr_insn = next_insn;
6209 while (curr_insn != ainsn);
6212 /* The function processes STATE in order to find equivalent ainsns. */
6214 process_state_for_insn_equiv_partition (state_t state)
6217 arc_t *insn_arcs_array = XCNEWVEC (arc_t, description->insns_num);
6219 /* Process insns of the arcs. */
6220 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6221 insn_arcs_array [arc->insn->insn_reserv_decl->insn_num] = arc;
6222 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6223 process_insn_equiv_class (arc->insn, insn_arcs_array);
6225 free (insn_arcs_array);
6228 /* The function searches for equivalent ainsns of AUTOMATON. */
6230 set_insn_equiv_classes (automaton_t automaton)
6235 ainsn_t cyclic_insn_list;
6236 ainsn_t insn_with_same_reservs;
6237 int equiv_classes_num;
6239 /* All insns are included in one equivalence class. */
6240 cyclic_insn_list = NULL;
6241 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6242 if (ainsn->first_insn_with_same_reservs)
6243 cyclic_insn_list = insert_ainsn_into_equiv_class (ainsn,
6245 /* Process insns in order to make equivalence partition. */
6246 pass_states (automaton, process_state_for_insn_equiv_partition);
6247 /* Enumerate equiv classes. */
6248 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6249 /* Set undefined value. */
6250 ainsn->insn_equiv_class_num = -1;
6251 equiv_classes_num = 0;
6252 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6253 if (ainsn->insn_equiv_class_num < 0)
6256 gcc_assert (first_insn->first_insn_with_same_reservs);
6257 first_insn->first_ainsn_with_given_equivalence_num = 1;
6258 curr_insn = first_insn;
6261 for (insn_with_same_reservs = curr_insn;
6262 insn_with_same_reservs != NULL;
6263 insn_with_same_reservs
6264 = insn_with_same_reservs->next_same_reservs_insn)
6265 insn_with_same_reservs->insn_equiv_class_num = equiv_classes_num;
6266 curr_insn = curr_insn->next_equiv_class_insn;
6268 while (curr_insn != first_insn);
6269 equiv_classes_num++;
6271 automaton->insn_equiv_classes_num = equiv_classes_num;
6276 /* This page contains code for creating DFA(s) and calls functions
6280 /* The following value is used to prevent floating point overflow for
6281 estimating an automaton bound. The value should be less DBL_MAX on
6282 the host machine. We use here approximate minimum of maximal
6283 double floating point value required by ANSI C standard. It
6284 will work for non ANSI sun compiler too. */
6286 #define MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND 1.0E37
6288 /* The function estimate size of the single DFA used by PHR (pipeline
6289 hazards recognizer). */
6291 estimate_one_automaton_bound (void)
6294 double one_automaton_estimation_bound;
6298 one_automaton_estimation_bound = 1.0;
6299 for (i = 0; i < description->decls_num; i++)
6301 decl = description->decls [i];
6302 if (decl->mode == dm_unit)
6304 root_value = exp (log (DECL_UNIT (decl)->max_occ_cycle_num
6305 - DECL_UNIT (decl)->min_occ_cycle_num + 1.0)
6307 if (MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND / root_value
6308 > one_automaton_estimation_bound)
6309 one_automaton_estimation_bound *= root_value;
6312 return one_automaton_estimation_bound;
6315 /* The function compares unit declarations according to their maximal
6316 cycle in reservations. */
6318 compare_max_occ_cycle_nums (const void *unit_decl_1,
6319 const void *unit_decl_2)
6321 if ((DECL_UNIT (*(const_decl_t const*) unit_decl_1)->max_occ_cycle_num)
6322 < (DECL_UNIT (*(const_decl_t const*) unit_decl_2)->max_occ_cycle_num))
6324 else if ((DECL_UNIT (*(const_decl_t const*) unit_decl_1)->max_occ_cycle_num)
6325 == (DECL_UNIT (*(const_decl_t const*) unit_decl_2)->max_occ_cycle_num))
6331 /* The function makes heuristic assigning automata to units. Actually
6332 efficacy of the algorithm has been checked yet??? */
6335 units_to_automata_heuristic_distr (void)
6337 double estimation_bound;
6341 unit_decl_t *unit_decls;
6344 if (description->units_num == 0)
6346 estimation_bound = estimate_one_automaton_bound ();
6347 unit_decls = XNEWVEC (unit_decl_t, description->units_num);
6349 for (i = 0, j = 0; i < description->decls_num; i++)
6350 if (description->decls[i]->mode == dm_unit)
6351 unit_decls[j++] = DECL_UNIT (description->decls[i]);
6352 gcc_assert (j == description->units_num);
6354 qsort (unit_decls, description->units_num,
6355 sizeof (unit_decl_t), compare_max_occ_cycle_nums);
6358 bound_value = unit_decls[0]->max_occ_cycle_num;
6359 unit_decls[0]->corresponding_automaton_num = automaton_num;
6361 for (i = 1; i < description->units_num; i++)
6363 rest_units_num = description->units_num - i + 1;
6364 gcc_assert (automata_num - automaton_num - 1 <= rest_units_num);
6365 if (automaton_num < automata_num - 1
6366 && ((automata_num - automaton_num - 1 == rest_units_num)
6369 / unit_decls[i]->max_occ_cycle_num))))
6371 bound_value = unit_decls[i]->max_occ_cycle_num;
6375 bound_value *= unit_decls[i]->max_occ_cycle_num;
6376 unit_decls[i]->corresponding_automaton_num = automaton_num;
6378 gcc_assert (automaton_num == automata_num - 1);
6382 /* The functions creates automaton insns for each automata. Automaton
6383 insn is simply insn for given automaton which makes reservation
6384 only of units of the automaton. */
6386 create_ainsns (void)
6389 ainsn_t first_ainsn;
6396 for (i = 0; i < description->decls_num; i++)
6398 decl = description->decls [i];
6399 if (decl->mode == dm_insn_reserv)
6401 curr_ainsn = create_node (sizeof (struct ainsn));
6402 curr_ainsn->insn_reserv_decl = DECL_INSN_RESERV (decl);
6403 curr_ainsn->important_p = FALSE;
6404 curr_ainsn->next_ainsn = NULL;
6405 if (prev_ainsn == NULL)
6406 first_ainsn = curr_ainsn;
6408 prev_ainsn->next_ainsn = curr_ainsn;
6409 prev_ainsn = curr_ainsn;
6415 /* The function assigns automata to units according to constructions
6416 `define_automaton' in the description. */
6418 units_to_automata_distr (void)
6423 for (i = 0; i < description->decls_num; i++)
6425 decl = description->decls [i];
6426 if (decl->mode == dm_unit)
6428 if (DECL_UNIT (decl)->automaton_decl == NULL
6429 || (DECL_UNIT (decl)->automaton_decl->corresponding_automaton
6431 /* Distribute to the first automaton. */
6432 DECL_UNIT (decl)->corresponding_automaton_num = 0;
6434 DECL_UNIT (decl)->corresponding_automaton_num
6435 = (DECL_UNIT (decl)->automaton_decl
6436 ->corresponding_automaton->automaton_order_num);
6441 /* The function creates DFA(s) for fast pipeline hazards recognition
6442 after checking and simplifying IR of the description. */
6444 create_automata (void)
6446 automaton_t curr_automaton;
6447 automaton_t prev_automaton;
6449 int curr_automaton_num;
6452 if (automata_num != 0)
6454 units_to_automata_heuristic_distr ();
6455 for (prev_automaton = NULL, curr_automaton_num = 0;
6456 curr_automaton_num < automata_num;
6457 curr_automaton_num++, prev_automaton = curr_automaton)
6459 curr_automaton = create_node (sizeof (struct automaton));
6460 curr_automaton->ainsn_list = create_ainsns ();
6461 curr_automaton->corresponding_automaton_decl = NULL;
6462 curr_automaton->next_automaton = NULL;
6463 curr_automaton->automaton_order_num = curr_automaton_num;
6464 if (prev_automaton == NULL)
6465 description->first_automaton = curr_automaton;
6467 prev_automaton->next_automaton = curr_automaton;
6472 curr_automaton_num = 0;
6473 prev_automaton = NULL;
6474 for (i = 0; i < description->decls_num; i++)
6476 decl = description->decls [i];
6477 if (decl->mode == dm_automaton
6478 && DECL_AUTOMATON (decl)->automaton_is_used)
6480 curr_automaton = create_node (sizeof (struct automaton));
6481 curr_automaton->ainsn_list = create_ainsns ();
6482 curr_automaton->corresponding_automaton_decl
6483 = DECL_AUTOMATON (decl);
6484 curr_automaton->next_automaton = NULL;
6485 DECL_AUTOMATON (decl)->corresponding_automaton = curr_automaton;
6486 curr_automaton->automaton_order_num = curr_automaton_num;
6487 if (prev_automaton == NULL)
6488 description->first_automaton = curr_automaton;
6490 prev_automaton->next_automaton = curr_automaton;
6491 curr_automaton_num++;
6492 prev_automaton = curr_automaton;
6495 if (curr_automaton_num == 0)
6497 curr_automaton = create_node (sizeof (struct automaton));
6498 curr_automaton->ainsn_list = create_ainsns ();
6499 curr_automaton->corresponding_automaton_decl = NULL;
6500 curr_automaton->next_automaton = NULL;
6501 description->first_automaton = curr_automaton;
6503 units_to_automata_distr ();
6505 NDFA_time = create_ticker ();
6506 ticker_off (&NDFA_time);
6507 NDFA_to_DFA_time = create_ticker ();
6508 ticker_off (&NDFA_to_DFA_time);
6509 minimize_time = create_ticker ();
6510 ticker_off (&minimize_time);
6511 equiv_time = create_ticker ();
6512 ticker_off (&equiv_time);
6513 for (curr_automaton = description->first_automaton;
6514 curr_automaton != NULL;
6515 curr_automaton = curr_automaton->next_automaton)
6519 if (curr_automaton->corresponding_automaton_decl == NULL)
6520 fprintf (stderr, "Prepare anonymous automaton creation ... ");
6522 fprintf (stderr, "Prepare automaton `%s' creation...",
6523 curr_automaton->corresponding_automaton_decl->name);
6525 create_alt_states (curr_automaton);
6526 form_ainsn_with_same_reservs (curr_automaton);
6528 fprintf (stderr, "done\n");
6529 build_automaton (curr_automaton);
6530 enumerate_states (curr_automaton);
6531 ticker_on (&equiv_time);
6532 set_insn_equiv_classes (curr_automaton);
6533 ticker_off (&equiv_time);
6539 /* This page contains code for forming string representation of
6540 regexp. The representation is formed on IR obstack. So you should
6541 not work with IR obstack between regexp_representation and
6542 finish_regexp_representation calls. */
6544 /* This recursive function forms string representation of regexp
6545 (without tailing '\0'). */
6547 form_regexp (regexp_t regexp)
6551 switch (regexp->mode)
6553 case rm_unit: case rm_reserv:
6555 const char *name = (regexp->mode == rm_unit
6556 ? REGEXP_UNIT (regexp)->name
6557 : REGEXP_RESERV (regexp)->name);
6559 obstack_grow (&irp, name, strlen (name));
6564 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
6567 obstack_1grow (&irp, ',');
6568 form_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
6573 obstack_1grow (&irp, '(');
6574 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
6577 obstack_1grow (&irp, '+');
6578 if (REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_sequence
6579 || REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_oneof)
6580 obstack_1grow (&irp, '(');
6581 form_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
6582 if (REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_sequence
6583 || REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_oneof)
6584 obstack_1grow (&irp, ')');
6586 obstack_1grow (&irp, ')');
6590 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
6593 obstack_1grow (&irp, '|');
6594 if (REGEXP_ONEOF (regexp)->regexps[i]->mode == rm_sequence)
6595 obstack_1grow (&irp, '(');
6596 form_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
6597 if (REGEXP_ONEOF (regexp)->regexps[i]->mode == rm_sequence)
6598 obstack_1grow (&irp, ')');
6606 if (REGEXP_REPEAT (regexp)->regexp->mode == rm_sequence
6607 || REGEXP_REPEAT (regexp)->regexp->mode == rm_allof
6608 || REGEXP_REPEAT (regexp)->regexp->mode == rm_oneof)
6609 obstack_1grow (&irp, '(');
6610 form_regexp (REGEXP_REPEAT (regexp)->regexp);
6611 if (REGEXP_REPEAT (regexp)->regexp->mode == rm_sequence
6612 || REGEXP_REPEAT (regexp)->regexp->mode == rm_allof
6613 || REGEXP_REPEAT (regexp)->regexp->mode == rm_oneof)
6614 obstack_1grow (&irp, ')');
6615 sprintf (digits, "*%d", REGEXP_REPEAT (regexp)->repeat_num);
6616 obstack_grow (&irp, digits, strlen (digits));
6621 obstack_grow (&irp, NOTHING_NAME, strlen (NOTHING_NAME));
6629 /* The function returns string representation of REGEXP on IR
6632 regexp_representation (regexp_t regexp)
6634 form_regexp (regexp);
6635 obstack_1grow (&irp, '\0');
6636 return obstack_base (&irp);
6639 /* The function frees memory allocated for last formed string
6640 representation of regexp. */
6642 finish_regexp_representation (void)
6644 int length = obstack_object_size (&irp);
6646 obstack_blank_fast (&irp, -length);
6651 /* This page contains code for output PHR (pipeline hazards recognizer). */
6653 /* The function outputs minimal C type which is sufficient for
6654 representation numbers in range min_range_value and
6655 max_range_value. Because host machine and build machine may be
6656 different, we use here minimal values required by ANSI C standard
6657 instead of UCHAR_MAX, SHRT_MAX, SHRT_MIN, etc. This is a good
6661 output_range_type (FILE *f, long int min_range_value,
6662 long int max_range_value)
6664 if (min_range_value >= 0 && max_range_value <= 255)
6665 fprintf (f, "unsigned char");
6666 else if (min_range_value >= -127 && max_range_value <= 127)
6667 fprintf (f, "signed char");
6668 else if (min_range_value >= 0 && max_range_value <= 65535)
6669 fprintf (f, "unsigned short");
6670 else if (min_range_value >= -32767 && max_range_value <= 32767)
6671 fprintf (f, "short");
6676 /* The function outputs all initialization values of VECT. */
6678 output_vect (vla_hwint_t vect)
6681 size_t vect_length = VEC_length (vect_el_t, vect);
6685 if (vect_length == 0)
6686 fputs ("0 /* This is dummy el because the vect is empty */", output_file);
6688 for (i = 0; i < vect_length; i++)
6690 fprintf (output_file, "%5ld", (long) VEC_index (vect_el_t, vect, i));
6691 if (els_on_line == 10)
6694 fputs (",\n", output_file);
6696 else if (i < vect_length-1)
6697 fputs (", ", output_file);
6702 /* The following is name of the structure which represents DFA(s) for
6704 #define CHIP_NAME "DFA_chip"
6706 /* The following is name of member which represents state of a DFA for
6709 output_chip_member_name (FILE *f, automaton_t automaton)
6711 if (automaton->corresponding_automaton_decl == NULL)
6712 fprintf (f, "automaton_state_%d", automaton->automaton_order_num);
6714 fprintf (f, "%s_automaton_state",
6715 automaton->corresponding_automaton_decl->name);
6718 /* The following is name of temporary variable which stores state of a
6721 output_temp_chip_member_name (FILE *f, automaton_t automaton)
6724 output_chip_member_name (f, automaton);
6727 /* This is name of macro value which is code of pseudo_insn
6728 representing advancing cpu cycle. Its value is used as internal
6729 code unknown insn. */
6730 #define ADVANCE_CYCLE_VALUE_NAME "DFA__ADVANCE_CYCLE"
6732 /* Output name of translate vector for given automaton. */
6734 output_translate_vect_name (FILE *f, automaton_t automaton)
6736 if (automaton->corresponding_automaton_decl == NULL)
6737 fprintf (f, "translate_%d", automaton->automaton_order_num);
6739 fprintf (f, "%s_translate", automaton->corresponding_automaton_decl->name);
6742 /* Output name for simple transition table representation. */
6744 output_trans_full_vect_name (FILE *f, automaton_t automaton)
6746 if (automaton->corresponding_automaton_decl == NULL)
6747 fprintf (f, "transitions_%d", automaton->automaton_order_num);
6749 fprintf (f, "%s_transitions",
6750 automaton->corresponding_automaton_decl->name);
6753 /* Output name of comb vector of the transition table for given
6756 output_trans_comb_vect_name (FILE *f, automaton_t automaton)
6758 if (automaton->corresponding_automaton_decl == NULL)
6759 fprintf (f, "transitions_%d", automaton->automaton_order_num);
6761 fprintf (f, "%s_transitions",
6762 automaton->corresponding_automaton_decl->name);
6765 /* Output name of check vector of the transition table for given
6768 output_trans_check_vect_name (FILE *f, automaton_t automaton)
6770 if (automaton->corresponding_automaton_decl == NULL)
6771 fprintf (f, "check_%d", automaton->automaton_order_num);
6773 fprintf (f, "%s_check", automaton->corresponding_automaton_decl->name);
6776 /* Output name of base vector of the transition table for given
6779 output_trans_base_vect_name (FILE *f, automaton_t automaton)
6781 if (automaton->corresponding_automaton_decl == NULL)
6782 fprintf (f, "base_%d", automaton->automaton_order_num);
6784 fprintf (f, "%s_base", automaton->corresponding_automaton_decl->name);
6787 /* Output name of simple min issue delay table representation. */
6789 output_min_issue_delay_vect_name (FILE *f, automaton_t automaton)
6791 if (automaton->corresponding_automaton_decl == NULL)
6792 fprintf (f, "min_issue_delay_%d", automaton->automaton_order_num);
6794 fprintf (f, "%s_min_issue_delay",
6795 automaton->corresponding_automaton_decl->name);
6798 /* Output name of deadlock vector for given automaton. */
6800 output_dead_lock_vect_name (FILE *f, automaton_t automaton)
6802 if (automaton->corresponding_automaton_decl == NULL)
6803 fprintf (f, "dead_lock_%d", automaton->automaton_order_num);
6805 fprintf (f, "%s_dead_lock", automaton->corresponding_automaton_decl->name);
6808 /* Output name of reserved units table for AUTOMATON into file F. */
6810 output_reserved_units_table_name (FILE *f, automaton_t automaton)
6812 if (automaton->corresponding_automaton_decl == NULL)
6813 fprintf (f, "reserved_units_%d", automaton->automaton_order_num);
6815 fprintf (f, "%s_reserved_units",
6816 automaton->corresponding_automaton_decl->name);
6819 /* Name of the PHR interface macro. */
6820 #define CPU_UNITS_QUERY_MACRO_NAME "CPU_UNITS_QUERY"
6822 /* Names of an internal functions: */
6823 #define INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME "internal_min_issue_delay"
6825 /* This is external type of DFA(s) state. */
6826 #define STATE_TYPE_NAME "state_t"
6828 #define INTERNAL_TRANSITION_FUNC_NAME "internal_state_transition"
6830 #define INTERNAL_RESET_FUNC_NAME "internal_reset"
6832 #define INTERNAL_DEAD_LOCK_FUNC_NAME "internal_state_dead_lock_p"
6834 #define INTERNAL_INSN_LATENCY_FUNC_NAME "internal_insn_latency"
6836 /* Name of cache of insn dfa codes. */
6837 #define DFA_INSN_CODES_VARIABLE_NAME "dfa_insn_codes"
6839 /* Name of length of cache of insn dfa codes. */
6840 #define DFA_INSN_CODES_LENGTH_VARIABLE_NAME "dfa_insn_codes_length"
6842 /* Names of the PHR interface functions: */
6843 #define SIZE_FUNC_NAME "state_size"
6845 #define TRANSITION_FUNC_NAME "state_transition"
6847 #define MIN_ISSUE_DELAY_FUNC_NAME "min_issue_delay"
6849 #define MIN_INSN_CONFLICT_DELAY_FUNC_NAME "min_insn_conflict_delay"
6851 #define DEAD_LOCK_FUNC_NAME "state_dead_lock_p"
6853 #define RESET_FUNC_NAME "state_reset"
6855 #define INSN_LATENCY_FUNC_NAME "insn_latency"
6857 #define PRINT_RESERVATION_FUNC_NAME "print_reservation"
6859 #define GET_CPU_UNIT_CODE_FUNC_NAME "get_cpu_unit_code"
6861 #define CPU_UNIT_RESERVATION_P_FUNC_NAME "cpu_unit_reservation_p"
6863 #define DFA_CLEAN_INSN_CACHE_FUNC_NAME "dfa_clean_insn_cache"
6865 #define DFA_CLEAR_SINGLE_INSN_CACHE_FUNC_NAME "dfa_clear_single_insn_cache"
6867 #define DFA_START_FUNC_NAME "dfa_start"
6869 #define DFA_FINISH_FUNC_NAME "dfa_finish"
6871 /* Names of parameters of the PHR interface functions. */
6872 #define STATE_NAME "state"
6874 #define INSN_PARAMETER_NAME "insn"
6876 #define INSN2_PARAMETER_NAME "insn2"
6878 #define CHIP_PARAMETER_NAME "chip"
6880 #define FILE_PARAMETER_NAME "f"
6882 #define CPU_UNIT_NAME_PARAMETER_NAME "cpu_unit_name"
6884 #define CPU_CODE_PARAMETER_NAME "cpu_unit_code"
6886 /* Names of the variables whose values are internal insn code of rtx
6888 #define INTERNAL_INSN_CODE_NAME "insn_code"
6890 #define INTERNAL_INSN2_CODE_NAME "insn2_code"
6892 /* Names of temporary variables in some functions. */
6893 #define TEMPORARY_VARIABLE_NAME "temp"
6895 #define I_VARIABLE_NAME "i"
6897 /* Name of result variable in some functions. */
6898 #define RESULT_VARIABLE_NAME "res"
6900 /* Name of function (attribute) to translate insn into internal insn
6902 #define INTERNAL_DFA_INSN_CODE_FUNC_NAME "internal_dfa_insn_code"
6904 /* Name of function (attribute) to translate insn into internal insn
6905 code with caching. */
6906 #define DFA_INSN_CODE_FUNC_NAME "dfa_insn_code"
6908 /* Output C type which is used for representation of codes of states
6911 output_state_member_type (FILE *f, automaton_t automaton)
6913 output_range_type (f, 0, automaton->achieved_states_num);
6916 /* Output definition of the structure representing current DFA(s)
6919 output_chip_definitions (void)
6921 automaton_t automaton;
6923 fprintf (output_file, "struct %s\n{\n", CHIP_NAME);
6924 for (automaton = description->first_automaton;
6926 automaton = automaton->next_automaton)
6928 fprintf (output_file, " ");
6929 output_state_member_type (output_file, automaton);
6930 fprintf (output_file, " ");
6931 output_chip_member_name (output_file, automaton);
6932 fprintf (output_file, ";\n");
6934 fprintf (output_file, "};\n\n");
6936 fprintf (output_file, "static struct %s %s;\n\n", CHIP_NAME, CHIP_NAME);
6941 /* The function outputs translate vector of internal insn code into
6942 insn equivalence class number. The equivalence class number is
6943 used to access to table and vectors representing DFA(s). */
6945 output_translate_vect (automaton_t automaton)
6949 vla_hwint_t translate_vect;
6951 translate_vect = VEC_alloc (vect_el_t,heap, description->insns_num);
6953 for (insn_value = 0; insn_value < description->insns_num; insn_value++)
6954 /* Undefined value */
6955 VEC_quick_push (vect_el_t, translate_vect,
6956 automaton->insn_equiv_classes_num);
6958 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6959 VEC_replace (vect_el_t, translate_vect,
6960 ainsn->insn_reserv_decl->insn_num,
6961 ainsn->insn_equiv_class_num);
6963 fprintf (output_file,
6964 "/* Vector translating external insn codes to internal ones.*/\n");
6965 fprintf (output_file, "static const ");
6966 output_range_type (output_file, 0, automaton->insn_equiv_classes_num);
6967 fprintf (output_file, " ");
6968 output_translate_vect_name (output_file, automaton);
6969 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
6970 output_vect (translate_vect);
6971 fprintf (output_file, "};\n\n");
6972 VEC_free (vect_el_t,heap, translate_vect);
6975 /* The value in a table state x ainsn -> something which represents
6977 static int undefined_vect_el_value;
6979 /* The following function returns nonzero value if the best
6980 representation of the table is comb vector. */
6982 comb_vect_p (state_ainsn_table_t tab)
6984 return (2 * VEC_length (vect_el_t, tab->full_vect)
6985 > 5 * VEC_length (vect_el_t, tab->comb_vect));
6988 /* The following function creates new table for AUTOMATON. */
6989 static state_ainsn_table_t
6990 create_state_ainsn_table (automaton_t automaton)
6992 state_ainsn_table_t tab;
6993 int full_vect_length;
6996 tab = create_node (sizeof (struct state_ainsn_table));
6997 tab->automaton = automaton;
6999 tab->comb_vect = VEC_alloc (vect_el_t,heap, 10000);
7000 tab->check_vect = VEC_alloc (vect_el_t,heap, 10000);
7003 VEC_safe_grow (vect_el_t,heap, tab->base_vect,
7004 automaton->achieved_states_num);
7006 full_vect_length = (automaton->insn_equiv_classes_num
7007 * automaton->achieved_states_num);
7008 tab->full_vect = VEC_alloc (vect_el_t,heap, full_vect_length);
7009 for (i = 0; i < full_vect_length; i++)
7010 VEC_quick_push (vect_el_t, tab->full_vect, undefined_vect_el_value);
7012 tab->min_base_vect_el_value = 0;
7013 tab->max_base_vect_el_value = 0;
7014 tab->min_comb_vect_el_value = 0;
7015 tab->max_comb_vect_el_value = 0;
7019 /* The following function outputs the best C representation of the
7020 table TAB of given TABLE_NAME. */
7022 output_state_ainsn_table (state_ainsn_table_t tab, const char *table_name,
7023 void (*output_full_vect_name_func) (FILE *, automaton_t),
7024 void (*output_comb_vect_name_func) (FILE *, automaton_t),
7025 void (*output_check_vect_name_func) (FILE *, automaton_t),
7026 void (*output_base_vect_name_func) (FILE *, automaton_t))
7028 if (!comb_vect_p (tab))
7030 fprintf (output_file, "/* Vector for %s. */\n", table_name);
7031 fprintf (output_file, "static const ");
7032 output_range_type (output_file, tab->min_comb_vect_el_value,
7033 tab->max_comb_vect_el_value);
7034 fprintf (output_file, " ");
7035 (*output_full_vect_name_func) (output_file, tab->automaton);
7036 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7037 output_vect (tab->full_vect);
7038 fprintf (output_file, "};\n\n");
7042 fprintf (output_file, "/* Comb vector for %s. */\n", table_name);
7043 fprintf (output_file, "static const ");
7044 output_range_type (output_file, tab->min_comb_vect_el_value,
7045 tab->max_comb_vect_el_value);
7046 fprintf (output_file, " ");
7047 (*output_comb_vect_name_func) (output_file, tab->automaton);
7048 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7049 output_vect (tab->comb_vect);
7050 fprintf (output_file, "};\n\n");
7051 fprintf (output_file, "/* Check vector for %s. */\n", table_name);
7052 fprintf (output_file, "static const ");
7053 output_range_type (output_file, 0, tab->automaton->achieved_states_num);
7054 fprintf (output_file, " ");
7055 (*output_check_vect_name_func) (output_file, tab->automaton);
7056 fprintf (output_file, "[] = {\n");
7057 output_vect (tab->check_vect);
7058 fprintf (output_file, "};\n\n");
7059 fprintf (output_file, "/* Base vector for %s. */\n", table_name);
7060 fprintf (output_file, "static const ");
7061 output_range_type (output_file, tab->min_base_vect_el_value,
7062 tab->max_base_vect_el_value);
7063 fprintf (output_file, " ");
7064 (*output_base_vect_name_func) (output_file, tab->automaton);
7065 fprintf (output_file, "[] = {\n");
7066 output_vect (tab->base_vect);
7067 fprintf (output_file, "};\n\n");
7071 /* The following function adds vector VECT to table TAB as its line
7072 with number VECT_NUM. */
7074 add_vect (state_ainsn_table_t tab, int vect_num, vla_hwint_t vect)
7077 size_t real_vect_length;
7078 int comb_vect_index;
7079 int comb_vect_els_num;
7081 int first_unempty_vect_index;
7082 int additional_els_num;
7086 unsigned long vect_mask, comb_vect_mask;
7088 vect_length = VEC_length (vect_el_t, vect);
7089 gcc_assert (vect_length);
7090 gcc_assert (VEC_last (vect_el_t, vect) != undefined_vect_el_value);
7091 real_vect_length = tab->automaton->insn_equiv_classes_num;
7092 /* Form full vector in the table: */
7094 size_t full_base = tab->automaton->insn_equiv_classes_num * vect_num;
7095 if (VEC_length (vect_el_t, tab->full_vect) < full_base + vect_length)
7096 VEC_safe_grow (vect_el_t,heap, tab->full_vect,
7097 full_base + vect_length);
7098 for (i = 0; i < vect_length; i++)
7099 VEC_replace (vect_el_t, tab->full_vect, full_base + i,
7100 VEC_index (vect_el_t, vect, i));
7102 /* Form comb vector in the table: */
7103 gcc_assert (VEC_length (vect_el_t, tab->comb_vect)
7104 == VEC_length (vect_el_t, tab->check_vect));
7106 comb_vect_els_num = VEC_length (vect_el_t, tab->comb_vect);
7107 for (first_unempty_vect_index = 0;
7108 first_unempty_vect_index < vect_length;
7109 first_unempty_vect_index++)
7110 if (VEC_index (vect_el_t, vect, first_unempty_vect_index)
7111 != undefined_vect_el_value)
7114 /* Search for the place in comb vect for the inserted vect. */
7117 if (vect_length - first_unempty_vect_index >= SIZEOF_LONG * CHAR_BIT)
7119 for (comb_vect_index = 0;
7120 comb_vect_index < comb_vect_els_num;
7123 for (vect_index = first_unempty_vect_index;
7124 vect_index < vect_length
7125 && vect_index + comb_vect_index < comb_vect_els_num;
7127 if (VEC_index (vect_el_t, vect, vect_index)
7128 != undefined_vect_el_value
7129 && (VEC_index (vect_el_t, tab->comb_vect,
7130 vect_index + comb_vect_index)
7131 != undefined_vect_el_value))
7133 if (vect_index >= vect_length
7134 || vect_index + comb_vect_index >= comb_vect_els_num)
7142 for (vect_index = first_unempty_vect_index;
7143 vect_index < vect_length;
7146 vect_mask = vect_mask << 1;
7147 if (VEC_index (vect_el_t, vect, vect_index) != undefined_vect_el_value)
7151 /* Search for the place in comb vect for the inserted vect. */
7152 comb_vect_index = 0;
7153 if (comb_vect_els_num == 0)
7157 for (vect_index = first_unempty_vect_index;
7158 vect_index < vect_length && vect_index < comb_vect_els_num;
7161 comb_vect_mask <<= 1;
7162 if (vect_index + comb_vect_index < comb_vect_els_num
7163 && VEC_index (vect_el_t, tab->comb_vect, vect_index + comb_vect_index)
7164 != undefined_vect_el_value)
7165 comb_vect_mask |= 1;
7167 if ((vect_mask & comb_vect_mask) == 0)
7170 for (comb_vect_index = 1, i = vect_length; i < comb_vect_els_num;
7171 comb_vect_index++, i++)
7173 comb_vect_mask = (comb_vect_mask << 1) | 1;
7174 comb_vect_mask ^= (VEC_index (vect_el_t, tab->comb_vect, i)
7175 == undefined_vect_el_value);
7176 if ((vect_mask & comb_vect_mask) == 0)
7179 for ( ; comb_vect_index < comb_vect_els_num; comb_vect_index++)
7181 comb_vect_mask <<= 1;
7182 if ((vect_mask & comb_vect_mask) == 0)
7187 /* Slot was found. */
7188 additional_els_num = comb_vect_index + real_vect_length - comb_vect_els_num;
7189 if (additional_els_num < 0)
7190 additional_els_num = 0;
7191 /* Expand comb and check vectors. */
7192 vect_el = undefined_vect_el_value;
7193 no_state_value = tab->automaton->achieved_states_num;
7194 while (additional_els_num > 0)
7196 VEC_safe_push (vect_el_t,heap, tab->comb_vect, vect_el);
7197 VEC_safe_push (vect_el_t,heap, tab->check_vect, no_state_value);
7198 additional_els_num--;
7200 gcc_assert (VEC_length (vect_el_t, tab->comb_vect)
7201 >= comb_vect_index + real_vect_length);
7202 /* Fill comb and check vectors. */
7203 for (vect_index = 0; vect_index < vect_length; vect_index++)
7204 if (VEC_index (vect_el_t, vect, vect_index) != undefined_vect_el_value)
7206 vect_el_t x = VEC_index (vect_el_t, vect, vect_index);
7207 gcc_assert (VEC_index (vect_el_t, tab->comb_vect,
7208 comb_vect_index + vect_index)
7209 == undefined_vect_el_value);
7210 gcc_assert (x >= 0);
7211 if (tab->max_comb_vect_el_value < x)
7212 tab->max_comb_vect_el_value = x;
7213 if (tab->min_comb_vect_el_value > x)
7214 tab->min_comb_vect_el_value = x;
7215 VEC_replace (vect_el_t, tab->comb_vect,
7216 comb_vect_index + vect_index, x);
7217 VEC_replace (vect_el_t, tab->check_vect,
7218 comb_vect_index + vect_index, vect_num);
7220 if (tab->max_comb_vect_el_value < undefined_vect_el_value)
7221 tab->max_comb_vect_el_value = undefined_vect_el_value;
7222 if (tab->min_comb_vect_el_value > undefined_vect_el_value)
7223 tab->min_comb_vect_el_value = undefined_vect_el_value;
7224 if (tab->max_base_vect_el_value < comb_vect_index)
7225 tab->max_base_vect_el_value = comb_vect_index;
7226 if (tab->min_base_vect_el_value > comb_vect_index)
7227 tab->min_base_vect_el_value = comb_vect_index;
7229 VEC_replace (vect_el_t, tab->base_vect, vect_num, comb_vect_index);
7232 /* Return number of out arcs of STATE. */
7234 out_state_arcs_num (const_state_t state)
7240 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
7242 gcc_assert (arc->insn);
7243 if (arc->insn->first_ainsn_with_given_equivalence_num)
7249 /* Compare number of possible transitions from the states. */
7251 compare_transition_els_num (const void *state_ptr_1,
7252 const void *state_ptr_2)
7254 const int transition_els_num_1
7255 = out_state_arcs_num (*(const_state_t const*) state_ptr_1);
7256 const int transition_els_num_2
7257 = out_state_arcs_num (*(const_state_t const*) state_ptr_2);
7259 if (transition_els_num_1 < transition_els_num_2)
7261 else if (transition_els_num_1 == transition_els_num_2)
7267 /* The function adds element EL_VALUE to vector VECT for a table state
7270 add_vect_el (vla_hwint_t *vect, ainsn_t ainsn, int el_value)
7272 int equiv_class_num;
7276 equiv_class_num = ainsn->insn_equiv_class_num;
7277 for (vect_index = VEC_length (vect_el_t, *vect);
7278 vect_index <= equiv_class_num;
7280 VEC_safe_push (vect_el_t,heap, *vect, undefined_vect_el_value);
7281 VEC_replace (vect_el_t, *vect, equiv_class_num, el_value);
7284 /* This is for forming vector of states of an automaton. */
7285 static VEC(state_t,heap) *output_states_vect;
7287 /* The function is called by function pass_states. The function adds
7288 STATE to `output_states_vect'. */
7290 add_states_vect_el (state_t state)
7292 VEC_safe_push (state_t,heap, output_states_vect, state);
7295 /* Form and output vectors (comb, check, base or full vector)
7296 representing transition table of AUTOMATON. */
7298 output_trans_table (automaton_t automaton)
7302 vla_hwint_t transition_vect = 0;
7304 undefined_vect_el_value = automaton->achieved_states_num;
7305 automaton->trans_table = create_state_ainsn_table (automaton);
7306 /* Create vect of pointers to states ordered by num of transitions
7307 from the state (state with the maximum num is the first). */
7308 output_states_vect = 0;
7309 pass_states (automaton, add_states_vect_el);
7310 qsort (VEC_address (state_t, output_states_vect),
7311 VEC_length (state_t, output_states_vect),
7312 sizeof (state_t), compare_transition_els_num);
7314 for (i = 0; i < VEC_length (state_t, output_states_vect); i++)
7316 VEC_truncate (vect_el_t, transition_vect, 0);
7317 for (arc = first_out_arc (VEC_index (state_t, output_states_vect, i));
7319 arc = next_out_arc (arc))
7321 gcc_assert (arc->insn);
7322 if (arc->insn->first_ainsn_with_given_equivalence_num)
7323 add_vect_el (&transition_vect, arc->insn,
7324 arc->to_state->order_state_num);
7326 add_vect (automaton->trans_table,
7327 VEC_index (state_t, output_states_vect, i)->order_state_num,
7330 output_state_ainsn_table
7331 (automaton->trans_table, "state transitions",
7332 output_trans_full_vect_name, output_trans_comb_vect_name,
7333 output_trans_check_vect_name, output_trans_base_vect_name);
7335 VEC_free (state_t,heap, output_states_vect);
7336 VEC_free (vect_el_t,heap, transition_vect);
7339 /* The current number of passing states to find minimal issue delay
7340 value for an ainsn and state. */
7341 static int curr_state_pass_num;
7343 /* This recursive function passes states to find minimal issue delay
7344 value for AINSN. The state being visited is STATE. The function
7345 returns minimal issue delay value for AINSN in STATE or -1 if we
7346 enter into a loop. */
7348 min_issue_delay_pass_states (state_t state, ainsn_t ainsn)
7351 int min_insn_issue_delay, insn_issue_delay;
7353 if (state->state_pass_num == curr_state_pass_num
7354 || state->min_insn_issue_delay != -1)
7355 /* We've entered into a loop or already have the correct value for
7356 given state and ainsn. */
7357 return state->min_insn_issue_delay;
7358 state->state_pass_num = curr_state_pass_num;
7359 min_insn_issue_delay = -1;
7360 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
7361 if (arc->insn == ainsn)
7363 min_insn_issue_delay = 0;
7368 insn_issue_delay = min_issue_delay_pass_states (arc->to_state, ainsn);
7369 if (insn_issue_delay != -1)
7371 if (arc->insn->insn_reserv_decl
7372 == DECL_INSN_RESERV (advance_cycle_insn_decl))
7374 if (min_insn_issue_delay == -1
7375 || min_insn_issue_delay > insn_issue_delay)
7377 min_insn_issue_delay = insn_issue_delay;
7378 if (insn_issue_delay == 0)
7383 return min_insn_issue_delay;
7386 /* The function searches minimal issue delay value for AINSN in STATE.
7387 The function can return negative value if we can not issue AINSN. We
7388 will report about it later. */
7390 min_issue_delay (state_t state, ainsn_t ainsn)
7392 curr_state_pass_num++;
7393 state->min_insn_issue_delay = min_issue_delay_pass_states (state, ainsn);
7394 return state->min_insn_issue_delay;
7397 /* The function initiates code for finding minimal issue delay values.
7398 It should be called only once. */
7400 initiate_min_issue_delay_pass_states (void)
7402 curr_state_pass_num = 0;
7405 /* Form and output vectors representing minimal issue delay table of
7406 AUTOMATON. The table is state x ainsn -> minimal issue delay of
7409 output_min_issue_delay_table (automaton_t automaton)
7411 vla_hwint_t min_issue_delay_vect;
7412 vla_hwint_t compressed_min_issue_delay_vect;
7413 vect_el_t min_delay;
7415 size_t i, min_issue_delay_len;
7416 size_t compressed_min_issue_delay_len;
7419 /* Create vect of pointers to states ordered by num of transitions
7420 from the state (state with the maximum num is the first). */
7421 output_states_vect = 0;
7422 pass_states (automaton, add_states_vect_el);
7424 min_issue_delay_len = (VEC_length (state_t, output_states_vect)
7425 * automaton->insn_equiv_classes_num);
7426 min_issue_delay_vect = VEC_alloc (vect_el_t,heap, min_issue_delay_len);
7427 for (i = 0; i < min_issue_delay_len; i++)
7428 VEC_quick_push (vect_el_t, min_issue_delay_vect, 0);
7430 automaton->max_min_delay = 0;
7431 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
7432 if (ainsn->first_ainsn_with_given_equivalence_num)
7434 for (i = 0; i < VEC_length (state_t, output_states_vect); i++)
7435 VEC_index (state_t, output_states_vect, i)->min_insn_issue_delay = -1;
7436 for (i = 0; i < VEC_length (state_t, output_states_vect); i++)
7438 state_t s = VEC_index (state_t, output_states_vect, i);
7439 min_delay = min_issue_delay (s, ainsn);
7440 if (automaton->max_min_delay < min_delay)
7441 automaton->max_min_delay = min_delay;
7442 VEC_replace (vect_el_t, min_issue_delay_vect,
7444 * automaton->insn_equiv_classes_num
7445 + ainsn->insn_equiv_class_num,
7449 fprintf (output_file, "/* Vector of min issue delay of insns. */\n");
7450 fprintf (output_file, "static const ");
7451 output_range_type (output_file, 0, automaton->max_min_delay);
7452 fprintf (output_file, " ");
7453 output_min_issue_delay_vect_name (output_file, automaton);
7454 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7455 /* Compress the vector. */
7456 if (automaton->max_min_delay < 2)
7458 else if (automaton->max_min_delay < 4)
7460 else if (automaton->max_min_delay < 16)
7464 automaton->min_issue_delay_table_compression_factor = cfactor;
7466 compressed_min_issue_delay_len = (min_issue_delay_len+cfactor-1) / cfactor;
7467 compressed_min_issue_delay_vect
7468 = VEC_alloc (vect_el_t,heap, compressed_min_issue_delay_len);
7470 for (i = 0; i < compressed_min_issue_delay_len; i++)
7471 VEC_quick_push (vect_el_t, compressed_min_issue_delay_vect, 0);
7473 for (i = 0; i < min_issue_delay_len; i++)
7475 size_t ci = i / cfactor;
7476 vect_el_t x = VEC_index (vect_el_t, min_issue_delay_vect, i);
7477 vect_el_t cx = VEC_index (vect_el_t, compressed_min_issue_delay_vect, ci);
7479 cx |= x << (8 - (i % cfactor + 1) * (8 / cfactor));
7480 VEC_replace (vect_el_t, compressed_min_issue_delay_vect, ci, cx);
7482 output_vect (compressed_min_issue_delay_vect);
7483 fprintf (output_file, "};\n\n");
7484 VEC_free (state_t,heap, output_states_vect);
7485 VEC_free (vect_el_t,heap, min_issue_delay_vect);
7486 VEC_free (vect_el_t,heap, compressed_min_issue_delay_vect);
7489 /* Form and output vector representing the locked states of
7492 output_dead_lock_vect (automaton_t automaton)
7496 vla_hwint_t dead_lock_vect = 0;
7498 /* Create vect of pointers to states ordered by num of
7499 transitions from the state (state with the maximum num is the
7501 automaton->locked_states = 0;
7502 output_states_vect = 0;
7503 pass_states (automaton, add_states_vect_el);
7505 VEC_safe_grow (vect_el_t,heap, dead_lock_vect,
7506 VEC_length (state_t, output_states_vect));
7507 for (i = 0; i < VEC_length (state_t, output_states_vect); i++)
7509 state_t s = VEC_index (state_t, output_states_vect, i);
7510 arc = first_out_arc (s);
7512 if (next_out_arc (arc) == NULL
7513 && (arc->insn->insn_reserv_decl
7514 == DECL_INSN_RESERV (advance_cycle_insn_decl)))
7516 VEC_replace (vect_el_t, dead_lock_vect, s->order_state_num, 1);
7517 automaton->locked_states++;
7520 VEC_replace (vect_el_t, dead_lock_vect, s->order_state_num, 0);
7522 if (automaton->locked_states == 0)
7525 fprintf (output_file, "/* Vector for locked state flags. */\n");
7526 fprintf (output_file, "static const ");
7527 output_range_type (output_file, 0, 1);
7528 fprintf (output_file, " ");
7529 output_dead_lock_vect_name (output_file, automaton);
7530 fprintf (output_file, "[] = {\n");
7531 output_vect (dead_lock_vect);
7532 fprintf (output_file, "};\n\n");
7533 VEC_free (state_t,heap, output_states_vect);
7534 VEC_free (vect_el_t,heap, dead_lock_vect);
7537 /* Form and output vector representing reserved units of the states of
7540 output_reserved_units_table (automaton_t automaton)
7542 vla_hwint_t reserved_units_table = 0;
7543 int state_byte_size;
7544 int reserved_units_size;
7548 if (description->query_units_num == 0)
7551 /* Create vect of pointers to states. */
7552 output_states_vect = 0;
7553 pass_states (automaton, add_states_vect_el);
7554 /* Create vector. */
7555 state_byte_size = (description->query_units_num + 7) / 8;
7556 reserved_units_size = (VEC_length (state_t, output_states_vect)
7559 reserved_units_table = VEC_alloc (vect_el_t,heap, reserved_units_size);
7561 for (i = 0; i < reserved_units_size; i++)
7562 VEC_quick_push (vect_el_t, reserved_units_table, 0);
7563 for (n = 0; n < VEC_length (state_t, output_states_vect); n++)
7565 state_t s = VEC_index (state_t, output_states_vect, n);
7566 for (i = 0; i < description->units_num; i++)
7567 if (units_array [i]->query_p
7568 && first_cycle_unit_presence (s, i))
7570 int ri = (s->order_state_num * state_byte_size
7571 + units_array [i]->query_num / 8);
7572 vect_el_t x = VEC_index (vect_el_t, reserved_units_table, ri);
7574 x += 1 << (units_array [i]->query_num % 8);
7575 VEC_replace (vect_el_t, reserved_units_table, ri, x);
7578 fprintf (output_file, "\n#if %s\n", CPU_UNITS_QUERY_MACRO_NAME);
7579 fprintf (output_file, "/* Vector for reserved units of states. */\n");
7580 fprintf (output_file, "static const ");
7581 output_range_type (output_file, 0, 255);
7582 fprintf (output_file, " ");
7583 output_reserved_units_table_name (output_file, automaton);
7584 fprintf (output_file, "[] = {\n");
7585 output_vect (reserved_units_table);
7586 fprintf (output_file, "};\n#endif /* #if %s */\n\n",
7587 CPU_UNITS_QUERY_MACRO_NAME);
7589 VEC_free (state_t,heap, output_states_vect);
7590 VEC_free (vect_el_t,heap, reserved_units_table);
7593 /* The function outputs all tables representing DFA(s) used for fast
7594 pipeline hazards recognition. */
7596 output_tables (void)
7598 automaton_t automaton;
7600 initiate_min_issue_delay_pass_states ();
7601 for (automaton = description->first_automaton;
7603 automaton = automaton->next_automaton)
7605 output_translate_vect (automaton);
7606 output_trans_table (automaton);
7607 output_min_issue_delay_table (automaton);
7608 output_dead_lock_vect (automaton);
7609 output_reserved_units_table (automaton);
7611 fprintf (output_file, "\n#define %s %d\n\n", ADVANCE_CYCLE_VALUE_NAME,
7612 DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
7615 /* The function outputs definition and value of PHR interface variable
7616 `max_insn_queue_index'. Its value is not less than maximal queue
7617 length needed for the insn scheduler. */
7619 output_max_insn_queue_index_def (void)
7621 int i, max, latency;
7624 max = description->max_insn_reserv_cycles;
7625 for (i = 0; i < description->decls_num; i++)
7627 decl = description->decls [i];
7628 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
7630 latency = DECL_INSN_RESERV (decl)->default_latency;
7634 else if (decl->mode == dm_bypass)
7636 latency = DECL_BYPASS (decl)->latency;
7641 for (i = 0; (1 << i) <= max; i++)
7643 gcc_assert (i >= 0);
7644 fprintf (output_file, "\nconst int max_insn_queue_index = %d;\n\n",
7648 /* The function outputs switch cases for insn reservations using
7649 function *output_automata_list_code. */
7651 output_insn_code_cases (void (*output_automata_list_code)
7652 (automata_list_el_t))
7657 for (i = 0; i < description->decls_num; i++)
7659 decl = description->decls [i];
7660 if (decl->mode == dm_insn_reserv)
7661 DECL_INSN_RESERV (decl)->processed_p = FALSE;
7663 for (i = 0; i < description->decls_num; i++)
7665 decl = description->decls [i];
7666 if (decl->mode == dm_insn_reserv
7667 && !DECL_INSN_RESERV (decl)->processed_p)
7669 for (j = i; j < description->decls_num; j++)
7671 decl2 = description->decls [j];
7672 if (decl2->mode == dm_insn_reserv
7673 && (DECL_INSN_RESERV (decl2)->important_automata_list
7674 == DECL_INSN_RESERV (decl)->important_automata_list))
7676 DECL_INSN_RESERV (decl2)->processed_p = TRUE;
7677 fprintf (output_file, " case %d: /* %s */\n",
7678 DECL_INSN_RESERV (decl2)->insn_num,
7679 DECL_INSN_RESERV (decl2)->name);
7682 (*output_automata_list_code)
7683 (DECL_INSN_RESERV (decl)->important_automata_list);
7689 /* The function outputs a code for evaluation of a minimal delay of
7690 issue of insns which have reservations in given AUTOMATA_LIST. */
7692 output_automata_list_min_issue_delay_code (automata_list_el_t automata_list)
7694 automata_list_el_t el;
7695 automaton_t automaton;
7697 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
7699 automaton = el->automaton;
7700 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
7701 output_min_issue_delay_vect_name (output_file, automaton);
7702 fprintf (output_file,
7703 (automaton->min_issue_delay_table_compression_factor != 1
7705 output_translate_vect_name (output_file, automaton);
7706 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
7707 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7708 output_chip_member_name (output_file, automaton);
7709 fprintf (output_file, " * %d", automaton->insn_equiv_classes_num);
7710 if (automaton->min_issue_delay_table_compression_factor == 1)
7711 fprintf (output_file, "];\n");
7714 fprintf (output_file, ") / %d];\n",
7715 automaton->min_issue_delay_table_compression_factor);
7716 fprintf (output_file, " %s = (%s >> (8 - (",
7717 TEMPORARY_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
7718 output_translate_vect_name (output_file, automaton);
7720 (output_file, " [%s] %% %d + 1) * %d)) & %d;\n",
7721 INTERNAL_INSN_CODE_NAME,
7722 automaton->min_issue_delay_table_compression_factor,
7723 8 / automaton->min_issue_delay_table_compression_factor,
7724 (1 << (8 / automaton->min_issue_delay_table_compression_factor))
7727 if (el == automata_list)
7728 fprintf (output_file, " %s = %s;\n",
7729 RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
7732 fprintf (output_file, " if (%s > %s)\n",
7733 TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
7734 fprintf (output_file, " %s = %s;\n",
7735 RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
7738 fprintf (output_file, " break;\n\n");
7741 /* Output function `internal_min_issue_delay'. */
7743 output_internal_min_issue_delay_func (void)
7745 fprintf (output_file,
7746 "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
7747 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7748 CHIP_NAME, CHIP_PARAMETER_NAME);
7749 fprintf (output_file, "{\n int %s ATTRIBUTE_UNUSED;\n int %s = -1;\n",
7750 TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
7751 fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
7752 output_insn_code_cases (output_automata_list_min_issue_delay_code);
7753 fprintf (output_file,
7754 "\n default:\n %s = -1;\n break;\n }\n",
7755 RESULT_VARIABLE_NAME);
7756 fprintf (output_file, " return %s;\n", RESULT_VARIABLE_NAME);
7757 fprintf (output_file, "}\n\n");
7760 /* The function outputs a code changing state after issue of insns
7761 which have reservations in given AUTOMATA_LIST. */
7763 output_automata_list_transition_code (automata_list_el_t automata_list)
7765 automata_list_el_t el, next_el;
7767 fprintf (output_file, " {\n");
7768 if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
7769 for (el = automata_list;; el = next_el)
7771 next_el = el->next_automata_list_el;
7772 if (next_el == NULL)
7774 fprintf (output_file, " ");
7775 output_state_member_type (output_file, el->automaton);
7776 fprintf (output_file, " ");
7777 output_temp_chip_member_name (output_file, el->automaton);
7778 fprintf (output_file, ";\n");
7780 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
7781 if (comb_vect_p (el->automaton->trans_table))
7783 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
7784 output_trans_base_vect_name (output_file, el->automaton);
7785 fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
7786 output_chip_member_name (output_file, el->automaton);
7787 fprintf (output_file, "] + ");
7788 output_translate_vect_name (output_file, el->automaton);
7789 fprintf (output_file, " [%s];\n", INTERNAL_INSN_CODE_NAME);
7790 fprintf (output_file, " if (");
7791 output_trans_check_vect_name (output_file, el->automaton);
7792 fprintf (output_file, " [%s] != %s->",
7793 TEMPORARY_VARIABLE_NAME, CHIP_PARAMETER_NAME);
7794 output_chip_member_name (output_file, el->automaton);
7795 fprintf (output_file, ")\n");
7796 fprintf (output_file, " return %s (%s, %s);\n",
7797 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7798 CHIP_PARAMETER_NAME);
7799 fprintf (output_file, " else\n");
7800 fprintf (output_file, " ");
7801 if (el->next_automata_list_el != NULL)
7802 output_temp_chip_member_name (output_file, el->automaton);
7805 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7806 output_chip_member_name (output_file, el->automaton);
7808 fprintf (output_file, " = ");
7809 output_trans_comb_vect_name (output_file, el->automaton);
7810 fprintf (output_file, " [%s];\n", TEMPORARY_VARIABLE_NAME);
7814 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
7815 output_trans_full_vect_name (output_file, el->automaton);
7816 fprintf (output_file, " [");
7817 output_translate_vect_name (output_file, el->automaton);
7818 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
7819 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7820 output_chip_member_name (output_file, el->automaton);
7821 fprintf (output_file, " * %d];\n",
7822 el->automaton->insn_equiv_classes_num);
7823 fprintf (output_file, " if (%s >= %d)\n",
7824 TEMPORARY_VARIABLE_NAME, el->automaton->achieved_states_num);
7825 fprintf (output_file, " return %s (%s, %s);\n",
7826 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7827 CHIP_PARAMETER_NAME);
7828 fprintf (output_file, " else\n ");
7829 if (el->next_automata_list_el != NULL)
7830 output_temp_chip_member_name (output_file, el->automaton);
7833 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7834 output_chip_member_name (output_file, el->automaton);
7836 fprintf (output_file, " = %s;\n", TEMPORARY_VARIABLE_NAME);
7838 if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
7839 for (el = automata_list;; el = next_el)
7841 next_el = el->next_automata_list_el;
7842 if (next_el == NULL)
7844 fprintf (output_file, " %s->", CHIP_PARAMETER_NAME);
7845 output_chip_member_name (output_file, el->automaton);
7846 fprintf (output_file, " = ");
7847 output_temp_chip_member_name (output_file, el->automaton);
7848 fprintf (output_file, ";\n");
7850 fprintf (output_file, " return -1;\n");
7851 fprintf (output_file, " }\n");
7854 /* Output function `internal_state_transition'. */
7856 output_internal_trans_func (void)
7858 fprintf (output_file,
7859 "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
7860 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7861 CHIP_NAME, CHIP_PARAMETER_NAME);
7862 fprintf (output_file, "{\n int %s ATTRIBUTE_UNUSED;\n", TEMPORARY_VARIABLE_NAME);
7863 fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
7864 output_insn_code_cases (output_automata_list_transition_code);
7865 fprintf (output_file, "\n default:\n return -1;\n }\n");
7866 fprintf (output_file, "}\n\n");
7873 insn_code = dfa_insn_code (insn);
7874 if (insn_code > DFA__ADVANCE_CYCLE)
7878 insn_code = DFA__ADVANCE_CYCLE;
7880 where insn denotes INSN_NAME, insn_code denotes INSN_CODE_NAME, and
7881 code denotes CODE. */
7883 output_internal_insn_code_evaluation (const char *insn_name,
7884 const char *insn_code_name,
7887 fprintf (output_file, "\n if (%s != 0)\n {\n", insn_name);
7888 fprintf (output_file, " %s = %s (%s);\n", insn_code_name,
7889 DFA_INSN_CODE_FUNC_NAME, insn_name);
7890 fprintf (output_file, " if (%s > %s)\n return %d;\n",
7891 insn_code_name, ADVANCE_CYCLE_VALUE_NAME, code);
7892 fprintf (output_file, " }\n else\n %s = %s;\n\n",
7893 insn_code_name, ADVANCE_CYCLE_VALUE_NAME);
7897 /* This function outputs `dfa_insn_code' and its helper function
7898 `dfa_insn_code_enlarge'. */
7900 output_dfa_insn_code_func (void)
7902 /* Emacs c-mode gets really confused if there's a { or } in column 0
7903 inside a string, so don't do that. */
7904 fprintf (output_file, "\
7906 dfa_insn_code_enlarge (int uid)\n\
7910 %s = xrealloc (%s,\n\
7911 %s * sizeof(int));\n\
7912 for (; i < %s; i++)\n\
7913 %s[i] = -1;\n}\n\n",
7914 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
7915 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
7916 DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
7917 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
7918 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
7919 DFA_INSN_CODES_VARIABLE_NAME);
7920 fprintf (output_file, "\
7921 static inline int\n%s (rtx %s)\n\
7923 int uid = INSN_UID (%s);\n\
7925 DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME,
7926 INSN_PARAMETER_NAME, INTERNAL_INSN_CODE_NAME);
7928 fprintf (output_file,
7929 " if (uid >= %s)\n dfa_insn_code_enlarge (uid);\n\n",
7930 DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
7931 fprintf (output_file, " %s = %s[uid];\n",
7932 INTERNAL_INSN_CODE_NAME, DFA_INSN_CODES_VARIABLE_NAME);
7933 fprintf (output_file, "\
7939 INTERNAL_INSN_CODE_NAME,
7940 INTERNAL_INSN_CODE_NAME,
7941 INTERNAL_DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME,
7942 DFA_INSN_CODES_VARIABLE_NAME, INTERNAL_INSN_CODE_NAME);
7943 fprintf (output_file, " return %s;\n}\n\n", INTERNAL_INSN_CODE_NAME);
7946 /* The function outputs PHR interface function `state_transition'. */
7948 output_trans_func (void)
7950 fprintf (output_file, "int\n%s (%s %s, rtx %s)\n",
7951 TRANSITION_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME,
7952 INSN_PARAMETER_NAME);
7953 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
7954 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
7955 INTERNAL_INSN_CODE_NAME, -1);
7956 fprintf (output_file, " return %s (%s, %s);\n}\n\n",
7957 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, STATE_NAME);
7960 /* Output function `min_issue_delay'. */
7962 output_min_issue_delay_func (void)
7964 fprintf (output_file, "int\n%s (%s %s, rtx %s)\n",
7965 MIN_ISSUE_DELAY_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME,
7966 INSN_PARAMETER_NAME);
7967 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
7968 fprintf (output_file, "\n if (%s != 0)\n {\n", INSN_PARAMETER_NAME);
7969 fprintf (output_file, " %s = %s (%s);\n", INTERNAL_INSN_CODE_NAME,
7970 DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME);
7971 fprintf (output_file, " if (%s > %s)\n return 0;\n",
7972 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
7973 fprintf (output_file, " }\n else\n %s = %s;\n",
7974 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
7975 fprintf (output_file, "\n return %s (%s, %s);\n",
7976 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7978 fprintf (output_file, "}\n\n");
7981 /* Output function `internal_dead_lock'. */
7983 output_internal_dead_lock_func (void)
7985 automaton_t automaton;
7987 fprintf (output_file, "static int\n%s (struct %s *ARG_UNUSED (%s))\n",
7988 INTERNAL_DEAD_LOCK_FUNC_NAME, CHIP_NAME, CHIP_PARAMETER_NAME);
7989 fprintf (output_file, "{\n");
7990 for (automaton = description->first_automaton;
7992 automaton = automaton->next_automaton)
7993 if (automaton->locked_states)
7995 fprintf (output_file, " if (");
7996 output_dead_lock_vect_name (output_file, automaton);
7997 fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
7998 output_chip_member_name (output_file, automaton);
7999 fprintf (output_file, "])\n return 1/* TRUE */;\n");
8001 fprintf (output_file, " return 0/* FALSE */;\n}\n\n");
8004 /* The function outputs PHR interface function `state_dead_lock_p'. */
8006 output_dead_lock_func (void)
8008 fprintf (output_file, "int\n%s (%s %s)\n",
8009 DEAD_LOCK_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME);
8010 fprintf (output_file, "{\n return %s (%s);\n}\n\n",
8011 INTERNAL_DEAD_LOCK_FUNC_NAME, STATE_NAME);
8014 /* Output function `internal_reset'. */
8016 output_internal_reset_func (void)
8018 fprintf (output_file, "static inline void\n%s (struct %s *%s)\n",
8019 INTERNAL_RESET_FUNC_NAME, CHIP_NAME, CHIP_PARAMETER_NAME);
8020 fprintf (output_file, "{\n memset (%s, 0, sizeof (struct %s));\n}\n\n",
8021 CHIP_PARAMETER_NAME, CHIP_NAME);
8024 /* The function outputs PHR interface function `state_size'. */
8026 output_size_func (void)
8028 fprintf (output_file, "int\n%s (void)\n", SIZE_FUNC_NAME);
8029 fprintf (output_file, "{\n return sizeof (struct %s);\n}\n\n", CHIP_NAME);
8032 /* The function outputs PHR interface function `state_reset'. */
8034 output_reset_func (void)
8036 fprintf (output_file, "void\n%s (%s %s)\n",
8037 RESET_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME);
8038 fprintf (output_file, "{\n %s (%s);\n}\n\n", INTERNAL_RESET_FUNC_NAME,
8042 /* Output function `min_insn_conflict_delay'. */
8044 output_min_insn_conflict_delay_func (void)
8046 fprintf (output_file,
8047 "int\n%s (%s %s, rtx %s, rtx %s)\n",
8048 MIN_INSN_CONFLICT_DELAY_FUNC_NAME, STATE_TYPE_NAME,
8049 STATE_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8050 fprintf (output_file, "{\n struct %s %s;\n int %s, %s, transition;\n",
8051 CHIP_NAME, CHIP_NAME, INTERNAL_INSN_CODE_NAME,
8052 INTERNAL_INSN2_CODE_NAME);
8053 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8054 INTERNAL_INSN_CODE_NAME, 0);
8055 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
8056 INTERNAL_INSN2_CODE_NAME, 0);
8057 fprintf (output_file, " memcpy (&%s, %s, sizeof (%s));\n",
8058 CHIP_NAME, STATE_NAME, CHIP_NAME);
8059 fprintf (output_file, " %s (&%s);\n", INTERNAL_RESET_FUNC_NAME, CHIP_NAME);
8060 fprintf (output_file, " transition = %s (%s, &%s);\n",
8061 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME);
8062 fprintf (output_file, " gcc_assert (transition <= 0);\n");
8063 fprintf (output_file, " return %s (%s, &%s);\n",
8064 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN2_CODE_NAME,
8066 fprintf (output_file, "}\n\n");
8069 /* Output function `internal_insn_latency'. */
8071 output_internal_insn_latency_func (void)
8074 struct bypass_decl *bypass;
8076 const char *tabletype = "unsigned char";
8078 /* Find the smallest integer type that can hold all the default
8080 for (i = 0; i < description->decls_num; i++)
8081 if (description->decls[i]->mode == dm_insn_reserv)
8083 decl = description->decls[i];
8084 if (DECL_INSN_RESERV (decl)->default_latency > UCHAR_MAX
8085 && tabletype[0] != 'i') /* Don't shrink it. */
8086 tabletype = "unsigned short";
8087 if (DECL_INSN_RESERV (decl)->default_latency > USHRT_MAX)
8091 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",
8092 INTERNAL_INSN_LATENCY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8093 INTERNAL_INSN2_CODE_NAME, INSN_PARAMETER_NAME,
8094 INSN2_PARAMETER_NAME);
8095 fprintf (output_file, "{\n");
8097 if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8099 fputs (" return 0;\n}\n\n", output_file);
8103 fprintf (output_file, " static const %s default_latencies[] =\n {",
8106 for (i = 0, j = 0, col = 7; i < description->decls_num; i++)
8107 if (description->decls[i]->mode == dm_insn_reserv
8108 && description->decls[i] != advance_cycle_insn_decl)
8110 if ((col = (col+1) % 8) == 0)
8111 fputs ("\n ", output_file);
8112 decl = description->decls[i];
8113 gcc_assert (j++ == DECL_INSN_RESERV (decl)->insn_num);
8114 fprintf (output_file, "% 4d,",
8115 DECL_INSN_RESERV (decl)->default_latency);
8117 gcc_assert (j == DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
8118 fputs ("\n };\n", output_file);
8120 fprintf (output_file, " if (%s >= %s || %s >= %s)\n return 0;\n",
8121 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8122 INTERNAL_INSN2_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8124 fprintf (output_file, " switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8125 for (i = 0; i < description->decls_num; i++)
8126 if (description->decls[i]->mode == dm_insn_reserv
8127 && DECL_INSN_RESERV (description->decls[i])->bypass_list)
8129 decl = description->decls [i];
8130 fprintf (output_file,
8131 " case %d:\n switch (%s)\n {\n",
8132 DECL_INSN_RESERV (decl)->insn_num,
8133 INTERNAL_INSN2_CODE_NAME);
8134 for (bypass = DECL_INSN_RESERV (decl)->bypass_list;
8136 bypass = bypass->next)
8138 gcc_assert (bypass->in_insn_reserv->insn_num
8139 != (DECL_INSN_RESERV
8140 (advance_cycle_insn_decl)->insn_num));
8141 fprintf (output_file, " case %d:\n",
8142 bypass->in_insn_reserv->insn_num);
8143 if (bypass->bypass_guard_name == NULL)
8144 fprintf (output_file, " return %d;\n",
8148 fprintf (output_file,
8149 " if (%s (%s, %s))\n",
8150 bypass->bypass_guard_name, INSN_PARAMETER_NAME,
8151 INSN2_PARAMETER_NAME);
8152 fprintf (output_file,
8153 " return %d;\n break;\n",
8157 fputs (" }\n break;\n", output_file);
8160 fprintf (output_file, " }\n return default_latencies[%s];\n}\n\n",
8161 INTERNAL_INSN_CODE_NAME);
8164 /* The function outputs PHR interface function `insn_latency'. */
8166 output_insn_latency_func (void)
8168 fprintf (output_file, "int\n%s (rtx %s, rtx %s)\n",
8169 INSN_LATENCY_FUNC_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8170 fprintf (output_file, "{\n int %s, %s;\n",
8171 INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME);
8172 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8173 INTERNAL_INSN_CODE_NAME, 0);
8174 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
8175 INTERNAL_INSN2_CODE_NAME, 0);
8176 fprintf (output_file, " return %s (%s, %s, %s, %s);\n}\n\n",
8177 INTERNAL_INSN_LATENCY_FUNC_NAME,
8178 INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME,
8179 INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8182 /* The function outputs PHR interface function `print_reservation'. */
8184 output_print_reservation_func (void)
8189 fprintf (output_file,
8190 "void\n%s (FILE *%s, rtx %s ATTRIBUTE_UNUSED)\n{\n",
8191 PRINT_RESERVATION_FUNC_NAME, FILE_PARAMETER_NAME,
8192 INSN_PARAMETER_NAME);
8194 if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8196 fprintf (output_file, " fputs (\"%s\", %s);\n}\n\n",
8197 NOTHING_NAME, FILE_PARAMETER_NAME);
8202 fputs (" static const char *const reservation_names[] =\n {",
8205 for (i = 0, j = 0; i < description->decls_num; i++)
8207 decl = description->decls [i];
8208 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
8210 gcc_assert (j == DECL_INSN_RESERV (decl)->insn_num);
8213 fprintf (output_file, "\n \"%s\",",
8214 regexp_representation (DECL_INSN_RESERV (decl)->regexp));
8215 finish_regexp_representation ();
8218 gcc_assert (j == DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
8220 fprintf (output_file, "\n \"%s\"\n };\n int %s;\n\n",
8221 NOTHING_NAME, INTERNAL_INSN_CODE_NAME);
8223 fprintf (output_file, " if (%s == 0)\n %s = %s;\n",
8224 INSN_PARAMETER_NAME,
8225 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8226 fprintf (output_file, " else\n\
8232 INTERNAL_INSN_CODE_NAME, DFA_INSN_CODE_FUNC_NAME,
8233 INSN_PARAMETER_NAME,
8234 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8235 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8237 fprintf (output_file, " fputs (reservation_names[%s], %s);\n}\n\n",
8238 INTERNAL_INSN_CODE_NAME, FILE_PARAMETER_NAME);
8241 /* The following function is used to sort unit declaration by their
8244 units_cmp (const void *unit1, const void *unit2)
8246 const_unit_decl_t const u1 = *(const_unit_decl_t const*) unit1;
8247 const_unit_decl_t const u2 = *(const_unit_decl_t const*) unit2;
8249 return strcmp (u1->name, u2->name);
8252 /* The following macro value is name of struct containing unit name
8254 #define NAME_CODE_STRUCT_NAME "name_code"
8256 /* The following macro value is name of table of struct name_code. */
8257 #define NAME_CODE_TABLE_NAME "name_code_table"
8259 /* The following macro values are member names for struct name_code. */
8260 #define NAME_MEMBER_NAME "name"
8261 #define CODE_MEMBER_NAME "code"
8263 /* The following macro values are local variable names for function
8264 `get_cpu_unit_code'. */
8265 #define CMP_VARIABLE_NAME "cmp"
8266 #define LOW_VARIABLE_NAME "l"
8267 #define MIDDLE_VARIABLE_NAME "m"
8268 #define HIGH_VARIABLE_NAME "h"
8270 /* The following function outputs function to obtain internal cpu unit
8271 code by the cpu unit name. */
8273 output_get_cpu_unit_code_func (void)
8278 fprintf (output_file, "int\n%s (const char *%s)\n",
8279 GET_CPU_UNIT_CODE_FUNC_NAME, CPU_UNIT_NAME_PARAMETER_NAME);
8280 fprintf (output_file, "{\n struct %s {const char *%s; int %s;};\n",
8281 NAME_CODE_STRUCT_NAME, NAME_MEMBER_NAME, CODE_MEMBER_NAME);
8282 fprintf (output_file, " int %s, %s, %s, %s;\n", CMP_VARIABLE_NAME,
8283 LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8284 fprintf (output_file, " static struct %s %s [] =\n {\n",
8285 NAME_CODE_STRUCT_NAME, NAME_CODE_TABLE_NAME);
8286 units = xmalloc (sizeof (unit_decl_t) * description->units_num);
8287 memcpy (units, units_array, sizeof (unit_decl_t) * description->units_num);
8288 qsort (units, description->units_num, sizeof (unit_decl_t), units_cmp);
8289 for (i = 0; i < description->units_num; i++)
8290 if (units [i]->query_p)
8291 fprintf (output_file, " {\"%s\", %d},\n",
8292 units[i]->name, units[i]->query_num);
8293 fprintf (output_file, " };\n\n");
8294 fprintf (output_file, " /* The following is binary search: */\n");
8295 fprintf (output_file, " %s = 0;\n", LOW_VARIABLE_NAME);
8296 fprintf (output_file, " %s = sizeof (%s) / sizeof (struct %s) - 1;\n",
8297 HIGH_VARIABLE_NAME, NAME_CODE_TABLE_NAME, NAME_CODE_STRUCT_NAME);
8298 fprintf (output_file, " while (%s <= %s)\n {\n",
8299 LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8300 fprintf (output_file, " %s = (%s + %s) / 2;\n",
8301 MIDDLE_VARIABLE_NAME, LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8302 fprintf (output_file, " %s = strcmp (%s, %s [%s].%s);\n",
8303 CMP_VARIABLE_NAME, CPU_UNIT_NAME_PARAMETER_NAME,
8304 NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, NAME_MEMBER_NAME);
8305 fprintf (output_file, " if (%s < 0)\n", CMP_VARIABLE_NAME);
8306 fprintf (output_file, " %s = %s - 1;\n",
8307 HIGH_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
8308 fprintf (output_file, " else if (%s > 0)\n", CMP_VARIABLE_NAME);
8309 fprintf (output_file, " %s = %s + 1;\n",
8310 LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
8311 fprintf (output_file, " else\n");
8312 fprintf (output_file, " return %s [%s].%s;\n }\n",
8313 NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, CODE_MEMBER_NAME);
8314 fprintf (output_file, " return -1;\n}\n\n");
8318 /* The following function outputs function to check reservation of cpu
8319 unit (its internal code will be passed as the function argument) in
8322 output_cpu_unit_reservation_p (void)
8324 automaton_t automaton;
8326 fprintf (output_file, "int\n%s (%s %s, int %s)\n",
8327 CPU_UNIT_RESERVATION_P_FUNC_NAME,
8328 STATE_TYPE_NAME, STATE_NAME,
8329 CPU_CODE_PARAMETER_NAME);
8330 fprintf (output_file, "{\n gcc_assert (%s >= 0 && %s < %d);\n",
8331 CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME,
8332 description->query_units_num);
8333 if (description->query_units_num > 0)
8334 for (automaton = description->first_automaton;
8336 automaton = automaton->next_automaton)
8338 fprintf (output_file, " if ((");
8339 output_reserved_units_table_name (output_file, automaton);
8340 fprintf (output_file, " [((struct %s *) %s)->", CHIP_NAME, STATE_NAME);
8341 output_chip_member_name (output_file, automaton);
8342 fprintf (output_file, " * %d + %s / 8] >> (%s %% 8)) & 1)\n",
8343 (description->query_units_num + 7) / 8,
8344 CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME);
8345 fprintf (output_file, " return 1;\n");
8347 fprintf (output_file, " return 0;\n}\n\n");
8350 /* The function outputs PHR interface functions `dfa_clean_insn_cache'
8351 and 'dfa_clear_single_insn_cache'. */
8353 output_dfa_clean_insn_cache_func (void)
8355 fprintf (output_file,
8356 "void\n%s (void)\n{\n int %s;\n\n",
8357 DFA_CLEAN_INSN_CACHE_FUNC_NAME, I_VARIABLE_NAME);
8358 fprintf (output_file,
8359 " for (%s = 0; %s < %s; %s++)\n %s [%s] = -1;\n}\n\n",
8360 I_VARIABLE_NAME, I_VARIABLE_NAME,
8361 DFA_INSN_CODES_LENGTH_VARIABLE_NAME, I_VARIABLE_NAME,
8362 DFA_INSN_CODES_VARIABLE_NAME, I_VARIABLE_NAME);
8364 fprintf (output_file,
8365 "void\n%s (rtx %s)\n{\n int %s;\n\n",
8366 DFA_CLEAR_SINGLE_INSN_CACHE_FUNC_NAME, INSN_PARAMETER_NAME,
8368 fprintf (output_file,
8369 " %s = INSN_UID (%s);\n if (%s < %s)\n %s [%s] = -1;\n}\n\n",
8370 I_VARIABLE_NAME, INSN_PARAMETER_NAME, I_VARIABLE_NAME,
8371 DFA_INSN_CODES_LENGTH_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
8375 /* The function outputs PHR interface function `dfa_start'. */
8377 output_dfa_start_func (void)
8379 fprintf (output_file,
8380 "void\n%s (void)\n{\n %s = get_max_uid ();\n",
8381 DFA_START_FUNC_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8382 fprintf (output_file, " %s = xmalloc (%s * sizeof (int));\n",
8383 DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8384 fprintf (output_file, " %s ();\n}\n\n", DFA_CLEAN_INSN_CACHE_FUNC_NAME);
8387 /* The function outputs PHR interface function `dfa_finish'. */
8389 output_dfa_finish_func (void)
8391 fprintf (output_file, "void\n%s (void)\n{\n free (%s);\n}\n\n",
8392 DFA_FINISH_FUNC_NAME, DFA_INSN_CODES_VARIABLE_NAME);
8397 /* The page contains code for output description file (readable
8398 representation of original description and generated DFA(s). */
8400 /* The function outputs string representation of IR reservation. */
8402 output_regexp (regexp_t regexp)
8404 fprintf (output_description_file, "%s", regexp_representation (regexp));
8405 finish_regexp_representation ();
8408 /* Output names of units in LIST separated by comma. */
8410 output_unit_set_el_list (unit_set_el_t list)
8414 for (el = list; el != NULL; el = el->next_unit_set_el)
8417 fprintf (output_description_file, ", ");
8418 fprintf (output_description_file, "%s", el->unit_decl->name);
8422 /* Output patterns in LIST separated by comma. */
8424 output_pattern_set_el_list (pattern_set_el_t list)
8426 pattern_set_el_t el;
8429 for (el = list; el != NULL; el = el->next_pattern_set_el)
8432 fprintf (output_description_file, ", ");
8433 for (i = 0; i < el->units_num; i++)
8434 fprintf (output_description_file, (i == 0 ? "%s" : " %s"),
8435 el->unit_decls [i]->name);
8439 /* The function outputs string representation of IR define_reservation
8440 and define_insn_reservation. */
8442 output_description (void)
8447 for (i = 0; i < description->decls_num; i++)
8449 decl = description->decls [i];
8450 if (decl->mode == dm_unit)
8452 if (DECL_UNIT (decl)->excl_list != NULL)
8454 fprintf (output_description_file, "unit %s exlusion_set: ",
8455 DECL_UNIT (decl)->name);
8456 output_unit_set_el_list (DECL_UNIT (decl)->excl_list);
8457 fprintf (output_description_file, "\n");
8459 if (DECL_UNIT (decl)->presence_list != NULL)
8461 fprintf (output_description_file, "unit %s presence_set: ",
8462 DECL_UNIT (decl)->name);
8463 output_pattern_set_el_list (DECL_UNIT (decl)->presence_list);
8464 fprintf (output_description_file, "\n");
8466 if (DECL_UNIT (decl)->final_presence_list != NULL)
8468 fprintf (output_description_file, "unit %s final_presence_set: ",
8469 DECL_UNIT (decl)->name);
8470 output_pattern_set_el_list
8471 (DECL_UNIT (decl)->final_presence_list);
8472 fprintf (output_description_file, "\n");
8474 if (DECL_UNIT (decl)->absence_list != NULL)
8476 fprintf (output_description_file, "unit %s absence_set: ",
8477 DECL_UNIT (decl)->name);
8478 output_pattern_set_el_list (DECL_UNIT (decl)->absence_list);
8479 fprintf (output_description_file, "\n");
8481 if (DECL_UNIT (decl)->final_absence_list != NULL)
8483 fprintf (output_description_file, "unit %s final_absence_set: ",
8484 DECL_UNIT (decl)->name);
8485 output_pattern_set_el_list
8486 (DECL_UNIT (decl)->final_absence_list);
8487 fprintf (output_description_file, "\n");
8491 fprintf (output_description_file, "\n");
8492 for (i = 0; i < description->decls_num; i++)
8494 decl = description->decls [i];
8495 if (decl->mode == dm_reserv)
8497 fprintf (output_description_file, "reservation %s: ",
8498 DECL_RESERV (decl)->name);
8499 output_regexp (DECL_RESERV (decl)->regexp);
8500 fprintf (output_description_file, "\n");
8502 else if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
8504 fprintf (output_description_file, "insn reservation %s ",
8505 DECL_INSN_RESERV (decl)->name);
8506 print_rtl (output_description_file,
8507 DECL_INSN_RESERV (decl)->condexp);
8508 fprintf (output_description_file, ": ");
8509 output_regexp (DECL_INSN_RESERV (decl)->regexp);
8510 fprintf (output_description_file, "\n");
8512 else if (decl->mode == dm_bypass)
8513 fprintf (output_description_file, "bypass %d %s %s\n",
8514 DECL_BYPASS (decl)->latency,
8515 DECL_BYPASS (decl)->out_insn_name,
8516 DECL_BYPASS (decl)->in_insn_name);
8518 fprintf (output_description_file, "\n\f\n");
8521 /* The function outputs name of AUTOMATON. */
8523 output_automaton_name (FILE *f, automaton_t automaton)
8525 if (automaton->corresponding_automaton_decl == NULL)
8526 fprintf (f, "#%d", automaton->automaton_order_num);
8528 fprintf (f, "`%s'", automaton->corresponding_automaton_decl->name);
8531 /* Maximal length of line for pretty printing into description
8533 #define MAX_LINE_LENGTH 70
8535 /* The function outputs units name belonging to AUTOMATON. */
8537 output_automaton_units (automaton_t automaton)
8541 int curr_line_length;
8542 int there_is_an_automaton_unit;
8545 fprintf (output_description_file, "\n Corresponding units:\n");
8546 fprintf (output_description_file, " ");
8547 curr_line_length = 4;
8548 there_is_an_automaton_unit = 0;
8549 for (i = 0; i < description->decls_num; i++)
8551 decl = description->decls [i];
8552 if (decl->mode == dm_unit
8553 && (DECL_UNIT (decl)->corresponding_automaton_num
8554 == automaton->automaton_order_num))
8556 there_is_an_automaton_unit = 1;
8557 name = DECL_UNIT (decl)->name;
8558 if (curr_line_length + strlen (name) + 1 > MAX_LINE_LENGTH )
8560 curr_line_length = strlen (name) + 4;
8561 fprintf (output_description_file, "\n ");
8565 curr_line_length += strlen (name) + 1;
8566 fprintf (output_description_file, " ");
8568 fprintf (output_description_file, "%s", name);
8571 if (!there_is_an_automaton_unit)
8572 fprintf (output_description_file, "<None>");
8573 fprintf (output_description_file, "\n\n");
8576 /* The following variable is used for forming array of all possible cpu unit
8577 reservations described by the current DFA state. */
8578 static VEC(reserv_sets_t,heap) *state_reservs;
8580 /* The function forms `state_reservs' for STATE. */
8582 add_state_reservs (state_t state)
8584 alt_state_t curr_alt_state;
8586 if (state->component_states != NULL)
8587 for (curr_alt_state = state->component_states;
8588 curr_alt_state != NULL;
8589 curr_alt_state = curr_alt_state->next_sorted_alt_state)
8590 add_state_reservs (curr_alt_state->state);
8592 VEC_safe_push (reserv_sets_t,heap, state_reservs, state->reservs);
8595 /* The function outputs readable representation of all out arcs of
8598 output_state_arcs (state_t state)
8602 const char *insn_name;
8603 int curr_line_length;
8605 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
8608 gcc_assert (ainsn->first_insn_with_same_reservs);
8609 fprintf (output_description_file, " ");
8610 curr_line_length = 7;
8611 fprintf (output_description_file, "%2d: ", ainsn->insn_equiv_class_num);
8614 insn_name = ainsn->insn_reserv_decl->name;
8615 if (curr_line_length + strlen (insn_name) > MAX_LINE_LENGTH)
8617 if (ainsn != arc->insn)
8619 fprintf (output_description_file, ",\n ");
8620 curr_line_length = strlen (insn_name) + 6;
8623 curr_line_length += strlen (insn_name);
8627 curr_line_length += strlen (insn_name);
8628 if (ainsn != arc->insn)
8630 curr_line_length += 2;
8631 fprintf (output_description_file, ", ");
8634 fprintf (output_description_file, "%s", insn_name);
8635 ainsn = ainsn->next_same_reservs_insn;
8637 while (ainsn != NULL);
8638 fprintf (output_description_file, " %d \n",
8639 arc->to_state->order_state_num);
8641 fprintf (output_description_file, "\n");
8644 /* The following function is used for sorting possible cpu unit
8645 reservation of a DFA state. */
8647 state_reservs_cmp (const void *reservs_ptr_1, const void *reservs_ptr_2)
8649 return reserv_sets_cmp (*(const_reserv_sets_t const*) reservs_ptr_1,
8650 *(const_reserv_sets_t const*) reservs_ptr_2);
8653 /* The following function is used for sorting possible cpu unit
8654 reservation of a DFA state. */
8656 remove_state_duplicate_reservs (void)
8660 for (i = 1, j = 0; i < VEC_length (reserv_sets_t, state_reservs); i++)
8661 if (reserv_sets_cmp (VEC_index (reserv_sets_t, state_reservs, j),
8662 VEC_index (reserv_sets_t, state_reservs, i)))
8665 VEC_replace (reserv_sets_t, state_reservs, j,
8666 VEC_index (reserv_sets_t, state_reservs, i));
8668 VEC_truncate (reserv_sets_t, state_reservs, j + 1);
8671 /* The following function output readable representation of DFA(s)
8672 state used for fast recognition of pipeline hazards. State is
8673 described by possible (current and scheduled) cpu unit
8676 output_state (state_t state)
8682 fprintf (output_description_file, " State #%d", state->order_state_num);
8683 fprintf (output_description_file,
8684 state->new_cycle_p ? " (new cycle)\n" : "\n");
8685 add_state_reservs (state);
8686 qsort (VEC_address (reserv_sets_t, state_reservs),
8687 VEC_length (reserv_sets_t, state_reservs),
8688 sizeof (reserv_sets_t), state_reservs_cmp);
8689 remove_state_duplicate_reservs ();
8690 for (i = 1; i < VEC_length (reserv_sets_t, state_reservs); i++)
8692 fprintf (output_description_file, " ");
8693 output_reserv_sets (output_description_file,
8694 VEC_index (reserv_sets_t, state_reservs, i));
8695 fprintf (output_description_file, "\n");
8697 fprintf (output_description_file, "\n");
8698 output_state_arcs (state);
8699 VEC_free (reserv_sets_t,heap, state_reservs);
8702 /* The following function output readable representation of
8703 DFAs used for fast recognition of pipeline hazards. */
8705 output_automaton_descriptions (void)
8707 automaton_t automaton;
8709 for (automaton = description->first_automaton;
8711 automaton = automaton->next_automaton)
8713 fprintf (output_description_file, "\nAutomaton ");
8714 output_automaton_name (output_description_file, automaton);
8715 fprintf (output_description_file, "\n");
8716 output_automaton_units (automaton);
8717 pass_states (automaton, output_state);
8723 /* The page contains top level function for generation DFA(s) used for
8726 /* The function outputs statistics about work of different phases of
8729 output_statistics (FILE *f)
8731 automaton_t automaton;
8734 int transition_comb_vect_els = 0;
8735 int transition_full_vect_els = 0;
8736 int min_issue_delay_vect_els = 0;
8737 int locked_states = 0;
8740 for (automaton = description->first_automaton;
8742 automaton = automaton->next_automaton)
8744 fprintf (f, "\nAutomaton ");
8745 output_automaton_name (f, automaton);
8746 fprintf (f, "\n %5d NDFA states, %5d NDFA arcs\n",
8747 automaton->NDFA_states_num, automaton->NDFA_arcs_num);
8748 fprintf (f, " %5d DFA states, %5d DFA arcs\n",
8749 automaton->DFA_states_num, automaton->DFA_arcs_num);
8750 states_num = automaton->DFA_states_num;
8751 if (!no_minimization_flag)
8753 fprintf (f, " %5d minimal DFA states, %5d minimal DFA arcs\n",
8754 automaton->minimal_DFA_states_num,
8755 automaton->minimal_DFA_arcs_num);
8756 states_num = automaton->minimal_DFA_states_num;
8758 fprintf (f, " %5d all insns %5d insn equivalence classes\n",
8759 description->insns_num, automaton->insn_equiv_classes_num);
8760 fprintf (f, " %d locked states\n", automaton->locked_states);
8763 (f, "%5ld transition comb vector els, %5ld trans table els: %s\n",
8764 (long) VEC_length (vect_el_t, automaton->trans_table->comb_vect),
8765 (long) VEC_length (vect_el_t, automaton->trans_table->full_vect),
8766 (comb_vect_p (automaton->trans_table)
8767 ? "use comb vect" : "use simple vect"));
8769 (f, "%5ld min delay table els, compression factor %d\n",
8770 (long) states_num * automaton->insn_equiv_classes_num,
8771 automaton->min_issue_delay_table_compression_factor);
8772 transition_comb_vect_els
8773 += VEC_length (vect_el_t, automaton->trans_table->comb_vect);
8774 transition_full_vect_els
8775 += VEC_length (vect_el_t, automaton->trans_table->full_vect);
8776 min_issue_delay_vect_els
8777 += states_num * automaton->insn_equiv_classes_num;
8779 += automaton->locked_states;
8783 fprintf (f, "\n%5d all allocated states, %5d all allocated arcs\n",
8784 allocated_states_num, allocated_arcs_num);
8785 fprintf (f, "%5d all allocated alternative states\n",
8786 allocated_alt_states_num);
8787 fprintf (f, "%5d all transition comb vector els, %5d all trans table els\n",
8788 transition_comb_vect_els, transition_full_vect_els);
8789 fprintf (f, "%5d all min delay table els\n", min_issue_delay_vect_els);
8790 fprintf (f, "%5d all locked states\n", locked_states);
8794 /* The function output times of work of different phases of DFA
8797 output_time_statistics (FILE *f)
8799 fprintf (f, "\n transformation: ");
8800 print_active_time (f, transform_time);
8801 fprintf (f, (!ndfa_flag ? ", building DFA: " : ", building NDFA: "));
8802 print_active_time (f, NDFA_time);
8805 fprintf (f, ", NDFA -> DFA: ");
8806 print_active_time (f, NDFA_to_DFA_time);
8808 fprintf (f, "\n DFA minimization: ");
8809 print_active_time (f, minimize_time);
8810 fprintf (f, ", making insn equivalence: ");
8811 print_active_time (f, equiv_time);
8812 fprintf (f, "\n all automaton generation: ");
8813 print_active_time (f, automaton_generation_time);
8814 fprintf (f, ", output: ");
8815 print_active_time (f, output_time);
8819 /* The function generates DFA (deterministic finite state automaton)
8820 for fast recognition of pipeline hazards. No errors during
8821 checking must be fixed before this function call. */
8825 automata_num = split_argument;
8826 if (description->units_num < automata_num)
8827 automata_num = description->units_num;
8830 initiate_automata_lists ();
8831 initiate_pass_states ();
8832 initiate_excl_sets ();
8833 initiate_presence_absence_pattern_sets ();
8834 automaton_generation_time = create_ticker ();
8836 ticker_off (&automaton_generation_time);
8841 /* This page mainly contains top level functions of pipeline hazards
8842 description translator. */
8844 /* The following macro value is suffix of name of description file of
8845 pipeline hazards description translator. */
8846 #define STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX ".dfa"
8848 /* The function returns suffix of given file name. The returned
8849 string can not be changed. */
8851 file_name_suffix (const char *file_name)
8853 const char *last_period;
8855 for (last_period = NULL; *file_name != '\0'; file_name++)
8856 if (*file_name == '.')
8857 last_period = file_name;
8858 return (last_period == NULL ? file_name : last_period);
8861 /* The function returns base name of given file name, i.e. pointer to
8862 first char after last `/' (or `\' for WIN32) in given file name,
8863 given file name itself if the directory name is absent. The
8864 returned string can not be changed. */
8866 base_file_name (const char *file_name)
8868 int directory_name_length;
8870 directory_name_length = strlen (file_name);
8872 while (directory_name_length >= 0 && file_name[directory_name_length] != '/'
8873 && file_name[directory_name_length] != '\\')
8875 while (directory_name_length >= 0 && file_name[directory_name_length] != '/')
8877 directory_name_length--;
8878 return file_name + directory_name_length + 1;
8881 /* The following is top level function to initialize the work of
8882 pipeline hazards description translator. */
8884 initiate_automaton_gen (int argc, char **argv)
8886 const char *base_name;
8890 split_argument = 0; /* default value */
8891 no_minimization_flag = 0;
8897 for (i = 2; i < argc; i++)
8898 if (strcmp (argv [i], NO_MINIMIZATION_OPTION) == 0)
8899 no_minimization_flag = 1;
8900 else if (strcmp (argv [i], TIME_OPTION) == 0)
8902 else if (strcmp (argv [i], STATS_OPTION) == 0)
8904 else if (strcmp (argv [i], V_OPTION) == 0)
8906 else if (strcmp (argv [i], W_OPTION) == 0)
8908 else if (strcmp (argv [i], NDFA_OPTION) == 0)
8910 else if (strcmp (argv [i], PROGRESS_OPTION) == 0)
8912 else if (strcmp (argv [i], "-split") == 0)
8915 fatal ("-split has no argument.");
8916 fatal ("option `-split' has not been implemented yet\n");
8917 /* split_argument = atoi (argument_vect [i + 1]); */
8920 /* Initialize IR storage. */
8921 obstack_init (&irp);
8922 initiate_automaton_decl_table ();
8923 initiate_insn_decl_table ();
8924 initiate_decl_table ();
8925 output_file = stdout;
8926 output_description_file = NULL;
8927 base_name = base_file_name (argv[1]);
8928 obstack_grow (&irp, base_name,
8929 strlen (base_name) - strlen (file_name_suffix (base_name)));
8930 obstack_grow (&irp, STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX,
8931 strlen (STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX) + 1);
8932 obstack_1grow (&irp, '\0');
8933 output_description_file_name = obstack_base (&irp);
8934 obstack_finish (&irp);
8937 /* The following function checks existence at least one arc marked by
8940 check_automata_insn_issues (void)
8942 automaton_t automaton;
8943 ainsn_t ainsn, reserv_ainsn;
8945 for (automaton = description->first_automaton;
8947 automaton = automaton->next_automaton)
8949 for (ainsn = automaton->ainsn_list;
8951 ainsn = ainsn->next_ainsn)
8952 if (ainsn->first_insn_with_same_reservs && !ainsn->arc_exists_p)
8954 for (reserv_ainsn = ainsn;
8955 reserv_ainsn != NULL;
8956 reserv_ainsn = reserv_ainsn->next_same_reservs_insn)
8957 if (automaton->corresponding_automaton_decl != NULL)
8960 error ("Automaton `%s': Insn `%s' will never be issued",
8961 automaton->corresponding_automaton_decl->name,
8962 reserv_ainsn->insn_reserv_decl->name);
8965 (0, "Automaton `%s': Insn `%s' will never be issued",
8966 automaton->corresponding_automaton_decl->name,
8967 reserv_ainsn->insn_reserv_decl->name);
8972 error ("Insn `%s' will never be issued",
8973 reserv_ainsn->insn_reserv_decl->name);
8975 warning (0, "Insn `%s' will never be issued",
8976 reserv_ainsn->insn_reserv_decl->name);
8982 /* The following vla is used for storing pointers to all achieved
8984 static VEC(state_t,heap) *automaton_states;
8986 /* This function is called by function pass_states to add an achieved
8989 add_automaton_state (state_t state)
8991 VEC_safe_push (state_t,heap, automaton_states, state);
8994 /* The following function forms list of important automata (whose
8995 states may be changed after the insn issue) for each insn. */
8997 form_important_insn_automata_lists (void)
8999 automaton_t automaton;
9006 automaton_states = 0;
9007 /* Mark important ainsns. */
9008 for (automaton = description->first_automaton;
9010 automaton = automaton->next_automaton)
9012 VEC_truncate (state_t, automaton_states, 0);
9013 pass_states (automaton, add_automaton_state);
9014 for (n = 0; n < VEC_length (state_t, automaton_states); n++)
9016 state_t s = VEC_index (state_t, automaton_states, n);
9017 for (arc = first_out_arc (s);
9019 arc = next_out_arc (arc))
9020 if (arc->to_state != s)
9022 gcc_assert (arc->insn->first_insn_with_same_reservs);
9023 for (ainsn = arc->insn;
9025 ainsn = ainsn->next_same_reservs_insn)
9026 ainsn->important_p = TRUE;
9030 VEC_free (state_t,heap, automaton_states);
9032 /* Create automata sets for the insns. */
9033 for (i = 0; i < description->decls_num; i++)
9035 decl = description->decls [i];
9036 if (decl->mode == dm_insn_reserv)
9038 automata_list_start ();
9039 for (automaton = description->first_automaton;
9041 automaton = automaton->next_automaton)
9042 for (ainsn = automaton->ainsn_list;
9044 ainsn = ainsn->next_ainsn)
9045 if (ainsn->important_p
9046 && ainsn->insn_reserv_decl == DECL_INSN_RESERV (decl))
9048 automata_list_add (automaton);
9051 DECL_INSN_RESERV (decl)->important_automata_list
9052 = automata_list_finish ();
9058 /* The following is top level function to generate automat(a,on) for
9059 fast recognition of pipeline hazards. */
9061 expand_automata (void)
9065 description = create_node (sizeof (struct description)
9066 /* One entry for cycle advancing insn. */
9067 + sizeof (decl_t) * VEC_length (decl_t, decls));
9068 description->decls_num = VEC_length (decl_t, decls);
9069 description->query_units_num = 0;
9070 for (i = 0; i < description->decls_num; i++)
9072 description->decls [i] = VEC_index (decl_t, decls, i);
9073 if (description->decls [i]->mode == dm_unit
9074 && DECL_UNIT (description->decls [i])->query_p)
9075 DECL_UNIT (description->decls [i])->query_num
9076 = description->query_units_num++;
9078 all_time = create_ticker ();
9079 check_time = create_ticker ();
9081 fprintf (stderr, "Check description...");
9082 check_all_description ();
9084 fprintf (stderr, "done\n");
9085 ticker_off (&check_time);
9086 generation_time = create_ticker ();
9089 transform_insn_regexps ();
9090 check_unit_distributions_to_automata ();
9095 check_automata_insn_issues ();
9099 form_important_insn_automata_lists ();
9101 ticker_off (&generation_time);
9104 /* The following is top level function to output PHR and to finish
9105 work with pipeline description translator. */
9107 write_automata (void)
9109 output_time = create_ticker ();
9111 fprintf (stderr, "Forming and outputting automata tables...");
9115 fprintf (stderr, "done\n");
9116 fprintf (stderr, "Output functions to work with automata...");
9118 output_chip_definitions ();
9119 output_max_insn_queue_index_def ();
9120 output_internal_min_issue_delay_func ();
9121 output_internal_trans_func ();
9122 /* Cache of insn dfa codes: */
9123 fprintf (output_file, "\nstatic int *%s;\n", DFA_INSN_CODES_VARIABLE_NAME);
9124 fprintf (output_file, "\nstatic int %s;\n\n",
9125 DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
9126 output_dfa_insn_code_func ();
9127 output_trans_func ();
9128 output_min_issue_delay_func ();
9129 output_internal_dead_lock_func ();
9130 output_dead_lock_func ();
9131 output_size_func ();
9132 output_internal_reset_func ();
9133 output_reset_func ();
9134 output_min_insn_conflict_delay_func ();
9135 output_internal_insn_latency_func ();
9136 output_insn_latency_func ();
9137 output_print_reservation_func ();
9138 /* Output function get_cpu_unit_code. */
9139 fprintf (output_file, "\n#if %s\n\n", CPU_UNITS_QUERY_MACRO_NAME);
9140 output_get_cpu_unit_code_func ();
9141 output_cpu_unit_reservation_p ();
9142 fprintf (output_file, "\n#endif /* #if %s */\n\n",
9143 CPU_UNITS_QUERY_MACRO_NAME);
9144 output_dfa_clean_insn_cache_func ();
9145 output_dfa_start_func ();
9146 output_dfa_finish_func ();
9148 fprintf (stderr, "done\n");
9151 output_description_file = fopen (output_description_file_name, "w");
9152 if (output_description_file == NULL)
9154 perror (output_description_file_name);
9155 exit (FATAL_EXIT_CODE);
9158 fprintf (stderr, "Output automata description...");
9159 output_description ();
9160 output_automaton_descriptions ();
9162 fprintf (stderr, "done\n");
9163 output_statistics (output_description_file);
9166 output_statistics (stderr);
9167 ticker_off (&output_time);
9169 output_time_statistics (stderr);
9172 finish_automata_lists ();
9175 fprintf (stderr, "Summary:\n");
9176 fprintf (stderr, " check time ");
9177 print_active_time (stderr, check_time);
9178 fprintf (stderr, ", generation time ");
9179 print_active_time (stderr, generation_time);
9180 fprintf (stderr, ", all time ");
9181 print_active_time (stderr, all_time);
9182 fprintf (stderr, "\n");
9184 /* Finish all work. */
9185 if (output_description_file != NULL)
9187 fflush (output_description_file);
9188 if (ferror (stdout) != 0)
9189 fatal ("Error in writing DFA description file %s: %s",
9190 output_description_file_name, xstrerror (errno));
9191 fclose (output_description_file);
9193 finish_automaton_decl_table ();
9194 finish_insn_decl_table ();
9195 finish_decl_table ();
9196 obstack_free (&irp, NULL);
9197 if (have_error && output_description_file != NULL)
9198 remove (output_description_file_name);
9202 main (int argc, char **argv)
9206 progname = "genautomata";
9208 if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
9209 return (FATAL_EXIT_CODE);
9211 initiate_automaton_gen (argc, argv);
9215 int insn_code_number;
9217 desc = read_md_rtx (&lineno, &insn_code_number);
9221 switch (GET_CODE (desc))
9223 case DEFINE_CPU_UNIT:
9224 gen_cpu_unit (desc);
9227 case DEFINE_QUERY_CPU_UNIT:
9228 gen_query_cpu_unit (desc);
9236 gen_excl_set (desc);
9240 gen_presence_set (desc);
9243 case FINAL_PRESENCE_SET:
9244 gen_final_presence_set (desc);
9248 gen_absence_set (desc);
9251 case FINAL_ABSENCE_SET:
9252 gen_final_absence_set (desc);
9255 case DEFINE_AUTOMATON:
9256 gen_automaton (desc);
9259 case AUTOMATA_OPTION:
9260 gen_automata_option (desc);
9263 case DEFINE_RESERVATION:
9267 case DEFINE_INSN_RESERVATION:
9268 gen_insn_reserv (desc);
9277 return FATAL_EXIT_CODE;
9279 puts ("/* Generated automatically by the program `genautomata'\n"
9280 " from the machine description file `md'. */\n\n"
9281 "#include \"config.h\"\n"
9282 "#include \"system.h\"\n"
9283 "#include \"coretypes.h\"\n"
9284 "#include \"tm.h\"\n"
9285 "#include \"rtl.h\"\n"
9286 "#include \"tm_p.h\"\n"
9287 "#include \"insn-config.h\"\n"
9288 "#include \"recog.h\"\n"
9289 "#include \"regs.h\"\n"
9290 "#include \"real.h\"\n"
9291 "#include \"output.h\"\n"
9292 "#include \"insn-attr.h\"\n"
9293 "#include \"toplev.h\"\n"
9294 "#include \"flags.h\"\n"
9295 "#include \"function.h\"\n");
9297 if (VEC_length (decl_t, decls) > 0)
9304 return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);