Mark as release
[official-gcc.git] / gcc / genautomata.c
blobf224887852192918f8868fc9c0c64e5948726ba5
1 /* Pipeline hazard description translator.
2 Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005
3 Free Software Foundation, Inc.
5 Written by Vladimir Makarov <vmakarov@redhat.com>
7 This file is part of GCC.
9 GCC is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by the
11 Free Software Foundation; either version 3, or (at your option) any
12 later version.
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
17 for more details.
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING3. If not see
21 <http://www.gnu.org/licenses/>. */
23 /* References:
25 1. Detecting pipeline structural hazards quickly. T. Proebsting,
26 C. Fraser. Proceedings of ACM SIGPLAN-SIGACT Symposium on
27 Principles of Programming Languages, pages 280--286, 1994.
29 This article is a good start point to understand usage of finite
30 state automata for pipeline hazard recognizers. But I'd
31 recommend the 2nd article for more deep understanding.
33 2. Efficient Instruction Scheduling Using Finite State Automata:
34 V. Bala and N. Rubin, Proceedings of MICRO-28. This is the best
35 article about usage of finite state automata for pipeline hazard
36 recognizers.
38 The current implementation is different from the 2nd article in the
39 following:
41 1. New operator `|' (alternative) is permitted in functional unit
42 reservation which can be treated deterministically and
43 non-deterministically.
45 2. Possibility of usage of nondeterministic automata too.
47 3. Possibility to query functional unit reservations for given
48 automaton state.
50 4. Several constructions to describe impossible reservations
51 (`exclusion_set', `presence_set', `final_presence_set',
52 `absence_set', and `final_absence_set').
54 5. No reverse automata are generated. Trace instruction scheduling
55 requires this. It can be easily added in the future if we
56 really need this.
58 6. Union of automaton states are not generated yet. It is planned
59 to be implemented. Such feature is needed to make more accurate
60 interlock insn scheduling to get state describing functional
61 unit reservation in a joint CFG point. */
63 /* This file code processes constructions of machine description file
64 which describes automaton used for recognition of processor pipeline
65 hazards by insn scheduler and can be used for other tasks (such as
66 VLIW insn packing.
68 The translator functions `gen_cpu_unit', `gen_query_cpu_unit',
69 `gen_bypass', `gen_excl_set', `gen_presence_set',
70 `gen_final_presence_set', `gen_absence_set',
71 `gen_final_absence_set', `gen_automaton', `gen_automata_option',
72 `gen_reserv', `gen_insn_reserv' are called from file
73 `genattrtab.c'. They transform RTL constructions describing
74 automata in .md file into internal representation convenient for
75 further processing.
77 The translator major function `expand_automata' processes the
78 description internal representation into finite state automaton.
79 It can be divided on:
81 o checking correctness of the automaton pipeline description
82 (major function is `check_all_description').
84 o generating automaton (automata) from the description (major
85 function is `make_automaton').
87 o optional transformation of nondeterministic finite state
88 automata into deterministic ones if the alternative operator
89 `|' is treated nondeterministically in the description (major
90 function is NDFA_to_DFA).
92 o optional minimization of the finite state automata by merging
93 equivalent automaton states (major function is `minimize_DFA').
95 o forming tables (some as comb vectors) and attributes
96 representing the automata (functions output_..._table).
98 Function `write_automata' outputs the created finite state
99 automaton as different tables and functions which works with the
100 automata to inquire automaton state and to change its state. These
101 function are used by gcc instruction scheduler and may be some
102 other gcc code. */
104 #include "bconfig.h"
105 #include "system.h"
106 #include "coretypes.h"
107 #include "tm.h"
108 #include "rtl.h"
109 #include "obstack.h"
110 #include "errors.h"
111 #include "gensupport.h"
113 #include <math.h>
114 #include "hashtab.h"
115 #include "vec.h"
117 #ifndef CHAR_BIT
118 #define CHAR_BIT 8
119 #endif
121 /* Positions in machine description file. Now they are not used. But
122 they could be used in the future for better diagnostic messages. */
123 typedef int pos_t;
125 /* The following is element of vector of current (and planned in the
126 future) functional unit reservations. */
127 typedef unsigned HOST_WIDE_INT set_el_t;
129 /* Reservations of function units are represented by value of the following
130 type. */
131 typedef set_el_t *reserv_sets_t;
133 /* The following structure describes a ticker. */
134 struct ticker
136 /* The following member value is time of the ticker creation with
137 taking into account time when the ticker is off. Active time of
138 the ticker is current time minus the value. */
139 int modified_creation_time;
140 /* The following member value is time (incremented by one) when the
141 ticker was off. Zero value means that now the ticker is on. */
142 int incremented_off_time;
145 /* The ticker is represented by the following type. */
146 typedef struct ticker ticker_t;
148 /* The following type describes elements of output vectors. */
149 typedef HOST_WIDE_INT vect_el_t;
151 /* Forward declaration of structures of internal representation of
152 pipeline description based on NDFA. */
154 struct unit_decl;
155 struct bypass_decl;
156 struct result_decl;
157 struct automaton_decl;
158 struct unit_pattern_rel_decl;
159 struct reserv_decl;
160 struct insn_reserv_decl;
161 struct decl;
162 struct unit_regexp;
163 struct result_regexp;
164 struct reserv_regexp;
165 struct nothing_regexp;
166 struct sequence_regexp;
167 struct repeat_regexp;
168 struct allof_regexp;
169 struct oneof_regexp;
170 struct regexp;
171 struct description;
172 struct unit_set_el;
173 struct pattern_set_el;
174 struct pattern_reserv;
175 struct state;
176 struct alt_state;
177 struct arc;
178 struct ainsn;
179 struct automaton;
180 struct state_ainsn_table;
182 /* The following typedefs are for brevity. */
183 typedef struct unit_decl *unit_decl_t;
184 typedef struct decl *decl_t;
185 typedef struct regexp *regexp_t;
186 typedef struct unit_set_el *unit_set_el_t;
187 typedef struct pattern_set_el *pattern_set_el_t;
188 typedef struct pattern_reserv *pattern_reserv_t;
189 typedef struct alt_state *alt_state_t;
190 typedef struct state *state_t;
191 typedef struct arc *arc_t;
192 typedef struct ainsn *ainsn_t;
193 typedef struct automaton *automaton_t;
194 typedef struct automata_list_el *automata_list_el_t;
195 typedef struct state_ainsn_table *state_ainsn_table_t;
197 /* Undefined position. */
198 static pos_t no_pos = 0;
200 /* All IR is stored in the following obstack. */
201 static struct obstack irp;
204 /* Declare vector types for various data structures: */
206 DEF_VEC_P(alt_state_t);
207 DEF_VEC_ALLOC_P(alt_state_t,heap);
208 DEF_VEC_P(ainsn_t);
209 DEF_VEC_ALLOC_P(ainsn_t,heap);
210 DEF_VEC_P(state_t);
211 DEF_VEC_ALLOC_P(state_t,heap);
212 DEF_VEC_P(decl_t);
213 DEF_VEC_ALLOC_P(decl_t,heap);
214 DEF_VEC_P(reserv_sets_t);
215 DEF_VEC_ALLOC_P(reserv_sets_t,heap);
217 DEF_VEC_I(vect_el_t);
218 DEF_VEC_ALLOC_I(vect_el_t, heap);
219 typedef VEC(vect_el_t,heap) *vla_hwint_t;
221 /* Forward declarations of functions used before their definitions, only. */
222 static regexp_t gen_regexp_sequence (const char *);
223 static void reserv_sets_or (reserv_sets_t, reserv_sets_t,
224 reserv_sets_t);
225 static reserv_sets_t get_excl_set (reserv_sets_t);
226 static int check_presence_pattern_sets (reserv_sets_t,
227 reserv_sets_t, int);
228 static int check_absence_pattern_sets (reserv_sets_t, reserv_sets_t,
229 int);
230 static arc_t first_out_arc (state_t);
231 static arc_t next_out_arc (arc_t);
235 /* Options with the following names can be set up in automata_option
236 construction. Because the strings occur more one time we use the
237 macros. */
239 #define NO_MINIMIZATION_OPTION "-no-minimization"
241 #define TIME_OPTION "-time"
243 #define V_OPTION "-v"
245 #define W_OPTION "-w"
247 #define NDFA_OPTION "-ndfa"
249 #define PROGRESS_OPTION "-progress"
251 /* The following flags are set up by function `initiate_automaton_gen'. */
253 /* Make automata with nondeterministic reservation by insns (`-ndfa'). */
254 static int ndfa_flag;
256 /* Do not make minimization of DFA (`-no-minimization'). */
257 static int no_minimization_flag;
259 /* Value of this variable is number of automata being generated. The
260 actual number of automata may be less this value if there is not
261 sufficient number of units. This value is defined by argument of
262 option `-split' or by constructions automaton if the value is zero
263 (it is default value of the argument). */
264 static int split_argument;
266 /* Flag of output time statistics (`-time'). */
267 static int time_flag;
269 /* Flag of creation of description file which contains description of
270 result automaton and statistics information (`-v'). */
271 static int v_flag;
273 /* Flag of output of a progress bar showing how many states were
274 generated so far for automaton being processed (`-progress'). */
275 static int progress_flag;
277 /* Flag of generating warning instead of error for non-critical errors
278 (`-w'). */
279 static int w_flag;
282 /* Output file for pipeline hazard recognizer (PHR) being generated.
283 The value is NULL if the file is not defined. */
284 static FILE *output_file;
286 /* Description file of PHR. The value is NULL if the file is not
287 created. */
288 static FILE *output_description_file;
290 /* PHR description file name. */
291 static char *output_description_file_name;
293 /* Value of the following variable is node representing description
294 being processed. This is start point of IR. */
295 static struct description *description;
299 /* This page contains description of IR structure (nodes). */
301 enum decl_mode
303 dm_unit,
304 dm_bypass,
305 dm_automaton,
306 dm_excl,
307 dm_presence,
308 dm_absence,
309 dm_reserv,
310 dm_insn_reserv
313 /* This describes define_cpu_unit and define_query_cpu_unit (see file
314 rtl.def). */
315 struct unit_decl
317 const char *name;
318 /* NULL if the automaton name is absent. */
319 const char *automaton_name;
320 /* If the following value is not zero, the cpu unit reservation is
321 described in define_query_cpu_unit. */
322 char query_p;
324 /* The following fields are defined by checker. */
326 /* The following field value is nonzero if the unit is used in an
327 regexp. */
328 char unit_is_used;
330 /* The following field value is order number (0, 1, ...) of given
331 unit. */
332 int unit_num;
333 /* The following field value is corresponding declaration of
334 automaton which was given in description. If the field value is
335 NULL then automaton in the unit declaration was absent. */
336 struct automaton_decl *automaton_decl;
337 /* The following field value is maximal cycle number (1, ...) on
338 which given unit occurs in insns. Zero value means that given
339 unit is not used in insns. */
340 int max_occ_cycle_num;
341 /* The following field value is minimal cycle number (0, ...) on
342 which given unit occurs in insns. -1 value means that given
343 unit is not used in insns. */
344 int min_occ_cycle_num;
345 /* The following list contains units which conflict with given
346 unit. */
347 unit_set_el_t excl_list;
348 /* The following list contains patterns which are required to
349 reservation of given unit. */
350 pattern_set_el_t presence_list;
351 pattern_set_el_t final_presence_list;
352 /* The following list contains patterns which should be not present
353 in reservation for given unit. */
354 pattern_set_el_t absence_list;
355 pattern_set_el_t final_absence_list;
356 /* The following is used only when `query_p' has nonzero value.
357 This is query number for the unit. */
358 int query_num;
359 /* The following is the last cycle on which the unit was checked for
360 correct distributions of units to automata in a regexp. */
361 int last_distribution_check_cycle;
363 /* The following fields are defined by automaton generator. */
365 /* The following field value is number of the automaton to which
366 given unit belongs. */
367 int corresponding_automaton_num;
368 /* If the following value is not zero, the cpu unit is present in a
369 `exclusion_set' or in right part of a `presence_set',
370 `final_presence_set', `absence_set', and
371 `final_absence_set'define_query_cpu_unit. */
372 char in_set_p;
375 /* This describes define_bypass (see file rtl.def). */
376 struct bypass_decl
378 int latency;
379 const char *out_insn_name;
380 const char *in_insn_name;
381 const char *bypass_guard_name;
383 /* The following fields are defined by checker. */
385 /* output and input insns of given bypass. */
386 struct insn_reserv_decl *out_insn_reserv;
387 struct insn_reserv_decl *in_insn_reserv;
388 /* The next bypass for given output insn. */
389 struct bypass_decl *next;
392 /* This describes define_automaton (see file rtl.def). */
393 struct automaton_decl
395 const char *name;
397 /* The following fields are defined by automaton generator. */
399 /* The following field value is nonzero if the automaton is used in
400 an regexp definition. */
401 char automaton_is_used;
403 /* The following fields are defined by checker. */
405 /* The following field value is the corresponding automaton. This
406 field is not NULL only if the automaton is present in unit
407 declarations and the automatic partition on automata is not
408 used. */
409 automaton_t corresponding_automaton;
412 /* This describes exclusion relations: exclusion_set (see file
413 rtl.def). */
414 struct excl_rel_decl
416 int all_names_num;
417 int first_list_length;
418 char *names [1];
421 /* This describes unit relations: [final_]presence_set or
422 [final_]absence_set (see file rtl.def). */
423 struct unit_pattern_rel_decl
425 int final_p;
426 int names_num;
427 int patterns_num;
428 char **names;
429 char ***patterns;
432 /* This describes define_reservation (see file rtl.def). */
433 struct reserv_decl
435 const char *name;
436 regexp_t regexp;
438 /* The following fields are defined by checker. */
440 /* The following field value is nonzero if the unit is used in an
441 regexp. */
442 char reserv_is_used;
443 /* The following field is used to check up cycle in expression
444 definition. */
445 int loop_pass_num;
448 /* This describes define_insn_reservation (see file rtl.def). */
449 struct insn_reserv_decl
451 rtx condexp;
452 int default_latency;
453 regexp_t regexp;
454 const char *name;
456 /* The following fields are defined by checker. */
458 /* The following field value is order number (0, 1, ...) of given
459 insn. */
460 int insn_num;
461 /* The following field value is list of bypasses in which given insn
462 is output insn. */
463 struct bypass_decl *bypass_list;
465 /* The following fields are defined by automaton generator. */
467 /* The following field is the insn regexp transformed that
468 the regexp has not optional regexp, repetition regexp, and an
469 reservation name (i.e. reservation identifiers are changed by the
470 corresponding regexp) and all alternations are the topest level
471 of the regexp. The value can be NULL only if it is special
472 insn `cycle advancing'. */
473 regexp_t transformed_regexp;
474 /* The following field value is list of arcs marked given
475 insn. The field is used in transformation NDFA -> DFA. */
476 arc_t arcs_marked_by_insn;
477 /* The two following fields are used during minimization of a finite state
478 automaton. */
479 /* The field value is number of equivalence class of state into
480 which arc marked by given insn enters from a state (fixed during
481 an automaton minimization). */
482 int equiv_class_num;
483 /* The following member value is the list to automata which can be
484 changed by the insn issue. */
485 automata_list_el_t important_automata_list;
486 /* The following member is used to process insn once for output. */
487 int processed_p;
490 /* This contains a declaration mentioned above. */
491 struct decl
493 /* What node in the union? */
494 enum decl_mode mode;
495 pos_t pos;
496 union
498 struct unit_decl unit;
499 struct bypass_decl bypass;
500 struct automaton_decl automaton;
501 struct excl_rel_decl excl;
502 struct unit_pattern_rel_decl presence;
503 struct unit_pattern_rel_decl absence;
504 struct reserv_decl reserv;
505 struct insn_reserv_decl insn_reserv;
506 } decl;
509 /* The following structures represent parsed reservation strings. */
510 enum regexp_mode
512 rm_unit,
513 rm_reserv,
514 rm_nothing,
515 rm_sequence,
516 rm_repeat,
517 rm_allof,
518 rm_oneof
521 /* Cpu unit in reservation. */
522 struct unit_regexp
524 const char *name;
525 unit_decl_t unit_decl;
528 /* Define_reservation in a reservation. */
529 struct reserv_regexp
531 const char *name;
532 struct reserv_decl *reserv_decl;
535 /* Absence of reservation (represented by string `nothing'). */
536 struct nothing_regexp
538 /* This used to be empty but ISO C doesn't allow that. */
539 char unused;
542 /* Representation of reservations separated by ',' (see file
543 rtl.def). */
544 struct sequence_regexp
546 int regexps_num;
547 regexp_t regexps [1];
550 /* Representation of construction `repeat' (see file rtl.def). */
551 struct repeat_regexp
553 int repeat_num;
554 regexp_t regexp;
557 /* Representation of reservations separated by '+' (see file
558 rtl.def). */
559 struct allof_regexp
561 int regexps_num;
562 regexp_t regexps [1];
565 /* Representation of reservations separated by '|' (see file
566 rtl.def). */
567 struct oneof_regexp
569 int regexps_num;
570 regexp_t regexps [1];
573 /* Representation of a reservation string. */
574 struct regexp
576 /* What node in the union? */
577 enum regexp_mode mode;
578 pos_t pos;
579 union
581 struct unit_regexp unit;
582 struct reserv_regexp reserv;
583 struct nothing_regexp nothing;
584 struct sequence_regexp sequence;
585 struct repeat_regexp repeat;
586 struct allof_regexp allof;
587 struct oneof_regexp oneof;
588 } regexp;
591 /* Represents description of pipeline hazard description based on
592 NDFA. */
593 struct description
595 int decls_num;
597 /* The following fields are defined by checker. */
599 /* The following fields values are correspondingly number of all
600 units, query units, and insns in the description. */
601 int units_num;
602 int query_units_num;
603 int insns_num;
604 /* The following field value is max length (in cycles) of
605 reservations of insns. The field value is defined only for
606 correct programs. */
607 int max_insn_reserv_cycles;
609 /* The following fields are defined by automaton generator. */
611 /* The following field value is the first automaton. */
612 automaton_t first_automaton;
614 /* The following field is created by pipeline hazard parser and
615 contains all declarations. We allocate additional entry for
616 special insn "cycle advancing" which is added by the automaton
617 generator. */
618 decl_t decls [1];
622 /* The following nodes are created in automaton checker. */
624 /* The following nodes represent exclusion set for cpu units. Each
625 element is accessed through only one excl_list. */
626 struct unit_set_el
628 unit_decl_t unit_decl;
629 unit_set_el_t next_unit_set_el;
632 /* The following nodes represent presence or absence pattern for cpu
633 units. Each element is accessed through only one presence_list or
634 absence_list. */
635 struct pattern_set_el
637 /* The number of units in unit_decls. */
638 int units_num;
639 /* The units forming the pattern. */
640 struct unit_decl **unit_decls;
641 pattern_set_el_t next_pattern_set_el;
645 /* The following nodes are created in automaton generator. */
648 /* The following nodes represent presence or absence pattern for cpu
649 units. Each element is accessed through only one element of
650 unit_presence_set_table or unit_absence_set_table. */
651 struct pattern_reserv
653 reserv_sets_t reserv;
654 pattern_reserv_t next_pattern_reserv;
657 /* The following node type describes state automaton. The state may
658 be deterministic or non-deterministic. Non-deterministic state has
659 several component states which represent alternative cpu units
660 reservations. The state also is used for describing a
661 deterministic reservation of automaton insn. */
662 struct state
664 /* The following member value is nonzero if there is a transition by
665 cycle advancing. */
666 int new_cycle_p;
667 /* The following field is list of processor unit reservations on
668 each cycle. */
669 reserv_sets_t reservs;
670 /* The following field is unique number of given state between other
671 states. */
672 int unique_num;
673 /* The following field value is automaton to which given state
674 belongs. */
675 automaton_t automaton;
676 /* The following field value is the first arc output from given
677 state. */
678 arc_t first_out_arc;
679 unsigned int num_out_arcs;
680 /* The following field is used to form NDFA. */
681 char it_was_placed_in_stack_for_NDFA_forming;
682 /* The following field is used to form DFA. */
683 char it_was_placed_in_stack_for_DFA_forming;
684 /* The following field is used to transform NDFA to DFA and DFA
685 minimization. The field value is not NULL if the state is a
686 compound state. In this case the value of field `unit_sets_list'
687 is NULL. All states in the list are in the hash table. The list
688 is formed through field `next_sorted_alt_state'. We should
689 support only one level of nesting state. */
690 alt_state_t component_states;
691 /* The following field is used for passing graph of states. */
692 int pass_num;
693 /* The list of states belonging to one equivalence class is formed
694 with the aid of the following field. */
695 state_t next_equiv_class_state;
696 /* The two following fields are used during minimization of a finite
697 state automaton. */
698 int equiv_class_num_1, equiv_class_num_2;
699 /* The following field is used during minimization of a finite state
700 automaton. The field value is state corresponding to equivalence
701 class to which given state belongs. */
702 state_t equiv_class_state;
703 unsigned int *presence_signature;
704 /* The following field value is the order number of given state.
705 The states in final DFA is enumerated with the aid of the
706 following field. */
707 int order_state_num;
708 /* This member is used for passing states for searching minimal
709 delay time. */
710 int state_pass_num;
711 /* The following member is used to evaluate min issue delay of insn
712 for a state. */
713 int min_insn_issue_delay;
714 /* The following member is used to evaluate max issue rate of the
715 processor. The value of the member is maximal length of the path
716 from given state no containing arcs marked by special insn `cycle
717 advancing'. */
718 int longest_path_length;
721 /* The following macro is an initial value of member
722 `longest_path_length' of a state. */
723 #define UNDEFINED_LONGEST_PATH_LENGTH -1
725 /* Automaton arc. */
726 struct arc
728 /* The following field refers for the state into which given arc
729 enters. */
730 state_t to_state;
731 /* The following field describes that the insn issue (with cycle
732 advancing for special insn `cycle advancing' and without cycle
733 advancing for others) makes transition from given state to
734 another given state. */
735 ainsn_t insn;
736 /* The following field value is the next arc output from the same
737 state. */
738 arc_t next_out_arc;
739 /* List of arcs marked given insn is formed with the following
740 field. The field is used in transformation NDFA -> DFA. */
741 arc_t next_arc_marked_by_insn;
744 /* The following node type describes a deterministic alternative in
745 non-deterministic state which characterizes cpu unit reservations
746 of automaton insn or which is part of NDFA. */
747 struct alt_state
749 /* The following field is a deterministic state which characterizes
750 unit reservations of the instruction. */
751 state_t state;
752 /* The following field refers to the next state which characterizes
753 unit reservations of the instruction. */
754 alt_state_t next_alt_state;
755 /* The following field refers to the next state in sorted list. */
756 alt_state_t next_sorted_alt_state;
759 /* The following node type describes insn of automaton. They are
760 labels of FA arcs. */
761 struct ainsn
763 /* The following field value is the corresponding insn declaration
764 of description. */
765 struct insn_reserv_decl *insn_reserv_decl;
766 /* The following field value is the next insn declaration for an
767 automaton. */
768 ainsn_t next_ainsn;
769 /* The following field is states which characterize automaton unit
770 reservations of the instruction. The value can be NULL only if it
771 is special insn `cycle advancing'. */
772 alt_state_t alt_states;
773 /* The following field is sorted list of states which characterize
774 automaton unit reservations of the instruction. The value can be
775 NULL only if it is special insn `cycle advancing'. */
776 alt_state_t sorted_alt_states;
777 /* The following field refers the next automaton insn with
778 the same reservations. */
779 ainsn_t next_same_reservs_insn;
780 /* The following field is flag of the first automaton insn with the
781 same reservations in the declaration list. Only arcs marked such
782 insn is present in the automaton. This significantly decreases
783 memory requirements especially when several automata are
784 formed. */
785 char first_insn_with_same_reservs;
786 /* The following member has nonzero value if there is arc from state of
787 the automaton marked by the ainsn. */
788 char arc_exists_p;
789 /* Cyclic list of insns of an equivalence class is formed with the
790 aid of the following field. */
791 ainsn_t next_equiv_class_insn;
792 /* The following field value is nonzero if the insn declaration is
793 the first insn declaration with given equivalence number. */
794 char first_ainsn_with_given_equivalence_num;
795 /* The following field is number of class of equivalence of insns.
796 It is necessary because many insns may be equivalent with the
797 point of view of pipeline hazards. */
798 int insn_equiv_class_num;
799 /* The following member value is TRUE if there is an arc in the
800 automaton marked by the insn into another state. In other
801 words, the insn can change the state of the automaton. */
802 int important_p;
805 /* The following describes an automaton for PHR. */
806 struct automaton
808 /* The following field value is the list of insn declarations for
809 given automaton. */
810 ainsn_t ainsn_list;
811 /* The following field value is the corresponding automaton
812 declaration. This field is not NULL only if the automatic
813 partition on automata is not used. */
814 struct automaton_decl *corresponding_automaton_decl;
815 /* The following field value is the next automaton. */
816 automaton_t next_automaton;
817 /* The following field is start state of FA. There are not unit
818 reservations in the state. */
819 state_t start_state;
820 /* The following field value is number of equivalence classes of
821 insns (see field `insn_equiv_class_num' in
822 `insn_reserv_decl'). */
823 int insn_equiv_classes_num;
824 /* The following field value is number of states of final DFA. */
825 int achieved_states_num;
826 /* The following field value is the order number (0, 1, ...) of
827 given automaton. */
828 int automaton_order_num;
829 /* The following fields contain statistics information about
830 building automaton. */
831 int NDFA_states_num, DFA_states_num;
832 /* The following field value is defined only if minimization of DFA
833 is used. */
834 int minimal_DFA_states_num;
835 int NDFA_arcs_num, DFA_arcs_num;
836 /* The following field value is defined only if minimization of DFA
837 is used. */
838 int minimal_DFA_arcs_num;
839 /* The following member refers for two table state x ainsn -> int.
840 ??? Above sentence is incomprehensible. */
841 state_ainsn_table_t trans_table;
842 /* The following member value is maximal value of min issue delay
843 for insns of the automaton. */
844 int max_min_delay;
845 /* Usually min issue delay is small and we can place several (2, 4,
846 8) elements in one vector element. So the compression factor can
847 be 1 (no compression), 2, 4, 8. */
848 int min_issue_delay_table_compression_factor;
849 /* Total number of locked states in this automaton. */
850 int locked_states;
853 /* The following is the element of the list of automata. */
854 struct automata_list_el
856 /* The automaton itself. */
857 automaton_t automaton;
858 /* The next automata set element. */
859 automata_list_el_t next_automata_list_el;
862 /* The following structure describes a table state X ainsn -> int(>= 0). */
863 struct state_ainsn_table
865 /* Automaton to which given table belongs. */
866 automaton_t automaton;
867 /* The following tree vectors for comb vector implementation of the
868 table. */
869 vla_hwint_t comb_vect;
870 vla_hwint_t check_vect;
871 vla_hwint_t base_vect;
872 /* This is simple implementation of the table. */
873 vla_hwint_t full_vect;
874 /* Minimal and maximal values of the previous vectors. */
875 int min_comb_vect_el_value, max_comb_vect_el_value;
876 int min_base_vect_el_value, max_base_vect_el_value;
879 /* Macros to access members of unions. Use only them for access to
880 union members of declarations and regexps. */
882 #if defined ENABLE_CHECKING && (GCC_VERSION >= 2007)
884 #define DECL_UNIT(d) __extension__ \
885 (({ struct decl *const _decl = (d); \
886 if (_decl->mode != dm_unit) \
887 decl_mode_check_failed (_decl->mode, "dm_unit", \
888 __FILE__, __LINE__, __FUNCTION__); \
889 &(_decl)->decl.unit; }))
891 #define DECL_BYPASS(d) __extension__ \
892 (({ struct decl *const _decl = (d); \
893 if (_decl->mode != dm_bypass) \
894 decl_mode_check_failed (_decl->mode, "dm_bypass", \
895 __FILE__, __LINE__, __FUNCTION__); \
896 &(_decl)->decl.bypass; }))
898 #define DECL_AUTOMATON(d) __extension__ \
899 (({ struct decl *const _decl = (d); \
900 if (_decl->mode != dm_automaton) \
901 decl_mode_check_failed (_decl->mode, "dm_automaton", \
902 __FILE__, __LINE__, __FUNCTION__); \
903 &(_decl)->decl.automaton; }))
905 #define DECL_EXCL(d) __extension__ \
906 (({ struct decl *const _decl = (d); \
907 if (_decl->mode != dm_excl) \
908 decl_mode_check_failed (_decl->mode, "dm_excl", \
909 __FILE__, __LINE__, __FUNCTION__); \
910 &(_decl)->decl.excl; }))
912 #define DECL_PRESENCE(d) __extension__ \
913 (({ struct decl *const _decl = (d); \
914 if (_decl->mode != dm_presence) \
915 decl_mode_check_failed (_decl->mode, "dm_presence", \
916 __FILE__, __LINE__, __FUNCTION__); \
917 &(_decl)->decl.presence; }))
919 #define DECL_ABSENCE(d) __extension__ \
920 (({ struct decl *const _decl = (d); \
921 if (_decl->mode != dm_absence) \
922 decl_mode_check_failed (_decl->mode, "dm_absence", \
923 __FILE__, __LINE__, __FUNCTION__); \
924 &(_decl)->decl.absence; }))
926 #define DECL_RESERV(d) __extension__ \
927 (({ struct decl *const _decl = (d); \
928 if (_decl->mode != dm_reserv) \
929 decl_mode_check_failed (_decl->mode, "dm_reserv", \
930 __FILE__, __LINE__, __FUNCTION__); \
931 &(_decl)->decl.reserv; }))
933 #define DECL_INSN_RESERV(d) __extension__ \
934 (({ struct decl *const _decl = (d); \
935 if (_decl->mode != dm_insn_reserv) \
936 decl_mode_check_failed (_decl->mode, "dm_insn_reserv", \
937 __FILE__, __LINE__, __FUNCTION__); \
938 &(_decl)->decl.insn_reserv; }))
940 static const char *decl_name (enum decl_mode);
941 static void decl_mode_check_failed (enum decl_mode, const char *,
942 const char *, int, const char *)
943 ATTRIBUTE_NORETURN;
945 /* Return string representation of declaration mode MODE. */
946 static const char *
947 decl_name (enum decl_mode mode)
949 static char str [100];
951 if (mode == dm_unit)
952 return "dm_unit";
953 else if (mode == dm_bypass)
954 return "dm_bypass";
955 else if (mode == dm_automaton)
956 return "dm_automaton";
957 else if (mode == dm_excl)
958 return "dm_excl";
959 else if (mode == dm_presence)
960 return "dm_presence";
961 else if (mode == dm_absence)
962 return "dm_absence";
963 else if (mode == dm_reserv)
964 return "dm_reserv";
965 else if (mode == dm_insn_reserv)
966 return "dm_insn_reserv";
967 else
968 sprintf (str, "unknown (%d)", (int) mode);
969 return str;
972 /* The function prints message about unexpected declaration and finish
973 the program. */
974 static void
975 decl_mode_check_failed (enum decl_mode mode, const char *expected_mode_str,
976 const char *file, int line, const char *func)
978 fprintf
979 (stderr,
980 "\n%s: %d: error in %s: DECL check: expected decl %s, have %s\n",
981 file, line, func, expected_mode_str, decl_name (mode));
982 exit (1);
986 #define REGEXP_UNIT(r) __extension__ \
987 (({ struct regexp *const _regexp = (r); \
988 if (_regexp->mode != rm_unit) \
989 regexp_mode_check_failed (_regexp->mode, "rm_unit", \
990 __FILE__, __LINE__, __FUNCTION__); \
991 &(_regexp)->regexp.unit; }))
993 #define REGEXP_RESERV(r) __extension__ \
994 (({ struct regexp *const _regexp = (r); \
995 if (_regexp->mode != rm_reserv) \
996 regexp_mode_check_failed (_regexp->mode, "rm_reserv", \
997 __FILE__, __LINE__, __FUNCTION__); \
998 &(_regexp)->regexp.reserv; }))
1000 #define REGEXP_SEQUENCE(r) __extension__ \
1001 (({ struct regexp *const _regexp = (r); \
1002 if (_regexp->mode != rm_sequence) \
1003 regexp_mode_check_failed (_regexp->mode, "rm_sequence", \
1004 __FILE__, __LINE__, __FUNCTION__); \
1005 &(_regexp)->regexp.sequence; }))
1007 #define REGEXP_REPEAT(r) __extension__ \
1008 (({ struct regexp *const _regexp = (r); \
1009 if (_regexp->mode != rm_repeat) \
1010 regexp_mode_check_failed (_regexp->mode, "rm_repeat", \
1011 __FILE__, __LINE__, __FUNCTION__); \
1012 &(_regexp)->regexp.repeat; }))
1014 #define REGEXP_ALLOF(r) __extension__ \
1015 (({ struct regexp *const _regexp = (r); \
1016 if (_regexp->mode != rm_allof) \
1017 regexp_mode_check_failed (_regexp->mode, "rm_allof", \
1018 __FILE__, __LINE__, __FUNCTION__); \
1019 &(_regexp)->regexp.allof; }))
1021 #define REGEXP_ONEOF(r) __extension__ \
1022 (({ struct regexp *const _regexp = (r); \
1023 if (_regexp->mode != rm_oneof) \
1024 regexp_mode_check_failed (_regexp->mode, "rm_oneof", \
1025 __FILE__, __LINE__, __FUNCTION__); \
1026 &(_regexp)->regexp.oneof; }))
1028 static const char *regexp_name (enum regexp_mode);
1029 static void regexp_mode_check_failed (enum regexp_mode, const char *,
1030 const char *, int,
1031 const char *) ATTRIBUTE_NORETURN;
1034 /* Return string representation of regexp mode MODE. */
1035 static const char *
1036 regexp_name (enum regexp_mode mode)
1038 switch (mode)
1040 case rm_unit:
1041 return "rm_unit";
1042 case rm_reserv:
1043 return "rm_reserv";
1044 case rm_nothing:
1045 return "rm_nothing";
1046 case rm_sequence:
1047 return "rm_sequence";
1048 case rm_repeat:
1049 return "rm_repeat";
1050 case rm_allof:
1051 return "rm_allof";
1052 case rm_oneof:
1053 return "rm_oneof";
1054 default:
1055 gcc_unreachable ();
1059 /* The function prints message about unexpected regexp and finish the
1060 program. */
1061 static void
1062 regexp_mode_check_failed (enum regexp_mode mode,
1063 const char *expected_mode_str,
1064 const char *file, int line, const char *func)
1066 fprintf
1067 (stderr,
1068 "\n%s: %d: error in %s: REGEXP check: expected decl %s, have %s\n",
1069 file, line, func, expected_mode_str, regexp_name (mode));
1070 exit (1);
1073 #else /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */
1075 #define DECL_UNIT(d) (&(d)->decl.unit)
1076 #define DECL_BYPASS(d) (&(d)->decl.bypass)
1077 #define DECL_AUTOMATON(d) (&(d)->decl.automaton)
1078 #define DECL_EXCL(d) (&(d)->decl.excl)
1079 #define DECL_PRESENCE(d) (&(d)->decl.presence)
1080 #define DECL_ABSENCE(d) (&(d)->decl.absence)
1081 #define DECL_RESERV(d) (&(d)->decl.reserv)
1082 #define DECL_INSN_RESERV(d) (&(d)->decl.insn_reserv)
1084 #define REGEXP_UNIT(r) (&(r)->regexp.unit)
1085 #define REGEXP_RESERV(r) (&(r)->regexp.reserv)
1086 #define REGEXP_SEQUENCE(r) (&(r)->regexp.sequence)
1087 #define REGEXP_REPEAT(r) (&(r)->regexp.repeat)
1088 #define REGEXP_ALLOF(r) (&(r)->regexp.allof)
1089 #define REGEXP_ONEOF(r) (&(r)->regexp.oneof)
1091 #endif /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */
1093 /* Create IR structure (node). */
1094 static void *
1095 create_node (size_t size)
1097 void *result;
1099 obstack_blank (&irp, size);
1100 result = obstack_base (&irp);
1101 obstack_finish (&irp);
1102 /* Default values of members are NULL and zero. */
1103 memset (result, 0, size);
1104 return result;
1107 /* Copy IR structure (node). */
1108 static void *
1109 copy_node (const void *from, size_t size)
1111 void *const result = create_node (size);
1112 memcpy (result, from, size);
1113 return result;
1116 /* The function checks that NAME does not contain quotes (`"'). */
1117 static const char *
1118 check_name (const char * name, pos_t pos ATTRIBUTE_UNUSED)
1120 const char *str;
1122 for (str = name; *str != '\0'; str++)
1123 if (*str == '\"')
1124 error ("Name `%s' contains quotes", name);
1125 return name;
1128 /* Pointers to all declarations during IR generation are stored in the
1129 following. */
1130 static VEC(decl_t,heap) *decls;
1132 /* Given a pointer to a (char *) and a separator, return an alloc'ed
1133 string containing the next separated element, taking parentheses
1134 into account if PAR_FLAG has nonzero value. Advance the pointer to
1135 after the string scanned, or the end-of-string. Return NULL if at
1136 end of string. */
1137 static char *
1138 next_sep_el (const char **pstr, int sep, int par_flag)
1140 char *out_str;
1141 const char *p;
1142 int pars_num;
1143 int n_spaces;
1145 /* Remove leading whitespaces. */
1146 while (ISSPACE ((int) **pstr))
1147 (*pstr)++;
1149 if (**pstr == '\0')
1150 return NULL;
1152 n_spaces = 0;
1153 for (pars_num = 0, p = *pstr; *p != '\0'; p++)
1155 if (par_flag && *p == '(')
1156 pars_num++;
1157 else if (par_flag && *p == ')')
1158 pars_num--;
1159 else if (pars_num == 0 && *p == sep)
1160 break;
1161 if (pars_num == 0 && ISSPACE ((int) *p))
1162 n_spaces++;
1163 else
1165 for (; n_spaces != 0; n_spaces--)
1166 obstack_1grow (&irp, p [-n_spaces]);
1167 obstack_1grow (&irp, *p);
1170 obstack_1grow (&irp, '\0');
1171 out_str = obstack_base (&irp);
1172 obstack_finish (&irp);
1174 *pstr = p;
1175 if (**pstr == sep)
1176 (*pstr)++;
1178 return out_str;
1181 /* Given a string and a separator, return the number of separated
1182 elements in it, taking parentheses into account if PAR_FLAG has
1183 nonzero value. Return 0 for the null string, -1 if parentheses is
1184 not balanced. */
1185 static int
1186 n_sep_els (const char *s, int sep, int par_flag)
1188 int n;
1189 int pars_num;
1191 if (*s == '\0')
1192 return 0;
1194 for (pars_num = 0, n = 1; *s; s++)
1195 if (par_flag && *s == '(')
1196 pars_num++;
1197 else if (par_flag && *s == ')')
1198 pars_num--;
1199 else if (pars_num == 0 && *s == sep)
1200 n++;
1202 return (pars_num != 0 ? -1 : n);
1205 /* Given a string and a separator, return vector of strings which are
1206 elements in the string and number of elements through els_num.
1207 Take parentheses into account if PAREN_P has nonzero value. The
1208 function also inserts the end marker NULL at the end of vector.
1209 Return 0 for the null string, -1 if parentheses are not balanced. */
1210 static char **
1211 get_str_vect (const char *str, int *els_num, int sep, int paren_p)
1213 int i;
1214 char **vect;
1215 const char **pstr;
1216 char *trail;
1218 *els_num = n_sep_els (str, sep, paren_p);
1219 if (*els_num <= 0)
1220 return NULL;
1221 obstack_blank (&irp, sizeof (char *) * (*els_num + 1));
1222 vect = (char **) obstack_base (&irp);
1223 obstack_finish (&irp);
1224 pstr = &str;
1225 for (i = 0; i < *els_num; i++)
1226 vect [i] = next_sep_el (pstr, sep, paren_p);
1227 trail = next_sep_el (pstr, sep, paren_p);
1228 gcc_assert (!trail);
1229 vect [i] = NULL;
1230 return vect;
1233 /* Process a DEFINE_CPU_UNIT.
1235 This gives information about a unit contained in CPU. We fill a
1236 struct unit_decl with information used later by `expand_automata'. */
1237 static void
1238 gen_cpu_unit (rtx def)
1240 decl_t decl;
1241 char **str_cpu_units;
1242 int vect_length;
1243 int i;
1245 str_cpu_units = get_str_vect (XSTR (def, 0), &vect_length, ',', FALSE);
1246 if (str_cpu_units == NULL)
1247 fatal ("invalid string `%s' in define_cpu_unit", XSTR (def, 0));
1248 for (i = 0; i < vect_length; i++)
1250 decl = create_node (sizeof (struct decl));
1251 decl->mode = dm_unit;
1252 decl->pos = 0;
1253 DECL_UNIT (decl)->name = check_name (str_cpu_units [i], decl->pos);
1254 DECL_UNIT (decl)->automaton_name = XSTR (def, 1);
1255 DECL_UNIT (decl)->query_p = 0;
1256 DECL_UNIT (decl)->min_occ_cycle_num = -1;
1257 DECL_UNIT (decl)->in_set_p = 0;
1258 VEC_safe_push (decl_t,heap, decls, decl);
1262 /* Process a DEFINE_QUERY_CPU_UNIT.
1264 This gives information about a unit contained in CPU. We fill a
1265 struct unit_decl with information used later by `expand_automata'. */
1266 static void
1267 gen_query_cpu_unit (rtx def)
1269 decl_t decl;
1270 char **str_cpu_units;
1271 int vect_length;
1272 int i;
1274 str_cpu_units = get_str_vect (XSTR (def, 0), &vect_length, ',',
1275 FALSE);
1276 if (str_cpu_units == NULL)
1277 fatal ("invalid string `%s' in define_query_cpu_unit", XSTR (def, 0));
1278 for (i = 0; i < vect_length; i++)
1280 decl = create_node (sizeof (struct decl));
1281 decl->mode = dm_unit;
1282 decl->pos = 0;
1283 DECL_UNIT (decl)->name = check_name (str_cpu_units [i], decl->pos);
1284 DECL_UNIT (decl)->automaton_name = XSTR (def, 1);
1285 DECL_UNIT (decl)->query_p = 1;
1286 VEC_safe_push (decl_t,heap, decls, decl);
1290 /* Process a DEFINE_BYPASS.
1292 This gives information about a unit contained in the CPU. We fill
1293 in a struct bypass_decl with information used later by
1294 `expand_automata'. */
1295 static void
1296 gen_bypass (rtx def)
1298 decl_t decl;
1299 char **out_insns;
1300 int out_length;
1301 char **in_insns;
1302 int in_length;
1303 int i, j;
1305 out_insns = get_str_vect (XSTR (def, 1), &out_length, ',', FALSE);
1306 if (out_insns == NULL)
1307 fatal ("invalid string `%s' in define_bypass", XSTR (def, 1));
1308 in_insns = get_str_vect (XSTR (def, 2), &in_length, ',', FALSE);
1309 if (in_insns == NULL)
1310 fatal ("invalid string `%s' in define_bypass", XSTR (def, 2));
1311 for (i = 0; i < out_length; i++)
1312 for (j = 0; j < in_length; j++)
1314 decl = create_node (sizeof (struct decl));
1315 decl->mode = dm_bypass;
1316 decl->pos = 0;
1317 DECL_BYPASS (decl)->latency = XINT (def, 0);
1318 DECL_BYPASS (decl)->out_insn_name = out_insns [i];
1319 DECL_BYPASS (decl)->in_insn_name = in_insns [j];
1320 DECL_BYPASS (decl)->bypass_guard_name = XSTR (def, 3);
1321 VEC_safe_push (decl_t,heap, decls, decl);
1325 /* Process an EXCLUSION_SET.
1327 This gives information about a cpu unit conflicts. We fill a
1328 struct excl_rel_decl (excl) with information used later by
1329 `expand_automata'. */
1330 static void
1331 gen_excl_set (rtx def)
1333 decl_t decl;
1334 char **first_str_cpu_units;
1335 char **second_str_cpu_units;
1336 int first_vect_length;
1337 int length;
1338 int i;
1340 first_str_cpu_units
1341 = get_str_vect (XSTR (def, 0), &first_vect_length, ',', FALSE);
1342 if (first_str_cpu_units == NULL)
1343 fatal ("invalid first string `%s' in exclusion_set", XSTR (def, 0));
1344 second_str_cpu_units = get_str_vect (XSTR (def, 1), &length, ',',
1345 FALSE);
1346 if (second_str_cpu_units == NULL)
1347 fatal ("invalid second string `%s' in exclusion_set", XSTR (def, 1));
1348 length += first_vect_length;
1349 decl = create_node (sizeof (struct decl) + (length - 1) * sizeof (char *));
1350 decl->mode = dm_excl;
1351 decl->pos = 0;
1352 DECL_EXCL (decl)->all_names_num = length;
1353 DECL_EXCL (decl)->first_list_length = first_vect_length;
1354 for (i = 0; i < length; i++)
1355 if (i < first_vect_length)
1356 DECL_EXCL (decl)->names [i] = first_str_cpu_units [i];
1357 else
1358 DECL_EXCL (decl)->names [i]
1359 = second_str_cpu_units [i - first_vect_length];
1360 VEC_safe_push (decl_t,heap, decls, decl);
1363 /* Process a PRESENCE_SET, a FINAL_PRESENCE_SET, an ABSENCE_SET,
1364 FINAL_ABSENCE_SET (it is depended on PRESENCE_P and FINAL_P).
1366 This gives information about a cpu unit reservation requirements.
1367 We fill a struct unit_pattern_rel_decl with information used later
1368 by `expand_automata'. */
1369 static void
1370 gen_presence_absence_set (rtx def, int presence_p, int final_p)
1372 decl_t decl;
1373 char **str_cpu_units;
1374 char **str_pattern_lists;
1375 char ***str_patterns;
1376 int cpu_units_length;
1377 int length;
1378 int patterns_length;
1379 int i;
1381 str_cpu_units = get_str_vect (XSTR (def, 0), &cpu_units_length, ',',
1382 FALSE);
1383 if (str_cpu_units == NULL)
1384 fatal ((presence_p
1385 ? (final_p
1386 ? "invalid first string `%s' in final_presence_set"
1387 : "invalid first string `%s' in presence_set")
1388 : (final_p
1389 ? "invalid first string `%s' in final_absence_set"
1390 : "invalid first string `%s' in absence_set")),
1391 XSTR (def, 0));
1392 str_pattern_lists = get_str_vect (XSTR (def, 1),
1393 &patterns_length, ',', FALSE);
1394 if (str_pattern_lists == NULL)
1395 fatal ((presence_p
1396 ? (final_p
1397 ? "invalid second string `%s' in final_presence_set"
1398 : "invalid second string `%s' in presence_set")
1399 : (final_p
1400 ? "invalid second string `%s' in final_absence_set"
1401 : "invalid second string `%s' in absence_set")), XSTR (def, 1));
1402 str_patterns = obstack_alloc (&irp, patterns_length * sizeof (char **));
1403 for (i = 0; i < patterns_length; i++)
1405 str_patterns [i] = get_str_vect (str_pattern_lists [i],
1406 &length, ' ', FALSE);
1407 gcc_assert (str_patterns [i]);
1409 decl = create_node (sizeof (struct decl));
1410 decl->pos = 0;
1411 if (presence_p)
1413 decl->mode = dm_presence;
1414 DECL_PRESENCE (decl)->names_num = cpu_units_length;
1415 DECL_PRESENCE (decl)->names = str_cpu_units;
1416 DECL_PRESENCE (decl)->patterns = str_patterns;
1417 DECL_PRESENCE (decl)->patterns_num = patterns_length;
1418 DECL_PRESENCE (decl)->final_p = final_p;
1420 else
1422 decl->mode = dm_absence;
1423 DECL_ABSENCE (decl)->names_num = cpu_units_length;
1424 DECL_ABSENCE (decl)->names = str_cpu_units;
1425 DECL_ABSENCE (decl)->patterns = str_patterns;
1426 DECL_ABSENCE (decl)->patterns_num = patterns_length;
1427 DECL_ABSENCE (decl)->final_p = final_p;
1429 VEC_safe_push (decl_t,heap, decls, decl);
1432 /* Process a PRESENCE_SET.
1434 This gives information about a cpu unit reservation requirements.
1435 We fill a struct unit_pattern_rel_decl (presence) with information
1436 used later by `expand_automata'. */
1437 static void
1438 gen_presence_set (rtx def)
1440 gen_presence_absence_set (def, TRUE, FALSE);
1443 /* Process a FINAL_PRESENCE_SET.
1445 This gives information about a cpu unit reservation requirements.
1446 We fill a struct unit_pattern_rel_decl (presence) with information
1447 used later by `expand_automata'. */
1448 static void
1449 gen_final_presence_set (rtx def)
1451 gen_presence_absence_set (def, TRUE, TRUE);
1454 /* Process an ABSENCE_SET.
1456 This gives information about a cpu unit reservation requirements.
1457 We fill a struct unit_pattern_rel_decl (absence) with information
1458 used later by `expand_automata'. */
1459 static void
1460 gen_absence_set (rtx def)
1462 gen_presence_absence_set (def, FALSE, FALSE);
1465 /* Process a FINAL_ABSENCE_SET.
1467 This gives information about a cpu unit reservation requirements.
1468 We fill a struct unit_pattern_rel_decl (absence) with information
1469 used later by `expand_automata'. */
1470 static void
1471 gen_final_absence_set (rtx def)
1473 gen_presence_absence_set (def, FALSE, TRUE);
1476 /* Process a DEFINE_AUTOMATON.
1478 This gives information about a finite state automaton used for
1479 recognizing pipeline hazards. We fill a struct automaton_decl
1480 with information used later by `expand_automata'. */
1481 static void
1482 gen_automaton (rtx def)
1484 decl_t decl;
1485 char **str_automata;
1486 int vect_length;
1487 int i;
1489 str_automata = get_str_vect (XSTR (def, 0), &vect_length, ',', FALSE);
1490 if (str_automata == NULL)
1491 fatal ("invalid string `%s' in define_automaton", XSTR (def, 0));
1492 for (i = 0; i < vect_length; i++)
1494 decl = create_node (sizeof (struct decl));
1495 decl->mode = dm_automaton;
1496 decl->pos = 0;
1497 DECL_AUTOMATON (decl)->name = check_name (str_automata [i], decl->pos);
1498 VEC_safe_push (decl_t,heap, decls, decl);
1502 /* Process an AUTOMATA_OPTION.
1504 This gives information how to generate finite state automaton used
1505 for recognizing pipeline hazards. */
1506 static void
1507 gen_automata_option (rtx def)
1509 if (strcmp (XSTR (def, 0), NO_MINIMIZATION_OPTION + 1) == 0)
1510 no_minimization_flag = 1;
1511 else if (strcmp (XSTR (def, 0), TIME_OPTION + 1) == 0)
1512 time_flag = 1;
1513 else if (strcmp (XSTR (def, 0), V_OPTION + 1) == 0)
1514 v_flag = 1;
1515 else if (strcmp (XSTR (def, 0), W_OPTION + 1) == 0)
1516 w_flag = 1;
1517 else if (strcmp (XSTR (def, 0), NDFA_OPTION + 1) == 0)
1518 ndfa_flag = 1;
1519 else if (strcmp (XSTR (def, 0), PROGRESS_OPTION + 1) == 0)
1520 progress_flag = 1;
1521 else
1522 fatal ("invalid option `%s' in automata_option", XSTR (def, 0));
1525 /* Name in reservation to denote absence reservation. */
1526 #define NOTHING_NAME "nothing"
1528 /* The following string contains original reservation string being
1529 parsed. */
1530 static const char *reserv_str;
1532 /* Parse an element in STR. */
1533 static regexp_t
1534 gen_regexp_el (const char *str)
1536 regexp_t regexp;
1537 char *dstr;
1538 int len;
1540 if (*str == '(')
1542 len = strlen (str);
1543 if (str [len - 1] != ')')
1544 fatal ("garbage after ) in reservation `%s'", reserv_str);
1545 dstr = alloca (len - 1);
1546 memcpy (dstr, str + 1, len - 2);
1547 dstr [len-2] = '\0';
1548 regexp = gen_regexp_sequence (dstr);
1550 else if (strcmp (str, NOTHING_NAME) == 0)
1552 regexp = create_node (sizeof (struct decl));
1553 regexp->mode = rm_nothing;
1555 else
1557 regexp = create_node (sizeof (struct decl));
1558 regexp->mode = rm_unit;
1559 REGEXP_UNIT (regexp)->name = str;
1561 return regexp;
1564 /* Parse construction `repeat' in STR. */
1565 static regexp_t
1566 gen_regexp_repeat (const char *str)
1568 regexp_t regexp;
1569 regexp_t repeat;
1570 char **repeat_vect;
1571 int els_num;
1572 int i;
1574 repeat_vect = get_str_vect (str, &els_num, '*', TRUE);
1575 if (repeat_vect == NULL)
1576 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1577 if (els_num > 1)
1579 regexp = gen_regexp_el (repeat_vect [0]);
1580 for (i = 1; i < els_num; i++)
1582 repeat = create_node (sizeof (struct regexp));
1583 repeat->mode = rm_repeat;
1584 REGEXP_REPEAT (repeat)->regexp = regexp;
1585 REGEXP_REPEAT (repeat)->repeat_num = atoi (repeat_vect [i]);
1586 if (REGEXP_REPEAT (repeat)->repeat_num <= 1)
1587 fatal ("repetition `%s' <= 1 in reservation `%s'",
1588 str, reserv_str);
1589 regexp = repeat;
1591 return regexp;
1593 else
1594 return gen_regexp_el (str);
1597 /* Parse reservation STR which possibly contains separator '+'. */
1598 static regexp_t
1599 gen_regexp_allof (const char *str)
1601 regexp_t allof;
1602 char **allof_vect;
1603 int els_num;
1604 int i;
1606 allof_vect = get_str_vect (str, &els_num, '+', TRUE);
1607 if (allof_vect == NULL)
1608 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1609 if (els_num > 1)
1611 allof = create_node (sizeof (struct regexp)
1612 + sizeof (regexp_t) * (els_num - 1));
1613 allof->mode = rm_allof;
1614 REGEXP_ALLOF (allof)->regexps_num = els_num;
1615 for (i = 0; i < els_num; i++)
1616 REGEXP_ALLOF (allof)->regexps [i] = gen_regexp_repeat (allof_vect [i]);
1617 return allof;
1619 else
1620 return gen_regexp_repeat (str);
1623 /* Parse reservation STR which possibly contains separator '|'. */
1624 static regexp_t
1625 gen_regexp_oneof (const char *str)
1627 regexp_t oneof;
1628 char **oneof_vect;
1629 int els_num;
1630 int i;
1632 oneof_vect = get_str_vect (str, &els_num, '|', TRUE);
1633 if (oneof_vect == NULL)
1634 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1635 if (els_num > 1)
1637 oneof = create_node (sizeof (struct regexp)
1638 + sizeof (regexp_t) * (els_num - 1));
1639 oneof->mode = rm_oneof;
1640 REGEXP_ONEOF (oneof)->regexps_num = els_num;
1641 for (i = 0; i < els_num; i++)
1642 REGEXP_ONEOF (oneof)->regexps [i] = gen_regexp_allof (oneof_vect [i]);
1643 return oneof;
1645 else
1646 return gen_regexp_allof (str);
1649 /* Parse reservation STR which possibly contains separator ','. */
1650 static regexp_t
1651 gen_regexp_sequence (const char *str)
1653 regexp_t sequence;
1654 char **sequence_vect;
1655 int els_num;
1656 int i;
1658 sequence_vect = get_str_vect (str, &els_num, ',', TRUE);
1659 if (els_num > 1)
1661 sequence = create_node (sizeof (struct regexp)
1662 + sizeof (regexp_t) * (els_num - 1));
1663 sequence->mode = rm_sequence;
1664 REGEXP_SEQUENCE (sequence)->regexps_num = els_num;
1665 for (i = 0; i < els_num; i++)
1666 REGEXP_SEQUENCE (sequence)->regexps [i]
1667 = gen_regexp_oneof (sequence_vect [i]);
1668 return sequence;
1670 else
1671 return gen_regexp_oneof (str);
1674 /* Parse construction reservation STR. */
1675 static regexp_t
1676 gen_regexp (const char *str)
1678 reserv_str = str;
1679 return gen_regexp_sequence (str);;
1682 /* Process a DEFINE_RESERVATION.
1684 This gives information about a reservation of cpu units. We fill
1685 in a struct reserv_decl with information used later by
1686 `expand_automata'. */
1687 static void
1688 gen_reserv (rtx def)
1690 decl_t decl;
1692 decl = create_node (sizeof (struct decl));
1693 decl->mode = dm_reserv;
1694 decl->pos = 0;
1695 DECL_RESERV (decl)->name = check_name (XSTR (def, 0), decl->pos);
1696 DECL_RESERV (decl)->regexp = gen_regexp (XSTR (def, 1));
1697 VEC_safe_push (decl_t,heap, decls, decl);
1700 /* Process a DEFINE_INSN_RESERVATION.
1702 This gives information about the reservation of cpu units by an
1703 insn. We fill a struct insn_reserv_decl with information used
1704 later by `expand_automata'. */
1705 static void
1706 gen_insn_reserv (rtx def)
1708 decl_t decl;
1710 decl = create_node (sizeof (struct decl));
1711 decl->mode = dm_insn_reserv;
1712 decl->pos = 0;
1713 DECL_INSN_RESERV (decl)->name
1714 = check_name (XSTR (def, 0), decl->pos);
1715 DECL_INSN_RESERV (decl)->default_latency = XINT (def, 1);
1716 DECL_INSN_RESERV (decl)->condexp = XEXP (def, 2);
1717 DECL_INSN_RESERV (decl)->regexp = gen_regexp (XSTR (def, 3));
1718 VEC_safe_push (decl_t,heap, decls, decl);
1723 /* The function evaluates hash value (0..UINT_MAX) of string. */
1724 static unsigned
1725 string_hash (const char *string)
1727 unsigned result, i;
1729 for (result = i = 0;*string++ != '\0'; i++)
1730 result += ((unsigned char) *string << (i % CHAR_BIT));
1731 return result;
1736 /* This page contains abstract data `table of automaton declarations'.
1737 Elements of the table is nodes representing automaton declarations.
1738 Key of the table elements is name of given automaton. Remember
1739 that automaton names have own space. */
1741 /* The function evaluates hash value of an automaton declaration. The
1742 function is used by abstract data `hashtab'. The function returns
1743 hash value (0..UINT_MAX) of given automaton declaration. */
1744 static hashval_t
1745 automaton_decl_hash (const void *automaton_decl)
1747 const decl_t decl = (decl_t) automaton_decl;
1749 gcc_assert (decl->mode != dm_automaton
1750 || DECL_AUTOMATON (decl)->name);
1751 return string_hash (DECL_AUTOMATON (decl)->name);
1754 /* The function tests automaton declarations on equality of their
1755 keys. The function is used by abstract data `hashtab'. The
1756 function returns 1 if the declarations have the same key, 0
1757 otherwise. */
1758 static int
1759 automaton_decl_eq_p (const void* automaton_decl_1,
1760 const void* automaton_decl_2)
1762 const decl_t decl1 = (decl_t) automaton_decl_1;
1763 const decl_t decl2 = (decl_t) automaton_decl_2;
1765 gcc_assert (decl1->mode == dm_automaton
1766 && DECL_AUTOMATON (decl1)->name
1767 && decl2->mode == dm_automaton
1768 && DECL_AUTOMATON (decl2)->name);
1769 return strcmp (DECL_AUTOMATON (decl1)->name,
1770 DECL_AUTOMATON (decl2)->name) == 0;
1773 /* The automaton declaration table itself is represented by the
1774 following variable. */
1775 static htab_t automaton_decl_table;
1777 /* The function inserts automaton declaration into the table. The
1778 function does nothing if an automaton declaration with the same key
1779 exists already in the table. The function returns automaton
1780 declaration node in the table with the same key as given automaton
1781 declaration node. */
1782 static decl_t
1783 insert_automaton_decl (decl_t automaton_decl)
1785 void **entry_ptr;
1787 entry_ptr = htab_find_slot (automaton_decl_table, automaton_decl, 1);
1788 if (*entry_ptr == NULL)
1789 *entry_ptr = (void *) automaton_decl;
1790 return (decl_t) *entry_ptr;
1793 /* The following variable value is node representing automaton
1794 declaration. The node used for searching automaton declaration
1795 with given name. */
1796 static struct decl work_automaton_decl;
1798 /* The function searches for automaton declaration in the table with
1799 the same key as node representing name of the automaton
1800 declaration. The function returns node found in the table, NULL if
1801 such node does not exist in the table. */
1802 static decl_t
1803 find_automaton_decl (const char *name)
1805 void *entry;
1807 work_automaton_decl.mode = dm_automaton;
1808 DECL_AUTOMATON (&work_automaton_decl)->name = name;
1809 entry = htab_find (automaton_decl_table, &work_automaton_decl);
1810 return (decl_t) entry;
1813 /* The function creates empty automaton declaration table and node
1814 representing automaton declaration and used for searching automaton
1815 declaration with given name. The function must be called only once
1816 before any work with the automaton declaration table. */
1817 static void
1818 initiate_automaton_decl_table (void)
1820 work_automaton_decl.mode = dm_automaton;
1821 automaton_decl_table = htab_create (10, automaton_decl_hash,
1822 automaton_decl_eq_p, (htab_del) 0);
1825 /* The function deletes the automaton declaration table. Only call of
1826 function `initiate_automaton_decl_table' is possible immediately
1827 after this function call. */
1828 static void
1829 finish_automaton_decl_table (void)
1831 htab_delete (automaton_decl_table);
1836 /* This page contains abstract data `table of insn declarations'.
1837 Elements of the table is nodes representing insn declarations. Key
1838 of the table elements is name of given insn (in corresponding
1839 define_insn_reservation). Remember that insn names have own
1840 space. */
1842 /* The function evaluates hash value of an insn declaration. The
1843 function is used by abstract data `hashtab'. The function returns
1844 hash value (0..UINT_MAX) of given insn declaration. */
1845 static hashval_t
1846 insn_decl_hash (const void *insn_decl)
1848 const decl_t decl = (decl_t) insn_decl;
1850 gcc_assert (decl->mode == dm_insn_reserv
1851 && DECL_INSN_RESERV (decl)->name);
1852 return string_hash (DECL_INSN_RESERV (decl)->name);
1855 /* The function tests insn declarations on equality of their keys.
1856 The function is used by abstract data `hashtab'. The function
1857 returns 1 if declarations have the same key, 0 otherwise. */
1858 static int
1859 insn_decl_eq_p (const void *insn_decl_1, const void *insn_decl_2)
1861 const decl_t decl1 = (decl_t) insn_decl_1;
1862 const decl_t decl2 = (decl_t) insn_decl_2;
1864 gcc_assert (decl1->mode == dm_insn_reserv
1865 && DECL_INSN_RESERV (decl1)->name
1866 && decl2->mode == dm_insn_reserv
1867 && DECL_INSN_RESERV (decl2)->name);
1868 return strcmp (DECL_INSN_RESERV (decl1)->name,
1869 DECL_INSN_RESERV (decl2)->name) == 0;
1872 /* The insn declaration table itself is represented by the following
1873 variable. The table does not contain insn reservation
1874 declarations. */
1875 static htab_t insn_decl_table;
1877 /* The function inserts insn declaration into the table. The function
1878 does nothing if an insn declaration with the same key exists
1879 already in the table. The function returns insn declaration node
1880 in the table with the same key as given insn declaration node. */
1881 static decl_t
1882 insert_insn_decl (decl_t insn_decl)
1884 void **entry_ptr;
1886 entry_ptr = htab_find_slot (insn_decl_table, insn_decl, 1);
1887 if (*entry_ptr == NULL)
1888 *entry_ptr = (void *) insn_decl;
1889 return (decl_t) *entry_ptr;
1892 /* The following variable value is node representing insn reservation
1893 declaration. The node used for searching insn reservation
1894 declaration with given name. */
1895 static struct decl work_insn_decl;
1897 /* The function searches for insn reservation declaration in the table
1898 with the same key as node representing name of the insn reservation
1899 declaration. The function returns node found in the table, NULL if
1900 such node does not exist in the table. */
1901 static decl_t
1902 find_insn_decl (const char *name)
1904 void *entry;
1906 work_insn_decl.mode = dm_insn_reserv;
1907 DECL_INSN_RESERV (&work_insn_decl)->name = name;
1908 entry = htab_find (insn_decl_table, &work_insn_decl);
1909 return (decl_t) entry;
1912 /* The function creates empty insn declaration table and node
1913 representing insn declaration and used for searching insn
1914 declaration with given name. The function must be called only once
1915 before any work with the insn declaration table. */
1916 static void
1917 initiate_insn_decl_table (void)
1919 work_insn_decl.mode = dm_insn_reserv;
1920 insn_decl_table = htab_create (10, insn_decl_hash, insn_decl_eq_p,
1921 (htab_del) 0);
1924 /* The function deletes the insn declaration table. Only call of
1925 function `initiate_insn_decl_table' is possible immediately after
1926 this function call. */
1927 static void
1928 finish_insn_decl_table (void)
1930 htab_delete (insn_decl_table);
1935 /* This page contains abstract data `table of declarations'. Elements
1936 of the table is nodes representing declarations (of units and
1937 reservations). Key of the table elements is names of given
1938 declarations. */
1940 /* The function evaluates hash value of a declaration. The function
1941 is used by abstract data `hashtab'. The function returns hash
1942 value (0..UINT_MAX) of given declaration. */
1943 static hashval_t
1944 decl_hash (const void *decl)
1946 const decl_t d = (const decl_t) decl;
1948 gcc_assert ((d->mode == dm_unit && DECL_UNIT (d)->name)
1949 || (d->mode == dm_reserv && DECL_RESERV (d)->name));
1950 return string_hash (d->mode == dm_unit
1951 ? DECL_UNIT (d)->name : DECL_RESERV (d)->name);
1954 /* The function tests declarations on equality of their keys. The
1955 function is used by abstract data 'hashtab'. The function
1956 returns 1 if the declarations have the same key, 0 otherwise. */
1957 static int
1958 decl_eq_p (const void *decl_1, const void *decl_2)
1960 const decl_t d1 = (const decl_t) decl_1;
1961 const decl_t d2 = (const decl_t) decl_2;
1963 gcc_assert ((d1->mode == dm_unit && DECL_UNIT (d1)->name)
1964 || (d1->mode == dm_reserv && DECL_RESERV (d1)->name));
1965 gcc_assert ((d2->mode == dm_unit && DECL_UNIT (d2)->name)
1966 || (d2->mode == dm_reserv && DECL_RESERV (d2)->name));
1967 return strcmp ((d1->mode == dm_unit
1968 ? DECL_UNIT (d1)->name : DECL_RESERV (d1)->name),
1969 (d2->mode == dm_unit
1970 ? DECL_UNIT (d2)->name : DECL_RESERV (d2)->name)) == 0;
1973 /* The declaration table itself is represented by the following
1974 variable. */
1975 static htab_t decl_table;
1977 /* The function inserts declaration into the table. The function does
1978 nothing if a declaration with the same key exists already in the
1979 table. The function returns declaration node in the table with the
1980 same key as given declaration node. */
1982 static decl_t
1983 insert_decl (decl_t decl)
1985 void **entry_ptr;
1987 entry_ptr = htab_find_slot (decl_table, decl, 1);
1988 if (*entry_ptr == NULL)
1989 *entry_ptr = (void *) decl;
1990 return (decl_t) *entry_ptr;
1993 /* The following variable value is node representing declaration. The
1994 node used for searching declaration with given name. */
1995 static struct decl work_decl;
1997 /* The function searches for declaration in the table with the same
1998 key as node representing name of the declaration. The function
1999 returns node found in the table, NULL if such node does not exist
2000 in the table. */
2001 static decl_t
2002 find_decl (const char *name)
2004 void *entry;
2006 work_decl.mode = dm_unit;
2007 DECL_UNIT (&work_decl)->name = name;
2008 entry = htab_find (decl_table, &work_decl);
2009 return (decl_t) entry;
2012 /* The function creates empty declaration table and node representing
2013 declaration and used for searching declaration with given name.
2014 The function must be called only once before any work with the
2015 declaration table. */
2016 static void
2017 initiate_decl_table (void)
2019 work_decl.mode = dm_unit;
2020 decl_table = htab_create (10, decl_hash, decl_eq_p, (htab_del) 0);
2023 /* The function deletes the declaration table. Only call of function
2024 `initiate_declaration_table' is possible immediately after this
2025 function call. */
2026 static void
2027 finish_decl_table (void)
2029 htab_delete (decl_table);
2034 /* This page contains checker of pipeline hazard description. */
2036 /* Checking NAMES in an exclusion clause vector and returning formed
2037 unit_set_el_list. */
2038 static unit_set_el_t
2039 process_excls (char **names, int num, pos_t excl_pos ATTRIBUTE_UNUSED)
2041 unit_set_el_t el_list;
2042 unit_set_el_t last_el;
2043 unit_set_el_t new_el;
2044 decl_t decl_in_table;
2045 int i;
2047 el_list = NULL;
2048 last_el = NULL;
2049 for (i = 0; i < num; i++)
2051 decl_in_table = find_decl (names [i]);
2052 if (decl_in_table == NULL)
2053 error ("unit `%s' in exclusion is not declared", names [i]);
2054 else if (decl_in_table->mode != dm_unit)
2055 error ("`%s' in exclusion is not unit", names [i]);
2056 else
2058 new_el = create_node (sizeof (struct unit_set_el));
2059 new_el->unit_decl = DECL_UNIT (decl_in_table);
2060 new_el->next_unit_set_el = NULL;
2061 if (last_el == NULL)
2062 el_list = last_el = new_el;
2063 else
2065 last_el->next_unit_set_el = new_el;
2066 last_el = last_el->next_unit_set_el;
2070 return el_list;
2073 /* The function adds each element from SOURCE_LIST to the exclusion
2074 list of the each element from DEST_LIST. Checking situation "unit
2075 excludes itself". */
2076 static void
2077 add_excls (unit_set_el_t dest_list, unit_set_el_t source_list,
2078 pos_t excl_pos ATTRIBUTE_UNUSED)
2080 unit_set_el_t dst;
2081 unit_set_el_t src;
2082 unit_set_el_t curr_el;
2083 unit_set_el_t prev_el;
2084 unit_set_el_t copy;
2086 for (dst = dest_list; dst != NULL; dst = dst->next_unit_set_el)
2087 for (src = source_list; src != NULL; src = src->next_unit_set_el)
2089 if (dst->unit_decl == src->unit_decl)
2091 error ("unit `%s' excludes itself", src->unit_decl->name);
2092 continue;
2094 if (dst->unit_decl->automaton_name != NULL
2095 && src->unit_decl->automaton_name != NULL
2096 && strcmp (dst->unit_decl->automaton_name,
2097 src->unit_decl->automaton_name) != 0)
2099 error ("units `%s' and `%s' in exclusion set belong to different automata",
2100 src->unit_decl->name, dst->unit_decl->name);
2101 continue;
2103 for (curr_el = dst->unit_decl->excl_list, prev_el = NULL;
2104 curr_el != NULL;
2105 prev_el = curr_el, curr_el = curr_el->next_unit_set_el)
2106 if (curr_el->unit_decl == src->unit_decl)
2107 break;
2108 if (curr_el == NULL)
2110 /* Element not found - insert. */
2111 copy = copy_node (src, sizeof (*src));
2112 copy->next_unit_set_el = NULL;
2113 if (prev_el == NULL)
2114 dst->unit_decl->excl_list = copy;
2115 else
2116 prev_el->next_unit_set_el = copy;
2121 /* Checking NAMES in presence/absence clause and returning the
2122 formed unit_set_el_list. The function is called only after
2123 processing all exclusion sets. */
2124 static unit_set_el_t
2125 process_presence_absence_names (char **names, int num,
2126 pos_t req_pos ATTRIBUTE_UNUSED,
2127 int presence_p, int final_p)
2129 unit_set_el_t el_list;
2130 unit_set_el_t last_el;
2131 unit_set_el_t new_el;
2132 decl_t decl_in_table;
2133 int i;
2135 el_list = NULL;
2136 last_el = NULL;
2137 for (i = 0; i < num; i++)
2139 decl_in_table = find_decl (names [i]);
2140 if (decl_in_table == NULL)
2141 error ((presence_p
2142 ? (final_p
2143 ? "unit `%s' in final presence set is not declared"
2144 : "unit `%s' in presence set is not declared")
2145 : (final_p
2146 ? "unit `%s' in final absence set is not declared"
2147 : "unit `%s' in absence set is not declared")), names [i]);
2148 else if (decl_in_table->mode != dm_unit)
2149 error ((presence_p
2150 ? (final_p
2151 ? "`%s' in final presence set is not unit"
2152 : "`%s' in presence set is not unit")
2153 : (final_p
2154 ? "`%s' in final absence set is not unit"
2155 : "`%s' in absence set is not unit")), names [i]);
2156 else
2158 new_el = create_node (sizeof (struct unit_set_el));
2159 new_el->unit_decl = DECL_UNIT (decl_in_table);
2160 new_el->next_unit_set_el = NULL;
2161 if (last_el == NULL)
2162 el_list = last_el = new_el;
2163 else
2165 last_el->next_unit_set_el = new_el;
2166 last_el = last_el->next_unit_set_el;
2170 return el_list;
2173 /* Checking NAMES in patterns of a presence/absence clause and
2174 returning the formed pattern_set_el_list. The function is called
2175 only after processing all exclusion sets. */
2176 static pattern_set_el_t
2177 process_presence_absence_patterns (char ***patterns, int num,
2178 pos_t req_pos ATTRIBUTE_UNUSED,
2179 int presence_p, int final_p)
2181 pattern_set_el_t el_list;
2182 pattern_set_el_t last_el;
2183 pattern_set_el_t new_el;
2184 decl_t decl_in_table;
2185 int i, j;
2187 el_list = NULL;
2188 last_el = NULL;
2189 for (i = 0; i < num; i++)
2191 for (j = 0; patterns [i] [j] != NULL; j++)
2193 new_el = create_node (sizeof (struct pattern_set_el)
2194 + sizeof (struct unit_decl *) * j);
2195 new_el->unit_decls
2196 = (struct unit_decl **) ((char *) new_el
2197 + sizeof (struct pattern_set_el));
2198 new_el->next_pattern_set_el = NULL;
2199 if (last_el == NULL)
2200 el_list = last_el = new_el;
2201 else
2203 last_el->next_pattern_set_el = new_el;
2204 last_el = last_el->next_pattern_set_el;
2206 new_el->units_num = 0;
2207 for (j = 0; patterns [i] [j] != NULL; j++)
2209 decl_in_table = find_decl (patterns [i] [j]);
2210 if (decl_in_table == NULL)
2211 error ((presence_p
2212 ? (final_p
2213 ? "unit `%s' in final presence set is not declared"
2214 : "unit `%s' in presence set is not declared")
2215 : (final_p
2216 ? "unit `%s' in final absence set is not declared"
2217 : "unit `%s' in absence set is not declared")),
2218 patterns [i] [j]);
2219 else if (decl_in_table->mode != dm_unit)
2220 error ((presence_p
2221 ? (final_p
2222 ? "`%s' in final presence set is not unit"
2223 : "`%s' in presence set is not unit")
2224 : (final_p
2225 ? "`%s' in final absence set is not unit"
2226 : "`%s' in absence set is not unit")),
2227 patterns [i] [j]);
2228 else
2230 new_el->unit_decls [new_el->units_num]
2231 = DECL_UNIT (decl_in_table);
2232 new_el->units_num++;
2236 return el_list;
2239 /* The function adds each element from PATTERN_LIST to presence (if
2240 PRESENCE_P) or absence list of the each element from DEST_LIST.
2241 Checking situations "unit requires own absence", and "unit excludes
2242 and requires presence of ...", "unit requires absence and presence
2243 of ...", "units in (final) presence set belong to different
2244 automata", and "units in (final) absence set belong to different
2245 automata". Remember that we process absence sets only after all
2246 presence sets. */
2247 static void
2248 add_presence_absence (unit_set_el_t dest_list,
2249 pattern_set_el_t pattern_list,
2250 pos_t req_pos ATTRIBUTE_UNUSED,
2251 int presence_p, int final_p)
2253 unit_set_el_t dst;
2254 pattern_set_el_t pat;
2255 struct unit_decl *unit;
2256 unit_set_el_t curr_excl_el;
2257 pattern_set_el_t curr_pat_el;
2258 pattern_set_el_t prev_el;
2259 pattern_set_el_t copy;
2260 int i;
2261 int no_error_flag;
2263 for (dst = dest_list; dst != NULL; dst = dst->next_unit_set_el)
2264 for (pat = pattern_list; pat != NULL; pat = pat->next_pattern_set_el)
2266 for (i = 0; i < pat->units_num; i++)
2268 unit = pat->unit_decls [i];
2269 if (dst->unit_decl == unit && pat->units_num == 1 && !presence_p)
2271 error ("unit `%s' requires own absence", unit->name);
2272 continue;
2274 if (dst->unit_decl->automaton_name != NULL
2275 && unit->automaton_name != NULL
2276 && strcmp (dst->unit_decl->automaton_name,
2277 unit->automaton_name) != 0)
2279 error ((presence_p
2280 ? (final_p
2281 ? "units `%s' and `%s' in final presence set belong to different automata"
2282 : "units `%s' and `%s' in presence set belong to different automata")
2283 : (final_p
2284 ? "units `%s' and `%s' in final absence set belong to different automata"
2285 : "units `%s' and `%s' in absence set belong to different automata")),
2286 unit->name, dst->unit_decl->name);
2287 continue;
2289 no_error_flag = 1;
2290 if (presence_p)
2291 for (curr_excl_el = dst->unit_decl->excl_list;
2292 curr_excl_el != NULL;
2293 curr_excl_el = curr_excl_el->next_unit_set_el)
2295 if (unit == curr_excl_el->unit_decl && pat->units_num == 1)
2297 if (!w_flag)
2299 error ("unit `%s' excludes and requires presence of `%s'",
2300 dst->unit_decl->name, unit->name);
2301 no_error_flag = 0;
2303 else
2304 warning
2305 (0, "unit `%s' excludes and requires presence of `%s'",
2306 dst->unit_decl->name, unit->name);
2309 else if (pat->units_num == 1)
2310 for (curr_pat_el = dst->unit_decl->presence_list;
2311 curr_pat_el != NULL;
2312 curr_pat_el = curr_pat_el->next_pattern_set_el)
2313 if (curr_pat_el->units_num == 1
2314 && unit == curr_pat_el->unit_decls [0])
2316 if (!w_flag)
2318 error
2319 ("unit `%s' requires absence and presence of `%s'",
2320 dst->unit_decl->name, unit->name);
2321 no_error_flag = 0;
2323 else
2324 warning
2325 (0, "unit `%s' requires absence and presence of `%s'",
2326 dst->unit_decl->name, unit->name);
2328 if (no_error_flag)
2330 for (prev_el = (presence_p
2331 ? (final_p
2332 ? dst->unit_decl->final_presence_list
2333 : dst->unit_decl->final_presence_list)
2334 : (final_p
2335 ? dst->unit_decl->final_absence_list
2336 : dst->unit_decl->absence_list));
2337 prev_el != NULL && prev_el->next_pattern_set_el != NULL;
2338 prev_el = prev_el->next_pattern_set_el)
2340 copy = copy_node (pat, sizeof (*pat));
2341 copy->next_pattern_set_el = NULL;
2342 if (prev_el == NULL)
2344 if (presence_p)
2346 if (final_p)
2347 dst->unit_decl->final_presence_list = copy;
2348 else
2349 dst->unit_decl->presence_list = copy;
2351 else if (final_p)
2352 dst->unit_decl->final_absence_list = copy;
2353 else
2354 dst->unit_decl->absence_list = copy;
2356 else
2357 prev_el->next_pattern_set_el = copy;
2364 /* The function searches for bypass with given IN_INSN_RESERV in given
2365 BYPASS_LIST. */
2366 static struct bypass_decl *
2367 find_bypass (struct bypass_decl *bypass_list,
2368 struct insn_reserv_decl *in_insn_reserv)
2370 struct bypass_decl *bypass;
2372 for (bypass = bypass_list; bypass != NULL; bypass = bypass->next)
2373 if (bypass->in_insn_reserv == in_insn_reserv)
2374 break;
2375 return bypass;
2378 /* The function processes pipeline description declarations, checks
2379 their correctness, and forms exclusion/presence/absence sets. */
2380 static void
2381 process_decls (void)
2383 decl_t decl;
2384 decl_t automaton_decl;
2385 decl_t decl_in_table;
2386 decl_t out_insn_reserv;
2387 decl_t in_insn_reserv;
2388 struct bypass_decl *bypass;
2389 int automaton_presence;
2390 int i;
2392 /* Checking repeated automata declarations. */
2393 automaton_presence = 0;
2394 for (i = 0; i < description->decls_num; i++)
2396 decl = description->decls [i];
2397 if (decl->mode == dm_automaton)
2399 automaton_presence = 1;
2400 decl_in_table = insert_automaton_decl (decl);
2401 if (decl_in_table != decl)
2403 if (!w_flag)
2404 error ("repeated declaration of automaton `%s'",
2405 DECL_AUTOMATON (decl)->name);
2406 else
2407 warning (0, "repeated declaration of automaton `%s'",
2408 DECL_AUTOMATON (decl)->name);
2412 /* Checking undeclared automata, repeated declarations (except for
2413 automata) and correctness of their attributes (insn latency times
2414 etc.). */
2415 for (i = 0; i < description->decls_num; i++)
2417 decl = description->decls [i];
2418 if (decl->mode == dm_insn_reserv)
2420 if (DECL_INSN_RESERV (decl)->default_latency < 0)
2421 error ("define_insn_reservation `%s' has negative latency time",
2422 DECL_INSN_RESERV (decl)->name);
2423 DECL_INSN_RESERV (decl)->insn_num = description->insns_num;
2424 description->insns_num++;
2425 decl_in_table = insert_insn_decl (decl);
2426 if (decl_in_table != decl)
2427 error ("`%s' is already used as insn reservation name",
2428 DECL_INSN_RESERV (decl)->name);
2430 else if (decl->mode == dm_bypass)
2432 if (DECL_BYPASS (decl)->latency < 0)
2433 error ("define_bypass `%s - %s' has negative latency time",
2434 DECL_BYPASS (decl)->out_insn_name,
2435 DECL_BYPASS (decl)->in_insn_name);
2437 else if (decl->mode == dm_unit || decl->mode == dm_reserv)
2439 if (decl->mode == dm_unit)
2441 DECL_UNIT (decl)->automaton_decl = NULL;
2442 if (DECL_UNIT (decl)->automaton_name != NULL)
2444 automaton_decl
2445 = find_automaton_decl (DECL_UNIT (decl)->automaton_name);
2446 if (automaton_decl == NULL)
2447 error ("automaton `%s' is not declared",
2448 DECL_UNIT (decl)->automaton_name);
2449 else
2451 DECL_AUTOMATON (automaton_decl)->automaton_is_used = 1;
2452 DECL_UNIT (decl)->automaton_decl
2453 = DECL_AUTOMATON (automaton_decl);
2456 else if (automaton_presence)
2457 error ("define_unit `%s' without automaton when one defined",
2458 DECL_UNIT (decl)->name);
2459 DECL_UNIT (decl)->unit_num = description->units_num;
2460 description->units_num++;
2461 if (strcmp (DECL_UNIT (decl)->name, NOTHING_NAME) == 0)
2463 error ("`%s' is declared as cpu unit", NOTHING_NAME);
2464 continue;
2466 decl_in_table = find_decl (DECL_UNIT (decl)->name);
2468 else
2470 if (strcmp (DECL_RESERV (decl)->name, NOTHING_NAME) == 0)
2472 error ("`%s' is declared as cpu reservation", NOTHING_NAME);
2473 continue;
2475 decl_in_table = find_decl (DECL_RESERV (decl)->name);
2477 if (decl_in_table == NULL)
2478 decl_in_table = insert_decl (decl);
2479 else
2481 if (decl->mode == dm_unit)
2482 error ("repeated declaration of unit `%s'",
2483 DECL_UNIT (decl)->name);
2484 else
2485 error ("repeated declaration of reservation `%s'",
2486 DECL_RESERV (decl)->name);
2490 /* Check bypasses and form list of bypasses for each (output)
2491 insn. */
2492 for (i = 0; i < description->decls_num; i++)
2494 decl = description->decls [i];
2495 if (decl->mode == dm_bypass)
2497 out_insn_reserv = find_insn_decl (DECL_BYPASS (decl)->out_insn_name);
2498 in_insn_reserv = find_insn_decl (DECL_BYPASS (decl)->in_insn_name);
2499 if (out_insn_reserv == NULL)
2500 error ("there is no insn reservation `%s'",
2501 DECL_BYPASS (decl)->out_insn_name);
2502 else if (in_insn_reserv == NULL)
2503 error ("there is no insn reservation `%s'",
2504 DECL_BYPASS (decl)->in_insn_name);
2505 else
2507 DECL_BYPASS (decl)->out_insn_reserv
2508 = DECL_INSN_RESERV (out_insn_reserv);
2509 DECL_BYPASS (decl)->in_insn_reserv
2510 = DECL_INSN_RESERV (in_insn_reserv);
2511 bypass
2512 = find_bypass (DECL_INSN_RESERV (out_insn_reserv)->bypass_list,
2513 DECL_BYPASS (decl)->in_insn_reserv);
2514 if (bypass != NULL)
2516 if (DECL_BYPASS (decl)->latency == bypass->latency)
2518 if (!w_flag)
2519 error
2520 ("the same bypass `%s - %s' is already defined",
2521 DECL_BYPASS (decl)->out_insn_name,
2522 DECL_BYPASS (decl)->in_insn_name);
2523 else
2524 warning
2525 (0, "the same bypass `%s - %s' is already defined",
2526 DECL_BYPASS (decl)->out_insn_name,
2527 DECL_BYPASS (decl)->in_insn_name);
2529 else
2530 error ("bypass `%s - %s' is already defined",
2531 DECL_BYPASS (decl)->out_insn_name,
2532 DECL_BYPASS (decl)->in_insn_name);
2534 else
2536 DECL_BYPASS (decl)->next
2537 = DECL_INSN_RESERV (out_insn_reserv)->bypass_list;
2538 DECL_INSN_RESERV (out_insn_reserv)->bypass_list
2539 = DECL_BYPASS (decl);
2545 /* Check exclusion set declarations and form exclusion sets. */
2546 for (i = 0; i < description->decls_num; i++)
2548 decl = description->decls [i];
2549 if (decl->mode == dm_excl)
2551 unit_set_el_t unit_set_el_list;
2552 unit_set_el_t unit_set_el_list_2;
2554 unit_set_el_list
2555 = process_excls (DECL_EXCL (decl)->names,
2556 DECL_EXCL (decl)->first_list_length, decl->pos);
2557 unit_set_el_list_2
2558 = process_excls (&DECL_EXCL (decl)->names
2559 [DECL_EXCL (decl)->first_list_length],
2560 DECL_EXCL (decl)->all_names_num
2561 - DECL_EXCL (decl)->first_list_length,
2562 decl->pos);
2563 add_excls (unit_set_el_list, unit_set_el_list_2, decl->pos);
2564 add_excls (unit_set_el_list_2, unit_set_el_list, decl->pos);
2568 /* Check presence set declarations and form presence sets. */
2569 for (i = 0; i < description->decls_num; i++)
2571 decl = description->decls [i];
2572 if (decl->mode == dm_presence)
2574 unit_set_el_t unit_set_el_list;
2575 pattern_set_el_t pattern_set_el_list;
2577 unit_set_el_list
2578 = process_presence_absence_names
2579 (DECL_PRESENCE (decl)->names, DECL_PRESENCE (decl)->names_num,
2580 decl->pos, TRUE, DECL_PRESENCE (decl)->final_p);
2581 pattern_set_el_list
2582 = process_presence_absence_patterns
2583 (DECL_PRESENCE (decl)->patterns,
2584 DECL_PRESENCE (decl)->patterns_num,
2585 decl->pos, TRUE, DECL_PRESENCE (decl)->final_p);
2586 add_presence_absence (unit_set_el_list, pattern_set_el_list,
2587 decl->pos, TRUE,
2588 DECL_PRESENCE (decl)->final_p);
2592 /* Check absence set declarations and form absence sets. */
2593 for (i = 0; i < description->decls_num; i++)
2595 decl = description->decls [i];
2596 if (decl->mode == dm_absence)
2598 unit_set_el_t unit_set_el_list;
2599 pattern_set_el_t pattern_set_el_list;
2601 unit_set_el_list
2602 = process_presence_absence_names
2603 (DECL_ABSENCE (decl)->names, DECL_ABSENCE (decl)->names_num,
2604 decl->pos, FALSE, DECL_ABSENCE (decl)->final_p);
2605 pattern_set_el_list
2606 = process_presence_absence_patterns
2607 (DECL_ABSENCE (decl)->patterns,
2608 DECL_ABSENCE (decl)->patterns_num,
2609 decl->pos, FALSE, DECL_ABSENCE (decl)->final_p);
2610 add_presence_absence (unit_set_el_list, pattern_set_el_list,
2611 decl->pos, FALSE,
2612 DECL_ABSENCE (decl)->final_p);
2617 /* The following function checks that declared automaton is used. If
2618 the automaton is not used, the function fixes error/warning. The
2619 following function must be called only after `process_decls'. */
2620 static void
2621 check_automaton_usage (void)
2623 decl_t decl;
2624 int i;
2626 for (i = 0; i < description->decls_num; i++)
2628 decl = description->decls [i];
2629 if (decl->mode == dm_automaton
2630 && !DECL_AUTOMATON (decl)->automaton_is_used)
2632 if (!w_flag)
2633 error ("automaton `%s' is not used", DECL_AUTOMATON (decl)->name);
2634 else
2635 warning (0, "automaton `%s' is not used",
2636 DECL_AUTOMATON (decl)->name);
2641 /* The following recursive function processes all regexp in order to
2642 fix usage of units or reservations and to fix errors of undeclared
2643 name. The function may change unit_regexp onto reserv_regexp.
2644 Remember that reserv_regexp does not exist before the function
2645 call. */
2646 static regexp_t
2647 process_regexp (regexp_t regexp)
2649 decl_t decl_in_table;
2650 regexp_t new_regexp;
2651 int i;
2653 switch (regexp->mode)
2655 case rm_unit:
2656 decl_in_table = find_decl (REGEXP_UNIT (regexp)->name);
2657 if (decl_in_table == NULL)
2658 error ("undeclared unit or reservation `%s'",
2659 REGEXP_UNIT (regexp)->name);
2660 else
2661 switch (decl_in_table->mode)
2663 case dm_unit:
2664 DECL_UNIT (decl_in_table)->unit_is_used = 1;
2665 REGEXP_UNIT (regexp)->unit_decl = DECL_UNIT (decl_in_table);
2666 break;
2668 case dm_reserv:
2669 DECL_RESERV (decl_in_table)->reserv_is_used = 1;
2670 new_regexp = create_node (sizeof (struct regexp));
2671 new_regexp->mode = rm_reserv;
2672 new_regexp->pos = regexp->pos;
2673 REGEXP_RESERV (new_regexp)->name = REGEXP_UNIT (regexp)->name;
2674 REGEXP_RESERV (new_regexp)->reserv_decl
2675 = DECL_RESERV (decl_in_table);
2676 regexp = new_regexp;
2677 break;
2679 default:
2680 gcc_unreachable ();
2682 break;
2683 case rm_sequence:
2684 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
2685 REGEXP_SEQUENCE (regexp)->regexps [i]
2686 = process_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
2687 break;
2688 case rm_allof:
2689 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
2690 REGEXP_ALLOF (regexp)->regexps [i]
2691 = process_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
2692 break;
2693 case rm_oneof:
2694 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
2695 REGEXP_ONEOF (regexp)->regexps [i]
2696 = process_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
2697 break;
2698 case rm_repeat:
2699 REGEXP_REPEAT (regexp)->regexp
2700 = process_regexp (REGEXP_REPEAT (regexp)->regexp);
2701 break;
2702 case rm_nothing:
2703 break;
2704 default:
2705 gcc_unreachable ();
2707 return regexp;
2710 /* The following function processes regexp of define_reservation and
2711 define_insn_reservation with the aid of function
2712 `process_regexp'. */
2713 static void
2714 process_regexp_decls (void)
2716 decl_t decl;
2717 int i;
2719 for (i = 0; i < description->decls_num; i++)
2721 decl = description->decls [i];
2722 if (decl->mode == dm_reserv)
2723 DECL_RESERV (decl)->regexp
2724 = process_regexp (DECL_RESERV (decl)->regexp);
2725 else if (decl->mode == dm_insn_reserv)
2726 DECL_INSN_RESERV (decl)->regexp
2727 = process_regexp (DECL_INSN_RESERV (decl)->regexp);
2731 /* The following function checks that declared unit is used. If the
2732 unit is not used, the function fixes errors/warnings. The
2733 following function must be called only after `process_decls',
2734 `process_regexp_decls'. */
2735 static void
2736 check_usage (void)
2738 decl_t decl;
2739 int i;
2741 for (i = 0; i < description->decls_num; i++)
2743 decl = description->decls [i];
2744 if (decl->mode == dm_unit && !DECL_UNIT (decl)->unit_is_used)
2746 if (!w_flag)
2747 error ("unit `%s' is not used", DECL_UNIT (decl)->name);
2748 else
2749 warning (0, "unit `%s' is not used", DECL_UNIT (decl)->name);
2751 else if (decl->mode == dm_reserv && !DECL_RESERV (decl)->reserv_is_used)
2753 if (!w_flag)
2754 error ("reservation `%s' is not used", DECL_RESERV (decl)->name);
2755 else
2756 warning (0, "reservation `%s' is not used", DECL_RESERV (decl)->name);
2761 /* The following variable value is number of reservation being
2762 processed on loop recognition. */
2763 static int curr_loop_pass_num;
2765 /* The following recursive function returns nonzero value if REGEXP
2766 contains given decl or reservations in given regexp refers for
2767 given decl. */
2768 static int
2769 loop_in_regexp (regexp_t regexp, decl_t start_decl)
2771 int i;
2773 if (regexp == NULL)
2774 return 0;
2775 switch (regexp->mode)
2777 case rm_unit:
2778 return 0;
2780 case rm_reserv:
2781 if (start_decl->mode == dm_reserv
2782 && REGEXP_RESERV (regexp)->reserv_decl == DECL_RESERV (start_decl))
2783 return 1;
2784 else if (REGEXP_RESERV (regexp)->reserv_decl->loop_pass_num
2785 == curr_loop_pass_num)
2786 /* declaration has been processed. */
2787 return 0;
2788 else
2790 REGEXP_RESERV (regexp)->reserv_decl->loop_pass_num
2791 = curr_loop_pass_num;
2792 return loop_in_regexp (REGEXP_RESERV (regexp)->reserv_decl->regexp,
2793 start_decl);
2796 case rm_sequence:
2797 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
2798 if (loop_in_regexp (REGEXP_SEQUENCE (regexp)->regexps [i], start_decl))
2799 return 1;
2800 return 0;
2802 case rm_allof:
2803 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
2804 if (loop_in_regexp (REGEXP_ALLOF (regexp)->regexps [i], start_decl))
2805 return 1;
2806 return 0;
2808 case rm_oneof:
2809 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
2810 if (loop_in_regexp (REGEXP_ONEOF (regexp)->regexps [i], start_decl))
2811 return 1;
2812 return 0;
2814 case rm_repeat:
2815 return loop_in_regexp (REGEXP_REPEAT (regexp)->regexp, start_decl);
2817 case rm_nothing:
2818 return 0;
2820 default:
2821 gcc_unreachable ();
2825 /* The following function fixes errors "cycle in definition ...". The
2826 function uses function `loop_in_regexp' for that. */
2827 static void
2828 check_loops_in_regexps (void)
2830 decl_t decl;
2831 int i;
2833 for (i = 0; i < description->decls_num; i++)
2835 decl = description->decls [i];
2836 if (decl->mode == dm_reserv)
2837 DECL_RESERV (decl)->loop_pass_num = 0;
2839 for (i = 0; i < description->decls_num; i++)
2841 decl = description->decls [i];
2842 curr_loop_pass_num = i;
2844 if (decl->mode == dm_reserv)
2846 DECL_RESERV (decl)->loop_pass_num = curr_loop_pass_num;
2847 if (loop_in_regexp (DECL_RESERV (decl)->regexp, decl))
2849 gcc_assert (DECL_RESERV (decl)->regexp);
2850 error ("cycle in definition of reservation `%s'",
2851 DECL_RESERV (decl)->name);
2857 /* The function recursively processes IR of reservation and defines
2858 max and min cycle for reservation of unit. */
2859 static void
2860 process_regexp_cycles (regexp_t regexp, int max_start_cycle,
2861 int min_start_cycle, int *max_finish_cycle,
2862 int *min_finish_cycle)
2864 int i;
2866 switch (regexp->mode)
2868 case rm_unit:
2869 if (REGEXP_UNIT (regexp)->unit_decl->max_occ_cycle_num < max_start_cycle)
2870 REGEXP_UNIT (regexp)->unit_decl->max_occ_cycle_num = max_start_cycle;
2871 if (REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num > min_start_cycle
2872 || REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num == -1)
2873 REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num = min_start_cycle;
2874 *max_finish_cycle = max_start_cycle;
2875 *min_finish_cycle = min_start_cycle;
2876 break;
2878 case rm_reserv:
2879 process_regexp_cycles (REGEXP_RESERV (regexp)->reserv_decl->regexp,
2880 max_start_cycle, min_start_cycle,
2881 max_finish_cycle, min_finish_cycle);
2882 break;
2884 case rm_repeat:
2885 for (i = 0; i < REGEXP_REPEAT (regexp)->repeat_num; i++)
2887 process_regexp_cycles (REGEXP_REPEAT (regexp)->regexp,
2888 max_start_cycle, min_start_cycle,
2889 max_finish_cycle, min_finish_cycle);
2890 max_start_cycle = *max_finish_cycle + 1;
2891 min_start_cycle = *min_finish_cycle + 1;
2893 break;
2895 case rm_sequence:
2896 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
2898 process_regexp_cycles (REGEXP_SEQUENCE (regexp)->regexps [i],
2899 max_start_cycle, min_start_cycle,
2900 max_finish_cycle, min_finish_cycle);
2901 max_start_cycle = *max_finish_cycle + 1;
2902 min_start_cycle = *min_finish_cycle + 1;
2904 break;
2906 case rm_allof:
2908 int max_cycle = 0;
2909 int min_cycle = 0;
2911 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
2913 process_regexp_cycles (REGEXP_ALLOF (regexp)->regexps [i],
2914 max_start_cycle, min_start_cycle,
2915 max_finish_cycle, min_finish_cycle);
2916 if (max_cycle < *max_finish_cycle)
2917 max_cycle = *max_finish_cycle;
2918 if (i == 0 || min_cycle > *min_finish_cycle)
2919 min_cycle = *min_finish_cycle;
2921 *max_finish_cycle = max_cycle;
2922 *min_finish_cycle = min_cycle;
2924 break;
2926 case rm_oneof:
2928 int max_cycle = 0;
2929 int min_cycle = 0;
2931 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
2933 process_regexp_cycles (REGEXP_ONEOF (regexp)->regexps [i],
2934 max_start_cycle, min_start_cycle,
2935 max_finish_cycle, min_finish_cycle);
2936 if (max_cycle < *max_finish_cycle)
2937 max_cycle = *max_finish_cycle;
2938 if (i == 0 || min_cycle > *min_finish_cycle)
2939 min_cycle = *min_finish_cycle;
2941 *max_finish_cycle = max_cycle;
2942 *min_finish_cycle = min_cycle;
2944 break;
2946 case rm_nothing:
2947 *max_finish_cycle = max_start_cycle;
2948 *min_finish_cycle = min_start_cycle;
2949 break;
2951 default:
2952 gcc_unreachable ();
2956 /* The following function is called only for correct program. The
2957 function defines max reservation of insns in cycles. */
2958 static void
2959 evaluate_max_reserv_cycles (void)
2961 int max_insn_cycles_num;
2962 int min_insn_cycles_num;
2963 decl_t decl;
2964 int i;
2966 description->max_insn_reserv_cycles = 0;
2967 for (i = 0; i < description->decls_num; i++)
2969 decl = description->decls [i];
2970 if (decl->mode == dm_insn_reserv)
2972 process_regexp_cycles (DECL_INSN_RESERV (decl)->regexp, 0, 0,
2973 &max_insn_cycles_num, &min_insn_cycles_num);
2974 if (description->max_insn_reserv_cycles < max_insn_cycles_num)
2975 description->max_insn_reserv_cycles = max_insn_cycles_num;
2978 description->max_insn_reserv_cycles++;
2981 /* The following function calls functions for checking all
2982 description. */
2983 static void
2984 check_all_description (void)
2986 process_decls ();
2987 check_automaton_usage ();
2988 process_regexp_decls ();
2989 check_usage ();
2990 check_loops_in_regexps ();
2991 if (!have_error)
2992 evaluate_max_reserv_cycles ();
2997 /* The page contains abstract data `ticker'. This data is used to
2998 report time of different phases of building automata. It is
2999 possibly to write a description for which automata will be built
3000 during several minutes even on fast machine. */
3002 /* The following function creates ticker and makes it active. */
3003 static ticker_t
3004 create_ticker (void)
3006 ticker_t ticker;
3008 ticker.modified_creation_time = get_run_time ();
3009 ticker.incremented_off_time = 0;
3010 return ticker;
3013 /* The following function switches off given ticker. */
3014 static void
3015 ticker_off (ticker_t *ticker)
3017 if (ticker->incremented_off_time == 0)
3018 ticker->incremented_off_time = get_run_time () + 1;
3021 /* The following function switches on given ticker. */
3022 static void
3023 ticker_on (ticker_t *ticker)
3025 if (ticker->incremented_off_time != 0)
3027 ticker->modified_creation_time
3028 += get_run_time () - ticker->incremented_off_time + 1;
3029 ticker->incremented_off_time = 0;
3033 /* The following function returns current time in milliseconds since
3034 the moment when given ticker was created. */
3035 static int
3036 active_time (ticker_t ticker)
3038 if (ticker.incremented_off_time != 0)
3039 return ticker.incremented_off_time - 1 - ticker.modified_creation_time;
3040 else
3041 return get_run_time () - ticker.modified_creation_time;
3044 /* The following function returns string representation of active time
3045 of given ticker. The result is string representation of seconds
3046 with accuracy of 1/100 second. Only result of the last call of the
3047 function exists. Therefore the following code is not correct
3049 printf ("parser time: %s\ngeneration time: %s\n",
3050 active_time_string (parser_ticker),
3051 active_time_string (generation_ticker));
3053 Correct code has to be the following
3055 printf ("parser time: %s\n", active_time_string (parser_ticker));
3056 printf ("generation time: %s\n",
3057 active_time_string (generation_ticker));
3060 static void
3061 print_active_time (FILE *f, ticker_t ticker)
3063 int msecs;
3065 msecs = active_time (ticker);
3066 fprintf (f, "%d.%06d", msecs / 1000000, msecs % 1000000);
3071 /* The following variable value is number of automaton which are
3072 really being created. This value is defined on the base of
3073 argument of option `-split'. If the variable has zero value the
3074 number of automata is defined by the constructions `%automaton'.
3075 This case occurs when option `-split' is absent or has zero
3076 argument. If constructions `define_automaton' is absent only one
3077 automaton is created. */
3078 static int automata_num;
3080 /* The following variable values are times of
3081 o transformation of regular expressions
3082 o building NDFA (DFA if !ndfa_flag)
3083 o NDFA -> DFA (simply the same automaton if !ndfa_flag)
3084 o DFA minimization
3085 o building insn equivalence classes
3086 o all previous ones
3087 o code output */
3088 static ticker_t transform_time;
3089 static ticker_t NDFA_time;
3090 static ticker_t NDFA_to_DFA_time;
3091 static ticker_t minimize_time;
3092 static ticker_t equiv_time;
3093 static ticker_t automaton_generation_time;
3094 static ticker_t output_time;
3096 /* The following variable values are times of
3097 all checking
3098 all generation
3099 all pipeline hazard translator work */
3100 static ticker_t check_time;
3101 static ticker_t generation_time;
3102 static ticker_t all_time;
3106 /* Pseudo insn decl which denotes advancing cycle. */
3107 static decl_t advance_cycle_insn_decl;
3108 static void
3109 add_advance_cycle_insn_decl (void)
3111 advance_cycle_insn_decl = create_node (sizeof (struct decl));
3112 advance_cycle_insn_decl->mode = dm_insn_reserv;
3113 advance_cycle_insn_decl->pos = no_pos;
3114 DECL_INSN_RESERV (advance_cycle_insn_decl)->regexp = NULL;
3115 DECL_INSN_RESERV (advance_cycle_insn_decl)->name = "$advance_cycle";
3116 DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num
3117 = description->insns_num;
3118 description->decls [description->decls_num] = advance_cycle_insn_decl;
3119 description->decls_num++;
3120 description->insns_num++;
3124 /* Abstract data `alternative states' which represents
3125 nondeterministic nature of the description (see comments for
3126 structures alt_state and state). */
3128 /* List of free states. */
3129 static alt_state_t first_free_alt_state;
3131 #ifndef NDEBUG
3132 /* The following variables is maximal number of allocated nodes
3133 alt_state. */
3134 static int allocated_alt_states_num = 0;
3135 #endif
3137 /* The following function returns free node alt_state. It may be new
3138 allocated node or node freed earlier. */
3139 static alt_state_t
3140 get_free_alt_state (void)
3142 alt_state_t result;
3144 if (first_free_alt_state != NULL)
3146 result = first_free_alt_state;
3147 first_free_alt_state = first_free_alt_state->next_alt_state;
3149 else
3151 #ifndef NDEBUG
3152 allocated_alt_states_num++;
3153 #endif
3154 result = create_node (sizeof (struct alt_state));
3156 result->state = NULL;
3157 result->next_alt_state = NULL;
3158 result->next_sorted_alt_state = NULL;
3159 return result;
3162 /* The function frees node ALT_STATE. */
3163 static void
3164 free_alt_state (alt_state_t alt_state)
3166 if (alt_state == NULL)
3167 return;
3168 alt_state->next_alt_state = first_free_alt_state;
3169 first_free_alt_state = alt_state;
3172 /* The function frees list started with node ALT_STATE_LIST. */
3173 static void
3174 free_alt_states (alt_state_t alt_states_list)
3176 alt_state_t curr_alt_state;
3177 alt_state_t next_alt_state;
3179 for (curr_alt_state = alt_states_list;
3180 curr_alt_state != NULL;
3181 curr_alt_state = next_alt_state)
3183 next_alt_state = curr_alt_state->next_alt_state;
3184 free_alt_state (curr_alt_state);
3188 /* The function compares unique numbers of alt states. */
3189 static int
3190 alt_state_cmp (const void *alt_state_ptr_1, const void *alt_state_ptr_2)
3192 if ((*(alt_state_t *) alt_state_ptr_1)->state->unique_num
3193 == (*(alt_state_t *) alt_state_ptr_2)->state->unique_num)
3194 return 0;
3195 else if ((*(alt_state_t *) alt_state_ptr_1)->state->unique_num
3196 < (*(alt_state_t *) alt_state_ptr_2)->state->unique_num)
3197 return -1;
3198 else
3199 return 1;
3202 /* The function sorts ALT_STATES_LIST and removes duplicated alt
3203 states from the list. The comparison key is alt state unique
3204 number. */
3206 static alt_state_t
3207 uniq_sort_alt_states (alt_state_t alt_states_list)
3209 alt_state_t curr_alt_state;
3210 VEC(alt_state_t,heap) *alt_states;
3211 size_t i;
3212 size_t prev_unique_state_ind;
3213 alt_state_t result;
3215 if (alt_states_list == 0)
3216 return 0;
3217 if (alt_states_list->next_alt_state == 0)
3218 return alt_states_list;
3220 alt_states = VEC_alloc (alt_state_t,heap, 150);
3221 for (curr_alt_state = alt_states_list;
3222 curr_alt_state != NULL;
3223 curr_alt_state = curr_alt_state->next_alt_state)
3224 VEC_safe_push (alt_state_t,heap, alt_states, curr_alt_state);
3226 qsort (VEC_address (alt_state_t, alt_states),
3227 VEC_length (alt_state_t, alt_states),
3228 sizeof (alt_state_t), alt_state_cmp);
3230 prev_unique_state_ind = 0;
3231 for (i = 1; i < VEC_length (alt_state_t, alt_states); i++)
3232 if (VEC_index (alt_state_t, alt_states, prev_unique_state_ind)->state
3233 != VEC_index (alt_state_t, alt_states, i)->state)
3235 prev_unique_state_ind++;
3236 VEC_replace (alt_state_t, alt_states, prev_unique_state_ind,
3237 VEC_index (alt_state_t, alt_states, i));
3239 VEC_truncate (alt_state_t, alt_states, prev_unique_state_ind + 1);
3241 for (i = 1; i < VEC_length (alt_state_t, alt_states); i++)
3242 VEC_index (alt_state_t, alt_states, i-1)->next_sorted_alt_state
3243 = VEC_index (alt_state_t, alt_states, i);
3244 VEC_last (alt_state_t, alt_states)->next_sorted_alt_state = 0;
3246 result = VEC_index (alt_state_t, alt_states, 0);
3248 VEC_free (alt_state_t,heap, alt_states);
3249 return result;
3252 /* The function checks equality of alt state lists. Remember that the
3253 lists must be already sorted by the previous function. */
3254 static int
3255 alt_states_eq (alt_state_t alt_states_1, alt_state_t alt_states_2)
3257 while (alt_states_1 != NULL && alt_states_2 != NULL
3258 && alt_state_cmp (&alt_states_1, &alt_states_2) == 0)
3260 alt_states_1 = alt_states_1->next_sorted_alt_state;
3261 alt_states_2 = alt_states_2->next_sorted_alt_state;
3263 return alt_states_1 == alt_states_2;
3266 /* Initialization of the abstract data. */
3267 static void
3268 initiate_alt_states (void)
3270 first_free_alt_state = NULL;
3273 /* Finishing work with the abstract data. */
3274 static void
3275 finish_alt_states (void)
3281 /* The page contains macros for work with bits strings. We could use
3282 standard gcc bitmap or sbitmap but it would result in difficulties
3283 of building canadian cross. */
3285 /* Set bit number bitno in the bit string. The macro is not side
3286 effect proof. */
3287 #define SET_BIT(bitstring, bitno) \
3288 (((char *) (bitstring)) [(bitno) / CHAR_BIT] |= 1 << (bitno) % CHAR_BIT)
3290 #define CLEAR_BIT(bitstring, bitno) \
3291 (((char *) (bitstring)) [(bitno) / CHAR_BIT] &= ~(1 << (bitno) % CHAR_BIT))
3293 /* Test if bit number bitno in the bitstring is set. The macro is not
3294 side effect proof. */
3295 #define TEST_BIT(bitstring, bitno) \
3296 (((char *) (bitstring)) [(bitno) / CHAR_BIT] >> (bitno) % CHAR_BIT & 1)
3300 /* This page contains abstract data `state'. */
3302 /* Maximal length of reservations in cycles (>= 1). */
3303 static int max_cycles_num;
3305 /* Number of set elements (see type set_el_t) needed for
3306 representation of one cycle reservation. It is depended on units
3307 number. */
3308 static int els_in_cycle_reserv;
3310 /* Number of set elements (see type set_el_t) needed for
3311 representation of maximal length reservation. Deterministic
3312 reservation is stored as set (bit string) of length equal to the
3313 variable value * number of bits in set_el_t. */
3314 static int els_in_reservs;
3316 /* Array of pointers to unit declarations. */
3317 static unit_decl_t *units_array;
3319 /* Temporary reservation of maximal length. */
3320 static reserv_sets_t temp_reserv;
3322 /* The state table itself is represented by the following variable. */
3323 static htab_t state_table;
3325 /* Linked list of free 'state' structures to be recycled. The
3326 next_equiv_class_state pointer is borrowed for a free list. */
3327 static state_t first_free_state;
3329 static int curr_unique_state_num;
3331 #ifndef NDEBUG
3332 /* The following variables is maximal number of allocated nodes
3333 `state'. */
3334 static int allocated_states_num = 0;
3335 #endif
3337 /* Allocate new reservation set. */
3338 static reserv_sets_t
3339 alloc_empty_reserv_sets (void)
3341 reserv_sets_t result;
3343 obstack_blank (&irp, els_in_reservs * sizeof (set_el_t));
3344 result = (reserv_sets_t) obstack_base (&irp);
3345 obstack_finish (&irp);
3346 memset (result, 0, els_in_reservs * sizeof (set_el_t));
3347 return result;
3350 /* Hash value of reservation set. */
3351 static unsigned
3352 reserv_sets_hash_value (reserv_sets_t reservs)
3354 set_el_t hash_value;
3355 unsigned result;
3356 int reservs_num, i;
3357 set_el_t *reserv_ptr;
3359 hash_value = 0;
3360 reservs_num = els_in_reservs;
3361 reserv_ptr = reservs;
3362 i = 0;
3363 while (reservs_num != 0)
3365 reservs_num--;
3366 hash_value += ((*reserv_ptr >> i)
3367 | (*reserv_ptr << (sizeof (set_el_t) * CHAR_BIT - i)));
3368 i++;
3369 if (i == sizeof (set_el_t) * CHAR_BIT)
3370 i = 0;
3371 reserv_ptr++;
3373 if (sizeof (set_el_t) <= sizeof (unsigned))
3374 return hash_value;
3375 result = 0;
3376 for (i = sizeof (set_el_t); i > 0; i -= sizeof (unsigned) - 1)
3378 result += (unsigned) hash_value;
3379 hash_value >>= (sizeof (unsigned) - 1) * CHAR_BIT;
3381 return result;
3384 /* Comparison of given reservation sets. */
3385 static int
3386 reserv_sets_cmp (reserv_sets_t reservs_1, reserv_sets_t reservs_2)
3388 int reservs_num;
3389 set_el_t *reserv_ptr_1;
3390 set_el_t *reserv_ptr_2;
3392 gcc_assert (reservs_1 && reservs_2);
3393 reservs_num = els_in_reservs;
3394 reserv_ptr_1 = reservs_1;
3395 reserv_ptr_2 = reservs_2;
3396 while (reservs_num != 0 && *reserv_ptr_1 == *reserv_ptr_2)
3398 reservs_num--;
3399 reserv_ptr_1++;
3400 reserv_ptr_2++;
3402 if (reservs_num == 0)
3403 return 0;
3404 else if (*reserv_ptr_1 < *reserv_ptr_2)
3405 return -1;
3406 else
3407 return 1;
3410 /* The function checks equality of the reservation sets. */
3411 static int
3412 reserv_sets_eq (reserv_sets_t reservs_1, reserv_sets_t reservs_2)
3414 return reserv_sets_cmp (reservs_1, reservs_2) == 0;
3417 /* Set up in the reservation set that unit with UNIT_NUM is used on
3418 CYCLE_NUM. */
3419 static void
3420 set_unit_reserv (reserv_sets_t reservs, int cycle_num, int unit_num)
3422 gcc_assert (cycle_num < max_cycles_num);
3423 SET_BIT (reservs, cycle_num * els_in_cycle_reserv
3424 * sizeof (set_el_t) * CHAR_BIT + unit_num);
3427 /* Set up in the reservation set RESERVS that unit with UNIT_NUM is
3428 used on CYCLE_NUM. */
3429 static int
3430 test_unit_reserv (reserv_sets_t reservs, int cycle_num, int unit_num)
3432 gcc_assert (cycle_num < max_cycles_num);
3433 return TEST_BIT (reservs, cycle_num * els_in_cycle_reserv
3434 * sizeof (set_el_t) * CHAR_BIT + unit_num);
3437 /* The function checks that the reservation sets are intersected,
3438 i.e. there is a unit reservation on a cycle in both reservation
3439 sets. */
3440 static int
3441 reserv_sets_are_intersected (reserv_sets_t operand_1,
3442 reserv_sets_t operand_2)
3444 set_el_t *el_ptr_1;
3445 set_el_t *el_ptr_2;
3446 set_el_t *cycle_ptr_1;
3447 set_el_t *cycle_ptr_2;
3449 gcc_assert (operand_1 && operand_2);
3450 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2;
3451 el_ptr_1 < operand_1 + els_in_reservs;
3452 el_ptr_1++, el_ptr_2++)
3453 if (*el_ptr_1 & *el_ptr_2)
3454 return 1;
3455 reserv_sets_or (temp_reserv, operand_1, operand_2);
3456 for (cycle_ptr_1 = operand_1, cycle_ptr_2 = operand_2;
3457 cycle_ptr_1 < operand_1 + els_in_reservs;
3458 cycle_ptr_1 += els_in_cycle_reserv, cycle_ptr_2 += els_in_cycle_reserv)
3460 for (el_ptr_1 = cycle_ptr_1, el_ptr_2 = get_excl_set (cycle_ptr_2);
3461 el_ptr_1 < cycle_ptr_1 + els_in_cycle_reserv;
3462 el_ptr_1++, el_ptr_2++)
3463 if (*el_ptr_1 & *el_ptr_2)
3464 return 1;
3465 if (!check_presence_pattern_sets (cycle_ptr_1, cycle_ptr_2, FALSE))
3466 return 1;
3467 if (!check_presence_pattern_sets (temp_reserv + (cycle_ptr_2
3468 - operand_2),
3469 cycle_ptr_2, TRUE))
3470 return 1;
3471 if (!check_absence_pattern_sets (cycle_ptr_1, cycle_ptr_2, FALSE))
3472 return 1;
3473 if (!check_absence_pattern_sets (temp_reserv + (cycle_ptr_2 - operand_2),
3474 cycle_ptr_2, TRUE))
3475 return 1;
3477 return 0;
3480 /* The function sets up RESULT bits by bits of OPERAND shifted on one
3481 cpu cycle. The remaining bits of OPERAND (representing the last
3482 cycle unit reservations) are not changed. */
3483 static void
3484 reserv_sets_shift (reserv_sets_t result, reserv_sets_t operand)
3486 int i;
3488 gcc_assert (result && operand && result != operand);
3489 for (i = els_in_cycle_reserv; i < els_in_reservs; i++)
3490 result [i - els_in_cycle_reserv] = operand [i];
3493 /* OR of the reservation sets. */
3494 static void
3495 reserv_sets_or (reserv_sets_t result, reserv_sets_t operand_1,
3496 reserv_sets_t operand_2)
3498 set_el_t *el_ptr_1;
3499 set_el_t *el_ptr_2;
3500 set_el_t *result_set_el_ptr;
3502 gcc_assert (result && operand_1 && operand_2);
3503 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2, result_set_el_ptr = result;
3504 el_ptr_1 < operand_1 + els_in_reservs;
3505 el_ptr_1++, el_ptr_2++, result_set_el_ptr++)
3506 *result_set_el_ptr = *el_ptr_1 | *el_ptr_2;
3509 /* AND of the reservation sets. */
3510 static void
3511 reserv_sets_and (reserv_sets_t result, reserv_sets_t operand_1,
3512 reserv_sets_t operand_2)
3514 set_el_t *el_ptr_1;
3515 set_el_t *el_ptr_2;
3516 set_el_t *result_set_el_ptr;
3518 gcc_assert (result && operand_1 && operand_2);
3519 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2, result_set_el_ptr = result;
3520 el_ptr_1 < operand_1 + els_in_reservs;
3521 el_ptr_1++, el_ptr_2++, result_set_el_ptr++)
3522 *result_set_el_ptr = *el_ptr_1 & *el_ptr_2;
3525 /* The function outputs string representation of units reservation on
3526 cycle START_CYCLE in the reservation set. The function uses repeat
3527 construction if REPETITION_NUM > 1. */
3528 static void
3529 output_cycle_reservs (FILE *f, reserv_sets_t reservs, int start_cycle,
3530 int repetition_num)
3532 int unit_num;
3533 int reserved_units_num;
3535 reserved_units_num = 0;
3536 for (unit_num = 0; unit_num < description->units_num; unit_num++)
3537 if (TEST_BIT (reservs, start_cycle * els_in_cycle_reserv
3538 * sizeof (set_el_t) * CHAR_BIT + unit_num))
3539 reserved_units_num++;
3540 gcc_assert (repetition_num > 0);
3541 if (repetition_num != 1 && reserved_units_num > 1)
3542 fprintf (f, "(");
3543 reserved_units_num = 0;
3544 for (unit_num = 0;
3545 unit_num < description->units_num;
3546 unit_num++)
3547 if (TEST_BIT (reservs, start_cycle * els_in_cycle_reserv
3548 * sizeof (set_el_t) * CHAR_BIT + unit_num))
3550 if (reserved_units_num != 0)
3551 fprintf (f, "+");
3552 reserved_units_num++;
3553 fprintf (f, "%s", units_array [unit_num]->name);
3555 if (reserved_units_num == 0)
3556 fprintf (f, NOTHING_NAME);
3557 gcc_assert (repetition_num > 0);
3558 if (repetition_num != 1 && reserved_units_num > 1)
3559 fprintf (f, ")");
3560 if (repetition_num != 1)
3561 fprintf (f, "*%d", repetition_num);
3564 /* The function outputs string representation of units reservation in
3565 the reservation set. */
3566 static void
3567 output_reserv_sets (FILE *f, reserv_sets_t reservs)
3569 int start_cycle = 0;
3570 int cycle;
3571 int repetition_num;
3573 repetition_num = 0;
3574 for (cycle = 0; cycle < max_cycles_num; cycle++)
3575 if (repetition_num == 0)
3577 repetition_num++;
3578 start_cycle = cycle;
3580 else if (memcmp
3581 ((char *) reservs + start_cycle * els_in_cycle_reserv
3582 * sizeof (set_el_t),
3583 (char *) reservs + cycle * els_in_cycle_reserv
3584 * sizeof (set_el_t),
3585 els_in_cycle_reserv * sizeof (set_el_t)) == 0)
3586 repetition_num++;
3587 else
3589 if (start_cycle != 0)
3590 fprintf (f, ", ");
3591 output_cycle_reservs (f, reservs, start_cycle, repetition_num);
3592 repetition_num = 1;
3593 start_cycle = cycle;
3595 if (start_cycle < max_cycles_num)
3597 if (start_cycle != 0)
3598 fprintf (f, ", ");
3599 output_cycle_reservs (f, reservs, start_cycle, repetition_num);
3603 /* The following function returns free node state for AUTOMATON. It
3604 may be new allocated node or node freed earlier. The function also
3605 allocates reservation set if WITH_RESERVS has nonzero value. */
3606 static state_t
3607 get_free_state (int with_reservs, automaton_t automaton)
3609 state_t result;
3611 gcc_assert (max_cycles_num > 0 && automaton);
3612 if (first_free_state)
3614 result = first_free_state;
3615 first_free_state = result->next_equiv_class_state;
3617 result->next_equiv_class_state = NULL;
3618 result->automaton = automaton;
3619 result->first_out_arc = NULL;
3620 result->it_was_placed_in_stack_for_NDFA_forming = 0;
3621 result->it_was_placed_in_stack_for_DFA_forming = 0;
3622 result->component_states = NULL;
3623 result->longest_path_length = UNDEFINED_LONGEST_PATH_LENGTH;
3625 else
3627 #ifndef NDEBUG
3628 allocated_states_num++;
3629 #endif
3630 result = create_node (sizeof (struct state));
3631 result->automaton = automaton;
3632 result->first_out_arc = NULL;
3633 result->unique_num = curr_unique_state_num;
3634 result->longest_path_length = UNDEFINED_LONGEST_PATH_LENGTH;
3635 curr_unique_state_num++;
3637 if (with_reservs)
3639 if (result->reservs == NULL)
3640 result->reservs = alloc_empty_reserv_sets ();
3641 else
3642 memset (result->reservs, 0, els_in_reservs * sizeof (set_el_t));
3644 return result;
3647 /* The function frees node STATE. */
3648 static void
3649 free_state (state_t state)
3651 free_alt_states (state->component_states);
3652 state->next_equiv_class_state = first_free_state;
3653 first_free_state = state;
3656 /* Hash value of STATE. If STATE represents deterministic state it is
3657 simply hash value of the corresponding reservation set. Otherwise
3658 it is formed from hash values of the component deterministic
3659 states. One more key is order number of state automaton. */
3660 static hashval_t
3661 state_hash (const void *state)
3663 unsigned int hash_value;
3664 alt_state_t alt_state;
3666 if (((state_t) state)->component_states == NULL)
3667 hash_value = reserv_sets_hash_value (((state_t) state)->reservs);
3668 else
3670 hash_value = 0;
3671 for (alt_state = ((state_t) state)->component_states;
3672 alt_state != NULL;
3673 alt_state = alt_state->next_sorted_alt_state)
3674 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
3675 | (hash_value << CHAR_BIT))
3676 + alt_state->state->unique_num);
3678 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
3679 | (hash_value << CHAR_BIT))
3680 + ((state_t) state)->automaton->automaton_order_num);
3681 return hash_value;
3684 /* Return nonzero value if the states are the same. */
3685 static int
3686 state_eq_p (const void *state_1, const void *state_2)
3688 alt_state_t alt_state_1;
3689 alt_state_t alt_state_2;
3691 if (((state_t) state_1)->automaton != ((state_t) state_2)->automaton)
3692 return 0;
3693 else if (((state_t) state_1)->component_states == NULL
3694 && ((state_t) state_2)->component_states == NULL)
3695 return reserv_sets_eq (((state_t) state_1)->reservs,
3696 ((state_t) state_2)->reservs);
3697 else if (((state_t) state_1)->component_states != NULL
3698 && ((state_t) state_2)->component_states != NULL)
3700 for (alt_state_1 = ((state_t) state_1)->component_states,
3701 alt_state_2 = ((state_t) state_2)->component_states;
3702 alt_state_1 != NULL && alt_state_2 != NULL;
3703 alt_state_1 = alt_state_1->next_sorted_alt_state,
3704 alt_state_2 = alt_state_2->next_sorted_alt_state)
3705 /* All state in the list must be already in the hash table.
3706 Also the lists must be sorted. */
3707 if (alt_state_1->state != alt_state_2->state)
3708 return 0;
3709 return alt_state_1 == alt_state_2;
3711 else
3712 return 0;
3715 /* Insert STATE into the state table. */
3716 static state_t
3717 insert_state (state_t state)
3719 void **entry_ptr;
3721 entry_ptr = htab_find_slot (state_table, (void *) state, 1);
3722 if (*entry_ptr == NULL)
3723 *entry_ptr = (void *) state;
3724 return (state_t) *entry_ptr;
3727 /* Add reservation of unit with UNIT_NUM on cycle CYCLE_NUM to
3728 deterministic STATE. */
3729 static void
3730 set_state_reserv (state_t state, int cycle_num, int unit_num)
3732 set_unit_reserv (state->reservs, cycle_num, unit_num);
3735 /* Return nonzero value if the deterministic states contains a
3736 reservation of the same cpu unit on the same cpu cycle. */
3737 static int
3738 intersected_state_reservs_p (state_t state1, state_t state2)
3740 gcc_assert (state1->automaton == state2->automaton);
3741 return reserv_sets_are_intersected (state1->reservs, state2->reservs);
3744 /* Return deterministic state (inserted into the table) which
3745 representing the automaton state which is union of reservations of
3746 the deterministic states masked by RESERVS. */
3747 static state_t
3748 states_union (state_t state1, state_t state2, reserv_sets_t reservs)
3750 state_t result;
3751 state_t state_in_table;
3753 gcc_assert (state1->automaton == state2->automaton);
3754 result = get_free_state (1, state1->automaton);
3755 reserv_sets_or (result->reservs, state1->reservs, state2->reservs);
3756 reserv_sets_and (result->reservs, result->reservs, reservs);
3757 state_in_table = insert_state (result);
3758 if (result != state_in_table)
3760 free_state (result);
3761 result = state_in_table;
3763 return result;
3766 /* Return deterministic state (inserted into the table) which
3767 represent the automaton state is obtained from deterministic STATE
3768 by advancing cpu cycle and masking by RESERVS. */
3769 static state_t
3770 state_shift (state_t state, reserv_sets_t reservs)
3772 state_t result;
3773 state_t state_in_table;
3775 result = get_free_state (1, state->automaton);
3776 reserv_sets_shift (result->reservs, state->reservs);
3777 reserv_sets_and (result->reservs, result->reservs, reservs);
3778 state_in_table = insert_state (result);
3779 if (result != state_in_table)
3781 free_state (result);
3782 result = state_in_table;
3784 return result;
3787 /* Initialization of the abstract data. */
3788 static void
3789 initiate_states (void)
3791 decl_t decl;
3792 int i;
3794 if (description->units_num)
3795 units_array = XNEWVEC (unit_decl_t, description->units_num);
3796 else
3797 units_array = 0;
3799 for (i = 0; i < description->decls_num; i++)
3801 decl = description->decls [i];
3802 if (decl->mode == dm_unit)
3803 units_array [DECL_UNIT (decl)->unit_num] = DECL_UNIT (decl);
3805 max_cycles_num = description->max_insn_reserv_cycles;
3806 els_in_cycle_reserv
3807 = ((description->units_num + sizeof (set_el_t) * CHAR_BIT - 1)
3808 / (sizeof (set_el_t) * CHAR_BIT));
3809 els_in_reservs = els_in_cycle_reserv * max_cycles_num;
3810 curr_unique_state_num = 0;
3811 initiate_alt_states ();
3812 state_table = htab_create (1500, state_hash, state_eq_p, (htab_del) 0);
3813 temp_reserv = alloc_empty_reserv_sets ();
3816 /* Finishing work with the abstract data. */
3817 static void
3818 finish_states (void)
3820 free (units_array);
3821 units_array = 0;
3822 htab_delete (state_table);
3823 first_free_state = NULL;
3824 finish_alt_states ();
3829 /* Abstract data `arcs'. */
3831 /* List of free arcs. */
3832 static arc_t first_free_arc;
3834 #ifndef NDEBUG
3835 /* The following variables is maximal number of allocated nodes
3836 `arc'. */
3837 static int allocated_arcs_num = 0;
3838 #endif
3840 /* The function frees node ARC. */
3841 static void
3842 free_arc (arc_t arc)
3844 arc->next_out_arc = first_free_arc;
3845 first_free_arc = arc;
3848 /* The function removes and frees ARC staring from FROM_STATE. */
3849 static void
3850 remove_arc (state_t from_state, arc_t arc)
3852 arc_t prev_arc;
3853 arc_t curr_arc;
3855 gcc_assert (arc);
3856 for (prev_arc = NULL, curr_arc = from_state->first_out_arc;
3857 curr_arc != NULL;
3858 prev_arc = curr_arc, curr_arc = curr_arc->next_out_arc)
3859 if (curr_arc == arc)
3860 break;
3861 gcc_assert (curr_arc);
3862 if (prev_arc == NULL)
3863 from_state->first_out_arc = arc->next_out_arc;
3864 else
3865 prev_arc->next_out_arc = arc->next_out_arc;
3866 from_state->num_out_arcs--;
3867 free_arc (arc);
3870 /* The functions returns arc with given characteristics (or NULL if
3871 the arc does not exist). */
3872 static arc_t
3873 find_arc (state_t from_state, state_t to_state, ainsn_t insn)
3875 arc_t arc;
3877 for (arc = first_out_arc (from_state); arc != NULL; arc = next_out_arc (arc))
3878 if (arc->to_state == to_state && arc->insn == insn)
3879 return arc;
3880 return NULL;
3883 /* The function adds arc from FROM_STATE to TO_STATE marked by AINSN.
3884 The function returns added arc (or already existing arc). */
3885 static arc_t
3886 add_arc (state_t from_state, state_t to_state, ainsn_t ainsn)
3888 arc_t new_arc;
3890 new_arc = find_arc (from_state, to_state, ainsn);
3891 if (new_arc != NULL)
3892 return new_arc;
3893 if (first_free_arc == NULL)
3895 #ifndef NDEBUG
3896 allocated_arcs_num++;
3897 #endif
3898 new_arc = create_node (sizeof (struct arc));
3899 new_arc->to_state = NULL;
3900 new_arc->insn = NULL;
3901 new_arc->next_out_arc = NULL;
3903 else
3905 new_arc = first_free_arc;
3906 first_free_arc = first_free_arc->next_out_arc;
3908 new_arc->to_state = to_state;
3909 new_arc->insn = ainsn;
3910 ainsn->arc_exists_p = 1;
3911 new_arc->next_out_arc = from_state->first_out_arc;
3912 from_state->first_out_arc = new_arc;
3913 from_state->num_out_arcs++;
3914 new_arc->next_arc_marked_by_insn = NULL;
3915 return new_arc;
3918 /* The function returns the first arc starting from STATE. */
3919 static arc_t
3920 first_out_arc (state_t state)
3922 return state->first_out_arc;
3925 /* The function returns next out arc after ARC. */
3926 static arc_t
3927 next_out_arc (arc_t arc)
3929 return arc->next_out_arc;
3932 /* Initialization of the abstract data. */
3933 static void
3934 initiate_arcs (void)
3936 first_free_arc = NULL;
3939 /* Finishing work with the abstract data. */
3940 static void
3941 finish_arcs (void)
3947 /* Abstract data `automata lists'. */
3949 /* List of free states. */
3950 static automata_list_el_t first_free_automata_list_el;
3952 /* The list being formed. */
3953 static automata_list_el_t current_automata_list;
3955 /* Hash table of automata lists. */
3956 static htab_t automata_list_table;
3958 /* The following function returns free automata list el. It may be
3959 new allocated node or node freed earlier. */
3960 static automata_list_el_t
3961 get_free_automata_list_el (void)
3963 automata_list_el_t result;
3965 if (first_free_automata_list_el != NULL)
3967 result = first_free_automata_list_el;
3968 first_free_automata_list_el
3969 = first_free_automata_list_el->next_automata_list_el;
3971 else
3972 result = create_node (sizeof (struct automata_list_el));
3973 result->automaton = NULL;
3974 result->next_automata_list_el = NULL;
3975 return result;
3978 /* The function frees node AUTOMATA_LIST_EL. */
3979 static void
3980 free_automata_list_el (automata_list_el_t automata_list_el)
3982 if (automata_list_el == NULL)
3983 return;
3984 automata_list_el->next_automata_list_el = first_free_automata_list_el;
3985 first_free_automata_list_el = automata_list_el;
3988 /* The function frees list AUTOMATA_LIST. */
3989 static void
3990 free_automata_list (automata_list_el_t automata_list)
3992 automata_list_el_t curr_automata_list_el;
3993 automata_list_el_t next_automata_list_el;
3995 for (curr_automata_list_el = automata_list;
3996 curr_automata_list_el != NULL;
3997 curr_automata_list_el = next_automata_list_el)
3999 next_automata_list_el = curr_automata_list_el->next_automata_list_el;
4000 free_automata_list_el (curr_automata_list_el);
4004 /* Hash value of AUTOMATA_LIST. */
4005 static hashval_t
4006 automata_list_hash (const void *automata_list)
4008 unsigned int hash_value;
4009 automata_list_el_t curr_automata_list_el;
4011 hash_value = 0;
4012 for (curr_automata_list_el = (automata_list_el_t) automata_list;
4013 curr_automata_list_el != NULL;
4014 curr_automata_list_el = curr_automata_list_el->next_automata_list_el)
4015 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
4016 | (hash_value << CHAR_BIT))
4017 + curr_automata_list_el->automaton->automaton_order_num);
4018 return hash_value;
4021 /* Return nonzero value if the automata_lists are the same. */
4022 static int
4023 automata_list_eq_p (const void *automata_list_1, const void *automata_list_2)
4025 automata_list_el_t automata_list_el_1;
4026 automata_list_el_t automata_list_el_2;
4028 for (automata_list_el_1 = (automata_list_el_t) automata_list_1,
4029 automata_list_el_2 = (automata_list_el_t) automata_list_2;
4030 automata_list_el_1 != NULL && automata_list_el_2 != NULL;
4031 automata_list_el_1 = automata_list_el_1->next_automata_list_el,
4032 automata_list_el_2 = automata_list_el_2->next_automata_list_el)
4033 if (automata_list_el_1->automaton != automata_list_el_2->automaton)
4034 return 0;
4035 return automata_list_el_1 == automata_list_el_2;
4038 /* Initialization of the abstract data. */
4039 static void
4040 initiate_automata_lists (void)
4042 first_free_automata_list_el = NULL;
4043 automata_list_table = htab_create (1500, automata_list_hash,
4044 automata_list_eq_p, (htab_del) 0);
4047 /* The following function starts new automata list and makes it the
4048 current one. */
4049 static void
4050 automata_list_start (void)
4052 current_automata_list = NULL;
4055 /* The following function adds AUTOMATON to the current list. */
4056 static void
4057 automata_list_add (automaton_t automaton)
4059 automata_list_el_t el;
4061 el = get_free_automata_list_el ();
4062 el->automaton = automaton;
4063 el->next_automata_list_el = current_automata_list;
4064 current_automata_list = el;
4067 /* The following function finishes forming the current list, inserts
4068 it into the table and returns it. */
4069 static automata_list_el_t
4070 automata_list_finish (void)
4072 void **entry_ptr;
4074 if (current_automata_list == NULL)
4075 return NULL;
4076 entry_ptr = htab_find_slot (automata_list_table,
4077 (void *) current_automata_list, 1);
4078 if (*entry_ptr == NULL)
4079 *entry_ptr = (void *) current_automata_list;
4080 else
4081 free_automata_list (current_automata_list);
4082 current_automata_list = NULL;
4083 return (automata_list_el_t) *entry_ptr;
4086 /* Finishing work with the abstract data. */
4087 static void
4088 finish_automata_lists (void)
4090 htab_delete (automata_list_table);
4095 /* The page contains abstract data for work with exclusion sets (see
4096 exclusion_set in file rtl.def). */
4098 /* The following variable refers to an exclusion set returned by
4099 get_excl_set. This is bit string of length equal to cpu units
4100 number. If exclusion set for given unit contains 1 for a unit,
4101 then simultaneous reservation of the units is prohibited. */
4102 static reserv_sets_t excl_set;
4104 /* The array contains exclusion sets for each unit. */
4105 static reserv_sets_t *unit_excl_set_table;
4107 /* The following function forms the array containing exclusion sets
4108 for each unit. */
4109 static void
4110 initiate_excl_sets (void)
4112 decl_t decl;
4113 reserv_sets_t unit_excl_set;
4114 unit_set_el_t el;
4115 int i;
4117 obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4118 excl_set = (reserv_sets_t) obstack_base (&irp);
4119 obstack_finish (&irp);
4120 obstack_blank (&irp, description->units_num * sizeof (reserv_sets_t));
4121 unit_excl_set_table = (reserv_sets_t *) obstack_base (&irp);
4122 obstack_finish (&irp);
4123 /* Evaluate unit exclusion sets. */
4124 for (i = 0; i < description->decls_num; i++)
4126 decl = description->decls [i];
4127 if (decl->mode == dm_unit)
4129 obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4130 unit_excl_set = (reserv_sets_t) obstack_base (&irp);
4131 obstack_finish (&irp);
4132 memset (unit_excl_set, 0, els_in_cycle_reserv * sizeof (set_el_t));
4133 for (el = DECL_UNIT (decl)->excl_list;
4134 el != NULL;
4135 el = el->next_unit_set_el)
4137 SET_BIT (unit_excl_set, el->unit_decl->unit_num);
4138 el->unit_decl->in_set_p = TRUE;
4140 unit_excl_set_table [DECL_UNIT (decl)->unit_num] = unit_excl_set;
4145 /* The function sets up and return EXCL_SET which is union of
4146 exclusion sets for each unit in IN_SET. */
4147 static reserv_sets_t
4148 get_excl_set (reserv_sets_t in_set)
4150 int excl_char_num;
4151 int chars_num;
4152 int i;
4153 int start_unit_num;
4154 int unit_num;
4156 chars_num = els_in_cycle_reserv * sizeof (set_el_t);
4157 memset (excl_set, 0, chars_num);
4158 for (excl_char_num = 0; excl_char_num < chars_num; excl_char_num++)
4159 if (((unsigned char *) in_set) [excl_char_num])
4160 for (i = CHAR_BIT - 1; i >= 0; i--)
4161 if ((((unsigned char *) in_set) [excl_char_num] >> i) & 1)
4163 start_unit_num = excl_char_num * CHAR_BIT + i;
4164 if (start_unit_num >= description->units_num)
4165 return excl_set;
4166 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4168 excl_set [unit_num]
4169 |= unit_excl_set_table [start_unit_num] [unit_num];
4172 return excl_set;
4177 /* The page contains abstract data for work with presence/absence
4178 pattern sets (see presence_set/absence_set in file rtl.def). */
4180 /* The following arrays contain correspondingly presence, final
4181 presence, absence, and final absence patterns for each unit. */
4182 static pattern_reserv_t *unit_presence_set_table;
4183 static pattern_reserv_t *unit_final_presence_set_table;
4184 static pattern_reserv_t *unit_absence_set_table;
4185 static pattern_reserv_t *unit_final_absence_set_table;
4187 /* The following function forms list of reservation sets for given
4188 PATTERN_LIST. */
4189 static pattern_reserv_t
4190 form_reserv_sets_list (pattern_set_el_t pattern_list)
4192 pattern_set_el_t el;
4193 pattern_reserv_t first, curr, prev;
4194 int i;
4196 prev = first = NULL;
4197 for (el = pattern_list; el != NULL; el = el->next_pattern_set_el)
4199 curr = create_node (sizeof (struct pattern_reserv));
4200 curr->reserv = alloc_empty_reserv_sets ();
4201 curr->next_pattern_reserv = NULL;
4202 for (i = 0; i < el->units_num; i++)
4204 SET_BIT (curr->reserv, el->unit_decls [i]->unit_num);
4205 el->unit_decls [i]->in_set_p = TRUE;
4207 if (prev != NULL)
4208 prev->next_pattern_reserv = curr;
4209 else
4210 first = curr;
4211 prev = curr;
4213 return first;
4216 /* The following function forms the array containing presence and
4217 absence pattern sets for each unit. */
4218 static void
4219 initiate_presence_absence_pattern_sets (void)
4221 decl_t decl;
4222 int i;
4224 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4225 unit_presence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4226 obstack_finish (&irp);
4227 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4228 unit_final_presence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4229 obstack_finish (&irp);
4230 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4231 unit_absence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4232 obstack_finish (&irp);
4233 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4234 unit_final_absence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4235 obstack_finish (&irp);
4236 /* Evaluate unit presence/absence sets. */
4237 for (i = 0; i < description->decls_num; i++)
4239 decl = description->decls [i];
4240 if (decl->mode == dm_unit)
4242 unit_presence_set_table [DECL_UNIT (decl)->unit_num]
4243 = form_reserv_sets_list (DECL_UNIT (decl)->presence_list);
4244 unit_final_presence_set_table [DECL_UNIT (decl)->unit_num]
4245 = form_reserv_sets_list (DECL_UNIT (decl)->final_presence_list);
4246 unit_absence_set_table [DECL_UNIT (decl)->unit_num]
4247 = form_reserv_sets_list (DECL_UNIT (decl)->absence_list);
4248 unit_final_absence_set_table [DECL_UNIT (decl)->unit_num]
4249 = form_reserv_sets_list (DECL_UNIT (decl)->final_absence_list);
4254 /* The function checks that CHECKED_SET satisfies all presence pattern
4255 sets for units in ORIGIONAL_SET. The function returns TRUE if it
4256 is ok. */
4257 static int
4258 check_presence_pattern_sets (reserv_sets_t checked_set,
4259 reserv_sets_t origional_set,
4260 int final_p)
4262 int char_num;
4263 int chars_num;
4264 int i;
4265 int start_unit_num;
4266 int unit_num;
4267 int presence_p;
4268 pattern_reserv_t pat_reserv;
4270 chars_num = els_in_cycle_reserv * sizeof (set_el_t);
4271 for (char_num = 0; char_num < chars_num; char_num++)
4272 if (((unsigned char *) origional_set) [char_num])
4273 for (i = CHAR_BIT - 1; i >= 0; i--)
4274 if ((((unsigned char *) origional_set) [char_num] >> i) & 1)
4276 start_unit_num = char_num * CHAR_BIT + i;
4277 if (start_unit_num >= description->units_num)
4278 break;
4279 if ((final_p
4280 && unit_final_presence_set_table [start_unit_num] == NULL)
4281 || (!final_p
4282 && unit_presence_set_table [start_unit_num] == NULL))
4283 continue;
4284 presence_p = FALSE;
4285 for (pat_reserv = (final_p
4286 ? unit_final_presence_set_table [start_unit_num]
4287 : unit_presence_set_table [start_unit_num]);
4288 pat_reserv != NULL;
4289 pat_reserv = pat_reserv->next_pattern_reserv)
4291 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4292 if ((checked_set [unit_num] & pat_reserv->reserv [unit_num])
4293 != pat_reserv->reserv [unit_num])
4294 break;
4295 presence_p = presence_p || unit_num >= els_in_cycle_reserv;
4297 if (!presence_p)
4298 return FALSE;
4300 return TRUE;
4303 /* The function checks that CHECKED_SET satisfies all absence pattern
4304 sets for units in ORIGIONAL_SET. The function returns TRUE if it
4305 is ok. */
4306 static int
4307 check_absence_pattern_sets (reserv_sets_t checked_set,
4308 reserv_sets_t origional_set,
4309 int final_p)
4311 int char_num;
4312 int chars_num;
4313 int i;
4314 int start_unit_num;
4315 int unit_num;
4316 pattern_reserv_t pat_reserv;
4318 chars_num = els_in_cycle_reserv * sizeof (set_el_t);
4319 for (char_num = 0; char_num < chars_num; char_num++)
4320 if (((unsigned char *) origional_set) [char_num])
4321 for (i = CHAR_BIT - 1; i >= 0; i--)
4322 if ((((unsigned char *) origional_set) [char_num] >> i) & 1)
4324 start_unit_num = char_num * CHAR_BIT + i;
4325 if (start_unit_num >= description->units_num)
4326 break;
4327 for (pat_reserv = (final_p
4328 ? unit_final_absence_set_table [start_unit_num]
4329 : unit_absence_set_table [start_unit_num]);
4330 pat_reserv != NULL;
4331 pat_reserv = pat_reserv->next_pattern_reserv)
4333 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4334 if ((checked_set [unit_num] & pat_reserv->reserv [unit_num])
4335 != pat_reserv->reserv [unit_num]
4336 && pat_reserv->reserv [unit_num])
4337 break;
4338 if (unit_num >= els_in_cycle_reserv)
4339 return FALSE;
4342 return TRUE;
4347 /* This page contains code for transformation of original reservations
4348 described in .md file. The main goal of transformations is
4349 simplifying reservation and lifting up all `|' on the top of IR
4350 reservation representation. */
4353 /* The following function makes copy of IR representation of
4354 reservation. The function also substitutes all reservations
4355 defined by define_reservation by corresponding value during making
4356 the copy. */
4357 static regexp_t
4358 copy_insn_regexp (regexp_t regexp)
4360 regexp_t result;
4361 int i;
4363 switch (regexp->mode)
4365 case rm_reserv:
4366 result = copy_insn_regexp (REGEXP_RESERV (regexp)->reserv_decl->regexp);
4367 break;
4369 case rm_unit:
4370 result = copy_node (regexp, sizeof (struct regexp));
4371 break;
4373 case rm_repeat:
4374 result = copy_node (regexp, sizeof (struct regexp));
4375 REGEXP_REPEAT (result)->regexp
4376 = copy_insn_regexp (REGEXP_REPEAT (regexp)->regexp);
4377 break;
4379 case rm_sequence:
4380 result = copy_node (regexp,
4381 sizeof (struct regexp) + sizeof (regexp_t)
4382 * (REGEXP_SEQUENCE (regexp)->regexps_num - 1));
4383 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4384 REGEXP_SEQUENCE (result)->regexps [i]
4385 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4386 break;
4388 case rm_allof:
4389 result = copy_node (regexp,
4390 sizeof (struct regexp) + sizeof (regexp_t)
4391 * (REGEXP_ALLOF (regexp)->regexps_num - 1));
4392 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4393 REGEXP_ALLOF (result)->regexps [i]
4394 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4395 break;
4397 case rm_oneof:
4398 result = copy_node (regexp,
4399 sizeof (struct regexp) + sizeof (regexp_t)
4400 * (REGEXP_ONEOF (regexp)->regexps_num - 1));
4401 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4402 REGEXP_ONEOF (result)->regexps [i]
4403 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4404 break;
4406 case rm_nothing:
4407 result = copy_node (regexp, sizeof (struct regexp));
4408 break;
4410 default:
4411 gcc_unreachable ();
4413 return result;
4416 /* The following variable is set up 1 if a transformation has been
4417 applied. */
4418 static int regexp_transformed_p;
4420 /* The function makes transformation
4421 A*N -> A, A, ... */
4422 static regexp_t
4423 transform_1 (regexp_t regexp)
4425 int i;
4426 int repeat_num;
4427 regexp_t operand;
4428 pos_t pos;
4430 if (regexp->mode == rm_repeat)
4432 repeat_num = REGEXP_REPEAT (regexp)->repeat_num;
4433 gcc_assert (repeat_num > 1);
4434 operand = REGEXP_REPEAT (regexp)->regexp;
4435 pos = regexp->mode;
4436 regexp = create_node (sizeof (struct regexp) + sizeof (regexp_t)
4437 * (repeat_num - 1));
4438 regexp->mode = rm_sequence;
4439 regexp->pos = pos;
4440 REGEXP_SEQUENCE (regexp)->regexps_num = repeat_num;
4441 for (i = 0; i < repeat_num; i++)
4442 REGEXP_SEQUENCE (regexp)->regexps [i] = copy_insn_regexp (operand);
4443 regexp_transformed_p = 1;
4445 return regexp;
4448 /* The function makes transformations
4449 ...,(A,B,...),C,... -> ...,A,B,...,C,...
4450 ...+(A+B+...)+C+... -> ...+A+B+...+C+...
4451 ...|(A|B|...)|C|... -> ...|A|B|...|C|... */
4452 static regexp_t
4453 transform_2 (regexp_t regexp)
4455 if (regexp->mode == rm_sequence)
4457 regexp_t sequence = NULL;
4458 regexp_t result;
4459 int sequence_index = 0;
4460 int i, j;
4462 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4463 if (REGEXP_SEQUENCE (regexp)->regexps [i]->mode == rm_sequence)
4465 sequence_index = i;
4466 sequence = REGEXP_SEQUENCE (regexp)->regexps [i];
4467 break;
4469 if (i < REGEXP_SEQUENCE (regexp)->regexps_num)
4471 gcc_assert (REGEXP_SEQUENCE (sequence)->regexps_num > 1
4472 && REGEXP_SEQUENCE (regexp)->regexps_num > 1);
4473 result = create_node (sizeof (struct regexp)
4474 + sizeof (regexp_t)
4475 * (REGEXP_SEQUENCE (regexp)->regexps_num
4476 + REGEXP_SEQUENCE (sequence)->regexps_num
4477 - 2));
4478 result->mode = rm_sequence;
4479 result->pos = regexp->pos;
4480 REGEXP_SEQUENCE (result)->regexps_num
4481 = (REGEXP_SEQUENCE (regexp)->regexps_num
4482 + REGEXP_SEQUENCE (sequence)->regexps_num - 1);
4483 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4484 if (i < sequence_index)
4485 REGEXP_SEQUENCE (result)->regexps [i]
4486 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4487 else if (i > sequence_index)
4488 REGEXP_SEQUENCE (result)->regexps
4489 [i + REGEXP_SEQUENCE (sequence)->regexps_num - 1]
4490 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4491 else
4492 for (j = 0; j < REGEXP_SEQUENCE (sequence)->regexps_num; j++)
4493 REGEXP_SEQUENCE (result)->regexps [i + j]
4494 = copy_insn_regexp (REGEXP_SEQUENCE (sequence)->regexps [j]);
4495 regexp_transformed_p = 1;
4496 regexp = result;
4499 else if (regexp->mode == rm_allof)
4501 regexp_t allof = NULL;
4502 regexp_t result;
4503 int allof_index = 0;
4504 int i, j;
4506 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4507 if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_allof)
4509 allof_index = i;
4510 allof = REGEXP_ALLOF (regexp)->regexps [i];
4511 break;
4513 if (i < REGEXP_ALLOF (regexp)->regexps_num)
4515 gcc_assert (REGEXP_ALLOF (allof)->regexps_num > 1
4516 && REGEXP_ALLOF (regexp)->regexps_num > 1);
4517 result = create_node (sizeof (struct regexp)
4518 + sizeof (regexp_t)
4519 * (REGEXP_ALLOF (regexp)->regexps_num
4520 + REGEXP_ALLOF (allof)->regexps_num - 2));
4521 result->mode = rm_allof;
4522 result->pos = regexp->pos;
4523 REGEXP_ALLOF (result)->regexps_num
4524 = (REGEXP_ALLOF (regexp)->regexps_num
4525 + REGEXP_ALLOF (allof)->regexps_num - 1);
4526 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4527 if (i < allof_index)
4528 REGEXP_ALLOF (result)->regexps [i]
4529 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4530 else if (i > allof_index)
4531 REGEXP_ALLOF (result)->regexps
4532 [i + REGEXP_ALLOF (allof)->regexps_num - 1]
4533 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4534 else
4535 for (j = 0; j < REGEXP_ALLOF (allof)->regexps_num; j++)
4536 REGEXP_ALLOF (result)->regexps [i + j]
4537 = copy_insn_regexp (REGEXP_ALLOF (allof)->regexps [j]);
4538 regexp_transformed_p = 1;
4539 regexp = result;
4542 else if (regexp->mode == rm_oneof)
4544 regexp_t oneof = NULL;
4545 regexp_t result;
4546 int oneof_index = 0;
4547 int i, j;
4549 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4550 if (REGEXP_ONEOF (regexp)->regexps [i]->mode == rm_oneof)
4552 oneof_index = i;
4553 oneof = REGEXP_ONEOF (regexp)->regexps [i];
4554 break;
4556 if (i < REGEXP_ONEOF (regexp)->regexps_num)
4558 gcc_assert (REGEXP_ONEOF (oneof)->regexps_num > 1
4559 && REGEXP_ONEOF (regexp)->regexps_num > 1);
4560 result = create_node (sizeof (struct regexp)
4561 + sizeof (regexp_t)
4562 * (REGEXP_ONEOF (regexp)->regexps_num
4563 + REGEXP_ONEOF (oneof)->regexps_num - 2));
4564 result->mode = rm_oneof;
4565 result->pos = regexp->pos;
4566 REGEXP_ONEOF (result)->regexps_num
4567 = (REGEXP_ONEOF (regexp)->regexps_num
4568 + REGEXP_ONEOF (oneof)->regexps_num - 1);
4569 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4570 if (i < oneof_index)
4571 REGEXP_ONEOF (result)->regexps [i]
4572 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4573 else if (i > oneof_index)
4574 REGEXP_ONEOF (result)->regexps
4575 [i + REGEXP_ONEOF (oneof)->regexps_num - 1]
4576 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4577 else
4578 for (j = 0; j < REGEXP_ONEOF (oneof)->regexps_num; j++)
4579 REGEXP_ONEOF (result)->regexps [i + j]
4580 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [j]);
4581 regexp_transformed_p = 1;
4582 regexp = result;
4585 return regexp;
4588 /* The function makes transformations
4589 ...,A|B|...,C,... -> (...,A,C,...)|(...,B,C,...)|...
4590 ...+(A|B|...)+C+... -> (...+A+C+...)|(...+B+C+...)|...
4591 ...+(A,B,...)+C+... -> (...+A+C+...),B,...
4592 ...+(A,B,...)+(C,D,...) -> (A+C),(B+D),... */
4593 static regexp_t
4594 transform_3 (regexp_t regexp)
4596 if (regexp->mode == rm_sequence)
4598 regexp_t oneof = NULL;
4599 int oneof_index = 0;
4600 regexp_t result;
4601 regexp_t sequence;
4602 int i, j;
4604 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4605 if (REGEXP_SEQUENCE (regexp)->regexps [i]->mode == rm_oneof)
4607 oneof_index = i;
4608 oneof = REGEXP_SEQUENCE (regexp)->regexps [i];
4609 break;
4611 if (i < REGEXP_SEQUENCE (regexp)->regexps_num)
4613 gcc_assert (REGEXP_ONEOF (oneof)->regexps_num > 1
4614 && REGEXP_SEQUENCE (regexp)->regexps_num > 1);
4615 result = create_node (sizeof (struct regexp)
4616 + sizeof (regexp_t)
4617 * (REGEXP_ONEOF (oneof)->regexps_num - 1));
4618 result->mode = rm_oneof;
4619 result->pos = regexp->pos;
4620 REGEXP_ONEOF (result)->regexps_num
4621 = REGEXP_ONEOF (oneof)->regexps_num;
4622 for (i = 0; i < REGEXP_ONEOF (result)->regexps_num; i++)
4624 sequence
4625 = create_node (sizeof (struct regexp)
4626 + sizeof (regexp_t)
4627 * (REGEXP_SEQUENCE (regexp)->regexps_num - 1));
4628 sequence->mode = rm_sequence;
4629 sequence->pos = regexp->pos;
4630 REGEXP_SEQUENCE (sequence)->regexps_num
4631 = REGEXP_SEQUENCE (regexp)->regexps_num;
4632 REGEXP_ONEOF (result)->regexps [i] = sequence;
4633 for (j = 0; j < REGEXP_SEQUENCE (sequence)->regexps_num; j++)
4634 if (j != oneof_index)
4635 REGEXP_SEQUENCE (sequence)->regexps [j]
4636 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [j]);
4637 else
4638 REGEXP_SEQUENCE (sequence)->regexps [j]
4639 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [i]);
4641 regexp_transformed_p = 1;
4642 regexp = result;
4645 else if (regexp->mode == rm_allof)
4647 regexp_t oneof = NULL;
4648 regexp_t seq;
4649 int oneof_index = 0;
4650 int max_seq_length, allof_length;
4651 regexp_t result;
4652 regexp_t allof = NULL;
4653 regexp_t allof_op = NULL;
4654 int i, j;
4656 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4657 if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_oneof)
4659 oneof_index = i;
4660 oneof = REGEXP_ALLOF (regexp)->regexps [i];
4661 break;
4663 if (i < REGEXP_ALLOF (regexp)->regexps_num)
4665 gcc_assert (REGEXP_ONEOF (oneof)->regexps_num > 1
4666 && REGEXP_ALLOF (regexp)->regexps_num > 1);
4667 result = create_node (sizeof (struct regexp)
4668 + sizeof (regexp_t)
4669 * (REGEXP_ONEOF (oneof)->regexps_num - 1));
4670 result->mode = rm_oneof;
4671 result->pos = regexp->pos;
4672 REGEXP_ONEOF (result)->regexps_num
4673 = REGEXP_ONEOF (oneof)->regexps_num;
4674 for (i = 0; i < REGEXP_ONEOF (result)->regexps_num; i++)
4676 allof
4677 = create_node (sizeof (struct regexp)
4678 + sizeof (regexp_t)
4679 * (REGEXP_ALLOF (regexp)->regexps_num - 1));
4680 allof->mode = rm_allof;
4681 allof->pos = regexp->pos;
4682 REGEXP_ALLOF (allof)->regexps_num
4683 = REGEXP_ALLOF (regexp)->regexps_num;
4684 REGEXP_ONEOF (result)->regexps [i] = allof;
4685 for (j = 0; j < REGEXP_ALLOF (allof)->regexps_num; j++)
4686 if (j != oneof_index)
4687 REGEXP_ALLOF (allof)->regexps [j]
4688 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [j]);
4689 else
4690 REGEXP_ALLOF (allof)->regexps [j]
4691 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [i]);
4693 regexp_transformed_p = 1;
4694 regexp = result;
4696 max_seq_length = 0;
4697 if (regexp->mode == rm_allof)
4698 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4700 switch (REGEXP_ALLOF (regexp)->regexps [i]->mode)
4702 case rm_sequence:
4703 seq = REGEXP_ALLOF (regexp)->regexps [i];
4704 if (max_seq_length < REGEXP_SEQUENCE (seq)->regexps_num)
4705 max_seq_length = REGEXP_SEQUENCE (seq)->regexps_num;
4706 break;
4708 case rm_unit:
4709 case rm_nothing:
4710 break;
4712 default:
4713 max_seq_length = 0;
4714 goto break_for;
4717 break_for:
4718 if (max_seq_length != 0)
4720 gcc_assert (max_seq_length != 1
4721 && REGEXP_ALLOF (regexp)->regexps_num > 1);
4722 result = create_node (sizeof (struct regexp)
4723 + sizeof (regexp_t) * (max_seq_length - 1));
4724 result->mode = rm_sequence;
4725 result->pos = regexp->pos;
4726 REGEXP_SEQUENCE (result)->regexps_num = max_seq_length;
4727 for (i = 0; i < max_seq_length; i++)
4729 allof_length = 0;
4730 for (j = 0; j < REGEXP_ALLOF (regexp)->regexps_num; j++)
4731 switch (REGEXP_ALLOF (regexp)->regexps [j]->mode)
4733 case rm_sequence:
4734 if (i < (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4735 ->regexps [j])->regexps_num))
4737 allof_op
4738 = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4739 ->regexps [j])
4740 ->regexps [i]);
4741 allof_length++;
4743 break;
4744 case rm_unit:
4745 case rm_nothing:
4746 if (i == 0)
4748 allof_op = REGEXP_ALLOF (regexp)->regexps [j];
4749 allof_length++;
4751 break;
4752 default:
4753 break;
4756 if (allof_length == 1)
4757 REGEXP_SEQUENCE (result)->regexps [i] = allof_op;
4758 else
4760 allof = create_node (sizeof (struct regexp)
4761 + sizeof (regexp_t)
4762 * (allof_length - 1));
4763 allof->mode = rm_allof;
4764 allof->pos = regexp->pos;
4765 REGEXP_ALLOF (allof)->regexps_num = allof_length;
4766 REGEXP_SEQUENCE (result)->regexps [i] = allof;
4767 allof_length = 0;
4768 for (j = 0; j < REGEXP_ALLOF (regexp)->regexps_num; j++)
4769 if (REGEXP_ALLOF (regexp)->regexps [j]->mode == rm_sequence
4770 && (i <
4771 (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4772 ->regexps [j])->regexps_num)))
4774 allof_op = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4775 ->regexps [j])
4776 ->regexps [i]);
4777 REGEXP_ALLOF (allof)->regexps [allof_length]
4778 = allof_op;
4779 allof_length++;
4781 else if (i == 0
4782 && (REGEXP_ALLOF (regexp)->regexps [j]->mode
4783 == rm_unit
4784 || (REGEXP_ALLOF (regexp)->regexps [j]->mode
4785 == rm_nothing)))
4787 allof_op = REGEXP_ALLOF (regexp)->regexps [j];
4788 REGEXP_ALLOF (allof)->regexps [allof_length]
4789 = allof_op;
4790 allof_length++;
4794 regexp_transformed_p = 1;
4795 regexp = result;
4798 return regexp;
4801 /* The function traverses IR of reservation and applies transformations
4802 implemented by FUNC. */
4803 static regexp_t
4804 regexp_transform_func (regexp_t regexp, regexp_t (*func) (regexp_t regexp))
4806 int i;
4808 switch (regexp->mode)
4810 case rm_sequence:
4811 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4812 REGEXP_SEQUENCE (regexp)->regexps [i]
4813 = regexp_transform_func (REGEXP_SEQUENCE (regexp)->regexps [i],
4814 func);
4815 break;
4817 case rm_allof:
4818 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4819 REGEXP_ALLOF (regexp)->regexps [i]
4820 = regexp_transform_func (REGEXP_ALLOF (regexp)->regexps [i], func);
4821 break;
4823 case rm_oneof:
4824 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4825 REGEXP_ONEOF (regexp)->regexps [i]
4826 = regexp_transform_func (REGEXP_ONEOF (regexp)->regexps [i], func);
4827 break;
4829 case rm_repeat:
4830 REGEXP_REPEAT (regexp)->regexp
4831 = regexp_transform_func (REGEXP_REPEAT (regexp)->regexp, func);
4832 break;
4834 case rm_nothing:
4835 case rm_unit:
4836 break;
4838 default:
4839 gcc_unreachable ();
4841 return (*func) (regexp);
4844 /* The function applies all transformations for IR representation of
4845 reservation REGEXP. */
4846 static regexp_t
4847 transform_regexp (regexp_t regexp)
4849 regexp = regexp_transform_func (regexp, transform_1);
4852 regexp_transformed_p = 0;
4853 regexp = regexp_transform_func (regexp, transform_2);
4854 regexp = regexp_transform_func (regexp, transform_3);
4856 while (regexp_transformed_p);
4857 return regexp;
4860 /* The function applies all transformations for reservations of all
4861 insn declarations. */
4862 static void
4863 transform_insn_regexps (void)
4865 decl_t decl;
4866 int i;
4868 transform_time = create_ticker ();
4869 add_advance_cycle_insn_decl ();
4870 if (progress_flag)
4871 fprintf (stderr, "Reservation transformation...");
4872 for (i = 0; i < description->decls_num; i++)
4874 decl = description->decls [i];
4875 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
4876 DECL_INSN_RESERV (decl)->transformed_regexp
4877 = transform_regexp (copy_insn_regexp
4878 (DECL_INSN_RESERV (decl)->regexp));
4880 if (progress_flag)
4881 fprintf (stderr, "done\n");
4882 ticker_off (&transform_time);
4887 /* The following variable value is TRUE if the first annotated message
4888 about units to automata distribution has been output. */
4889 static int annotation_message_reported_p;
4891 /* The following structure describes usage of a unit in a reservation. */
4892 struct unit_usage
4894 unit_decl_t unit_decl;
4895 /* The following forms a list of units used on the same cycle in the
4896 same alternative. */
4897 struct unit_usage *next;
4899 typedef struct unit_usage *unit_usage_t;
4901 DEF_VEC_P(unit_usage_t);
4902 DEF_VEC_ALLOC_P(unit_usage_t,heap);
4904 /* Obstack for unit_usage structures. */
4905 static struct obstack unit_usages;
4907 /* VLA for representation of array of pointers to unit usage
4908 structures. There is an element for each combination of
4909 (alternative number, cycle). Unit usages on given cycle in
4910 alternative with given number are referred through element with
4911 index equals to the cycle * number of all alternatives in the regexp
4912 + the alternative number. */
4913 static VEC(unit_usage_t,heap) *cycle_alt_unit_usages;
4915 /* The following function creates the structure unit_usage for UNIT on
4916 CYCLE in REGEXP alternative with ALT_NUM. The structure is made
4917 accessed through cycle_alt_unit_usages. */
4918 static void
4919 store_alt_unit_usage (regexp_t regexp, regexp_t unit, int cycle,
4920 int alt_num)
4922 size_t length;
4923 unit_decl_t unit_decl;
4924 unit_usage_t unit_usage_ptr;
4925 int index;
4927 gcc_assert (regexp && regexp->mode == rm_oneof
4928 && alt_num < REGEXP_ONEOF (regexp)->regexps_num);
4929 unit_decl = REGEXP_UNIT (unit)->unit_decl;
4931 length = (cycle + 1) * REGEXP_ONEOF (regexp)->regexps_num;
4932 while (VEC_length (unit_usage_t, cycle_alt_unit_usages) < length)
4933 VEC_safe_push (unit_usage_t,heap, cycle_alt_unit_usages, 0);
4935 obstack_blank (&unit_usages, sizeof (struct unit_usage));
4936 unit_usage_ptr = (struct unit_usage *) obstack_base (&unit_usages);
4937 obstack_finish (&unit_usages);
4938 unit_usage_ptr->unit_decl = unit_decl;
4939 index = cycle * REGEXP_ONEOF (regexp)->regexps_num + alt_num;
4940 unit_usage_ptr->next = VEC_index (unit_usage_t, cycle_alt_unit_usages, index);
4941 VEC_replace (unit_usage_t, cycle_alt_unit_usages, index, unit_usage_ptr);
4942 unit_decl->last_distribution_check_cycle = -1; /* undefined */
4945 /* The function processes given REGEXP to find units with the wrong
4946 distribution. */
4947 static void
4948 check_regexp_units_distribution (const char *insn_reserv_name,
4949 regexp_t regexp)
4951 int i, j, k, cycle;
4952 regexp_t seq, allof, unit;
4953 struct unit_usage *unit_usage_ptr, *other_unit_usage_ptr;
4955 if (regexp == NULL || regexp->mode != rm_oneof)
4956 return;
4957 /* Store all unit usages in the regexp: */
4958 obstack_init (&unit_usages);
4959 cycle_alt_unit_usages = 0;
4961 for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
4963 seq = REGEXP_ONEOF (regexp)->regexps [i];
4964 switch (seq->mode)
4966 case rm_sequence:
4967 for (j = 0; j < REGEXP_SEQUENCE (seq)->regexps_num; j++)
4969 allof = REGEXP_SEQUENCE (seq)->regexps [j];
4970 switch (allof->mode)
4972 case rm_allof:
4973 for (k = 0; k < REGEXP_ALLOF (allof)->regexps_num; k++)
4975 unit = REGEXP_ALLOF (allof)->regexps [k];
4976 if (unit->mode == rm_unit)
4977 store_alt_unit_usage (regexp, unit, j, i);
4978 else
4979 gcc_assert (unit->mode == rm_nothing);
4981 break;
4983 case rm_unit:
4984 store_alt_unit_usage (regexp, allof, j, i);
4985 break;
4987 case rm_nothing:
4988 break;
4990 default:
4991 gcc_unreachable ();
4994 break;
4996 case rm_allof:
4997 for (k = 0; k < REGEXP_ALLOF (seq)->regexps_num; k++)
4999 unit = REGEXP_ALLOF (seq)->regexps [k];
5000 switch (unit->mode)
5002 case rm_unit:
5003 store_alt_unit_usage (regexp, unit, 0, i);
5004 break;
5006 case rm_nothing:
5007 break;
5009 default:
5010 gcc_unreachable ();
5013 break;
5015 case rm_unit:
5016 store_alt_unit_usage (regexp, seq, 0, i);
5017 break;
5019 case rm_nothing:
5020 break;
5022 default:
5023 gcc_unreachable ();
5026 /* Check distribution: */
5027 for (i = 0; i < (int) VEC_length (unit_usage_t, cycle_alt_unit_usages); i++)
5029 cycle = i / REGEXP_ONEOF (regexp)->regexps_num;
5030 for (unit_usage_ptr = VEC_index (unit_usage_t, cycle_alt_unit_usages, i);
5031 unit_usage_ptr != NULL;
5032 unit_usage_ptr = unit_usage_ptr->next)
5033 if (cycle != unit_usage_ptr->unit_decl->last_distribution_check_cycle)
5035 unit_usage_ptr->unit_decl->last_distribution_check_cycle = cycle;
5036 for (k = cycle * REGEXP_ONEOF (regexp)->regexps_num;
5037 k < (int) VEC_length (unit_usage_t, cycle_alt_unit_usages)
5038 && k == cycle * REGEXP_ONEOF (regexp)->regexps_num;
5039 k++)
5041 for (other_unit_usage_ptr
5042 = VEC_index (unit_usage_t, cycle_alt_unit_usages, k);
5043 other_unit_usage_ptr != NULL;
5044 other_unit_usage_ptr = other_unit_usage_ptr->next)
5045 if (unit_usage_ptr->unit_decl->automaton_decl
5046 == other_unit_usage_ptr->unit_decl->automaton_decl)
5047 break;
5048 if (other_unit_usage_ptr == NULL
5049 && (VEC_index (unit_usage_t, cycle_alt_unit_usages, k)
5050 != NULL))
5051 break;
5053 if (k < (int) VEC_length (unit_usage_t, cycle_alt_unit_usages)
5054 && k == cycle * REGEXP_ONEOF (regexp)->regexps_num)
5056 if (!annotation_message_reported_p)
5058 fprintf (stderr, "\n");
5059 error ("The following units do not satisfy units-automata distribution rule");
5060 error (" (A unit of given unit automaton should be on each reserv. altern.)");
5061 annotation_message_reported_p = TRUE;
5063 error ("Unit %s, reserv. %s, cycle %d",
5064 unit_usage_ptr->unit_decl->name, insn_reserv_name,
5065 cycle);
5069 VEC_free (unit_usage_t,heap, cycle_alt_unit_usages);
5070 obstack_free (&unit_usages, NULL);
5073 /* The function finds units which violates units to automata
5074 distribution rule. If the units exist, report about them. */
5075 static void
5076 check_unit_distributions_to_automata (void)
5078 decl_t decl;
5079 int i;
5081 if (progress_flag)
5082 fprintf (stderr, "Check unit distributions to automata...");
5083 annotation_message_reported_p = FALSE;
5084 for (i = 0; i < description->decls_num; i++)
5086 decl = description->decls [i];
5087 if (decl->mode == dm_insn_reserv)
5088 check_regexp_units_distribution
5089 (DECL_INSN_RESERV (decl)->name,
5090 DECL_INSN_RESERV (decl)->transformed_regexp);
5092 if (progress_flag)
5093 fprintf (stderr, "done\n");
5098 /* The page contains code for building alt_states (see comments for
5099 IR) describing all possible insns reservations of an automaton. */
5101 /* Current state being formed for which the current alt_state
5102 refers. */
5103 static state_t state_being_formed;
5105 /* Current alt_state being formed. */
5106 static alt_state_t alt_state_being_formed;
5108 /* This recursive function processes `,' and units in reservation
5109 REGEXP for forming alt_states of AUTOMATON. It is believed that
5110 CURR_CYCLE is start cycle of all reservation REGEXP. */
5111 static int
5112 process_seq_for_forming_states (regexp_t regexp, automaton_t automaton,
5113 int curr_cycle)
5115 int i;
5117 if (regexp == NULL)
5118 return curr_cycle;
5120 switch (regexp->mode)
5122 case rm_unit:
5123 if (REGEXP_UNIT (regexp)->unit_decl->corresponding_automaton_num
5124 == automaton->automaton_order_num)
5125 set_state_reserv (state_being_formed, curr_cycle,
5126 REGEXP_UNIT (regexp)->unit_decl->unit_num);
5127 return curr_cycle;
5129 case rm_sequence:
5130 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
5131 curr_cycle
5132 = process_seq_for_forming_states
5133 (REGEXP_SEQUENCE (regexp)->regexps [i], automaton, curr_cycle) + 1;
5134 return curr_cycle;
5136 case rm_allof:
5138 int finish_cycle = 0;
5139 int cycle;
5141 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
5143 cycle = process_seq_for_forming_states (REGEXP_ALLOF (regexp)
5144 ->regexps [i],
5145 automaton, curr_cycle);
5146 if (finish_cycle < cycle)
5147 finish_cycle = cycle;
5149 return finish_cycle;
5152 case rm_nothing:
5153 return curr_cycle;
5155 default:
5156 gcc_unreachable ();
5160 /* This recursive function finishes forming ALT_STATE of AUTOMATON and
5161 inserts alt_state into the table. */
5162 static void
5163 finish_forming_alt_state (alt_state_t alt_state,
5164 automaton_t automaton ATTRIBUTE_UNUSED)
5166 state_t state_in_table;
5167 state_t corresponding_state;
5169 corresponding_state = alt_state->state;
5170 state_in_table = insert_state (corresponding_state);
5171 if (state_in_table != corresponding_state)
5173 free_state (corresponding_state);
5174 alt_state->state = state_in_table;
5178 /* The following variable value is current automaton insn for whose
5179 reservation the alt states are created. */
5180 static ainsn_t curr_ainsn;
5182 /* This recursive function processes `|' in reservation REGEXP for
5183 forming alt_states of AUTOMATON. List of the alt states should
5184 have the same order as in the description. */
5185 static void
5186 process_alts_for_forming_states (regexp_t regexp, automaton_t automaton,
5187 int inside_oneof_p)
5189 int i;
5191 if (regexp->mode != rm_oneof)
5193 alt_state_being_formed = get_free_alt_state ();
5194 state_being_formed = get_free_state (1, automaton);
5195 alt_state_being_formed->state = state_being_formed;
5196 /* We inserts in reverse order but we process alternatives also
5197 in reverse order. So we have the same order of alternative
5198 as in the description. */
5199 alt_state_being_formed->next_alt_state = curr_ainsn->alt_states;
5200 curr_ainsn->alt_states = alt_state_being_formed;
5201 (void) process_seq_for_forming_states (regexp, automaton, 0);
5202 finish_forming_alt_state (alt_state_being_formed, automaton);
5204 else
5206 gcc_assert (!inside_oneof_p);
5207 /* We processes it in reverse order to get list with the same
5208 order as in the description. See also the previous
5209 commentary. */
5210 for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
5211 process_alts_for_forming_states (REGEXP_ONEOF (regexp)->regexps [i],
5212 automaton, 1);
5216 /* Create nodes alt_state for all AUTOMATON insns. */
5217 static void
5218 create_alt_states (automaton_t automaton)
5220 struct insn_reserv_decl *reserv_decl;
5222 for (curr_ainsn = automaton->ainsn_list;
5223 curr_ainsn != NULL;
5224 curr_ainsn = curr_ainsn->next_ainsn)
5226 reserv_decl = curr_ainsn->insn_reserv_decl;
5227 if (reserv_decl != DECL_INSN_RESERV (advance_cycle_insn_decl))
5229 curr_ainsn->alt_states = NULL;
5230 process_alts_for_forming_states (reserv_decl->transformed_regexp,
5231 automaton, 0);
5232 curr_ainsn->sorted_alt_states
5233 = uniq_sort_alt_states (curr_ainsn->alt_states);
5240 /* The page contains major code for building DFA(s) for fast pipeline
5241 hazards recognition. */
5243 /* The function forms list of ainsns of AUTOMATON with the same
5244 reservation. */
5246 static void
5247 form_ainsn_with_same_reservs (automaton_t automaton)
5249 ainsn_t curr_ainsn;
5250 size_t i;
5251 VEC(ainsn_t,heap) *last_insns = VEC_alloc (ainsn_t,heap, 150);
5253 for (curr_ainsn = automaton->ainsn_list;
5254 curr_ainsn != NULL;
5255 curr_ainsn = curr_ainsn->next_ainsn)
5256 if (curr_ainsn->insn_reserv_decl
5257 == DECL_INSN_RESERV (advance_cycle_insn_decl))
5259 curr_ainsn->next_same_reservs_insn = NULL;
5260 curr_ainsn->first_insn_with_same_reservs = 1;
5262 else
5264 for (i = 0; i < VEC_length (ainsn_t, last_insns); i++)
5265 if (alt_states_eq
5266 (curr_ainsn->sorted_alt_states,
5267 VEC_index (ainsn_t, last_insns, i)->sorted_alt_states))
5268 break;
5269 curr_ainsn->next_same_reservs_insn = NULL;
5270 if (i < VEC_length (ainsn_t, last_insns))
5272 curr_ainsn->first_insn_with_same_reservs = 0;
5273 VEC_index (ainsn_t, last_insns, i)->next_same_reservs_insn
5274 = curr_ainsn;
5275 VEC_replace (ainsn_t, last_insns, i, curr_ainsn);
5277 else
5279 VEC_safe_push (ainsn_t, heap, last_insns, curr_ainsn);
5280 curr_ainsn->first_insn_with_same_reservs = 1;
5283 VEC_free (ainsn_t,heap, last_insns);
5286 /* Forming unit reservations which can affect creating the automaton
5287 states achieved from a given state. It permits to build smaller
5288 automata in many cases. We would have the same automata after
5289 the minimization without such optimization, but the automaton
5290 right after the building could be huge. So in other words, usage
5291 of reservs_matter means some minimization during building the
5292 automaton. */
5293 static reserv_sets_t
5294 form_reservs_matter (automaton_t automaton)
5296 int cycle, unit;
5297 reserv_sets_t reservs_matter = alloc_empty_reserv_sets();
5299 for (cycle = 0; cycle < max_cycles_num; cycle++)
5300 for (unit = 0; unit < description->units_num; unit++)
5301 if (units_array [unit]->automaton_decl
5302 == automaton->corresponding_automaton_decl
5303 && (cycle >= units_array [unit]->min_occ_cycle_num
5304 /* We can not remove queried unit from reservations. */
5305 || units_array [unit]->query_p
5306 /* We can not remove units which are used
5307 `exclusion_set', `presence_set',
5308 `final_presence_set', `absence_set', and
5309 `final_absence_set'. */
5310 || units_array [unit]->in_set_p))
5311 set_unit_reserv (reservs_matter, cycle, unit);
5312 return reservs_matter;
5315 /* The following function creates all states of nondeterministic AUTOMATON. */
5316 static void
5317 make_automaton (automaton_t automaton)
5319 ainsn_t ainsn;
5320 struct insn_reserv_decl *insn_reserv_decl;
5321 alt_state_t alt_state;
5322 state_t state;
5323 state_t start_state;
5324 state_t state2;
5325 ainsn_t advance_cycle_ainsn;
5326 arc_t added_arc;
5327 VEC(state_t,heap) *state_stack = VEC_alloc(state_t,heap, 150);
5328 int states_n;
5329 reserv_sets_t reservs_matter = form_reservs_matter (automaton);
5331 /* Create the start state (empty state). */
5332 start_state = insert_state (get_free_state (1, automaton));
5333 automaton->start_state = start_state;
5334 start_state->it_was_placed_in_stack_for_NDFA_forming = 1;
5335 VEC_safe_push (state_t,heap, state_stack, start_state);
5336 states_n = 1;
5337 while (VEC_length (state_t, state_stack) != 0)
5339 state = VEC_pop (state_t, state_stack);
5340 advance_cycle_ainsn = NULL;
5341 for (ainsn = automaton->ainsn_list;
5342 ainsn != NULL;
5343 ainsn = ainsn->next_ainsn)
5344 if (ainsn->first_insn_with_same_reservs)
5346 insn_reserv_decl = ainsn->insn_reserv_decl;
5347 if (insn_reserv_decl != DECL_INSN_RESERV (advance_cycle_insn_decl))
5349 /* We process alt_states in the same order as they are
5350 present in the description. */
5351 added_arc = NULL;
5352 for (alt_state = ainsn->alt_states;
5353 alt_state != NULL;
5354 alt_state = alt_state->next_alt_state)
5356 state2 = alt_state->state;
5357 if (!intersected_state_reservs_p (state, state2))
5359 state2 = states_union (state, state2, reservs_matter);
5360 if (!state2->it_was_placed_in_stack_for_NDFA_forming)
5362 state2->it_was_placed_in_stack_for_NDFA_forming
5363 = 1;
5364 VEC_safe_push (state_t,heap, state_stack, state2);
5365 states_n++;
5366 if (progress_flag && states_n % 100 == 0)
5367 fprintf (stderr, ".");
5369 added_arc = add_arc (state, state2, ainsn);
5370 if (!ndfa_flag)
5371 break;
5374 if (!ndfa_flag && added_arc != NULL)
5376 for (alt_state = ainsn->alt_states;
5377 alt_state != NULL;
5378 alt_state = alt_state->next_alt_state)
5379 state2 = alt_state->state;
5382 else
5383 advance_cycle_ainsn = ainsn;
5385 /* Add transition to advance cycle. */
5386 state2 = state_shift (state, reservs_matter);
5387 if (!state2->it_was_placed_in_stack_for_NDFA_forming)
5389 state2->it_was_placed_in_stack_for_NDFA_forming = 1;
5390 VEC_safe_push (state_t,heap, state_stack, state2);
5391 states_n++;
5392 if (progress_flag && states_n % 100 == 0)
5393 fprintf (stderr, ".");
5395 gcc_assert (advance_cycle_ainsn);
5396 add_arc (state, state2, advance_cycle_ainsn);
5398 VEC_free (state_t,heap, state_stack);
5401 /* Foms lists of all arcs of STATE marked by the same ainsn. */
5402 static void
5403 form_arcs_marked_by_insn (state_t state)
5405 decl_t decl;
5406 arc_t arc;
5407 int i;
5409 for (i = 0; i < description->decls_num; i++)
5411 decl = description->decls [i];
5412 if (decl->mode == dm_insn_reserv)
5413 DECL_INSN_RESERV (decl)->arcs_marked_by_insn = NULL;
5415 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5417 gcc_assert (arc->insn);
5418 arc->next_arc_marked_by_insn
5419 = arc->insn->insn_reserv_decl->arcs_marked_by_insn;
5420 arc->insn->insn_reserv_decl->arcs_marked_by_insn = arc;
5424 /* The function creates composed state (see comments for IR) from
5425 ORIGINAL_STATE and list of arcs ARCS_MARKED_BY_INSN marked by the
5426 same insn. If the composed state is not in STATE_STACK yet, it is
5427 pushed into STATE_STACK. */
5429 static int
5430 create_composed_state (state_t original_state, arc_t arcs_marked_by_insn,
5431 VEC(state_t,heap) **state_stack)
5433 state_t state;
5434 alt_state_t alt_state, curr_alt_state;
5435 alt_state_t new_alt_state;
5436 arc_t curr_arc;
5437 arc_t next_arc;
5438 state_t state_in_table;
5439 state_t temp_state;
5440 alt_state_t canonical_alt_states_list;
5441 int alts_number;
5442 int new_state_p = 0;
5444 if (arcs_marked_by_insn == NULL)
5445 return new_state_p;
5446 if (arcs_marked_by_insn->next_arc_marked_by_insn == NULL)
5447 state = arcs_marked_by_insn->to_state;
5448 else
5450 gcc_assert (ndfa_flag);
5451 /* Create composed state. */
5452 state = get_free_state (0, arcs_marked_by_insn->to_state->automaton);
5453 curr_alt_state = NULL;
5454 for (curr_arc = arcs_marked_by_insn;
5455 curr_arc != NULL;
5456 curr_arc = curr_arc->next_arc_marked_by_insn)
5457 if (curr_arc->to_state->component_states == NULL)
5459 new_alt_state = get_free_alt_state ();
5460 new_alt_state->next_alt_state = curr_alt_state;
5461 new_alt_state->state = curr_arc->to_state;
5462 curr_alt_state = new_alt_state;
5464 else
5465 for (alt_state = curr_arc->to_state->component_states;
5466 alt_state != NULL;
5467 alt_state = alt_state->next_sorted_alt_state)
5469 new_alt_state = get_free_alt_state ();
5470 new_alt_state->next_alt_state = curr_alt_state;
5471 new_alt_state->state = alt_state->state;
5472 gcc_assert (!alt_state->state->component_states);
5473 curr_alt_state = new_alt_state;
5475 /* There are not identical sets in the alt state list. */
5476 canonical_alt_states_list = uniq_sort_alt_states (curr_alt_state);
5477 if (canonical_alt_states_list->next_sorted_alt_state == NULL)
5479 temp_state = state;
5480 state = canonical_alt_states_list->state;
5481 free_state (temp_state);
5483 else
5485 state->component_states = canonical_alt_states_list;
5486 state_in_table = insert_state (state);
5487 if (state_in_table != state)
5489 gcc_assert
5490 (state_in_table->it_was_placed_in_stack_for_DFA_forming);
5491 free_state (state);
5492 state = state_in_table;
5494 else
5496 gcc_assert (!state->it_was_placed_in_stack_for_DFA_forming);
5497 new_state_p = 1;
5498 for (curr_alt_state = state->component_states;
5499 curr_alt_state != NULL;
5500 curr_alt_state = curr_alt_state->next_sorted_alt_state)
5501 for (curr_arc = first_out_arc (curr_alt_state->state);
5502 curr_arc != NULL;
5503 curr_arc = next_out_arc (curr_arc))
5504 add_arc (state, curr_arc->to_state, curr_arc->insn);
5506 arcs_marked_by_insn->to_state = state;
5507 for (alts_number = 0,
5508 curr_arc = arcs_marked_by_insn->next_arc_marked_by_insn;
5509 curr_arc != NULL;
5510 curr_arc = next_arc)
5512 next_arc = curr_arc->next_arc_marked_by_insn;
5513 remove_arc (original_state, curr_arc);
5514 alts_number++;
5518 if (!state->it_was_placed_in_stack_for_DFA_forming)
5520 state->it_was_placed_in_stack_for_DFA_forming = 1;
5521 VEC_safe_push (state_t,heap, *state_stack, state);
5523 return new_state_p;
5526 /* The function transforms nondeterministic AUTOMATON into
5527 deterministic. */
5529 static void
5530 NDFA_to_DFA (automaton_t automaton)
5532 state_t start_state;
5533 state_t state;
5534 decl_t decl;
5535 VEC(state_t,heap) *state_stack;
5536 int i;
5537 int states_n;
5539 state_stack = VEC_alloc (state_t,heap, 0);
5541 /* Create the start state (empty state). */
5542 start_state = automaton->start_state;
5543 start_state->it_was_placed_in_stack_for_DFA_forming = 1;
5544 VEC_safe_push (state_t,heap, state_stack, start_state);
5545 states_n = 1;
5546 while (VEC_length (state_t, state_stack) != 0)
5548 state = VEC_pop (state_t, state_stack);
5549 form_arcs_marked_by_insn (state);
5550 for (i = 0; i < description->decls_num; i++)
5552 decl = description->decls [i];
5553 if (decl->mode == dm_insn_reserv
5554 && create_composed_state
5555 (state, DECL_INSN_RESERV (decl)->arcs_marked_by_insn,
5556 &state_stack))
5558 states_n++;
5559 if (progress_flag && states_n % 100 == 0)
5560 fprintf (stderr, ".");
5564 VEC_free (state_t,heap, state_stack);
5567 /* The following variable value is current number (1, 2, ...) of passing
5568 graph of states. */
5569 static int curr_state_graph_pass_num;
5571 /* This recursive function passes all states achieved from START_STATE
5572 and applies APPLIED_FUNC to them. */
5573 static void
5574 pass_state_graph (state_t start_state, void (*applied_func) (state_t state))
5576 arc_t arc;
5578 if (start_state->pass_num == curr_state_graph_pass_num)
5579 return;
5580 start_state->pass_num = curr_state_graph_pass_num;
5581 (*applied_func) (start_state);
5582 for (arc = first_out_arc (start_state);
5583 arc != NULL;
5584 arc = next_out_arc (arc))
5585 pass_state_graph (arc->to_state, applied_func);
5588 /* This recursive function passes all states of AUTOMATON and applies
5589 APPLIED_FUNC to them. */
5590 static void
5591 pass_states (automaton_t automaton, void (*applied_func) (state_t state))
5593 curr_state_graph_pass_num++;
5594 pass_state_graph (automaton->start_state, applied_func);
5597 /* The function initializes code for passing of all states. */
5598 static void
5599 initiate_pass_states (void)
5601 curr_state_graph_pass_num = 0;
5604 /* The following vla is used for storing pointers to all achieved
5605 states. */
5606 static VEC(state_t,heap) *all_achieved_states;
5608 /* This function is called by function pass_states to add an achieved
5609 STATE. */
5610 static void
5611 add_achieved_state (state_t state)
5613 VEC_safe_push (state_t,heap, all_achieved_states, state);
5616 /* The function sets up equivalence numbers of insns which mark all
5617 out arcs of STATE by equiv_class_num_1 (if ODD_ITERATION_FLAG has
5618 nonzero value) or by equiv_class_num_2 of the destination state.
5619 The function returns number of out arcs of STATE. */
5620 static void
5621 set_out_arc_insns_equiv_num (state_t state, int odd_iteration_flag)
5623 arc_t arc;
5625 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5627 gcc_assert (!arc->insn->insn_reserv_decl->equiv_class_num);
5628 arc->insn->insn_reserv_decl->equiv_class_num
5629 = (odd_iteration_flag
5630 ? arc->to_state->equiv_class_num_1
5631 : arc->to_state->equiv_class_num_2);
5632 gcc_assert (arc->insn->insn_reserv_decl->equiv_class_num);
5636 /* The function clears equivalence numbers and alt_states in all insns
5637 which mark all out arcs of STATE. */
5638 static void
5639 clear_arc_insns_equiv_num (state_t state)
5641 arc_t arc;
5643 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5644 arc->insn->insn_reserv_decl->equiv_class_num = 0;
5648 /* The following function returns TRUE if STATE reserves the unit with
5649 UNIT_NUM on the first cycle. */
5650 static int
5651 first_cycle_unit_presence (state_t state, int unit_num)
5653 alt_state_t alt_state;
5655 if (state->component_states == NULL)
5656 return test_unit_reserv (state->reservs, 0, unit_num);
5657 else
5659 for (alt_state = state->component_states;
5660 alt_state != NULL;
5661 alt_state = alt_state->next_sorted_alt_state)
5662 if (test_unit_reserv (alt_state->state->reservs, 0, unit_num))
5663 return true;
5665 return false;
5668 /* This fills in the presence_signature[] member of STATE. */
5669 static void
5670 cache_presence (state_t state)
5672 int i, num = 0;
5673 unsigned int sz;
5674 sz = (description->query_units_num + sizeof (int) * CHAR_BIT - 1)
5675 / (sizeof (int) * CHAR_BIT);
5677 state->presence_signature = create_node (sz * sizeof (int));
5678 for (i = 0; i < description->units_num; i++)
5679 if (units_array [i]->query_p)
5681 int presence1_p = first_cycle_unit_presence (state, i);
5682 state->presence_signature[num / (sizeof (int) * CHAR_BIT)]
5683 |= (!!presence1_p) << (num % (sizeof (int) * CHAR_BIT));
5684 num++;
5688 /* The function returns nonzero value if STATE is not equivalent to
5689 ANOTHER_STATE from the same current partition on equivalence
5690 classes. Another state has ANOTHER_STATE_OUT_ARCS_NUM number of
5691 output arcs. Iteration of making equivalence partition is defined
5692 by ODD_ITERATION_FLAG. */
5693 static int
5694 state_is_differed (state_t state, state_t another_state,
5695 int odd_iteration_flag)
5697 arc_t arc;
5698 unsigned int sz, si;
5700 gcc_assert (state->num_out_arcs == another_state->num_out_arcs);
5702 sz = (description->query_units_num + sizeof (int) * CHAR_BIT - 1)
5703 / (sizeof (int) * CHAR_BIT);
5705 for (si = 0; si < sz; si++)
5706 gcc_assert (state->presence_signature[si]
5707 == another_state->presence_signature[si]);
5709 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5711 if ((odd_iteration_flag
5712 ? arc->to_state->equiv_class_num_1
5713 : arc->to_state->equiv_class_num_2)
5714 != arc->insn->insn_reserv_decl->equiv_class_num)
5715 return 1;
5718 return 0;
5721 /* Compares two states pointed to by STATE_PTR_1 and STATE_PTR_2
5722 and return -1, 0 or 1. This function can be used as predicate for
5723 qsort(). It requires the member presence_signature[] of both
5724 states be filled. */
5725 static int
5726 compare_states_for_equiv (const void *state_ptr_1,
5727 const void *state_ptr_2)
5729 state_t s1 = *(state_t *)state_ptr_1;
5730 state_t s2 = *(state_t *)state_ptr_2;
5731 unsigned int sz, si;
5732 if (s1->num_out_arcs < s2->num_out_arcs)
5733 return -1;
5734 else if (s1->num_out_arcs > s2->num_out_arcs)
5735 return 1;
5737 sz = (description->query_units_num + sizeof (int) * CHAR_BIT - 1)
5738 / (sizeof (int) * CHAR_BIT);
5740 for (si = 0; si < sz; si++)
5741 if (s1->presence_signature[si] < s2->presence_signature[si])
5742 return -1;
5743 else if (s1->presence_signature[si] > s2->presence_signature[si])
5744 return 1;
5745 return 0;
5748 /* The function makes initial partition of STATES on equivalent
5749 classes and saves it into *CLASSES. This function requires the input
5750 to be sorted via compare_states_for_equiv(). */
5751 static int
5752 init_equiv_class (VEC(state_t,heap) *states, VEC (state_t,heap) **classes)
5754 size_t i;
5755 state_t prev = 0;
5756 int class_num = 1;
5758 *classes = VEC_alloc (state_t,heap, 150);
5759 for (i = 0; i < VEC_length (state_t, states); i++)
5761 state_t state = VEC_index (state_t, states, i);
5762 if (prev)
5764 if (compare_states_for_equiv (&prev, &state) != 0)
5766 VEC_safe_push (state_t,heap, *classes, prev);
5767 class_num++;
5768 prev = NULL;
5771 state->equiv_class_num_1 = class_num;
5772 state->next_equiv_class_state = prev;
5773 prev = state;
5775 if (prev)
5776 VEC_safe_push (state_t,heap, *classes, prev);
5777 return class_num;
5780 /* The function copies pointers to equivalent states from vla FROM
5781 into vla TO. */
5782 static void
5783 copy_equiv_class (VEC(state_t,heap) **to, VEC(state_t,heap) *from)
5785 VEC_free (state_t,heap, *to);
5786 *to = VEC_copy (state_t,heap, from);
5789 /* The function processes equivalence class given by its first state,
5790 FIRST_STATE, on odd iteration if ODD_ITERATION_FLAG. If there
5791 are not equivalent states, the function partitions the class
5792 removing nonequivalent states and placing them in
5793 *NEXT_ITERATION_CLASSES, increments *NEW_EQUIV_CLASS_NUM_PTR ans
5794 assigns it to the state equivalence number. If the class has been
5795 partitioned, the function returns nonzero value. */
5796 static int
5797 partition_equiv_class (state_t first_state, int odd_iteration_flag,
5798 VEC(state_t,heap) **next_iteration_classes,
5799 int *new_equiv_class_num_ptr)
5801 state_t new_equiv_class;
5802 int partition_p;
5803 state_t curr_state;
5804 state_t prev_state;
5805 state_t next_state;
5807 partition_p = 0;
5809 while (first_state != NULL)
5811 new_equiv_class = NULL;
5812 if (first_state->next_equiv_class_state != NULL)
5814 /* There are more one states in the class equivalence. */
5815 set_out_arc_insns_equiv_num (first_state, odd_iteration_flag);
5816 for (prev_state = first_state,
5817 curr_state = first_state->next_equiv_class_state;
5818 curr_state != NULL;
5819 curr_state = next_state)
5821 next_state = curr_state->next_equiv_class_state;
5822 if (state_is_differed (curr_state, first_state,
5823 odd_iteration_flag))
5825 /* Remove curr state from the class equivalence. */
5826 prev_state->next_equiv_class_state = next_state;
5827 /* Add curr state to the new class equivalence. */
5828 curr_state->next_equiv_class_state = new_equiv_class;
5829 if (new_equiv_class == NULL)
5830 (*new_equiv_class_num_ptr)++;
5831 if (odd_iteration_flag)
5832 curr_state->equiv_class_num_2 = *new_equiv_class_num_ptr;
5833 else
5834 curr_state->equiv_class_num_1 = *new_equiv_class_num_ptr;
5835 new_equiv_class = curr_state;
5836 partition_p = 1;
5838 else
5839 prev_state = curr_state;
5841 clear_arc_insns_equiv_num (first_state);
5843 if (new_equiv_class != NULL)
5844 VEC_safe_push (state_t,heap, *next_iteration_classes, new_equiv_class);
5845 first_state = new_equiv_class;
5847 return partition_p;
5850 /* The function finds equivalent states of AUTOMATON. */
5851 static void
5852 evaluate_equiv_classes (automaton_t automaton,
5853 VEC(state_t,heap) **equiv_classes)
5855 int new_equiv_class_num;
5856 int odd_iteration_flag;
5857 int finish_flag;
5858 VEC (state_t,heap) *next_iteration_classes;
5859 size_t i;
5861 all_achieved_states = VEC_alloc (state_t,heap, 1500);
5862 pass_states (automaton, add_achieved_state);
5863 pass_states (automaton, cache_presence);
5864 qsort (VEC_address (state_t, all_achieved_states),
5865 VEC_length (state_t, all_achieved_states),
5866 sizeof (state_t), compare_states_for_equiv);
5868 odd_iteration_flag = 0;
5869 new_equiv_class_num = init_equiv_class (all_achieved_states,
5870 &next_iteration_classes);
5874 odd_iteration_flag = !odd_iteration_flag;
5875 finish_flag = 1;
5876 copy_equiv_class (equiv_classes, next_iteration_classes);
5878 /* Transfer equiv numbers for the next iteration. */
5879 for (i = 0; i < VEC_length (state_t, all_achieved_states); i++)
5880 if (odd_iteration_flag)
5881 VEC_index (state_t, all_achieved_states, i)->equiv_class_num_2
5882 = VEC_index (state_t, all_achieved_states, i)->equiv_class_num_1;
5883 else
5884 VEC_index (state_t, all_achieved_states, i)->equiv_class_num_1
5885 = VEC_index (state_t, all_achieved_states, i)->equiv_class_num_2;
5887 for (i = 0; i < VEC_length (state_t, *equiv_classes); i++)
5888 if (partition_equiv_class (VEC_index (state_t, *equiv_classes, i),
5889 odd_iteration_flag,
5890 &next_iteration_classes,
5891 &new_equiv_class_num))
5892 finish_flag = 0;
5894 while (!finish_flag);
5895 VEC_free (state_t,heap, next_iteration_classes);
5896 VEC_free (state_t,heap, all_achieved_states);
5899 /* The function merges equivalent states of AUTOMATON. */
5900 static void
5901 merge_states (automaton_t automaton, VEC(state_t,heap) *equiv_classes)
5903 state_t curr_state;
5904 state_t new_state;
5905 state_t first_class_state;
5906 alt_state_t alt_states;
5907 alt_state_t alt_state, new_alt_state;
5908 arc_t curr_arc;
5909 arc_t next_arc;
5910 size_t i;
5912 /* Create states corresponding to equivalence classes containing two
5913 or more states. */
5914 for (i = 0; i < VEC_length (state_t, equiv_classes); i++)
5916 curr_state = VEC_index (state_t, equiv_classes, i);
5917 if (curr_state->next_equiv_class_state != NULL)
5919 /* There are more one states in the class equivalence. */
5920 /* Create new compound state. */
5921 new_state = get_free_state (0, automaton);
5922 alt_states = NULL;
5923 first_class_state = curr_state;
5924 for (curr_state = first_class_state;
5925 curr_state != NULL;
5926 curr_state = curr_state->next_equiv_class_state)
5928 curr_state->equiv_class_state = new_state;
5929 if (curr_state->component_states == NULL)
5931 new_alt_state = get_free_alt_state ();
5932 new_alt_state->state = curr_state;
5933 new_alt_state->next_alt_state = alt_states;
5934 alt_states = new_alt_state;
5936 else
5937 for (alt_state = curr_state->component_states;
5938 alt_state != NULL;
5939 alt_state = alt_state->next_sorted_alt_state)
5941 new_alt_state = get_free_alt_state ();
5942 new_alt_state->state = alt_state->state;
5943 new_alt_state->next_alt_state = alt_states;
5944 alt_states = new_alt_state;
5947 /* Its is important that alt states were sorted before and
5948 after merging to have the same querying results. */
5949 new_state->component_states = uniq_sort_alt_states (alt_states);
5951 else
5952 curr_state->equiv_class_state = curr_state;
5955 for (i = 0; i < VEC_length (state_t, equiv_classes); i++)
5957 curr_state = VEC_index (state_t, equiv_classes, i);
5958 if (curr_state->next_equiv_class_state != NULL)
5960 first_class_state = curr_state;
5961 /* Create new arcs output from the state corresponding to
5962 equiv class. */
5963 for (curr_arc = first_out_arc (first_class_state);
5964 curr_arc != NULL;
5965 curr_arc = next_out_arc (curr_arc))
5966 add_arc (first_class_state->equiv_class_state,
5967 curr_arc->to_state->equiv_class_state,
5968 curr_arc->insn);
5969 /* Delete output arcs from states of given class equivalence. */
5970 for (curr_state = first_class_state;
5971 curr_state != NULL;
5972 curr_state = curr_state->next_equiv_class_state)
5974 if (automaton->start_state == curr_state)
5975 automaton->start_state = curr_state->equiv_class_state;
5976 /* Delete the state and its output arcs. */
5977 for (curr_arc = first_out_arc (curr_state);
5978 curr_arc != NULL;
5979 curr_arc = next_arc)
5981 next_arc = next_out_arc (curr_arc);
5982 free_arc (curr_arc);
5986 else
5988 /* Change `to_state' of arcs output from the state of given
5989 equivalence class. */
5990 for (curr_arc = first_out_arc (curr_state);
5991 curr_arc != NULL;
5992 curr_arc = next_out_arc (curr_arc))
5993 curr_arc->to_state = curr_arc->to_state->equiv_class_state;
5998 /* The function sets up new_cycle_p for states if there is arc to the
5999 state marked by advance_cycle_insn_decl. */
6000 static void
6001 set_new_cycle_flags (state_t state)
6003 arc_t arc;
6005 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6006 if (arc->insn->insn_reserv_decl
6007 == DECL_INSN_RESERV (advance_cycle_insn_decl))
6008 arc->to_state->new_cycle_p = 1;
6011 /* The top level function for minimization of deterministic
6012 AUTOMATON. */
6013 static void
6014 minimize_DFA (automaton_t automaton)
6016 VEC(state_t,heap) *equiv_classes = 0;
6018 evaluate_equiv_classes (automaton, &equiv_classes);
6019 merge_states (automaton, equiv_classes);
6020 pass_states (automaton, set_new_cycle_flags);
6022 VEC_free (state_t,heap, equiv_classes);
6025 /* Values of two variables are counted number of states and arcs in an
6026 automaton. */
6027 static int curr_counted_states_num;
6028 static int curr_counted_arcs_num;
6030 /* The function is called by function `pass_states' to count states
6031 and arcs of an automaton. */
6032 static void
6033 incr_states_and_arcs_nums (state_t state)
6035 arc_t arc;
6037 curr_counted_states_num++;
6038 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6039 curr_counted_arcs_num++;
6042 /* The function counts states and arcs of AUTOMATON. */
6043 static void
6044 count_states_and_arcs (automaton_t automaton, int *states_num,
6045 int *arcs_num)
6047 curr_counted_states_num = 0;
6048 curr_counted_arcs_num = 0;
6049 pass_states (automaton, incr_states_and_arcs_nums);
6050 *states_num = curr_counted_states_num;
6051 *arcs_num = curr_counted_arcs_num;
6054 /* The function builds one DFA AUTOMATON for fast pipeline hazards
6055 recognition after checking and simplifying IR of the
6056 description. */
6057 static void
6058 build_automaton (automaton_t automaton)
6060 int states_num;
6061 int arcs_num;
6063 ticker_on (&NDFA_time);
6064 if (progress_flag)
6066 if (automaton->corresponding_automaton_decl == NULL)
6067 fprintf (stderr, "Create anonymous automaton");
6068 else
6069 fprintf (stderr, "Create automaton `%s'",
6070 automaton->corresponding_automaton_decl->name);
6071 fprintf (stderr, " (1 dot is 100 new states):");
6073 make_automaton (automaton);
6074 if (progress_flag)
6075 fprintf (stderr, " done\n");
6076 ticker_off (&NDFA_time);
6077 count_states_and_arcs (automaton, &states_num, &arcs_num);
6078 automaton->NDFA_states_num = states_num;
6079 automaton->NDFA_arcs_num = arcs_num;
6080 ticker_on (&NDFA_to_DFA_time);
6081 if (progress_flag)
6083 if (automaton->corresponding_automaton_decl == NULL)
6084 fprintf (stderr, "Make anonymous DFA");
6085 else
6086 fprintf (stderr, "Make DFA `%s'",
6087 automaton->corresponding_automaton_decl->name);
6088 fprintf (stderr, " (1 dot is 100 new states):");
6090 NDFA_to_DFA (automaton);
6091 if (progress_flag)
6092 fprintf (stderr, " done\n");
6093 ticker_off (&NDFA_to_DFA_time);
6094 count_states_and_arcs (automaton, &states_num, &arcs_num);
6095 automaton->DFA_states_num = states_num;
6096 automaton->DFA_arcs_num = arcs_num;
6097 if (!no_minimization_flag)
6099 ticker_on (&minimize_time);
6100 if (progress_flag)
6102 if (automaton->corresponding_automaton_decl == NULL)
6103 fprintf (stderr, "Minimize anonymous DFA...");
6104 else
6105 fprintf (stderr, "Minimize DFA `%s'...",
6106 automaton->corresponding_automaton_decl->name);
6108 minimize_DFA (automaton);
6109 if (progress_flag)
6110 fprintf (stderr, "done\n");
6111 ticker_off (&minimize_time);
6112 count_states_and_arcs (automaton, &states_num, &arcs_num);
6113 automaton->minimal_DFA_states_num = states_num;
6114 automaton->minimal_DFA_arcs_num = arcs_num;
6120 /* The page contains code for enumeration of all states of an automaton. */
6122 /* Variable used for enumeration of all states of an automaton. Its
6123 value is current number of automaton states. */
6124 static int curr_state_order_num;
6126 /* The function is called by function `pass_states' for enumerating
6127 states. */
6128 static void
6129 set_order_state_num (state_t state)
6131 state->order_state_num = curr_state_order_num;
6132 curr_state_order_num++;
6135 /* The function enumerates all states of AUTOMATON. */
6136 static void
6137 enumerate_states (automaton_t automaton)
6139 curr_state_order_num = 0;
6140 pass_states (automaton, set_order_state_num);
6141 automaton->achieved_states_num = curr_state_order_num;
6146 /* The page contains code for finding equivalent automaton insns
6147 (ainsns). */
6149 /* The function inserts AINSN into cyclic list
6150 CYCLIC_EQUIV_CLASS_INSN_LIST of ainsns. */
6151 static ainsn_t
6152 insert_ainsn_into_equiv_class (ainsn_t ainsn,
6153 ainsn_t cyclic_equiv_class_insn_list)
6155 if (cyclic_equiv_class_insn_list == NULL)
6156 ainsn->next_equiv_class_insn = ainsn;
6157 else
6159 ainsn->next_equiv_class_insn
6160 = cyclic_equiv_class_insn_list->next_equiv_class_insn;
6161 cyclic_equiv_class_insn_list->next_equiv_class_insn = ainsn;
6163 return ainsn;
6166 /* The function deletes equiv_class_insn into cyclic list of
6167 equivalent ainsns. */
6168 static void
6169 delete_ainsn_from_equiv_class (ainsn_t equiv_class_insn)
6171 ainsn_t curr_equiv_class_insn;
6172 ainsn_t prev_equiv_class_insn;
6174 prev_equiv_class_insn = equiv_class_insn;
6175 for (curr_equiv_class_insn = equiv_class_insn->next_equiv_class_insn;
6176 curr_equiv_class_insn != equiv_class_insn;
6177 curr_equiv_class_insn = curr_equiv_class_insn->next_equiv_class_insn)
6178 prev_equiv_class_insn = curr_equiv_class_insn;
6179 if (prev_equiv_class_insn != equiv_class_insn)
6180 prev_equiv_class_insn->next_equiv_class_insn
6181 = equiv_class_insn->next_equiv_class_insn;
6184 /* The function processes AINSN of a state in order to find equivalent
6185 ainsns. INSN_ARCS_ARRAY is table: code of insn -> out arc of the
6186 state. */
6187 static void
6188 process_insn_equiv_class (ainsn_t ainsn, arc_t *insn_arcs_array)
6190 ainsn_t next_insn;
6191 ainsn_t curr_insn;
6192 ainsn_t cyclic_insn_list;
6193 arc_t arc;
6195 gcc_assert (insn_arcs_array [ainsn->insn_reserv_decl->insn_num]);
6196 curr_insn = ainsn;
6197 /* New class of ainsns which are not equivalent to given ainsn. */
6198 cyclic_insn_list = NULL;
6201 next_insn = curr_insn->next_equiv_class_insn;
6202 arc = insn_arcs_array [curr_insn->insn_reserv_decl->insn_num];
6203 if (arc == NULL
6204 || (insn_arcs_array [ainsn->insn_reserv_decl->insn_num]->to_state
6205 != arc->to_state))
6207 delete_ainsn_from_equiv_class (curr_insn);
6208 cyclic_insn_list = insert_ainsn_into_equiv_class (curr_insn,
6209 cyclic_insn_list);
6211 curr_insn = next_insn;
6213 while (curr_insn != ainsn);
6216 /* The function processes STATE in order to find equivalent ainsns. */
6217 static void
6218 process_state_for_insn_equiv_partition (state_t state)
6220 arc_t arc;
6221 arc_t *insn_arcs_array = XCNEWVEC (arc_t, description->insns_num);
6223 /* Process insns of the arcs. */
6224 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6225 insn_arcs_array [arc->insn->insn_reserv_decl->insn_num] = arc;
6226 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6227 process_insn_equiv_class (arc->insn, insn_arcs_array);
6229 free (insn_arcs_array);
6232 /* The function searches for equivalent ainsns of AUTOMATON. */
6233 static void
6234 set_insn_equiv_classes (automaton_t automaton)
6236 ainsn_t ainsn;
6237 ainsn_t first_insn;
6238 ainsn_t curr_insn;
6239 ainsn_t cyclic_insn_list;
6240 ainsn_t insn_with_same_reservs;
6241 int equiv_classes_num;
6243 /* All insns are included in one equivalence class. */
6244 cyclic_insn_list = NULL;
6245 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6246 if (ainsn->first_insn_with_same_reservs)
6247 cyclic_insn_list = insert_ainsn_into_equiv_class (ainsn,
6248 cyclic_insn_list);
6249 /* Process insns in order to make equivalence partition. */
6250 pass_states (automaton, process_state_for_insn_equiv_partition);
6251 /* Enumerate equiv classes. */
6252 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6253 /* Set undefined value. */
6254 ainsn->insn_equiv_class_num = -1;
6255 equiv_classes_num = 0;
6256 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6257 if (ainsn->insn_equiv_class_num < 0)
6259 first_insn = ainsn;
6260 gcc_assert (first_insn->first_insn_with_same_reservs);
6261 first_insn->first_ainsn_with_given_equivalence_num = 1;
6262 curr_insn = first_insn;
6265 for (insn_with_same_reservs = curr_insn;
6266 insn_with_same_reservs != NULL;
6267 insn_with_same_reservs
6268 = insn_with_same_reservs->next_same_reservs_insn)
6269 insn_with_same_reservs->insn_equiv_class_num = equiv_classes_num;
6270 curr_insn = curr_insn->next_equiv_class_insn;
6272 while (curr_insn != first_insn);
6273 equiv_classes_num++;
6275 automaton->insn_equiv_classes_num = equiv_classes_num;
6280 /* This page contains code for creating DFA(s) and calls functions
6281 building them. */
6284 /* The following value is used to prevent floating point overflow for
6285 estimating an automaton bound. The value should be less DBL_MAX on
6286 the host machine. We use here approximate minimum of maximal
6287 double floating point value required by ANSI C standard. It
6288 will work for non ANSI sun compiler too. */
6290 #define MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND 1.0E37
6292 /* The function estimate size of the single DFA used by PHR (pipeline
6293 hazards recognizer). */
6294 static double
6295 estimate_one_automaton_bound (void)
6297 decl_t decl;
6298 double one_automaton_estimation_bound;
6299 double root_value;
6300 int i;
6302 one_automaton_estimation_bound = 1.0;
6303 for (i = 0; i < description->decls_num; i++)
6305 decl = description->decls [i];
6306 if (decl->mode == dm_unit)
6308 root_value = exp (log (DECL_UNIT (decl)->max_occ_cycle_num
6309 - DECL_UNIT (decl)->min_occ_cycle_num + 1.0)
6310 / automata_num);
6311 if (MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND / root_value
6312 > one_automaton_estimation_bound)
6313 one_automaton_estimation_bound *= root_value;
6316 return one_automaton_estimation_bound;
6319 /* The function compares unit declarations according to their maximal
6320 cycle in reservations. */
6321 static int
6322 compare_max_occ_cycle_nums (const void *unit_decl_1,
6323 const void *unit_decl_2)
6325 if ((DECL_UNIT (*(decl_t *) unit_decl_1)->max_occ_cycle_num)
6326 < (DECL_UNIT (*(decl_t *) unit_decl_2)->max_occ_cycle_num))
6327 return 1;
6328 else if ((DECL_UNIT (*(decl_t *) unit_decl_1)->max_occ_cycle_num)
6329 == (DECL_UNIT (*(decl_t *) unit_decl_2)->max_occ_cycle_num))
6330 return 0;
6331 else
6332 return -1;
6335 /* The function makes heuristic assigning automata to units. Actually
6336 efficacy of the algorithm has been checked yet??? */
6338 static void
6339 units_to_automata_heuristic_distr (void)
6341 double estimation_bound;
6342 int automaton_num;
6343 int rest_units_num;
6344 double bound_value;
6345 unit_decl_t *unit_decls;
6346 int i, j;
6348 if (description->units_num == 0)
6349 return;
6350 estimation_bound = estimate_one_automaton_bound ();
6351 unit_decls = XNEWVEC (unit_decl_t, description->units_num);
6353 for (i = 0, j = 0; i < description->decls_num; i++)
6354 if (description->decls[i]->mode == dm_unit)
6355 unit_decls[j++] = DECL_UNIT (description->decls[i]);
6356 gcc_assert (j == description->units_num);
6358 qsort (unit_decls, description->units_num,
6359 sizeof (unit_decl_t), compare_max_occ_cycle_nums);
6361 automaton_num = 0;
6362 bound_value = unit_decls[0]->max_occ_cycle_num;
6363 unit_decls[0]->corresponding_automaton_num = automaton_num;
6365 for (i = 1; i < description->units_num; i++)
6367 rest_units_num = description->units_num - i + 1;
6368 gcc_assert (automata_num - automaton_num - 1 <= rest_units_num);
6369 if (automaton_num < automata_num - 1
6370 && ((automata_num - automaton_num - 1 == rest_units_num)
6371 || (bound_value
6372 > (estimation_bound
6373 / unit_decls[i]->max_occ_cycle_num))))
6375 bound_value = unit_decls[i]->max_occ_cycle_num;
6376 automaton_num++;
6378 else
6379 bound_value *= unit_decls[i]->max_occ_cycle_num;
6380 unit_decls[i]->corresponding_automaton_num = automaton_num;
6382 gcc_assert (automaton_num == automata_num - 1);
6383 free (unit_decls);
6386 /* The functions creates automaton insns for each automata. Automaton
6387 insn is simply insn for given automaton which makes reservation
6388 only of units of the automaton. */
6389 static ainsn_t
6390 create_ainsns (void)
6392 decl_t decl;
6393 ainsn_t first_ainsn;
6394 ainsn_t curr_ainsn;
6395 ainsn_t prev_ainsn;
6396 int i;
6398 first_ainsn = NULL;
6399 prev_ainsn = NULL;
6400 for (i = 0; i < description->decls_num; i++)
6402 decl = description->decls [i];
6403 if (decl->mode == dm_insn_reserv)
6405 curr_ainsn = create_node (sizeof (struct ainsn));
6406 curr_ainsn->insn_reserv_decl = DECL_INSN_RESERV (decl);
6407 curr_ainsn->important_p = FALSE;
6408 curr_ainsn->next_ainsn = NULL;
6409 if (prev_ainsn == NULL)
6410 first_ainsn = curr_ainsn;
6411 else
6412 prev_ainsn->next_ainsn = curr_ainsn;
6413 prev_ainsn = curr_ainsn;
6416 return first_ainsn;
6419 /* The function assigns automata to units according to constructions
6420 `define_automaton' in the description. */
6421 static void
6422 units_to_automata_distr (void)
6424 decl_t decl;
6425 int i;
6427 for (i = 0; i < description->decls_num; i++)
6429 decl = description->decls [i];
6430 if (decl->mode == dm_unit)
6432 if (DECL_UNIT (decl)->automaton_decl == NULL
6433 || (DECL_UNIT (decl)->automaton_decl->corresponding_automaton
6434 == NULL))
6435 /* Distribute to the first automaton. */
6436 DECL_UNIT (decl)->corresponding_automaton_num = 0;
6437 else
6438 DECL_UNIT (decl)->corresponding_automaton_num
6439 = (DECL_UNIT (decl)->automaton_decl
6440 ->corresponding_automaton->automaton_order_num);
6445 /* The function creates DFA(s) for fast pipeline hazards recognition
6446 after checking and simplifying IR of the description. */
6447 static void
6448 create_automata (void)
6450 automaton_t curr_automaton;
6451 automaton_t prev_automaton;
6452 decl_t decl;
6453 int curr_automaton_num;
6454 int i;
6456 if (automata_num != 0)
6458 units_to_automata_heuristic_distr ();
6459 for (prev_automaton = NULL, curr_automaton_num = 0;
6460 curr_automaton_num < automata_num;
6461 curr_automaton_num++, prev_automaton = curr_automaton)
6463 curr_automaton = create_node (sizeof (struct automaton));
6464 curr_automaton->ainsn_list = create_ainsns ();
6465 curr_automaton->corresponding_automaton_decl = NULL;
6466 curr_automaton->next_automaton = NULL;
6467 curr_automaton->automaton_order_num = curr_automaton_num;
6468 if (prev_automaton == NULL)
6469 description->first_automaton = curr_automaton;
6470 else
6471 prev_automaton->next_automaton = curr_automaton;
6474 else
6476 curr_automaton_num = 0;
6477 prev_automaton = NULL;
6478 for (i = 0; i < description->decls_num; i++)
6480 decl = description->decls [i];
6481 if (decl->mode == dm_automaton
6482 && DECL_AUTOMATON (decl)->automaton_is_used)
6484 curr_automaton = create_node (sizeof (struct automaton));
6485 curr_automaton->ainsn_list = create_ainsns ();
6486 curr_automaton->corresponding_automaton_decl
6487 = DECL_AUTOMATON (decl);
6488 curr_automaton->next_automaton = NULL;
6489 DECL_AUTOMATON (decl)->corresponding_automaton = curr_automaton;
6490 curr_automaton->automaton_order_num = curr_automaton_num;
6491 if (prev_automaton == NULL)
6492 description->first_automaton = curr_automaton;
6493 else
6494 prev_automaton->next_automaton = curr_automaton;
6495 curr_automaton_num++;
6496 prev_automaton = curr_automaton;
6499 if (curr_automaton_num == 0)
6501 curr_automaton = create_node (sizeof (struct automaton));
6502 curr_automaton->ainsn_list = create_ainsns ();
6503 curr_automaton->corresponding_automaton_decl = NULL;
6504 curr_automaton->next_automaton = NULL;
6505 description->first_automaton = curr_automaton;
6507 units_to_automata_distr ();
6509 NDFA_time = create_ticker ();
6510 ticker_off (&NDFA_time);
6511 NDFA_to_DFA_time = create_ticker ();
6512 ticker_off (&NDFA_to_DFA_time);
6513 minimize_time = create_ticker ();
6514 ticker_off (&minimize_time);
6515 equiv_time = create_ticker ();
6516 ticker_off (&equiv_time);
6517 for (curr_automaton = description->first_automaton;
6518 curr_automaton != NULL;
6519 curr_automaton = curr_automaton->next_automaton)
6521 if (progress_flag)
6523 if (curr_automaton->corresponding_automaton_decl == NULL)
6524 fprintf (stderr, "Prepare anonymous automaton creation ... ");
6525 else
6526 fprintf (stderr, "Prepare automaton `%s' creation...",
6527 curr_automaton->corresponding_automaton_decl->name);
6529 create_alt_states (curr_automaton);
6530 form_ainsn_with_same_reservs (curr_automaton);
6531 if (progress_flag)
6532 fprintf (stderr, "done\n");
6533 build_automaton (curr_automaton);
6534 enumerate_states (curr_automaton);
6535 ticker_on (&equiv_time);
6536 set_insn_equiv_classes (curr_automaton);
6537 ticker_off (&equiv_time);
6543 /* This page contains code for forming string representation of
6544 regexp. The representation is formed on IR obstack. So you should
6545 not work with IR obstack between regexp_representation and
6546 finish_regexp_representation calls. */
6548 /* This recursive function forms string representation of regexp
6549 (without tailing '\0'). */
6550 static void
6551 form_regexp (regexp_t regexp)
6553 int i;
6555 switch (regexp->mode)
6557 case rm_unit: case rm_reserv:
6559 const char *name = (regexp->mode == rm_unit
6560 ? REGEXP_UNIT (regexp)->name
6561 : REGEXP_RESERV (regexp)->name);
6563 obstack_grow (&irp, name, strlen (name));
6564 break;
6567 case rm_sequence:
6568 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
6570 if (i != 0)
6571 obstack_1grow (&irp, ',');
6572 form_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
6574 break;
6576 case rm_allof:
6577 obstack_1grow (&irp, '(');
6578 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
6580 if (i != 0)
6581 obstack_1grow (&irp, '+');
6582 if (REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_sequence
6583 || REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_oneof)
6584 obstack_1grow (&irp, '(');
6585 form_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
6586 if (REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_sequence
6587 || REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_oneof)
6588 obstack_1grow (&irp, ')');
6590 obstack_1grow (&irp, ')');
6591 break;
6593 case rm_oneof:
6594 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
6596 if (i != 0)
6597 obstack_1grow (&irp, '|');
6598 if (REGEXP_ONEOF (regexp)->regexps[i]->mode == rm_sequence)
6599 obstack_1grow (&irp, '(');
6600 form_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
6601 if (REGEXP_ONEOF (regexp)->regexps[i]->mode == rm_sequence)
6602 obstack_1grow (&irp, ')');
6604 break;
6606 case rm_repeat:
6608 char digits [30];
6610 if (REGEXP_REPEAT (regexp)->regexp->mode == rm_sequence
6611 || REGEXP_REPEAT (regexp)->regexp->mode == rm_allof
6612 || REGEXP_REPEAT (regexp)->regexp->mode == rm_oneof)
6613 obstack_1grow (&irp, '(');
6614 form_regexp (REGEXP_REPEAT (regexp)->regexp);
6615 if (REGEXP_REPEAT (regexp)->regexp->mode == rm_sequence
6616 || REGEXP_REPEAT (regexp)->regexp->mode == rm_allof
6617 || REGEXP_REPEAT (regexp)->regexp->mode == rm_oneof)
6618 obstack_1grow (&irp, ')');
6619 sprintf (digits, "*%d", REGEXP_REPEAT (regexp)->repeat_num);
6620 obstack_grow (&irp, digits, strlen (digits));
6621 break;
6624 case rm_nothing:
6625 obstack_grow (&irp, NOTHING_NAME, strlen (NOTHING_NAME));
6626 break;
6628 default:
6629 gcc_unreachable ();
6633 /* The function returns string representation of REGEXP on IR
6634 obstack. */
6635 static const char *
6636 regexp_representation (regexp_t regexp)
6638 form_regexp (regexp);
6639 obstack_1grow (&irp, '\0');
6640 return obstack_base (&irp);
6643 /* The function frees memory allocated for last formed string
6644 representation of regexp. */
6645 static void
6646 finish_regexp_representation (void)
6648 int length = obstack_object_size (&irp);
6650 obstack_blank_fast (&irp, -length);
6655 /* This page contains code for output PHR (pipeline hazards recognizer). */
6657 /* The function outputs minimal C type which is sufficient for
6658 representation numbers in range min_range_value and
6659 max_range_value. Because host machine and build machine may be
6660 different, we use here minimal values required by ANSI C standard
6661 instead of UCHAR_MAX, SHRT_MAX, SHRT_MIN, etc. This is a good
6662 approximation. */
6664 static void
6665 output_range_type (FILE *f, long int min_range_value,
6666 long int max_range_value)
6668 if (min_range_value >= 0 && max_range_value <= 255)
6669 fprintf (f, "unsigned char");
6670 else if (min_range_value >= -127 && max_range_value <= 127)
6671 fprintf (f, "signed char");
6672 else if (min_range_value >= 0 && max_range_value <= 65535)
6673 fprintf (f, "unsigned short");
6674 else if (min_range_value >= -32767 && max_range_value <= 32767)
6675 fprintf (f, "short");
6676 else
6677 fprintf (f, "int");
6680 /* The following macro value is used as value of member
6681 `longest_path_length' of state when we are processing path and the
6682 state on the path. */
6684 #define ON_THE_PATH -2
6686 /* The following recursive function searches for the length of the
6687 longest path starting from STATE which does not contain cycles and
6688 `cycle advance' arcs. */
6690 static int
6691 longest_path_length (state_t state)
6693 arc_t arc;
6694 int length, result;
6696 if (state->longest_path_length != UNDEFINED_LONGEST_PATH_LENGTH)
6698 /* We don't expect the path cycle here. Our graph may contain
6699 only cycles with one state on the path not containing `cycle
6700 advance' arcs -- see comment below. */
6701 gcc_assert (state->longest_path_length != ON_THE_PATH);
6703 /* We already visited the state. */
6704 return state->longest_path_length;
6707 result = 0;
6708 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6709 /* Ignore cycles containing one state and `cycle advance' arcs. */
6710 if (arc->to_state != state
6711 && (arc->insn->insn_reserv_decl
6712 != DECL_INSN_RESERV (advance_cycle_insn_decl)))
6714 length = longest_path_length (arc->to_state);
6715 if (length > result)
6716 result = length;
6718 state->longest_path_length = result + 1;
6719 return result;
6722 /* The function outputs all initialization values of VECT. */
6723 static void
6724 output_vect (vla_hwint_t vect)
6726 int els_on_line;
6727 size_t vect_length = VEC_length (vect_el_t, vect);
6728 size_t i;
6730 els_on_line = 1;
6731 if (vect_length == 0)
6732 fputs ("0 /* This is dummy el because the vect is empty */", output_file);
6733 else
6734 for (i = 0; i < vect_length; i++)
6736 fprintf (output_file, "%5ld", (long) VEC_index (vect_el_t, vect, i));
6737 if (els_on_line == 10)
6739 els_on_line = 0;
6740 fputs (",\n", output_file);
6742 else if (i < vect_length-1)
6743 fputs (", ", output_file);
6744 els_on_line++;
6748 /* The following is name of the structure which represents DFA(s) for
6749 PHR. */
6750 #define CHIP_NAME "DFA_chip"
6752 /* The following is name of member which represents state of a DFA for
6753 PHR. */
6754 static void
6755 output_chip_member_name (FILE *f, automaton_t automaton)
6757 if (automaton->corresponding_automaton_decl == NULL)
6758 fprintf (f, "automaton_state_%d", automaton->automaton_order_num);
6759 else
6760 fprintf (f, "%s_automaton_state",
6761 automaton->corresponding_automaton_decl->name);
6764 /* The following is name of temporary variable which stores state of a
6765 DFA for PHR. */
6766 static void
6767 output_temp_chip_member_name (FILE *f, automaton_t automaton)
6769 fprintf (f, "_");
6770 output_chip_member_name (f, automaton);
6773 /* This is name of macro value which is code of pseudo_insn
6774 representing advancing cpu cycle. Its value is used as internal
6775 code unknown insn. */
6776 #define ADVANCE_CYCLE_VALUE_NAME "DFA__ADVANCE_CYCLE"
6778 /* Output name of translate vector for given automaton. */
6779 static void
6780 output_translate_vect_name (FILE *f, automaton_t automaton)
6782 if (automaton->corresponding_automaton_decl == NULL)
6783 fprintf (f, "translate_%d", automaton->automaton_order_num);
6784 else
6785 fprintf (f, "%s_translate", automaton->corresponding_automaton_decl->name);
6788 /* Output name for simple transition table representation. */
6789 static void
6790 output_trans_full_vect_name (FILE *f, automaton_t automaton)
6792 if (automaton->corresponding_automaton_decl == NULL)
6793 fprintf (f, "transitions_%d", automaton->automaton_order_num);
6794 else
6795 fprintf (f, "%s_transitions",
6796 automaton->corresponding_automaton_decl->name);
6799 /* Output name of comb vector of the transition table for given
6800 automaton. */
6801 static void
6802 output_trans_comb_vect_name (FILE *f, automaton_t automaton)
6804 if (automaton->corresponding_automaton_decl == NULL)
6805 fprintf (f, "transitions_%d", automaton->automaton_order_num);
6806 else
6807 fprintf (f, "%s_transitions",
6808 automaton->corresponding_automaton_decl->name);
6811 /* Output name of check vector of the transition table for given
6812 automaton. */
6813 static void
6814 output_trans_check_vect_name (FILE *f, automaton_t automaton)
6816 if (automaton->corresponding_automaton_decl == NULL)
6817 fprintf (f, "check_%d", automaton->automaton_order_num);
6818 else
6819 fprintf (f, "%s_check", automaton->corresponding_automaton_decl->name);
6822 /* Output name of base vector of the transition table for given
6823 automaton. */
6824 static void
6825 output_trans_base_vect_name (FILE *f, automaton_t automaton)
6827 if (automaton->corresponding_automaton_decl == NULL)
6828 fprintf (f, "base_%d", automaton->automaton_order_num);
6829 else
6830 fprintf (f, "%s_base", automaton->corresponding_automaton_decl->name);
6833 /* Output name of simple min issue delay table representation. */
6834 static void
6835 output_min_issue_delay_vect_name (FILE *f, automaton_t automaton)
6837 if (automaton->corresponding_automaton_decl == NULL)
6838 fprintf (f, "min_issue_delay_%d", automaton->automaton_order_num);
6839 else
6840 fprintf (f, "%s_min_issue_delay",
6841 automaton->corresponding_automaton_decl->name);
6844 /* Output name of deadlock vector for given automaton. */
6845 static void
6846 output_dead_lock_vect_name (FILE *f, automaton_t automaton)
6848 if (automaton->corresponding_automaton_decl == NULL)
6849 fprintf (f, "dead_lock_%d", automaton->automaton_order_num);
6850 else
6851 fprintf (f, "%s_dead_lock", automaton->corresponding_automaton_decl->name);
6854 /* Output name of reserved units table for AUTOMATON into file F. */
6855 static void
6856 output_reserved_units_table_name (FILE *f, automaton_t automaton)
6858 if (automaton->corresponding_automaton_decl == NULL)
6859 fprintf (f, "reserved_units_%d", automaton->automaton_order_num);
6860 else
6861 fprintf (f, "%s_reserved_units",
6862 automaton->corresponding_automaton_decl->name);
6865 /* Name of the PHR interface macro. */
6866 #define CPU_UNITS_QUERY_MACRO_NAME "CPU_UNITS_QUERY"
6868 /* Names of an internal functions: */
6869 #define INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME "internal_min_issue_delay"
6871 /* This is external type of DFA(s) state. */
6872 #define STATE_TYPE_NAME "state_t"
6874 #define INTERNAL_TRANSITION_FUNC_NAME "internal_state_transition"
6876 #define INTERNAL_RESET_FUNC_NAME "internal_reset"
6878 #define INTERNAL_DEAD_LOCK_FUNC_NAME "internal_state_dead_lock_p"
6880 #define INTERNAL_INSN_LATENCY_FUNC_NAME "internal_insn_latency"
6882 /* Name of cache of insn dfa codes. */
6883 #define DFA_INSN_CODES_VARIABLE_NAME "dfa_insn_codes"
6885 /* Name of length of cache of insn dfa codes. */
6886 #define DFA_INSN_CODES_LENGTH_VARIABLE_NAME "dfa_insn_codes_length"
6888 /* Names of the PHR interface functions: */
6889 #define SIZE_FUNC_NAME "state_size"
6891 #define TRANSITION_FUNC_NAME "state_transition"
6893 #define MIN_ISSUE_DELAY_FUNC_NAME "min_issue_delay"
6895 #define MIN_INSN_CONFLICT_DELAY_FUNC_NAME "min_insn_conflict_delay"
6897 #define DEAD_LOCK_FUNC_NAME "state_dead_lock_p"
6899 #define RESET_FUNC_NAME "state_reset"
6901 #define INSN_LATENCY_FUNC_NAME "insn_latency"
6903 #define PRINT_RESERVATION_FUNC_NAME "print_reservation"
6905 #define GET_CPU_UNIT_CODE_FUNC_NAME "get_cpu_unit_code"
6907 #define CPU_UNIT_RESERVATION_P_FUNC_NAME "cpu_unit_reservation_p"
6909 #define DFA_CLEAN_INSN_CACHE_FUNC_NAME "dfa_clean_insn_cache"
6911 #define DFA_CLEAR_SINGLE_INSN_CACHE_FUNC_NAME "dfa_clear_single_insn_cache"
6913 #define DFA_START_FUNC_NAME "dfa_start"
6915 #define DFA_FINISH_FUNC_NAME "dfa_finish"
6917 /* Names of parameters of the PHR interface functions. */
6918 #define STATE_NAME "state"
6920 #define INSN_PARAMETER_NAME "insn"
6922 #define INSN2_PARAMETER_NAME "insn2"
6924 #define CHIP_PARAMETER_NAME "chip"
6926 #define FILE_PARAMETER_NAME "f"
6928 #define CPU_UNIT_NAME_PARAMETER_NAME "cpu_unit_name"
6930 #define CPU_CODE_PARAMETER_NAME "cpu_unit_code"
6932 /* Names of the variables whose values are internal insn code of rtx
6933 insn. */
6934 #define INTERNAL_INSN_CODE_NAME "insn_code"
6936 #define INTERNAL_INSN2_CODE_NAME "insn2_code"
6938 /* Names of temporary variables in some functions. */
6939 #define TEMPORARY_VARIABLE_NAME "temp"
6941 #define I_VARIABLE_NAME "i"
6943 /* Name of result variable in some functions. */
6944 #define RESULT_VARIABLE_NAME "res"
6946 /* Name of function (attribute) to translate insn into internal insn
6947 code. */
6948 #define INTERNAL_DFA_INSN_CODE_FUNC_NAME "internal_dfa_insn_code"
6950 /* Name of function (attribute) to translate insn into internal insn
6951 code with caching. */
6952 #define DFA_INSN_CODE_FUNC_NAME "dfa_insn_code"
6954 /* Output C type which is used for representation of codes of states
6955 of AUTOMATON. */
6956 static void
6957 output_state_member_type (FILE *f, automaton_t automaton)
6959 output_range_type (f, 0, automaton->achieved_states_num);
6962 /* Output definition of the structure representing current DFA(s)
6963 state(s). */
6964 static void
6965 output_chip_definitions (void)
6967 automaton_t automaton;
6969 fprintf (output_file, "struct %s\n{\n", CHIP_NAME);
6970 for (automaton = description->first_automaton;
6971 automaton != NULL;
6972 automaton = automaton->next_automaton)
6974 fprintf (output_file, " ");
6975 output_state_member_type (output_file, automaton);
6976 fprintf (output_file, " ");
6977 output_chip_member_name (output_file, automaton);
6978 fprintf (output_file, ";\n");
6980 fprintf (output_file, "};\n\n");
6981 #if 0
6982 fprintf (output_file, "static struct %s %s;\n\n", CHIP_NAME, CHIP_NAME);
6983 #endif
6987 /* The function outputs translate vector of internal insn code into
6988 insn equivalence class number. The equivalence class number is
6989 used to access to table and vectors representing DFA(s). */
6990 static void
6991 output_translate_vect (automaton_t automaton)
6993 ainsn_t ainsn;
6994 int insn_value;
6995 vla_hwint_t translate_vect;
6997 translate_vect = VEC_alloc (vect_el_t,heap, description->insns_num);
6999 for (insn_value = 0; insn_value < description->insns_num; insn_value++)
7000 /* Undefined value */
7001 VEC_quick_push (vect_el_t, translate_vect,
7002 automaton->insn_equiv_classes_num);
7004 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
7005 VEC_replace (vect_el_t, translate_vect,
7006 ainsn->insn_reserv_decl->insn_num,
7007 ainsn->insn_equiv_class_num);
7009 fprintf (output_file,
7010 "/* Vector translating external insn codes to internal ones.*/\n");
7011 fprintf (output_file, "static const ");
7012 output_range_type (output_file, 0, automaton->insn_equiv_classes_num);
7013 fprintf (output_file, " ");
7014 output_translate_vect_name (output_file, automaton);
7015 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7016 output_vect (translate_vect);
7017 fprintf (output_file, "};\n\n");
7018 VEC_free (vect_el_t,heap, translate_vect);
7021 /* The value in a table state x ainsn -> something which represents
7022 undefined value. */
7023 static int undefined_vect_el_value;
7025 /* The following function returns nonzero value if the best
7026 representation of the table is comb vector. */
7027 static int
7028 comb_vect_p (state_ainsn_table_t tab)
7030 return (2 * VEC_length (vect_el_t, tab->full_vect)
7031 > 5 * VEC_length (vect_el_t, tab->comb_vect));
7034 /* The following function creates new table for AUTOMATON. */
7035 static state_ainsn_table_t
7036 create_state_ainsn_table (automaton_t automaton)
7038 state_ainsn_table_t tab;
7039 int full_vect_length;
7040 int i;
7042 tab = create_node (sizeof (struct state_ainsn_table));
7043 tab->automaton = automaton;
7045 tab->comb_vect = VEC_alloc (vect_el_t,heap, 10000);
7046 tab->check_vect = VEC_alloc (vect_el_t,heap, 10000);
7048 tab->base_vect = 0;
7049 VEC_safe_grow (vect_el_t,heap, tab->base_vect,
7050 automaton->achieved_states_num);
7052 full_vect_length = (automaton->insn_equiv_classes_num
7053 * automaton->achieved_states_num);
7054 tab->full_vect = VEC_alloc (vect_el_t,heap, full_vect_length);
7055 for (i = 0; i < full_vect_length; i++)
7056 VEC_quick_push (vect_el_t, tab->full_vect, undefined_vect_el_value);
7058 tab->min_base_vect_el_value = 0;
7059 tab->max_base_vect_el_value = 0;
7060 tab->min_comb_vect_el_value = 0;
7061 tab->max_comb_vect_el_value = 0;
7062 return tab;
7065 /* The following function outputs the best C representation of the
7066 table TAB of given TABLE_NAME. */
7067 static void
7068 output_state_ainsn_table (state_ainsn_table_t tab, const char *table_name,
7069 void (*output_full_vect_name_func) (FILE *, automaton_t),
7070 void (*output_comb_vect_name_func) (FILE *, automaton_t),
7071 void (*output_check_vect_name_func) (FILE *, automaton_t),
7072 void (*output_base_vect_name_func) (FILE *, automaton_t))
7074 if (!comb_vect_p (tab))
7076 fprintf (output_file, "/* Vector for %s. */\n", table_name);
7077 fprintf (output_file, "static const ");
7078 output_range_type (output_file, tab->min_comb_vect_el_value,
7079 tab->max_comb_vect_el_value);
7080 fprintf (output_file, " ");
7081 (*output_full_vect_name_func) (output_file, tab->automaton);
7082 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7083 output_vect (tab->full_vect);
7084 fprintf (output_file, "};\n\n");
7086 else
7088 fprintf (output_file, "/* Comb vector for %s. */\n", table_name);
7089 fprintf (output_file, "static const ");
7090 output_range_type (output_file, tab->min_comb_vect_el_value,
7091 tab->max_comb_vect_el_value);
7092 fprintf (output_file, " ");
7093 (*output_comb_vect_name_func) (output_file, tab->automaton);
7094 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7095 output_vect (tab->comb_vect);
7096 fprintf (output_file, "};\n\n");
7097 fprintf (output_file, "/* Check vector for %s. */\n", table_name);
7098 fprintf (output_file, "static const ");
7099 output_range_type (output_file, 0, tab->automaton->achieved_states_num);
7100 fprintf (output_file, " ");
7101 (*output_check_vect_name_func) (output_file, tab->automaton);
7102 fprintf (output_file, "[] = {\n");
7103 output_vect (tab->check_vect);
7104 fprintf (output_file, "};\n\n");
7105 fprintf (output_file, "/* Base vector for %s. */\n", table_name);
7106 fprintf (output_file, "static const ");
7107 output_range_type (output_file, tab->min_base_vect_el_value,
7108 tab->max_base_vect_el_value);
7109 fprintf (output_file, " ");
7110 (*output_base_vect_name_func) (output_file, tab->automaton);
7111 fprintf (output_file, "[] = {\n");
7112 output_vect (tab->base_vect);
7113 fprintf (output_file, "};\n\n");
7117 /* The following function adds vector VECT to table TAB as its line
7118 with number VECT_NUM. */
7119 static void
7120 add_vect (state_ainsn_table_t tab, int vect_num, vla_hwint_t vect)
7122 int vect_length;
7123 size_t real_vect_length;
7124 int comb_vect_index;
7125 int comb_vect_els_num;
7126 int vect_index;
7127 int first_unempty_vect_index;
7128 int additional_els_num;
7129 int no_state_value;
7130 vect_el_t vect_el;
7131 int i;
7132 unsigned long vect_mask, comb_vect_mask;
7134 vect_length = VEC_length (vect_el_t, vect);
7135 gcc_assert (vect_length);
7136 gcc_assert (VEC_last (vect_el_t, vect) != undefined_vect_el_value);
7137 real_vect_length = tab->automaton->insn_equiv_classes_num;
7138 /* Form full vector in the table: */
7140 size_t full_base = tab->automaton->insn_equiv_classes_num * vect_num;
7141 if (VEC_length (vect_el_t, tab->full_vect) < full_base + vect_length)
7142 VEC_safe_grow (vect_el_t,heap, tab->full_vect,
7143 full_base + vect_length);
7144 for (i = 0; i < vect_length; i++)
7145 VEC_replace (vect_el_t, tab->full_vect, full_base + i,
7146 VEC_index (vect_el_t, vect, i));
7148 /* Form comb vector in the table: */
7149 gcc_assert (VEC_length (vect_el_t, tab->comb_vect)
7150 == VEC_length (vect_el_t, tab->check_vect));
7152 comb_vect_els_num = VEC_length (vect_el_t, tab->comb_vect);
7153 for (first_unempty_vect_index = 0;
7154 first_unempty_vect_index < vect_length;
7155 first_unempty_vect_index++)
7156 if (VEC_index (vect_el_t, vect, first_unempty_vect_index)
7157 != undefined_vect_el_value)
7158 break;
7160 /* Search for the place in comb vect for the inserted vect. */
7162 /* Slow case. */
7163 if (vect_length - first_unempty_vect_index >= SIZEOF_LONG * CHAR_BIT)
7165 for (comb_vect_index = 0;
7166 comb_vect_index < comb_vect_els_num;
7167 comb_vect_index++)
7169 for (vect_index = first_unempty_vect_index;
7170 vect_index < vect_length
7171 && vect_index + comb_vect_index < comb_vect_els_num;
7172 vect_index++)
7173 if (VEC_index (vect_el_t, vect, vect_index)
7174 != undefined_vect_el_value
7175 && (VEC_index (vect_el_t, tab->comb_vect,
7176 vect_index + comb_vect_index)
7177 != undefined_vect_el_value))
7178 break;
7179 if (vect_index >= vect_length
7180 || vect_index + comb_vect_index >= comb_vect_els_num)
7181 break;
7183 goto found;
7186 /* Fast case. */
7187 vect_mask = 0;
7188 for (vect_index = first_unempty_vect_index;
7189 vect_index < vect_length;
7190 vect_index++)
7192 vect_mask = vect_mask << 1;
7193 if (VEC_index (vect_el_t, vect, vect_index) != undefined_vect_el_value)
7194 vect_mask |= 1;
7197 /* Search for the place in comb vect for the inserted vect. */
7198 comb_vect_index = 0;
7199 if (comb_vect_els_num == 0)
7200 goto found;
7202 comb_vect_mask = 0;
7203 for (vect_index = first_unempty_vect_index;
7204 vect_index < vect_length && vect_index < comb_vect_els_num;
7205 vect_index++)
7207 comb_vect_mask <<= 1;
7208 if (vect_index + comb_vect_index < comb_vect_els_num
7209 && VEC_index (vect_el_t, tab->comb_vect, vect_index + comb_vect_index)
7210 != undefined_vect_el_value)
7211 comb_vect_mask |= 1;
7213 if ((vect_mask & comb_vect_mask) == 0)
7214 goto found;
7216 for (comb_vect_index = 1, i = vect_length; i < comb_vect_els_num;
7217 comb_vect_index++, i++)
7219 comb_vect_mask = (comb_vect_mask << 1) | 1;
7220 comb_vect_mask ^= (VEC_index (vect_el_t, tab->comb_vect, i)
7221 == undefined_vect_el_value);
7222 if ((vect_mask & comb_vect_mask) == 0)
7223 goto found;
7225 for ( ; comb_vect_index < comb_vect_els_num; comb_vect_index++)
7227 comb_vect_mask <<= 1;
7228 if ((vect_mask & comb_vect_mask) == 0)
7229 goto found;
7232 found:
7233 /* Slot was found. */
7234 additional_els_num = comb_vect_index + real_vect_length - comb_vect_els_num;
7235 if (additional_els_num < 0)
7236 additional_els_num = 0;
7237 /* Expand comb and check vectors. */
7238 vect_el = undefined_vect_el_value;
7239 no_state_value = tab->automaton->achieved_states_num;
7240 while (additional_els_num > 0)
7242 VEC_safe_push (vect_el_t,heap, tab->comb_vect, vect_el);
7243 VEC_safe_push (vect_el_t,heap, tab->check_vect, no_state_value);
7244 additional_els_num--;
7246 gcc_assert (VEC_length (vect_el_t, tab->comb_vect)
7247 >= comb_vect_index + real_vect_length);
7248 /* Fill comb and check vectors. */
7249 for (vect_index = 0; vect_index < vect_length; vect_index++)
7250 if (VEC_index (vect_el_t, vect, vect_index) != undefined_vect_el_value)
7252 vect_el_t x = VEC_index (vect_el_t, vect, vect_index);
7253 gcc_assert (VEC_index (vect_el_t, tab->comb_vect,
7254 comb_vect_index + vect_index)
7255 == undefined_vect_el_value);
7256 gcc_assert (x >= 0);
7257 if (tab->max_comb_vect_el_value < x)
7258 tab->max_comb_vect_el_value = x;
7259 if (tab->min_comb_vect_el_value > x)
7260 tab->min_comb_vect_el_value = x;
7261 VEC_replace (vect_el_t, tab->comb_vect,
7262 comb_vect_index + vect_index, x);
7263 VEC_replace (vect_el_t, tab->check_vect,
7264 comb_vect_index + vect_index, vect_num);
7266 if (tab->max_comb_vect_el_value < undefined_vect_el_value)
7267 tab->max_comb_vect_el_value = undefined_vect_el_value;
7268 if (tab->min_comb_vect_el_value > undefined_vect_el_value)
7269 tab->min_comb_vect_el_value = undefined_vect_el_value;
7270 if (tab->max_base_vect_el_value < comb_vect_index)
7271 tab->max_base_vect_el_value = comb_vect_index;
7272 if (tab->min_base_vect_el_value > comb_vect_index)
7273 tab->min_base_vect_el_value = comb_vect_index;
7275 VEC_replace (vect_el_t, tab->base_vect, vect_num, comb_vect_index);
7278 /* Return number of out arcs of STATE. */
7279 static int
7280 out_state_arcs_num (state_t state)
7282 int result;
7283 arc_t arc;
7285 result = 0;
7286 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
7288 gcc_assert (arc->insn);
7289 if (arc->insn->first_ainsn_with_given_equivalence_num)
7290 result++;
7292 return result;
7295 /* Compare number of possible transitions from the states. */
7296 static int
7297 compare_transition_els_num (const void *state_ptr_1,
7298 const void *state_ptr_2)
7300 int transition_els_num_1;
7301 int transition_els_num_2;
7303 transition_els_num_1 = out_state_arcs_num (*(state_t *) state_ptr_1);
7304 transition_els_num_2 = out_state_arcs_num (*(state_t *) state_ptr_2);
7305 if (transition_els_num_1 < transition_els_num_2)
7306 return 1;
7307 else if (transition_els_num_1 == transition_els_num_2)
7308 return 0;
7309 else
7310 return -1;
7313 /* The function adds element EL_VALUE to vector VECT for a table state
7314 x AINSN. */
7315 static void
7316 add_vect_el (vla_hwint_t *vect, ainsn_t ainsn, int el_value)
7318 int equiv_class_num;
7319 int vect_index;
7321 gcc_assert (ainsn);
7322 equiv_class_num = ainsn->insn_equiv_class_num;
7323 for (vect_index = VEC_length (vect_el_t, *vect);
7324 vect_index <= equiv_class_num;
7325 vect_index++)
7326 VEC_safe_push (vect_el_t,heap, *vect, undefined_vect_el_value);
7327 VEC_replace (vect_el_t, *vect, equiv_class_num, el_value);
7330 /* This is for forming vector of states of an automaton. */
7331 static VEC(state_t,heap) *output_states_vect;
7333 /* The function is called by function pass_states. The function adds
7334 STATE to `output_states_vect'. */
7335 static void
7336 add_states_vect_el (state_t state)
7338 VEC_safe_push (state_t,heap, output_states_vect, state);
7341 /* Form and output vectors (comb, check, base or full vector)
7342 representing transition table of AUTOMATON. */
7343 static void
7344 output_trans_table (automaton_t automaton)
7346 size_t i;
7347 arc_t arc;
7348 vla_hwint_t transition_vect = 0;
7350 undefined_vect_el_value = automaton->achieved_states_num;
7351 automaton->trans_table = create_state_ainsn_table (automaton);
7352 /* Create vect of pointers to states ordered by num of transitions
7353 from the state (state with the maximum num is the first). */
7354 output_states_vect = 0;
7355 pass_states (automaton, add_states_vect_el);
7356 qsort (VEC_address (state_t, output_states_vect),
7357 VEC_length (state_t, output_states_vect),
7358 sizeof (state_t), compare_transition_els_num);
7360 for (i = 0; i < VEC_length (state_t, output_states_vect); i++)
7362 VEC_truncate (vect_el_t, transition_vect, 0);
7363 for (arc = first_out_arc (VEC_index (state_t, output_states_vect, i));
7364 arc != NULL;
7365 arc = next_out_arc (arc))
7367 gcc_assert (arc->insn);
7368 if (arc->insn->first_ainsn_with_given_equivalence_num)
7369 add_vect_el (&transition_vect, arc->insn,
7370 arc->to_state->order_state_num);
7372 add_vect (automaton->trans_table,
7373 VEC_index (state_t, output_states_vect, i)->order_state_num,
7374 transition_vect);
7376 output_state_ainsn_table
7377 (automaton->trans_table, "state transitions",
7378 output_trans_full_vect_name, output_trans_comb_vect_name,
7379 output_trans_check_vect_name, output_trans_base_vect_name);
7381 VEC_free (state_t,heap, output_states_vect);
7382 VEC_free (vect_el_t,heap, transition_vect);
7385 /* The current number of passing states to find minimal issue delay
7386 value for an ainsn and state. */
7387 static int curr_state_pass_num;
7389 /* This recursive function passes states to find minimal issue delay
7390 value for AINSN. The state being visited is STATE. The function
7391 returns minimal issue delay value for AINSN in STATE or -1 if we
7392 enter into a loop. */
7393 static int
7394 min_issue_delay_pass_states (state_t state, ainsn_t ainsn)
7396 arc_t arc;
7397 int min_insn_issue_delay, insn_issue_delay;
7399 if (state->state_pass_num == curr_state_pass_num
7400 || state->min_insn_issue_delay != -1)
7401 /* We've entered into a loop or already have the correct value for
7402 given state and ainsn. */
7403 return state->min_insn_issue_delay;
7404 state->state_pass_num = curr_state_pass_num;
7405 min_insn_issue_delay = -1;
7406 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
7407 if (arc->insn == ainsn)
7409 min_insn_issue_delay = 0;
7410 break;
7412 else
7414 insn_issue_delay = min_issue_delay_pass_states (arc->to_state, ainsn);
7415 if (insn_issue_delay != -1)
7417 if (arc->insn->insn_reserv_decl
7418 == DECL_INSN_RESERV (advance_cycle_insn_decl))
7419 insn_issue_delay++;
7420 if (min_insn_issue_delay == -1
7421 || min_insn_issue_delay > insn_issue_delay)
7423 min_insn_issue_delay = insn_issue_delay;
7424 if (insn_issue_delay == 0)
7425 break;
7429 return min_insn_issue_delay;
7432 /* The function searches minimal issue delay value for AINSN in STATE.
7433 The function can return negative value if we can not issue AINSN. We
7434 will report about it later. */
7435 static int
7436 min_issue_delay (state_t state, ainsn_t ainsn)
7438 curr_state_pass_num++;
7439 state->min_insn_issue_delay = min_issue_delay_pass_states (state, ainsn);
7440 return state->min_insn_issue_delay;
7443 /* The function initiates code for finding minimal issue delay values.
7444 It should be called only once. */
7445 static void
7446 initiate_min_issue_delay_pass_states (void)
7448 curr_state_pass_num = 0;
7451 /* Form and output vectors representing minimal issue delay table of
7452 AUTOMATON. The table is state x ainsn -> minimal issue delay of
7453 the ainsn. */
7454 static void
7455 output_min_issue_delay_table (automaton_t automaton)
7457 vla_hwint_t min_issue_delay_vect;
7458 vla_hwint_t compressed_min_issue_delay_vect;
7459 vect_el_t min_delay;
7460 ainsn_t ainsn;
7461 size_t i, min_issue_delay_len;
7462 size_t compressed_min_issue_delay_len;
7463 size_t cfactor;
7465 /* Create vect of pointers to states ordered by num of transitions
7466 from the state (state with the maximum num is the first). */
7467 output_states_vect = 0;
7468 pass_states (automaton, add_states_vect_el);
7470 min_issue_delay_len = (VEC_length (state_t, output_states_vect)
7471 * automaton->insn_equiv_classes_num);
7472 min_issue_delay_vect = VEC_alloc (vect_el_t,heap, min_issue_delay_len);
7473 for (i = 0; i < min_issue_delay_len; i++)
7474 VEC_quick_push (vect_el_t, min_issue_delay_vect, 0);
7476 automaton->max_min_delay = 0;
7477 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
7478 if (ainsn->first_ainsn_with_given_equivalence_num)
7480 for (i = 0; i < VEC_length (state_t, output_states_vect); i++)
7481 VEC_index (state_t, output_states_vect, i)->min_insn_issue_delay = -1;
7482 for (i = 0; i < VEC_length (state_t, output_states_vect); i++)
7484 state_t s = VEC_index (state_t, output_states_vect, i);
7485 min_delay = min_issue_delay (s, ainsn);
7486 if (automaton->max_min_delay < min_delay)
7487 automaton->max_min_delay = min_delay;
7488 VEC_replace (vect_el_t, min_issue_delay_vect,
7489 s->order_state_num
7490 * automaton->insn_equiv_classes_num
7491 + ainsn->insn_equiv_class_num,
7492 min_delay);
7495 fprintf (output_file, "/* Vector of min issue delay of insns. */\n");
7496 fprintf (output_file, "static const ");
7497 output_range_type (output_file, 0, automaton->max_min_delay);
7498 fprintf (output_file, " ");
7499 output_min_issue_delay_vect_name (output_file, automaton);
7500 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7501 /* Compress the vector. */
7502 if (automaton->max_min_delay < 2)
7503 cfactor = 8;
7504 else if (automaton->max_min_delay < 4)
7505 cfactor = 4;
7506 else if (automaton->max_min_delay < 16)
7507 cfactor = 2;
7508 else
7509 cfactor = 1;
7510 automaton->min_issue_delay_table_compression_factor = cfactor;
7512 compressed_min_issue_delay_len = (min_issue_delay_len+cfactor-1) / cfactor;
7513 compressed_min_issue_delay_vect
7514 = VEC_alloc (vect_el_t,heap, compressed_min_issue_delay_len);
7516 for (i = 0; i < compressed_min_issue_delay_len; i++)
7517 VEC_quick_push (vect_el_t, compressed_min_issue_delay_vect, 0);
7519 for (i = 0; i < min_issue_delay_len; i++)
7521 size_t ci = i / cfactor;
7522 vect_el_t x = VEC_index (vect_el_t, min_issue_delay_vect, i);
7523 vect_el_t cx = VEC_index (vect_el_t, compressed_min_issue_delay_vect, ci);
7525 cx |= x << (8 - (i % cfactor + 1) * (8 / cfactor));
7526 VEC_replace (vect_el_t, compressed_min_issue_delay_vect, ci, cx);
7528 output_vect (compressed_min_issue_delay_vect);
7529 fprintf (output_file, "};\n\n");
7530 VEC_free (state_t,heap, output_states_vect);
7531 VEC_free (vect_el_t,heap, min_issue_delay_vect);
7532 VEC_free (vect_el_t,heap, compressed_min_issue_delay_vect);
7535 /* Form and output vector representing the locked states of
7536 AUTOMATON. */
7537 static void
7538 output_dead_lock_vect (automaton_t automaton)
7540 size_t i;
7541 arc_t arc;
7542 vla_hwint_t dead_lock_vect = 0;
7544 /* Create vect of pointers to states ordered by num of
7545 transitions from the state (state with the maximum num is the
7546 first). */
7547 automaton->locked_states = 0;
7548 output_states_vect = 0;
7549 pass_states (automaton, add_states_vect_el);
7551 VEC_safe_grow (vect_el_t,heap, dead_lock_vect,
7552 VEC_length (state_t, output_states_vect));
7553 for (i = 0; i < VEC_length (state_t, output_states_vect); i++)
7555 state_t s = VEC_index (state_t, output_states_vect, i);
7556 arc = first_out_arc (s);
7557 gcc_assert (arc);
7558 if (next_out_arc (arc) == NULL
7559 && (arc->insn->insn_reserv_decl
7560 == DECL_INSN_RESERV (advance_cycle_insn_decl)))
7562 VEC_replace (vect_el_t, dead_lock_vect, s->order_state_num, 1);
7563 automaton->locked_states++;
7565 else
7566 VEC_replace (vect_el_t, dead_lock_vect, s->order_state_num, 0);
7568 if (automaton->locked_states == 0)
7569 return;
7571 fprintf (output_file, "/* Vector for locked state flags. */\n");
7572 fprintf (output_file, "static const ");
7573 output_range_type (output_file, 0, 1);
7574 fprintf (output_file, " ");
7575 output_dead_lock_vect_name (output_file, automaton);
7576 fprintf (output_file, "[] = {\n");
7577 output_vect (dead_lock_vect);
7578 fprintf (output_file, "};\n\n");
7579 VEC_free (state_t,heap, output_states_vect);
7580 VEC_free (vect_el_t,heap, dead_lock_vect);
7583 /* Form and output vector representing reserved units of the states of
7584 AUTOMATON. */
7585 static void
7586 output_reserved_units_table (automaton_t automaton)
7588 vla_hwint_t reserved_units_table = 0;
7589 int state_byte_size;
7590 int reserved_units_size;
7591 size_t n;
7592 int i;
7594 if (description->query_units_num == 0)
7595 return;
7597 /* Create vect of pointers to states. */
7598 output_states_vect = 0;
7599 pass_states (automaton, add_states_vect_el);
7600 /* Create vector. */
7601 state_byte_size = (description->query_units_num + 7) / 8;
7602 reserved_units_size = (VEC_length (state_t, output_states_vect)
7603 * state_byte_size);
7605 reserved_units_table = VEC_alloc (vect_el_t,heap, reserved_units_size);
7607 for (i = 0; i < reserved_units_size; i++)
7608 VEC_quick_push (vect_el_t, reserved_units_table, 0);
7609 for (n = 0; n < VEC_length (state_t, output_states_vect); n++)
7611 state_t s = VEC_index (state_t, output_states_vect, n);
7612 for (i = 0; i < description->units_num; i++)
7613 if (units_array [i]->query_p
7614 && first_cycle_unit_presence (s, i))
7616 int ri = (s->order_state_num * state_byte_size
7617 + units_array [i]->query_num / 8);
7618 vect_el_t x = VEC_index (vect_el_t, reserved_units_table, ri);
7620 x += 1 << (units_array [i]->query_num % 8);
7621 VEC_replace (vect_el_t, reserved_units_table, ri, x);
7624 fprintf (output_file, "\n#if %s\n", CPU_UNITS_QUERY_MACRO_NAME);
7625 fprintf (output_file, "/* Vector for reserved units of states. */\n");
7626 fprintf (output_file, "static const ");
7627 output_range_type (output_file, 0, 255);
7628 fprintf (output_file, " ");
7629 output_reserved_units_table_name (output_file, automaton);
7630 fprintf (output_file, "[] = {\n");
7631 output_vect (reserved_units_table);
7632 fprintf (output_file, "};\n#endif /* #if %s */\n\n",
7633 CPU_UNITS_QUERY_MACRO_NAME);
7635 VEC_free (state_t,heap, output_states_vect);
7636 VEC_free (vect_el_t,heap, reserved_units_table);
7639 /* The function outputs all tables representing DFA(s) used for fast
7640 pipeline hazards recognition. */
7641 static void
7642 output_tables (void)
7644 automaton_t automaton;
7646 initiate_min_issue_delay_pass_states ();
7647 for (automaton = description->first_automaton;
7648 automaton != NULL;
7649 automaton = automaton->next_automaton)
7651 output_translate_vect (automaton);
7652 output_trans_table (automaton);
7653 output_min_issue_delay_table (automaton);
7654 output_dead_lock_vect (automaton);
7655 output_reserved_units_table (automaton);
7657 fprintf (output_file, "\n#define %s %d\n\n", ADVANCE_CYCLE_VALUE_NAME,
7658 DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
7661 /* The function outputs definition and value of PHR interface variable
7662 `max_insn_queue_index'. Its value is not less than maximal queue
7663 length needed for the insn scheduler. */
7664 static void
7665 output_max_insn_queue_index_def (void)
7667 int i, max, latency;
7668 decl_t decl;
7670 max = description->max_insn_reserv_cycles;
7671 for (i = 0; i < description->decls_num; i++)
7673 decl = description->decls [i];
7674 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
7676 latency = DECL_INSN_RESERV (decl)->default_latency;
7677 if (latency > max)
7678 max = latency;
7680 else if (decl->mode == dm_bypass)
7682 latency = DECL_BYPASS (decl)->latency;
7683 if (latency > max)
7684 max = latency;
7687 for (i = 0; (1 << i) <= max; i++)
7689 gcc_assert (i >= 0);
7690 fprintf (output_file, "\nconst int max_insn_queue_index = %d;\n\n",
7691 (1 << i) - 1);
7694 /* The function outputs switch cases for insn reservations using
7695 function *output_automata_list_code. */
7696 static void
7697 output_insn_code_cases (void (*output_automata_list_code)
7698 (automata_list_el_t))
7700 decl_t decl, decl2;
7701 int i, j;
7703 for (i = 0; i < description->decls_num; i++)
7705 decl = description->decls [i];
7706 if (decl->mode == dm_insn_reserv)
7707 DECL_INSN_RESERV (decl)->processed_p = FALSE;
7709 for (i = 0; i < description->decls_num; i++)
7711 decl = description->decls [i];
7712 if (decl->mode == dm_insn_reserv
7713 && !DECL_INSN_RESERV (decl)->processed_p)
7715 for (j = i; j < description->decls_num; j++)
7717 decl2 = description->decls [j];
7718 if (decl2->mode == dm_insn_reserv
7719 && (DECL_INSN_RESERV (decl2)->important_automata_list
7720 == DECL_INSN_RESERV (decl)->important_automata_list))
7722 DECL_INSN_RESERV (decl2)->processed_p = TRUE;
7723 fprintf (output_file, " case %d: /* %s */\n",
7724 DECL_INSN_RESERV (decl2)->insn_num,
7725 DECL_INSN_RESERV (decl2)->name);
7728 (*output_automata_list_code)
7729 (DECL_INSN_RESERV (decl)->important_automata_list);
7735 /* The function outputs a code for evaluation of a minimal delay of
7736 issue of insns which have reservations in given AUTOMATA_LIST. */
7737 static void
7738 output_automata_list_min_issue_delay_code (automata_list_el_t automata_list)
7740 automata_list_el_t el;
7741 automaton_t automaton;
7743 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
7745 automaton = el->automaton;
7746 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
7747 output_min_issue_delay_vect_name (output_file, automaton);
7748 fprintf (output_file,
7749 (automaton->min_issue_delay_table_compression_factor != 1
7750 ? " [(" : " ["));
7751 output_translate_vect_name (output_file, automaton);
7752 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
7753 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7754 output_chip_member_name (output_file, automaton);
7755 fprintf (output_file, " * %d", automaton->insn_equiv_classes_num);
7756 if (automaton->min_issue_delay_table_compression_factor == 1)
7757 fprintf (output_file, "];\n");
7758 else
7760 fprintf (output_file, ") / %d];\n",
7761 automaton->min_issue_delay_table_compression_factor);
7762 fprintf (output_file, " %s = (%s >> (8 - (",
7763 TEMPORARY_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
7764 output_translate_vect_name (output_file, automaton);
7765 fprintf
7766 (output_file, " [%s] %% %d + 1) * %d)) & %d;\n",
7767 INTERNAL_INSN_CODE_NAME,
7768 automaton->min_issue_delay_table_compression_factor,
7769 8 / automaton->min_issue_delay_table_compression_factor,
7770 (1 << (8 / automaton->min_issue_delay_table_compression_factor))
7771 - 1);
7773 if (el == automata_list)
7774 fprintf (output_file, " %s = %s;\n",
7775 RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
7776 else
7778 fprintf (output_file, " if (%s > %s)\n",
7779 TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
7780 fprintf (output_file, " %s = %s;\n",
7781 RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
7784 fprintf (output_file, " break;\n\n");
7787 /* Output function `internal_min_issue_delay'. */
7788 static void
7789 output_internal_min_issue_delay_func (void)
7791 fprintf (output_file,
7792 "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
7793 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7794 CHIP_NAME, CHIP_PARAMETER_NAME);
7795 fprintf (output_file, "{\n int %s ATTRIBUTE_UNUSED;\n int %s = -1;\n",
7796 TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
7797 fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
7798 output_insn_code_cases (output_automata_list_min_issue_delay_code);
7799 fprintf (output_file,
7800 "\n default:\n %s = -1;\n break;\n }\n",
7801 RESULT_VARIABLE_NAME);
7802 fprintf (output_file, " return %s;\n", RESULT_VARIABLE_NAME);
7803 fprintf (output_file, "}\n\n");
7806 /* The function outputs a code changing state after issue of insns
7807 which have reservations in given AUTOMATA_LIST. */
7808 static void
7809 output_automata_list_transition_code (automata_list_el_t automata_list)
7811 automata_list_el_t el, next_el;
7813 fprintf (output_file, " {\n");
7814 if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
7815 for (el = automata_list;; el = next_el)
7817 next_el = el->next_automata_list_el;
7818 if (next_el == NULL)
7819 break;
7820 fprintf (output_file, " ");
7821 output_state_member_type (output_file, el->automaton);
7822 fprintf (output_file, " ");
7823 output_temp_chip_member_name (output_file, el->automaton);
7824 fprintf (output_file, ";\n");
7826 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
7827 if (comb_vect_p (el->automaton->trans_table))
7829 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
7830 output_trans_base_vect_name (output_file, el->automaton);
7831 fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
7832 output_chip_member_name (output_file, el->automaton);
7833 fprintf (output_file, "] + ");
7834 output_translate_vect_name (output_file, el->automaton);
7835 fprintf (output_file, " [%s];\n", INTERNAL_INSN_CODE_NAME);
7836 fprintf (output_file, " if (");
7837 output_trans_check_vect_name (output_file, el->automaton);
7838 fprintf (output_file, " [%s] != %s->",
7839 TEMPORARY_VARIABLE_NAME, CHIP_PARAMETER_NAME);
7840 output_chip_member_name (output_file, el->automaton);
7841 fprintf (output_file, ")\n");
7842 fprintf (output_file, " return %s (%s, %s);\n",
7843 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7844 CHIP_PARAMETER_NAME);
7845 fprintf (output_file, " else\n");
7846 fprintf (output_file, " ");
7847 if (el->next_automata_list_el != NULL)
7848 output_temp_chip_member_name (output_file, el->automaton);
7849 else
7851 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7852 output_chip_member_name (output_file, el->automaton);
7854 fprintf (output_file, " = ");
7855 output_trans_comb_vect_name (output_file, el->automaton);
7856 fprintf (output_file, " [%s];\n", TEMPORARY_VARIABLE_NAME);
7858 else
7860 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
7861 output_trans_full_vect_name (output_file, el->automaton);
7862 fprintf (output_file, " [");
7863 output_translate_vect_name (output_file, el->automaton);
7864 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
7865 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7866 output_chip_member_name (output_file, el->automaton);
7867 fprintf (output_file, " * %d];\n",
7868 el->automaton->insn_equiv_classes_num);
7869 fprintf (output_file, " if (%s >= %d)\n",
7870 TEMPORARY_VARIABLE_NAME, el->automaton->achieved_states_num);
7871 fprintf (output_file, " return %s (%s, %s);\n",
7872 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7873 CHIP_PARAMETER_NAME);
7874 fprintf (output_file, " else\n ");
7875 if (el->next_automata_list_el != NULL)
7876 output_temp_chip_member_name (output_file, el->automaton);
7877 else
7879 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7880 output_chip_member_name (output_file, el->automaton);
7882 fprintf (output_file, " = %s;\n", TEMPORARY_VARIABLE_NAME);
7884 if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
7885 for (el = automata_list;; el = next_el)
7887 next_el = el->next_automata_list_el;
7888 if (next_el == NULL)
7889 break;
7890 fprintf (output_file, " %s->", CHIP_PARAMETER_NAME);
7891 output_chip_member_name (output_file, el->automaton);
7892 fprintf (output_file, " = ");
7893 output_temp_chip_member_name (output_file, el->automaton);
7894 fprintf (output_file, ";\n");
7896 fprintf (output_file, " return -1;\n");
7897 fprintf (output_file, " }\n");
7900 /* Output function `internal_state_transition'. */
7901 static void
7902 output_internal_trans_func (void)
7904 fprintf (output_file,
7905 "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
7906 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7907 CHIP_NAME, CHIP_PARAMETER_NAME);
7908 fprintf (output_file, "{\n int %s ATTRIBUTE_UNUSED;\n", TEMPORARY_VARIABLE_NAME);
7909 fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
7910 output_insn_code_cases (output_automata_list_transition_code);
7911 fprintf (output_file, "\n default:\n return -1;\n }\n");
7912 fprintf (output_file, "}\n\n");
7915 /* Output code
7917 if (insn != 0)
7919 insn_code = dfa_insn_code (insn);
7920 if (insn_code > DFA__ADVANCE_CYCLE)
7921 return code;
7923 else
7924 insn_code = DFA__ADVANCE_CYCLE;
7926 where insn denotes INSN_NAME, insn_code denotes INSN_CODE_NAME, and
7927 code denotes CODE. */
7928 static void
7929 output_internal_insn_code_evaluation (const char *insn_name,
7930 const char *insn_code_name,
7931 int code)
7933 fprintf (output_file, "\n if (%s != 0)\n {\n", insn_name);
7934 fprintf (output_file, " %s = %s (%s);\n", insn_code_name,
7935 DFA_INSN_CODE_FUNC_NAME, insn_name);
7936 fprintf (output_file, " if (%s > %s)\n return %d;\n",
7937 insn_code_name, ADVANCE_CYCLE_VALUE_NAME, code);
7938 fprintf (output_file, " }\n else\n %s = %s;\n\n",
7939 insn_code_name, ADVANCE_CYCLE_VALUE_NAME);
7943 /* This function outputs `dfa_insn_code' and its helper function
7944 `dfa_insn_code_enlarge'. */
7945 static void
7946 output_dfa_insn_code_func (void)
7948 /* Emacs c-mode gets really confused if there's a { or } in column 0
7949 inside a string, so don't do that. */
7950 fprintf (output_file, "\
7951 static void\n\
7952 dfa_insn_code_enlarge (int uid)\n\
7953 {\n\
7954 int i = %s;\n\
7955 %s = 2 * uid;\n\
7956 %s = xrealloc (%s,\n\
7957 %s * sizeof(int));\n\
7958 for (; i < %s; i++)\n\
7959 %s[i] = -1;\n}\n\n",
7960 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
7961 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
7962 DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
7963 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
7964 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
7965 DFA_INSN_CODES_VARIABLE_NAME);
7966 fprintf (output_file, "\
7967 static inline int\n%s (rtx %s)\n\
7968 {\n\
7969 int uid = INSN_UID (%s);\n\
7970 int %s;\n\n",
7971 DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME,
7972 INSN_PARAMETER_NAME, INTERNAL_INSN_CODE_NAME);
7974 fprintf (output_file,
7975 " if (uid >= %s)\n dfa_insn_code_enlarge (uid);\n\n",
7976 DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
7977 fprintf (output_file, " %s = %s[uid];\n",
7978 INTERNAL_INSN_CODE_NAME, DFA_INSN_CODES_VARIABLE_NAME);
7979 fprintf (output_file, "\
7980 if (%s < 0)\n\
7981 {\n\
7982 %s = %s (%s);\n\
7983 %s[uid] = %s;\n\
7984 }\n",
7985 INTERNAL_INSN_CODE_NAME,
7986 INTERNAL_INSN_CODE_NAME,
7987 INTERNAL_DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME,
7988 DFA_INSN_CODES_VARIABLE_NAME, INTERNAL_INSN_CODE_NAME);
7989 fprintf (output_file, " return %s;\n}\n\n", INTERNAL_INSN_CODE_NAME);
7992 /* The function outputs PHR interface function `state_transition'. */
7993 static void
7994 output_trans_func (void)
7996 fprintf (output_file, "int\n%s (%s %s, rtx %s)\n",
7997 TRANSITION_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME,
7998 INSN_PARAMETER_NAME);
7999 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
8000 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8001 INTERNAL_INSN_CODE_NAME, -1);
8002 fprintf (output_file, " return %s (%s, %s);\n}\n\n",
8003 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, STATE_NAME);
8006 /* Output function `min_issue_delay'. */
8007 static void
8008 output_min_issue_delay_func (void)
8010 fprintf (output_file, "int\n%s (%s %s, rtx %s)\n",
8011 MIN_ISSUE_DELAY_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME,
8012 INSN_PARAMETER_NAME);
8013 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
8014 fprintf (output_file, "\n if (%s != 0)\n {\n", INSN_PARAMETER_NAME);
8015 fprintf (output_file, " %s = %s (%s);\n", INTERNAL_INSN_CODE_NAME,
8016 DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME);
8017 fprintf (output_file, " if (%s > %s)\n return 0;\n",
8018 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8019 fprintf (output_file, " }\n else\n %s = %s;\n",
8020 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8021 fprintf (output_file, "\n return %s (%s, %s);\n",
8022 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8023 STATE_NAME);
8024 fprintf (output_file, "}\n\n");
8027 /* Output function `internal_dead_lock'. */
8028 static void
8029 output_internal_dead_lock_func (void)
8031 automaton_t automaton;
8033 fprintf (output_file, "static int\n%s (struct %s *ARG_UNUSED (%s))\n",
8034 INTERNAL_DEAD_LOCK_FUNC_NAME, CHIP_NAME, CHIP_PARAMETER_NAME);
8035 fprintf (output_file, "{\n");
8036 for (automaton = description->first_automaton;
8037 automaton != NULL;
8038 automaton = automaton->next_automaton)
8039 if (automaton->locked_states)
8041 fprintf (output_file, " if (");
8042 output_dead_lock_vect_name (output_file, automaton);
8043 fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
8044 output_chip_member_name (output_file, automaton);
8045 fprintf (output_file, "])\n return 1/* TRUE */;\n");
8047 fprintf (output_file, " return 0/* FALSE */;\n}\n\n");
8050 /* The function outputs PHR interface function `state_dead_lock_p'. */
8051 static void
8052 output_dead_lock_func (void)
8054 fprintf (output_file, "int\n%s (%s %s)\n",
8055 DEAD_LOCK_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME);
8056 fprintf (output_file, "{\n return %s (%s);\n}\n\n",
8057 INTERNAL_DEAD_LOCK_FUNC_NAME, STATE_NAME);
8060 /* Output function `internal_reset'. */
8061 static void
8062 output_internal_reset_func (void)
8064 fprintf (output_file, "static inline void\n%s (struct %s *%s)\n",
8065 INTERNAL_RESET_FUNC_NAME, CHIP_NAME, CHIP_PARAMETER_NAME);
8066 fprintf (output_file, "{\n memset (%s, 0, sizeof (struct %s));\n}\n\n",
8067 CHIP_PARAMETER_NAME, CHIP_NAME);
8070 /* The function outputs PHR interface function `state_size'. */
8071 static void
8072 output_size_func (void)
8074 fprintf (output_file, "int\n%s (void)\n", SIZE_FUNC_NAME);
8075 fprintf (output_file, "{\n return sizeof (struct %s);\n}\n\n", CHIP_NAME);
8078 /* The function outputs PHR interface function `state_reset'. */
8079 static void
8080 output_reset_func (void)
8082 fprintf (output_file, "void\n%s (%s %s)\n",
8083 RESET_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME);
8084 fprintf (output_file, "{\n %s (%s);\n}\n\n", INTERNAL_RESET_FUNC_NAME,
8085 STATE_NAME);
8088 /* Output function `min_insn_conflict_delay'. */
8089 static void
8090 output_min_insn_conflict_delay_func (void)
8092 fprintf (output_file,
8093 "int\n%s (%s %s, rtx %s, rtx %s)\n",
8094 MIN_INSN_CONFLICT_DELAY_FUNC_NAME, STATE_TYPE_NAME,
8095 STATE_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8096 fprintf (output_file, "{\n struct %s %s;\n int %s, %s, transition;\n",
8097 CHIP_NAME, CHIP_NAME, INTERNAL_INSN_CODE_NAME,
8098 INTERNAL_INSN2_CODE_NAME);
8099 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8100 INTERNAL_INSN_CODE_NAME, 0);
8101 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
8102 INTERNAL_INSN2_CODE_NAME, 0);
8103 fprintf (output_file, " memcpy (&%s, %s, sizeof (%s));\n",
8104 CHIP_NAME, STATE_NAME, CHIP_NAME);
8105 fprintf (output_file, " %s (&%s);\n", INTERNAL_RESET_FUNC_NAME, CHIP_NAME);
8106 fprintf (output_file, " transition = %s (%s, &%s);\n",
8107 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME);
8108 fprintf (output_file, " gcc_assert (transition <= 0);\n");
8109 fprintf (output_file, " return %s (%s, &%s);\n",
8110 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN2_CODE_NAME,
8111 CHIP_NAME);
8112 fprintf (output_file, "}\n\n");
8115 /* Output function `internal_insn_latency'. */
8116 static void
8117 output_internal_insn_latency_func (void)
8119 decl_t decl;
8120 struct bypass_decl *bypass;
8121 int i, j, col;
8122 const char *tabletype = "unsigned char";
8124 /* Find the smallest integer type that can hold all the default
8125 latency values. */
8126 for (i = 0; i < description->decls_num; i++)
8127 if (description->decls[i]->mode == dm_insn_reserv)
8129 decl = description->decls[i];
8130 if (DECL_INSN_RESERV (decl)->default_latency > UCHAR_MAX
8131 && tabletype[0] != 'i') /* Don't shrink it. */
8132 tabletype = "unsigned short";
8133 if (DECL_INSN_RESERV (decl)->default_latency > USHRT_MAX)
8134 tabletype = "int";
8137 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",
8138 INTERNAL_INSN_LATENCY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8139 INTERNAL_INSN2_CODE_NAME, INSN_PARAMETER_NAME,
8140 INSN2_PARAMETER_NAME);
8141 fprintf (output_file, "{\n");
8143 if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8145 fputs (" return 0;\n}\n\n", output_file);
8146 return;
8149 fprintf (output_file, " static const %s default_latencies[] =\n {",
8150 tabletype);
8152 for (i = 0, j = 0, col = 7; i < description->decls_num; i++)
8153 if (description->decls[i]->mode == dm_insn_reserv
8154 && description->decls[i] != advance_cycle_insn_decl)
8156 if ((col = (col+1) % 8) == 0)
8157 fputs ("\n ", output_file);
8158 decl = description->decls[i];
8159 gcc_assert (j++ == DECL_INSN_RESERV (decl)->insn_num);
8160 fprintf (output_file, "% 4d,",
8161 DECL_INSN_RESERV (decl)->default_latency);
8163 gcc_assert (j == DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
8164 fputs ("\n };\n", output_file);
8166 fprintf (output_file, " if (%s >= %s || %s >= %s)\n return 0;\n",
8167 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8168 INTERNAL_INSN2_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8170 fprintf (output_file, " switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8171 for (i = 0; i < description->decls_num; i++)
8172 if (description->decls[i]->mode == dm_insn_reserv
8173 && DECL_INSN_RESERV (description->decls[i])->bypass_list)
8175 decl = description->decls [i];
8176 fprintf (output_file,
8177 " case %d:\n switch (%s)\n {\n",
8178 DECL_INSN_RESERV (decl)->insn_num,
8179 INTERNAL_INSN2_CODE_NAME);
8180 for (bypass = DECL_INSN_RESERV (decl)->bypass_list;
8181 bypass != NULL;
8182 bypass = bypass->next)
8184 gcc_assert (bypass->in_insn_reserv->insn_num
8185 != (DECL_INSN_RESERV
8186 (advance_cycle_insn_decl)->insn_num));
8187 fprintf (output_file, " case %d:\n",
8188 bypass->in_insn_reserv->insn_num);
8189 if (bypass->bypass_guard_name == NULL)
8190 fprintf (output_file, " return %d;\n",
8191 bypass->latency);
8192 else
8194 fprintf (output_file,
8195 " if (%s (%s, %s))\n",
8196 bypass->bypass_guard_name, INSN_PARAMETER_NAME,
8197 INSN2_PARAMETER_NAME);
8198 fprintf (output_file,
8199 " return %d;\n break;\n",
8200 bypass->latency);
8203 fputs (" }\n break;\n", output_file);
8206 fprintf (output_file, " }\n return default_latencies[%s];\n}\n\n",
8207 INTERNAL_INSN_CODE_NAME);
8210 /* The function outputs PHR interface function `insn_latency'. */
8211 static void
8212 output_insn_latency_func (void)
8214 fprintf (output_file, "int\n%s (rtx %s, rtx %s)\n",
8215 INSN_LATENCY_FUNC_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8216 fprintf (output_file, "{\n int %s, %s;\n",
8217 INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME);
8218 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8219 INTERNAL_INSN_CODE_NAME, 0);
8220 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
8221 INTERNAL_INSN2_CODE_NAME, 0);
8222 fprintf (output_file, " return %s (%s, %s, %s, %s);\n}\n\n",
8223 INTERNAL_INSN_LATENCY_FUNC_NAME,
8224 INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME,
8225 INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8228 /* The function outputs PHR interface function `print_reservation'. */
8229 static void
8230 output_print_reservation_func (void)
8232 decl_t decl;
8233 int i, j;
8235 fprintf (output_file,
8236 "void\n%s (FILE *%s, rtx %s ATTRIBUTE_UNUSED)\n{\n",
8237 PRINT_RESERVATION_FUNC_NAME, FILE_PARAMETER_NAME,
8238 INSN_PARAMETER_NAME);
8240 if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8242 fprintf (output_file, " fputs (\"%s\", %s);\n}\n\n",
8243 NOTHING_NAME, FILE_PARAMETER_NAME);
8244 return;
8248 fputs (" static const char *const reservation_names[] =\n {",
8249 output_file);
8251 for (i = 0, j = 0; i < description->decls_num; i++)
8253 decl = description->decls [i];
8254 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
8256 gcc_assert (j == DECL_INSN_RESERV (decl)->insn_num);
8257 j++;
8259 fprintf (output_file, "\n \"%s\",",
8260 regexp_representation (DECL_INSN_RESERV (decl)->regexp));
8261 finish_regexp_representation ();
8264 gcc_assert (j == DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
8266 fprintf (output_file, "\n \"%s\"\n };\n int %s;\n\n",
8267 NOTHING_NAME, INTERNAL_INSN_CODE_NAME);
8269 fprintf (output_file, " if (%s == 0)\n %s = %s;\n",
8270 INSN_PARAMETER_NAME,
8271 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8272 fprintf (output_file, " else\n\
8273 {\n\
8274 %s = %s (%s);\n\
8275 if (%s > %s)\n\
8276 %s = %s;\n\
8277 }\n",
8278 INTERNAL_INSN_CODE_NAME, DFA_INSN_CODE_FUNC_NAME,
8279 INSN_PARAMETER_NAME,
8280 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8281 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8283 fprintf (output_file, " fputs (reservation_names[%s], %s);\n}\n\n",
8284 INTERNAL_INSN_CODE_NAME, FILE_PARAMETER_NAME);
8287 /* The following function is used to sort unit declaration by their
8288 names. */
8289 static int
8290 units_cmp (const void *unit1, const void *unit2)
8292 const unit_decl_t u1 = *(unit_decl_t *) unit1;
8293 const unit_decl_t u2 = *(unit_decl_t *) unit2;
8295 return strcmp (u1->name, u2->name);
8298 /* The following macro value is name of struct containing unit name
8299 and unit code. */
8300 #define NAME_CODE_STRUCT_NAME "name_code"
8302 /* The following macro value is name of table of struct name_code. */
8303 #define NAME_CODE_TABLE_NAME "name_code_table"
8305 /* The following macro values are member names for struct name_code. */
8306 #define NAME_MEMBER_NAME "name"
8307 #define CODE_MEMBER_NAME "code"
8309 /* The following macro values are local variable names for function
8310 `get_cpu_unit_code'. */
8311 #define CMP_VARIABLE_NAME "cmp"
8312 #define LOW_VARIABLE_NAME "l"
8313 #define MIDDLE_VARIABLE_NAME "m"
8314 #define HIGH_VARIABLE_NAME "h"
8316 /* The following function outputs function to obtain internal cpu unit
8317 code by the cpu unit name. */
8318 static void
8319 output_get_cpu_unit_code_func (void)
8321 int i;
8322 unit_decl_t *units;
8324 fprintf (output_file, "int\n%s (const char *%s)\n",
8325 GET_CPU_UNIT_CODE_FUNC_NAME, CPU_UNIT_NAME_PARAMETER_NAME);
8326 fprintf (output_file, "{\n struct %s {const char *%s; int %s;};\n",
8327 NAME_CODE_STRUCT_NAME, NAME_MEMBER_NAME, CODE_MEMBER_NAME);
8328 fprintf (output_file, " int %s, %s, %s, %s;\n", CMP_VARIABLE_NAME,
8329 LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8330 fprintf (output_file, " static struct %s %s [] =\n {\n",
8331 NAME_CODE_STRUCT_NAME, NAME_CODE_TABLE_NAME);
8332 units = xmalloc (sizeof (unit_decl_t) * description->units_num);
8333 memcpy (units, units_array, sizeof (unit_decl_t) * description->units_num);
8334 qsort (units, description->units_num, sizeof (unit_decl_t), units_cmp);
8335 for (i = 0; i < description->units_num; i++)
8336 if (units [i]->query_p)
8337 fprintf (output_file, " {\"%s\", %d},\n",
8338 units[i]->name, units[i]->query_num);
8339 fprintf (output_file, " };\n\n");
8340 fprintf (output_file, " /* The following is binary search: */\n");
8341 fprintf (output_file, " %s = 0;\n", LOW_VARIABLE_NAME);
8342 fprintf (output_file, " %s = sizeof (%s) / sizeof (struct %s) - 1;\n",
8343 HIGH_VARIABLE_NAME, NAME_CODE_TABLE_NAME, NAME_CODE_STRUCT_NAME);
8344 fprintf (output_file, " while (%s <= %s)\n {\n",
8345 LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8346 fprintf (output_file, " %s = (%s + %s) / 2;\n",
8347 MIDDLE_VARIABLE_NAME, LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8348 fprintf (output_file, " %s = strcmp (%s, %s [%s].%s);\n",
8349 CMP_VARIABLE_NAME, CPU_UNIT_NAME_PARAMETER_NAME,
8350 NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, NAME_MEMBER_NAME);
8351 fprintf (output_file, " if (%s < 0)\n", CMP_VARIABLE_NAME);
8352 fprintf (output_file, " %s = %s - 1;\n",
8353 HIGH_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
8354 fprintf (output_file, " else if (%s > 0)\n", CMP_VARIABLE_NAME);
8355 fprintf (output_file, " %s = %s + 1;\n",
8356 LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
8357 fprintf (output_file, " else\n");
8358 fprintf (output_file, " return %s [%s].%s;\n }\n",
8359 NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, CODE_MEMBER_NAME);
8360 fprintf (output_file, " return -1;\n}\n\n");
8361 free (units);
8364 /* The following function outputs function to check reservation of cpu
8365 unit (its internal code will be passed as the function argument) in
8366 given cpu state. */
8367 static void
8368 output_cpu_unit_reservation_p (void)
8370 automaton_t automaton;
8372 fprintf (output_file, "int\n%s (%s %s, int %s)\n",
8373 CPU_UNIT_RESERVATION_P_FUNC_NAME,
8374 STATE_TYPE_NAME, STATE_NAME,
8375 CPU_CODE_PARAMETER_NAME);
8376 fprintf (output_file, "{\n gcc_assert (%s >= 0 && %s < %d);\n",
8377 CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME,
8378 description->query_units_num);
8379 if (description->query_units_num > 0)
8380 for (automaton = description->first_automaton;
8381 automaton != NULL;
8382 automaton = automaton->next_automaton)
8384 fprintf (output_file, " if ((");
8385 output_reserved_units_table_name (output_file, automaton);
8386 fprintf (output_file, " [((struct %s *) %s)->", CHIP_NAME, STATE_NAME);
8387 output_chip_member_name (output_file, automaton);
8388 fprintf (output_file, " * %d + %s / 8] >> (%s %% 8)) & 1)\n",
8389 (description->query_units_num + 7) / 8,
8390 CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME);
8391 fprintf (output_file, " return 1;\n");
8393 fprintf (output_file, " return 0;\n}\n\n");
8396 /* The function outputs PHR interface functions `dfa_clean_insn_cache'
8397 and 'dfa_clear_single_insn_cache'. */
8398 static void
8399 output_dfa_clean_insn_cache_func (void)
8401 fprintf (output_file,
8402 "void\n%s (void)\n{\n int %s;\n\n",
8403 DFA_CLEAN_INSN_CACHE_FUNC_NAME, I_VARIABLE_NAME);
8404 fprintf (output_file,
8405 " for (%s = 0; %s < %s; %s++)\n %s [%s] = -1;\n}\n\n",
8406 I_VARIABLE_NAME, I_VARIABLE_NAME,
8407 DFA_INSN_CODES_LENGTH_VARIABLE_NAME, I_VARIABLE_NAME,
8408 DFA_INSN_CODES_VARIABLE_NAME, I_VARIABLE_NAME);
8410 fprintf (output_file,
8411 "void\n%s (rtx %s)\n{\n int %s;\n\n",
8412 DFA_CLEAR_SINGLE_INSN_CACHE_FUNC_NAME, INSN_PARAMETER_NAME,
8413 I_VARIABLE_NAME);
8414 fprintf (output_file,
8415 " %s = INSN_UID (%s);\n if (%s < %s)\n %s [%s] = -1;\n}\n\n",
8416 I_VARIABLE_NAME, INSN_PARAMETER_NAME, I_VARIABLE_NAME,
8417 DFA_INSN_CODES_LENGTH_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
8418 I_VARIABLE_NAME);
8421 /* The function outputs PHR interface function `dfa_start'. */
8422 static void
8423 output_dfa_start_func (void)
8425 fprintf (output_file,
8426 "void\n%s (void)\n{\n %s = get_max_uid ();\n",
8427 DFA_START_FUNC_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8428 fprintf (output_file, " %s = xmalloc (%s * sizeof (int));\n",
8429 DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8430 fprintf (output_file, " %s ();\n}\n\n", DFA_CLEAN_INSN_CACHE_FUNC_NAME);
8433 /* The function outputs PHR interface function `dfa_finish'. */
8434 static void
8435 output_dfa_finish_func (void)
8437 fprintf (output_file, "void\n%s (void)\n{\n free (%s);\n}\n\n",
8438 DFA_FINISH_FUNC_NAME, DFA_INSN_CODES_VARIABLE_NAME);
8443 /* The page contains code for output description file (readable
8444 representation of original description and generated DFA(s). */
8446 /* The function outputs string representation of IR reservation. */
8447 static void
8448 output_regexp (regexp_t regexp)
8450 fprintf (output_description_file, "%s", regexp_representation (regexp));
8451 finish_regexp_representation ();
8454 /* Output names of units in LIST separated by comma. */
8455 static void
8456 output_unit_set_el_list (unit_set_el_t list)
8458 unit_set_el_t el;
8460 for (el = list; el != NULL; el = el->next_unit_set_el)
8462 if (el != list)
8463 fprintf (output_description_file, ", ");
8464 fprintf (output_description_file, "%s", el->unit_decl->name);
8468 /* Output patterns in LIST separated by comma. */
8469 static void
8470 output_pattern_set_el_list (pattern_set_el_t list)
8472 pattern_set_el_t el;
8473 int i;
8475 for (el = list; el != NULL; el = el->next_pattern_set_el)
8477 if (el != list)
8478 fprintf (output_description_file, ", ");
8479 for (i = 0; i < el->units_num; i++)
8480 fprintf (output_description_file, (i == 0 ? "%s" : " %s"),
8481 el->unit_decls [i]->name);
8485 /* The function outputs string representation of IR define_reservation
8486 and define_insn_reservation. */
8487 static void
8488 output_description (void)
8490 decl_t decl;
8491 int i;
8493 for (i = 0; i < description->decls_num; i++)
8495 decl = description->decls [i];
8496 if (decl->mode == dm_unit)
8498 if (DECL_UNIT (decl)->excl_list != NULL)
8500 fprintf (output_description_file, "unit %s exlusion_set: ",
8501 DECL_UNIT (decl)->name);
8502 output_unit_set_el_list (DECL_UNIT (decl)->excl_list);
8503 fprintf (output_description_file, "\n");
8505 if (DECL_UNIT (decl)->presence_list != NULL)
8507 fprintf (output_description_file, "unit %s presence_set: ",
8508 DECL_UNIT (decl)->name);
8509 output_pattern_set_el_list (DECL_UNIT (decl)->presence_list);
8510 fprintf (output_description_file, "\n");
8512 if (DECL_UNIT (decl)->final_presence_list != NULL)
8514 fprintf (output_description_file, "unit %s final_presence_set: ",
8515 DECL_UNIT (decl)->name);
8516 output_pattern_set_el_list
8517 (DECL_UNIT (decl)->final_presence_list);
8518 fprintf (output_description_file, "\n");
8520 if (DECL_UNIT (decl)->absence_list != NULL)
8522 fprintf (output_description_file, "unit %s absence_set: ",
8523 DECL_UNIT (decl)->name);
8524 output_pattern_set_el_list (DECL_UNIT (decl)->absence_list);
8525 fprintf (output_description_file, "\n");
8527 if (DECL_UNIT (decl)->final_absence_list != NULL)
8529 fprintf (output_description_file, "unit %s final_absence_set: ",
8530 DECL_UNIT (decl)->name);
8531 output_pattern_set_el_list
8532 (DECL_UNIT (decl)->final_absence_list);
8533 fprintf (output_description_file, "\n");
8537 fprintf (output_description_file, "\n");
8538 for (i = 0; i < description->decls_num; i++)
8540 decl = description->decls [i];
8541 if (decl->mode == dm_reserv)
8543 fprintf (output_description_file, "reservation %s: ",
8544 DECL_RESERV (decl)->name);
8545 output_regexp (DECL_RESERV (decl)->regexp);
8546 fprintf (output_description_file, "\n");
8548 else if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
8550 fprintf (output_description_file, "insn reservation %s ",
8551 DECL_INSN_RESERV (decl)->name);
8552 print_rtl (output_description_file,
8553 DECL_INSN_RESERV (decl)->condexp);
8554 fprintf (output_description_file, ": ");
8555 output_regexp (DECL_INSN_RESERV (decl)->regexp);
8556 fprintf (output_description_file, "\n");
8558 else if (decl->mode == dm_bypass)
8559 fprintf (output_description_file, "bypass %d %s %s\n",
8560 DECL_BYPASS (decl)->latency,
8561 DECL_BYPASS (decl)->out_insn_name,
8562 DECL_BYPASS (decl)->in_insn_name);
8564 fprintf (output_description_file, "\n\f\n");
8567 /* The function outputs name of AUTOMATON. */
8568 static void
8569 output_automaton_name (FILE *f, automaton_t automaton)
8571 if (automaton->corresponding_automaton_decl == NULL)
8572 fprintf (f, "#%d", automaton->automaton_order_num);
8573 else
8574 fprintf (f, "`%s'", automaton->corresponding_automaton_decl->name);
8577 /* Maximal length of line for pretty printing into description
8578 file. */
8579 #define MAX_LINE_LENGTH 70
8581 /* The function outputs units name belonging to AUTOMATON. */
8582 static void
8583 output_automaton_units (automaton_t automaton)
8585 decl_t decl;
8586 const char *name;
8587 int curr_line_length;
8588 int there_is_an_automaton_unit;
8589 int i;
8591 fprintf (output_description_file, "\n Corresponding units:\n");
8592 fprintf (output_description_file, " ");
8593 curr_line_length = 4;
8594 there_is_an_automaton_unit = 0;
8595 for (i = 0; i < description->decls_num; i++)
8597 decl = description->decls [i];
8598 if (decl->mode == dm_unit
8599 && (DECL_UNIT (decl)->corresponding_automaton_num
8600 == automaton->automaton_order_num))
8602 there_is_an_automaton_unit = 1;
8603 name = DECL_UNIT (decl)->name;
8604 if (curr_line_length + strlen (name) + 1 > MAX_LINE_LENGTH )
8606 curr_line_length = strlen (name) + 4;
8607 fprintf (output_description_file, "\n ");
8609 else
8611 curr_line_length += strlen (name) + 1;
8612 fprintf (output_description_file, " ");
8614 fprintf (output_description_file, "%s", name);
8617 if (!there_is_an_automaton_unit)
8618 fprintf (output_description_file, "<None>");
8619 fprintf (output_description_file, "\n\n");
8622 /* The following variable is used for forming array of all possible cpu unit
8623 reservations described by the current DFA state. */
8624 static VEC(reserv_sets_t,heap) *state_reservs;
8626 /* The function forms `state_reservs' for STATE. */
8627 static void
8628 add_state_reservs (state_t state)
8630 alt_state_t curr_alt_state;
8632 if (state->component_states != NULL)
8633 for (curr_alt_state = state->component_states;
8634 curr_alt_state != NULL;
8635 curr_alt_state = curr_alt_state->next_sorted_alt_state)
8636 add_state_reservs (curr_alt_state->state);
8637 else
8638 VEC_safe_push (reserv_sets_t,heap, state_reservs, state->reservs);
8641 /* The function outputs readable representation of all out arcs of
8642 STATE. */
8643 static void
8644 output_state_arcs (state_t state)
8646 arc_t arc;
8647 ainsn_t ainsn;
8648 const char *insn_name;
8649 int curr_line_length;
8651 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
8653 ainsn = arc->insn;
8654 gcc_assert (ainsn->first_insn_with_same_reservs);
8655 fprintf (output_description_file, " ");
8656 curr_line_length = 7;
8657 fprintf (output_description_file, "%2d: ", ainsn->insn_equiv_class_num);
8660 insn_name = ainsn->insn_reserv_decl->name;
8661 if (curr_line_length + strlen (insn_name) > MAX_LINE_LENGTH)
8663 if (ainsn != arc->insn)
8665 fprintf (output_description_file, ",\n ");
8666 curr_line_length = strlen (insn_name) + 6;
8668 else
8669 curr_line_length += strlen (insn_name);
8671 else
8673 curr_line_length += strlen (insn_name);
8674 if (ainsn != arc->insn)
8676 curr_line_length += 2;
8677 fprintf (output_description_file, ", ");
8680 fprintf (output_description_file, "%s", insn_name);
8681 ainsn = ainsn->next_same_reservs_insn;
8683 while (ainsn != NULL);
8684 fprintf (output_description_file, " %d \n",
8685 arc->to_state->order_state_num);
8687 fprintf (output_description_file, "\n");
8690 /* The following function is used for sorting possible cpu unit
8691 reservation of a DFA state. */
8692 static int
8693 state_reservs_cmp (const void *reservs_ptr_1, const void *reservs_ptr_2)
8695 return reserv_sets_cmp (*(reserv_sets_t *) reservs_ptr_1,
8696 *(reserv_sets_t *) reservs_ptr_2);
8699 /* The following function is used for sorting possible cpu unit
8700 reservation of a DFA state. */
8701 static void
8702 remove_state_duplicate_reservs (void)
8704 size_t i, j;
8706 for (i = 1, j = 0; i < VEC_length (reserv_sets_t, state_reservs); i++)
8707 if (reserv_sets_cmp (VEC_index (reserv_sets_t, state_reservs, j),
8708 VEC_index (reserv_sets_t, state_reservs, i)))
8710 j++;
8711 VEC_replace (reserv_sets_t, state_reservs, j,
8712 VEC_index (reserv_sets_t, state_reservs, i));
8714 VEC_truncate (reserv_sets_t, state_reservs, j + 1);
8717 /* The following function output readable representation of DFA(s)
8718 state used for fast recognition of pipeline hazards. State is
8719 described by possible (current and scheduled) cpu unit
8720 reservations. */
8721 static void
8722 output_state (state_t state)
8724 size_t i;
8726 state_reservs = 0;
8728 fprintf (output_description_file, " State #%d", state->order_state_num);
8729 fprintf (output_description_file,
8730 state->new_cycle_p ? " (new cycle)\n" : "\n");
8731 add_state_reservs (state);
8732 qsort (VEC_address (reserv_sets_t, state_reservs),
8733 VEC_length (reserv_sets_t, state_reservs),
8734 sizeof (reserv_sets_t), state_reservs_cmp);
8735 remove_state_duplicate_reservs ();
8736 for (i = 1; i < VEC_length (reserv_sets_t, state_reservs); i++)
8738 fprintf (output_description_file, " ");
8739 output_reserv_sets (output_description_file,
8740 VEC_index (reserv_sets_t, state_reservs, i));
8741 fprintf (output_description_file, "\n");
8743 fprintf (output_description_file, "\n");
8744 output_state_arcs (state);
8745 VEC_free (reserv_sets_t,heap, state_reservs);
8748 /* The following function output readable representation of
8749 DFAs used for fast recognition of pipeline hazards. */
8750 static void
8751 output_automaton_descriptions (void)
8753 automaton_t automaton;
8755 for (automaton = description->first_automaton;
8756 automaton != NULL;
8757 automaton = automaton->next_automaton)
8759 fprintf (output_description_file, "\nAutomaton ");
8760 output_automaton_name (output_description_file, automaton);
8761 fprintf (output_description_file, "\n");
8762 output_automaton_units (automaton);
8763 pass_states (automaton, output_state);
8769 /* The page contains top level function for generation DFA(s) used for
8770 PHR. */
8772 /* The function outputs statistics about work of different phases of
8773 DFA generator. */
8774 static void
8775 output_statistics (FILE *f)
8777 automaton_t automaton;
8778 int states_num;
8779 #ifndef NDEBUG
8780 int transition_comb_vect_els = 0;
8781 int transition_full_vect_els = 0;
8782 int min_issue_delay_vect_els = 0;
8783 int locked_states = 0;
8784 #endif
8786 for (automaton = description->first_automaton;
8787 automaton != NULL;
8788 automaton = automaton->next_automaton)
8790 fprintf (f, "\nAutomaton ");
8791 output_automaton_name (f, automaton);
8792 fprintf (f, "\n %5d NDFA states, %5d NDFA arcs\n",
8793 automaton->NDFA_states_num, automaton->NDFA_arcs_num);
8794 fprintf (f, " %5d DFA states, %5d DFA arcs\n",
8795 automaton->DFA_states_num, automaton->DFA_arcs_num);
8796 states_num = automaton->DFA_states_num;
8797 if (!no_minimization_flag)
8799 fprintf (f, " %5d minimal DFA states, %5d minimal DFA arcs\n",
8800 automaton->minimal_DFA_states_num,
8801 automaton->minimal_DFA_arcs_num);
8802 states_num = automaton->minimal_DFA_states_num;
8804 fprintf (f, " %5d all insns %5d insn equivalence classes\n",
8805 description->insns_num, automaton->insn_equiv_classes_num);
8806 fprintf (f, " %d locked states\n", automaton->locked_states);
8807 #ifndef NDEBUG
8808 fprintf
8809 (f, "%5ld transition comb vector els, %5ld trans table els: %s\n",
8810 (long) VEC_length (vect_el_t, automaton->trans_table->comb_vect),
8811 (long) VEC_length (vect_el_t, automaton->trans_table->full_vect),
8812 (comb_vect_p (automaton->trans_table)
8813 ? "use comb vect" : "use simple vect"));
8814 fprintf
8815 (f, "%5ld min delay table els, compression factor %d\n",
8816 (long) states_num * automaton->insn_equiv_classes_num,
8817 automaton->min_issue_delay_table_compression_factor);
8818 transition_comb_vect_els
8819 += VEC_length (vect_el_t, automaton->trans_table->comb_vect);
8820 transition_full_vect_els
8821 += VEC_length (vect_el_t, automaton->trans_table->full_vect);
8822 min_issue_delay_vect_els
8823 += states_num * automaton->insn_equiv_classes_num;
8824 locked_states
8825 += automaton->locked_states;
8826 #endif
8828 #ifndef NDEBUG
8829 fprintf (f, "\n%5d all allocated states, %5d all allocated arcs\n",
8830 allocated_states_num, allocated_arcs_num);
8831 fprintf (f, "%5d all allocated alternative states\n",
8832 allocated_alt_states_num);
8833 fprintf (f, "%5d all transition comb vector els, %5d all trans table els\n",
8834 transition_comb_vect_els, transition_full_vect_els);
8835 fprintf (f, "%5d all min delay table els\n", min_issue_delay_vect_els);
8836 fprintf (f, "%5d all locked states\n", locked_states);
8837 #endif
8840 /* The function output times of work of different phases of DFA
8841 generator. */
8842 static void
8843 output_time_statistics (FILE *f)
8845 fprintf (f, "\n transformation: ");
8846 print_active_time (f, transform_time);
8847 fprintf (f, (!ndfa_flag ? ", building DFA: " : ", building NDFA: "));
8848 print_active_time (f, NDFA_time);
8849 if (ndfa_flag)
8851 fprintf (f, ", NDFA -> DFA: ");
8852 print_active_time (f, NDFA_to_DFA_time);
8854 fprintf (f, "\n DFA minimization: ");
8855 print_active_time (f, minimize_time);
8856 fprintf (f, ", making insn equivalence: ");
8857 print_active_time (f, equiv_time);
8858 fprintf (f, "\n all automaton generation: ");
8859 print_active_time (f, automaton_generation_time);
8860 fprintf (f, ", output: ");
8861 print_active_time (f, output_time);
8862 fprintf (f, "\n");
8865 /* The function generates DFA (deterministic finite state automaton)
8866 for fast recognition of pipeline hazards. No errors during
8867 checking must be fixed before this function call. */
8868 static void
8869 generate (void)
8871 automata_num = split_argument;
8872 if (description->units_num < automata_num)
8873 automata_num = description->units_num;
8874 initiate_states ();
8875 initiate_arcs ();
8876 initiate_automata_lists ();
8877 initiate_pass_states ();
8878 initiate_excl_sets ();
8879 initiate_presence_absence_pattern_sets ();
8880 automaton_generation_time = create_ticker ();
8881 create_automata ();
8882 ticker_off (&automaton_generation_time);
8887 /* This page mainly contains top level functions of pipeline hazards
8888 description translator. */
8890 /* The following macro value is suffix of name of description file of
8891 pipeline hazards description translator. */
8892 #define STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX ".dfa"
8894 /* The function returns suffix of given file name. The returned
8895 string can not be changed. */
8896 static const char *
8897 file_name_suffix (const char *file_name)
8899 const char *last_period;
8901 for (last_period = NULL; *file_name != '\0'; file_name++)
8902 if (*file_name == '.')
8903 last_period = file_name;
8904 return (last_period == NULL ? file_name : last_period);
8907 /* The function returns base name of given file name, i.e. pointer to
8908 first char after last `/' (or `\' for WIN32) in given file name,
8909 given file name itself if the directory name is absent. The
8910 returned string can not be changed. */
8911 static const char *
8912 base_file_name (const char *file_name)
8914 int directory_name_length;
8916 directory_name_length = strlen (file_name);
8917 #ifdef WIN32
8918 while (directory_name_length >= 0 && file_name[directory_name_length] != '/'
8919 && file_name[directory_name_length] != '\\')
8920 #else
8921 while (directory_name_length >= 0 && file_name[directory_name_length] != '/')
8922 #endif
8923 directory_name_length--;
8924 return file_name + directory_name_length + 1;
8927 /* The following is top level function to initialize the work of
8928 pipeline hazards description translator. */
8929 static void
8930 initiate_automaton_gen (int argc, char **argv)
8932 const char *base_name;
8933 int i;
8935 ndfa_flag = 0;
8936 split_argument = 0; /* default value */
8937 no_minimization_flag = 0;
8938 time_flag = 0;
8939 v_flag = 0;
8940 w_flag = 0;
8941 progress_flag = 0;
8942 for (i = 2; i < argc; i++)
8943 if (strcmp (argv [i], NO_MINIMIZATION_OPTION) == 0)
8944 no_minimization_flag = 1;
8945 else if (strcmp (argv [i], TIME_OPTION) == 0)
8946 time_flag = 1;
8947 else if (strcmp (argv [i], V_OPTION) == 0)
8948 v_flag = 1;
8949 else if (strcmp (argv [i], W_OPTION) == 0)
8950 w_flag = 1;
8951 else if (strcmp (argv [i], NDFA_OPTION) == 0)
8952 ndfa_flag = 1;
8953 else if (strcmp (argv [i], PROGRESS_OPTION) == 0)
8954 progress_flag = 1;
8955 else if (strcmp (argv [i], "-split") == 0)
8957 if (i + 1 >= argc)
8958 fatal ("-split has no argument.");
8959 fatal ("option `-split' has not been implemented yet\n");
8960 /* split_argument = atoi (argument_vect [i + 1]); */
8963 /* Initialize IR storage. */
8964 obstack_init (&irp);
8965 initiate_automaton_decl_table ();
8966 initiate_insn_decl_table ();
8967 initiate_decl_table ();
8968 output_file = stdout;
8969 output_description_file = NULL;
8970 base_name = base_file_name (argv[1]);
8971 obstack_grow (&irp, base_name,
8972 strlen (base_name) - strlen (file_name_suffix (base_name)));
8973 obstack_grow (&irp, STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX,
8974 strlen (STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX) + 1);
8975 obstack_1grow (&irp, '\0');
8976 output_description_file_name = obstack_base (&irp);
8977 obstack_finish (&irp);
8980 /* The following function checks existence at least one arc marked by
8981 each insn. */
8982 static void
8983 check_automata_insn_issues (void)
8985 automaton_t automaton;
8986 ainsn_t ainsn, reserv_ainsn;
8988 for (automaton = description->first_automaton;
8989 automaton != NULL;
8990 automaton = automaton->next_automaton)
8992 for (ainsn = automaton->ainsn_list;
8993 ainsn != NULL;
8994 ainsn = ainsn->next_ainsn)
8995 if (ainsn->first_insn_with_same_reservs && !ainsn->arc_exists_p)
8997 for (reserv_ainsn = ainsn;
8998 reserv_ainsn != NULL;
8999 reserv_ainsn = reserv_ainsn->next_same_reservs_insn)
9000 if (automaton->corresponding_automaton_decl != NULL)
9002 if (!w_flag)
9003 error ("Automaton `%s': Insn `%s' will never be issued",
9004 automaton->corresponding_automaton_decl->name,
9005 reserv_ainsn->insn_reserv_decl->name);
9006 else
9007 warning
9008 (0, "Automaton `%s': Insn `%s' will never be issued",
9009 automaton->corresponding_automaton_decl->name,
9010 reserv_ainsn->insn_reserv_decl->name);
9012 else
9014 if (!w_flag)
9015 error ("Insn `%s' will never be issued",
9016 reserv_ainsn->insn_reserv_decl->name);
9017 else
9018 warning (0, "Insn `%s' will never be issued",
9019 reserv_ainsn->insn_reserv_decl->name);
9025 /* The following vla is used for storing pointers to all achieved
9026 states. */
9027 static VEC(state_t,heap) *automaton_states;
9029 /* This function is called by function pass_states to add an achieved
9030 STATE. */
9031 static void
9032 add_automaton_state (state_t state)
9034 VEC_safe_push (state_t,heap, automaton_states, state);
9037 /* The following function forms list of important automata (whose
9038 states may be changed after the insn issue) for each insn. */
9039 static void
9040 form_important_insn_automata_lists (void)
9042 automaton_t automaton;
9043 decl_t decl;
9044 ainsn_t ainsn;
9045 arc_t arc;
9046 int i;
9047 size_t n;
9049 automaton_states = 0;
9050 /* Mark important ainsns. */
9051 for (automaton = description->first_automaton;
9052 automaton != NULL;
9053 automaton = automaton->next_automaton)
9055 VEC_truncate (state_t, automaton_states, 0);
9056 pass_states (automaton, add_automaton_state);
9057 for (n = 0; n < VEC_length (state_t, automaton_states); n++)
9059 state_t s = VEC_index (state_t, automaton_states, n);
9060 for (arc = first_out_arc (s);
9061 arc != NULL;
9062 arc = next_out_arc (arc))
9063 if (arc->to_state != s)
9065 gcc_assert (arc->insn->first_insn_with_same_reservs);
9066 for (ainsn = arc->insn;
9067 ainsn != NULL;
9068 ainsn = ainsn->next_same_reservs_insn)
9069 ainsn->important_p = TRUE;
9073 VEC_free (state_t,heap, automaton_states);
9075 /* Create automata sets for the insns. */
9076 for (i = 0; i < description->decls_num; i++)
9078 decl = description->decls [i];
9079 if (decl->mode == dm_insn_reserv)
9081 automata_list_start ();
9082 for (automaton = description->first_automaton;
9083 automaton != NULL;
9084 automaton = automaton->next_automaton)
9085 for (ainsn = automaton->ainsn_list;
9086 ainsn != NULL;
9087 ainsn = ainsn->next_ainsn)
9088 if (ainsn->important_p
9089 && ainsn->insn_reserv_decl == DECL_INSN_RESERV (decl))
9091 automata_list_add (automaton);
9092 break;
9094 DECL_INSN_RESERV (decl)->important_automata_list
9095 = automata_list_finish ();
9101 /* The following is top level function to generate automat(a,on) for
9102 fast recognition of pipeline hazards. */
9103 static void
9104 expand_automata (void)
9106 int i;
9108 description = create_node (sizeof (struct description)
9109 /* One entry for cycle advancing insn. */
9110 + sizeof (decl_t) * VEC_length (decl_t, decls));
9111 description->decls_num = VEC_length (decl_t, decls);
9112 description->query_units_num = 0;
9113 for (i = 0; i < description->decls_num; i++)
9115 description->decls [i] = VEC_index (decl_t, decls, i);
9116 if (description->decls [i]->mode == dm_unit
9117 && DECL_UNIT (description->decls [i])->query_p)
9118 DECL_UNIT (description->decls [i])->query_num
9119 = description->query_units_num++;
9121 all_time = create_ticker ();
9122 check_time = create_ticker ();
9123 if (progress_flag)
9124 fprintf (stderr, "Check description...");
9125 check_all_description ();
9126 if (progress_flag)
9127 fprintf (stderr, "done\n");
9128 ticker_off (&check_time);
9129 generation_time = create_ticker ();
9130 if (!have_error)
9132 transform_insn_regexps ();
9133 check_unit_distributions_to_automata ();
9135 if (!have_error)
9137 generate ();
9138 check_automata_insn_issues ();
9140 if (!have_error)
9142 form_important_insn_automata_lists ();
9144 ticker_off (&generation_time);
9147 /* The following is top level function to output PHR and to finish
9148 work with pipeline description translator. */
9149 static void
9150 write_automata (void)
9152 output_time = create_ticker ();
9153 if (progress_flag)
9154 fprintf (stderr, "Forming and outputting automata tables...");
9155 output_tables ();
9156 if (progress_flag)
9158 fprintf (stderr, "done\n");
9159 fprintf (stderr, "Output functions to work with automata...");
9161 output_chip_definitions ();
9162 output_max_insn_queue_index_def ();
9163 output_internal_min_issue_delay_func ();
9164 output_internal_trans_func ();
9165 /* Cache of insn dfa codes: */
9166 fprintf (output_file, "\nstatic int *%s;\n", DFA_INSN_CODES_VARIABLE_NAME);
9167 fprintf (output_file, "\nstatic int %s;\n\n",
9168 DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
9169 output_dfa_insn_code_func ();
9170 output_trans_func ();
9171 output_min_issue_delay_func ();
9172 output_internal_dead_lock_func ();
9173 output_dead_lock_func ();
9174 output_size_func ();
9175 output_internal_reset_func ();
9176 output_reset_func ();
9177 output_min_insn_conflict_delay_func ();
9178 output_internal_insn_latency_func ();
9179 output_insn_latency_func ();
9180 output_print_reservation_func ();
9181 /* Output function get_cpu_unit_code. */
9182 fprintf (output_file, "\n#if %s\n\n", CPU_UNITS_QUERY_MACRO_NAME);
9183 output_get_cpu_unit_code_func ();
9184 output_cpu_unit_reservation_p ();
9185 fprintf (output_file, "\n#endif /* #if %s */\n\n",
9186 CPU_UNITS_QUERY_MACRO_NAME);
9187 output_dfa_clean_insn_cache_func ();
9188 output_dfa_start_func ();
9189 output_dfa_finish_func ();
9190 if (progress_flag)
9191 fprintf (stderr, "done\n");
9192 if (v_flag)
9194 output_description_file = fopen (output_description_file_name, "w");
9195 if (output_description_file == NULL)
9197 perror (output_description_file_name);
9198 exit (FATAL_EXIT_CODE);
9200 if (progress_flag)
9201 fprintf (stderr, "Output automata description...");
9202 output_description ();
9203 output_automaton_descriptions ();
9204 if (progress_flag)
9205 fprintf (stderr, "done\n");
9206 output_statistics (output_description_file);
9208 output_statistics (stderr);
9209 ticker_off (&output_time);
9210 output_time_statistics (stderr);
9211 finish_states ();
9212 finish_arcs ();
9213 finish_automata_lists ();
9214 if (time_flag)
9216 fprintf (stderr, "Summary:\n");
9217 fprintf (stderr, " check time ");
9218 print_active_time (stderr, check_time);
9219 fprintf (stderr, ", generation time ");
9220 print_active_time (stderr, generation_time);
9221 fprintf (stderr, ", all time ");
9222 print_active_time (stderr, all_time);
9223 fprintf (stderr, "\n");
9225 /* Finish all work. */
9226 if (output_description_file != NULL)
9228 fflush (output_description_file);
9229 if (ferror (stdout) != 0)
9230 fatal ("Error in writing DFA description file %s",
9231 output_description_file_name);
9232 fclose (output_description_file);
9234 finish_automaton_decl_table ();
9235 finish_insn_decl_table ();
9236 finish_decl_table ();
9237 obstack_free (&irp, NULL);
9238 if (have_error && output_description_file != NULL)
9239 remove (output_description_file_name);
9243 main (int argc, char **argv)
9245 rtx desc;
9247 progname = "genautomata";
9249 if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
9250 return (FATAL_EXIT_CODE);
9252 initiate_automaton_gen (argc, argv);
9253 while (1)
9255 int lineno;
9256 int insn_code_number;
9258 desc = read_md_rtx (&lineno, &insn_code_number);
9259 if (desc == NULL)
9260 break;
9262 switch (GET_CODE (desc))
9264 case DEFINE_CPU_UNIT:
9265 gen_cpu_unit (desc);
9266 break;
9268 case DEFINE_QUERY_CPU_UNIT:
9269 gen_query_cpu_unit (desc);
9270 break;
9272 case DEFINE_BYPASS:
9273 gen_bypass (desc);
9274 break;
9276 case EXCLUSION_SET:
9277 gen_excl_set (desc);
9278 break;
9280 case PRESENCE_SET:
9281 gen_presence_set (desc);
9282 break;
9284 case FINAL_PRESENCE_SET:
9285 gen_final_presence_set (desc);
9286 break;
9288 case ABSENCE_SET:
9289 gen_absence_set (desc);
9290 break;
9292 case FINAL_ABSENCE_SET:
9293 gen_final_absence_set (desc);
9294 break;
9296 case DEFINE_AUTOMATON:
9297 gen_automaton (desc);
9298 break;
9300 case AUTOMATA_OPTION:
9301 gen_automata_option (desc);
9302 break;
9304 case DEFINE_RESERVATION:
9305 gen_reserv (desc);
9306 break;
9308 case DEFINE_INSN_RESERVATION:
9309 gen_insn_reserv (desc);
9310 break;
9312 default:
9313 break;
9317 if (have_error)
9318 return FATAL_EXIT_CODE;
9320 puts ("/* Generated automatically by the program `genautomata'\n"
9321 " from the machine description file `md'. */\n\n"
9322 "#include \"config.h\"\n"
9323 "#include \"system.h\"\n"
9324 "#include \"coretypes.h\"\n"
9325 "#include \"tm.h\"\n"
9326 "#include \"rtl.h\"\n"
9327 "#include \"tm_p.h\"\n"
9328 "#include \"insn-config.h\"\n"
9329 "#include \"recog.h\"\n"
9330 "#include \"regs.h\"\n"
9331 "#include \"real.h\"\n"
9332 "#include \"output.h\"\n"
9333 "#include \"insn-attr.h\"\n"
9334 "#include \"toplev.h\"\n"
9335 "#include \"flags.h\"\n"
9336 "#include \"function.h\"\n");
9338 if (VEC_length (decl_t, decls) > 0)
9340 expand_automata ();
9341 write_automata ();
9344 fflush (stdout);
9345 return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);