* config/i386/i386.md (paritydi2, paritysi2): New expanders.
[official-gcc.git] / gcc / genautomata.c
blob26eb281e812ad0abadedf2e86fcfdf05969c6b28
1 /* Pipeline hazard description translator.
2 Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007
3 Free Software Foundation, Inc.
5 Written by Vladimir Makarov <vmakarov@redhat.com>
7 This file is part of GCC.
9 GCC is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by the
11 Free Software Foundation; either version 2, or (at your option) any
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 COPYING. If not, write to the Free
21 Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
22 02110-1301, USA. */
24 /* References:
26 1. Detecting pipeline structural hazards quickly. T. Proebsting,
27 C. Fraser. Proceedings of ACM SIGPLAN-SIGACT Symposium on
28 Principles of Programming Languages, pages 280--286, 1994.
30 This article is a good start point to understand usage of finite
31 state automata for pipeline hazard recognizers. But I'd
32 recommend the 2nd article for more deep understanding.
34 2. Efficient Instruction Scheduling Using Finite State Automata:
35 V. Bala and N. Rubin, Proceedings of MICRO-28. This is the best
36 article about usage of finite state automata for pipeline hazard
37 recognizers.
39 The current implementation is different from the 2nd article in the
40 following:
42 1. New operator `|' (alternative) is permitted in functional unit
43 reservation which can be treated deterministically and
44 non-deterministically.
46 2. Possibility of usage of nondeterministic automata too.
48 3. Possibility to query functional unit reservations for given
49 automaton state.
51 4. Several constructions to describe impossible reservations
52 (`exclusion_set', `presence_set', `final_presence_set',
53 `absence_set', and `final_absence_set').
55 5. No reverse automata are generated. Trace instruction scheduling
56 requires this. It can be easily added in the future if we
57 really need this.
59 6. Union of automaton states are not generated yet. It is planned
60 to be implemented. Such feature is needed to make more accurate
61 interlock insn scheduling to get state describing functional
62 unit reservation in a joint CFG point. */
64 /* This file code processes constructions of machine description file
65 which describes automaton used for recognition of processor pipeline
66 hazards by insn scheduler and can be used for other tasks (such as
67 VLIW insn packing.
69 The translator functions `gen_cpu_unit', `gen_query_cpu_unit',
70 `gen_bypass', `gen_excl_set', `gen_presence_set',
71 `gen_final_presence_set', `gen_absence_set',
72 `gen_final_absence_set', `gen_automaton', `gen_automata_option',
73 `gen_reserv', `gen_insn_reserv' are called from file
74 `genattrtab.c'. They transform RTL constructions describing
75 automata in .md file into internal representation convenient for
76 further processing.
78 The translator major function `expand_automata' processes the
79 description internal representation into finite state automaton.
80 It can be divided on:
82 o checking correctness of the automaton pipeline description
83 (major function is `check_all_description').
85 o generating automaton (automata) from the description (major
86 function is `make_automaton').
88 o optional transformation of nondeterministic finite state
89 automata into deterministic ones if the alternative operator
90 `|' is treated nondeterministically in the description (major
91 function is NDFA_to_DFA).
93 o optional minimization of the finite state automata by merging
94 equivalent automaton states (major function is `minimize_DFA').
96 o forming tables (some as comb vectors) and attributes
97 representing the automata (functions output_..._table).
99 Function `write_automata' outputs the created finite state
100 automaton as different tables and functions which works with the
101 automata to inquire automaton state and to change its state. These
102 function are used by gcc instruction scheduler and may be some
103 other gcc code. */
105 #include "bconfig.h"
106 #include "system.h"
107 #include "coretypes.h"
108 #include "tm.h"
109 #include "rtl.h"
110 #include "obstack.h"
111 #include "errors.h"
112 #include "gensupport.h"
114 #include <math.h>
115 #include "hashtab.h"
116 #include "vec.h"
118 #ifndef CHAR_BIT
119 #define CHAR_BIT 8
120 #endif
122 /* Positions in machine description file. Now they are not used. But
123 they could be used in the future for better diagnostic messages. */
124 typedef int pos_t;
126 /* The following is element of vector of current (and planned in the
127 future) functional unit reservations. */
128 typedef unsigned HOST_WIDE_INT set_el_t;
130 /* Reservations of function units are represented by value of the following
131 type. */
132 typedef set_el_t *reserv_sets_t;
134 /* The following structure describes a ticker. */
135 struct ticker
137 /* The following member value is time of the ticker creation with
138 taking into account time when the ticker is off. Active time of
139 the ticker is current time minus the value. */
140 int modified_creation_time;
141 /* The following member value is time (incremented by one) when the
142 ticker was off. Zero value means that now the ticker is on. */
143 int incremented_off_time;
146 /* The ticker is represented by the following type. */
147 typedef struct ticker ticker_t;
149 /* The following type describes elements of output vectors. */
150 typedef HOST_WIDE_INT vect_el_t;
152 /* Forward declaration of structures of internal representation of
153 pipeline description based on NDFA. */
155 struct unit_decl;
156 struct bypass_decl;
157 struct result_decl;
158 struct automaton_decl;
159 struct unit_pattern_rel_decl;
160 struct reserv_decl;
161 struct insn_reserv_decl;
162 struct decl;
163 struct unit_regexp;
164 struct result_regexp;
165 struct reserv_regexp;
166 struct nothing_regexp;
167 struct sequence_regexp;
168 struct repeat_regexp;
169 struct allof_regexp;
170 struct oneof_regexp;
171 struct regexp;
172 struct description;
173 struct unit_set_el;
174 struct pattern_set_el;
175 struct pattern_reserv;
176 struct state;
177 struct alt_state;
178 struct arc;
179 struct ainsn;
180 struct automaton;
181 struct state_ainsn_table;
183 /* The following typedefs are for brevity. */
184 typedef struct unit_decl *unit_decl_t;
185 typedef struct decl *decl_t;
186 typedef struct regexp *regexp_t;
187 typedef struct unit_set_el *unit_set_el_t;
188 typedef struct pattern_set_el *pattern_set_el_t;
189 typedef struct pattern_reserv *pattern_reserv_t;
190 typedef struct alt_state *alt_state_t;
191 typedef struct state *state_t;
192 typedef struct arc *arc_t;
193 typedef struct ainsn *ainsn_t;
194 typedef struct automaton *automaton_t;
195 typedef struct automata_list_el *automata_list_el_t;
196 typedef struct state_ainsn_table *state_ainsn_table_t;
198 /* Undefined position. */
199 static pos_t no_pos = 0;
201 /* All IR is stored in the following obstack. */
202 static struct obstack irp;
205 /* Declare vector types for various data structures: */
207 DEF_VEC_P(alt_state_t);
208 DEF_VEC_ALLOC_P(alt_state_t,heap);
209 DEF_VEC_P(ainsn_t);
210 DEF_VEC_ALLOC_P(ainsn_t,heap);
211 DEF_VEC_P(state_t);
212 DEF_VEC_ALLOC_P(state_t,heap);
213 DEF_VEC_P(decl_t);
214 DEF_VEC_ALLOC_P(decl_t,heap);
215 DEF_VEC_P(reserv_sets_t);
216 DEF_VEC_ALLOC_P(reserv_sets_t,heap);
218 DEF_VEC_I(vect_el_t);
219 DEF_VEC_ALLOC_I(vect_el_t, heap);
220 typedef VEC(vect_el_t,heap) *vla_hwint_t;
222 /* Forward declarations of functions used before their definitions, only. */
223 static regexp_t gen_regexp_sequence (const char *);
224 static void reserv_sets_or (reserv_sets_t, reserv_sets_t,
225 reserv_sets_t);
226 static reserv_sets_t get_excl_set (reserv_sets_t);
227 static int check_presence_pattern_sets (reserv_sets_t,
228 reserv_sets_t, int);
229 static int check_absence_pattern_sets (reserv_sets_t, reserv_sets_t,
230 int);
231 static arc_t first_out_arc (state_t);
232 static arc_t next_out_arc (arc_t);
236 /* Options with the following names can be set up in automata_option
237 construction. Because the strings occur more one time we use the
238 macros. */
240 #define NO_MINIMIZATION_OPTION "-no-minimization"
241 #define TIME_OPTION "-time"
242 #define STATS_OPTION "-stats"
243 #define V_OPTION "-v"
244 #define W_OPTION "-w"
245 #define NDFA_OPTION "-ndfa"
246 #define PROGRESS_OPTION "-progress"
248 /* The following flags are set up by function `initiate_automaton_gen'. */
250 /* Make automata with nondeterministic reservation by insns (`-ndfa'). */
251 static int ndfa_flag;
253 /* Do not make minimization of DFA (`-no-minimization'). */
254 static int no_minimization_flag;
256 /* Value of this variable is number of automata being generated. The
257 actual number of automata may be less this value if there is not
258 sufficient number of units. This value is defined by argument of
259 option `-split' or by constructions automaton if the value is zero
260 (it is default value of the argument). */
261 static int split_argument;
263 /* Flag of output time statistics (`-time'). */
264 static int time_flag;
266 /* Flag of automata statistics (`-stats'). */
267 static int stats_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;
716 /* Automaton arc. */
717 struct arc
719 /* The following field refers for the state into which given arc
720 enters. */
721 state_t to_state;
722 /* The following field describes that the insn issue (with cycle
723 advancing for special insn `cycle advancing' and without cycle
724 advancing for others) makes transition from given state to
725 another given state. */
726 ainsn_t insn;
727 /* The following field value is the next arc output from the same
728 state. */
729 arc_t next_out_arc;
730 /* List of arcs marked given insn is formed with the following
731 field. The field is used in transformation NDFA -> DFA. */
732 arc_t next_arc_marked_by_insn;
735 /* The following node type describes a deterministic alternative in
736 non-deterministic state which characterizes cpu unit reservations
737 of automaton insn or which is part of NDFA. */
738 struct alt_state
740 /* The following field is a deterministic state which characterizes
741 unit reservations of the instruction. */
742 state_t state;
743 /* The following field refers to the next state which characterizes
744 unit reservations of the instruction. */
745 alt_state_t next_alt_state;
746 /* The following field refers to the next state in sorted list. */
747 alt_state_t next_sorted_alt_state;
750 /* The following node type describes insn of automaton. They are
751 labels of FA arcs. */
752 struct ainsn
754 /* The following field value is the corresponding insn declaration
755 of description. */
756 struct insn_reserv_decl *insn_reserv_decl;
757 /* The following field value is the next insn declaration for an
758 automaton. */
759 ainsn_t next_ainsn;
760 /* The following field is states which characterize automaton unit
761 reservations of the instruction. The value can be NULL only if it
762 is special insn `cycle advancing'. */
763 alt_state_t alt_states;
764 /* The following field is sorted list of states which characterize
765 automaton unit reservations of the instruction. The value can be
766 NULL only if it is special insn `cycle advancing'. */
767 alt_state_t sorted_alt_states;
768 /* The following field refers the next automaton insn with
769 the same reservations. */
770 ainsn_t next_same_reservs_insn;
771 /* The following field is flag of the first automaton insn with the
772 same reservations in the declaration list. Only arcs marked such
773 insn is present in the automaton. This significantly decreases
774 memory requirements especially when several automata are
775 formed. */
776 char first_insn_with_same_reservs;
777 /* The following member has nonzero value if there is arc from state of
778 the automaton marked by the ainsn. */
779 char arc_exists_p;
780 /* Cyclic list of insns of an equivalence class is formed with the
781 aid of the following field. */
782 ainsn_t next_equiv_class_insn;
783 /* The following field value is nonzero if the insn declaration is
784 the first insn declaration with given equivalence number. */
785 char first_ainsn_with_given_equivalence_num;
786 /* The following field is number of class of equivalence of insns.
787 It is necessary because many insns may be equivalent with the
788 point of view of pipeline hazards. */
789 int insn_equiv_class_num;
790 /* The following member value is TRUE if there is an arc in the
791 automaton marked by the insn into another state. In other
792 words, the insn can change the state of the automaton. */
793 int important_p;
796 /* The following describes an automaton for PHR. */
797 struct automaton
799 /* The following field value is the list of insn declarations for
800 given automaton. */
801 ainsn_t ainsn_list;
802 /* The following field value is the corresponding automaton
803 declaration. This field is not NULL only if the automatic
804 partition on automata is not used. */
805 struct automaton_decl *corresponding_automaton_decl;
806 /* The following field value is the next automaton. */
807 automaton_t next_automaton;
808 /* The following field is start state of FA. There are not unit
809 reservations in the state. */
810 state_t start_state;
811 /* The following field value is number of equivalence classes of
812 insns (see field `insn_equiv_class_num' in
813 `insn_reserv_decl'). */
814 int insn_equiv_classes_num;
815 /* The following field value is number of states of final DFA. */
816 int achieved_states_num;
817 /* The following field value is the order number (0, 1, ...) of
818 given automaton. */
819 int automaton_order_num;
820 /* The following fields contain statistics information about
821 building automaton. */
822 int NDFA_states_num, DFA_states_num;
823 /* The following field value is defined only if minimization of DFA
824 is used. */
825 int minimal_DFA_states_num;
826 int NDFA_arcs_num, DFA_arcs_num;
827 /* The following field value is defined only if minimization of DFA
828 is used. */
829 int minimal_DFA_arcs_num;
830 /* The following member refers for two table state x ainsn -> int.
831 ??? Above sentence is incomprehensible. */
832 state_ainsn_table_t trans_table;
833 /* The following member value is maximal value of min issue delay
834 for insns of the automaton. */
835 int max_min_delay;
836 /* Usually min issue delay is small and we can place several (2, 4,
837 8) elements in one vector element. So the compression factor can
838 be 1 (no compression), 2, 4, 8. */
839 int min_issue_delay_table_compression_factor;
840 /* Total number of locked states in this automaton. */
841 int locked_states;
844 /* The following is the element of the list of automata. */
845 struct automata_list_el
847 /* The automaton itself. */
848 automaton_t automaton;
849 /* The next automata set element. */
850 automata_list_el_t next_automata_list_el;
853 /* The following structure describes a table state X ainsn -> int(>= 0). */
854 struct state_ainsn_table
856 /* Automaton to which given table belongs. */
857 automaton_t automaton;
858 /* The following tree vectors for comb vector implementation of the
859 table. */
860 vla_hwint_t comb_vect;
861 vla_hwint_t check_vect;
862 vla_hwint_t base_vect;
863 /* This is simple implementation of the table. */
864 vla_hwint_t full_vect;
865 /* Minimal and maximal values of the previous vectors. */
866 int min_comb_vect_el_value, max_comb_vect_el_value;
867 int min_base_vect_el_value, max_base_vect_el_value;
870 /* Macros to access members of unions. Use only them for access to
871 union members of declarations and regexps. */
873 #if defined ENABLE_CHECKING && (GCC_VERSION >= 2007)
875 #define DECL_UNIT(d) __extension__ \
876 (({ struct decl *const _decl = (d); \
877 if (_decl->mode != dm_unit) \
878 decl_mode_check_failed (_decl->mode, "dm_unit", \
879 __FILE__, __LINE__, __FUNCTION__); \
880 &(_decl)->decl.unit; }))
882 #define DECL_BYPASS(d) __extension__ \
883 (({ struct decl *const _decl = (d); \
884 if (_decl->mode != dm_bypass) \
885 decl_mode_check_failed (_decl->mode, "dm_bypass", \
886 __FILE__, __LINE__, __FUNCTION__); \
887 &(_decl)->decl.bypass; }))
889 #define DECL_AUTOMATON(d) __extension__ \
890 (({ struct decl *const _decl = (d); \
891 if (_decl->mode != dm_automaton) \
892 decl_mode_check_failed (_decl->mode, "dm_automaton", \
893 __FILE__, __LINE__, __FUNCTION__); \
894 &(_decl)->decl.automaton; }))
896 #define DECL_EXCL(d) __extension__ \
897 (({ struct decl *const _decl = (d); \
898 if (_decl->mode != dm_excl) \
899 decl_mode_check_failed (_decl->mode, "dm_excl", \
900 __FILE__, __LINE__, __FUNCTION__); \
901 &(_decl)->decl.excl; }))
903 #define DECL_PRESENCE(d) __extension__ \
904 (({ struct decl *const _decl = (d); \
905 if (_decl->mode != dm_presence) \
906 decl_mode_check_failed (_decl->mode, "dm_presence", \
907 __FILE__, __LINE__, __FUNCTION__); \
908 &(_decl)->decl.presence; }))
910 #define DECL_ABSENCE(d) __extension__ \
911 (({ struct decl *const _decl = (d); \
912 if (_decl->mode != dm_absence) \
913 decl_mode_check_failed (_decl->mode, "dm_absence", \
914 __FILE__, __LINE__, __FUNCTION__); \
915 &(_decl)->decl.absence; }))
917 #define DECL_RESERV(d) __extension__ \
918 (({ struct decl *const _decl = (d); \
919 if (_decl->mode != dm_reserv) \
920 decl_mode_check_failed (_decl->mode, "dm_reserv", \
921 __FILE__, __LINE__, __FUNCTION__); \
922 &(_decl)->decl.reserv; }))
924 #define DECL_INSN_RESERV(d) __extension__ \
925 (({ struct decl *const _decl = (d); \
926 if (_decl->mode != dm_insn_reserv) \
927 decl_mode_check_failed (_decl->mode, "dm_insn_reserv", \
928 __FILE__, __LINE__, __FUNCTION__); \
929 &(_decl)->decl.insn_reserv; }))
931 static const char *decl_name (enum decl_mode);
932 static void decl_mode_check_failed (enum decl_mode, const char *,
933 const char *, int, const char *)
934 ATTRIBUTE_NORETURN;
936 /* Return string representation of declaration mode MODE. */
937 static const char *
938 decl_name (enum decl_mode mode)
940 static char str [100];
942 if (mode == dm_unit)
943 return "dm_unit";
944 else if (mode == dm_bypass)
945 return "dm_bypass";
946 else if (mode == dm_automaton)
947 return "dm_automaton";
948 else if (mode == dm_excl)
949 return "dm_excl";
950 else if (mode == dm_presence)
951 return "dm_presence";
952 else if (mode == dm_absence)
953 return "dm_absence";
954 else if (mode == dm_reserv)
955 return "dm_reserv";
956 else if (mode == dm_insn_reserv)
957 return "dm_insn_reserv";
958 else
959 sprintf (str, "unknown (%d)", (int) mode);
960 return str;
963 /* The function prints message about unexpected declaration and finish
964 the program. */
965 static void
966 decl_mode_check_failed (enum decl_mode mode, const char *expected_mode_str,
967 const char *file, int line, const char *func)
969 fprintf
970 (stderr,
971 "\n%s: %d: error in %s: DECL check: expected decl %s, have %s\n",
972 file, line, func, expected_mode_str, decl_name (mode));
973 exit (1);
977 #define REGEXP_UNIT(r) __extension__ \
978 (({ struct regexp *const _regexp = (r); \
979 if (_regexp->mode != rm_unit) \
980 regexp_mode_check_failed (_regexp->mode, "rm_unit", \
981 __FILE__, __LINE__, __FUNCTION__); \
982 &(_regexp)->regexp.unit; }))
984 #define REGEXP_RESERV(r) __extension__ \
985 (({ struct regexp *const _regexp = (r); \
986 if (_regexp->mode != rm_reserv) \
987 regexp_mode_check_failed (_regexp->mode, "rm_reserv", \
988 __FILE__, __LINE__, __FUNCTION__); \
989 &(_regexp)->regexp.reserv; }))
991 #define REGEXP_SEQUENCE(r) __extension__ \
992 (({ struct regexp *const _regexp = (r); \
993 if (_regexp->mode != rm_sequence) \
994 regexp_mode_check_failed (_regexp->mode, "rm_sequence", \
995 __FILE__, __LINE__, __FUNCTION__); \
996 &(_regexp)->regexp.sequence; }))
998 #define REGEXP_REPEAT(r) __extension__ \
999 (({ struct regexp *const _regexp = (r); \
1000 if (_regexp->mode != rm_repeat) \
1001 regexp_mode_check_failed (_regexp->mode, "rm_repeat", \
1002 __FILE__, __LINE__, __FUNCTION__); \
1003 &(_regexp)->regexp.repeat; }))
1005 #define REGEXP_ALLOF(r) __extension__ \
1006 (({ struct regexp *const _regexp = (r); \
1007 if (_regexp->mode != rm_allof) \
1008 regexp_mode_check_failed (_regexp->mode, "rm_allof", \
1009 __FILE__, __LINE__, __FUNCTION__); \
1010 &(_regexp)->regexp.allof; }))
1012 #define REGEXP_ONEOF(r) __extension__ \
1013 (({ struct regexp *const _regexp = (r); \
1014 if (_regexp->mode != rm_oneof) \
1015 regexp_mode_check_failed (_regexp->mode, "rm_oneof", \
1016 __FILE__, __LINE__, __FUNCTION__); \
1017 &(_regexp)->regexp.oneof; }))
1019 static const char *regexp_name (enum regexp_mode);
1020 static void regexp_mode_check_failed (enum regexp_mode, const char *,
1021 const char *, int,
1022 const char *) ATTRIBUTE_NORETURN;
1025 /* Return string representation of regexp mode MODE. */
1026 static const char *
1027 regexp_name (enum regexp_mode mode)
1029 switch (mode)
1031 case rm_unit:
1032 return "rm_unit";
1033 case rm_reserv:
1034 return "rm_reserv";
1035 case rm_nothing:
1036 return "rm_nothing";
1037 case rm_sequence:
1038 return "rm_sequence";
1039 case rm_repeat:
1040 return "rm_repeat";
1041 case rm_allof:
1042 return "rm_allof";
1043 case rm_oneof:
1044 return "rm_oneof";
1045 default:
1046 gcc_unreachable ();
1050 /* The function prints message about unexpected regexp and finish the
1051 program. */
1052 static void
1053 regexp_mode_check_failed (enum regexp_mode mode,
1054 const char *expected_mode_str,
1055 const char *file, int line, const char *func)
1057 fprintf
1058 (stderr,
1059 "\n%s: %d: error in %s: REGEXP check: expected decl %s, have %s\n",
1060 file, line, func, expected_mode_str, regexp_name (mode));
1061 exit (1);
1064 #else /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */
1066 #define DECL_UNIT(d) (&(d)->decl.unit)
1067 #define DECL_BYPASS(d) (&(d)->decl.bypass)
1068 #define DECL_AUTOMATON(d) (&(d)->decl.automaton)
1069 #define DECL_EXCL(d) (&(d)->decl.excl)
1070 #define DECL_PRESENCE(d) (&(d)->decl.presence)
1071 #define DECL_ABSENCE(d) (&(d)->decl.absence)
1072 #define DECL_RESERV(d) (&(d)->decl.reserv)
1073 #define DECL_INSN_RESERV(d) (&(d)->decl.insn_reserv)
1075 #define REGEXP_UNIT(r) (&(r)->regexp.unit)
1076 #define REGEXP_RESERV(r) (&(r)->regexp.reserv)
1077 #define REGEXP_SEQUENCE(r) (&(r)->regexp.sequence)
1078 #define REGEXP_REPEAT(r) (&(r)->regexp.repeat)
1079 #define REGEXP_ALLOF(r) (&(r)->regexp.allof)
1080 #define REGEXP_ONEOF(r) (&(r)->regexp.oneof)
1082 #endif /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */
1084 /* Create IR structure (node). */
1085 static void *
1086 create_node (size_t size)
1088 void *result;
1090 obstack_blank (&irp, size);
1091 result = obstack_base (&irp);
1092 obstack_finish (&irp);
1093 /* Default values of members are NULL and zero. */
1094 memset (result, 0, size);
1095 return result;
1098 /* Copy IR structure (node). */
1099 static void *
1100 copy_node (const void *from, size_t size)
1102 void *const result = create_node (size);
1103 memcpy (result, from, size);
1104 return result;
1107 /* The function checks that NAME does not contain quotes (`"'). */
1108 static const char *
1109 check_name (const char * name, pos_t pos ATTRIBUTE_UNUSED)
1111 const char *str;
1113 for (str = name; *str != '\0'; str++)
1114 if (*str == '\"')
1115 error ("Name `%s' contains quotes", name);
1116 return name;
1119 /* Pointers to all declarations during IR generation are stored in the
1120 following. */
1121 static VEC(decl_t,heap) *decls;
1123 /* Given a pointer to a (char *) and a separator, return an alloc'ed
1124 string containing the next separated element, taking parentheses
1125 into account if PAR_FLAG has nonzero value. Advance the pointer to
1126 after the string scanned, or the end-of-string. Return NULL if at
1127 end of string. */
1128 static char *
1129 next_sep_el (const char **pstr, int sep, int par_flag)
1131 char *out_str;
1132 const char *p;
1133 int pars_num;
1134 int n_spaces;
1136 /* Remove leading whitespaces. */
1137 while (ISSPACE ((int) **pstr))
1138 (*pstr)++;
1140 if (**pstr == '\0')
1141 return NULL;
1143 n_spaces = 0;
1144 for (pars_num = 0, p = *pstr; *p != '\0'; p++)
1146 if (par_flag && *p == '(')
1147 pars_num++;
1148 else if (par_flag && *p == ')')
1149 pars_num--;
1150 else if (pars_num == 0 && *p == sep)
1151 break;
1152 if (pars_num == 0 && ISSPACE ((int) *p))
1153 n_spaces++;
1154 else
1156 for (; n_spaces != 0; n_spaces--)
1157 obstack_1grow (&irp, p [-n_spaces]);
1158 obstack_1grow (&irp, *p);
1161 obstack_1grow (&irp, '\0');
1162 out_str = obstack_base (&irp);
1163 obstack_finish (&irp);
1165 *pstr = p;
1166 if (**pstr == sep)
1167 (*pstr)++;
1169 return out_str;
1172 /* Given a string and a separator, return the number of separated
1173 elements in it, taking parentheses into account if PAR_FLAG has
1174 nonzero value. Return 0 for the null string, -1 if parentheses is
1175 not balanced. */
1176 static int
1177 n_sep_els (const char *s, int sep, int par_flag)
1179 int n;
1180 int pars_num;
1182 if (*s == '\0')
1183 return 0;
1185 for (pars_num = 0, n = 1; *s; s++)
1186 if (par_flag && *s == '(')
1187 pars_num++;
1188 else if (par_flag && *s == ')')
1189 pars_num--;
1190 else if (pars_num == 0 && *s == sep)
1191 n++;
1193 return (pars_num != 0 ? -1 : n);
1196 /* Given a string and a separator, return vector of strings which are
1197 elements in the string and number of elements through els_num.
1198 Take parentheses into account if PAREN_P has nonzero value. The
1199 function also inserts the end marker NULL at the end of vector.
1200 Return 0 for the null string, -1 if parentheses are not balanced. */
1201 static char **
1202 get_str_vect (const char *str, int *els_num, int sep, int paren_p)
1204 int i;
1205 char **vect;
1206 const char **pstr;
1207 char *trail;
1209 *els_num = n_sep_els (str, sep, paren_p);
1210 if (*els_num <= 0)
1211 return NULL;
1212 obstack_blank (&irp, sizeof (char *) * (*els_num + 1));
1213 vect = (char **) obstack_base (&irp);
1214 obstack_finish (&irp);
1215 pstr = &str;
1216 for (i = 0; i < *els_num; i++)
1217 vect [i] = next_sep_el (pstr, sep, paren_p);
1218 trail = next_sep_el (pstr, sep, paren_p);
1219 gcc_assert (!trail);
1220 vect [i] = NULL;
1221 return vect;
1224 /* Process a DEFINE_CPU_UNIT.
1226 This gives information about a unit contained in CPU. We fill a
1227 struct unit_decl with information used later by `expand_automata'. */
1228 static void
1229 gen_cpu_unit (rtx def)
1231 decl_t decl;
1232 char **str_cpu_units;
1233 int vect_length;
1234 int i;
1236 str_cpu_units = get_str_vect (XSTR (def, 0), &vect_length, ',', FALSE);
1237 if (str_cpu_units == NULL)
1238 fatal ("invalid string `%s' in define_cpu_unit", XSTR (def, 0));
1239 for (i = 0; i < vect_length; i++)
1241 decl = create_node (sizeof (struct decl));
1242 decl->mode = dm_unit;
1243 decl->pos = 0;
1244 DECL_UNIT (decl)->name = check_name (str_cpu_units [i], decl->pos);
1245 DECL_UNIT (decl)->automaton_name = XSTR (def, 1);
1246 DECL_UNIT (decl)->query_p = 0;
1247 DECL_UNIT (decl)->min_occ_cycle_num = -1;
1248 DECL_UNIT (decl)->in_set_p = 0;
1249 VEC_safe_push (decl_t,heap, decls, decl);
1253 /* Process a DEFINE_QUERY_CPU_UNIT.
1255 This gives information about a unit contained in CPU. We fill a
1256 struct unit_decl with information used later by `expand_automata'. */
1257 static void
1258 gen_query_cpu_unit (rtx def)
1260 decl_t decl;
1261 char **str_cpu_units;
1262 int vect_length;
1263 int i;
1265 str_cpu_units = get_str_vect (XSTR (def, 0), &vect_length, ',',
1266 FALSE);
1267 if (str_cpu_units == NULL)
1268 fatal ("invalid string `%s' in define_query_cpu_unit", XSTR (def, 0));
1269 for (i = 0; i < vect_length; i++)
1271 decl = create_node (sizeof (struct decl));
1272 decl->mode = dm_unit;
1273 decl->pos = 0;
1274 DECL_UNIT (decl)->name = check_name (str_cpu_units [i], decl->pos);
1275 DECL_UNIT (decl)->automaton_name = XSTR (def, 1);
1276 DECL_UNIT (decl)->query_p = 1;
1277 VEC_safe_push (decl_t,heap, decls, decl);
1281 /* Process a DEFINE_BYPASS.
1283 This gives information about a unit contained in the CPU. We fill
1284 in a struct bypass_decl with information used later by
1285 `expand_automata'. */
1286 static void
1287 gen_bypass (rtx def)
1289 decl_t decl;
1290 char **out_insns;
1291 int out_length;
1292 char **in_insns;
1293 int in_length;
1294 int i, j;
1296 out_insns = get_str_vect (XSTR (def, 1), &out_length, ',', FALSE);
1297 if (out_insns == NULL)
1298 fatal ("invalid string `%s' in define_bypass", XSTR (def, 1));
1299 in_insns = get_str_vect (XSTR (def, 2), &in_length, ',', FALSE);
1300 if (in_insns == NULL)
1301 fatal ("invalid string `%s' in define_bypass", XSTR (def, 2));
1302 for (i = 0; i < out_length; i++)
1303 for (j = 0; j < in_length; j++)
1305 decl = create_node (sizeof (struct decl));
1306 decl->mode = dm_bypass;
1307 decl->pos = 0;
1308 DECL_BYPASS (decl)->latency = XINT (def, 0);
1309 DECL_BYPASS (decl)->out_insn_name = out_insns [i];
1310 DECL_BYPASS (decl)->in_insn_name = in_insns [j];
1311 DECL_BYPASS (decl)->bypass_guard_name = XSTR (def, 3);
1312 VEC_safe_push (decl_t,heap, decls, decl);
1316 /* Process an EXCLUSION_SET.
1318 This gives information about a cpu unit conflicts. We fill a
1319 struct excl_rel_decl (excl) with information used later by
1320 `expand_automata'. */
1321 static void
1322 gen_excl_set (rtx def)
1324 decl_t decl;
1325 char **first_str_cpu_units;
1326 char **second_str_cpu_units;
1327 int first_vect_length;
1328 int length;
1329 int i;
1331 first_str_cpu_units
1332 = get_str_vect (XSTR (def, 0), &first_vect_length, ',', FALSE);
1333 if (first_str_cpu_units == NULL)
1334 fatal ("invalid first string `%s' in exclusion_set", XSTR (def, 0));
1335 second_str_cpu_units = get_str_vect (XSTR (def, 1), &length, ',',
1336 FALSE);
1337 if (second_str_cpu_units == NULL)
1338 fatal ("invalid second string `%s' in exclusion_set", XSTR (def, 1));
1339 length += first_vect_length;
1340 decl = create_node (sizeof (struct decl) + (length - 1) * sizeof (char *));
1341 decl->mode = dm_excl;
1342 decl->pos = 0;
1343 DECL_EXCL (decl)->all_names_num = length;
1344 DECL_EXCL (decl)->first_list_length = first_vect_length;
1345 for (i = 0; i < length; i++)
1346 if (i < first_vect_length)
1347 DECL_EXCL (decl)->names [i] = first_str_cpu_units [i];
1348 else
1349 DECL_EXCL (decl)->names [i]
1350 = second_str_cpu_units [i - first_vect_length];
1351 VEC_safe_push (decl_t,heap, decls, decl);
1354 /* Process a PRESENCE_SET, a FINAL_PRESENCE_SET, an ABSENCE_SET,
1355 FINAL_ABSENCE_SET (it is depended on PRESENCE_P and FINAL_P).
1357 This gives information about a cpu unit reservation requirements.
1358 We fill a struct unit_pattern_rel_decl with information used later
1359 by `expand_automata'. */
1360 static void
1361 gen_presence_absence_set (rtx def, int presence_p, int final_p)
1363 decl_t decl;
1364 char **str_cpu_units;
1365 char **str_pattern_lists;
1366 char ***str_patterns;
1367 int cpu_units_length;
1368 int length;
1369 int patterns_length;
1370 int i;
1372 str_cpu_units = get_str_vect (XSTR (def, 0), &cpu_units_length, ',',
1373 FALSE);
1374 if (str_cpu_units == NULL)
1375 fatal ((presence_p
1376 ? (final_p
1377 ? "invalid first string `%s' in final_presence_set"
1378 : "invalid first string `%s' in presence_set")
1379 : (final_p
1380 ? "invalid first string `%s' in final_absence_set"
1381 : "invalid first string `%s' in absence_set")),
1382 XSTR (def, 0));
1383 str_pattern_lists = get_str_vect (XSTR (def, 1),
1384 &patterns_length, ',', FALSE);
1385 if (str_pattern_lists == NULL)
1386 fatal ((presence_p
1387 ? (final_p
1388 ? "invalid second string `%s' in final_presence_set"
1389 : "invalid second string `%s' in presence_set")
1390 : (final_p
1391 ? "invalid second string `%s' in final_absence_set"
1392 : "invalid second string `%s' in absence_set")), XSTR (def, 1));
1393 str_patterns = obstack_alloc (&irp, patterns_length * sizeof (char **));
1394 for (i = 0; i < patterns_length; i++)
1396 str_patterns [i] = get_str_vect (str_pattern_lists [i],
1397 &length, ' ', FALSE);
1398 gcc_assert (str_patterns [i]);
1400 decl = create_node (sizeof (struct decl));
1401 decl->pos = 0;
1402 if (presence_p)
1404 decl->mode = dm_presence;
1405 DECL_PRESENCE (decl)->names_num = cpu_units_length;
1406 DECL_PRESENCE (decl)->names = str_cpu_units;
1407 DECL_PRESENCE (decl)->patterns = str_patterns;
1408 DECL_PRESENCE (decl)->patterns_num = patterns_length;
1409 DECL_PRESENCE (decl)->final_p = final_p;
1411 else
1413 decl->mode = dm_absence;
1414 DECL_ABSENCE (decl)->names_num = cpu_units_length;
1415 DECL_ABSENCE (decl)->names = str_cpu_units;
1416 DECL_ABSENCE (decl)->patterns = str_patterns;
1417 DECL_ABSENCE (decl)->patterns_num = patterns_length;
1418 DECL_ABSENCE (decl)->final_p = final_p;
1420 VEC_safe_push (decl_t,heap, decls, decl);
1423 /* Process a PRESENCE_SET.
1425 This gives information about a cpu unit reservation requirements.
1426 We fill a struct unit_pattern_rel_decl (presence) with information
1427 used later by `expand_automata'. */
1428 static void
1429 gen_presence_set (rtx def)
1431 gen_presence_absence_set (def, TRUE, FALSE);
1434 /* Process a FINAL_PRESENCE_SET.
1436 This gives information about a cpu unit reservation requirements.
1437 We fill a struct unit_pattern_rel_decl (presence) with information
1438 used later by `expand_automata'. */
1439 static void
1440 gen_final_presence_set (rtx def)
1442 gen_presence_absence_set (def, TRUE, TRUE);
1445 /* Process an ABSENCE_SET.
1447 This gives information about a cpu unit reservation requirements.
1448 We fill a struct unit_pattern_rel_decl (absence) with information
1449 used later by `expand_automata'. */
1450 static void
1451 gen_absence_set (rtx def)
1453 gen_presence_absence_set (def, FALSE, FALSE);
1456 /* Process a FINAL_ABSENCE_SET.
1458 This gives information about a cpu unit reservation requirements.
1459 We fill a struct unit_pattern_rel_decl (absence) with information
1460 used later by `expand_automata'. */
1461 static void
1462 gen_final_absence_set (rtx def)
1464 gen_presence_absence_set (def, FALSE, TRUE);
1467 /* Process a DEFINE_AUTOMATON.
1469 This gives information about a finite state automaton used for
1470 recognizing pipeline hazards. We fill a struct automaton_decl
1471 with information used later by `expand_automata'. */
1472 static void
1473 gen_automaton (rtx def)
1475 decl_t decl;
1476 char **str_automata;
1477 int vect_length;
1478 int i;
1480 str_automata = get_str_vect (XSTR (def, 0), &vect_length, ',', FALSE);
1481 if (str_automata == NULL)
1482 fatal ("invalid string `%s' in define_automaton", XSTR (def, 0));
1483 for (i = 0; i < vect_length; i++)
1485 decl = create_node (sizeof (struct decl));
1486 decl->mode = dm_automaton;
1487 decl->pos = 0;
1488 DECL_AUTOMATON (decl)->name = check_name (str_automata [i], decl->pos);
1489 VEC_safe_push (decl_t,heap, decls, decl);
1493 /* Process an AUTOMATA_OPTION.
1495 This gives information how to generate finite state automaton used
1496 for recognizing pipeline hazards. */
1497 static void
1498 gen_automata_option (rtx def)
1500 if (strcmp (XSTR (def, 0), NO_MINIMIZATION_OPTION + 1) == 0)
1501 no_minimization_flag = 1;
1502 else if (strcmp (XSTR (def, 0), TIME_OPTION + 1) == 0)
1503 time_flag = 1;
1504 else if (strcmp (XSTR (def, 0), STATS_OPTION + 1) == 0)
1505 stats_flag = 1;
1506 else if (strcmp (XSTR (def, 0), V_OPTION + 1) == 0)
1507 v_flag = 1;
1508 else if (strcmp (XSTR (def, 0), W_OPTION + 1) == 0)
1509 w_flag = 1;
1510 else if (strcmp (XSTR (def, 0), NDFA_OPTION + 1) == 0)
1511 ndfa_flag = 1;
1512 else if (strcmp (XSTR (def, 0), PROGRESS_OPTION + 1) == 0)
1513 progress_flag = 1;
1514 else
1515 fatal ("invalid option `%s' in automata_option", XSTR (def, 0));
1518 /* Name in reservation to denote absence reservation. */
1519 #define NOTHING_NAME "nothing"
1521 /* The following string contains original reservation string being
1522 parsed. */
1523 static const char *reserv_str;
1525 /* Parse an element in STR. */
1526 static regexp_t
1527 gen_regexp_el (const char *str)
1529 regexp_t regexp;
1530 char *dstr;
1531 int len;
1533 if (*str == '(')
1535 len = strlen (str);
1536 if (str [len - 1] != ')')
1537 fatal ("garbage after ) in reservation `%s'", reserv_str);
1538 dstr = alloca (len - 1);
1539 memcpy (dstr, str + 1, len - 2);
1540 dstr [len-2] = '\0';
1541 regexp = gen_regexp_sequence (dstr);
1543 else if (strcmp (str, NOTHING_NAME) == 0)
1545 regexp = create_node (sizeof (struct decl));
1546 regexp->mode = rm_nothing;
1548 else
1550 regexp = create_node (sizeof (struct decl));
1551 regexp->mode = rm_unit;
1552 REGEXP_UNIT (regexp)->name = str;
1554 return regexp;
1557 /* Parse construction `repeat' in STR. */
1558 static regexp_t
1559 gen_regexp_repeat (const char *str)
1561 regexp_t regexp;
1562 regexp_t repeat;
1563 char **repeat_vect;
1564 int els_num;
1565 int i;
1567 repeat_vect = get_str_vect (str, &els_num, '*', TRUE);
1568 if (repeat_vect == NULL)
1569 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1570 if (els_num > 1)
1572 regexp = gen_regexp_el (repeat_vect [0]);
1573 for (i = 1; i < els_num; i++)
1575 repeat = create_node (sizeof (struct regexp));
1576 repeat->mode = rm_repeat;
1577 REGEXP_REPEAT (repeat)->regexp = regexp;
1578 REGEXP_REPEAT (repeat)->repeat_num = atoi (repeat_vect [i]);
1579 if (REGEXP_REPEAT (repeat)->repeat_num <= 1)
1580 fatal ("repetition `%s' <= 1 in reservation `%s'",
1581 str, reserv_str);
1582 regexp = repeat;
1584 return regexp;
1586 else
1587 return gen_regexp_el (str);
1590 /* Parse reservation STR which possibly contains separator '+'. */
1591 static regexp_t
1592 gen_regexp_allof (const char *str)
1594 regexp_t allof;
1595 char **allof_vect;
1596 int els_num;
1597 int i;
1599 allof_vect = get_str_vect (str, &els_num, '+', TRUE);
1600 if (allof_vect == NULL)
1601 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1602 if (els_num > 1)
1604 allof = create_node (sizeof (struct regexp)
1605 + sizeof (regexp_t) * (els_num - 1));
1606 allof->mode = rm_allof;
1607 REGEXP_ALLOF (allof)->regexps_num = els_num;
1608 for (i = 0; i < els_num; i++)
1609 REGEXP_ALLOF (allof)->regexps [i] = gen_regexp_repeat (allof_vect [i]);
1610 return allof;
1612 else
1613 return gen_regexp_repeat (str);
1616 /* Parse reservation STR which possibly contains separator '|'. */
1617 static regexp_t
1618 gen_regexp_oneof (const char *str)
1620 regexp_t oneof;
1621 char **oneof_vect;
1622 int els_num;
1623 int i;
1625 oneof_vect = get_str_vect (str, &els_num, '|', TRUE);
1626 if (oneof_vect == NULL)
1627 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1628 if (els_num > 1)
1630 oneof = create_node (sizeof (struct regexp)
1631 + sizeof (regexp_t) * (els_num - 1));
1632 oneof->mode = rm_oneof;
1633 REGEXP_ONEOF (oneof)->regexps_num = els_num;
1634 for (i = 0; i < els_num; i++)
1635 REGEXP_ONEOF (oneof)->regexps [i] = gen_regexp_allof (oneof_vect [i]);
1636 return oneof;
1638 else
1639 return gen_regexp_allof (str);
1642 /* Parse reservation STR which possibly contains separator ','. */
1643 static regexp_t
1644 gen_regexp_sequence (const char *str)
1646 regexp_t sequence;
1647 char **sequence_vect;
1648 int els_num;
1649 int i;
1651 sequence_vect = get_str_vect (str, &els_num, ',', TRUE);
1652 if (els_num > 1)
1654 sequence = create_node (sizeof (struct regexp)
1655 + sizeof (regexp_t) * (els_num - 1));
1656 sequence->mode = rm_sequence;
1657 REGEXP_SEQUENCE (sequence)->regexps_num = els_num;
1658 for (i = 0; i < els_num; i++)
1659 REGEXP_SEQUENCE (sequence)->regexps [i]
1660 = gen_regexp_oneof (sequence_vect [i]);
1661 return sequence;
1663 else
1664 return gen_regexp_oneof (str);
1667 /* Parse construction reservation STR. */
1668 static regexp_t
1669 gen_regexp (const char *str)
1671 reserv_str = str;
1672 return gen_regexp_sequence (str);;
1675 /* Process a DEFINE_RESERVATION.
1677 This gives information about a reservation of cpu units. We fill
1678 in a struct reserv_decl with information used later by
1679 `expand_automata'. */
1680 static void
1681 gen_reserv (rtx def)
1683 decl_t decl;
1685 decl = create_node (sizeof (struct decl));
1686 decl->mode = dm_reserv;
1687 decl->pos = 0;
1688 DECL_RESERV (decl)->name = check_name (XSTR (def, 0), decl->pos);
1689 DECL_RESERV (decl)->regexp = gen_regexp (XSTR (def, 1));
1690 VEC_safe_push (decl_t,heap, decls, decl);
1693 /* Process a DEFINE_INSN_RESERVATION.
1695 This gives information about the reservation of cpu units by an
1696 insn. We fill a struct insn_reserv_decl with information used
1697 later by `expand_automata'. */
1698 static void
1699 gen_insn_reserv (rtx def)
1701 decl_t decl;
1703 decl = create_node (sizeof (struct decl));
1704 decl->mode = dm_insn_reserv;
1705 decl->pos = 0;
1706 DECL_INSN_RESERV (decl)->name
1707 = check_name (XSTR (def, 0), decl->pos);
1708 DECL_INSN_RESERV (decl)->default_latency = XINT (def, 1);
1709 DECL_INSN_RESERV (decl)->condexp = XEXP (def, 2);
1710 DECL_INSN_RESERV (decl)->regexp = gen_regexp (XSTR (def, 3));
1711 VEC_safe_push (decl_t,heap, decls, decl);
1716 /* The function evaluates hash value (0..UINT_MAX) of string. */
1717 static unsigned
1718 string_hash (const char *string)
1720 unsigned result, i;
1722 for (result = i = 0;*string++ != '\0'; i++)
1723 result += ((unsigned char) *string << (i % CHAR_BIT));
1724 return result;
1729 /* This page contains abstract data `table of automaton declarations'.
1730 Elements of the table is nodes representing automaton declarations.
1731 Key of the table elements is name of given automaton. Remember
1732 that automaton names have own space. */
1734 /* The function evaluates hash value of an automaton declaration. The
1735 function is used by abstract data `hashtab'. The function returns
1736 hash value (0..UINT_MAX) of given automaton declaration. */
1737 static hashval_t
1738 automaton_decl_hash (const void *automaton_decl)
1740 const decl_t decl = (decl_t) automaton_decl;
1742 gcc_assert (decl->mode != dm_automaton
1743 || DECL_AUTOMATON (decl)->name);
1744 return string_hash (DECL_AUTOMATON (decl)->name);
1747 /* The function tests automaton declarations on equality of their
1748 keys. The function is used by abstract data `hashtab'. The
1749 function returns 1 if the declarations have the same key, 0
1750 otherwise. */
1751 static int
1752 automaton_decl_eq_p (const void* automaton_decl_1,
1753 const void* automaton_decl_2)
1755 const decl_t decl1 = (decl_t) automaton_decl_1;
1756 const decl_t decl2 = (decl_t) automaton_decl_2;
1758 gcc_assert (decl1->mode == dm_automaton
1759 && DECL_AUTOMATON (decl1)->name
1760 && decl2->mode == dm_automaton
1761 && DECL_AUTOMATON (decl2)->name);
1762 return strcmp (DECL_AUTOMATON (decl1)->name,
1763 DECL_AUTOMATON (decl2)->name) == 0;
1766 /* The automaton declaration table itself is represented by the
1767 following variable. */
1768 static htab_t automaton_decl_table;
1770 /* The function inserts automaton declaration into the table. The
1771 function does nothing if an automaton declaration with the same key
1772 exists already in the table. The function returns automaton
1773 declaration node in the table with the same key as given automaton
1774 declaration node. */
1775 static decl_t
1776 insert_automaton_decl (decl_t automaton_decl)
1778 void **entry_ptr;
1780 entry_ptr = htab_find_slot (automaton_decl_table, automaton_decl, 1);
1781 if (*entry_ptr == NULL)
1782 *entry_ptr = (void *) automaton_decl;
1783 return (decl_t) *entry_ptr;
1786 /* The following variable value is node representing automaton
1787 declaration. The node used for searching automaton declaration
1788 with given name. */
1789 static struct decl work_automaton_decl;
1791 /* The function searches for automaton declaration in the table with
1792 the same key as node representing name of the automaton
1793 declaration. The function returns node found in the table, NULL if
1794 such node does not exist in the table. */
1795 static decl_t
1796 find_automaton_decl (const char *name)
1798 void *entry;
1800 work_automaton_decl.mode = dm_automaton;
1801 DECL_AUTOMATON (&work_automaton_decl)->name = name;
1802 entry = htab_find (automaton_decl_table, &work_automaton_decl);
1803 return (decl_t) entry;
1806 /* The function creates empty automaton declaration table and node
1807 representing automaton declaration and used for searching automaton
1808 declaration with given name. The function must be called only once
1809 before any work with the automaton declaration table. */
1810 static void
1811 initiate_automaton_decl_table (void)
1813 work_automaton_decl.mode = dm_automaton;
1814 automaton_decl_table = htab_create (10, automaton_decl_hash,
1815 automaton_decl_eq_p, (htab_del) 0);
1818 /* The function deletes the automaton declaration table. Only call of
1819 function `initiate_automaton_decl_table' is possible immediately
1820 after this function call. */
1821 static void
1822 finish_automaton_decl_table (void)
1824 htab_delete (automaton_decl_table);
1829 /* This page contains abstract data `table of insn declarations'.
1830 Elements of the table is nodes representing insn declarations. Key
1831 of the table elements is name of given insn (in corresponding
1832 define_insn_reservation). Remember that insn names have own
1833 space. */
1835 /* The function evaluates hash value of an insn declaration. The
1836 function is used by abstract data `hashtab'. The function returns
1837 hash value (0..UINT_MAX) of given insn declaration. */
1838 static hashval_t
1839 insn_decl_hash (const void *insn_decl)
1841 const decl_t decl = (decl_t) insn_decl;
1843 gcc_assert (decl->mode == dm_insn_reserv
1844 && DECL_INSN_RESERV (decl)->name);
1845 return string_hash (DECL_INSN_RESERV (decl)->name);
1848 /* The function tests insn declarations on equality of their keys.
1849 The function is used by abstract data `hashtab'. The function
1850 returns 1 if declarations have the same key, 0 otherwise. */
1851 static int
1852 insn_decl_eq_p (const void *insn_decl_1, const void *insn_decl_2)
1854 const decl_t decl1 = (decl_t) insn_decl_1;
1855 const decl_t decl2 = (decl_t) insn_decl_2;
1857 gcc_assert (decl1->mode == dm_insn_reserv
1858 && DECL_INSN_RESERV (decl1)->name
1859 && decl2->mode == dm_insn_reserv
1860 && DECL_INSN_RESERV (decl2)->name);
1861 return strcmp (DECL_INSN_RESERV (decl1)->name,
1862 DECL_INSN_RESERV (decl2)->name) == 0;
1865 /* The insn declaration table itself is represented by the following
1866 variable. The table does not contain insn reservation
1867 declarations. */
1868 static htab_t insn_decl_table;
1870 /* The function inserts insn declaration into the table. The function
1871 does nothing if an insn declaration with the same key exists
1872 already in the table. The function returns insn declaration node
1873 in the table with the same key as given insn declaration node. */
1874 static decl_t
1875 insert_insn_decl (decl_t insn_decl)
1877 void **entry_ptr;
1879 entry_ptr = htab_find_slot (insn_decl_table, insn_decl, 1);
1880 if (*entry_ptr == NULL)
1881 *entry_ptr = (void *) insn_decl;
1882 return (decl_t) *entry_ptr;
1885 /* The following variable value is node representing insn reservation
1886 declaration. The node used for searching insn reservation
1887 declaration with given name. */
1888 static struct decl work_insn_decl;
1890 /* The function searches for insn reservation declaration in the table
1891 with the same key as node representing name of the insn reservation
1892 declaration. The function returns node found in the table, NULL if
1893 such node does not exist in the table. */
1894 static decl_t
1895 find_insn_decl (const char *name)
1897 void *entry;
1899 work_insn_decl.mode = dm_insn_reserv;
1900 DECL_INSN_RESERV (&work_insn_decl)->name = name;
1901 entry = htab_find (insn_decl_table, &work_insn_decl);
1902 return (decl_t) entry;
1905 /* The function creates empty insn declaration table and node
1906 representing insn declaration and used for searching insn
1907 declaration with given name. The function must be called only once
1908 before any work with the insn declaration table. */
1909 static void
1910 initiate_insn_decl_table (void)
1912 work_insn_decl.mode = dm_insn_reserv;
1913 insn_decl_table = htab_create (10, insn_decl_hash, insn_decl_eq_p,
1914 (htab_del) 0);
1917 /* The function deletes the insn declaration table. Only call of
1918 function `initiate_insn_decl_table' is possible immediately after
1919 this function call. */
1920 static void
1921 finish_insn_decl_table (void)
1923 htab_delete (insn_decl_table);
1928 /* This page contains abstract data `table of declarations'. Elements
1929 of the table is nodes representing declarations (of units and
1930 reservations). Key of the table elements is names of given
1931 declarations. */
1933 /* The function evaluates hash value of a declaration. The function
1934 is used by abstract data `hashtab'. The function returns hash
1935 value (0..UINT_MAX) of given declaration. */
1936 static hashval_t
1937 decl_hash (const void *decl)
1939 const decl_t d = (const decl_t) decl;
1941 gcc_assert ((d->mode == dm_unit && DECL_UNIT (d)->name)
1942 || (d->mode == dm_reserv && DECL_RESERV (d)->name));
1943 return string_hash (d->mode == dm_unit
1944 ? DECL_UNIT (d)->name : DECL_RESERV (d)->name);
1947 /* The function tests declarations on equality of their keys. The
1948 function is used by abstract data 'hashtab'. The function
1949 returns 1 if the declarations have the same key, 0 otherwise. */
1950 static int
1951 decl_eq_p (const void *decl_1, const void *decl_2)
1953 const decl_t d1 = (const decl_t) decl_1;
1954 const decl_t d2 = (const decl_t) decl_2;
1956 gcc_assert ((d1->mode == dm_unit && DECL_UNIT (d1)->name)
1957 || (d1->mode == dm_reserv && DECL_RESERV (d1)->name));
1958 gcc_assert ((d2->mode == dm_unit && DECL_UNIT (d2)->name)
1959 || (d2->mode == dm_reserv && DECL_RESERV (d2)->name));
1960 return strcmp ((d1->mode == dm_unit
1961 ? DECL_UNIT (d1)->name : DECL_RESERV (d1)->name),
1962 (d2->mode == dm_unit
1963 ? DECL_UNIT (d2)->name : DECL_RESERV (d2)->name)) == 0;
1966 /* The declaration table itself is represented by the following
1967 variable. */
1968 static htab_t decl_table;
1970 /* The function inserts declaration into the table. The function does
1971 nothing if a declaration with the same key exists already in the
1972 table. The function returns declaration node in the table with the
1973 same key as given declaration node. */
1975 static decl_t
1976 insert_decl (decl_t decl)
1978 void **entry_ptr;
1980 entry_ptr = htab_find_slot (decl_table, decl, 1);
1981 if (*entry_ptr == NULL)
1982 *entry_ptr = (void *) decl;
1983 return (decl_t) *entry_ptr;
1986 /* The following variable value is node representing declaration. The
1987 node used for searching declaration with given name. */
1988 static struct decl work_decl;
1990 /* The function searches for declaration in the table with the same
1991 key as node representing name of the declaration. The function
1992 returns node found in the table, NULL if such node does not exist
1993 in the table. */
1994 static decl_t
1995 find_decl (const char *name)
1997 void *entry;
1999 work_decl.mode = dm_unit;
2000 DECL_UNIT (&work_decl)->name = name;
2001 entry = htab_find (decl_table, &work_decl);
2002 return (decl_t) entry;
2005 /* The function creates empty declaration table and node representing
2006 declaration and used for searching declaration with given name.
2007 The function must be called only once before any work with the
2008 declaration table. */
2009 static void
2010 initiate_decl_table (void)
2012 work_decl.mode = dm_unit;
2013 decl_table = htab_create (10, decl_hash, decl_eq_p, (htab_del) 0);
2016 /* The function deletes the declaration table. Only call of function
2017 `initiate_declaration_table' is possible immediately after this
2018 function call. */
2019 static void
2020 finish_decl_table (void)
2022 htab_delete (decl_table);
2027 /* This page contains checker of pipeline hazard description. */
2029 /* Checking NAMES in an exclusion clause vector and returning formed
2030 unit_set_el_list. */
2031 static unit_set_el_t
2032 process_excls (char **names, int num, pos_t excl_pos ATTRIBUTE_UNUSED)
2034 unit_set_el_t el_list;
2035 unit_set_el_t last_el;
2036 unit_set_el_t new_el;
2037 decl_t decl_in_table;
2038 int i;
2040 el_list = NULL;
2041 last_el = NULL;
2042 for (i = 0; i < num; i++)
2044 decl_in_table = find_decl (names [i]);
2045 if (decl_in_table == NULL)
2046 error ("unit `%s' in exclusion is not declared", names [i]);
2047 else if (decl_in_table->mode != dm_unit)
2048 error ("`%s' in exclusion is not unit", names [i]);
2049 else
2051 new_el = create_node (sizeof (struct unit_set_el));
2052 new_el->unit_decl = DECL_UNIT (decl_in_table);
2053 new_el->next_unit_set_el = NULL;
2054 if (last_el == NULL)
2055 el_list = last_el = new_el;
2056 else
2058 last_el->next_unit_set_el = new_el;
2059 last_el = last_el->next_unit_set_el;
2063 return el_list;
2066 /* The function adds each element from SOURCE_LIST to the exclusion
2067 list of the each element from DEST_LIST. Checking situation "unit
2068 excludes itself". */
2069 static void
2070 add_excls (unit_set_el_t dest_list, unit_set_el_t source_list,
2071 pos_t excl_pos ATTRIBUTE_UNUSED)
2073 unit_set_el_t dst;
2074 unit_set_el_t src;
2075 unit_set_el_t curr_el;
2076 unit_set_el_t prev_el;
2077 unit_set_el_t copy;
2079 for (dst = dest_list; dst != NULL; dst = dst->next_unit_set_el)
2080 for (src = source_list; src != NULL; src = src->next_unit_set_el)
2082 if (dst->unit_decl == src->unit_decl)
2084 error ("unit `%s' excludes itself", src->unit_decl->name);
2085 continue;
2087 if (dst->unit_decl->automaton_name != NULL
2088 && src->unit_decl->automaton_name != NULL
2089 && strcmp (dst->unit_decl->automaton_name,
2090 src->unit_decl->automaton_name) != 0)
2092 error ("units `%s' and `%s' in exclusion set belong to different automata",
2093 src->unit_decl->name, dst->unit_decl->name);
2094 continue;
2096 for (curr_el = dst->unit_decl->excl_list, prev_el = NULL;
2097 curr_el != NULL;
2098 prev_el = curr_el, curr_el = curr_el->next_unit_set_el)
2099 if (curr_el->unit_decl == src->unit_decl)
2100 break;
2101 if (curr_el == NULL)
2103 /* Element not found - insert. */
2104 copy = copy_node (src, sizeof (*src));
2105 copy->next_unit_set_el = NULL;
2106 if (prev_el == NULL)
2107 dst->unit_decl->excl_list = copy;
2108 else
2109 prev_el->next_unit_set_el = copy;
2114 /* Checking NAMES in presence/absence clause and returning the
2115 formed unit_set_el_list. The function is called only after
2116 processing all exclusion sets. */
2117 static unit_set_el_t
2118 process_presence_absence_names (char **names, int num,
2119 pos_t req_pos ATTRIBUTE_UNUSED,
2120 int presence_p, int final_p)
2122 unit_set_el_t el_list;
2123 unit_set_el_t last_el;
2124 unit_set_el_t new_el;
2125 decl_t decl_in_table;
2126 int i;
2128 el_list = NULL;
2129 last_el = NULL;
2130 for (i = 0; i < num; i++)
2132 decl_in_table = find_decl (names [i]);
2133 if (decl_in_table == NULL)
2134 error ((presence_p
2135 ? (final_p
2136 ? "unit `%s' in final presence set is not declared"
2137 : "unit `%s' in presence set is not declared")
2138 : (final_p
2139 ? "unit `%s' in final absence set is not declared"
2140 : "unit `%s' in absence set is not declared")), names [i]);
2141 else if (decl_in_table->mode != dm_unit)
2142 error ((presence_p
2143 ? (final_p
2144 ? "`%s' in final presence set is not unit"
2145 : "`%s' in presence set is not unit")
2146 : (final_p
2147 ? "`%s' in final absence set is not unit"
2148 : "`%s' in absence set is not unit")), names [i]);
2149 else
2151 new_el = create_node (sizeof (struct unit_set_el));
2152 new_el->unit_decl = DECL_UNIT (decl_in_table);
2153 new_el->next_unit_set_el = NULL;
2154 if (last_el == NULL)
2155 el_list = last_el = new_el;
2156 else
2158 last_el->next_unit_set_el = new_el;
2159 last_el = last_el->next_unit_set_el;
2163 return el_list;
2166 /* Checking NAMES in patterns of a presence/absence clause and
2167 returning the formed pattern_set_el_list. The function is called
2168 only after processing all exclusion sets. */
2169 static pattern_set_el_t
2170 process_presence_absence_patterns (char ***patterns, int num,
2171 pos_t req_pos ATTRIBUTE_UNUSED,
2172 int presence_p, int final_p)
2174 pattern_set_el_t el_list;
2175 pattern_set_el_t last_el;
2176 pattern_set_el_t new_el;
2177 decl_t decl_in_table;
2178 int i, j;
2180 el_list = NULL;
2181 last_el = NULL;
2182 for (i = 0; i < num; i++)
2184 for (j = 0; patterns [i] [j] != NULL; j++)
2186 new_el = create_node (sizeof (struct pattern_set_el)
2187 + sizeof (struct unit_decl *) * j);
2188 new_el->unit_decls
2189 = (struct unit_decl **) ((char *) new_el
2190 + sizeof (struct pattern_set_el));
2191 new_el->next_pattern_set_el = NULL;
2192 if (last_el == NULL)
2193 el_list = last_el = new_el;
2194 else
2196 last_el->next_pattern_set_el = new_el;
2197 last_el = last_el->next_pattern_set_el;
2199 new_el->units_num = 0;
2200 for (j = 0; patterns [i] [j] != NULL; j++)
2202 decl_in_table = find_decl (patterns [i] [j]);
2203 if (decl_in_table == NULL)
2204 error ((presence_p
2205 ? (final_p
2206 ? "unit `%s' in final presence set is not declared"
2207 : "unit `%s' in presence set is not declared")
2208 : (final_p
2209 ? "unit `%s' in final absence set is not declared"
2210 : "unit `%s' in absence set is not declared")),
2211 patterns [i] [j]);
2212 else if (decl_in_table->mode != dm_unit)
2213 error ((presence_p
2214 ? (final_p
2215 ? "`%s' in final presence set is not unit"
2216 : "`%s' in presence set is not unit")
2217 : (final_p
2218 ? "`%s' in final absence set is not unit"
2219 : "`%s' in absence set is not unit")),
2220 patterns [i] [j]);
2221 else
2223 new_el->unit_decls [new_el->units_num]
2224 = DECL_UNIT (decl_in_table);
2225 new_el->units_num++;
2229 return el_list;
2232 /* The function adds each element from PATTERN_LIST to presence (if
2233 PRESENCE_P) or absence list of the each element from DEST_LIST.
2234 Checking situations "unit requires own absence", and "unit excludes
2235 and requires presence of ...", "unit requires absence and presence
2236 of ...", "units in (final) presence set belong to different
2237 automata", and "units in (final) absence set belong to different
2238 automata". Remember that we process absence sets only after all
2239 presence sets. */
2240 static void
2241 add_presence_absence (unit_set_el_t dest_list,
2242 pattern_set_el_t pattern_list,
2243 pos_t req_pos ATTRIBUTE_UNUSED,
2244 int presence_p, int final_p)
2246 unit_set_el_t dst;
2247 pattern_set_el_t pat;
2248 struct unit_decl *unit;
2249 unit_set_el_t curr_excl_el;
2250 pattern_set_el_t curr_pat_el;
2251 pattern_set_el_t prev_el;
2252 pattern_set_el_t copy;
2253 int i;
2254 int no_error_flag;
2256 for (dst = dest_list; dst != NULL; dst = dst->next_unit_set_el)
2257 for (pat = pattern_list; pat != NULL; pat = pat->next_pattern_set_el)
2259 for (i = 0; i < pat->units_num; i++)
2261 unit = pat->unit_decls [i];
2262 if (dst->unit_decl == unit && pat->units_num == 1 && !presence_p)
2264 error ("unit `%s' requires own absence", unit->name);
2265 continue;
2267 if (dst->unit_decl->automaton_name != NULL
2268 && unit->automaton_name != NULL
2269 && strcmp (dst->unit_decl->automaton_name,
2270 unit->automaton_name) != 0)
2272 error ((presence_p
2273 ? (final_p
2274 ? "units `%s' and `%s' in final presence set belong to different automata"
2275 : "units `%s' and `%s' in presence set belong to different automata")
2276 : (final_p
2277 ? "units `%s' and `%s' in final absence set belong to different automata"
2278 : "units `%s' and `%s' in absence set belong to different automata")),
2279 unit->name, dst->unit_decl->name);
2280 continue;
2282 no_error_flag = 1;
2283 if (presence_p)
2284 for (curr_excl_el = dst->unit_decl->excl_list;
2285 curr_excl_el != NULL;
2286 curr_excl_el = curr_excl_el->next_unit_set_el)
2288 if (unit == curr_excl_el->unit_decl && pat->units_num == 1)
2290 if (!w_flag)
2292 error ("unit `%s' excludes and requires presence of `%s'",
2293 dst->unit_decl->name, unit->name);
2294 no_error_flag = 0;
2296 else
2297 warning
2298 (0, "unit `%s' excludes and requires presence of `%s'",
2299 dst->unit_decl->name, unit->name);
2302 else if (pat->units_num == 1)
2303 for (curr_pat_el = dst->unit_decl->presence_list;
2304 curr_pat_el != NULL;
2305 curr_pat_el = curr_pat_el->next_pattern_set_el)
2306 if (curr_pat_el->units_num == 1
2307 && unit == curr_pat_el->unit_decls [0])
2309 if (!w_flag)
2311 error
2312 ("unit `%s' requires absence and presence of `%s'",
2313 dst->unit_decl->name, unit->name);
2314 no_error_flag = 0;
2316 else
2317 warning
2318 (0, "unit `%s' requires absence and presence of `%s'",
2319 dst->unit_decl->name, unit->name);
2321 if (no_error_flag)
2323 for (prev_el = (presence_p
2324 ? (final_p
2325 ? dst->unit_decl->final_presence_list
2326 : dst->unit_decl->final_presence_list)
2327 : (final_p
2328 ? dst->unit_decl->final_absence_list
2329 : dst->unit_decl->absence_list));
2330 prev_el != NULL && prev_el->next_pattern_set_el != NULL;
2331 prev_el = prev_el->next_pattern_set_el)
2333 copy = copy_node (pat, sizeof (*pat));
2334 copy->next_pattern_set_el = NULL;
2335 if (prev_el == NULL)
2337 if (presence_p)
2339 if (final_p)
2340 dst->unit_decl->final_presence_list = copy;
2341 else
2342 dst->unit_decl->presence_list = copy;
2344 else if (final_p)
2345 dst->unit_decl->final_absence_list = copy;
2346 else
2347 dst->unit_decl->absence_list = copy;
2349 else
2350 prev_el->next_pattern_set_el = copy;
2357 /* The function searches for bypass with given IN_INSN_RESERV in given
2358 BYPASS_LIST. */
2359 static struct bypass_decl *
2360 find_bypass (struct bypass_decl *bypass_list,
2361 struct insn_reserv_decl *in_insn_reserv)
2363 struct bypass_decl *bypass;
2365 for (bypass = bypass_list; bypass != NULL; bypass = bypass->next)
2366 if (bypass->in_insn_reserv == in_insn_reserv)
2367 break;
2368 return bypass;
2371 /* The function processes pipeline description declarations, checks
2372 their correctness, and forms exclusion/presence/absence sets. */
2373 static void
2374 process_decls (void)
2376 decl_t decl;
2377 decl_t automaton_decl;
2378 decl_t decl_in_table;
2379 decl_t out_insn_reserv;
2380 decl_t in_insn_reserv;
2381 struct bypass_decl *bypass;
2382 int automaton_presence;
2383 int i;
2385 /* Checking repeated automata declarations. */
2386 automaton_presence = 0;
2387 for (i = 0; i < description->decls_num; i++)
2389 decl = description->decls [i];
2390 if (decl->mode == dm_automaton)
2392 automaton_presence = 1;
2393 decl_in_table = insert_automaton_decl (decl);
2394 if (decl_in_table != decl)
2396 if (!w_flag)
2397 error ("repeated declaration of automaton `%s'",
2398 DECL_AUTOMATON (decl)->name);
2399 else
2400 warning (0, "repeated declaration of automaton `%s'",
2401 DECL_AUTOMATON (decl)->name);
2405 /* Checking undeclared automata, repeated declarations (except for
2406 automata) and correctness of their attributes (insn latency times
2407 etc.). */
2408 for (i = 0; i < description->decls_num; i++)
2410 decl = description->decls [i];
2411 if (decl->mode == dm_insn_reserv)
2413 if (DECL_INSN_RESERV (decl)->default_latency < 0)
2414 error ("define_insn_reservation `%s' has negative latency time",
2415 DECL_INSN_RESERV (decl)->name);
2416 DECL_INSN_RESERV (decl)->insn_num = description->insns_num;
2417 description->insns_num++;
2418 decl_in_table = insert_insn_decl (decl);
2419 if (decl_in_table != decl)
2420 error ("`%s' is already used as insn reservation name",
2421 DECL_INSN_RESERV (decl)->name);
2423 else if (decl->mode == dm_bypass)
2425 if (DECL_BYPASS (decl)->latency < 0)
2426 error ("define_bypass `%s - %s' has negative latency time",
2427 DECL_BYPASS (decl)->out_insn_name,
2428 DECL_BYPASS (decl)->in_insn_name);
2430 else if (decl->mode == dm_unit || decl->mode == dm_reserv)
2432 if (decl->mode == dm_unit)
2434 DECL_UNIT (decl)->automaton_decl = NULL;
2435 if (DECL_UNIT (decl)->automaton_name != NULL)
2437 automaton_decl
2438 = find_automaton_decl (DECL_UNIT (decl)->automaton_name);
2439 if (automaton_decl == NULL)
2440 error ("automaton `%s' is not declared",
2441 DECL_UNIT (decl)->automaton_name);
2442 else
2444 DECL_AUTOMATON (automaton_decl)->automaton_is_used = 1;
2445 DECL_UNIT (decl)->automaton_decl
2446 = DECL_AUTOMATON (automaton_decl);
2449 else if (automaton_presence)
2450 error ("define_unit `%s' without automaton when one defined",
2451 DECL_UNIT (decl)->name);
2452 DECL_UNIT (decl)->unit_num = description->units_num;
2453 description->units_num++;
2454 if (strcmp (DECL_UNIT (decl)->name, NOTHING_NAME) == 0)
2456 error ("`%s' is declared as cpu unit", NOTHING_NAME);
2457 continue;
2459 decl_in_table = find_decl (DECL_UNIT (decl)->name);
2461 else
2463 if (strcmp (DECL_RESERV (decl)->name, NOTHING_NAME) == 0)
2465 error ("`%s' is declared as cpu reservation", NOTHING_NAME);
2466 continue;
2468 decl_in_table = find_decl (DECL_RESERV (decl)->name);
2470 if (decl_in_table == NULL)
2471 decl_in_table = insert_decl (decl);
2472 else
2474 if (decl->mode == dm_unit)
2475 error ("repeated declaration of unit `%s'",
2476 DECL_UNIT (decl)->name);
2477 else
2478 error ("repeated declaration of reservation `%s'",
2479 DECL_RESERV (decl)->name);
2483 /* Check bypasses and form list of bypasses for each (output)
2484 insn. */
2485 for (i = 0; i < description->decls_num; i++)
2487 decl = description->decls [i];
2488 if (decl->mode == dm_bypass)
2490 out_insn_reserv = find_insn_decl (DECL_BYPASS (decl)->out_insn_name);
2491 in_insn_reserv = find_insn_decl (DECL_BYPASS (decl)->in_insn_name);
2492 if (out_insn_reserv == NULL)
2493 error ("there is no insn reservation `%s'",
2494 DECL_BYPASS (decl)->out_insn_name);
2495 else if (in_insn_reserv == NULL)
2496 error ("there is no insn reservation `%s'",
2497 DECL_BYPASS (decl)->in_insn_name);
2498 else
2500 DECL_BYPASS (decl)->out_insn_reserv
2501 = DECL_INSN_RESERV (out_insn_reserv);
2502 DECL_BYPASS (decl)->in_insn_reserv
2503 = DECL_INSN_RESERV (in_insn_reserv);
2504 bypass
2505 = find_bypass (DECL_INSN_RESERV (out_insn_reserv)->bypass_list,
2506 DECL_BYPASS (decl)->in_insn_reserv);
2507 if (bypass != NULL)
2509 if (DECL_BYPASS (decl)->latency == bypass->latency)
2511 if (!w_flag)
2512 error
2513 ("the same bypass `%s - %s' is already defined",
2514 DECL_BYPASS (decl)->out_insn_name,
2515 DECL_BYPASS (decl)->in_insn_name);
2516 else
2517 warning
2518 (0, "the same bypass `%s - %s' is already defined",
2519 DECL_BYPASS (decl)->out_insn_name,
2520 DECL_BYPASS (decl)->in_insn_name);
2522 else
2523 error ("bypass `%s - %s' is already defined",
2524 DECL_BYPASS (decl)->out_insn_name,
2525 DECL_BYPASS (decl)->in_insn_name);
2527 else
2529 DECL_BYPASS (decl)->next
2530 = DECL_INSN_RESERV (out_insn_reserv)->bypass_list;
2531 DECL_INSN_RESERV (out_insn_reserv)->bypass_list
2532 = DECL_BYPASS (decl);
2538 /* Check exclusion set declarations and form exclusion sets. */
2539 for (i = 0; i < description->decls_num; i++)
2541 decl = description->decls [i];
2542 if (decl->mode == dm_excl)
2544 unit_set_el_t unit_set_el_list;
2545 unit_set_el_t unit_set_el_list_2;
2547 unit_set_el_list
2548 = process_excls (DECL_EXCL (decl)->names,
2549 DECL_EXCL (decl)->first_list_length, decl->pos);
2550 unit_set_el_list_2
2551 = process_excls (&DECL_EXCL (decl)->names
2552 [DECL_EXCL (decl)->first_list_length],
2553 DECL_EXCL (decl)->all_names_num
2554 - DECL_EXCL (decl)->first_list_length,
2555 decl->pos);
2556 add_excls (unit_set_el_list, unit_set_el_list_2, decl->pos);
2557 add_excls (unit_set_el_list_2, unit_set_el_list, decl->pos);
2561 /* Check presence set declarations and form presence sets. */
2562 for (i = 0; i < description->decls_num; i++)
2564 decl = description->decls [i];
2565 if (decl->mode == dm_presence)
2567 unit_set_el_t unit_set_el_list;
2568 pattern_set_el_t pattern_set_el_list;
2570 unit_set_el_list
2571 = process_presence_absence_names
2572 (DECL_PRESENCE (decl)->names, DECL_PRESENCE (decl)->names_num,
2573 decl->pos, TRUE, DECL_PRESENCE (decl)->final_p);
2574 pattern_set_el_list
2575 = process_presence_absence_patterns
2576 (DECL_PRESENCE (decl)->patterns,
2577 DECL_PRESENCE (decl)->patterns_num,
2578 decl->pos, TRUE, DECL_PRESENCE (decl)->final_p);
2579 add_presence_absence (unit_set_el_list, pattern_set_el_list,
2580 decl->pos, TRUE,
2581 DECL_PRESENCE (decl)->final_p);
2585 /* Check absence set declarations and form absence sets. */
2586 for (i = 0; i < description->decls_num; i++)
2588 decl = description->decls [i];
2589 if (decl->mode == dm_absence)
2591 unit_set_el_t unit_set_el_list;
2592 pattern_set_el_t pattern_set_el_list;
2594 unit_set_el_list
2595 = process_presence_absence_names
2596 (DECL_ABSENCE (decl)->names, DECL_ABSENCE (decl)->names_num,
2597 decl->pos, FALSE, DECL_ABSENCE (decl)->final_p);
2598 pattern_set_el_list
2599 = process_presence_absence_patterns
2600 (DECL_ABSENCE (decl)->patterns,
2601 DECL_ABSENCE (decl)->patterns_num,
2602 decl->pos, FALSE, DECL_ABSENCE (decl)->final_p);
2603 add_presence_absence (unit_set_el_list, pattern_set_el_list,
2604 decl->pos, FALSE,
2605 DECL_ABSENCE (decl)->final_p);
2610 /* The following function checks that declared automaton is used. If
2611 the automaton is not used, the function fixes error/warning. The
2612 following function must be called only after `process_decls'. */
2613 static void
2614 check_automaton_usage (void)
2616 decl_t decl;
2617 int i;
2619 for (i = 0; i < description->decls_num; i++)
2621 decl = description->decls [i];
2622 if (decl->mode == dm_automaton
2623 && !DECL_AUTOMATON (decl)->automaton_is_used)
2625 if (!w_flag)
2626 error ("automaton `%s' is not used", DECL_AUTOMATON (decl)->name);
2627 else
2628 warning (0, "automaton `%s' is not used",
2629 DECL_AUTOMATON (decl)->name);
2634 /* The following recursive function processes all regexp in order to
2635 fix usage of units or reservations and to fix errors of undeclared
2636 name. The function may change unit_regexp onto reserv_regexp.
2637 Remember that reserv_regexp does not exist before the function
2638 call. */
2639 static regexp_t
2640 process_regexp (regexp_t regexp)
2642 decl_t decl_in_table;
2643 regexp_t new_regexp;
2644 int i;
2646 switch (regexp->mode)
2648 case rm_unit:
2649 decl_in_table = find_decl (REGEXP_UNIT (regexp)->name);
2650 if (decl_in_table == NULL)
2651 error ("undeclared unit or reservation `%s'",
2652 REGEXP_UNIT (regexp)->name);
2653 else
2654 switch (decl_in_table->mode)
2656 case dm_unit:
2657 DECL_UNIT (decl_in_table)->unit_is_used = 1;
2658 REGEXP_UNIT (regexp)->unit_decl = DECL_UNIT (decl_in_table);
2659 break;
2661 case dm_reserv:
2662 DECL_RESERV (decl_in_table)->reserv_is_used = 1;
2663 new_regexp = create_node (sizeof (struct regexp));
2664 new_regexp->mode = rm_reserv;
2665 new_regexp->pos = regexp->pos;
2666 REGEXP_RESERV (new_regexp)->name = REGEXP_UNIT (regexp)->name;
2667 REGEXP_RESERV (new_regexp)->reserv_decl
2668 = DECL_RESERV (decl_in_table);
2669 regexp = new_regexp;
2670 break;
2672 default:
2673 gcc_unreachable ();
2675 break;
2676 case rm_sequence:
2677 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
2678 REGEXP_SEQUENCE (regexp)->regexps [i]
2679 = process_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
2680 break;
2681 case rm_allof:
2682 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
2683 REGEXP_ALLOF (regexp)->regexps [i]
2684 = process_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
2685 break;
2686 case rm_oneof:
2687 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
2688 REGEXP_ONEOF (regexp)->regexps [i]
2689 = process_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
2690 break;
2691 case rm_repeat:
2692 REGEXP_REPEAT (regexp)->regexp
2693 = process_regexp (REGEXP_REPEAT (regexp)->regexp);
2694 break;
2695 case rm_nothing:
2696 break;
2697 default:
2698 gcc_unreachable ();
2700 return regexp;
2703 /* The following function processes regexp of define_reservation and
2704 define_insn_reservation with the aid of function
2705 `process_regexp'. */
2706 static void
2707 process_regexp_decls (void)
2709 decl_t decl;
2710 int i;
2712 for (i = 0; i < description->decls_num; i++)
2714 decl = description->decls [i];
2715 if (decl->mode == dm_reserv)
2716 DECL_RESERV (decl)->regexp
2717 = process_regexp (DECL_RESERV (decl)->regexp);
2718 else if (decl->mode == dm_insn_reserv)
2719 DECL_INSN_RESERV (decl)->regexp
2720 = process_regexp (DECL_INSN_RESERV (decl)->regexp);
2724 /* The following function checks that declared unit is used. If the
2725 unit is not used, the function fixes errors/warnings. The
2726 following function must be called only after `process_decls',
2727 `process_regexp_decls'. */
2728 static void
2729 check_usage (void)
2731 decl_t decl;
2732 int i;
2734 for (i = 0; i < description->decls_num; i++)
2736 decl = description->decls [i];
2737 if (decl->mode == dm_unit && !DECL_UNIT (decl)->unit_is_used)
2739 if (!w_flag)
2740 error ("unit `%s' is not used", DECL_UNIT (decl)->name);
2741 else
2742 warning (0, "unit `%s' is not used", DECL_UNIT (decl)->name);
2744 else if (decl->mode == dm_reserv && !DECL_RESERV (decl)->reserv_is_used)
2746 if (!w_flag)
2747 error ("reservation `%s' is not used", DECL_RESERV (decl)->name);
2748 else
2749 warning (0, "reservation `%s' is not used", DECL_RESERV (decl)->name);
2754 /* The following variable value is number of reservation being
2755 processed on loop recognition. */
2756 static int curr_loop_pass_num;
2758 /* The following recursive function returns nonzero value if REGEXP
2759 contains given decl or reservations in given regexp refers for
2760 given decl. */
2761 static int
2762 loop_in_regexp (regexp_t regexp, decl_t start_decl)
2764 int i;
2766 if (regexp == NULL)
2767 return 0;
2768 switch (regexp->mode)
2770 case rm_unit:
2771 return 0;
2773 case rm_reserv:
2774 if (start_decl->mode == dm_reserv
2775 && REGEXP_RESERV (regexp)->reserv_decl == DECL_RESERV (start_decl))
2776 return 1;
2777 else if (REGEXP_RESERV (regexp)->reserv_decl->loop_pass_num
2778 == curr_loop_pass_num)
2779 /* declaration has been processed. */
2780 return 0;
2781 else
2783 REGEXP_RESERV (regexp)->reserv_decl->loop_pass_num
2784 = curr_loop_pass_num;
2785 return loop_in_regexp (REGEXP_RESERV (regexp)->reserv_decl->regexp,
2786 start_decl);
2789 case rm_sequence:
2790 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
2791 if (loop_in_regexp (REGEXP_SEQUENCE (regexp)->regexps [i], start_decl))
2792 return 1;
2793 return 0;
2795 case rm_allof:
2796 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
2797 if (loop_in_regexp (REGEXP_ALLOF (regexp)->regexps [i], start_decl))
2798 return 1;
2799 return 0;
2801 case rm_oneof:
2802 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
2803 if (loop_in_regexp (REGEXP_ONEOF (regexp)->regexps [i], start_decl))
2804 return 1;
2805 return 0;
2807 case rm_repeat:
2808 return loop_in_regexp (REGEXP_REPEAT (regexp)->regexp, start_decl);
2810 case rm_nothing:
2811 return 0;
2813 default:
2814 gcc_unreachable ();
2818 /* The following function fixes errors "cycle in definition ...". The
2819 function uses function `loop_in_regexp' for that. */
2820 static void
2821 check_loops_in_regexps (void)
2823 decl_t decl;
2824 int i;
2826 for (i = 0; i < description->decls_num; i++)
2828 decl = description->decls [i];
2829 if (decl->mode == dm_reserv)
2830 DECL_RESERV (decl)->loop_pass_num = 0;
2832 for (i = 0; i < description->decls_num; i++)
2834 decl = description->decls [i];
2835 curr_loop_pass_num = i;
2837 if (decl->mode == dm_reserv)
2839 DECL_RESERV (decl)->loop_pass_num = curr_loop_pass_num;
2840 if (loop_in_regexp (DECL_RESERV (decl)->regexp, decl))
2842 gcc_assert (DECL_RESERV (decl)->regexp);
2843 error ("cycle in definition of reservation `%s'",
2844 DECL_RESERV (decl)->name);
2850 /* The function recursively processes IR of reservation and defines
2851 max and min cycle for reservation of unit. */
2852 static void
2853 process_regexp_cycles (regexp_t regexp, int max_start_cycle,
2854 int min_start_cycle, int *max_finish_cycle,
2855 int *min_finish_cycle)
2857 int i;
2859 switch (regexp->mode)
2861 case rm_unit:
2862 if (REGEXP_UNIT (regexp)->unit_decl->max_occ_cycle_num < max_start_cycle)
2863 REGEXP_UNIT (regexp)->unit_decl->max_occ_cycle_num = max_start_cycle;
2864 if (REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num > min_start_cycle
2865 || REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num == -1)
2866 REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num = min_start_cycle;
2867 *max_finish_cycle = max_start_cycle;
2868 *min_finish_cycle = min_start_cycle;
2869 break;
2871 case rm_reserv:
2872 process_regexp_cycles (REGEXP_RESERV (regexp)->reserv_decl->regexp,
2873 max_start_cycle, min_start_cycle,
2874 max_finish_cycle, min_finish_cycle);
2875 break;
2877 case rm_repeat:
2878 for (i = 0; i < REGEXP_REPEAT (regexp)->repeat_num; i++)
2880 process_regexp_cycles (REGEXP_REPEAT (regexp)->regexp,
2881 max_start_cycle, min_start_cycle,
2882 max_finish_cycle, min_finish_cycle);
2883 max_start_cycle = *max_finish_cycle + 1;
2884 min_start_cycle = *min_finish_cycle + 1;
2886 break;
2888 case rm_sequence:
2889 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
2891 process_regexp_cycles (REGEXP_SEQUENCE (regexp)->regexps [i],
2892 max_start_cycle, min_start_cycle,
2893 max_finish_cycle, min_finish_cycle);
2894 max_start_cycle = *max_finish_cycle + 1;
2895 min_start_cycle = *min_finish_cycle + 1;
2897 break;
2899 case rm_allof:
2901 int max_cycle = 0;
2902 int min_cycle = 0;
2904 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
2906 process_regexp_cycles (REGEXP_ALLOF (regexp)->regexps [i],
2907 max_start_cycle, min_start_cycle,
2908 max_finish_cycle, min_finish_cycle);
2909 if (max_cycle < *max_finish_cycle)
2910 max_cycle = *max_finish_cycle;
2911 if (i == 0 || min_cycle > *min_finish_cycle)
2912 min_cycle = *min_finish_cycle;
2914 *max_finish_cycle = max_cycle;
2915 *min_finish_cycle = min_cycle;
2917 break;
2919 case rm_oneof:
2921 int max_cycle = 0;
2922 int min_cycle = 0;
2924 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
2926 process_regexp_cycles (REGEXP_ONEOF (regexp)->regexps [i],
2927 max_start_cycle, min_start_cycle,
2928 max_finish_cycle, min_finish_cycle);
2929 if (max_cycle < *max_finish_cycle)
2930 max_cycle = *max_finish_cycle;
2931 if (i == 0 || min_cycle > *min_finish_cycle)
2932 min_cycle = *min_finish_cycle;
2934 *max_finish_cycle = max_cycle;
2935 *min_finish_cycle = min_cycle;
2937 break;
2939 case rm_nothing:
2940 *max_finish_cycle = max_start_cycle;
2941 *min_finish_cycle = min_start_cycle;
2942 break;
2944 default:
2945 gcc_unreachable ();
2949 /* The following function is called only for correct program. The
2950 function defines max reservation of insns in cycles. */
2951 static void
2952 evaluate_max_reserv_cycles (void)
2954 int max_insn_cycles_num;
2955 int min_insn_cycles_num;
2956 decl_t decl;
2957 int i;
2959 description->max_insn_reserv_cycles = 0;
2960 for (i = 0; i < description->decls_num; i++)
2962 decl = description->decls [i];
2963 if (decl->mode == dm_insn_reserv)
2965 process_regexp_cycles (DECL_INSN_RESERV (decl)->regexp, 0, 0,
2966 &max_insn_cycles_num, &min_insn_cycles_num);
2967 if (description->max_insn_reserv_cycles < max_insn_cycles_num)
2968 description->max_insn_reserv_cycles = max_insn_cycles_num;
2971 description->max_insn_reserv_cycles++;
2974 /* The following function calls functions for checking all
2975 description. */
2976 static void
2977 check_all_description (void)
2979 process_decls ();
2980 check_automaton_usage ();
2981 process_regexp_decls ();
2982 check_usage ();
2983 check_loops_in_regexps ();
2984 if (!have_error)
2985 evaluate_max_reserv_cycles ();
2990 /* The page contains abstract data `ticker'. This data is used to
2991 report time of different phases of building automata. It is
2992 possibly to write a description for which automata will be built
2993 during several minutes even on fast machine. */
2995 /* The following function creates ticker and makes it active. */
2996 static ticker_t
2997 create_ticker (void)
2999 ticker_t ticker;
3001 ticker.modified_creation_time = get_run_time ();
3002 ticker.incremented_off_time = 0;
3003 return ticker;
3006 /* The following function switches off given ticker. */
3007 static void
3008 ticker_off (ticker_t *ticker)
3010 if (ticker->incremented_off_time == 0)
3011 ticker->incremented_off_time = get_run_time () + 1;
3014 /* The following function switches on given ticker. */
3015 static void
3016 ticker_on (ticker_t *ticker)
3018 if (ticker->incremented_off_time != 0)
3020 ticker->modified_creation_time
3021 += get_run_time () - ticker->incremented_off_time + 1;
3022 ticker->incremented_off_time = 0;
3026 /* The following function returns current time in milliseconds since
3027 the moment when given ticker was created. */
3028 static int
3029 active_time (ticker_t ticker)
3031 if (ticker.incremented_off_time != 0)
3032 return ticker.incremented_off_time - 1 - ticker.modified_creation_time;
3033 else
3034 return get_run_time () - ticker.modified_creation_time;
3037 /* The following function returns string representation of active time
3038 of given ticker. The result is string representation of seconds
3039 with accuracy of 1/100 second. Only result of the last call of the
3040 function exists. Therefore the following code is not correct
3042 printf ("parser time: %s\ngeneration time: %s\n",
3043 active_time_string (parser_ticker),
3044 active_time_string (generation_ticker));
3046 Correct code has to be the following
3048 printf ("parser time: %s\n", active_time_string (parser_ticker));
3049 printf ("generation time: %s\n",
3050 active_time_string (generation_ticker));
3053 static void
3054 print_active_time (FILE *f, ticker_t ticker)
3056 int msecs;
3058 msecs = active_time (ticker);
3059 fprintf (f, "%d.%06d", msecs / 1000000, msecs % 1000000);
3064 /* The following variable value is number of automaton which are
3065 really being created. This value is defined on the base of
3066 argument of option `-split'. If the variable has zero value the
3067 number of automata is defined by the constructions `%automaton'.
3068 This case occurs when option `-split' is absent or has zero
3069 argument. If constructions `define_automaton' is absent only one
3070 automaton is created. */
3071 static int automata_num;
3073 /* The following variable values are times of
3074 o transformation of regular expressions
3075 o building NDFA (DFA if !ndfa_flag)
3076 o NDFA -> DFA (simply the same automaton if !ndfa_flag)
3077 o DFA minimization
3078 o building insn equivalence classes
3079 o all previous ones
3080 o code output */
3081 static ticker_t transform_time;
3082 static ticker_t NDFA_time;
3083 static ticker_t NDFA_to_DFA_time;
3084 static ticker_t minimize_time;
3085 static ticker_t equiv_time;
3086 static ticker_t automaton_generation_time;
3087 static ticker_t output_time;
3089 /* The following variable values are times of
3090 all checking
3091 all generation
3092 all pipeline hazard translator work */
3093 static ticker_t check_time;
3094 static ticker_t generation_time;
3095 static ticker_t all_time;
3099 /* Pseudo insn decl which denotes advancing cycle. */
3100 static decl_t advance_cycle_insn_decl;
3101 static void
3102 add_advance_cycle_insn_decl (void)
3104 advance_cycle_insn_decl = create_node (sizeof (struct decl));
3105 advance_cycle_insn_decl->mode = dm_insn_reserv;
3106 advance_cycle_insn_decl->pos = no_pos;
3107 DECL_INSN_RESERV (advance_cycle_insn_decl)->regexp = NULL;
3108 DECL_INSN_RESERV (advance_cycle_insn_decl)->name = "$advance_cycle";
3109 DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num
3110 = description->insns_num;
3111 description->decls [description->decls_num] = advance_cycle_insn_decl;
3112 description->decls_num++;
3113 description->insns_num++;
3117 /* Abstract data `alternative states' which represents
3118 nondeterministic nature of the description (see comments for
3119 structures alt_state and state). */
3121 /* List of free states. */
3122 static alt_state_t first_free_alt_state;
3124 #ifndef NDEBUG
3125 /* The following variables is maximal number of allocated nodes
3126 alt_state. */
3127 static int allocated_alt_states_num = 0;
3128 #endif
3130 /* The following function returns free node alt_state. It may be new
3131 allocated node or node freed earlier. */
3132 static alt_state_t
3133 get_free_alt_state (void)
3135 alt_state_t result;
3137 if (first_free_alt_state != NULL)
3139 result = first_free_alt_state;
3140 first_free_alt_state = first_free_alt_state->next_alt_state;
3142 else
3144 #ifndef NDEBUG
3145 allocated_alt_states_num++;
3146 #endif
3147 result = create_node (sizeof (struct alt_state));
3149 result->state = NULL;
3150 result->next_alt_state = NULL;
3151 result->next_sorted_alt_state = NULL;
3152 return result;
3155 /* The function frees node ALT_STATE. */
3156 static void
3157 free_alt_state (alt_state_t alt_state)
3159 if (alt_state == NULL)
3160 return;
3161 alt_state->next_alt_state = first_free_alt_state;
3162 first_free_alt_state = alt_state;
3165 /* The function frees list started with node ALT_STATE_LIST. */
3166 static void
3167 free_alt_states (alt_state_t alt_states_list)
3169 alt_state_t curr_alt_state;
3170 alt_state_t next_alt_state;
3172 for (curr_alt_state = alt_states_list;
3173 curr_alt_state != NULL;
3174 curr_alt_state = next_alt_state)
3176 next_alt_state = curr_alt_state->next_alt_state;
3177 free_alt_state (curr_alt_state);
3181 /* The function compares unique numbers of alt states. */
3182 static int
3183 alt_state_cmp (const void *alt_state_ptr_1, const void *alt_state_ptr_2)
3185 if ((*(alt_state_t *) alt_state_ptr_1)->state->unique_num
3186 == (*(alt_state_t *) alt_state_ptr_2)->state->unique_num)
3187 return 0;
3188 else if ((*(alt_state_t *) alt_state_ptr_1)->state->unique_num
3189 < (*(alt_state_t *) alt_state_ptr_2)->state->unique_num)
3190 return -1;
3191 else
3192 return 1;
3195 /* The function sorts ALT_STATES_LIST and removes duplicated alt
3196 states from the list. The comparison key is alt state unique
3197 number. */
3199 static alt_state_t
3200 uniq_sort_alt_states (alt_state_t alt_states_list)
3202 alt_state_t curr_alt_state;
3203 VEC(alt_state_t,heap) *alt_states;
3204 size_t i;
3205 size_t prev_unique_state_ind;
3206 alt_state_t result;
3208 if (alt_states_list == 0)
3209 return 0;
3210 if (alt_states_list->next_alt_state == 0)
3211 return alt_states_list;
3213 alt_states = VEC_alloc (alt_state_t,heap, 150);
3214 for (curr_alt_state = alt_states_list;
3215 curr_alt_state != NULL;
3216 curr_alt_state = curr_alt_state->next_alt_state)
3217 VEC_safe_push (alt_state_t,heap, alt_states, curr_alt_state);
3219 qsort (VEC_address (alt_state_t, alt_states),
3220 VEC_length (alt_state_t, alt_states),
3221 sizeof (alt_state_t), alt_state_cmp);
3223 prev_unique_state_ind = 0;
3224 for (i = 1; i < VEC_length (alt_state_t, alt_states); i++)
3225 if (VEC_index (alt_state_t, alt_states, prev_unique_state_ind)->state
3226 != VEC_index (alt_state_t, alt_states, i)->state)
3228 prev_unique_state_ind++;
3229 VEC_replace (alt_state_t, alt_states, prev_unique_state_ind,
3230 VEC_index (alt_state_t, alt_states, i));
3232 VEC_truncate (alt_state_t, alt_states, prev_unique_state_ind + 1);
3234 for (i = 1; i < VEC_length (alt_state_t, alt_states); i++)
3235 VEC_index (alt_state_t, alt_states, i-1)->next_sorted_alt_state
3236 = VEC_index (alt_state_t, alt_states, i);
3237 VEC_last (alt_state_t, alt_states)->next_sorted_alt_state = 0;
3239 result = VEC_index (alt_state_t, alt_states, 0);
3241 VEC_free (alt_state_t,heap, alt_states);
3242 return result;
3245 /* The function checks equality of alt state lists. Remember that the
3246 lists must be already sorted by the previous function. */
3247 static int
3248 alt_states_eq (alt_state_t alt_states_1, alt_state_t alt_states_2)
3250 while (alt_states_1 != NULL && alt_states_2 != NULL
3251 && alt_state_cmp (&alt_states_1, &alt_states_2) == 0)
3253 alt_states_1 = alt_states_1->next_sorted_alt_state;
3254 alt_states_2 = alt_states_2->next_sorted_alt_state;
3256 return alt_states_1 == alt_states_2;
3259 /* Initialization of the abstract data. */
3260 static void
3261 initiate_alt_states (void)
3263 first_free_alt_state = NULL;
3266 /* Finishing work with the abstract data. */
3267 static void
3268 finish_alt_states (void)
3274 /* The page contains macros for work with bits strings. We could use
3275 standard gcc bitmap or sbitmap but it would result in difficulties
3276 of building canadian cross. */
3278 /* Set bit number bitno in the bit string. The macro is not side
3279 effect proof. */
3280 #define SET_BIT(bitstring, bitno) \
3281 (((char *) (bitstring)) [(bitno) / CHAR_BIT] |= 1 << (bitno) % CHAR_BIT)
3283 #define CLEAR_BIT(bitstring, bitno) \
3284 (((char *) (bitstring)) [(bitno) / CHAR_BIT] &= ~(1 << (bitno) % CHAR_BIT))
3286 /* Test if bit number bitno in the bitstring is set. The macro is not
3287 side effect proof. */
3288 #define TEST_BIT(bitstring, bitno) \
3289 (((char *) (bitstring)) [(bitno) / CHAR_BIT] >> (bitno) % CHAR_BIT & 1)
3293 /* This page contains abstract data `state'. */
3295 /* Maximal length of reservations in cycles (>= 1). */
3296 static int max_cycles_num;
3298 /* Number of set elements (see type set_el_t) needed for
3299 representation of one cycle reservation. It is depended on units
3300 number. */
3301 static int els_in_cycle_reserv;
3303 /* Number of set elements (see type set_el_t) needed for
3304 representation of maximal length reservation. Deterministic
3305 reservation is stored as set (bit string) of length equal to the
3306 variable value * number of bits in set_el_t. */
3307 static int els_in_reservs;
3309 /* Array of pointers to unit declarations. */
3310 static unit_decl_t *units_array;
3312 /* Temporary reservation of maximal length. */
3313 static reserv_sets_t temp_reserv;
3315 /* The state table itself is represented by the following variable. */
3316 static htab_t state_table;
3318 /* Linked list of free 'state' structures to be recycled. The
3319 next_equiv_class_state pointer is borrowed for a free list. */
3320 static state_t first_free_state;
3322 static int curr_unique_state_num;
3324 #ifndef NDEBUG
3325 /* The following variables is maximal number of allocated nodes
3326 `state'. */
3327 static int allocated_states_num = 0;
3328 #endif
3330 /* Allocate new reservation set. */
3331 static reserv_sets_t
3332 alloc_empty_reserv_sets (void)
3334 reserv_sets_t result;
3336 obstack_blank (&irp, els_in_reservs * sizeof (set_el_t));
3337 result = (reserv_sets_t) obstack_base (&irp);
3338 obstack_finish (&irp);
3339 memset (result, 0, els_in_reservs * sizeof (set_el_t));
3340 return result;
3343 /* Hash value of reservation set. */
3344 static unsigned
3345 reserv_sets_hash_value (reserv_sets_t reservs)
3347 set_el_t hash_value;
3348 unsigned result;
3349 int reservs_num, i;
3350 set_el_t *reserv_ptr;
3352 hash_value = 0;
3353 reservs_num = els_in_reservs;
3354 reserv_ptr = reservs;
3355 i = 0;
3356 while (reservs_num != 0)
3358 reservs_num--;
3359 hash_value += ((*reserv_ptr >> i)
3360 | (*reserv_ptr << (sizeof (set_el_t) * CHAR_BIT - i)));
3361 i++;
3362 if (i == sizeof (set_el_t) * CHAR_BIT)
3363 i = 0;
3364 reserv_ptr++;
3366 if (sizeof (set_el_t) <= sizeof (unsigned))
3367 return hash_value;
3368 result = 0;
3369 for (i = sizeof (set_el_t); i > 0; i -= sizeof (unsigned) - 1)
3371 result += (unsigned) hash_value;
3372 hash_value >>= (sizeof (unsigned) - 1) * CHAR_BIT;
3374 return result;
3377 /* Comparison of given reservation sets. */
3378 static int
3379 reserv_sets_cmp (reserv_sets_t reservs_1, reserv_sets_t reservs_2)
3381 int reservs_num;
3382 set_el_t *reserv_ptr_1;
3383 set_el_t *reserv_ptr_2;
3385 gcc_assert (reservs_1 && reservs_2);
3386 reservs_num = els_in_reservs;
3387 reserv_ptr_1 = reservs_1;
3388 reserv_ptr_2 = reservs_2;
3389 while (reservs_num != 0 && *reserv_ptr_1 == *reserv_ptr_2)
3391 reservs_num--;
3392 reserv_ptr_1++;
3393 reserv_ptr_2++;
3395 if (reservs_num == 0)
3396 return 0;
3397 else if (*reserv_ptr_1 < *reserv_ptr_2)
3398 return -1;
3399 else
3400 return 1;
3403 /* The function checks equality of the reservation sets. */
3404 static int
3405 reserv_sets_eq (reserv_sets_t reservs_1, reserv_sets_t reservs_2)
3407 return reserv_sets_cmp (reservs_1, reservs_2) == 0;
3410 /* Set up in the reservation set that unit with UNIT_NUM is used on
3411 CYCLE_NUM. */
3412 static void
3413 set_unit_reserv (reserv_sets_t reservs, int cycle_num, int unit_num)
3415 gcc_assert (cycle_num < max_cycles_num);
3416 SET_BIT (reservs, cycle_num * els_in_cycle_reserv
3417 * sizeof (set_el_t) * CHAR_BIT + unit_num);
3420 /* Set up in the reservation set RESERVS that unit with UNIT_NUM is
3421 used on CYCLE_NUM. */
3422 static int
3423 test_unit_reserv (reserv_sets_t reservs, int cycle_num, int unit_num)
3425 gcc_assert (cycle_num < max_cycles_num);
3426 return TEST_BIT (reservs, cycle_num * els_in_cycle_reserv
3427 * sizeof (set_el_t) * CHAR_BIT + unit_num);
3430 /* The function checks that the reservation sets are intersected,
3431 i.e. there is a unit reservation on a cycle in both reservation
3432 sets. */
3433 static int
3434 reserv_sets_are_intersected (reserv_sets_t operand_1,
3435 reserv_sets_t operand_2)
3437 set_el_t *el_ptr_1;
3438 set_el_t *el_ptr_2;
3439 set_el_t *cycle_ptr_1;
3440 set_el_t *cycle_ptr_2;
3442 gcc_assert (operand_1 && operand_2);
3443 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2;
3444 el_ptr_1 < operand_1 + els_in_reservs;
3445 el_ptr_1++, el_ptr_2++)
3446 if (*el_ptr_1 & *el_ptr_2)
3447 return 1;
3448 reserv_sets_or (temp_reserv, operand_1, operand_2);
3449 for (cycle_ptr_1 = operand_1, cycle_ptr_2 = operand_2;
3450 cycle_ptr_1 < operand_1 + els_in_reservs;
3451 cycle_ptr_1 += els_in_cycle_reserv, cycle_ptr_2 += els_in_cycle_reserv)
3453 for (el_ptr_1 = cycle_ptr_1, el_ptr_2 = get_excl_set (cycle_ptr_2);
3454 el_ptr_1 < cycle_ptr_1 + els_in_cycle_reserv;
3455 el_ptr_1++, el_ptr_2++)
3456 if (*el_ptr_1 & *el_ptr_2)
3457 return 1;
3458 if (!check_presence_pattern_sets (cycle_ptr_1, cycle_ptr_2, FALSE))
3459 return 1;
3460 if (!check_presence_pattern_sets (temp_reserv + (cycle_ptr_2
3461 - operand_2),
3462 cycle_ptr_2, TRUE))
3463 return 1;
3464 if (!check_absence_pattern_sets (cycle_ptr_1, cycle_ptr_2, FALSE))
3465 return 1;
3466 if (!check_absence_pattern_sets (temp_reserv + (cycle_ptr_2 - operand_2),
3467 cycle_ptr_2, TRUE))
3468 return 1;
3470 return 0;
3473 /* The function sets up RESULT bits by bits of OPERAND shifted on one
3474 cpu cycle. The remaining bits of OPERAND (representing the last
3475 cycle unit reservations) are not changed. */
3476 static void
3477 reserv_sets_shift (reserv_sets_t result, reserv_sets_t operand)
3479 int i;
3481 gcc_assert (result && operand && result != operand);
3482 for (i = els_in_cycle_reserv; i < els_in_reservs; i++)
3483 result [i - els_in_cycle_reserv] = operand [i];
3486 /* OR of the reservation sets. */
3487 static void
3488 reserv_sets_or (reserv_sets_t result, reserv_sets_t operand_1,
3489 reserv_sets_t operand_2)
3491 set_el_t *el_ptr_1;
3492 set_el_t *el_ptr_2;
3493 set_el_t *result_set_el_ptr;
3495 gcc_assert (result && operand_1 && operand_2);
3496 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2, result_set_el_ptr = result;
3497 el_ptr_1 < operand_1 + els_in_reservs;
3498 el_ptr_1++, el_ptr_2++, result_set_el_ptr++)
3499 *result_set_el_ptr = *el_ptr_1 | *el_ptr_2;
3502 /* AND of the reservation sets. */
3503 static void
3504 reserv_sets_and (reserv_sets_t result, reserv_sets_t operand_1,
3505 reserv_sets_t operand_2)
3507 set_el_t *el_ptr_1;
3508 set_el_t *el_ptr_2;
3509 set_el_t *result_set_el_ptr;
3511 gcc_assert (result && operand_1 && operand_2);
3512 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2, result_set_el_ptr = result;
3513 el_ptr_1 < operand_1 + els_in_reservs;
3514 el_ptr_1++, el_ptr_2++, result_set_el_ptr++)
3515 *result_set_el_ptr = *el_ptr_1 & *el_ptr_2;
3518 /* The function outputs string representation of units reservation on
3519 cycle START_CYCLE in the reservation set. The function uses repeat
3520 construction if REPETITION_NUM > 1. */
3521 static void
3522 output_cycle_reservs (FILE *f, reserv_sets_t reservs, int start_cycle,
3523 int repetition_num)
3525 int unit_num;
3526 int reserved_units_num;
3528 reserved_units_num = 0;
3529 for (unit_num = 0; unit_num < description->units_num; unit_num++)
3530 if (TEST_BIT (reservs, start_cycle * els_in_cycle_reserv
3531 * sizeof (set_el_t) * CHAR_BIT + unit_num))
3532 reserved_units_num++;
3533 gcc_assert (repetition_num > 0);
3534 if (repetition_num != 1 && reserved_units_num > 1)
3535 fprintf (f, "(");
3536 reserved_units_num = 0;
3537 for (unit_num = 0;
3538 unit_num < description->units_num;
3539 unit_num++)
3540 if (TEST_BIT (reservs, start_cycle * els_in_cycle_reserv
3541 * sizeof (set_el_t) * CHAR_BIT + unit_num))
3543 if (reserved_units_num != 0)
3544 fprintf (f, "+");
3545 reserved_units_num++;
3546 fprintf (f, "%s", units_array [unit_num]->name);
3548 if (reserved_units_num == 0)
3549 fprintf (f, NOTHING_NAME);
3550 gcc_assert (repetition_num > 0);
3551 if (repetition_num != 1 && reserved_units_num > 1)
3552 fprintf (f, ")");
3553 if (repetition_num != 1)
3554 fprintf (f, "*%d", repetition_num);
3557 /* The function outputs string representation of units reservation in
3558 the reservation set. */
3559 static void
3560 output_reserv_sets (FILE *f, reserv_sets_t reservs)
3562 int start_cycle = 0;
3563 int cycle;
3564 int repetition_num;
3566 repetition_num = 0;
3567 for (cycle = 0; cycle < max_cycles_num; cycle++)
3568 if (repetition_num == 0)
3570 repetition_num++;
3571 start_cycle = cycle;
3573 else if (memcmp
3574 ((char *) reservs + start_cycle * els_in_cycle_reserv
3575 * sizeof (set_el_t),
3576 (char *) reservs + cycle * els_in_cycle_reserv
3577 * sizeof (set_el_t),
3578 els_in_cycle_reserv * sizeof (set_el_t)) == 0)
3579 repetition_num++;
3580 else
3582 if (start_cycle != 0)
3583 fprintf (f, ", ");
3584 output_cycle_reservs (f, reservs, start_cycle, repetition_num);
3585 repetition_num = 1;
3586 start_cycle = cycle;
3588 if (start_cycle < max_cycles_num)
3590 if (start_cycle != 0)
3591 fprintf (f, ", ");
3592 output_cycle_reservs (f, reservs, start_cycle, repetition_num);
3596 /* The following function returns free node state for AUTOMATON. It
3597 may be new allocated node or node freed earlier. The function also
3598 allocates reservation set if WITH_RESERVS has nonzero value. */
3599 static state_t
3600 get_free_state (int with_reservs, automaton_t automaton)
3602 state_t result;
3604 gcc_assert (max_cycles_num > 0 && automaton);
3605 if (first_free_state)
3607 result = first_free_state;
3608 first_free_state = result->next_equiv_class_state;
3610 result->next_equiv_class_state = NULL;
3611 result->automaton = automaton;
3612 result->first_out_arc = NULL;
3613 result->it_was_placed_in_stack_for_NDFA_forming = 0;
3614 result->it_was_placed_in_stack_for_DFA_forming = 0;
3615 result->component_states = NULL;
3617 else
3619 #ifndef NDEBUG
3620 allocated_states_num++;
3621 #endif
3622 result = create_node (sizeof (struct state));
3623 result->automaton = automaton;
3624 result->first_out_arc = NULL;
3625 result->unique_num = curr_unique_state_num;
3626 curr_unique_state_num++;
3628 if (with_reservs)
3630 if (result->reservs == NULL)
3631 result->reservs = alloc_empty_reserv_sets ();
3632 else
3633 memset (result->reservs, 0, els_in_reservs * sizeof (set_el_t));
3635 return result;
3638 /* The function frees node STATE. */
3639 static void
3640 free_state (state_t state)
3642 free_alt_states (state->component_states);
3643 state->next_equiv_class_state = first_free_state;
3644 first_free_state = state;
3647 /* Hash value of STATE. If STATE represents deterministic state it is
3648 simply hash value of the corresponding reservation set. Otherwise
3649 it is formed from hash values of the component deterministic
3650 states. One more key is order number of state automaton. */
3651 static hashval_t
3652 state_hash (const void *state)
3654 unsigned int hash_value;
3655 alt_state_t alt_state;
3657 if (((state_t) state)->component_states == NULL)
3658 hash_value = reserv_sets_hash_value (((state_t) state)->reservs);
3659 else
3661 hash_value = 0;
3662 for (alt_state = ((state_t) state)->component_states;
3663 alt_state != NULL;
3664 alt_state = alt_state->next_sorted_alt_state)
3665 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
3666 | (hash_value << CHAR_BIT))
3667 + alt_state->state->unique_num);
3669 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
3670 | (hash_value << CHAR_BIT))
3671 + ((state_t) state)->automaton->automaton_order_num);
3672 return hash_value;
3675 /* Return nonzero value if the states are the same. */
3676 static int
3677 state_eq_p (const void *state_1, const void *state_2)
3679 alt_state_t alt_state_1;
3680 alt_state_t alt_state_2;
3682 if (((state_t) state_1)->automaton != ((state_t) state_2)->automaton)
3683 return 0;
3684 else if (((state_t) state_1)->component_states == NULL
3685 && ((state_t) state_2)->component_states == NULL)
3686 return reserv_sets_eq (((state_t) state_1)->reservs,
3687 ((state_t) state_2)->reservs);
3688 else if (((state_t) state_1)->component_states != NULL
3689 && ((state_t) state_2)->component_states != NULL)
3691 for (alt_state_1 = ((state_t) state_1)->component_states,
3692 alt_state_2 = ((state_t) state_2)->component_states;
3693 alt_state_1 != NULL && alt_state_2 != NULL;
3694 alt_state_1 = alt_state_1->next_sorted_alt_state,
3695 alt_state_2 = alt_state_2->next_sorted_alt_state)
3696 /* All state in the list must be already in the hash table.
3697 Also the lists must be sorted. */
3698 if (alt_state_1->state != alt_state_2->state)
3699 return 0;
3700 return alt_state_1 == alt_state_2;
3702 else
3703 return 0;
3706 /* Insert STATE into the state table. */
3707 static state_t
3708 insert_state (state_t state)
3710 void **entry_ptr;
3712 entry_ptr = htab_find_slot (state_table, (void *) state, 1);
3713 if (*entry_ptr == NULL)
3714 *entry_ptr = (void *) state;
3715 return (state_t) *entry_ptr;
3718 /* Add reservation of unit with UNIT_NUM on cycle CYCLE_NUM to
3719 deterministic STATE. */
3720 static void
3721 set_state_reserv (state_t state, int cycle_num, int unit_num)
3723 set_unit_reserv (state->reservs, cycle_num, unit_num);
3726 /* Return nonzero value if the deterministic states contains a
3727 reservation of the same cpu unit on the same cpu cycle. */
3728 static int
3729 intersected_state_reservs_p (state_t state1, state_t state2)
3731 gcc_assert (state1->automaton == state2->automaton);
3732 return reserv_sets_are_intersected (state1->reservs, state2->reservs);
3735 /* Return deterministic state (inserted into the table) which
3736 representing the automaton state which is union of reservations of
3737 the deterministic states masked by RESERVS. */
3738 static state_t
3739 states_union (state_t state1, state_t state2, reserv_sets_t reservs)
3741 state_t result;
3742 state_t state_in_table;
3744 gcc_assert (state1->automaton == state2->automaton);
3745 result = get_free_state (1, state1->automaton);
3746 reserv_sets_or (result->reservs, state1->reservs, state2->reservs);
3747 reserv_sets_and (result->reservs, result->reservs, reservs);
3748 state_in_table = insert_state (result);
3749 if (result != state_in_table)
3751 free_state (result);
3752 result = state_in_table;
3754 return result;
3757 /* Return deterministic state (inserted into the table) which
3758 represent the automaton state is obtained from deterministic STATE
3759 by advancing cpu cycle and masking by RESERVS. */
3760 static state_t
3761 state_shift (state_t state, reserv_sets_t reservs)
3763 state_t result;
3764 state_t state_in_table;
3766 result = get_free_state (1, state->automaton);
3767 reserv_sets_shift (result->reservs, state->reservs);
3768 reserv_sets_and (result->reservs, result->reservs, reservs);
3769 state_in_table = insert_state (result);
3770 if (result != state_in_table)
3772 free_state (result);
3773 result = state_in_table;
3775 return result;
3778 /* Initialization of the abstract data. */
3779 static void
3780 initiate_states (void)
3782 decl_t decl;
3783 int i;
3785 if (description->units_num)
3786 units_array = XNEWVEC (unit_decl_t, description->units_num);
3787 else
3788 units_array = 0;
3790 for (i = 0; i < description->decls_num; i++)
3792 decl = description->decls [i];
3793 if (decl->mode == dm_unit)
3794 units_array [DECL_UNIT (decl)->unit_num] = DECL_UNIT (decl);
3796 max_cycles_num = description->max_insn_reserv_cycles;
3797 els_in_cycle_reserv
3798 = ((description->units_num + sizeof (set_el_t) * CHAR_BIT - 1)
3799 / (sizeof (set_el_t) * CHAR_BIT));
3800 els_in_reservs = els_in_cycle_reserv * max_cycles_num;
3801 curr_unique_state_num = 0;
3802 initiate_alt_states ();
3803 state_table = htab_create (1500, state_hash, state_eq_p, (htab_del) 0);
3804 temp_reserv = alloc_empty_reserv_sets ();
3807 /* Finishing work with the abstract data. */
3808 static void
3809 finish_states (void)
3811 free (units_array);
3812 units_array = 0;
3813 htab_delete (state_table);
3814 first_free_state = NULL;
3815 finish_alt_states ();
3820 /* Abstract data `arcs'. */
3822 /* List of free arcs. */
3823 static arc_t first_free_arc;
3825 #ifndef NDEBUG
3826 /* The following variables is maximal number of allocated nodes
3827 `arc'. */
3828 static int allocated_arcs_num = 0;
3829 #endif
3831 /* The function frees node ARC. */
3832 static void
3833 free_arc (arc_t arc)
3835 arc->next_out_arc = first_free_arc;
3836 first_free_arc = arc;
3839 /* The function removes and frees ARC staring from FROM_STATE. */
3840 static void
3841 remove_arc (state_t from_state, arc_t arc)
3843 arc_t prev_arc;
3844 arc_t curr_arc;
3846 gcc_assert (arc);
3847 for (prev_arc = NULL, curr_arc = from_state->first_out_arc;
3848 curr_arc != NULL;
3849 prev_arc = curr_arc, curr_arc = curr_arc->next_out_arc)
3850 if (curr_arc == arc)
3851 break;
3852 gcc_assert (curr_arc);
3853 if (prev_arc == NULL)
3854 from_state->first_out_arc = arc->next_out_arc;
3855 else
3856 prev_arc->next_out_arc = arc->next_out_arc;
3857 from_state->num_out_arcs--;
3858 free_arc (arc);
3861 /* The functions returns arc with given characteristics (or NULL if
3862 the arc does not exist). */
3863 static arc_t
3864 find_arc (state_t from_state, state_t to_state, ainsn_t insn)
3866 arc_t arc;
3868 for (arc = first_out_arc (from_state); arc != NULL; arc = next_out_arc (arc))
3869 if (arc->to_state == to_state && arc->insn == insn)
3870 return arc;
3871 return NULL;
3874 /* The function adds arc from FROM_STATE to TO_STATE marked by AINSN.
3875 The function returns added arc (or already existing arc). */
3876 static arc_t
3877 add_arc (state_t from_state, state_t to_state, ainsn_t ainsn)
3879 arc_t new_arc;
3881 new_arc = find_arc (from_state, to_state, ainsn);
3882 if (new_arc != NULL)
3883 return new_arc;
3884 if (first_free_arc == NULL)
3886 #ifndef NDEBUG
3887 allocated_arcs_num++;
3888 #endif
3889 new_arc = create_node (sizeof (struct arc));
3890 new_arc->to_state = NULL;
3891 new_arc->insn = NULL;
3892 new_arc->next_out_arc = NULL;
3894 else
3896 new_arc = first_free_arc;
3897 first_free_arc = first_free_arc->next_out_arc;
3899 new_arc->to_state = to_state;
3900 new_arc->insn = ainsn;
3901 ainsn->arc_exists_p = 1;
3902 new_arc->next_out_arc = from_state->first_out_arc;
3903 from_state->first_out_arc = new_arc;
3904 from_state->num_out_arcs++;
3905 new_arc->next_arc_marked_by_insn = NULL;
3906 return new_arc;
3909 /* The function returns the first arc starting from STATE. */
3910 static arc_t
3911 first_out_arc (state_t state)
3913 return state->first_out_arc;
3916 /* The function returns next out arc after ARC. */
3917 static arc_t
3918 next_out_arc (arc_t arc)
3920 return arc->next_out_arc;
3923 /* Initialization of the abstract data. */
3924 static void
3925 initiate_arcs (void)
3927 first_free_arc = NULL;
3930 /* Finishing work with the abstract data. */
3931 static void
3932 finish_arcs (void)
3938 /* Abstract data `automata lists'. */
3940 /* List of free states. */
3941 static automata_list_el_t first_free_automata_list_el;
3943 /* The list being formed. */
3944 static automata_list_el_t current_automata_list;
3946 /* Hash table of automata lists. */
3947 static htab_t automata_list_table;
3949 /* The following function returns free automata list el. It may be
3950 new allocated node or node freed earlier. */
3951 static automata_list_el_t
3952 get_free_automata_list_el (void)
3954 automata_list_el_t result;
3956 if (first_free_automata_list_el != NULL)
3958 result = first_free_automata_list_el;
3959 first_free_automata_list_el
3960 = first_free_automata_list_el->next_automata_list_el;
3962 else
3963 result = create_node (sizeof (struct automata_list_el));
3964 result->automaton = NULL;
3965 result->next_automata_list_el = NULL;
3966 return result;
3969 /* The function frees node AUTOMATA_LIST_EL. */
3970 static void
3971 free_automata_list_el (automata_list_el_t automata_list_el)
3973 if (automata_list_el == NULL)
3974 return;
3975 automata_list_el->next_automata_list_el = first_free_automata_list_el;
3976 first_free_automata_list_el = automata_list_el;
3979 /* The function frees list AUTOMATA_LIST. */
3980 static void
3981 free_automata_list (automata_list_el_t automata_list)
3983 automata_list_el_t curr_automata_list_el;
3984 automata_list_el_t next_automata_list_el;
3986 for (curr_automata_list_el = automata_list;
3987 curr_automata_list_el != NULL;
3988 curr_automata_list_el = next_automata_list_el)
3990 next_automata_list_el = curr_automata_list_el->next_automata_list_el;
3991 free_automata_list_el (curr_automata_list_el);
3995 /* Hash value of AUTOMATA_LIST. */
3996 static hashval_t
3997 automata_list_hash (const void *automata_list)
3999 unsigned int hash_value;
4000 automata_list_el_t curr_automata_list_el;
4002 hash_value = 0;
4003 for (curr_automata_list_el = (automata_list_el_t) automata_list;
4004 curr_automata_list_el != NULL;
4005 curr_automata_list_el = curr_automata_list_el->next_automata_list_el)
4006 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
4007 | (hash_value << CHAR_BIT))
4008 + curr_automata_list_el->automaton->automaton_order_num);
4009 return hash_value;
4012 /* Return nonzero value if the automata_lists are the same. */
4013 static int
4014 automata_list_eq_p (const void *automata_list_1, const void *automata_list_2)
4016 automata_list_el_t automata_list_el_1;
4017 automata_list_el_t automata_list_el_2;
4019 for (automata_list_el_1 = (automata_list_el_t) automata_list_1,
4020 automata_list_el_2 = (automata_list_el_t) automata_list_2;
4021 automata_list_el_1 != NULL && automata_list_el_2 != NULL;
4022 automata_list_el_1 = automata_list_el_1->next_automata_list_el,
4023 automata_list_el_2 = automata_list_el_2->next_automata_list_el)
4024 if (automata_list_el_1->automaton != automata_list_el_2->automaton)
4025 return 0;
4026 return automata_list_el_1 == automata_list_el_2;
4029 /* Initialization of the abstract data. */
4030 static void
4031 initiate_automata_lists (void)
4033 first_free_automata_list_el = NULL;
4034 automata_list_table = htab_create (1500, automata_list_hash,
4035 automata_list_eq_p, (htab_del) 0);
4038 /* The following function starts new automata list and makes it the
4039 current one. */
4040 static void
4041 automata_list_start (void)
4043 current_automata_list = NULL;
4046 /* The following function adds AUTOMATON to the current list. */
4047 static void
4048 automata_list_add (automaton_t automaton)
4050 automata_list_el_t el;
4052 el = get_free_automata_list_el ();
4053 el->automaton = automaton;
4054 el->next_automata_list_el = current_automata_list;
4055 current_automata_list = el;
4058 /* The following function finishes forming the current list, inserts
4059 it into the table and returns it. */
4060 static automata_list_el_t
4061 automata_list_finish (void)
4063 void **entry_ptr;
4065 if (current_automata_list == NULL)
4066 return NULL;
4067 entry_ptr = htab_find_slot (automata_list_table,
4068 (void *) current_automata_list, 1);
4069 if (*entry_ptr == NULL)
4070 *entry_ptr = (void *) current_automata_list;
4071 else
4072 free_automata_list (current_automata_list);
4073 current_automata_list = NULL;
4074 return (automata_list_el_t) *entry_ptr;
4077 /* Finishing work with the abstract data. */
4078 static void
4079 finish_automata_lists (void)
4081 htab_delete (automata_list_table);
4086 /* The page contains abstract data for work with exclusion sets (see
4087 exclusion_set in file rtl.def). */
4089 /* The following variable refers to an exclusion set returned by
4090 get_excl_set. This is bit string of length equal to cpu units
4091 number. If exclusion set for given unit contains 1 for a unit,
4092 then simultaneous reservation of the units is prohibited. */
4093 static reserv_sets_t excl_set;
4095 /* The array contains exclusion sets for each unit. */
4096 static reserv_sets_t *unit_excl_set_table;
4098 /* The following function forms the array containing exclusion sets
4099 for each unit. */
4100 static void
4101 initiate_excl_sets (void)
4103 decl_t decl;
4104 reserv_sets_t unit_excl_set;
4105 unit_set_el_t el;
4106 int i;
4108 obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4109 excl_set = (reserv_sets_t) obstack_base (&irp);
4110 obstack_finish (&irp);
4111 obstack_blank (&irp, description->units_num * sizeof (reserv_sets_t));
4112 unit_excl_set_table = (reserv_sets_t *) obstack_base (&irp);
4113 obstack_finish (&irp);
4114 /* Evaluate unit exclusion sets. */
4115 for (i = 0; i < description->decls_num; i++)
4117 decl = description->decls [i];
4118 if (decl->mode == dm_unit)
4120 obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4121 unit_excl_set = (reserv_sets_t) obstack_base (&irp);
4122 obstack_finish (&irp);
4123 memset (unit_excl_set, 0, els_in_cycle_reserv * sizeof (set_el_t));
4124 for (el = DECL_UNIT (decl)->excl_list;
4125 el != NULL;
4126 el = el->next_unit_set_el)
4128 SET_BIT (unit_excl_set, el->unit_decl->unit_num);
4129 el->unit_decl->in_set_p = TRUE;
4131 unit_excl_set_table [DECL_UNIT (decl)->unit_num] = unit_excl_set;
4136 /* The function sets up and return EXCL_SET which is union of
4137 exclusion sets for each unit in IN_SET. */
4138 static reserv_sets_t
4139 get_excl_set (reserv_sets_t in_set)
4141 int excl_char_num;
4142 int chars_num;
4143 int i;
4144 int start_unit_num;
4145 int unit_num;
4147 chars_num = els_in_cycle_reserv * sizeof (set_el_t);
4148 memset (excl_set, 0, chars_num);
4149 for (excl_char_num = 0; excl_char_num < chars_num; excl_char_num++)
4150 if (((unsigned char *) in_set) [excl_char_num])
4151 for (i = CHAR_BIT - 1; i >= 0; i--)
4152 if ((((unsigned char *) in_set) [excl_char_num] >> i) & 1)
4154 start_unit_num = excl_char_num * CHAR_BIT + i;
4155 if (start_unit_num >= description->units_num)
4156 return excl_set;
4157 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4159 excl_set [unit_num]
4160 |= unit_excl_set_table [start_unit_num] [unit_num];
4163 return excl_set;
4168 /* The page contains abstract data for work with presence/absence
4169 pattern sets (see presence_set/absence_set in file rtl.def). */
4171 /* The following arrays contain correspondingly presence, final
4172 presence, absence, and final absence patterns for each unit. */
4173 static pattern_reserv_t *unit_presence_set_table;
4174 static pattern_reserv_t *unit_final_presence_set_table;
4175 static pattern_reserv_t *unit_absence_set_table;
4176 static pattern_reserv_t *unit_final_absence_set_table;
4178 /* The following function forms list of reservation sets for given
4179 PATTERN_LIST. */
4180 static pattern_reserv_t
4181 form_reserv_sets_list (pattern_set_el_t pattern_list)
4183 pattern_set_el_t el;
4184 pattern_reserv_t first, curr, prev;
4185 int i;
4187 prev = first = NULL;
4188 for (el = pattern_list; el != NULL; el = el->next_pattern_set_el)
4190 curr = create_node (sizeof (struct pattern_reserv));
4191 curr->reserv = alloc_empty_reserv_sets ();
4192 curr->next_pattern_reserv = NULL;
4193 for (i = 0; i < el->units_num; i++)
4195 SET_BIT (curr->reserv, el->unit_decls [i]->unit_num);
4196 el->unit_decls [i]->in_set_p = TRUE;
4198 if (prev != NULL)
4199 prev->next_pattern_reserv = curr;
4200 else
4201 first = curr;
4202 prev = curr;
4204 return first;
4207 /* The following function forms the array containing presence and
4208 absence pattern sets for each unit. */
4209 static void
4210 initiate_presence_absence_pattern_sets (void)
4212 decl_t decl;
4213 int i;
4215 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4216 unit_presence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4217 obstack_finish (&irp);
4218 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4219 unit_final_presence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4220 obstack_finish (&irp);
4221 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4222 unit_absence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4223 obstack_finish (&irp);
4224 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4225 unit_final_absence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4226 obstack_finish (&irp);
4227 /* Evaluate unit presence/absence sets. */
4228 for (i = 0; i < description->decls_num; i++)
4230 decl = description->decls [i];
4231 if (decl->mode == dm_unit)
4233 unit_presence_set_table [DECL_UNIT (decl)->unit_num]
4234 = form_reserv_sets_list (DECL_UNIT (decl)->presence_list);
4235 unit_final_presence_set_table [DECL_UNIT (decl)->unit_num]
4236 = form_reserv_sets_list (DECL_UNIT (decl)->final_presence_list);
4237 unit_absence_set_table [DECL_UNIT (decl)->unit_num]
4238 = form_reserv_sets_list (DECL_UNIT (decl)->absence_list);
4239 unit_final_absence_set_table [DECL_UNIT (decl)->unit_num]
4240 = form_reserv_sets_list (DECL_UNIT (decl)->final_absence_list);
4245 /* The function checks that CHECKED_SET satisfies all presence pattern
4246 sets for units in ORIGIONAL_SET. The function returns TRUE if it
4247 is ok. */
4248 static int
4249 check_presence_pattern_sets (reserv_sets_t checked_set,
4250 reserv_sets_t origional_set,
4251 int final_p)
4253 int char_num;
4254 int chars_num;
4255 int i;
4256 int start_unit_num;
4257 int unit_num;
4258 int presence_p;
4259 pattern_reserv_t pat_reserv;
4261 chars_num = els_in_cycle_reserv * sizeof (set_el_t);
4262 for (char_num = 0; char_num < chars_num; char_num++)
4263 if (((unsigned char *) origional_set) [char_num])
4264 for (i = CHAR_BIT - 1; i >= 0; i--)
4265 if ((((unsigned char *) origional_set) [char_num] >> i) & 1)
4267 start_unit_num = char_num * CHAR_BIT + i;
4268 if (start_unit_num >= description->units_num)
4269 break;
4270 if ((final_p
4271 && unit_final_presence_set_table [start_unit_num] == NULL)
4272 || (!final_p
4273 && unit_presence_set_table [start_unit_num] == NULL))
4274 continue;
4275 presence_p = FALSE;
4276 for (pat_reserv = (final_p
4277 ? unit_final_presence_set_table [start_unit_num]
4278 : unit_presence_set_table [start_unit_num]);
4279 pat_reserv != NULL;
4280 pat_reserv = pat_reserv->next_pattern_reserv)
4282 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4283 if ((checked_set [unit_num] & pat_reserv->reserv [unit_num])
4284 != pat_reserv->reserv [unit_num])
4285 break;
4286 presence_p = presence_p || unit_num >= els_in_cycle_reserv;
4288 if (!presence_p)
4289 return FALSE;
4291 return TRUE;
4294 /* The function checks that CHECKED_SET satisfies all absence pattern
4295 sets for units in ORIGIONAL_SET. The function returns TRUE if it
4296 is ok. */
4297 static int
4298 check_absence_pattern_sets (reserv_sets_t checked_set,
4299 reserv_sets_t origional_set,
4300 int final_p)
4302 int char_num;
4303 int chars_num;
4304 int i;
4305 int start_unit_num;
4306 int unit_num;
4307 pattern_reserv_t pat_reserv;
4309 chars_num = els_in_cycle_reserv * sizeof (set_el_t);
4310 for (char_num = 0; char_num < chars_num; char_num++)
4311 if (((unsigned char *) origional_set) [char_num])
4312 for (i = CHAR_BIT - 1; i >= 0; i--)
4313 if ((((unsigned char *) origional_set) [char_num] >> i) & 1)
4315 start_unit_num = char_num * CHAR_BIT + i;
4316 if (start_unit_num >= description->units_num)
4317 break;
4318 for (pat_reserv = (final_p
4319 ? unit_final_absence_set_table [start_unit_num]
4320 : unit_absence_set_table [start_unit_num]);
4321 pat_reserv != NULL;
4322 pat_reserv = pat_reserv->next_pattern_reserv)
4324 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4325 if ((checked_set [unit_num] & pat_reserv->reserv [unit_num])
4326 != pat_reserv->reserv [unit_num]
4327 && pat_reserv->reserv [unit_num])
4328 break;
4329 if (unit_num >= els_in_cycle_reserv)
4330 return FALSE;
4333 return TRUE;
4338 /* This page contains code for transformation of original reservations
4339 described in .md file. The main goal of transformations is
4340 simplifying reservation and lifting up all `|' on the top of IR
4341 reservation representation. */
4344 /* The following function makes copy of IR representation of
4345 reservation. The function also substitutes all reservations
4346 defined by define_reservation by corresponding value during making
4347 the copy. */
4348 static regexp_t
4349 copy_insn_regexp (regexp_t regexp)
4351 regexp_t result;
4352 int i;
4354 switch (regexp->mode)
4356 case rm_reserv:
4357 result = copy_insn_regexp (REGEXP_RESERV (regexp)->reserv_decl->regexp);
4358 break;
4360 case rm_unit:
4361 result = copy_node (regexp, sizeof (struct regexp));
4362 break;
4364 case rm_repeat:
4365 result = copy_node (regexp, sizeof (struct regexp));
4366 REGEXP_REPEAT (result)->regexp
4367 = copy_insn_regexp (REGEXP_REPEAT (regexp)->regexp);
4368 break;
4370 case rm_sequence:
4371 result = copy_node (regexp,
4372 sizeof (struct regexp) + sizeof (regexp_t)
4373 * (REGEXP_SEQUENCE (regexp)->regexps_num - 1));
4374 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4375 REGEXP_SEQUENCE (result)->regexps [i]
4376 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4377 break;
4379 case rm_allof:
4380 result = copy_node (regexp,
4381 sizeof (struct regexp) + sizeof (regexp_t)
4382 * (REGEXP_ALLOF (regexp)->regexps_num - 1));
4383 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4384 REGEXP_ALLOF (result)->regexps [i]
4385 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4386 break;
4388 case rm_oneof:
4389 result = copy_node (regexp,
4390 sizeof (struct regexp) + sizeof (regexp_t)
4391 * (REGEXP_ONEOF (regexp)->regexps_num - 1));
4392 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4393 REGEXP_ONEOF (result)->regexps [i]
4394 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4395 break;
4397 case rm_nothing:
4398 result = copy_node (regexp, sizeof (struct regexp));
4399 break;
4401 default:
4402 gcc_unreachable ();
4404 return result;
4407 /* The following variable is set up 1 if a transformation has been
4408 applied. */
4409 static int regexp_transformed_p;
4411 /* The function makes transformation
4412 A*N -> A, A, ... */
4413 static regexp_t
4414 transform_1 (regexp_t regexp)
4416 int i;
4417 int repeat_num;
4418 regexp_t operand;
4419 pos_t pos;
4421 if (regexp->mode == rm_repeat)
4423 repeat_num = REGEXP_REPEAT (regexp)->repeat_num;
4424 gcc_assert (repeat_num > 1);
4425 operand = REGEXP_REPEAT (regexp)->regexp;
4426 pos = regexp->mode;
4427 regexp = create_node (sizeof (struct regexp) + sizeof (regexp_t)
4428 * (repeat_num - 1));
4429 regexp->mode = rm_sequence;
4430 regexp->pos = pos;
4431 REGEXP_SEQUENCE (regexp)->regexps_num = repeat_num;
4432 for (i = 0; i < repeat_num; i++)
4433 REGEXP_SEQUENCE (regexp)->regexps [i] = copy_insn_regexp (operand);
4434 regexp_transformed_p = 1;
4436 return regexp;
4439 /* The function makes transformations
4440 ...,(A,B,...),C,... -> ...,A,B,...,C,...
4441 ...+(A+B+...)+C+... -> ...+A+B+...+C+...
4442 ...|(A|B|...)|C|... -> ...|A|B|...|C|... */
4443 static regexp_t
4444 transform_2 (regexp_t regexp)
4446 if (regexp->mode == rm_sequence)
4448 regexp_t sequence = NULL;
4449 regexp_t result;
4450 int sequence_index = 0;
4451 int i, j;
4453 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4454 if (REGEXP_SEQUENCE (regexp)->regexps [i]->mode == rm_sequence)
4456 sequence_index = i;
4457 sequence = REGEXP_SEQUENCE (regexp)->regexps [i];
4458 break;
4460 if (i < REGEXP_SEQUENCE (regexp)->regexps_num)
4462 gcc_assert (REGEXP_SEQUENCE (sequence)->regexps_num > 1
4463 && REGEXP_SEQUENCE (regexp)->regexps_num > 1);
4464 result = create_node (sizeof (struct regexp)
4465 + sizeof (regexp_t)
4466 * (REGEXP_SEQUENCE (regexp)->regexps_num
4467 + REGEXP_SEQUENCE (sequence)->regexps_num
4468 - 2));
4469 result->mode = rm_sequence;
4470 result->pos = regexp->pos;
4471 REGEXP_SEQUENCE (result)->regexps_num
4472 = (REGEXP_SEQUENCE (regexp)->regexps_num
4473 + REGEXP_SEQUENCE (sequence)->regexps_num - 1);
4474 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4475 if (i < sequence_index)
4476 REGEXP_SEQUENCE (result)->regexps [i]
4477 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4478 else if (i > sequence_index)
4479 REGEXP_SEQUENCE (result)->regexps
4480 [i + REGEXP_SEQUENCE (sequence)->regexps_num - 1]
4481 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4482 else
4483 for (j = 0; j < REGEXP_SEQUENCE (sequence)->regexps_num; j++)
4484 REGEXP_SEQUENCE (result)->regexps [i + j]
4485 = copy_insn_regexp (REGEXP_SEQUENCE (sequence)->regexps [j]);
4486 regexp_transformed_p = 1;
4487 regexp = result;
4490 else if (regexp->mode == rm_allof)
4492 regexp_t allof = NULL;
4493 regexp_t result;
4494 int allof_index = 0;
4495 int i, j;
4497 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4498 if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_allof)
4500 allof_index = i;
4501 allof = REGEXP_ALLOF (regexp)->regexps [i];
4502 break;
4504 if (i < REGEXP_ALLOF (regexp)->regexps_num)
4506 gcc_assert (REGEXP_ALLOF (allof)->regexps_num > 1
4507 && REGEXP_ALLOF (regexp)->regexps_num > 1);
4508 result = create_node (sizeof (struct regexp)
4509 + sizeof (regexp_t)
4510 * (REGEXP_ALLOF (regexp)->regexps_num
4511 + REGEXP_ALLOF (allof)->regexps_num - 2));
4512 result->mode = rm_allof;
4513 result->pos = regexp->pos;
4514 REGEXP_ALLOF (result)->regexps_num
4515 = (REGEXP_ALLOF (regexp)->regexps_num
4516 + REGEXP_ALLOF (allof)->regexps_num - 1);
4517 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4518 if (i < allof_index)
4519 REGEXP_ALLOF (result)->regexps [i]
4520 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4521 else if (i > allof_index)
4522 REGEXP_ALLOF (result)->regexps
4523 [i + REGEXP_ALLOF (allof)->regexps_num - 1]
4524 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4525 else
4526 for (j = 0; j < REGEXP_ALLOF (allof)->regexps_num; j++)
4527 REGEXP_ALLOF (result)->regexps [i + j]
4528 = copy_insn_regexp (REGEXP_ALLOF (allof)->regexps [j]);
4529 regexp_transformed_p = 1;
4530 regexp = result;
4533 else if (regexp->mode == rm_oneof)
4535 regexp_t oneof = NULL;
4536 regexp_t result;
4537 int oneof_index = 0;
4538 int i, j;
4540 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4541 if (REGEXP_ONEOF (regexp)->regexps [i]->mode == rm_oneof)
4543 oneof_index = i;
4544 oneof = REGEXP_ONEOF (regexp)->regexps [i];
4545 break;
4547 if (i < REGEXP_ONEOF (regexp)->regexps_num)
4549 gcc_assert (REGEXP_ONEOF (oneof)->regexps_num > 1
4550 && REGEXP_ONEOF (regexp)->regexps_num > 1);
4551 result = create_node (sizeof (struct regexp)
4552 + sizeof (regexp_t)
4553 * (REGEXP_ONEOF (regexp)->regexps_num
4554 + REGEXP_ONEOF (oneof)->regexps_num - 2));
4555 result->mode = rm_oneof;
4556 result->pos = regexp->pos;
4557 REGEXP_ONEOF (result)->regexps_num
4558 = (REGEXP_ONEOF (regexp)->regexps_num
4559 + REGEXP_ONEOF (oneof)->regexps_num - 1);
4560 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4561 if (i < oneof_index)
4562 REGEXP_ONEOF (result)->regexps [i]
4563 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4564 else if (i > oneof_index)
4565 REGEXP_ONEOF (result)->regexps
4566 [i + REGEXP_ONEOF (oneof)->regexps_num - 1]
4567 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4568 else
4569 for (j = 0; j < REGEXP_ONEOF (oneof)->regexps_num; j++)
4570 REGEXP_ONEOF (result)->regexps [i + j]
4571 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [j]);
4572 regexp_transformed_p = 1;
4573 regexp = result;
4576 return regexp;
4579 /* The function makes transformations
4580 ...,A|B|...,C,... -> (...,A,C,...)|(...,B,C,...)|...
4581 ...+(A|B|...)+C+... -> (...+A+C+...)|(...+B+C+...)|...
4582 ...+(A,B,...)+C+... -> (...+A+C+...),B,...
4583 ...+(A,B,...)+(C,D,...) -> (A+C),(B+D),... */
4584 static regexp_t
4585 transform_3 (regexp_t regexp)
4587 if (regexp->mode == rm_sequence)
4589 regexp_t oneof = NULL;
4590 int oneof_index = 0;
4591 regexp_t result;
4592 regexp_t sequence;
4593 int i, j;
4595 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4596 if (REGEXP_SEQUENCE (regexp)->regexps [i]->mode == rm_oneof)
4598 oneof_index = i;
4599 oneof = REGEXP_SEQUENCE (regexp)->regexps [i];
4600 break;
4602 if (i < REGEXP_SEQUENCE (regexp)->regexps_num)
4604 gcc_assert (REGEXP_ONEOF (oneof)->regexps_num > 1
4605 && REGEXP_SEQUENCE (regexp)->regexps_num > 1);
4606 result = create_node (sizeof (struct regexp)
4607 + sizeof (regexp_t)
4608 * (REGEXP_ONEOF (oneof)->regexps_num - 1));
4609 result->mode = rm_oneof;
4610 result->pos = regexp->pos;
4611 REGEXP_ONEOF (result)->regexps_num
4612 = REGEXP_ONEOF (oneof)->regexps_num;
4613 for (i = 0; i < REGEXP_ONEOF (result)->regexps_num; i++)
4615 sequence
4616 = create_node (sizeof (struct regexp)
4617 + sizeof (regexp_t)
4618 * (REGEXP_SEQUENCE (regexp)->regexps_num - 1));
4619 sequence->mode = rm_sequence;
4620 sequence->pos = regexp->pos;
4621 REGEXP_SEQUENCE (sequence)->regexps_num
4622 = REGEXP_SEQUENCE (regexp)->regexps_num;
4623 REGEXP_ONEOF (result)->regexps [i] = sequence;
4624 for (j = 0; j < REGEXP_SEQUENCE (sequence)->regexps_num; j++)
4625 if (j != oneof_index)
4626 REGEXP_SEQUENCE (sequence)->regexps [j]
4627 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [j]);
4628 else
4629 REGEXP_SEQUENCE (sequence)->regexps [j]
4630 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [i]);
4632 regexp_transformed_p = 1;
4633 regexp = result;
4636 else if (regexp->mode == rm_allof)
4638 regexp_t oneof = NULL;
4639 regexp_t seq;
4640 int oneof_index = 0;
4641 int max_seq_length, allof_length;
4642 regexp_t result;
4643 regexp_t allof = NULL;
4644 regexp_t allof_op = NULL;
4645 int i, j;
4647 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4648 if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_oneof)
4650 oneof_index = i;
4651 oneof = REGEXP_ALLOF (regexp)->regexps [i];
4652 break;
4654 if (i < REGEXP_ALLOF (regexp)->regexps_num)
4656 gcc_assert (REGEXP_ONEOF (oneof)->regexps_num > 1
4657 && REGEXP_ALLOF (regexp)->regexps_num > 1);
4658 result = create_node (sizeof (struct regexp)
4659 + sizeof (regexp_t)
4660 * (REGEXP_ONEOF (oneof)->regexps_num - 1));
4661 result->mode = rm_oneof;
4662 result->pos = regexp->pos;
4663 REGEXP_ONEOF (result)->regexps_num
4664 = REGEXP_ONEOF (oneof)->regexps_num;
4665 for (i = 0; i < REGEXP_ONEOF (result)->regexps_num; i++)
4667 allof
4668 = create_node (sizeof (struct regexp)
4669 + sizeof (regexp_t)
4670 * (REGEXP_ALLOF (regexp)->regexps_num - 1));
4671 allof->mode = rm_allof;
4672 allof->pos = regexp->pos;
4673 REGEXP_ALLOF (allof)->regexps_num
4674 = REGEXP_ALLOF (regexp)->regexps_num;
4675 REGEXP_ONEOF (result)->regexps [i] = allof;
4676 for (j = 0; j < REGEXP_ALLOF (allof)->regexps_num; j++)
4677 if (j != oneof_index)
4678 REGEXP_ALLOF (allof)->regexps [j]
4679 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [j]);
4680 else
4681 REGEXP_ALLOF (allof)->regexps [j]
4682 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [i]);
4684 regexp_transformed_p = 1;
4685 regexp = result;
4687 max_seq_length = 0;
4688 if (regexp->mode == rm_allof)
4689 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4691 switch (REGEXP_ALLOF (regexp)->regexps [i]->mode)
4693 case rm_sequence:
4694 seq = REGEXP_ALLOF (regexp)->regexps [i];
4695 if (max_seq_length < REGEXP_SEQUENCE (seq)->regexps_num)
4696 max_seq_length = REGEXP_SEQUENCE (seq)->regexps_num;
4697 break;
4699 case rm_unit:
4700 case rm_nothing:
4701 break;
4703 default:
4704 max_seq_length = 0;
4705 goto break_for;
4708 break_for:
4709 if (max_seq_length != 0)
4711 gcc_assert (max_seq_length != 1
4712 && REGEXP_ALLOF (regexp)->regexps_num > 1);
4713 result = create_node (sizeof (struct regexp)
4714 + sizeof (regexp_t) * (max_seq_length - 1));
4715 result->mode = rm_sequence;
4716 result->pos = regexp->pos;
4717 REGEXP_SEQUENCE (result)->regexps_num = max_seq_length;
4718 for (i = 0; i < max_seq_length; i++)
4720 allof_length = 0;
4721 for (j = 0; j < REGEXP_ALLOF (regexp)->regexps_num; j++)
4722 switch (REGEXP_ALLOF (regexp)->regexps [j]->mode)
4724 case rm_sequence:
4725 if (i < (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4726 ->regexps [j])->regexps_num))
4728 allof_op
4729 = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4730 ->regexps [j])
4731 ->regexps [i]);
4732 allof_length++;
4734 break;
4735 case rm_unit:
4736 case rm_nothing:
4737 if (i == 0)
4739 allof_op = REGEXP_ALLOF (regexp)->regexps [j];
4740 allof_length++;
4742 break;
4743 default:
4744 break;
4747 if (allof_length == 1)
4748 REGEXP_SEQUENCE (result)->regexps [i] = allof_op;
4749 else
4751 allof = create_node (sizeof (struct regexp)
4752 + sizeof (regexp_t)
4753 * (allof_length - 1));
4754 allof->mode = rm_allof;
4755 allof->pos = regexp->pos;
4756 REGEXP_ALLOF (allof)->regexps_num = allof_length;
4757 REGEXP_SEQUENCE (result)->regexps [i] = allof;
4758 allof_length = 0;
4759 for (j = 0; j < REGEXP_ALLOF (regexp)->regexps_num; j++)
4760 if (REGEXP_ALLOF (regexp)->regexps [j]->mode == rm_sequence
4761 && (i <
4762 (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4763 ->regexps [j])->regexps_num)))
4765 allof_op = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4766 ->regexps [j])
4767 ->regexps [i]);
4768 REGEXP_ALLOF (allof)->regexps [allof_length]
4769 = allof_op;
4770 allof_length++;
4772 else if (i == 0
4773 && (REGEXP_ALLOF (regexp)->regexps [j]->mode
4774 == rm_unit
4775 || (REGEXP_ALLOF (regexp)->regexps [j]->mode
4776 == rm_nothing)))
4778 allof_op = REGEXP_ALLOF (regexp)->regexps [j];
4779 REGEXP_ALLOF (allof)->regexps [allof_length]
4780 = allof_op;
4781 allof_length++;
4785 regexp_transformed_p = 1;
4786 regexp = result;
4789 return regexp;
4792 /* The function traverses IR of reservation and applies transformations
4793 implemented by FUNC. */
4794 static regexp_t
4795 regexp_transform_func (regexp_t regexp, regexp_t (*func) (regexp_t regexp))
4797 int i;
4799 switch (regexp->mode)
4801 case rm_sequence:
4802 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4803 REGEXP_SEQUENCE (regexp)->regexps [i]
4804 = regexp_transform_func (REGEXP_SEQUENCE (regexp)->regexps [i],
4805 func);
4806 break;
4808 case rm_allof:
4809 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4810 REGEXP_ALLOF (regexp)->regexps [i]
4811 = regexp_transform_func (REGEXP_ALLOF (regexp)->regexps [i], func);
4812 break;
4814 case rm_oneof:
4815 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4816 REGEXP_ONEOF (regexp)->regexps [i]
4817 = regexp_transform_func (REGEXP_ONEOF (regexp)->regexps [i], func);
4818 break;
4820 case rm_repeat:
4821 REGEXP_REPEAT (regexp)->regexp
4822 = regexp_transform_func (REGEXP_REPEAT (regexp)->regexp, func);
4823 break;
4825 case rm_nothing:
4826 case rm_unit:
4827 break;
4829 default:
4830 gcc_unreachable ();
4832 return (*func) (regexp);
4835 /* The function applies all transformations for IR representation of
4836 reservation REGEXP. */
4837 static regexp_t
4838 transform_regexp (regexp_t regexp)
4840 regexp = regexp_transform_func (regexp, transform_1);
4843 regexp_transformed_p = 0;
4844 regexp = regexp_transform_func (regexp, transform_2);
4845 regexp = regexp_transform_func (regexp, transform_3);
4847 while (regexp_transformed_p);
4848 return regexp;
4851 /* The function applies all transformations for reservations of all
4852 insn declarations. */
4853 static void
4854 transform_insn_regexps (void)
4856 decl_t decl;
4857 int i;
4859 transform_time = create_ticker ();
4860 add_advance_cycle_insn_decl ();
4861 if (progress_flag)
4862 fprintf (stderr, "Reservation transformation...");
4863 for (i = 0; i < description->decls_num; i++)
4865 decl = description->decls [i];
4866 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
4867 DECL_INSN_RESERV (decl)->transformed_regexp
4868 = transform_regexp (copy_insn_regexp
4869 (DECL_INSN_RESERV (decl)->regexp));
4871 if (progress_flag)
4872 fprintf (stderr, "done\n");
4873 ticker_off (&transform_time);
4878 /* The following variable value is TRUE if the first annotated message
4879 about units to automata distribution has been output. */
4880 static int annotation_message_reported_p;
4882 /* The following structure describes usage of a unit in a reservation. */
4883 struct unit_usage
4885 unit_decl_t unit_decl;
4886 /* The following forms a list of units used on the same cycle in the
4887 same alternative. */
4888 struct unit_usage *next;
4890 typedef struct unit_usage *unit_usage_t;
4892 DEF_VEC_P(unit_usage_t);
4893 DEF_VEC_ALLOC_P(unit_usage_t,heap);
4895 /* Obstack for unit_usage structures. */
4896 static struct obstack unit_usages;
4898 /* VLA for representation of array of pointers to unit usage
4899 structures. There is an element for each combination of
4900 (alternative number, cycle). Unit usages on given cycle in
4901 alternative with given number are referred through element with
4902 index equals to the cycle * number of all alternatives in the regexp
4903 + the alternative number. */
4904 static VEC(unit_usage_t,heap) *cycle_alt_unit_usages;
4906 /* The following function creates the structure unit_usage for UNIT on
4907 CYCLE in REGEXP alternative with ALT_NUM. The structure is made
4908 accessed through cycle_alt_unit_usages. */
4909 static void
4910 store_alt_unit_usage (regexp_t regexp, regexp_t unit, int cycle,
4911 int alt_num)
4913 size_t length;
4914 unit_decl_t unit_decl;
4915 unit_usage_t unit_usage_ptr;
4916 int index;
4918 gcc_assert (regexp && regexp->mode == rm_oneof
4919 && alt_num < REGEXP_ONEOF (regexp)->regexps_num);
4920 unit_decl = REGEXP_UNIT (unit)->unit_decl;
4922 length = (cycle + 1) * REGEXP_ONEOF (regexp)->regexps_num;
4923 while (VEC_length (unit_usage_t, cycle_alt_unit_usages) < length)
4924 VEC_safe_push (unit_usage_t,heap, cycle_alt_unit_usages, 0);
4926 obstack_blank (&unit_usages, sizeof (struct unit_usage));
4927 unit_usage_ptr = (struct unit_usage *) obstack_base (&unit_usages);
4928 obstack_finish (&unit_usages);
4929 unit_usage_ptr->unit_decl = unit_decl;
4930 index = cycle * REGEXP_ONEOF (regexp)->regexps_num + alt_num;
4931 unit_usage_ptr->next = VEC_index (unit_usage_t, cycle_alt_unit_usages, index);
4932 VEC_replace (unit_usage_t, cycle_alt_unit_usages, index, unit_usage_ptr);
4933 unit_decl->last_distribution_check_cycle = -1; /* undefined */
4936 /* The function processes given REGEXP to find units with the wrong
4937 distribution. */
4938 static void
4939 check_regexp_units_distribution (const char *insn_reserv_name,
4940 regexp_t regexp)
4942 int i, j, k, cycle;
4943 regexp_t seq, allof, unit;
4944 struct unit_usage *unit_usage_ptr, *other_unit_usage_ptr;
4946 if (regexp == NULL || regexp->mode != rm_oneof)
4947 return;
4948 /* Store all unit usages in the regexp: */
4949 obstack_init (&unit_usages);
4950 cycle_alt_unit_usages = 0;
4952 for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
4954 seq = REGEXP_ONEOF (regexp)->regexps [i];
4955 switch (seq->mode)
4957 case rm_sequence:
4958 for (j = 0; j < REGEXP_SEQUENCE (seq)->regexps_num; j++)
4960 allof = REGEXP_SEQUENCE (seq)->regexps [j];
4961 switch (allof->mode)
4963 case rm_allof:
4964 for (k = 0; k < REGEXP_ALLOF (allof)->regexps_num; k++)
4966 unit = REGEXP_ALLOF (allof)->regexps [k];
4967 if (unit->mode == rm_unit)
4968 store_alt_unit_usage (regexp, unit, j, i);
4969 else
4970 gcc_assert (unit->mode == rm_nothing);
4972 break;
4974 case rm_unit:
4975 store_alt_unit_usage (regexp, allof, j, i);
4976 break;
4978 case rm_nothing:
4979 break;
4981 default:
4982 gcc_unreachable ();
4985 break;
4987 case rm_allof:
4988 for (k = 0; k < REGEXP_ALLOF (seq)->regexps_num; k++)
4990 unit = REGEXP_ALLOF (seq)->regexps [k];
4991 switch (unit->mode)
4993 case rm_unit:
4994 store_alt_unit_usage (regexp, unit, 0, i);
4995 break;
4997 case rm_nothing:
4998 break;
5000 default:
5001 gcc_unreachable ();
5004 break;
5006 case rm_unit:
5007 store_alt_unit_usage (regexp, seq, 0, i);
5008 break;
5010 case rm_nothing:
5011 break;
5013 default:
5014 gcc_unreachable ();
5017 /* Check distribution: */
5018 for (i = 0; i < (int) VEC_length (unit_usage_t, cycle_alt_unit_usages); i++)
5020 cycle = i / REGEXP_ONEOF (regexp)->regexps_num;
5021 for (unit_usage_ptr = VEC_index (unit_usage_t, cycle_alt_unit_usages, i);
5022 unit_usage_ptr != NULL;
5023 unit_usage_ptr = unit_usage_ptr->next)
5024 if (cycle != unit_usage_ptr->unit_decl->last_distribution_check_cycle)
5026 unit_usage_ptr->unit_decl->last_distribution_check_cycle = cycle;
5027 for (k = cycle * REGEXP_ONEOF (regexp)->regexps_num;
5028 k < (int) VEC_length (unit_usage_t, cycle_alt_unit_usages)
5029 && k == cycle * REGEXP_ONEOF (regexp)->regexps_num;
5030 k++)
5032 for (other_unit_usage_ptr
5033 = VEC_index (unit_usage_t, cycle_alt_unit_usages, k);
5034 other_unit_usage_ptr != NULL;
5035 other_unit_usage_ptr = other_unit_usage_ptr->next)
5036 if (unit_usage_ptr->unit_decl->automaton_decl
5037 == other_unit_usage_ptr->unit_decl->automaton_decl)
5038 break;
5039 if (other_unit_usage_ptr == NULL
5040 && (VEC_index (unit_usage_t, cycle_alt_unit_usages, k)
5041 != NULL))
5042 break;
5044 if (k < (int) VEC_length (unit_usage_t, cycle_alt_unit_usages)
5045 && k == cycle * REGEXP_ONEOF (regexp)->regexps_num)
5047 if (!annotation_message_reported_p)
5049 fprintf (stderr, "\n");
5050 error ("The following units do not satisfy units-automata distribution rule");
5051 error (" (A unit of given unit automaton should be on each reserv. altern.)");
5052 annotation_message_reported_p = TRUE;
5054 error ("Unit %s, reserv. %s, cycle %d",
5055 unit_usage_ptr->unit_decl->name, insn_reserv_name,
5056 cycle);
5060 VEC_free (unit_usage_t,heap, cycle_alt_unit_usages);
5061 obstack_free (&unit_usages, NULL);
5064 /* The function finds units which violates units to automata
5065 distribution rule. If the units exist, report about them. */
5066 static void
5067 check_unit_distributions_to_automata (void)
5069 decl_t decl;
5070 int i;
5072 if (progress_flag)
5073 fprintf (stderr, "Check unit distributions to automata...");
5074 annotation_message_reported_p = FALSE;
5075 for (i = 0; i < description->decls_num; i++)
5077 decl = description->decls [i];
5078 if (decl->mode == dm_insn_reserv)
5079 check_regexp_units_distribution
5080 (DECL_INSN_RESERV (decl)->name,
5081 DECL_INSN_RESERV (decl)->transformed_regexp);
5083 if (progress_flag)
5084 fprintf (stderr, "done\n");
5089 /* The page contains code for building alt_states (see comments for
5090 IR) describing all possible insns reservations of an automaton. */
5092 /* Current state being formed for which the current alt_state
5093 refers. */
5094 static state_t state_being_formed;
5096 /* Current alt_state being formed. */
5097 static alt_state_t alt_state_being_formed;
5099 /* This recursive function processes `,' and units in reservation
5100 REGEXP for forming alt_states of AUTOMATON. It is believed that
5101 CURR_CYCLE is start cycle of all reservation REGEXP. */
5102 static int
5103 process_seq_for_forming_states (regexp_t regexp, automaton_t automaton,
5104 int curr_cycle)
5106 int i;
5108 if (regexp == NULL)
5109 return curr_cycle;
5111 switch (regexp->mode)
5113 case rm_unit:
5114 if (REGEXP_UNIT (regexp)->unit_decl->corresponding_automaton_num
5115 == automaton->automaton_order_num)
5116 set_state_reserv (state_being_formed, curr_cycle,
5117 REGEXP_UNIT (regexp)->unit_decl->unit_num);
5118 return curr_cycle;
5120 case rm_sequence:
5121 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
5122 curr_cycle
5123 = process_seq_for_forming_states
5124 (REGEXP_SEQUENCE (regexp)->regexps [i], automaton, curr_cycle) + 1;
5125 return curr_cycle;
5127 case rm_allof:
5129 int finish_cycle = 0;
5130 int cycle;
5132 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
5134 cycle = process_seq_for_forming_states (REGEXP_ALLOF (regexp)
5135 ->regexps [i],
5136 automaton, curr_cycle);
5137 if (finish_cycle < cycle)
5138 finish_cycle = cycle;
5140 return finish_cycle;
5143 case rm_nothing:
5144 return curr_cycle;
5146 default:
5147 gcc_unreachable ();
5151 /* This recursive function finishes forming ALT_STATE of AUTOMATON and
5152 inserts alt_state into the table. */
5153 static void
5154 finish_forming_alt_state (alt_state_t alt_state,
5155 automaton_t automaton ATTRIBUTE_UNUSED)
5157 state_t state_in_table;
5158 state_t corresponding_state;
5160 corresponding_state = alt_state->state;
5161 state_in_table = insert_state (corresponding_state);
5162 if (state_in_table != corresponding_state)
5164 free_state (corresponding_state);
5165 alt_state->state = state_in_table;
5169 /* The following variable value is current automaton insn for whose
5170 reservation the alt states are created. */
5171 static ainsn_t curr_ainsn;
5173 /* This recursive function processes `|' in reservation REGEXP for
5174 forming alt_states of AUTOMATON. List of the alt states should
5175 have the same order as in the description. */
5176 static void
5177 process_alts_for_forming_states (regexp_t regexp, automaton_t automaton,
5178 int inside_oneof_p)
5180 int i;
5182 if (regexp->mode != rm_oneof)
5184 alt_state_being_formed = get_free_alt_state ();
5185 state_being_formed = get_free_state (1, automaton);
5186 alt_state_being_formed->state = state_being_formed;
5187 /* We inserts in reverse order but we process alternatives also
5188 in reverse order. So we have the same order of alternative
5189 as in the description. */
5190 alt_state_being_formed->next_alt_state = curr_ainsn->alt_states;
5191 curr_ainsn->alt_states = alt_state_being_formed;
5192 (void) process_seq_for_forming_states (regexp, automaton, 0);
5193 finish_forming_alt_state (alt_state_being_formed, automaton);
5195 else
5197 gcc_assert (!inside_oneof_p);
5198 /* We processes it in reverse order to get list with the same
5199 order as in the description. See also the previous
5200 commentary. */
5201 for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
5202 process_alts_for_forming_states (REGEXP_ONEOF (regexp)->regexps [i],
5203 automaton, 1);
5207 /* Create nodes alt_state for all AUTOMATON insns. */
5208 static void
5209 create_alt_states (automaton_t automaton)
5211 struct insn_reserv_decl *reserv_decl;
5213 for (curr_ainsn = automaton->ainsn_list;
5214 curr_ainsn != NULL;
5215 curr_ainsn = curr_ainsn->next_ainsn)
5217 reserv_decl = curr_ainsn->insn_reserv_decl;
5218 if (reserv_decl != DECL_INSN_RESERV (advance_cycle_insn_decl))
5220 curr_ainsn->alt_states = NULL;
5221 process_alts_for_forming_states (reserv_decl->transformed_regexp,
5222 automaton, 0);
5223 curr_ainsn->sorted_alt_states
5224 = uniq_sort_alt_states (curr_ainsn->alt_states);
5231 /* The page contains major code for building DFA(s) for fast pipeline
5232 hazards recognition. */
5234 /* The function forms list of ainsns of AUTOMATON with the same
5235 reservation. */
5237 static void
5238 form_ainsn_with_same_reservs (automaton_t automaton)
5240 ainsn_t curr_ainsn;
5241 size_t i;
5242 VEC(ainsn_t,heap) *last_insns = VEC_alloc (ainsn_t,heap, 150);
5244 for (curr_ainsn = automaton->ainsn_list;
5245 curr_ainsn != NULL;
5246 curr_ainsn = curr_ainsn->next_ainsn)
5247 if (curr_ainsn->insn_reserv_decl
5248 == DECL_INSN_RESERV (advance_cycle_insn_decl))
5250 curr_ainsn->next_same_reservs_insn = NULL;
5251 curr_ainsn->first_insn_with_same_reservs = 1;
5253 else
5255 for (i = 0; i < VEC_length (ainsn_t, last_insns); i++)
5256 if (alt_states_eq
5257 (curr_ainsn->sorted_alt_states,
5258 VEC_index (ainsn_t, last_insns, i)->sorted_alt_states))
5259 break;
5260 curr_ainsn->next_same_reservs_insn = NULL;
5261 if (i < VEC_length (ainsn_t, last_insns))
5263 curr_ainsn->first_insn_with_same_reservs = 0;
5264 VEC_index (ainsn_t, last_insns, i)->next_same_reservs_insn
5265 = curr_ainsn;
5266 VEC_replace (ainsn_t, last_insns, i, curr_ainsn);
5268 else
5270 VEC_safe_push (ainsn_t, heap, last_insns, curr_ainsn);
5271 curr_ainsn->first_insn_with_same_reservs = 1;
5274 VEC_free (ainsn_t,heap, last_insns);
5277 /* Forming unit reservations which can affect creating the automaton
5278 states achieved from a given state. It permits to build smaller
5279 automata in many cases. We would have the same automata after
5280 the minimization without such optimization, but the automaton
5281 right after the building could be huge. So in other words, usage
5282 of reservs_matter means some minimization during building the
5283 automaton. */
5284 static reserv_sets_t
5285 form_reservs_matter (automaton_t automaton)
5287 int cycle, unit;
5288 reserv_sets_t reservs_matter = alloc_empty_reserv_sets();
5290 for (cycle = 0; cycle < max_cycles_num; cycle++)
5291 for (unit = 0; unit < description->units_num; unit++)
5292 if (units_array [unit]->automaton_decl
5293 == automaton->corresponding_automaton_decl
5294 && (cycle >= units_array [unit]->min_occ_cycle_num
5295 /* We can not remove queried unit from reservations. */
5296 || units_array [unit]->query_p
5297 /* We can not remove units which are used
5298 `exclusion_set', `presence_set',
5299 `final_presence_set', `absence_set', and
5300 `final_absence_set'. */
5301 || units_array [unit]->in_set_p))
5302 set_unit_reserv (reservs_matter, cycle, unit);
5303 return reservs_matter;
5306 /* The following function creates all states of nondeterministic AUTOMATON. */
5307 static void
5308 make_automaton (automaton_t automaton)
5310 ainsn_t ainsn;
5311 struct insn_reserv_decl *insn_reserv_decl;
5312 alt_state_t alt_state;
5313 state_t state;
5314 state_t start_state;
5315 state_t state2;
5316 ainsn_t advance_cycle_ainsn;
5317 arc_t added_arc;
5318 VEC(state_t,heap) *state_stack = VEC_alloc(state_t,heap, 150);
5319 int states_n;
5320 reserv_sets_t reservs_matter = form_reservs_matter (automaton);
5322 /* Create the start state (empty state). */
5323 start_state = insert_state (get_free_state (1, automaton));
5324 automaton->start_state = start_state;
5325 start_state->it_was_placed_in_stack_for_NDFA_forming = 1;
5326 VEC_safe_push (state_t,heap, state_stack, start_state);
5327 states_n = 1;
5328 while (VEC_length (state_t, state_stack) != 0)
5330 state = VEC_pop (state_t, state_stack);
5331 advance_cycle_ainsn = NULL;
5332 for (ainsn = automaton->ainsn_list;
5333 ainsn != NULL;
5334 ainsn = ainsn->next_ainsn)
5335 if (ainsn->first_insn_with_same_reservs)
5337 insn_reserv_decl = ainsn->insn_reserv_decl;
5338 if (insn_reserv_decl != DECL_INSN_RESERV (advance_cycle_insn_decl))
5340 /* We process alt_states in the same order as they are
5341 present in the description. */
5342 added_arc = NULL;
5343 for (alt_state = ainsn->alt_states;
5344 alt_state != NULL;
5345 alt_state = alt_state->next_alt_state)
5347 state2 = alt_state->state;
5348 if (!intersected_state_reservs_p (state, state2))
5350 state2 = states_union (state, state2, reservs_matter);
5351 if (!state2->it_was_placed_in_stack_for_NDFA_forming)
5353 state2->it_was_placed_in_stack_for_NDFA_forming
5354 = 1;
5355 VEC_safe_push (state_t,heap, state_stack, state2);
5356 states_n++;
5357 if (progress_flag && states_n % 100 == 0)
5358 fprintf (stderr, ".");
5360 added_arc = add_arc (state, state2, ainsn);
5361 if (!ndfa_flag)
5362 break;
5365 if (!ndfa_flag && added_arc != NULL)
5367 for (alt_state = ainsn->alt_states;
5368 alt_state != NULL;
5369 alt_state = alt_state->next_alt_state)
5370 state2 = alt_state->state;
5373 else
5374 advance_cycle_ainsn = ainsn;
5376 /* Add transition to advance cycle. */
5377 state2 = state_shift (state, reservs_matter);
5378 if (!state2->it_was_placed_in_stack_for_NDFA_forming)
5380 state2->it_was_placed_in_stack_for_NDFA_forming = 1;
5381 VEC_safe_push (state_t,heap, state_stack, state2);
5382 states_n++;
5383 if (progress_flag && states_n % 100 == 0)
5384 fprintf (stderr, ".");
5386 gcc_assert (advance_cycle_ainsn);
5387 add_arc (state, state2, advance_cycle_ainsn);
5389 VEC_free (state_t,heap, state_stack);
5392 /* Foms lists of all arcs of STATE marked by the same ainsn. */
5393 static void
5394 form_arcs_marked_by_insn (state_t state)
5396 decl_t decl;
5397 arc_t arc;
5398 int i;
5400 for (i = 0; i < description->decls_num; i++)
5402 decl = description->decls [i];
5403 if (decl->mode == dm_insn_reserv)
5404 DECL_INSN_RESERV (decl)->arcs_marked_by_insn = NULL;
5406 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5408 gcc_assert (arc->insn);
5409 arc->next_arc_marked_by_insn
5410 = arc->insn->insn_reserv_decl->arcs_marked_by_insn;
5411 arc->insn->insn_reserv_decl->arcs_marked_by_insn = arc;
5415 /* The function creates composed state (see comments for IR) from
5416 ORIGINAL_STATE and list of arcs ARCS_MARKED_BY_INSN marked by the
5417 same insn. If the composed state is not in STATE_STACK yet, it is
5418 pushed into STATE_STACK. */
5420 static int
5421 create_composed_state (state_t original_state, arc_t arcs_marked_by_insn,
5422 VEC(state_t,heap) **state_stack)
5424 state_t state;
5425 alt_state_t alt_state, curr_alt_state;
5426 alt_state_t new_alt_state;
5427 arc_t curr_arc;
5428 arc_t next_arc;
5429 state_t state_in_table;
5430 state_t temp_state;
5431 alt_state_t canonical_alt_states_list;
5432 int alts_number;
5433 int new_state_p = 0;
5435 if (arcs_marked_by_insn == NULL)
5436 return new_state_p;
5437 if (arcs_marked_by_insn->next_arc_marked_by_insn == NULL)
5438 state = arcs_marked_by_insn->to_state;
5439 else
5441 gcc_assert (ndfa_flag);
5442 /* Create composed state. */
5443 state = get_free_state (0, arcs_marked_by_insn->to_state->automaton);
5444 curr_alt_state = NULL;
5445 for (curr_arc = arcs_marked_by_insn;
5446 curr_arc != NULL;
5447 curr_arc = curr_arc->next_arc_marked_by_insn)
5448 if (curr_arc->to_state->component_states == NULL)
5450 new_alt_state = get_free_alt_state ();
5451 new_alt_state->next_alt_state = curr_alt_state;
5452 new_alt_state->state = curr_arc->to_state;
5453 curr_alt_state = new_alt_state;
5455 else
5456 for (alt_state = curr_arc->to_state->component_states;
5457 alt_state != NULL;
5458 alt_state = alt_state->next_sorted_alt_state)
5460 new_alt_state = get_free_alt_state ();
5461 new_alt_state->next_alt_state = curr_alt_state;
5462 new_alt_state->state = alt_state->state;
5463 gcc_assert (!alt_state->state->component_states);
5464 curr_alt_state = new_alt_state;
5466 /* There are not identical sets in the alt state list. */
5467 canonical_alt_states_list = uniq_sort_alt_states (curr_alt_state);
5468 if (canonical_alt_states_list->next_sorted_alt_state == NULL)
5470 temp_state = state;
5471 state = canonical_alt_states_list->state;
5472 free_state (temp_state);
5474 else
5476 state->component_states = canonical_alt_states_list;
5477 state_in_table = insert_state (state);
5478 if (state_in_table != state)
5480 gcc_assert
5481 (state_in_table->it_was_placed_in_stack_for_DFA_forming);
5482 free_state (state);
5483 state = state_in_table;
5485 else
5487 gcc_assert (!state->it_was_placed_in_stack_for_DFA_forming);
5488 new_state_p = 1;
5489 for (curr_alt_state = state->component_states;
5490 curr_alt_state != NULL;
5491 curr_alt_state = curr_alt_state->next_sorted_alt_state)
5492 for (curr_arc = first_out_arc (curr_alt_state->state);
5493 curr_arc != NULL;
5494 curr_arc = next_out_arc (curr_arc))
5495 add_arc (state, curr_arc->to_state, curr_arc->insn);
5497 arcs_marked_by_insn->to_state = state;
5498 for (alts_number = 0,
5499 curr_arc = arcs_marked_by_insn->next_arc_marked_by_insn;
5500 curr_arc != NULL;
5501 curr_arc = next_arc)
5503 next_arc = curr_arc->next_arc_marked_by_insn;
5504 remove_arc (original_state, curr_arc);
5505 alts_number++;
5509 if (!state->it_was_placed_in_stack_for_DFA_forming)
5511 state->it_was_placed_in_stack_for_DFA_forming = 1;
5512 VEC_safe_push (state_t,heap, *state_stack, state);
5514 return new_state_p;
5517 /* The function transforms nondeterministic AUTOMATON into
5518 deterministic. */
5520 static void
5521 NDFA_to_DFA (automaton_t automaton)
5523 state_t start_state;
5524 state_t state;
5525 decl_t decl;
5526 VEC(state_t,heap) *state_stack;
5527 int i;
5528 int states_n;
5530 state_stack = VEC_alloc (state_t,heap, 0);
5532 /* Create the start state (empty state). */
5533 start_state = automaton->start_state;
5534 start_state->it_was_placed_in_stack_for_DFA_forming = 1;
5535 VEC_safe_push (state_t,heap, state_stack, start_state);
5536 states_n = 1;
5537 while (VEC_length (state_t, state_stack) != 0)
5539 state = VEC_pop (state_t, state_stack);
5540 form_arcs_marked_by_insn (state);
5541 for (i = 0; i < description->decls_num; i++)
5543 decl = description->decls [i];
5544 if (decl->mode == dm_insn_reserv
5545 && create_composed_state
5546 (state, DECL_INSN_RESERV (decl)->arcs_marked_by_insn,
5547 &state_stack))
5549 states_n++;
5550 if (progress_flag && states_n % 100 == 0)
5551 fprintf (stderr, ".");
5555 VEC_free (state_t,heap, state_stack);
5558 /* The following variable value is current number (1, 2, ...) of passing
5559 graph of states. */
5560 static int curr_state_graph_pass_num;
5562 /* This recursive function passes all states achieved from START_STATE
5563 and applies APPLIED_FUNC to them. */
5564 static void
5565 pass_state_graph (state_t start_state, void (*applied_func) (state_t state))
5567 arc_t arc;
5569 if (start_state->pass_num == curr_state_graph_pass_num)
5570 return;
5571 start_state->pass_num = curr_state_graph_pass_num;
5572 (*applied_func) (start_state);
5573 for (arc = first_out_arc (start_state);
5574 arc != NULL;
5575 arc = next_out_arc (arc))
5576 pass_state_graph (arc->to_state, applied_func);
5579 /* This recursive function passes all states of AUTOMATON and applies
5580 APPLIED_FUNC to them. */
5581 static void
5582 pass_states (automaton_t automaton, void (*applied_func) (state_t state))
5584 curr_state_graph_pass_num++;
5585 pass_state_graph (automaton->start_state, applied_func);
5588 /* The function initializes code for passing of all states. */
5589 static void
5590 initiate_pass_states (void)
5592 curr_state_graph_pass_num = 0;
5595 /* The following vla is used for storing pointers to all achieved
5596 states. */
5597 static VEC(state_t,heap) *all_achieved_states;
5599 /* This function is called by function pass_states to add an achieved
5600 STATE. */
5601 static void
5602 add_achieved_state (state_t state)
5604 VEC_safe_push (state_t,heap, all_achieved_states, state);
5607 /* The function sets up equivalence numbers of insns which mark all
5608 out arcs of STATE by equiv_class_num_1 (if ODD_ITERATION_FLAG has
5609 nonzero value) or by equiv_class_num_2 of the destination state.
5610 The function returns number of out arcs of STATE. */
5611 static void
5612 set_out_arc_insns_equiv_num (state_t state, int odd_iteration_flag)
5614 arc_t arc;
5616 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5618 gcc_assert (!arc->insn->insn_reserv_decl->equiv_class_num);
5619 arc->insn->insn_reserv_decl->equiv_class_num
5620 = (odd_iteration_flag
5621 ? arc->to_state->equiv_class_num_1
5622 : arc->to_state->equiv_class_num_2);
5623 gcc_assert (arc->insn->insn_reserv_decl->equiv_class_num);
5627 /* The function clears equivalence numbers and alt_states in all insns
5628 which mark all out arcs of STATE. */
5629 static void
5630 clear_arc_insns_equiv_num (state_t state)
5632 arc_t arc;
5634 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5635 arc->insn->insn_reserv_decl->equiv_class_num = 0;
5639 /* The following function returns TRUE if STATE reserves the unit with
5640 UNIT_NUM on the first cycle. */
5641 static int
5642 first_cycle_unit_presence (state_t state, int unit_num)
5644 alt_state_t alt_state;
5646 if (state->component_states == NULL)
5647 return test_unit_reserv (state->reservs, 0, unit_num);
5648 else
5650 for (alt_state = state->component_states;
5651 alt_state != NULL;
5652 alt_state = alt_state->next_sorted_alt_state)
5653 if (test_unit_reserv (alt_state->state->reservs, 0, unit_num))
5654 return true;
5656 return false;
5659 /* This fills in the presence_signature[] member of STATE. */
5660 static void
5661 cache_presence (state_t state)
5663 int i, num = 0;
5664 unsigned int sz;
5665 sz = (description->query_units_num + sizeof (int) * CHAR_BIT - 1)
5666 / (sizeof (int) * CHAR_BIT);
5668 state->presence_signature = create_node (sz * sizeof (int));
5669 for (i = 0; i < description->units_num; i++)
5670 if (units_array [i]->query_p)
5672 int presence1_p = first_cycle_unit_presence (state, i);
5673 state->presence_signature[num / (sizeof (int) * CHAR_BIT)]
5674 |= (!!presence1_p) << (num % (sizeof (int) * CHAR_BIT));
5675 num++;
5679 /* The function returns nonzero value if STATE is not equivalent to
5680 ANOTHER_STATE from the same current partition on equivalence
5681 classes. Another state has ANOTHER_STATE_OUT_ARCS_NUM number of
5682 output arcs. Iteration of making equivalence partition is defined
5683 by ODD_ITERATION_FLAG. */
5684 static int
5685 state_is_differed (state_t state, state_t another_state,
5686 int odd_iteration_flag)
5688 arc_t arc;
5689 unsigned int sz, si;
5691 gcc_assert (state->num_out_arcs == another_state->num_out_arcs);
5693 sz = (description->query_units_num + sizeof (int) * CHAR_BIT - 1)
5694 / (sizeof (int) * CHAR_BIT);
5696 for (si = 0; si < sz; si++)
5697 gcc_assert (state->presence_signature[si]
5698 == another_state->presence_signature[si]);
5700 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5702 if ((odd_iteration_flag
5703 ? arc->to_state->equiv_class_num_1
5704 : arc->to_state->equiv_class_num_2)
5705 != arc->insn->insn_reserv_decl->equiv_class_num)
5706 return 1;
5709 return 0;
5712 /* Compares two states pointed to by STATE_PTR_1 and STATE_PTR_2
5713 and return -1, 0 or 1. This function can be used as predicate for
5714 qsort(). It requires the member presence_signature[] of both
5715 states be filled. */
5716 static int
5717 compare_states_for_equiv (const void *state_ptr_1,
5718 const void *state_ptr_2)
5720 state_t s1 = *(state_t *)state_ptr_1;
5721 state_t s2 = *(state_t *)state_ptr_2;
5722 unsigned int sz, si;
5723 if (s1->num_out_arcs < s2->num_out_arcs)
5724 return -1;
5725 else if (s1->num_out_arcs > s2->num_out_arcs)
5726 return 1;
5728 sz = (description->query_units_num + sizeof (int) * CHAR_BIT - 1)
5729 / (sizeof (int) * CHAR_BIT);
5731 for (si = 0; si < sz; si++)
5732 if (s1->presence_signature[si] < s2->presence_signature[si])
5733 return -1;
5734 else if (s1->presence_signature[si] > s2->presence_signature[si])
5735 return 1;
5736 return 0;
5739 /* The function makes initial partition of STATES on equivalent
5740 classes and saves it into *CLASSES. This function requires the input
5741 to be sorted via compare_states_for_equiv(). */
5742 static int
5743 init_equiv_class (VEC(state_t,heap) *states, VEC (state_t,heap) **classes)
5745 size_t i;
5746 state_t prev = 0;
5747 int class_num = 1;
5749 *classes = VEC_alloc (state_t,heap, 150);
5750 for (i = 0; i < VEC_length (state_t, states); i++)
5752 state_t state = VEC_index (state_t, states, i);
5753 if (prev)
5755 if (compare_states_for_equiv (&prev, &state) != 0)
5757 VEC_safe_push (state_t,heap, *classes, prev);
5758 class_num++;
5759 prev = NULL;
5762 state->equiv_class_num_1 = class_num;
5763 state->next_equiv_class_state = prev;
5764 prev = state;
5766 if (prev)
5767 VEC_safe_push (state_t,heap, *classes, prev);
5768 return class_num;
5771 /* The function copies pointers to equivalent states from vla FROM
5772 into vla TO. */
5773 static void
5774 copy_equiv_class (VEC(state_t,heap) **to, VEC(state_t,heap) *from)
5776 VEC_free (state_t,heap, *to);
5777 *to = VEC_copy (state_t,heap, from);
5780 /* The function processes equivalence class given by its first state,
5781 FIRST_STATE, on odd iteration if ODD_ITERATION_FLAG. If there
5782 are not equivalent states, the function partitions the class
5783 removing nonequivalent states and placing them in
5784 *NEXT_ITERATION_CLASSES, increments *NEW_EQUIV_CLASS_NUM_PTR ans
5785 assigns it to the state equivalence number. If the class has been
5786 partitioned, the function returns nonzero value. */
5787 static int
5788 partition_equiv_class (state_t first_state, int odd_iteration_flag,
5789 VEC(state_t,heap) **next_iteration_classes,
5790 int *new_equiv_class_num_ptr)
5792 state_t new_equiv_class;
5793 int partition_p;
5794 state_t curr_state;
5795 state_t prev_state;
5796 state_t next_state;
5798 partition_p = 0;
5800 while (first_state != NULL)
5802 new_equiv_class = NULL;
5803 if (first_state->next_equiv_class_state != NULL)
5805 /* There are more one states in the class equivalence. */
5806 set_out_arc_insns_equiv_num (first_state, odd_iteration_flag);
5807 for (prev_state = first_state,
5808 curr_state = first_state->next_equiv_class_state;
5809 curr_state != NULL;
5810 curr_state = next_state)
5812 next_state = curr_state->next_equiv_class_state;
5813 if (state_is_differed (curr_state, first_state,
5814 odd_iteration_flag))
5816 /* Remove curr state from the class equivalence. */
5817 prev_state->next_equiv_class_state = next_state;
5818 /* Add curr state to the new class equivalence. */
5819 curr_state->next_equiv_class_state = new_equiv_class;
5820 if (new_equiv_class == NULL)
5821 (*new_equiv_class_num_ptr)++;
5822 if (odd_iteration_flag)
5823 curr_state->equiv_class_num_2 = *new_equiv_class_num_ptr;
5824 else
5825 curr_state->equiv_class_num_1 = *new_equiv_class_num_ptr;
5826 new_equiv_class = curr_state;
5827 partition_p = 1;
5829 else
5830 prev_state = curr_state;
5832 clear_arc_insns_equiv_num (first_state);
5834 if (new_equiv_class != NULL)
5835 VEC_safe_push (state_t,heap, *next_iteration_classes, new_equiv_class);
5836 first_state = new_equiv_class;
5838 return partition_p;
5841 /* The function finds equivalent states of AUTOMATON. */
5842 static void
5843 evaluate_equiv_classes (automaton_t automaton,
5844 VEC(state_t,heap) **equiv_classes)
5846 int new_equiv_class_num;
5847 int odd_iteration_flag;
5848 int finish_flag;
5849 VEC (state_t,heap) *next_iteration_classes;
5850 size_t i;
5852 all_achieved_states = VEC_alloc (state_t,heap, 1500);
5853 pass_states (automaton, add_achieved_state);
5854 pass_states (automaton, cache_presence);
5855 qsort (VEC_address (state_t, all_achieved_states),
5856 VEC_length (state_t, all_achieved_states),
5857 sizeof (state_t), compare_states_for_equiv);
5859 odd_iteration_flag = 0;
5860 new_equiv_class_num = init_equiv_class (all_achieved_states,
5861 &next_iteration_classes);
5865 odd_iteration_flag = !odd_iteration_flag;
5866 finish_flag = 1;
5867 copy_equiv_class (equiv_classes, next_iteration_classes);
5869 /* Transfer equiv numbers for the next iteration. */
5870 for (i = 0; i < VEC_length (state_t, all_achieved_states); i++)
5871 if (odd_iteration_flag)
5872 VEC_index (state_t, all_achieved_states, i)->equiv_class_num_2
5873 = VEC_index (state_t, all_achieved_states, i)->equiv_class_num_1;
5874 else
5875 VEC_index (state_t, all_achieved_states, i)->equiv_class_num_1
5876 = VEC_index (state_t, all_achieved_states, i)->equiv_class_num_2;
5878 for (i = 0; i < VEC_length (state_t, *equiv_classes); i++)
5879 if (partition_equiv_class (VEC_index (state_t, *equiv_classes, i),
5880 odd_iteration_flag,
5881 &next_iteration_classes,
5882 &new_equiv_class_num))
5883 finish_flag = 0;
5885 while (!finish_flag);
5886 VEC_free (state_t,heap, next_iteration_classes);
5887 VEC_free (state_t,heap, all_achieved_states);
5890 /* The function merges equivalent states of AUTOMATON. */
5891 static void
5892 merge_states (automaton_t automaton, VEC(state_t,heap) *equiv_classes)
5894 state_t curr_state;
5895 state_t new_state;
5896 state_t first_class_state;
5897 alt_state_t alt_states;
5898 alt_state_t alt_state, new_alt_state;
5899 arc_t curr_arc;
5900 arc_t next_arc;
5901 size_t i;
5903 /* Create states corresponding to equivalence classes containing two
5904 or more states. */
5905 for (i = 0; i < VEC_length (state_t, equiv_classes); i++)
5907 curr_state = VEC_index (state_t, equiv_classes, i);
5908 if (curr_state->next_equiv_class_state != NULL)
5910 /* There are more one states in the class equivalence. */
5911 /* Create new compound state. */
5912 new_state = get_free_state (0, automaton);
5913 alt_states = NULL;
5914 first_class_state = curr_state;
5915 for (curr_state = first_class_state;
5916 curr_state != NULL;
5917 curr_state = curr_state->next_equiv_class_state)
5919 curr_state->equiv_class_state = new_state;
5920 if (curr_state->component_states == NULL)
5922 new_alt_state = get_free_alt_state ();
5923 new_alt_state->state = curr_state;
5924 new_alt_state->next_alt_state = alt_states;
5925 alt_states = new_alt_state;
5927 else
5928 for (alt_state = curr_state->component_states;
5929 alt_state != NULL;
5930 alt_state = alt_state->next_sorted_alt_state)
5932 new_alt_state = get_free_alt_state ();
5933 new_alt_state->state = alt_state->state;
5934 new_alt_state->next_alt_state = alt_states;
5935 alt_states = new_alt_state;
5938 /* Its is important that alt states were sorted before and
5939 after merging to have the same querying results. */
5940 new_state->component_states = uniq_sort_alt_states (alt_states);
5942 else
5943 curr_state->equiv_class_state = curr_state;
5946 for (i = 0; i < VEC_length (state_t, equiv_classes); i++)
5948 curr_state = VEC_index (state_t, equiv_classes, i);
5949 if (curr_state->next_equiv_class_state != NULL)
5951 first_class_state = curr_state;
5952 /* Create new arcs output from the state corresponding to
5953 equiv class. */
5954 for (curr_arc = first_out_arc (first_class_state);
5955 curr_arc != NULL;
5956 curr_arc = next_out_arc (curr_arc))
5957 add_arc (first_class_state->equiv_class_state,
5958 curr_arc->to_state->equiv_class_state,
5959 curr_arc->insn);
5960 /* Delete output arcs from states of given class equivalence. */
5961 for (curr_state = first_class_state;
5962 curr_state != NULL;
5963 curr_state = curr_state->next_equiv_class_state)
5965 if (automaton->start_state == curr_state)
5966 automaton->start_state = curr_state->equiv_class_state;
5967 /* Delete the state and its output arcs. */
5968 for (curr_arc = first_out_arc (curr_state);
5969 curr_arc != NULL;
5970 curr_arc = next_arc)
5972 next_arc = next_out_arc (curr_arc);
5973 free_arc (curr_arc);
5977 else
5979 /* Change `to_state' of arcs output from the state of given
5980 equivalence class. */
5981 for (curr_arc = first_out_arc (curr_state);
5982 curr_arc != NULL;
5983 curr_arc = next_out_arc (curr_arc))
5984 curr_arc->to_state = curr_arc->to_state->equiv_class_state;
5989 /* The function sets up new_cycle_p for states if there is arc to the
5990 state marked by advance_cycle_insn_decl. */
5991 static void
5992 set_new_cycle_flags (state_t state)
5994 arc_t arc;
5996 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5997 if (arc->insn->insn_reserv_decl
5998 == DECL_INSN_RESERV (advance_cycle_insn_decl))
5999 arc->to_state->new_cycle_p = 1;
6002 /* The top level function for minimization of deterministic
6003 AUTOMATON. */
6004 static void
6005 minimize_DFA (automaton_t automaton)
6007 VEC(state_t,heap) *equiv_classes = 0;
6009 evaluate_equiv_classes (automaton, &equiv_classes);
6010 merge_states (automaton, equiv_classes);
6011 pass_states (automaton, set_new_cycle_flags);
6013 VEC_free (state_t,heap, equiv_classes);
6016 /* Values of two variables are counted number of states and arcs in an
6017 automaton. */
6018 static int curr_counted_states_num;
6019 static int curr_counted_arcs_num;
6021 /* The function is called by function `pass_states' to count states
6022 and arcs of an automaton. */
6023 static void
6024 incr_states_and_arcs_nums (state_t state)
6026 arc_t arc;
6028 curr_counted_states_num++;
6029 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6030 curr_counted_arcs_num++;
6033 /* The function counts states and arcs of AUTOMATON. */
6034 static void
6035 count_states_and_arcs (automaton_t automaton, int *states_num,
6036 int *arcs_num)
6038 curr_counted_states_num = 0;
6039 curr_counted_arcs_num = 0;
6040 pass_states (automaton, incr_states_and_arcs_nums);
6041 *states_num = curr_counted_states_num;
6042 *arcs_num = curr_counted_arcs_num;
6045 /* The function builds one DFA AUTOMATON for fast pipeline hazards
6046 recognition after checking and simplifying IR of the
6047 description. */
6048 static void
6049 build_automaton (automaton_t automaton)
6051 int states_num;
6052 int arcs_num;
6054 ticker_on (&NDFA_time);
6055 if (progress_flag)
6057 if (automaton->corresponding_automaton_decl == NULL)
6058 fprintf (stderr, "Create anonymous automaton");
6059 else
6060 fprintf (stderr, "Create automaton `%s'",
6061 automaton->corresponding_automaton_decl->name);
6062 fprintf (stderr, " (1 dot is 100 new states):");
6064 make_automaton (automaton);
6065 if (progress_flag)
6066 fprintf (stderr, " done\n");
6067 ticker_off (&NDFA_time);
6068 count_states_and_arcs (automaton, &states_num, &arcs_num);
6069 automaton->NDFA_states_num = states_num;
6070 automaton->NDFA_arcs_num = arcs_num;
6071 ticker_on (&NDFA_to_DFA_time);
6072 if (progress_flag)
6074 if (automaton->corresponding_automaton_decl == NULL)
6075 fprintf (stderr, "Make anonymous DFA");
6076 else
6077 fprintf (stderr, "Make DFA `%s'",
6078 automaton->corresponding_automaton_decl->name);
6079 fprintf (stderr, " (1 dot is 100 new states):");
6081 NDFA_to_DFA (automaton);
6082 if (progress_flag)
6083 fprintf (stderr, " done\n");
6084 ticker_off (&NDFA_to_DFA_time);
6085 count_states_and_arcs (automaton, &states_num, &arcs_num);
6086 automaton->DFA_states_num = states_num;
6087 automaton->DFA_arcs_num = arcs_num;
6088 if (!no_minimization_flag)
6090 ticker_on (&minimize_time);
6091 if (progress_flag)
6093 if (automaton->corresponding_automaton_decl == NULL)
6094 fprintf (stderr, "Minimize anonymous DFA...");
6095 else
6096 fprintf (stderr, "Minimize DFA `%s'...",
6097 automaton->corresponding_automaton_decl->name);
6099 minimize_DFA (automaton);
6100 if (progress_flag)
6101 fprintf (stderr, "done\n");
6102 ticker_off (&minimize_time);
6103 count_states_and_arcs (automaton, &states_num, &arcs_num);
6104 automaton->minimal_DFA_states_num = states_num;
6105 automaton->minimal_DFA_arcs_num = arcs_num;
6111 /* The page contains code for enumeration of all states of an automaton. */
6113 /* Variable used for enumeration of all states of an automaton. Its
6114 value is current number of automaton states. */
6115 static int curr_state_order_num;
6117 /* The function is called by function `pass_states' for enumerating
6118 states. */
6119 static void
6120 set_order_state_num (state_t state)
6122 state->order_state_num = curr_state_order_num;
6123 curr_state_order_num++;
6126 /* The function enumerates all states of AUTOMATON. */
6127 static void
6128 enumerate_states (automaton_t automaton)
6130 curr_state_order_num = 0;
6131 pass_states (automaton, set_order_state_num);
6132 automaton->achieved_states_num = curr_state_order_num;
6137 /* The page contains code for finding equivalent automaton insns
6138 (ainsns). */
6140 /* The function inserts AINSN into cyclic list
6141 CYCLIC_EQUIV_CLASS_INSN_LIST of ainsns. */
6142 static ainsn_t
6143 insert_ainsn_into_equiv_class (ainsn_t ainsn,
6144 ainsn_t cyclic_equiv_class_insn_list)
6146 if (cyclic_equiv_class_insn_list == NULL)
6147 ainsn->next_equiv_class_insn = ainsn;
6148 else
6150 ainsn->next_equiv_class_insn
6151 = cyclic_equiv_class_insn_list->next_equiv_class_insn;
6152 cyclic_equiv_class_insn_list->next_equiv_class_insn = ainsn;
6154 return ainsn;
6157 /* The function deletes equiv_class_insn into cyclic list of
6158 equivalent ainsns. */
6159 static void
6160 delete_ainsn_from_equiv_class (ainsn_t equiv_class_insn)
6162 ainsn_t curr_equiv_class_insn;
6163 ainsn_t prev_equiv_class_insn;
6165 prev_equiv_class_insn = equiv_class_insn;
6166 for (curr_equiv_class_insn = equiv_class_insn->next_equiv_class_insn;
6167 curr_equiv_class_insn != equiv_class_insn;
6168 curr_equiv_class_insn = curr_equiv_class_insn->next_equiv_class_insn)
6169 prev_equiv_class_insn = curr_equiv_class_insn;
6170 if (prev_equiv_class_insn != equiv_class_insn)
6171 prev_equiv_class_insn->next_equiv_class_insn
6172 = equiv_class_insn->next_equiv_class_insn;
6175 /* The function processes AINSN of a state in order to find equivalent
6176 ainsns. INSN_ARCS_ARRAY is table: code of insn -> out arc of the
6177 state. */
6178 static void
6179 process_insn_equiv_class (ainsn_t ainsn, arc_t *insn_arcs_array)
6181 ainsn_t next_insn;
6182 ainsn_t curr_insn;
6183 ainsn_t cyclic_insn_list;
6184 arc_t arc;
6186 gcc_assert (insn_arcs_array [ainsn->insn_reserv_decl->insn_num]);
6187 curr_insn = ainsn;
6188 /* New class of ainsns which are not equivalent to given ainsn. */
6189 cyclic_insn_list = NULL;
6192 next_insn = curr_insn->next_equiv_class_insn;
6193 arc = insn_arcs_array [curr_insn->insn_reserv_decl->insn_num];
6194 if (arc == NULL
6195 || (insn_arcs_array [ainsn->insn_reserv_decl->insn_num]->to_state
6196 != arc->to_state))
6198 delete_ainsn_from_equiv_class (curr_insn);
6199 cyclic_insn_list = insert_ainsn_into_equiv_class (curr_insn,
6200 cyclic_insn_list);
6202 curr_insn = next_insn;
6204 while (curr_insn != ainsn);
6207 /* The function processes STATE in order to find equivalent ainsns. */
6208 static void
6209 process_state_for_insn_equiv_partition (state_t state)
6211 arc_t arc;
6212 arc_t *insn_arcs_array = XCNEWVEC (arc_t, description->insns_num);
6214 /* Process insns of the arcs. */
6215 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6216 insn_arcs_array [arc->insn->insn_reserv_decl->insn_num] = arc;
6217 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6218 process_insn_equiv_class (arc->insn, insn_arcs_array);
6220 free (insn_arcs_array);
6223 /* The function searches for equivalent ainsns of AUTOMATON. */
6224 static void
6225 set_insn_equiv_classes (automaton_t automaton)
6227 ainsn_t ainsn;
6228 ainsn_t first_insn;
6229 ainsn_t curr_insn;
6230 ainsn_t cyclic_insn_list;
6231 ainsn_t insn_with_same_reservs;
6232 int equiv_classes_num;
6234 /* All insns are included in one equivalence class. */
6235 cyclic_insn_list = NULL;
6236 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6237 if (ainsn->first_insn_with_same_reservs)
6238 cyclic_insn_list = insert_ainsn_into_equiv_class (ainsn,
6239 cyclic_insn_list);
6240 /* Process insns in order to make equivalence partition. */
6241 pass_states (automaton, process_state_for_insn_equiv_partition);
6242 /* Enumerate equiv classes. */
6243 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6244 /* Set undefined value. */
6245 ainsn->insn_equiv_class_num = -1;
6246 equiv_classes_num = 0;
6247 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6248 if (ainsn->insn_equiv_class_num < 0)
6250 first_insn = ainsn;
6251 gcc_assert (first_insn->first_insn_with_same_reservs);
6252 first_insn->first_ainsn_with_given_equivalence_num = 1;
6253 curr_insn = first_insn;
6256 for (insn_with_same_reservs = curr_insn;
6257 insn_with_same_reservs != NULL;
6258 insn_with_same_reservs
6259 = insn_with_same_reservs->next_same_reservs_insn)
6260 insn_with_same_reservs->insn_equiv_class_num = equiv_classes_num;
6261 curr_insn = curr_insn->next_equiv_class_insn;
6263 while (curr_insn != first_insn);
6264 equiv_classes_num++;
6266 automaton->insn_equiv_classes_num = equiv_classes_num;
6271 /* This page contains code for creating DFA(s) and calls functions
6272 building them. */
6275 /* The following value is used to prevent floating point overflow for
6276 estimating an automaton bound. The value should be less DBL_MAX on
6277 the host machine. We use here approximate minimum of maximal
6278 double floating point value required by ANSI C standard. It
6279 will work for non ANSI sun compiler too. */
6281 #define MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND 1.0E37
6283 /* The function estimate size of the single DFA used by PHR (pipeline
6284 hazards recognizer). */
6285 static double
6286 estimate_one_automaton_bound (void)
6288 decl_t decl;
6289 double one_automaton_estimation_bound;
6290 double root_value;
6291 int i;
6293 one_automaton_estimation_bound = 1.0;
6294 for (i = 0; i < description->decls_num; i++)
6296 decl = description->decls [i];
6297 if (decl->mode == dm_unit)
6299 root_value = exp (log (DECL_UNIT (decl)->max_occ_cycle_num
6300 - DECL_UNIT (decl)->min_occ_cycle_num + 1.0)
6301 / automata_num);
6302 if (MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND / root_value
6303 > one_automaton_estimation_bound)
6304 one_automaton_estimation_bound *= root_value;
6307 return one_automaton_estimation_bound;
6310 /* The function compares unit declarations according to their maximal
6311 cycle in reservations. */
6312 static int
6313 compare_max_occ_cycle_nums (const void *unit_decl_1,
6314 const void *unit_decl_2)
6316 if ((DECL_UNIT (*(decl_t *) unit_decl_1)->max_occ_cycle_num)
6317 < (DECL_UNIT (*(decl_t *) unit_decl_2)->max_occ_cycle_num))
6318 return 1;
6319 else if ((DECL_UNIT (*(decl_t *) unit_decl_1)->max_occ_cycle_num)
6320 == (DECL_UNIT (*(decl_t *) unit_decl_2)->max_occ_cycle_num))
6321 return 0;
6322 else
6323 return -1;
6326 /* The function makes heuristic assigning automata to units. Actually
6327 efficacy of the algorithm has been checked yet??? */
6329 static void
6330 units_to_automata_heuristic_distr (void)
6332 double estimation_bound;
6333 int automaton_num;
6334 int rest_units_num;
6335 double bound_value;
6336 unit_decl_t *unit_decls;
6337 int i, j;
6339 if (description->units_num == 0)
6340 return;
6341 estimation_bound = estimate_one_automaton_bound ();
6342 unit_decls = XNEWVEC (unit_decl_t, description->units_num);
6344 for (i = 0, j = 0; i < description->decls_num; i++)
6345 if (description->decls[i]->mode == dm_unit)
6346 unit_decls[j++] = DECL_UNIT (description->decls[i]);
6347 gcc_assert (j == description->units_num);
6349 qsort (unit_decls, description->units_num,
6350 sizeof (unit_decl_t), compare_max_occ_cycle_nums);
6352 automaton_num = 0;
6353 bound_value = unit_decls[0]->max_occ_cycle_num;
6354 unit_decls[0]->corresponding_automaton_num = automaton_num;
6356 for (i = 1; i < description->units_num; i++)
6358 rest_units_num = description->units_num - i + 1;
6359 gcc_assert (automata_num - automaton_num - 1 <= rest_units_num);
6360 if (automaton_num < automata_num - 1
6361 && ((automata_num - automaton_num - 1 == rest_units_num)
6362 || (bound_value
6363 > (estimation_bound
6364 / unit_decls[i]->max_occ_cycle_num))))
6366 bound_value = unit_decls[i]->max_occ_cycle_num;
6367 automaton_num++;
6369 else
6370 bound_value *= unit_decls[i]->max_occ_cycle_num;
6371 unit_decls[i]->corresponding_automaton_num = automaton_num;
6373 gcc_assert (automaton_num == automata_num - 1);
6374 free (unit_decls);
6377 /* The functions creates automaton insns for each automata. Automaton
6378 insn is simply insn for given automaton which makes reservation
6379 only of units of the automaton. */
6380 static ainsn_t
6381 create_ainsns (void)
6383 decl_t decl;
6384 ainsn_t first_ainsn;
6385 ainsn_t curr_ainsn;
6386 ainsn_t prev_ainsn;
6387 int i;
6389 first_ainsn = NULL;
6390 prev_ainsn = NULL;
6391 for (i = 0; i < description->decls_num; i++)
6393 decl = description->decls [i];
6394 if (decl->mode == dm_insn_reserv)
6396 curr_ainsn = create_node (sizeof (struct ainsn));
6397 curr_ainsn->insn_reserv_decl = DECL_INSN_RESERV (decl);
6398 curr_ainsn->important_p = FALSE;
6399 curr_ainsn->next_ainsn = NULL;
6400 if (prev_ainsn == NULL)
6401 first_ainsn = curr_ainsn;
6402 else
6403 prev_ainsn->next_ainsn = curr_ainsn;
6404 prev_ainsn = curr_ainsn;
6407 return first_ainsn;
6410 /* The function assigns automata to units according to constructions
6411 `define_automaton' in the description. */
6412 static void
6413 units_to_automata_distr (void)
6415 decl_t decl;
6416 int i;
6418 for (i = 0; i < description->decls_num; i++)
6420 decl = description->decls [i];
6421 if (decl->mode == dm_unit)
6423 if (DECL_UNIT (decl)->automaton_decl == NULL
6424 || (DECL_UNIT (decl)->automaton_decl->corresponding_automaton
6425 == NULL))
6426 /* Distribute to the first automaton. */
6427 DECL_UNIT (decl)->corresponding_automaton_num = 0;
6428 else
6429 DECL_UNIT (decl)->corresponding_automaton_num
6430 = (DECL_UNIT (decl)->automaton_decl
6431 ->corresponding_automaton->automaton_order_num);
6436 /* The function creates DFA(s) for fast pipeline hazards recognition
6437 after checking and simplifying IR of the description. */
6438 static void
6439 create_automata (void)
6441 automaton_t curr_automaton;
6442 automaton_t prev_automaton;
6443 decl_t decl;
6444 int curr_automaton_num;
6445 int i;
6447 if (automata_num != 0)
6449 units_to_automata_heuristic_distr ();
6450 for (prev_automaton = NULL, curr_automaton_num = 0;
6451 curr_automaton_num < automata_num;
6452 curr_automaton_num++, prev_automaton = curr_automaton)
6454 curr_automaton = create_node (sizeof (struct automaton));
6455 curr_automaton->ainsn_list = create_ainsns ();
6456 curr_automaton->corresponding_automaton_decl = NULL;
6457 curr_automaton->next_automaton = NULL;
6458 curr_automaton->automaton_order_num = curr_automaton_num;
6459 if (prev_automaton == NULL)
6460 description->first_automaton = curr_automaton;
6461 else
6462 prev_automaton->next_automaton = curr_automaton;
6465 else
6467 curr_automaton_num = 0;
6468 prev_automaton = NULL;
6469 for (i = 0; i < description->decls_num; i++)
6471 decl = description->decls [i];
6472 if (decl->mode == dm_automaton
6473 && DECL_AUTOMATON (decl)->automaton_is_used)
6475 curr_automaton = create_node (sizeof (struct automaton));
6476 curr_automaton->ainsn_list = create_ainsns ();
6477 curr_automaton->corresponding_automaton_decl
6478 = DECL_AUTOMATON (decl);
6479 curr_automaton->next_automaton = NULL;
6480 DECL_AUTOMATON (decl)->corresponding_automaton = curr_automaton;
6481 curr_automaton->automaton_order_num = curr_automaton_num;
6482 if (prev_automaton == NULL)
6483 description->first_automaton = curr_automaton;
6484 else
6485 prev_automaton->next_automaton = curr_automaton;
6486 curr_automaton_num++;
6487 prev_automaton = curr_automaton;
6490 if (curr_automaton_num == 0)
6492 curr_automaton = create_node (sizeof (struct automaton));
6493 curr_automaton->ainsn_list = create_ainsns ();
6494 curr_automaton->corresponding_automaton_decl = NULL;
6495 curr_automaton->next_automaton = NULL;
6496 description->first_automaton = curr_automaton;
6498 units_to_automata_distr ();
6500 NDFA_time = create_ticker ();
6501 ticker_off (&NDFA_time);
6502 NDFA_to_DFA_time = create_ticker ();
6503 ticker_off (&NDFA_to_DFA_time);
6504 minimize_time = create_ticker ();
6505 ticker_off (&minimize_time);
6506 equiv_time = create_ticker ();
6507 ticker_off (&equiv_time);
6508 for (curr_automaton = description->first_automaton;
6509 curr_automaton != NULL;
6510 curr_automaton = curr_automaton->next_automaton)
6512 if (progress_flag)
6514 if (curr_automaton->corresponding_automaton_decl == NULL)
6515 fprintf (stderr, "Prepare anonymous automaton creation ... ");
6516 else
6517 fprintf (stderr, "Prepare automaton `%s' creation...",
6518 curr_automaton->corresponding_automaton_decl->name);
6520 create_alt_states (curr_automaton);
6521 form_ainsn_with_same_reservs (curr_automaton);
6522 if (progress_flag)
6523 fprintf (stderr, "done\n");
6524 build_automaton (curr_automaton);
6525 enumerate_states (curr_automaton);
6526 ticker_on (&equiv_time);
6527 set_insn_equiv_classes (curr_automaton);
6528 ticker_off (&equiv_time);
6534 /* This page contains code for forming string representation of
6535 regexp. The representation is formed on IR obstack. So you should
6536 not work with IR obstack between regexp_representation and
6537 finish_regexp_representation calls. */
6539 /* This recursive function forms string representation of regexp
6540 (without tailing '\0'). */
6541 static void
6542 form_regexp (regexp_t regexp)
6544 int i;
6546 switch (regexp->mode)
6548 case rm_unit: case rm_reserv:
6550 const char *name = (regexp->mode == rm_unit
6551 ? REGEXP_UNIT (regexp)->name
6552 : REGEXP_RESERV (regexp)->name);
6554 obstack_grow (&irp, name, strlen (name));
6555 break;
6558 case rm_sequence:
6559 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
6561 if (i != 0)
6562 obstack_1grow (&irp, ',');
6563 form_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
6565 break;
6567 case rm_allof:
6568 obstack_1grow (&irp, '(');
6569 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
6571 if (i != 0)
6572 obstack_1grow (&irp, '+');
6573 if (REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_sequence
6574 || REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_oneof)
6575 obstack_1grow (&irp, '(');
6576 form_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
6577 if (REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_sequence
6578 || REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_oneof)
6579 obstack_1grow (&irp, ')');
6581 obstack_1grow (&irp, ')');
6582 break;
6584 case rm_oneof:
6585 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
6587 if (i != 0)
6588 obstack_1grow (&irp, '|');
6589 if (REGEXP_ONEOF (regexp)->regexps[i]->mode == rm_sequence)
6590 obstack_1grow (&irp, '(');
6591 form_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
6592 if (REGEXP_ONEOF (regexp)->regexps[i]->mode == rm_sequence)
6593 obstack_1grow (&irp, ')');
6595 break;
6597 case rm_repeat:
6599 char digits [30];
6601 if (REGEXP_REPEAT (regexp)->regexp->mode == rm_sequence
6602 || REGEXP_REPEAT (regexp)->regexp->mode == rm_allof
6603 || REGEXP_REPEAT (regexp)->regexp->mode == rm_oneof)
6604 obstack_1grow (&irp, '(');
6605 form_regexp (REGEXP_REPEAT (regexp)->regexp);
6606 if (REGEXP_REPEAT (regexp)->regexp->mode == rm_sequence
6607 || REGEXP_REPEAT (regexp)->regexp->mode == rm_allof
6608 || REGEXP_REPEAT (regexp)->regexp->mode == rm_oneof)
6609 obstack_1grow (&irp, ')');
6610 sprintf (digits, "*%d", REGEXP_REPEAT (regexp)->repeat_num);
6611 obstack_grow (&irp, digits, strlen (digits));
6612 break;
6615 case rm_nothing:
6616 obstack_grow (&irp, NOTHING_NAME, strlen (NOTHING_NAME));
6617 break;
6619 default:
6620 gcc_unreachable ();
6624 /* The function returns string representation of REGEXP on IR
6625 obstack. */
6626 static const char *
6627 regexp_representation (regexp_t regexp)
6629 form_regexp (regexp);
6630 obstack_1grow (&irp, '\0');
6631 return obstack_base (&irp);
6634 /* The function frees memory allocated for last formed string
6635 representation of regexp. */
6636 static void
6637 finish_regexp_representation (void)
6639 int length = obstack_object_size (&irp);
6641 obstack_blank_fast (&irp, -length);
6646 /* This page contains code for output PHR (pipeline hazards recognizer). */
6648 /* The function outputs minimal C type which is sufficient for
6649 representation numbers in range min_range_value and
6650 max_range_value. Because host machine and build machine may be
6651 different, we use here minimal values required by ANSI C standard
6652 instead of UCHAR_MAX, SHRT_MAX, SHRT_MIN, etc. This is a good
6653 approximation. */
6655 static void
6656 output_range_type (FILE *f, long int min_range_value,
6657 long int max_range_value)
6659 if (min_range_value >= 0 && max_range_value <= 255)
6660 fprintf (f, "unsigned char");
6661 else if (min_range_value >= -127 && max_range_value <= 127)
6662 fprintf (f, "signed char");
6663 else if (min_range_value >= 0 && max_range_value <= 65535)
6664 fprintf (f, "unsigned short");
6665 else if (min_range_value >= -32767 && max_range_value <= 32767)
6666 fprintf (f, "short");
6667 else
6668 fprintf (f, "int");
6671 /* The function outputs all initialization values of VECT. */
6672 static void
6673 output_vect (vla_hwint_t vect)
6675 int els_on_line;
6676 size_t vect_length = VEC_length (vect_el_t, vect);
6677 size_t i;
6679 els_on_line = 1;
6680 if (vect_length == 0)
6681 fputs ("0 /* This is dummy el because the vect is empty */", output_file);
6682 else
6683 for (i = 0; i < vect_length; i++)
6685 fprintf (output_file, "%5ld", (long) VEC_index (vect_el_t, vect, i));
6686 if (els_on_line == 10)
6688 els_on_line = 0;
6689 fputs (",\n", output_file);
6691 else if (i < vect_length-1)
6692 fputs (", ", output_file);
6693 els_on_line++;
6697 /* The following is name of the structure which represents DFA(s) for
6698 PHR. */
6699 #define CHIP_NAME "DFA_chip"
6701 /* The following is name of member which represents state of a DFA for
6702 PHR. */
6703 static void
6704 output_chip_member_name (FILE *f, automaton_t automaton)
6706 if (automaton->corresponding_automaton_decl == NULL)
6707 fprintf (f, "automaton_state_%d", automaton->automaton_order_num);
6708 else
6709 fprintf (f, "%s_automaton_state",
6710 automaton->corresponding_automaton_decl->name);
6713 /* The following is name of temporary variable which stores state of a
6714 DFA for PHR. */
6715 static void
6716 output_temp_chip_member_name (FILE *f, automaton_t automaton)
6718 fprintf (f, "_");
6719 output_chip_member_name (f, automaton);
6722 /* This is name of macro value which is code of pseudo_insn
6723 representing advancing cpu cycle. Its value is used as internal
6724 code unknown insn. */
6725 #define ADVANCE_CYCLE_VALUE_NAME "DFA__ADVANCE_CYCLE"
6727 /* Output name of translate vector for given automaton. */
6728 static void
6729 output_translate_vect_name (FILE *f, automaton_t automaton)
6731 if (automaton->corresponding_automaton_decl == NULL)
6732 fprintf (f, "translate_%d", automaton->automaton_order_num);
6733 else
6734 fprintf (f, "%s_translate", automaton->corresponding_automaton_decl->name);
6737 /* Output name for simple transition table representation. */
6738 static void
6739 output_trans_full_vect_name (FILE *f, automaton_t automaton)
6741 if (automaton->corresponding_automaton_decl == NULL)
6742 fprintf (f, "transitions_%d", automaton->automaton_order_num);
6743 else
6744 fprintf (f, "%s_transitions",
6745 automaton->corresponding_automaton_decl->name);
6748 /* Output name of comb vector of the transition table for given
6749 automaton. */
6750 static void
6751 output_trans_comb_vect_name (FILE *f, automaton_t automaton)
6753 if (automaton->corresponding_automaton_decl == NULL)
6754 fprintf (f, "transitions_%d", automaton->automaton_order_num);
6755 else
6756 fprintf (f, "%s_transitions",
6757 automaton->corresponding_automaton_decl->name);
6760 /* Output name of check vector of the transition table for given
6761 automaton. */
6762 static void
6763 output_trans_check_vect_name (FILE *f, automaton_t automaton)
6765 if (automaton->corresponding_automaton_decl == NULL)
6766 fprintf (f, "check_%d", automaton->automaton_order_num);
6767 else
6768 fprintf (f, "%s_check", automaton->corresponding_automaton_decl->name);
6771 /* Output name of base vector of the transition table for given
6772 automaton. */
6773 static void
6774 output_trans_base_vect_name (FILE *f, automaton_t automaton)
6776 if (automaton->corresponding_automaton_decl == NULL)
6777 fprintf (f, "base_%d", automaton->automaton_order_num);
6778 else
6779 fprintf (f, "%s_base", automaton->corresponding_automaton_decl->name);
6782 /* Output name of simple min issue delay table representation. */
6783 static void
6784 output_min_issue_delay_vect_name (FILE *f, automaton_t automaton)
6786 if (automaton->corresponding_automaton_decl == NULL)
6787 fprintf (f, "min_issue_delay_%d", automaton->automaton_order_num);
6788 else
6789 fprintf (f, "%s_min_issue_delay",
6790 automaton->corresponding_automaton_decl->name);
6793 /* Output name of deadlock vector for given automaton. */
6794 static void
6795 output_dead_lock_vect_name (FILE *f, automaton_t automaton)
6797 if (automaton->corresponding_automaton_decl == NULL)
6798 fprintf (f, "dead_lock_%d", automaton->automaton_order_num);
6799 else
6800 fprintf (f, "%s_dead_lock", automaton->corresponding_automaton_decl->name);
6803 /* Output name of reserved units table for AUTOMATON into file F. */
6804 static void
6805 output_reserved_units_table_name (FILE *f, automaton_t automaton)
6807 if (automaton->corresponding_automaton_decl == NULL)
6808 fprintf (f, "reserved_units_%d", automaton->automaton_order_num);
6809 else
6810 fprintf (f, "%s_reserved_units",
6811 automaton->corresponding_automaton_decl->name);
6814 /* Name of the PHR interface macro. */
6815 #define CPU_UNITS_QUERY_MACRO_NAME "CPU_UNITS_QUERY"
6817 /* Names of an internal functions: */
6818 #define INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME "internal_min_issue_delay"
6820 /* This is external type of DFA(s) state. */
6821 #define STATE_TYPE_NAME "state_t"
6823 #define INTERNAL_TRANSITION_FUNC_NAME "internal_state_transition"
6825 #define INTERNAL_RESET_FUNC_NAME "internal_reset"
6827 #define INTERNAL_DEAD_LOCK_FUNC_NAME "internal_state_dead_lock_p"
6829 #define INTERNAL_INSN_LATENCY_FUNC_NAME "internal_insn_latency"
6831 /* Name of cache of insn dfa codes. */
6832 #define DFA_INSN_CODES_VARIABLE_NAME "dfa_insn_codes"
6834 /* Name of length of cache of insn dfa codes. */
6835 #define DFA_INSN_CODES_LENGTH_VARIABLE_NAME "dfa_insn_codes_length"
6837 /* Names of the PHR interface functions: */
6838 #define SIZE_FUNC_NAME "state_size"
6840 #define TRANSITION_FUNC_NAME "state_transition"
6842 #define MIN_ISSUE_DELAY_FUNC_NAME "min_issue_delay"
6844 #define MIN_INSN_CONFLICT_DELAY_FUNC_NAME "min_insn_conflict_delay"
6846 #define DEAD_LOCK_FUNC_NAME "state_dead_lock_p"
6848 #define RESET_FUNC_NAME "state_reset"
6850 #define INSN_LATENCY_FUNC_NAME "insn_latency"
6852 #define PRINT_RESERVATION_FUNC_NAME "print_reservation"
6854 #define GET_CPU_UNIT_CODE_FUNC_NAME "get_cpu_unit_code"
6856 #define CPU_UNIT_RESERVATION_P_FUNC_NAME "cpu_unit_reservation_p"
6858 #define DFA_CLEAN_INSN_CACHE_FUNC_NAME "dfa_clean_insn_cache"
6860 #define DFA_CLEAR_SINGLE_INSN_CACHE_FUNC_NAME "dfa_clear_single_insn_cache"
6862 #define DFA_START_FUNC_NAME "dfa_start"
6864 #define DFA_FINISH_FUNC_NAME "dfa_finish"
6866 /* Names of parameters of the PHR interface functions. */
6867 #define STATE_NAME "state"
6869 #define INSN_PARAMETER_NAME "insn"
6871 #define INSN2_PARAMETER_NAME "insn2"
6873 #define CHIP_PARAMETER_NAME "chip"
6875 #define FILE_PARAMETER_NAME "f"
6877 #define CPU_UNIT_NAME_PARAMETER_NAME "cpu_unit_name"
6879 #define CPU_CODE_PARAMETER_NAME "cpu_unit_code"
6881 /* Names of the variables whose values are internal insn code of rtx
6882 insn. */
6883 #define INTERNAL_INSN_CODE_NAME "insn_code"
6885 #define INTERNAL_INSN2_CODE_NAME "insn2_code"
6887 /* Names of temporary variables in some functions. */
6888 #define TEMPORARY_VARIABLE_NAME "temp"
6890 #define I_VARIABLE_NAME "i"
6892 /* Name of result variable in some functions. */
6893 #define RESULT_VARIABLE_NAME "res"
6895 /* Name of function (attribute) to translate insn into internal insn
6896 code. */
6897 #define INTERNAL_DFA_INSN_CODE_FUNC_NAME "internal_dfa_insn_code"
6899 /* Name of function (attribute) to translate insn into internal insn
6900 code with caching. */
6901 #define DFA_INSN_CODE_FUNC_NAME "dfa_insn_code"
6903 /* Output C type which is used for representation of codes of states
6904 of AUTOMATON. */
6905 static void
6906 output_state_member_type (FILE *f, automaton_t automaton)
6908 output_range_type (f, 0, automaton->achieved_states_num);
6911 /* Output definition of the structure representing current DFA(s)
6912 state(s). */
6913 static void
6914 output_chip_definitions (void)
6916 automaton_t automaton;
6918 fprintf (output_file, "struct %s\n{\n", CHIP_NAME);
6919 for (automaton = description->first_automaton;
6920 automaton != NULL;
6921 automaton = automaton->next_automaton)
6923 fprintf (output_file, " ");
6924 output_state_member_type (output_file, automaton);
6925 fprintf (output_file, " ");
6926 output_chip_member_name (output_file, automaton);
6927 fprintf (output_file, ";\n");
6929 fprintf (output_file, "};\n\n");
6930 #if 0
6931 fprintf (output_file, "static struct %s %s;\n\n", CHIP_NAME, CHIP_NAME);
6932 #endif
6936 /* The function outputs translate vector of internal insn code into
6937 insn equivalence class number. The equivalence class number is
6938 used to access to table and vectors representing DFA(s). */
6939 static void
6940 output_translate_vect (automaton_t automaton)
6942 ainsn_t ainsn;
6943 int insn_value;
6944 vla_hwint_t translate_vect;
6946 translate_vect = VEC_alloc (vect_el_t,heap, description->insns_num);
6948 for (insn_value = 0; insn_value < description->insns_num; insn_value++)
6949 /* Undefined value */
6950 VEC_quick_push (vect_el_t, translate_vect,
6951 automaton->insn_equiv_classes_num);
6953 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6954 VEC_replace (vect_el_t, translate_vect,
6955 ainsn->insn_reserv_decl->insn_num,
6956 ainsn->insn_equiv_class_num);
6958 fprintf (output_file,
6959 "/* Vector translating external insn codes to internal ones.*/\n");
6960 fprintf (output_file, "static const ");
6961 output_range_type (output_file, 0, automaton->insn_equiv_classes_num);
6962 fprintf (output_file, " ");
6963 output_translate_vect_name (output_file, automaton);
6964 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
6965 output_vect (translate_vect);
6966 fprintf (output_file, "};\n\n");
6967 VEC_free (vect_el_t,heap, translate_vect);
6970 /* The value in a table state x ainsn -> something which represents
6971 undefined value. */
6972 static int undefined_vect_el_value;
6974 /* The following function returns nonzero value if the best
6975 representation of the table is comb vector. */
6976 static int
6977 comb_vect_p (state_ainsn_table_t tab)
6979 return (2 * VEC_length (vect_el_t, tab->full_vect)
6980 > 5 * VEC_length (vect_el_t, tab->comb_vect));
6983 /* The following function creates new table for AUTOMATON. */
6984 static state_ainsn_table_t
6985 create_state_ainsn_table (automaton_t automaton)
6987 state_ainsn_table_t tab;
6988 int full_vect_length;
6989 int i;
6991 tab = create_node (sizeof (struct state_ainsn_table));
6992 tab->automaton = automaton;
6994 tab->comb_vect = VEC_alloc (vect_el_t,heap, 10000);
6995 tab->check_vect = VEC_alloc (vect_el_t,heap, 10000);
6997 tab->base_vect = 0;
6998 VEC_safe_grow (vect_el_t,heap, tab->base_vect,
6999 automaton->achieved_states_num);
7001 full_vect_length = (automaton->insn_equiv_classes_num
7002 * automaton->achieved_states_num);
7003 tab->full_vect = VEC_alloc (vect_el_t,heap, full_vect_length);
7004 for (i = 0; i < full_vect_length; i++)
7005 VEC_quick_push (vect_el_t, tab->full_vect, undefined_vect_el_value);
7007 tab->min_base_vect_el_value = 0;
7008 tab->max_base_vect_el_value = 0;
7009 tab->min_comb_vect_el_value = 0;
7010 tab->max_comb_vect_el_value = 0;
7011 return tab;
7014 /* The following function outputs the best C representation of the
7015 table TAB of given TABLE_NAME. */
7016 static void
7017 output_state_ainsn_table (state_ainsn_table_t tab, const char *table_name,
7018 void (*output_full_vect_name_func) (FILE *, automaton_t),
7019 void (*output_comb_vect_name_func) (FILE *, automaton_t),
7020 void (*output_check_vect_name_func) (FILE *, automaton_t),
7021 void (*output_base_vect_name_func) (FILE *, automaton_t))
7023 if (!comb_vect_p (tab))
7025 fprintf (output_file, "/* Vector for %s. */\n", table_name);
7026 fprintf (output_file, "static const ");
7027 output_range_type (output_file, tab->min_comb_vect_el_value,
7028 tab->max_comb_vect_el_value);
7029 fprintf (output_file, " ");
7030 (*output_full_vect_name_func) (output_file, tab->automaton);
7031 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7032 output_vect (tab->full_vect);
7033 fprintf (output_file, "};\n\n");
7035 else
7037 fprintf (output_file, "/* Comb vector for %s. */\n", table_name);
7038 fprintf (output_file, "static const ");
7039 output_range_type (output_file, tab->min_comb_vect_el_value,
7040 tab->max_comb_vect_el_value);
7041 fprintf (output_file, " ");
7042 (*output_comb_vect_name_func) (output_file, tab->automaton);
7043 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7044 output_vect (tab->comb_vect);
7045 fprintf (output_file, "};\n\n");
7046 fprintf (output_file, "/* Check vector for %s. */\n", table_name);
7047 fprintf (output_file, "static const ");
7048 output_range_type (output_file, 0, tab->automaton->achieved_states_num);
7049 fprintf (output_file, " ");
7050 (*output_check_vect_name_func) (output_file, tab->automaton);
7051 fprintf (output_file, "[] = {\n");
7052 output_vect (tab->check_vect);
7053 fprintf (output_file, "};\n\n");
7054 fprintf (output_file, "/* Base vector for %s. */\n", table_name);
7055 fprintf (output_file, "static const ");
7056 output_range_type (output_file, tab->min_base_vect_el_value,
7057 tab->max_base_vect_el_value);
7058 fprintf (output_file, " ");
7059 (*output_base_vect_name_func) (output_file, tab->automaton);
7060 fprintf (output_file, "[] = {\n");
7061 output_vect (tab->base_vect);
7062 fprintf (output_file, "};\n\n");
7066 /* The following function adds vector VECT to table TAB as its line
7067 with number VECT_NUM. */
7068 static void
7069 add_vect (state_ainsn_table_t tab, int vect_num, vla_hwint_t vect)
7071 int vect_length;
7072 size_t real_vect_length;
7073 int comb_vect_index;
7074 int comb_vect_els_num;
7075 int vect_index;
7076 int first_unempty_vect_index;
7077 int additional_els_num;
7078 int no_state_value;
7079 vect_el_t vect_el;
7080 int i;
7081 unsigned long vect_mask, comb_vect_mask;
7083 vect_length = VEC_length (vect_el_t, vect);
7084 gcc_assert (vect_length);
7085 gcc_assert (VEC_last (vect_el_t, vect) != undefined_vect_el_value);
7086 real_vect_length = tab->automaton->insn_equiv_classes_num;
7087 /* Form full vector in the table: */
7089 size_t full_base = tab->automaton->insn_equiv_classes_num * vect_num;
7090 if (VEC_length (vect_el_t, tab->full_vect) < full_base + vect_length)
7091 VEC_safe_grow (vect_el_t,heap, tab->full_vect,
7092 full_base + vect_length);
7093 for (i = 0; i < vect_length; i++)
7094 VEC_replace (vect_el_t, tab->full_vect, full_base + i,
7095 VEC_index (vect_el_t, vect, i));
7097 /* Form comb vector in the table: */
7098 gcc_assert (VEC_length (vect_el_t, tab->comb_vect)
7099 == VEC_length (vect_el_t, tab->check_vect));
7101 comb_vect_els_num = VEC_length (vect_el_t, tab->comb_vect);
7102 for (first_unempty_vect_index = 0;
7103 first_unempty_vect_index < vect_length;
7104 first_unempty_vect_index++)
7105 if (VEC_index (vect_el_t, vect, first_unempty_vect_index)
7106 != undefined_vect_el_value)
7107 break;
7109 /* Search for the place in comb vect for the inserted vect. */
7111 /* Slow case. */
7112 if (vect_length - first_unempty_vect_index >= SIZEOF_LONG * CHAR_BIT)
7114 for (comb_vect_index = 0;
7115 comb_vect_index < comb_vect_els_num;
7116 comb_vect_index++)
7118 for (vect_index = first_unempty_vect_index;
7119 vect_index < vect_length
7120 && vect_index + comb_vect_index < comb_vect_els_num;
7121 vect_index++)
7122 if (VEC_index (vect_el_t, vect, vect_index)
7123 != undefined_vect_el_value
7124 && (VEC_index (vect_el_t, tab->comb_vect,
7125 vect_index + comb_vect_index)
7126 != undefined_vect_el_value))
7127 break;
7128 if (vect_index >= vect_length
7129 || vect_index + comb_vect_index >= comb_vect_els_num)
7130 break;
7132 goto found;
7135 /* Fast case. */
7136 vect_mask = 0;
7137 for (vect_index = first_unempty_vect_index;
7138 vect_index < vect_length;
7139 vect_index++)
7141 vect_mask = vect_mask << 1;
7142 if (VEC_index (vect_el_t, vect, vect_index) != undefined_vect_el_value)
7143 vect_mask |= 1;
7146 /* Search for the place in comb vect for the inserted vect. */
7147 comb_vect_index = 0;
7148 if (comb_vect_els_num == 0)
7149 goto found;
7151 comb_vect_mask = 0;
7152 for (vect_index = first_unempty_vect_index;
7153 vect_index < vect_length && vect_index < comb_vect_els_num;
7154 vect_index++)
7156 comb_vect_mask <<= 1;
7157 if (vect_index + comb_vect_index < comb_vect_els_num
7158 && VEC_index (vect_el_t, tab->comb_vect, vect_index + comb_vect_index)
7159 != undefined_vect_el_value)
7160 comb_vect_mask |= 1;
7162 if ((vect_mask & comb_vect_mask) == 0)
7163 goto found;
7165 for (comb_vect_index = 1, i = vect_length; i < comb_vect_els_num;
7166 comb_vect_index++, i++)
7168 comb_vect_mask = (comb_vect_mask << 1) | 1;
7169 comb_vect_mask ^= (VEC_index (vect_el_t, tab->comb_vect, i)
7170 == undefined_vect_el_value);
7171 if ((vect_mask & comb_vect_mask) == 0)
7172 goto found;
7174 for ( ; comb_vect_index < comb_vect_els_num; comb_vect_index++)
7176 comb_vect_mask <<= 1;
7177 if ((vect_mask & comb_vect_mask) == 0)
7178 goto found;
7181 found:
7182 /* Slot was found. */
7183 additional_els_num = comb_vect_index + real_vect_length - comb_vect_els_num;
7184 if (additional_els_num < 0)
7185 additional_els_num = 0;
7186 /* Expand comb and check vectors. */
7187 vect_el = undefined_vect_el_value;
7188 no_state_value = tab->automaton->achieved_states_num;
7189 while (additional_els_num > 0)
7191 VEC_safe_push (vect_el_t,heap, tab->comb_vect, vect_el);
7192 VEC_safe_push (vect_el_t,heap, tab->check_vect, no_state_value);
7193 additional_els_num--;
7195 gcc_assert (VEC_length (vect_el_t, tab->comb_vect)
7196 >= comb_vect_index + real_vect_length);
7197 /* Fill comb and check vectors. */
7198 for (vect_index = 0; vect_index < vect_length; vect_index++)
7199 if (VEC_index (vect_el_t, vect, vect_index) != undefined_vect_el_value)
7201 vect_el_t x = VEC_index (vect_el_t, vect, vect_index);
7202 gcc_assert (VEC_index (vect_el_t, tab->comb_vect,
7203 comb_vect_index + vect_index)
7204 == undefined_vect_el_value);
7205 gcc_assert (x >= 0);
7206 if (tab->max_comb_vect_el_value < x)
7207 tab->max_comb_vect_el_value = x;
7208 if (tab->min_comb_vect_el_value > x)
7209 tab->min_comb_vect_el_value = x;
7210 VEC_replace (vect_el_t, tab->comb_vect,
7211 comb_vect_index + vect_index, x);
7212 VEC_replace (vect_el_t, tab->check_vect,
7213 comb_vect_index + vect_index, vect_num);
7215 if (tab->max_comb_vect_el_value < undefined_vect_el_value)
7216 tab->max_comb_vect_el_value = undefined_vect_el_value;
7217 if (tab->min_comb_vect_el_value > undefined_vect_el_value)
7218 tab->min_comb_vect_el_value = undefined_vect_el_value;
7219 if (tab->max_base_vect_el_value < comb_vect_index)
7220 tab->max_base_vect_el_value = comb_vect_index;
7221 if (tab->min_base_vect_el_value > comb_vect_index)
7222 tab->min_base_vect_el_value = comb_vect_index;
7224 VEC_replace (vect_el_t, tab->base_vect, vect_num, comb_vect_index);
7227 /* Return number of out arcs of STATE. */
7228 static int
7229 out_state_arcs_num (state_t state)
7231 int result;
7232 arc_t arc;
7234 result = 0;
7235 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
7237 gcc_assert (arc->insn);
7238 if (arc->insn->first_ainsn_with_given_equivalence_num)
7239 result++;
7241 return result;
7244 /* Compare number of possible transitions from the states. */
7245 static int
7246 compare_transition_els_num (const void *state_ptr_1,
7247 const void *state_ptr_2)
7249 int transition_els_num_1;
7250 int transition_els_num_2;
7252 transition_els_num_1 = out_state_arcs_num (*(state_t *) state_ptr_1);
7253 transition_els_num_2 = out_state_arcs_num (*(state_t *) state_ptr_2);
7254 if (transition_els_num_1 < transition_els_num_2)
7255 return 1;
7256 else if (transition_els_num_1 == transition_els_num_2)
7257 return 0;
7258 else
7259 return -1;
7262 /* The function adds element EL_VALUE to vector VECT for a table state
7263 x AINSN. */
7264 static void
7265 add_vect_el (vla_hwint_t *vect, ainsn_t ainsn, int el_value)
7267 int equiv_class_num;
7268 int vect_index;
7270 gcc_assert (ainsn);
7271 equiv_class_num = ainsn->insn_equiv_class_num;
7272 for (vect_index = VEC_length (vect_el_t, *vect);
7273 vect_index <= equiv_class_num;
7274 vect_index++)
7275 VEC_safe_push (vect_el_t,heap, *vect, undefined_vect_el_value);
7276 VEC_replace (vect_el_t, *vect, equiv_class_num, el_value);
7279 /* This is for forming vector of states of an automaton. */
7280 static VEC(state_t,heap) *output_states_vect;
7282 /* The function is called by function pass_states. The function adds
7283 STATE to `output_states_vect'. */
7284 static void
7285 add_states_vect_el (state_t state)
7287 VEC_safe_push (state_t,heap, output_states_vect, state);
7290 /* Form and output vectors (comb, check, base or full vector)
7291 representing transition table of AUTOMATON. */
7292 static void
7293 output_trans_table (automaton_t automaton)
7295 size_t i;
7296 arc_t arc;
7297 vla_hwint_t transition_vect = 0;
7299 undefined_vect_el_value = automaton->achieved_states_num;
7300 automaton->trans_table = create_state_ainsn_table (automaton);
7301 /* Create vect of pointers to states ordered by num of transitions
7302 from the state (state with the maximum num is the first). */
7303 output_states_vect = 0;
7304 pass_states (automaton, add_states_vect_el);
7305 qsort (VEC_address (state_t, output_states_vect),
7306 VEC_length (state_t, output_states_vect),
7307 sizeof (state_t), compare_transition_els_num);
7309 for (i = 0; i < VEC_length (state_t, output_states_vect); i++)
7311 VEC_truncate (vect_el_t, transition_vect, 0);
7312 for (arc = first_out_arc (VEC_index (state_t, output_states_vect, i));
7313 arc != NULL;
7314 arc = next_out_arc (arc))
7316 gcc_assert (arc->insn);
7317 if (arc->insn->first_ainsn_with_given_equivalence_num)
7318 add_vect_el (&transition_vect, arc->insn,
7319 arc->to_state->order_state_num);
7321 add_vect (automaton->trans_table,
7322 VEC_index (state_t, output_states_vect, i)->order_state_num,
7323 transition_vect);
7325 output_state_ainsn_table
7326 (automaton->trans_table, "state transitions",
7327 output_trans_full_vect_name, output_trans_comb_vect_name,
7328 output_trans_check_vect_name, output_trans_base_vect_name);
7330 VEC_free (state_t,heap, output_states_vect);
7331 VEC_free (vect_el_t,heap, transition_vect);
7334 /* The current number of passing states to find minimal issue delay
7335 value for an ainsn and state. */
7336 static int curr_state_pass_num;
7338 /* This recursive function passes states to find minimal issue delay
7339 value for AINSN. The state being visited is STATE. The function
7340 returns minimal issue delay value for AINSN in STATE or -1 if we
7341 enter into a loop. */
7342 static int
7343 min_issue_delay_pass_states (state_t state, ainsn_t ainsn)
7345 arc_t arc;
7346 int min_insn_issue_delay, insn_issue_delay;
7348 if (state->state_pass_num == curr_state_pass_num
7349 || state->min_insn_issue_delay != -1)
7350 /* We've entered into a loop or already have the correct value for
7351 given state and ainsn. */
7352 return state->min_insn_issue_delay;
7353 state->state_pass_num = curr_state_pass_num;
7354 min_insn_issue_delay = -1;
7355 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
7356 if (arc->insn == ainsn)
7358 min_insn_issue_delay = 0;
7359 break;
7361 else
7363 insn_issue_delay = min_issue_delay_pass_states (arc->to_state, ainsn);
7364 if (insn_issue_delay != -1)
7366 if (arc->insn->insn_reserv_decl
7367 == DECL_INSN_RESERV (advance_cycle_insn_decl))
7368 insn_issue_delay++;
7369 if (min_insn_issue_delay == -1
7370 || min_insn_issue_delay > insn_issue_delay)
7372 min_insn_issue_delay = insn_issue_delay;
7373 if (insn_issue_delay == 0)
7374 break;
7378 return min_insn_issue_delay;
7381 /* The function searches minimal issue delay value for AINSN in STATE.
7382 The function can return negative value if we can not issue AINSN. We
7383 will report about it later. */
7384 static int
7385 min_issue_delay (state_t state, ainsn_t ainsn)
7387 curr_state_pass_num++;
7388 state->min_insn_issue_delay = min_issue_delay_pass_states (state, ainsn);
7389 return state->min_insn_issue_delay;
7392 /* The function initiates code for finding minimal issue delay values.
7393 It should be called only once. */
7394 static void
7395 initiate_min_issue_delay_pass_states (void)
7397 curr_state_pass_num = 0;
7400 /* Form and output vectors representing minimal issue delay table of
7401 AUTOMATON. The table is state x ainsn -> minimal issue delay of
7402 the ainsn. */
7403 static void
7404 output_min_issue_delay_table (automaton_t automaton)
7406 vla_hwint_t min_issue_delay_vect;
7407 vla_hwint_t compressed_min_issue_delay_vect;
7408 vect_el_t min_delay;
7409 ainsn_t ainsn;
7410 size_t i, min_issue_delay_len;
7411 size_t compressed_min_issue_delay_len;
7412 size_t cfactor;
7414 /* Create vect of pointers to states ordered by num of transitions
7415 from the state (state with the maximum num is the first). */
7416 output_states_vect = 0;
7417 pass_states (automaton, add_states_vect_el);
7419 min_issue_delay_len = (VEC_length (state_t, output_states_vect)
7420 * automaton->insn_equiv_classes_num);
7421 min_issue_delay_vect = VEC_alloc (vect_el_t,heap, min_issue_delay_len);
7422 for (i = 0; i < min_issue_delay_len; i++)
7423 VEC_quick_push (vect_el_t, min_issue_delay_vect, 0);
7425 automaton->max_min_delay = 0;
7426 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
7427 if (ainsn->first_ainsn_with_given_equivalence_num)
7429 for (i = 0; i < VEC_length (state_t, output_states_vect); i++)
7430 VEC_index (state_t, output_states_vect, i)->min_insn_issue_delay = -1;
7431 for (i = 0; i < VEC_length (state_t, output_states_vect); i++)
7433 state_t s = VEC_index (state_t, output_states_vect, i);
7434 min_delay = min_issue_delay (s, ainsn);
7435 if (automaton->max_min_delay < min_delay)
7436 automaton->max_min_delay = min_delay;
7437 VEC_replace (vect_el_t, min_issue_delay_vect,
7438 s->order_state_num
7439 * automaton->insn_equiv_classes_num
7440 + ainsn->insn_equiv_class_num,
7441 min_delay);
7444 fprintf (output_file, "/* Vector of min issue delay of insns. */\n");
7445 fprintf (output_file, "static const ");
7446 output_range_type (output_file, 0, automaton->max_min_delay);
7447 fprintf (output_file, " ");
7448 output_min_issue_delay_vect_name (output_file, automaton);
7449 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7450 /* Compress the vector. */
7451 if (automaton->max_min_delay < 2)
7452 cfactor = 8;
7453 else if (automaton->max_min_delay < 4)
7454 cfactor = 4;
7455 else if (automaton->max_min_delay < 16)
7456 cfactor = 2;
7457 else
7458 cfactor = 1;
7459 automaton->min_issue_delay_table_compression_factor = cfactor;
7461 compressed_min_issue_delay_len = (min_issue_delay_len+cfactor-1) / cfactor;
7462 compressed_min_issue_delay_vect
7463 = VEC_alloc (vect_el_t,heap, compressed_min_issue_delay_len);
7465 for (i = 0; i < compressed_min_issue_delay_len; i++)
7466 VEC_quick_push (vect_el_t, compressed_min_issue_delay_vect, 0);
7468 for (i = 0; i < min_issue_delay_len; i++)
7470 size_t ci = i / cfactor;
7471 vect_el_t x = VEC_index (vect_el_t, min_issue_delay_vect, i);
7472 vect_el_t cx = VEC_index (vect_el_t, compressed_min_issue_delay_vect, ci);
7474 cx |= x << (8 - (i % cfactor + 1) * (8 / cfactor));
7475 VEC_replace (vect_el_t, compressed_min_issue_delay_vect, ci, cx);
7477 output_vect (compressed_min_issue_delay_vect);
7478 fprintf (output_file, "};\n\n");
7479 VEC_free (state_t,heap, output_states_vect);
7480 VEC_free (vect_el_t,heap, min_issue_delay_vect);
7481 VEC_free (vect_el_t,heap, compressed_min_issue_delay_vect);
7484 /* Form and output vector representing the locked states of
7485 AUTOMATON. */
7486 static void
7487 output_dead_lock_vect (automaton_t automaton)
7489 size_t i;
7490 arc_t arc;
7491 vla_hwint_t dead_lock_vect = 0;
7493 /* Create vect of pointers to states ordered by num of
7494 transitions from the state (state with the maximum num is the
7495 first). */
7496 automaton->locked_states = 0;
7497 output_states_vect = 0;
7498 pass_states (automaton, add_states_vect_el);
7500 VEC_safe_grow (vect_el_t,heap, dead_lock_vect,
7501 VEC_length (state_t, output_states_vect));
7502 for (i = 0; i < VEC_length (state_t, output_states_vect); i++)
7504 state_t s = VEC_index (state_t, output_states_vect, i);
7505 arc = first_out_arc (s);
7506 gcc_assert (arc);
7507 if (next_out_arc (arc) == NULL
7508 && (arc->insn->insn_reserv_decl
7509 == DECL_INSN_RESERV (advance_cycle_insn_decl)))
7511 VEC_replace (vect_el_t, dead_lock_vect, s->order_state_num, 1);
7512 automaton->locked_states++;
7514 else
7515 VEC_replace (vect_el_t, dead_lock_vect, s->order_state_num, 0);
7517 if (automaton->locked_states == 0)
7518 return;
7520 fprintf (output_file, "/* Vector for locked state flags. */\n");
7521 fprintf (output_file, "static const ");
7522 output_range_type (output_file, 0, 1);
7523 fprintf (output_file, " ");
7524 output_dead_lock_vect_name (output_file, automaton);
7525 fprintf (output_file, "[] = {\n");
7526 output_vect (dead_lock_vect);
7527 fprintf (output_file, "};\n\n");
7528 VEC_free (state_t,heap, output_states_vect);
7529 VEC_free (vect_el_t,heap, dead_lock_vect);
7532 /* Form and output vector representing reserved units of the states of
7533 AUTOMATON. */
7534 static void
7535 output_reserved_units_table (automaton_t automaton)
7537 vla_hwint_t reserved_units_table = 0;
7538 int state_byte_size;
7539 int reserved_units_size;
7540 size_t n;
7541 int i;
7543 if (description->query_units_num == 0)
7544 return;
7546 /* Create vect of pointers to states. */
7547 output_states_vect = 0;
7548 pass_states (automaton, add_states_vect_el);
7549 /* Create vector. */
7550 state_byte_size = (description->query_units_num + 7) / 8;
7551 reserved_units_size = (VEC_length (state_t, output_states_vect)
7552 * state_byte_size);
7554 reserved_units_table = VEC_alloc (vect_el_t,heap, reserved_units_size);
7556 for (i = 0; i < reserved_units_size; i++)
7557 VEC_quick_push (vect_el_t, reserved_units_table, 0);
7558 for (n = 0; n < VEC_length (state_t, output_states_vect); n++)
7560 state_t s = VEC_index (state_t, output_states_vect, n);
7561 for (i = 0; i < description->units_num; i++)
7562 if (units_array [i]->query_p
7563 && first_cycle_unit_presence (s, i))
7565 int ri = (s->order_state_num * state_byte_size
7566 + units_array [i]->query_num / 8);
7567 vect_el_t x = VEC_index (vect_el_t, reserved_units_table, ri);
7569 x += 1 << (units_array [i]->query_num % 8);
7570 VEC_replace (vect_el_t, reserved_units_table, ri, x);
7573 fprintf (output_file, "\n#if %s\n", CPU_UNITS_QUERY_MACRO_NAME);
7574 fprintf (output_file, "/* Vector for reserved units of states. */\n");
7575 fprintf (output_file, "static const ");
7576 output_range_type (output_file, 0, 255);
7577 fprintf (output_file, " ");
7578 output_reserved_units_table_name (output_file, automaton);
7579 fprintf (output_file, "[] = {\n");
7580 output_vect (reserved_units_table);
7581 fprintf (output_file, "};\n#endif /* #if %s */\n\n",
7582 CPU_UNITS_QUERY_MACRO_NAME);
7584 VEC_free (state_t,heap, output_states_vect);
7585 VEC_free (vect_el_t,heap, reserved_units_table);
7588 /* The function outputs all tables representing DFA(s) used for fast
7589 pipeline hazards recognition. */
7590 static void
7591 output_tables (void)
7593 automaton_t automaton;
7595 initiate_min_issue_delay_pass_states ();
7596 for (automaton = description->first_automaton;
7597 automaton != NULL;
7598 automaton = automaton->next_automaton)
7600 output_translate_vect (automaton);
7601 output_trans_table (automaton);
7602 output_min_issue_delay_table (automaton);
7603 output_dead_lock_vect (automaton);
7604 output_reserved_units_table (automaton);
7606 fprintf (output_file, "\n#define %s %d\n\n", ADVANCE_CYCLE_VALUE_NAME,
7607 DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
7610 /* The function outputs definition and value of PHR interface variable
7611 `max_insn_queue_index'. Its value is not less than maximal queue
7612 length needed for the insn scheduler. */
7613 static void
7614 output_max_insn_queue_index_def (void)
7616 int i, max, latency;
7617 decl_t decl;
7619 max = description->max_insn_reserv_cycles;
7620 for (i = 0; i < description->decls_num; i++)
7622 decl = description->decls [i];
7623 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
7625 latency = DECL_INSN_RESERV (decl)->default_latency;
7626 if (latency > max)
7627 max = latency;
7629 else if (decl->mode == dm_bypass)
7631 latency = DECL_BYPASS (decl)->latency;
7632 if (latency > max)
7633 max = latency;
7636 for (i = 0; (1 << i) <= max; i++)
7638 gcc_assert (i >= 0);
7639 fprintf (output_file, "\nconst int max_insn_queue_index = %d;\n\n",
7640 (1 << i) - 1);
7643 /* The function outputs switch cases for insn reservations using
7644 function *output_automata_list_code. */
7645 static void
7646 output_insn_code_cases (void (*output_automata_list_code)
7647 (automata_list_el_t))
7649 decl_t decl, decl2;
7650 int i, j;
7652 for (i = 0; i < description->decls_num; i++)
7654 decl = description->decls [i];
7655 if (decl->mode == dm_insn_reserv)
7656 DECL_INSN_RESERV (decl)->processed_p = FALSE;
7658 for (i = 0; i < description->decls_num; i++)
7660 decl = description->decls [i];
7661 if (decl->mode == dm_insn_reserv
7662 && !DECL_INSN_RESERV (decl)->processed_p)
7664 for (j = i; j < description->decls_num; j++)
7666 decl2 = description->decls [j];
7667 if (decl2->mode == dm_insn_reserv
7668 && (DECL_INSN_RESERV (decl2)->important_automata_list
7669 == DECL_INSN_RESERV (decl)->important_automata_list))
7671 DECL_INSN_RESERV (decl2)->processed_p = TRUE;
7672 fprintf (output_file, " case %d: /* %s */\n",
7673 DECL_INSN_RESERV (decl2)->insn_num,
7674 DECL_INSN_RESERV (decl2)->name);
7677 (*output_automata_list_code)
7678 (DECL_INSN_RESERV (decl)->important_automata_list);
7684 /* The function outputs a code for evaluation of a minimal delay of
7685 issue of insns which have reservations in given AUTOMATA_LIST. */
7686 static void
7687 output_automata_list_min_issue_delay_code (automata_list_el_t automata_list)
7689 automata_list_el_t el;
7690 automaton_t automaton;
7692 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
7694 automaton = el->automaton;
7695 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
7696 output_min_issue_delay_vect_name (output_file, automaton);
7697 fprintf (output_file,
7698 (automaton->min_issue_delay_table_compression_factor != 1
7699 ? " [(" : " ["));
7700 output_translate_vect_name (output_file, automaton);
7701 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
7702 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7703 output_chip_member_name (output_file, automaton);
7704 fprintf (output_file, " * %d", automaton->insn_equiv_classes_num);
7705 if (automaton->min_issue_delay_table_compression_factor == 1)
7706 fprintf (output_file, "];\n");
7707 else
7709 fprintf (output_file, ") / %d];\n",
7710 automaton->min_issue_delay_table_compression_factor);
7711 fprintf (output_file, " %s = (%s >> (8 - (",
7712 TEMPORARY_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
7713 output_translate_vect_name (output_file, automaton);
7714 fprintf
7715 (output_file, " [%s] %% %d + 1) * %d)) & %d;\n",
7716 INTERNAL_INSN_CODE_NAME,
7717 automaton->min_issue_delay_table_compression_factor,
7718 8 / automaton->min_issue_delay_table_compression_factor,
7719 (1 << (8 / automaton->min_issue_delay_table_compression_factor))
7720 - 1);
7722 if (el == automata_list)
7723 fprintf (output_file, " %s = %s;\n",
7724 RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
7725 else
7727 fprintf (output_file, " if (%s > %s)\n",
7728 TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
7729 fprintf (output_file, " %s = %s;\n",
7730 RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
7733 fprintf (output_file, " break;\n\n");
7736 /* Output function `internal_min_issue_delay'. */
7737 static void
7738 output_internal_min_issue_delay_func (void)
7740 fprintf (output_file,
7741 "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
7742 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7743 CHIP_NAME, CHIP_PARAMETER_NAME);
7744 fprintf (output_file, "{\n int %s ATTRIBUTE_UNUSED;\n int %s = -1;\n",
7745 TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
7746 fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
7747 output_insn_code_cases (output_automata_list_min_issue_delay_code);
7748 fprintf (output_file,
7749 "\n default:\n %s = -1;\n break;\n }\n",
7750 RESULT_VARIABLE_NAME);
7751 fprintf (output_file, " return %s;\n", RESULT_VARIABLE_NAME);
7752 fprintf (output_file, "}\n\n");
7755 /* The function outputs a code changing state after issue of insns
7756 which have reservations in given AUTOMATA_LIST. */
7757 static void
7758 output_automata_list_transition_code (automata_list_el_t automata_list)
7760 automata_list_el_t el, next_el;
7762 fprintf (output_file, " {\n");
7763 if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
7764 for (el = automata_list;; el = next_el)
7766 next_el = el->next_automata_list_el;
7767 if (next_el == NULL)
7768 break;
7769 fprintf (output_file, " ");
7770 output_state_member_type (output_file, el->automaton);
7771 fprintf (output_file, " ");
7772 output_temp_chip_member_name (output_file, el->automaton);
7773 fprintf (output_file, ";\n");
7775 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
7776 if (comb_vect_p (el->automaton->trans_table))
7778 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
7779 output_trans_base_vect_name (output_file, el->automaton);
7780 fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
7781 output_chip_member_name (output_file, el->automaton);
7782 fprintf (output_file, "] + ");
7783 output_translate_vect_name (output_file, el->automaton);
7784 fprintf (output_file, " [%s];\n", INTERNAL_INSN_CODE_NAME);
7785 fprintf (output_file, " if (");
7786 output_trans_check_vect_name (output_file, el->automaton);
7787 fprintf (output_file, " [%s] != %s->",
7788 TEMPORARY_VARIABLE_NAME, CHIP_PARAMETER_NAME);
7789 output_chip_member_name (output_file, el->automaton);
7790 fprintf (output_file, ")\n");
7791 fprintf (output_file, " return %s (%s, %s);\n",
7792 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7793 CHIP_PARAMETER_NAME);
7794 fprintf (output_file, " else\n");
7795 fprintf (output_file, " ");
7796 if (el->next_automata_list_el != NULL)
7797 output_temp_chip_member_name (output_file, el->automaton);
7798 else
7800 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7801 output_chip_member_name (output_file, el->automaton);
7803 fprintf (output_file, " = ");
7804 output_trans_comb_vect_name (output_file, el->automaton);
7805 fprintf (output_file, " [%s];\n", TEMPORARY_VARIABLE_NAME);
7807 else
7809 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
7810 output_trans_full_vect_name (output_file, el->automaton);
7811 fprintf (output_file, " [");
7812 output_translate_vect_name (output_file, el->automaton);
7813 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
7814 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7815 output_chip_member_name (output_file, el->automaton);
7816 fprintf (output_file, " * %d];\n",
7817 el->automaton->insn_equiv_classes_num);
7818 fprintf (output_file, " if (%s >= %d)\n",
7819 TEMPORARY_VARIABLE_NAME, el->automaton->achieved_states_num);
7820 fprintf (output_file, " return %s (%s, %s);\n",
7821 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7822 CHIP_PARAMETER_NAME);
7823 fprintf (output_file, " else\n ");
7824 if (el->next_automata_list_el != NULL)
7825 output_temp_chip_member_name (output_file, el->automaton);
7826 else
7828 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7829 output_chip_member_name (output_file, el->automaton);
7831 fprintf (output_file, " = %s;\n", TEMPORARY_VARIABLE_NAME);
7833 if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
7834 for (el = automata_list;; el = next_el)
7836 next_el = el->next_automata_list_el;
7837 if (next_el == NULL)
7838 break;
7839 fprintf (output_file, " %s->", CHIP_PARAMETER_NAME);
7840 output_chip_member_name (output_file, el->automaton);
7841 fprintf (output_file, " = ");
7842 output_temp_chip_member_name (output_file, el->automaton);
7843 fprintf (output_file, ";\n");
7845 fprintf (output_file, " return -1;\n");
7846 fprintf (output_file, " }\n");
7849 /* Output function `internal_state_transition'. */
7850 static void
7851 output_internal_trans_func (void)
7853 fprintf (output_file,
7854 "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
7855 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7856 CHIP_NAME, CHIP_PARAMETER_NAME);
7857 fprintf (output_file, "{\n int %s ATTRIBUTE_UNUSED;\n", TEMPORARY_VARIABLE_NAME);
7858 fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
7859 output_insn_code_cases (output_automata_list_transition_code);
7860 fprintf (output_file, "\n default:\n return -1;\n }\n");
7861 fprintf (output_file, "}\n\n");
7864 /* Output code
7866 if (insn != 0)
7868 insn_code = dfa_insn_code (insn);
7869 if (insn_code > DFA__ADVANCE_CYCLE)
7870 return code;
7872 else
7873 insn_code = DFA__ADVANCE_CYCLE;
7875 where insn denotes INSN_NAME, insn_code denotes INSN_CODE_NAME, and
7876 code denotes CODE. */
7877 static void
7878 output_internal_insn_code_evaluation (const char *insn_name,
7879 const char *insn_code_name,
7880 int code)
7882 fprintf (output_file, "\n if (%s != 0)\n {\n", insn_name);
7883 fprintf (output_file, " %s = %s (%s);\n", insn_code_name,
7884 DFA_INSN_CODE_FUNC_NAME, insn_name);
7885 fprintf (output_file, " if (%s > %s)\n return %d;\n",
7886 insn_code_name, ADVANCE_CYCLE_VALUE_NAME, code);
7887 fprintf (output_file, " }\n else\n %s = %s;\n\n",
7888 insn_code_name, ADVANCE_CYCLE_VALUE_NAME);
7892 /* This function outputs `dfa_insn_code' and its helper function
7893 `dfa_insn_code_enlarge'. */
7894 static void
7895 output_dfa_insn_code_func (void)
7897 /* Emacs c-mode gets really confused if there's a { or } in column 0
7898 inside a string, so don't do that. */
7899 fprintf (output_file, "\
7900 static void\n\
7901 dfa_insn_code_enlarge (int uid)\n\
7902 {\n\
7903 int i = %s;\n\
7904 %s = 2 * uid;\n\
7905 %s = xrealloc (%s,\n\
7906 %s * sizeof(int));\n\
7907 for (; i < %s; i++)\n\
7908 %s[i] = -1;\n}\n\n",
7909 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
7910 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
7911 DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
7912 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
7913 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
7914 DFA_INSN_CODES_VARIABLE_NAME);
7915 fprintf (output_file, "\
7916 static inline int\n%s (rtx %s)\n\
7917 {\n\
7918 int uid = INSN_UID (%s);\n\
7919 int %s;\n\n",
7920 DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME,
7921 INSN_PARAMETER_NAME, INTERNAL_INSN_CODE_NAME);
7923 fprintf (output_file,
7924 " if (uid >= %s)\n dfa_insn_code_enlarge (uid);\n\n",
7925 DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
7926 fprintf (output_file, " %s = %s[uid];\n",
7927 INTERNAL_INSN_CODE_NAME, DFA_INSN_CODES_VARIABLE_NAME);
7928 fprintf (output_file, "\
7929 if (%s < 0)\n\
7930 {\n\
7931 %s = %s (%s);\n\
7932 %s[uid] = %s;\n\
7933 }\n",
7934 INTERNAL_INSN_CODE_NAME,
7935 INTERNAL_INSN_CODE_NAME,
7936 INTERNAL_DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME,
7937 DFA_INSN_CODES_VARIABLE_NAME, INTERNAL_INSN_CODE_NAME);
7938 fprintf (output_file, " return %s;\n}\n\n", INTERNAL_INSN_CODE_NAME);
7941 /* The function outputs PHR interface function `state_transition'. */
7942 static void
7943 output_trans_func (void)
7945 fprintf (output_file, "int\n%s (%s %s, rtx %s)\n",
7946 TRANSITION_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME,
7947 INSN_PARAMETER_NAME);
7948 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
7949 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
7950 INTERNAL_INSN_CODE_NAME, -1);
7951 fprintf (output_file, " return %s (%s, %s);\n}\n\n",
7952 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, STATE_NAME);
7955 /* Output function `min_issue_delay'. */
7956 static void
7957 output_min_issue_delay_func (void)
7959 fprintf (output_file, "int\n%s (%s %s, rtx %s)\n",
7960 MIN_ISSUE_DELAY_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME,
7961 INSN_PARAMETER_NAME);
7962 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
7963 fprintf (output_file, "\n if (%s != 0)\n {\n", INSN_PARAMETER_NAME);
7964 fprintf (output_file, " %s = %s (%s);\n", INTERNAL_INSN_CODE_NAME,
7965 DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME);
7966 fprintf (output_file, " if (%s > %s)\n return 0;\n",
7967 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
7968 fprintf (output_file, " }\n else\n %s = %s;\n",
7969 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
7970 fprintf (output_file, "\n return %s (%s, %s);\n",
7971 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7972 STATE_NAME);
7973 fprintf (output_file, "}\n\n");
7976 /* Output function `internal_dead_lock'. */
7977 static void
7978 output_internal_dead_lock_func (void)
7980 automaton_t automaton;
7982 fprintf (output_file, "static int\n%s (struct %s *ARG_UNUSED (%s))\n",
7983 INTERNAL_DEAD_LOCK_FUNC_NAME, CHIP_NAME, CHIP_PARAMETER_NAME);
7984 fprintf (output_file, "{\n");
7985 for (automaton = description->first_automaton;
7986 automaton != NULL;
7987 automaton = automaton->next_automaton)
7988 if (automaton->locked_states)
7990 fprintf (output_file, " if (");
7991 output_dead_lock_vect_name (output_file, automaton);
7992 fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
7993 output_chip_member_name (output_file, automaton);
7994 fprintf (output_file, "])\n return 1/* TRUE */;\n");
7996 fprintf (output_file, " return 0/* FALSE */;\n}\n\n");
7999 /* The function outputs PHR interface function `state_dead_lock_p'. */
8000 static void
8001 output_dead_lock_func (void)
8003 fprintf (output_file, "int\n%s (%s %s)\n",
8004 DEAD_LOCK_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME);
8005 fprintf (output_file, "{\n return %s (%s);\n}\n\n",
8006 INTERNAL_DEAD_LOCK_FUNC_NAME, STATE_NAME);
8009 /* Output function `internal_reset'. */
8010 static void
8011 output_internal_reset_func (void)
8013 fprintf (output_file, "static inline void\n%s (struct %s *%s)\n",
8014 INTERNAL_RESET_FUNC_NAME, CHIP_NAME, CHIP_PARAMETER_NAME);
8015 fprintf (output_file, "{\n memset (%s, 0, sizeof (struct %s));\n}\n\n",
8016 CHIP_PARAMETER_NAME, CHIP_NAME);
8019 /* The function outputs PHR interface function `state_size'. */
8020 static void
8021 output_size_func (void)
8023 fprintf (output_file, "int\n%s (void)\n", SIZE_FUNC_NAME);
8024 fprintf (output_file, "{\n return sizeof (struct %s);\n}\n\n", CHIP_NAME);
8027 /* The function outputs PHR interface function `state_reset'. */
8028 static void
8029 output_reset_func (void)
8031 fprintf (output_file, "void\n%s (%s %s)\n",
8032 RESET_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME);
8033 fprintf (output_file, "{\n %s (%s);\n}\n\n", INTERNAL_RESET_FUNC_NAME,
8034 STATE_NAME);
8037 /* Output function `min_insn_conflict_delay'. */
8038 static void
8039 output_min_insn_conflict_delay_func (void)
8041 fprintf (output_file,
8042 "int\n%s (%s %s, rtx %s, rtx %s)\n",
8043 MIN_INSN_CONFLICT_DELAY_FUNC_NAME, STATE_TYPE_NAME,
8044 STATE_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8045 fprintf (output_file, "{\n struct %s %s;\n int %s, %s, transition;\n",
8046 CHIP_NAME, CHIP_NAME, INTERNAL_INSN_CODE_NAME,
8047 INTERNAL_INSN2_CODE_NAME);
8048 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8049 INTERNAL_INSN_CODE_NAME, 0);
8050 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
8051 INTERNAL_INSN2_CODE_NAME, 0);
8052 fprintf (output_file, " memcpy (&%s, %s, sizeof (%s));\n",
8053 CHIP_NAME, STATE_NAME, CHIP_NAME);
8054 fprintf (output_file, " %s (&%s);\n", INTERNAL_RESET_FUNC_NAME, CHIP_NAME);
8055 fprintf (output_file, " transition = %s (%s, &%s);\n",
8056 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME);
8057 fprintf (output_file, " gcc_assert (transition <= 0);\n");
8058 fprintf (output_file, " return %s (%s, &%s);\n",
8059 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN2_CODE_NAME,
8060 CHIP_NAME);
8061 fprintf (output_file, "}\n\n");
8064 /* Output function `internal_insn_latency'. */
8065 static void
8066 output_internal_insn_latency_func (void)
8068 decl_t decl;
8069 struct bypass_decl *bypass;
8070 int i, j, col;
8071 const char *tabletype = "unsigned char";
8073 /* Find the smallest integer type that can hold all the default
8074 latency values. */
8075 for (i = 0; i < description->decls_num; i++)
8076 if (description->decls[i]->mode == dm_insn_reserv)
8078 decl = description->decls[i];
8079 if (DECL_INSN_RESERV (decl)->default_latency > UCHAR_MAX
8080 && tabletype[0] != 'i') /* Don't shrink it. */
8081 tabletype = "unsigned short";
8082 if (DECL_INSN_RESERV (decl)->default_latency > USHRT_MAX)
8083 tabletype = "int";
8086 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",
8087 INTERNAL_INSN_LATENCY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8088 INTERNAL_INSN2_CODE_NAME, INSN_PARAMETER_NAME,
8089 INSN2_PARAMETER_NAME);
8090 fprintf (output_file, "{\n");
8092 if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8094 fputs (" return 0;\n}\n\n", output_file);
8095 return;
8098 fprintf (output_file, " static const %s default_latencies[] =\n {",
8099 tabletype);
8101 for (i = 0, j = 0, col = 7; i < description->decls_num; i++)
8102 if (description->decls[i]->mode == dm_insn_reserv
8103 && description->decls[i] != advance_cycle_insn_decl)
8105 if ((col = (col+1) % 8) == 0)
8106 fputs ("\n ", output_file);
8107 decl = description->decls[i];
8108 gcc_assert (j++ == DECL_INSN_RESERV (decl)->insn_num);
8109 fprintf (output_file, "% 4d,",
8110 DECL_INSN_RESERV (decl)->default_latency);
8112 gcc_assert (j == DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
8113 fputs ("\n };\n", output_file);
8115 fprintf (output_file, " if (%s >= %s || %s >= %s)\n return 0;\n",
8116 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8117 INTERNAL_INSN2_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8119 fprintf (output_file, " switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8120 for (i = 0; i < description->decls_num; i++)
8121 if (description->decls[i]->mode == dm_insn_reserv
8122 && DECL_INSN_RESERV (description->decls[i])->bypass_list)
8124 decl = description->decls [i];
8125 fprintf (output_file,
8126 " case %d:\n switch (%s)\n {\n",
8127 DECL_INSN_RESERV (decl)->insn_num,
8128 INTERNAL_INSN2_CODE_NAME);
8129 for (bypass = DECL_INSN_RESERV (decl)->bypass_list;
8130 bypass != NULL;
8131 bypass = bypass->next)
8133 gcc_assert (bypass->in_insn_reserv->insn_num
8134 != (DECL_INSN_RESERV
8135 (advance_cycle_insn_decl)->insn_num));
8136 fprintf (output_file, " case %d:\n",
8137 bypass->in_insn_reserv->insn_num);
8138 if (bypass->bypass_guard_name == NULL)
8139 fprintf (output_file, " return %d;\n",
8140 bypass->latency);
8141 else
8143 fprintf (output_file,
8144 " if (%s (%s, %s))\n",
8145 bypass->bypass_guard_name, INSN_PARAMETER_NAME,
8146 INSN2_PARAMETER_NAME);
8147 fprintf (output_file,
8148 " return %d;\n break;\n",
8149 bypass->latency);
8152 fputs (" }\n break;\n", output_file);
8155 fprintf (output_file, " }\n return default_latencies[%s];\n}\n\n",
8156 INTERNAL_INSN_CODE_NAME);
8159 /* The function outputs PHR interface function `insn_latency'. */
8160 static void
8161 output_insn_latency_func (void)
8163 fprintf (output_file, "int\n%s (rtx %s, rtx %s)\n",
8164 INSN_LATENCY_FUNC_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8165 fprintf (output_file, "{\n int %s, %s;\n",
8166 INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME);
8167 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8168 INTERNAL_INSN_CODE_NAME, 0);
8169 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
8170 INTERNAL_INSN2_CODE_NAME, 0);
8171 fprintf (output_file, " return %s (%s, %s, %s, %s);\n}\n\n",
8172 INTERNAL_INSN_LATENCY_FUNC_NAME,
8173 INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME,
8174 INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8177 /* The function outputs PHR interface function `print_reservation'. */
8178 static void
8179 output_print_reservation_func (void)
8181 decl_t decl;
8182 int i, j;
8184 fprintf (output_file,
8185 "void\n%s (FILE *%s, rtx %s ATTRIBUTE_UNUSED)\n{\n",
8186 PRINT_RESERVATION_FUNC_NAME, FILE_PARAMETER_NAME,
8187 INSN_PARAMETER_NAME);
8189 if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8191 fprintf (output_file, " fputs (\"%s\", %s);\n}\n\n",
8192 NOTHING_NAME, FILE_PARAMETER_NAME);
8193 return;
8197 fputs (" static const char *const reservation_names[] =\n {",
8198 output_file);
8200 for (i = 0, j = 0; i < description->decls_num; i++)
8202 decl = description->decls [i];
8203 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
8205 gcc_assert (j == DECL_INSN_RESERV (decl)->insn_num);
8206 j++;
8208 fprintf (output_file, "\n \"%s\",",
8209 regexp_representation (DECL_INSN_RESERV (decl)->regexp));
8210 finish_regexp_representation ();
8213 gcc_assert (j == DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
8215 fprintf (output_file, "\n \"%s\"\n };\n int %s;\n\n",
8216 NOTHING_NAME, INTERNAL_INSN_CODE_NAME);
8218 fprintf (output_file, " if (%s == 0)\n %s = %s;\n",
8219 INSN_PARAMETER_NAME,
8220 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8221 fprintf (output_file, " else\n\
8222 {\n\
8223 %s = %s (%s);\n\
8224 if (%s > %s)\n\
8225 %s = %s;\n\
8226 }\n",
8227 INTERNAL_INSN_CODE_NAME, DFA_INSN_CODE_FUNC_NAME,
8228 INSN_PARAMETER_NAME,
8229 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8230 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8232 fprintf (output_file, " fputs (reservation_names[%s], %s);\n}\n\n",
8233 INTERNAL_INSN_CODE_NAME, FILE_PARAMETER_NAME);
8236 /* The following function is used to sort unit declaration by their
8237 names. */
8238 static int
8239 units_cmp (const void *unit1, const void *unit2)
8241 const unit_decl_t u1 = *(unit_decl_t *) unit1;
8242 const unit_decl_t u2 = *(unit_decl_t *) unit2;
8244 return strcmp (u1->name, u2->name);
8247 /* The following macro value is name of struct containing unit name
8248 and unit code. */
8249 #define NAME_CODE_STRUCT_NAME "name_code"
8251 /* The following macro value is name of table of struct name_code. */
8252 #define NAME_CODE_TABLE_NAME "name_code_table"
8254 /* The following macro values are member names for struct name_code. */
8255 #define NAME_MEMBER_NAME "name"
8256 #define CODE_MEMBER_NAME "code"
8258 /* The following macro values are local variable names for function
8259 `get_cpu_unit_code'. */
8260 #define CMP_VARIABLE_NAME "cmp"
8261 #define LOW_VARIABLE_NAME "l"
8262 #define MIDDLE_VARIABLE_NAME "m"
8263 #define HIGH_VARIABLE_NAME "h"
8265 /* The following function outputs function to obtain internal cpu unit
8266 code by the cpu unit name. */
8267 static void
8268 output_get_cpu_unit_code_func (void)
8270 int i;
8271 unit_decl_t *units;
8273 fprintf (output_file, "int\n%s (const char *%s)\n",
8274 GET_CPU_UNIT_CODE_FUNC_NAME, CPU_UNIT_NAME_PARAMETER_NAME);
8275 fprintf (output_file, "{\n struct %s {const char *%s; int %s;};\n",
8276 NAME_CODE_STRUCT_NAME, NAME_MEMBER_NAME, CODE_MEMBER_NAME);
8277 fprintf (output_file, " int %s, %s, %s, %s;\n", CMP_VARIABLE_NAME,
8278 LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8279 fprintf (output_file, " static struct %s %s [] =\n {\n",
8280 NAME_CODE_STRUCT_NAME, NAME_CODE_TABLE_NAME);
8281 units = xmalloc (sizeof (unit_decl_t) * description->units_num);
8282 memcpy (units, units_array, sizeof (unit_decl_t) * description->units_num);
8283 qsort (units, description->units_num, sizeof (unit_decl_t), units_cmp);
8284 for (i = 0; i < description->units_num; i++)
8285 if (units [i]->query_p)
8286 fprintf (output_file, " {\"%s\", %d},\n",
8287 units[i]->name, units[i]->query_num);
8288 fprintf (output_file, " };\n\n");
8289 fprintf (output_file, " /* The following is binary search: */\n");
8290 fprintf (output_file, " %s = 0;\n", LOW_VARIABLE_NAME);
8291 fprintf (output_file, " %s = sizeof (%s) / sizeof (struct %s) - 1;\n",
8292 HIGH_VARIABLE_NAME, NAME_CODE_TABLE_NAME, NAME_CODE_STRUCT_NAME);
8293 fprintf (output_file, " while (%s <= %s)\n {\n",
8294 LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8295 fprintf (output_file, " %s = (%s + %s) / 2;\n",
8296 MIDDLE_VARIABLE_NAME, LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8297 fprintf (output_file, " %s = strcmp (%s, %s [%s].%s);\n",
8298 CMP_VARIABLE_NAME, CPU_UNIT_NAME_PARAMETER_NAME,
8299 NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, NAME_MEMBER_NAME);
8300 fprintf (output_file, " if (%s < 0)\n", CMP_VARIABLE_NAME);
8301 fprintf (output_file, " %s = %s - 1;\n",
8302 HIGH_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
8303 fprintf (output_file, " else if (%s > 0)\n", CMP_VARIABLE_NAME);
8304 fprintf (output_file, " %s = %s + 1;\n",
8305 LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
8306 fprintf (output_file, " else\n");
8307 fprintf (output_file, " return %s [%s].%s;\n }\n",
8308 NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, CODE_MEMBER_NAME);
8309 fprintf (output_file, " return -1;\n}\n\n");
8310 free (units);
8313 /* The following function outputs function to check reservation of cpu
8314 unit (its internal code will be passed as the function argument) in
8315 given cpu state. */
8316 static void
8317 output_cpu_unit_reservation_p (void)
8319 automaton_t automaton;
8321 fprintf (output_file, "int\n%s (%s %s, int %s)\n",
8322 CPU_UNIT_RESERVATION_P_FUNC_NAME,
8323 STATE_TYPE_NAME, STATE_NAME,
8324 CPU_CODE_PARAMETER_NAME);
8325 fprintf (output_file, "{\n gcc_assert (%s >= 0 && %s < %d);\n",
8326 CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME,
8327 description->query_units_num);
8328 if (description->query_units_num > 0)
8329 for (automaton = description->first_automaton;
8330 automaton != NULL;
8331 automaton = automaton->next_automaton)
8333 fprintf (output_file, " if ((");
8334 output_reserved_units_table_name (output_file, automaton);
8335 fprintf (output_file, " [((struct %s *) %s)->", CHIP_NAME, STATE_NAME);
8336 output_chip_member_name (output_file, automaton);
8337 fprintf (output_file, " * %d + %s / 8] >> (%s %% 8)) & 1)\n",
8338 (description->query_units_num + 7) / 8,
8339 CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME);
8340 fprintf (output_file, " return 1;\n");
8342 fprintf (output_file, " return 0;\n}\n\n");
8345 /* The function outputs PHR interface functions `dfa_clean_insn_cache'
8346 and 'dfa_clear_single_insn_cache'. */
8347 static void
8348 output_dfa_clean_insn_cache_func (void)
8350 fprintf (output_file,
8351 "void\n%s (void)\n{\n int %s;\n\n",
8352 DFA_CLEAN_INSN_CACHE_FUNC_NAME, I_VARIABLE_NAME);
8353 fprintf (output_file,
8354 " for (%s = 0; %s < %s; %s++)\n %s [%s] = -1;\n}\n\n",
8355 I_VARIABLE_NAME, I_VARIABLE_NAME,
8356 DFA_INSN_CODES_LENGTH_VARIABLE_NAME, I_VARIABLE_NAME,
8357 DFA_INSN_CODES_VARIABLE_NAME, I_VARIABLE_NAME);
8359 fprintf (output_file,
8360 "void\n%s (rtx %s)\n{\n int %s;\n\n",
8361 DFA_CLEAR_SINGLE_INSN_CACHE_FUNC_NAME, INSN_PARAMETER_NAME,
8362 I_VARIABLE_NAME);
8363 fprintf (output_file,
8364 " %s = INSN_UID (%s);\n if (%s < %s)\n %s [%s] = -1;\n}\n\n",
8365 I_VARIABLE_NAME, INSN_PARAMETER_NAME, I_VARIABLE_NAME,
8366 DFA_INSN_CODES_LENGTH_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
8367 I_VARIABLE_NAME);
8370 /* The function outputs PHR interface function `dfa_start'. */
8371 static void
8372 output_dfa_start_func (void)
8374 fprintf (output_file,
8375 "void\n%s (void)\n{\n %s = get_max_uid ();\n",
8376 DFA_START_FUNC_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8377 fprintf (output_file, " %s = xmalloc (%s * sizeof (int));\n",
8378 DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8379 fprintf (output_file, " %s ();\n}\n\n", DFA_CLEAN_INSN_CACHE_FUNC_NAME);
8382 /* The function outputs PHR interface function `dfa_finish'. */
8383 static void
8384 output_dfa_finish_func (void)
8386 fprintf (output_file, "void\n%s (void)\n{\n free (%s);\n}\n\n",
8387 DFA_FINISH_FUNC_NAME, DFA_INSN_CODES_VARIABLE_NAME);
8392 /* The page contains code for output description file (readable
8393 representation of original description and generated DFA(s). */
8395 /* The function outputs string representation of IR reservation. */
8396 static void
8397 output_regexp (regexp_t regexp)
8399 fprintf (output_description_file, "%s", regexp_representation (regexp));
8400 finish_regexp_representation ();
8403 /* Output names of units in LIST separated by comma. */
8404 static void
8405 output_unit_set_el_list (unit_set_el_t list)
8407 unit_set_el_t el;
8409 for (el = list; el != NULL; el = el->next_unit_set_el)
8411 if (el != list)
8412 fprintf (output_description_file, ", ");
8413 fprintf (output_description_file, "%s", el->unit_decl->name);
8417 /* Output patterns in LIST separated by comma. */
8418 static void
8419 output_pattern_set_el_list (pattern_set_el_t list)
8421 pattern_set_el_t el;
8422 int i;
8424 for (el = list; el != NULL; el = el->next_pattern_set_el)
8426 if (el != list)
8427 fprintf (output_description_file, ", ");
8428 for (i = 0; i < el->units_num; i++)
8429 fprintf (output_description_file, (i == 0 ? "%s" : " %s"),
8430 el->unit_decls [i]->name);
8434 /* The function outputs string representation of IR define_reservation
8435 and define_insn_reservation. */
8436 static void
8437 output_description (void)
8439 decl_t decl;
8440 int i;
8442 for (i = 0; i < description->decls_num; i++)
8444 decl = description->decls [i];
8445 if (decl->mode == dm_unit)
8447 if (DECL_UNIT (decl)->excl_list != NULL)
8449 fprintf (output_description_file, "unit %s exlusion_set: ",
8450 DECL_UNIT (decl)->name);
8451 output_unit_set_el_list (DECL_UNIT (decl)->excl_list);
8452 fprintf (output_description_file, "\n");
8454 if (DECL_UNIT (decl)->presence_list != NULL)
8456 fprintf (output_description_file, "unit %s presence_set: ",
8457 DECL_UNIT (decl)->name);
8458 output_pattern_set_el_list (DECL_UNIT (decl)->presence_list);
8459 fprintf (output_description_file, "\n");
8461 if (DECL_UNIT (decl)->final_presence_list != NULL)
8463 fprintf (output_description_file, "unit %s final_presence_set: ",
8464 DECL_UNIT (decl)->name);
8465 output_pattern_set_el_list
8466 (DECL_UNIT (decl)->final_presence_list);
8467 fprintf (output_description_file, "\n");
8469 if (DECL_UNIT (decl)->absence_list != NULL)
8471 fprintf (output_description_file, "unit %s absence_set: ",
8472 DECL_UNIT (decl)->name);
8473 output_pattern_set_el_list (DECL_UNIT (decl)->absence_list);
8474 fprintf (output_description_file, "\n");
8476 if (DECL_UNIT (decl)->final_absence_list != NULL)
8478 fprintf (output_description_file, "unit %s final_absence_set: ",
8479 DECL_UNIT (decl)->name);
8480 output_pattern_set_el_list
8481 (DECL_UNIT (decl)->final_absence_list);
8482 fprintf (output_description_file, "\n");
8486 fprintf (output_description_file, "\n");
8487 for (i = 0; i < description->decls_num; i++)
8489 decl = description->decls [i];
8490 if (decl->mode == dm_reserv)
8492 fprintf (output_description_file, "reservation %s: ",
8493 DECL_RESERV (decl)->name);
8494 output_regexp (DECL_RESERV (decl)->regexp);
8495 fprintf (output_description_file, "\n");
8497 else if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
8499 fprintf (output_description_file, "insn reservation %s ",
8500 DECL_INSN_RESERV (decl)->name);
8501 print_rtl (output_description_file,
8502 DECL_INSN_RESERV (decl)->condexp);
8503 fprintf (output_description_file, ": ");
8504 output_regexp (DECL_INSN_RESERV (decl)->regexp);
8505 fprintf (output_description_file, "\n");
8507 else if (decl->mode == dm_bypass)
8508 fprintf (output_description_file, "bypass %d %s %s\n",
8509 DECL_BYPASS (decl)->latency,
8510 DECL_BYPASS (decl)->out_insn_name,
8511 DECL_BYPASS (decl)->in_insn_name);
8513 fprintf (output_description_file, "\n\f\n");
8516 /* The function outputs name of AUTOMATON. */
8517 static void
8518 output_automaton_name (FILE *f, automaton_t automaton)
8520 if (automaton->corresponding_automaton_decl == NULL)
8521 fprintf (f, "#%d", automaton->automaton_order_num);
8522 else
8523 fprintf (f, "`%s'", automaton->corresponding_automaton_decl->name);
8526 /* Maximal length of line for pretty printing into description
8527 file. */
8528 #define MAX_LINE_LENGTH 70
8530 /* The function outputs units name belonging to AUTOMATON. */
8531 static void
8532 output_automaton_units (automaton_t automaton)
8534 decl_t decl;
8535 const char *name;
8536 int curr_line_length;
8537 int there_is_an_automaton_unit;
8538 int i;
8540 fprintf (output_description_file, "\n Corresponding units:\n");
8541 fprintf (output_description_file, " ");
8542 curr_line_length = 4;
8543 there_is_an_automaton_unit = 0;
8544 for (i = 0; i < description->decls_num; i++)
8546 decl = description->decls [i];
8547 if (decl->mode == dm_unit
8548 && (DECL_UNIT (decl)->corresponding_automaton_num
8549 == automaton->automaton_order_num))
8551 there_is_an_automaton_unit = 1;
8552 name = DECL_UNIT (decl)->name;
8553 if (curr_line_length + strlen (name) + 1 > MAX_LINE_LENGTH )
8555 curr_line_length = strlen (name) + 4;
8556 fprintf (output_description_file, "\n ");
8558 else
8560 curr_line_length += strlen (name) + 1;
8561 fprintf (output_description_file, " ");
8563 fprintf (output_description_file, "%s", name);
8566 if (!there_is_an_automaton_unit)
8567 fprintf (output_description_file, "<None>");
8568 fprintf (output_description_file, "\n\n");
8571 /* The following variable is used for forming array of all possible cpu unit
8572 reservations described by the current DFA state. */
8573 static VEC(reserv_sets_t,heap) *state_reservs;
8575 /* The function forms `state_reservs' for STATE. */
8576 static void
8577 add_state_reservs (state_t state)
8579 alt_state_t curr_alt_state;
8581 if (state->component_states != NULL)
8582 for (curr_alt_state = state->component_states;
8583 curr_alt_state != NULL;
8584 curr_alt_state = curr_alt_state->next_sorted_alt_state)
8585 add_state_reservs (curr_alt_state->state);
8586 else
8587 VEC_safe_push (reserv_sets_t,heap, state_reservs, state->reservs);
8590 /* The function outputs readable representation of all out arcs of
8591 STATE. */
8592 static void
8593 output_state_arcs (state_t state)
8595 arc_t arc;
8596 ainsn_t ainsn;
8597 const char *insn_name;
8598 int curr_line_length;
8600 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
8602 ainsn = arc->insn;
8603 gcc_assert (ainsn->first_insn_with_same_reservs);
8604 fprintf (output_description_file, " ");
8605 curr_line_length = 7;
8606 fprintf (output_description_file, "%2d: ", ainsn->insn_equiv_class_num);
8609 insn_name = ainsn->insn_reserv_decl->name;
8610 if (curr_line_length + strlen (insn_name) > MAX_LINE_LENGTH)
8612 if (ainsn != arc->insn)
8614 fprintf (output_description_file, ",\n ");
8615 curr_line_length = strlen (insn_name) + 6;
8617 else
8618 curr_line_length += strlen (insn_name);
8620 else
8622 curr_line_length += strlen (insn_name);
8623 if (ainsn != arc->insn)
8625 curr_line_length += 2;
8626 fprintf (output_description_file, ", ");
8629 fprintf (output_description_file, "%s", insn_name);
8630 ainsn = ainsn->next_same_reservs_insn;
8632 while (ainsn != NULL);
8633 fprintf (output_description_file, " %d \n",
8634 arc->to_state->order_state_num);
8636 fprintf (output_description_file, "\n");
8639 /* The following function is used for sorting possible cpu unit
8640 reservation of a DFA state. */
8641 static int
8642 state_reservs_cmp (const void *reservs_ptr_1, const void *reservs_ptr_2)
8644 return reserv_sets_cmp (*(reserv_sets_t *) reservs_ptr_1,
8645 *(reserv_sets_t *) reservs_ptr_2);
8648 /* The following function is used for sorting possible cpu unit
8649 reservation of a DFA state. */
8650 static void
8651 remove_state_duplicate_reservs (void)
8653 size_t i, j;
8655 for (i = 1, j = 0; i < VEC_length (reserv_sets_t, state_reservs); i++)
8656 if (reserv_sets_cmp (VEC_index (reserv_sets_t, state_reservs, j),
8657 VEC_index (reserv_sets_t, state_reservs, i)))
8659 j++;
8660 VEC_replace (reserv_sets_t, state_reservs, j,
8661 VEC_index (reserv_sets_t, state_reservs, i));
8663 VEC_truncate (reserv_sets_t, state_reservs, j + 1);
8666 /* The following function output readable representation of DFA(s)
8667 state used for fast recognition of pipeline hazards. State is
8668 described by possible (current and scheduled) cpu unit
8669 reservations. */
8670 static void
8671 output_state (state_t state)
8673 size_t i;
8675 state_reservs = 0;
8677 fprintf (output_description_file, " State #%d", state->order_state_num);
8678 fprintf (output_description_file,
8679 state->new_cycle_p ? " (new cycle)\n" : "\n");
8680 add_state_reservs (state);
8681 qsort (VEC_address (reserv_sets_t, state_reservs),
8682 VEC_length (reserv_sets_t, state_reservs),
8683 sizeof (reserv_sets_t), state_reservs_cmp);
8684 remove_state_duplicate_reservs ();
8685 for (i = 1; i < VEC_length (reserv_sets_t, state_reservs); i++)
8687 fprintf (output_description_file, " ");
8688 output_reserv_sets (output_description_file,
8689 VEC_index (reserv_sets_t, state_reservs, i));
8690 fprintf (output_description_file, "\n");
8692 fprintf (output_description_file, "\n");
8693 output_state_arcs (state);
8694 VEC_free (reserv_sets_t,heap, state_reservs);
8697 /* The following function output readable representation of
8698 DFAs used for fast recognition of pipeline hazards. */
8699 static void
8700 output_automaton_descriptions (void)
8702 automaton_t automaton;
8704 for (automaton = description->first_automaton;
8705 automaton != NULL;
8706 automaton = automaton->next_automaton)
8708 fprintf (output_description_file, "\nAutomaton ");
8709 output_automaton_name (output_description_file, automaton);
8710 fprintf (output_description_file, "\n");
8711 output_automaton_units (automaton);
8712 pass_states (automaton, output_state);
8718 /* The page contains top level function for generation DFA(s) used for
8719 PHR. */
8721 /* The function outputs statistics about work of different phases of
8722 DFA generator. */
8723 static void
8724 output_statistics (FILE *f)
8726 automaton_t automaton;
8727 int states_num;
8728 #ifndef NDEBUG
8729 int transition_comb_vect_els = 0;
8730 int transition_full_vect_els = 0;
8731 int min_issue_delay_vect_els = 0;
8732 int locked_states = 0;
8733 #endif
8735 for (automaton = description->first_automaton;
8736 automaton != NULL;
8737 automaton = automaton->next_automaton)
8739 fprintf (f, "\nAutomaton ");
8740 output_automaton_name (f, automaton);
8741 fprintf (f, "\n %5d NDFA states, %5d NDFA arcs\n",
8742 automaton->NDFA_states_num, automaton->NDFA_arcs_num);
8743 fprintf (f, " %5d DFA states, %5d DFA arcs\n",
8744 automaton->DFA_states_num, automaton->DFA_arcs_num);
8745 states_num = automaton->DFA_states_num;
8746 if (!no_minimization_flag)
8748 fprintf (f, " %5d minimal DFA states, %5d minimal DFA arcs\n",
8749 automaton->minimal_DFA_states_num,
8750 automaton->minimal_DFA_arcs_num);
8751 states_num = automaton->minimal_DFA_states_num;
8753 fprintf (f, " %5d all insns %5d insn equivalence classes\n",
8754 description->insns_num, automaton->insn_equiv_classes_num);
8755 fprintf (f, " %d locked states\n", automaton->locked_states);
8756 #ifndef NDEBUG
8757 fprintf
8758 (f, "%5ld transition comb vector els, %5ld trans table els: %s\n",
8759 (long) VEC_length (vect_el_t, automaton->trans_table->comb_vect),
8760 (long) VEC_length (vect_el_t, automaton->trans_table->full_vect),
8761 (comb_vect_p (automaton->trans_table)
8762 ? "use comb vect" : "use simple vect"));
8763 fprintf
8764 (f, "%5ld min delay table els, compression factor %d\n",
8765 (long) states_num * automaton->insn_equiv_classes_num,
8766 automaton->min_issue_delay_table_compression_factor);
8767 transition_comb_vect_els
8768 += VEC_length (vect_el_t, automaton->trans_table->comb_vect);
8769 transition_full_vect_els
8770 += VEC_length (vect_el_t, automaton->trans_table->full_vect);
8771 min_issue_delay_vect_els
8772 += states_num * automaton->insn_equiv_classes_num;
8773 locked_states
8774 += automaton->locked_states;
8775 #endif
8777 #ifndef NDEBUG
8778 fprintf (f, "\n%5d all allocated states, %5d all allocated arcs\n",
8779 allocated_states_num, allocated_arcs_num);
8780 fprintf (f, "%5d all allocated alternative states\n",
8781 allocated_alt_states_num);
8782 fprintf (f, "%5d all transition comb vector els, %5d all trans table els\n",
8783 transition_comb_vect_els, transition_full_vect_els);
8784 fprintf (f, "%5d all min delay table els\n", min_issue_delay_vect_els);
8785 fprintf (f, "%5d all locked states\n", locked_states);
8786 #endif
8789 /* The function output times of work of different phases of DFA
8790 generator. */
8791 static void
8792 output_time_statistics (FILE *f)
8794 fprintf (f, "\n transformation: ");
8795 print_active_time (f, transform_time);
8796 fprintf (f, (!ndfa_flag ? ", building DFA: " : ", building NDFA: "));
8797 print_active_time (f, NDFA_time);
8798 if (ndfa_flag)
8800 fprintf (f, ", NDFA -> DFA: ");
8801 print_active_time (f, NDFA_to_DFA_time);
8803 fprintf (f, "\n DFA minimization: ");
8804 print_active_time (f, minimize_time);
8805 fprintf (f, ", making insn equivalence: ");
8806 print_active_time (f, equiv_time);
8807 fprintf (f, "\n all automaton generation: ");
8808 print_active_time (f, automaton_generation_time);
8809 fprintf (f, ", output: ");
8810 print_active_time (f, output_time);
8811 fprintf (f, "\n");
8814 /* The function generates DFA (deterministic finite state automaton)
8815 for fast recognition of pipeline hazards. No errors during
8816 checking must be fixed before this function call. */
8817 static void
8818 generate (void)
8820 automata_num = split_argument;
8821 if (description->units_num < automata_num)
8822 automata_num = description->units_num;
8823 initiate_states ();
8824 initiate_arcs ();
8825 initiate_automata_lists ();
8826 initiate_pass_states ();
8827 initiate_excl_sets ();
8828 initiate_presence_absence_pattern_sets ();
8829 automaton_generation_time = create_ticker ();
8830 create_automata ();
8831 ticker_off (&automaton_generation_time);
8836 /* This page mainly contains top level functions of pipeline hazards
8837 description translator. */
8839 /* The following macro value is suffix of name of description file of
8840 pipeline hazards description translator. */
8841 #define STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX ".dfa"
8843 /* The function returns suffix of given file name. The returned
8844 string can not be changed. */
8845 static const char *
8846 file_name_suffix (const char *file_name)
8848 const char *last_period;
8850 for (last_period = NULL; *file_name != '\0'; file_name++)
8851 if (*file_name == '.')
8852 last_period = file_name;
8853 return (last_period == NULL ? file_name : last_period);
8856 /* The function returns base name of given file name, i.e. pointer to
8857 first char after last `/' (or `\' for WIN32) in given file name,
8858 given file name itself if the directory name is absent. The
8859 returned string can not be changed. */
8860 static const char *
8861 base_file_name (const char *file_name)
8863 int directory_name_length;
8865 directory_name_length = strlen (file_name);
8866 #ifdef WIN32
8867 while (directory_name_length >= 0 && file_name[directory_name_length] != '/'
8868 && file_name[directory_name_length] != '\\')
8869 #else
8870 while (directory_name_length >= 0 && file_name[directory_name_length] != '/')
8871 #endif
8872 directory_name_length--;
8873 return file_name + directory_name_length + 1;
8876 /* The following is top level function to initialize the work of
8877 pipeline hazards description translator. */
8878 static void
8879 initiate_automaton_gen (int argc, char **argv)
8881 const char *base_name;
8882 int i;
8884 ndfa_flag = 0;
8885 split_argument = 0; /* default value */
8886 no_minimization_flag = 0;
8887 time_flag = 0;
8888 stats_flag = 0;
8889 v_flag = 0;
8890 w_flag = 0;
8891 progress_flag = 0;
8892 for (i = 2; i < argc; i++)
8893 if (strcmp (argv [i], NO_MINIMIZATION_OPTION) == 0)
8894 no_minimization_flag = 1;
8895 else if (strcmp (argv [i], TIME_OPTION) == 0)
8896 time_flag = 1;
8897 else if (strcmp (argv [i], STATS_OPTION) == 0)
8898 stats_flag = 1;
8899 else if (strcmp (argv [i], V_OPTION) == 0)
8900 v_flag = 1;
8901 else if (strcmp (argv [i], W_OPTION) == 0)
8902 w_flag = 1;
8903 else if (strcmp (argv [i], NDFA_OPTION) == 0)
8904 ndfa_flag = 1;
8905 else if (strcmp (argv [i], PROGRESS_OPTION) == 0)
8906 progress_flag = 1;
8907 else if (strcmp (argv [i], "-split") == 0)
8909 if (i + 1 >= argc)
8910 fatal ("-split has no argument.");
8911 fatal ("option `-split' has not been implemented yet\n");
8912 /* split_argument = atoi (argument_vect [i + 1]); */
8915 /* Initialize IR storage. */
8916 obstack_init (&irp);
8917 initiate_automaton_decl_table ();
8918 initiate_insn_decl_table ();
8919 initiate_decl_table ();
8920 output_file = stdout;
8921 output_description_file = NULL;
8922 base_name = base_file_name (argv[1]);
8923 obstack_grow (&irp, base_name,
8924 strlen (base_name) - strlen (file_name_suffix (base_name)));
8925 obstack_grow (&irp, STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX,
8926 strlen (STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX) + 1);
8927 obstack_1grow (&irp, '\0');
8928 output_description_file_name = obstack_base (&irp);
8929 obstack_finish (&irp);
8932 /* The following function checks existence at least one arc marked by
8933 each insn. */
8934 static void
8935 check_automata_insn_issues (void)
8937 automaton_t automaton;
8938 ainsn_t ainsn, reserv_ainsn;
8940 for (automaton = description->first_automaton;
8941 automaton != NULL;
8942 automaton = automaton->next_automaton)
8944 for (ainsn = automaton->ainsn_list;
8945 ainsn != NULL;
8946 ainsn = ainsn->next_ainsn)
8947 if (ainsn->first_insn_with_same_reservs && !ainsn->arc_exists_p)
8949 for (reserv_ainsn = ainsn;
8950 reserv_ainsn != NULL;
8951 reserv_ainsn = reserv_ainsn->next_same_reservs_insn)
8952 if (automaton->corresponding_automaton_decl != NULL)
8954 if (!w_flag)
8955 error ("Automaton `%s': Insn `%s' will never be issued",
8956 automaton->corresponding_automaton_decl->name,
8957 reserv_ainsn->insn_reserv_decl->name);
8958 else
8959 warning
8960 (0, "Automaton `%s': Insn `%s' will never be issued",
8961 automaton->corresponding_automaton_decl->name,
8962 reserv_ainsn->insn_reserv_decl->name);
8964 else
8966 if (!w_flag)
8967 error ("Insn `%s' will never be issued",
8968 reserv_ainsn->insn_reserv_decl->name);
8969 else
8970 warning (0, "Insn `%s' will never be issued",
8971 reserv_ainsn->insn_reserv_decl->name);
8977 /* The following vla is used for storing pointers to all achieved
8978 states. */
8979 static VEC(state_t,heap) *automaton_states;
8981 /* This function is called by function pass_states to add an achieved
8982 STATE. */
8983 static void
8984 add_automaton_state (state_t state)
8986 VEC_safe_push (state_t,heap, automaton_states, state);
8989 /* The following function forms list of important automata (whose
8990 states may be changed after the insn issue) for each insn. */
8991 static void
8992 form_important_insn_automata_lists (void)
8994 automaton_t automaton;
8995 decl_t decl;
8996 ainsn_t ainsn;
8997 arc_t arc;
8998 int i;
8999 size_t n;
9001 automaton_states = 0;
9002 /* Mark important ainsns. */
9003 for (automaton = description->first_automaton;
9004 automaton != NULL;
9005 automaton = automaton->next_automaton)
9007 VEC_truncate (state_t, automaton_states, 0);
9008 pass_states (automaton, add_automaton_state);
9009 for (n = 0; n < VEC_length (state_t, automaton_states); n++)
9011 state_t s = VEC_index (state_t, automaton_states, n);
9012 for (arc = first_out_arc (s);
9013 arc != NULL;
9014 arc = next_out_arc (arc))
9015 if (arc->to_state != s)
9017 gcc_assert (arc->insn->first_insn_with_same_reservs);
9018 for (ainsn = arc->insn;
9019 ainsn != NULL;
9020 ainsn = ainsn->next_same_reservs_insn)
9021 ainsn->important_p = TRUE;
9025 VEC_free (state_t,heap, automaton_states);
9027 /* Create automata sets for the insns. */
9028 for (i = 0; i < description->decls_num; i++)
9030 decl = description->decls [i];
9031 if (decl->mode == dm_insn_reserv)
9033 automata_list_start ();
9034 for (automaton = description->first_automaton;
9035 automaton != NULL;
9036 automaton = automaton->next_automaton)
9037 for (ainsn = automaton->ainsn_list;
9038 ainsn != NULL;
9039 ainsn = ainsn->next_ainsn)
9040 if (ainsn->important_p
9041 && ainsn->insn_reserv_decl == DECL_INSN_RESERV (decl))
9043 automata_list_add (automaton);
9044 break;
9046 DECL_INSN_RESERV (decl)->important_automata_list
9047 = automata_list_finish ();
9053 /* The following is top level function to generate automat(a,on) for
9054 fast recognition of pipeline hazards. */
9055 static void
9056 expand_automata (void)
9058 int i;
9060 description = create_node (sizeof (struct description)
9061 /* One entry for cycle advancing insn. */
9062 + sizeof (decl_t) * VEC_length (decl_t, decls));
9063 description->decls_num = VEC_length (decl_t, decls);
9064 description->query_units_num = 0;
9065 for (i = 0; i < description->decls_num; i++)
9067 description->decls [i] = VEC_index (decl_t, decls, i);
9068 if (description->decls [i]->mode == dm_unit
9069 && DECL_UNIT (description->decls [i])->query_p)
9070 DECL_UNIT (description->decls [i])->query_num
9071 = description->query_units_num++;
9073 all_time = create_ticker ();
9074 check_time = create_ticker ();
9075 if (progress_flag)
9076 fprintf (stderr, "Check description...");
9077 check_all_description ();
9078 if (progress_flag)
9079 fprintf (stderr, "done\n");
9080 ticker_off (&check_time);
9081 generation_time = create_ticker ();
9082 if (!have_error)
9084 transform_insn_regexps ();
9085 check_unit_distributions_to_automata ();
9087 if (!have_error)
9089 generate ();
9090 check_automata_insn_issues ();
9092 if (!have_error)
9094 form_important_insn_automata_lists ();
9096 ticker_off (&generation_time);
9099 /* The following is top level function to output PHR and to finish
9100 work with pipeline description translator. */
9101 static void
9102 write_automata (void)
9104 output_time = create_ticker ();
9105 if (progress_flag)
9106 fprintf (stderr, "Forming and outputting automata tables...");
9107 output_tables ();
9108 if (progress_flag)
9110 fprintf (stderr, "done\n");
9111 fprintf (stderr, "Output functions to work with automata...");
9113 output_chip_definitions ();
9114 output_max_insn_queue_index_def ();
9115 output_internal_min_issue_delay_func ();
9116 output_internal_trans_func ();
9117 /* Cache of insn dfa codes: */
9118 fprintf (output_file, "\nstatic int *%s;\n", DFA_INSN_CODES_VARIABLE_NAME);
9119 fprintf (output_file, "\nstatic int %s;\n\n",
9120 DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
9121 output_dfa_insn_code_func ();
9122 output_trans_func ();
9123 output_min_issue_delay_func ();
9124 output_internal_dead_lock_func ();
9125 output_dead_lock_func ();
9126 output_size_func ();
9127 output_internal_reset_func ();
9128 output_reset_func ();
9129 output_min_insn_conflict_delay_func ();
9130 output_internal_insn_latency_func ();
9131 output_insn_latency_func ();
9132 output_print_reservation_func ();
9133 /* Output function get_cpu_unit_code. */
9134 fprintf (output_file, "\n#if %s\n\n", CPU_UNITS_QUERY_MACRO_NAME);
9135 output_get_cpu_unit_code_func ();
9136 output_cpu_unit_reservation_p ();
9137 fprintf (output_file, "\n#endif /* #if %s */\n\n",
9138 CPU_UNITS_QUERY_MACRO_NAME);
9139 output_dfa_clean_insn_cache_func ();
9140 output_dfa_start_func ();
9141 output_dfa_finish_func ();
9142 if (progress_flag)
9143 fprintf (stderr, "done\n");
9144 if (v_flag)
9146 output_description_file = fopen (output_description_file_name, "w");
9147 if (output_description_file == NULL)
9149 perror (output_description_file_name);
9150 exit (FATAL_EXIT_CODE);
9152 if (progress_flag)
9153 fprintf (stderr, "Output automata description...");
9154 output_description ();
9155 output_automaton_descriptions ();
9156 if (progress_flag)
9157 fprintf (stderr, "done\n");
9158 output_statistics (output_description_file);
9160 if (stats_flag)
9161 output_statistics (stderr);
9162 ticker_off (&output_time);
9163 if (time_flag)
9164 output_time_statistics (stderr);
9165 finish_states ();
9166 finish_arcs ();
9167 finish_automata_lists ();
9168 if (time_flag)
9170 fprintf (stderr, "Summary:\n");
9171 fprintf (stderr, " check time ");
9172 print_active_time (stderr, check_time);
9173 fprintf (stderr, ", generation time ");
9174 print_active_time (stderr, generation_time);
9175 fprintf (stderr, ", all time ");
9176 print_active_time (stderr, all_time);
9177 fprintf (stderr, "\n");
9179 /* Finish all work. */
9180 if (output_description_file != NULL)
9182 fflush (output_description_file);
9183 if (ferror (stdout) != 0)
9184 fatal ("Error in writing DFA description file %s: %s",
9185 output_description_file_name, xstrerror (errno));
9186 fclose (output_description_file);
9188 finish_automaton_decl_table ();
9189 finish_insn_decl_table ();
9190 finish_decl_table ();
9191 obstack_free (&irp, NULL);
9192 if (have_error && output_description_file != NULL)
9193 remove (output_description_file_name);
9197 main (int argc, char **argv)
9199 rtx desc;
9201 progname = "genautomata";
9203 if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
9204 return (FATAL_EXIT_CODE);
9206 initiate_automaton_gen (argc, argv);
9207 while (1)
9209 int lineno;
9210 int insn_code_number;
9212 desc = read_md_rtx (&lineno, &insn_code_number);
9213 if (desc == NULL)
9214 break;
9216 switch (GET_CODE (desc))
9218 case DEFINE_CPU_UNIT:
9219 gen_cpu_unit (desc);
9220 break;
9222 case DEFINE_QUERY_CPU_UNIT:
9223 gen_query_cpu_unit (desc);
9224 break;
9226 case DEFINE_BYPASS:
9227 gen_bypass (desc);
9228 break;
9230 case EXCLUSION_SET:
9231 gen_excl_set (desc);
9232 break;
9234 case PRESENCE_SET:
9235 gen_presence_set (desc);
9236 break;
9238 case FINAL_PRESENCE_SET:
9239 gen_final_presence_set (desc);
9240 break;
9242 case ABSENCE_SET:
9243 gen_absence_set (desc);
9244 break;
9246 case FINAL_ABSENCE_SET:
9247 gen_final_absence_set (desc);
9248 break;
9250 case DEFINE_AUTOMATON:
9251 gen_automaton (desc);
9252 break;
9254 case AUTOMATA_OPTION:
9255 gen_automata_option (desc);
9256 break;
9258 case DEFINE_RESERVATION:
9259 gen_reserv (desc);
9260 break;
9262 case DEFINE_INSN_RESERVATION:
9263 gen_insn_reserv (desc);
9264 break;
9266 default:
9267 break;
9271 if (have_error)
9272 return FATAL_EXIT_CODE;
9274 puts ("/* Generated automatically by the program `genautomata'\n"
9275 " from the machine description file `md'. */\n\n"
9276 "#include \"config.h\"\n"
9277 "#include \"system.h\"\n"
9278 "#include \"coretypes.h\"\n"
9279 "#include \"tm.h\"\n"
9280 "#include \"rtl.h\"\n"
9281 "#include \"tm_p.h\"\n"
9282 "#include \"insn-config.h\"\n"
9283 "#include \"recog.h\"\n"
9284 "#include \"regs.h\"\n"
9285 "#include \"real.h\"\n"
9286 "#include \"output.h\"\n"
9287 "#include \"insn-attr.h\"\n"
9288 "#include \"toplev.h\"\n"
9289 "#include \"flags.h\"\n"
9290 "#include \"function.h\"\n");
9292 if (VEC_length (decl_t, decls) > 0)
9294 expand_automata ();
9295 write_automata ();
9298 fflush (stdout);
9299 return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);