2008-05-20 Gary Dismukes <dismukes@adacore.com>
[official-gcc.git] / gcc / genautomata.c
blob96737bcf6544d2ff7743ac9d26f573fa4fba77fb
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 3, or (at your option) any
12 later version.
14 GCC is distributed in the hope that it will be useful, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 for more details.
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING3. If not see
21 <http://www.gnu.org/licenses/>. */
23 /* References:
25 1. Detecting pipeline structural hazards quickly. T. Proebsting,
26 C. Fraser. Proceedings of ACM SIGPLAN-SIGACT Symposium on
27 Principles of Programming Languages, pages 280--286, 1994.
29 This article is a good start point to understand usage of finite
30 state automata for pipeline hazard recognizers. But I'd
31 recommend the 2nd article for more deep understanding.
33 2. Efficient Instruction Scheduling Using Finite State Automata:
34 V. Bala and N. Rubin, Proceedings of MICRO-28. This is the best
35 article about usage of finite state automata for pipeline hazard
36 recognizers.
38 The current implementation is different from the 2nd article in the
39 following:
41 1. New operator `|' (alternative) is permitted in functional unit
42 reservation which can be treated deterministically and
43 non-deterministically.
45 2. Possibility of usage of nondeterministic automata too.
47 3. Possibility to query functional unit reservations for given
48 automaton state.
50 4. Several constructions to describe impossible reservations
51 (`exclusion_set', `presence_set', `final_presence_set',
52 `absence_set', and `final_absence_set').
54 5. No reverse automata are generated. Trace instruction scheduling
55 requires this. It can be easily added in the future if we
56 really need this.
58 6. Union of automaton states are not generated yet. It is planned
59 to be implemented. Such feature is needed to make more accurate
60 interlock insn scheduling to get state describing functional
61 unit reservation in a joint CFG point. */
63 /* This file code processes constructions of machine description file
64 which describes automaton used for recognition of processor pipeline
65 hazards by insn scheduler and can be used for other tasks (such as
66 VLIW insn packing.
68 The translator functions `gen_cpu_unit', `gen_query_cpu_unit',
69 `gen_bypass', `gen_excl_set', `gen_presence_set',
70 `gen_final_presence_set', `gen_absence_set',
71 `gen_final_absence_set', `gen_automaton', `gen_automata_option',
72 `gen_reserv', `gen_insn_reserv' are called from file
73 `genattrtab.c'. They transform RTL constructions describing
74 automata in .md file into internal representation convenient for
75 further processing.
77 The translator major function `expand_automata' processes the
78 description internal representation into finite state automaton.
79 It can be divided on:
81 o checking correctness of the automaton pipeline description
82 (major function is `check_all_description').
84 o generating automaton (automata) from the description (major
85 function is `make_automaton').
87 o optional transformation of nondeterministic finite state
88 automata into deterministic ones if the alternative operator
89 `|' is treated nondeterministically in the description (major
90 function is NDFA_to_DFA).
92 o optional minimization of the finite state automata by merging
93 equivalent automaton states (major function is `minimize_DFA').
95 o forming tables (some as comb vectors) and attributes
96 representing the automata (functions output_..._table).
98 Function `write_automata' outputs the created finite state
99 automaton as different tables and functions which works with the
100 automata to inquire automaton state and to change its state. These
101 function are used by gcc instruction scheduler and may be some
102 other gcc code. */
104 #include "bconfig.h"
105 #include "system.h"
106 #include "coretypes.h"
107 #include "tm.h"
108 #include "rtl.h"
109 #include "obstack.h"
110 #include "errors.h"
111 #include "gensupport.h"
113 #include <math.h>
114 #include "hashtab.h"
115 #include "vec.h"
117 #ifndef CHAR_BIT
118 #define CHAR_BIT 8
119 #endif
121 /* Positions in machine description file. Now they are not used. But
122 they could be used in the future for better diagnostic messages. */
123 typedef int pos_t;
125 /* The following is element of vector of current (and planned in the
126 future) functional unit reservations. */
127 typedef unsigned HOST_WIDE_INT set_el_t;
129 /* Reservations of function units are represented by value of the following
130 type. */
131 typedef set_el_t *reserv_sets_t;
132 typedef const set_el_t *const_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 const struct unit_decl *const_unit_decl_t;
186 typedef struct decl *decl_t;
187 typedef const struct decl *const_decl_t;
188 typedef struct regexp *regexp_t;
189 typedef struct unit_set_el *unit_set_el_t;
190 typedef struct pattern_set_el *pattern_set_el_t;
191 typedef struct pattern_reserv *pattern_reserv_t;
192 typedef struct alt_state *alt_state_t;
193 typedef struct state *state_t;
194 typedef const struct state *const_state_t;
195 typedef struct arc *arc_t;
196 typedef struct ainsn *ainsn_t;
197 typedef struct automaton *automaton_t;
198 typedef struct automata_list_el *automata_list_el_t;
199 typedef const struct automata_list_el *const_automata_list_el_t;
200 typedef struct state_ainsn_table *state_ainsn_table_t;
202 /* Undefined position. */
203 static pos_t no_pos = 0;
205 /* All IR is stored in the following obstack. */
206 static struct obstack irp;
209 /* Declare vector types for various data structures: */
211 DEF_VEC_P(alt_state_t);
212 DEF_VEC_ALLOC_P(alt_state_t,heap);
213 DEF_VEC_P(ainsn_t);
214 DEF_VEC_ALLOC_P(ainsn_t,heap);
215 DEF_VEC_P(state_t);
216 DEF_VEC_ALLOC_P(state_t,heap);
217 DEF_VEC_P(decl_t);
218 DEF_VEC_ALLOC_P(decl_t,heap);
219 DEF_VEC_P(reserv_sets_t);
220 DEF_VEC_ALLOC_P(reserv_sets_t,heap);
222 DEF_VEC_I(vect_el_t);
223 DEF_VEC_ALLOC_I(vect_el_t, heap);
224 typedef VEC(vect_el_t,heap) *vla_hwint_t;
226 /* Forward declarations of functions used before their definitions, only. */
227 static regexp_t gen_regexp_sequence (const char *);
228 static void reserv_sets_or (reserv_sets_t, reserv_sets_t,
229 reserv_sets_t);
230 static reserv_sets_t get_excl_set (reserv_sets_t);
231 static int check_presence_pattern_sets (reserv_sets_t,
232 reserv_sets_t, int);
233 static int check_absence_pattern_sets (reserv_sets_t, reserv_sets_t,
234 int);
235 static arc_t first_out_arc (const_state_t);
236 static arc_t next_out_arc (arc_t);
240 /* Options with the following names can be set up in automata_option
241 construction. Because the strings occur more one time we use the
242 macros. */
244 #define NO_MINIMIZATION_OPTION "-no-minimization"
245 #define TIME_OPTION "-time"
246 #define STATS_OPTION "-stats"
247 #define V_OPTION "-v"
248 #define W_OPTION "-w"
249 #define NDFA_OPTION "-ndfa"
250 #define PROGRESS_OPTION "-progress"
252 /* The following flags are set up by function `initiate_automaton_gen'. */
254 /* Make automata with nondeterministic reservation by insns (`-ndfa'). */
255 static int ndfa_flag;
257 /* Do not make minimization of DFA (`-no-minimization'). */
258 static int no_minimization_flag;
260 /* Value of this variable is number of automata being generated. The
261 actual number of automata may be less this value if there is not
262 sufficient number of units. This value is defined by argument of
263 option `-split' or by constructions automaton if the value is zero
264 (it is default value of the argument). */
265 static int split_argument;
267 /* Flag of output time statistics (`-time'). */
268 static int time_flag;
270 /* Flag of automata statistics (`-stats'). */
271 static int stats_flag;
273 /* Flag of creation of description file which contains description of
274 result automaton and statistics information (`-v'). */
275 static int v_flag;
277 /* Flag of output of a progress bar showing how many states were
278 generated so far for automaton being processed (`-progress'). */
279 static int progress_flag;
281 /* Flag of generating warning instead of error for non-critical errors
282 (`-w'). */
283 static int w_flag;
286 /* Output file for pipeline hazard recognizer (PHR) being generated.
287 The value is NULL if the file is not defined. */
288 static FILE *output_file;
290 /* Description file of PHR. The value is NULL if the file is not
291 created. */
292 static FILE *output_description_file;
294 /* PHR description file name. */
295 static char *output_description_file_name;
297 /* Value of the following variable is node representing description
298 being processed. This is start point of IR. */
299 static struct description *description;
303 /* This page contains description of IR structure (nodes). */
305 enum decl_mode
307 dm_unit,
308 dm_bypass,
309 dm_automaton,
310 dm_excl,
311 dm_presence,
312 dm_absence,
313 dm_reserv,
314 dm_insn_reserv
317 /* This describes define_cpu_unit and define_query_cpu_unit (see file
318 rtl.def). */
319 struct unit_decl
321 const char *name;
322 /* NULL if the automaton name is absent. */
323 const char *automaton_name;
324 /* If the following value is not zero, the cpu unit reservation is
325 described in define_query_cpu_unit. */
326 char query_p;
328 /* The following fields are defined by checker. */
330 /* The following field value is nonzero if the unit is used in an
331 regexp. */
332 char unit_is_used;
334 /* The following field value is order number (0, 1, ...) of given
335 unit. */
336 int unit_num;
337 /* The following field value is corresponding declaration of
338 automaton which was given in description. If the field value is
339 NULL then automaton in the unit declaration was absent. */
340 struct automaton_decl *automaton_decl;
341 /* The following field value is maximal cycle number (1, ...) on
342 which given unit occurs in insns. Zero value means that given
343 unit is not used in insns. */
344 int max_occ_cycle_num;
345 /* The following field value is minimal cycle number (0, ...) on
346 which given unit occurs in insns. -1 value means that given
347 unit is not used in insns. */
348 int min_occ_cycle_num;
349 /* The following list contains units which conflict with given
350 unit. */
351 unit_set_el_t excl_list;
352 /* The following list contains patterns which are required to
353 reservation of given unit. */
354 pattern_set_el_t presence_list;
355 pattern_set_el_t final_presence_list;
356 /* The following list contains patterns which should be not present
357 in reservation for given unit. */
358 pattern_set_el_t absence_list;
359 pattern_set_el_t final_absence_list;
360 /* The following is used only when `query_p' has nonzero value.
361 This is query number for the unit. */
362 int query_num;
363 /* The following is the last cycle on which the unit was checked for
364 correct distributions of units to automata in a regexp. */
365 int last_distribution_check_cycle;
367 /* The following fields are defined by automaton generator. */
369 /* The following field value is number of the automaton to which
370 given unit belongs. */
371 int corresponding_automaton_num;
372 /* If the following value is not zero, the cpu unit is present in a
373 `exclusion_set' or in right part of a `presence_set',
374 `final_presence_set', `absence_set', and
375 `final_absence_set'define_query_cpu_unit. */
376 char in_set_p;
379 /* This describes define_bypass (see file rtl.def). */
380 struct bypass_decl
382 int latency;
383 const char *out_insn_name;
384 const char *in_insn_name;
385 const char *bypass_guard_name;
387 /* The following fields are defined by checker. */
389 /* output and input insns of given bypass. */
390 struct insn_reserv_decl *out_insn_reserv;
391 struct insn_reserv_decl *in_insn_reserv;
392 /* The next bypass for given output insn. */
393 struct bypass_decl *next;
396 /* This describes define_automaton (see file rtl.def). */
397 struct automaton_decl
399 const char *name;
401 /* The following fields are defined by automaton generator. */
403 /* The following field value is nonzero if the automaton is used in
404 an regexp definition. */
405 char automaton_is_used;
407 /* The following fields are defined by checker. */
409 /* The following field value is the corresponding automaton. This
410 field is not NULL only if the automaton is present in unit
411 declarations and the automatic partition on automata is not
412 used. */
413 automaton_t corresponding_automaton;
416 /* This describes exclusion relations: exclusion_set (see file
417 rtl.def). */
418 struct excl_rel_decl
420 int all_names_num;
421 int first_list_length;
422 char *names [1];
425 /* This describes unit relations: [final_]presence_set or
426 [final_]absence_set (see file rtl.def). */
427 struct unit_pattern_rel_decl
429 int final_p;
430 int names_num;
431 int patterns_num;
432 char **names;
433 char ***patterns;
436 /* This describes define_reservation (see file rtl.def). */
437 struct reserv_decl
439 const char *name;
440 regexp_t regexp;
442 /* The following fields are defined by checker. */
444 /* The following field value is nonzero if the unit is used in an
445 regexp. */
446 char reserv_is_used;
447 /* The following field is used to check up cycle in expression
448 definition. */
449 int loop_pass_num;
452 /* This describes define_insn_reservation (see file rtl.def). */
453 struct insn_reserv_decl
455 rtx condexp;
456 int default_latency;
457 regexp_t regexp;
458 const char *name;
460 /* The following fields are defined by checker. */
462 /* The following field value is order number (0, 1, ...) of given
463 insn. */
464 int insn_num;
465 /* The following field value is list of bypasses in which given insn
466 is output insn. */
467 struct bypass_decl *bypass_list;
469 /* The following fields are defined by automaton generator. */
471 /* The following field is the insn regexp transformed that
472 the regexp has not optional regexp, repetition regexp, and an
473 reservation name (i.e. reservation identifiers are changed by the
474 corresponding regexp) and all alternations are the topest level
475 of the regexp. The value can be NULL only if it is special
476 insn `cycle advancing'. */
477 regexp_t transformed_regexp;
478 /* The following field value is list of arcs marked given
479 insn. The field is used in transformation NDFA -> DFA. */
480 arc_t arcs_marked_by_insn;
481 /* The two following fields are used during minimization of a finite state
482 automaton. */
483 /* The field value is number of equivalence class of state into
484 which arc marked by given insn enters from a state (fixed during
485 an automaton minimization). */
486 int equiv_class_num;
487 /* The following member value is the list to automata which can be
488 changed by the insn issue. */
489 automata_list_el_t important_automata_list;
490 /* The following member is used to process insn once for output. */
491 int processed_p;
494 /* This contains a declaration mentioned above. */
495 struct decl
497 /* What node in the union? */
498 enum decl_mode mode;
499 pos_t pos;
500 union
502 struct unit_decl unit;
503 struct bypass_decl bypass;
504 struct automaton_decl automaton;
505 struct excl_rel_decl excl;
506 struct unit_pattern_rel_decl presence;
507 struct unit_pattern_rel_decl absence;
508 struct reserv_decl reserv;
509 struct insn_reserv_decl insn_reserv;
510 } decl;
513 /* The following structures represent parsed reservation strings. */
514 enum regexp_mode
516 rm_unit,
517 rm_reserv,
518 rm_nothing,
519 rm_sequence,
520 rm_repeat,
521 rm_allof,
522 rm_oneof
525 /* Cpu unit in reservation. */
526 struct unit_regexp
528 const char *name;
529 unit_decl_t unit_decl;
532 /* Define_reservation in a reservation. */
533 struct reserv_regexp
535 const char *name;
536 struct reserv_decl *reserv_decl;
539 /* Absence of reservation (represented by string `nothing'). */
540 struct nothing_regexp
542 /* This used to be empty but ISO C doesn't allow that. */
543 char unused;
546 /* Representation of reservations separated by ',' (see file
547 rtl.def). */
548 struct sequence_regexp
550 int regexps_num;
551 regexp_t regexps [1];
554 /* Representation of construction `repeat' (see file rtl.def). */
555 struct repeat_regexp
557 int repeat_num;
558 regexp_t regexp;
561 /* Representation of reservations separated by '+' (see file
562 rtl.def). */
563 struct allof_regexp
565 int regexps_num;
566 regexp_t regexps [1];
569 /* Representation of reservations separated by '|' (see file
570 rtl.def). */
571 struct oneof_regexp
573 int regexps_num;
574 regexp_t regexps [1];
577 /* Representation of a reservation string. */
578 struct regexp
580 /* What node in the union? */
581 enum regexp_mode mode;
582 pos_t pos;
583 union
585 struct unit_regexp unit;
586 struct reserv_regexp reserv;
587 struct nothing_regexp nothing;
588 struct sequence_regexp sequence;
589 struct repeat_regexp repeat;
590 struct allof_regexp allof;
591 struct oneof_regexp oneof;
592 } regexp;
595 /* Represents description of pipeline hazard description based on
596 NDFA. */
597 struct description
599 int decls_num;
601 /* The following fields are defined by checker. */
603 /* The following fields values are correspondingly number of all
604 units, query units, and insns in the description. */
605 int units_num;
606 int query_units_num;
607 int insns_num;
608 /* The following field value is max length (in cycles) of
609 reservations of insns. The field value is defined only for
610 correct programs. */
611 int max_insn_reserv_cycles;
613 /* The following fields are defined by automaton generator. */
615 /* The following field value is the first automaton. */
616 automaton_t first_automaton;
618 /* The following field is created by pipeline hazard parser and
619 contains all declarations. We allocate additional entry for
620 special insn "cycle advancing" which is added by the automaton
621 generator. */
622 decl_t decls [1];
626 /* The following nodes are created in automaton checker. */
628 /* The following nodes represent exclusion set for cpu units. Each
629 element is accessed through only one excl_list. */
630 struct unit_set_el
632 unit_decl_t unit_decl;
633 unit_set_el_t next_unit_set_el;
636 /* The following nodes represent presence or absence pattern for cpu
637 units. Each element is accessed through only one presence_list or
638 absence_list. */
639 struct pattern_set_el
641 /* The number of units in unit_decls. */
642 int units_num;
643 /* The units forming the pattern. */
644 struct unit_decl **unit_decls;
645 pattern_set_el_t next_pattern_set_el;
649 /* The following nodes are created in automaton generator. */
652 /* The following nodes represent presence or absence pattern for cpu
653 units. Each element is accessed through only one element of
654 unit_presence_set_table or unit_absence_set_table. */
655 struct pattern_reserv
657 reserv_sets_t reserv;
658 pattern_reserv_t next_pattern_reserv;
661 /* The following node type describes state automaton. The state may
662 be deterministic or non-deterministic. Non-deterministic state has
663 several component states which represent alternative cpu units
664 reservations. The state also is used for describing a
665 deterministic reservation of automaton insn. */
666 struct state
668 /* The following member value is nonzero if there is a transition by
669 cycle advancing. */
670 int new_cycle_p;
671 /* The following field is list of processor unit reservations on
672 each cycle. */
673 reserv_sets_t reservs;
674 /* The following field is unique number of given state between other
675 states. */
676 int unique_num;
677 /* The following field value is automaton to which given state
678 belongs. */
679 automaton_t automaton;
680 /* The following field value is the first arc output from given
681 state. */
682 arc_t first_out_arc;
683 unsigned int num_out_arcs;
684 /* The following field is used to form NDFA. */
685 char it_was_placed_in_stack_for_NDFA_forming;
686 /* The following field is used to form DFA. */
687 char it_was_placed_in_stack_for_DFA_forming;
688 /* The following field is used to transform NDFA to DFA and DFA
689 minimization. The field value is not NULL if the state is a
690 compound state. In this case the value of field `unit_sets_list'
691 is NULL. All states in the list are in the hash table. The list
692 is formed through field `next_sorted_alt_state'. We should
693 support only one level of nesting state. */
694 alt_state_t component_states;
695 /* The following field is used for passing graph of states. */
696 int pass_num;
697 /* The list of states belonging to one equivalence class is formed
698 with the aid of the following field. */
699 state_t next_equiv_class_state;
700 /* The two following fields are used during minimization of a finite
701 state automaton. */
702 int equiv_class_num_1, equiv_class_num_2;
703 /* The following field is used during minimization of a finite state
704 automaton. The field value is state corresponding to equivalence
705 class to which given state belongs. */
706 state_t equiv_class_state;
707 unsigned int *presence_signature;
708 /* The following field value is the order number of given state.
709 The states in final DFA is enumerated with the aid of the
710 following field. */
711 int order_state_num;
712 /* This member is used for passing states for searching minimal
713 delay time. */
714 int state_pass_num;
715 /* The following member is used to evaluate min issue delay of insn
716 for a state. */
717 int min_insn_issue_delay;
720 /* Automaton arc. */
721 struct arc
723 /* The following field refers for the state into which given arc
724 enters. */
725 state_t to_state;
726 /* The following field describes that the insn issue (with cycle
727 advancing for special insn `cycle advancing' and without cycle
728 advancing for others) makes transition from given state to
729 another given state. */
730 ainsn_t insn;
731 /* The following field value is the next arc output from the same
732 state. */
733 arc_t next_out_arc;
734 /* List of arcs marked given insn is formed with the following
735 field. The field is used in transformation NDFA -> DFA. */
736 arc_t next_arc_marked_by_insn;
739 /* The following node type describes a deterministic alternative in
740 non-deterministic state which characterizes cpu unit reservations
741 of automaton insn or which is part of NDFA. */
742 struct alt_state
744 /* The following field is a deterministic state which characterizes
745 unit reservations of the instruction. */
746 state_t state;
747 /* The following field refers to the next state which characterizes
748 unit reservations of the instruction. */
749 alt_state_t next_alt_state;
750 /* The following field refers to the next state in sorted list. */
751 alt_state_t next_sorted_alt_state;
754 /* The following node type describes insn of automaton. They are
755 labels of FA arcs. */
756 struct ainsn
758 /* The following field value is the corresponding insn declaration
759 of description. */
760 struct insn_reserv_decl *insn_reserv_decl;
761 /* The following field value is the next insn declaration for an
762 automaton. */
763 ainsn_t next_ainsn;
764 /* The following field is states which characterize automaton unit
765 reservations of the instruction. The value can be NULL only if it
766 is special insn `cycle advancing'. */
767 alt_state_t alt_states;
768 /* The following field is sorted list of states which characterize
769 automaton unit reservations of the instruction. The value can be
770 NULL only if it is special insn `cycle advancing'. */
771 alt_state_t sorted_alt_states;
772 /* The following field refers the next automaton insn with
773 the same reservations. */
774 ainsn_t next_same_reservs_insn;
775 /* The following field is flag of the first automaton insn with the
776 same reservations in the declaration list. Only arcs marked such
777 insn is present in the automaton. This significantly decreases
778 memory requirements especially when several automata are
779 formed. */
780 char first_insn_with_same_reservs;
781 /* The following member has nonzero value if there is arc from state of
782 the automaton marked by the ainsn. */
783 char arc_exists_p;
784 /* Cyclic list of insns of an equivalence class is formed with the
785 aid of the following field. */
786 ainsn_t next_equiv_class_insn;
787 /* The following field value is nonzero if the insn declaration is
788 the first insn declaration with given equivalence number. */
789 char first_ainsn_with_given_equivalence_num;
790 /* The following field is number of class of equivalence of insns.
791 It is necessary because many insns may be equivalent with the
792 point of view of pipeline hazards. */
793 int insn_equiv_class_num;
794 /* The following member value is TRUE if there is an arc in the
795 automaton marked by the insn into another state. In other
796 words, the insn can change the state of the automaton. */
797 int important_p;
800 /* The following describes an automaton for PHR. */
801 struct automaton
803 /* The following field value is the list of insn declarations for
804 given automaton. */
805 ainsn_t ainsn_list;
806 /* The following field value is the corresponding automaton
807 declaration. This field is not NULL only if the automatic
808 partition on automata is not used. */
809 struct automaton_decl *corresponding_automaton_decl;
810 /* The following field value is the next automaton. */
811 automaton_t next_automaton;
812 /* The following field is start state of FA. There are not unit
813 reservations in the state. */
814 state_t start_state;
815 /* The following field value is number of equivalence classes of
816 insns (see field `insn_equiv_class_num' in
817 `insn_reserv_decl'). */
818 int insn_equiv_classes_num;
819 /* The following field value is number of states of final DFA. */
820 int achieved_states_num;
821 /* The following field value is the order number (0, 1, ...) of
822 given automaton. */
823 int automaton_order_num;
824 /* The following fields contain statistics information about
825 building automaton. */
826 int NDFA_states_num, DFA_states_num;
827 /* The following field value is defined only if minimization of DFA
828 is used. */
829 int minimal_DFA_states_num;
830 int NDFA_arcs_num, DFA_arcs_num;
831 /* The following field value is defined only if minimization of DFA
832 is used. */
833 int minimal_DFA_arcs_num;
834 /* The following member refers for two table state x ainsn -> int.
835 ??? Above sentence is incomprehensible. */
836 state_ainsn_table_t trans_table;
837 /* The following member value is maximal value of min issue delay
838 for insns of the automaton. */
839 int max_min_delay;
840 /* Usually min issue delay is small and we can place several (2, 4,
841 8) elements in one vector element. So the compression factor can
842 be 1 (no compression), 2, 4, 8. */
843 int min_issue_delay_table_compression_factor;
844 /* Total number of locked states in this automaton. */
845 int locked_states;
848 /* The following is the element of the list of automata. */
849 struct automata_list_el
851 /* The automaton itself. */
852 automaton_t automaton;
853 /* The next automata set element. */
854 automata_list_el_t next_automata_list_el;
857 /* The following structure describes a table state X ainsn -> int(>= 0). */
858 struct state_ainsn_table
860 /* Automaton to which given table belongs. */
861 automaton_t automaton;
862 /* The following tree vectors for comb vector implementation of the
863 table. */
864 vla_hwint_t comb_vect;
865 vla_hwint_t check_vect;
866 vla_hwint_t base_vect;
867 /* This is simple implementation of the table. */
868 vla_hwint_t full_vect;
869 /* Minimal and maximal values of the previous vectors. */
870 int min_comb_vect_el_value, max_comb_vect_el_value;
871 int min_base_vect_el_value, max_base_vect_el_value;
874 /* Macros to access members of unions. Use only them for access to
875 union members of declarations and regexps. */
877 #if defined ENABLE_CHECKING && (GCC_VERSION >= 2007)
879 #define DECL_UNIT(d) __extension__ \
880 (({ __typeof (d) const _decl = (d); \
881 if (_decl->mode != dm_unit) \
882 decl_mode_check_failed (_decl->mode, "dm_unit", \
883 __FILE__, __LINE__, __FUNCTION__); \
884 &(_decl)->decl.unit; }))
886 #define DECL_BYPASS(d) __extension__ \
887 (({ __typeof (d) const _decl = (d); \
888 if (_decl->mode != dm_bypass) \
889 decl_mode_check_failed (_decl->mode, "dm_bypass", \
890 __FILE__, __LINE__, __FUNCTION__); \
891 &(_decl)->decl.bypass; }))
893 #define DECL_AUTOMATON(d) __extension__ \
894 (({ __typeof (d) const _decl = (d); \
895 if (_decl->mode != dm_automaton) \
896 decl_mode_check_failed (_decl->mode, "dm_automaton", \
897 __FILE__, __LINE__, __FUNCTION__); \
898 &(_decl)->decl.automaton; }))
900 #define DECL_EXCL(d) __extension__ \
901 (({ __typeof (d) const _decl = (d); \
902 if (_decl->mode != dm_excl) \
903 decl_mode_check_failed (_decl->mode, "dm_excl", \
904 __FILE__, __LINE__, __FUNCTION__); \
905 &(_decl)->decl.excl; }))
907 #define DECL_PRESENCE(d) __extension__ \
908 (({ __typeof (d) const _decl = (d); \
909 if (_decl->mode != dm_presence) \
910 decl_mode_check_failed (_decl->mode, "dm_presence", \
911 __FILE__, __LINE__, __FUNCTION__); \
912 &(_decl)->decl.presence; }))
914 #define DECL_ABSENCE(d) __extension__ \
915 (({ __typeof (d) const _decl = (d); \
916 if (_decl->mode != dm_absence) \
917 decl_mode_check_failed (_decl->mode, "dm_absence", \
918 __FILE__, __LINE__, __FUNCTION__); \
919 &(_decl)->decl.absence; }))
921 #define DECL_RESERV(d) __extension__ \
922 (({ __typeof (d) const _decl = (d); \
923 if (_decl->mode != dm_reserv) \
924 decl_mode_check_failed (_decl->mode, "dm_reserv", \
925 __FILE__, __LINE__, __FUNCTION__); \
926 &(_decl)->decl.reserv; }))
928 #define DECL_INSN_RESERV(d) __extension__ \
929 (({ __typeof (d) const _decl = (d); \
930 if (_decl->mode != dm_insn_reserv) \
931 decl_mode_check_failed (_decl->mode, "dm_insn_reserv", \
932 __FILE__, __LINE__, __FUNCTION__); \
933 &(_decl)->decl.insn_reserv; }))
935 static const char *decl_name (enum decl_mode);
936 static void decl_mode_check_failed (enum decl_mode, const char *,
937 const char *, int, const char *)
938 ATTRIBUTE_NORETURN;
940 /* Return string representation of declaration mode MODE. */
941 static const char *
942 decl_name (enum decl_mode mode)
944 static char str [100];
946 if (mode == dm_unit)
947 return "dm_unit";
948 else if (mode == dm_bypass)
949 return "dm_bypass";
950 else if (mode == dm_automaton)
951 return "dm_automaton";
952 else if (mode == dm_excl)
953 return "dm_excl";
954 else if (mode == dm_presence)
955 return "dm_presence";
956 else if (mode == dm_absence)
957 return "dm_absence";
958 else if (mode == dm_reserv)
959 return "dm_reserv";
960 else if (mode == dm_insn_reserv)
961 return "dm_insn_reserv";
962 else
963 sprintf (str, "unknown (%d)", (int) mode);
964 return str;
967 /* The function prints message about unexpected declaration and finish
968 the program. */
969 static void
970 decl_mode_check_failed (enum decl_mode mode, const char *expected_mode_str,
971 const char *file, int line, const char *func)
973 fprintf
974 (stderr,
975 "\n%s: %d: error in %s: DECL check: expected decl %s, have %s\n",
976 file, line, func, expected_mode_str, decl_name (mode));
977 exit (1);
981 #define REGEXP_UNIT(r) __extension__ \
982 (({ struct regexp *const _regexp = (r); \
983 if (_regexp->mode != rm_unit) \
984 regexp_mode_check_failed (_regexp->mode, "rm_unit", \
985 __FILE__, __LINE__, __FUNCTION__); \
986 &(_regexp)->regexp.unit; }))
988 #define REGEXP_RESERV(r) __extension__ \
989 (({ struct regexp *const _regexp = (r); \
990 if (_regexp->mode != rm_reserv) \
991 regexp_mode_check_failed (_regexp->mode, "rm_reserv", \
992 __FILE__, __LINE__, __FUNCTION__); \
993 &(_regexp)->regexp.reserv; }))
995 #define REGEXP_SEQUENCE(r) __extension__ \
996 (({ struct regexp *const _regexp = (r); \
997 if (_regexp->mode != rm_sequence) \
998 regexp_mode_check_failed (_regexp->mode, "rm_sequence", \
999 __FILE__, __LINE__, __FUNCTION__); \
1000 &(_regexp)->regexp.sequence; }))
1002 #define REGEXP_REPEAT(r) __extension__ \
1003 (({ struct regexp *const _regexp = (r); \
1004 if (_regexp->mode != rm_repeat) \
1005 regexp_mode_check_failed (_regexp->mode, "rm_repeat", \
1006 __FILE__, __LINE__, __FUNCTION__); \
1007 &(_regexp)->regexp.repeat; }))
1009 #define REGEXP_ALLOF(r) __extension__ \
1010 (({ struct regexp *const _regexp = (r); \
1011 if (_regexp->mode != rm_allof) \
1012 regexp_mode_check_failed (_regexp->mode, "rm_allof", \
1013 __FILE__, __LINE__, __FUNCTION__); \
1014 &(_regexp)->regexp.allof; }))
1016 #define REGEXP_ONEOF(r) __extension__ \
1017 (({ struct regexp *const _regexp = (r); \
1018 if (_regexp->mode != rm_oneof) \
1019 regexp_mode_check_failed (_regexp->mode, "rm_oneof", \
1020 __FILE__, __LINE__, __FUNCTION__); \
1021 &(_regexp)->regexp.oneof; }))
1023 static const char *regexp_name (enum regexp_mode);
1024 static void regexp_mode_check_failed (enum regexp_mode, const char *,
1025 const char *, int,
1026 const char *) ATTRIBUTE_NORETURN;
1029 /* Return string representation of regexp mode MODE. */
1030 static const char *
1031 regexp_name (enum regexp_mode mode)
1033 switch (mode)
1035 case rm_unit:
1036 return "rm_unit";
1037 case rm_reserv:
1038 return "rm_reserv";
1039 case rm_nothing:
1040 return "rm_nothing";
1041 case rm_sequence:
1042 return "rm_sequence";
1043 case rm_repeat:
1044 return "rm_repeat";
1045 case rm_allof:
1046 return "rm_allof";
1047 case rm_oneof:
1048 return "rm_oneof";
1049 default:
1050 gcc_unreachable ();
1054 /* The function prints message about unexpected regexp and finish the
1055 program. */
1056 static void
1057 regexp_mode_check_failed (enum regexp_mode mode,
1058 const char *expected_mode_str,
1059 const char *file, int line, const char *func)
1061 fprintf
1062 (stderr,
1063 "\n%s: %d: error in %s: REGEXP check: expected decl %s, have %s\n",
1064 file, line, func, expected_mode_str, regexp_name (mode));
1065 exit (1);
1068 #else /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */
1070 #define DECL_UNIT(d) (&(d)->decl.unit)
1071 #define DECL_BYPASS(d) (&(d)->decl.bypass)
1072 #define DECL_AUTOMATON(d) (&(d)->decl.automaton)
1073 #define DECL_EXCL(d) (&(d)->decl.excl)
1074 #define DECL_PRESENCE(d) (&(d)->decl.presence)
1075 #define DECL_ABSENCE(d) (&(d)->decl.absence)
1076 #define DECL_RESERV(d) (&(d)->decl.reserv)
1077 #define DECL_INSN_RESERV(d) (&(d)->decl.insn_reserv)
1079 #define REGEXP_UNIT(r) (&(r)->regexp.unit)
1080 #define REGEXP_RESERV(r) (&(r)->regexp.reserv)
1081 #define REGEXP_SEQUENCE(r) (&(r)->regexp.sequence)
1082 #define REGEXP_REPEAT(r) (&(r)->regexp.repeat)
1083 #define REGEXP_ALLOF(r) (&(r)->regexp.allof)
1084 #define REGEXP_ONEOF(r) (&(r)->regexp.oneof)
1086 #endif /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */
1088 /* Create IR structure (node). */
1089 static void *
1090 create_node (size_t size)
1092 void *result;
1094 obstack_blank (&irp, size);
1095 result = obstack_base (&irp);
1096 obstack_finish (&irp);
1097 /* Default values of members are NULL and zero. */
1098 memset (result, 0, size);
1099 return result;
1102 /* Copy IR structure (node). */
1103 static void *
1104 copy_node (const void *from, size_t size)
1106 void *const result = create_node (size);
1107 memcpy (result, from, size);
1108 return result;
1111 /* The function checks that NAME does not contain quotes (`"'). */
1112 static const char *
1113 check_name (const char * name, pos_t pos ATTRIBUTE_UNUSED)
1115 const char *str;
1117 for (str = name; *str != '\0'; str++)
1118 if (*str == '\"')
1119 error ("Name `%s' contains quotes", name);
1120 return name;
1123 /* Pointers to all declarations during IR generation are stored in the
1124 following. */
1125 static VEC(decl_t,heap) *decls;
1127 /* Given a pointer to a (char *) and a separator, return an alloc'ed
1128 string containing the next separated element, taking parentheses
1129 into account if PAR_FLAG has nonzero value. Advance the pointer to
1130 after the string scanned, or the end-of-string. Return NULL if at
1131 end of string. */
1132 static char *
1133 next_sep_el (const char **pstr, int sep, int par_flag)
1135 char *out_str;
1136 const char *p;
1137 int pars_num;
1138 int n_spaces;
1140 /* Remove leading whitespaces. */
1141 while (ISSPACE ((int) **pstr))
1142 (*pstr)++;
1144 if (**pstr == '\0')
1145 return NULL;
1147 n_spaces = 0;
1148 for (pars_num = 0, p = *pstr; *p != '\0'; p++)
1150 if (par_flag && *p == '(')
1151 pars_num++;
1152 else if (par_flag && *p == ')')
1153 pars_num--;
1154 else if (pars_num == 0 && *p == sep)
1155 break;
1156 if (pars_num == 0 && ISSPACE ((int) *p))
1157 n_spaces++;
1158 else
1160 for (; n_spaces != 0; n_spaces--)
1161 obstack_1grow (&irp, p [-n_spaces]);
1162 obstack_1grow (&irp, *p);
1165 obstack_1grow (&irp, '\0');
1166 out_str = obstack_base (&irp);
1167 obstack_finish (&irp);
1169 *pstr = p;
1170 if (**pstr == sep)
1171 (*pstr)++;
1173 return out_str;
1176 /* Given a string and a separator, return the number of separated
1177 elements in it, taking parentheses into account if PAR_FLAG has
1178 nonzero value. Return 0 for the null string, -1 if parentheses is
1179 not balanced. */
1180 static int
1181 n_sep_els (const char *s, int sep, int par_flag)
1183 int n;
1184 int pars_num;
1186 if (*s == '\0')
1187 return 0;
1189 for (pars_num = 0, n = 1; *s; s++)
1190 if (par_flag && *s == '(')
1191 pars_num++;
1192 else if (par_flag && *s == ')')
1193 pars_num--;
1194 else if (pars_num == 0 && *s == sep)
1195 n++;
1197 return (pars_num != 0 ? -1 : n);
1200 /* Given a string and a separator, return vector of strings which are
1201 elements in the string and number of elements through els_num.
1202 Take parentheses into account if PAREN_P has nonzero value. The
1203 function also inserts the end marker NULL at the end of vector.
1204 Return 0 for the null string, -1 if parentheses are not balanced. */
1205 static char **
1206 get_str_vect (const char *str, int *els_num, int sep, int paren_p)
1208 int i;
1209 char **vect;
1210 const char **pstr;
1211 char *trail;
1213 *els_num = n_sep_els (str, sep, paren_p);
1214 if (*els_num <= 0)
1215 return NULL;
1216 obstack_blank (&irp, sizeof (char *) * (*els_num + 1));
1217 vect = (char **) obstack_base (&irp);
1218 obstack_finish (&irp);
1219 pstr = &str;
1220 for (i = 0; i < *els_num; i++)
1221 vect [i] = next_sep_el (pstr, sep, paren_p);
1222 trail = next_sep_el (pstr, sep, paren_p);
1223 gcc_assert (!trail);
1224 vect [i] = NULL;
1225 return vect;
1228 /* Process a DEFINE_CPU_UNIT.
1230 This gives information about a unit contained in CPU. We fill a
1231 struct unit_decl with information used later by `expand_automata'. */
1232 static void
1233 gen_cpu_unit (rtx def)
1235 decl_t decl;
1236 char **str_cpu_units;
1237 int vect_length;
1238 int i;
1240 str_cpu_units = get_str_vect (XSTR (def, 0), &vect_length, ',', FALSE);
1241 if (str_cpu_units == NULL)
1242 fatal ("invalid string `%s' in define_cpu_unit", XSTR (def, 0));
1243 for (i = 0; i < vect_length; i++)
1245 decl = create_node (sizeof (struct decl));
1246 decl->mode = dm_unit;
1247 decl->pos = 0;
1248 DECL_UNIT (decl)->name = check_name (str_cpu_units [i], decl->pos);
1249 DECL_UNIT (decl)->automaton_name = XSTR (def, 1);
1250 DECL_UNIT (decl)->query_p = 0;
1251 DECL_UNIT (decl)->min_occ_cycle_num = -1;
1252 DECL_UNIT (decl)->in_set_p = 0;
1253 VEC_safe_push (decl_t,heap, decls, decl);
1257 /* Process a DEFINE_QUERY_CPU_UNIT.
1259 This gives information about a unit contained in CPU. We fill a
1260 struct unit_decl with information used later by `expand_automata'. */
1261 static void
1262 gen_query_cpu_unit (rtx def)
1264 decl_t decl;
1265 char **str_cpu_units;
1266 int vect_length;
1267 int i;
1269 str_cpu_units = get_str_vect (XSTR (def, 0), &vect_length, ',',
1270 FALSE);
1271 if (str_cpu_units == NULL)
1272 fatal ("invalid string `%s' in define_query_cpu_unit", XSTR (def, 0));
1273 for (i = 0; i < vect_length; i++)
1275 decl = create_node (sizeof (struct decl));
1276 decl->mode = dm_unit;
1277 decl->pos = 0;
1278 DECL_UNIT (decl)->name = check_name (str_cpu_units [i], decl->pos);
1279 DECL_UNIT (decl)->automaton_name = XSTR (def, 1);
1280 DECL_UNIT (decl)->query_p = 1;
1281 VEC_safe_push (decl_t,heap, decls, decl);
1285 /* Process a DEFINE_BYPASS.
1287 This gives information about a unit contained in the CPU. We fill
1288 in a struct bypass_decl with information used later by
1289 `expand_automata'. */
1290 static void
1291 gen_bypass (rtx def)
1293 decl_t decl;
1294 char **out_insns;
1295 int out_length;
1296 char **in_insns;
1297 int in_length;
1298 int i, j;
1300 out_insns = get_str_vect (XSTR (def, 1), &out_length, ',', FALSE);
1301 if (out_insns == NULL)
1302 fatal ("invalid string `%s' in define_bypass", XSTR (def, 1));
1303 in_insns = get_str_vect (XSTR (def, 2), &in_length, ',', FALSE);
1304 if (in_insns == NULL)
1305 fatal ("invalid string `%s' in define_bypass", XSTR (def, 2));
1306 for (i = 0; i < out_length; i++)
1307 for (j = 0; j < in_length; j++)
1309 decl = create_node (sizeof (struct decl));
1310 decl->mode = dm_bypass;
1311 decl->pos = 0;
1312 DECL_BYPASS (decl)->latency = XINT (def, 0);
1313 DECL_BYPASS (decl)->out_insn_name = out_insns [i];
1314 DECL_BYPASS (decl)->in_insn_name = in_insns [j];
1315 DECL_BYPASS (decl)->bypass_guard_name = XSTR (def, 3);
1316 VEC_safe_push (decl_t,heap, decls, decl);
1320 /* Process an EXCLUSION_SET.
1322 This gives information about a cpu unit conflicts. We fill a
1323 struct excl_rel_decl (excl) with information used later by
1324 `expand_automata'. */
1325 static void
1326 gen_excl_set (rtx def)
1328 decl_t decl;
1329 char **first_str_cpu_units;
1330 char **second_str_cpu_units;
1331 int first_vect_length;
1332 int length;
1333 int i;
1335 first_str_cpu_units
1336 = get_str_vect (XSTR (def, 0), &first_vect_length, ',', FALSE);
1337 if (first_str_cpu_units == NULL)
1338 fatal ("invalid first string `%s' in exclusion_set", XSTR (def, 0));
1339 second_str_cpu_units = get_str_vect (XSTR (def, 1), &length, ',',
1340 FALSE);
1341 if (second_str_cpu_units == NULL)
1342 fatal ("invalid second string `%s' in exclusion_set", XSTR (def, 1));
1343 length += first_vect_length;
1344 decl = create_node (sizeof (struct decl) + (length - 1) * sizeof (char *));
1345 decl->mode = dm_excl;
1346 decl->pos = 0;
1347 DECL_EXCL (decl)->all_names_num = length;
1348 DECL_EXCL (decl)->first_list_length = first_vect_length;
1349 for (i = 0; i < length; i++)
1350 if (i < first_vect_length)
1351 DECL_EXCL (decl)->names [i] = first_str_cpu_units [i];
1352 else
1353 DECL_EXCL (decl)->names [i]
1354 = second_str_cpu_units [i - first_vect_length];
1355 VEC_safe_push (decl_t,heap, decls, decl);
1358 /* Process a PRESENCE_SET, a FINAL_PRESENCE_SET, an ABSENCE_SET,
1359 FINAL_ABSENCE_SET (it is depended on PRESENCE_P and FINAL_P).
1361 This gives information about a cpu unit reservation requirements.
1362 We fill a struct unit_pattern_rel_decl with information used later
1363 by `expand_automata'. */
1364 static void
1365 gen_presence_absence_set (rtx def, int presence_p, int final_p)
1367 decl_t decl;
1368 char **str_cpu_units;
1369 char **str_pattern_lists;
1370 char ***str_patterns;
1371 int cpu_units_length;
1372 int length;
1373 int patterns_length;
1374 int i;
1376 str_cpu_units = get_str_vect (XSTR (def, 0), &cpu_units_length, ',',
1377 FALSE);
1378 if (str_cpu_units == NULL)
1379 fatal ((presence_p
1380 ? (final_p
1381 ? "invalid first string `%s' in final_presence_set"
1382 : "invalid first string `%s' in presence_set")
1383 : (final_p
1384 ? "invalid first string `%s' in final_absence_set"
1385 : "invalid first string `%s' in absence_set")),
1386 XSTR (def, 0));
1387 str_pattern_lists = get_str_vect (XSTR (def, 1),
1388 &patterns_length, ',', FALSE);
1389 if (str_pattern_lists == NULL)
1390 fatal ((presence_p
1391 ? (final_p
1392 ? "invalid second string `%s' in final_presence_set"
1393 : "invalid second string `%s' in presence_set")
1394 : (final_p
1395 ? "invalid second string `%s' in final_absence_set"
1396 : "invalid second string `%s' in absence_set")), XSTR (def, 1));
1397 str_patterns = obstack_alloc (&irp, patterns_length * sizeof (char **));
1398 for (i = 0; i < patterns_length; i++)
1400 str_patterns [i] = get_str_vect (str_pattern_lists [i],
1401 &length, ' ', FALSE);
1402 gcc_assert (str_patterns [i]);
1404 decl = create_node (sizeof (struct decl));
1405 decl->pos = 0;
1406 if (presence_p)
1408 decl->mode = dm_presence;
1409 DECL_PRESENCE (decl)->names_num = cpu_units_length;
1410 DECL_PRESENCE (decl)->names = str_cpu_units;
1411 DECL_PRESENCE (decl)->patterns = str_patterns;
1412 DECL_PRESENCE (decl)->patterns_num = patterns_length;
1413 DECL_PRESENCE (decl)->final_p = final_p;
1415 else
1417 decl->mode = dm_absence;
1418 DECL_ABSENCE (decl)->names_num = cpu_units_length;
1419 DECL_ABSENCE (decl)->names = str_cpu_units;
1420 DECL_ABSENCE (decl)->patterns = str_patterns;
1421 DECL_ABSENCE (decl)->patterns_num = patterns_length;
1422 DECL_ABSENCE (decl)->final_p = final_p;
1424 VEC_safe_push (decl_t,heap, decls, decl);
1427 /* Process a PRESENCE_SET.
1429 This gives information about a cpu unit reservation requirements.
1430 We fill a struct unit_pattern_rel_decl (presence) with information
1431 used later by `expand_automata'. */
1432 static void
1433 gen_presence_set (rtx def)
1435 gen_presence_absence_set (def, TRUE, FALSE);
1438 /* Process a FINAL_PRESENCE_SET.
1440 This gives information about a cpu unit reservation requirements.
1441 We fill a struct unit_pattern_rel_decl (presence) with information
1442 used later by `expand_automata'. */
1443 static void
1444 gen_final_presence_set (rtx def)
1446 gen_presence_absence_set (def, TRUE, TRUE);
1449 /* Process an ABSENCE_SET.
1451 This gives information about a cpu unit reservation requirements.
1452 We fill a struct unit_pattern_rel_decl (absence) with information
1453 used later by `expand_automata'. */
1454 static void
1455 gen_absence_set (rtx def)
1457 gen_presence_absence_set (def, FALSE, FALSE);
1460 /* Process a FINAL_ABSENCE_SET.
1462 This gives information about a cpu unit reservation requirements.
1463 We fill a struct unit_pattern_rel_decl (absence) with information
1464 used later by `expand_automata'. */
1465 static void
1466 gen_final_absence_set (rtx def)
1468 gen_presence_absence_set (def, FALSE, TRUE);
1471 /* Process a DEFINE_AUTOMATON.
1473 This gives information about a finite state automaton used for
1474 recognizing pipeline hazards. We fill a struct automaton_decl
1475 with information used later by `expand_automata'. */
1476 static void
1477 gen_automaton (rtx def)
1479 decl_t decl;
1480 char **str_automata;
1481 int vect_length;
1482 int i;
1484 str_automata = get_str_vect (XSTR (def, 0), &vect_length, ',', FALSE);
1485 if (str_automata == NULL)
1486 fatal ("invalid string `%s' in define_automaton", XSTR (def, 0));
1487 for (i = 0; i < vect_length; i++)
1489 decl = create_node (sizeof (struct decl));
1490 decl->mode = dm_automaton;
1491 decl->pos = 0;
1492 DECL_AUTOMATON (decl)->name = check_name (str_automata [i], decl->pos);
1493 VEC_safe_push (decl_t,heap, decls, decl);
1497 /* Process an AUTOMATA_OPTION.
1499 This gives information how to generate finite state automaton used
1500 for recognizing pipeline hazards. */
1501 static void
1502 gen_automata_option (rtx def)
1504 if (strcmp (XSTR (def, 0), NO_MINIMIZATION_OPTION + 1) == 0)
1505 no_minimization_flag = 1;
1506 else if (strcmp (XSTR (def, 0), TIME_OPTION + 1) == 0)
1507 time_flag = 1;
1508 else if (strcmp (XSTR (def, 0), STATS_OPTION + 1) == 0)
1509 stats_flag = 1;
1510 else if (strcmp (XSTR (def, 0), V_OPTION + 1) == 0)
1511 v_flag = 1;
1512 else if (strcmp (XSTR (def, 0), W_OPTION + 1) == 0)
1513 w_flag = 1;
1514 else if (strcmp (XSTR (def, 0), NDFA_OPTION + 1) == 0)
1515 ndfa_flag = 1;
1516 else if (strcmp (XSTR (def, 0), PROGRESS_OPTION + 1) == 0)
1517 progress_flag = 1;
1518 else
1519 fatal ("invalid option `%s' in automata_option", XSTR (def, 0));
1522 /* Name in reservation to denote absence reservation. */
1523 #define NOTHING_NAME "nothing"
1525 /* The following string contains original reservation string being
1526 parsed. */
1527 static const char *reserv_str;
1529 /* Parse an element in STR. */
1530 static regexp_t
1531 gen_regexp_el (const char *str)
1533 regexp_t regexp;
1534 char *dstr;
1535 int len;
1537 if (*str == '(')
1539 len = strlen (str);
1540 if (str [len - 1] != ')')
1541 fatal ("garbage after ) in reservation `%s'", reserv_str);
1542 dstr = alloca (len - 1);
1543 memcpy (dstr, str + 1, len - 2);
1544 dstr [len-2] = '\0';
1545 regexp = gen_regexp_sequence (dstr);
1547 else if (strcmp (str, NOTHING_NAME) == 0)
1549 regexp = create_node (sizeof *regexp);
1550 regexp->mode = rm_nothing;
1552 else
1554 regexp = create_node (sizeof *regexp);
1555 regexp->mode = rm_unit;
1556 REGEXP_UNIT (regexp)->name = str;
1558 return regexp;
1561 /* Parse construction `repeat' in STR. */
1562 static regexp_t
1563 gen_regexp_repeat (const char *str)
1565 regexp_t regexp;
1566 regexp_t repeat;
1567 char **repeat_vect;
1568 int els_num;
1569 int i;
1571 repeat_vect = get_str_vect (str, &els_num, '*', TRUE);
1572 if (repeat_vect == NULL)
1573 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1574 if (els_num > 1)
1576 regexp = gen_regexp_el (repeat_vect [0]);
1577 for (i = 1; i < els_num; i++)
1579 repeat = create_node (sizeof (struct regexp));
1580 repeat->mode = rm_repeat;
1581 REGEXP_REPEAT (repeat)->regexp = regexp;
1582 REGEXP_REPEAT (repeat)->repeat_num = atoi (repeat_vect [i]);
1583 if (REGEXP_REPEAT (repeat)->repeat_num <= 1)
1584 fatal ("repetition `%s' <= 1 in reservation `%s'",
1585 str, reserv_str);
1586 regexp = repeat;
1588 return regexp;
1590 else
1591 return gen_regexp_el (str);
1594 /* Parse reservation STR which possibly contains separator '+'. */
1595 static regexp_t
1596 gen_regexp_allof (const char *str)
1598 regexp_t allof;
1599 char **allof_vect;
1600 int els_num;
1601 int i;
1603 allof_vect = get_str_vect (str, &els_num, '+', TRUE);
1604 if (allof_vect == NULL)
1605 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1606 if (els_num > 1)
1608 allof = create_node (sizeof (struct regexp)
1609 + sizeof (regexp_t) * (els_num - 1));
1610 allof->mode = rm_allof;
1611 REGEXP_ALLOF (allof)->regexps_num = els_num;
1612 for (i = 0; i < els_num; i++)
1613 REGEXP_ALLOF (allof)->regexps [i] = gen_regexp_repeat (allof_vect [i]);
1614 return allof;
1616 else
1617 return gen_regexp_repeat (str);
1620 /* Parse reservation STR which possibly contains separator '|'. */
1621 static regexp_t
1622 gen_regexp_oneof (const char *str)
1624 regexp_t oneof;
1625 char **oneof_vect;
1626 int els_num;
1627 int i;
1629 oneof_vect = get_str_vect (str, &els_num, '|', TRUE);
1630 if (oneof_vect == NULL)
1631 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1632 if (els_num > 1)
1634 oneof = create_node (sizeof (struct regexp)
1635 + sizeof (regexp_t) * (els_num - 1));
1636 oneof->mode = rm_oneof;
1637 REGEXP_ONEOF (oneof)->regexps_num = els_num;
1638 for (i = 0; i < els_num; i++)
1639 REGEXP_ONEOF (oneof)->regexps [i] = gen_regexp_allof (oneof_vect [i]);
1640 return oneof;
1642 else
1643 return gen_regexp_allof (str);
1646 /* Parse reservation STR which possibly contains separator ','. */
1647 static regexp_t
1648 gen_regexp_sequence (const char *str)
1650 regexp_t sequence;
1651 char **sequence_vect;
1652 int els_num;
1653 int i;
1655 sequence_vect = get_str_vect (str, &els_num, ',', TRUE);
1656 if (els_num > 1)
1658 sequence = create_node (sizeof (struct regexp)
1659 + sizeof (regexp_t) * (els_num - 1));
1660 sequence->mode = rm_sequence;
1661 REGEXP_SEQUENCE (sequence)->regexps_num = els_num;
1662 for (i = 0; i < els_num; i++)
1663 REGEXP_SEQUENCE (sequence)->regexps [i]
1664 = gen_regexp_oneof (sequence_vect [i]);
1665 return sequence;
1667 else
1668 return gen_regexp_oneof (str);
1671 /* Parse construction reservation STR. */
1672 static regexp_t
1673 gen_regexp (const char *str)
1675 reserv_str = str;
1676 return gen_regexp_sequence (str);;
1679 /* Process a DEFINE_RESERVATION.
1681 This gives information about a reservation of cpu units. We fill
1682 in a struct reserv_decl with information used later by
1683 `expand_automata'. */
1684 static void
1685 gen_reserv (rtx def)
1687 decl_t decl;
1689 decl = create_node (sizeof (struct decl));
1690 decl->mode = dm_reserv;
1691 decl->pos = 0;
1692 DECL_RESERV (decl)->name = check_name (XSTR (def, 0), decl->pos);
1693 DECL_RESERV (decl)->regexp = gen_regexp (XSTR (def, 1));
1694 VEC_safe_push (decl_t,heap, decls, decl);
1697 /* Process a DEFINE_INSN_RESERVATION.
1699 This gives information about the reservation of cpu units by an
1700 insn. We fill a struct insn_reserv_decl with information used
1701 later by `expand_automata'. */
1702 static void
1703 gen_insn_reserv (rtx def)
1705 decl_t decl;
1707 decl = create_node (sizeof (struct decl));
1708 decl->mode = dm_insn_reserv;
1709 decl->pos = 0;
1710 DECL_INSN_RESERV (decl)->name
1711 = check_name (XSTR (def, 0), decl->pos);
1712 DECL_INSN_RESERV (decl)->default_latency = XINT (def, 1);
1713 DECL_INSN_RESERV (decl)->condexp = XEXP (def, 2);
1714 DECL_INSN_RESERV (decl)->regexp = gen_regexp (XSTR (def, 3));
1715 VEC_safe_push (decl_t,heap, decls, decl);
1720 /* The function evaluates hash value (0..UINT_MAX) of string. */
1721 static unsigned
1722 string_hash (const char *string)
1724 unsigned result, i;
1726 for (result = i = 0;*string++ != '\0'; i++)
1727 result += ((unsigned char) *string << (i % CHAR_BIT));
1728 return result;
1733 /* This page contains abstract data `table of automaton declarations'.
1734 Elements of the table is nodes representing automaton declarations.
1735 Key of the table elements is name of given automaton. Remember
1736 that automaton names have own space. */
1738 /* The function evaluates hash value of an automaton declaration. The
1739 function is used by abstract data `hashtab'. The function returns
1740 hash value (0..UINT_MAX) of given automaton declaration. */
1741 static hashval_t
1742 automaton_decl_hash (const void *automaton_decl)
1744 const_decl_t const decl = (const_decl_t) automaton_decl;
1746 gcc_assert (decl->mode != dm_automaton
1747 || DECL_AUTOMATON (decl)->name);
1748 return string_hash (DECL_AUTOMATON (decl)->name);
1751 /* The function tests automaton declarations on equality of their
1752 keys. The function is used by abstract data `hashtab'. The
1753 function returns 1 if the declarations have the same key, 0
1754 otherwise. */
1755 static int
1756 automaton_decl_eq_p (const void* automaton_decl_1,
1757 const void* automaton_decl_2)
1759 const_decl_t const decl1 = (const_decl_t) automaton_decl_1;
1760 const_decl_t const decl2 = (const_decl_t) automaton_decl_2;
1762 gcc_assert (decl1->mode == dm_automaton
1763 && DECL_AUTOMATON (decl1)->name
1764 && decl2->mode == dm_automaton
1765 && DECL_AUTOMATON (decl2)->name);
1766 return strcmp (DECL_AUTOMATON (decl1)->name,
1767 DECL_AUTOMATON (decl2)->name) == 0;
1770 /* The automaton declaration table itself is represented by the
1771 following variable. */
1772 static htab_t automaton_decl_table;
1774 /* The function inserts automaton declaration into the table. The
1775 function does nothing if an automaton declaration with the same key
1776 exists already in the table. The function returns automaton
1777 declaration node in the table with the same key as given automaton
1778 declaration node. */
1779 static decl_t
1780 insert_automaton_decl (decl_t automaton_decl)
1782 void **entry_ptr;
1784 entry_ptr = htab_find_slot (automaton_decl_table, automaton_decl, 1);
1785 if (*entry_ptr == NULL)
1786 *entry_ptr = (void *) automaton_decl;
1787 return (decl_t) *entry_ptr;
1790 /* The following variable value is node representing automaton
1791 declaration. The node used for searching automaton declaration
1792 with given name. */
1793 static struct decl work_automaton_decl;
1795 /* The function searches for automaton declaration in the table with
1796 the same key as node representing name of the automaton
1797 declaration. The function returns node found in the table, NULL if
1798 such node does not exist in the table. */
1799 static decl_t
1800 find_automaton_decl (const char *name)
1802 void *entry;
1804 work_automaton_decl.mode = dm_automaton;
1805 DECL_AUTOMATON (&work_automaton_decl)->name = name;
1806 entry = htab_find (automaton_decl_table, &work_automaton_decl);
1807 return (decl_t) entry;
1810 /* The function creates empty automaton declaration table and node
1811 representing automaton declaration and used for searching automaton
1812 declaration with given name. The function must be called only once
1813 before any work with the automaton declaration table. */
1814 static void
1815 initiate_automaton_decl_table (void)
1817 work_automaton_decl.mode = dm_automaton;
1818 automaton_decl_table = htab_create (10, automaton_decl_hash,
1819 automaton_decl_eq_p, (htab_del) 0);
1822 /* The function deletes the automaton declaration table. Only call of
1823 function `initiate_automaton_decl_table' is possible immediately
1824 after this function call. */
1825 static void
1826 finish_automaton_decl_table (void)
1828 htab_delete (automaton_decl_table);
1833 /* This page contains abstract data `table of insn declarations'.
1834 Elements of the table is nodes representing insn declarations. Key
1835 of the table elements is name of given insn (in corresponding
1836 define_insn_reservation). Remember that insn names have own
1837 space. */
1839 /* The function evaluates hash value of an insn declaration. The
1840 function is used by abstract data `hashtab'. The function returns
1841 hash value (0..UINT_MAX) of given insn declaration. */
1842 static hashval_t
1843 insn_decl_hash (const void *insn_decl)
1845 const_decl_t const decl = (const_decl_t) insn_decl;
1847 gcc_assert (decl->mode == dm_insn_reserv
1848 && DECL_INSN_RESERV (decl)->name);
1849 return string_hash (DECL_INSN_RESERV (decl)->name);
1852 /* The function tests insn declarations on equality of their keys.
1853 The function is used by abstract data `hashtab'. The function
1854 returns 1 if declarations have the same key, 0 otherwise. */
1855 static int
1856 insn_decl_eq_p (const void *insn_decl_1, const void *insn_decl_2)
1858 const_decl_t const decl1 = (const_decl_t) insn_decl_1;
1859 const_decl_t const decl2 = (const_decl_t) insn_decl_2;
1861 gcc_assert (decl1->mode == dm_insn_reserv
1862 && DECL_INSN_RESERV (decl1)->name
1863 && decl2->mode == dm_insn_reserv
1864 && DECL_INSN_RESERV (decl2)->name);
1865 return strcmp (DECL_INSN_RESERV (decl1)->name,
1866 DECL_INSN_RESERV (decl2)->name) == 0;
1869 /* The insn declaration table itself is represented by the following
1870 variable. The table does not contain insn reservation
1871 declarations. */
1872 static htab_t insn_decl_table;
1874 /* The function inserts insn declaration into the table. The function
1875 does nothing if an insn declaration with the same key exists
1876 already in the table. The function returns insn declaration node
1877 in the table with the same key as given insn declaration node. */
1878 static decl_t
1879 insert_insn_decl (decl_t insn_decl)
1881 void **entry_ptr;
1883 entry_ptr = htab_find_slot (insn_decl_table, insn_decl, 1);
1884 if (*entry_ptr == NULL)
1885 *entry_ptr = (void *) insn_decl;
1886 return (decl_t) *entry_ptr;
1889 /* The following variable value is node representing insn reservation
1890 declaration. The node used for searching insn reservation
1891 declaration with given name. */
1892 static struct decl work_insn_decl;
1894 /* The function searches for insn reservation declaration in the table
1895 with the same key as node representing name of the insn reservation
1896 declaration. The function returns node found in the table, NULL if
1897 such node does not exist in the table. */
1898 static decl_t
1899 find_insn_decl (const char *name)
1901 void *entry;
1903 work_insn_decl.mode = dm_insn_reserv;
1904 DECL_INSN_RESERV (&work_insn_decl)->name = name;
1905 entry = htab_find (insn_decl_table, &work_insn_decl);
1906 return (decl_t) entry;
1909 /* The function creates empty insn declaration table and node
1910 representing insn declaration and used for searching insn
1911 declaration with given name. The function must be called only once
1912 before any work with the insn declaration table. */
1913 static void
1914 initiate_insn_decl_table (void)
1916 work_insn_decl.mode = dm_insn_reserv;
1917 insn_decl_table = htab_create (10, insn_decl_hash, insn_decl_eq_p,
1918 (htab_del) 0);
1921 /* The function deletes the insn declaration table. Only call of
1922 function `initiate_insn_decl_table' is possible immediately after
1923 this function call. */
1924 static void
1925 finish_insn_decl_table (void)
1927 htab_delete (insn_decl_table);
1932 /* This page contains abstract data `table of declarations'. Elements
1933 of the table is nodes representing declarations (of units and
1934 reservations). Key of the table elements is names of given
1935 declarations. */
1937 /* The function evaluates hash value of a declaration. The function
1938 is used by abstract data `hashtab'. The function returns hash
1939 value (0..UINT_MAX) of given declaration. */
1940 static hashval_t
1941 decl_hash (const void *decl)
1943 const_decl_t const d = (const_decl_t) decl;
1945 gcc_assert ((d->mode == dm_unit && DECL_UNIT (d)->name)
1946 || (d->mode == dm_reserv && DECL_RESERV (d)->name));
1947 return string_hash (d->mode == dm_unit
1948 ? DECL_UNIT (d)->name : DECL_RESERV (d)->name);
1951 /* The function tests declarations on equality of their keys. The
1952 function is used by abstract data 'hashtab'. The function
1953 returns 1 if the declarations have the same key, 0 otherwise. */
1954 static int
1955 decl_eq_p (const void *decl_1, const void *decl_2)
1957 const_decl_t const d1 = (const_decl_t) decl_1;
1958 const_decl_t const d2 = (const_decl_t) decl_2;
1960 gcc_assert ((d1->mode == dm_unit && DECL_UNIT (d1)->name)
1961 || (d1->mode == dm_reserv && DECL_RESERV (d1)->name));
1962 gcc_assert ((d2->mode == dm_unit && DECL_UNIT (d2)->name)
1963 || (d2->mode == dm_reserv && DECL_RESERV (d2)->name));
1964 return strcmp ((d1->mode == dm_unit
1965 ? DECL_UNIT (d1)->name : DECL_RESERV (d1)->name),
1966 (d2->mode == dm_unit
1967 ? DECL_UNIT (d2)->name : DECL_RESERV (d2)->name)) == 0;
1970 /* The declaration table itself is represented by the following
1971 variable. */
1972 static htab_t decl_table;
1974 /* The function inserts declaration into the table. The function does
1975 nothing if a declaration with the same key exists already in the
1976 table. The function returns declaration node in the table with the
1977 same key as given declaration node. */
1979 static decl_t
1980 insert_decl (decl_t decl)
1982 void **entry_ptr;
1984 entry_ptr = htab_find_slot (decl_table, decl, 1);
1985 if (*entry_ptr == NULL)
1986 *entry_ptr = (void *) decl;
1987 return (decl_t) *entry_ptr;
1990 /* The following variable value is node representing declaration. The
1991 node used for searching declaration with given name. */
1992 static struct decl work_decl;
1994 /* The function searches for declaration in the table with the same
1995 key as node representing name of the declaration. The function
1996 returns node found in the table, NULL if such node does not exist
1997 in the table. */
1998 static decl_t
1999 find_decl (const char *name)
2001 void *entry;
2003 work_decl.mode = dm_unit;
2004 DECL_UNIT (&work_decl)->name = name;
2005 entry = htab_find (decl_table, &work_decl);
2006 return (decl_t) entry;
2009 /* The function creates empty declaration table and node representing
2010 declaration and used for searching declaration with given name.
2011 The function must be called only once before any work with the
2012 declaration table. */
2013 static void
2014 initiate_decl_table (void)
2016 work_decl.mode = dm_unit;
2017 decl_table = htab_create (10, decl_hash, decl_eq_p, (htab_del) 0);
2020 /* The function deletes the declaration table. Only call of function
2021 `initiate_declaration_table' is possible immediately after this
2022 function call. */
2023 static void
2024 finish_decl_table (void)
2026 htab_delete (decl_table);
2031 /* This page contains checker of pipeline hazard description. */
2033 /* Checking NAMES in an exclusion clause vector and returning formed
2034 unit_set_el_list. */
2035 static unit_set_el_t
2036 process_excls (char **names, int num, pos_t excl_pos ATTRIBUTE_UNUSED)
2038 unit_set_el_t el_list;
2039 unit_set_el_t last_el;
2040 unit_set_el_t new_el;
2041 decl_t decl_in_table;
2042 int i;
2044 el_list = NULL;
2045 last_el = NULL;
2046 for (i = 0; i < num; i++)
2048 decl_in_table = find_decl (names [i]);
2049 if (decl_in_table == NULL)
2050 error ("unit `%s' in exclusion is not declared", names [i]);
2051 else if (decl_in_table->mode != dm_unit)
2052 error ("`%s' in exclusion is not unit", names [i]);
2053 else
2055 new_el = create_node (sizeof (struct unit_set_el));
2056 new_el->unit_decl = DECL_UNIT (decl_in_table);
2057 new_el->next_unit_set_el = NULL;
2058 if (last_el == NULL)
2059 el_list = last_el = new_el;
2060 else
2062 last_el->next_unit_set_el = new_el;
2063 last_el = last_el->next_unit_set_el;
2067 return el_list;
2070 /* The function adds each element from SOURCE_LIST to the exclusion
2071 list of the each element from DEST_LIST. Checking situation "unit
2072 excludes itself". */
2073 static void
2074 add_excls (unit_set_el_t dest_list, unit_set_el_t source_list,
2075 pos_t excl_pos ATTRIBUTE_UNUSED)
2077 unit_set_el_t dst;
2078 unit_set_el_t src;
2079 unit_set_el_t curr_el;
2080 unit_set_el_t prev_el;
2081 unit_set_el_t copy;
2083 for (dst = dest_list; dst != NULL; dst = dst->next_unit_set_el)
2084 for (src = source_list; src != NULL; src = src->next_unit_set_el)
2086 if (dst->unit_decl == src->unit_decl)
2088 error ("unit `%s' excludes itself", src->unit_decl->name);
2089 continue;
2091 if (dst->unit_decl->automaton_name != NULL
2092 && src->unit_decl->automaton_name != NULL
2093 && strcmp (dst->unit_decl->automaton_name,
2094 src->unit_decl->automaton_name) != 0)
2096 error ("units `%s' and `%s' in exclusion set belong to different automata",
2097 src->unit_decl->name, dst->unit_decl->name);
2098 continue;
2100 for (curr_el = dst->unit_decl->excl_list, prev_el = NULL;
2101 curr_el != NULL;
2102 prev_el = curr_el, curr_el = curr_el->next_unit_set_el)
2103 if (curr_el->unit_decl == src->unit_decl)
2104 break;
2105 if (curr_el == NULL)
2107 /* Element not found - insert. */
2108 copy = copy_node (src, sizeof (*src));
2109 copy->next_unit_set_el = NULL;
2110 if (prev_el == NULL)
2111 dst->unit_decl->excl_list = copy;
2112 else
2113 prev_el->next_unit_set_el = copy;
2118 /* Checking NAMES in presence/absence clause and returning the
2119 formed unit_set_el_list. The function is called only after
2120 processing all exclusion sets. */
2121 static unit_set_el_t
2122 process_presence_absence_names (char **names, int num,
2123 pos_t req_pos ATTRIBUTE_UNUSED,
2124 int presence_p, int final_p)
2126 unit_set_el_t el_list;
2127 unit_set_el_t last_el;
2128 unit_set_el_t new_el;
2129 decl_t decl_in_table;
2130 int i;
2132 el_list = NULL;
2133 last_el = NULL;
2134 for (i = 0; i < num; i++)
2136 decl_in_table = find_decl (names [i]);
2137 if (decl_in_table == NULL)
2138 error ((presence_p
2139 ? (final_p
2140 ? "unit `%s' in final presence set is not declared"
2141 : "unit `%s' in presence set is not declared")
2142 : (final_p
2143 ? "unit `%s' in final absence set is not declared"
2144 : "unit `%s' in absence set is not declared")), names [i]);
2145 else if (decl_in_table->mode != dm_unit)
2146 error ((presence_p
2147 ? (final_p
2148 ? "`%s' in final presence set is not unit"
2149 : "`%s' in presence set is not unit")
2150 : (final_p
2151 ? "`%s' in final absence set is not unit"
2152 : "`%s' in absence set is not unit")), names [i]);
2153 else
2155 new_el = create_node (sizeof (struct unit_set_el));
2156 new_el->unit_decl = DECL_UNIT (decl_in_table);
2157 new_el->next_unit_set_el = NULL;
2158 if (last_el == NULL)
2159 el_list = last_el = new_el;
2160 else
2162 last_el->next_unit_set_el = new_el;
2163 last_el = last_el->next_unit_set_el;
2167 return el_list;
2170 /* Checking NAMES in patterns of a presence/absence clause and
2171 returning the formed pattern_set_el_list. The function is called
2172 only after processing all exclusion sets. */
2173 static pattern_set_el_t
2174 process_presence_absence_patterns (char ***patterns, int num,
2175 pos_t req_pos ATTRIBUTE_UNUSED,
2176 int presence_p, int final_p)
2178 pattern_set_el_t el_list;
2179 pattern_set_el_t last_el;
2180 pattern_set_el_t new_el;
2181 decl_t decl_in_table;
2182 int i, j;
2184 el_list = NULL;
2185 last_el = NULL;
2186 for (i = 0; i < num; i++)
2188 for (j = 0; patterns [i] [j] != NULL; j++)
2190 new_el = create_node (sizeof (struct pattern_set_el)
2191 + sizeof (struct unit_decl *) * j);
2192 new_el->unit_decls
2193 = (struct unit_decl **) ((char *) new_el
2194 + sizeof (struct pattern_set_el));
2195 new_el->next_pattern_set_el = NULL;
2196 if (last_el == NULL)
2197 el_list = last_el = new_el;
2198 else
2200 last_el->next_pattern_set_el = new_el;
2201 last_el = last_el->next_pattern_set_el;
2203 new_el->units_num = 0;
2204 for (j = 0; patterns [i] [j] != NULL; j++)
2206 decl_in_table = find_decl (patterns [i] [j]);
2207 if (decl_in_table == NULL)
2208 error ((presence_p
2209 ? (final_p
2210 ? "unit `%s' in final presence set is not declared"
2211 : "unit `%s' in presence set is not declared")
2212 : (final_p
2213 ? "unit `%s' in final absence set is not declared"
2214 : "unit `%s' in absence set is not declared")),
2215 patterns [i] [j]);
2216 else if (decl_in_table->mode != dm_unit)
2217 error ((presence_p
2218 ? (final_p
2219 ? "`%s' in final presence set is not unit"
2220 : "`%s' in presence set is not unit")
2221 : (final_p
2222 ? "`%s' in final absence set is not unit"
2223 : "`%s' in absence set is not unit")),
2224 patterns [i] [j]);
2225 else
2227 new_el->unit_decls [new_el->units_num]
2228 = DECL_UNIT (decl_in_table);
2229 new_el->units_num++;
2233 return el_list;
2236 /* The function adds each element from PATTERN_LIST to presence (if
2237 PRESENCE_P) or absence list of the each element from DEST_LIST.
2238 Checking situations "unit requires own absence", and "unit excludes
2239 and requires presence of ...", "unit requires absence and presence
2240 of ...", "units in (final) presence set belong to different
2241 automata", and "units in (final) absence set belong to different
2242 automata". Remember that we process absence sets only after all
2243 presence sets. */
2244 static void
2245 add_presence_absence (unit_set_el_t dest_list,
2246 pattern_set_el_t pattern_list,
2247 pos_t req_pos ATTRIBUTE_UNUSED,
2248 int presence_p, int final_p)
2250 unit_set_el_t dst;
2251 pattern_set_el_t pat;
2252 struct unit_decl *unit;
2253 unit_set_el_t curr_excl_el;
2254 pattern_set_el_t curr_pat_el;
2255 pattern_set_el_t prev_el;
2256 pattern_set_el_t copy;
2257 int i;
2258 int no_error_flag;
2260 for (dst = dest_list; dst != NULL; dst = dst->next_unit_set_el)
2261 for (pat = pattern_list; pat != NULL; pat = pat->next_pattern_set_el)
2263 for (i = 0; i < pat->units_num; i++)
2265 unit = pat->unit_decls [i];
2266 if (dst->unit_decl == unit && pat->units_num == 1 && !presence_p)
2268 error ("unit `%s' requires own absence", unit->name);
2269 continue;
2271 if (dst->unit_decl->automaton_name != NULL
2272 && unit->automaton_name != NULL
2273 && strcmp (dst->unit_decl->automaton_name,
2274 unit->automaton_name) != 0)
2276 error ((presence_p
2277 ? (final_p
2278 ? "units `%s' and `%s' in final presence set belong to different automata"
2279 : "units `%s' and `%s' in presence set belong to different automata")
2280 : (final_p
2281 ? "units `%s' and `%s' in final absence set belong to different automata"
2282 : "units `%s' and `%s' in absence set belong to different automata")),
2283 unit->name, dst->unit_decl->name);
2284 continue;
2286 no_error_flag = 1;
2287 if (presence_p)
2288 for (curr_excl_el = dst->unit_decl->excl_list;
2289 curr_excl_el != NULL;
2290 curr_excl_el = curr_excl_el->next_unit_set_el)
2292 if (unit == curr_excl_el->unit_decl && pat->units_num == 1)
2294 if (!w_flag)
2296 error ("unit `%s' excludes and requires presence of `%s'",
2297 dst->unit_decl->name, unit->name);
2298 no_error_flag = 0;
2300 else
2301 warning
2302 (0, "unit `%s' excludes and requires presence of `%s'",
2303 dst->unit_decl->name, unit->name);
2306 else if (pat->units_num == 1)
2307 for (curr_pat_el = dst->unit_decl->presence_list;
2308 curr_pat_el != NULL;
2309 curr_pat_el = curr_pat_el->next_pattern_set_el)
2310 if (curr_pat_el->units_num == 1
2311 && unit == curr_pat_el->unit_decls [0])
2313 if (!w_flag)
2315 error
2316 ("unit `%s' requires absence and presence of `%s'",
2317 dst->unit_decl->name, unit->name);
2318 no_error_flag = 0;
2320 else
2321 warning
2322 (0, "unit `%s' requires absence and presence of `%s'",
2323 dst->unit_decl->name, unit->name);
2325 if (no_error_flag)
2327 for (prev_el = (presence_p
2328 ? (final_p
2329 ? dst->unit_decl->final_presence_list
2330 : dst->unit_decl->final_presence_list)
2331 : (final_p
2332 ? dst->unit_decl->final_absence_list
2333 : dst->unit_decl->absence_list));
2334 prev_el != NULL && prev_el->next_pattern_set_el != NULL;
2335 prev_el = prev_el->next_pattern_set_el)
2337 copy = copy_node (pat, sizeof (*pat));
2338 copy->next_pattern_set_el = NULL;
2339 if (prev_el == NULL)
2341 if (presence_p)
2343 if (final_p)
2344 dst->unit_decl->final_presence_list = copy;
2345 else
2346 dst->unit_decl->presence_list = copy;
2348 else if (final_p)
2349 dst->unit_decl->final_absence_list = copy;
2350 else
2351 dst->unit_decl->absence_list = copy;
2353 else
2354 prev_el->next_pattern_set_el = copy;
2361 /* The function searches for bypass with given IN_INSN_RESERV in given
2362 BYPASS_LIST. */
2363 static struct bypass_decl *
2364 find_bypass (struct bypass_decl *bypass_list,
2365 struct insn_reserv_decl *in_insn_reserv)
2367 struct bypass_decl *bypass;
2369 for (bypass = bypass_list; bypass != NULL; bypass = bypass->next)
2370 if (bypass->in_insn_reserv == in_insn_reserv)
2371 break;
2372 return bypass;
2375 /* The function processes pipeline description declarations, checks
2376 their correctness, and forms exclusion/presence/absence sets. */
2377 static void
2378 process_decls (void)
2380 decl_t decl;
2381 decl_t automaton_decl;
2382 decl_t decl_in_table;
2383 decl_t out_insn_reserv;
2384 decl_t in_insn_reserv;
2385 struct bypass_decl *bypass;
2386 int automaton_presence;
2387 int i;
2389 /* Checking repeated automata declarations. */
2390 automaton_presence = 0;
2391 for (i = 0; i < description->decls_num; i++)
2393 decl = description->decls [i];
2394 if (decl->mode == dm_automaton)
2396 automaton_presence = 1;
2397 decl_in_table = insert_automaton_decl (decl);
2398 if (decl_in_table != decl)
2400 if (!w_flag)
2401 error ("repeated declaration of automaton `%s'",
2402 DECL_AUTOMATON (decl)->name);
2403 else
2404 warning (0, "repeated declaration of automaton `%s'",
2405 DECL_AUTOMATON (decl)->name);
2409 /* Checking undeclared automata, repeated declarations (except for
2410 automata) and correctness of their attributes (insn latency times
2411 etc.). */
2412 for (i = 0; i < description->decls_num; i++)
2414 decl = description->decls [i];
2415 if (decl->mode == dm_insn_reserv)
2417 if (DECL_INSN_RESERV (decl)->default_latency < 0)
2418 error ("define_insn_reservation `%s' has negative latency time",
2419 DECL_INSN_RESERV (decl)->name);
2420 DECL_INSN_RESERV (decl)->insn_num = description->insns_num;
2421 description->insns_num++;
2422 decl_in_table = insert_insn_decl (decl);
2423 if (decl_in_table != decl)
2424 error ("`%s' is already used as insn reservation name",
2425 DECL_INSN_RESERV (decl)->name);
2427 else if (decl->mode == dm_bypass)
2429 if (DECL_BYPASS (decl)->latency < 0)
2430 error ("define_bypass `%s - %s' has negative latency time",
2431 DECL_BYPASS (decl)->out_insn_name,
2432 DECL_BYPASS (decl)->in_insn_name);
2434 else if (decl->mode == dm_unit || decl->mode == dm_reserv)
2436 if (decl->mode == dm_unit)
2438 DECL_UNIT (decl)->automaton_decl = NULL;
2439 if (DECL_UNIT (decl)->automaton_name != NULL)
2441 automaton_decl
2442 = find_automaton_decl (DECL_UNIT (decl)->automaton_name);
2443 if (automaton_decl == NULL)
2444 error ("automaton `%s' is not declared",
2445 DECL_UNIT (decl)->automaton_name);
2446 else
2448 DECL_AUTOMATON (automaton_decl)->automaton_is_used = 1;
2449 DECL_UNIT (decl)->automaton_decl
2450 = DECL_AUTOMATON (automaton_decl);
2453 else if (automaton_presence)
2454 error ("define_unit `%s' without automaton when one defined",
2455 DECL_UNIT (decl)->name);
2456 DECL_UNIT (decl)->unit_num = description->units_num;
2457 description->units_num++;
2458 if (strcmp (DECL_UNIT (decl)->name, NOTHING_NAME) == 0)
2460 error ("`%s' is declared as cpu unit", NOTHING_NAME);
2461 continue;
2463 decl_in_table = find_decl (DECL_UNIT (decl)->name);
2465 else
2467 if (strcmp (DECL_RESERV (decl)->name, NOTHING_NAME) == 0)
2469 error ("`%s' is declared as cpu reservation", NOTHING_NAME);
2470 continue;
2472 decl_in_table = find_decl (DECL_RESERV (decl)->name);
2474 if (decl_in_table == NULL)
2475 decl_in_table = insert_decl (decl);
2476 else
2478 if (decl->mode == dm_unit)
2479 error ("repeated declaration of unit `%s'",
2480 DECL_UNIT (decl)->name);
2481 else
2482 error ("repeated declaration of reservation `%s'",
2483 DECL_RESERV (decl)->name);
2487 /* Check bypasses and form list of bypasses for each (output)
2488 insn. */
2489 for (i = 0; i < description->decls_num; i++)
2491 decl = description->decls [i];
2492 if (decl->mode == dm_bypass)
2494 out_insn_reserv = find_insn_decl (DECL_BYPASS (decl)->out_insn_name);
2495 in_insn_reserv = find_insn_decl (DECL_BYPASS (decl)->in_insn_name);
2496 if (out_insn_reserv == NULL)
2497 error ("there is no insn reservation `%s'",
2498 DECL_BYPASS (decl)->out_insn_name);
2499 else if (in_insn_reserv == NULL)
2500 error ("there is no insn reservation `%s'",
2501 DECL_BYPASS (decl)->in_insn_name);
2502 else
2504 DECL_BYPASS (decl)->out_insn_reserv
2505 = DECL_INSN_RESERV (out_insn_reserv);
2506 DECL_BYPASS (decl)->in_insn_reserv
2507 = DECL_INSN_RESERV (in_insn_reserv);
2508 bypass
2509 = find_bypass (DECL_INSN_RESERV (out_insn_reserv)->bypass_list,
2510 DECL_BYPASS (decl)->in_insn_reserv);
2511 if (bypass != NULL)
2513 if (DECL_BYPASS (decl)->latency == bypass->latency)
2515 if (!w_flag)
2516 error
2517 ("the same bypass `%s - %s' is already defined",
2518 DECL_BYPASS (decl)->out_insn_name,
2519 DECL_BYPASS (decl)->in_insn_name);
2520 else
2521 warning
2522 (0, "the same bypass `%s - %s' is already defined",
2523 DECL_BYPASS (decl)->out_insn_name,
2524 DECL_BYPASS (decl)->in_insn_name);
2526 else
2527 error ("bypass `%s - %s' is already defined",
2528 DECL_BYPASS (decl)->out_insn_name,
2529 DECL_BYPASS (decl)->in_insn_name);
2531 else
2533 DECL_BYPASS (decl)->next
2534 = DECL_INSN_RESERV (out_insn_reserv)->bypass_list;
2535 DECL_INSN_RESERV (out_insn_reserv)->bypass_list
2536 = DECL_BYPASS (decl);
2542 /* Check exclusion set declarations and form exclusion sets. */
2543 for (i = 0; i < description->decls_num; i++)
2545 decl = description->decls [i];
2546 if (decl->mode == dm_excl)
2548 unit_set_el_t unit_set_el_list;
2549 unit_set_el_t unit_set_el_list_2;
2551 unit_set_el_list
2552 = process_excls (DECL_EXCL (decl)->names,
2553 DECL_EXCL (decl)->first_list_length, decl->pos);
2554 unit_set_el_list_2
2555 = process_excls (&DECL_EXCL (decl)->names
2556 [DECL_EXCL (decl)->first_list_length],
2557 DECL_EXCL (decl)->all_names_num
2558 - DECL_EXCL (decl)->first_list_length,
2559 decl->pos);
2560 add_excls (unit_set_el_list, unit_set_el_list_2, decl->pos);
2561 add_excls (unit_set_el_list_2, unit_set_el_list, decl->pos);
2565 /* Check presence set declarations and form presence sets. */
2566 for (i = 0; i < description->decls_num; i++)
2568 decl = description->decls [i];
2569 if (decl->mode == dm_presence)
2571 unit_set_el_t unit_set_el_list;
2572 pattern_set_el_t pattern_set_el_list;
2574 unit_set_el_list
2575 = process_presence_absence_names
2576 (DECL_PRESENCE (decl)->names, DECL_PRESENCE (decl)->names_num,
2577 decl->pos, TRUE, DECL_PRESENCE (decl)->final_p);
2578 pattern_set_el_list
2579 = process_presence_absence_patterns
2580 (DECL_PRESENCE (decl)->patterns,
2581 DECL_PRESENCE (decl)->patterns_num,
2582 decl->pos, TRUE, DECL_PRESENCE (decl)->final_p);
2583 add_presence_absence (unit_set_el_list, pattern_set_el_list,
2584 decl->pos, TRUE,
2585 DECL_PRESENCE (decl)->final_p);
2589 /* Check absence set declarations and form absence sets. */
2590 for (i = 0; i < description->decls_num; i++)
2592 decl = description->decls [i];
2593 if (decl->mode == dm_absence)
2595 unit_set_el_t unit_set_el_list;
2596 pattern_set_el_t pattern_set_el_list;
2598 unit_set_el_list
2599 = process_presence_absence_names
2600 (DECL_ABSENCE (decl)->names, DECL_ABSENCE (decl)->names_num,
2601 decl->pos, FALSE, DECL_ABSENCE (decl)->final_p);
2602 pattern_set_el_list
2603 = process_presence_absence_patterns
2604 (DECL_ABSENCE (decl)->patterns,
2605 DECL_ABSENCE (decl)->patterns_num,
2606 decl->pos, FALSE, DECL_ABSENCE (decl)->final_p);
2607 add_presence_absence (unit_set_el_list, pattern_set_el_list,
2608 decl->pos, FALSE,
2609 DECL_ABSENCE (decl)->final_p);
2614 /* The following function checks that declared automaton is used. If
2615 the automaton is not used, the function fixes error/warning. The
2616 following function must be called only after `process_decls'. */
2617 static void
2618 check_automaton_usage (void)
2620 decl_t decl;
2621 int i;
2623 for (i = 0; i < description->decls_num; i++)
2625 decl = description->decls [i];
2626 if (decl->mode == dm_automaton
2627 && !DECL_AUTOMATON (decl)->automaton_is_used)
2629 if (!w_flag)
2630 error ("automaton `%s' is not used", DECL_AUTOMATON (decl)->name);
2631 else
2632 warning (0, "automaton `%s' is not used",
2633 DECL_AUTOMATON (decl)->name);
2638 /* The following recursive function processes all regexp in order to
2639 fix usage of units or reservations and to fix errors of undeclared
2640 name. The function may change unit_regexp onto reserv_regexp.
2641 Remember that reserv_regexp does not exist before the function
2642 call. */
2643 static regexp_t
2644 process_regexp (regexp_t regexp)
2646 decl_t decl_in_table;
2647 regexp_t new_regexp;
2648 int i;
2650 switch (regexp->mode)
2652 case rm_unit:
2653 decl_in_table = find_decl (REGEXP_UNIT (regexp)->name);
2654 if (decl_in_table == NULL)
2655 error ("undeclared unit or reservation `%s'",
2656 REGEXP_UNIT (regexp)->name);
2657 else
2658 switch (decl_in_table->mode)
2660 case dm_unit:
2661 DECL_UNIT (decl_in_table)->unit_is_used = 1;
2662 REGEXP_UNIT (regexp)->unit_decl = DECL_UNIT (decl_in_table);
2663 break;
2665 case dm_reserv:
2666 DECL_RESERV (decl_in_table)->reserv_is_used = 1;
2667 new_regexp = create_node (sizeof (struct regexp));
2668 new_regexp->mode = rm_reserv;
2669 new_regexp->pos = regexp->pos;
2670 REGEXP_RESERV (new_regexp)->name = REGEXP_UNIT (regexp)->name;
2671 REGEXP_RESERV (new_regexp)->reserv_decl
2672 = DECL_RESERV (decl_in_table);
2673 regexp = new_regexp;
2674 break;
2676 default:
2677 gcc_unreachable ();
2679 break;
2680 case rm_sequence:
2681 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
2682 REGEXP_SEQUENCE (regexp)->regexps [i]
2683 = process_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
2684 break;
2685 case rm_allof:
2686 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
2687 REGEXP_ALLOF (regexp)->regexps [i]
2688 = process_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
2689 break;
2690 case rm_oneof:
2691 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
2692 REGEXP_ONEOF (regexp)->regexps [i]
2693 = process_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
2694 break;
2695 case rm_repeat:
2696 REGEXP_REPEAT (regexp)->regexp
2697 = process_regexp (REGEXP_REPEAT (regexp)->regexp);
2698 break;
2699 case rm_nothing:
2700 break;
2701 default:
2702 gcc_unreachable ();
2704 return regexp;
2707 /* The following function processes regexp of define_reservation and
2708 define_insn_reservation with the aid of function
2709 `process_regexp'. */
2710 static void
2711 process_regexp_decls (void)
2713 decl_t decl;
2714 int i;
2716 for (i = 0; i < description->decls_num; i++)
2718 decl = description->decls [i];
2719 if (decl->mode == dm_reserv)
2720 DECL_RESERV (decl)->regexp
2721 = process_regexp (DECL_RESERV (decl)->regexp);
2722 else if (decl->mode == dm_insn_reserv)
2723 DECL_INSN_RESERV (decl)->regexp
2724 = process_regexp (DECL_INSN_RESERV (decl)->regexp);
2728 /* The following function checks that declared unit is used. If the
2729 unit is not used, the function fixes errors/warnings. The
2730 following function must be called only after `process_decls',
2731 `process_regexp_decls'. */
2732 static void
2733 check_usage (void)
2735 decl_t decl;
2736 int i;
2738 for (i = 0; i < description->decls_num; i++)
2740 decl = description->decls [i];
2741 if (decl->mode == dm_unit && !DECL_UNIT (decl)->unit_is_used)
2743 if (!w_flag)
2744 error ("unit `%s' is not used", DECL_UNIT (decl)->name);
2745 else
2746 warning (0, "unit `%s' is not used", DECL_UNIT (decl)->name);
2748 else if (decl->mode == dm_reserv && !DECL_RESERV (decl)->reserv_is_used)
2750 if (!w_flag)
2751 error ("reservation `%s' is not used", DECL_RESERV (decl)->name);
2752 else
2753 warning (0, "reservation `%s' is not used", DECL_RESERV (decl)->name);
2758 /* The following variable value is number of reservation being
2759 processed on loop recognition. */
2760 static int curr_loop_pass_num;
2762 /* The following recursive function returns nonzero value if REGEXP
2763 contains given decl or reservations in given regexp refers for
2764 given decl. */
2765 static int
2766 loop_in_regexp (regexp_t regexp, decl_t start_decl)
2768 int i;
2770 if (regexp == NULL)
2771 return 0;
2772 switch (regexp->mode)
2774 case rm_unit:
2775 return 0;
2777 case rm_reserv:
2778 if (start_decl->mode == dm_reserv
2779 && REGEXP_RESERV (regexp)->reserv_decl == DECL_RESERV (start_decl))
2780 return 1;
2781 else if (REGEXP_RESERV (regexp)->reserv_decl->loop_pass_num
2782 == curr_loop_pass_num)
2783 /* declaration has been processed. */
2784 return 0;
2785 else
2787 REGEXP_RESERV (regexp)->reserv_decl->loop_pass_num
2788 = curr_loop_pass_num;
2789 return loop_in_regexp (REGEXP_RESERV (regexp)->reserv_decl->regexp,
2790 start_decl);
2793 case rm_sequence:
2794 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
2795 if (loop_in_regexp (REGEXP_SEQUENCE (regexp)->regexps [i], start_decl))
2796 return 1;
2797 return 0;
2799 case rm_allof:
2800 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
2801 if (loop_in_regexp (REGEXP_ALLOF (regexp)->regexps [i], start_decl))
2802 return 1;
2803 return 0;
2805 case rm_oneof:
2806 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
2807 if (loop_in_regexp (REGEXP_ONEOF (regexp)->regexps [i], start_decl))
2808 return 1;
2809 return 0;
2811 case rm_repeat:
2812 return loop_in_regexp (REGEXP_REPEAT (regexp)->regexp, start_decl);
2814 case rm_nothing:
2815 return 0;
2817 default:
2818 gcc_unreachable ();
2822 /* The following function fixes errors "cycle in definition ...". The
2823 function uses function `loop_in_regexp' for that. */
2824 static void
2825 check_loops_in_regexps (void)
2827 decl_t decl;
2828 int i;
2830 for (i = 0; i < description->decls_num; i++)
2832 decl = description->decls [i];
2833 if (decl->mode == dm_reserv)
2834 DECL_RESERV (decl)->loop_pass_num = 0;
2836 for (i = 0; i < description->decls_num; i++)
2838 decl = description->decls [i];
2839 curr_loop_pass_num = i;
2841 if (decl->mode == dm_reserv)
2843 DECL_RESERV (decl)->loop_pass_num = curr_loop_pass_num;
2844 if (loop_in_regexp (DECL_RESERV (decl)->regexp, decl))
2846 gcc_assert (DECL_RESERV (decl)->regexp);
2847 error ("cycle in definition of reservation `%s'",
2848 DECL_RESERV (decl)->name);
2854 /* The function recursively processes IR of reservation and defines
2855 max and min cycle for reservation of unit. */
2856 static void
2857 process_regexp_cycles (regexp_t regexp, int max_start_cycle,
2858 int min_start_cycle, int *max_finish_cycle,
2859 int *min_finish_cycle)
2861 int i;
2863 switch (regexp->mode)
2865 case rm_unit:
2866 if (REGEXP_UNIT (regexp)->unit_decl->max_occ_cycle_num < max_start_cycle)
2867 REGEXP_UNIT (regexp)->unit_decl->max_occ_cycle_num = max_start_cycle;
2868 if (REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num > min_start_cycle
2869 || REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num == -1)
2870 REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num = min_start_cycle;
2871 *max_finish_cycle = max_start_cycle;
2872 *min_finish_cycle = min_start_cycle;
2873 break;
2875 case rm_reserv:
2876 process_regexp_cycles (REGEXP_RESERV (regexp)->reserv_decl->regexp,
2877 max_start_cycle, min_start_cycle,
2878 max_finish_cycle, min_finish_cycle);
2879 break;
2881 case rm_repeat:
2882 for (i = 0; i < REGEXP_REPEAT (regexp)->repeat_num; i++)
2884 process_regexp_cycles (REGEXP_REPEAT (regexp)->regexp,
2885 max_start_cycle, min_start_cycle,
2886 max_finish_cycle, min_finish_cycle);
2887 max_start_cycle = *max_finish_cycle + 1;
2888 min_start_cycle = *min_finish_cycle + 1;
2890 break;
2892 case rm_sequence:
2893 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
2895 process_regexp_cycles (REGEXP_SEQUENCE (regexp)->regexps [i],
2896 max_start_cycle, min_start_cycle,
2897 max_finish_cycle, min_finish_cycle);
2898 max_start_cycle = *max_finish_cycle + 1;
2899 min_start_cycle = *min_finish_cycle + 1;
2901 break;
2903 case rm_allof:
2905 int max_cycle = 0;
2906 int min_cycle = 0;
2908 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
2910 process_regexp_cycles (REGEXP_ALLOF (regexp)->regexps [i],
2911 max_start_cycle, min_start_cycle,
2912 max_finish_cycle, min_finish_cycle);
2913 if (max_cycle < *max_finish_cycle)
2914 max_cycle = *max_finish_cycle;
2915 if (i == 0 || min_cycle > *min_finish_cycle)
2916 min_cycle = *min_finish_cycle;
2918 *max_finish_cycle = max_cycle;
2919 *min_finish_cycle = min_cycle;
2921 break;
2923 case rm_oneof:
2925 int max_cycle = 0;
2926 int min_cycle = 0;
2928 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
2930 process_regexp_cycles (REGEXP_ONEOF (regexp)->regexps [i],
2931 max_start_cycle, min_start_cycle,
2932 max_finish_cycle, min_finish_cycle);
2933 if (max_cycle < *max_finish_cycle)
2934 max_cycle = *max_finish_cycle;
2935 if (i == 0 || min_cycle > *min_finish_cycle)
2936 min_cycle = *min_finish_cycle;
2938 *max_finish_cycle = max_cycle;
2939 *min_finish_cycle = min_cycle;
2941 break;
2943 case rm_nothing:
2944 *max_finish_cycle = max_start_cycle;
2945 *min_finish_cycle = min_start_cycle;
2946 break;
2948 default:
2949 gcc_unreachable ();
2953 /* The following function is called only for correct program. The
2954 function defines max reservation of insns in cycles. */
2955 static void
2956 evaluate_max_reserv_cycles (void)
2958 int max_insn_cycles_num;
2959 int min_insn_cycles_num;
2960 decl_t decl;
2961 int i;
2963 description->max_insn_reserv_cycles = 0;
2964 for (i = 0; i < description->decls_num; i++)
2966 decl = description->decls [i];
2967 if (decl->mode == dm_insn_reserv)
2969 process_regexp_cycles (DECL_INSN_RESERV (decl)->regexp, 0, 0,
2970 &max_insn_cycles_num, &min_insn_cycles_num);
2971 if (description->max_insn_reserv_cycles < max_insn_cycles_num)
2972 description->max_insn_reserv_cycles = max_insn_cycles_num;
2975 description->max_insn_reserv_cycles++;
2978 /* The following function calls functions for checking all
2979 description. */
2980 static void
2981 check_all_description (void)
2983 process_decls ();
2984 check_automaton_usage ();
2985 process_regexp_decls ();
2986 check_usage ();
2987 check_loops_in_regexps ();
2988 if (!have_error)
2989 evaluate_max_reserv_cycles ();
2994 /* The page contains abstract data `ticker'. This data is used to
2995 report time of different phases of building automata. It is
2996 possibly to write a description for which automata will be built
2997 during several minutes even on fast machine. */
2999 /* The following function creates ticker and makes it active. */
3000 static ticker_t
3001 create_ticker (void)
3003 ticker_t ticker;
3005 ticker.modified_creation_time = get_run_time ();
3006 ticker.incremented_off_time = 0;
3007 return ticker;
3010 /* The following function switches off given ticker. */
3011 static void
3012 ticker_off (ticker_t *ticker)
3014 if (ticker->incremented_off_time == 0)
3015 ticker->incremented_off_time = get_run_time () + 1;
3018 /* The following function switches on given ticker. */
3019 static void
3020 ticker_on (ticker_t *ticker)
3022 if (ticker->incremented_off_time != 0)
3024 ticker->modified_creation_time
3025 += get_run_time () - ticker->incremented_off_time + 1;
3026 ticker->incremented_off_time = 0;
3030 /* The following function returns current time in milliseconds since
3031 the moment when given ticker was created. */
3032 static int
3033 active_time (ticker_t ticker)
3035 if (ticker.incremented_off_time != 0)
3036 return ticker.incremented_off_time - 1 - ticker.modified_creation_time;
3037 else
3038 return get_run_time () - ticker.modified_creation_time;
3041 /* The following function returns string representation of active time
3042 of given ticker. The result is string representation of seconds
3043 with accuracy of 1/100 second. Only result of the last call of the
3044 function exists. Therefore the following code is not correct
3046 printf ("parser time: %s\ngeneration time: %s\n",
3047 active_time_string (parser_ticker),
3048 active_time_string (generation_ticker));
3050 Correct code has to be the following
3052 printf ("parser time: %s\n", active_time_string (parser_ticker));
3053 printf ("generation time: %s\n",
3054 active_time_string (generation_ticker));
3057 static void
3058 print_active_time (FILE *f, ticker_t ticker)
3060 int msecs;
3062 msecs = active_time (ticker);
3063 fprintf (f, "%d.%06d", msecs / 1000000, msecs % 1000000);
3068 /* The following variable value is number of automaton which are
3069 really being created. This value is defined on the base of
3070 argument of option `-split'. If the variable has zero value the
3071 number of automata is defined by the constructions `%automaton'.
3072 This case occurs when option `-split' is absent or has zero
3073 argument. If constructions `define_automaton' is absent only one
3074 automaton is created. */
3075 static int automata_num;
3077 /* The following variable values are times of
3078 o transformation of regular expressions
3079 o building NDFA (DFA if !ndfa_flag)
3080 o NDFA -> DFA (simply the same automaton if !ndfa_flag)
3081 o DFA minimization
3082 o building insn equivalence classes
3083 o all previous ones
3084 o code output */
3085 static ticker_t transform_time;
3086 static ticker_t NDFA_time;
3087 static ticker_t NDFA_to_DFA_time;
3088 static ticker_t minimize_time;
3089 static ticker_t equiv_time;
3090 static ticker_t automaton_generation_time;
3091 static ticker_t output_time;
3093 /* The following variable values are times of
3094 all checking
3095 all generation
3096 all pipeline hazard translator work */
3097 static ticker_t check_time;
3098 static ticker_t generation_time;
3099 static ticker_t all_time;
3103 /* Pseudo insn decl which denotes advancing cycle. */
3104 static decl_t advance_cycle_insn_decl;
3105 static void
3106 add_advance_cycle_insn_decl (void)
3108 advance_cycle_insn_decl = create_node (sizeof (struct decl));
3109 advance_cycle_insn_decl->mode = dm_insn_reserv;
3110 advance_cycle_insn_decl->pos = no_pos;
3111 DECL_INSN_RESERV (advance_cycle_insn_decl)->regexp = NULL;
3112 DECL_INSN_RESERV (advance_cycle_insn_decl)->name = "$advance_cycle";
3113 DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num
3114 = description->insns_num;
3115 description->decls [description->decls_num] = advance_cycle_insn_decl;
3116 description->decls_num++;
3117 description->insns_num++;
3121 /* Abstract data `alternative states' which represents
3122 nondeterministic nature of the description (see comments for
3123 structures alt_state and state). */
3125 /* List of free states. */
3126 static alt_state_t first_free_alt_state;
3128 #ifndef NDEBUG
3129 /* The following variables is maximal number of allocated nodes
3130 alt_state. */
3131 static int allocated_alt_states_num = 0;
3132 #endif
3134 /* The following function returns free node alt_state. It may be new
3135 allocated node or node freed earlier. */
3136 static alt_state_t
3137 get_free_alt_state (void)
3139 alt_state_t result;
3141 if (first_free_alt_state != NULL)
3143 result = first_free_alt_state;
3144 first_free_alt_state = first_free_alt_state->next_alt_state;
3146 else
3148 #ifndef NDEBUG
3149 allocated_alt_states_num++;
3150 #endif
3151 result = create_node (sizeof (struct alt_state));
3153 result->state = NULL;
3154 result->next_alt_state = NULL;
3155 result->next_sorted_alt_state = NULL;
3156 return result;
3159 /* The function frees node ALT_STATE. */
3160 static void
3161 free_alt_state (alt_state_t alt_state)
3163 if (alt_state == NULL)
3164 return;
3165 alt_state->next_alt_state = first_free_alt_state;
3166 first_free_alt_state = alt_state;
3169 /* The function frees list started with node ALT_STATE_LIST. */
3170 static void
3171 free_alt_states (alt_state_t alt_states_list)
3173 alt_state_t curr_alt_state;
3174 alt_state_t next_alt_state;
3176 for (curr_alt_state = alt_states_list;
3177 curr_alt_state != NULL;
3178 curr_alt_state = next_alt_state)
3180 next_alt_state = curr_alt_state->next_alt_state;
3181 free_alt_state (curr_alt_state);
3185 /* The function compares unique numbers of alt states. */
3186 static int
3187 alt_state_cmp (const void *alt_state_ptr_1, const void *alt_state_ptr_2)
3189 if ((*(const alt_state_t *) alt_state_ptr_1)->state->unique_num
3190 == (*(const alt_state_t *) alt_state_ptr_2)->state->unique_num)
3191 return 0;
3192 else if ((*(const alt_state_t *) alt_state_ptr_1)->state->unique_num
3193 < (*(const alt_state_t *) alt_state_ptr_2)->state->unique_num)
3194 return -1;
3195 else
3196 return 1;
3199 /* The function sorts ALT_STATES_LIST and removes duplicated alt
3200 states from the list. The comparison key is alt state unique
3201 number. */
3203 static alt_state_t
3204 uniq_sort_alt_states (alt_state_t alt_states_list)
3206 alt_state_t curr_alt_state;
3207 VEC(alt_state_t,heap) *alt_states;
3208 size_t i;
3209 size_t prev_unique_state_ind;
3210 alt_state_t result;
3212 if (alt_states_list == 0)
3213 return 0;
3214 if (alt_states_list->next_alt_state == 0)
3215 return alt_states_list;
3217 alt_states = VEC_alloc (alt_state_t,heap, 150);
3218 for (curr_alt_state = alt_states_list;
3219 curr_alt_state != NULL;
3220 curr_alt_state = curr_alt_state->next_alt_state)
3221 VEC_safe_push (alt_state_t,heap, alt_states, curr_alt_state);
3223 qsort (VEC_address (alt_state_t, alt_states),
3224 VEC_length (alt_state_t, alt_states),
3225 sizeof (alt_state_t), alt_state_cmp);
3227 prev_unique_state_ind = 0;
3228 for (i = 1; i < VEC_length (alt_state_t, alt_states); i++)
3229 if (VEC_index (alt_state_t, alt_states, prev_unique_state_ind)->state
3230 != VEC_index (alt_state_t, alt_states, i)->state)
3232 prev_unique_state_ind++;
3233 VEC_replace (alt_state_t, alt_states, prev_unique_state_ind,
3234 VEC_index (alt_state_t, alt_states, i));
3236 VEC_truncate (alt_state_t, alt_states, prev_unique_state_ind + 1);
3238 for (i = 1; i < VEC_length (alt_state_t, alt_states); i++)
3239 VEC_index (alt_state_t, alt_states, i-1)->next_sorted_alt_state
3240 = VEC_index (alt_state_t, alt_states, i);
3241 VEC_last (alt_state_t, alt_states)->next_sorted_alt_state = 0;
3243 result = VEC_index (alt_state_t, alt_states, 0);
3245 VEC_free (alt_state_t,heap, alt_states);
3246 return result;
3249 /* The function checks equality of alt state lists. Remember that the
3250 lists must be already sorted by the previous function. */
3251 static int
3252 alt_states_eq (alt_state_t alt_states_1, alt_state_t alt_states_2)
3254 while (alt_states_1 != NULL && alt_states_2 != NULL
3255 && alt_state_cmp (&alt_states_1, &alt_states_2) == 0)
3257 alt_states_1 = alt_states_1->next_sorted_alt_state;
3258 alt_states_2 = alt_states_2->next_sorted_alt_state;
3260 return alt_states_1 == alt_states_2;
3263 /* Initialization of the abstract data. */
3264 static void
3265 initiate_alt_states (void)
3267 first_free_alt_state = NULL;
3270 /* Finishing work with the abstract data. */
3271 static void
3272 finish_alt_states (void)
3278 /* The page contains macros for work with bits strings. We could use
3279 standard gcc bitmap or sbitmap but it would result in difficulties
3280 of building canadian cross. */
3282 /* Set bit number bitno in the bit string. The macro is not side
3283 effect proof. */
3284 #define SET_BIT(bitstring, bitno) \
3285 (((char *) (bitstring)) [(bitno) / CHAR_BIT] |= 1 << (bitno) % CHAR_BIT)
3287 #define CLEAR_BIT(bitstring, bitno) \
3288 (((char *) (bitstring)) [(bitno) / CHAR_BIT] &= ~(1 << (bitno) % CHAR_BIT))
3290 /* Test if bit number bitno in the bitstring is set. The macro is not
3291 side effect proof. */
3292 #define TEST_BIT(bitstring, bitno) \
3293 (((char *) (bitstring)) [(bitno) / CHAR_BIT] >> (bitno) % CHAR_BIT & 1)
3297 /* This page contains abstract data `state'. */
3299 /* Maximal length of reservations in cycles (>= 1). */
3300 static int max_cycles_num;
3302 /* Number of set elements (see type set_el_t) needed for
3303 representation of one cycle reservation. It is depended on units
3304 number. */
3305 static int els_in_cycle_reserv;
3307 /* Number of set elements (see type set_el_t) needed for
3308 representation of maximal length reservation. Deterministic
3309 reservation is stored as set (bit string) of length equal to the
3310 variable value * number of bits in set_el_t. */
3311 static int els_in_reservs;
3313 /* Array of pointers to unit declarations. */
3314 static unit_decl_t *units_array;
3316 /* Temporary reservation of maximal length. */
3317 static reserv_sets_t temp_reserv;
3319 /* The state table itself is represented by the following variable. */
3320 static htab_t state_table;
3322 /* Linked list of free 'state' structures to be recycled. The
3323 next_equiv_class_state pointer is borrowed for a free list. */
3324 static state_t first_free_state;
3326 static int curr_unique_state_num;
3328 #ifndef NDEBUG
3329 /* The following variables is maximal number of allocated nodes
3330 `state'. */
3331 static int allocated_states_num = 0;
3332 #endif
3334 /* Allocate new reservation set. */
3335 static reserv_sets_t
3336 alloc_empty_reserv_sets (void)
3338 reserv_sets_t result;
3340 obstack_blank (&irp, els_in_reservs * sizeof (set_el_t));
3341 result = (reserv_sets_t) obstack_base (&irp);
3342 obstack_finish (&irp);
3343 memset (result, 0, els_in_reservs * sizeof (set_el_t));
3344 return result;
3347 /* Hash value of reservation set. */
3348 static unsigned
3349 reserv_sets_hash_value (reserv_sets_t reservs)
3351 set_el_t hash_value;
3352 unsigned result;
3353 int reservs_num, i;
3354 set_el_t *reserv_ptr;
3356 hash_value = 0;
3357 reservs_num = els_in_reservs;
3358 reserv_ptr = reservs;
3359 i = 0;
3360 while (reservs_num != 0)
3362 reservs_num--;
3363 hash_value += ((*reserv_ptr >> i)
3364 | (*reserv_ptr << (sizeof (set_el_t) * CHAR_BIT - i)));
3365 i++;
3366 if (i == sizeof (set_el_t) * CHAR_BIT)
3367 i = 0;
3368 reserv_ptr++;
3370 if (sizeof (set_el_t) <= sizeof (unsigned))
3371 return hash_value;
3372 result = 0;
3373 for (i = sizeof (set_el_t); i > 0; i -= sizeof (unsigned) - 1)
3375 result += (unsigned) hash_value;
3376 hash_value >>= (sizeof (unsigned) - 1) * CHAR_BIT;
3378 return result;
3381 /* Comparison of given reservation sets. */
3382 static int
3383 reserv_sets_cmp (const_reserv_sets_t reservs_1, const_reserv_sets_t reservs_2)
3385 int reservs_num;
3386 const set_el_t *reserv_ptr_1;
3387 const set_el_t *reserv_ptr_2;
3389 gcc_assert (reservs_1 && reservs_2);
3390 reservs_num = els_in_reservs;
3391 reserv_ptr_1 = reservs_1;
3392 reserv_ptr_2 = reservs_2;
3393 while (reservs_num != 0 && *reserv_ptr_1 == *reserv_ptr_2)
3395 reservs_num--;
3396 reserv_ptr_1++;
3397 reserv_ptr_2++;
3399 if (reservs_num == 0)
3400 return 0;
3401 else if (*reserv_ptr_1 < *reserv_ptr_2)
3402 return -1;
3403 else
3404 return 1;
3407 /* The function checks equality of the reservation sets. */
3408 static int
3409 reserv_sets_eq (const_reserv_sets_t reservs_1, const_reserv_sets_t reservs_2)
3411 return reserv_sets_cmp (reservs_1, reservs_2) == 0;
3414 /* Set up in the reservation set that unit with UNIT_NUM is used on
3415 CYCLE_NUM. */
3416 static void
3417 set_unit_reserv (reserv_sets_t reservs, int cycle_num, int unit_num)
3419 gcc_assert (cycle_num < max_cycles_num);
3420 SET_BIT (reservs, cycle_num * els_in_cycle_reserv
3421 * sizeof (set_el_t) * CHAR_BIT + unit_num);
3424 /* Set up in the reservation set RESERVS that unit with UNIT_NUM is
3425 used on CYCLE_NUM. */
3426 static int
3427 test_unit_reserv (reserv_sets_t reservs, int cycle_num, int unit_num)
3429 gcc_assert (cycle_num < max_cycles_num);
3430 return TEST_BIT (reservs, cycle_num * els_in_cycle_reserv
3431 * sizeof (set_el_t) * CHAR_BIT + unit_num);
3434 /* The function checks that the reservation sets are intersected,
3435 i.e. there is a unit reservation on a cycle in both reservation
3436 sets. */
3437 static int
3438 reserv_sets_are_intersected (reserv_sets_t operand_1,
3439 reserv_sets_t operand_2)
3441 set_el_t *el_ptr_1;
3442 set_el_t *el_ptr_2;
3443 set_el_t *cycle_ptr_1;
3444 set_el_t *cycle_ptr_2;
3446 gcc_assert (operand_1 && operand_2);
3447 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2;
3448 el_ptr_1 < operand_1 + els_in_reservs;
3449 el_ptr_1++, el_ptr_2++)
3450 if (*el_ptr_1 & *el_ptr_2)
3451 return 1;
3452 reserv_sets_or (temp_reserv, operand_1, operand_2);
3453 for (cycle_ptr_1 = operand_1, cycle_ptr_2 = operand_2;
3454 cycle_ptr_1 < operand_1 + els_in_reservs;
3455 cycle_ptr_1 += els_in_cycle_reserv, cycle_ptr_2 += els_in_cycle_reserv)
3457 for (el_ptr_1 = cycle_ptr_1, el_ptr_2 = get_excl_set (cycle_ptr_2);
3458 el_ptr_1 < cycle_ptr_1 + els_in_cycle_reserv;
3459 el_ptr_1++, el_ptr_2++)
3460 if (*el_ptr_1 & *el_ptr_2)
3461 return 1;
3462 if (!check_presence_pattern_sets (cycle_ptr_1, cycle_ptr_2, FALSE))
3463 return 1;
3464 if (!check_presence_pattern_sets (temp_reserv + (cycle_ptr_2
3465 - operand_2),
3466 cycle_ptr_2, TRUE))
3467 return 1;
3468 if (!check_absence_pattern_sets (cycle_ptr_1, cycle_ptr_2, FALSE))
3469 return 1;
3470 if (!check_absence_pattern_sets (temp_reserv + (cycle_ptr_2 - operand_2),
3471 cycle_ptr_2, TRUE))
3472 return 1;
3474 return 0;
3477 /* The function sets up RESULT bits by bits of OPERAND shifted on one
3478 cpu cycle. The remaining bits of OPERAND (representing the last
3479 cycle unit reservations) are not changed. */
3480 static void
3481 reserv_sets_shift (reserv_sets_t result, reserv_sets_t operand)
3483 int i;
3485 gcc_assert (result && operand && result != operand);
3486 for (i = els_in_cycle_reserv; i < els_in_reservs; i++)
3487 result [i - els_in_cycle_reserv] = operand [i];
3490 /* OR of the reservation sets. */
3491 static void
3492 reserv_sets_or (reserv_sets_t result, reserv_sets_t operand_1,
3493 reserv_sets_t operand_2)
3495 set_el_t *el_ptr_1;
3496 set_el_t *el_ptr_2;
3497 set_el_t *result_set_el_ptr;
3499 gcc_assert (result && operand_1 && operand_2);
3500 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2, result_set_el_ptr = result;
3501 el_ptr_1 < operand_1 + els_in_reservs;
3502 el_ptr_1++, el_ptr_2++, result_set_el_ptr++)
3503 *result_set_el_ptr = *el_ptr_1 | *el_ptr_2;
3506 /* AND of the reservation sets. */
3507 static void
3508 reserv_sets_and (reserv_sets_t result, reserv_sets_t operand_1,
3509 reserv_sets_t operand_2)
3511 set_el_t *el_ptr_1;
3512 set_el_t *el_ptr_2;
3513 set_el_t *result_set_el_ptr;
3515 gcc_assert (result && operand_1 && operand_2);
3516 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2, result_set_el_ptr = result;
3517 el_ptr_1 < operand_1 + els_in_reservs;
3518 el_ptr_1++, el_ptr_2++, result_set_el_ptr++)
3519 *result_set_el_ptr = *el_ptr_1 & *el_ptr_2;
3522 /* The function outputs string representation of units reservation on
3523 cycle START_CYCLE in the reservation set. The function uses repeat
3524 construction if REPETITION_NUM > 1. */
3525 static void
3526 output_cycle_reservs (FILE *f, reserv_sets_t reservs, int start_cycle,
3527 int repetition_num)
3529 int unit_num;
3530 int reserved_units_num;
3532 reserved_units_num = 0;
3533 for (unit_num = 0; unit_num < description->units_num; unit_num++)
3534 if (TEST_BIT (reservs, start_cycle * els_in_cycle_reserv
3535 * sizeof (set_el_t) * CHAR_BIT + unit_num))
3536 reserved_units_num++;
3537 gcc_assert (repetition_num > 0);
3538 if (repetition_num != 1 && reserved_units_num > 1)
3539 fprintf (f, "(");
3540 reserved_units_num = 0;
3541 for (unit_num = 0;
3542 unit_num < description->units_num;
3543 unit_num++)
3544 if (TEST_BIT (reservs, start_cycle * els_in_cycle_reserv
3545 * sizeof (set_el_t) * CHAR_BIT + unit_num))
3547 if (reserved_units_num != 0)
3548 fprintf (f, "+");
3549 reserved_units_num++;
3550 fprintf (f, "%s", units_array [unit_num]->name);
3552 if (reserved_units_num == 0)
3553 fprintf (f, NOTHING_NAME);
3554 gcc_assert (repetition_num > 0);
3555 if (repetition_num != 1 && reserved_units_num > 1)
3556 fprintf (f, ")");
3557 if (repetition_num != 1)
3558 fprintf (f, "*%d", repetition_num);
3561 /* The function outputs string representation of units reservation in
3562 the reservation set. */
3563 static void
3564 output_reserv_sets (FILE *f, reserv_sets_t reservs)
3566 int start_cycle = 0;
3567 int cycle;
3568 int repetition_num;
3570 repetition_num = 0;
3571 for (cycle = 0; cycle < max_cycles_num; cycle++)
3572 if (repetition_num == 0)
3574 repetition_num++;
3575 start_cycle = cycle;
3577 else if (memcmp
3578 ((char *) reservs + start_cycle * els_in_cycle_reserv
3579 * sizeof (set_el_t),
3580 (char *) reservs + cycle * els_in_cycle_reserv
3581 * sizeof (set_el_t),
3582 els_in_cycle_reserv * sizeof (set_el_t)) == 0)
3583 repetition_num++;
3584 else
3586 if (start_cycle != 0)
3587 fprintf (f, ", ");
3588 output_cycle_reservs (f, reservs, start_cycle, repetition_num);
3589 repetition_num = 1;
3590 start_cycle = cycle;
3592 if (start_cycle < max_cycles_num)
3594 if (start_cycle != 0)
3595 fprintf (f, ", ");
3596 output_cycle_reservs (f, reservs, start_cycle, repetition_num);
3600 /* The following function returns free node state for AUTOMATON. It
3601 may be new allocated node or node freed earlier. The function also
3602 allocates reservation set if WITH_RESERVS has nonzero value. */
3603 static state_t
3604 get_free_state (int with_reservs, automaton_t automaton)
3606 state_t result;
3608 gcc_assert (max_cycles_num > 0 && automaton);
3609 if (first_free_state)
3611 result = first_free_state;
3612 first_free_state = result->next_equiv_class_state;
3614 result->next_equiv_class_state = NULL;
3615 result->automaton = automaton;
3616 result->first_out_arc = NULL;
3617 result->it_was_placed_in_stack_for_NDFA_forming = 0;
3618 result->it_was_placed_in_stack_for_DFA_forming = 0;
3619 result->component_states = NULL;
3621 else
3623 #ifndef NDEBUG
3624 allocated_states_num++;
3625 #endif
3626 result = create_node (sizeof (struct state));
3627 result->automaton = automaton;
3628 result->first_out_arc = NULL;
3629 result->unique_num = curr_unique_state_num;
3630 curr_unique_state_num++;
3632 if (with_reservs)
3634 if (result->reservs == NULL)
3635 result->reservs = alloc_empty_reserv_sets ();
3636 else
3637 memset (result->reservs, 0, els_in_reservs * sizeof (set_el_t));
3639 return result;
3642 /* The function frees node STATE. */
3643 static void
3644 free_state (state_t state)
3646 free_alt_states (state->component_states);
3647 state->next_equiv_class_state = first_free_state;
3648 first_free_state = state;
3651 /* Hash value of STATE. If STATE represents deterministic state it is
3652 simply hash value of the corresponding reservation set. Otherwise
3653 it is formed from hash values of the component deterministic
3654 states. One more key is order number of state automaton. */
3655 static hashval_t
3656 state_hash (const void *state)
3658 unsigned int hash_value;
3659 alt_state_t alt_state;
3661 if (((const_state_t) state)->component_states == NULL)
3662 hash_value = reserv_sets_hash_value (((const_state_t) state)->reservs);
3663 else
3665 hash_value = 0;
3666 for (alt_state = ((const_state_t) state)->component_states;
3667 alt_state != NULL;
3668 alt_state = alt_state->next_sorted_alt_state)
3669 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
3670 | (hash_value << CHAR_BIT))
3671 + alt_state->state->unique_num);
3673 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
3674 | (hash_value << CHAR_BIT))
3675 + ((const_state_t) state)->automaton->automaton_order_num);
3676 return hash_value;
3679 /* Return nonzero value if the states are the same. */
3680 static int
3681 state_eq_p (const void *state_1, const void *state_2)
3683 alt_state_t alt_state_1;
3684 alt_state_t alt_state_2;
3686 if (((const_state_t) state_1)->automaton != ((const_state_t) state_2)->automaton)
3687 return 0;
3688 else if (((const_state_t) state_1)->component_states == NULL
3689 && ((const_state_t) state_2)->component_states == NULL)
3690 return reserv_sets_eq (((const_state_t) state_1)->reservs,
3691 ((const_state_t) state_2)->reservs);
3692 else if (((const_state_t) state_1)->component_states != NULL
3693 && ((const_state_t) state_2)->component_states != NULL)
3695 for (alt_state_1 = ((const_state_t) state_1)->component_states,
3696 alt_state_2 = ((const_state_t) state_2)->component_states;
3697 alt_state_1 != NULL && alt_state_2 != NULL;
3698 alt_state_1 = alt_state_1->next_sorted_alt_state,
3699 alt_state_2 = alt_state_2->next_sorted_alt_state)
3700 /* All state in the list must be already in the hash table.
3701 Also the lists must be sorted. */
3702 if (alt_state_1->state != alt_state_2->state)
3703 return 0;
3704 return alt_state_1 == alt_state_2;
3706 else
3707 return 0;
3710 /* Insert STATE into the state table. */
3711 static state_t
3712 insert_state (state_t state)
3714 void **entry_ptr;
3716 entry_ptr = htab_find_slot (state_table, (void *) state, 1);
3717 if (*entry_ptr == NULL)
3718 *entry_ptr = (void *) state;
3719 return (state_t) *entry_ptr;
3722 /* Add reservation of unit with UNIT_NUM on cycle CYCLE_NUM to
3723 deterministic STATE. */
3724 static void
3725 set_state_reserv (state_t state, int cycle_num, int unit_num)
3727 set_unit_reserv (state->reservs, cycle_num, unit_num);
3730 /* Return nonzero value if the deterministic states contains a
3731 reservation of the same cpu unit on the same cpu cycle. */
3732 static int
3733 intersected_state_reservs_p (state_t state1, state_t state2)
3735 gcc_assert (state1->automaton == state2->automaton);
3736 return reserv_sets_are_intersected (state1->reservs, state2->reservs);
3739 /* Return deterministic state (inserted into the table) which
3740 representing the automaton state which is union of reservations of
3741 the deterministic states masked by RESERVS. */
3742 static state_t
3743 states_union (state_t state1, state_t state2, reserv_sets_t reservs)
3745 state_t result;
3746 state_t state_in_table;
3748 gcc_assert (state1->automaton == state2->automaton);
3749 result = get_free_state (1, state1->automaton);
3750 reserv_sets_or (result->reservs, state1->reservs, state2->reservs);
3751 reserv_sets_and (result->reservs, result->reservs, reservs);
3752 state_in_table = insert_state (result);
3753 if (result != state_in_table)
3755 free_state (result);
3756 result = state_in_table;
3758 return result;
3761 /* Return deterministic state (inserted into the table) which
3762 represent the automaton state is obtained from deterministic STATE
3763 by advancing cpu cycle and masking by RESERVS. */
3764 static state_t
3765 state_shift (state_t state, reserv_sets_t reservs)
3767 state_t result;
3768 state_t state_in_table;
3770 result = get_free_state (1, state->automaton);
3771 reserv_sets_shift (result->reservs, state->reservs);
3772 reserv_sets_and (result->reservs, result->reservs, reservs);
3773 state_in_table = insert_state (result);
3774 if (result != state_in_table)
3776 free_state (result);
3777 result = state_in_table;
3779 return result;
3782 /* Initialization of the abstract data. */
3783 static void
3784 initiate_states (void)
3786 decl_t decl;
3787 int i;
3789 if (description->units_num)
3790 units_array = XNEWVEC (unit_decl_t, description->units_num);
3791 else
3792 units_array = 0;
3794 for (i = 0; i < description->decls_num; i++)
3796 decl = description->decls [i];
3797 if (decl->mode == dm_unit)
3798 units_array [DECL_UNIT (decl)->unit_num] = DECL_UNIT (decl);
3800 max_cycles_num = description->max_insn_reserv_cycles;
3801 els_in_cycle_reserv
3802 = ((description->units_num + sizeof (set_el_t) * CHAR_BIT - 1)
3803 / (sizeof (set_el_t) * CHAR_BIT));
3804 els_in_reservs = els_in_cycle_reserv * max_cycles_num;
3805 curr_unique_state_num = 0;
3806 initiate_alt_states ();
3807 state_table = htab_create (1500, state_hash, state_eq_p, (htab_del) 0);
3808 temp_reserv = alloc_empty_reserv_sets ();
3811 /* Finishing work with the abstract data. */
3812 static void
3813 finish_states (void)
3815 free (units_array);
3816 units_array = 0;
3817 htab_delete (state_table);
3818 first_free_state = NULL;
3819 finish_alt_states ();
3824 /* Abstract data `arcs'. */
3826 /* List of free arcs. */
3827 static arc_t first_free_arc;
3829 #ifndef NDEBUG
3830 /* The following variables is maximal number of allocated nodes
3831 `arc'. */
3832 static int allocated_arcs_num = 0;
3833 #endif
3835 /* The function frees node ARC. */
3836 static void
3837 free_arc (arc_t arc)
3839 arc->next_out_arc = first_free_arc;
3840 first_free_arc = arc;
3843 /* The function removes and frees ARC staring from FROM_STATE. */
3844 static void
3845 remove_arc (state_t from_state, arc_t arc)
3847 arc_t prev_arc;
3848 arc_t curr_arc;
3850 gcc_assert (arc);
3851 for (prev_arc = NULL, curr_arc = from_state->first_out_arc;
3852 curr_arc != NULL;
3853 prev_arc = curr_arc, curr_arc = curr_arc->next_out_arc)
3854 if (curr_arc == arc)
3855 break;
3856 gcc_assert (curr_arc);
3857 if (prev_arc == NULL)
3858 from_state->first_out_arc = arc->next_out_arc;
3859 else
3860 prev_arc->next_out_arc = arc->next_out_arc;
3861 from_state->num_out_arcs--;
3862 free_arc (arc);
3865 /* The functions returns arc with given characteristics (or NULL if
3866 the arc does not exist). */
3867 static arc_t
3868 find_arc (state_t from_state, state_t to_state, ainsn_t insn)
3870 arc_t arc;
3872 for (arc = first_out_arc (from_state); arc != NULL; arc = next_out_arc (arc))
3873 if (arc->to_state == to_state && arc->insn == insn)
3874 return arc;
3875 return NULL;
3878 /* The function adds arc from FROM_STATE to TO_STATE marked by AINSN.
3879 The function returns added arc (or already existing arc). */
3880 static arc_t
3881 add_arc (state_t from_state, state_t to_state, ainsn_t ainsn)
3883 arc_t new_arc;
3885 new_arc = find_arc (from_state, to_state, ainsn);
3886 if (new_arc != NULL)
3887 return new_arc;
3888 if (first_free_arc == NULL)
3890 #ifndef NDEBUG
3891 allocated_arcs_num++;
3892 #endif
3893 new_arc = create_node (sizeof (struct arc));
3894 new_arc->to_state = NULL;
3895 new_arc->insn = NULL;
3896 new_arc->next_out_arc = NULL;
3898 else
3900 new_arc = first_free_arc;
3901 first_free_arc = first_free_arc->next_out_arc;
3903 new_arc->to_state = to_state;
3904 new_arc->insn = ainsn;
3905 ainsn->arc_exists_p = 1;
3906 new_arc->next_out_arc = from_state->first_out_arc;
3907 from_state->first_out_arc = new_arc;
3908 from_state->num_out_arcs++;
3909 new_arc->next_arc_marked_by_insn = NULL;
3910 return new_arc;
3913 /* The function returns the first arc starting from STATE. */
3914 static arc_t
3915 first_out_arc (const_state_t state)
3917 return state->first_out_arc;
3920 /* The function returns next out arc after ARC. */
3921 static arc_t
3922 next_out_arc (arc_t arc)
3924 return arc->next_out_arc;
3927 /* Initialization of the abstract data. */
3928 static void
3929 initiate_arcs (void)
3931 first_free_arc = NULL;
3934 /* Finishing work with the abstract data. */
3935 static void
3936 finish_arcs (void)
3942 /* Abstract data `automata lists'. */
3944 /* List of free states. */
3945 static automata_list_el_t first_free_automata_list_el;
3947 /* The list being formed. */
3948 static automata_list_el_t current_automata_list;
3950 /* Hash table of automata lists. */
3951 static htab_t automata_list_table;
3953 /* The following function returns free automata list el. It may be
3954 new allocated node or node freed earlier. */
3955 static automata_list_el_t
3956 get_free_automata_list_el (void)
3958 automata_list_el_t result;
3960 if (first_free_automata_list_el != NULL)
3962 result = first_free_automata_list_el;
3963 first_free_automata_list_el
3964 = first_free_automata_list_el->next_automata_list_el;
3966 else
3967 result = create_node (sizeof (struct automata_list_el));
3968 result->automaton = NULL;
3969 result->next_automata_list_el = NULL;
3970 return result;
3973 /* The function frees node AUTOMATA_LIST_EL. */
3974 static void
3975 free_automata_list_el (automata_list_el_t automata_list_el)
3977 if (automata_list_el == NULL)
3978 return;
3979 automata_list_el->next_automata_list_el = first_free_automata_list_el;
3980 first_free_automata_list_el = automata_list_el;
3983 /* The function frees list AUTOMATA_LIST. */
3984 static void
3985 free_automata_list (automata_list_el_t automata_list)
3987 automata_list_el_t curr_automata_list_el;
3988 automata_list_el_t next_automata_list_el;
3990 for (curr_automata_list_el = automata_list;
3991 curr_automata_list_el != NULL;
3992 curr_automata_list_el = next_automata_list_el)
3994 next_automata_list_el = curr_automata_list_el->next_automata_list_el;
3995 free_automata_list_el (curr_automata_list_el);
3999 /* Hash value of AUTOMATA_LIST. */
4000 static hashval_t
4001 automata_list_hash (const void *automata_list)
4003 unsigned int hash_value;
4004 const_automata_list_el_t curr_automata_list_el;
4006 hash_value = 0;
4007 for (curr_automata_list_el = (const_automata_list_el_t) automata_list;
4008 curr_automata_list_el != NULL;
4009 curr_automata_list_el = curr_automata_list_el->next_automata_list_el)
4010 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
4011 | (hash_value << CHAR_BIT))
4012 + curr_automata_list_el->automaton->automaton_order_num);
4013 return hash_value;
4016 /* Return nonzero value if the automata_lists are the same. */
4017 static int
4018 automata_list_eq_p (const void *automata_list_1, const void *automata_list_2)
4020 const_automata_list_el_t automata_list_el_1;
4021 const_automata_list_el_t automata_list_el_2;
4023 for (automata_list_el_1 = (const_automata_list_el_t) automata_list_1,
4024 automata_list_el_2 = (const_automata_list_el_t) automata_list_2;
4025 automata_list_el_1 != NULL && automata_list_el_2 != NULL;
4026 automata_list_el_1 = automata_list_el_1->next_automata_list_el,
4027 automata_list_el_2 = automata_list_el_2->next_automata_list_el)
4028 if (automata_list_el_1->automaton != automata_list_el_2->automaton)
4029 return 0;
4030 return automata_list_el_1 == automata_list_el_2;
4033 /* Initialization of the abstract data. */
4034 static void
4035 initiate_automata_lists (void)
4037 first_free_automata_list_el = NULL;
4038 automata_list_table = htab_create (1500, automata_list_hash,
4039 automata_list_eq_p, (htab_del) 0);
4042 /* The following function starts new automata list and makes it the
4043 current one. */
4044 static void
4045 automata_list_start (void)
4047 current_automata_list = NULL;
4050 /* The following function adds AUTOMATON to the current list. */
4051 static void
4052 automata_list_add (automaton_t automaton)
4054 automata_list_el_t el;
4056 el = get_free_automata_list_el ();
4057 el->automaton = automaton;
4058 el->next_automata_list_el = current_automata_list;
4059 current_automata_list = el;
4062 /* The following function finishes forming the current list, inserts
4063 it into the table and returns it. */
4064 static automata_list_el_t
4065 automata_list_finish (void)
4067 void **entry_ptr;
4069 if (current_automata_list == NULL)
4070 return NULL;
4071 entry_ptr = htab_find_slot (automata_list_table,
4072 (void *) current_automata_list, 1);
4073 if (*entry_ptr == NULL)
4074 *entry_ptr = (void *) current_automata_list;
4075 else
4076 free_automata_list (current_automata_list);
4077 current_automata_list = NULL;
4078 return (automata_list_el_t) *entry_ptr;
4081 /* Finishing work with the abstract data. */
4082 static void
4083 finish_automata_lists (void)
4085 htab_delete (automata_list_table);
4090 /* The page contains abstract data for work with exclusion sets (see
4091 exclusion_set in file rtl.def). */
4093 /* The following variable refers to an exclusion set returned by
4094 get_excl_set. This is bit string of length equal to cpu units
4095 number. If exclusion set for given unit contains 1 for a unit,
4096 then simultaneous reservation of the units is prohibited. */
4097 static reserv_sets_t excl_set;
4099 /* The array contains exclusion sets for each unit. */
4100 static reserv_sets_t *unit_excl_set_table;
4102 /* The following function forms the array containing exclusion sets
4103 for each unit. */
4104 static void
4105 initiate_excl_sets (void)
4107 decl_t decl;
4108 reserv_sets_t unit_excl_set;
4109 unit_set_el_t el;
4110 int i;
4112 obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4113 excl_set = (reserv_sets_t) obstack_base (&irp);
4114 obstack_finish (&irp);
4115 obstack_blank (&irp, description->units_num * sizeof (reserv_sets_t));
4116 unit_excl_set_table = (reserv_sets_t *) obstack_base (&irp);
4117 obstack_finish (&irp);
4118 /* Evaluate unit exclusion sets. */
4119 for (i = 0; i < description->decls_num; i++)
4121 decl = description->decls [i];
4122 if (decl->mode == dm_unit)
4124 obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4125 unit_excl_set = (reserv_sets_t) obstack_base (&irp);
4126 obstack_finish (&irp);
4127 memset (unit_excl_set, 0, els_in_cycle_reserv * sizeof (set_el_t));
4128 for (el = DECL_UNIT (decl)->excl_list;
4129 el != NULL;
4130 el = el->next_unit_set_el)
4132 SET_BIT (unit_excl_set, el->unit_decl->unit_num);
4133 el->unit_decl->in_set_p = TRUE;
4135 unit_excl_set_table [DECL_UNIT (decl)->unit_num] = unit_excl_set;
4140 /* The function sets up and return EXCL_SET which is union of
4141 exclusion sets for each unit in IN_SET. */
4142 static reserv_sets_t
4143 get_excl_set (reserv_sets_t in_set)
4145 int excl_char_num;
4146 int chars_num;
4147 int i;
4148 int start_unit_num;
4149 int unit_num;
4151 chars_num = els_in_cycle_reserv * sizeof (set_el_t);
4152 memset (excl_set, 0, chars_num);
4153 for (excl_char_num = 0; excl_char_num < chars_num; excl_char_num++)
4154 if (((unsigned char *) in_set) [excl_char_num])
4155 for (i = CHAR_BIT - 1; i >= 0; i--)
4156 if ((((unsigned char *) in_set) [excl_char_num] >> i) & 1)
4158 start_unit_num = excl_char_num * CHAR_BIT + i;
4159 if (start_unit_num >= description->units_num)
4160 return excl_set;
4161 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4163 excl_set [unit_num]
4164 |= unit_excl_set_table [start_unit_num] [unit_num];
4167 return excl_set;
4172 /* The page contains abstract data for work with presence/absence
4173 pattern sets (see presence_set/absence_set in file rtl.def). */
4175 /* The following arrays contain correspondingly presence, final
4176 presence, absence, and final absence patterns for each unit. */
4177 static pattern_reserv_t *unit_presence_set_table;
4178 static pattern_reserv_t *unit_final_presence_set_table;
4179 static pattern_reserv_t *unit_absence_set_table;
4180 static pattern_reserv_t *unit_final_absence_set_table;
4182 /* The following function forms list of reservation sets for given
4183 PATTERN_LIST. */
4184 static pattern_reserv_t
4185 form_reserv_sets_list (pattern_set_el_t pattern_list)
4187 pattern_set_el_t el;
4188 pattern_reserv_t first, curr, prev;
4189 int i;
4191 prev = first = NULL;
4192 for (el = pattern_list; el != NULL; el = el->next_pattern_set_el)
4194 curr = create_node (sizeof (struct pattern_reserv));
4195 curr->reserv = alloc_empty_reserv_sets ();
4196 curr->next_pattern_reserv = NULL;
4197 for (i = 0; i < el->units_num; i++)
4199 SET_BIT (curr->reserv, el->unit_decls [i]->unit_num);
4200 el->unit_decls [i]->in_set_p = TRUE;
4202 if (prev != NULL)
4203 prev->next_pattern_reserv = curr;
4204 else
4205 first = curr;
4206 prev = curr;
4208 return first;
4211 /* The following function forms the array containing presence and
4212 absence pattern sets for each unit. */
4213 static void
4214 initiate_presence_absence_pattern_sets (void)
4216 decl_t decl;
4217 int i;
4219 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4220 unit_presence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4221 obstack_finish (&irp);
4222 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4223 unit_final_presence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4224 obstack_finish (&irp);
4225 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4226 unit_absence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4227 obstack_finish (&irp);
4228 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4229 unit_final_absence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4230 obstack_finish (&irp);
4231 /* Evaluate unit presence/absence sets. */
4232 for (i = 0; i < description->decls_num; i++)
4234 decl = description->decls [i];
4235 if (decl->mode == dm_unit)
4237 unit_presence_set_table [DECL_UNIT (decl)->unit_num]
4238 = form_reserv_sets_list (DECL_UNIT (decl)->presence_list);
4239 unit_final_presence_set_table [DECL_UNIT (decl)->unit_num]
4240 = form_reserv_sets_list (DECL_UNIT (decl)->final_presence_list);
4241 unit_absence_set_table [DECL_UNIT (decl)->unit_num]
4242 = form_reserv_sets_list (DECL_UNIT (decl)->absence_list);
4243 unit_final_absence_set_table [DECL_UNIT (decl)->unit_num]
4244 = form_reserv_sets_list (DECL_UNIT (decl)->final_absence_list);
4249 /* The function checks that CHECKED_SET satisfies all presence pattern
4250 sets for units in ORIGIONAL_SET. The function returns TRUE if it
4251 is ok. */
4252 static int
4253 check_presence_pattern_sets (reserv_sets_t checked_set,
4254 reserv_sets_t origional_set,
4255 int final_p)
4257 int char_num;
4258 int chars_num;
4259 int i;
4260 int start_unit_num;
4261 int unit_num;
4262 int presence_p;
4263 pattern_reserv_t pat_reserv;
4265 chars_num = els_in_cycle_reserv * sizeof (set_el_t);
4266 for (char_num = 0; char_num < chars_num; char_num++)
4267 if (((unsigned char *) origional_set) [char_num])
4268 for (i = CHAR_BIT - 1; i >= 0; i--)
4269 if ((((unsigned char *) origional_set) [char_num] >> i) & 1)
4271 start_unit_num = char_num * CHAR_BIT + i;
4272 if (start_unit_num >= description->units_num)
4273 break;
4274 if ((final_p
4275 && unit_final_presence_set_table [start_unit_num] == NULL)
4276 || (!final_p
4277 && unit_presence_set_table [start_unit_num] == NULL))
4278 continue;
4279 presence_p = FALSE;
4280 for (pat_reserv = (final_p
4281 ? unit_final_presence_set_table [start_unit_num]
4282 : unit_presence_set_table [start_unit_num]);
4283 pat_reserv != NULL;
4284 pat_reserv = pat_reserv->next_pattern_reserv)
4286 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4287 if ((checked_set [unit_num] & pat_reserv->reserv [unit_num])
4288 != pat_reserv->reserv [unit_num])
4289 break;
4290 presence_p = presence_p || unit_num >= els_in_cycle_reserv;
4292 if (!presence_p)
4293 return FALSE;
4295 return TRUE;
4298 /* The function checks that CHECKED_SET satisfies all absence pattern
4299 sets for units in ORIGIONAL_SET. The function returns TRUE if it
4300 is ok. */
4301 static int
4302 check_absence_pattern_sets (reserv_sets_t checked_set,
4303 reserv_sets_t origional_set,
4304 int final_p)
4306 int char_num;
4307 int chars_num;
4308 int i;
4309 int start_unit_num;
4310 int unit_num;
4311 pattern_reserv_t pat_reserv;
4313 chars_num = els_in_cycle_reserv * sizeof (set_el_t);
4314 for (char_num = 0; char_num < chars_num; char_num++)
4315 if (((unsigned char *) origional_set) [char_num])
4316 for (i = CHAR_BIT - 1; i >= 0; i--)
4317 if ((((unsigned char *) origional_set) [char_num] >> i) & 1)
4319 start_unit_num = char_num * CHAR_BIT + i;
4320 if (start_unit_num >= description->units_num)
4321 break;
4322 for (pat_reserv = (final_p
4323 ? unit_final_absence_set_table [start_unit_num]
4324 : unit_absence_set_table [start_unit_num]);
4325 pat_reserv != NULL;
4326 pat_reserv = pat_reserv->next_pattern_reserv)
4328 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4329 if ((checked_set [unit_num] & pat_reserv->reserv [unit_num])
4330 != pat_reserv->reserv [unit_num]
4331 && pat_reserv->reserv [unit_num])
4332 break;
4333 if (unit_num >= els_in_cycle_reserv)
4334 return FALSE;
4337 return TRUE;
4342 /* This page contains code for transformation of original reservations
4343 described in .md file. The main goal of transformations is
4344 simplifying reservation and lifting up all `|' on the top of IR
4345 reservation representation. */
4348 /* The following function makes copy of IR representation of
4349 reservation. The function also substitutes all reservations
4350 defined by define_reservation by corresponding value during making
4351 the copy. */
4352 static regexp_t
4353 copy_insn_regexp (regexp_t regexp)
4355 regexp_t result;
4356 int i;
4358 switch (regexp->mode)
4360 case rm_reserv:
4361 result = copy_insn_regexp (REGEXP_RESERV (regexp)->reserv_decl->regexp);
4362 break;
4364 case rm_unit:
4365 result = copy_node (regexp, sizeof (struct regexp));
4366 break;
4368 case rm_repeat:
4369 result = copy_node (regexp, sizeof (struct regexp));
4370 REGEXP_REPEAT (result)->regexp
4371 = copy_insn_regexp (REGEXP_REPEAT (regexp)->regexp);
4372 break;
4374 case rm_sequence:
4375 result = copy_node (regexp,
4376 sizeof (struct regexp) + sizeof (regexp_t)
4377 * (REGEXP_SEQUENCE (regexp)->regexps_num - 1));
4378 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4379 REGEXP_SEQUENCE (result)->regexps [i]
4380 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4381 break;
4383 case rm_allof:
4384 result = copy_node (regexp,
4385 sizeof (struct regexp) + sizeof (regexp_t)
4386 * (REGEXP_ALLOF (regexp)->regexps_num - 1));
4387 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4388 REGEXP_ALLOF (result)->regexps [i]
4389 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4390 break;
4392 case rm_oneof:
4393 result = copy_node (regexp,
4394 sizeof (struct regexp) + sizeof (regexp_t)
4395 * (REGEXP_ONEOF (regexp)->regexps_num - 1));
4396 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4397 REGEXP_ONEOF (result)->regexps [i]
4398 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4399 break;
4401 case rm_nothing:
4402 result = copy_node (regexp, sizeof (struct regexp));
4403 break;
4405 default:
4406 gcc_unreachable ();
4408 return result;
4411 /* The following variable is set up 1 if a transformation has been
4412 applied. */
4413 static int regexp_transformed_p;
4415 /* The function makes transformation
4416 A*N -> A, A, ... */
4417 static regexp_t
4418 transform_1 (regexp_t regexp)
4420 int i;
4421 int repeat_num;
4422 regexp_t operand;
4423 pos_t pos;
4425 if (regexp->mode == rm_repeat)
4427 repeat_num = REGEXP_REPEAT (regexp)->repeat_num;
4428 gcc_assert (repeat_num > 1);
4429 operand = REGEXP_REPEAT (regexp)->regexp;
4430 pos = regexp->mode;
4431 regexp = create_node (sizeof (struct regexp) + sizeof (regexp_t)
4432 * (repeat_num - 1));
4433 regexp->mode = rm_sequence;
4434 regexp->pos = pos;
4435 REGEXP_SEQUENCE (regexp)->regexps_num = repeat_num;
4436 for (i = 0; i < repeat_num; i++)
4437 REGEXP_SEQUENCE (regexp)->regexps [i] = copy_insn_regexp (operand);
4438 regexp_transformed_p = 1;
4440 return regexp;
4443 /* The function makes transformations
4444 ...,(A,B,...),C,... -> ...,A,B,...,C,...
4445 ...+(A+B+...)+C+... -> ...+A+B+...+C+...
4446 ...|(A|B|...)|C|... -> ...|A|B|...|C|... */
4447 static regexp_t
4448 transform_2 (regexp_t regexp)
4450 if (regexp->mode == rm_sequence)
4452 regexp_t sequence = NULL;
4453 regexp_t result;
4454 int sequence_index = 0;
4455 int i, j;
4457 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4458 if (REGEXP_SEQUENCE (regexp)->regexps [i]->mode == rm_sequence)
4460 sequence_index = i;
4461 sequence = REGEXP_SEQUENCE (regexp)->regexps [i];
4462 break;
4464 if (i < REGEXP_SEQUENCE (regexp)->regexps_num)
4466 gcc_assert (REGEXP_SEQUENCE (sequence)->regexps_num > 1
4467 && REGEXP_SEQUENCE (regexp)->regexps_num > 1);
4468 result = create_node (sizeof (struct regexp)
4469 + sizeof (regexp_t)
4470 * (REGEXP_SEQUENCE (regexp)->regexps_num
4471 + REGEXP_SEQUENCE (sequence)->regexps_num
4472 - 2));
4473 result->mode = rm_sequence;
4474 result->pos = regexp->pos;
4475 REGEXP_SEQUENCE (result)->regexps_num
4476 = (REGEXP_SEQUENCE (regexp)->regexps_num
4477 + REGEXP_SEQUENCE (sequence)->regexps_num - 1);
4478 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4479 if (i < sequence_index)
4480 REGEXP_SEQUENCE (result)->regexps [i]
4481 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4482 else if (i > sequence_index)
4483 REGEXP_SEQUENCE (result)->regexps
4484 [i + REGEXP_SEQUENCE (sequence)->regexps_num - 1]
4485 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4486 else
4487 for (j = 0; j < REGEXP_SEQUENCE (sequence)->regexps_num; j++)
4488 REGEXP_SEQUENCE (result)->regexps [i + j]
4489 = copy_insn_regexp (REGEXP_SEQUENCE (sequence)->regexps [j]);
4490 regexp_transformed_p = 1;
4491 regexp = result;
4494 else if (regexp->mode == rm_allof)
4496 regexp_t allof = NULL;
4497 regexp_t result;
4498 int allof_index = 0;
4499 int i, j;
4501 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4502 if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_allof)
4504 allof_index = i;
4505 allof = REGEXP_ALLOF (regexp)->regexps [i];
4506 break;
4508 if (i < REGEXP_ALLOF (regexp)->regexps_num)
4510 gcc_assert (REGEXP_ALLOF (allof)->regexps_num > 1
4511 && REGEXP_ALLOF (regexp)->regexps_num > 1);
4512 result = create_node (sizeof (struct regexp)
4513 + sizeof (regexp_t)
4514 * (REGEXP_ALLOF (regexp)->regexps_num
4515 + REGEXP_ALLOF (allof)->regexps_num - 2));
4516 result->mode = rm_allof;
4517 result->pos = regexp->pos;
4518 REGEXP_ALLOF (result)->regexps_num
4519 = (REGEXP_ALLOF (regexp)->regexps_num
4520 + REGEXP_ALLOF (allof)->regexps_num - 1);
4521 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4522 if (i < allof_index)
4523 REGEXP_ALLOF (result)->regexps [i]
4524 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4525 else if (i > allof_index)
4526 REGEXP_ALLOF (result)->regexps
4527 [i + REGEXP_ALLOF (allof)->regexps_num - 1]
4528 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4529 else
4530 for (j = 0; j < REGEXP_ALLOF (allof)->regexps_num; j++)
4531 REGEXP_ALLOF (result)->regexps [i + j]
4532 = copy_insn_regexp (REGEXP_ALLOF (allof)->regexps [j]);
4533 regexp_transformed_p = 1;
4534 regexp = result;
4537 else if (regexp->mode == rm_oneof)
4539 regexp_t oneof = NULL;
4540 regexp_t result;
4541 int oneof_index = 0;
4542 int i, j;
4544 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4545 if (REGEXP_ONEOF (regexp)->regexps [i]->mode == rm_oneof)
4547 oneof_index = i;
4548 oneof = REGEXP_ONEOF (regexp)->regexps [i];
4549 break;
4551 if (i < REGEXP_ONEOF (regexp)->regexps_num)
4553 gcc_assert (REGEXP_ONEOF (oneof)->regexps_num > 1
4554 && REGEXP_ONEOF (regexp)->regexps_num > 1);
4555 result = create_node (sizeof (struct regexp)
4556 + sizeof (regexp_t)
4557 * (REGEXP_ONEOF (regexp)->regexps_num
4558 + REGEXP_ONEOF (oneof)->regexps_num - 2));
4559 result->mode = rm_oneof;
4560 result->pos = regexp->pos;
4561 REGEXP_ONEOF (result)->regexps_num
4562 = (REGEXP_ONEOF (regexp)->regexps_num
4563 + REGEXP_ONEOF (oneof)->regexps_num - 1);
4564 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4565 if (i < oneof_index)
4566 REGEXP_ONEOF (result)->regexps [i]
4567 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4568 else if (i > oneof_index)
4569 REGEXP_ONEOF (result)->regexps
4570 [i + REGEXP_ONEOF (oneof)->regexps_num - 1]
4571 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4572 else
4573 for (j = 0; j < REGEXP_ONEOF (oneof)->regexps_num; j++)
4574 REGEXP_ONEOF (result)->regexps [i + j]
4575 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [j]);
4576 regexp_transformed_p = 1;
4577 regexp = result;
4580 return regexp;
4583 /* The function makes transformations
4584 ...,A|B|...,C,... -> (...,A,C,...)|(...,B,C,...)|...
4585 ...+(A|B|...)+C+... -> (...+A+C+...)|(...+B+C+...)|...
4586 ...+(A,B,...)+C+... -> (...+A+C+...),B,...
4587 ...+(A,B,...)+(C,D,...) -> (A+C),(B+D),... */
4588 static regexp_t
4589 transform_3 (regexp_t regexp)
4591 if (regexp->mode == rm_sequence)
4593 regexp_t oneof = NULL;
4594 int oneof_index = 0;
4595 regexp_t result;
4596 regexp_t sequence;
4597 int i, j;
4599 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4600 if (REGEXP_SEQUENCE (regexp)->regexps [i]->mode == rm_oneof)
4602 oneof_index = i;
4603 oneof = REGEXP_SEQUENCE (regexp)->regexps [i];
4604 break;
4606 if (i < REGEXP_SEQUENCE (regexp)->regexps_num)
4608 gcc_assert (REGEXP_ONEOF (oneof)->regexps_num > 1
4609 && REGEXP_SEQUENCE (regexp)->regexps_num > 1);
4610 result = create_node (sizeof (struct regexp)
4611 + sizeof (regexp_t)
4612 * (REGEXP_ONEOF (oneof)->regexps_num - 1));
4613 result->mode = rm_oneof;
4614 result->pos = regexp->pos;
4615 REGEXP_ONEOF (result)->regexps_num
4616 = REGEXP_ONEOF (oneof)->regexps_num;
4617 for (i = 0; i < REGEXP_ONEOF (result)->regexps_num; i++)
4619 sequence
4620 = create_node (sizeof (struct regexp)
4621 + sizeof (regexp_t)
4622 * (REGEXP_SEQUENCE (regexp)->regexps_num - 1));
4623 sequence->mode = rm_sequence;
4624 sequence->pos = regexp->pos;
4625 REGEXP_SEQUENCE (sequence)->regexps_num
4626 = REGEXP_SEQUENCE (regexp)->regexps_num;
4627 REGEXP_ONEOF (result)->regexps [i] = sequence;
4628 for (j = 0; j < REGEXP_SEQUENCE (sequence)->regexps_num; j++)
4629 if (j != oneof_index)
4630 REGEXP_SEQUENCE (sequence)->regexps [j]
4631 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [j]);
4632 else
4633 REGEXP_SEQUENCE (sequence)->regexps [j]
4634 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [i]);
4636 regexp_transformed_p = 1;
4637 regexp = result;
4640 else if (regexp->mode == rm_allof)
4642 regexp_t oneof = NULL;
4643 regexp_t seq;
4644 int oneof_index = 0;
4645 int max_seq_length, allof_length;
4646 regexp_t result;
4647 regexp_t allof = NULL;
4648 regexp_t allof_op = NULL;
4649 int i, j;
4651 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4652 if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_oneof)
4654 oneof_index = i;
4655 oneof = REGEXP_ALLOF (regexp)->regexps [i];
4656 break;
4658 if (i < REGEXP_ALLOF (regexp)->regexps_num)
4660 gcc_assert (REGEXP_ONEOF (oneof)->regexps_num > 1
4661 && REGEXP_ALLOF (regexp)->regexps_num > 1);
4662 result = create_node (sizeof (struct regexp)
4663 + sizeof (regexp_t)
4664 * (REGEXP_ONEOF (oneof)->regexps_num - 1));
4665 result->mode = rm_oneof;
4666 result->pos = regexp->pos;
4667 REGEXP_ONEOF (result)->regexps_num
4668 = REGEXP_ONEOF (oneof)->regexps_num;
4669 for (i = 0; i < REGEXP_ONEOF (result)->regexps_num; i++)
4671 allof
4672 = create_node (sizeof (struct regexp)
4673 + sizeof (regexp_t)
4674 * (REGEXP_ALLOF (regexp)->regexps_num - 1));
4675 allof->mode = rm_allof;
4676 allof->pos = regexp->pos;
4677 REGEXP_ALLOF (allof)->regexps_num
4678 = REGEXP_ALLOF (regexp)->regexps_num;
4679 REGEXP_ONEOF (result)->regexps [i] = allof;
4680 for (j = 0; j < REGEXP_ALLOF (allof)->regexps_num; j++)
4681 if (j != oneof_index)
4682 REGEXP_ALLOF (allof)->regexps [j]
4683 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [j]);
4684 else
4685 REGEXP_ALLOF (allof)->regexps [j]
4686 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [i]);
4688 regexp_transformed_p = 1;
4689 regexp = result;
4691 max_seq_length = 0;
4692 if (regexp->mode == rm_allof)
4693 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4695 switch (REGEXP_ALLOF (regexp)->regexps [i]->mode)
4697 case rm_sequence:
4698 seq = REGEXP_ALLOF (regexp)->regexps [i];
4699 if (max_seq_length < REGEXP_SEQUENCE (seq)->regexps_num)
4700 max_seq_length = REGEXP_SEQUENCE (seq)->regexps_num;
4701 break;
4703 case rm_unit:
4704 case rm_nothing:
4705 break;
4707 default:
4708 max_seq_length = 0;
4709 goto break_for;
4712 break_for:
4713 if (max_seq_length != 0)
4715 gcc_assert (max_seq_length != 1
4716 && REGEXP_ALLOF (regexp)->regexps_num > 1);
4717 result = create_node (sizeof (struct regexp)
4718 + sizeof (regexp_t) * (max_seq_length - 1));
4719 result->mode = rm_sequence;
4720 result->pos = regexp->pos;
4721 REGEXP_SEQUENCE (result)->regexps_num = max_seq_length;
4722 for (i = 0; i < max_seq_length; i++)
4724 allof_length = 0;
4725 for (j = 0; j < REGEXP_ALLOF (regexp)->regexps_num; j++)
4726 switch (REGEXP_ALLOF (regexp)->regexps [j]->mode)
4728 case rm_sequence:
4729 if (i < (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4730 ->regexps [j])->regexps_num))
4732 allof_op
4733 = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4734 ->regexps [j])
4735 ->regexps [i]);
4736 allof_length++;
4738 break;
4739 case rm_unit:
4740 case rm_nothing:
4741 if (i == 0)
4743 allof_op = REGEXP_ALLOF (regexp)->regexps [j];
4744 allof_length++;
4746 break;
4747 default:
4748 break;
4751 if (allof_length == 1)
4752 REGEXP_SEQUENCE (result)->regexps [i] = allof_op;
4753 else
4755 allof = create_node (sizeof (struct regexp)
4756 + sizeof (regexp_t)
4757 * (allof_length - 1));
4758 allof->mode = rm_allof;
4759 allof->pos = regexp->pos;
4760 REGEXP_ALLOF (allof)->regexps_num = allof_length;
4761 REGEXP_SEQUENCE (result)->regexps [i] = allof;
4762 allof_length = 0;
4763 for (j = 0; j < REGEXP_ALLOF (regexp)->regexps_num; j++)
4764 if (REGEXP_ALLOF (regexp)->regexps [j]->mode == rm_sequence
4765 && (i <
4766 (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4767 ->regexps [j])->regexps_num)))
4769 allof_op = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4770 ->regexps [j])
4771 ->regexps [i]);
4772 REGEXP_ALLOF (allof)->regexps [allof_length]
4773 = allof_op;
4774 allof_length++;
4776 else if (i == 0
4777 && (REGEXP_ALLOF (regexp)->regexps [j]->mode
4778 == rm_unit
4779 || (REGEXP_ALLOF (regexp)->regexps [j]->mode
4780 == rm_nothing)))
4782 allof_op = REGEXP_ALLOF (regexp)->regexps [j];
4783 REGEXP_ALLOF (allof)->regexps [allof_length]
4784 = allof_op;
4785 allof_length++;
4789 regexp_transformed_p = 1;
4790 regexp = result;
4793 return regexp;
4796 /* The function traverses IR of reservation and applies transformations
4797 implemented by FUNC. */
4798 static regexp_t
4799 regexp_transform_func (regexp_t regexp, regexp_t (*func) (regexp_t regexp))
4801 int i;
4803 switch (regexp->mode)
4805 case rm_sequence:
4806 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4807 REGEXP_SEQUENCE (regexp)->regexps [i]
4808 = regexp_transform_func (REGEXP_SEQUENCE (regexp)->regexps [i],
4809 func);
4810 break;
4812 case rm_allof:
4813 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4814 REGEXP_ALLOF (regexp)->regexps [i]
4815 = regexp_transform_func (REGEXP_ALLOF (regexp)->regexps [i], func);
4816 break;
4818 case rm_oneof:
4819 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4820 REGEXP_ONEOF (regexp)->regexps [i]
4821 = regexp_transform_func (REGEXP_ONEOF (regexp)->regexps [i], func);
4822 break;
4824 case rm_repeat:
4825 REGEXP_REPEAT (regexp)->regexp
4826 = regexp_transform_func (REGEXP_REPEAT (regexp)->regexp, func);
4827 break;
4829 case rm_nothing:
4830 case rm_unit:
4831 break;
4833 default:
4834 gcc_unreachable ();
4836 return (*func) (regexp);
4839 /* The function applies all transformations for IR representation of
4840 reservation REGEXP. */
4841 static regexp_t
4842 transform_regexp (regexp_t regexp)
4844 regexp = regexp_transform_func (regexp, transform_1);
4847 regexp_transformed_p = 0;
4848 regexp = regexp_transform_func (regexp, transform_2);
4849 regexp = regexp_transform_func (regexp, transform_3);
4851 while (regexp_transformed_p);
4852 return regexp;
4855 /* The function applies all transformations for reservations of all
4856 insn declarations. */
4857 static void
4858 transform_insn_regexps (void)
4860 decl_t decl;
4861 int i;
4863 transform_time = create_ticker ();
4864 add_advance_cycle_insn_decl ();
4865 if (progress_flag)
4866 fprintf (stderr, "Reservation transformation...");
4867 for (i = 0; i < description->decls_num; i++)
4869 decl = description->decls [i];
4870 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
4871 DECL_INSN_RESERV (decl)->transformed_regexp
4872 = transform_regexp (copy_insn_regexp
4873 (DECL_INSN_RESERV (decl)->regexp));
4875 if (progress_flag)
4876 fprintf (stderr, "done\n");
4877 ticker_off (&transform_time);
4882 /* The following variable value is TRUE if the first annotated message
4883 about units to automata distribution has been output. */
4884 static int annotation_message_reported_p;
4886 /* The following structure describes usage of a unit in a reservation. */
4887 struct unit_usage
4889 unit_decl_t unit_decl;
4890 /* The following forms a list of units used on the same cycle in the
4891 same alternative. */
4892 struct unit_usage *next;
4894 typedef struct unit_usage *unit_usage_t;
4896 DEF_VEC_P(unit_usage_t);
4897 DEF_VEC_ALLOC_P(unit_usage_t,heap);
4899 /* Obstack for unit_usage structures. */
4900 static struct obstack unit_usages;
4902 /* VLA for representation of array of pointers to unit usage
4903 structures. There is an element for each combination of
4904 (alternative number, cycle). Unit usages on given cycle in
4905 alternative with given number are referred through element with
4906 index equals to the cycle * number of all alternatives in the regexp
4907 + the alternative number. */
4908 static VEC(unit_usage_t,heap) *cycle_alt_unit_usages;
4910 /* The following function creates the structure unit_usage for UNIT on
4911 CYCLE in REGEXP alternative with ALT_NUM. The structure is made
4912 accessed through cycle_alt_unit_usages. */
4913 static void
4914 store_alt_unit_usage (regexp_t regexp, regexp_t unit, int cycle,
4915 int alt_num)
4917 size_t length;
4918 unit_decl_t unit_decl;
4919 unit_usage_t unit_usage_ptr;
4920 int index;
4922 gcc_assert (regexp && regexp->mode == rm_oneof
4923 && alt_num < REGEXP_ONEOF (regexp)->regexps_num);
4924 unit_decl = REGEXP_UNIT (unit)->unit_decl;
4926 length = (cycle + 1) * REGEXP_ONEOF (regexp)->regexps_num;
4927 while (VEC_length (unit_usage_t, cycle_alt_unit_usages) < length)
4928 VEC_safe_push (unit_usage_t,heap, cycle_alt_unit_usages, 0);
4930 obstack_blank (&unit_usages, sizeof (struct unit_usage));
4931 unit_usage_ptr = (struct unit_usage *) obstack_base (&unit_usages);
4932 obstack_finish (&unit_usages);
4933 unit_usage_ptr->unit_decl = unit_decl;
4934 index = cycle * REGEXP_ONEOF (regexp)->regexps_num + alt_num;
4935 unit_usage_ptr->next = VEC_index (unit_usage_t, cycle_alt_unit_usages, index);
4936 VEC_replace (unit_usage_t, cycle_alt_unit_usages, index, unit_usage_ptr);
4937 unit_decl->last_distribution_check_cycle = -1; /* undefined */
4940 /* The function processes given REGEXP to find units with the wrong
4941 distribution. */
4942 static void
4943 check_regexp_units_distribution (const char *insn_reserv_name,
4944 regexp_t regexp)
4946 int i, j, k, cycle;
4947 regexp_t seq, allof, unit;
4948 struct unit_usage *unit_usage_ptr, *other_unit_usage_ptr;
4950 if (regexp == NULL || regexp->mode != rm_oneof)
4951 return;
4952 /* Store all unit usages in the regexp: */
4953 obstack_init (&unit_usages);
4954 cycle_alt_unit_usages = 0;
4956 for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
4958 seq = REGEXP_ONEOF (regexp)->regexps [i];
4959 switch (seq->mode)
4961 case rm_sequence:
4962 for (j = 0; j < REGEXP_SEQUENCE (seq)->regexps_num; j++)
4964 allof = REGEXP_SEQUENCE (seq)->regexps [j];
4965 switch (allof->mode)
4967 case rm_allof:
4968 for (k = 0; k < REGEXP_ALLOF (allof)->regexps_num; k++)
4970 unit = REGEXP_ALLOF (allof)->regexps [k];
4971 if (unit->mode == rm_unit)
4972 store_alt_unit_usage (regexp, unit, j, i);
4973 else
4974 gcc_assert (unit->mode == rm_nothing);
4976 break;
4978 case rm_unit:
4979 store_alt_unit_usage (regexp, allof, j, i);
4980 break;
4982 case rm_nothing:
4983 break;
4985 default:
4986 gcc_unreachable ();
4989 break;
4991 case rm_allof:
4992 for (k = 0; k < REGEXP_ALLOF (seq)->regexps_num; k++)
4994 unit = REGEXP_ALLOF (seq)->regexps [k];
4995 switch (unit->mode)
4997 case rm_unit:
4998 store_alt_unit_usage (regexp, unit, 0, i);
4999 break;
5001 case rm_nothing:
5002 break;
5004 default:
5005 gcc_unreachable ();
5008 break;
5010 case rm_unit:
5011 store_alt_unit_usage (regexp, seq, 0, i);
5012 break;
5014 case rm_nothing:
5015 break;
5017 default:
5018 gcc_unreachable ();
5021 /* Check distribution: */
5022 for (i = 0; i < (int) VEC_length (unit_usage_t, cycle_alt_unit_usages); i++)
5024 cycle = i / REGEXP_ONEOF (regexp)->regexps_num;
5025 for (unit_usage_ptr = VEC_index (unit_usage_t, cycle_alt_unit_usages, i);
5026 unit_usage_ptr != NULL;
5027 unit_usage_ptr = unit_usage_ptr->next)
5028 if (cycle != unit_usage_ptr->unit_decl->last_distribution_check_cycle)
5030 unit_usage_ptr->unit_decl->last_distribution_check_cycle = cycle;
5031 for (k = cycle * REGEXP_ONEOF (regexp)->regexps_num;
5032 k < (int) VEC_length (unit_usage_t, cycle_alt_unit_usages)
5033 && k == cycle * REGEXP_ONEOF (regexp)->regexps_num;
5034 k++)
5036 for (other_unit_usage_ptr
5037 = VEC_index (unit_usage_t, cycle_alt_unit_usages, k);
5038 other_unit_usage_ptr != NULL;
5039 other_unit_usage_ptr = other_unit_usage_ptr->next)
5040 if (unit_usage_ptr->unit_decl->automaton_decl
5041 == other_unit_usage_ptr->unit_decl->automaton_decl)
5042 break;
5043 if (other_unit_usage_ptr == NULL
5044 && (VEC_index (unit_usage_t, cycle_alt_unit_usages, k)
5045 != NULL))
5046 break;
5048 if (k < (int) VEC_length (unit_usage_t, cycle_alt_unit_usages)
5049 && k == cycle * REGEXP_ONEOF (regexp)->regexps_num)
5051 if (!annotation_message_reported_p)
5053 fprintf (stderr, "\n");
5054 error ("The following units do not satisfy units-automata distribution rule");
5055 error (" (A unit of given unit automaton should be on each reserv. altern.)");
5056 annotation_message_reported_p = TRUE;
5058 error ("Unit %s, reserv. %s, cycle %d",
5059 unit_usage_ptr->unit_decl->name, insn_reserv_name,
5060 cycle);
5064 VEC_free (unit_usage_t,heap, cycle_alt_unit_usages);
5065 obstack_free (&unit_usages, NULL);
5068 /* The function finds units which violates units to automata
5069 distribution rule. If the units exist, report about them. */
5070 static void
5071 check_unit_distributions_to_automata (void)
5073 decl_t decl;
5074 int i;
5076 if (progress_flag)
5077 fprintf (stderr, "Check unit distributions to automata...");
5078 annotation_message_reported_p = FALSE;
5079 for (i = 0; i < description->decls_num; i++)
5081 decl = description->decls [i];
5082 if (decl->mode == dm_insn_reserv)
5083 check_regexp_units_distribution
5084 (DECL_INSN_RESERV (decl)->name,
5085 DECL_INSN_RESERV (decl)->transformed_regexp);
5087 if (progress_flag)
5088 fprintf (stderr, "done\n");
5093 /* The page contains code for building alt_states (see comments for
5094 IR) describing all possible insns reservations of an automaton. */
5096 /* Current state being formed for which the current alt_state
5097 refers. */
5098 static state_t state_being_formed;
5100 /* Current alt_state being formed. */
5101 static alt_state_t alt_state_being_formed;
5103 /* This recursive function processes `,' and units in reservation
5104 REGEXP for forming alt_states of AUTOMATON. It is believed that
5105 CURR_CYCLE is start cycle of all reservation REGEXP. */
5106 static int
5107 process_seq_for_forming_states (regexp_t regexp, automaton_t automaton,
5108 int curr_cycle)
5110 int i;
5112 if (regexp == NULL)
5113 return curr_cycle;
5115 switch (regexp->mode)
5117 case rm_unit:
5118 if (REGEXP_UNIT (regexp)->unit_decl->corresponding_automaton_num
5119 == automaton->automaton_order_num)
5120 set_state_reserv (state_being_formed, curr_cycle,
5121 REGEXP_UNIT (regexp)->unit_decl->unit_num);
5122 return curr_cycle;
5124 case rm_sequence:
5125 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
5126 curr_cycle
5127 = process_seq_for_forming_states
5128 (REGEXP_SEQUENCE (regexp)->regexps [i], automaton, curr_cycle) + 1;
5129 return curr_cycle;
5131 case rm_allof:
5133 int finish_cycle = 0;
5134 int cycle;
5136 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
5138 cycle = process_seq_for_forming_states (REGEXP_ALLOF (regexp)
5139 ->regexps [i],
5140 automaton, curr_cycle);
5141 if (finish_cycle < cycle)
5142 finish_cycle = cycle;
5144 return finish_cycle;
5147 case rm_nothing:
5148 return curr_cycle;
5150 default:
5151 gcc_unreachable ();
5155 /* This recursive function finishes forming ALT_STATE of AUTOMATON and
5156 inserts alt_state into the table. */
5157 static void
5158 finish_forming_alt_state (alt_state_t alt_state,
5159 automaton_t automaton ATTRIBUTE_UNUSED)
5161 state_t state_in_table;
5162 state_t corresponding_state;
5164 corresponding_state = alt_state->state;
5165 state_in_table = insert_state (corresponding_state);
5166 if (state_in_table != corresponding_state)
5168 free_state (corresponding_state);
5169 alt_state->state = state_in_table;
5173 /* The following variable value is current automaton insn for whose
5174 reservation the alt states are created. */
5175 static ainsn_t curr_ainsn;
5177 /* This recursive function processes `|' in reservation REGEXP for
5178 forming alt_states of AUTOMATON. List of the alt states should
5179 have the same order as in the description. */
5180 static void
5181 process_alts_for_forming_states (regexp_t regexp, automaton_t automaton,
5182 int inside_oneof_p)
5184 int i;
5186 if (regexp->mode != rm_oneof)
5188 alt_state_being_formed = get_free_alt_state ();
5189 state_being_formed = get_free_state (1, automaton);
5190 alt_state_being_formed->state = state_being_formed;
5191 /* We inserts in reverse order but we process alternatives also
5192 in reverse order. So we have the same order of alternative
5193 as in the description. */
5194 alt_state_being_formed->next_alt_state = curr_ainsn->alt_states;
5195 curr_ainsn->alt_states = alt_state_being_formed;
5196 (void) process_seq_for_forming_states (regexp, automaton, 0);
5197 finish_forming_alt_state (alt_state_being_formed, automaton);
5199 else
5201 gcc_assert (!inside_oneof_p);
5202 /* We processes it in reverse order to get list with the same
5203 order as in the description. See also the previous
5204 commentary. */
5205 for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
5206 process_alts_for_forming_states (REGEXP_ONEOF (regexp)->regexps [i],
5207 automaton, 1);
5211 /* Create nodes alt_state for all AUTOMATON insns. */
5212 static void
5213 create_alt_states (automaton_t automaton)
5215 struct insn_reserv_decl *reserv_decl;
5217 for (curr_ainsn = automaton->ainsn_list;
5218 curr_ainsn != NULL;
5219 curr_ainsn = curr_ainsn->next_ainsn)
5221 reserv_decl = curr_ainsn->insn_reserv_decl;
5222 if (reserv_decl != DECL_INSN_RESERV (advance_cycle_insn_decl))
5224 curr_ainsn->alt_states = NULL;
5225 process_alts_for_forming_states (reserv_decl->transformed_regexp,
5226 automaton, 0);
5227 curr_ainsn->sorted_alt_states
5228 = uniq_sort_alt_states (curr_ainsn->alt_states);
5235 /* The page contains major code for building DFA(s) for fast pipeline
5236 hazards recognition. */
5238 /* The function forms list of ainsns of AUTOMATON with the same
5239 reservation. */
5241 static void
5242 form_ainsn_with_same_reservs (automaton_t automaton)
5244 ainsn_t curr_ainsn;
5245 size_t i;
5246 VEC(ainsn_t,heap) *last_insns = VEC_alloc (ainsn_t,heap, 150);
5248 for (curr_ainsn = automaton->ainsn_list;
5249 curr_ainsn != NULL;
5250 curr_ainsn = curr_ainsn->next_ainsn)
5251 if (curr_ainsn->insn_reserv_decl
5252 == DECL_INSN_RESERV (advance_cycle_insn_decl))
5254 curr_ainsn->next_same_reservs_insn = NULL;
5255 curr_ainsn->first_insn_with_same_reservs = 1;
5257 else
5259 for (i = 0; i < VEC_length (ainsn_t, last_insns); i++)
5260 if (alt_states_eq
5261 (curr_ainsn->sorted_alt_states,
5262 VEC_index (ainsn_t, last_insns, i)->sorted_alt_states))
5263 break;
5264 curr_ainsn->next_same_reservs_insn = NULL;
5265 if (i < VEC_length (ainsn_t, last_insns))
5267 curr_ainsn->first_insn_with_same_reservs = 0;
5268 VEC_index (ainsn_t, last_insns, i)->next_same_reservs_insn
5269 = curr_ainsn;
5270 VEC_replace (ainsn_t, last_insns, i, curr_ainsn);
5272 else
5274 VEC_safe_push (ainsn_t, heap, last_insns, curr_ainsn);
5275 curr_ainsn->first_insn_with_same_reservs = 1;
5278 VEC_free (ainsn_t,heap, last_insns);
5281 /* Forming unit reservations which can affect creating the automaton
5282 states achieved from a given state. It permits to build smaller
5283 automata in many cases. We would have the same automata after
5284 the minimization without such optimization, but the automaton
5285 right after the building could be huge. So in other words, usage
5286 of reservs_matter means some minimization during building the
5287 automaton. */
5288 static reserv_sets_t
5289 form_reservs_matter (automaton_t automaton)
5291 int cycle, unit;
5292 reserv_sets_t reservs_matter = alloc_empty_reserv_sets();
5294 for (cycle = 0; cycle < max_cycles_num; cycle++)
5295 for (unit = 0; unit < description->units_num; unit++)
5296 if (units_array [unit]->automaton_decl
5297 == automaton->corresponding_automaton_decl
5298 && (cycle >= units_array [unit]->min_occ_cycle_num
5299 /* We can not remove queried unit from reservations. */
5300 || units_array [unit]->query_p
5301 /* We can not remove units which are used
5302 `exclusion_set', `presence_set',
5303 `final_presence_set', `absence_set', and
5304 `final_absence_set'. */
5305 || units_array [unit]->in_set_p))
5306 set_unit_reserv (reservs_matter, cycle, unit);
5307 return reservs_matter;
5310 /* The following function creates all states of nondeterministic AUTOMATON. */
5311 static void
5312 make_automaton (automaton_t automaton)
5314 ainsn_t ainsn;
5315 struct insn_reserv_decl *insn_reserv_decl;
5316 alt_state_t alt_state;
5317 state_t state;
5318 state_t start_state;
5319 state_t state2;
5320 ainsn_t advance_cycle_ainsn;
5321 arc_t added_arc;
5322 VEC(state_t,heap) *state_stack = VEC_alloc(state_t,heap, 150);
5323 int states_n;
5324 reserv_sets_t reservs_matter = form_reservs_matter (automaton);
5326 /* Create the start state (empty state). */
5327 start_state = insert_state (get_free_state (1, automaton));
5328 automaton->start_state = start_state;
5329 start_state->it_was_placed_in_stack_for_NDFA_forming = 1;
5330 VEC_safe_push (state_t,heap, state_stack, start_state);
5331 states_n = 1;
5332 while (VEC_length (state_t, state_stack) != 0)
5334 state = VEC_pop (state_t, state_stack);
5335 advance_cycle_ainsn = NULL;
5336 for (ainsn = automaton->ainsn_list;
5337 ainsn != NULL;
5338 ainsn = ainsn->next_ainsn)
5339 if (ainsn->first_insn_with_same_reservs)
5341 insn_reserv_decl = ainsn->insn_reserv_decl;
5342 if (insn_reserv_decl != DECL_INSN_RESERV (advance_cycle_insn_decl))
5344 /* We process alt_states in the same order as they are
5345 present in the description. */
5346 added_arc = NULL;
5347 for (alt_state = ainsn->alt_states;
5348 alt_state != NULL;
5349 alt_state = alt_state->next_alt_state)
5351 state2 = alt_state->state;
5352 if (!intersected_state_reservs_p (state, state2))
5354 state2 = states_union (state, state2, reservs_matter);
5355 if (!state2->it_was_placed_in_stack_for_NDFA_forming)
5357 state2->it_was_placed_in_stack_for_NDFA_forming
5358 = 1;
5359 VEC_safe_push (state_t,heap, state_stack, state2);
5360 states_n++;
5361 if (progress_flag && states_n % 100 == 0)
5362 fprintf (stderr, ".");
5364 added_arc = add_arc (state, state2, ainsn);
5365 if (!ndfa_flag)
5366 break;
5369 if (!ndfa_flag && added_arc != NULL)
5371 for (alt_state = ainsn->alt_states;
5372 alt_state != NULL;
5373 alt_state = alt_state->next_alt_state)
5374 state2 = alt_state->state;
5377 else
5378 advance_cycle_ainsn = ainsn;
5380 /* Add transition to advance cycle. */
5381 state2 = state_shift (state, reservs_matter);
5382 if (!state2->it_was_placed_in_stack_for_NDFA_forming)
5384 state2->it_was_placed_in_stack_for_NDFA_forming = 1;
5385 VEC_safe_push (state_t,heap, state_stack, state2);
5386 states_n++;
5387 if (progress_flag && states_n % 100 == 0)
5388 fprintf (stderr, ".");
5390 gcc_assert (advance_cycle_ainsn);
5391 add_arc (state, state2, advance_cycle_ainsn);
5393 VEC_free (state_t,heap, state_stack);
5396 /* Foms lists of all arcs of STATE marked by the same ainsn. */
5397 static void
5398 form_arcs_marked_by_insn (state_t state)
5400 decl_t decl;
5401 arc_t arc;
5402 int i;
5404 for (i = 0; i < description->decls_num; i++)
5406 decl = description->decls [i];
5407 if (decl->mode == dm_insn_reserv)
5408 DECL_INSN_RESERV (decl)->arcs_marked_by_insn = NULL;
5410 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5412 gcc_assert (arc->insn);
5413 arc->next_arc_marked_by_insn
5414 = arc->insn->insn_reserv_decl->arcs_marked_by_insn;
5415 arc->insn->insn_reserv_decl->arcs_marked_by_insn = arc;
5419 /* The function creates composed state (see comments for IR) from
5420 ORIGINAL_STATE and list of arcs ARCS_MARKED_BY_INSN marked by the
5421 same insn. If the composed state is not in STATE_STACK yet, it is
5422 pushed into STATE_STACK. */
5424 static int
5425 create_composed_state (state_t original_state, arc_t arcs_marked_by_insn,
5426 VEC(state_t,heap) **state_stack)
5428 state_t state;
5429 alt_state_t alt_state, curr_alt_state;
5430 alt_state_t new_alt_state;
5431 arc_t curr_arc;
5432 arc_t next_arc;
5433 state_t state_in_table;
5434 state_t temp_state;
5435 alt_state_t canonical_alt_states_list;
5436 int alts_number;
5437 int new_state_p = 0;
5439 if (arcs_marked_by_insn == NULL)
5440 return new_state_p;
5441 if (arcs_marked_by_insn->next_arc_marked_by_insn == NULL)
5442 state = arcs_marked_by_insn->to_state;
5443 else
5445 gcc_assert (ndfa_flag);
5446 /* Create composed state. */
5447 state = get_free_state (0, arcs_marked_by_insn->to_state->automaton);
5448 curr_alt_state = NULL;
5449 for (curr_arc = arcs_marked_by_insn;
5450 curr_arc != NULL;
5451 curr_arc = curr_arc->next_arc_marked_by_insn)
5452 if (curr_arc->to_state->component_states == NULL)
5454 new_alt_state = get_free_alt_state ();
5455 new_alt_state->next_alt_state = curr_alt_state;
5456 new_alt_state->state = curr_arc->to_state;
5457 curr_alt_state = new_alt_state;
5459 else
5460 for (alt_state = curr_arc->to_state->component_states;
5461 alt_state != NULL;
5462 alt_state = alt_state->next_sorted_alt_state)
5464 new_alt_state = get_free_alt_state ();
5465 new_alt_state->next_alt_state = curr_alt_state;
5466 new_alt_state->state = alt_state->state;
5467 gcc_assert (!alt_state->state->component_states);
5468 curr_alt_state = new_alt_state;
5470 /* There are not identical sets in the alt state list. */
5471 canonical_alt_states_list = uniq_sort_alt_states (curr_alt_state);
5472 if (canonical_alt_states_list->next_sorted_alt_state == NULL)
5474 temp_state = state;
5475 state = canonical_alt_states_list->state;
5476 free_state (temp_state);
5478 else
5480 state->component_states = canonical_alt_states_list;
5481 state_in_table = insert_state (state);
5482 if (state_in_table != state)
5484 gcc_assert
5485 (state_in_table->it_was_placed_in_stack_for_DFA_forming);
5486 free_state (state);
5487 state = state_in_table;
5489 else
5491 gcc_assert (!state->it_was_placed_in_stack_for_DFA_forming);
5492 new_state_p = 1;
5493 for (curr_alt_state = state->component_states;
5494 curr_alt_state != NULL;
5495 curr_alt_state = curr_alt_state->next_sorted_alt_state)
5496 for (curr_arc = first_out_arc (curr_alt_state->state);
5497 curr_arc != NULL;
5498 curr_arc = next_out_arc (curr_arc))
5499 add_arc (state, curr_arc->to_state, curr_arc->insn);
5501 arcs_marked_by_insn->to_state = state;
5502 for (alts_number = 0,
5503 curr_arc = arcs_marked_by_insn->next_arc_marked_by_insn;
5504 curr_arc != NULL;
5505 curr_arc = next_arc)
5507 next_arc = curr_arc->next_arc_marked_by_insn;
5508 remove_arc (original_state, curr_arc);
5509 alts_number++;
5513 if (!state->it_was_placed_in_stack_for_DFA_forming)
5515 state->it_was_placed_in_stack_for_DFA_forming = 1;
5516 VEC_safe_push (state_t,heap, *state_stack, state);
5518 return new_state_p;
5521 /* The function transforms nondeterministic AUTOMATON into
5522 deterministic. */
5524 static void
5525 NDFA_to_DFA (automaton_t automaton)
5527 state_t start_state;
5528 state_t state;
5529 decl_t decl;
5530 VEC(state_t,heap) *state_stack;
5531 int i;
5532 int states_n;
5534 state_stack = VEC_alloc (state_t,heap, 0);
5536 /* Create the start state (empty state). */
5537 start_state = automaton->start_state;
5538 start_state->it_was_placed_in_stack_for_DFA_forming = 1;
5539 VEC_safe_push (state_t,heap, state_stack, start_state);
5540 states_n = 1;
5541 while (VEC_length (state_t, state_stack) != 0)
5543 state = VEC_pop (state_t, state_stack);
5544 form_arcs_marked_by_insn (state);
5545 for (i = 0; i < description->decls_num; i++)
5547 decl = description->decls [i];
5548 if (decl->mode == dm_insn_reserv
5549 && create_composed_state
5550 (state, DECL_INSN_RESERV (decl)->arcs_marked_by_insn,
5551 &state_stack))
5553 states_n++;
5554 if (progress_flag && states_n % 100 == 0)
5555 fprintf (stderr, ".");
5559 VEC_free (state_t,heap, state_stack);
5562 /* The following variable value is current number (1, 2, ...) of passing
5563 graph of states. */
5564 static int curr_state_graph_pass_num;
5566 /* This recursive function passes all states achieved from START_STATE
5567 and applies APPLIED_FUNC to them. */
5568 static void
5569 pass_state_graph (state_t start_state, void (*applied_func) (state_t state))
5571 arc_t arc;
5573 if (start_state->pass_num == curr_state_graph_pass_num)
5574 return;
5575 start_state->pass_num = curr_state_graph_pass_num;
5576 (*applied_func) (start_state);
5577 for (arc = first_out_arc (start_state);
5578 arc != NULL;
5579 arc = next_out_arc (arc))
5580 pass_state_graph (arc->to_state, applied_func);
5583 /* This recursive function passes all states of AUTOMATON and applies
5584 APPLIED_FUNC to them. */
5585 static void
5586 pass_states (automaton_t automaton, void (*applied_func) (state_t state))
5588 curr_state_graph_pass_num++;
5589 pass_state_graph (automaton->start_state, applied_func);
5592 /* The function initializes code for passing of all states. */
5593 static void
5594 initiate_pass_states (void)
5596 curr_state_graph_pass_num = 0;
5599 /* The following vla is used for storing pointers to all achieved
5600 states. */
5601 static VEC(state_t,heap) *all_achieved_states;
5603 /* This function is called by function pass_states to add an achieved
5604 STATE. */
5605 static void
5606 add_achieved_state (state_t state)
5608 VEC_safe_push (state_t,heap, all_achieved_states, state);
5611 /* The function sets up equivalence numbers of insns which mark all
5612 out arcs of STATE by equiv_class_num_1 (if ODD_ITERATION_FLAG has
5613 nonzero value) or by equiv_class_num_2 of the destination state.
5614 The function returns number of out arcs of STATE. */
5615 static void
5616 set_out_arc_insns_equiv_num (state_t state, int odd_iteration_flag)
5618 arc_t arc;
5620 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5622 gcc_assert (!arc->insn->insn_reserv_decl->equiv_class_num);
5623 arc->insn->insn_reserv_decl->equiv_class_num
5624 = (odd_iteration_flag
5625 ? arc->to_state->equiv_class_num_1
5626 : arc->to_state->equiv_class_num_2);
5627 gcc_assert (arc->insn->insn_reserv_decl->equiv_class_num);
5631 /* The function clears equivalence numbers and alt_states in all insns
5632 which mark all out arcs of STATE. */
5633 static void
5634 clear_arc_insns_equiv_num (state_t state)
5636 arc_t arc;
5638 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5639 arc->insn->insn_reserv_decl->equiv_class_num = 0;
5643 /* The following function returns TRUE if STATE reserves the unit with
5644 UNIT_NUM on the first cycle. */
5645 static int
5646 first_cycle_unit_presence (state_t state, int unit_num)
5648 alt_state_t alt_state;
5650 if (state->component_states == NULL)
5651 return test_unit_reserv (state->reservs, 0, unit_num);
5652 else
5654 for (alt_state = state->component_states;
5655 alt_state != NULL;
5656 alt_state = alt_state->next_sorted_alt_state)
5657 if (test_unit_reserv (alt_state->state->reservs, 0, unit_num))
5658 return true;
5660 return false;
5663 /* This fills in the presence_signature[] member of STATE. */
5664 static void
5665 cache_presence (state_t state)
5667 int i, num = 0;
5668 unsigned int sz;
5669 sz = (description->query_units_num + sizeof (int) * CHAR_BIT - 1)
5670 / (sizeof (int) * CHAR_BIT);
5672 state->presence_signature = create_node (sz * sizeof (int));
5673 for (i = 0; i < description->units_num; i++)
5674 if (units_array [i]->query_p)
5676 int presence1_p = first_cycle_unit_presence (state, i);
5677 state->presence_signature[num / (sizeof (int) * CHAR_BIT)]
5678 |= (!!presence1_p) << (num % (sizeof (int) * CHAR_BIT));
5679 num++;
5683 /* The function returns nonzero value if STATE is not equivalent to
5684 ANOTHER_STATE from the same current partition on equivalence
5685 classes. Another state has ANOTHER_STATE_OUT_ARCS_NUM number of
5686 output arcs. Iteration of making equivalence partition is defined
5687 by ODD_ITERATION_FLAG. */
5688 static int
5689 state_is_differed (state_t state, state_t another_state,
5690 int odd_iteration_flag)
5692 arc_t arc;
5693 unsigned int sz, si;
5695 gcc_assert (state->num_out_arcs == another_state->num_out_arcs);
5697 sz = (description->query_units_num + sizeof (int) * CHAR_BIT - 1)
5698 / (sizeof (int) * CHAR_BIT);
5700 for (si = 0; si < sz; si++)
5701 gcc_assert (state->presence_signature[si]
5702 == another_state->presence_signature[si]);
5704 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5706 if ((odd_iteration_flag
5707 ? arc->to_state->equiv_class_num_1
5708 : arc->to_state->equiv_class_num_2)
5709 != arc->insn->insn_reserv_decl->equiv_class_num)
5710 return 1;
5713 return 0;
5716 /* Compares two states pointed to by STATE_PTR_1 and STATE_PTR_2
5717 and return -1, 0 or 1. This function can be used as predicate for
5718 qsort(). It requires the member presence_signature[] of both
5719 states be filled. */
5720 static int
5721 compare_states_for_equiv (const void *state_ptr_1,
5722 const void *state_ptr_2)
5724 const_state_t const s1 = *(const_state_t const*)state_ptr_1;
5725 const_state_t const s2 = *(const_state_t const*)state_ptr_2;
5726 unsigned int sz, si;
5727 if (s1->num_out_arcs < s2->num_out_arcs)
5728 return -1;
5729 else if (s1->num_out_arcs > s2->num_out_arcs)
5730 return 1;
5732 sz = (description->query_units_num + sizeof (int) * CHAR_BIT - 1)
5733 / (sizeof (int) * CHAR_BIT);
5735 for (si = 0; si < sz; si++)
5736 if (s1->presence_signature[si] < s2->presence_signature[si])
5737 return -1;
5738 else if (s1->presence_signature[si] > s2->presence_signature[si])
5739 return 1;
5740 return 0;
5743 /* The function makes initial partition of STATES on equivalent
5744 classes and saves it into *CLASSES. This function requires the input
5745 to be sorted via compare_states_for_equiv(). */
5746 static int
5747 init_equiv_class (VEC(state_t,heap) *states, VEC (state_t,heap) **classes)
5749 size_t i;
5750 state_t prev = 0;
5751 int class_num = 1;
5753 *classes = VEC_alloc (state_t,heap, 150);
5754 for (i = 0; i < VEC_length (state_t, states); i++)
5756 state_t state = VEC_index (state_t, states, i);
5757 if (prev)
5759 if (compare_states_for_equiv (&prev, &state) != 0)
5761 VEC_safe_push (state_t,heap, *classes, prev);
5762 class_num++;
5763 prev = NULL;
5766 state->equiv_class_num_1 = class_num;
5767 state->next_equiv_class_state = prev;
5768 prev = state;
5770 if (prev)
5771 VEC_safe_push (state_t,heap, *classes, prev);
5772 return class_num;
5775 /* The function copies pointers to equivalent states from vla FROM
5776 into vla TO. */
5777 static void
5778 copy_equiv_class (VEC(state_t,heap) **to, VEC(state_t,heap) *from)
5780 VEC_free (state_t,heap, *to);
5781 *to = VEC_copy (state_t,heap, from);
5784 /* The function processes equivalence class given by its first state,
5785 FIRST_STATE, on odd iteration if ODD_ITERATION_FLAG. If there
5786 are not equivalent states, the function partitions the class
5787 removing nonequivalent states and placing them in
5788 *NEXT_ITERATION_CLASSES, increments *NEW_EQUIV_CLASS_NUM_PTR ans
5789 assigns it to the state equivalence number. If the class has been
5790 partitioned, the function returns nonzero value. */
5791 static int
5792 partition_equiv_class (state_t first_state, int odd_iteration_flag,
5793 VEC(state_t,heap) **next_iteration_classes,
5794 int *new_equiv_class_num_ptr)
5796 state_t new_equiv_class;
5797 int partition_p;
5798 state_t curr_state;
5799 state_t prev_state;
5800 state_t next_state;
5802 partition_p = 0;
5804 while (first_state != NULL)
5806 new_equiv_class = NULL;
5807 if (first_state->next_equiv_class_state != NULL)
5809 /* There are more one states in the class equivalence. */
5810 set_out_arc_insns_equiv_num (first_state, odd_iteration_flag);
5811 for (prev_state = first_state,
5812 curr_state = first_state->next_equiv_class_state;
5813 curr_state != NULL;
5814 curr_state = next_state)
5816 next_state = curr_state->next_equiv_class_state;
5817 if (state_is_differed (curr_state, first_state,
5818 odd_iteration_flag))
5820 /* Remove curr state from the class equivalence. */
5821 prev_state->next_equiv_class_state = next_state;
5822 /* Add curr state to the new class equivalence. */
5823 curr_state->next_equiv_class_state = new_equiv_class;
5824 if (new_equiv_class == NULL)
5825 (*new_equiv_class_num_ptr)++;
5826 if (odd_iteration_flag)
5827 curr_state->equiv_class_num_2 = *new_equiv_class_num_ptr;
5828 else
5829 curr_state->equiv_class_num_1 = *new_equiv_class_num_ptr;
5830 new_equiv_class = curr_state;
5831 partition_p = 1;
5833 else
5834 prev_state = curr_state;
5836 clear_arc_insns_equiv_num (first_state);
5838 if (new_equiv_class != NULL)
5839 VEC_safe_push (state_t,heap, *next_iteration_classes, new_equiv_class);
5840 first_state = new_equiv_class;
5842 return partition_p;
5845 /* The function finds equivalent states of AUTOMATON. */
5846 static void
5847 evaluate_equiv_classes (automaton_t automaton,
5848 VEC(state_t,heap) **equiv_classes)
5850 int new_equiv_class_num;
5851 int odd_iteration_flag;
5852 int finish_flag;
5853 VEC (state_t,heap) *next_iteration_classes;
5854 size_t i;
5856 all_achieved_states = VEC_alloc (state_t,heap, 1500);
5857 pass_states (automaton, add_achieved_state);
5858 pass_states (automaton, cache_presence);
5859 qsort (VEC_address (state_t, all_achieved_states),
5860 VEC_length (state_t, all_achieved_states),
5861 sizeof (state_t), compare_states_for_equiv);
5863 odd_iteration_flag = 0;
5864 new_equiv_class_num = init_equiv_class (all_achieved_states,
5865 &next_iteration_classes);
5869 odd_iteration_flag = !odd_iteration_flag;
5870 finish_flag = 1;
5871 copy_equiv_class (equiv_classes, next_iteration_classes);
5873 /* Transfer equiv numbers for the next iteration. */
5874 for (i = 0; i < VEC_length (state_t, all_achieved_states); i++)
5875 if (odd_iteration_flag)
5876 VEC_index (state_t, all_achieved_states, i)->equiv_class_num_2
5877 = VEC_index (state_t, all_achieved_states, i)->equiv_class_num_1;
5878 else
5879 VEC_index (state_t, all_achieved_states, i)->equiv_class_num_1
5880 = VEC_index (state_t, all_achieved_states, i)->equiv_class_num_2;
5882 for (i = 0; i < VEC_length (state_t, *equiv_classes); i++)
5883 if (partition_equiv_class (VEC_index (state_t, *equiv_classes, i),
5884 odd_iteration_flag,
5885 &next_iteration_classes,
5886 &new_equiv_class_num))
5887 finish_flag = 0;
5889 while (!finish_flag);
5890 VEC_free (state_t,heap, next_iteration_classes);
5891 VEC_free (state_t,heap, all_achieved_states);
5894 /* The function merges equivalent states of AUTOMATON. */
5895 static void
5896 merge_states (automaton_t automaton, VEC(state_t,heap) *equiv_classes)
5898 state_t curr_state;
5899 state_t new_state;
5900 state_t first_class_state;
5901 alt_state_t alt_states;
5902 alt_state_t alt_state, new_alt_state;
5903 arc_t curr_arc;
5904 arc_t next_arc;
5905 size_t i;
5907 /* Create states corresponding to equivalence classes containing two
5908 or more states. */
5909 for (i = 0; i < VEC_length (state_t, equiv_classes); i++)
5911 curr_state = VEC_index (state_t, equiv_classes, i);
5912 if (curr_state->next_equiv_class_state != NULL)
5914 /* There are more one states in the class equivalence. */
5915 /* Create new compound state. */
5916 new_state = get_free_state (0, automaton);
5917 alt_states = NULL;
5918 first_class_state = curr_state;
5919 for (curr_state = first_class_state;
5920 curr_state != NULL;
5921 curr_state = curr_state->next_equiv_class_state)
5923 curr_state->equiv_class_state = new_state;
5924 if (curr_state->component_states == NULL)
5926 new_alt_state = get_free_alt_state ();
5927 new_alt_state->state = curr_state;
5928 new_alt_state->next_alt_state = alt_states;
5929 alt_states = new_alt_state;
5931 else
5932 for (alt_state = curr_state->component_states;
5933 alt_state != NULL;
5934 alt_state = alt_state->next_sorted_alt_state)
5936 new_alt_state = get_free_alt_state ();
5937 new_alt_state->state = alt_state->state;
5938 new_alt_state->next_alt_state = alt_states;
5939 alt_states = new_alt_state;
5942 /* Its is important that alt states were sorted before and
5943 after merging to have the same querying results. */
5944 new_state->component_states = uniq_sort_alt_states (alt_states);
5946 else
5947 curr_state->equiv_class_state = curr_state;
5950 for (i = 0; i < VEC_length (state_t, equiv_classes); i++)
5952 curr_state = VEC_index (state_t, equiv_classes, i);
5953 if (curr_state->next_equiv_class_state != NULL)
5955 first_class_state = curr_state;
5956 /* Create new arcs output from the state corresponding to
5957 equiv class. */
5958 for (curr_arc = first_out_arc (first_class_state);
5959 curr_arc != NULL;
5960 curr_arc = next_out_arc (curr_arc))
5961 add_arc (first_class_state->equiv_class_state,
5962 curr_arc->to_state->equiv_class_state,
5963 curr_arc->insn);
5964 /* Delete output arcs from states of given class equivalence. */
5965 for (curr_state = first_class_state;
5966 curr_state != NULL;
5967 curr_state = curr_state->next_equiv_class_state)
5969 if (automaton->start_state == curr_state)
5970 automaton->start_state = curr_state->equiv_class_state;
5971 /* Delete the state and its output arcs. */
5972 for (curr_arc = first_out_arc (curr_state);
5973 curr_arc != NULL;
5974 curr_arc = next_arc)
5976 next_arc = next_out_arc (curr_arc);
5977 free_arc (curr_arc);
5981 else
5983 /* Change `to_state' of arcs output from the state of given
5984 equivalence class. */
5985 for (curr_arc = first_out_arc (curr_state);
5986 curr_arc != NULL;
5987 curr_arc = next_out_arc (curr_arc))
5988 curr_arc->to_state = curr_arc->to_state->equiv_class_state;
5993 /* The function sets up new_cycle_p for states if there is arc to the
5994 state marked by advance_cycle_insn_decl. */
5995 static void
5996 set_new_cycle_flags (state_t state)
5998 arc_t arc;
6000 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6001 if (arc->insn->insn_reserv_decl
6002 == DECL_INSN_RESERV (advance_cycle_insn_decl))
6003 arc->to_state->new_cycle_p = 1;
6006 /* The top level function for minimization of deterministic
6007 AUTOMATON. */
6008 static void
6009 minimize_DFA (automaton_t automaton)
6011 VEC(state_t,heap) *equiv_classes = 0;
6013 evaluate_equiv_classes (automaton, &equiv_classes);
6014 merge_states (automaton, equiv_classes);
6015 pass_states (automaton, set_new_cycle_flags);
6017 VEC_free (state_t,heap, equiv_classes);
6020 /* Values of two variables are counted number of states and arcs in an
6021 automaton. */
6022 static int curr_counted_states_num;
6023 static int curr_counted_arcs_num;
6025 /* The function is called by function `pass_states' to count states
6026 and arcs of an automaton. */
6027 static void
6028 incr_states_and_arcs_nums (state_t state)
6030 arc_t arc;
6032 curr_counted_states_num++;
6033 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6034 curr_counted_arcs_num++;
6037 /* The function counts states and arcs of AUTOMATON. */
6038 static void
6039 count_states_and_arcs (automaton_t automaton, int *states_num,
6040 int *arcs_num)
6042 curr_counted_states_num = 0;
6043 curr_counted_arcs_num = 0;
6044 pass_states (automaton, incr_states_and_arcs_nums);
6045 *states_num = curr_counted_states_num;
6046 *arcs_num = curr_counted_arcs_num;
6049 /* The function builds one DFA AUTOMATON for fast pipeline hazards
6050 recognition after checking and simplifying IR of the
6051 description. */
6052 static void
6053 build_automaton (automaton_t automaton)
6055 int states_num;
6056 int arcs_num;
6058 ticker_on (&NDFA_time);
6059 if (progress_flag)
6061 if (automaton->corresponding_automaton_decl == NULL)
6062 fprintf (stderr, "Create anonymous automaton");
6063 else
6064 fprintf (stderr, "Create automaton `%s'",
6065 automaton->corresponding_automaton_decl->name);
6066 fprintf (stderr, " (1 dot is 100 new states):");
6068 make_automaton (automaton);
6069 if (progress_flag)
6070 fprintf (stderr, " done\n");
6071 ticker_off (&NDFA_time);
6072 count_states_and_arcs (automaton, &states_num, &arcs_num);
6073 automaton->NDFA_states_num = states_num;
6074 automaton->NDFA_arcs_num = arcs_num;
6075 ticker_on (&NDFA_to_DFA_time);
6076 if (progress_flag)
6078 if (automaton->corresponding_automaton_decl == NULL)
6079 fprintf (stderr, "Make anonymous DFA");
6080 else
6081 fprintf (stderr, "Make DFA `%s'",
6082 automaton->corresponding_automaton_decl->name);
6083 fprintf (stderr, " (1 dot is 100 new states):");
6085 NDFA_to_DFA (automaton);
6086 if (progress_flag)
6087 fprintf (stderr, " done\n");
6088 ticker_off (&NDFA_to_DFA_time);
6089 count_states_and_arcs (automaton, &states_num, &arcs_num);
6090 automaton->DFA_states_num = states_num;
6091 automaton->DFA_arcs_num = arcs_num;
6092 if (!no_minimization_flag)
6094 ticker_on (&minimize_time);
6095 if (progress_flag)
6097 if (automaton->corresponding_automaton_decl == NULL)
6098 fprintf (stderr, "Minimize anonymous DFA...");
6099 else
6100 fprintf (stderr, "Minimize DFA `%s'...",
6101 automaton->corresponding_automaton_decl->name);
6103 minimize_DFA (automaton);
6104 if (progress_flag)
6105 fprintf (stderr, "done\n");
6106 ticker_off (&minimize_time);
6107 count_states_and_arcs (automaton, &states_num, &arcs_num);
6108 automaton->minimal_DFA_states_num = states_num;
6109 automaton->minimal_DFA_arcs_num = arcs_num;
6115 /* The page contains code for enumeration of all states of an automaton. */
6117 /* Variable used for enumeration of all states of an automaton. Its
6118 value is current number of automaton states. */
6119 static int curr_state_order_num;
6121 /* The function is called by function `pass_states' for enumerating
6122 states. */
6123 static void
6124 set_order_state_num (state_t state)
6126 state->order_state_num = curr_state_order_num;
6127 curr_state_order_num++;
6130 /* The function enumerates all states of AUTOMATON. */
6131 static void
6132 enumerate_states (automaton_t automaton)
6134 curr_state_order_num = 0;
6135 pass_states (automaton, set_order_state_num);
6136 automaton->achieved_states_num = curr_state_order_num;
6141 /* The page contains code for finding equivalent automaton insns
6142 (ainsns). */
6144 /* The function inserts AINSN into cyclic list
6145 CYCLIC_EQUIV_CLASS_INSN_LIST of ainsns. */
6146 static ainsn_t
6147 insert_ainsn_into_equiv_class (ainsn_t ainsn,
6148 ainsn_t cyclic_equiv_class_insn_list)
6150 if (cyclic_equiv_class_insn_list == NULL)
6151 ainsn->next_equiv_class_insn = ainsn;
6152 else
6154 ainsn->next_equiv_class_insn
6155 = cyclic_equiv_class_insn_list->next_equiv_class_insn;
6156 cyclic_equiv_class_insn_list->next_equiv_class_insn = ainsn;
6158 return ainsn;
6161 /* The function deletes equiv_class_insn into cyclic list of
6162 equivalent ainsns. */
6163 static void
6164 delete_ainsn_from_equiv_class (ainsn_t equiv_class_insn)
6166 ainsn_t curr_equiv_class_insn;
6167 ainsn_t prev_equiv_class_insn;
6169 prev_equiv_class_insn = equiv_class_insn;
6170 for (curr_equiv_class_insn = equiv_class_insn->next_equiv_class_insn;
6171 curr_equiv_class_insn != equiv_class_insn;
6172 curr_equiv_class_insn = curr_equiv_class_insn->next_equiv_class_insn)
6173 prev_equiv_class_insn = curr_equiv_class_insn;
6174 if (prev_equiv_class_insn != equiv_class_insn)
6175 prev_equiv_class_insn->next_equiv_class_insn
6176 = equiv_class_insn->next_equiv_class_insn;
6179 /* The function processes AINSN of a state in order to find equivalent
6180 ainsns. INSN_ARCS_ARRAY is table: code of insn -> out arc of the
6181 state. */
6182 static void
6183 process_insn_equiv_class (ainsn_t ainsn, arc_t *insn_arcs_array)
6185 ainsn_t next_insn;
6186 ainsn_t curr_insn;
6187 ainsn_t cyclic_insn_list;
6188 arc_t arc;
6190 gcc_assert (insn_arcs_array [ainsn->insn_reserv_decl->insn_num]);
6191 curr_insn = ainsn;
6192 /* New class of ainsns which are not equivalent to given ainsn. */
6193 cyclic_insn_list = NULL;
6196 next_insn = curr_insn->next_equiv_class_insn;
6197 arc = insn_arcs_array [curr_insn->insn_reserv_decl->insn_num];
6198 if (arc == NULL
6199 || (insn_arcs_array [ainsn->insn_reserv_decl->insn_num]->to_state
6200 != arc->to_state))
6202 delete_ainsn_from_equiv_class (curr_insn);
6203 cyclic_insn_list = insert_ainsn_into_equiv_class (curr_insn,
6204 cyclic_insn_list);
6206 curr_insn = next_insn;
6208 while (curr_insn != ainsn);
6211 /* The function processes STATE in order to find equivalent ainsns. */
6212 static void
6213 process_state_for_insn_equiv_partition (state_t state)
6215 arc_t arc;
6216 arc_t *insn_arcs_array = XCNEWVEC (arc_t, description->insns_num);
6218 /* Process insns of the arcs. */
6219 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6220 insn_arcs_array [arc->insn->insn_reserv_decl->insn_num] = arc;
6221 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6222 process_insn_equiv_class (arc->insn, insn_arcs_array);
6224 free (insn_arcs_array);
6227 /* The function searches for equivalent ainsns of AUTOMATON. */
6228 static void
6229 set_insn_equiv_classes (automaton_t automaton)
6231 ainsn_t ainsn;
6232 ainsn_t first_insn;
6233 ainsn_t curr_insn;
6234 ainsn_t cyclic_insn_list;
6235 ainsn_t insn_with_same_reservs;
6236 int equiv_classes_num;
6238 /* All insns are included in one equivalence class. */
6239 cyclic_insn_list = NULL;
6240 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6241 if (ainsn->first_insn_with_same_reservs)
6242 cyclic_insn_list = insert_ainsn_into_equiv_class (ainsn,
6243 cyclic_insn_list);
6244 /* Process insns in order to make equivalence partition. */
6245 pass_states (automaton, process_state_for_insn_equiv_partition);
6246 /* Enumerate equiv classes. */
6247 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6248 /* Set undefined value. */
6249 ainsn->insn_equiv_class_num = -1;
6250 equiv_classes_num = 0;
6251 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6252 if (ainsn->insn_equiv_class_num < 0)
6254 first_insn = ainsn;
6255 gcc_assert (first_insn->first_insn_with_same_reservs);
6256 first_insn->first_ainsn_with_given_equivalence_num = 1;
6257 curr_insn = first_insn;
6260 for (insn_with_same_reservs = curr_insn;
6261 insn_with_same_reservs != NULL;
6262 insn_with_same_reservs
6263 = insn_with_same_reservs->next_same_reservs_insn)
6264 insn_with_same_reservs->insn_equiv_class_num = equiv_classes_num;
6265 curr_insn = curr_insn->next_equiv_class_insn;
6267 while (curr_insn != first_insn);
6268 equiv_classes_num++;
6270 automaton->insn_equiv_classes_num = equiv_classes_num;
6275 /* This page contains code for creating DFA(s) and calls functions
6276 building them. */
6279 /* The following value is used to prevent floating point overflow for
6280 estimating an automaton bound. The value should be less DBL_MAX on
6281 the host machine. We use here approximate minimum of maximal
6282 double floating point value required by ANSI C standard. It
6283 will work for non ANSI sun compiler too. */
6285 #define MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND 1.0E37
6287 /* The function estimate size of the single DFA used by PHR (pipeline
6288 hazards recognizer). */
6289 static double
6290 estimate_one_automaton_bound (void)
6292 decl_t decl;
6293 double one_automaton_estimation_bound;
6294 double root_value;
6295 int i;
6297 one_automaton_estimation_bound = 1.0;
6298 for (i = 0; i < description->decls_num; i++)
6300 decl = description->decls [i];
6301 if (decl->mode == dm_unit)
6303 root_value = exp (log (DECL_UNIT (decl)->max_occ_cycle_num
6304 - DECL_UNIT (decl)->min_occ_cycle_num + 1.0)
6305 / automata_num);
6306 if (MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND / root_value
6307 > one_automaton_estimation_bound)
6308 one_automaton_estimation_bound *= root_value;
6311 return one_automaton_estimation_bound;
6314 /* The function compares unit declarations according to their maximal
6315 cycle in reservations. */
6316 static int
6317 compare_max_occ_cycle_nums (const void *unit_decl_1,
6318 const void *unit_decl_2)
6320 if ((DECL_UNIT (*(const_decl_t const*) unit_decl_1)->max_occ_cycle_num)
6321 < (DECL_UNIT (*(const_decl_t const*) unit_decl_2)->max_occ_cycle_num))
6322 return 1;
6323 else if ((DECL_UNIT (*(const_decl_t const*) unit_decl_1)->max_occ_cycle_num)
6324 == (DECL_UNIT (*(const_decl_t const*) unit_decl_2)->max_occ_cycle_num))
6325 return 0;
6326 else
6327 return -1;
6330 /* The function makes heuristic assigning automata to units. Actually
6331 efficacy of the algorithm has been checked yet??? */
6333 static void
6334 units_to_automata_heuristic_distr (void)
6336 double estimation_bound;
6337 int automaton_num;
6338 int rest_units_num;
6339 double bound_value;
6340 unit_decl_t *unit_decls;
6341 int i, j;
6343 if (description->units_num == 0)
6344 return;
6345 estimation_bound = estimate_one_automaton_bound ();
6346 unit_decls = XNEWVEC (unit_decl_t, description->units_num);
6348 for (i = 0, j = 0; i < description->decls_num; i++)
6349 if (description->decls[i]->mode == dm_unit)
6350 unit_decls[j++] = DECL_UNIT (description->decls[i]);
6351 gcc_assert (j == description->units_num);
6353 qsort (unit_decls, description->units_num,
6354 sizeof (unit_decl_t), compare_max_occ_cycle_nums);
6356 automaton_num = 0;
6357 bound_value = unit_decls[0]->max_occ_cycle_num;
6358 unit_decls[0]->corresponding_automaton_num = automaton_num;
6360 for (i = 1; i < description->units_num; i++)
6362 rest_units_num = description->units_num - i + 1;
6363 gcc_assert (automata_num - automaton_num - 1 <= rest_units_num);
6364 if (automaton_num < automata_num - 1
6365 && ((automata_num - automaton_num - 1 == rest_units_num)
6366 || (bound_value
6367 > (estimation_bound
6368 / unit_decls[i]->max_occ_cycle_num))))
6370 bound_value = unit_decls[i]->max_occ_cycle_num;
6371 automaton_num++;
6373 else
6374 bound_value *= unit_decls[i]->max_occ_cycle_num;
6375 unit_decls[i]->corresponding_automaton_num = automaton_num;
6377 gcc_assert (automaton_num == automata_num - 1);
6378 free (unit_decls);
6381 /* The functions creates automaton insns for each automata. Automaton
6382 insn is simply insn for given automaton which makes reservation
6383 only of units of the automaton. */
6384 static ainsn_t
6385 create_ainsns (void)
6387 decl_t decl;
6388 ainsn_t first_ainsn;
6389 ainsn_t curr_ainsn;
6390 ainsn_t prev_ainsn;
6391 int i;
6393 first_ainsn = NULL;
6394 prev_ainsn = NULL;
6395 for (i = 0; i < description->decls_num; i++)
6397 decl = description->decls [i];
6398 if (decl->mode == dm_insn_reserv)
6400 curr_ainsn = create_node (sizeof (struct ainsn));
6401 curr_ainsn->insn_reserv_decl = DECL_INSN_RESERV (decl);
6402 curr_ainsn->important_p = FALSE;
6403 curr_ainsn->next_ainsn = NULL;
6404 if (prev_ainsn == NULL)
6405 first_ainsn = curr_ainsn;
6406 else
6407 prev_ainsn->next_ainsn = curr_ainsn;
6408 prev_ainsn = curr_ainsn;
6411 return first_ainsn;
6414 /* The function assigns automata to units according to constructions
6415 `define_automaton' in the description. */
6416 static void
6417 units_to_automata_distr (void)
6419 decl_t decl;
6420 int i;
6422 for (i = 0; i < description->decls_num; i++)
6424 decl = description->decls [i];
6425 if (decl->mode == dm_unit)
6427 if (DECL_UNIT (decl)->automaton_decl == NULL
6428 || (DECL_UNIT (decl)->automaton_decl->corresponding_automaton
6429 == NULL))
6430 /* Distribute to the first automaton. */
6431 DECL_UNIT (decl)->corresponding_automaton_num = 0;
6432 else
6433 DECL_UNIT (decl)->corresponding_automaton_num
6434 = (DECL_UNIT (decl)->automaton_decl
6435 ->corresponding_automaton->automaton_order_num);
6440 /* The function creates DFA(s) for fast pipeline hazards recognition
6441 after checking and simplifying IR of the description. */
6442 static void
6443 create_automata (void)
6445 automaton_t curr_automaton;
6446 automaton_t prev_automaton;
6447 decl_t decl;
6448 int curr_automaton_num;
6449 int i;
6451 if (automata_num != 0)
6453 units_to_automata_heuristic_distr ();
6454 for (prev_automaton = NULL, curr_automaton_num = 0;
6455 curr_automaton_num < automata_num;
6456 curr_automaton_num++, prev_automaton = curr_automaton)
6458 curr_automaton = create_node (sizeof (struct automaton));
6459 curr_automaton->ainsn_list = create_ainsns ();
6460 curr_automaton->corresponding_automaton_decl = NULL;
6461 curr_automaton->next_automaton = NULL;
6462 curr_automaton->automaton_order_num = curr_automaton_num;
6463 if (prev_automaton == NULL)
6464 description->first_automaton = curr_automaton;
6465 else
6466 prev_automaton->next_automaton = curr_automaton;
6469 else
6471 curr_automaton_num = 0;
6472 prev_automaton = NULL;
6473 for (i = 0; i < description->decls_num; i++)
6475 decl = description->decls [i];
6476 if (decl->mode == dm_automaton
6477 && DECL_AUTOMATON (decl)->automaton_is_used)
6479 curr_automaton = create_node (sizeof (struct automaton));
6480 curr_automaton->ainsn_list = create_ainsns ();
6481 curr_automaton->corresponding_automaton_decl
6482 = DECL_AUTOMATON (decl);
6483 curr_automaton->next_automaton = NULL;
6484 DECL_AUTOMATON (decl)->corresponding_automaton = curr_automaton;
6485 curr_automaton->automaton_order_num = curr_automaton_num;
6486 if (prev_automaton == NULL)
6487 description->first_automaton = curr_automaton;
6488 else
6489 prev_automaton->next_automaton = curr_automaton;
6490 curr_automaton_num++;
6491 prev_automaton = curr_automaton;
6494 if (curr_automaton_num == 0)
6496 curr_automaton = create_node (sizeof (struct automaton));
6497 curr_automaton->ainsn_list = create_ainsns ();
6498 curr_automaton->corresponding_automaton_decl = NULL;
6499 curr_automaton->next_automaton = NULL;
6500 description->first_automaton = curr_automaton;
6502 units_to_automata_distr ();
6504 NDFA_time = create_ticker ();
6505 ticker_off (&NDFA_time);
6506 NDFA_to_DFA_time = create_ticker ();
6507 ticker_off (&NDFA_to_DFA_time);
6508 minimize_time = create_ticker ();
6509 ticker_off (&minimize_time);
6510 equiv_time = create_ticker ();
6511 ticker_off (&equiv_time);
6512 for (curr_automaton = description->first_automaton;
6513 curr_automaton != NULL;
6514 curr_automaton = curr_automaton->next_automaton)
6516 if (progress_flag)
6518 if (curr_automaton->corresponding_automaton_decl == NULL)
6519 fprintf (stderr, "Prepare anonymous automaton creation ... ");
6520 else
6521 fprintf (stderr, "Prepare automaton `%s' creation...",
6522 curr_automaton->corresponding_automaton_decl->name);
6524 create_alt_states (curr_automaton);
6525 form_ainsn_with_same_reservs (curr_automaton);
6526 if (progress_flag)
6527 fprintf (stderr, "done\n");
6528 build_automaton (curr_automaton);
6529 enumerate_states (curr_automaton);
6530 ticker_on (&equiv_time);
6531 set_insn_equiv_classes (curr_automaton);
6532 ticker_off (&equiv_time);
6538 /* This page contains code for forming string representation of
6539 regexp. The representation is formed on IR obstack. So you should
6540 not work with IR obstack between regexp_representation and
6541 finish_regexp_representation calls. */
6543 /* This recursive function forms string representation of regexp
6544 (without tailing '\0'). */
6545 static void
6546 form_regexp (regexp_t regexp)
6548 int i;
6550 switch (regexp->mode)
6552 case rm_unit: case rm_reserv:
6554 const char *name = (regexp->mode == rm_unit
6555 ? REGEXP_UNIT (regexp)->name
6556 : REGEXP_RESERV (regexp)->name);
6558 obstack_grow (&irp, name, strlen (name));
6559 break;
6562 case rm_sequence:
6563 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
6565 if (i != 0)
6566 obstack_1grow (&irp, ',');
6567 form_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
6569 break;
6571 case rm_allof:
6572 obstack_1grow (&irp, '(');
6573 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
6575 if (i != 0)
6576 obstack_1grow (&irp, '+');
6577 if (REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_sequence
6578 || REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_oneof)
6579 obstack_1grow (&irp, '(');
6580 form_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
6581 if (REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_sequence
6582 || REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_oneof)
6583 obstack_1grow (&irp, ')');
6585 obstack_1grow (&irp, ')');
6586 break;
6588 case rm_oneof:
6589 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
6591 if (i != 0)
6592 obstack_1grow (&irp, '|');
6593 if (REGEXP_ONEOF (regexp)->regexps[i]->mode == rm_sequence)
6594 obstack_1grow (&irp, '(');
6595 form_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
6596 if (REGEXP_ONEOF (regexp)->regexps[i]->mode == rm_sequence)
6597 obstack_1grow (&irp, ')');
6599 break;
6601 case rm_repeat:
6603 char digits [30];
6605 if (REGEXP_REPEAT (regexp)->regexp->mode == rm_sequence
6606 || REGEXP_REPEAT (regexp)->regexp->mode == rm_allof
6607 || REGEXP_REPEAT (regexp)->regexp->mode == rm_oneof)
6608 obstack_1grow (&irp, '(');
6609 form_regexp (REGEXP_REPEAT (regexp)->regexp);
6610 if (REGEXP_REPEAT (regexp)->regexp->mode == rm_sequence
6611 || REGEXP_REPEAT (regexp)->regexp->mode == rm_allof
6612 || REGEXP_REPEAT (regexp)->regexp->mode == rm_oneof)
6613 obstack_1grow (&irp, ')');
6614 sprintf (digits, "*%d", REGEXP_REPEAT (regexp)->repeat_num);
6615 obstack_grow (&irp, digits, strlen (digits));
6616 break;
6619 case rm_nothing:
6620 obstack_grow (&irp, NOTHING_NAME, strlen (NOTHING_NAME));
6621 break;
6623 default:
6624 gcc_unreachable ();
6628 /* The function returns string representation of REGEXP on IR
6629 obstack. */
6630 static const char *
6631 regexp_representation (regexp_t regexp)
6633 form_regexp (regexp);
6634 obstack_1grow (&irp, '\0');
6635 return obstack_base (&irp);
6638 /* The function frees memory allocated for last formed string
6639 representation of regexp. */
6640 static void
6641 finish_regexp_representation (void)
6643 int length = obstack_object_size (&irp);
6645 obstack_blank_fast (&irp, -length);
6650 /* This page contains code for output PHR (pipeline hazards recognizer). */
6652 /* The function outputs minimal C type which is sufficient for
6653 representation numbers in range min_range_value and
6654 max_range_value. Because host machine and build machine may be
6655 different, we use here minimal values required by ANSI C standard
6656 instead of UCHAR_MAX, SHRT_MAX, SHRT_MIN, etc. This is a good
6657 approximation. */
6659 static void
6660 output_range_type (FILE *f, long int min_range_value,
6661 long int max_range_value)
6663 if (min_range_value >= 0 && max_range_value <= 255)
6664 fprintf (f, "unsigned char");
6665 else if (min_range_value >= -127 && max_range_value <= 127)
6666 fprintf (f, "signed char");
6667 else if (min_range_value >= 0 && max_range_value <= 65535)
6668 fprintf (f, "unsigned short");
6669 else if (min_range_value >= -32767 && max_range_value <= 32767)
6670 fprintf (f, "short");
6671 else
6672 fprintf (f, "int");
6675 /* The function outputs all initialization values of VECT. */
6676 static void
6677 output_vect (vla_hwint_t vect)
6679 int els_on_line;
6680 size_t vect_length = VEC_length (vect_el_t, vect);
6681 size_t i;
6683 els_on_line = 1;
6684 if (vect_length == 0)
6685 fputs ("0 /* This is dummy el because the vect is empty */", output_file);
6686 else
6687 for (i = 0; i < vect_length; i++)
6689 fprintf (output_file, "%5ld", (long) VEC_index (vect_el_t, vect, i));
6690 if (els_on_line == 10)
6692 els_on_line = 0;
6693 fputs (",\n", output_file);
6695 else if (i < vect_length-1)
6696 fputs (", ", output_file);
6697 els_on_line++;
6701 /* The following is name of the structure which represents DFA(s) for
6702 PHR. */
6703 #define CHIP_NAME "DFA_chip"
6705 /* The following is name of member which represents state of a DFA for
6706 PHR. */
6707 static void
6708 output_chip_member_name (FILE *f, automaton_t automaton)
6710 if (automaton->corresponding_automaton_decl == NULL)
6711 fprintf (f, "automaton_state_%d", automaton->automaton_order_num);
6712 else
6713 fprintf (f, "%s_automaton_state",
6714 automaton->corresponding_automaton_decl->name);
6717 /* The following is name of temporary variable which stores state of a
6718 DFA for PHR. */
6719 static void
6720 output_temp_chip_member_name (FILE *f, automaton_t automaton)
6722 fprintf (f, "_");
6723 output_chip_member_name (f, automaton);
6726 /* This is name of macro value which is code of pseudo_insn
6727 representing advancing cpu cycle. Its value is used as internal
6728 code unknown insn. */
6729 #define ADVANCE_CYCLE_VALUE_NAME "DFA__ADVANCE_CYCLE"
6731 /* Output name of translate vector for given automaton. */
6732 static void
6733 output_translate_vect_name (FILE *f, automaton_t automaton)
6735 if (automaton->corresponding_automaton_decl == NULL)
6736 fprintf (f, "translate_%d", automaton->automaton_order_num);
6737 else
6738 fprintf (f, "%s_translate", automaton->corresponding_automaton_decl->name);
6741 /* Output name for simple transition table representation. */
6742 static void
6743 output_trans_full_vect_name (FILE *f, automaton_t automaton)
6745 if (automaton->corresponding_automaton_decl == NULL)
6746 fprintf (f, "transitions_%d", automaton->automaton_order_num);
6747 else
6748 fprintf (f, "%s_transitions",
6749 automaton->corresponding_automaton_decl->name);
6752 /* Output name of comb vector of the transition table for given
6753 automaton. */
6754 static void
6755 output_trans_comb_vect_name (FILE *f, automaton_t automaton)
6757 if (automaton->corresponding_automaton_decl == NULL)
6758 fprintf (f, "transitions_%d", automaton->automaton_order_num);
6759 else
6760 fprintf (f, "%s_transitions",
6761 automaton->corresponding_automaton_decl->name);
6764 /* Output name of check vector of the transition table for given
6765 automaton. */
6766 static void
6767 output_trans_check_vect_name (FILE *f, automaton_t automaton)
6769 if (automaton->corresponding_automaton_decl == NULL)
6770 fprintf (f, "check_%d", automaton->automaton_order_num);
6771 else
6772 fprintf (f, "%s_check", automaton->corresponding_automaton_decl->name);
6775 /* Output name of base vector of the transition table for given
6776 automaton. */
6777 static void
6778 output_trans_base_vect_name (FILE *f, automaton_t automaton)
6780 if (automaton->corresponding_automaton_decl == NULL)
6781 fprintf (f, "base_%d", automaton->automaton_order_num);
6782 else
6783 fprintf (f, "%s_base", automaton->corresponding_automaton_decl->name);
6786 /* Output name of simple min issue delay table representation. */
6787 static void
6788 output_min_issue_delay_vect_name (FILE *f, automaton_t automaton)
6790 if (automaton->corresponding_automaton_decl == NULL)
6791 fprintf (f, "min_issue_delay_%d", automaton->automaton_order_num);
6792 else
6793 fprintf (f, "%s_min_issue_delay",
6794 automaton->corresponding_automaton_decl->name);
6797 /* Output name of deadlock vector for given automaton. */
6798 static void
6799 output_dead_lock_vect_name (FILE *f, automaton_t automaton)
6801 if (automaton->corresponding_automaton_decl == NULL)
6802 fprintf (f, "dead_lock_%d", automaton->automaton_order_num);
6803 else
6804 fprintf (f, "%s_dead_lock", automaton->corresponding_automaton_decl->name);
6807 /* Output name of reserved units table for AUTOMATON into file F. */
6808 static void
6809 output_reserved_units_table_name (FILE *f, automaton_t automaton)
6811 if (automaton->corresponding_automaton_decl == NULL)
6812 fprintf (f, "reserved_units_%d", automaton->automaton_order_num);
6813 else
6814 fprintf (f, "%s_reserved_units",
6815 automaton->corresponding_automaton_decl->name);
6818 /* Name of the PHR interface macro. */
6819 #define CPU_UNITS_QUERY_MACRO_NAME "CPU_UNITS_QUERY"
6821 /* Names of an internal functions: */
6822 #define INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME "internal_min_issue_delay"
6824 /* This is external type of DFA(s) state. */
6825 #define STATE_TYPE_NAME "state_t"
6827 #define INTERNAL_TRANSITION_FUNC_NAME "internal_state_transition"
6829 #define INTERNAL_RESET_FUNC_NAME "internal_reset"
6831 #define INTERNAL_DEAD_LOCK_FUNC_NAME "internal_state_dead_lock_p"
6833 #define INTERNAL_INSN_LATENCY_FUNC_NAME "internal_insn_latency"
6835 /* Name of cache of insn dfa codes. */
6836 #define DFA_INSN_CODES_VARIABLE_NAME "dfa_insn_codes"
6838 /* Name of length of cache of insn dfa codes. */
6839 #define DFA_INSN_CODES_LENGTH_VARIABLE_NAME "dfa_insn_codes_length"
6841 /* Names of the PHR interface functions: */
6842 #define SIZE_FUNC_NAME "state_size"
6844 #define TRANSITION_FUNC_NAME "state_transition"
6846 #define MIN_ISSUE_DELAY_FUNC_NAME "min_issue_delay"
6848 #define MIN_INSN_CONFLICT_DELAY_FUNC_NAME "min_insn_conflict_delay"
6850 #define DEAD_LOCK_FUNC_NAME "state_dead_lock_p"
6852 #define RESET_FUNC_NAME "state_reset"
6854 #define INSN_LATENCY_FUNC_NAME "insn_latency"
6856 #define PRINT_RESERVATION_FUNC_NAME "print_reservation"
6858 #define GET_CPU_UNIT_CODE_FUNC_NAME "get_cpu_unit_code"
6860 #define CPU_UNIT_RESERVATION_P_FUNC_NAME "cpu_unit_reservation_p"
6862 #define INSN_HAS_DFA_RESERVATION_P_FUNC_NAME "insn_has_dfa_reservation_p"
6864 #define DFA_CLEAN_INSN_CACHE_FUNC_NAME "dfa_clean_insn_cache"
6866 #define DFA_CLEAR_SINGLE_INSN_CACHE_FUNC_NAME "dfa_clear_single_insn_cache"
6868 #define DFA_START_FUNC_NAME "dfa_start"
6870 #define DFA_FINISH_FUNC_NAME "dfa_finish"
6872 /* Names of parameters of the PHR interface functions. */
6873 #define STATE_NAME "state"
6875 #define INSN_PARAMETER_NAME "insn"
6877 #define INSN2_PARAMETER_NAME "insn2"
6879 #define CHIP_PARAMETER_NAME "chip"
6881 #define FILE_PARAMETER_NAME "f"
6883 #define CPU_UNIT_NAME_PARAMETER_NAME "cpu_unit_name"
6885 #define CPU_CODE_PARAMETER_NAME "cpu_unit_code"
6887 /* Names of the variables whose values are internal insn code of rtx
6888 insn. */
6889 #define INTERNAL_INSN_CODE_NAME "insn_code"
6891 #define INTERNAL_INSN2_CODE_NAME "insn2_code"
6893 /* Names of temporary variables in some functions. */
6894 #define TEMPORARY_VARIABLE_NAME "temp"
6896 #define I_VARIABLE_NAME "i"
6898 /* Name of result variable in some functions. */
6899 #define RESULT_VARIABLE_NAME "res"
6901 /* Name of function (attribute) to translate insn into internal insn
6902 code. */
6903 #define INTERNAL_DFA_INSN_CODE_FUNC_NAME "internal_dfa_insn_code"
6905 /* Name of function (attribute) to translate insn into internal insn
6906 code with caching. */
6907 #define DFA_INSN_CODE_FUNC_NAME "dfa_insn_code"
6909 /* Output C type which is used for representation of codes of states
6910 of AUTOMATON. */
6911 static void
6912 output_state_member_type (FILE *f, automaton_t automaton)
6914 output_range_type (f, 0, automaton->achieved_states_num);
6917 /* Output definition of the structure representing current DFA(s)
6918 state(s). */
6919 static void
6920 output_chip_definitions (void)
6922 automaton_t automaton;
6924 fprintf (output_file, "struct %s\n{\n", CHIP_NAME);
6925 for (automaton = description->first_automaton;
6926 automaton != NULL;
6927 automaton = automaton->next_automaton)
6929 fprintf (output_file, " ");
6930 output_state_member_type (output_file, automaton);
6931 fprintf (output_file, " ");
6932 output_chip_member_name (output_file, automaton);
6933 fprintf (output_file, ";\n");
6935 fprintf (output_file, "};\n\n");
6936 #if 0
6937 fprintf (output_file, "static struct %s %s;\n\n", CHIP_NAME, CHIP_NAME);
6938 #endif
6942 /* The function outputs translate vector of internal insn code into
6943 insn equivalence class number. The equivalence class number is
6944 used to access to table and vectors representing DFA(s). */
6945 static void
6946 output_translate_vect (automaton_t automaton)
6948 ainsn_t ainsn;
6949 int insn_value;
6950 vla_hwint_t translate_vect;
6952 translate_vect = VEC_alloc (vect_el_t,heap, description->insns_num);
6954 for (insn_value = 0; insn_value < description->insns_num; insn_value++)
6955 /* Undefined value */
6956 VEC_quick_push (vect_el_t, translate_vect,
6957 automaton->insn_equiv_classes_num);
6959 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6960 VEC_replace (vect_el_t, translate_vect,
6961 ainsn->insn_reserv_decl->insn_num,
6962 ainsn->insn_equiv_class_num);
6964 fprintf (output_file,
6965 "/* Vector translating external insn codes to internal ones.*/\n");
6966 fprintf (output_file, "static const ");
6967 output_range_type (output_file, 0, automaton->insn_equiv_classes_num);
6968 fprintf (output_file, " ");
6969 output_translate_vect_name (output_file, automaton);
6970 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
6971 output_vect (translate_vect);
6972 fprintf (output_file, "};\n\n");
6973 VEC_free (vect_el_t,heap, translate_vect);
6976 /* The value in a table state x ainsn -> something which represents
6977 undefined value. */
6978 static int undefined_vect_el_value;
6980 /* The following function returns nonzero value if the best
6981 representation of the table is comb vector. */
6982 static int
6983 comb_vect_p (state_ainsn_table_t tab)
6985 return (2 * VEC_length (vect_el_t, tab->full_vect)
6986 > 5 * VEC_length (vect_el_t, tab->comb_vect));
6989 /* The following function creates new table for AUTOMATON. */
6990 static state_ainsn_table_t
6991 create_state_ainsn_table (automaton_t automaton)
6993 state_ainsn_table_t tab;
6994 int full_vect_length;
6995 int i;
6997 tab = create_node (sizeof (struct state_ainsn_table));
6998 tab->automaton = automaton;
7000 tab->comb_vect = VEC_alloc (vect_el_t,heap, 10000);
7001 tab->check_vect = VEC_alloc (vect_el_t,heap, 10000);
7003 tab->base_vect = 0;
7004 VEC_safe_grow (vect_el_t,heap, tab->base_vect,
7005 automaton->achieved_states_num);
7007 full_vect_length = (automaton->insn_equiv_classes_num
7008 * automaton->achieved_states_num);
7009 tab->full_vect = VEC_alloc (vect_el_t,heap, full_vect_length);
7010 for (i = 0; i < full_vect_length; i++)
7011 VEC_quick_push (vect_el_t, tab->full_vect, undefined_vect_el_value);
7013 tab->min_base_vect_el_value = 0;
7014 tab->max_base_vect_el_value = 0;
7015 tab->min_comb_vect_el_value = 0;
7016 tab->max_comb_vect_el_value = 0;
7017 return tab;
7020 /* The following function outputs the best C representation of the
7021 table TAB of given TABLE_NAME. */
7022 static void
7023 output_state_ainsn_table (state_ainsn_table_t tab, const char *table_name,
7024 void (*output_full_vect_name_func) (FILE *, automaton_t),
7025 void (*output_comb_vect_name_func) (FILE *, automaton_t),
7026 void (*output_check_vect_name_func) (FILE *, automaton_t),
7027 void (*output_base_vect_name_func) (FILE *, automaton_t))
7029 if (!comb_vect_p (tab))
7031 fprintf (output_file, "/* Vector for %s. */\n", table_name);
7032 fprintf (output_file, "static const ");
7033 output_range_type (output_file, tab->min_comb_vect_el_value,
7034 tab->max_comb_vect_el_value);
7035 fprintf (output_file, " ");
7036 (*output_full_vect_name_func) (output_file, tab->automaton);
7037 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7038 output_vect (tab->full_vect);
7039 fprintf (output_file, "};\n\n");
7041 else
7043 fprintf (output_file, "/* Comb vector for %s. */\n", table_name);
7044 fprintf (output_file, "static const ");
7045 output_range_type (output_file, tab->min_comb_vect_el_value,
7046 tab->max_comb_vect_el_value);
7047 fprintf (output_file, " ");
7048 (*output_comb_vect_name_func) (output_file, tab->automaton);
7049 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7050 output_vect (tab->comb_vect);
7051 fprintf (output_file, "};\n\n");
7052 fprintf (output_file, "/* Check vector for %s. */\n", table_name);
7053 fprintf (output_file, "static const ");
7054 output_range_type (output_file, 0, tab->automaton->achieved_states_num);
7055 fprintf (output_file, " ");
7056 (*output_check_vect_name_func) (output_file, tab->automaton);
7057 fprintf (output_file, "[] = {\n");
7058 output_vect (tab->check_vect);
7059 fprintf (output_file, "};\n\n");
7060 fprintf (output_file, "/* Base vector for %s. */\n", table_name);
7061 fprintf (output_file, "static const ");
7062 output_range_type (output_file, tab->min_base_vect_el_value,
7063 tab->max_base_vect_el_value);
7064 fprintf (output_file, " ");
7065 (*output_base_vect_name_func) (output_file, tab->automaton);
7066 fprintf (output_file, "[] = {\n");
7067 output_vect (tab->base_vect);
7068 fprintf (output_file, "};\n\n");
7072 /* The following function adds vector VECT to table TAB as its line
7073 with number VECT_NUM. */
7074 static void
7075 add_vect (state_ainsn_table_t tab, int vect_num, vla_hwint_t vect)
7077 int vect_length;
7078 size_t real_vect_length;
7079 int comb_vect_index;
7080 int comb_vect_els_num;
7081 int vect_index;
7082 int first_unempty_vect_index;
7083 int additional_els_num;
7084 int no_state_value;
7085 vect_el_t vect_el;
7086 int i;
7087 unsigned long vect_mask, comb_vect_mask;
7089 vect_length = VEC_length (vect_el_t, vect);
7090 gcc_assert (vect_length);
7091 gcc_assert (VEC_last (vect_el_t, vect) != undefined_vect_el_value);
7092 real_vect_length = tab->automaton->insn_equiv_classes_num;
7093 /* Form full vector in the table: */
7095 size_t full_base = tab->automaton->insn_equiv_classes_num * vect_num;
7096 if (VEC_length (vect_el_t, tab->full_vect) < full_base + vect_length)
7097 VEC_safe_grow (vect_el_t,heap, tab->full_vect,
7098 full_base + vect_length);
7099 for (i = 0; i < vect_length; i++)
7100 VEC_replace (vect_el_t, tab->full_vect, full_base + i,
7101 VEC_index (vect_el_t, vect, i));
7103 /* Form comb vector in the table: */
7104 gcc_assert (VEC_length (vect_el_t, tab->comb_vect)
7105 == VEC_length (vect_el_t, tab->check_vect));
7107 comb_vect_els_num = VEC_length (vect_el_t, tab->comb_vect);
7108 for (first_unempty_vect_index = 0;
7109 first_unempty_vect_index < vect_length;
7110 first_unempty_vect_index++)
7111 if (VEC_index (vect_el_t, vect, first_unempty_vect_index)
7112 != undefined_vect_el_value)
7113 break;
7115 /* Search for the place in comb vect for the inserted vect. */
7117 /* Slow case. */
7118 if (vect_length - first_unempty_vect_index >= SIZEOF_LONG * CHAR_BIT)
7120 for (comb_vect_index = 0;
7121 comb_vect_index < comb_vect_els_num;
7122 comb_vect_index++)
7124 for (vect_index = first_unempty_vect_index;
7125 vect_index < vect_length
7126 && vect_index + comb_vect_index < comb_vect_els_num;
7127 vect_index++)
7128 if (VEC_index (vect_el_t, vect, vect_index)
7129 != undefined_vect_el_value
7130 && (VEC_index (vect_el_t, tab->comb_vect,
7131 vect_index + comb_vect_index)
7132 != undefined_vect_el_value))
7133 break;
7134 if (vect_index >= vect_length
7135 || vect_index + comb_vect_index >= comb_vect_els_num)
7136 break;
7138 goto found;
7141 /* Fast case. */
7142 vect_mask = 0;
7143 for (vect_index = first_unempty_vect_index;
7144 vect_index < vect_length;
7145 vect_index++)
7147 vect_mask = vect_mask << 1;
7148 if (VEC_index (vect_el_t, vect, vect_index) != undefined_vect_el_value)
7149 vect_mask |= 1;
7152 /* Search for the place in comb vect for the inserted vect. */
7153 comb_vect_index = 0;
7154 if (comb_vect_els_num == 0)
7155 goto found;
7157 comb_vect_mask = 0;
7158 for (vect_index = first_unempty_vect_index;
7159 vect_index < vect_length && vect_index < comb_vect_els_num;
7160 vect_index++)
7162 comb_vect_mask <<= 1;
7163 if (vect_index + comb_vect_index < comb_vect_els_num
7164 && VEC_index (vect_el_t, tab->comb_vect, vect_index + comb_vect_index)
7165 != undefined_vect_el_value)
7166 comb_vect_mask |= 1;
7168 if ((vect_mask & comb_vect_mask) == 0)
7169 goto found;
7171 for (comb_vect_index = 1, i = vect_length; i < comb_vect_els_num;
7172 comb_vect_index++, i++)
7174 comb_vect_mask = (comb_vect_mask << 1) | 1;
7175 comb_vect_mask ^= (VEC_index (vect_el_t, tab->comb_vect, i)
7176 == undefined_vect_el_value);
7177 if ((vect_mask & comb_vect_mask) == 0)
7178 goto found;
7180 for ( ; comb_vect_index < comb_vect_els_num; comb_vect_index++)
7182 comb_vect_mask <<= 1;
7183 if ((vect_mask & comb_vect_mask) == 0)
7184 goto found;
7187 found:
7188 /* Slot was found. */
7189 additional_els_num = comb_vect_index + real_vect_length - comb_vect_els_num;
7190 if (additional_els_num < 0)
7191 additional_els_num = 0;
7192 /* Expand comb and check vectors. */
7193 vect_el = undefined_vect_el_value;
7194 no_state_value = tab->automaton->achieved_states_num;
7195 while (additional_els_num > 0)
7197 VEC_safe_push (vect_el_t,heap, tab->comb_vect, vect_el);
7198 VEC_safe_push (vect_el_t,heap, tab->check_vect, no_state_value);
7199 additional_els_num--;
7201 gcc_assert (VEC_length (vect_el_t, tab->comb_vect)
7202 >= comb_vect_index + real_vect_length);
7203 /* Fill comb and check vectors. */
7204 for (vect_index = 0; vect_index < vect_length; vect_index++)
7205 if (VEC_index (vect_el_t, vect, vect_index) != undefined_vect_el_value)
7207 vect_el_t x = VEC_index (vect_el_t, vect, vect_index);
7208 gcc_assert (VEC_index (vect_el_t, tab->comb_vect,
7209 comb_vect_index + vect_index)
7210 == undefined_vect_el_value);
7211 gcc_assert (x >= 0);
7212 if (tab->max_comb_vect_el_value < x)
7213 tab->max_comb_vect_el_value = x;
7214 if (tab->min_comb_vect_el_value > x)
7215 tab->min_comb_vect_el_value = x;
7216 VEC_replace (vect_el_t, tab->comb_vect,
7217 comb_vect_index + vect_index, x);
7218 VEC_replace (vect_el_t, tab->check_vect,
7219 comb_vect_index + vect_index, vect_num);
7221 if (tab->max_comb_vect_el_value < undefined_vect_el_value)
7222 tab->max_comb_vect_el_value = undefined_vect_el_value;
7223 if (tab->min_comb_vect_el_value > undefined_vect_el_value)
7224 tab->min_comb_vect_el_value = undefined_vect_el_value;
7225 if (tab->max_base_vect_el_value < comb_vect_index)
7226 tab->max_base_vect_el_value = comb_vect_index;
7227 if (tab->min_base_vect_el_value > comb_vect_index)
7228 tab->min_base_vect_el_value = comb_vect_index;
7230 VEC_replace (vect_el_t, tab->base_vect, vect_num, comb_vect_index);
7233 /* Return number of out arcs of STATE. */
7234 static int
7235 out_state_arcs_num (const_state_t state)
7237 int result;
7238 arc_t arc;
7240 result = 0;
7241 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
7243 gcc_assert (arc->insn);
7244 if (arc->insn->first_ainsn_with_given_equivalence_num)
7245 result++;
7247 return result;
7250 /* Compare number of possible transitions from the states. */
7251 static int
7252 compare_transition_els_num (const void *state_ptr_1,
7253 const void *state_ptr_2)
7255 const int transition_els_num_1
7256 = out_state_arcs_num (*(const_state_t const*) state_ptr_1);
7257 const int transition_els_num_2
7258 = out_state_arcs_num (*(const_state_t const*) state_ptr_2);
7260 if (transition_els_num_1 < transition_els_num_2)
7261 return 1;
7262 else if (transition_els_num_1 == transition_els_num_2)
7263 return 0;
7264 else
7265 return -1;
7268 /* The function adds element EL_VALUE to vector VECT for a table state
7269 x AINSN. */
7270 static void
7271 add_vect_el (vla_hwint_t *vect, ainsn_t ainsn, int el_value)
7273 int equiv_class_num;
7274 int vect_index;
7276 gcc_assert (ainsn);
7277 equiv_class_num = ainsn->insn_equiv_class_num;
7278 for (vect_index = VEC_length (vect_el_t, *vect);
7279 vect_index <= equiv_class_num;
7280 vect_index++)
7281 VEC_safe_push (vect_el_t,heap, *vect, undefined_vect_el_value);
7282 VEC_replace (vect_el_t, *vect, equiv_class_num, el_value);
7285 /* This is for forming vector of states of an automaton. */
7286 static VEC(state_t,heap) *output_states_vect;
7288 /* The function is called by function pass_states. The function adds
7289 STATE to `output_states_vect'. */
7290 static void
7291 add_states_vect_el (state_t state)
7293 VEC_safe_push (state_t,heap, output_states_vect, state);
7296 /* Form and output vectors (comb, check, base or full vector)
7297 representing transition table of AUTOMATON. */
7298 static void
7299 output_trans_table (automaton_t automaton)
7301 size_t i;
7302 arc_t arc;
7303 vla_hwint_t transition_vect = 0;
7305 undefined_vect_el_value = automaton->achieved_states_num;
7306 automaton->trans_table = create_state_ainsn_table (automaton);
7307 /* Create vect of pointers to states ordered by num of transitions
7308 from the state (state with the maximum num is the first). */
7309 output_states_vect = 0;
7310 pass_states (automaton, add_states_vect_el);
7311 qsort (VEC_address (state_t, output_states_vect),
7312 VEC_length (state_t, output_states_vect),
7313 sizeof (state_t), compare_transition_els_num);
7315 for (i = 0; i < VEC_length (state_t, output_states_vect); i++)
7317 VEC_truncate (vect_el_t, transition_vect, 0);
7318 for (arc = first_out_arc (VEC_index (state_t, output_states_vect, i));
7319 arc != NULL;
7320 arc = next_out_arc (arc))
7322 gcc_assert (arc->insn);
7323 if (arc->insn->first_ainsn_with_given_equivalence_num)
7324 add_vect_el (&transition_vect, arc->insn,
7325 arc->to_state->order_state_num);
7327 add_vect (automaton->trans_table,
7328 VEC_index (state_t, output_states_vect, i)->order_state_num,
7329 transition_vect);
7331 output_state_ainsn_table
7332 (automaton->trans_table, "state transitions",
7333 output_trans_full_vect_name, output_trans_comb_vect_name,
7334 output_trans_check_vect_name, output_trans_base_vect_name);
7336 VEC_free (state_t,heap, output_states_vect);
7337 VEC_free (vect_el_t,heap, transition_vect);
7340 /* The current number of passing states to find minimal issue delay
7341 value for an ainsn and state. */
7342 static int curr_state_pass_num;
7344 /* This recursive function passes states to find minimal issue delay
7345 value for AINSN. The state being visited is STATE. The function
7346 returns minimal issue delay value for AINSN in STATE or -1 if we
7347 enter into a loop. */
7348 static int
7349 min_issue_delay_pass_states (state_t state, ainsn_t ainsn)
7351 arc_t arc;
7352 int min_insn_issue_delay, insn_issue_delay;
7354 if (state->state_pass_num == curr_state_pass_num
7355 || state->min_insn_issue_delay != -1)
7356 /* We've entered into a loop or already have the correct value for
7357 given state and ainsn. */
7358 return state->min_insn_issue_delay;
7359 state->state_pass_num = curr_state_pass_num;
7360 min_insn_issue_delay = -1;
7361 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
7362 if (arc->insn == ainsn)
7364 min_insn_issue_delay = 0;
7365 break;
7367 else
7369 insn_issue_delay = min_issue_delay_pass_states (arc->to_state, ainsn);
7370 if (insn_issue_delay != -1)
7372 if (arc->insn->insn_reserv_decl
7373 == DECL_INSN_RESERV (advance_cycle_insn_decl))
7374 insn_issue_delay++;
7375 if (min_insn_issue_delay == -1
7376 || min_insn_issue_delay > insn_issue_delay)
7378 min_insn_issue_delay = insn_issue_delay;
7379 if (insn_issue_delay == 0)
7380 break;
7384 return min_insn_issue_delay;
7387 /* The function searches minimal issue delay value for AINSN in STATE.
7388 The function can return negative value if we can not issue AINSN. We
7389 will report about it later. */
7390 static int
7391 min_issue_delay (state_t state, ainsn_t ainsn)
7393 curr_state_pass_num++;
7394 state->min_insn_issue_delay = min_issue_delay_pass_states (state, ainsn);
7395 return state->min_insn_issue_delay;
7398 /* The function initiates code for finding minimal issue delay values.
7399 It should be called only once. */
7400 static void
7401 initiate_min_issue_delay_pass_states (void)
7403 curr_state_pass_num = 0;
7406 /* Form and output vectors representing minimal issue delay table of
7407 AUTOMATON. The table is state x ainsn -> minimal issue delay of
7408 the ainsn. */
7409 static void
7410 output_min_issue_delay_table (automaton_t automaton)
7412 vla_hwint_t min_issue_delay_vect;
7413 vla_hwint_t compressed_min_issue_delay_vect;
7414 vect_el_t min_delay;
7415 ainsn_t ainsn;
7416 size_t i, min_issue_delay_len;
7417 size_t compressed_min_issue_delay_len;
7418 size_t cfactor;
7420 /* Create vect of pointers to states ordered by num of transitions
7421 from the state (state with the maximum num is the first). */
7422 output_states_vect = 0;
7423 pass_states (automaton, add_states_vect_el);
7425 min_issue_delay_len = (VEC_length (state_t, output_states_vect)
7426 * automaton->insn_equiv_classes_num);
7427 min_issue_delay_vect = VEC_alloc (vect_el_t,heap, min_issue_delay_len);
7428 for (i = 0; i < min_issue_delay_len; i++)
7429 VEC_quick_push (vect_el_t, min_issue_delay_vect, 0);
7431 automaton->max_min_delay = 0;
7432 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
7433 if (ainsn->first_ainsn_with_given_equivalence_num)
7435 for (i = 0; i < VEC_length (state_t, output_states_vect); i++)
7436 VEC_index (state_t, output_states_vect, i)->min_insn_issue_delay = -1;
7437 for (i = 0; i < VEC_length (state_t, output_states_vect); i++)
7439 state_t s = VEC_index (state_t, output_states_vect, i);
7440 min_delay = min_issue_delay (s, ainsn);
7441 if (automaton->max_min_delay < min_delay)
7442 automaton->max_min_delay = min_delay;
7443 VEC_replace (vect_el_t, min_issue_delay_vect,
7444 s->order_state_num
7445 * automaton->insn_equiv_classes_num
7446 + ainsn->insn_equiv_class_num,
7447 min_delay);
7450 fprintf (output_file, "/* Vector of min issue delay of insns. */\n");
7451 fprintf (output_file, "static const ");
7452 output_range_type (output_file, 0, automaton->max_min_delay);
7453 fprintf (output_file, " ");
7454 output_min_issue_delay_vect_name (output_file, automaton);
7455 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7456 /* Compress the vector. */
7457 if (automaton->max_min_delay < 2)
7458 cfactor = 8;
7459 else if (automaton->max_min_delay < 4)
7460 cfactor = 4;
7461 else if (automaton->max_min_delay < 16)
7462 cfactor = 2;
7463 else
7464 cfactor = 1;
7465 automaton->min_issue_delay_table_compression_factor = cfactor;
7467 compressed_min_issue_delay_len = (min_issue_delay_len+cfactor-1) / cfactor;
7468 compressed_min_issue_delay_vect
7469 = VEC_alloc (vect_el_t,heap, compressed_min_issue_delay_len);
7471 for (i = 0; i < compressed_min_issue_delay_len; i++)
7472 VEC_quick_push (vect_el_t, compressed_min_issue_delay_vect, 0);
7474 for (i = 0; i < min_issue_delay_len; i++)
7476 size_t ci = i / cfactor;
7477 vect_el_t x = VEC_index (vect_el_t, min_issue_delay_vect, i);
7478 vect_el_t cx = VEC_index (vect_el_t, compressed_min_issue_delay_vect, ci);
7480 cx |= x << (8 - (i % cfactor + 1) * (8 / cfactor));
7481 VEC_replace (vect_el_t, compressed_min_issue_delay_vect, ci, cx);
7483 output_vect (compressed_min_issue_delay_vect);
7484 fprintf (output_file, "};\n\n");
7485 VEC_free (state_t,heap, output_states_vect);
7486 VEC_free (vect_el_t,heap, min_issue_delay_vect);
7487 VEC_free (vect_el_t,heap, compressed_min_issue_delay_vect);
7490 /* Form and output vector representing the locked states of
7491 AUTOMATON. */
7492 static void
7493 output_dead_lock_vect (automaton_t automaton)
7495 size_t i;
7496 arc_t arc;
7497 vla_hwint_t dead_lock_vect = 0;
7499 /* Create vect of pointers to states ordered by num of
7500 transitions from the state (state with the maximum num is the
7501 first). */
7502 automaton->locked_states = 0;
7503 output_states_vect = 0;
7504 pass_states (automaton, add_states_vect_el);
7506 VEC_safe_grow (vect_el_t,heap, dead_lock_vect,
7507 VEC_length (state_t, output_states_vect));
7508 for (i = 0; i < VEC_length (state_t, output_states_vect); i++)
7510 state_t s = VEC_index (state_t, output_states_vect, i);
7511 arc = first_out_arc (s);
7512 gcc_assert (arc);
7513 if (next_out_arc (arc) == NULL
7514 && (arc->insn->insn_reserv_decl
7515 == DECL_INSN_RESERV (advance_cycle_insn_decl)))
7517 VEC_replace (vect_el_t, dead_lock_vect, s->order_state_num, 1);
7518 automaton->locked_states++;
7520 else
7521 VEC_replace (vect_el_t, dead_lock_vect, s->order_state_num, 0);
7523 if (automaton->locked_states == 0)
7524 return;
7526 fprintf (output_file, "/* Vector for locked state flags. */\n");
7527 fprintf (output_file, "static const ");
7528 output_range_type (output_file, 0, 1);
7529 fprintf (output_file, " ");
7530 output_dead_lock_vect_name (output_file, automaton);
7531 fprintf (output_file, "[] = {\n");
7532 output_vect (dead_lock_vect);
7533 fprintf (output_file, "};\n\n");
7534 VEC_free (state_t,heap, output_states_vect);
7535 VEC_free (vect_el_t,heap, dead_lock_vect);
7538 /* Form and output vector representing reserved units of the states of
7539 AUTOMATON. */
7540 static void
7541 output_reserved_units_table (automaton_t automaton)
7543 vla_hwint_t reserved_units_table = 0;
7544 int state_byte_size;
7545 int reserved_units_size;
7546 size_t n;
7547 int i;
7549 if (description->query_units_num == 0)
7550 return;
7552 /* Create vect of pointers to states. */
7553 output_states_vect = 0;
7554 pass_states (automaton, add_states_vect_el);
7555 /* Create vector. */
7556 state_byte_size = (description->query_units_num + 7) / 8;
7557 reserved_units_size = (VEC_length (state_t, output_states_vect)
7558 * state_byte_size);
7560 reserved_units_table = VEC_alloc (vect_el_t,heap, reserved_units_size);
7562 for (i = 0; i < reserved_units_size; i++)
7563 VEC_quick_push (vect_el_t, reserved_units_table, 0);
7564 for (n = 0; n < VEC_length (state_t, output_states_vect); n++)
7566 state_t s = VEC_index (state_t, output_states_vect, n);
7567 for (i = 0; i < description->units_num; i++)
7568 if (units_array [i]->query_p
7569 && first_cycle_unit_presence (s, i))
7571 int ri = (s->order_state_num * state_byte_size
7572 + units_array [i]->query_num / 8);
7573 vect_el_t x = VEC_index (vect_el_t, reserved_units_table, ri);
7575 x += 1 << (units_array [i]->query_num % 8);
7576 VEC_replace (vect_el_t, reserved_units_table, ri, x);
7579 fprintf (output_file, "\n#if %s\n", CPU_UNITS_QUERY_MACRO_NAME);
7580 fprintf (output_file, "/* Vector for reserved units of states. */\n");
7581 fprintf (output_file, "static const ");
7582 output_range_type (output_file, 0, 255);
7583 fprintf (output_file, " ");
7584 output_reserved_units_table_name (output_file, automaton);
7585 fprintf (output_file, "[] = {\n");
7586 output_vect (reserved_units_table);
7587 fprintf (output_file, "};\n#endif /* #if %s */\n\n",
7588 CPU_UNITS_QUERY_MACRO_NAME);
7590 VEC_free (state_t,heap, output_states_vect);
7591 VEC_free (vect_el_t,heap, reserved_units_table);
7594 /* The function outputs all tables representing DFA(s) used for fast
7595 pipeline hazards recognition. */
7596 static void
7597 output_tables (void)
7599 automaton_t automaton;
7601 initiate_min_issue_delay_pass_states ();
7602 for (automaton = description->first_automaton;
7603 automaton != NULL;
7604 automaton = automaton->next_automaton)
7606 output_translate_vect (automaton);
7607 output_trans_table (automaton);
7608 output_min_issue_delay_table (automaton);
7609 output_dead_lock_vect (automaton);
7610 output_reserved_units_table (automaton);
7612 fprintf (output_file, "\n#define %s %d\n\n", ADVANCE_CYCLE_VALUE_NAME,
7613 DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
7616 /* The function outputs definition and value of PHR interface variable
7617 `max_insn_queue_index'. Its value is not less than maximal queue
7618 length needed for the insn scheduler. */
7619 static void
7620 output_max_insn_queue_index_def (void)
7622 int i, max, latency;
7623 decl_t decl;
7625 max = description->max_insn_reserv_cycles;
7626 for (i = 0; i < description->decls_num; i++)
7628 decl = description->decls [i];
7629 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
7631 latency = DECL_INSN_RESERV (decl)->default_latency;
7632 if (latency > max)
7633 max = latency;
7635 else if (decl->mode == dm_bypass)
7637 latency = DECL_BYPASS (decl)->latency;
7638 if (latency > max)
7639 max = latency;
7642 for (i = 0; (1 << i) <= max; i++)
7644 gcc_assert (i >= 0);
7645 fprintf (output_file, "\nconst int max_insn_queue_index = %d;\n\n",
7646 (1 << i) - 1);
7649 /* The function outputs switch cases for insn reservations using
7650 function *output_automata_list_code. */
7651 static void
7652 output_insn_code_cases (void (*output_automata_list_code)
7653 (automata_list_el_t))
7655 decl_t decl, decl2;
7656 int i, j;
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 = FALSE;
7664 for (i = 0; i < description->decls_num; i++)
7666 decl = description->decls [i];
7667 if (decl->mode == dm_insn_reserv
7668 && !DECL_INSN_RESERV (decl)->processed_p)
7670 for (j = i; j < description->decls_num; j++)
7672 decl2 = description->decls [j];
7673 if (decl2->mode == dm_insn_reserv
7674 && (DECL_INSN_RESERV (decl2)->important_automata_list
7675 == DECL_INSN_RESERV (decl)->important_automata_list))
7677 DECL_INSN_RESERV (decl2)->processed_p = TRUE;
7678 fprintf (output_file, " case %d: /* %s */\n",
7679 DECL_INSN_RESERV (decl2)->insn_num,
7680 DECL_INSN_RESERV (decl2)->name);
7683 (*output_automata_list_code)
7684 (DECL_INSN_RESERV (decl)->important_automata_list);
7690 /* The function outputs a code for evaluation of a minimal delay of
7691 issue of insns which have reservations in given AUTOMATA_LIST. */
7692 static void
7693 output_automata_list_min_issue_delay_code (automata_list_el_t automata_list)
7695 automata_list_el_t el;
7696 automaton_t automaton;
7698 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
7700 automaton = el->automaton;
7701 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
7702 output_min_issue_delay_vect_name (output_file, automaton);
7703 fprintf (output_file,
7704 (automaton->min_issue_delay_table_compression_factor != 1
7705 ? " [(" : " ["));
7706 output_translate_vect_name (output_file, automaton);
7707 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
7708 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7709 output_chip_member_name (output_file, automaton);
7710 fprintf (output_file, " * %d", automaton->insn_equiv_classes_num);
7711 if (automaton->min_issue_delay_table_compression_factor == 1)
7712 fprintf (output_file, "];\n");
7713 else
7715 fprintf (output_file, ") / %d];\n",
7716 automaton->min_issue_delay_table_compression_factor);
7717 fprintf (output_file, " %s = (%s >> (8 - (",
7718 TEMPORARY_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
7719 output_translate_vect_name (output_file, automaton);
7720 fprintf
7721 (output_file, " [%s] %% %d + 1) * %d)) & %d;\n",
7722 INTERNAL_INSN_CODE_NAME,
7723 automaton->min_issue_delay_table_compression_factor,
7724 8 / automaton->min_issue_delay_table_compression_factor,
7725 (1 << (8 / automaton->min_issue_delay_table_compression_factor))
7726 - 1);
7728 if (el == automata_list)
7729 fprintf (output_file, " %s = %s;\n",
7730 RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
7731 else
7733 fprintf (output_file, " if (%s > %s)\n",
7734 TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
7735 fprintf (output_file, " %s = %s;\n",
7736 RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
7739 fprintf (output_file, " break;\n\n");
7742 /* Output function `internal_min_issue_delay'. */
7743 static void
7744 output_internal_min_issue_delay_func (void)
7746 fprintf (output_file,
7747 "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
7748 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7749 CHIP_NAME, CHIP_PARAMETER_NAME);
7750 fprintf (output_file, "{\n int %s ATTRIBUTE_UNUSED;\n int %s = -1;\n",
7751 TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
7752 fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
7753 output_insn_code_cases (output_automata_list_min_issue_delay_code);
7754 fprintf (output_file,
7755 "\n default:\n %s = -1;\n break;\n }\n",
7756 RESULT_VARIABLE_NAME);
7757 fprintf (output_file, " return %s;\n", RESULT_VARIABLE_NAME);
7758 fprintf (output_file, "}\n\n");
7761 /* The function outputs a code changing state after issue of insns
7762 which have reservations in given AUTOMATA_LIST. */
7763 static void
7764 output_automata_list_transition_code (automata_list_el_t automata_list)
7766 automata_list_el_t el, next_el;
7768 fprintf (output_file, " {\n");
7769 if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
7770 for (el = automata_list;; el = next_el)
7772 next_el = el->next_automata_list_el;
7773 if (next_el == NULL)
7774 break;
7775 fprintf (output_file, " ");
7776 output_state_member_type (output_file, el->automaton);
7777 fprintf (output_file, " ");
7778 output_temp_chip_member_name (output_file, el->automaton);
7779 fprintf (output_file, ";\n");
7781 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
7782 if (comb_vect_p (el->automaton->trans_table))
7784 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
7785 output_trans_base_vect_name (output_file, el->automaton);
7786 fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
7787 output_chip_member_name (output_file, el->automaton);
7788 fprintf (output_file, "] + ");
7789 output_translate_vect_name (output_file, el->automaton);
7790 fprintf (output_file, " [%s];\n", INTERNAL_INSN_CODE_NAME);
7791 fprintf (output_file, " if (");
7792 output_trans_check_vect_name (output_file, el->automaton);
7793 fprintf (output_file, " [%s] != %s->",
7794 TEMPORARY_VARIABLE_NAME, CHIP_PARAMETER_NAME);
7795 output_chip_member_name (output_file, el->automaton);
7796 fprintf (output_file, ")\n");
7797 fprintf (output_file, " return %s (%s, %s);\n",
7798 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7799 CHIP_PARAMETER_NAME);
7800 fprintf (output_file, " else\n");
7801 fprintf (output_file, " ");
7802 if (el->next_automata_list_el != NULL)
7803 output_temp_chip_member_name (output_file, el->automaton);
7804 else
7806 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7807 output_chip_member_name (output_file, el->automaton);
7809 fprintf (output_file, " = ");
7810 output_trans_comb_vect_name (output_file, el->automaton);
7811 fprintf (output_file, " [%s];\n", TEMPORARY_VARIABLE_NAME);
7813 else
7815 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
7816 output_trans_full_vect_name (output_file, el->automaton);
7817 fprintf (output_file, " [");
7818 output_translate_vect_name (output_file, el->automaton);
7819 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
7820 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7821 output_chip_member_name (output_file, el->automaton);
7822 fprintf (output_file, " * %d];\n",
7823 el->automaton->insn_equiv_classes_num);
7824 fprintf (output_file, " if (%s >= %d)\n",
7825 TEMPORARY_VARIABLE_NAME, el->automaton->achieved_states_num);
7826 fprintf (output_file, " return %s (%s, %s);\n",
7827 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7828 CHIP_PARAMETER_NAME);
7829 fprintf (output_file, " else\n ");
7830 if (el->next_automata_list_el != NULL)
7831 output_temp_chip_member_name (output_file, el->automaton);
7832 else
7834 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7835 output_chip_member_name (output_file, el->automaton);
7837 fprintf (output_file, " = %s;\n", TEMPORARY_VARIABLE_NAME);
7839 if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
7840 for (el = automata_list;; el = next_el)
7842 next_el = el->next_automata_list_el;
7843 if (next_el == NULL)
7844 break;
7845 fprintf (output_file, " %s->", CHIP_PARAMETER_NAME);
7846 output_chip_member_name (output_file, el->automaton);
7847 fprintf (output_file, " = ");
7848 output_temp_chip_member_name (output_file, el->automaton);
7849 fprintf (output_file, ";\n");
7851 fprintf (output_file, " return -1;\n");
7852 fprintf (output_file, " }\n");
7855 /* Output function `internal_state_transition'. */
7856 static void
7857 output_internal_trans_func (void)
7859 fprintf (output_file,
7860 "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
7861 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7862 CHIP_NAME, CHIP_PARAMETER_NAME);
7863 fprintf (output_file, "{\n int %s ATTRIBUTE_UNUSED;\n", TEMPORARY_VARIABLE_NAME);
7864 fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
7865 output_insn_code_cases (output_automata_list_transition_code);
7866 fprintf (output_file, "\n default:\n return -1;\n }\n");
7867 fprintf (output_file, "}\n\n");
7870 /* Output code
7872 if (insn != 0)
7874 insn_code = dfa_insn_code (insn);
7875 if (insn_code > DFA__ADVANCE_CYCLE)
7876 return code;
7878 else
7879 insn_code = DFA__ADVANCE_CYCLE;
7881 where insn denotes INSN_NAME, insn_code denotes INSN_CODE_NAME, and
7882 code denotes CODE. */
7883 static void
7884 output_internal_insn_code_evaluation (const char *insn_name,
7885 const char *insn_code_name,
7886 int code)
7888 fprintf (output_file, "\n if (%s != 0)\n {\n", insn_name);
7889 fprintf (output_file, " %s = %s (%s);\n", insn_code_name,
7890 DFA_INSN_CODE_FUNC_NAME, insn_name);
7891 fprintf (output_file, " if (%s > %s)\n return %d;\n",
7892 insn_code_name, ADVANCE_CYCLE_VALUE_NAME, code);
7893 fprintf (output_file, " }\n else\n %s = %s;\n\n",
7894 insn_code_name, ADVANCE_CYCLE_VALUE_NAME);
7898 /* This function outputs `dfa_insn_code' and its helper function
7899 `dfa_insn_code_enlarge'. */
7900 static void
7901 output_dfa_insn_code_func (void)
7903 /* Emacs c-mode gets really confused if there's a { or } in column 0
7904 inside a string, so don't do that. */
7905 fprintf (output_file, "\
7906 static void\n\
7907 dfa_insn_code_enlarge (int uid)\n\
7908 {\n\
7909 int i = %s;\n\
7910 %s = 2 * uid;\n\
7911 %s = xrealloc (%s,\n\
7912 %s * sizeof(int));\n\
7913 for (; i < %s; i++)\n\
7914 %s[i] = -1;\n}\n\n",
7915 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
7916 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
7917 DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
7918 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
7919 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
7920 DFA_INSN_CODES_VARIABLE_NAME);
7921 fprintf (output_file, "\
7922 static inline int\n%s (rtx %s)\n\
7923 {\n\
7924 int uid = INSN_UID (%s);\n\
7925 int %s;\n\n",
7926 DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME,
7927 INSN_PARAMETER_NAME, INTERNAL_INSN_CODE_NAME);
7929 fprintf (output_file,
7930 " if (uid >= %s)\n dfa_insn_code_enlarge (uid);\n\n",
7931 DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
7932 fprintf (output_file, " %s = %s[uid];\n",
7933 INTERNAL_INSN_CODE_NAME, DFA_INSN_CODES_VARIABLE_NAME);
7934 fprintf (output_file, "\
7935 if (%s < 0)\n\
7936 {\n\
7937 %s = %s (%s);\n\
7938 %s[uid] = %s;\n\
7939 }\n",
7940 INTERNAL_INSN_CODE_NAME,
7941 INTERNAL_INSN_CODE_NAME,
7942 INTERNAL_DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME,
7943 DFA_INSN_CODES_VARIABLE_NAME, INTERNAL_INSN_CODE_NAME);
7944 fprintf (output_file, " return %s;\n}\n\n", INTERNAL_INSN_CODE_NAME);
7947 /* The function outputs PHR interface function `state_transition'. */
7948 static void
7949 output_trans_func (void)
7951 fprintf (output_file, "int\n%s (%s %s, rtx %s)\n",
7952 TRANSITION_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME,
7953 INSN_PARAMETER_NAME);
7954 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
7955 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
7956 INTERNAL_INSN_CODE_NAME, -1);
7957 fprintf (output_file, " return %s (%s, %s);\n}\n\n",
7958 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, STATE_NAME);
7961 /* Output function `min_issue_delay'. */
7962 static void
7963 output_min_issue_delay_func (void)
7965 fprintf (output_file, "int\n%s (%s %s, rtx %s)\n",
7966 MIN_ISSUE_DELAY_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME,
7967 INSN_PARAMETER_NAME);
7968 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
7969 fprintf (output_file, "\n if (%s != 0)\n {\n", INSN_PARAMETER_NAME);
7970 fprintf (output_file, " %s = %s (%s);\n", INTERNAL_INSN_CODE_NAME,
7971 DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME);
7972 fprintf (output_file, " if (%s > %s)\n return 0;\n",
7973 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
7974 fprintf (output_file, " }\n else\n %s = %s;\n",
7975 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
7976 fprintf (output_file, "\n return %s (%s, %s);\n",
7977 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7978 STATE_NAME);
7979 fprintf (output_file, "}\n\n");
7982 /* Output function `internal_dead_lock'. */
7983 static void
7984 output_internal_dead_lock_func (void)
7986 automaton_t automaton;
7988 fprintf (output_file, "static int\n%s (struct %s *ARG_UNUSED (%s))\n",
7989 INTERNAL_DEAD_LOCK_FUNC_NAME, CHIP_NAME, CHIP_PARAMETER_NAME);
7990 fprintf (output_file, "{\n");
7991 for (automaton = description->first_automaton;
7992 automaton != NULL;
7993 automaton = automaton->next_automaton)
7994 if (automaton->locked_states)
7996 fprintf (output_file, " if (");
7997 output_dead_lock_vect_name (output_file, automaton);
7998 fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
7999 output_chip_member_name (output_file, automaton);
8000 fprintf (output_file, "])\n return 1/* TRUE */;\n");
8002 fprintf (output_file, " return 0/* FALSE */;\n}\n\n");
8005 /* The function outputs PHR interface function `state_dead_lock_p'. */
8006 static void
8007 output_dead_lock_func (void)
8009 fprintf (output_file, "int\n%s (%s %s)\n",
8010 DEAD_LOCK_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME);
8011 fprintf (output_file, "{\n return %s (%s);\n}\n\n",
8012 INTERNAL_DEAD_LOCK_FUNC_NAME, STATE_NAME);
8015 /* Output function `internal_reset'. */
8016 static void
8017 output_internal_reset_func (void)
8019 fprintf (output_file, "static inline void\n%s (struct %s *%s)\n",
8020 INTERNAL_RESET_FUNC_NAME, CHIP_NAME, CHIP_PARAMETER_NAME);
8021 fprintf (output_file, "{\n memset (%s, 0, sizeof (struct %s));\n}\n\n",
8022 CHIP_PARAMETER_NAME, CHIP_NAME);
8025 /* The function outputs PHR interface function `state_size'. */
8026 static void
8027 output_size_func (void)
8029 fprintf (output_file, "int\n%s (void)\n", SIZE_FUNC_NAME);
8030 fprintf (output_file, "{\n return sizeof (struct %s);\n}\n\n", CHIP_NAME);
8033 /* The function outputs PHR interface function `state_reset'. */
8034 static void
8035 output_reset_func (void)
8037 fprintf (output_file, "void\n%s (%s %s)\n",
8038 RESET_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME);
8039 fprintf (output_file, "{\n %s (%s);\n}\n\n", INTERNAL_RESET_FUNC_NAME,
8040 STATE_NAME);
8043 /* Output function `min_insn_conflict_delay'. */
8044 static void
8045 output_min_insn_conflict_delay_func (void)
8047 fprintf (output_file,
8048 "int\n%s (%s %s, rtx %s, rtx %s)\n",
8049 MIN_INSN_CONFLICT_DELAY_FUNC_NAME, STATE_TYPE_NAME,
8050 STATE_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8051 fprintf (output_file, "{\n struct %s %s;\n int %s, %s, transition;\n",
8052 CHIP_NAME, CHIP_NAME, INTERNAL_INSN_CODE_NAME,
8053 INTERNAL_INSN2_CODE_NAME);
8054 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8055 INTERNAL_INSN_CODE_NAME, 0);
8056 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
8057 INTERNAL_INSN2_CODE_NAME, 0);
8058 fprintf (output_file, " memcpy (&%s, %s, sizeof (%s));\n",
8059 CHIP_NAME, STATE_NAME, CHIP_NAME);
8060 fprintf (output_file, " %s (&%s);\n", INTERNAL_RESET_FUNC_NAME, CHIP_NAME);
8061 fprintf (output_file, " transition = %s (%s, &%s);\n",
8062 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME);
8063 fprintf (output_file, " gcc_assert (transition <= 0);\n");
8064 fprintf (output_file, " return %s (%s, &%s);\n",
8065 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN2_CODE_NAME,
8066 CHIP_NAME);
8067 fprintf (output_file, "}\n\n");
8070 /* Output function `internal_insn_latency'. */
8071 static void
8072 output_internal_insn_latency_func (void)
8074 decl_t decl;
8075 struct bypass_decl *bypass;
8076 int i, j, col;
8077 const char *tabletype = "unsigned char";
8079 /* Find the smallest integer type that can hold all the default
8080 latency values. */
8081 for (i = 0; i < description->decls_num; i++)
8082 if (description->decls[i]->mode == dm_insn_reserv)
8084 decl = description->decls[i];
8085 if (DECL_INSN_RESERV (decl)->default_latency > UCHAR_MAX
8086 && tabletype[0] != 'i') /* Don't shrink it. */
8087 tabletype = "unsigned short";
8088 if (DECL_INSN_RESERV (decl)->default_latency > USHRT_MAX)
8089 tabletype = "int";
8092 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",
8093 INTERNAL_INSN_LATENCY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8094 INTERNAL_INSN2_CODE_NAME, INSN_PARAMETER_NAME,
8095 INSN2_PARAMETER_NAME);
8096 fprintf (output_file, "{\n");
8098 if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8100 fputs (" return 0;\n}\n\n", output_file);
8101 return;
8104 fprintf (output_file, " static const %s default_latencies[] =\n {",
8105 tabletype);
8107 for (i = 0, j = 0, col = 7; i < description->decls_num; i++)
8108 if (description->decls[i]->mode == dm_insn_reserv
8109 && description->decls[i] != advance_cycle_insn_decl)
8111 if ((col = (col+1) % 8) == 0)
8112 fputs ("\n ", output_file);
8113 decl = description->decls[i];
8114 gcc_assert (j++ == DECL_INSN_RESERV (decl)->insn_num);
8115 fprintf (output_file, "% 4d,",
8116 DECL_INSN_RESERV (decl)->default_latency);
8118 gcc_assert (j == DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
8119 fputs ("\n };\n", output_file);
8121 fprintf (output_file, " if (%s >= %s || %s >= %s)\n return 0;\n",
8122 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8123 INTERNAL_INSN2_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8125 fprintf (output_file, " switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8126 for (i = 0; i < description->decls_num; i++)
8127 if (description->decls[i]->mode == dm_insn_reserv
8128 && DECL_INSN_RESERV (description->decls[i])->bypass_list)
8130 decl = description->decls [i];
8131 fprintf (output_file,
8132 " case %d:\n switch (%s)\n {\n",
8133 DECL_INSN_RESERV (decl)->insn_num,
8134 INTERNAL_INSN2_CODE_NAME);
8135 for (bypass = DECL_INSN_RESERV (decl)->bypass_list;
8136 bypass != NULL;
8137 bypass = bypass->next)
8139 gcc_assert (bypass->in_insn_reserv->insn_num
8140 != (DECL_INSN_RESERV
8141 (advance_cycle_insn_decl)->insn_num));
8142 fprintf (output_file, " case %d:\n",
8143 bypass->in_insn_reserv->insn_num);
8144 if (bypass->bypass_guard_name == NULL)
8145 fprintf (output_file, " return %d;\n",
8146 bypass->latency);
8147 else
8149 fprintf (output_file,
8150 " if (%s (%s, %s))\n",
8151 bypass->bypass_guard_name, INSN_PARAMETER_NAME,
8152 INSN2_PARAMETER_NAME);
8153 fprintf (output_file,
8154 " return %d;\n break;\n",
8155 bypass->latency);
8158 fputs (" }\n break;\n", output_file);
8161 fprintf (output_file, " }\n return default_latencies[%s];\n}\n\n",
8162 INTERNAL_INSN_CODE_NAME);
8165 /* The function outputs PHR interface function `insn_latency'. */
8166 static void
8167 output_insn_latency_func (void)
8169 fprintf (output_file, "int\n%s (rtx %s, rtx %s)\n",
8170 INSN_LATENCY_FUNC_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8171 fprintf (output_file, "{\n int %s, %s;\n",
8172 INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME);
8173 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8174 INTERNAL_INSN_CODE_NAME, 0);
8175 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
8176 INTERNAL_INSN2_CODE_NAME, 0);
8177 fprintf (output_file, " return %s (%s, %s, %s, %s);\n}\n\n",
8178 INTERNAL_INSN_LATENCY_FUNC_NAME,
8179 INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME,
8180 INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8183 /* The function outputs PHR interface function `print_reservation'. */
8184 static void
8185 output_print_reservation_func (void)
8187 decl_t decl;
8188 int i, j;
8190 fprintf (output_file,
8191 "void\n%s (FILE *%s, rtx %s ATTRIBUTE_UNUSED)\n{\n",
8192 PRINT_RESERVATION_FUNC_NAME, FILE_PARAMETER_NAME,
8193 INSN_PARAMETER_NAME);
8195 if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8197 fprintf (output_file, " fputs (\"%s\", %s);\n}\n\n",
8198 NOTHING_NAME, FILE_PARAMETER_NAME);
8199 return;
8203 fputs (" static const char *const reservation_names[] =\n {",
8204 output_file);
8206 for (i = 0, j = 0; i < description->decls_num; i++)
8208 decl = description->decls [i];
8209 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
8211 gcc_assert (j == DECL_INSN_RESERV (decl)->insn_num);
8212 j++;
8214 fprintf (output_file, "\n \"%s\",",
8215 regexp_representation (DECL_INSN_RESERV (decl)->regexp));
8216 finish_regexp_representation ();
8219 gcc_assert (j == DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
8221 fprintf (output_file, "\n \"%s\"\n };\n int %s;\n\n",
8222 NOTHING_NAME, INTERNAL_INSN_CODE_NAME);
8224 fprintf (output_file, " if (%s == 0)\n %s = %s;\n",
8225 INSN_PARAMETER_NAME,
8226 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8227 fprintf (output_file, " else\n\
8228 {\n\
8229 %s = %s (%s);\n\
8230 if (%s > %s)\n\
8231 %s = %s;\n\
8232 }\n",
8233 INTERNAL_INSN_CODE_NAME, DFA_INSN_CODE_FUNC_NAME,
8234 INSN_PARAMETER_NAME,
8235 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8236 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8238 fprintf (output_file, " fputs (reservation_names[%s], %s);\n}\n\n",
8239 INTERNAL_INSN_CODE_NAME, FILE_PARAMETER_NAME);
8242 /* The following function is used to sort unit declaration by their
8243 names. */
8244 static int
8245 units_cmp (const void *unit1, const void *unit2)
8247 const_unit_decl_t const u1 = *(const_unit_decl_t const*) unit1;
8248 const_unit_decl_t const u2 = *(const_unit_decl_t const*) unit2;
8250 return strcmp (u1->name, u2->name);
8253 /* The following macro value is name of struct containing unit name
8254 and unit code. */
8255 #define NAME_CODE_STRUCT_NAME "name_code"
8257 /* The following macro value is name of table of struct name_code. */
8258 #define NAME_CODE_TABLE_NAME "name_code_table"
8260 /* The following macro values are member names for struct name_code. */
8261 #define NAME_MEMBER_NAME "name"
8262 #define CODE_MEMBER_NAME "code"
8264 /* The following macro values are local variable names for function
8265 `get_cpu_unit_code'. */
8266 #define CMP_VARIABLE_NAME "cmp"
8267 #define LOW_VARIABLE_NAME "l"
8268 #define MIDDLE_VARIABLE_NAME "m"
8269 #define HIGH_VARIABLE_NAME "h"
8271 /* The following function outputs function to obtain internal cpu unit
8272 code by the cpu unit name. */
8273 static void
8274 output_get_cpu_unit_code_func (void)
8276 int i;
8277 unit_decl_t *units;
8279 fprintf (output_file, "int\n%s (const char *%s)\n",
8280 GET_CPU_UNIT_CODE_FUNC_NAME, CPU_UNIT_NAME_PARAMETER_NAME);
8281 fprintf (output_file, "{\n struct %s {const char *%s; int %s;};\n",
8282 NAME_CODE_STRUCT_NAME, NAME_MEMBER_NAME, CODE_MEMBER_NAME);
8283 fprintf (output_file, " int %s, %s, %s, %s;\n", CMP_VARIABLE_NAME,
8284 LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8285 fprintf (output_file, " static struct %s %s [] =\n {\n",
8286 NAME_CODE_STRUCT_NAME, NAME_CODE_TABLE_NAME);
8287 units = xmalloc (sizeof (unit_decl_t) * description->units_num);
8288 memcpy (units, units_array, sizeof (unit_decl_t) * description->units_num);
8289 qsort (units, description->units_num, sizeof (unit_decl_t), units_cmp);
8290 for (i = 0; i < description->units_num; i++)
8291 if (units [i]->query_p)
8292 fprintf (output_file, " {\"%s\", %d},\n",
8293 units[i]->name, units[i]->query_num);
8294 fprintf (output_file, " };\n\n");
8295 fprintf (output_file, " /* The following is binary search: */\n");
8296 fprintf (output_file, " %s = 0;\n", LOW_VARIABLE_NAME);
8297 fprintf (output_file, " %s = sizeof (%s) / sizeof (struct %s) - 1;\n",
8298 HIGH_VARIABLE_NAME, NAME_CODE_TABLE_NAME, NAME_CODE_STRUCT_NAME);
8299 fprintf (output_file, " while (%s <= %s)\n {\n",
8300 LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8301 fprintf (output_file, " %s = (%s + %s) / 2;\n",
8302 MIDDLE_VARIABLE_NAME, LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8303 fprintf (output_file, " %s = strcmp (%s, %s [%s].%s);\n",
8304 CMP_VARIABLE_NAME, CPU_UNIT_NAME_PARAMETER_NAME,
8305 NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, NAME_MEMBER_NAME);
8306 fprintf (output_file, " if (%s < 0)\n", CMP_VARIABLE_NAME);
8307 fprintf (output_file, " %s = %s - 1;\n",
8308 HIGH_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
8309 fprintf (output_file, " else if (%s > 0)\n", CMP_VARIABLE_NAME);
8310 fprintf (output_file, " %s = %s + 1;\n",
8311 LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
8312 fprintf (output_file, " else\n");
8313 fprintf (output_file, " return %s [%s].%s;\n }\n",
8314 NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, CODE_MEMBER_NAME);
8315 fprintf (output_file, " return -1;\n}\n\n");
8316 free (units);
8319 /* The following function outputs function to check reservation of cpu
8320 unit (its internal code will be passed as the function argument) in
8321 given cpu state. */
8322 static void
8323 output_cpu_unit_reservation_p (void)
8325 automaton_t automaton;
8327 fprintf (output_file, "int\n%s (%s %s, int %s)\n",
8328 CPU_UNIT_RESERVATION_P_FUNC_NAME,
8329 STATE_TYPE_NAME, STATE_NAME,
8330 CPU_CODE_PARAMETER_NAME);
8331 fprintf (output_file, "{\n gcc_assert (%s >= 0 && %s < %d);\n",
8332 CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME,
8333 description->query_units_num);
8334 if (description->query_units_num > 0)
8335 for (automaton = description->first_automaton;
8336 automaton != NULL;
8337 automaton = automaton->next_automaton)
8339 fprintf (output_file, " if ((");
8340 output_reserved_units_table_name (output_file, automaton);
8341 fprintf (output_file, " [((struct %s *) %s)->", CHIP_NAME, STATE_NAME);
8342 output_chip_member_name (output_file, automaton);
8343 fprintf (output_file, " * %d + %s / 8] >> (%s %% 8)) & 1)\n",
8344 (description->query_units_num + 7) / 8,
8345 CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME);
8346 fprintf (output_file, " return 1;\n");
8348 fprintf (output_file, " return 0;\n}\n\n");
8351 /* The following function outputs a function to check if insn
8352 has a dfa reservation. */
8353 static void
8354 output_insn_has_dfa_reservation_p (void)
8356 fprintf (output_file,
8357 "bool\n%s (rtx %s ATTRIBUTE_UNUSED)\n{\n",
8358 INSN_HAS_DFA_RESERVATION_P_FUNC_NAME,
8359 INSN_PARAMETER_NAME);
8361 if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8363 fprintf (output_file, " return false;\n}\n\n");
8364 return;
8367 fprintf (output_file, " int %s;\n\n", INTERNAL_INSN_CODE_NAME);
8369 fprintf (output_file, " if (%s == 0)\n %s = %s;\n",
8370 INSN_PARAMETER_NAME,
8371 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8372 fprintf (output_file, " else\n\
8373 {\n\
8374 %s = %s (%s);\n\
8375 if (%s > %s)\n\
8376 %s = %s;\n\
8377 }\n\n",
8378 INTERNAL_INSN_CODE_NAME, DFA_INSN_CODE_FUNC_NAME,
8379 INSN_PARAMETER_NAME,
8380 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8381 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8383 fprintf (output_file, " return %s != %s;\n}\n\n",
8384 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8387 /* The function outputs PHR interface functions `dfa_clean_insn_cache'
8388 and 'dfa_clear_single_insn_cache'. */
8389 static void
8390 output_dfa_clean_insn_cache_func (void)
8392 fprintf (output_file,
8393 "void\n%s (void)\n{\n int %s;\n\n",
8394 DFA_CLEAN_INSN_CACHE_FUNC_NAME, I_VARIABLE_NAME);
8395 fprintf (output_file,
8396 " for (%s = 0; %s < %s; %s++)\n %s [%s] = -1;\n}\n\n",
8397 I_VARIABLE_NAME, I_VARIABLE_NAME,
8398 DFA_INSN_CODES_LENGTH_VARIABLE_NAME, I_VARIABLE_NAME,
8399 DFA_INSN_CODES_VARIABLE_NAME, I_VARIABLE_NAME);
8401 fprintf (output_file,
8402 "void\n%s (rtx %s)\n{\n int %s;\n\n",
8403 DFA_CLEAR_SINGLE_INSN_CACHE_FUNC_NAME, INSN_PARAMETER_NAME,
8404 I_VARIABLE_NAME);
8405 fprintf (output_file,
8406 " %s = INSN_UID (%s);\n if (%s < %s)\n %s [%s] = -1;\n}\n\n",
8407 I_VARIABLE_NAME, INSN_PARAMETER_NAME, I_VARIABLE_NAME,
8408 DFA_INSN_CODES_LENGTH_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
8409 I_VARIABLE_NAME);
8412 /* The function outputs PHR interface function `dfa_start'. */
8413 static void
8414 output_dfa_start_func (void)
8416 fprintf (output_file,
8417 "void\n%s (void)\n{\n %s = get_max_uid ();\n",
8418 DFA_START_FUNC_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8419 fprintf (output_file, " %s = xmalloc (%s * sizeof (int));\n",
8420 DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8421 fprintf (output_file, " %s ();\n}\n\n", DFA_CLEAN_INSN_CACHE_FUNC_NAME);
8424 /* The function outputs PHR interface function `dfa_finish'. */
8425 static void
8426 output_dfa_finish_func (void)
8428 fprintf (output_file, "void\n%s (void)\n{\n free (%s);\n}\n\n",
8429 DFA_FINISH_FUNC_NAME, DFA_INSN_CODES_VARIABLE_NAME);
8434 /* The page contains code for output description file (readable
8435 representation of original description and generated DFA(s). */
8437 /* The function outputs string representation of IR reservation. */
8438 static void
8439 output_regexp (regexp_t regexp)
8441 fprintf (output_description_file, "%s", regexp_representation (regexp));
8442 finish_regexp_representation ();
8445 /* Output names of units in LIST separated by comma. */
8446 static void
8447 output_unit_set_el_list (unit_set_el_t list)
8449 unit_set_el_t el;
8451 for (el = list; el != NULL; el = el->next_unit_set_el)
8453 if (el != list)
8454 fprintf (output_description_file, ", ");
8455 fprintf (output_description_file, "%s", el->unit_decl->name);
8459 /* Output patterns in LIST separated by comma. */
8460 static void
8461 output_pattern_set_el_list (pattern_set_el_t list)
8463 pattern_set_el_t el;
8464 int i;
8466 for (el = list; el != NULL; el = el->next_pattern_set_el)
8468 if (el != list)
8469 fprintf (output_description_file, ", ");
8470 for (i = 0; i < el->units_num; i++)
8471 fprintf (output_description_file, (i == 0 ? "%s" : " %s"),
8472 el->unit_decls [i]->name);
8476 /* The function outputs string representation of IR define_reservation
8477 and define_insn_reservation. */
8478 static void
8479 output_description (void)
8481 decl_t decl;
8482 int i;
8484 for (i = 0; i < description->decls_num; i++)
8486 decl = description->decls [i];
8487 if (decl->mode == dm_unit)
8489 if (DECL_UNIT (decl)->excl_list != NULL)
8491 fprintf (output_description_file, "unit %s exlusion_set: ",
8492 DECL_UNIT (decl)->name);
8493 output_unit_set_el_list (DECL_UNIT (decl)->excl_list);
8494 fprintf (output_description_file, "\n");
8496 if (DECL_UNIT (decl)->presence_list != NULL)
8498 fprintf (output_description_file, "unit %s presence_set: ",
8499 DECL_UNIT (decl)->name);
8500 output_pattern_set_el_list (DECL_UNIT (decl)->presence_list);
8501 fprintf (output_description_file, "\n");
8503 if (DECL_UNIT (decl)->final_presence_list != NULL)
8505 fprintf (output_description_file, "unit %s final_presence_set: ",
8506 DECL_UNIT (decl)->name);
8507 output_pattern_set_el_list
8508 (DECL_UNIT (decl)->final_presence_list);
8509 fprintf (output_description_file, "\n");
8511 if (DECL_UNIT (decl)->absence_list != NULL)
8513 fprintf (output_description_file, "unit %s absence_set: ",
8514 DECL_UNIT (decl)->name);
8515 output_pattern_set_el_list (DECL_UNIT (decl)->absence_list);
8516 fprintf (output_description_file, "\n");
8518 if (DECL_UNIT (decl)->final_absence_list != NULL)
8520 fprintf (output_description_file, "unit %s final_absence_set: ",
8521 DECL_UNIT (decl)->name);
8522 output_pattern_set_el_list
8523 (DECL_UNIT (decl)->final_absence_list);
8524 fprintf (output_description_file, "\n");
8528 fprintf (output_description_file, "\n");
8529 for (i = 0; i < description->decls_num; i++)
8531 decl = description->decls [i];
8532 if (decl->mode == dm_reserv)
8534 fprintf (output_description_file, "reservation %s: ",
8535 DECL_RESERV (decl)->name);
8536 output_regexp (DECL_RESERV (decl)->regexp);
8537 fprintf (output_description_file, "\n");
8539 else if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
8541 fprintf (output_description_file, "insn reservation %s ",
8542 DECL_INSN_RESERV (decl)->name);
8543 print_rtl (output_description_file,
8544 DECL_INSN_RESERV (decl)->condexp);
8545 fprintf (output_description_file, ": ");
8546 output_regexp (DECL_INSN_RESERV (decl)->regexp);
8547 fprintf (output_description_file, "\n");
8549 else if (decl->mode == dm_bypass)
8550 fprintf (output_description_file, "bypass %d %s %s\n",
8551 DECL_BYPASS (decl)->latency,
8552 DECL_BYPASS (decl)->out_insn_name,
8553 DECL_BYPASS (decl)->in_insn_name);
8555 fprintf (output_description_file, "\n\f\n");
8558 /* The function outputs name of AUTOMATON. */
8559 static void
8560 output_automaton_name (FILE *f, automaton_t automaton)
8562 if (automaton->corresponding_automaton_decl == NULL)
8563 fprintf (f, "#%d", automaton->automaton_order_num);
8564 else
8565 fprintf (f, "`%s'", automaton->corresponding_automaton_decl->name);
8568 /* Maximal length of line for pretty printing into description
8569 file. */
8570 #define MAX_LINE_LENGTH 70
8572 /* The function outputs units name belonging to AUTOMATON. */
8573 static void
8574 output_automaton_units (automaton_t automaton)
8576 decl_t decl;
8577 const char *name;
8578 int curr_line_length;
8579 int there_is_an_automaton_unit;
8580 int i;
8582 fprintf (output_description_file, "\n Corresponding units:\n");
8583 fprintf (output_description_file, " ");
8584 curr_line_length = 4;
8585 there_is_an_automaton_unit = 0;
8586 for (i = 0; i < description->decls_num; i++)
8588 decl = description->decls [i];
8589 if (decl->mode == dm_unit
8590 && (DECL_UNIT (decl)->corresponding_automaton_num
8591 == automaton->automaton_order_num))
8593 there_is_an_automaton_unit = 1;
8594 name = DECL_UNIT (decl)->name;
8595 if (curr_line_length + strlen (name) + 1 > MAX_LINE_LENGTH )
8597 curr_line_length = strlen (name) + 4;
8598 fprintf (output_description_file, "\n ");
8600 else
8602 curr_line_length += strlen (name) + 1;
8603 fprintf (output_description_file, " ");
8605 fprintf (output_description_file, "%s", name);
8608 if (!there_is_an_automaton_unit)
8609 fprintf (output_description_file, "<None>");
8610 fprintf (output_description_file, "\n\n");
8613 /* The following variable is used for forming array of all possible cpu unit
8614 reservations described by the current DFA state. */
8615 static VEC(reserv_sets_t,heap) *state_reservs;
8617 /* The function forms `state_reservs' for STATE. */
8618 static void
8619 add_state_reservs (state_t state)
8621 alt_state_t curr_alt_state;
8623 if (state->component_states != NULL)
8624 for (curr_alt_state = state->component_states;
8625 curr_alt_state != NULL;
8626 curr_alt_state = curr_alt_state->next_sorted_alt_state)
8627 add_state_reservs (curr_alt_state->state);
8628 else
8629 VEC_safe_push (reserv_sets_t,heap, state_reservs, state->reservs);
8632 /* The function outputs readable representation of all out arcs of
8633 STATE. */
8634 static void
8635 output_state_arcs (state_t state)
8637 arc_t arc;
8638 ainsn_t ainsn;
8639 const char *insn_name;
8640 int curr_line_length;
8642 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
8644 ainsn = arc->insn;
8645 gcc_assert (ainsn->first_insn_with_same_reservs);
8646 fprintf (output_description_file, " ");
8647 curr_line_length = 7;
8648 fprintf (output_description_file, "%2d: ", ainsn->insn_equiv_class_num);
8651 insn_name = ainsn->insn_reserv_decl->name;
8652 if (curr_line_length + strlen (insn_name) > MAX_LINE_LENGTH)
8654 if (ainsn != arc->insn)
8656 fprintf (output_description_file, ",\n ");
8657 curr_line_length = strlen (insn_name) + 6;
8659 else
8660 curr_line_length += strlen (insn_name);
8662 else
8664 curr_line_length += strlen (insn_name);
8665 if (ainsn != arc->insn)
8667 curr_line_length += 2;
8668 fprintf (output_description_file, ", ");
8671 fprintf (output_description_file, "%s", insn_name);
8672 ainsn = ainsn->next_same_reservs_insn;
8674 while (ainsn != NULL);
8675 fprintf (output_description_file, " %d \n",
8676 arc->to_state->order_state_num);
8678 fprintf (output_description_file, "\n");
8681 /* The following function is used for sorting possible cpu unit
8682 reservation of a DFA state. */
8683 static int
8684 state_reservs_cmp (const void *reservs_ptr_1, const void *reservs_ptr_2)
8686 return reserv_sets_cmp (*(const_reserv_sets_t const*) reservs_ptr_1,
8687 *(const_reserv_sets_t const*) reservs_ptr_2);
8690 /* The following function is used for sorting possible cpu unit
8691 reservation of a DFA state. */
8692 static void
8693 remove_state_duplicate_reservs (void)
8695 size_t i, j;
8697 for (i = 1, j = 0; i < VEC_length (reserv_sets_t, state_reservs); i++)
8698 if (reserv_sets_cmp (VEC_index (reserv_sets_t, state_reservs, j),
8699 VEC_index (reserv_sets_t, state_reservs, i)))
8701 j++;
8702 VEC_replace (reserv_sets_t, state_reservs, j,
8703 VEC_index (reserv_sets_t, state_reservs, i));
8705 VEC_truncate (reserv_sets_t, state_reservs, j + 1);
8708 /* The following function output readable representation of DFA(s)
8709 state used for fast recognition of pipeline hazards. State is
8710 described by possible (current and scheduled) cpu unit
8711 reservations. */
8712 static void
8713 output_state (state_t state)
8715 size_t i;
8717 state_reservs = 0;
8719 fprintf (output_description_file, " State #%d", state->order_state_num);
8720 fprintf (output_description_file,
8721 state->new_cycle_p ? " (new cycle)\n" : "\n");
8722 add_state_reservs (state);
8723 qsort (VEC_address (reserv_sets_t, state_reservs),
8724 VEC_length (reserv_sets_t, state_reservs),
8725 sizeof (reserv_sets_t), state_reservs_cmp);
8726 remove_state_duplicate_reservs ();
8727 for (i = 1; i < VEC_length (reserv_sets_t, state_reservs); i++)
8729 fprintf (output_description_file, " ");
8730 output_reserv_sets (output_description_file,
8731 VEC_index (reserv_sets_t, state_reservs, i));
8732 fprintf (output_description_file, "\n");
8734 fprintf (output_description_file, "\n");
8735 output_state_arcs (state);
8736 VEC_free (reserv_sets_t,heap, state_reservs);
8739 /* The following function output readable representation of
8740 DFAs used for fast recognition of pipeline hazards. */
8741 static void
8742 output_automaton_descriptions (void)
8744 automaton_t automaton;
8746 for (automaton = description->first_automaton;
8747 automaton != NULL;
8748 automaton = automaton->next_automaton)
8750 fprintf (output_description_file, "\nAutomaton ");
8751 output_automaton_name (output_description_file, automaton);
8752 fprintf (output_description_file, "\n");
8753 output_automaton_units (automaton);
8754 pass_states (automaton, output_state);
8760 /* The page contains top level function for generation DFA(s) used for
8761 PHR. */
8763 /* The function outputs statistics about work of different phases of
8764 DFA generator. */
8765 static void
8766 output_statistics (FILE *f)
8768 automaton_t automaton;
8769 int states_num;
8770 #ifndef NDEBUG
8771 int transition_comb_vect_els = 0;
8772 int transition_full_vect_els = 0;
8773 int min_issue_delay_vect_els = 0;
8774 int locked_states = 0;
8775 #endif
8777 for (automaton = description->first_automaton;
8778 automaton != NULL;
8779 automaton = automaton->next_automaton)
8781 fprintf (f, "\nAutomaton ");
8782 output_automaton_name (f, automaton);
8783 fprintf (f, "\n %5d NDFA states, %5d NDFA arcs\n",
8784 automaton->NDFA_states_num, automaton->NDFA_arcs_num);
8785 fprintf (f, " %5d DFA states, %5d DFA arcs\n",
8786 automaton->DFA_states_num, automaton->DFA_arcs_num);
8787 states_num = automaton->DFA_states_num;
8788 if (!no_minimization_flag)
8790 fprintf (f, " %5d minimal DFA states, %5d minimal DFA arcs\n",
8791 automaton->minimal_DFA_states_num,
8792 automaton->minimal_DFA_arcs_num);
8793 states_num = automaton->minimal_DFA_states_num;
8795 fprintf (f, " %5d all insns %5d insn equivalence classes\n",
8796 description->insns_num, automaton->insn_equiv_classes_num);
8797 fprintf (f, " %d locked states\n", automaton->locked_states);
8798 #ifndef NDEBUG
8799 fprintf
8800 (f, "%5ld transition comb vector els, %5ld trans table els: %s\n",
8801 (long) VEC_length (vect_el_t, automaton->trans_table->comb_vect),
8802 (long) VEC_length (vect_el_t, automaton->trans_table->full_vect),
8803 (comb_vect_p (automaton->trans_table)
8804 ? "use comb vect" : "use simple vect"));
8805 fprintf
8806 (f, "%5ld min delay table els, compression factor %d\n",
8807 (long) states_num * automaton->insn_equiv_classes_num,
8808 automaton->min_issue_delay_table_compression_factor);
8809 transition_comb_vect_els
8810 += VEC_length (vect_el_t, automaton->trans_table->comb_vect);
8811 transition_full_vect_els
8812 += VEC_length (vect_el_t, automaton->trans_table->full_vect);
8813 min_issue_delay_vect_els
8814 += states_num * automaton->insn_equiv_classes_num;
8815 locked_states
8816 += automaton->locked_states;
8817 #endif
8819 #ifndef NDEBUG
8820 fprintf (f, "\n%5d all allocated states, %5d all allocated arcs\n",
8821 allocated_states_num, allocated_arcs_num);
8822 fprintf (f, "%5d all allocated alternative states\n",
8823 allocated_alt_states_num);
8824 fprintf (f, "%5d all transition comb vector els, %5d all trans table els\n",
8825 transition_comb_vect_els, transition_full_vect_els);
8826 fprintf (f, "%5d all min delay table els\n", min_issue_delay_vect_els);
8827 fprintf (f, "%5d all locked states\n", locked_states);
8828 #endif
8831 /* The function output times of work of different phases of DFA
8832 generator. */
8833 static void
8834 output_time_statistics (FILE *f)
8836 fprintf (f, "\n transformation: ");
8837 print_active_time (f, transform_time);
8838 fprintf (f, (!ndfa_flag ? ", building DFA: " : ", building NDFA: "));
8839 print_active_time (f, NDFA_time);
8840 if (ndfa_flag)
8842 fprintf (f, ", NDFA -> DFA: ");
8843 print_active_time (f, NDFA_to_DFA_time);
8845 fprintf (f, "\n DFA minimization: ");
8846 print_active_time (f, minimize_time);
8847 fprintf (f, ", making insn equivalence: ");
8848 print_active_time (f, equiv_time);
8849 fprintf (f, "\n all automaton generation: ");
8850 print_active_time (f, automaton_generation_time);
8851 fprintf (f, ", output: ");
8852 print_active_time (f, output_time);
8853 fprintf (f, "\n");
8856 /* The function generates DFA (deterministic finite state automaton)
8857 for fast recognition of pipeline hazards. No errors during
8858 checking must be fixed before this function call. */
8859 static void
8860 generate (void)
8862 automata_num = split_argument;
8863 if (description->units_num < automata_num)
8864 automata_num = description->units_num;
8865 initiate_states ();
8866 initiate_arcs ();
8867 initiate_automata_lists ();
8868 initiate_pass_states ();
8869 initiate_excl_sets ();
8870 initiate_presence_absence_pattern_sets ();
8871 automaton_generation_time = create_ticker ();
8872 create_automata ();
8873 ticker_off (&automaton_generation_time);
8878 /* This page mainly contains top level functions of pipeline hazards
8879 description translator. */
8881 /* The following macro value is suffix of name of description file of
8882 pipeline hazards description translator. */
8883 #define STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX ".dfa"
8885 /* The function returns suffix of given file name. The returned
8886 string can not be changed. */
8887 static const char *
8888 file_name_suffix (const char *file_name)
8890 const char *last_period;
8892 for (last_period = NULL; *file_name != '\0'; file_name++)
8893 if (*file_name == '.')
8894 last_period = file_name;
8895 return (last_period == NULL ? file_name : last_period);
8898 /* The function returns base name of given file name, i.e. pointer to
8899 first char after last `/' (or `\' for WIN32) in given file name,
8900 given file name itself if the directory name is absent. The
8901 returned string can not be changed. */
8902 static const char *
8903 base_file_name (const char *file_name)
8905 int directory_name_length;
8907 directory_name_length = strlen (file_name);
8908 #ifdef WIN32
8909 while (directory_name_length >= 0 && file_name[directory_name_length] != '/'
8910 && file_name[directory_name_length] != '\\')
8911 #else
8912 while (directory_name_length >= 0 && file_name[directory_name_length] != '/')
8913 #endif
8914 directory_name_length--;
8915 return file_name + directory_name_length + 1;
8918 /* The following is top level function to initialize the work of
8919 pipeline hazards description translator. */
8920 static void
8921 initiate_automaton_gen (int argc, char **argv)
8923 const char *base_name;
8924 int i;
8926 ndfa_flag = 0;
8927 split_argument = 0; /* default value */
8928 no_minimization_flag = 0;
8929 time_flag = 0;
8930 stats_flag = 0;
8931 v_flag = 0;
8932 w_flag = 0;
8933 progress_flag = 0;
8934 for (i = 2; i < argc; i++)
8935 if (strcmp (argv [i], NO_MINIMIZATION_OPTION) == 0)
8936 no_minimization_flag = 1;
8937 else if (strcmp (argv [i], TIME_OPTION) == 0)
8938 time_flag = 1;
8939 else if (strcmp (argv [i], STATS_OPTION) == 0)
8940 stats_flag = 1;
8941 else if (strcmp (argv [i], V_OPTION) == 0)
8942 v_flag = 1;
8943 else if (strcmp (argv [i], W_OPTION) == 0)
8944 w_flag = 1;
8945 else if (strcmp (argv [i], NDFA_OPTION) == 0)
8946 ndfa_flag = 1;
8947 else if (strcmp (argv [i], PROGRESS_OPTION) == 0)
8948 progress_flag = 1;
8949 else if (strcmp (argv [i], "-split") == 0)
8951 if (i + 1 >= argc)
8952 fatal ("-split has no argument.");
8953 fatal ("option `-split' has not been implemented yet\n");
8954 /* split_argument = atoi (argument_vect [i + 1]); */
8957 /* Initialize IR storage. */
8958 obstack_init (&irp);
8959 initiate_automaton_decl_table ();
8960 initiate_insn_decl_table ();
8961 initiate_decl_table ();
8962 output_file = stdout;
8963 output_description_file = NULL;
8964 base_name = base_file_name (argv[1]);
8965 obstack_grow (&irp, base_name,
8966 strlen (base_name) - strlen (file_name_suffix (base_name)));
8967 obstack_grow (&irp, STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX,
8968 strlen (STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX) + 1);
8969 obstack_1grow (&irp, '\0');
8970 output_description_file_name = obstack_base (&irp);
8971 obstack_finish (&irp);
8974 /* The following function checks existence at least one arc marked by
8975 each insn. */
8976 static void
8977 check_automata_insn_issues (void)
8979 automaton_t automaton;
8980 ainsn_t ainsn, reserv_ainsn;
8982 for (automaton = description->first_automaton;
8983 automaton != NULL;
8984 automaton = automaton->next_automaton)
8986 for (ainsn = automaton->ainsn_list;
8987 ainsn != NULL;
8988 ainsn = ainsn->next_ainsn)
8989 if (ainsn->first_insn_with_same_reservs && !ainsn->arc_exists_p)
8991 for (reserv_ainsn = ainsn;
8992 reserv_ainsn != NULL;
8993 reserv_ainsn = reserv_ainsn->next_same_reservs_insn)
8994 if (automaton->corresponding_automaton_decl != NULL)
8996 if (!w_flag)
8997 error ("Automaton `%s': Insn `%s' will never be issued",
8998 automaton->corresponding_automaton_decl->name,
8999 reserv_ainsn->insn_reserv_decl->name);
9000 else
9001 warning
9002 (0, "Automaton `%s': Insn `%s' will never be issued",
9003 automaton->corresponding_automaton_decl->name,
9004 reserv_ainsn->insn_reserv_decl->name);
9006 else
9008 if (!w_flag)
9009 error ("Insn `%s' will never be issued",
9010 reserv_ainsn->insn_reserv_decl->name);
9011 else
9012 warning (0, "Insn `%s' will never be issued",
9013 reserv_ainsn->insn_reserv_decl->name);
9019 /* The following vla is used for storing pointers to all achieved
9020 states. */
9021 static VEC(state_t,heap) *automaton_states;
9023 /* This function is called by function pass_states to add an achieved
9024 STATE. */
9025 static void
9026 add_automaton_state (state_t state)
9028 VEC_safe_push (state_t,heap, automaton_states, state);
9031 /* The following function forms list of important automata (whose
9032 states may be changed after the insn issue) for each insn. */
9033 static void
9034 form_important_insn_automata_lists (void)
9036 automaton_t automaton;
9037 decl_t decl;
9038 ainsn_t ainsn;
9039 arc_t arc;
9040 int i;
9041 size_t n;
9043 automaton_states = 0;
9044 /* Mark important ainsns. */
9045 for (automaton = description->first_automaton;
9046 automaton != NULL;
9047 automaton = automaton->next_automaton)
9049 VEC_truncate (state_t, automaton_states, 0);
9050 pass_states (automaton, add_automaton_state);
9051 for (n = 0; n < VEC_length (state_t, automaton_states); n++)
9053 state_t s = VEC_index (state_t, automaton_states, n);
9054 for (arc = first_out_arc (s);
9055 arc != NULL;
9056 arc = next_out_arc (arc))
9057 if (arc->to_state != s)
9059 gcc_assert (arc->insn->first_insn_with_same_reservs);
9060 for (ainsn = arc->insn;
9061 ainsn != NULL;
9062 ainsn = ainsn->next_same_reservs_insn)
9063 ainsn->important_p = TRUE;
9067 VEC_free (state_t,heap, automaton_states);
9069 /* Create automata sets for the insns. */
9070 for (i = 0; i < description->decls_num; i++)
9072 decl = description->decls [i];
9073 if (decl->mode == dm_insn_reserv)
9075 automata_list_start ();
9076 for (automaton = description->first_automaton;
9077 automaton != NULL;
9078 automaton = automaton->next_automaton)
9079 for (ainsn = automaton->ainsn_list;
9080 ainsn != NULL;
9081 ainsn = ainsn->next_ainsn)
9082 if (ainsn->important_p
9083 && ainsn->insn_reserv_decl == DECL_INSN_RESERV (decl))
9085 automata_list_add (automaton);
9086 break;
9088 DECL_INSN_RESERV (decl)->important_automata_list
9089 = automata_list_finish ();
9095 /* The following is top level function to generate automat(a,on) for
9096 fast recognition of pipeline hazards. */
9097 static void
9098 expand_automata (void)
9100 int i;
9102 description = create_node (sizeof (struct description)
9103 /* One entry for cycle advancing insn. */
9104 + sizeof (decl_t) * VEC_length (decl_t, decls));
9105 description->decls_num = VEC_length (decl_t, decls);
9106 description->query_units_num = 0;
9107 for (i = 0; i < description->decls_num; i++)
9109 description->decls [i] = VEC_index (decl_t, decls, i);
9110 if (description->decls [i]->mode == dm_unit
9111 && DECL_UNIT (description->decls [i])->query_p)
9112 DECL_UNIT (description->decls [i])->query_num
9113 = description->query_units_num++;
9115 all_time = create_ticker ();
9116 check_time = create_ticker ();
9117 if (progress_flag)
9118 fprintf (stderr, "Check description...");
9119 check_all_description ();
9120 if (progress_flag)
9121 fprintf (stderr, "done\n");
9122 ticker_off (&check_time);
9123 generation_time = create_ticker ();
9124 if (!have_error)
9126 transform_insn_regexps ();
9127 check_unit_distributions_to_automata ();
9129 if (!have_error)
9131 generate ();
9132 check_automata_insn_issues ();
9134 if (!have_error)
9136 form_important_insn_automata_lists ();
9138 ticker_off (&generation_time);
9141 /* The following is top level function to output PHR and to finish
9142 work with pipeline description translator. */
9143 static void
9144 write_automata (void)
9146 output_time = create_ticker ();
9147 if (progress_flag)
9148 fprintf (stderr, "Forming and outputting automata tables...");
9149 output_tables ();
9150 if (progress_flag)
9152 fprintf (stderr, "done\n");
9153 fprintf (stderr, "Output functions to work with automata...");
9155 output_chip_definitions ();
9156 output_max_insn_queue_index_def ();
9157 output_internal_min_issue_delay_func ();
9158 output_internal_trans_func ();
9159 /* Cache of insn dfa codes: */
9160 fprintf (output_file, "\nstatic int *%s;\n", DFA_INSN_CODES_VARIABLE_NAME);
9161 fprintf (output_file, "\nstatic int %s;\n\n",
9162 DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
9163 output_dfa_insn_code_func ();
9164 output_trans_func ();
9165 output_min_issue_delay_func ();
9166 output_internal_dead_lock_func ();
9167 output_dead_lock_func ();
9168 output_size_func ();
9169 output_internal_reset_func ();
9170 output_reset_func ();
9171 output_min_insn_conflict_delay_func ();
9172 output_internal_insn_latency_func ();
9173 output_insn_latency_func ();
9174 output_print_reservation_func ();
9175 /* Output function get_cpu_unit_code. */
9176 fprintf (output_file, "\n#if %s\n\n", CPU_UNITS_QUERY_MACRO_NAME);
9177 output_get_cpu_unit_code_func ();
9178 output_cpu_unit_reservation_p ();
9179 output_insn_has_dfa_reservation_p ();
9180 fprintf (output_file, "\n#endif /* #if %s */\n\n",
9181 CPU_UNITS_QUERY_MACRO_NAME);
9182 output_dfa_clean_insn_cache_func ();
9183 output_dfa_start_func ();
9184 output_dfa_finish_func ();
9185 if (progress_flag)
9186 fprintf (stderr, "done\n");
9187 if (v_flag)
9189 output_description_file = fopen (output_description_file_name, "w");
9190 if (output_description_file == NULL)
9192 perror (output_description_file_name);
9193 exit (FATAL_EXIT_CODE);
9195 if (progress_flag)
9196 fprintf (stderr, "Output automata description...");
9197 output_description ();
9198 output_automaton_descriptions ();
9199 if (progress_flag)
9200 fprintf (stderr, "done\n");
9201 output_statistics (output_description_file);
9203 if (stats_flag)
9204 output_statistics (stderr);
9205 ticker_off (&output_time);
9206 if (time_flag)
9207 output_time_statistics (stderr);
9208 finish_states ();
9209 finish_arcs ();
9210 finish_automata_lists ();
9211 if (time_flag)
9213 fprintf (stderr, "Summary:\n");
9214 fprintf (stderr, " check time ");
9215 print_active_time (stderr, check_time);
9216 fprintf (stderr, ", generation time ");
9217 print_active_time (stderr, generation_time);
9218 fprintf (stderr, ", all time ");
9219 print_active_time (stderr, all_time);
9220 fprintf (stderr, "\n");
9222 /* Finish all work. */
9223 if (output_description_file != NULL)
9225 fflush (output_description_file);
9226 if (ferror (stdout) != 0)
9227 fatal ("Error in writing DFA description file %s: %s",
9228 output_description_file_name, xstrerror (errno));
9229 fclose (output_description_file);
9231 finish_automaton_decl_table ();
9232 finish_insn_decl_table ();
9233 finish_decl_table ();
9234 obstack_free (&irp, NULL);
9235 if (have_error && output_description_file != NULL)
9236 remove (output_description_file_name);
9240 main (int argc, char **argv)
9242 rtx desc;
9244 progname = "genautomata";
9246 if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
9247 return (FATAL_EXIT_CODE);
9249 initiate_automaton_gen (argc, argv);
9250 while (1)
9252 int lineno;
9253 int insn_code_number;
9255 desc = read_md_rtx (&lineno, &insn_code_number);
9256 if (desc == NULL)
9257 break;
9259 switch (GET_CODE (desc))
9261 case DEFINE_CPU_UNIT:
9262 gen_cpu_unit (desc);
9263 break;
9265 case DEFINE_QUERY_CPU_UNIT:
9266 gen_query_cpu_unit (desc);
9267 break;
9269 case DEFINE_BYPASS:
9270 gen_bypass (desc);
9271 break;
9273 case EXCLUSION_SET:
9274 gen_excl_set (desc);
9275 break;
9277 case PRESENCE_SET:
9278 gen_presence_set (desc);
9279 break;
9281 case FINAL_PRESENCE_SET:
9282 gen_final_presence_set (desc);
9283 break;
9285 case ABSENCE_SET:
9286 gen_absence_set (desc);
9287 break;
9289 case FINAL_ABSENCE_SET:
9290 gen_final_absence_set (desc);
9291 break;
9293 case DEFINE_AUTOMATON:
9294 gen_automaton (desc);
9295 break;
9297 case AUTOMATA_OPTION:
9298 gen_automata_option (desc);
9299 break;
9301 case DEFINE_RESERVATION:
9302 gen_reserv (desc);
9303 break;
9305 case DEFINE_INSN_RESERVATION:
9306 gen_insn_reserv (desc);
9307 break;
9309 default:
9310 break;
9314 if (have_error)
9315 return FATAL_EXIT_CODE;
9317 puts ("/* Generated automatically by the program `genautomata'\n"
9318 " from the machine description file `md'. */\n\n"
9319 "#include \"config.h\"\n"
9320 "#include \"system.h\"\n"
9321 "#include \"coretypes.h\"\n"
9322 "#include \"tm.h\"\n"
9323 "#include \"rtl.h\"\n"
9324 "#include \"tm_p.h\"\n"
9325 "#include \"insn-config.h\"\n"
9326 "#include \"recog.h\"\n"
9327 "#include \"regs.h\"\n"
9328 "#include \"real.h\"\n"
9329 "#include \"output.h\"\n"
9330 "#include \"insn-attr.h\"\n"
9331 "#include \"toplev.h\"\n"
9332 "#include \"flags.h\"\n"
9333 "#include \"function.h\"\n");
9335 if (VEC_length (decl_t, decls) > 0)
9337 expand_automata ();
9338 write_automata ();
9341 fflush (stdout);
9342 return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);