PR fortran/38830
[official-gcc.git] / gcc / genautomata.c
blobe78eea2c258564506a91962f8804f95bef935ac2
1 /* Pipeline hazard description translator.
2 Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009
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. The finite state automaton based pipeline hazard recognizer and
26 instruction scheduler in GCC. V. Makarov. Proceedings of GCC
27 summit, 2003.
29 2. Detecting pipeline structural hazards quickly. T. Proebsting,
30 C. Fraser. Proceedings of ACM SIGPLAN-SIGACT Symposium on
31 Principles of Programming Languages, pages 280--286, 1994.
33 This article is a good start point to understand usage of finite
34 state automata for pipeline hazard recognizers. But I'd
35 recommend the 1st and 3rd article for more deep understanding.
37 3. Efficient Instruction Scheduling Using Finite State Automata:
38 V. Bala and N. Rubin, Proceedings of MICRO-28. This is the best
39 article about usage of finite state automata for pipeline hazard
40 recognizers.
42 The current implementation is described in the 1st article and it
43 is different from the 3rd article in the following:
45 1. New operator `|' (alternative) is permitted in functional unit
46 reservation which can be treated deterministically and
47 non-deterministically.
49 2. Possibility of usage of nondeterministic automata too.
51 3. Possibility to query functional unit reservations for given
52 automaton state.
54 4. Several constructions to describe impossible reservations
55 (`exclusion_set', `presence_set', `final_presence_set',
56 `absence_set', and `final_absence_set').
58 5. No reverse automata are generated. Trace instruction scheduling
59 requires this. It can be easily added in the future if we
60 really need this.
62 6. Union of automaton states are not generated yet. It is planned
63 to be implemented. Such feature is needed to make more accurate
64 interlock insn scheduling to get state describing functional
65 unit reservation in a joint CFG point. */
67 /* This file code processes constructions of machine description file
68 which describes automaton used for recognition of processor pipeline
69 hazards by insn scheduler and can be used for other tasks (such as
70 VLIW insn packing.
72 The translator functions `gen_cpu_unit', `gen_query_cpu_unit',
73 `gen_bypass', `gen_excl_set', `gen_presence_set',
74 `gen_final_presence_set', `gen_absence_set',
75 `gen_final_absence_set', `gen_automaton', `gen_automata_option',
76 `gen_reserv', `gen_insn_reserv' are called from file
77 `genattrtab.c'. They transform RTL constructions describing
78 automata in .md file into internal representation convenient for
79 further processing.
81 The translator major function `expand_automata' processes the
82 description internal representation into finite state automaton.
83 It can be divided on:
85 o checking correctness of the automaton pipeline description
86 (major function is `check_all_description').
88 o generating automaton (automata) from the description (major
89 function is `make_automaton').
91 o optional transformation of nondeterministic finite state
92 automata into deterministic ones if the alternative operator
93 `|' is treated nondeterministically in the description (major
94 function is NDFA_to_DFA).
96 o optional minimization of the finite state automata by merging
97 equivalent automaton states (major function is `minimize_DFA').
99 o forming tables (some as comb vectors) and attributes
100 representing the automata (functions output_..._table).
102 Function `write_automata' outputs the created finite state
103 automaton as different tables and functions which works with the
104 automata to inquire automaton state and to change its state. These
105 function are used by gcc instruction scheduler and may be some
106 other gcc code. */
108 #include "bconfig.h"
109 #include "system.h"
110 #include "coretypes.h"
111 #include "tm.h"
112 #include "rtl.h"
113 #include "obstack.h"
114 #include "errors.h"
115 #include "gensupport.h"
117 #include <math.h>
118 #include "hashtab.h"
119 #include "vec.h"
121 #ifndef CHAR_BIT
122 #define CHAR_BIT 8
123 #endif
125 /* Positions in machine description file. Now they are not used. But
126 they could be used in the future for better diagnostic messages. */
127 typedef int pos_t;
129 /* The following is element of vector of current (and planned in the
130 future) functional unit reservations. */
131 typedef unsigned HOST_WIDE_INT set_el_t;
133 /* Reservations of function units are represented by value of the following
134 type. */
135 typedef set_el_t *reserv_sets_t;
136 typedef const set_el_t *const_reserv_sets_t;
138 /* The following structure describes a ticker. */
139 struct ticker
141 /* The following member value is time of the ticker creation with
142 taking into account time when the ticker is off. Active time of
143 the ticker is current time minus the value. */
144 int modified_creation_time;
145 /* The following member value is time (incremented by one) when the
146 ticker was off. Zero value means that now the ticker is on. */
147 int incremented_off_time;
150 /* The ticker is represented by the following type. */
151 typedef struct ticker ticker_t;
153 /* The following type describes elements of output vectors. */
154 typedef HOST_WIDE_INT vect_el_t;
156 /* Forward declaration of structures of internal representation of
157 pipeline description based on NDFA. */
159 struct unit_decl;
160 struct bypass_decl;
161 struct result_decl;
162 struct automaton_decl;
163 struct unit_pattern_rel_decl;
164 struct reserv_decl;
165 struct insn_reserv_decl;
166 struct decl;
167 struct unit_regexp;
168 struct result_regexp;
169 struct reserv_regexp;
170 struct nothing_regexp;
171 struct sequence_regexp;
172 struct repeat_regexp;
173 struct allof_regexp;
174 struct oneof_regexp;
175 struct regexp;
176 struct description;
177 struct unit_set_el;
178 struct pattern_set_el;
179 struct pattern_reserv;
180 struct state;
181 struct alt_state;
182 struct arc;
183 struct ainsn;
184 struct automaton;
185 struct state_ainsn_table;
187 /* The following typedefs are for brevity. */
188 typedef struct unit_decl *unit_decl_t;
189 typedef const struct unit_decl *const_unit_decl_t;
190 typedef struct decl *decl_t;
191 typedef const struct decl *const_decl_t;
192 typedef struct regexp *regexp_t;
193 typedef struct unit_set_el *unit_set_el_t;
194 typedef struct pattern_set_el *pattern_set_el_t;
195 typedef struct pattern_reserv *pattern_reserv_t;
196 typedef struct alt_state *alt_state_t;
197 typedef struct state *state_t;
198 typedef const struct state *const_state_t;
199 typedef struct arc *arc_t;
200 typedef struct ainsn *ainsn_t;
201 typedef struct automaton *automaton_t;
202 typedef struct automata_list_el *automata_list_el_t;
203 typedef const struct automata_list_el *const_automata_list_el_t;
204 typedef struct state_ainsn_table *state_ainsn_table_t;
206 /* Undefined position. */
207 static pos_t no_pos = 0;
209 /* All IR is stored in the following obstack. */
210 static struct obstack irp;
213 /* Declare vector types for various data structures: */
215 DEF_VEC_P(alt_state_t);
216 DEF_VEC_ALLOC_P(alt_state_t, heap);
217 DEF_VEC_P(ainsn_t);
218 DEF_VEC_ALLOC_P(ainsn_t, heap);
219 DEF_VEC_P(state_t);
220 DEF_VEC_ALLOC_P(state_t, heap);
221 DEF_VEC_P(decl_t);
222 DEF_VEC_ALLOC_P(decl_t, heap);
223 DEF_VEC_P(reserv_sets_t);
224 DEF_VEC_ALLOC_P(reserv_sets_t, heap);
226 DEF_VEC_I(vect_el_t);
227 DEF_VEC_ALLOC_I(vect_el_t, heap);
228 typedef VEC(vect_el_t, heap) *vla_hwint_t;
230 /* Forward declarations of functions used before their definitions, only. */
231 static regexp_t gen_regexp_sequence (const char *);
232 static void reserv_sets_or (reserv_sets_t, reserv_sets_t,
233 reserv_sets_t);
234 static reserv_sets_t get_excl_set (reserv_sets_t);
235 static int check_presence_pattern_sets (reserv_sets_t,
236 reserv_sets_t, int);
237 static int check_absence_pattern_sets (reserv_sets_t, reserv_sets_t,
238 int);
239 static arc_t first_out_arc (const_state_t);
240 static arc_t next_out_arc (arc_t);
244 /* Options with the following names can be set up in automata_option
245 construction. Because the strings occur more one time we use the
246 macros. */
248 #define NO_MINIMIZATION_OPTION "-no-minimization"
249 #define TIME_OPTION "-time"
250 #define STATS_OPTION "-stats"
251 #define V_OPTION "-v"
252 #define W_OPTION "-w"
253 #define NDFA_OPTION "-ndfa"
254 #define PROGRESS_OPTION "-progress"
256 /* The following flags are set up by function `initiate_automaton_gen'. */
258 /* Make automata with nondeterministic reservation by insns (`-ndfa'). */
259 static int ndfa_flag;
261 /* Do not make minimization of DFA (`-no-minimization'). */
262 static int no_minimization_flag;
264 /* Value of this variable is number of automata being generated. The
265 actual number of automata may be less this value if there is not
266 sufficient number of units. This value is defined by argument of
267 option `-split' or by constructions automaton if the value is zero
268 (it is default value of the argument). */
269 static int split_argument;
271 /* Flag of output time statistics (`-time'). */
272 static int time_flag;
274 /* Flag of automata statistics (`-stats'). */
275 static int stats_flag;
277 /* Flag of creation of description file which contains description of
278 result automaton and statistics information (`-v'). */
279 static int v_flag;
281 /* Flag of output of a progress bar showing how many states were
282 generated so far for automaton being processed (`-progress'). */
283 static int progress_flag;
285 /* Flag of generating warning instead of error for non-critical errors
286 (`-w'). */
287 static int w_flag;
290 /* Output file for pipeline hazard recognizer (PHR) being generated.
291 The value is NULL if the file is not defined. */
292 static FILE *output_file;
294 /* Description file of PHR. The value is NULL if the file is not
295 created. */
296 static FILE *output_description_file;
298 /* PHR description file name. */
299 static char *output_description_file_name;
301 /* Value of the following variable is node representing description
302 being processed. This is start point of IR. */
303 static struct description *description;
307 /* This page contains description of IR structure (nodes). */
309 enum decl_mode
311 dm_unit,
312 dm_bypass,
313 dm_automaton,
314 dm_excl,
315 dm_presence,
316 dm_absence,
317 dm_reserv,
318 dm_insn_reserv
321 /* This describes define_cpu_unit and define_query_cpu_unit (see file
322 rtl.def). */
323 struct unit_decl
325 const char *name;
326 /* NULL if the automaton name is absent. */
327 const char *automaton_name;
328 /* If the following value is not zero, the cpu unit reservation is
329 described in define_query_cpu_unit. */
330 char query_p;
332 /* The following fields are defined by checker. */
334 /* The following field value is nonzero if the unit is used in an
335 regexp. */
336 char unit_is_used;
338 /* The following field value is order number (0, 1, ...) of given
339 unit. */
340 int unit_num;
341 /* The following field value is corresponding declaration of
342 automaton which was given in description. If the field value is
343 NULL then automaton in the unit declaration was absent. */
344 struct automaton_decl *automaton_decl;
345 /* The following field value is maximal cycle number (1, ...) on
346 which given unit occurs in insns. Zero value means that given
347 unit is not used in insns. */
348 int max_occ_cycle_num;
349 /* The following field value is minimal cycle number (0, ...) on
350 which given unit occurs in insns. -1 value means that given
351 unit is not used in insns. */
352 int min_occ_cycle_num;
353 /* The following list contains units which conflict with given
354 unit. */
355 unit_set_el_t excl_list;
356 /* The following list contains patterns which are required to
357 reservation of given unit. */
358 pattern_set_el_t presence_list;
359 pattern_set_el_t final_presence_list;
360 /* The following list contains patterns which should be not present
361 in reservation for given unit. */
362 pattern_set_el_t absence_list;
363 pattern_set_el_t final_absence_list;
364 /* The following is used only when `query_p' has nonzero value.
365 This is query number for the unit. */
366 int query_num;
367 /* The following is the last cycle on which the unit was checked for
368 correct distributions of units to automata in a regexp. */
369 int last_distribution_check_cycle;
371 /* The following fields are defined by automaton generator. */
373 /* The following field value is number of the automaton to which
374 given unit belongs. */
375 int corresponding_automaton_num;
376 /* If the following value is not zero, the cpu unit is present in a
377 `exclusion_set' or in right part of a `presence_set',
378 `final_presence_set', `absence_set', and
379 `final_absence_set'define_query_cpu_unit. */
380 char in_set_p;
383 /* This describes define_bypass (see file rtl.def). */
384 struct bypass_decl
386 int latency;
387 const char *out_insn_name;
388 const char *in_insn_name;
389 const char *bypass_guard_name;
391 /* The following fields are defined by checker. */
393 /* output and input insns of given bypass. */
394 struct insn_reserv_decl *out_insn_reserv;
395 struct insn_reserv_decl *in_insn_reserv;
396 /* The next bypass for given output insn. */
397 struct bypass_decl *next;
400 /* This describes define_automaton (see file rtl.def). */
401 struct automaton_decl
403 const char *name;
405 /* The following fields are defined by automaton generator. */
407 /* The following field value is nonzero if the automaton is used in
408 an regexp definition. */
409 char automaton_is_used;
411 /* The following fields are defined by checker. */
413 /* The following field value is the corresponding automaton. This
414 field is not NULL only if the automaton is present in unit
415 declarations and the automatic partition on automata is not
416 used. */
417 automaton_t corresponding_automaton;
420 /* This describes exclusion relations: exclusion_set (see file
421 rtl.def). */
422 struct excl_rel_decl
424 int all_names_num;
425 int first_list_length;
426 char *names [1];
429 /* This describes unit relations: [final_]presence_set or
430 [final_]absence_set (see file rtl.def). */
431 struct unit_pattern_rel_decl
433 int final_p;
434 int names_num;
435 int patterns_num;
436 char **names;
437 char ***patterns;
440 /* This describes define_reservation (see file rtl.def). */
441 struct reserv_decl
443 const char *name;
444 regexp_t regexp;
446 /* The following fields are defined by checker. */
448 /* The following field value is nonzero if the unit is used in an
449 regexp. */
450 char reserv_is_used;
451 /* The following field is used to check up cycle in expression
452 definition. */
453 int loop_pass_num;
456 /* This describes define_insn_reservation (see file rtl.def). */
457 struct insn_reserv_decl
459 rtx condexp;
460 int default_latency;
461 regexp_t regexp;
462 const char *name;
464 /* The following fields are defined by checker. */
466 /* The following field value is order number (0, 1, ...) of given
467 insn. */
468 int insn_num;
469 /* The following field value is list of bypasses in which given insn
470 is output insn. Bypasses with the same input insn stay one after
471 another in the list in the same order as their occurrences in the
472 description but the bypass without a guard stays always the last
473 in a row of bypasses with the same input insn. */
474 struct bypass_decl *bypass_list;
476 /* The following fields are defined by automaton generator. */
478 /* The following field is the insn regexp transformed that
479 the regexp has not optional regexp, repetition regexp, and an
480 reservation name (i.e. reservation identifiers are changed by the
481 corresponding regexp) and all alternations are the top level
482 of the regexp. The value can be NULL only if it is special
483 insn `cycle advancing'. */
484 regexp_t transformed_regexp;
485 /* The following field value is list of arcs marked given
486 insn. The field is used in transformation NDFA -> DFA. */
487 arc_t arcs_marked_by_insn;
488 /* The two following fields are used during minimization of a finite state
489 automaton. */
490 /* The field value is number of equivalence class of state into
491 which arc marked by given insn enters from a state (fixed during
492 an automaton minimization). */
493 int equiv_class_num;
494 /* The following member value is the list to automata which can be
495 changed by the insn issue. */
496 automata_list_el_t important_automata_list;
497 /* The following member is used to process insn once for output. */
498 int processed_p;
501 /* This contains a declaration mentioned above. */
502 struct decl
504 /* What node in the union? */
505 enum decl_mode mode;
506 pos_t pos;
507 union
509 struct unit_decl unit;
510 struct bypass_decl bypass;
511 struct automaton_decl automaton;
512 struct excl_rel_decl excl;
513 struct unit_pattern_rel_decl presence;
514 struct unit_pattern_rel_decl absence;
515 struct reserv_decl reserv;
516 struct insn_reserv_decl insn_reserv;
517 } decl;
520 /* The following structures represent parsed reservation strings. */
521 enum regexp_mode
523 rm_unit,
524 rm_reserv,
525 rm_nothing,
526 rm_sequence,
527 rm_repeat,
528 rm_allof,
529 rm_oneof
532 /* Cpu unit in reservation. */
533 struct unit_regexp
535 const char *name;
536 unit_decl_t unit_decl;
539 /* Define_reservation in a reservation. */
540 struct reserv_regexp
542 const char *name;
543 struct reserv_decl *reserv_decl;
546 /* Absence of reservation (represented by string `nothing'). */
547 struct nothing_regexp
549 /* This used to be empty but ISO C doesn't allow that. */
550 char unused;
553 /* Representation of reservations separated by ',' (see file
554 rtl.def). */
555 struct sequence_regexp
557 int regexps_num;
558 regexp_t regexps [1];
561 /* Representation of construction `repeat' (see file rtl.def). */
562 struct repeat_regexp
564 int repeat_num;
565 regexp_t regexp;
568 /* Representation of reservations separated by '+' (see file
569 rtl.def). */
570 struct allof_regexp
572 int regexps_num;
573 regexp_t regexps [1];
576 /* Representation of reservations separated by '|' (see file
577 rtl.def). */
578 struct oneof_regexp
580 int regexps_num;
581 regexp_t regexps [1];
584 /* Representation of a reservation string. */
585 struct regexp
587 /* What node in the union? */
588 enum regexp_mode mode;
589 pos_t pos;
590 union
592 struct unit_regexp unit;
593 struct reserv_regexp reserv;
594 struct nothing_regexp nothing;
595 struct sequence_regexp sequence;
596 struct repeat_regexp repeat;
597 struct allof_regexp allof;
598 struct oneof_regexp oneof;
599 } regexp;
602 /* Represents description of pipeline hazard description based on
603 NDFA. */
604 struct description
606 int decls_num;
608 /* The following fields are defined by checker. */
610 /* The following fields values are correspondingly number of all
611 units, query units, and insns in the description. */
612 int units_num;
613 int query_units_num;
614 int insns_num;
615 /* The following field value is max length (in cycles) of
616 reservations of insns. The field value is defined only for
617 correct programs. */
618 int max_insn_reserv_cycles;
620 /* The following fields are defined by automaton generator. */
622 /* The following field value is the first automaton. */
623 automaton_t first_automaton;
625 /* The following field is created by pipeline hazard parser and
626 contains all declarations. We allocate additional entry for
627 special insn "cycle advancing" which is added by the automaton
628 generator. */
629 decl_t decls [1];
633 /* The following nodes are created in automaton checker. */
635 /* The following nodes represent exclusion set for cpu units. Each
636 element is accessed through only one excl_list. */
637 struct unit_set_el
639 unit_decl_t unit_decl;
640 unit_set_el_t next_unit_set_el;
643 /* The following nodes represent presence or absence pattern for cpu
644 units. Each element is accessed through only one presence_list or
645 absence_list. */
646 struct pattern_set_el
648 /* The number of units in unit_decls. */
649 int units_num;
650 /* The units forming the pattern. */
651 struct unit_decl **unit_decls;
652 pattern_set_el_t next_pattern_set_el;
656 /* The following nodes are created in automaton generator. */
659 /* The following nodes represent presence or absence pattern for cpu
660 units. Each element is accessed through only one element of
661 unit_presence_set_table or unit_absence_set_table. */
662 struct pattern_reserv
664 reserv_sets_t reserv;
665 pattern_reserv_t next_pattern_reserv;
668 /* The following node type describes state automaton. The state may
669 be deterministic or non-deterministic. Non-deterministic state has
670 several component states which represent alternative cpu units
671 reservations. The state also is used for describing a
672 deterministic reservation of automaton insn. */
673 struct state
675 /* The following member value is nonzero if there is a transition by
676 cycle advancing. */
677 int new_cycle_p;
678 /* The following field is list of processor unit reservations on
679 each cycle. */
680 reserv_sets_t reservs;
681 /* The following field is unique number of given state between other
682 states. */
683 int unique_num;
684 /* The following field value is automaton to which given state
685 belongs. */
686 automaton_t automaton;
687 /* The following field value is the first arc output from given
688 state. */
689 arc_t first_out_arc;
690 unsigned int num_out_arcs;
691 /* The following field is used to form NDFA. */
692 char it_was_placed_in_stack_for_NDFA_forming;
693 /* The following field is used to form DFA. */
694 char it_was_placed_in_stack_for_DFA_forming;
695 /* The following field is used to transform NDFA to DFA and DFA
696 minimization. The field value is not NULL if the state is a
697 compound state. In this case the value of field `unit_sets_list'
698 is NULL. All states in the list are in the hash table. The list
699 is formed through field `next_sorted_alt_state'. We should
700 support only one level of nesting state. */
701 alt_state_t component_states;
702 /* The following field is used for passing graph of states. */
703 int pass_num;
704 /* The list of states belonging to one equivalence class is formed
705 with the aid of the following field. */
706 state_t next_equiv_class_state;
707 /* The two following fields are used during minimization of a finite
708 state automaton. */
709 int equiv_class_num_1, equiv_class_num_2;
710 /* The following field is used during minimization of a finite state
711 automaton. The field value is state corresponding to equivalence
712 class to which given state belongs. */
713 state_t equiv_class_state;
714 unsigned int *presence_signature;
715 /* The following field value is the order number of given state.
716 The states in final DFA is enumerated with the aid of the
717 following field. */
718 int order_state_num;
719 /* This member is used for passing states for searching minimal
720 delay time. */
721 int state_pass_num;
722 /* The following member is used to evaluate min issue delay of insn
723 for a state. */
724 int min_insn_issue_delay;
727 /* Automaton arc. */
728 struct arc
730 /* The following field refers for the state into which given arc
731 enters. */
732 state_t to_state;
733 /* The following field describes that the insn issue (with cycle
734 advancing for special insn `cycle advancing' and without cycle
735 advancing for others) makes transition from given state to
736 another given state. */
737 ainsn_t insn;
738 /* The following field value is the next arc output from the same
739 state. */
740 arc_t next_out_arc;
741 /* List of arcs marked given insn is formed with the following
742 field. The field is used in transformation NDFA -> DFA. */
743 arc_t next_arc_marked_by_insn;
746 /* The following node type describes a deterministic alternative in
747 non-deterministic state which characterizes cpu unit reservations
748 of automaton insn or which is part of NDFA. */
749 struct alt_state
751 /* The following field is a deterministic state which characterizes
752 unit reservations of the instruction. */
753 state_t state;
754 /* The following field refers to the next state which characterizes
755 unit reservations of the instruction. */
756 alt_state_t next_alt_state;
757 /* The following field refers to the next state in sorted list. */
758 alt_state_t next_sorted_alt_state;
761 /* The following node type describes insn of automaton. They are
762 labels of FA arcs. */
763 struct ainsn
765 /* The following field value is the corresponding insn declaration
766 of description. */
767 struct insn_reserv_decl *insn_reserv_decl;
768 /* The following field value is the next insn declaration for an
769 automaton. */
770 ainsn_t next_ainsn;
771 /* The following field is states which characterize automaton unit
772 reservations of the instruction. The value can be NULL only if it
773 is special insn `cycle advancing'. */
774 alt_state_t alt_states;
775 /* The following field is sorted list of states which characterize
776 automaton unit reservations of the instruction. The value can be
777 NULL only if it is special insn `cycle advancing'. */
778 alt_state_t sorted_alt_states;
779 /* The following field refers the next automaton insn with
780 the same reservations. */
781 ainsn_t next_same_reservs_insn;
782 /* The following field is flag of the first automaton insn with the
783 same reservations in the declaration list. Only arcs marked such
784 insn is present in the automaton. This significantly decreases
785 memory requirements especially when several automata are
786 formed. */
787 char first_insn_with_same_reservs;
788 /* The following member has nonzero value if there is arc from state of
789 the automaton marked by the ainsn. */
790 char arc_exists_p;
791 /* Cyclic list of insns of an equivalence class is formed with the
792 aid of the following field. */
793 ainsn_t next_equiv_class_insn;
794 /* The following field value is nonzero if the insn declaration is
795 the first insn declaration with given equivalence number. */
796 char first_ainsn_with_given_equivalence_num;
797 /* The following field is number of class of equivalence of insns.
798 It is necessary because many insns may be equivalent with the
799 point of view of pipeline hazards. */
800 int insn_equiv_class_num;
801 /* The following member value is TRUE if there is an arc in the
802 automaton marked by the insn into another state. In other
803 words, the insn can change the state of the automaton. */
804 int important_p;
807 /* The following describes an automaton for PHR. */
808 struct automaton
810 /* The following field value is the list of insn declarations for
811 given automaton. */
812 ainsn_t ainsn_list;
813 /* The following field value is the corresponding automaton
814 declaration. This field is not NULL only if the automatic
815 partition on automata is not used. */
816 struct automaton_decl *corresponding_automaton_decl;
817 /* The following field value is the next automaton. */
818 automaton_t next_automaton;
819 /* The following field is start state of FA. There are not unit
820 reservations in the state. */
821 state_t start_state;
822 /* The following field value is number of equivalence classes of
823 insns (see field `insn_equiv_class_num' in
824 `insn_reserv_decl'). */
825 int insn_equiv_classes_num;
826 /* The following field value is number of states of final DFA. */
827 int achieved_states_num;
828 /* The following field value is the order number (0, 1, ...) of
829 given automaton. */
830 int automaton_order_num;
831 /* The following fields contain statistics information about
832 building automaton. */
833 int NDFA_states_num, DFA_states_num;
834 /* The following field value is defined only if minimization of DFA
835 is used. */
836 int minimal_DFA_states_num;
837 int NDFA_arcs_num, DFA_arcs_num;
838 /* The following field value is defined only if minimization of DFA
839 is used. */
840 int minimal_DFA_arcs_num;
841 /* The following member refers for two table state x ainsn -> int.
842 ??? Above sentence is incomprehensible. */
843 state_ainsn_table_t trans_table;
844 /* The following member value is maximal value of min issue delay
845 for insns of the automaton. */
846 int max_min_delay;
847 /* Usually min issue delay is small and we can place several (2, 4,
848 8) elements in one vector element. So the compression factor can
849 be 1 (no compression), 2, 4, 8. */
850 int min_issue_delay_table_compression_factor;
851 /* Total number of locked states in this automaton. */
852 int locked_states;
855 /* The following is the element of the list of automata. */
856 struct automata_list_el
858 /* The automaton itself. */
859 automaton_t automaton;
860 /* The next automata set element. */
861 automata_list_el_t next_automata_list_el;
864 /* The following structure describes a table state X ainsn -> int(>= 0). */
865 struct state_ainsn_table
867 /* Automaton to which given table belongs. */
868 automaton_t automaton;
869 /* The following tree vectors for comb vector implementation of the
870 table. */
871 vla_hwint_t comb_vect;
872 vla_hwint_t check_vect;
873 vla_hwint_t base_vect;
874 /* This is simple implementation of the table. */
875 vla_hwint_t full_vect;
876 /* Minimal and maximal values of the previous vectors. */
877 int min_comb_vect_el_value, max_comb_vect_el_value;
878 int min_base_vect_el_value, max_base_vect_el_value;
881 /* Macros to access members of unions. Use only them for access to
882 union members of declarations and regexps. */
884 #if defined ENABLE_CHECKING && (GCC_VERSION >= 2007)
886 #define DECL_UNIT(d) __extension__ \
887 (({ __typeof (d) const _decl = (d); \
888 if (_decl->mode != dm_unit) \
889 decl_mode_check_failed (_decl->mode, "dm_unit", \
890 __FILE__, __LINE__, __FUNCTION__); \
891 &(_decl)->decl.unit; }))
893 #define DECL_BYPASS(d) __extension__ \
894 (({ __typeof (d) const _decl = (d); \
895 if (_decl->mode != dm_bypass) \
896 decl_mode_check_failed (_decl->mode, "dm_bypass", \
897 __FILE__, __LINE__, __FUNCTION__); \
898 &(_decl)->decl.bypass; }))
900 #define DECL_AUTOMATON(d) __extension__ \
901 (({ __typeof (d) const _decl = (d); \
902 if (_decl->mode != dm_automaton) \
903 decl_mode_check_failed (_decl->mode, "dm_automaton", \
904 __FILE__, __LINE__, __FUNCTION__); \
905 &(_decl)->decl.automaton; }))
907 #define DECL_EXCL(d) __extension__ \
908 (({ __typeof (d) const _decl = (d); \
909 if (_decl->mode != dm_excl) \
910 decl_mode_check_failed (_decl->mode, "dm_excl", \
911 __FILE__, __LINE__, __FUNCTION__); \
912 &(_decl)->decl.excl; }))
914 #define DECL_PRESENCE(d) __extension__ \
915 (({ __typeof (d) const _decl = (d); \
916 if (_decl->mode != dm_presence) \
917 decl_mode_check_failed (_decl->mode, "dm_presence", \
918 __FILE__, __LINE__, __FUNCTION__); \
919 &(_decl)->decl.presence; }))
921 #define DECL_ABSENCE(d) __extension__ \
922 (({ __typeof (d) const _decl = (d); \
923 if (_decl->mode != dm_absence) \
924 decl_mode_check_failed (_decl->mode, "dm_absence", \
925 __FILE__, __LINE__, __FUNCTION__); \
926 &(_decl)->decl.absence; }))
928 #define DECL_RESERV(d) __extension__ \
929 (({ __typeof (d) const _decl = (d); \
930 if (_decl->mode != dm_reserv) \
931 decl_mode_check_failed (_decl->mode, "dm_reserv", \
932 __FILE__, __LINE__, __FUNCTION__); \
933 &(_decl)->decl.reserv; }))
935 #define DECL_INSN_RESERV(d) __extension__ \
936 (({ __typeof (d) const _decl = (d); \
937 if (_decl->mode != dm_insn_reserv) \
938 decl_mode_check_failed (_decl->mode, "dm_insn_reserv", \
939 __FILE__, __LINE__, __FUNCTION__); \
940 &(_decl)->decl.insn_reserv; }))
942 static const char *decl_name (enum decl_mode);
943 static void decl_mode_check_failed (enum decl_mode, const char *,
944 const char *, int, const char *)
945 ATTRIBUTE_NORETURN;
947 /* Return string representation of declaration mode MODE. */
948 static const char *
949 decl_name (enum decl_mode mode)
951 static char str [100];
953 if (mode == dm_unit)
954 return "dm_unit";
955 else if (mode == dm_bypass)
956 return "dm_bypass";
957 else if (mode == dm_automaton)
958 return "dm_automaton";
959 else if (mode == dm_excl)
960 return "dm_excl";
961 else if (mode == dm_presence)
962 return "dm_presence";
963 else if (mode == dm_absence)
964 return "dm_absence";
965 else if (mode == dm_reserv)
966 return "dm_reserv";
967 else if (mode == dm_insn_reserv)
968 return "dm_insn_reserv";
969 else
970 sprintf (str, "unknown (%d)", (int) mode);
971 return str;
974 /* The function prints message about unexpected declaration and finish
975 the program. */
976 static void
977 decl_mode_check_failed (enum decl_mode mode, const char *expected_mode_str,
978 const char *file, int line, const char *func)
980 fprintf
981 (stderr,
982 "\n%s: %d: error in %s: DECL check: expected decl %s, have %s\n",
983 file, line, func, expected_mode_str, decl_name (mode));
984 exit (1);
988 #define REGEXP_UNIT(r) __extension__ \
989 (({ struct regexp *const _regexp = (r); \
990 if (_regexp->mode != rm_unit) \
991 regexp_mode_check_failed (_regexp->mode, "rm_unit", \
992 __FILE__, __LINE__, __FUNCTION__); \
993 &(_regexp)->regexp.unit; }))
995 #define REGEXP_RESERV(r) __extension__ \
996 (({ struct regexp *const _regexp = (r); \
997 if (_regexp->mode != rm_reserv) \
998 regexp_mode_check_failed (_regexp->mode, "rm_reserv", \
999 __FILE__, __LINE__, __FUNCTION__); \
1000 &(_regexp)->regexp.reserv; }))
1002 #define REGEXP_SEQUENCE(r) __extension__ \
1003 (({ struct regexp *const _regexp = (r); \
1004 if (_regexp->mode != rm_sequence) \
1005 regexp_mode_check_failed (_regexp->mode, "rm_sequence", \
1006 __FILE__, __LINE__, __FUNCTION__); \
1007 &(_regexp)->regexp.sequence; }))
1009 #define REGEXP_REPEAT(r) __extension__ \
1010 (({ struct regexp *const _regexp = (r); \
1011 if (_regexp->mode != rm_repeat) \
1012 regexp_mode_check_failed (_regexp->mode, "rm_repeat", \
1013 __FILE__, __LINE__, __FUNCTION__); \
1014 &(_regexp)->regexp.repeat; }))
1016 #define REGEXP_ALLOF(r) __extension__ \
1017 (({ struct regexp *const _regexp = (r); \
1018 if (_regexp->mode != rm_allof) \
1019 regexp_mode_check_failed (_regexp->mode, "rm_allof", \
1020 __FILE__, __LINE__, __FUNCTION__); \
1021 &(_regexp)->regexp.allof; }))
1023 #define REGEXP_ONEOF(r) __extension__ \
1024 (({ struct regexp *const _regexp = (r); \
1025 if (_regexp->mode != rm_oneof) \
1026 regexp_mode_check_failed (_regexp->mode, "rm_oneof", \
1027 __FILE__, __LINE__, __FUNCTION__); \
1028 &(_regexp)->regexp.oneof; }))
1030 static const char *regexp_name (enum regexp_mode);
1031 static void regexp_mode_check_failed (enum regexp_mode, const char *,
1032 const char *, int,
1033 const char *) ATTRIBUTE_NORETURN;
1036 /* Return string representation of regexp mode MODE. */
1037 static const char *
1038 regexp_name (enum regexp_mode mode)
1040 switch (mode)
1042 case rm_unit:
1043 return "rm_unit";
1044 case rm_reserv:
1045 return "rm_reserv";
1046 case rm_nothing:
1047 return "rm_nothing";
1048 case rm_sequence:
1049 return "rm_sequence";
1050 case rm_repeat:
1051 return "rm_repeat";
1052 case rm_allof:
1053 return "rm_allof";
1054 case rm_oneof:
1055 return "rm_oneof";
1056 default:
1057 gcc_unreachable ();
1061 /* The function prints message about unexpected regexp and finish the
1062 program. */
1063 static void
1064 regexp_mode_check_failed (enum regexp_mode mode,
1065 const char *expected_mode_str,
1066 const char *file, int line, const char *func)
1068 fprintf
1069 (stderr,
1070 "\n%s: %d: error in %s: REGEXP check: expected decl %s, have %s\n",
1071 file, line, func, expected_mode_str, regexp_name (mode));
1072 exit (1);
1075 #else /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */
1077 #define DECL_UNIT(d) (&(d)->decl.unit)
1078 #define DECL_BYPASS(d) (&(d)->decl.bypass)
1079 #define DECL_AUTOMATON(d) (&(d)->decl.automaton)
1080 #define DECL_EXCL(d) (&(d)->decl.excl)
1081 #define DECL_PRESENCE(d) (&(d)->decl.presence)
1082 #define DECL_ABSENCE(d) (&(d)->decl.absence)
1083 #define DECL_RESERV(d) (&(d)->decl.reserv)
1084 #define DECL_INSN_RESERV(d) (&(d)->decl.insn_reserv)
1086 #define REGEXP_UNIT(r) (&(r)->regexp.unit)
1087 #define REGEXP_RESERV(r) (&(r)->regexp.reserv)
1088 #define REGEXP_SEQUENCE(r) (&(r)->regexp.sequence)
1089 #define REGEXP_REPEAT(r) (&(r)->regexp.repeat)
1090 #define REGEXP_ALLOF(r) (&(r)->regexp.allof)
1091 #define REGEXP_ONEOF(r) (&(r)->regexp.oneof)
1093 #endif /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */
1095 #define XCREATENODE(T) ((T *) create_node (sizeof (T)))
1096 #define XCREATENODEVEC(T, N) ((T *) create_node (sizeof (T) * (N)))
1097 #define XCREATENODEVAR(T, S) ((T *) create_node ((S)))
1099 #define XCOPYNODE(T, P) ((T *) copy_node ((P), sizeof (T)))
1100 #define XCOPYNODEVEC(T, P, N) ((T *) copy_node ((P), sizeof (T) * (N)))
1101 #define XCOPYNODEVAR(T, P, S) ((T *) copy_node ((P), (S)))
1103 /* Create IR structure (node). */
1104 static void *
1105 create_node (size_t size)
1107 void *result;
1109 obstack_blank (&irp, size);
1110 result = obstack_base (&irp);
1111 obstack_finish (&irp);
1112 /* Default values of members are NULL and zero. */
1113 memset (result, 0, size);
1114 return result;
1117 /* Copy IR structure (node). */
1118 static void *
1119 copy_node (const void *from, size_t size)
1121 void *const result = create_node (size);
1122 memcpy (result, from, size);
1123 return result;
1126 /* The function checks that NAME does not contain quotes (`"'). */
1127 static const char *
1128 check_name (const char * name, pos_t pos ATTRIBUTE_UNUSED)
1130 const char *str;
1132 for (str = name; *str != '\0'; str++)
1133 if (*str == '\"')
1134 error ("Name `%s' contains quotes", name);
1135 return name;
1138 /* Pointers to all declarations during IR generation are stored in the
1139 following. */
1140 static VEC(decl_t, heap) *decls;
1142 /* Given a pointer to a (char *) and a separator, return an alloc'ed
1143 string containing the next separated element, taking parentheses
1144 into account if PAR_FLAG has nonzero value. Advance the pointer to
1145 after the string scanned, or the end-of-string. Return NULL if at
1146 end of string. */
1147 static char *
1148 next_sep_el (const char **pstr, int sep, int par_flag)
1150 char *out_str;
1151 const char *p;
1152 int pars_num;
1153 int n_spaces;
1155 /* Remove leading whitespaces. */
1156 while (ISSPACE ((int) **pstr))
1157 (*pstr)++;
1159 if (**pstr == '\0')
1160 return NULL;
1162 n_spaces = 0;
1163 for (pars_num = 0, p = *pstr; *p != '\0'; p++)
1165 if (par_flag && *p == '(')
1166 pars_num++;
1167 else if (par_flag && *p == ')')
1168 pars_num--;
1169 else if (pars_num == 0 && *p == sep)
1170 break;
1171 if (pars_num == 0 && ISSPACE ((int) *p))
1172 n_spaces++;
1173 else
1175 for (; n_spaces != 0; n_spaces--)
1176 obstack_1grow (&irp, p [-n_spaces]);
1177 obstack_1grow (&irp, *p);
1180 obstack_1grow (&irp, '\0');
1181 out_str = obstack_base (&irp);
1182 obstack_finish (&irp);
1184 *pstr = p;
1185 if (**pstr == sep)
1186 (*pstr)++;
1188 return out_str;
1191 /* Given a string and a separator, return the number of separated
1192 elements in it, taking parentheses into account if PAR_FLAG has
1193 nonzero value. Return 0 for the null string, -1 if parentheses is
1194 not balanced. */
1195 static int
1196 n_sep_els (const char *s, int sep, int par_flag)
1198 int n;
1199 int pars_num;
1201 if (*s == '\0')
1202 return 0;
1204 for (pars_num = 0, n = 1; *s; s++)
1205 if (par_flag && *s == '(')
1206 pars_num++;
1207 else if (par_flag && *s == ')')
1208 pars_num--;
1209 else if (pars_num == 0 && *s == sep)
1210 n++;
1212 return (pars_num != 0 ? -1 : n);
1215 /* Given a string and a separator, return vector of strings which are
1216 elements in the string and number of elements through els_num.
1217 Take parentheses into account if PAREN_P has nonzero value. The
1218 function also inserts the end marker NULL at the end of vector.
1219 Return 0 for the null string, -1 if parentheses are not balanced. */
1220 static char **
1221 get_str_vect (const char *str, int *els_num, int sep, int paren_p)
1223 int i;
1224 char **vect;
1225 const char **pstr;
1226 char *trail;
1228 *els_num = n_sep_els (str, sep, paren_p);
1229 if (*els_num <= 0)
1230 return NULL;
1231 obstack_blank (&irp, sizeof (char *) * (*els_num + 1));
1232 vect = (char **) obstack_base (&irp);
1233 obstack_finish (&irp);
1234 pstr = &str;
1235 for (i = 0; i < *els_num; i++)
1236 vect [i] = next_sep_el (pstr, sep, paren_p);
1237 trail = next_sep_el (pstr, sep, paren_p);
1238 gcc_assert (!trail);
1239 vect [i] = NULL;
1240 return vect;
1243 /* Process a DEFINE_CPU_UNIT.
1245 This gives information about a unit contained in CPU. We fill a
1246 struct unit_decl with information used later by `expand_automata'. */
1247 static void
1248 gen_cpu_unit (rtx def)
1250 decl_t decl;
1251 char **str_cpu_units;
1252 int vect_length;
1253 int i;
1255 str_cpu_units = get_str_vect (XSTR (def, 0), &vect_length, ',', FALSE);
1256 if (str_cpu_units == NULL)
1257 fatal ("invalid string `%s' in define_cpu_unit", XSTR (def, 0));
1258 for (i = 0; i < vect_length; i++)
1260 decl = XCREATENODE (struct decl);
1261 decl->mode = dm_unit;
1262 decl->pos = 0;
1263 DECL_UNIT (decl)->name = check_name (str_cpu_units [i], decl->pos);
1264 DECL_UNIT (decl)->automaton_name = XSTR (def, 1);
1265 DECL_UNIT (decl)->query_p = 0;
1266 DECL_UNIT (decl)->min_occ_cycle_num = -1;
1267 DECL_UNIT (decl)->in_set_p = 0;
1268 VEC_safe_push (decl_t, heap, decls, decl);
1272 /* Process a DEFINE_QUERY_CPU_UNIT.
1274 This gives information about a unit contained in CPU. We fill a
1275 struct unit_decl with information used later by `expand_automata'. */
1276 static void
1277 gen_query_cpu_unit (rtx def)
1279 decl_t decl;
1280 char **str_cpu_units;
1281 int vect_length;
1282 int i;
1284 str_cpu_units = get_str_vect (XSTR (def, 0), &vect_length, ',',
1285 FALSE);
1286 if (str_cpu_units == NULL)
1287 fatal ("invalid string `%s' in define_query_cpu_unit", XSTR (def, 0));
1288 for (i = 0; i < vect_length; i++)
1290 decl = XCREATENODE (struct decl);
1291 decl->mode = dm_unit;
1292 decl->pos = 0;
1293 DECL_UNIT (decl)->name = check_name (str_cpu_units [i], decl->pos);
1294 DECL_UNIT (decl)->automaton_name = XSTR (def, 1);
1295 DECL_UNIT (decl)->query_p = 1;
1296 VEC_safe_push (decl_t, heap, decls, decl);
1300 /* Process a DEFINE_BYPASS.
1302 This gives information about a unit contained in the CPU. We fill
1303 in a struct bypass_decl with information used later by
1304 `expand_automata'. */
1305 static void
1306 gen_bypass (rtx def)
1308 decl_t decl;
1309 char **out_insns;
1310 int out_length;
1311 char **in_insns;
1312 int in_length;
1313 int i, j;
1315 out_insns = get_str_vect (XSTR (def, 1), &out_length, ',', FALSE);
1316 if (out_insns == NULL)
1317 fatal ("invalid string `%s' in define_bypass", XSTR (def, 1));
1318 in_insns = get_str_vect (XSTR (def, 2), &in_length, ',', FALSE);
1319 if (in_insns == NULL)
1320 fatal ("invalid string `%s' in define_bypass", XSTR (def, 2));
1321 for (i = 0; i < out_length; i++)
1322 for (j = 0; j < in_length; j++)
1324 decl = XCREATENODE (struct decl);
1325 decl->mode = dm_bypass;
1326 decl->pos = 0;
1327 DECL_BYPASS (decl)->latency = XINT (def, 0);
1328 DECL_BYPASS (decl)->out_insn_name = out_insns [i];
1329 DECL_BYPASS (decl)->in_insn_name = in_insns [j];
1330 DECL_BYPASS (decl)->bypass_guard_name = XSTR (def, 3);
1331 VEC_safe_push (decl_t, heap, decls, decl);
1335 /* Process an EXCLUSION_SET.
1337 This gives information about a cpu unit conflicts. We fill a
1338 struct excl_rel_decl (excl) with information used later by
1339 `expand_automata'. */
1340 static void
1341 gen_excl_set (rtx def)
1343 decl_t decl;
1344 char **first_str_cpu_units;
1345 char **second_str_cpu_units;
1346 int first_vect_length;
1347 int length;
1348 int i;
1350 first_str_cpu_units
1351 = get_str_vect (XSTR (def, 0), &first_vect_length, ',', FALSE);
1352 if (first_str_cpu_units == NULL)
1353 fatal ("invalid first string `%s' in exclusion_set", XSTR (def, 0));
1354 second_str_cpu_units = get_str_vect (XSTR (def, 1), &length, ',',
1355 FALSE);
1356 if (second_str_cpu_units == NULL)
1357 fatal ("invalid second string `%s' in exclusion_set", XSTR (def, 1));
1358 length += first_vect_length;
1359 decl = XCREATENODEVAR (struct decl, sizeof (struct decl) + (length - 1) * sizeof (char *));
1360 decl->mode = dm_excl;
1361 decl->pos = 0;
1362 DECL_EXCL (decl)->all_names_num = length;
1363 DECL_EXCL (decl)->first_list_length = first_vect_length;
1364 for (i = 0; i < length; i++)
1365 if (i < first_vect_length)
1366 DECL_EXCL (decl)->names [i] = first_str_cpu_units [i];
1367 else
1368 DECL_EXCL (decl)->names [i]
1369 = second_str_cpu_units [i - first_vect_length];
1370 VEC_safe_push (decl_t, heap, decls, decl);
1373 /* Process a PRESENCE_SET, a FINAL_PRESENCE_SET, an ABSENCE_SET,
1374 FINAL_ABSENCE_SET (it is depended on PRESENCE_P and FINAL_P).
1376 This gives information about a cpu unit reservation requirements.
1377 We fill a struct unit_pattern_rel_decl with information used later
1378 by `expand_automata'. */
1379 static void
1380 gen_presence_absence_set (rtx def, int presence_p, int final_p)
1382 decl_t decl;
1383 char **str_cpu_units;
1384 char **str_pattern_lists;
1385 char ***str_patterns;
1386 int cpu_units_length;
1387 int length;
1388 int patterns_length;
1389 int i;
1391 str_cpu_units = get_str_vect (XSTR (def, 0), &cpu_units_length, ',',
1392 FALSE);
1393 if (str_cpu_units == NULL)
1394 fatal ((presence_p
1395 ? (final_p
1396 ? "invalid first string `%s' in final_presence_set"
1397 : "invalid first string `%s' in presence_set")
1398 : (final_p
1399 ? "invalid first string `%s' in final_absence_set"
1400 : "invalid first string `%s' in absence_set")),
1401 XSTR (def, 0));
1402 str_pattern_lists = get_str_vect (XSTR (def, 1),
1403 &patterns_length, ',', FALSE);
1404 if (str_pattern_lists == NULL)
1405 fatal ((presence_p
1406 ? (final_p
1407 ? "invalid second string `%s' in final_presence_set"
1408 : "invalid second string `%s' in presence_set")
1409 : (final_p
1410 ? "invalid second string `%s' in final_absence_set"
1411 : "invalid second string `%s' in absence_set")), XSTR (def, 1));
1412 str_patterns = XOBNEWVEC (&irp, char **, patterns_length);
1413 for (i = 0; i < patterns_length; i++)
1415 str_patterns [i] = get_str_vect (str_pattern_lists [i],
1416 &length, ' ', FALSE);
1417 gcc_assert (str_patterns [i]);
1419 decl = XCREATENODE (struct decl);
1420 decl->pos = 0;
1421 if (presence_p)
1423 decl->mode = dm_presence;
1424 DECL_PRESENCE (decl)->names_num = cpu_units_length;
1425 DECL_PRESENCE (decl)->names = str_cpu_units;
1426 DECL_PRESENCE (decl)->patterns = str_patterns;
1427 DECL_PRESENCE (decl)->patterns_num = patterns_length;
1428 DECL_PRESENCE (decl)->final_p = final_p;
1430 else
1432 decl->mode = dm_absence;
1433 DECL_ABSENCE (decl)->names_num = cpu_units_length;
1434 DECL_ABSENCE (decl)->names = str_cpu_units;
1435 DECL_ABSENCE (decl)->patterns = str_patterns;
1436 DECL_ABSENCE (decl)->patterns_num = patterns_length;
1437 DECL_ABSENCE (decl)->final_p = final_p;
1439 VEC_safe_push (decl_t, heap, decls, decl);
1442 /* Process a PRESENCE_SET.
1444 This gives information about a cpu unit reservation requirements.
1445 We fill a struct unit_pattern_rel_decl (presence) with information
1446 used later by `expand_automata'. */
1447 static void
1448 gen_presence_set (rtx def)
1450 gen_presence_absence_set (def, TRUE, FALSE);
1453 /* Process a FINAL_PRESENCE_SET.
1455 This gives information about a cpu unit reservation requirements.
1456 We fill a struct unit_pattern_rel_decl (presence) with information
1457 used later by `expand_automata'. */
1458 static void
1459 gen_final_presence_set (rtx def)
1461 gen_presence_absence_set (def, TRUE, TRUE);
1464 /* Process an ABSENCE_SET.
1466 This gives information about a cpu unit reservation requirements.
1467 We fill a struct unit_pattern_rel_decl (absence) with information
1468 used later by `expand_automata'. */
1469 static void
1470 gen_absence_set (rtx def)
1472 gen_presence_absence_set (def, FALSE, FALSE);
1475 /* Process a FINAL_ABSENCE_SET.
1477 This gives information about a cpu unit reservation requirements.
1478 We fill a struct unit_pattern_rel_decl (absence) with information
1479 used later by `expand_automata'. */
1480 static void
1481 gen_final_absence_set (rtx def)
1483 gen_presence_absence_set (def, FALSE, TRUE);
1486 /* Process a DEFINE_AUTOMATON.
1488 This gives information about a finite state automaton used for
1489 recognizing pipeline hazards. We fill a struct automaton_decl
1490 with information used later by `expand_automata'. */
1491 static void
1492 gen_automaton (rtx def)
1494 decl_t decl;
1495 char **str_automata;
1496 int vect_length;
1497 int i;
1499 str_automata = get_str_vect (XSTR (def, 0), &vect_length, ',', FALSE);
1500 if (str_automata == NULL)
1501 fatal ("invalid string `%s' in define_automaton", XSTR (def, 0));
1502 for (i = 0; i < vect_length; i++)
1504 decl = XCREATENODE (struct decl);
1505 decl->mode = dm_automaton;
1506 decl->pos = 0;
1507 DECL_AUTOMATON (decl)->name = check_name (str_automata [i], decl->pos);
1508 VEC_safe_push (decl_t, heap, decls, decl);
1512 /* Process an AUTOMATA_OPTION.
1514 This gives information how to generate finite state automaton used
1515 for recognizing pipeline hazards. */
1516 static void
1517 gen_automata_option (rtx def)
1519 if (strcmp (XSTR (def, 0), NO_MINIMIZATION_OPTION + 1) == 0)
1520 no_minimization_flag = 1;
1521 else if (strcmp (XSTR (def, 0), TIME_OPTION + 1) == 0)
1522 time_flag = 1;
1523 else if (strcmp (XSTR (def, 0), STATS_OPTION + 1) == 0)
1524 stats_flag = 1;
1525 else if (strcmp (XSTR (def, 0), V_OPTION + 1) == 0)
1526 v_flag = 1;
1527 else if (strcmp (XSTR (def, 0), W_OPTION + 1) == 0)
1528 w_flag = 1;
1529 else if (strcmp (XSTR (def, 0), NDFA_OPTION + 1) == 0)
1530 ndfa_flag = 1;
1531 else if (strcmp (XSTR (def, 0), PROGRESS_OPTION + 1) == 0)
1532 progress_flag = 1;
1533 else
1534 fatal ("invalid option `%s' in automata_option", XSTR (def, 0));
1537 /* Name in reservation to denote absence reservation. */
1538 #define NOTHING_NAME "nothing"
1540 /* The following string contains original reservation string being
1541 parsed. */
1542 static const char *reserv_str;
1544 /* Parse an element in STR. */
1545 static regexp_t
1546 gen_regexp_el (const char *str)
1548 regexp_t regexp;
1549 char *dstr;
1550 int len;
1552 if (*str == '(')
1554 len = strlen (str);
1555 if (str [len - 1] != ')')
1556 fatal ("garbage after ) in reservation `%s'", reserv_str);
1557 dstr = XALLOCAVAR (char, len - 1);
1558 memcpy (dstr, str + 1, len - 2);
1559 dstr [len-2] = '\0';
1560 regexp = gen_regexp_sequence (dstr);
1562 else if (strcmp (str, NOTHING_NAME) == 0)
1564 regexp = XCREATENODE (struct regexp);
1565 regexp->mode = rm_nothing;
1567 else
1569 regexp = XCREATENODE (struct regexp);
1570 regexp->mode = rm_unit;
1571 REGEXP_UNIT (regexp)->name = str;
1573 return regexp;
1576 /* Parse construction `repeat' in STR. */
1577 static regexp_t
1578 gen_regexp_repeat (const char *str)
1580 regexp_t regexp;
1581 regexp_t repeat;
1582 char **repeat_vect;
1583 int els_num;
1584 int i;
1586 repeat_vect = get_str_vect (str, &els_num, '*', TRUE);
1587 if (repeat_vect == NULL)
1588 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1589 if (els_num > 1)
1591 regexp = gen_regexp_el (repeat_vect [0]);
1592 for (i = 1; i < els_num; i++)
1594 repeat = XCREATENODE (struct regexp);
1595 repeat->mode = rm_repeat;
1596 REGEXP_REPEAT (repeat)->regexp = regexp;
1597 REGEXP_REPEAT (repeat)->repeat_num = atoi (repeat_vect [i]);
1598 if (REGEXP_REPEAT (repeat)->repeat_num <= 1)
1599 fatal ("repetition `%s' <= 1 in reservation `%s'",
1600 str, reserv_str);
1601 regexp = repeat;
1603 return regexp;
1605 else
1606 return gen_regexp_el (str);
1609 /* Parse reservation STR which possibly contains separator '+'. */
1610 static regexp_t
1611 gen_regexp_allof (const char *str)
1613 regexp_t allof;
1614 char **allof_vect;
1615 int els_num;
1616 int i;
1618 allof_vect = get_str_vect (str, &els_num, '+', TRUE);
1619 if (allof_vect == NULL)
1620 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1621 if (els_num > 1)
1623 allof = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
1624 + sizeof (regexp_t) * (els_num - 1));
1625 allof->mode = rm_allof;
1626 REGEXP_ALLOF (allof)->regexps_num = els_num;
1627 for (i = 0; i < els_num; i++)
1628 REGEXP_ALLOF (allof)->regexps [i] = gen_regexp_repeat (allof_vect [i]);
1629 return allof;
1631 else
1632 return gen_regexp_repeat (str);
1635 /* Parse reservation STR which possibly contains separator '|'. */
1636 static regexp_t
1637 gen_regexp_oneof (const char *str)
1639 regexp_t oneof;
1640 char **oneof_vect;
1641 int els_num;
1642 int i;
1644 oneof_vect = get_str_vect (str, &els_num, '|', TRUE);
1645 if (oneof_vect == NULL)
1646 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1647 if (els_num > 1)
1649 oneof = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
1650 + sizeof (regexp_t) * (els_num - 1));
1651 oneof->mode = rm_oneof;
1652 REGEXP_ONEOF (oneof)->regexps_num = els_num;
1653 for (i = 0; i < els_num; i++)
1654 REGEXP_ONEOF (oneof)->regexps [i] = gen_regexp_allof (oneof_vect [i]);
1655 return oneof;
1657 else
1658 return gen_regexp_allof (str);
1661 /* Parse reservation STR which possibly contains separator ','. */
1662 static regexp_t
1663 gen_regexp_sequence (const char *str)
1665 regexp_t sequence;
1666 char **sequence_vect;
1667 int els_num;
1668 int i;
1670 sequence_vect = get_str_vect (str, &els_num, ',', TRUE);
1671 if (els_num > 1)
1673 sequence = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
1674 + sizeof (regexp_t) * (els_num - 1));
1675 sequence->mode = rm_sequence;
1676 REGEXP_SEQUENCE (sequence)->regexps_num = els_num;
1677 for (i = 0; i < els_num; i++)
1678 REGEXP_SEQUENCE (sequence)->regexps [i]
1679 = gen_regexp_oneof (sequence_vect [i]);
1680 return sequence;
1682 else
1683 return gen_regexp_oneof (str);
1686 /* Parse construction reservation STR. */
1687 static regexp_t
1688 gen_regexp (const char *str)
1690 reserv_str = str;
1691 return gen_regexp_sequence (str);;
1694 /* Process a DEFINE_RESERVATION.
1696 This gives information about a reservation of cpu units. We fill
1697 in a struct reserv_decl with information used later by
1698 `expand_automata'. */
1699 static void
1700 gen_reserv (rtx def)
1702 decl_t decl;
1704 decl = XCREATENODE (struct decl);
1705 decl->mode = dm_reserv;
1706 decl->pos = 0;
1707 DECL_RESERV (decl)->name = check_name (XSTR (def, 0), decl->pos);
1708 DECL_RESERV (decl)->regexp = gen_regexp (XSTR (def, 1));
1709 VEC_safe_push (decl_t, heap, decls, decl);
1712 /* Process a DEFINE_INSN_RESERVATION.
1714 This gives information about the reservation of cpu units by an
1715 insn. We fill a struct insn_reserv_decl with information used
1716 later by `expand_automata'. */
1717 static void
1718 gen_insn_reserv (rtx def)
1720 decl_t decl;
1722 decl = XCREATENODE (struct decl);
1723 decl->mode = dm_insn_reserv;
1724 decl->pos = 0;
1725 DECL_INSN_RESERV (decl)->name
1726 = check_name (XSTR (def, 0), decl->pos);
1727 DECL_INSN_RESERV (decl)->default_latency = XINT (def, 1);
1728 DECL_INSN_RESERV (decl)->condexp = XEXP (def, 2);
1729 DECL_INSN_RESERV (decl)->regexp = gen_regexp (XSTR (def, 3));
1730 VEC_safe_push (decl_t, heap, decls, decl);
1735 /* The function evaluates hash value (0..UINT_MAX) of string. */
1736 static unsigned
1737 string_hash (const char *string)
1739 unsigned result, i;
1741 for (result = i = 0;*string++ != '\0'; i++)
1742 result += ((unsigned char) *string << (i % CHAR_BIT));
1743 return result;
1748 /* This page contains abstract data `table of automaton declarations'.
1749 Elements of the table is nodes representing automaton declarations.
1750 Key of the table elements is name of given automaton. Remember
1751 that automaton names have own space. */
1753 /* The function evaluates hash value of an automaton declaration. The
1754 function is used by abstract data `hashtab'. The function returns
1755 hash value (0..UINT_MAX) of given automaton declaration. */
1756 static hashval_t
1757 automaton_decl_hash (const void *automaton_decl)
1759 const_decl_t const decl = (const_decl_t) automaton_decl;
1761 gcc_assert (decl->mode != dm_automaton
1762 || DECL_AUTOMATON (decl)->name);
1763 return string_hash (DECL_AUTOMATON (decl)->name);
1766 /* The function tests automaton declarations on equality of their
1767 keys. The function is used by abstract data `hashtab'. The
1768 function returns 1 if the declarations have the same key, 0
1769 otherwise. */
1770 static int
1771 automaton_decl_eq_p (const void* automaton_decl_1,
1772 const void* automaton_decl_2)
1774 const_decl_t const decl1 = (const_decl_t) automaton_decl_1;
1775 const_decl_t const decl2 = (const_decl_t) automaton_decl_2;
1777 gcc_assert (decl1->mode == dm_automaton
1778 && DECL_AUTOMATON (decl1)->name
1779 && decl2->mode == dm_automaton
1780 && DECL_AUTOMATON (decl2)->name);
1781 return strcmp (DECL_AUTOMATON (decl1)->name,
1782 DECL_AUTOMATON (decl2)->name) == 0;
1785 /* The automaton declaration table itself is represented by the
1786 following variable. */
1787 static htab_t automaton_decl_table;
1789 /* The function inserts automaton declaration into the table. The
1790 function does nothing if an automaton declaration with the same key
1791 exists already in the table. The function returns automaton
1792 declaration node in the table with the same key as given automaton
1793 declaration node. */
1794 static decl_t
1795 insert_automaton_decl (decl_t automaton_decl)
1797 void **entry_ptr;
1799 entry_ptr = htab_find_slot (automaton_decl_table, automaton_decl, INSERT);
1800 if (*entry_ptr == NULL)
1801 *entry_ptr = (void *) automaton_decl;
1802 return (decl_t) *entry_ptr;
1805 /* The following variable value is node representing automaton
1806 declaration. The node used for searching automaton declaration
1807 with given name. */
1808 static struct decl work_automaton_decl;
1810 /* The function searches for automaton declaration in the table with
1811 the same key as node representing name of the automaton
1812 declaration. The function returns node found in the table, NULL if
1813 such node does not exist in the table. */
1814 static decl_t
1815 find_automaton_decl (const char *name)
1817 void *entry;
1819 work_automaton_decl.mode = dm_automaton;
1820 DECL_AUTOMATON (&work_automaton_decl)->name = name;
1821 entry = htab_find (automaton_decl_table, &work_automaton_decl);
1822 return (decl_t) entry;
1825 /* The function creates empty automaton declaration table and node
1826 representing automaton declaration and used for searching automaton
1827 declaration with given name. The function must be called only once
1828 before any work with the automaton declaration table. */
1829 static void
1830 initiate_automaton_decl_table (void)
1832 work_automaton_decl.mode = dm_automaton;
1833 automaton_decl_table = htab_create (10, automaton_decl_hash,
1834 automaton_decl_eq_p, (htab_del) 0);
1837 /* The function deletes the automaton declaration table. Only call of
1838 function `initiate_automaton_decl_table' is possible immediately
1839 after this function call. */
1840 static void
1841 finish_automaton_decl_table (void)
1843 htab_delete (automaton_decl_table);
1848 /* This page contains abstract data `table of insn declarations'.
1849 Elements of the table is nodes representing insn declarations. Key
1850 of the table elements is name of given insn (in corresponding
1851 define_insn_reservation). Remember that insn names have own
1852 space. */
1854 /* The function evaluates hash value of an insn declaration. The
1855 function is used by abstract data `hashtab'. The function returns
1856 hash value (0..UINT_MAX) of given insn declaration. */
1857 static hashval_t
1858 insn_decl_hash (const void *insn_decl)
1860 const_decl_t const decl = (const_decl_t) insn_decl;
1862 gcc_assert (decl->mode == dm_insn_reserv
1863 && DECL_INSN_RESERV (decl)->name);
1864 return string_hash (DECL_INSN_RESERV (decl)->name);
1867 /* The function tests insn declarations on equality of their keys.
1868 The function is used by abstract data `hashtab'. The function
1869 returns 1 if declarations have the same key, 0 otherwise. */
1870 static int
1871 insn_decl_eq_p (const void *insn_decl_1, const void *insn_decl_2)
1873 const_decl_t const decl1 = (const_decl_t) insn_decl_1;
1874 const_decl_t const decl2 = (const_decl_t) insn_decl_2;
1876 gcc_assert (decl1->mode == dm_insn_reserv
1877 && DECL_INSN_RESERV (decl1)->name
1878 && decl2->mode == dm_insn_reserv
1879 && DECL_INSN_RESERV (decl2)->name);
1880 return strcmp (DECL_INSN_RESERV (decl1)->name,
1881 DECL_INSN_RESERV (decl2)->name) == 0;
1884 /* The insn declaration table itself is represented by the following
1885 variable. The table does not contain insn reservation
1886 declarations. */
1887 static htab_t insn_decl_table;
1889 /* The function inserts insn declaration into the table. The function
1890 does nothing if an insn declaration with the same key exists
1891 already in the table. The function returns insn declaration node
1892 in the table with the same key as given insn declaration node. */
1893 static decl_t
1894 insert_insn_decl (decl_t insn_decl)
1896 void **entry_ptr;
1898 entry_ptr = htab_find_slot (insn_decl_table, insn_decl, INSERT);
1899 if (*entry_ptr == NULL)
1900 *entry_ptr = (void *) insn_decl;
1901 return (decl_t) *entry_ptr;
1904 /* The following variable value is node representing insn reservation
1905 declaration. The node used for searching insn reservation
1906 declaration with given name. */
1907 static struct decl work_insn_decl;
1909 /* The function searches for insn reservation declaration in the table
1910 with the same key as node representing name of the insn reservation
1911 declaration. The function returns node found in the table, NULL if
1912 such node does not exist in the table. */
1913 static decl_t
1914 find_insn_decl (const char *name)
1916 void *entry;
1918 work_insn_decl.mode = dm_insn_reserv;
1919 DECL_INSN_RESERV (&work_insn_decl)->name = name;
1920 entry = htab_find (insn_decl_table, &work_insn_decl);
1921 return (decl_t) entry;
1924 /* The function creates empty insn declaration table and node
1925 representing insn declaration and used for searching insn
1926 declaration with given name. The function must be called only once
1927 before any work with the insn declaration table. */
1928 static void
1929 initiate_insn_decl_table (void)
1931 work_insn_decl.mode = dm_insn_reserv;
1932 insn_decl_table = htab_create (10, insn_decl_hash, insn_decl_eq_p,
1933 (htab_del) 0);
1936 /* The function deletes the insn declaration table. Only call of
1937 function `initiate_insn_decl_table' is possible immediately after
1938 this function call. */
1939 static void
1940 finish_insn_decl_table (void)
1942 htab_delete (insn_decl_table);
1947 /* This page contains abstract data `table of declarations'. Elements
1948 of the table is nodes representing declarations (of units and
1949 reservations). Key of the table elements is names of given
1950 declarations. */
1952 /* The function evaluates hash value of a declaration. The function
1953 is used by abstract data `hashtab'. The function returns hash
1954 value (0..UINT_MAX) of given declaration. */
1955 static hashval_t
1956 decl_hash (const void *decl)
1958 const_decl_t const d = (const_decl_t) decl;
1960 gcc_assert ((d->mode == dm_unit && DECL_UNIT (d)->name)
1961 || (d->mode == dm_reserv && DECL_RESERV (d)->name));
1962 return string_hash (d->mode == dm_unit
1963 ? DECL_UNIT (d)->name : DECL_RESERV (d)->name);
1966 /* The function tests declarations on equality of their keys. The
1967 function is used by abstract data 'hashtab'. The function
1968 returns 1 if the declarations have the same key, 0 otherwise. */
1969 static int
1970 decl_eq_p (const void *decl_1, const void *decl_2)
1972 const_decl_t const d1 = (const_decl_t) decl_1;
1973 const_decl_t const d2 = (const_decl_t) decl_2;
1975 gcc_assert ((d1->mode == dm_unit && DECL_UNIT (d1)->name)
1976 || (d1->mode == dm_reserv && DECL_RESERV (d1)->name));
1977 gcc_assert ((d2->mode == dm_unit && DECL_UNIT (d2)->name)
1978 || (d2->mode == dm_reserv && DECL_RESERV (d2)->name));
1979 return strcmp ((d1->mode == dm_unit
1980 ? DECL_UNIT (d1)->name : DECL_RESERV (d1)->name),
1981 (d2->mode == dm_unit
1982 ? DECL_UNIT (d2)->name : DECL_RESERV (d2)->name)) == 0;
1985 /* The declaration table itself is represented by the following
1986 variable. */
1987 static htab_t decl_table;
1989 /* The function inserts declaration into the table. The function does
1990 nothing if a declaration with the same key exists already in the
1991 table. The function returns declaration node in the table with the
1992 same key as given declaration node. */
1994 static decl_t
1995 insert_decl (decl_t decl)
1997 void **entry_ptr;
1999 entry_ptr = htab_find_slot (decl_table, decl, INSERT);
2000 if (*entry_ptr == NULL)
2001 *entry_ptr = (void *) decl;
2002 return (decl_t) *entry_ptr;
2005 /* The following variable value is node representing declaration. The
2006 node used for searching declaration with given name. */
2007 static struct decl work_decl;
2009 /* The function searches for declaration in the table with the same
2010 key as node representing name of the declaration. The function
2011 returns node found in the table, NULL if such node does not exist
2012 in the table. */
2013 static decl_t
2014 find_decl (const char *name)
2016 void *entry;
2018 work_decl.mode = dm_unit;
2019 DECL_UNIT (&work_decl)->name = name;
2020 entry = htab_find (decl_table, &work_decl);
2021 return (decl_t) entry;
2024 /* The function creates empty declaration table and node representing
2025 declaration and used for searching declaration with given name.
2026 The function must be called only once before any work with the
2027 declaration table. */
2028 static void
2029 initiate_decl_table (void)
2031 work_decl.mode = dm_unit;
2032 decl_table = htab_create (10, decl_hash, decl_eq_p, (htab_del) 0);
2035 /* The function deletes the declaration table. Only call of function
2036 `initiate_declaration_table' is possible immediately after this
2037 function call. */
2038 static void
2039 finish_decl_table (void)
2041 htab_delete (decl_table);
2046 /* This page contains checker of pipeline hazard description. */
2048 /* Checking NAMES in an exclusion clause vector and returning formed
2049 unit_set_el_list. */
2050 static unit_set_el_t
2051 process_excls (char **names, int num, pos_t excl_pos ATTRIBUTE_UNUSED)
2053 unit_set_el_t el_list;
2054 unit_set_el_t last_el;
2055 unit_set_el_t new_el;
2056 decl_t decl_in_table;
2057 int i;
2059 el_list = NULL;
2060 last_el = NULL;
2061 for (i = 0; i < num; i++)
2063 decl_in_table = find_decl (names [i]);
2064 if (decl_in_table == NULL)
2065 error ("unit `%s' in exclusion is not declared", names [i]);
2066 else if (decl_in_table->mode != dm_unit)
2067 error ("`%s' in exclusion is not unit", names [i]);
2068 else
2070 new_el = XCREATENODE (struct unit_set_el);
2071 new_el->unit_decl = DECL_UNIT (decl_in_table);
2072 new_el->next_unit_set_el = NULL;
2073 if (last_el == NULL)
2074 el_list = last_el = new_el;
2075 else
2077 last_el->next_unit_set_el = new_el;
2078 last_el = last_el->next_unit_set_el;
2082 return el_list;
2085 /* The function adds each element from SOURCE_LIST to the exclusion
2086 list of the each element from DEST_LIST. Checking situation "unit
2087 excludes itself". */
2088 static void
2089 add_excls (unit_set_el_t dest_list, unit_set_el_t source_list,
2090 pos_t excl_pos ATTRIBUTE_UNUSED)
2092 unit_set_el_t dst;
2093 unit_set_el_t src;
2094 unit_set_el_t curr_el;
2095 unit_set_el_t prev_el;
2096 unit_set_el_t copy;
2098 for (dst = dest_list; dst != NULL; dst = dst->next_unit_set_el)
2099 for (src = source_list; src != NULL; src = src->next_unit_set_el)
2101 if (dst->unit_decl == src->unit_decl)
2103 error ("unit `%s' excludes itself", src->unit_decl->name);
2104 continue;
2106 if (dst->unit_decl->automaton_name != NULL
2107 && src->unit_decl->automaton_name != NULL
2108 && strcmp (dst->unit_decl->automaton_name,
2109 src->unit_decl->automaton_name) != 0)
2111 error ("units `%s' and `%s' in exclusion set belong to different automata",
2112 src->unit_decl->name, dst->unit_decl->name);
2113 continue;
2115 for (curr_el = dst->unit_decl->excl_list, prev_el = NULL;
2116 curr_el != NULL;
2117 prev_el = curr_el, curr_el = curr_el->next_unit_set_el)
2118 if (curr_el->unit_decl == src->unit_decl)
2119 break;
2120 if (curr_el == NULL)
2122 /* Element not found - insert. */
2123 copy = XCOPYNODE (struct unit_set_el, src);
2124 copy->next_unit_set_el = NULL;
2125 if (prev_el == NULL)
2126 dst->unit_decl->excl_list = copy;
2127 else
2128 prev_el->next_unit_set_el = copy;
2133 /* Checking NAMES in presence/absence clause and returning the
2134 formed unit_set_el_list. The function is called only after
2135 processing all exclusion sets. */
2136 static unit_set_el_t
2137 process_presence_absence_names (char **names, int num,
2138 pos_t req_pos ATTRIBUTE_UNUSED,
2139 int presence_p, int final_p)
2141 unit_set_el_t el_list;
2142 unit_set_el_t last_el;
2143 unit_set_el_t new_el;
2144 decl_t decl_in_table;
2145 int i;
2147 el_list = NULL;
2148 last_el = NULL;
2149 for (i = 0; i < num; i++)
2151 decl_in_table = find_decl (names [i]);
2152 if (decl_in_table == NULL)
2153 error ((presence_p
2154 ? (final_p
2155 ? "unit `%s' in final presence set is not declared"
2156 : "unit `%s' in presence set is not declared")
2157 : (final_p
2158 ? "unit `%s' in final absence set is not declared"
2159 : "unit `%s' in absence set is not declared")), names [i]);
2160 else if (decl_in_table->mode != dm_unit)
2161 error ((presence_p
2162 ? (final_p
2163 ? "`%s' in final presence set is not unit"
2164 : "`%s' in presence set is not unit")
2165 : (final_p
2166 ? "`%s' in final absence set is not unit"
2167 : "`%s' in absence set is not unit")), names [i]);
2168 else
2170 new_el = XCREATENODE (struct unit_set_el);
2171 new_el->unit_decl = DECL_UNIT (decl_in_table);
2172 new_el->next_unit_set_el = NULL;
2173 if (last_el == NULL)
2174 el_list = last_el = new_el;
2175 else
2177 last_el->next_unit_set_el = new_el;
2178 last_el = last_el->next_unit_set_el;
2182 return el_list;
2185 /* Checking NAMES in patterns of a presence/absence clause and
2186 returning the formed pattern_set_el_list. The function is called
2187 only after processing all exclusion sets. */
2188 static pattern_set_el_t
2189 process_presence_absence_patterns (char ***patterns, int num,
2190 pos_t req_pos ATTRIBUTE_UNUSED,
2191 int presence_p, int final_p)
2193 pattern_set_el_t el_list;
2194 pattern_set_el_t last_el;
2195 pattern_set_el_t new_el;
2196 decl_t decl_in_table;
2197 int i, j;
2199 el_list = NULL;
2200 last_el = NULL;
2201 for (i = 0; i < num; i++)
2203 for (j = 0; patterns [i] [j] != NULL; j++)
2205 new_el = XCREATENODEVAR (struct pattern_set_el,
2206 sizeof (struct pattern_set_el)
2207 + sizeof (struct unit_decl *) * j);
2208 new_el->unit_decls
2209 = (struct unit_decl **) ((char *) new_el
2210 + sizeof (struct pattern_set_el));
2211 new_el->next_pattern_set_el = NULL;
2212 if (last_el == NULL)
2213 el_list = last_el = new_el;
2214 else
2216 last_el->next_pattern_set_el = new_el;
2217 last_el = last_el->next_pattern_set_el;
2219 new_el->units_num = 0;
2220 for (j = 0; patterns [i] [j] != NULL; j++)
2222 decl_in_table = find_decl (patterns [i] [j]);
2223 if (decl_in_table == NULL)
2224 error ((presence_p
2225 ? (final_p
2226 ? "unit `%s' in final presence set is not declared"
2227 : "unit `%s' in presence set is not declared")
2228 : (final_p
2229 ? "unit `%s' in final absence set is not declared"
2230 : "unit `%s' in absence set is not declared")),
2231 patterns [i] [j]);
2232 else if (decl_in_table->mode != dm_unit)
2233 error ((presence_p
2234 ? (final_p
2235 ? "`%s' in final presence set is not unit"
2236 : "`%s' in presence set is not unit")
2237 : (final_p
2238 ? "`%s' in final absence set is not unit"
2239 : "`%s' in absence set is not unit")),
2240 patterns [i] [j]);
2241 else
2243 new_el->unit_decls [new_el->units_num]
2244 = DECL_UNIT (decl_in_table);
2245 new_el->units_num++;
2249 return el_list;
2252 /* The function adds each element from PATTERN_LIST to presence (if
2253 PRESENCE_P) or absence list of the each element from DEST_LIST.
2254 Checking situations "unit requires own absence", and "unit excludes
2255 and requires presence of ...", "unit requires absence and presence
2256 of ...", "units in (final) presence set belong to different
2257 automata", and "units in (final) absence set belong to different
2258 automata". Remember that we process absence sets only after all
2259 presence sets. */
2260 static void
2261 add_presence_absence (unit_set_el_t dest_list,
2262 pattern_set_el_t pattern_list,
2263 pos_t req_pos ATTRIBUTE_UNUSED,
2264 int presence_p, int final_p)
2266 unit_set_el_t dst;
2267 pattern_set_el_t pat;
2268 struct unit_decl *unit;
2269 unit_set_el_t curr_excl_el;
2270 pattern_set_el_t curr_pat_el;
2271 pattern_set_el_t prev_el;
2272 pattern_set_el_t copy;
2273 int i;
2274 int no_error_flag;
2276 for (dst = dest_list; dst != NULL; dst = dst->next_unit_set_el)
2277 for (pat = pattern_list; pat != NULL; pat = pat->next_pattern_set_el)
2279 for (i = 0; i < pat->units_num; i++)
2281 unit = pat->unit_decls [i];
2282 if (dst->unit_decl == unit && pat->units_num == 1 && !presence_p)
2284 error ("unit `%s' requires own absence", unit->name);
2285 continue;
2287 if (dst->unit_decl->automaton_name != NULL
2288 && unit->automaton_name != NULL
2289 && strcmp (dst->unit_decl->automaton_name,
2290 unit->automaton_name) != 0)
2292 error ((presence_p
2293 ? (final_p
2294 ? "units `%s' and `%s' in final presence set belong to different automata"
2295 : "units `%s' and `%s' in presence set belong to different automata")
2296 : (final_p
2297 ? "units `%s' and `%s' in final absence set belong to different automata"
2298 : "units `%s' and `%s' in absence set belong to different automata")),
2299 unit->name, dst->unit_decl->name);
2300 continue;
2302 no_error_flag = 1;
2303 if (presence_p)
2304 for (curr_excl_el = dst->unit_decl->excl_list;
2305 curr_excl_el != NULL;
2306 curr_excl_el = curr_excl_el->next_unit_set_el)
2308 if (unit == curr_excl_el->unit_decl && pat->units_num == 1)
2310 if (!w_flag)
2312 error ("unit `%s' excludes and requires presence of `%s'",
2313 dst->unit_decl->name, unit->name);
2314 no_error_flag = 0;
2316 else
2317 warning ("unit `%s' excludes and requires presence of `%s'",
2318 dst->unit_decl->name, unit->name);
2321 else if (pat->units_num == 1)
2322 for (curr_pat_el = dst->unit_decl->presence_list;
2323 curr_pat_el != NULL;
2324 curr_pat_el = curr_pat_el->next_pattern_set_el)
2325 if (curr_pat_el->units_num == 1
2326 && unit == curr_pat_el->unit_decls [0])
2328 if (!w_flag)
2330 error ("unit `%s' requires absence and presence of `%s'",
2331 dst->unit_decl->name, unit->name);
2332 no_error_flag = 0;
2334 else
2335 warning ("unit `%s' requires absence and presence of `%s'",
2336 dst->unit_decl->name, unit->name);
2338 if (no_error_flag)
2340 for (prev_el = (presence_p
2341 ? (final_p
2342 ? dst->unit_decl->final_presence_list
2343 : dst->unit_decl->final_presence_list)
2344 : (final_p
2345 ? dst->unit_decl->final_absence_list
2346 : dst->unit_decl->absence_list));
2347 prev_el != NULL && prev_el->next_pattern_set_el != NULL;
2348 prev_el = prev_el->next_pattern_set_el)
2350 copy = XCOPYNODE (struct pattern_set_el, pat);
2351 copy->next_pattern_set_el = NULL;
2352 if (prev_el == NULL)
2354 if (presence_p)
2356 if (final_p)
2357 dst->unit_decl->final_presence_list = copy;
2358 else
2359 dst->unit_decl->presence_list = copy;
2361 else if (final_p)
2362 dst->unit_decl->final_absence_list = copy;
2363 else
2364 dst->unit_decl->absence_list = copy;
2366 else
2367 prev_el->next_pattern_set_el = copy;
2374 /* The function inserts BYPASS in the list of bypasses of the
2375 corresponding output insn. The order of bypasses in the list is
2376 decribed in a comment for member `bypass_list' (see above). If
2377 there is already the same bypass in the list the function reports
2378 this and does nothing. */
2379 static void
2380 insert_bypass (struct bypass_decl *bypass)
2382 struct bypass_decl *curr, *last;
2383 struct insn_reserv_decl *out_insn_reserv = bypass->out_insn_reserv;
2384 struct insn_reserv_decl *in_insn_reserv = bypass->in_insn_reserv;
2386 for (curr = out_insn_reserv->bypass_list, last = NULL;
2387 curr != NULL;
2388 last = curr, curr = curr->next)
2389 if (curr->in_insn_reserv == in_insn_reserv)
2391 if ((bypass->bypass_guard_name != NULL
2392 && curr->bypass_guard_name != NULL
2393 && ! strcmp (bypass->bypass_guard_name, curr->bypass_guard_name))
2394 || bypass->bypass_guard_name == curr->bypass_guard_name)
2396 if (bypass->bypass_guard_name == NULL)
2398 if (!w_flag)
2399 error ("the same bypass `%s - %s' is already defined",
2400 bypass->out_insn_name, bypass->in_insn_name);
2401 else
2402 warning ("the same bypass `%s - %s' is already defined",
2403 bypass->out_insn_name, bypass->in_insn_name);
2405 else if (!w_flag)
2406 error ("the same bypass `%s - %s' (guard %s) is already defined",
2407 bypass->out_insn_name, bypass->in_insn_name,
2408 bypass->bypass_guard_name);
2409 else
2410 warning
2411 ("the same bypass `%s - %s' (guard %s) is already defined",
2412 bypass->out_insn_name, bypass->in_insn_name,
2413 bypass->bypass_guard_name);
2414 return;
2416 if (curr->bypass_guard_name == NULL)
2417 break;
2418 if (curr->next == NULL || curr->next->in_insn_reserv != in_insn_reserv)
2420 last = curr;
2421 break;
2425 if (last == NULL)
2427 bypass->next = out_insn_reserv->bypass_list;
2428 out_insn_reserv->bypass_list = bypass;
2430 else
2432 bypass->next = last->next;
2433 last->next = bypass;
2437 /* The function processes pipeline description declarations, checks
2438 their correctness, and forms exclusion/presence/absence sets. */
2439 static void
2440 process_decls (void)
2442 decl_t decl;
2443 decl_t automaton_decl;
2444 decl_t decl_in_table;
2445 decl_t out_insn_reserv;
2446 decl_t in_insn_reserv;
2447 int automaton_presence;
2448 int i;
2450 /* Checking repeated automata declarations. */
2451 automaton_presence = 0;
2452 for (i = 0; i < description->decls_num; i++)
2454 decl = description->decls [i];
2455 if (decl->mode == dm_automaton)
2457 automaton_presence = 1;
2458 decl_in_table = insert_automaton_decl (decl);
2459 if (decl_in_table != decl)
2461 if (!w_flag)
2462 error ("repeated declaration of automaton `%s'",
2463 DECL_AUTOMATON (decl)->name);
2464 else
2465 warning ("repeated declaration of automaton `%s'",
2466 DECL_AUTOMATON (decl)->name);
2470 /* Checking undeclared automata, repeated declarations (except for
2471 automata) and correctness of their attributes (insn latency times
2472 etc.). */
2473 for (i = 0; i < description->decls_num; i++)
2475 decl = description->decls [i];
2476 if (decl->mode == dm_insn_reserv)
2478 if (DECL_INSN_RESERV (decl)->default_latency < 0)
2479 error ("define_insn_reservation `%s' has negative latency time",
2480 DECL_INSN_RESERV (decl)->name);
2481 DECL_INSN_RESERV (decl)->insn_num = description->insns_num;
2482 description->insns_num++;
2483 decl_in_table = insert_insn_decl (decl);
2484 if (decl_in_table != decl)
2485 error ("`%s' is already used as insn reservation name",
2486 DECL_INSN_RESERV (decl)->name);
2488 else if (decl->mode == dm_bypass)
2490 if (DECL_BYPASS (decl)->latency < 0)
2491 error ("define_bypass `%s - %s' has negative latency time",
2492 DECL_BYPASS (decl)->out_insn_name,
2493 DECL_BYPASS (decl)->in_insn_name);
2495 else if (decl->mode == dm_unit || decl->mode == dm_reserv)
2497 if (decl->mode == dm_unit)
2499 DECL_UNIT (decl)->automaton_decl = NULL;
2500 if (DECL_UNIT (decl)->automaton_name != NULL)
2502 automaton_decl
2503 = find_automaton_decl (DECL_UNIT (decl)->automaton_name);
2504 if (automaton_decl == NULL)
2505 error ("automaton `%s' is not declared",
2506 DECL_UNIT (decl)->automaton_name);
2507 else
2509 DECL_AUTOMATON (automaton_decl)->automaton_is_used = 1;
2510 DECL_UNIT (decl)->automaton_decl
2511 = DECL_AUTOMATON (automaton_decl);
2514 else if (automaton_presence)
2515 error ("define_unit `%s' without automaton when one defined",
2516 DECL_UNIT (decl)->name);
2517 DECL_UNIT (decl)->unit_num = description->units_num;
2518 description->units_num++;
2519 if (strcmp (DECL_UNIT (decl)->name, NOTHING_NAME) == 0)
2521 error ("`%s' is declared as cpu unit", NOTHING_NAME);
2522 continue;
2524 decl_in_table = find_decl (DECL_UNIT (decl)->name);
2526 else
2528 if (strcmp (DECL_RESERV (decl)->name, NOTHING_NAME) == 0)
2530 error ("`%s' is declared as cpu reservation", NOTHING_NAME);
2531 continue;
2533 decl_in_table = find_decl (DECL_RESERV (decl)->name);
2535 if (decl_in_table == NULL)
2536 decl_in_table = insert_decl (decl);
2537 else
2539 if (decl->mode == dm_unit)
2540 error ("repeated declaration of unit `%s'",
2541 DECL_UNIT (decl)->name);
2542 else
2543 error ("repeated declaration of reservation `%s'",
2544 DECL_RESERV (decl)->name);
2548 /* Check bypasses and form list of bypasses for each (output)
2549 insn. */
2550 for (i = 0; i < description->decls_num; i++)
2552 decl = description->decls [i];
2553 if (decl->mode == dm_bypass)
2555 out_insn_reserv = find_insn_decl (DECL_BYPASS (decl)->out_insn_name);
2556 in_insn_reserv = find_insn_decl (DECL_BYPASS (decl)->in_insn_name);
2557 if (out_insn_reserv == NULL)
2558 error ("there is no insn reservation `%s'",
2559 DECL_BYPASS (decl)->out_insn_name);
2560 else if (in_insn_reserv == NULL)
2561 error ("there is no insn reservation `%s'",
2562 DECL_BYPASS (decl)->in_insn_name);
2563 else
2565 DECL_BYPASS (decl)->out_insn_reserv
2566 = DECL_INSN_RESERV (out_insn_reserv);
2567 DECL_BYPASS (decl)->in_insn_reserv
2568 = DECL_INSN_RESERV (in_insn_reserv);
2569 insert_bypass (DECL_BYPASS (decl));
2574 /* Check exclusion set declarations and form exclusion sets. */
2575 for (i = 0; i < description->decls_num; i++)
2577 decl = description->decls [i];
2578 if (decl->mode == dm_excl)
2580 unit_set_el_t unit_set_el_list;
2581 unit_set_el_t unit_set_el_list_2;
2583 unit_set_el_list
2584 = process_excls (DECL_EXCL (decl)->names,
2585 DECL_EXCL (decl)->first_list_length, decl->pos);
2586 unit_set_el_list_2
2587 = process_excls (&DECL_EXCL (decl)->names
2588 [DECL_EXCL (decl)->first_list_length],
2589 DECL_EXCL (decl)->all_names_num
2590 - DECL_EXCL (decl)->first_list_length,
2591 decl->pos);
2592 add_excls (unit_set_el_list, unit_set_el_list_2, decl->pos);
2593 add_excls (unit_set_el_list_2, unit_set_el_list, decl->pos);
2597 /* Check presence set declarations and form presence sets. */
2598 for (i = 0; i < description->decls_num; i++)
2600 decl = description->decls [i];
2601 if (decl->mode == dm_presence)
2603 unit_set_el_t unit_set_el_list;
2604 pattern_set_el_t pattern_set_el_list;
2606 unit_set_el_list
2607 = process_presence_absence_names
2608 (DECL_PRESENCE (decl)->names, DECL_PRESENCE (decl)->names_num,
2609 decl->pos, TRUE, DECL_PRESENCE (decl)->final_p);
2610 pattern_set_el_list
2611 = process_presence_absence_patterns
2612 (DECL_PRESENCE (decl)->patterns,
2613 DECL_PRESENCE (decl)->patterns_num,
2614 decl->pos, TRUE, DECL_PRESENCE (decl)->final_p);
2615 add_presence_absence (unit_set_el_list, pattern_set_el_list,
2616 decl->pos, TRUE,
2617 DECL_PRESENCE (decl)->final_p);
2621 /* Check absence set declarations and form absence sets. */
2622 for (i = 0; i < description->decls_num; i++)
2624 decl = description->decls [i];
2625 if (decl->mode == dm_absence)
2627 unit_set_el_t unit_set_el_list;
2628 pattern_set_el_t pattern_set_el_list;
2630 unit_set_el_list
2631 = process_presence_absence_names
2632 (DECL_ABSENCE (decl)->names, DECL_ABSENCE (decl)->names_num,
2633 decl->pos, FALSE, DECL_ABSENCE (decl)->final_p);
2634 pattern_set_el_list
2635 = process_presence_absence_patterns
2636 (DECL_ABSENCE (decl)->patterns,
2637 DECL_ABSENCE (decl)->patterns_num,
2638 decl->pos, FALSE, DECL_ABSENCE (decl)->final_p);
2639 add_presence_absence (unit_set_el_list, pattern_set_el_list,
2640 decl->pos, FALSE,
2641 DECL_ABSENCE (decl)->final_p);
2646 /* The following function checks that declared automaton is used. If
2647 the automaton is not used, the function fixes error/warning. The
2648 following function must be called only after `process_decls'. */
2649 static void
2650 check_automaton_usage (void)
2652 decl_t decl;
2653 int i;
2655 for (i = 0; i < description->decls_num; i++)
2657 decl = description->decls [i];
2658 if (decl->mode == dm_automaton
2659 && !DECL_AUTOMATON (decl)->automaton_is_used)
2661 if (!w_flag)
2662 error ("automaton `%s' is not used", DECL_AUTOMATON (decl)->name);
2663 else
2664 warning ("automaton `%s' is not used",
2665 DECL_AUTOMATON (decl)->name);
2670 /* The following recursive function processes all regexp in order to
2671 fix usage of units or reservations and to fix errors of undeclared
2672 name. The function may change unit_regexp onto reserv_regexp.
2673 Remember that reserv_regexp does not exist before the function
2674 call. */
2675 static regexp_t
2676 process_regexp (regexp_t regexp)
2678 decl_t decl_in_table;
2679 regexp_t new_regexp;
2680 int i;
2682 switch (regexp->mode)
2684 case rm_unit:
2685 decl_in_table = find_decl (REGEXP_UNIT (regexp)->name);
2686 if (decl_in_table == NULL)
2687 error ("undeclared unit or reservation `%s'",
2688 REGEXP_UNIT (regexp)->name);
2689 else
2690 switch (decl_in_table->mode)
2692 case dm_unit:
2693 DECL_UNIT (decl_in_table)->unit_is_used = 1;
2694 REGEXP_UNIT (regexp)->unit_decl = DECL_UNIT (decl_in_table);
2695 break;
2697 case dm_reserv:
2698 DECL_RESERV (decl_in_table)->reserv_is_used = 1;
2699 new_regexp = XCREATENODE (struct regexp);
2700 new_regexp->mode = rm_reserv;
2701 new_regexp->pos = regexp->pos;
2702 REGEXP_RESERV (new_regexp)->name = REGEXP_UNIT (regexp)->name;
2703 REGEXP_RESERV (new_regexp)->reserv_decl
2704 = DECL_RESERV (decl_in_table);
2705 regexp = new_regexp;
2706 break;
2708 default:
2709 gcc_unreachable ();
2711 break;
2712 case rm_sequence:
2713 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
2714 REGEXP_SEQUENCE (regexp)->regexps [i]
2715 = process_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
2716 break;
2717 case rm_allof:
2718 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
2719 REGEXP_ALLOF (regexp)->regexps [i]
2720 = process_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
2721 break;
2722 case rm_oneof:
2723 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
2724 REGEXP_ONEOF (regexp)->regexps [i]
2725 = process_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
2726 break;
2727 case rm_repeat:
2728 REGEXP_REPEAT (regexp)->regexp
2729 = process_regexp (REGEXP_REPEAT (regexp)->regexp);
2730 break;
2731 case rm_nothing:
2732 break;
2733 default:
2734 gcc_unreachable ();
2736 return regexp;
2739 /* The following function processes regexp of define_reservation and
2740 define_insn_reservation with the aid of function
2741 `process_regexp'. */
2742 static void
2743 process_regexp_decls (void)
2745 decl_t decl;
2746 int i;
2748 for (i = 0; i < description->decls_num; i++)
2750 decl = description->decls [i];
2751 if (decl->mode == dm_reserv)
2752 DECL_RESERV (decl)->regexp
2753 = process_regexp (DECL_RESERV (decl)->regexp);
2754 else if (decl->mode == dm_insn_reserv)
2755 DECL_INSN_RESERV (decl)->regexp
2756 = process_regexp (DECL_INSN_RESERV (decl)->regexp);
2760 /* The following function checks that declared unit is used. If the
2761 unit is not used, the function fixes errors/warnings. The
2762 following function must be called only after `process_decls',
2763 `process_regexp_decls'. */
2764 static void
2765 check_usage (void)
2767 decl_t decl;
2768 int i;
2770 for (i = 0; i < description->decls_num; i++)
2772 decl = description->decls [i];
2773 if (decl->mode == dm_unit && !DECL_UNIT (decl)->unit_is_used)
2775 if (!w_flag)
2776 error ("unit `%s' is not used", DECL_UNIT (decl)->name);
2777 else
2778 warning ("unit `%s' is not used", DECL_UNIT (decl)->name);
2780 else if (decl->mode == dm_reserv && !DECL_RESERV (decl)->reserv_is_used)
2782 if (!w_flag)
2783 error ("reservation `%s' is not used", DECL_RESERV (decl)->name);
2784 else
2785 warning ("reservation `%s' is not used", DECL_RESERV (decl)->name);
2790 /* The following variable value is number of reservation being
2791 processed on loop recognition. */
2792 static int curr_loop_pass_num;
2794 /* The following recursive function returns nonzero value if REGEXP
2795 contains given decl or reservations in given regexp refers for
2796 given decl. */
2797 static int
2798 loop_in_regexp (regexp_t regexp, decl_t start_decl)
2800 int i;
2802 if (regexp == NULL)
2803 return 0;
2804 switch (regexp->mode)
2806 case rm_unit:
2807 return 0;
2809 case rm_reserv:
2810 if (start_decl->mode == dm_reserv
2811 && REGEXP_RESERV (regexp)->reserv_decl == DECL_RESERV (start_decl))
2812 return 1;
2813 else if (REGEXP_RESERV (regexp)->reserv_decl->loop_pass_num
2814 == curr_loop_pass_num)
2815 /* declaration has been processed. */
2816 return 0;
2817 else
2819 REGEXP_RESERV (regexp)->reserv_decl->loop_pass_num
2820 = curr_loop_pass_num;
2821 return loop_in_regexp (REGEXP_RESERV (regexp)->reserv_decl->regexp,
2822 start_decl);
2825 case rm_sequence:
2826 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
2827 if (loop_in_regexp (REGEXP_SEQUENCE (regexp)->regexps [i], start_decl))
2828 return 1;
2829 return 0;
2831 case rm_allof:
2832 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
2833 if (loop_in_regexp (REGEXP_ALLOF (regexp)->regexps [i], start_decl))
2834 return 1;
2835 return 0;
2837 case rm_oneof:
2838 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
2839 if (loop_in_regexp (REGEXP_ONEOF (regexp)->regexps [i], start_decl))
2840 return 1;
2841 return 0;
2843 case rm_repeat:
2844 return loop_in_regexp (REGEXP_REPEAT (regexp)->regexp, start_decl);
2846 case rm_nothing:
2847 return 0;
2849 default:
2850 gcc_unreachable ();
2854 /* The following function fixes errors "cycle in definition ...". The
2855 function uses function `loop_in_regexp' for that. */
2856 static void
2857 check_loops_in_regexps (void)
2859 decl_t decl;
2860 int i;
2862 for (i = 0; i < description->decls_num; i++)
2864 decl = description->decls [i];
2865 if (decl->mode == dm_reserv)
2866 DECL_RESERV (decl)->loop_pass_num = 0;
2868 for (i = 0; i < description->decls_num; i++)
2870 decl = description->decls [i];
2871 curr_loop_pass_num = i;
2873 if (decl->mode == dm_reserv)
2875 DECL_RESERV (decl)->loop_pass_num = curr_loop_pass_num;
2876 if (loop_in_regexp (DECL_RESERV (decl)->regexp, decl))
2878 gcc_assert (DECL_RESERV (decl)->regexp);
2879 error ("cycle in definition of reservation `%s'",
2880 DECL_RESERV (decl)->name);
2886 /* The function recursively processes IR of reservation and defines
2887 max and min cycle for reservation of unit. */
2888 static void
2889 process_regexp_cycles (regexp_t regexp, int max_start_cycle,
2890 int min_start_cycle, int *max_finish_cycle,
2891 int *min_finish_cycle)
2893 int i;
2895 switch (regexp->mode)
2897 case rm_unit:
2898 if (REGEXP_UNIT (regexp)->unit_decl->max_occ_cycle_num < max_start_cycle)
2899 REGEXP_UNIT (regexp)->unit_decl->max_occ_cycle_num = max_start_cycle;
2900 if (REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num > min_start_cycle
2901 || REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num == -1)
2902 REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num = min_start_cycle;
2903 *max_finish_cycle = max_start_cycle;
2904 *min_finish_cycle = min_start_cycle;
2905 break;
2907 case rm_reserv:
2908 process_regexp_cycles (REGEXP_RESERV (regexp)->reserv_decl->regexp,
2909 max_start_cycle, min_start_cycle,
2910 max_finish_cycle, min_finish_cycle);
2911 break;
2913 case rm_repeat:
2914 for (i = 0; i < REGEXP_REPEAT (regexp)->repeat_num; i++)
2916 process_regexp_cycles (REGEXP_REPEAT (regexp)->regexp,
2917 max_start_cycle, min_start_cycle,
2918 max_finish_cycle, min_finish_cycle);
2919 max_start_cycle = *max_finish_cycle + 1;
2920 min_start_cycle = *min_finish_cycle + 1;
2922 break;
2924 case rm_sequence:
2925 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
2927 process_regexp_cycles (REGEXP_SEQUENCE (regexp)->regexps [i],
2928 max_start_cycle, min_start_cycle,
2929 max_finish_cycle, min_finish_cycle);
2930 max_start_cycle = *max_finish_cycle + 1;
2931 min_start_cycle = *min_finish_cycle + 1;
2933 break;
2935 case rm_allof:
2937 int max_cycle = 0;
2938 int min_cycle = 0;
2940 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
2942 process_regexp_cycles (REGEXP_ALLOF (regexp)->regexps [i],
2943 max_start_cycle, min_start_cycle,
2944 max_finish_cycle, min_finish_cycle);
2945 if (max_cycle < *max_finish_cycle)
2946 max_cycle = *max_finish_cycle;
2947 if (i == 0 || min_cycle > *min_finish_cycle)
2948 min_cycle = *min_finish_cycle;
2950 *max_finish_cycle = max_cycle;
2951 *min_finish_cycle = min_cycle;
2953 break;
2955 case rm_oneof:
2957 int max_cycle = 0;
2958 int min_cycle = 0;
2960 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
2962 process_regexp_cycles (REGEXP_ONEOF (regexp)->regexps [i],
2963 max_start_cycle, min_start_cycle,
2964 max_finish_cycle, min_finish_cycle);
2965 if (max_cycle < *max_finish_cycle)
2966 max_cycle = *max_finish_cycle;
2967 if (i == 0 || min_cycle > *min_finish_cycle)
2968 min_cycle = *min_finish_cycle;
2970 *max_finish_cycle = max_cycle;
2971 *min_finish_cycle = min_cycle;
2973 break;
2975 case rm_nothing:
2976 *max_finish_cycle = max_start_cycle;
2977 *min_finish_cycle = min_start_cycle;
2978 break;
2980 default:
2981 gcc_unreachable ();
2985 /* The following function is called only for correct program. The
2986 function defines max reservation of insns in cycles. */
2987 static void
2988 evaluate_max_reserv_cycles (void)
2990 int max_insn_cycles_num;
2991 int min_insn_cycles_num;
2992 decl_t decl;
2993 int i;
2995 description->max_insn_reserv_cycles = 0;
2996 for (i = 0; i < description->decls_num; i++)
2998 decl = description->decls [i];
2999 if (decl->mode == dm_insn_reserv)
3001 process_regexp_cycles (DECL_INSN_RESERV (decl)->regexp, 0, 0,
3002 &max_insn_cycles_num, &min_insn_cycles_num);
3003 if (description->max_insn_reserv_cycles < max_insn_cycles_num)
3004 description->max_insn_reserv_cycles = max_insn_cycles_num;
3007 description->max_insn_reserv_cycles++;
3010 /* The following function calls functions for checking all
3011 description. */
3012 static void
3013 check_all_description (void)
3015 process_decls ();
3016 check_automaton_usage ();
3017 process_regexp_decls ();
3018 check_usage ();
3019 check_loops_in_regexps ();
3020 if (!have_error)
3021 evaluate_max_reserv_cycles ();
3026 /* The page contains abstract data `ticker'. This data is used to
3027 report time of different phases of building automata. It is
3028 possibly to write a description for which automata will be built
3029 during several minutes even on fast machine. */
3031 /* The following function creates ticker and makes it active. */
3032 static ticker_t
3033 create_ticker (void)
3035 ticker_t ticker;
3037 ticker.modified_creation_time = get_run_time ();
3038 ticker.incremented_off_time = 0;
3039 return ticker;
3042 /* The following function switches off given ticker. */
3043 static void
3044 ticker_off (ticker_t *ticker)
3046 if (ticker->incremented_off_time == 0)
3047 ticker->incremented_off_time = get_run_time () + 1;
3050 /* The following function switches on given ticker. */
3051 static void
3052 ticker_on (ticker_t *ticker)
3054 if (ticker->incremented_off_time != 0)
3056 ticker->modified_creation_time
3057 += get_run_time () - ticker->incremented_off_time + 1;
3058 ticker->incremented_off_time = 0;
3062 /* The following function returns current time in milliseconds since
3063 the moment when given ticker was created. */
3064 static int
3065 active_time (ticker_t ticker)
3067 if (ticker.incremented_off_time != 0)
3068 return ticker.incremented_off_time - 1 - ticker.modified_creation_time;
3069 else
3070 return get_run_time () - ticker.modified_creation_time;
3073 /* The following function returns string representation of active time
3074 of given ticker. The result is string representation of seconds
3075 with accuracy of 1/100 second. Only result of the last call of the
3076 function exists. Therefore the following code is not correct
3078 printf ("parser time: %s\ngeneration time: %s\n",
3079 active_time_string (parser_ticker),
3080 active_time_string (generation_ticker));
3082 Correct code has to be the following
3084 printf ("parser time: %s\n", active_time_string (parser_ticker));
3085 printf ("generation time: %s\n",
3086 active_time_string (generation_ticker));
3089 static void
3090 print_active_time (FILE *f, ticker_t ticker)
3092 int msecs;
3094 msecs = active_time (ticker);
3095 fprintf (f, "%d.%06d", msecs / 1000000, msecs % 1000000);
3100 /* The following variable value is number of automaton which are
3101 really being created. This value is defined on the base of
3102 argument of option `-split'. If the variable has zero value the
3103 number of automata is defined by the constructions `%automaton'.
3104 This case occurs when option `-split' is absent or has zero
3105 argument. If constructions `define_automaton' is absent only one
3106 automaton is created. */
3107 static int automata_num;
3109 /* The following variable values are times of
3110 o transformation of regular expressions
3111 o building NDFA (DFA if !ndfa_flag)
3112 o NDFA -> DFA (simply the same automaton if !ndfa_flag)
3113 o DFA minimization
3114 o building insn equivalence classes
3115 o all previous ones
3116 o code output */
3117 static ticker_t transform_time;
3118 static ticker_t NDFA_time;
3119 static ticker_t NDFA_to_DFA_time;
3120 static ticker_t minimize_time;
3121 static ticker_t equiv_time;
3122 static ticker_t automaton_generation_time;
3123 static ticker_t output_time;
3125 /* The following variable values are times of
3126 all checking
3127 all generation
3128 all pipeline hazard translator work */
3129 static ticker_t check_time;
3130 static ticker_t generation_time;
3131 static ticker_t all_time;
3135 /* Pseudo insn decl which denotes advancing cycle. */
3136 static decl_t advance_cycle_insn_decl;
3137 static void
3138 add_advance_cycle_insn_decl (void)
3140 advance_cycle_insn_decl = XCREATENODE (struct decl);
3141 advance_cycle_insn_decl->mode = dm_insn_reserv;
3142 advance_cycle_insn_decl->pos = no_pos;
3143 DECL_INSN_RESERV (advance_cycle_insn_decl)->regexp = NULL;
3144 DECL_INSN_RESERV (advance_cycle_insn_decl)->name = "$advance_cycle";
3145 DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num
3146 = description->insns_num;
3147 description->decls [description->decls_num] = advance_cycle_insn_decl;
3148 description->decls_num++;
3149 description->insns_num++;
3153 /* Abstract data `alternative states' which represents
3154 nondeterministic nature of the description (see comments for
3155 structures alt_state and state). */
3157 /* List of free states. */
3158 static alt_state_t first_free_alt_state;
3160 #ifndef NDEBUG
3161 /* The following variables is maximal number of allocated nodes
3162 alt_state. */
3163 static int allocated_alt_states_num = 0;
3164 #endif
3166 /* The following function returns free node alt_state. It may be new
3167 allocated node or node freed earlier. */
3168 static alt_state_t
3169 get_free_alt_state (void)
3171 alt_state_t result;
3173 if (first_free_alt_state != NULL)
3175 result = first_free_alt_state;
3176 first_free_alt_state = first_free_alt_state->next_alt_state;
3178 else
3180 #ifndef NDEBUG
3181 allocated_alt_states_num++;
3182 #endif
3183 result = XCREATENODE (struct alt_state);
3185 result->state = NULL;
3186 result->next_alt_state = NULL;
3187 result->next_sorted_alt_state = NULL;
3188 return result;
3191 /* The function frees node ALT_STATE. */
3192 static void
3193 free_alt_state (alt_state_t alt_state)
3195 if (alt_state == NULL)
3196 return;
3197 alt_state->next_alt_state = first_free_alt_state;
3198 first_free_alt_state = alt_state;
3201 /* The function frees list started with node ALT_STATE_LIST. */
3202 static void
3203 free_alt_states (alt_state_t alt_states_list)
3205 alt_state_t curr_alt_state;
3206 alt_state_t next_alt_state;
3208 for (curr_alt_state = alt_states_list;
3209 curr_alt_state != NULL;
3210 curr_alt_state = next_alt_state)
3212 next_alt_state = curr_alt_state->next_alt_state;
3213 free_alt_state (curr_alt_state);
3217 /* The function compares unique numbers of alt states. */
3218 static int
3219 alt_state_cmp (const void *alt_state_ptr_1, const void *alt_state_ptr_2)
3221 if ((*(const alt_state_t *) alt_state_ptr_1)->state->unique_num
3222 == (*(const alt_state_t *) alt_state_ptr_2)->state->unique_num)
3223 return 0;
3224 else if ((*(const alt_state_t *) alt_state_ptr_1)->state->unique_num
3225 < (*(const alt_state_t *) alt_state_ptr_2)->state->unique_num)
3226 return -1;
3227 else
3228 return 1;
3231 /* The function sorts ALT_STATES_LIST and removes duplicated alt
3232 states from the list. The comparison key is alt state unique
3233 number. */
3235 static alt_state_t
3236 uniq_sort_alt_states (alt_state_t alt_states_list)
3238 alt_state_t curr_alt_state;
3239 VEC(alt_state_t, heap) *alt_states;
3240 size_t i;
3241 size_t prev_unique_state_ind;
3242 alt_state_t result;
3244 if (alt_states_list == 0)
3245 return 0;
3246 if (alt_states_list->next_alt_state == 0)
3247 return alt_states_list;
3249 alt_states = VEC_alloc (alt_state_t, heap, 150);
3250 for (curr_alt_state = alt_states_list;
3251 curr_alt_state != NULL;
3252 curr_alt_state = curr_alt_state->next_alt_state)
3253 VEC_safe_push (alt_state_t, heap, alt_states, curr_alt_state);
3255 qsort (VEC_address (alt_state_t, alt_states),
3256 VEC_length (alt_state_t, alt_states),
3257 sizeof (alt_state_t), alt_state_cmp);
3259 prev_unique_state_ind = 0;
3260 for (i = 1; i < VEC_length (alt_state_t, alt_states); i++)
3261 if (VEC_index (alt_state_t, alt_states, prev_unique_state_ind)->state
3262 != VEC_index (alt_state_t, alt_states, i)->state)
3264 prev_unique_state_ind++;
3265 VEC_replace (alt_state_t, alt_states, prev_unique_state_ind,
3266 VEC_index (alt_state_t, alt_states, i));
3268 VEC_truncate (alt_state_t, alt_states, prev_unique_state_ind + 1);
3270 for (i = 1; i < VEC_length (alt_state_t, alt_states); i++)
3271 VEC_index (alt_state_t, alt_states, i-1)->next_sorted_alt_state
3272 = VEC_index (alt_state_t, alt_states, i);
3273 VEC_last (alt_state_t, alt_states)->next_sorted_alt_state = 0;
3275 result = VEC_index (alt_state_t, alt_states, 0);
3277 VEC_free (alt_state_t, heap, alt_states);
3278 return result;
3281 /* The function checks equality of alt state lists. Remember that the
3282 lists must be already sorted by the previous function. */
3283 static int
3284 alt_states_eq (alt_state_t alt_states_1, alt_state_t alt_states_2)
3286 while (alt_states_1 != NULL && alt_states_2 != NULL
3287 && alt_state_cmp (&alt_states_1, &alt_states_2) == 0)
3289 alt_states_1 = alt_states_1->next_sorted_alt_state;
3290 alt_states_2 = alt_states_2->next_sorted_alt_state;
3292 return alt_states_1 == alt_states_2;
3295 /* Initialization of the abstract data. */
3296 static void
3297 initiate_alt_states (void)
3299 first_free_alt_state = NULL;
3302 /* Finishing work with the abstract data. */
3303 static void
3304 finish_alt_states (void)
3310 /* The page contains macros for work with bits strings. We could use
3311 standard gcc bitmap or sbitmap but it would result in difficulties
3312 of building canadian cross. */
3314 /* Set bit number bitno in the bit string. The macro is not side
3315 effect proof. */
3316 #define SET_BIT(bitstring, bitno) \
3317 (((char *) (bitstring)) [(bitno) / CHAR_BIT] |= 1 << (bitno) % CHAR_BIT)
3319 #define CLEAR_BIT(bitstring, bitno) \
3320 (((char *) (bitstring)) [(bitno) / CHAR_BIT] &= ~(1 << (bitno) % CHAR_BIT))
3322 /* Test if bit number bitno in the bitstring is set. The macro is not
3323 side effect proof. */
3324 #define TEST_BIT(bitstring, bitno) \
3325 (((char *) (bitstring)) [(bitno) / CHAR_BIT] >> (bitno) % CHAR_BIT & 1)
3329 /* This page contains abstract data `state'. */
3331 /* Maximal length of reservations in cycles (>= 1). */
3332 static int max_cycles_num;
3334 /* Number of set elements (see type set_el_t) needed for
3335 representation of one cycle reservation. It is depended on units
3336 number. */
3337 static int els_in_cycle_reserv;
3339 /* Number of set elements (see type set_el_t) needed for
3340 representation of maximal length reservation. Deterministic
3341 reservation is stored as set (bit string) of length equal to the
3342 variable value * number of bits in set_el_t. */
3343 static int els_in_reservs;
3345 /* Array of pointers to unit declarations. */
3346 static unit_decl_t *units_array;
3348 /* Temporary reservation of maximal length. */
3349 static reserv_sets_t temp_reserv;
3351 /* The state table itself is represented by the following variable. */
3352 static htab_t state_table;
3354 /* Linked list of free 'state' structures to be recycled. The
3355 next_equiv_class_state pointer is borrowed for a free list. */
3356 static state_t first_free_state;
3358 static int curr_unique_state_num;
3360 #ifndef NDEBUG
3361 /* The following variables is maximal number of allocated nodes
3362 `state'. */
3363 static int allocated_states_num = 0;
3364 #endif
3366 /* Allocate new reservation set. */
3367 static reserv_sets_t
3368 alloc_empty_reserv_sets (void)
3370 reserv_sets_t result;
3372 obstack_blank (&irp, els_in_reservs * sizeof (set_el_t));
3373 result = (reserv_sets_t) obstack_base (&irp);
3374 obstack_finish (&irp);
3375 memset (result, 0, els_in_reservs * sizeof (set_el_t));
3376 return result;
3379 /* Hash value of reservation set. */
3380 static unsigned
3381 reserv_sets_hash_value (reserv_sets_t reservs)
3383 set_el_t hash_value;
3384 unsigned result;
3385 int reservs_num, i;
3386 set_el_t *reserv_ptr;
3388 hash_value = 0;
3389 reservs_num = els_in_reservs;
3390 reserv_ptr = reservs;
3391 i = 0;
3392 while (reservs_num != 0)
3394 reservs_num--;
3395 hash_value += ((*reserv_ptr >> i)
3396 | (*reserv_ptr << (sizeof (set_el_t) * CHAR_BIT - i)));
3397 i++;
3398 if (i == sizeof (set_el_t) * CHAR_BIT)
3399 i = 0;
3400 reserv_ptr++;
3402 if (sizeof (set_el_t) <= sizeof (unsigned))
3403 return hash_value;
3404 result = 0;
3405 for (i = sizeof (set_el_t); i > 0; i -= sizeof (unsigned) - 1)
3407 result += (unsigned) hash_value;
3408 hash_value >>= (sizeof (unsigned) - 1) * CHAR_BIT;
3410 return result;
3413 /* Comparison of given reservation sets. */
3414 static int
3415 reserv_sets_cmp (const_reserv_sets_t reservs_1, const_reserv_sets_t reservs_2)
3417 int reservs_num;
3418 const set_el_t *reserv_ptr_1;
3419 const set_el_t *reserv_ptr_2;
3421 gcc_assert (reservs_1 && reservs_2);
3422 reservs_num = els_in_reservs;
3423 reserv_ptr_1 = reservs_1;
3424 reserv_ptr_2 = reservs_2;
3425 while (reservs_num != 0 && *reserv_ptr_1 == *reserv_ptr_2)
3427 reservs_num--;
3428 reserv_ptr_1++;
3429 reserv_ptr_2++;
3431 if (reservs_num == 0)
3432 return 0;
3433 else if (*reserv_ptr_1 < *reserv_ptr_2)
3434 return -1;
3435 else
3436 return 1;
3439 /* The function checks equality of the reservation sets. */
3440 static int
3441 reserv_sets_eq (const_reserv_sets_t reservs_1, const_reserv_sets_t reservs_2)
3443 return reserv_sets_cmp (reservs_1, reservs_2) == 0;
3446 /* Set up in the reservation set that unit with UNIT_NUM is used on
3447 CYCLE_NUM. */
3448 static void
3449 set_unit_reserv (reserv_sets_t reservs, int cycle_num, int unit_num)
3451 gcc_assert (cycle_num < max_cycles_num);
3452 SET_BIT (reservs, cycle_num * els_in_cycle_reserv
3453 * sizeof (set_el_t) * CHAR_BIT + unit_num);
3456 /* Set up in the reservation set RESERVS that unit with UNIT_NUM is
3457 used on CYCLE_NUM. */
3458 static int
3459 test_unit_reserv (reserv_sets_t reservs, int cycle_num, int unit_num)
3461 gcc_assert (cycle_num < max_cycles_num);
3462 return TEST_BIT (reservs, cycle_num * els_in_cycle_reserv
3463 * sizeof (set_el_t) * CHAR_BIT + unit_num);
3466 /* The function checks that the reservation sets are intersected,
3467 i.e. there is a unit reservation on a cycle in both reservation
3468 sets. */
3469 static int
3470 reserv_sets_are_intersected (reserv_sets_t operand_1,
3471 reserv_sets_t operand_2)
3473 set_el_t *el_ptr_1;
3474 set_el_t *el_ptr_2;
3475 set_el_t *cycle_ptr_1;
3476 set_el_t *cycle_ptr_2;
3478 gcc_assert (operand_1 && operand_2);
3479 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2;
3480 el_ptr_1 < operand_1 + els_in_reservs;
3481 el_ptr_1++, el_ptr_2++)
3482 if (*el_ptr_1 & *el_ptr_2)
3483 return 1;
3484 reserv_sets_or (temp_reserv, operand_1, operand_2);
3485 for (cycle_ptr_1 = operand_1, cycle_ptr_2 = operand_2;
3486 cycle_ptr_1 < operand_1 + els_in_reservs;
3487 cycle_ptr_1 += els_in_cycle_reserv, cycle_ptr_2 += els_in_cycle_reserv)
3489 for (el_ptr_1 = cycle_ptr_1, el_ptr_2 = get_excl_set (cycle_ptr_2);
3490 el_ptr_1 < cycle_ptr_1 + els_in_cycle_reserv;
3491 el_ptr_1++, el_ptr_2++)
3492 if (*el_ptr_1 & *el_ptr_2)
3493 return 1;
3494 if (!check_presence_pattern_sets (cycle_ptr_1, cycle_ptr_2, FALSE))
3495 return 1;
3496 if (!check_presence_pattern_sets (temp_reserv + (cycle_ptr_2
3497 - operand_2),
3498 cycle_ptr_2, TRUE))
3499 return 1;
3500 if (!check_absence_pattern_sets (cycle_ptr_1, cycle_ptr_2, FALSE))
3501 return 1;
3502 if (!check_absence_pattern_sets (temp_reserv + (cycle_ptr_2 - operand_2),
3503 cycle_ptr_2, TRUE))
3504 return 1;
3506 return 0;
3509 /* The function sets up RESULT bits by bits of OPERAND shifted on one
3510 cpu cycle. The remaining bits of OPERAND (representing the last
3511 cycle unit reservations) are not changed. */
3512 static void
3513 reserv_sets_shift (reserv_sets_t result, reserv_sets_t operand)
3515 int i;
3517 gcc_assert (result && operand && result != operand);
3518 for (i = els_in_cycle_reserv; i < els_in_reservs; i++)
3519 result [i - els_in_cycle_reserv] = operand [i];
3522 /* OR of the reservation sets. */
3523 static void
3524 reserv_sets_or (reserv_sets_t result, reserv_sets_t operand_1,
3525 reserv_sets_t operand_2)
3527 set_el_t *el_ptr_1;
3528 set_el_t *el_ptr_2;
3529 set_el_t *result_set_el_ptr;
3531 gcc_assert (result && operand_1 && operand_2);
3532 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2, result_set_el_ptr = result;
3533 el_ptr_1 < operand_1 + els_in_reservs;
3534 el_ptr_1++, el_ptr_2++, result_set_el_ptr++)
3535 *result_set_el_ptr = *el_ptr_1 | *el_ptr_2;
3538 /* AND of the reservation sets. */
3539 static void
3540 reserv_sets_and (reserv_sets_t result, reserv_sets_t operand_1,
3541 reserv_sets_t operand_2)
3543 set_el_t *el_ptr_1;
3544 set_el_t *el_ptr_2;
3545 set_el_t *result_set_el_ptr;
3547 gcc_assert (result && operand_1 && operand_2);
3548 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2, result_set_el_ptr = result;
3549 el_ptr_1 < operand_1 + els_in_reservs;
3550 el_ptr_1++, el_ptr_2++, result_set_el_ptr++)
3551 *result_set_el_ptr = *el_ptr_1 & *el_ptr_2;
3554 /* The function outputs string representation of units reservation on
3555 cycle START_CYCLE in the reservation set. The function uses repeat
3556 construction if REPETITION_NUM > 1. */
3557 static void
3558 output_cycle_reservs (FILE *f, reserv_sets_t reservs, int start_cycle,
3559 int repetition_num)
3561 int unit_num;
3562 int reserved_units_num;
3564 reserved_units_num = 0;
3565 for (unit_num = 0; unit_num < description->units_num; unit_num++)
3566 if (TEST_BIT (reservs, start_cycle * els_in_cycle_reserv
3567 * sizeof (set_el_t) * CHAR_BIT + unit_num))
3568 reserved_units_num++;
3569 gcc_assert (repetition_num > 0);
3570 if (repetition_num != 1 && reserved_units_num > 1)
3571 fprintf (f, "(");
3572 reserved_units_num = 0;
3573 for (unit_num = 0;
3574 unit_num < description->units_num;
3575 unit_num++)
3576 if (TEST_BIT (reservs, start_cycle * els_in_cycle_reserv
3577 * sizeof (set_el_t) * CHAR_BIT + unit_num))
3579 if (reserved_units_num != 0)
3580 fprintf (f, "+");
3581 reserved_units_num++;
3582 fprintf (f, "%s", units_array [unit_num]->name);
3584 if (reserved_units_num == 0)
3585 fprintf (f, NOTHING_NAME);
3586 gcc_assert (repetition_num > 0);
3587 if (repetition_num != 1 && reserved_units_num > 1)
3588 fprintf (f, ")");
3589 if (repetition_num != 1)
3590 fprintf (f, "*%d", repetition_num);
3593 /* The function outputs string representation of units reservation in
3594 the reservation set. */
3595 static void
3596 output_reserv_sets (FILE *f, reserv_sets_t reservs)
3598 int start_cycle = 0;
3599 int cycle;
3600 int repetition_num;
3602 repetition_num = 0;
3603 for (cycle = 0; cycle < max_cycles_num; cycle++)
3604 if (repetition_num == 0)
3606 repetition_num++;
3607 start_cycle = cycle;
3609 else if (memcmp
3610 ((char *) reservs + start_cycle * els_in_cycle_reserv
3611 * sizeof (set_el_t),
3612 (char *) reservs + cycle * els_in_cycle_reserv
3613 * sizeof (set_el_t),
3614 els_in_cycle_reserv * sizeof (set_el_t)) == 0)
3615 repetition_num++;
3616 else
3618 if (start_cycle != 0)
3619 fprintf (f, ", ");
3620 output_cycle_reservs (f, reservs, start_cycle, repetition_num);
3621 repetition_num = 1;
3622 start_cycle = cycle;
3624 if (start_cycle < max_cycles_num)
3626 if (start_cycle != 0)
3627 fprintf (f, ", ");
3628 output_cycle_reservs (f, reservs, start_cycle, repetition_num);
3632 /* The following function returns free node state for AUTOMATON. It
3633 may be new allocated node or node freed earlier. The function also
3634 allocates reservation set if WITH_RESERVS has nonzero value. */
3635 static state_t
3636 get_free_state (int with_reservs, automaton_t automaton)
3638 state_t result;
3640 gcc_assert (max_cycles_num > 0 && automaton);
3641 if (first_free_state)
3643 result = first_free_state;
3644 first_free_state = result->next_equiv_class_state;
3646 result->next_equiv_class_state = NULL;
3647 result->automaton = automaton;
3648 result->first_out_arc = NULL;
3649 result->it_was_placed_in_stack_for_NDFA_forming = 0;
3650 result->it_was_placed_in_stack_for_DFA_forming = 0;
3651 result->component_states = NULL;
3653 else
3655 #ifndef NDEBUG
3656 allocated_states_num++;
3657 #endif
3658 result = XCREATENODE (struct state);
3659 result->automaton = automaton;
3660 result->first_out_arc = NULL;
3661 result->unique_num = curr_unique_state_num;
3662 curr_unique_state_num++;
3664 if (with_reservs)
3666 if (result->reservs == NULL)
3667 result->reservs = alloc_empty_reserv_sets ();
3668 else
3669 memset (result->reservs, 0, els_in_reservs * sizeof (set_el_t));
3671 return result;
3674 /* The function frees node STATE. */
3675 static void
3676 free_state (state_t state)
3678 free_alt_states (state->component_states);
3679 state->next_equiv_class_state = first_free_state;
3680 first_free_state = state;
3683 /* Hash value of STATE. If STATE represents deterministic state it is
3684 simply hash value of the corresponding reservation set. Otherwise
3685 it is formed from hash values of the component deterministic
3686 states. One more key is order number of state automaton. */
3687 static hashval_t
3688 state_hash (const void *state)
3690 unsigned int hash_value;
3691 alt_state_t alt_state;
3693 if (((const_state_t) state)->component_states == NULL)
3694 hash_value = reserv_sets_hash_value (((const_state_t) state)->reservs);
3695 else
3697 hash_value = 0;
3698 for (alt_state = ((const_state_t) state)->component_states;
3699 alt_state != NULL;
3700 alt_state = alt_state->next_sorted_alt_state)
3701 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
3702 | (hash_value << CHAR_BIT))
3703 + alt_state->state->unique_num);
3705 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
3706 | (hash_value << CHAR_BIT))
3707 + ((const_state_t) state)->automaton->automaton_order_num);
3708 return hash_value;
3711 /* Return nonzero value if the states are the same. */
3712 static int
3713 state_eq_p (const void *state_1, const void *state_2)
3715 alt_state_t alt_state_1;
3716 alt_state_t alt_state_2;
3718 if (((const_state_t) state_1)->automaton != ((const_state_t) state_2)->automaton)
3719 return 0;
3720 else if (((const_state_t) state_1)->component_states == NULL
3721 && ((const_state_t) state_2)->component_states == NULL)
3722 return reserv_sets_eq (((const_state_t) state_1)->reservs,
3723 ((const_state_t) state_2)->reservs);
3724 else if (((const_state_t) state_1)->component_states != NULL
3725 && ((const_state_t) state_2)->component_states != NULL)
3727 for (alt_state_1 = ((const_state_t) state_1)->component_states,
3728 alt_state_2 = ((const_state_t) state_2)->component_states;
3729 alt_state_1 != NULL && alt_state_2 != NULL;
3730 alt_state_1 = alt_state_1->next_sorted_alt_state,
3731 alt_state_2 = alt_state_2->next_sorted_alt_state)
3732 /* All state in the list must be already in the hash table.
3733 Also the lists must be sorted. */
3734 if (alt_state_1->state != alt_state_2->state)
3735 return 0;
3736 return alt_state_1 == alt_state_2;
3738 else
3739 return 0;
3742 /* Insert STATE into the state table. */
3743 static state_t
3744 insert_state (state_t state)
3746 void **entry_ptr;
3748 entry_ptr = htab_find_slot (state_table, (void *) state, INSERT);
3749 if (*entry_ptr == NULL)
3750 *entry_ptr = (void *) state;
3751 return (state_t) *entry_ptr;
3754 /* Add reservation of unit with UNIT_NUM on cycle CYCLE_NUM to
3755 deterministic STATE. */
3756 static void
3757 set_state_reserv (state_t state, int cycle_num, int unit_num)
3759 set_unit_reserv (state->reservs, cycle_num, unit_num);
3762 /* Return nonzero value if the deterministic states contains a
3763 reservation of the same cpu unit on the same cpu cycle. */
3764 static int
3765 intersected_state_reservs_p (state_t state1, state_t state2)
3767 gcc_assert (state1->automaton == state2->automaton);
3768 return reserv_sets_are_intersected (state1->reservs, state2->reservs);
3771 /* Return deterministic state (inserted into the table) which
3772 representing the automaton state which is union of reservations of
3773 the deterministic states masked by RESERVS. */
3774 static state_t
3775 states_union (state_t state1, state_t state2, reserv_sets_t reservs)
3777 state_t result;
3778 state_t state_in_table;
3780 gcc_assert (state1->automaton == state2->automaton);
3781 result = get_free_state (1, state1->automaton);
3782 reserv_sets_or (result->reservs, state1->reservs, state2->reservs);
3783 reserv_sets_and (result->reservs, result->reservs, reservs);
3784 state_in_table = insert_state (result);
3785 if (result != state_in_table)
3787 free_state (result);
3788 result = state_in_table;
3790 return result;
3793 /* Return deterministic state (inserted into the table) which
3794 represent the automaton state is obtained from deterministic STATE
3795 by advancing cpu cycle and masking by RESERVS. */
3796 static state_t
3797 state_shift (state_t state, reserv_sets_t reservs)
3799 state_t result;
3800 state_t state_in_table;
3802 result = get_free_state (1, state->automaton);
3803 reserv_sets_shift (result->reservs, state->reservs);
3804 reserv_sets_and (result->reservs, result->reservs, reservs);
3805 state_in_table = insert_state (result);
3806 if (result != state_in_table)
3808 free_state (result);
3809 result = state_in_table;
3811 return result;
3814 /* Initialization of the abstract data. */
3815 static void
3816 initiate_states (void)
3818 decl_t decl;
3819 int i;
3821 if (description->units_num)
3822 units_array = XNEWVEC (unit_decl_t, description->units_num);
3823 else
3824 units_array = 0;
3826 for (i = 0; i < description->decls_num; i++)
3828 decl = description->decls [i];
3829 if (decl->mode == dm_unit)
3830 units_array [DECL_UNIT (decl)->unit_num] = DECL_UNIT (decl);
3832 max_cycles_num = description->max_insn_reserv_cycles;
3833 els_in_cycle_reserv
3834 = ((description->units_num + sizeof (set_el_t) * CHAR_BIT - 1)
3835 / (sizeof (set_el_t) * CHAR_BIT));
3836 els_in_reservs = els_in_cycle_reserv * max_cycles_num;
3837 curr_unique_state_num = 0;
3838 initiate_alt_states ();
3839 state_table = htab_create (1500, state_hash, state_eq_p, (htab_del) 0);
3840 temp_reserv = alloc_empty_reserv_sets ();
3843 /* Finishing work with the abstract data. */
3844 static void
3845 finish_states (void)
3847 free (units_array);
3848 units_array = 0;
3849 htab_delete (state_table);
3850 first_free_state = NULL;
3851 finish_alt_states ();
3856 /* Abstract data `arcs'. */
3858 /* List of free arcs. */
3859 static arc_t first_free_arc;
3861 #ifndef NDEBUG
3862 /* The following variables is maximal number of allocated nodes
3863 `arc'. */
3864 static int allocated_arcs_num = 0;
3865 #endif
3867 /* The function frees node ARC. */
3868 static void
3869 free_arc (arc_t arc)
3871 arc->next_out_arc = first_free_arc;
3872 first_free_arc = arc;
3875 /* The function removes and frees ARC staring from FROM_STATE. */
3876 static void
3877 remove_arc (state_t from_state, arc_t arc)
3879 arc_t prev_arc;
3880 arc_t curr_arc;
3882 gcc_assert (arc);
3883 for (prev_arc = NULL, curr_arc = from_state->first_out_arc;
3884 curr_arc != NULL;
3885 prev_arc = curr_arc, curr_arc = curr_arc->next_out_arc)
3886 if (curr_arc == arc)
3887 break;
3888 gcc_assert (curr_arc);
3889 if (prev_arc == NULL)
3890 from_state->first_out_arc = arc->next_out_arc;
3891 else
3892 prev_arc->next_out_arc = arc->next_out_arc;
3893 from_state->num_out_arcs--;
3894 free_arc (arc);
3897 /* The functions returns arc with given characteristics (or NULL if
3898 the arc does not exist). */
3899 static arc_t
3900 find_arc (state_t from_state, state_t to_state, ainsn_t insn)
3902 arc_t arc;
3904 for (arc = first_out_arc (from_state); arc != NULL; arc = next_out_arc (arc))
3905 if (arc->to_state == to_state && arc->insn == insn)
3906 return arc;
3907 return NULL;
3910 /* The function adds arc from FROM_STATE to TO_STATE marked by AINSN.
3911 The function returns added arc (or already existing arc). */
3912 static arc_t
3913 add_arc (state_t from_state, state_t to_state, ainsn_t ainsn)
3915 arc_t new_arc;
3917 new_arc = find_arc (from_state, to_state, ainsn);
3918 if (new_arc != NULL)
3919 return new_arc;
3920 if (first_free_arc == NULL)
3922 #ifndef NDEBUG
3923 allocated_arcs_num++;
3924 #endif
3925 new_arc = XCREATENODE (struct arc);
3926 new_arc->to_state = NULL;
3927 new_arc->insn = NULL;
3928 new_arc->next_out_arc = NULL;
3930 else
3932 new_arc = first_free_arc;
3933 first_free_arc = first_free_arc->next_out_arc;
3935 new_arc->to_state = to_state;
3936 new_arc->insn = ainsn;
3937 ainsn->arc_exists_p = 1;
3938 new_arc->next_out_arc = from_state->first_out_arc;
3939 from_state->first_out_arc = new_arc;
3940 from_state->num_out_arcs++;
3941 new_arc->next_arc_marked_by_insn = NULL;
3942 return new_arc;
3945 /* The function returns the first arc starting from STATE. */
3946 static arc_t
3947 first_out_arc (const_state_t state)
3949 return state->first_out_arc;
3952 /* The function returns next out arc after ARC. */
3953 static arc_t
3954 next_out_arc (arc_t arc)
3956 return arc->next_out_arc;
3959 /* Initialization of the abstract data. */
3960 static void
3961 initiate_arcs (void)
3963 first_free_arc = NULL;
3966 /* Finishing work with the abstract data. */
3967 static void
3968 finish_arcs (void)
3974 /* Abstract data `automata lists'. */
3976 /* List of free states. */
3977 static automata_list_el_t first_free_automata_list_el;
3979 /* The list being formed. */
3980 static automata_list_el_t current_automata_list;
3982 /* Hash table of automata lists. */
3983 static htab_t automata_list_table;
3985 /* The following function returns free automata list el. It may be
3986 new allocated node or node freed earlier. */
3987 static automata_list_el_t
3988 get_free_automata_list_el (void)
3990 automata_list_el_t result;
3992 if (first_free_automata_list_el != NULL)
3994 result = first_free_automata_list_el;
3995 first_free_automata_list_el
3996 = first_free_automata_list_el->next_automata_list_el;
3998 else
3999 result = XCREATENODE (struct automata_list_el);
4000 result->automaton = NULL;
4001 result->next_automata_list_el = NULL;
4002 return result;
4005 /* The function frees node AUTOMATA_LIST_EL. */
4006 static void
4007 free_automata_list_el (automata_list_el_t automata_list_el)
4009 if (automata_list_el == NULL)
4010 return;
4011 automata_list_el->next_automata_list_el = first_free_automata_list_el;
4012 first_free_automata_list_el = automata_list_el;
4015 /* The function frees list AUTOMATA_LIST. */
4016 static void
4017 free_automata_list (automata_list_el_t automata_list)
4019 automata_list_el_t curr_automata_list_el;
4020 automata_list_el_t next_automata_list_el;
4022 for (curr_automata_list_el = automata_list;
4023 curr_automata_list_el != NULL;
4024 curr_automata_list_el = next_automata_list_el)
4026 next_automata_list_el = curr_automata_list_el->next_automata_list_el;
4027 free_automata_list_el (curr_automata_list_el);
4031 /* Hash value of AUTOMATA_LIST. */
4032 static hashval_t
4033 automata_list_hash (const void *automata_list)
4035 unsigned int hash_value;
4036 const_automata_list_el_t curr_automata_list_el;
4038 hash_value = 0;
4039 for (curr_automata_list_el = (const_automata_list_el_t) automata_list;
4040 curr_automata_list_el != NULL;
4041 curr_automata_list_el = curr_automata_list_el->next_automata_list_el)
4042 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
4043 | (hash_value << CHAR_BIT))
4044 + curr_automata_list_el->automaton->automaton_order_num);
4045 return hash_value;
4048 /* Return nonzero value if the automata_lists are the same. */
4049 static int
4050 automata_list_eq_p (const void *automata_list_1, const void *automata_list_2)
4052 const_automata_list_el_t automata_list_el_1;
4053 const_automata_list_el_t automata_list_el_2;
4055 for (automata_list_el_1 = (const_automata_list_el_t) automata_list_1,
4056 automata_list_el_2 = (const_automata_list_el_t) automata_list_2;
4057 automata_list_el_1 != NULL && automata_list_el_2 != NULL;
4058 automata_list_el_1 = automata_list_el_1->next_automata_list_el,
4059 automata_list_el_2 = automata_list_el_2->next_automata_list_el)
4060 if (automata_list_el_1->automaton != automata_list_el_2->automaton)
4061 return 0;
4062 return automata_list_el_1 == automata_list_el_2;
4065 /* Initialization of the abstract data. */
4066 static void
4067 initiate_automata_lists (void)
4069 first_free_automata_list_el = NULL;
4070 automata_list_table = htab_create (1500, automata_list_hash,
4071 automata_list_eq_p, (htab_del) 0);
4074 /* The following function starts new automata list and makes it the
4075 current one. */
4076 static void
4077 automata_list_start (void)
4079 current_automata_list = NULL;
4082 /* The following function adds AUTOMATON to the current list. */
4083 static void
4084 automata_list_add (automaton_t automaton)
4086 automata_list_el_t el;
4088 el = get_free_automata_list_el ();
4089 el->automaton = automaton;
4090 el->next_automata_list_el = current_automata_list;
4091 current_automata_list = el;
4094 /* The following function finishes forming the current list, inserts
4095 it into the table and returns it. */
4096 static automata_list_el_t
4097 automata_list_finish (void)
4099 void **entry_ptr;
4101 if (current_automata_list == NULL)
4102 return NULL;
4103 entry_ptr = htab_find_slot (automata_list_table,
4104 (void *) current_automata_list, INSERT);
4105 if (*entry_ptr == NULL)
4106 *entry_ptr = (void *) current_automata_list;
4107 else
4108 free_automata_list (current_automata_list);
4109 current_automata_list = NULL;
4110 return (automata_list_el_t) *entry_ptr;
4113 /* Finishing work with the abstract data. */
4114 static void
4115 finish_automata_lists (void)
4117 htab_delete (automata_list_table);
4122 /* The page contains abstract data for work with exclusion sets (see
4123 exclusion_set in file rtl.def). */
4125 /* The following variable refers to an exclusion set returned by
4126 get_excl_set. This is bit string of length equal to cpu units
4127 number. If exclusion set for given unit contains 1 for a unit,
4128 then simultaneous reservation of the units is prohibited. */
4129 static reserv_sets_t excl_set;
4131 /* The array contains exclusion sets for each unit. */
4132 static reserv_sets_t *unit_excl_set_table;
4134 /* The following function forms the array containing exclusion sets
4135 for each unit. */
4136 static void
4137 initiate_excl_sets (void)
4139 decl_t decl;
4140 reserv_sets_t unit_excl_set;
4141 unit_set_el_t el;
4142 int i;
4144 obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4145 excl_set = (reserv_sets_t) obstack_base (&irp);
4146 obstack_finish (&irp);
4147 obstack_blank (&irp, description->units_num * sizeof (reserv_sets_t));
4148 unit_excl_set_table = (reserv_sets_t *) obstack_base (&irp);
4149 obstack_finish (&irp);
4150 /* Evaluate unit exclusion sets. */
4151 for (i = 0; i < description->decls_num; i++)
4153 decl = description->decls [i];
4154 if (decl->mode == dm_unit)
4156 obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4157 unit_excl_set = (reserv_sets_t) obstack_base (&irp);
4158 obstack_finish (&irp);
4159 memset (unit_excl_set, 0, els_in_cycle_reserv * sizeof (set_el_t));
4160 for (el = DECL_UNIT (decl)->excl_list;
4161 el != NULL;
4162 el = el->next_unit_set_el)
4164 SET_BIT (unit_excl_set, el->unit_decl->unit_num);
4165 el->unit_decl->in_set_p = TRUE;
4167 unit_excl_set_table [DECL_UNIT (decl)->unit_num] = unit_excl_set;
4172 /* The function sets up and return EXCL_SET which is union of
4173 exclusion sets for each unit in IN_SET. */
4174 static reserv_sets_t
4175 get_excl_set (reserv_sets_t in_set)
4177 int excl_char_num;
4178 int chars_num;
4179 int i;
4180 int start_unit_num;
4181 int unit_num;
4183 chars_num = els_in_cycle_reserv * sizeof (set_el_t);
4184 memset (excl_set, 0, chars_num);
4185 for (excl_char_num = 0; excl_char_num < chars_num; excl_char_num++)
4186 if (((unsigned char *) in_set) [excl_char_num])
4187 for (i = CHAR_BIT - 1; i >= 0; i--)
4188 if ((((unsigned char *) in_set) [excl_char_num] >> i) & 1)
4190 start_unit_num = excl_char_num * CHAR_BIT + i;
4191 if (start_unit_num >= description->units_num)
4192 return excl_set;
4193 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4195 excl_set [unit_num]
4196 |= unit_excl_set_table [start_unit_num] [unit_num];
4199 return excl_set;
4204 /* The page contains abstract data for work with presence/absence
4205 pattern sets (see presence_set/absence_set in file rtl.def). */
4207 /* The following arrays contain correspondingly presence, final
4208 presence, absence, and final absence patterns for each unit. */
4209 static pattern_reserv_t *unit_presence_set_table;
4210 static pattern_reserv_t *unit_final_presence_set_table;
4211 static pattern_reserv_t *unit_absence_set_table;
4212 static pattern_reserv_t *unit_final_absence_set_table;
4214 /* The following function forms list of reservation sets for given
4215 PATTERN_LIST. */
4216 static pattern_reserv_t
4217 form_reserv_sets_list (pattern_set_el_t pattern_list)
4219 pattern_set_el_t el;
4220 pattern_reserv_t first, curr, prev;
4221 int i;
4223 prev = first = NULL;
4224 for (el = pattern_list; el != NULL; el = el->next_pattern_set_el)
4226 curr = XCREATENODE (struct pattern_reserv);
4227 curr->reserv = alloc_empty_reserv_sets ();
4228 curr->next_pattern_reserv = NULL;
4229 for (i = 0; i < el->units_num; i++)
4231 SET_BIT (curr->reserv, el->unit_decls [i]->unit_num);
4232 el->unit_decls [i]->in_set_p = TRUE;
4234 if (prev != NULL)
4235 prev->next_pattern_reserv = curr;
4236 else
4237 first = curr;
4238 prev = curr;
4240 return first;
4243 /* The following function forms the array containing presence and
4244 absence pattern sets for each unit. */
4245 static void
4246 initiate_presence_absence_pattern_sets (void)
4248 decl_t decl;
4249 int i;
4251 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4252 unit_presence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4253 obstack_finish (&irp);
4254 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4255 unit_final_presence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4256 obstack_finish (&irp);
4257 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4258 unit_absence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4259 obstack_finish (&irp);
4260 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4261 unit_final_absence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4262 obstack_finish (&irp);
4263 /* Evaluate unit presence/absence sets. */
4264 for (i = 0; i < description->decls_num; i++)
4266 decl = description->decls [i];
4267 if (decl->mode == dm_unit)
4269 unit_presence_set_table [DECL_UNIT (decl)->unit_num]
4270 = form_reserv_sets_list (DECL_UNIT (decl)->presence_list);
4271 unit_final_presence_set_table [DECL_UNIT (decl)->unit_num]
4272 = form_reserv_sets_list (DECL_UNIT (decl)->final_presence_list);
4273 unit_absence_set_table [DECL_UNIT (decl)->unit_num]
4274 = form_reserv_sets_list (DECL_UNIT (decl)->absence_list);
4275 unit_final_absence_set_table [DECL_UNIT (decl)->unit_num]
4276 = form_reserv_sets_list (DECL_UNIT (decl)->final_absence_list);
4281 /* The function checks that CHECKED_SET satisfies all presence pattern
4282 sets for units in ORIGINAL_SET. The function returns TRUE if it
4283 is ok. */
4284 static int
4285 check_presence_pattern_sets (reserv_sets_t checked_set,
4286 reserv_sets_t original_set,
4287 int final_p)
4289 int char_num;
4290 int chars_num;
4291 int i;
4292 int start_unit_num;
4293 int unit_num;
4294 int presence_p;
4295 pattern_reserv_t pat_reserv;
4297 chars_num = els_in_cycle_reserv * sizeof (set_el_t);
4298 for (char_num = 0; char_num < chars_num; char_num++)
4299 if (((unsigned char *) original_set) [char_num])
4300 for (i = CHAR_BIT - 1; i >= 0; i--)
4301 if ((((unsigned char *) original_set) [char_num] >> i) & 1)
4303 start_unit_num = char_num * CHAR_BIT + i;
4304 if (start_unit_num >= description->units_num)
4305 break;
4306 if ((final_p
4307 && unit_final_presence_set_table [start_unit_num] == NULL)
4308 || (!final_p
4309 && unit_presence_set_table [start_unit_num] == NULL))
4310 continue;
4311 presence_p = FALSE;
4312 for (pat_reserv = (final_p
4313 ? unit_final_presence_set_table [start_unit_num]
4314 : unit_presence_set_table [start_unit_num]);
4315 pat_reserv != NULL;
4316 pat_reserv = pat_reserv->next_pattern_reserv)
4318 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4319 if ((checked_set [unit_num] & pat_reserv->reserv [unit_num])
4320 != pat_reserv->reserv [unit_num])
4321 break;
4322 presence_p = presence_p || unit_num >= els_in_cycle_reserv;
4324 if (!presence_p)
4325 return FALSE;
4327 return TRUE;
4330 /* The function checks that CHECKED_SET satisfies all absence pattern
4331 sets for units in ORIGINAL_SET. The function returns TRUE if it
4332 is ok. */
4333 static int
4334 check_absence_pattern_sets (reserv_sets_t checked_set,
4335 reserv_sets_t original_set,
4336 int final_p)
4338 int char_num;
4339 int chars_num;
4340 int i;
4341 int start_unit_num;
4342 int unit_num;
4343 pattern_reserv_t pat_reserv;
4345 chars_num = els_in_cycle_reserv * sizeof (set_el_t);
4346 for (char_num = 0; char_num < chars_num; char_num++)
4347 if (((unsigned char *) original_set) [char_num])
4348 for (i = CHAR_BIT - 1; i >= 0; i--)
4349 if ((((unsigned char *) original_set) [char_num] >> i) & 1)
4351 start_unit_num = char_num * CHAR_BIT + i;
4352 if (start_unit_num >= description->units_num)
4353 break;
4354 for (pat_reserv = (final_p
4355 ? unit_final_absence_set_table [start_unit_num]
4356 : unit_absence_set_table [start_unit_num]);
4357 pat_reserv != NULL;
4358 pat_reserv = pat_reserv->next_pattern_reserv)
4360 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4361 if ((checked_set [unit_num] & pat_reserv->reserv [unit_num])
4362 != pat_reserv->reserv [unit_num]
4363 && pat_reserv->reserv [unit_num])
4364 break;
4365 if (unit_num >= els_in_cycle_reserv)
4366 return FALSE;
4369 return TRUE;
4374 /* This page contains code for transformation of original reservations
4375 described in .md file. The main goal of transformations is
4376 simplifying reservation and lifting up all `|' on the top of IR
4377 reservation representation. */
4380 /* The following function makes copy of IR representation of
4381 reservation. The function also substitutes all reservations
4382 defined by define_reservation by corresponding value during making
4383 the copy. */
4384 static regexp_t
4385 copy_insn_regexp (regexp_t regexp)
4387 regexp_t result;
4388 int i;
4390 switch (regexp->mode)
4392 case rm_reserv:
4393 result = copy_insn_regexp (REGEXP_RESERV (regexp)->reserv_decl->regexp);
4394 break;
4396 case rm_unit:
4397 result = XCOPYNODE (struct regexp, regexp);
4398 break;
4400 case rm_repeat:
4401 result = XCOPYNODE (struct regexp, regexp);
4402 REGEXP_REPEAT (result)->regexp
4403 = copy_insn_regexp (REGEXP_REPEAT (regexp)->regexp);
4404 break;
4406 case rm_sequence:
4407 result = XCOPYNODEVAR (struct regexp, regexp,
4408 sizeof (struct regexp) + sizeof (regexp_t)
4409 * (REGEXP_SEQUENCE (regexp)->regexps_num - 1));
4410 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4411 REGEXP_SEQUENCE (result)->regexps [i]
4412 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4413 break;
4415 case rm_allof:
4416 result = XCOPYNODEVAR (struct regexp, regexp,
4417 sizeof (struct regexp) + sizeof (regexp_t)
4418 * (REGEXP_ALLOF (regexp)->regexps_num - 1));
4419 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4420 REGEXP_ALLOF (result)->regexps [i]
4421 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4422 break;
4424 case rm_oneof:
4425 result = XCOPYNODEVAR (struct regexp, regexp,
4426 sizeof (struct regexp) + sizeof (regexp_t)
4427 * (REGEXP_ONEOF (regexp)->regexps_num - 1));
4428 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4429 REGEXP_ONEOF (result)->regexps [i]
4430 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4431 break;
4433 case rm_nothing:
4434 result = XCOPYNODE (struct regexp, regexp);
4435 break;
4437 default:
4438 gcc_unreachable ();
4440 return result;
4443 /* The following variable is set up 1 if a transformation has been
4444 applied. */
4445 static int regexp_transformed_p;
4447 /* The function makes transformation
4448 A*N -> A, A, ... */
4449 static regexp_t
4450 transform_1 (regexp_t regexp)
4452 int i;
4453 int repeat_num;
4454 regexp_t operand;
4455 pos_t pos;
4457 if (regexp->mode == rm_repeat)
4459 repeat_num = REGEXP_REPEAT (regexp)->repeat_num;
4460 gcc_assert (repeat_num > 1);
4461 operand = REGEXP_REPEAT (regexp)->regexp;
4462 pos = regexp->mode;
4463 regexp = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4464 + sizeof (regexp_t) * (repeat_num - 1));
4465 regexp->mode = rm_sequence;
4466 regexp->pos = pos;
4467 REGEXP_SEQUENCE (regexp)->regexps_num = repeat_num;
4468 for (i = 0; i < repeat_num; i++)
4469 REGEXP_SEQUENCE (regexp)->regexps [i] = copy_insn_regexp (operand);
4470 regexp_transformed_p = 1;
4472 return regexp;
4475 /* The function makes transformations
4476 ...,(A,B,...),C,... -> ...,A,B,...,C,...
4477 ...+(A+B+...)+C+... -> ...+A+B+...+C+...
4478 ...|(A|B|...)|C|... -> ...|A|B|...|C|... */
4479 static regexp_t
4480 transform_2 (regexp_t regexp)
4482 if (regexp->mode == rm_sequence)
4484 regexp_t sequence = NULL;
4485 regexp_t result;
4486 int sequence_index = 0;
4487 int i, j;
4489 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4490 if (REGEXP_SEQUENCE (regexp)->regexps [i]->mode == rm_sequence)
4492 sequence_index = i;
4493 sequence = REGEXP_SEQUENCE (regexp)->regexps [i];
4494 break;
4496 if (i < REGEXP_SEQUENCE (regexp)->regexps_num)
4498 gcc_assert (REGEXP_SEQUENCE (sequence)->regexps_num > 1
4499 && REGEXP_SEQUENCE (regexp)->regexps_num > 1);
4500 result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4501 + sizeof (regexp_t)
4502 * (REGEXP_SEQUENCE (regexp)->regexps_num
4503 + REGEXP_SEQUENCE (sequence)->regexps_num
4504 - 2));
4505 result->mode = rm_sequence;
4506 result->pos = regexp->pos;
4507 REGEXP_SEQUENCE (result)->regexps_num
4508 = (REGEXP_SEQUENCE (regexp)->regexps_num
4509 + REGEXP_SEQUENCE (sequence)->regexps_num - 1);
4510 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4511 if (i < sequence_index)
4512 REGEXP_SEQUENCE (result)->regexps [i]
4513 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4514 else if (i > sequence_index)
4515 REGEXP_SEQUENCE (result)->regexps
4516 [i + REGEXP_SEQUENCE (sequence)->regexps_num - 1]
4517 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4518 else
4519 for (j = 0; j < REGEXP_SEQUENCE (sequence)->regexps_num; j++)
4520 REGEXP_SEQUENCE (result)->regexps [i + j]
4521 = copy_insn_regexp (REGEXP_SEQUENCE (sequence)->regexps [j]);
4522 regexp_transformed_p = 1;
4523 regexp = result;
4526 else if (regexp->mode == rm_allof)
4528 regexp_t allof = NULL;
4529 regexp_t result;
4530 int allof_index = 0;
4531 int i, j;
4533 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4534 if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_allof)
4536 allof_index = i;
4537 allof = REGEXP_ALLOF (regexp)->regexps [i];
4538 break;
4540 if (i < REGEXP_ALLOF (regexp)->regexps_num)
4542 gcc_assert (REGEXP_ALLOF (allof)->regexps_num > 1
4543 && REGEXP_ALLOF (regexp)->regexps_num > 1);
4544 result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4545 + sizeof (regexp_t)
4546 * (REGEXP_ALLOF (regexp)->regexps_num
4547 + REGEXP_ALLOF (allof)->regexps_num - 2));
4548 result->mode = rm_allof;
4549 result->pos = regexp->pos;
4550 REGEXP_ALLOF (result)->regexps_num
4551 = (REGEXP_ALLOF (regexp)->regexps_num
4552 + REGEXP_ALLOF (allof)->regexps_num - 1);
4553 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4554 if (i < allof_index)
4555 REGEXP_ALLOF (result)->regexps [i]
4556 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4557 else if (i > allof_index)
4558 REGEXP_ALLOF (result)->regexps
4559 [i + REGEXP_ALLOF (allof)->regexps_num - 1]
4560 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4561 else
4562 for (j = 0; j < REGEXP_ALLOF (allof)->regexps_num; j++)
4563 REGEXP_ALLOF (result)->regexps [i + j]
4564 = copy_insn_regexp (REGEXP_ALLOF (allof)->regexps [j]);
4565 regexp_transformed_p = 1;
4566 regexp = result;
4569 else if (regexp->mode == rm_oneof)
4571 regexp_t oneof = NULL;
4572 regexp_t result;
4573 int oneof_index = 0;
4574 int i, j;
4576 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4577 if (REGEXP_ONEOF (regexp)->regexps [i]->mode == rm_oneof)
4579 oneof_index = i;
4580 oneof = REGEXP_ONEOF (regexp)->regexps [i];
4581 break;
4583 if (i < REGEXP_ONEOF (regexp)->regexps_num)
4585 gcc_assert (REGEXP_ONEOF (oneof)->regexps_num > 1
4586 && REGEXP_ONEOF (regexp)->regexps_num > 1);
4587 result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4588 + sizeof (regexp_t)
4589 * (REGEXP_ONEOF (regexp)->regexps_num
4590 + REGEXP_ONEOF (oneof)->regexps_num - 2));
4591 result->mode = rm_oneof;
4592 result->pos = regexp->pos;
4593 REGEXP_ONEOF (result)->regexps_num
4594 = (REGEXP_ONEOF (regexp)->regexps_num
4595 + REGEXP_ONEOF (oneof)->regexps_num - 1);
4596 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4597 if (i < oneof_index)
4598 REGEXP_ONEOF (result)->regexps [i]
4599 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4600 else if (i > oneof_index)
4601 REGEXP_ONEOF (result)->regexps
4602 [i + REGEXP_ONEOF (oneof)->regexps_num - 1]
4603 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4604 else
4605 for (j = 0; j < REGEXP_ONEOF (oneof)->regexps_num; j++)
4606 REGEXP_ONEOF (result)->regexps [i + j]
4607 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [j]);
4608 regexp_transformed_p = 1;
4609 regexp = result;
4612 return regexp;
4615 /* The function makes transformations
4616 ...,A|B|...,C,... -> (...,A,C,...)|(...,B,C,...)|...
4617 ...+(A|B|...)+C+... -> (...+A+C+...)|(...+B+C+...)|...
4618 ...+(A,B,...)+C+... -> (...+A+C+...),B,...
4619 ...+(A,B,...)+(C,D,...) -> (A+C),(B+D),... */
4620 static regexp_t
4621 transform_3 (regexp_t regexp)
4623 if (regexp->mode == rm_sequence)
4625 regexp_t oneof = NULL;
4626 int oneof_index = 0;
4627 regexp_t result;
4628 regexp_t sequence;
4629 int i, j;
4631 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4632 if (REGEXP_SEQUENCE (regexp)->regexps [i]->mode == rm_oneof)
4634 oneof_index = i;
4635 oneof = REGEXP_SEQUENCE (regexp)->regexps [i];
4636 break;
4638 if (i < REGEXP_SEQUENCE (regexp)->regexps_num)
4640 gcc_assert (REGEXP_ONEOF (oneof)->regexps_num > 1
4641 && REGEXP_SEQUENCE (regexp)->regexps_num > 1);
4642 result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4643 + sizeof (regexp_t)
4644 * (REGEXP_ONEOF (oneof)->regexps_num - 1));
4645 result->mode = rm_oneof;
4646 result->pos = regexp->pos;
4647 REGEXP_ONEOF (result)->regexps_num
4648 = REGEXP_ONEOF (oneof)->regexps_num;
4649 for (i = 0; i < REGEXP_ONEOF (result)->regexps_num; i++)
4651 sequence
4652 = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4653 + sizeof (regexp_t)
4654 * (REGEXP_SEQUENCE (regexp)->regexps_num - 1));
4655 sequence->mode = rm_sequence;
4656 sequence->pos = regexp->pos;
4657 REGEXP_SEQUENCE (sequence)->regexps_num
4658 = REGEXP_SEQUENCE (regexp)->regexps_num;
4659 REGEXP_ONEOF (result)->regexps [i] = sequence;
4660 for (j = 0; j < REGEXP_SEQUENCE (sequence)->regexps_num; j++)
4661 if (j != oneof_index)
4662 REGEXP_SEQUENCE (sequence)->regexps [j]
4663 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [j]);
4664 else
4665 REGEXP_SEQUENCE (sequence)->regexps [j]
4666 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [i]);
4668 regexp_transformed_p = 1;
4669 regexp = result;
4672 else if (regexp->mode == rm_allof)
4674 regexp_t oneof = NULL;
4675 regexp_t seq;
4676 int oneof_index = 0;
4677 int max_seq_length, allof_length;
4678 regexp_t result;
4679 regexp_t allof = NULL;
4680 regexp_t allof_op = NULL;
4681 int i, j;
4683 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4684 if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_oneof)
4686 oneof_index = i;
4687 oneof = REGEXP_ALLOF (regexp)->regexps [i];
4688 break;
4690 if (i < REGEXP_ALLOF (regexp)->regexps_num)
4692 gcc_assert (REGEXP_ONEOF (oneof)->regexps_num > 1
4693 && REGEXP_ALLOF (regexp)->regexps_num > 1);
4694 result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4695 + sizeof (regexp_t)
4696 * (REGEXP_ONEOF (oneof)->regexps_num - 1));
4697 result->mode = rm_oneof;
4698 result->pos = regexp->pos;
4699 REGEXP_ONEOF (result)->regexps_num
4700 = REGEXP_ONEOF (oneof)->regexps_num;
4701 for (i = 0; i < REGEXP_ONEOF (result)->regexps_num; i++)
4703 allof
4704 = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4705 + sizeof (regexp_t)
4706 * (REGEXP_ALLOF (regexp)->regexps_num - 1));
4707 allof->mode = rm_allof;
4708 allof->pos = regexp->pos;
4709 REGEXP_ALLOF (allof)->regexps_num
4710 = REGEXP_ALLOF (regexp)->regexps_num;
4711 REGEXP_ONEOF (result)->regexps [i] = allof;
4712 for (j = 0; j < REGEXP_ALLOF (allof)->regexps_num; j++)
4713 if (j != oneof_index)
4714 REGEXP_ALLOF (allof)->regexps [j]
4715 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [j]);
4716 else
4717 REGEXP_ALLOF (allof)->regexps [j]
4718 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [i]);
4720 regexp_transformed_p = 1;
4721 regexp = result;
4723 max_seq_length = 0;
4724 if (regexp->mode == rm_allof)
4725 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4727 switch (REGEXP_ALLOF (regexp)->regexps [i]->mode)
4729 case rm_sequence:
4730 seq = REGEXP_ALLOF (regexp)->regexps [i];
4731 if (max_seq_length < REGEXP_SEQUENCE (seq)->regexps_num)
4732 max_seq_length = REGEXP_SEQUENCE (seq)->regexps_num;
4733 break;
4735 case rm_unit:
4736 case rm_nothing:
4737 break;
4739 default:
4740 max_seq_length = 0;
4741 goto break_for;
4744 break_for:
4745 if (max_seq_length != 0)
4747 gcc_assert (max_seq_length != 1
4748 && REGEXP_ALLOF (regexp)->regexps_num > 1);
4749 result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4750 + sizeof (regexp_t) * (max_seq_length - 1));
4751 result->mode = rm_sequence;
4752 result->pos = regexp->pos;
4753 REGEXP_SEQUENCE (result)->regexps_num = max_seq_length;
4754 for (i = 0; i < max_seq_length; i++)
4756 allof_length = 0;
4757 for (j = 0; j < REGEXP_ALLOF (regexp)->regexps_num; j++)
4758 switch (REGEXP_ALLOF (regexp)->regexps [j]->mode)
4760 case rm_sequence:
4761 if (i < (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4762 ->regexps [j])->regexps_num))
4764 allof_op
4765 = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4766 ->regexps [j])
4767 ->regexps [i]);
4768 allof_length++;
4770 break;
4771 case rm_unit:
4772 case rm_nothing:
4773 if (i == 0)
4775 allof_op = REGEXP_ALLOF (regexp)->regexps [j];
4776 allof_length++;
4778 break;
4779 default:
4780 break;
4783 if (allof_length == 1)
4784 REGEXP_SEQUENCE (result)->regexps [i] = allof_op;
4785 else
4787 allof = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4788 + sizeof (regexp_t)
4789 * (allof_length - 1));
4790 allof->mode = rm_allof;
4791 allof->pos = regexp->pos;
4792 REGEXP_ALLOF (allof)->regexps_num = allof_length;
4793 REGEXP_SEQUENCE (result)->regexps [i] = allof;
4794 allof_length = 0;
4795 for (j = 0; j < REGEXP_ALLOF (regexp)->regexps_num; j++)
4796 if (REGEXP_ALLOF (regexp)->regexps [j]->mode == rm_sequence
4797 && (i <
4798 (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4799 ->regexps [j])->regexps_num)))
4801 allof_op = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4802 ->regexps [j])
4803 ->regexps [i]);
4804 REGEXP_ALLOF (allof)->regexps [allof_length]
4805 = allof_op;
4806 allof_length++;
4808 else if (i == 0
4809 && (REGEXP_ALLOF (regexp)->regexps [j]->mode
4810 == rm_unit
4811 || (REGEXP_ALLOF (regexp)->regexps [j]->mode
4812 == rm_nothing)))
4814 allof_op = REGEXP_ALLOF (regexp)->regexps [j];
4815 REGEXP_ALLOF (allof)->regexps [allof_length]
4816 = allof_op;
4817 allof_length++;
4821 regexp_transformed_p = 1;
4822 regexp = result;
4825 return regexp;
4828 /* The function traverses IR of reservation and applies transformations
4829 implemented by FUNC. */
4830 static regexp_t
4831 regexp_transform_func (regexp_t regexp, regexp_t (*func) (regexp_t regexp))
4833 int i;
4835 switch (regexp->mode)
4837 case rm_sequence:
4838 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4839 REGEXP_SEQUENCE (regexp)->regexps [i]
4840 = regexp_transform_func (REGEXP_SEQUENCE (regexp)->regexps [i],
4841 func);
4842 break;
4844 case rm_allof:
4845 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4846 REGEXP_ALLOF (regexp)->regexps [i]
4847 = regexp_transform_func (REGEXP_ALLOF (regexp)->regexps [i], func);
4848 break;
4850 case rm_oneof:
4851 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4852 REGEXP_ONEOF (regexp)->regexps [i]
4853 = regexp_transform_func (REGEXP_ONEOF (regexp)->regexps [i], func);
4854 break;
4856 case rm_repeat:
4857 REGEXP_REPEAT (regexp)->regexp
4858 = regexp_transform_func (REGEXP_REPEAT (regexp)->regexp, func);
4859 break;
4861 case rm_nothing:
4862 case rm_unit:
4863 break;
4865 default:
4866 gcc_unreachable ();
4868 return (*func) (regexp);
4871 /* The function applies all transformations for IR representation of
4872 reservation REGEXP. */
4873 static regexp_t
4874 transform_regexp (regexp_t regexp)
4876 regexp = regexp_transform_func (regexp, transform_1);
4879 regexp_transformed_p = 0;
4880 regexp = regexp_transform_func (regexp, transform_2);
4881 regexp = regexp_transform_func (regexp, transform_3);
4883 while (regexp_transformed_p);
4884 return regexp;
4887 /* The function applies all transformations for reservations of all
4888 insn declarations. */
4889 static void
4890 transform_insn_regexps (void)
4892 decl_t decl;
4893 int i;
4895 transform_time = create_ticker ();
4896 add_advance_cycle_insn_decl ();
4897 if (progress_flag)
4898 fprintf (stderr, "Reservation transformation...");
4899 for (i = 0; i < description->decls_num; i++)
4901 decl = description->decls [i];
4902 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
4903 DECL_INSN_RESERV (decl)->transformed_regexp
4904 = transform_regexp (copy_insn_regexp
4905 (DECL_INSN_RESERV (decl)->regexp));
4907 if (progress_flag)
4908 fprintf (stderr, "done\n");
4909 ticker_off (&transform_time);
4914 /* The following variable value is TRUE if the first annotated message
4915 about units to automata distribution has been output. */
4916 static int annotation_message_reported_p;
4918 /* The vector contains all decls which are automata. */
4919 static VEC(decl_t, heap) *automaton_decls;
4921 /* The following structure describes usage of a unit in a reservation. */
4922 struct unit_usage
4924 unit_decl_t unit_decl;
4925 /* The following forms a list of units used on the same cycle in the
4926 same alternative. The list is ordered by the correspdoning unit
4927 declarations and there is no unit declaration duplication in the
4928 list. */
4929 struct unit_usage *next;
4931 typedef struct unit_usage *unit_usage_t;
4933 DEF_VEC_P(unit_usage_t);
4934 DEF_VEC_ALLOC_P(unit_usage_t, heap);
4936 /* Obstack for unit_usage structures. */
4937 static struct obstack unit_usages;
4939 /* VLA for representation of array of pointers to unit usage
4940 structures. There is an element for each combination of
4941 (alternative number, cycle). Unit usages on given cycle in
4942 alternative with given number are referred through element with
4943 index equals to the cycle * number of all alternatives in the
4944 regexp + the alternative number. */
4945 static VEC(unit_usage_t, heap) *cycle_alt_unit_usages;
4947 /* The following function creates the structure unit_usage for UNIT on
4948 CYCLE in REGEXP alternative with ALT_NUM. The structure is made
4949 accessed through cycle_alt_unit_usages. */
4950 static void
4951 store_alt_unit_usage (regexp_t regexp, regexp_t unit, int cycle,
4952 int alt_num)
4954 size_t length;
4955 unit_decl_t unit_decl;
4956 unit_usage_t unit_usage_ptr, curr, prev;
4957 int index;
4959 gcc_assert (regexp && regexp->mode == rm_oneof
4960 && alt_num < REGEXP_ONEOF (regexp)->regexps_num);
4961 unit_decl = REGEXP_UNIT (unit)->unit_decl;
4963 length = (cycle + 1) * REGEXP_ONEOF (regexp)->regexps_num;
4964 while (VEC_length (unit_usage_t, cycle_alt_unit_usages) < length)
4965 VEC_safe_push (unit_usage_t, heap, cycle_alt_unit_usages, 0);
4967 index = cycle * REGEXP_ONEOF (regexp)->regexps_num + alt_num;
4968 prev = NULL;
4969 for (curr = VEC_index (unit_usage_t, cycle_alt_unit_usages, index);
4970 curr != NULL;
4971 prev = curr, curr = curr->next)
4972 if (curr->unit_decl >= unit_decl)
4973 break;
4974 if (curr != NULL && curr->unit_decl == unit_decl)
4975 return;
4976 obstack_blank (&unit_usages, sizeof (struct unit_usage));
4977 unit_usage_ptr = (struct unit_usage *) obstack_base (&unit_usages);
4978 obstack_finish (&unit_usages);
4979 unit_usage_ptr->unit_decl = unit_decl;
4980 unit_decl->last_distribution_check_cycle = -1; /* undefined */
4981 unit_usage_ptr->next = curr;
4982 if (prev == NULL)
4983 VEC_replace (unit_usage_t, cycle_alt_unit_usages, index, unit_usage_ptr);
4984 else
4985 prev->next = unit_usage_ptr;
4988 /* Return true if unit UNIT_DECL is present on the LIST. */
4989 static bool
4990 unit_present_on_list_p (unit_usage_t list, unit_decl_t unit_decl)
4992 while (list != NULL)
4994 if (list->unit_decl == unit_decl)
4995 return true;
4996 list = list->next;
4998 return false;
5001 /* The function returns true if reservations of alternatives ALT1 and
5002 ALT2 are equal after excluding reservations of units of
5003 EXCLUDED_AUTOMATON_DECL. */
5004 static bool
5005 equal_alternatives_p (int alt1, int alt2, int n_alts,
5006 struct automaton_decl *excluded_automaton_decl)
5008 int i;
5009 unit_usage_t list1, list2;
5011 for (i = 0;
5012 i < (int) VEC_length (unit_usage_t, cycle_alt_unit_usages);
5013 i += n_alts)
5015 for (list1 = VEC_index (unit_usage_t, cycle_alt_unit_usages, i + alt1),
5016 list2 = VEC_index (unit_usage_t, cycle_alt_unit_usages, i + alt2);;
5017 list1 = list1->next, list2 = list2->next)
5019 while (list1 != NULL
5020 && list1->unit_decl->automaton_decl == excluded_automaton_decl)
5021 list1 = list1->next;
5022 while (list2 != NULL
5023 && list2->unit_decl->automaton_decl == excluded_automaton_decl)
5024 list2 = list2->next;
5025 if (list1 == NULL || list2 == NULL)
5027 if (list1 != list2)
5028 return false;
5029 else
5030 break;
5032 if (list1->unit_decl != list2->unit_decl)
5033 return false;
5036 return true;
5039 DEF_VEC_I(int);
5040 DEF_VEC_ALLOC_I(int, heap);
5042 /* The function processes given REGEXP to find units with the wrong
5043 distribution. */
5044 static void
5045 check_regexp_units_distribution (const char *insn_reserv_name,
5046 regexp_t regexp)
5048 int i, j, k, cycle, cycle2, start, n_alts, alt, alt2;
5049 bool annotation_reservation_message_reported_p;
5050 regexp_t seq, allof, unit;
5051 struct unit_usage *unit_usage_ptr;
5052 VEC(int, heap) *marked;
5054 if (regexp == NULL || regexp->mode != rm_oneof)
5055 return;
5056 /* Store all unit usages in the regexp: */
5057 obstack_init (&unit_usages);
5058 cycle_alt_unit_usages = VEC_alloc (unit_usage_t, heap, 10);
5060 for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
5062 seq = REGEXP_ONEOF (regexp)->regexps [i];
5063 switch (seq->mode)
5065 case rm_sequence:
5066 for (j = 0; j < REGEXP_SEQUENCE (seq)->regexps_num; j++)
5068 allof = REGEXP_SEQUENCE (seq)->regexps [j];
5069 switch (allof->mode)
5071 case rm_allof:
5072 for (k = 0; k < REGEXP_ALLOF (allof)->regexps_num; k++)
5074 unit = REGEXP_ALLOF (allof)->regexps [k];
5075 if (unit->mode == rm_unit)
5076 store_alt_unit_usage (regexp, unit, j, i);
5077 else
5078 gcc_assert (unit->mode == rm_nothing);
5080 break;
5082 case rm_unit:
5083 store_alt_unit_usage (regexp, allof, j, i);
5084 break;
5086 case rm_nothing:
5087 break;
5089 default:
5090 gcc_unreachable ();
5093 break;
5095 case rm_allof:
5096 for (k = 0; k < REGEXP_ALLOF (seq)->regexps_num; k++)
5098 unit = REGEXP_ALLOF (seq)->regexps [k];
5099 switch (unit->mode)
5101 case rm_unit:
5102 store_alt_unit_usage (regexp, unit, 0, i);
5103 break;
5105 case rm_nothing:
5106 break;
5108 default:
5109 gcc_unreachable ();
5112 break;
5114 case rm_unit:
5115 store_alt_unit_usage (regexp, seq, 0, i);
5116 break;
5118 case rm_nothing:
5119 break;
5121 default:
5122 gcc_unreachable ();
5125 /* Check distribution: */
5126 for (i = 0; i < (int) VEC_length (unit_usage_t, cycle_alt_unit_usages); i++)
5127 for (unit_usage_ptr = VEC_index (unit_usage_t, cycle_alt_unit_usages, i);
5128 unit_usage_ptr != NULL;
5129 unit_usage_ptr = unit_usage_ptr->next)
5130 unit_usage_ptr->unit_decl->last_distribution_check_cycle = -1;
5131 n_alts = REGEXP_ONEOF (regexp)->regexps_num;
5132 marked = VEC_alloc (int, heap, n_alts);
5133 for (i = 0; i < n_alts; i++)
5134 VEC_safe_push (int, heap, marked, 0);
5135 annotation_reservation_message_reported_p = false;
5136 for (i = 0; i < (int) VEC_length (unit_usage_t, cycle_alt_unit_usages); i++)
5138 cycle = i / n_alts;
5139 start = cycle * n_alts;
5140 for (unit_usage_ptr = VEC_index (unit_usage_t, cycle_alt_unit_usages, i);
5141 unit_usage_ptr != NULL;
5142 unit_usage_ptr = unit_usage_ptr->next)
5144 if (unit_usage_ptr->unit_decl->last_distribution_check_cycle == cycle)
5145 continue;
5146 unit_usage_ptr->unit_decl->last_distribution_check_cycle = cycle;
5147 for (alt = 0; alt < n_alts; alt++)
5148 if (! unit_present_on_list_p (VEC_index (unit_usage_t,
5149 cycle_alt_unit_usages,
5150 start + alt),
5151 unit_usage_ptr->unit_decl))
5152 break;
5153 if (alt >= n_alts)
5154 continue;
5155 memset (VEC_address (int, marked), 0, n_alts * sizeof (int));
5156 for (alt = 0; alt < n_alts; alt++)
5158 if (! unit_present_on_list_p (VEC_index (unit_usage_t,
5159 cycle_alt_unit_usages,
5160 start + alt),
5161 unit_usage_ptr->unit_decl))
5162 continue;
5163 for (j = 0;
5164 j < (int) VEC_length (unit_usage_t, cycle_alt_unit_usages);
5165 j++)
5167 cycle2 = j / n_alts;
5168 alt2 = j % n_alts;
5169 if (! unit_present_on_list_p
5170 (VEC_index (unit_usage_t, cycle_alt_unit_usages,
5171 start + alt2),
5172 unit_usage_ptr->unit_decl)
5173 && equal_alternatives_p (alt, alt2, n_alts,
5174 unit_usage_ptr
5175 ->unit_decl->automaton_decl))
5177 VEC_replace (int, marked, alt, 1);
5178 VEC_replace (int, marked, alt2, 1);
5182 for (alt = 0; alt < n_alts && VEC_index (int, marked, alt); alt++)
5184 if (alt < n_alts && 0)
5186 if (! annotation_message_reported_p)
5188 fprintf (stderr, "\n");
5189 error ("The following units do not satisfy units-automata distribution rule");
5190 error ("(Unit presence on one alt and its absence on other alt\n");
5191 error (" result in different other automata reservations)");
5192 annotation_message_reported_p = TRUE;
5194 if (! annotation_reservation_message_reported_p)
5196 error ("Reserv %s:", insn_reserv_name);
5197 annotation_reservation_message_reported_p = true;
5199 error (" Unit %s, cycle %d, alt %d, another alt %d",
5200 unit_usage_ptr->unit_decl->name, cycle, i % n_alts, alt);
5204 VEC_free (int, heap, marked);
5205 VEC_free (unit_usage_t, heap, cycle_alt_unit_usages);
5206 obstack_free (&unit_usages, NULL);
5209 /* The function finds units which violates units to automata
5210 distribution rule. If the units exist, report about them. */
5211 static void
5212 check_unit_distributions_to_automata (void)
5214 decl_t decl;
5215 int i;
5217 if (progress_flag)
5218 fprintf (stderr, "Check unit distributions to automata...");
5219 automaton_decls = NULL;
5220 for (i = 0; i < description->decls_num; i++)
5222 decl = description->decls [i];
5223 if (decl->mode == dm_automaton)
5224 VEC_safe_push (decl_t, heap, automaton_decls, decl);
5226 if (VEC_length (decl_t, automaton_decls) > 1)
5228 annotation_message_reported_p = FALSE;
5229 for (i = 0; i < description->decls_num; i++)
5231 decl = description->decls [i];
5232 if (decl->mode == dm_insn_reserv)
5233 check_regexp_units_distribution
5234 (DECL_INSN_RESERV (decl)->name,
5235 DECL_INSN_RESERV (decl)->transformed_regexp);
5238 VEC_free (decl_t, heap, automaton_decls);
5239 if (progress_flag)
5240 fprintf (stderr, "done\n");
5245 /* The page contains code for building alt_states (see comments for
5246 IR) describing all possible insns reservations of an automaton. */
5248 /* Current state being formed for which the current alt_state
5249 refers. */
5250 static state_t state_being_formed;
5252 /* Current alt_state being formed. */
5253 static alt_state_t alt_state_being_formed;
5255 /* This recursive function processes `,' and units in reservation
5256 REGEXP for forming alt_states of AUTOMATON. It is believed that
5257 CURR_CYCLE is start cycle of all reservation REGEXP. */
5258 static int
5259 process_seq_for_forming_states (regexp_t regexp, automaton_t automaton,
5260 int curr_cycle)
5262 int i;
5264 if (regexp == NULL)
5265 return curr_cycle;
5267 switch (regexp->mode)
5269 case rm_unit:
5270 if (REGEXP_UNIT (regexp)->unit_decl->corresponding_automaton_num
5271 == automaton->automaton_order_num)
5272 set_state_reserv (state_being_formed, curr_cycle,
5273 REGEXP_UNIT (regexp)->unit_decl->unit_num);
5274 return curr_cycle;
5276 case rm_sequence:
5277 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
5278 curr_cycle
5279 = process_seq_for_forming_states
5280 (REGEXP_SEQUENCE (regexp)->regexps [i], automaton, curr_cycle) + 1;
5281 return curr_cycle;
5283 case rm_allof:
5285 int finish_cycle = 0;
5286 int cycle;
5288 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
5290 cycle = process_seq_for_forming_states (REGEXP_ALLOF (regexp)
5291 ->regexps [i],
5292 automaton, curr_cycle);
5293 if (finish_cycle < cycle)
5294 finish_cycle = cycle;
5296 return finish_cycle;
5299 case rm_nothing:
5300 return curr_cycle;
5302 default:
5303 gcc_unreachable ();
5307 /* This recursive function finishes forming ALT_STATE of AUTOMATON and
5308 inserts alt_state into the table. */
5309 static void
5310 finish_forming_alt_state (alt_state_t alt_state,
5311 automaton_t automaton ATTRIBUTE_UNUSED)
5313 state_t state_in_table;
5314 state_t corresponding_state;
5316 corresponding_state = alt_state->state;
5317 state_in_table = insert_state (corresponding_state);
5318 if (state_in_table != corresponding_state)
5320 free_state (corresponding_state);
5321 alt_state->state = state_in_table;
5325 /* The following variable value is current automaton insn for whose
5326 reservation the alt states are created. */
5327 static ainsn_t curr_ainsn;
5329 /* This recursive function processes `|' in reservation REGEXP for
5330 forming alt_states of AUTOMATON. List of the alt states should
5331 have the same order as in the description. */
5332 static void
5333 process_alts_for_forming_states (regexp_t regexp, automaton_t automaton,
5334 int inside_oneof_p)
5336 int i;
5338 if (regexp->mode != rm_oneof)
5340 alt_state_being_formed = get_free_alt_state ();
5341 state_being_formed = get_free_state (1, automaton);
5342 alt_state_being_formed->state = state_being_formed;
5343 /* We inserts in reverse order but we process alternatives also
5344 in reverse order. So we have the same order of alternative
5345 as in the description. */
5346 alt_state_being_formed->next_alt_state = curr_ainsn->alt_states;
5347 curr_ainsn->alt_states = alt_state_being_formed;
5348 (void) process_seq_for_forming_states (regexp, automaton, 0);
5349 finish_forming_alt_state (alt_state_being_formed, automaton);
5351 else
5353 gcc_assert (!inside_oneof_p);
5354 /* We processes it in reverse order to get list with the same
5355 order as in the description. See also the previous
5356 commentary. */
5357 for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
5358 process_alts_for_forming_states (REGEXP_ONEOF (regexp)->regexps [i],
5359 automaton, 1);
5363 /* Create nodes alt_state for all AUTOMATON insns. */
5364 static void
5365 create_alt_states (automaton_t automaton)
5367 struct insn_reserv_decl *reserv_decl;
5369 for (curr_ainsn = automaton->ainsn_list;
5370 curr_ainsn != NULL;
5371 curr_ainsn = curr_ainsn->next_ainsn)
5373 reserv_decl = curr_ainsn->insn_reserv_decl;
5374 if (reserv_decl != DECL_INSN_RESERV (advance_cycle_insn_decl))
5376 curr_ainsn->alt_states = NULL;
5377 process_alts_for_forming_states (reserv_decl->transformed_regexp,
5378 automaton, 0);
5379 curr_ainsn->sorted_alt_states
5380 = uniq_sort_alt_states (curr_ainsn->alt_states);
5387 /* The page contains major code for building DFA(s) for fast pipeline
5388 hazards recognition. */
5390 /* The function forms list of ainsns of AUTOMATON with the same
5391 reservation. */
5393 static void
5394 form_ainsn_with_same_reservs (automaton_t automaton)
5396 ainsn_t curr_ainsn;
5397 size_t i;
5398 VEC(ainsn_t, heap) *last_insns = VEC_alloc (ainsn_t, heap, 150);
5400 for (curr_ainsn = automaton->ainsn_list;
5401 curr_ainsn != NULL;
5402 curr_ainsn = curr_ainsn->next_ainsn)
5403 if (curr_ainsn->insn_reserv_decl
5404 == DECL_INSN_RESERV (advance_cycle_insn_decl))
5406 curr_ainsn->next_same_reservs_insn = NULL;
5407 curr_ainsn->first_insn_with_same_reservs = 1;
5409 else
5411 for (i = 0; i < VEC_length (ainsn_t, last_insns); i++)
5412 if (alt_states_eq
5413 (curr_ainsn->sorted_alt_states,
5414 VEC_index (ainsn_t, last_insns, i)->sorted_alt_states))
5415 break;
5416 curr_ainsn->next_same_reservs_insn = NULL;
5417 if (i < VEC_length (ainsn_t, last_insns))
5419 curr_ainsn->first_insn_with_same_reservs = 0;
5420 VEC_index (ainsn_t, last_insns, i)->next_same_reservs_insn
5421 = curr_ainsn;
5422 VEC_replace (ainsn_t, last_insns, i, curr_ainsn);
5424 else
5426 VEC_safe_push (ainsn_t, heap, last_insns, curr_ainsn);
5427 curr_ainsn->first_insn_with_same_reservs = 1;
5430 VEC_free (ainsn_t, heap, last_insns);
5433 /* Forming unit reservations which can affect creating the automaton
5434 states achieved from a given state. It permits to build smaller
5435 automata in many cases. We would have the same automata after
5436 the minimization without such optimization, but the automaton
5437 right after the building could be huge. So in other words, usage
5438 of reservs_matter means some minimization during building the
5439 automaton. */
5440 static reserv_sets_t
5441 form_reservs_matter (automaton_t automaton)
5443 int cycle, unit;
5444 reserv_sets_t reservs_matter = alloc_empty_reserv_sets();
5446 for (cycle = 0; cycle < max_cycles_num; cycle++)
5447 for (unit = 0; unit < description->units_num; unit++)
5448 if (units_array [unit]->automaton_decl
5449 == automaton->corresponding_automaton_decl
5450 && (cycle >= units_array [unit]->min_occ_cycle_num
5451 /* We can not remove queried unit from reservations. */
5452 || units_array [unit]->query_p
5453 /* We can not remove units which are used
5454 `exclusion_set', `presence_set',
5455 `final_presence_set', `absence_set', and
5456 `final_absence_set'. */
5457 || units_array [unit]->in_set_p))
5458 set_unit_reserv (reservs_matter, cycle, unit);
5459 return reservs_matter;
5462 /* The following function creates all states of nondeterministic AUTOMATON. */
5463 static void
5464 make_automaton (automaton_t automaton)
5466 ainsn_t ainsn;
5467 struct insn_reserv_decl *insn_reserv_decl;
5468 alt_state_t alt_state;
5469 state_t state;
5470 state_t start_state;
5471 state_t state2;
5472 ainsn_t advance_cycle_ainsn;
5473 arc_t added_arc;
5474 VEC(state_t, heap) *state_stack = VEC_alloc(state_t, heap, 150);
5475 int states_n;
5476 reserv_sets_t reservs_matter = form_reservs_matter (automaton);
5478 /* Create the start state (empty state). */
5479 start_state = insert_state (get_free_state (1, automaton));
5480 automaton->start_state = start_state;
5481 start_state->it_was_placed_in_stack_for_NDFA_forming = 1;
5482 VEC_safe_push (state_t, heap, state_stack, start_state);
5483 states_n = 1;
5484 while (VEC_length (state_t, state_stack) != 0)
5486 state = VEC_pop (state_t, state_stack);
5487 advance_cycle_ainsn = NULL;
5488 for (ainsn = automaton->ainsn_list;
5489 ainsn != NULL;
5490 ainsn = ainsn->next_ainsn)
5491 if (ainsn->first_insn_with_same_reservs)
5493 insn_reserv_decl = ainsn->insn_reserv_decl;
5494 if (insn_reserv_decl != DECL_INSN_RESERV (advance_cycle_insn_decl))
5496 /* We process alt_states in the same order as they are
5497 present in the description. */
5498 added_arc = NULL;
5499 for (alt_state = ainsn->alt_states;
5500 alt_state != NULL;
5501 alt_state = alt_state->next_alt_state)
5503 state2 = alt_state->state;
5504 if (!intersected_state_reservs_p (state, state2))
5506 state2 = states_union (state, state2, reservs_matter);
5507 if (!state2->it_was_placed_in_stack_for_NDFA_forming)
5509 state2->it_was_placed_in_stack_for_NDFA_forming
5510 = 1;
5511 VEC_safe_push (state_t, heap, state_stack, state2);
5512 states_n++;
5513 if (progress_flag && states_n % 100 == 0)
5514 fprintf (stderr, ".");
5516 added_arc = add_arc (state, state2, ainsn);
5517 if (!ndfa_flag)
5518 break;
5521 if (!ndfa_flag && added_arc != NULL)
5523 for (alt_state = ainsn->alt_states;
5524 alt_state != NULL;
5525 alt_state = alt_state->next_alt_state)
5526 state2 = alt_state->state;
5529 else
5530 advance_cycle_ainsn = ainsn;
5532 /* Add transition to advance cycle. */
5533 state2 = state_shift (state, reservs_matter);
5534 if (!state2->it_was_placed_in_stack_for_NDFA_forming)
5536 state2->it_was_placed_in_stack_for_NDFA_forming = 1;
5537 VEC_safe_push (state_t, heap, state_stack, state2);
5538 states_n++;
5539 if (progress_flag && states_n % 100 == 0)
5540 fprintf (stderr, ".");
5542 gcc_assert (advance_cycle_ainsn);
5543 add_arc (state, state2, advance_cycle_ainsn);
5545 VEC_free (state_t, heap, state_stack);
5548 /* Form lists of all arcs of STATE marked by the same ainsn. */
5549 static void
5550 form_arcs_marked_by_insn (state_t state)
5552 decl_t decl;
5553 arc_t arc;
5554 int i;
5556 for (i = 0; i < description->decls_num; i++)
5558 decl = description->decls [i];
5559 if (decl->mode == dm_insn_reserv)
5560 DECL_INSN_RESERV (decl)->arcs_marked_by_insn = NULL;
5562 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5564 gcc_assert (arc->insn);
5565 arc->next_arc_marked_by_insn
5566 = arc->insn->insn_reserv_decl->arcs_marked_by_insn;
5567 arc->insn->insn_reserv_decl->arcs_marked_by_insn = arc;
5571 /* The function creates composed state (see comments for IR) from
5572 ORIGINAL_STATE and list of arcs ARCS_MARKED_BY_INSN marked by the
5573 same insn. If the composed state is not in STATE_STACK yet, it is
5574 pushed into STATE_STACK. */
5576 static int
5577 create_composed_state (state_t original_state, arc_t arcs_marked_by_insn,
5578 VEC(state_t, heap) **state_stack)
5580 state_t state;
5581 alt_state_t alt_state, curr_alt_state;
5582 alt_state_t new_alt_state;
5583 arc_t curr_arc;
5584 arc_t next_arc;
5585 state_t state_in_table;
5586 state_t temp_state;
5587 alt_state_t canonical_alt_states_list;
5588 int alts_number;
5589 int new_state_p = 0;
5591 if (arcs_marked_by_insn == NULL)
5592 return new_state_p;
5593 if (arcs_marked_by_insn->next_arc_marked_by_insn == NULL)
5594 state = arcs_marked_by_insn->to_state;
5595 else
5597 gcc_assert (ndfa_flag);
5598 /* Create composed state. */
5599 state = get_free_state (0, arcs_marked_by_insn->to_state->automaton);
5600 curr_alt_state = NULL;
5601 for (curr_arc = arcs_marked_by_insn;
5602 curr_arc != NULL;
5603 curr_arc = curr_arc->next_arc_marked_by_insn)
5604 if (curr_arc->to_state->component_states == NULL)
5606 new_alt_state = get_free_alt_state ();
5607 new_alt_state->next_alt_state = curr_alt_state;
5608 new_alt_state->state = curr_arc->to_state;
5609 curr_alt_state = new_alt_state;
5611 else
5612 for (alt_state = curr_arc->to_state->component_states;
5613 alt_state != NULL;
5614 alt_state = alt_state->next_sorted_alt_state)
5616 new_alt_state = get_free_alt_state ();
5617 new_alt_state->next_alt_state = curr_alt_state;
5618 new_alt_state->state = alt_state->state;
5619 gcc_assert (!alt_state->state->component_states);
5620 curr_alt_state = new_alt_state;
5622 /* There are not identical sets in the alt state list. */
5623 canonical_alt_states_list = uniq_sort_alt_states (curr_alt_state);
5624 if (canonical_alt_states_list->next_sorted_alt_state == NULL)
5626 temp_state = state;
5627 state = canonical_alt_states_list->state;
5628 free_state (temp_state);
5630 else
5632 state->component_states = canonical_alt_states_list;
5633 state_in_table = insert_state (state);
5634 if (state_in_table != state)
5636 gcc_assert
5637 (state_in_table->it_was_placed_in_stack_for_DFA_forming);
5638 free_state (state);
5639 state = state_in_table;
5641 else
5643 gcc_assert (!state->it_was_placed_in_stack_for_DFA_forming);
5644 new_state_p = 1;
5645 for (curr_alt_state = state->component_states;
5646 curr_alt_state != NULL;
5647 curr_alt_state = curr_alt_state->next_sorted_alt_state)
5648 for (curr_arc = first_out_arc (curr_alt_state->state);
5649 curr_arc != NULL;
5650 curr_arc = next_out_arc (curr_arc))
5651 add_arc (state, curr_arc->to_state, curr_arc->insn);
5653 arcs_marked_by_insn->to_state = state;
5654 for (alts_number = 0,
5655 curr_arc = arcs_marked_by_insn->next_arc_marked_by_insn;
5656 curr_arc != NULL;
5657 curr_arc = next_arc)
5659 next_arc = curr_arc->next_arc_marked_by_insn;
5660 remove_arc (original_state, curr_arc);
5661 alts_number++;
5665 if (!state->it_was_placed_in_stack_for_DFA_forming)
5667 state->it_was_placed_in_stack_for_DFA_forming = 1;
5668 VEC_safe_push (state_t, heap, *state_stack, state);
5670 return new_state_p;
5673 /* The function transforms nondeterministic AUTOMATON into
5674 deterministic. */
5676 static void
5677 NDFA_to_DFA (automaton_t automaton)
5679 state_t start_state;
5680 state_t state;
5681 decl_t decl;
5682 VEC(state_t, heap) *state_stack;
5683 int i;
5684 int states_n;
5686 state_stack = VEC_alloc (state_t, heap, 0);
5688 /* Create the start state (empty state). */
5689 start_state = automaton->start_state;
5690 start_state->it_was_placed_in_stack_for_DFA_forming = 1;
5691 VEC_safe_push (state_t, heap, state_stack, start_state);
5692 states_n = 1;
5693 while (VEC_length (state_t, state_stack) != 0)
5695 state = VEC_pop (state_t, state_stack);
5696 form_arcs_marked_by_insn (state);
5697 for (i = 0; i < description->decls_num; i++)
5699 decl = description->decls [i];
5700 if (decl->mode == dm_insn_reserv
5701 && create_composed_state
5702 (state, DECL_INSN_RESERV (decl)->arcs_marked_by_insn,
5703 &state_stack))
5705 states_n++;
5706 if (progress_flag && states_n % 100 == 0)
5707 fprintf (stderr, ".");
5711 VEC_free (state_t, heap, state_stack);
5714 /* The following variable value is current number (1, 2, ...) of passing
5715 graph of states. */
5716 static int curr_state_graph_pass_num;
5718 /* This recursive function passes all states achieved from START_STATE
5719 and applies APPLIED_FUNC to them. */
5720 static void
5721 pass_state_graph (state_t start_state, void (*applied_func) (state_t state))
5723 arc_t arc;
5725 if (start_state->pass_num == curr_state_graph_pass_num)
5726 return;
5727 start_state->pass_num = curr_state_graph_pass_num;
5728 (*applied_func) (start_state);
5729 for (arc = first_out_arc (start_state);
5730 arc != NULL;
5731 arc = next_out_arc (arc))
5732 pass_state_graph (arc->to_state, applied_func);
5735 /* This recursive function passes all states of AUTOMATON and applies
5736 APPLIED_FUNC to them. */
5737 static void
5738 pass_states (automaton_t automaton, void (*applied_func) (state_t state))
5740 curr_state_graph_pass_num++;
5741 pass_state_graph (automaton->start_state, applied_func);
5744 /* The function initializes code for passing of all states. */
5745 static void
5746 initiate_pass_states (void)
5748 curr_state_graph_pass_num = 0;
5751 /* The following vla is used for storing pointers to all achieved
5752 states. */
5753 static VEC(state_t, heap) *all_achieved_states;
5755 /* This function is called by function pass_states to add an achieved
5756 STATE. */
5757 static void
5758 add_achieved_state (state_t state)
5760 VEC_safe_push (state_t, heap, all_achieved_states, state);
5763 /* The function sets up equivalence numbers of insns which mark all
5764 out arcs of STATE by equiv_class_num_1 (if ODD_ITERATION_FLAG has
5765 nonzero value) or by equiv_class_num_2 of the destination state.
5766 The function returns number of out arcs of STATE. */
5767 static void
5768 set_out_arc_insns_equiv_num (state_t state, int odd_iteration_flag)
5770 arc_t arc;
5772 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5774 gcc_assert (!arc->insn->insn_reserv_decl->equiv_class_num);
5775 arc->insn->insn_reserv_decl->equiv_class_num
5776 = (odd_iteration_flag
5777 ? arc->to_state->equiv_class_num_1
5778 : arc->to_state->equiv_class_num_2);
5779 gcc_assert (arc->insn->insn_reserv_decl->equiv_class_num);
5783 /* The function clears equivalence numbers and alt_states in all insns
5784 which mark all out arcs of STATE. */
5785 static void
5786 clear_arc_insns_equiv_num (state_t state)
5788 arc_t arc;
5790 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5791 arc->insn->insn_reserv_decl->equiv_class_num = 0;
5795 /* The following function returns TRUE if STATE reserves the unit with
5796 UNIT_NUM on the first cycle. */
5797 static int
5798 first_cycle_unit_presence (state_t state, int unit_num)
5800 alt_state_t alt_state;
5802 if (state->component_states == NULL)
5803 return test_unit_reserv (state->reservs, 0, unit_num);
5804 else
5806 for (alt_state = state->component_states;
5807 alt_state != NULL;
5808 alt_state = alt_state->next_sorted_alt_state)
5809 if (test_unit_reserv (alt_state->state->reservs, 0, unit_num))
5810 return true;
5812 return false;
5815 /* This fills in the presence_signature[] member of STATE. */
5816 static void
5817 cache_presence (state_t state)
5819 int i, num = 0;
5820 unsigned int sz;
5821 sz = (description->query_units_num + sizeof (int) * CHAR_BIT - 1)
5822 / (sizeof (int) * CHAR_BIT);
5824 state->presence_signature = XCREATENODEVEC (unsigned int, sz);
5825 for (i = 0; i < description->units_num; i++)
5826 if (units_array [i]->query_p)
5828 int presence1_p = first_cycle_unit_presence (state, i);
5829 state->presence_signature[num / (sizeof (int) * CHAR_BIT)]
5830 |= (!!presence1_p) << (num % (sizeof (int) * CHAR_BIT));
5831 num++;
5835 /* The function returns nonzero value if STATE is not equivalent to
5836 ANOTHER_STATE from the same current partition on equivalence
5837 classes. Another state has ANOTHER_STATE_OUT_ARCS_NUM number of
5838 output arcs. Iteration of making equivalence partition is defined
5839 by ODD_ITERATION_FLAG. */
5840 static int
5841 state_is_differed (state_t state, state_t another_state,
5842 int odd_iteration_flag)
5844 arc_t arc;
5845 unsigned int sz, si;
5847 gcc_assert (state->num_out_arcs == another_state->num_out_arcs);
5849 sz = (description->query_units_num + sizeof (int) * CHAR_BIT - 1)
5850 / (sizeof (int) * CHAR_BIT);
5852 for (si = 0; si < sz; si++)
5853 gcc_assert (state->presence_signature[si]
5854 == another_state->presence_signature[si]);
5856 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5858 if ((odd_iteration_flag
5859 ? arc->to_state->equiv_class_num_1
5860 : arc->to_state->equiv_class_num_2)
5861 != arc->insn->insn_reserv_decl->equiv_class_num)
5862 return 1;
5865 return 0;
5868 /* Compares two states pointed to by STATE_PTR_1 and STATE_PTR_2
5869 and return -1, 0 or 1. This function can be used as predicate for
5870 qsort(). It requires the member presence_signature[] of both
5871 states be filled. */
5872 static int
5873 compare_states_for_equiv (const void *state_ptr_1,
5874 const void *state_ptr_2)
5876 const_state_t const s1 = *(const_state_t const*)state_ptr_1;
5877 const_state_t const s2 = *(const_state_t const*)state_ptr_2;
5878 unsigned int sz, si;
5879 if (s1->num_out_arcs < s2->num_out_arcs)
5880 return -1;
5881 else if (s1->num_out_arcs > s2->num_out_arcs)
5882 return 1;
5884 sz = (description->query_units_num + sizeof (int) * CHAR_BIT - 1)
5885 / (sizeof (int) * CHAR_BIT);
5887 for (si = 0; si < sz; si++)
5888 if (s1->presence_signature[si] < s2->presence_signature[si])
5889 return -1;
5890 else if (s1->presence_signature[si] > s2->presence_signature[si])
5891 return 1;
5892 return 0;
5895 /* The function makes initial partition of STATES on equivalent
5896 classes and saves it into *CLASSES. This function requires the input
5897 to be sorted via compare_states_for_equiv(). */
5898 static int
5899 init_equiv_class (VEC(state_t, heap) *states, VEC (state_t, heap) **classes)
5901 size_t i;
5902 state_t prev = 0;
5903 int class_num = 1;
5905 *classes = VEC_alloc (state_t, heap, 150);
5906 for (i = 0; i < VEC_length (state_t, states); i++)
5908 state_t state = VEC_index (state_t, states, i);
5909 if (prev)
5911 if (compare_states_for_equiv (&prev, &state) != 0)
5913 VEC_safe_push (state_t, heap, *classes, prev);
5914 class_num++;
5915 prev = NULL;
5918 state->equiv_class_num_1 = class_num;
5919 state->next_equiv_class_state = prev;
5920 prev = state;
5922 if (prev)
5923 VEC_safe_push (state_t, heap, *classes, prev);
5924 return class_num;
5927 /* The function copies pointers to equivalent states from vla FROM
5928 into vla TO. */
5929 static void
5930 copy_equiv_class (VEC(state_t, heap) **to, VEC(state_t, heap) *from)
5932 VEC_free (state_t, heap, *to);
5933 *to = VEC_copy (state_t, heap, from);
5936 /* The function processes equivalence class given by its first state,
5937 FIRST_STATE, on odd iteration if ODD_ITERATION_FLAG. If there
5938 are not equivalent states, the function partitions the class
5939 removing nonequivalent states and placing them in
5940 *NEXT_ITERATION_CLASSES, increments *NEW_EQUIV_CLASS_NUM_PTR ans
5941 assigns it to the state equivalence number. If the class has been
5942 partitioned, the function returns nonzero value. */
5943 static int
5944 partition_equiv_class (state_t first_state, int odd_iteration_flag,
5945 VEC(state_t, heap) **next_iteration_classes,
5946 int *new_equiv_class_num_ptr)
5948 state_t new_equiv_class;
5949 int partition_p;
5950 state_t curr_state;
5951 state_t prev_state;
5952 state_t next_state;
5954 partition_p = 0;
5956 while (first_state != NULL)
5958 new_equiv_class = NULL;
5959 if (first_state->next_equiv_class_state != NULL)
5961 /* There are more one states in the class equivalence. */
5962 set_out_arc_insns_equiv_num (first_state, odd_iteration_flag);
5963 for (prev_state = first_state,
5964 curr_state = first_state->next_equiv_class_state;
5965 curr_state != NULL;
5966 curr_state = next_state)
5968 next_state = curr_state->next_equiv_class_state;
5969 if (state_is_differed (curr_state, first_state,
5970 odd_iteration_flag))
5972 /* Remove curr state from the class equivalence. */
5973 prev_state->next_equiv_class_state = next_state;
5974 /* Add curr state to the new class equivalence. */
5975 curr_state->next_equiv_class_state = new_equiv_class;
5976 if (new_equiv_class == NULL)
5977 (*new_equiv_class_num_ptr)++;
5978 if (odd_iteration_flag)
5979 curr_state->equiv_class_num_2 = *new_equiv_class_num_ptr;
5980 else
5981 curr_state->equiv_class_num_1 = *new_equiv_class_num_ptr;
5982 new_equiv_class = curr_state;
5983 partition_p = 1;
5985 else
5986 prev_state = curr_state;
5988 clear_arc_insns_equiv_num (first_state);
5990 if (new_equiv_class != NULL)
5991 VEC_safe_push (state_t, heap, *next_iteration_classes, new_equiv_class);
5992 first_state = new_equiv_class;
5994 return partition_p;
5997 /* The function finds equivalent states of AUTOMATON. */
5998 static void
5999 evaluate_equiv_classes (automaton_t automaton,
6000 VEC(state_t, heap) **equiv_classes)
6002 int new_equiv_class_num;
6003 int odd_iteration_flag;
6004 int finish_flag;
6005 VEC (state_t, heap) *next_iteration_classes;
6006 size_t i;
6008 all_achieved_states = VEC_alloc (state_t, heap, 1500);
6009 pass_states (automaton, add_achieved_state);
6010 pass_states (automaton, cache_presence);
6011 qsort (VEC_address (state_t, all_achieved_states),
6012 VEC_length (state_t, all_achieved_states),
6013 sizeof (state_t), compare_states_for_equiv);
6015 odd_iteration_flag = 0;
6016 new_equiv_class_num = init_equiv_class (all_achieved_states,
6017 &next_iteration_classes);
6021 odd_iteration_flag = !odd_iteration_flag;
6022 finish_flag = 1;
6023 copy_equiv_class (equiv_classes, next_iteration_classes);
6025 /* Transfer equiv numbers for the next iteration. */
6026 for (i = 0; i < VEC_length (state_t, all_achieved_states); i++)
6027 if (odd_iteration_flag)
6028 VEC_index (state_t, all_achieved_states, i)->equiv_class_num_2
6029 = VEC_index (state_t, all_achieved_states, i)->equiv_class_num_1;
6030 else
6031 VEC_index (state_t, all_achieved_states, i)->equiv_class_num_1
6032 = VEC_index (state_t, all_achieved_states, i)->equiv_class_num_2;
6034 for (i = 0; i < VEC_length (state_t, *equiv_classes); i++)
6035 if (partition_equiv_class (VEC_index (state_t, *equiv_classes, i),
6036 odd_iteration_flag,
6037 &next_iteration_classes,
6038 &new_equiv_class_num))
6039 finish_flag = 0;
6041 while (!finish_flag);
6042 VEC_free (state_t, heap, next_iteration_classes);
6043 VEC_free (state_t, heap, all_achieved_states);
6046 /* The function merges equivalent states of AUTOMATON. */
6047 static void
6048 merge_states (automaton_t automaton, VEC(state_t, heap) *equiv_classes)
6050 state_t curr_state;
6051 state_t new_state;
6052 state_t first_class_state;
6053 alt_state_t alt_states;
6054 alt_state_t alt_state, new_alt_state;
6055 arc_t curr_arc;
6056 arc_t next_arc;
6057 size_t i;
6059 /* Create states corresponding to equivalence classes containing two
6060 or more states. */
6061 for (i = 0; i < VEC_length (state_t, equiv_classes); i++)
6063 curr_state = VEC_index (state_t, equiv_classes, i);
6064 if (curr_state->next_equiv_class_state != NULL)
6066 /* There are more one states in the class equivalence. */
6067 /* Create new compound state. */
6068 new_state = get_free_state (0, automaton);
6069 alt_states = NULL;
6070 first_class_state = curr_state;
6071 for (curr_state = first_class_state;
6072 curr_state != NULL;
6073 curr_state = curr_state->next_equiv_class_state)
6075 curr_state->equiv_class_state = new_state;
6076 if (curr_state->component_states == NULL)
6078 new_alt_state = get_free_alt_state ();
6079 new_alt_state->state = curr_state;
6080 new_alt_state->next_alt_state = alt_states;
6081 alt_states = new_alt_state;
6083 else
6084 for (alt_state = curr_state->component_states;
6085 alt_state != NULL;
6086 alt_state = alt_state->next_sorted_alt_state)
6088 new_alt_state = get_free_alt_state ();
6089 new_alt_state->state = alt_state->state;
6090 new_alt_state->next_alt_state = alt_states;
6091 alt_states = new_alt_state;
6094 /* Its is important that alt states were sorted before and
6095 after merging to have the same querying results. */
6096 new_state->component_states = uniq_sort_alt_states (alt_states);
6098 else
6099 curr_state->equiv_class_state = curr_state;
6102 for (i = 0; i < VEC_length (state_t, equiv_classes); i++)
6104 curr_state = VEC_index (state_t, equiv_classes, i);
6105 if (curr_state->next_equiv_class_state != NULL)
6107 first_class_state = curr_state;
6108 /* Create new arcs output from the state corresponding to
6109 equiv class. */
6110 for (curr_arc = first_out_arc (first_class_state);
6111 curr_arc != NULL;
6112 curr_arc = next_out_arc (curr_arc))
6113 add_arc (first_class_state->equiv_class_state,
6114 curr_arc->to_state->equiv_class_state,
6115 curr_arc->insn);
6116 /* Delete output arcs from states of given class equivalence. */
6117 for (curr_state = first_class_state;
6118 curr_state != NULL;
6119 curr_state = curr_state->next_equiv_class_state)
6121 if (automaton->start_state == curr_state)
6122 automaton->start_state = curr_state->equiv_class_state;
6123 /* Delete the state and its output arcs. */
6124 for (curr_arc = first_out_arc (curr_state);
6125 curr_arc != NULL;
6126 curr_arc = next_arc)
6128 next_arc = next_out_arc (curr_arc);
6129 free_arc (curr_arc);
6133 else
6135 /* Change `to_state' of arcs output from the state of given
6136 equivalence class. */
6137 for (curr_arc = first_out_arc (curr_state);
6138 curr_arc != NULL;
6139 curr_arc = next_out_arc (curr_arc))
6140 curr_arc->to_state = curr_arc->to_state->equiv_class_state;
6145 /* The function sets up new_cycle_p for states if there is arc to the
6146 state marked by advance_cycle_insn_decl. */
6147 static void
6148 set_new_cycle_flags (state_t state)
6150 arc_t arc;
6152 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6153 if (arc->insn->insn_reserv_decl
6154 == DECL_INSN_RESERV (advance_cycle_insn_decl))
6155 arc->to_state->new_cycle_p = 1;
6158 /* The top level function for minimization of deterministic
6159 AUTOMATON. */
6160 static void
6161 minimize_DFA (automaton_t automaton)
6163 VEC(state_t, heap) *equiv_classes = 0;
6165 evaluate_equiv_classes (automaton, &equiv_classes);
6166 merge_states (automaton, equiv_classes);
6167 pass_states (automaton, set_new_cycle_flags);
6169 VEC_free (state_t, heap, equiv_classes);
6172 /* Values of two variables are counted number of states and arcs in an
6173 automaton. */
6174 static int curr_counted_states_num;
6175 static int curr_counted_arcs_num;
6177 /* The function is called by function `pass_states' to count states
6178 and arcs of an automaton. */
6179 static void
6180 incr_states_and_arcs_nums (state_t state)
6182 arc_t arc;
6184 curr_counted_states_num++;
6185 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6186 curr_counted_arcs_num++;
6189 /* The function counts states and arcs of AUTOMATON. */
6190 static void
6191 count_states_and_arcs (automaton_t automaton, int *states_num,
6192 int *arcs_num)
6194 curr_counted_states_num = 0;
6195 curr_counted_arcs_num = 0;
6196 pass_states (automaton, incr_states_and_arcs_nums);
6197 *states_num = curr_counted_states_num;
6198 *arcs_num = curr_counted_arcs_num;
6201 /* The function builds one DFA AUTOMATON for fast pipeline hazards
6202 recognition after checking and simplifying IR of the
6203 description. */
6204 static void
6205 build_automaton (automaton_t automaton)
6207 int states_num;
6208 int arcs_num;
6210 ticker_on (&NDFA_time);
6211 if (progress_flag)
6213 if (automaton->corresponding_automaton_decl == NULL)
6214 fprintf (stderr, "Create anonymous automaton");
6215 else
6216 fprintf (stderr, "Create automaton `%s'",
6217 automaton->corresponding_automaton_decl->name);
6218 fprintf (stderr, " (1 dot is 100 new states):");
6220 make_automaton (automaton);
6221 if (progress_flag)
6222 fprintf (stderr, " done\n");
6223 ticker_off (&NDFA_time);
6224 count_states_and_arcs (automaton, &states_num, &arcs_num);
6225 automaton->NDFA_states_num = states_num;
6226 automaton->NDFA_arcs_num = arcs_num;
6227 ticker_on (&NDFA_to_DFA_time);
6228 if (progress_flag)
6230 if (automaton->corresponding_automaton_decl == NULL)
6231 fprintf (stderr, "Make anonymous DFA");
6232 else
6233 fprintf (stderr, "Make DFA `%s'",
6234 automaton->corresponding_automaton_decl->name);
6235 fprintf (stderr, " (1 dot is 100 new states):");
6237 NDFA_to_DFA (automaton);
6238 if (progress_flag)
6239 fprintf (stderr, " done\n");
6240 ticker_off (&NDFA_to_DFA_time);
6241 count_states_and_arcs (automaton, &states_num, &arcs_num);
6242 automaton->DFA_states_num = states_num;
6243 automaton->DFA_arcs_num = arcs_num;
6244 if (!no_minimization_flag)
6246 ticker_on (&minimize_time);
6247 if (progress_flag)
6249 if (automaton->corresponding_automaton_decl == NULL)
6250 fprintf (stderr, "Minimize anonymous DFA...");
6251 else
6252 fprintf (stderr, "Minimize DFA `%s'...",
6253 automaton->corresponding_automaton_decl->name);
6255 minimize_DFA (automaton);
6256 if (progress_flag)
6257 fprintf (stderr, "done\n");
6258 ticker_off (&minimize_time);
6259 count_states_and_arcs (automaton, &states_num, &arcs_num);
6260 automaton->minimal_DFA_states_num = states_num;
6261 automaton->minimal_DFA_arcs_num = arcs_num;
6267 /* The page contains code for enumeration of all states of an automaton. */
6269 /* Variable used for enumeration of all states of an automaton. Its
6270 value is current number of automaton states. */
6271 static int curr_state_order_num;
6273 /* The function is called by function `pass_states' for enumerating
6274 states. */
6275 static void
6276 set_order_state_num (state_t state)
6278 state->order_state_num = curr_state_order_num;
6279 curr_state_order_num++;
6282 /* The function enumerates all states of AUTOMATON. */
6283 static void
6284 enumerate_states (automaton_t automaton)
6286 curr_state_order_num = 0;
6287 pass_states (automaton, set_order_state_num);
6288 automaton->achieved_states_num = curr_state_order_num;
6293 /* The page contains code for finding equivalent automaton insns
6294 (ainsns). */
6296 /* The function inserts AINSN into cyclic list
6297 CYCLIC_EQUIV_CLASS_INSN_LIST of ainsns. */
6298 static ainsn_t
6299 insert_ainsn_into_equiv_class (ainsn_t ainsn,
6300 ainsn_t cyclic_equiv_class_insn_list)
6302 if (cyclic_equiv_class_insn_list == NULL)
6303 ainsn->next_equiv_class_insn = ainsn;
6304 else
6306 ainsn->next_equiv_class_insn
6307 = cyclic_equiv_class_insn_list->next_equiv_class_insn;
6308 cyclic_equiv_class_insn_list->next_equiv_class_insn = ainsn;
6310 return ainsn;
6313 /* The function deletes equiv_class_insn into cyclic list of
6314 equivalent ainsns. */
6315 static void
6316 delete_ainsn_from_equiv_class (ainsn_t equiv_class_insn)
6318 ainsn_t curr_equiv_class_insn;
6319 ainsn_t prev_equiv_class_insn;
6321 prev_equiv_class_insn = equiv_class_insn;
6322 for (curr_equiv_class_insn = equiv_class_insn->next_equiv_class_insn;
6323 curr_equiv_class_insn != equiv_class_insn;
6324 curr_equiv_class_insn = curr_equiv_class_insn->next_equiv_class_insn)
6325 prev_equiv_class_insn = curr_equiv_class_insn;
6326 if (prev_equiv_class_insn != equiv_class_insn)
6327 prev_equiv_class_insn->next_equiv_class_insn
6328 = equiv_class_insn->next_equiv_class_insn;
6331 /* The function processes AINSN of a state in order to find equivalent
6332 ainsns. INSN_ARCS_ARRAY is table: code of insn -> out arc of the
6333 state. */
6334 static void
6335 process_insn_equiv_class (ainsn_t ainsn, arc_t *insn_arcs_array)
6337 ainsn_t next_insn;
6338 ainsn_t curr_insn;
6339 ainsn_t cyclic_insn_list;
6340 arc_t arc;
6342 gcc_assert (insn_arcs_array [ainsn->insn_reserv_decl->insn_num]);
6343 curr_insn = ainsn;
6344 /* New class of ainsns which are not equivalent to given ainsn. */
6345 cyclic_insn_list = NULL;
6348 next_insn = curr_insn->next_equiv_class_insn;
6349 arc = insn_arcs_array [curr_insn->insn_reserv_decl->insn_num];
6350 if (arc == NULL
6351 || (insn_arcs_array [ainsn->insn_reserv_decl->insn_num]->to_state
6352 != arc->to_state))
6354 delete_ainsn_from_equiv_class (curr_insn);
6355 cyclic_insn_list = insert_ainsn_into_equiv_class (curr_insn,
6356 cyclic_insn_list);
6358 curr_insn = next_insn;
6360 while (curr_insn != ainsn);
6363 /* The function processes STATE in order to find equivalent ainsns. */
6364 static void
6365 process_state_for_insn_equiv_partition (state_t state)
6367 arc_t arc;
6368 arc_t *insn_arcs_array = XCNEWVEC (arc_t, description->insns_num);
6370 /* Process insns of the arcs. */
6371 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6372 insn_arcs_array [arc->insn->insn_reserv_decl->insn_num] = arc;
6373 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6374 process_insn_equiv_class (arc->insn, insn_arcs_array);
6376 free (insn_arcs_array);
6379 /* The function searches for equivalent ainsns of AUTOMATON. */
6380 static void
6381 set_insn_equiv_classes (automaton_t automaton)
6383 ainsn_t ainsn;
6384 ainsn_t first_insn;
6385 ainsn_t curr_insn;
6386 ainsn_t cyclic_insn_list;
6387 ainsn_t insn_with_same_reservs;
6388 int equiv_classes_num;
6390 /* All insns are included in one equivalence class. */
6391 cyclic_insn_list = NULL;
6392 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6393 if (ainsn->first_insn_with_same_reservs)
6394 cyclic_insn_list = insert_ainsn_into_equiv_class (ainsn,
6395 cyclic_insn_list);
6396 /* Process insns in order to make equivalence partition. */
6397 pass_states (automaton, process_state_for_insn_equiv_partition);
6398 /* Enumerate equiv classes. */
6399 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6400 /* Set undefined value. */
6401 ainsn->insn_equiv_class_num = -1;
6402 equiv_classes_num = 0;
6403 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6404 if (ainsn->insn_equiv_class_num < 0)
6406 first_insn = ainsn;
6407 gcc_assert (first_insn->first_insn_with_same_reservs);
6408 first_insn->first_ainsn_with_given_equivalence_num = 1;
6409 curr_insn = first_insn;
6412 for (insn_with_same_reservs = curr_insn;
6413 insn_with_same_reservs != NULL;
6414 insn_with_same_reservs
6415 = insn_with_same_reservs->next_same_reservs_insn)
6416 insn_with_same_reservs->insn_equiv_class_num = equiv_classes_num;
6417 curr_insn = curr_insn->next_equiv_class_insn;
6419 while (curr_insn != first_insn);
6420 equiv_classes_num++;
6422 automaton->insn_equiv_classes_num = equiv_classes_num;
6427 /* This page contains code for creating DFA(s) and calls functions
6428 building them. */
6431 /* The following value is used to prevent floating point overflow for
6432 estimating an automaton bound. The value should be less DBL_MAX on
6433 the host machine. We use here approximate minimum of maximal
6434 double floating point value required by ANSI C standard. It
6435 will work for non ANSI sun compiler too. */
6437 #define MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND 1.0E37
6439 /* The function estimate size of the single DFA used by PHR (pipeline
6440 hazards recognizer). */
6441 static double
6442 estimate_one_automaton_bound (void)
6444 decl_t decl;
6445 double one_automaton_estimation_bound;
6446 double root_value;
6447 int i;
6449 one_automaton_estimation_bound = 1.0;
6450 for (i = 0; i < description->decls_num; i++)
6452 decl = description->decls [i];
6453 if (decl->mode == dm_unit)
6455 root_value = exp (log (DECL_UNIT (decl)->max_occ_cycle_num
6456 - DECL_UNIT (decl)->min_occ_cycle_num + 1.0)
6457 / automata_num);
6458 if (MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND / root_value
6459 > one_automaton_estimation_bound)
6460 one_automaton_estimation_bound *= root_value;
6463 return one_automaton_estimation_bound;
6466 /* The function compares unit declarations according to their maximal
6467 cycle in reservations. */
6468 static int
6469 compare_max_occ_cycle_nums (const void *unit_decl_1,
6470 const void *unit_decl_2)
6472 if ((DECL_UNIT (*(const_decl_t const*) unit_decl_1)->max_occ_cycle_num)
6473 < (DECL_UNIT (*(const_decl_t const*) unit_decl_2)->max_occ_cycle_num))
6474 return 1;
6475 else if ((DECL_UNIT (*(const_decl_t const*) unit_decl_1)->max_occ_cycle_num)
6476 == (DECL_UNIT (*(const_decl_t const*) unit_decl_2)->max_occ_cycle_num))
6477 return 0;
6478 else
6479 return -1;
6482 /* The function makes heuristic assigning automata to units. Actually
6483 efficacy of the algorithm has been checked yet??? */
6485 static void
6486 units_to_automata_heuristic_distr (void)
6488 double estimation_bound;
6489 int automaton_num;
6490 int rest_units_num;
6491 double bound_value;
6492 unit_decl_t *unit_decls;
6493 int i, j;
6495 if (description->units_num == 0)
6496 return;
6497 estimation_bound = estimate_one_automaton_bound ();
6498 unit_decls = XNEWVEC (unit_decl_t, description->units_num);
6500 for (i = 0, j = 0; i < description->decls_num; i++)
6501 if (description->decls[i]->mode == dm_unit)
6502 unit_decls[j++] = DECL_UNIT (description->decls[i]);
6503 gcc_assert (j == description->units_num);
6505 qsort (unit_decls, description->units_num,
6506 sizeof (unit_decl_t), compare_max_occ_cycle_nums);
6508 automaton_num = 0;
6509 bound_value = unit_decls[0]->max_occ_cycle_num;
6510 unit_decls[0]->corresponding_automaton_num = automaton_num;
6512 for (i = 1; i < description->units_num; i++)
6514 rest_units_num = description->units_num - i + 1;
6515 gcc_assert (automata_num - automaton_num - 1 <= rest_units_num);
6516 if (automaton_num < automata_num - 1
6517 && ((automata_num - automaton_num - 1 == rest_units_num)
6518 || (bound_value
6519 > (estimation_bound
6520 / unit_decls[i]->max_occ_cycle_num))))
6522 bound_value = unit_decls[i]->max_occ_cycle_num;
6523 automaton_num++;
6525 else
6526 bound_value *= unit_decls[i]->max_occ_cycle_num;
6527 unit_decls[i]->corresponding_automaton_num = automaton_num;
6529 gcc_assert (automaton_num == automata_num - 1);
6530 free (unit_decls);
6533 /* The functions creates automaton insns for each automata. Automaton
6534 insn is simply insn for given automaton which makes reservation
6535 only of units of the automaton. */
6536 static ainsn_t
6537 create_ainsns (void)
6539 decl_t decl;
6540 ainsn_t first_ainsn;
6541 ainsn_t curr_ainsn;
6542 ainsn_t prev_ainsn;
6543 int i;
6545 first_ainsn = NULL;
6546 prev_ainsn = NULL;
6547 for (i = 0; i < description->decls_num; i++)
6549 decl = description->decls [i];
6550 if (decl->mode == dm_insn_reserv)
6552 curr_ainsn = XCREATENODE (struct ainsn);
6553 curr_ainsn->insn_reserv_decl = DECL_INSN_RESERV (decl);
6554 curr_ainsn->important_p = FALSE;
6555 curr_ainsn->next_ainsn = NULL;
6556 if (prev_ainsn == NULL)
6557 first_ainsn = curr_ainsn;
6558 else
6559 prev_ainsn->next_ainsn = curr_ainsn;
6560 prev_ainsn = curr_ainsn;
6563 return first_ainsn;
6566 /* The function assigns automata to units according to constructions
6567 `define_automaton' in the description. */
6568 static void
6569 units_to_automata_distr (void)
6571 decl_t decl;
6572 int i;
6574 for (i = 0; i < description->decls_num; i++)
6576 decl = description->decls [i];
6577 if (decl->mode == dm_unit)
6579 if (DECL_UNIT (decl)->automaton_decl == NULL
6580 || (DECL_UNIT (decl)->automaton_decl->corresponding_automaton
6581 == NULL))
6582 /* Distribute to the first automaton. */
6583 DECL_UNIT (decl)->corresponding_automaton_num = 0;
6584 else
6585 DECL_UNIT (decl)->corresponding_automaton_num
6586 = (DECL_UNIT (decl)->automaton_decl
6587 ->corresponding_automaton->automaton_order_num);
6592 /* The function creates DFA(s) for fast pipeline hazards recognition
6593 after checking and simplifying IR of the description. */
6594 static void
6595 create_automata (void)
6597 automaton_t curr_automaton;
6598 automaton_t prev_automaton;
6599 decl_t decl;
6600 int curr_automaton_num;
6601 int i;
6603 if (automata_num != 0)
6605 units_to_automata_heuristic_distr ();
6606 for (prev_automaton = NULL, curr_automaton_num = 0;
6607 curr_automaton_num < automata_num;
6608 curr_automaton_num++, prev_automaton = curr_automaton)
6610 curr_automaton = XCREATENODE (struct automaton);
6611 curr_automaton->ainsn_list = create_ainsns ();
6612 curr_automaton->corresponding_automaton_decl = NULL;
6613 curr_automaton->next_automaton = NULL;
6614 curr_automaton->automaton_order_num = curr_automaton_num;
6615 if (prev_automaton == NULL)
6616 description->first_automaton = curr_automaton;
6617 else
6618 prev_automaton->next_automaton = curr_automaton;
6621 else
6623 curr_automaton_num = 0;
6624 prev_automaton = NULL;
6625 for (i = 0; i < description->decls_num; i++)
6627 decl = description->decls [i];
6628 if (decl->mode == dm_automaton
6629 && DECL_AUTOMATON (decl)->automaton_is_used)
6631 curr_automaton = XCREATENODE (struct automaton);
6632 curr_automaton->ainsn_list = create_ainsns ();
6633 curr_automaton->corresponding_automaton_decl
6634 = DECL_AUTOMATON (decl);
6635 curr_automaton->next_automaton = NULL;
6636 DECL_AUTOMATON (decl)->corresponding_automaton = curr_automaton;
6637 curr_automaton->automaton_order_num = curr_automaton_num;
6638 if (prev_automaton == NULL)
6639 description->first_automaton = curr_automaton;
6640 else
6641 prev_automaton->next_automaton = curr_automaton;
6642 curr_automaton_num++;
6643 prev_automaton = curr_automaton;
6646 if (curr_automaton_num == 0)
6648 curr_automaton = XCREATENODE (struct automaton);
6649 curr_automaton->ainsn_list = create_ainsns ();
6650 curr_automaton->corresponding_automaton_decl = NULL;
6651 curr_automaton->next_automaton = NULL;
6652 description->first_automaton = curr_automaton;
6654 units_to_automata_distr ();
6656 NDFA_time = create_ticker ();
6657 ticker_off (&NDFA_time);
6658 NDFA_to_DFA_time = create_ticker ();
6659 ticker_off (&NDFA_to_DFA_time);
6660 minimize_time = create_ticker ();
6661 ticker_off (&minimize_time);
6662 equiv_time = create_ticker ();
6663 ticker_off (&equiv_time);
6664 for (curr_automaton = description->first_automaton;
6665 curr_automaton != NULL;
6666 curr_automaton = curr_automaton->next_automaton)
6668 if (progress_flag)
6670 if (curr_automaton->corresponding_automaton_decl == NULL)
6671 fprintf (stderr, "Prepare anonymous automaton creation ... ");
6672 else
6673 fprintf (stderr, "Prepare automaton `%s' creation...",
6674 curr_automaton->corresponding_automaton_decl->name);
6676 create_alt_states (curr_automaton);
6677 form_ainsn_with_same_reservs (curr_automaton);
6678 if (progress_flag)
6679 fprintf (stderr, "done\n");
6680 build_automaton (curr_automaton);
6681 enumerate_states (curr_automaton);
6682 ticker_on (&equiv_time);
6683 set_insn_equiv_classes (curr_automaton);
6684 ticker_off (&equiv_time);
6690 /* This page contains code for forming string representation of
6691 regexp. The representation is formed on IR obstack. So you should
6692 not work with IR obstack between regexp_representation and
6693 finish_regexp_representation calls. */
6695 /* This recursive function forms string representation of regexp
6696 (without tailing '\0'). */
6697 static void
6698 form_regexp (regexp_t regexp)
6700 int i;
6702 switch (regexp->mode)
6704 case rm_unit: case rm_reserv:
6706 const char *name = (regexp->mode == rm_unit
6707 ? REGEXP_UNIT (regexp)->name
6708 : REGEXP_RESERV (regexp)->name);
6710 obstack_grow (&irp, name, strlen (name));
6711 break;
6714 case rm_sequence:
6715 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
6717 if (i != 0)
6718 obstack_1grow (&irp, ',');
6719 form_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
6721 break;
6723 case rm_allof:
6724 obstack_1grow (&irp, '(');
6725 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
6727 if (i != 0)
6728 obstack_1grow (&irp, '+');
6729 if (REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_sequence
6730 || REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_oneof)
6731 obstack_1grow (&irp, '(');
6732 form_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
6733 if (REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_sequence
6734 || REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_oneof)
6735 obstack_1grow (&irp, ')');
6737 obstack_1grow (&irp, ')');
6738 break;
6740 case rm_oneof:
6741 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
6743 if (i != 0)
6744 obstack_1grow (&irp, '|');
6745 if (REGEXP_ONEOF (regexp)->regexps[i]->mode == rm_sequence)
6746 obstack_1grow (&irp, '(');
6747 form_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
6748 if (REGEXP_ONEOF (regexp)->regexps[i]->mode == rm_sequence)
6749 obstack_1grow (&irp, ')');
6751 break;
6753 case rm_repeat:
6755 char digits [30];
6757 if (REGEXP_REPEAT (regexp)->regexp->mode == rm_sequence
6758 || REGEXP_REPEAT (regexp)->regexp->mode == rm_allof
6759 || REGEXP_REPEAT (regexp)->regexp->mode == rm_oneof)
6760 obstack_1grow (&irp, '(');
6761 form_regexp (REGEXP_REPEAT (regexp)->regexp);
6762 if (REGEXP_REPEAT (regexp)->regexp->mode == rm_sequence
6763 || REGEXP_REPEAT (regexp)->regexp->mode == rm_allof
6764 || REGEXP_REPEAT (regexp)->regexp->mode == rm_oneof)
6765 obstack_1grow (&irp, ')');
6766 sprintf (digits, "*%d", REGEXP_REPEAT (regexp)->repeat_num);
6767 obstack_grow (&irp, digits, strlen (digits));
6768 break;
6771 case rm_nothing:
6772 obstack_grow (&irp, NOTHING_NAME, strlen (NOTHING_NAME));
6773 break;
6775 default:
6776 gcc_unreachable ();
6780 /* The function returns string representation of REGEXP on IR
6781 obstack. */
6782 static const char *
6783 regexp_representation (regexp_t regexp)
6785 form_regexp (regexp);
6786 obstack_1grow (&irp, '\0');
6787 return obstack_base (&irp);
6790 /* The function frees memory allocated for last formed string
6791 representation of regexp. */
6792 static void
6793 finish_regexp_representation (void)
6795 int length = obstack_object_size (&irp);
6797 obstack_blank_fast (&irp, -length);
6802 /* This page contains code for output PHR (pipeline hazards recognizer). */
6804 /* The function outputs minimal C type which is sufficient for
6805 representation numbers in range min_range_value and
6806 max_range_value. Because host machine and build machine may be
6807 different, we use here minimal values required by ANSI C standard
6808 instead of UCHAR_MAX, SHRT_MAX, SHRT_MIN, etc. This is a good
6809 approximation. */
6811 static void
6812 output_range_type (FILE *f, long int min_range_value,
6813 long int max_range_value)
6815 if (min_range_value >= 0 && max_range_value <= 255)
6816 fprintf (f, "unsigned char");
6817 else if (min_range_value >= -127 && max_range_value <= 127)
6818 fprintf (f, "signed char");
6819 else if (min_range_value >= 0 && max_range_value <= 65535)
6820 fprintf (f, "unsigned short");
6821 else if (min_range_value >= -32767 && max_range_value <= 32767)
6822 fprintf (f, "short");
6823 else
6824 fprintf (f, "int");
6827 /* The function outputs all initialization values of VECT. */
6828 static void
6829 output_vect (vla_hwint_t vect)
6831 int els_on_line;
6832 size_t vect_length = VEC_length (vect_el_t, vect);
6833 size_t i;
6835 els_on_line = 1;
6836 if (vect_length == 0)
6837 fputs ("0 /* This is dummy el because the vect is empty */", output_file);
6838 else
6839 for (i = 0; i < vect_length; i++)
6841 fprintf (output_file, "%5ld", (long) VEC_index (vect_el_t, vect, i));
6842 if (els_on_line == 10)
6844 els_on_line = 0;
6845 fputs (",\n", output_file);
6847 else if (i < vect_length-1)
6848 fputs (", ", output_file);
6849 els_on_line++;
6853 /* The following is name of the structure which represents DFA(s) for
6854 PHR. */
6855 #define CHIP_NAME "DFA_chip"
6857 /* The following is name of member which represents state of a DFA for
6858 PHR. */
6859 static void
6860 output_chip_member_name (FILE *f, automaton_t automaton)
6862 if (automaton->corresponding_automaton_decl == NULL)
6863 fprintf (f, "automaton_state_%d", automaton->automaton_order_num);
6864 else
6865 fprintf (f, "%s_automaton_state",
6866 automaton->corresponding_automaton_decl->name);
6869 /* The following is name of temporary variable which stores state of a
6870 DFA for PHR. */
6871 static void
6872 output_temp_chip_member_name (FILE *f, automaton_t automaton)
6874 fprintf (f, "_");
6875 output_chip_member_name (f, automaton);
6878 /* This is name of macro value which is code of pseudo_insn
6879 representing advancing cpu cycle. Its value is used as internal
6880 code unknown insn. */
6881 #define ADVANCE_CYCLE_VALUE_NAME "DFA__ADVANCE_CYCLE"
6883 /* Output name of translate vector for given automaton. */
6884 static void
6885 output_translate_vect_name (FILE *f, automaton_t automaton)
6887 if (automaton->corresponding_automaton_decl == NULL)
6888 fprintf (f, "translate_%d", automaton->automaton_order_num);
6889 else
6890 fprintf (f, "%s_translate", automaton->corresponding_automaton_decl->name);
6893 /* Output name for simple transition table representation. */
6894 static void
6895 output_trans_full_vect_name (FILE *f, automaton_t automaton)
6897 if (automaton->corresponding_automaton_decl == NULL)
6898 fprintf (f, "transitions_%d", automaton->automaton_order_num);
6899 else
6900 fprintf (f, "%s_transitions",
6901 automaton->corresponding_automaton_decl->name);
6904 /* Output name of comb vector of the transition table for given
6905 automaton. */
6906 static void
6907 output_trans_comb_vect_name (FILE *f, automaton_t automaton)
6909 if (automaton->corresponding_automaton_decl == NULL)
6910 fprintf (f, "transitions_%d", automaton->automaton_order_num);
6911 else
6912 fprintf (f, "%s_transitions",
6913 automaton->corresponding_automaton_decl->name);
6916 /* Output name of check vector of the transition table for given
6917 automaton. */
6918 static void
6919 output_trans_check_vect_name (FILE *f, automaton_t automaton)
6921 if (automaton->corresponding_automaton_decl == NULL)
6922 fprintf (f, "check_%d", automaton->automaton_order_num);
6923 else
6924 fprintf (f, "%s_check", automaton->corresponding_automaton_decl->name);
6927 /* Output name of base vector of the transition table for given
6928 automaton. */
6929 static void
6930 output_trans_base_vect_name (FILE *f, automaton_t automaton)
6932 if (automaton->corresponding_automaton_decl == NULL)
6933 fprintf (f, "base_%d", automaton->automaton_order_num);
6934 else
6935 fprintf (f, "%s_base", automaton->corresponding_automaton_decl->name);
6938 /* Output name of simple min issue delay table representation. */
6939 static void
6940 output_min_issue_delay_vect_name (FILE *f, automaton_t automaton)
6942 if (automaton->corresponding_automaton_decl == NULL)
6943 fprintf (f, "min_issue_delay_%d", automaton->automaton_order_num);
6944 else
6945 fprintf (f, "%s_min_issue_delay",
6946 automaton->corresponding_automaton_decl->name);
6949 /* Output name of deadlock vector for given automaton. */
6950 static void
6951 output_dead_lock_vect_name (FILE *f, automaton_t automaton)
6953 if (automaton->corresponding_automaton_decl == NULL)
6954 fprintf (f, "dead_lock_%d", automaton->automaton_order_num);
6955 else
6956 fprintf (f, "%s_dead_lock", automaton->corresponding_automaton_decl->name);
6959 /* Output name of reserved units table for AUTOMATON into file F. */
6960 static void
6961 output_reserved_units_table_name (FILE *f, automaton_t automaton)
6963 if (automaton->corresponding_automaton_decl == NULL)
6964 fprintf (f, "reserved_units_%d", automaton->automaton_order_num);
6965 else
6966 fprintf (f, "%s_reserved_units",
6967 automaton->corresponding_automaton_decl->name);
6970 /* Name of the PHR interface macro. */
6971 #define CPU_UNITS_QUERY_MACRO_NAME "CPU_UNITS_QUERY"
6973 /* Names of an internal functions: */
6974 #define INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME "internal_min_issue_delay"
6976 /* This is external type of DFA(s) state. */
6977 #define STATE_TYPE_NAME "state_t"
6979 #define INTERNAL_TRANSITION_FUNC_NAME "internal_state_transition"
6981 #define INTERNAL_RESET_FUNC_NAME "internal_reset"
6983 #define INTERNAL_DEAD_LOCK_FUNC_NAME "internal_state_dead_lock_p"
6985 #define INTERNAL_INSN_LATENCY_FUNC_NAME "internal_insn_latency"
6987 /* Name of cache of insn dfa codes. */
6988 #define DFA_INSN_CODES_VARIABLE_NAME "dfa_insn_codes"
6990 /* Name of length of cache of insn dfa codes. */
6991 #define DFA_INSN_CODES_LENGTH_VARIABLE_NAME "dfa_insn_codes_length"
6993 /* Names of the PHR interface functions: */
6994 #define SIZE_FUNC_NAME "state_size"
6996 #define TRANSITION_FUNC_NAME "state_transition"
6998 #define MIN_ISSUE_DELAY_FUNC_NAME "min_issue_delay"
7000 #define MIN_INSN_CONFLICT_DELAY_FUNC_NAME "min_insn_conflict_delay"
7002 #define DEAD_LOCK_FUNC_NAME "state_dead_lock_p"
7004 #define RESET_FUNC_NAME "state_reset"
7006 #define INSN_LATENCY_FUNC_NAME "insn_latency"
7008 #define PRINT_RESERVATION_FUNC_NAME "print_reservation"
7010 #define GET_CPU_UNIT_CODE_FUNC_NAME "get_cpu_unit_code"
7012 #define CPU_UNIT_RESERVATION_P_FUNC_NAME "cpu_unit_reservation_p"
7014 #define INSN_HAS_DFA_RESERVATION_P_FUNC_NAME "insn_has_dfa_reservation_p"
7016 #define DFA_CLEAN_INSN_CACHE_FUNC_NAME "dfa_clean_insn_cache"
7018 #define DFA_CLEAR_SINGLE_INSN_CACHE_FUNC_NAME "dfa_clear_single_insn_cache"
7020 #define DFA_START_FUNC_NAME "dfa_start"
7022 #define DFA_FINISH_FUNC_NAME "dfa_finish"
7024 /* Names of parameters of the PHR interface functions. */
7025 #define STATE_NAME "state"
7027 #define INSN_PARAMETER_NAME "insn"
7029 #define INSN2_PARAMETER_NAME "insn2"
7031 #define CHIP_PARAMETER_NAME "chip"
7033 #define FILE_PARAMETER_NAME "f"
7035 #define CPU_UNIT_NAME_PARAMETER_NAME "cpu_unit_name"
7037 #define CPU_CODE_PARAMETER_NAME "cpu_unit_code"
7039 /* Names of the variables whose values are internal insn code of rtx
7040 insn. */
7041 #define INTERNAL_INSN_CODE_NAME "insn_code"
7043 #define INTERNAL_INSN2_CODE_NAME "insn2_code"
7045 /* Names of temporary variables in some functions. */
7046 #define TEMPORARY_VARIABLE_NAME "temp"
7048 #define I_VARIABLE_NAME "i"
7050 /* Name of result variable in some functions. */
7051 #define RESULT_VARIABLE_NAME "res"
7053 /* Name of function (attribute) to translate insn into internal insn
7054 code. */
7055 #define INTERNAL_DFA_INSN_CODE_FUNC_NAME "internal_dfa_insn_code"
7057 /* Name of function (attribute) to translate insn into internal insn
7058 code with caching. */
7059 #define DFA_INSN_CODE_FUNC_NAME "dfa_insn_code"
7061 /* Output C type which is used for representation of codes of states
7062 of AUTOMATON. */
7063 static void
7064 output_state_member_type (FILE *f, automaton_t automaton)
7066 output_range_type (f, 0, automaton->achieved_states_num);
7069 /* Output definition of the structure representing current DFA(s)
7070 state(s). */
7071 static void
7072 output_chip_definitions (void)
7074 automaton_t automaton;
7076 fprintf (output_file, "struct %s\n{\n", CHIP_NAME);
7077 for (automaton = description->first_automaton;
7078 automaton != NULL;
7079 automaton = automaton->next_automaton)
7081 fprintf (output_file, " ");
7082 output_state_member_type (output_file, automaton);
7083 fprintf (output_file, " ");
7084 output_chip_member_name (output_file, automaton);
7085 fprintf (output_file, ";\n");
7087 fprintf (output_file, "};\n\n");
7088 #if 0
7089 fprintf (output_file, "static struct %s %s;\n\n", CHIP_NAME, CHIP_NAME);
7090 #endif
7094 /* The function outputs translate vector of internal insn code into
7095 insn equivalence class number. The equivalence class number is
7096 used to access to table and vectors representing DFA(s). */
7097 static void
7098 output_translate_vect (automaton_t automaton)
7100 ainsn_t ainsn;
7101 int insn_value;
7102 vla_hwint_t translate_vect;
7104 translate_vect = VEC_alloc (vect_el_t, heap, description->insns_num);
7106 for (insn_value = 0; insn_value < description->insns_num; insn_value++)
7107 /* Undefined value */
7108 VEC_quick_push (vect_el_t, translate_vect,
7109 automaton->insn_equiv_classes_num);
7111 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
7112 VEC_replace (vect_el_t, translate_vect,
7113 ainsn->insn_reserv_decl->insn_num,
7114 ainsn->insn_equiv_class_num);
7116 fprintf (output_file,
7117 "/* Vector translating external insn codes to internal ones.*/\n");
7118 fprintf (output_file, "static const ");
7119 output_range_type (output_file, 0, automaton->insn_equiv_classes_num);
7120 fprintf (output_file, " ");
7121 output_translate_vect_name (output_file, automaton);
7122 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7123 output_vect (translate_vect);
7124 fprintf (output_file, "};\n\n");
7125 VEC_free (vect_el_t, heap, translate_vect);
7128 /* The value in a table state x ainsn -> something which represents
7129 undefined value. */
7130 static int undefined_vect_el_value;
7132 /* The following function returns nonzero value if the best
7133 representation of the table is comb vector. */
7134 static int
7135 comb_vect_p (state_ainsn_table_t tab)
7137 return (2 * VEC_length (vect_el_t, tab->full_vect)
7138 > 5 * VEC_length (vect_el_t, tab->comb_vect));
7141 /* The following function creates new table for AUTOMATON. */
7142 static state_ainsn_table_t
7143 create_state_ainsn_table (automaton_t automaton)
7145 state_ainsn_table_t tab;
7146 int full_vect_length;
7147 int i;
7149 tab = XCREATENODE (struct state_ainsn_table);
7150 tab->automaton = automaton;
7152 tab->comb_vect = VEC_alloc (vect_el_t, heap, 10000);
7153 tab->check_vect = VEC_alloc (vect_el_t, heap, 10000);
7155 tab->base_vect = 0;
7156 VEC_safe_grow (vect_el_t, heap, tab->base_vect,
7157 automaton->achieved_states_num);
7159 full_vect_length = (automaton->insn_equiv_classes_num
7160 * automaton->achieved_states_num);
7161 tab->full_vect = VEC_alloc (vect_el_t, heap, full_vect_length);
7162 for (i = 0; i < full_vect_length; i++)
7163 VEC_quick_push (vect_el_t, tab->full_vect, undefined_vect_el_value);
7165 tab->min_base_vect_el_value = 0;
7166 tab->max_base_vect_el_value = 0;
7167 tab->min_comb_vect_el_value = 0;
7168 tab->max_comb_vect_el_value = 0;
7169 return tab;
7172 /* The following function outputs the best C representation of the
7173 table TAB of given TABLE_NAME. */
7174 static void
7175 output_state_ainsn_table (state_ainsn_table_t tab, const char *table_name,
7176 void (*output_full_vect_name_func) (FILE *, automaton_t),
7177 void (*output_comb_vect_name_func) (FILE *, automaton_t),
7178 void (*output_check_vect_name_func) (FILE *, automaton_t),
7179 void (*output_base_vect_name_func) (FILE *, automaton_t))
7181 if (!comb_vect_p (tab))
7183 fprintf (output_file, "/* Vector for %s. */\n", table_name);
7184 fprintf (output_file, "static const ");
7185 output_range_type (output_file, tab->min_comb_vect_el_value,
7186 tab->max_comb_vect_el_value);
7187 fprintf (output_file, " ");
7188 (*output_full_vect_name_func) (output_file, tab->automaton);
7189 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7190 output_vect (tab->full_vect);
7191 fprintf (output_file, "};\n\n");
7193 else
7195 fprintf (output_file, "/* Comb vector for %s. */\n", table_name);
7196 fprintf (output_file, "static const ");
7197 output_range_type (output_file, tab->min_comb_vect_el_value,
7198 tab->max_comb_vect_el_value);
7199 fprintf (output_file, " ");
7200 (*output_comb_vect_name_func) (output_file, tab->automaton);
7201 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7202 output_vect (tab->comb_vect);
7203 fprintf (output_file, "};\n\n");
7204 fprintf (output_file, "/* Check vector for %s. */\n", table_name);
7205 fprintf (output_file, "static const ");
7206 output_range_type (output_file, 0, tab->automaton->achieved_states_num);
7207 fprintf (output_file, " ");
7208 (*output_check_vect_name_func) (output_file, tab->automaton);
7209 fprintf (output_file, "[] = {\n");
7210 output_vect (tab->check_vect);
7211 fprintf (output_file, "};\n\n");
7212 fprintf (output_file, "/* Base vector for %s. */\n", table_name);
7213 fprintf (output_file, "static const ");
7214 output_range_type (output_file, tab->min_base_vect_el_value,
7215 tab->max_base_vect_el_value);
7216 fprintf (output_file, " ");
7217 (*output_base_vect_name_func) (output_file, tab->automaton);
7218 fprintf (output_file, "[] = {\n");
7219 output_vect (tab->base_vect);
7220 fprintf (output_file, "};\n\n");
7224 /* The following function adds vector VECT to table TAB as its line
7225 with number VECT_NUM. */
7226 static void
7227 add_vect (state_ainsn_table_t tab, int vect_num, vla_hwint_t vect)
7229 int vect_length;
7230 size_t real_vect_length;
7231 int comb_vect_index;
7232 int comb_vect_els_num;
7233 int vect_index;
7234 int first_unempty_vect_index;
7235 int additional_els_num;
7236 int no_state_value;
7237 vect_el_t vect_el;
7238 int i;
7239 unsigned long vect_mask, comb_vect_mask;
7241 vect_length = VEC_length (vect_el_t, vect);
7242 gcc_assert (vect_length);
7243 gcc_assert (VEC_last (vect_el_t, vect) != undefined_vect_el_value);
7244 real_vect_length = tab->automaton->insn_equiv_classes_num;
7245 /* Form full vector in the table: */
7247 size_t full_base = tab->automaton->insn_equiv_classes_num * vect_num;
7248 if (VEC_length (vect_el_t, tab->full_vect) < full_base + vect_length)
7249 VEC_safe_grow (vect_el_t, heap, tab->full_vect,
7250 full_base + vect_length);
7251 for (i = 0; i < vect_length; i++)
7252 VEC_replace (vect_el_t, tab->full_vect, full_base + i,
7253 VEC_index (vect_el_t, vect, i));
7255 /* Form comb vector in the table: */
7256 gcc_assert (VEC_length (vect_el_t, tab->comb_vect)
7257 == VEC_length (vect_el_t, tab->check_vect));
7259 comb_vect_els_num = VEC_length (vect_el_t, tab->comb_vect);
7260 for (first_unempty_vect_index = 0;
7261 first_unempty_vect_index < vect_length;
7262 first_unempty_vect_index++)
7263 if (VEC_index (vect_el_t, vect, first_unempty_vect_index)
7264 != undefined_vect_el_value)
7265 break;
7267 /* Search for the place in comb vect for the inserted vect. */
7269 /* Slow case. */
7270 if (vect_length - first_unempty_vect_index >= SIZEOF_LONG * CHAR_BIT)
7272 for (comb_vect_index = 0;
7273 comb_vect_index < comb_vect_els_num;
7274 comb_vect_index++)
7276 for (vect_index = first_unempty_vect_index;
7277 vect_index < vect_length
7278 && vect_index + comb_vect_index < comb_vect_els_num;
7279 vect_index++)
7280 if (VEC_index (vect_el_t, vect, vect_index)
7281 != undefined_vect_el_value
7282 && (VEC_index (vect_el_t, tab->comb_vect,
7283 vect_index + comb_vect_index)
7284 != undefined_vect_el_value))
7285 break;
7286 if (vect_index >= vect_length
7287 || vect_index + comb_vect_index >= comb_vect_els_num)
7288 break;
7290 goto found;
7293 /* Fast case. */
7294 vect_mask = 0;
7295 for (vect_index = first_unempty_vect_index;
7296 vect_index < vect_length;
7297 vect_index++)
7299 vect_mask = vect_mask << 1;
7300 if (VEC_index (vect_el_t, vect, vect_index) != undefined_vect_el_value)
7301 vect_mask |= 1;
7304 /* Search for the place in comb vect for the inserted vect. */
7305 comb_vect_index = 0;
7306 if (comb_vect_els_num == 0)
7307 goto found;
7309 comb_vect_mask = 0;
7310 for (vect_index = first_unempty_vect_index;
7311 vect_index < vect_length && vect_index < comb_vect_els_num;
7312 vect_index++)
7314 comb_vect_mask <<= 1;
7315 if (vect_index + comb_vect_index < comb_vect_els_num
7316 && VEC_index (vect_el_t, tab->comb_vect, vect_index + comb_vect_index)
7317 != undefined_vect_el_value)
7318 comb_vect_mask |= 1;
7320 if ((vect_mask & comb_vect_mask) == 0)
7321 goto found;
7323 for (comb_vect_index = 1, i = vect_length; i < comb_vect_els_num;
7324 comb_vect_index++, i++)
7326 comb_vect_mask = (comb_vect_mask << 1) | 1;
7327 comb_vect_mask ^= (VEC_index (vect_el_t, tab->comb_vect, i)
7328 == undefined_vect_el_value);
7329 if ((vect_mask & comb_vect_mask) == 0)
7330 goto found;
7332 for ( ; comb_vect_index < comb_vect_els_num; comb_vect_index++)
7334 comb_vect_mask <<= 1;
7335 if ((vect_mask & comb_vect_mask) == 0)
7336 goto found;
7339 found:
7340 /* Slot was found. */
7341 additional_els_num = comb_vect_index + real_vect_length - comb_vect_els_num;
7342 if (additional_els_num < 0)
7343 additional_els_num = 0;
7344 /* Expand comb and check vectors. */
7345 vect_el = undefined_vect_el_value;
7346 no_state_value = tab->automaton->achieved_states_num;
7347 while (additional_els_num > 0)
7349 VEC_safe_push (vect_el_t, heap, tab->comb_vect, vect_el);
7350 VEC_safe_push (vect_el_t, heap, tab->check_vect, no_state_value);
7351 additional_els_num--;
7353 gcc_assert (VEC_length (vect_el_t, tab->comb_vect)
7354 >= comb_vect_index + real_vect_length);
7355 /* Fill comb and check vectors. */
7356 for (vect_index = 0; vect_index < vect_length; vect_index++)
7357 if (VEC_index (vect_el_t, vect, vect_index) != undefined_vect_el_value)
7359 vect_el_t x = VEC_index (vect_el_t, vect, vect_index);
7360 gcc_assert (VEC_index (vect_el_t, tab->comb_vect,
7361 comb_vect_index + vect_index)
7362 == undefined_vect_el_value);
7363 gcc_assert (x >= 0);
7364 if (tab->max_comb_vect_el_value < x)
7365 tab->max_comb_vect_el_value = x;
7366 if (tab->min_comb_vect_el_value > x)
7367 tab->min_comb_vect_el_value = x;
7368 VEC_replace (vect_el_t, tab->comb_vect,
7369 comb_vect_index + vect_index, x);
7370 VEC_replace (vect_el_t, tab->check_vect,
7371 comb_vect_index + vect_index, vect_num);
7373 if (tab->max_comb_vect_el_value < undefined_vect_el_value)
7374 tab->max_comb_vect_el_value = undefined_vect_el_value;
7375 if (tab->min_comb_vect_el_value > undefined_vect_el_value)
7376 tab->min_comb_vect_el_value = undefined_vect_el_value;
7377 if (tab->max_base_vect_el_value < comb_vect_index)
7378 tab->max_base_vect_el_value = comb_vect_index;
7379 if (tab->min_base_vect_el_value > comb_vect_index)
7380 tab->min_base_vect_el_value = comb_vect_index;
7382 VEC_replace (vect_el_t, tab->base_vect, vect_num, comb_vect_index);
7385 /* Return number of out arcs of STATE. */
7386 static int
7387 out_state_arcs_num (const_state_t state)
7389 int result;
7390 arc_t arc;
7392 result = 0;
7393 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
7395 gcc_assert (arc->insn);
7396 if (arc->insn->first_ainsn_with_given_equivalence_num)
7397 result++;
7399 return result;
7402 /* Compare number of possible transitions from the states. */
7403 static int
7404 compare_transition_els_num (const void *state_ptr_1,
7405 const void *state_ptr_2)
7407 const int transition_els_num_1
7408 = out_state_arcs_num (*(const_state_t const*) state_ptr_1);
7409 const int transition_els_num_2
7410 = out_state_arcs_num (*(const_state_t const*) state_ptr_2);
7412 if (transition_els_num_1 < transition_els_num_2)
7413 return 1;
7414 else if (transition_els_num_1 == transition_els_num_2)
7415 return 0;
7416 else
7417 return -1;
7420 /* The function adds element EL_VALUE to vector VECT for a table state
7421 x AINSN. */
7422 static void
7423 add_vect_el (vla_hwint_t *vect, ainsn_t ainsn, int el_value)
7425 int equiv_class_num;
7426 int vect_index;
7428 gcc_assert (ainsn);
7429 equiv_class_num = ainsn->insn_equiv_class_num;
7430 for (vect_index = VEC_length (vect_el_t, *vect);
7431 vect_index <= equiv_class_num;
7432 vect_index++)
7433 VEC_safe_push (vect_el_t, heap, *vect, undefined_vect_el_value);
7434 VEC_replace (vect_el_t, *vect, equiv_class_num, el_value);
7437 /* This is for forming vector of states of an automaton. */
7438 static VEC(state_t, heap) *output_states_vect;
7440 /* The function is called by function pass_states. The function adds
7441 STATE to `output_states_vect'. */
7442 static void
7443 add_states_vect_el (state_t state)
7445 VEC_safe_push (state_t, heap, output_states_vect, state);
7448 /* Form and output vectors (comb, check, base or full vector)
7449 representing transition table of AUTOMATON. */
7450 static void
7451 output_trans_table (automaton_t automaton)
7453 size_t i;
7454 arc_t arc;
7455 vla_hwint_t transition_vect = 0;
7457 undefined_vect_el_value = automaton->achieved_states_num;
7458 automaton->trans_table = create_state_ainsn_table (automaton);
7459 /* Create vect of pointers to states ordered by num of transitions
7460 from the state (state with the maximum num is the first). */
7461 output_states_vect = 0;
7462 pass_states (automaton, add_states_vect_el);
7463 qsort (VEC_address (state_t, output_states_vect),
7464 VEC_length (state_t, output_states_vect),
7465 sizeof (state_t), compare_transition_els_num);
7467 for (i = 0; i < VEC_length (state_t, output_states_vect); i++)
7469 VEC_truncate (vect_el_t, transition_vect, 0);
7470 for (arc = first_out_arc (VEC_index (state_t, output_states_vect, i));
7471 arc != NULL;
7472 arc = next_out_arc (arc))
7474 gcc_assert (arc->insn);
7475 if (arc->insn->first_ainsn_with_given_equivalence_num)
7476 add_vect_el (&transition_vect, arc->insn,
7477 arc->to_state->order_state_num);
7479 add_vect (automaton->trans_table,
7480 VEC_index (state_t, output_states_vect, i)->order_state_num,
7481 transition_vect);
7483 output_state_ainsn_table
7484 (automaton->trans_table, "state transitions",
7485 output_trans_full_vect_name, output_trans_comb_vect_name,
7486 output_trans_check_vect_name, output_trans_base_vect_name);
7488 VEC_free (state_t, heap, output_states_vect);
7489 VEC_free (vect_el_t, heap, transition_vect);
7492 /* The current number of passing states to find minimal issue delay
7493 value for an ainsn and state. */
7494 static int curr_state_pass_num;
7496 /* This recursive function passes states to find minimal issue delay
7497 value for AINSN. The state being visited is STATE. The function
7498 returns minimal issue delay value for AINSN in STATE or -1 if we
7499 enter into a loop. */
7500 static int
7501 min_issue_delay_pass_states (state_t state, ainsn_t ainsn)
7503 arc_t arc;
7504 int min_insn_issue_delay, insn_issue_delay;
7506 if (state->state_pass_num == curr_state_pass_num
7507 || state->min_insn_issue_delay != -1)
7508 /* We've entered into a loop or already have the correct value for
7509 given state and ainsn. */
7510 return state->min_insn_issue_delay;
7511 state->state_pass_num = curr_state_pass_num;
7512 min_insn_issue_delay = -1;
7513 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
7514 if (arc->insn == ainsn)
7516 min_insn_issue_delay = 0;
7517 break;
7519 else
7521 insn_issue_delay = min_issue_delay_pass_states (arc->to_state, ainsn);
7522 if (insn_issue_delay != -1)
7524 if (arc->insn->insn_reserv_decl
7525 == DECL_INSN_RESERV (advance_cycle_insn_decl))
7526 insn_issue_delay++;
7527 if (min_insn_issue_delay == -1
7528 || min_insn_issue_delay > insn_issue_delay)
7530 min_insn_issue_delay = insn_issue_delay;
7531 if (insn_issue_delay == 0)
7532 break;
7536 return min_insn_issue_delay;
7539 /* The function searches minimal issue delay value for AINSN in STATE.
7540 The function can return negative value if we can not issue AINSN. We
7541 will report about it later. */
7542 static int
7543 min_issue_delay (state_t state, ainsn_t ainsn)
7545 curr_state_pass_num++;
7546 state->min_insn_issue_delay = min_issue_delay_pass_states (state, ainsn);
7547 return state->min_insn_issue_delay;
7550 /* The function initiates code for finding minimal issue delay values.
7551 It should be called only once. */
7552 static void
7553 initiate_min_issue_delay_pass_states (void)
7555 curr_state_pass_num = 0;
7558 /* Form and output vectors representing minimal issue delay table of
7559 AUTOMATON. The table is state x ainsn -> minimal issue delay of
7560 the ainsn. */
7561 static void
7562 output_min_issue_delay_table (automaton_t automaton)
7564 vla_hwint_t min_issue_delay_vect;
7565 vla_hwint_t compressed_min_issue_delay_vect;
7566 vect_el_t min_delay;
7567 ainsn_t ainsn;
7568 size_t i, min_issue_delay_len;
7569 size_t compressed_min_issue_delay_len;
7570 size_t cfactor;
7572 /* Create vect of pointers to states ordered by num of transitions
7573 from the state (state with the maximum num is the first). */
7574 output_states_vect = 0;
7575 pass_states (automaton, add_states_vect_el);
7577 min_issue_delay_len = (VEC_length (state_t, output_states_vect)
7578 * automaton->insn_equiv_classes_num);
7579 min_issue_delay_vect = VEC_alloc (vect_el_t, heap, min_issue_delay_len);
7580 for (i = 0; i < min_issue_delay_len; i++)
7581 VEC_quick_push (vect_el_t, min_issue_delay_vect, 0);
7583 automaton->max_min_delay = 0;
7584 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
7585 if (ainsn->first_ainsn_with_given_equivalence_num)
7587 for (i = 0; i < VEC_length (state_t, output_states_vect); i++)
7588 VEC_index (state_t, output_states_vect, i)->min_insn_issue_delay = -1;
7589 for (i = 0; i < VEC_length (state_t, output_states_vect); i++)
7591 state_t s = VEC_index (state_t, output_states_vect, i);
7592 min_delay = min_issue_delay (s, ainsn);
7593 if (automaton->max_min_delay < min_delay)
7594 automaton->max_min_delay = min_delay;
7595 VEC_replace (vect_el_t, min_issue_delay_vect,
7596 s->order_state_num
7597 * automaton->insn_equiv_classes_num
7598 + ainsn->insn_equiv_class_num,
7599 min_delay);
7602 fprintf (output_file, "/* Vector of min issue delay of insns. */\n");
7603 fprintf (output_file, "static const ");
7604 output_range_type (output_file, 0, automaton->max_min_delay);
7605 fprintf (output_file, " ");
7606 output_min_issue_delay_vect_name (output_file, automaton);
7607 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7608 /* Compress the vector. */
7609 if (automaton->max_min_delay < 2)
7610 cfactor = 8;
7611 else if (automaton->max_min_delay < 4)
7612 cfactor = 4;
7613 else if (automaton->max_min_delay < 16)
7614 cfactor = 2;
7615 else
7616 cfactor = 1;
7617 automaton->min_issue_delay_table_compression_factor = cfactor;
7619 compressed_min_issue_delay_len = (min_issue_delay_len+cfactor-1) / cfactor;
7620 compressed_min_issue_delay_vect
7621 = VEC_alloc (vect_el_t, heap, compressed_min_issue_delay_len);
7623 for (i = 0; i < compressed_min_issue_delay_len; i++)
7624 VEC_quick_push (vect_el_t, compressed_min_issue_delay_vect, 0);
7626 for (i = 0; i < min_issue_delay_len; i++)
7628 size_t ci = i / cfactor;
7629 vect_el_t x = VEC_index (vect_el_t, min_issue_delay_vect, i);
7630 vect_el_t cx = VEC_index (vect_el_t, compressed_min_issue_delay_vect, ci);
7632 cx |= x << (8 - (i % cfactor + 1) * (8 / cfactor));
7633 VEC_replace (vect_el_t, compressed_min_issue_delay_vect, ci, cx);
7635 output_vect (compressed_min_issue_delay_vect);
7636 fprintf (output_file, "};\n\n");
7637 VEC_free (state_t, heap, output_states_vect);
7638 VEC_free (vect_el_t, heap, min_issue_delay_vect);
7639 VEC_free (vect_el_t, heap, compressed_min_issue_delay_vect);
7642 /* Form and output vector representing the locked states of
7643 AUTOMATON. */
7644 static void
7645 output_dead_lock_vect (automaton_t automaton)
7647 size_t i;
7648 arc_t arc;
7649 vla_hwint_t dead_lock_vect = 0;
7651 /* Create vect of pointers to states ordered by num of
7652 transitions from the state (state with the maximum num is the
7653 first). */
7654 automaton->locked_states = 0;
7655 output_states_vect = 0;
7656 pass_states (automaton, add_states_vect_el);
7658 VEC_safe_grow (vect_el_t, heap, dead_lock_vect,
7659 VEC_length (state_t, output_states_vect));
7660 for (i = 0; i < VEC_length (state_t, output_states_vect); i++)
7662 state_t s = VEC_index (state_t, output_states_vect, i);
7663 arc = first_out_arc (s);
7664 gcc_assert (arc);
7665 if (next_out_arc (arc) == NULL
7666 && (arc->insn->insn_reserv_decl
7667 == DECL_INSN_RESERV (advance_cycle_insn_decl)))
7669 VEC_replace (vect_el_t, dead_lock_vect, s->order_state_num, 1);
7670 automaton->locked_states++;
7672 else
7673 VEC_replace (vect_el_t, dead_lock_vect, s->order_state_num, 0);
7675 if (automaton->locked_states == 0)
7676 return;
7678 fprintf (output_file, "/* Vector for locked state flags. */\n");
7679 fprintf (output_file, "static const ");
7680 output_range_type (output_file, 0, 1);
7681 fprintf (output_file, " ");
7682 output_dead_lock_vect_name (output_file, automaton);
7683 fprintf (output_file, "[] = {\n");
7684 output_vect (dead_lock_vect);
7685 fprintf (output_file, "};\n\n");
7686 VEC_free (state_t, heap, output_states_vect);
7687 VEC_free (vect_el_t, heap, dead_lock_vect);
7690 /* Form and output vector representing reserved units of the states of
7691 AUTOMATON. */
7692 static void
7693 output_reserved_units_table (automaton_t automaton)
7695 vla_hwint_t reserved_units_table = 0;
7696 int state_byte_size;
7697 int reserved_units_size;
7698 size_t n;
7699 int i;
7701 if (description->query_units_num == 0)
7702 return;
7704 /* Create vect of pointers to states. */
7705 output_states_vect = 0;
7706 pass_states (automaton, add_states_vect_el);
7707 /* Create vector. */
7708 state_byte_size = (description->query_units_num + 7) / 8;
7709 reserved_units_size = (VEC_length (state_t, output_states_vect)
7710 * state_byte_size);
7712 reserved_units_table = VEC_alloc (vect_el_t, heap, reserved_units_size);
7714 for (i = 0; i < reserved_units_size; i++)
7715 VEC_quick_push (vect_el_t, reserved_units_table, 0);
7716 for (n = 0; n < VEC_length (state_t, output_states_vect); n++)
7718 state_t s = VEC_index (state_t, output_states_vect, n);
7719 for (i = 0; i < description->units_num; i++)
7720 if (units_array [i]->query_p
7721 && first_cycle_unit_presence (s, i))
7723 int ri = (s->order_state_num * state_byte_size
7724 + units_array [i]->query_num / 8);
7725 vect_el_t x = VEC_index (vect_el_t, reserved_units_table, ri);
7727 x += 1 << (units_array [i]->query_num % 8);
7728 VEC_replace (vect_el_t, reserved_units_table, ri, x);
7731 fprintf (output_file, "\n#if %s\n", CPU_UNITS_QUERY_MACRO_NAME);
7732 fprintf (output_file, "/* Vector for reserved units of states. */\n");
7733 fprintf (output_file, "static const ");
7734 output_range_type (output_file, 0, 255);
7735 fprintf (output_file, " ");
7736 output_reserved_units_table_name (output_file, automaton);
7737 fprintf (output_file, "[] = {\n");
7738 output_vect (reserved_units_table);
7739 fprintf (output_file, "};\n#endif /* #if %s */\n\n",
7740 CPU_UNITS_QUERY_MACRO_NAME);
7742 VEC_free (state_t, heap, output_states_vect);
7743 VEC_free (vect_el_t, heap, reserved_units_table);
7746 /* The function outputs all tables representing DFA(s) used for fast
7747 pipeline hazards recognition. */
7748 static void
7749 output_tables (void)
7751 automaton_t automaton;
7753 initiate_min_issue_delay_pass_states ();
7754 for (automaton = description->first_automaton;
7755 automaton != NULL;
7756 automaton = automaton->next_automaton)
7758 output_translate_vect (automaton);
7759 output_trans_table (automaton);
7760 output_min_issue_delay_table (automaton);
7761 output_dead_lock_vect (automaton);
7762 output_reserved_units_table (automaton);
7764 fprintf (output_file, "\n#define %s %d\n\n", ADVANCE_CYCLE_VALUE_NAME,
7765 DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
7768 /* The function outputs definition and value of PHR interface variable
7769 `max_insn_queue_index'. Its value is not less than maximal queue
7770 length needed for the insn scheduler. */
7771 static void
7772 output_max_insn_queue_index_def (void)
7774 int i, max, latency;
7775 decl_t decl;
7777 max = description->max_insn_reserv_cycles;
7778 for (i = 0; i < description->decls_num; i++)
7780 decl = description->decls [i];
7781 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
7783 latency = DECL_INSN_RESERV (decl)->default_latency;
7784 if (latency > max)
7785 max = latency;
7787 else if (decl->mode == dm_bypass)
7789 latency = DECL_BYPASS (decl)->latency;
7790 if (latency > max)
7791 max = latency;
7794 for (i = 0; (1 << i) <= max; i++)
7796 gcc_assert (i >= 0);
7797 fprintf (output_file, "\nconst int max_insn_queue_index = %d;\n\n",
7798 (1 << i) - 1);
7801 /* The function outputs switch cases for insn reservations using
7802 function *output_automata_list_code. */
7803 static void
7804 output_insn_code_cases (void (*output_automata_list_code)
7805 (automata_list_el_t))
7807 decl_t decl, decl2;
7808 int i, j;
7810 for (i = 0; i < description->decls_num; i++)
7812 decl = description->decls [i];
7813 if (decl->mode == dm_insn_reserv)
7814 DECL_INSN_RESERV (decl)->processed_p = FALSE;
7816 for (i = 0; i < description->decls_num; i++)
7818 decl = description->decls [i];
7819 if (decl->mode == dm_insn_reserv
7820 && !DECL_INSN_RESERV (decl)->processed_p)
7822 for (j = i; j < description->decls_num; j++)
7824 decl2 = description->decls [j];
7825 if (decl2->mode == dm_insn_reserv
7826 && (DECL_INSN_RESERV (decl2)->important_automata_list
7827 == DECL_INSN_RESERV (decl)->important_automata_list))
7829 DECL_INSN_RESERV (decl2)->processed_p = TRUE;
7830 fprintf (output_file, " case %d: /* %s */\n",
7831 DECL_INSN_RESERV (decl2)->insn_num,
7832 DECL_INSN_RESERV (decl2)->name);
7835 (*output_automata_list_code)
7836 (DECL_INSN_RESERV (decl)->important_automata_list);
7842 /* The function outputs a code for evaluation of a minimal delay of
7843 issue of insns which have reservations in given AUTOMATA_LIST. */
7844 static void
7845 output_automata_list_min_issue_delay_code (automata_list_el_t automata_list)
7847 automata_list_el_t el;
7848 automaton_t automaton;
7850 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
7852 automaton = el->automaton;
7853 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
7854 output_min_issue_delay_vect_name (output_file, automaton);
7855 fprintf (output_file,
7856 (automaton->min_issue_delay_table_compression_factor != 1
7857 ? " [(" : " ["));
7858 output_translate_vect_name (output_file, automaton);
7859 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
7860 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7861 output_chip_member_name (output_file, automaton);
7862 fprintf (output_file, " * %d", automaton->insn_equiv_classes_num);
7863 if (automaton->min_issue_delay_table_compression_factor == 1)
7864 fprintf (output_file, "];\n");
7865 else
7867 fprintf (output_file, ") / %d];\n",
7868 automaton->min_issue_delay_table_compression_factor);
7869 fprintf (output_file, " %s = (%s >> (8 - (",
7870 TEMPORARY_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
7871 output_translate_vect_name (output_file, automaton);
7872 fprintf
7873 (output_file, " [%s] %% %d + 1) * %d)) & %d;\n",
7874 INTERNAL_INSN_CODE_NAME,
7875 automaton->min_issue_delay_table_compression_factor,
7876 8 / automaton->min_issue_delay_table_compression_factor,
7877 (1 << (8 / automaton->min_issue_delay_table_compression_factor))
7878 - 1);
7880 if (el == automata_list)
7881 fprintf (output_file, " %s = %s;\n",
7882 RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
7883 else
7885 fprintf (output_file, " if (%s > %s)\n",
7886 TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
7887 fprintf (output_file, " %s = %s;\n",
7888 RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
7891 fprintf (output_file, " break;\n\n");
7894 /* Output function `internal_min_issue_delay'. */
7895 static void
7896 output_internal_min_issue_delay_func (void)
7898 fprintf (output_file,
7899 "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
7900 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7901 CHIP_NAME, CHIP_PARAMETER_NAME);
7902 fprintf (output_file, "{\n int %s ATTRIBUTE_UNUSED;\n int %s = -1;\n",
7903 TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
7904 fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
7905 output_insn_code_cases (output_automata_list_min_issue_delay_code);
7906 fprintf (output_file,
7907 "\n default:\n %s = -1;\n break;\n }\n",
7908 RESULT_VARIABLE_NAME);
7909 fprintf (output_file, " return %s;\n", RESULT_VARIABLE_NAME);
7910 fprintf (output_file, "}\n\n");
7913 /* The function outputs a code changing state after issue of insns
7914 which have reservations in given AUTOMATA_LIST. */
7915 static void
7916 output_automata_list_transition_code (automata_list_el_t automata_list)
7918 automata_list_el_t el, next_el;
7920 fprintf (output_file, " {\n");
7921 if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
7922 for (el = automata_list;; el = next_el)
7924 next_el = el->next_automata_list_el;
7925 if (next_el == NULL)
7926 break;
7927 fprintf (output_file, " ");
7928 output_state_member_type (output_file, el->automaton);
7929 fprintf (output_file, " ");
7930 output_temp_chip_member_name (output_file, el->automaton);
7931 fprintf (output_file, ";\n");
7933 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
7934 if (comb_vect_p (el->automaton->trans_table))
7936 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
7937 output_trans_base_vect_name (output_file, el->automaton);
7938 fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
7939 output_chip_member_name (output_file, el->automaton);
7940 fprintf (output_file, "] + ");
7941 output_translate_vect_name (output_file, el->automaton);
7942 fprintf (output_file, " [%s];\n", INTERNAL_INSN_CODE_NAME);
7943 fprintf (output_file, " if (");
7944 output_trans_check_vect_name (output_file, el->automaton);
7945 fprintf (output_file, " [%s] != %s->",
7946 TEMPORARY_VARIABLE_NAME, CHIP_PARAMETER_NAME);
7947 output_chip_member_name (output_file, el->automaton);
7948 fprintf (output_file, ")\n");
7949 fprintf (output_file, " return %s (%s, %s);\n",
7950 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7951 CHIP_PARAMETER_NAME);
7952 fprintf (output_file, " else\n");
7953 fprintf (output_file, " ");
7954 if (el->next_automata_list_el != NULL)
7955 output_temp_chip_member_name (output_file, el->automaton);
7956 else
7958 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7959 output_chip_member_name (output_file, el->automaton);
7961 fprintf (output_file, " = ");
7962 output_trans_comb_vect_name (output_file, el->automaton);
7963 fprintf (output_file, " [%s];\n", TEMPORARY_VARIABLE_NAME);
7965 else
7967 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
7968 output_trans_full_vect_name (output_file, el->automaton);
7969 fprintf (output_file, " [");
7970 output_translate_vect_name (output_file, el->automaton);
7971 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
7972 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7973 output_chip_member_name (output_file, el->automaton);
7974 fprintf (output_file, " * %d];\n",
7975 el->automaton->insn_equiv_classes_num);
7976 fprintf (output_file, " if (%s >= %d)\n",
7977 TEMPORARY_VARIABLE_NAME, el->automaton->achieved_states_num);
7978 fprintf (output_file, " return %s (%s, %s);\n",
7979 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7980 CHIP_PARAMETER_NAME);
7981 fprintf (output_file, " else\n ");
7982 if (el->next_automata_list_el != NULL)
7983 output_temp_chip_member_name (output_file, el->automaton);
7984 else
7986 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7987 output_chip_member_name (output_file, el->automaton);
7989 fprintf (output_file, " = %s;\n", TEMPORARY_VARIABLE_NAME);
7991 if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
7992 for (el = automata_list;; el = next_el)
7994 next_el = el->next_automata_list_el;
7995 if (next_el == NULL)
7996 break;
7997 fprintf (output_file, " %s->", CHIP_PARAMETER_NAME);
7998 output_chip_member_name (output_file, el->automaton);
7999 fprintf (output_file, " = ");
8000 output_temp_chip_member_name (output_file, el->automaton);
8001 fprintf (output_file, ";\n");
8003 fprintf (output_file, " return -1;\n");
8004 fprintf (output_file, " }\n");
8007 /* Output function `internal_state_transition'. */
8008 static void
8009 output_internal_trans_func (void)
8011 fprintf (output_file,
8012 "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
8013 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8014 CHIP_NAME, CHIP_PARAMETER_NAME);
8015 fprintf (output_file, "{\n int %s ATTRIBUTE_UNUSED;\n", TEMPORARY_VARIABLE_NAME);
8016 fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8017 output_insn_code_cases (output_automata_list_transition_code);
8018 fprintf (output_file, "\n default:\n return -1;\n }\n");
8019 fprintf (output_file, "}\n\n");
8022 /* Output code
8024 if (insn != 0)
8026 insn_code = dfa_insn_code (insn);
8027 if (insn_code > DFA__ADVANCE_CYCLE)
8028 return code;
8030 else
8031 insn_code = DFA__ADVANCE_CYCLE;
8033 where insn denotes INSN_NAME, insn_code denotes INSN_CODE_NAME, and
8034 code denotes CODE. */
8035 static void
8036 output_internal_insn_code_evaluation (const char *insn_name,
8037 const char *insn_code_name,
8038 int code)
8040 fprintf (output_file, "\n if (%s != 0)\n {\n", insn_name);
8041 fprintf (output_file, " %s = %s (%s);\n", insn_code_name,
8042 DFA_INSN_CODE_FUNC_NAME, insn_name);
8043 fprintf (output_file, " if (%s > %s)\n return %d;\n",
8044 insn_code_name, ADVANCE_CYCLE_VALUE_NAME, code);
8045 fprintf (output_file, " }\n else\n %s = %s;\n\n",
8046 insn_code_name, ADVANCE_CYCLE_VALUE_NAME);
8050 /* This function outputs `dfa_insn_code' and its helper function
8051 `dfa_insn_code_enlarge'. */
8052 static void
8053 output_dfa_insn_code_func (void)
8055 /* Emacs c-mode gets really confused if there's a { or } in column 0
8056 inside a string, so don't do that. */
8057 fprintf (output_file, "\
8058 static void\n\
8059 dfa_insn_code_enlarge (int uid)\n\
8060 {\n\
8061 int i = %s;\n\
8062 %s = 2 * uid;\n\
8063 %s = XRESIZEVEC (int, %s,\n\
8064 %s);\n\
8065 for (; i < %s; i++)\n\
8066 %s[i] = -1;\n}\n\n",
8067 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8068 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8069 DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
8070 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8071 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8072 DFA_INSN_CODES_VARIABLE_NAME);
8073 fprintf (output_file, "\
8074 static inline int\n%s (rtx %s)\n\
8075 {\n\
8076 int uid = INSN_UID (%s);\n\
8077 int %s;\n\n",
8078 DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME,
8079 INSN_PARAMETER_NAME, INTERNAL_INSN_CODE_NAME);
8081 fprintf (output_file,
8082 " if (uid >= %s)\n dfa_insn_code_enlarge (uid);\n\n",
8083 DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8084 fprintf (output_file, " %s = %s[uid];\n",
8085 INTERNAL_INSN_CODE_NAME, DFA_INSN_CODES_VARIABLE_NAME);
8086 fprintf (output_file, "\
8087 if (%s < 0)\n\
8088 {\n\
8089 %s = %s (%s);\n\
8090 %s[uid] = %s;\n\
8091 }\n",
8092 INTERNAL_INSN_CODE_NAME,
8093 INTERNAL_INSN_CODE_NAME,
8094 INTERNAL_DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME,
8095 DFA_INSN_CODES_VARIABLE_NAME, INTERNAL_INSN_CODE_NAME);
8096 fprintf (output_file, " return %s;\n}\n\n", INTERNAL_INSN_CODE_NAME);
8099 /* The function outputs PHR interface function `state_transition'. */
8100 static void
8101 output_trans_func (void)
8103 fprintf (output_file, "int\n%s (%s %s, rtx %s)\n",
8104 TRANSITION_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME,
8105 INSN_PARAMETER_NAME);
8106 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
8107 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8108 INTERNAL_INSN_CODE_NAME, -1);
8109 fprintf (output_file, " return %s (%s, (struct %s *) %s);\n}\n\n",
8110 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME, STATE_NAME);
8113 /* Output function `min_issue_delay'. */
8114 static void
8115 output_min_issue_delay_func (void)
8117 fprintf (output_file, "int\n%s (%s %s, rtx %s)\n",
8118 MIN_ISSUE_DELAY_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME,
8119 INSN_PARAMETER_NAME);
8120 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
8121 fprintf (output_file, "\n if (%s != 0)\n {\n", INSN_PARAMETER_NAME);
8122 fprintf (output_file, " %s = %s (%s);\n", INTERNAL_INSN_CODE_NAME,
8123 DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME);
8124 fprintf (output_file, " if (%s > %s)\n return 0;\n",
8125 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8126 fprintf (output_file, " }\n else\n %s = %s;\n",
8127 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8128 fprintf (output_file, "\n return %s (%s, (struct %s *) %s);\n",
8129 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8130 CHIP_NAME, STATE_NAME);
8131 fprintf (output_file, "}\n\n");
8134 /* Output function `internal_dead_lock'. */
8135 static void
8136 output_internal_dead_lock_func (void)
8138 automaton_t automaton;
8140 fprintf (output_file, "static int\n%s (struct %s *ARG_UNUSED (%s))\n",
8141 INTERNAL_DEAD_LOCK_FUNC_NAME, CHIP_NAME, CHIP_PARAMETER_NAME);
8142 fprintf (output_file, "{\n");
8143 for (automaton = description->first_automaton;
8144 automaton != NULL;
8145 automaton = automaton->next_automaton)
8146 if (automaton->locked_states)
8148 fprintf (output_file, " if (");
8149 output_dead_lock_vect_name (output_file, automaton);
8150 fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
8151 output_chip_member_name (output_file, automaton);
8152 fprintf (output_file, "])\n return 1/* TRUE */;\n");
8154 fprintf (output_file, " return 0/* FALSE */;\n}\n\n");
8157 /* The function outputs PHR interface function `state_dead_lock_p'. */
8158 static void
8159 output_dead_lock_func (void)
8161 fprintf (output_file, "int\n%s (%s %s)\n",
8162 DEAD_LOCK_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME);
8163 fprintf (output_file, "{\n return %s ((struct %s *) %s);\n}\n\n",
8164 INTERNAL_DEAD_LOCK_FUNC_NAME, CHIP_NAME, STATE_NAME);
8167 /* Output function `internal_reset'. */
8168 static void
8169 output_internal_reset_func (void)
8171 fprintf (output_file, "static inline void\n%s (struct %s *%s)\n",
8172 INTERNAL_RESET_FUNC_NAME, CHIP_NAME, CHIP_PARAMETER_NAME);
8173 fprintf (output_file, "{\n memset (%s, 0, sizeof (struct %s));\n}\n\n",
8174 CHIP_PARAMETER_NAME, CHIP_NAME);
8177 /* The function outputs PHR interface function `state_size'. */
8178 static void
8179 output_size_func (void)
8181 fprintf (output_file, "int\n%s (void)\n", SIZE_FUNC_NAME);
8182 fprintf (output_file, "{\n return sizeof (struct %s);\n}\n\n", CHIP_NAME);
8185 /* The function outputs PHR interface function `state_reset'. */
8186 static void
8187 output_reset_func (void)
8189 fprintf (output_file, "void\n%s (%s %s)\n",
8190 RESET_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME);
8191 fprintf (output_file, "{\n %s ((struct %s *) %s);\n}\n\n", INTERNAL_RESET_FUNC_NAME,
8192 CHIP_NAME, STATE_NAME);
8195 /* Output function `min_insn_conflict_delay'. */
8196 static void
8197 output_min_insn_conflict_delay_func (void)
8199 fprintf (output_file,
8200 "int\n%s (%s %s, rtx %s, rtx %s)\n",
8201 MIN_INSN_CONFLICT_DELAY_FUNC_NAME, STATE_TYPE_NAME,
8202 STATE_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8203 fprintf (output_file, "{\n struct %s %s;\n int %s, %s, transition;\n",
8204 CHIP_NAME, CHIP_NAME, INTERNAL_INSN_CODE_NAME,
8205 INTERNAL_INSN2_CODE_NAME);
8206 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8207 INTERNAL_INSN_CODE_NAME, 0);
8208 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
8209 INTERNAL_INSN2_CODE_NAME, 0);
8210 fprintf (output_file, " memcpy (&%s, %s, sizeof (%s));\n",
8211 CHIP_NAME, STATE_NAME, CHIP_NAME);
8212 fprintf (output_file, " %s (&%s);\n", INTERNAL_RESET_FUNC_NAME, CHIP_NAME);
8213 fprintf (output_file, " transition = %s (%s, &%s);\n",
8214 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME);
8215 fprintf (output_file, " gcc_assert (transition <= 0);\n");
8216 fprintf (output_file, " return %s (%s, &%s);\n",
8217 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN2_CODE_NAME,
8218 CHIP_NAME);
8219 fprintf (output_file, "}\n\n");
8222 /* Output the array holding default latency values. These are used in
8223 insn_latency and maximal_insn_latency function implementations. */
8224 static void
8225 output_default_latencies (void)
8227 int i, j, col;
8228 decl_t decl;
8229 const char *tabletype = "unsigned char";
8231 /* Find the smallest integer type that can hold all the default
8232 latency values. */
8233 for (i = 0; i < description->decls_num; i++)
8234 if (description->decls[i]->mode == dm_insn_reserv)
8236 decl = description->decls[i];
8237 if (DECL_INSN_RESERV (decl)->default_latency > UCHAR_MAX
8238 && tabletype[0] != 'i') /* Don't shrink it. */
8239 tabletype = "unsigned short";
8240 if (DECL_INSN_RESERV (decl)->default_latency > USHRT_MAX)
8241 tabletype = "int";
8244 fprintf (output_file, " static const %s default_latencies[] =\n {",
8245 tabletype);
8247 for (i = 0, j = 0, col = 7; i < description->decls_num; i++)
8248 if (description->decls[i]->mode == dm_insn_reserv
8249 && description->decls[i] != advance_cycle_insn_decl)
8251 if ((col = (col+1) % 8) == 0)
8252 fputs ("\n ", output_file);
8253 decl = description->decls[i];
8254 gcc_assert (j++ == DECL_INSN_RESERV (decl)->insn_num);
8255 fprintf (output_file, "% 4d,",
8256 DECL_INSN_RESERV (decl)->default_latency);
8258 gcc_assert (j == DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
8259 fputs ("\n };\n", output_file);
8262 /* Output function `internal_insn_latency'. */
8263 static void
8264 output_internal_insn_latency_func (void)
8266 int i;
8267 decl_t decl;
8268 struct bypass_decl *bypass;
8270 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",
8271 INTERNAL_INSN_LATENCY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8272 INTERNAL_INSN2_CODE_NAME, INSN_PARAMETER_NAME,
8273 INSN2_PARAMETER_NAME);
8274 fprintf (output_file, "{\n");
8276 if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8278 fputs (" return 0;\n}\n\n", output_file);
8279 return;
8282 fprintf (output_file, " if (%s >= %s || %s >= %s)\n return 0;\n",
8283 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8284 INTERNAL_INSN2_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8286 fprintf (output_file, " switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8287 for (i = 0; i < description->decls_num; i++)
8288 if (description->decls[i]->mode == dm_insn_reserv
8289 && DECL_INSN_RESERV (description->decls[i])->bypass_list)
8291 decl = description->decls [i];
8292 fprintf (output_file,
8293 " case %d:\n switch (%s)\n {\n",
8294 DECL_INSN_RESERV (decl)->insn_num,
8295 INTERNAL_INSN2_CODE_NAME);
8296 for (bypass = DECL_INSN_RESERV (decl)->bypass_list;
8297 bypass != NULL;
8298 bypass = bypass->next)
8300 gcc_assert (bypass->in_insn_reserv->insn_num
8301 != (DECL_INSN_RESERV
8302 (advance_cycle_insn_decl)->insn_num));
8303 fprintf (output_file, " case %d:\n",
8304 bypass->in_insn_reserv->insn_num);
8305 for (;;)
8307 if (bypass->bypass_guard_name == NULL)
8309 gcc_assert (bypass->next == NULL
8310 || (bypass->in_insn_reserv
8311 != bypass->next->in_insn_reserv));
8312 fprintf (output_file, " return %d;\n",
8313 bypass->latency);
8315 else
8317 fprintf (output_file,
8318 " if (%s (%s, %s))\n",
8319 bypass->bypass_guard_name, INSN_PARAMETER_NAME,
8320 INSN2_PARAMETER_NAME);
8321 fprintf (output_file, " return %d;\n",
8322 bypass->latency);
8324 if (bypass->next == NULL
8325 || bypass->in_insn_reserv != bypass->next->in_insn_reserv)
8326 break;
8327 bypass = bypass->next;
8329 if (bypass->bypass_guard_name != NULL)
8330 fprintf (output_file, " break;\n");
8332 fputs (" }\n break;\n", output_file);
8335 fprintf (output_file, " }\n return default_latencies[%s];\n}\n\n",
8336 INTERNAL_INSN_CODE_NAME);
8339 /* Output function `internal_maximum_insn_latency'. */
8340 static void
8341 output_internal_maximal_insn_latency_func (void)
8343 decl_t decl;
8344 struct bypass_decl *bypass;
8345 int i;
8346 int max;
8348 fprintf (output_file, "static int\n%s (int %s ATTRIBUTE_UNUSED,\n\trtx %s ATTRIBUTE_UNUSED)\n",
8349 "internal_maximal_insn_latency", INTERNAL_INSN_CODE_NAME,
8350 INSN_PARAMETER_NAME);
8351 fprintf (output_file, "{\n");
8353 if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8355 fputs (" return 0;\n}\n\n", output_file);
8356 return;
8359 fprintf (output_file, " switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8360 for (i = 0; i < description->decls_num; i++)
8361 if (description->decls[i]->mode == dm_insn_reserv
8362 && DECL_INSN_RESERV (description->decls[i])->bypass_list)
8364 decl = description->decls [i];
8365 max = DECL_INSN_RESERV (decl)->default_latency;
8366 fprintf (output_file,
8367 " case %d: {",
8368 DECL_INSN_RESERV (decl)->insn_num);
8369 for (bypass = DECL_INSN_RESERV (decl)->bypass_list;
8370 bypass != NULL;
8371 bypass = bypass->next)
8373 if (bypass->latency > max)
8374 max = bypass->latency;
8376 fprintf (output_file, " return %d; }\n break;\n", max);
8379 fprintf (output_file, " }\n return default_latencies[%s];\n}\n\n",
8380 INTERNAL_INSN_CODE_NAME);
8383 /* The function outputs PHR interface function `insn_latency'. */
8384 static void
8385 output_insn_latency_func (void)
8387 fprintf (output_file, "int\n%s (rtx %s, rtx %s)\n",
8388 INSN_LATENCY_FUNC_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8389 fprintf (output_file, "{\n int %s, %s;\n",
8390 INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME);
8391 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8392 INTERNAL_INSN_CODE_NAME, 0);
8393 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
8394 INTERNAL_INSN2_CODE_NAME, 0);
8395 fprintf (output_file, " return %s (%s, %s, %s, %s);\n}\n\n",
8396 INTERNAL_INSN_LATENCY_FUNC_NAME,
8397 INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME,
8398 INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8401 /* The function outputs PHR interface function `maximal_insn_latency'. */
8402 static void
8403 output_maximal_insn_latency_func (void)
8405 fprintf (output_file, "int\n%s (rtx %s)\n",
8406 "maximal_insn_latency", INSN_PARAMETER_NAME);
8407 fprintf (output_file, "{\n int %s;\n",
8408 INTERNAL_INSN_CODE_NAME);
8409 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8410 INTERNAL_INSN_CODE_NAME, 0);
8411 fprintf (output_file, " return %s (%s, %s);\n}\n\n",
8412 "internal_maximal_insn_latency",
8413 INTERNAL_INSN_CODE_NAME, INSN_PARAMETER_NAME);
8416 /* The function outputs PHR interface function `print_reservation'. */
8417 static void
8418 output_print_reservation_func (void)
8420 decl_t decl;
8421 int i, j;
8423 fprintf (output_file,
8424 "void\n%s (FILE *%s, rtx %s ATTRIBUTE_UNUSED)\n{\n",
8425 PRINT_RESERVATION_FUNC_NAME, FILE_PARAMETER_NAME,
8426 INSN_PARAMETER_NAME);
8428 if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8430 fprintf (output_file, " fputs (\"%s\", %s);\n}\n\n",
8431 NOTHING_NAME, FILE_PARAMETER_NAME);
8432 return;
8436 fputs (" static const char *const reservation_names[] =\n {",
8437 output_file);
8439 for (i = 0, j = 0; i < description->decls_num; i++)
8441 decl = description->decls [i];
8442 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
8444 gcc_assert (j == DECL_INSN_RESERV (decl)->insn_num);
8445 j++;
8447 fprintf (output_file, "\n \"%s\",",
8448 regexp_representation (DECL_INSN_RESERV (decl)->regexp));
8449 finish_regexp_representation ();
8452 gcc_assert (j == DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
8454 fprintf (output_file, "\n \"%s\"\n };\n int %s;\n\n",
8455 NOTHING_NAME, INTERNAL_INSN_CODE_NAME);
8457 fprintf (output_file, " if (%s == 0)\n %s = %s;\n",
8458 INSN_PARAMETER_NAME,
8459 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8460 fprintf (output_file, " else\n\
8461 {\n\
8462 %s = %s (%s);\n\
8463 if (%s > %s)\n\
8464 %s = %s;\n\
8465 }\n",
8466 INTERNAL_INSN_CODE_NAME, DFA_INSN_CODE_FUNC_NAME,
8467 INSN_PARAMETER_NAME,
8468 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8469 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8471 fprintf (output_file, " fputs (reservation_names[%s], %s);\n}\n\n",
8472 INTERNAL_INSN_CODE_NAME, FILE_PARAMETER_NAME);
8475 /* The following function is used to sort unit declaration by their
8476 names. */
8477 static int
8478 units_cmp (const void *unit1, const void *unit2)
8480 const_unit_decl_t const u1 = *(const_unit_decl_t const*) unit1;
8481 const_unit_decl_t const u2 = *(const_unit_decl_t const*) unit2;
8483 return strcmp (u1->name, u2->name);
8486 /* The following macro value is name of struct containing unit name
8487 and unit code. */
8488 #define NAME_CODE_STRUCT_NAME "name_code"
8490 /* The following macro value is name of table of struct name_code. */
8491 #define NAME_CODE_TABLE_NAME "name_code_table"
8493 /* The following macro values are member names for struct name_code. */
8494 #define NAME_MEMBER_NAME "name"
8495 #define CODE_MEMBER_NAME "code"
8497 /* The following macro values are local variable names for function
8498 `get_cpu_unit_code'. */
8499 #define CMP_VARIABLE_NAME "cmp"
8500 #define LOW_VARIABLE_NAME "l"
8501 #define MIDDLE_VARIABLE_NAME "m"
8502 #define HIGH_VARIABLE_NAME "h"
8504 /* The following function outputs function to obtain internal cpu unit
8505 code by the cpu unit name. */
8506 static void
8507 output_get_cpu_unit_code_func (void)
8509 int i;
8510 unit_decl_t *units;
8512 fprintf (output_file, "int\n%s (const char *%s)\n",
8513 GET_CPU_UNIT_CODE_FUNC_NAME, CPU_UNIT_NAME_PARAMETER_NAME);
8514 fprintf (output_file, "{\n struct %s {const char *%s; int %s;};\n",
8515 NAME_CODE_STRUCT_NAME, NAME_MEMBER_NAME, CODE_MEMBER_NAME);
8516 fprintf (output_file, " int %s, %s, %s, %s;\n", CMP_VARIABLE_NAME,
8517 LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8518 fprintf (output_file, " static struct %s %s [] =\n {\n",
8519 NAME_CODE_STRUCT_NAME, NAME_CODE_TABLE_NAME);
8520 units = XNEWVEC (unit_decl_t, description->units_num);
8521 memcpy (units, units_array, sizeof (unit_decl_t) * description->units_num);
8522 qsort (units, description->units_num, sizeof (unit_decl_t), units_cmp);
8523 for (i = 0; i < description->units_num; i++)
8524 if (units [i]->query_p)
8525 fprintf (output_file, " {\"%s\", %d},\n",
8526 units[i]->name, units[i]->query_num);
8527 fprintf (output_file, " };\n\n");
8528 fprintf (output_file, " /* The following is binary search: */\n");
8529 fprintf (output_file, " %s = 0;\n", LOW_VARIABLE_NAME);
8530 fprintf (output_file, " %s = sizeof (%s) / sizeof (struct %s) - 1;\n",
8531 HIGH_VARIABLE_NAME, NAME_CODE_TABLE_NAME, NAME_CODE_STRUCT_NAME);
8532 fprintf (output_file, " while (%s <= %s)\n {\n",
8533 LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8534 fprintf (output_file, " %s = (%s + %s) / 2;\n",
8535 MIDDLE_VARIABLE_NAME, LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8536 fprintf (output_file, " %s = strcmp (%s, %s [%s].%s);\n",
8537 CMP_VARIABLE_NAME, CPU_UNIT_NAME_PARAMETER_NAME,
8538 NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, NAME_MEMBER_NAME);
8539 fprintf (output_file, " if (%s < 0)\n", CMP_VARIABLE_NAME);
8540 fprintf (output_file, " %s = %s - 1;\n",
8541 HIGH_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
8542 fprintf (output_file, " else if (%s > 0)\n", CMP_VARIABLE_NAME);
8543 fprintf (output_file, " %s = %s + 1;\n",
8544 LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
8545 fprintf (output_file, " else\n");
8546 fprintf (output_file, " return %s [%s].%s;\n }\n",
8547 NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, CODE_MEMBER_NAME);
8548 fprintf (output_file, " return -1;\n}\n\n");
8549 free (units);
8552 /* The following function outputs function to check reservation of cpu
8553 unit (its internal code will be passed as the function argument) in
8554 given cpu state. */
8555 static void
8556 output_cpu_unit_reservation_p (void)
8558 automaton_t automaton;
8560 fprintf (output_file, "int\n%s (%s %s, int %s)\n",
8561 CPU_UNIT_RESERVATION_P_FUNC_NAME,
8562 STATE_TYPE_NAME, STATE_NAME,
8563 CPU_CODE_PARAMETER_NAME);
8564 fprintf (output_file, "{\n gcc_assert (%s >= 0 && %s < %d);\n",
8565 CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME,
8566 description->query_units_num);
8567 if (description->query_units_num > 0)
8568 for (automaton = description->first_automaton;
8569 automaton != NULL;
8570 automaton = automaton->next_automaton)
8572 fprintf (output_file, " if ((");
8573 output_reserved_units_table_name (output_file, automaton);
8574 fprintf (output_file, " [((struct %s *) %s)->", CHIP_NAME, STATE_NAME);
8575 output_chip_member_name (output_file, automaton);
8576 fprintf (output_file, " * %d + %s / 8] >> (%s %% 8)) & 1)\n",
8577 (description->query_units_num + 7) / 8,
8578 CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME);
8579 fprintf (output_file, " return 1;\n");
8581 fprintf (output_file, " return 0;\n}\n\n");
8584 /* The following function outputs a function to check if insn
8585 has a dfa reservation. */
8586 static void
8587 output_insn_has_dfa_reservation_p (void)
8589 fprintf (output_file,
8590 "bool\n%s (rtx %s ATTRIBUTE_UNUSED)\n{\n",
8591 INSN_HAS_DFA_RESERVATION_P_FUNC_NAME,
8592 INSN_PARAMETER_NAME);
8594 if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8596 fprintf (output_file, " return false;\n}\n\n");
8597 return;
8600 fprintf (output_file, " int %s;\n\n", INTERNAL_INSN_CODE_NAME);
8602 fprintf (output_file, " if (%s == 0)\n %s = %s;\n",
8603 INSN_PARAMETER_NAME,
8604 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8605 fprintf (output_file, " else\n\
8606 {\n\
8607 %s = %s (%s);\n\
8608 if (%s > %s)\n\
8609 %s = %s;\n\
8610 }\n\n",
8611 INTERNAL_INSN_CODE_NAME, DFA_INSN_CODE_FUNC_NAME,
8612 INSN_PARAMETER_NAME,
8613 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8614 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8616 fprintf (output_file, " return %s != %s;\n}\n\n",
8617 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8620 /* The function outputs PHR interface functions `dfa_clean_insn_cache'
8621 and 'dfa_clear_single_insn_cache'. */
8622 static void
8623 output_dfa_clean_insn_cache_func (void)
8625 fprintf (output_file,
8626 "void\n%s (void)\n{\n int %s;\n\n",
8627 DFA_CLEAN_INSN_CACHE_FUNC_NAME, I_VARIABLE_NAME);
8628 fprintf (output_file,
8629 " for (%s = 0; %s < %s; %s++)\n %s [%s] = -1;\n}\n\n",
8630 I_VARIABLE_NAME, I_VARIABLE_NAME,
8631 DFA_INSN_CODES_LENGTH_VARIABLE_NAME, I_VARIABLE_NAME,
8632 DFA_INSN_CODES_VARIABLE_NAME, I_VARIABLE_NAME);
8634 fprintf (output_file,
8635 "void\n%s (rtx %s)\n{\n int %s;\n\n",
8636 DFA_CLEAR_SINGLE_INSN_CACHE_FUNC_NAME, INSN_PARAMETER_NAME,
8637 I_VARIABLE_NAME);
8638 fprintf (output_file,
8639 " %s = INSN_UID (%s);\n if (%s < %s)\n %s [%s] = -1;\n}\n\n",
8640 I_VARIABLE_NAME, INSN_PARAMETER_NAME, I_VARIABLE_NAME,
8641 DFA_INSN_CODES_LENGTH_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
8642 I_VARIABLE_NAME);
8645 /* The function outputs PHR interface function `dfa_start'. */
8646 static void
8647 output_dfa_start_func (void)
8649 fprintf (output_file,
8650 "void\n%s (void)\n{\n %s = get_max_uid ();\n",
8651 DFA_START_FUNC_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8652 fprintf (output_file, " %s = XNEWVEC (int, %s);\n",
8653 DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8654 fprintf (output_file, " %s ();\n}\n\n", DFA_CLEAN_INSN_CACHE_FUNC_NAME);
8657 /* The function outputs PHR interface function `dfa_finish'. */
8658 static void
8659 output_dfa_finish_func (void)
8661 fprintf (output_file, "void\n%s (void)\n{\n free (%s);\n}\n\n",
8662 DFA_FINISH_FUNC_NAME, DFA_INSN_CODES_VARIABLE_NAME);
8667 /* The page contains code for output description file (readable
8668 representation of original description and generated DFA(s). */
8670 /* The function outputs string representation of IR reservation. */
8671 static void
8672 output_regexp (regexp_t regexp)
8674 fprintf (output_description_file, "%s", regexp_representation (regexp));
8675 finish_regexp_representation ();
8678 /* Output names of units in LIST separated by comma. */
8679 static void
8680 output_unit_set_el_list (unit_set_el_t list)
8682 unit_set_el_t el;
8684 for (el = list; el != NULL; el = el->next_unit_set_el)
8686 if (el != list)
8687 fprintf (output_description_file, ", ");
8688 fprintf (output_description_file, "%s", el->unit_decl->name);
8692 /* Output patterns in LIST separated by comma. */
8693 static void
8694 output_pattern_set_el_list (pattern_set_el_t list)
8696 pattern_set_el_t el;
8697 int i;
8699 for (el = list; el != NULL; el = el->next_pattern_set_el)
8701 if (el != list)
8702 fprintf (output_description_file, ", ");
8703 for (i = 0; i < el->units_num; i++)
8704 fprintf (output_description_file, (i == 0 ? "%s" : " %s"),
8705 el->unit_decls [i]->name);
8709 /* The function outputs string representation of IR define_reservation
8710 and define_insn_reservation. */
8711 static void
8712 output_description (void)
8714 decl_t decl;
8715 int i;
8717 for (i = 0; i < description->decls_num; i++)
8719 decl = description->decls [i];
8720 if (decl->mode == dm_unit)
8722 if (DECL_UNIT (decl)->excl_list != NULL)
8724 fprintf (output_description_file, "unit %s exclusion_set: ",
8725 DECL_UNIT (decl)->name);
8726 output_unit_set_el_list (DECL_UNIT (decl)->excl_list);
8727 fprintf (output_description_file, "\n");
8729 if (DECL_UNIT (decl)->presence_list != NULL)
8731 fprintf (output_description_file, "unit %s presence_set: ",
8732 DECL_UNIT (decl)->name);
8733 output_pattern_set_el_list (DECL_UNIT (decl)->presence_list);
8734 fprintf (output_description_file, "\n");
8736 if (DECL_UNIT (decl)->final_presence_list != NULL)
8738 fprintf (output_description_file, "unit %s final_presence_set: ",
8739 DECL_UNIT (decl)->name);
8740 output_pattern_set_el_list
8741 (DECL_UNIT (decl)->final_presence_list);
8742 fprintf (output_description_file, "\n");
8744 if (DECL_UNIT (decl)->absence_list != NULL)
8746 fprintf (output_description_file, "unit %s absence_set: ",
8747 DECL_UNIT (decl)->name);
8748 output_pattern_set_el_list (DECL_UNIT (decl)->absence_list);
8749 fprintf (output_description_file, "\n");
8751 if (DECL_UNIT (decl)->final_absence_list != NULL)
8753 fprintf (output_description_file, "unit %s final_absence_set: ",
8754 DECL_UNIT (decl)->name);
8755 output_pattern_set_el_list
8756 (DECL_UNIT (decl)->final_absence_list);
8757 fprintf (output_description_file, "\n");
8761 fprintf (output_description_file, "\n");
8762 for (i = 0; i < description->decls_num; i++)
8764 decl = description->decls [i];
8765 if (decl->mode == dm_reserv)
8767 fprintf (output_description_file, "reservation %s: ",
8768 DECL_RESERV (decl)->name);
8769 output_regexp (DECL_RESERV (decl)->regexp);
8770 fprintf (output_description_file, "\n");
8772 else if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
8774 fprintf (output_description_file, "insn reservation %s ",
8775 DECL_INSN_RESERV (decl)->name);
8776 print_rtl (output_description_file,
8777 DECL_INSN_RESERV (decl)->condexp);
8778 fprintf (output_description_file, ": ");
8779 output_regexp (DECL_INSN_RESERV (decl)->regexp);
8780 fprintf (output_description_file, "\n");
8782 else if (decl->mode == dm_bypass)
8783 fprintf (output_description_file, "bypass %d %s %s\n",
8784 DECL_BYPASS (decl)->latency,
8785 DECL_BYPASS (decl)->out_insn_name,
8786 DECL_BYPASS (decl)->in_insn_name);
8788 fprintf (output_description_file, "\n\f\n");
8791 /* The function outputs name of AUTOMATON. */
8792 static void
8793 output_automaton_name (FILE *f, automaton_t automaton)
8795 if (automaton->corresponding_automaton_decl == NULL)
8796 fprintf (f, "#%d", automaton->automaton_order_num);
8797 else
8798 fprintf (f, "`%s'", automaton->corresponding_automaton_decl->name);
8801 /* Maximal length of line for pretty printing into description
8802 file. */
8803 #define MAX_LINE_LENGTH 70
8805 /* The function outputs units name belonging to AUTOMATON. */
8806 static void
8807 output_automaton_units (automaton_t automaton)
8809 decl_t decl;
8810 const char *name;
8811 int curr_line_length;
8812 int there_is_an_automaton_unit;
8813 int i;
8815 fprintf (output_description_file, "\n Corresponding units:\n");
8816 fprintf (output_description_file, " ");
8817 curr_line_length = 4;
8818 there_is_an_automaton_unit = 0;
8819 for (i = 0; i < description->decls_num; i++)
8821 decl = description->decls [i];
8822 if (decl->mode == dm_unit
8823 && (DECL_UNIT (decl)->corresponding_automaton_num
8824 == automaton->automaton_order_num))
8826 there_is_an_automaton_unit = 1;
8827 name = DECL_UNIT (decl)->name;
8828 if (curr_line_length + strlen (name) + 1 > MAX_LINE_LENGTH )
8830 curr_line_length = strlen (name) + 4;
8831 fprintf (output_description_file, "\n ");
8833 else
8835 curr_line_length += strlen (name) + 1;
8836 fprintf (output_description_file, " ");
8838 fprintf (output_description_file, "%s", name);
8841 if (!there_is_an_automaton_unit)
8842 fprintf (output_description_file, "<None>");
8843 fprintf (output_description_file, "\n\n");
8846 /* The following variable is used for forming array of all possible cpu unit
8847 reservations described by the current DFA state. */
8848 static VEC(reserv_sets_t, heap) *state_reservs;
8850 /* The function forms `state_reservs' for STATE. */
8851 static void
8852 add_state_reservs (state_t state)
8854 alt_state_t curr_alt_state;
8856 if (state->component_states != NULL)
8857 for (curr_alt_state = state->component_states;
8858 curr_alt_state != NULL;
8859 curr_alt_state = curr_alt_state->next_sorted_alt_state)
8860 add_state_reservs (curr_alt_state->state);
8861 else
8862 VEC_safe_push (reserv_sets_t, heap, state_reservs, state->reservs);
8865 /* The function outputs readable representation of all out arcs of
8866 STATE. */
8867 static void
8868 output_state_arcs (state_t state)
8870 arc_t arc;
8871 ainsn_t ainsn;
8872 const char *insn_name;
8873 int curr_line_length;
8875 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
8877 ainsn = arc->insn;
8878 gcc_assert (ainsn->first_insn_with_same_reservs);
8879 fprintf (output_description_file, " ");
8880 curr_line_length = 7;
8881 fprintf (output_description_file, "%2d: ", ainsn->insn_equiv_class_num);
8884 insn_name = ainsn->insn_reserv_decl->name;
8885 if (curr_line_length + strlen (insn_name) > MAX_LINE_LENGTH)
8887 if (ainsn != arc->insn)
8889 fprintf (output_description_file, ",\n ");
8890 curr_line_length = strlen (insn_name) + 6;
8892 else
8893 curr_line_length += strlen (insn_name);
8895 else
8897 curr_line_length += strlen (insn_name);
8898 if (ainsn != arc->insn)
8900 curr_line_length += 2;
8901 fprintf (output_description_file, ", ");
8904 fprintf (output_description_file, "%s", insn_name);
8905 ainsn = ainsn->next_same_reservs_insn;
8907 while (ainsn != NULL);
8908 fprintf (output_description_file, " %d \n",
8909 arc->to_state->order_state_num);
8911 fprintf (output_description_file, "\n");
8914 /* The following function is used for sorting possible cpu unit
8915 reservation of a DFA state. */
8916 static int
8917 state_reservs_cmp (const void *reservs_ptr_1, const void *reservs_ptr_2)
8919 return reserv_sets_cmp (*(const_reserv_sets_t const*) reservs_ptr_1,
8920 *(const_reserv_sets_t const*) reservs_ptr_2);
8923 /* The following function is used for sorting possible cpu unit
8924 reservation of a DFA state. */
8925 static void
8926 remove_state_duplicate_reservs (void)
8928 size_t i, j;
8930 for (i = 1, j = 0; i < VEC_length (reserv_sets_t, state_reservs); i++)
8931 if (reserv_sets_cmp (VEC_index (reserv_sets_t, state_reservs, j),
8932 VEC_index (reserv_sets_t, state_reservs, i)))
8934 j++;
8935 VEC_replace (reserv_sets_t, state_reservs, j,
8936 VEC_index (reserv_sets_t, state_reservs, i));
8938 VEC_truncate (reserv_sets_t, state_reservs, j + 1);
8941 /* The following function output readable representation of DFA(s)
8942 state used for fast recognition of pipeline hazards. State is
8943 described by possible (current and scheduled) cpu unit
8944 reservations. */
8945 static void
8946 output_state (state_t state)
8948 size_t i;
8950 state_reservs = 0;
8952 fprintf (output_description_file, " State #%d", state->order_state_num);
8953 fprintf (output_description_file,
8954 state->new_cycle_p ? " (new cycle)\n" : "\n");
8955 add_state_reservs (state);
8956 qsort (VEC_address (reserv_sets_t, state_reservs),
8957 VEC_length (reserv_sets_t, state_reservs),
8958 sizeof (reserv_sets_t), state_reservs_cmp);
8959 remove_state_duplicate_reservs ();
8960 for (i = 0; i < VEC_length (reserv_sets_t, state_reservs); i++)
8962 fprintf (output_description_file, " ");
8963 output_reserv_sets (output_description_file,
8964 VEC_index (reserv_sets_t, state_reservs, i));
8965 fprintf (output_description_file, "\n");
8967 fprintf (output_description_file, "\n");
8968 output_state_arcs (state);
8969 VEC_free (reserv_sets_t, heap, state_reservs);
8972 /* The following function output readable representation of
8973 DFAs used for fast recognition of pipeline hazards. */
8974 static void
8975 output_automaton_descriptions (void)
8977 automaton_t automaton;
8979 for (automaton = description->first_automaton;
8980 automaton != NULL;
8981 automaton = automaton->next_automaton)
8983 fprintf (output_description_file, "\nAutomaton ");
8984 output_automaton_name (output_description_file, automaton);
8985 fprintf (output_description_file, "\n");
8986 output_automaton_units (automaton);
8987 pass_states (automaton, output_state);
8993 /* The page contains top level function for generation DFA(s) used for
8994 PHR. */
8996 /* The function outputs statistics about work of different phases of
8997 DFA generator. */
8998 static void
8999 output_statistics (FILE *f)
9001 automaton_t automaton;
9002 int states_num;
9003 #ifndef NDEBUG
9004 int transition_comb_vect_els = 0;
9005 int transition_full_vect_els = 0;
9006 int min_issue_delay_vect_els = 0;
9007 int locked_states = 0;
9008 #endif
9010 for (automaton = description->first_automaton;
9011 automaton != NULL;
9012 automaton = automaton->next_automaton)
9014 fprintf (f, "\nAutomaton ");
9015 output_automaton_name (f, automaton);
9016 fprintf (f, "\n %5d NDFA states, %5d NDFA arcs\n",
9017 automaton->NDFA_states_num, automaton->NDFA_arcs_num);
9018 fprintf (f, " %5d DFA states, %5d DFA arcs\n",
9019 automaton->DFA_states_num, automaton->DFA_arcs_num);
9020 states_num = automaton->DFA_states_num;
9021 if (!no_minimization_flag)
9023 fprintf (f, " %5d minimal DFA states, %5d minimal DFA arcs\n",
9024 automaton->minimal_DFA_states_num,
9025 automaton->minimal_DFA_arcs_num);
9026 states_num = automaton->minimal_DFA_states_num;
9028 fprintf (f, " %5d all insns %5d insn equivalence classes\n",
9029 description->insns_num, automaton->insn_equiv_classes_num);
9030 fprintf (f, " %d locked states\n", automaton->locked_states);
9031 #ifndef NDEBUG
9032 fprintf
9033 (f, "%5ld transition comb vector els, %5ld trans table els: %s\n",
9034 (long) VEC_length (vect_el_t, automaton->trans_table->comb_vect),
9035 (long) VEC_length (vect_el_t, automaton->trans_table->full_vect),
9036 (comb_vect_p (automaton->trans_table)
9037 ? "use comb vect" : "use simple vect"));
9038 fprintf
9039 (f, "%5ld min delay table els, compression factor %d\n",
9040 (long) states_num * automaton->insn_equiv_classes_num,
9041 automaton->min_issue_delay_table_compression_factor);
9042 transition_comb_vect_els
9043 += VEC_length (vect_el_t, automaton->trans_table->comb_vect);
9044 transition_full_vect_els
9045 += VEC_length (vect_el_t, automaton->trans_table->full_vect);
9046 min_issue_delay_vect_els
9047 += states_num * automaton->insn_equiv_classes_num;
9048 locked_states
9049 += automaton->locked_states;
9050 #endif
9052 #ifndef NDEBUG
9053 fprintf (f, "\n%5d all allocated states, %5d all allocated arcs\n",
9054 allocated_states_num, allocated_arcs_num);
9055 fprintf (f, "%5d all allocated alternative states\n",
9056 allocated_alt_states_num);
9057 fprintf (f, "%5d all transition comb vector els, %5d all trans table els\n",
9058 transition_comb_vect_els, transition_full_vect_els);
9059 fprintf (f, "%5d all min delay table els\n", min_issue_delay_vect_els);
9060 fprintf (f, "%5d all locked states\n", locked_states);
9061 #endif
9064 /* The function output times of work of different phases of DFA
9065 generator. */
9066 static void
9067 output_time_statistics (FILE *f)
9069 fprintf (f, "\n transformation: ");
9070 print_active_time (f, transform_time);
9071 fprintf (f, (!ndfa_flag ? ", building DFA: " : ", building NDFA: "));
9072 print_active_time (f, NDFA_time);
9073 if (ndfa_flag)
9075 fprintf (f, ", NDFA -> DFA: ");
9076 print_active_time (f, NDFA_to_DFA_time);
9078 fprintf (f, "\n DFA minimization: ");
9079 print_active_time (f, minimize_time);
9080 fprintf (f, ", making insn equivalence: ");
9081 print_active_time (f, equiv_time);
9082 fprintf (f, "\n all automaton generation: ");
9083 print_active_time (f, automaton_generation_time);
9084 fprintf (f, ", output: ");
9085 print_active_time (f, output_time);
9086 fprintf (f, "\n");
9089 /* The function generates DFA (deterministic finite state automaton)
9090 for fast recognition of pipeline hazards. No errors during
9091 checking must be fixed before this function call. */
9092 static void
9093 generate (void)
9095 automata_num = split_argument;
9096 if (description->units_num < automata_num)
9097 automata_num = description->units_num;
9098 initiate_states ();
9099 initiate_arcs ();
9100 initiate_automata_lists ();
9101 initiate_pass_states ();
9102 initiate_excl_sets ();
9103 initiate_presence_absence_pattern_sets ();
9104 automaton_generation_time = create_ticker ();
9105 create_automata ();
9106 ticker_off (&automaton_generation_time);
9111 /* This page mainly contains top level functions of pipeline hazards
9112 description translator. */
9114 /* The following macro value is suffix of name of description file of
9115 pipeline hazards description translator. */
9116 #define STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX ".dfa"
9118 /* The function returns suffix of given file name. The returned
9119 string can not be changed. */
9120 static const char *
9121 file_name_suffix (const char *file_name)
9123 const char *last_period;
9125 for (last_period = NULL; *file_name != '\0'; file_name++)
9126 if (*file_name == '.')
9127 last_period = file_name;
9128 return (last_period == NULL ? file_name : last_period);
9131 /* The function returns base name of given file name, i.e. pointer to
9132 first char after last `/' (or `\' for WIN32) in given file name,
9133 given file name itself if the directory name is absent. The
9134 returned string can not be changed. */
9135 static const char *
9136 base_file_name (const char *file_name)
9138 int directory_name_length;
9140 directory_name_length = strlen (file_name);
9141 #ifdef WIN32
9142 while (directory_name_length >= 0 && file_name[directory_name_length] != '/'
9143 && file_name[directory_name_length] != '\\')
9144 #else
9145 while (directory_name_length >= 0 && file_name[directory_name_length] != '/')
9146 #endif
9147 directory_name_length--;
9148 return file_name + directory_name_length + 1;
9151 /* The following is top level function to initialize the work of
9152 pipeline hazards description translator. */
9153 static void
9154 initiate_automaton_gen (int argc, char **argv)
9156 const char *base_name;
9157 int i;
9159 ndfa_flag = 0;
9160 split_argument = 0; /* default value */
9161 no_minimization_flag = 0;
9162 time_flag = 0;
9163 stats_flag = 0;
9164 v_flag = 0;
9165 w_flag = 0;
9166 progress_flag = 0;
9167 for (i = 2; i < argc; i++)
9168 if (strcmp (argv [i], NO_MINIMIZATION_OPTION) == 0)
9169 no_minimization_flag = 1;
9170 else if (strcmp (argv [i], TIME_OPTION) == 0)
9171 time_flag = 1;
9172 else if (strcmp (argv [i], STATS_OPTION) == 0)
9173 stats_flag = 1;
9174 else if (strcmp (argv [i], V_OPTION) == 0)
9175 v_flag = 1;
9176 else if (strcmp (argv [i], W_OPTION) == 0)
9177 w_flag = 1;
9178 else if (strcmp (argv [i], NDFA_OPTION) == 0)
9179 ndfa_flag = 1;
9180 else if (strcmp (argv [i], PROGRESS_OPTION) == 0)
9181 progress_flag = 1;
9182 else if (strcmp (argv [i], "-split") == 0)
9184 if (i + 1 >= argc)
9185 fatal ("-split has no argument.");
9186 fatal ("option `-split' has not been implemented yet\n");
9187 /* split_argument = atoi (argument_vect [i + 1]); */
9190 /* Initialize IR storage. */
9191 obstack_init (&irp);
9192 initiate_automaton_decl_table ();
9193 initiate_insn_decl_table ();
9194 initiate_decl_table ();
9195 output_file = stdout;
9196 output_description_file = NULL;
9197 base_name = base_file_name (argv[1]);
9198 obstack_grow (&irp, base_name,
9199 strlen (base_name) - strlen (file_name_suffix (base_name)));
9200 obstack_grow (&irp, STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX,
9201 strlen (STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX) + 1);
9202 obstack_1grow (&irp, '\0');
9203 output_description_file_name = obstack_base (&irp);
9204 obstack_finish (&irp);
9207 /* The following function checks existence at least one arc marked by
9208 each insn. */
9209 static void
9210 check_automata_insn_issues (void)
9212 automaton_t automaton;
9213 ainsn_t ainsn, reserv_ainsn;
9215 for (automaton = description->first_automaton;
9216 automaton != NULL;
9217 automaton = automaton->next_automaton)
9219 for (ainsn = automaton->ainsn_list;
9220 ainsn != NULL;
9221 ainsn = ainsn->next_ainsn)
9222 if (ainsn->first_insn_with_same_reservs && !ainsn->arc_exists_p)
9224 for (reserv_ainsn = ainsn;
9225 reserv_ainsn != NULL;
9226 reserv_ainsn = reserv_ainsn->next_same_reservs_insn)
9227 if (automaton->corresponding_automaton_decl != NULL)
9229 if (!w_flag)
9230 error ("Automaton `%s': Insn `%s' will never be issued",
9231 automaton->corresponding_automaton_decl->name,
9232 reserv_ainsn->insn_reserv_decl->name);
9233 else
9234 warning ("Automaton `%s': Insn `%s' will never be issued",
9235 automaton->corresponding_automaton_decl->name,
9236 reserv_ainsn->insn_reserv_decl->name);
9238 else
9240 if (!w_flag)
9241 error ("Insn `%s' will never be issued",
9242 reserv_ainsn->insn_reserv_decl->name);
9243 else
9244 warning ("Insn `%s' will never be issued",
9245 reserv_ainsn->insn_reserv_decl->name);
9251 /* The following vla is used for storing pointers to all achieved
9252 states. */
9253 static VEC(state_t, heap) *automaton_states;
9255 /* This function is called by function pass_states to add an achieved
9256 STATE. */
9257 static void
9258 add_automaton_state (state_t state)
9260 VEC_safe_push (state_t, heap, automaton_states, state);
9263 /* The following function forms list of important automata (whose
9264 states may be changed after the insn issue) for each insn. */
9265 static void
9266 form_important_insn_automata_lists (void)
9268 automaton_t automaton;
9269 decl_t decl;
9270 ainsn_t ainsn;
9271 arc_t arc;
9272 int i;
9273 size_t n;
9275 automaton_states = 0;
9276 /* Mark important ainsns. */
9277 for (automaton = description->first_automaton;
9278 automaton != NULL;
9279 automaton = automaton->next_automaton)
9281 VEC_truncate (state_t, automaton_states, 0);
9282 pass_states (automaton, add_automaton_state);
9283 for (n = 0; n < VEC_length (state_t, automaton_states); n++)
9285 state_t s = VEC_index (state_t, automaton_states, n);
9286 for (arc = first_out_arc (s);
9287 arc != NULL;
9288 arc = next_out_arc (arc))
9289 if (arc->to_state != s)
9291 gcc_assert (arc->insn->first_insn_with_same_reservs);
9292 for (ainsn = arc->insn;
9293 ainsn != NULL;
9294 ainsn = ainsn->next_same_reservs_insn)
9295 ainsn->important_p = TRUE;
9299 VEC_free (state_t, heap, automaton_states);
9301 /* Create automata sets for the insns. */
9302 for (i = 0; i < description->decls_num; i++)
9304 decl = description->decls [i];
9305 if (decl->mode == dm_insn_reserv)
9307 automata_list_start ();
9308 for (automaton = description->first_automaton;
9309 automaton != NULL;
9310 automaton = automaton->next_automaton)
9311 for (ainsn = automaton->ainsn_list;
9312 ainsn != NULL;
9313 ainsn = ainsn->next_ainsn)
9314 if (ainsn->important_p
9315 && ainsn->insn_reserv_decl == DECL_INSN_RESERV (decl))
9317 automata_list_add (automaton);
9318 break;
9320 DECL_INSN_RESERV (decl)->important_automata_list
9321 = automata_list_finish ();
9327 /* The following is top level function to generate automat(a,on) for
9328 fast recognition of pipeline hazards. */
9329 static void
9330 expand_automata (void)
9332 int i;
9334 description = XCREATENODEVAR (struct description,
9335 sizeof (struct description)
9336 /* One entry for cycle advancing insn. */
9337 + sizeof (decl_t) * VEC_length (decl_t, decls));
9338 description->decls_num = VEC_length (decl_t, decls);
9339 description->query_units_num = 0;
9340 for (i = 0; i < description->decls_num; i++)
9342 description->decls [i] = VEC_index (decl_t, decls, i);
9343 if (description->decls [i]->mode == dm_unit
9344 && DECL_UNIT (description->decls [i])->query_p)
9345 DECL_UNIT (description->decls [i])->query_num
9346 = description->query_units_num++;
9348 all_time = create_ticker ();
9349 check_time = create_ticker ();
9350 if (progress_flag)
9351 fprintf (stderr, "Check description...");
9352 check_all_description ();
9353 if (progress_flag)
9354 fprintf (stderr, "done\n");
9355 ticker_off (&check_time);
9356 generation_time = create_ticker ();
9357 if (!have_error)
9359 transform_insn_regexps ();
9360 check_unit_distributions_to_automata ();
9362 if (!have_error)
9364 generate ();
9365 check_automata_insn_issues ();
9367 if (!have_error)
9369 form_important_insn_automata_lists ();
9371 ticker_off (&generation_time);
9374 /* The following is top level function to output PHR and to finish
9375 work with pipeline description translator. */
9376 static void
9377 write_automata (void)
9379 output_time = create_ticker ();
9380 if (progress_flag)
9381 fprintf (stderr, "Forming and outputting automata tables...");
9382 output_tables ();
9383 if (progress_flag)
9385 fprintf (stderr, "done\n");
9386 fprintf (stderr, "Output functions to work with automata...");
9388 output_chip_definitions ();
9389 output_max_insn_queue_index_def ();
9390 output_internal_min_issue_delay_func ();
9391 output_internal_trans_func ();
9392 /* Cache of insn dfa codes: */
9393 fprintf (output_file, "\nstatic int *%s;\n", DFA_INSN_CODES_VARIABLE_NAME);
9394 fprintf (output_file, "\nstatic int %s;\n\n",
9395 DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
9396 output_dfa_insn_code_func ();
9397 output_trans_func ();
9398 output_min_issue_delay_func ();
9399 output_internal_dead_lock_func ();
9400 output_dead_lock_func ();
9401 output_size_func ();
9402 output_internal_reset_func ();
9403 output_reset_func ();
9404 output_min_insn_conflict_delay_func ();
9405 output_default_latencies ();
9406 output_internal_insn_latency_func ();
9407 output_insn_latency_func ();
9408 output_internal_maximal_insn_latency_func ();
9409 output_maximal_insn_latency_func ();
9410 output_print_reservation_func ();
9411 /* Output function get_cpu_unit_code. */
9412 fprintf (output_file, "\n#if %s\n\n", CPU_UNITS_QUERY_MACRO_NAME);
9413 output_get_cpu_unit_code_func ();
9414 output_cpu_unit_reservation_p ();
9415 output_insn_has_dfa_reservation_p ();
9416 fprintf (output_file, "\n#endif /* #if %s */\n\n",
9417 CPU_UNITS_QUERY_MACRO_NAME);
9418 output_dfa_clean_insn_cache_func ();
9419 output_dfa_start_func ();
9420 output_dfa_finish_func ();
9421 if (progress_flag)
9422 fprintf (stderr, "done\n");
9423 if (v_flag)
9425 output_description_file = fopen (output_description_file_name, "w");
9426 if (output_description_file == NULL)
9428 perror (output_description_file_name);
9429 exit (FATAL_EXIT_CODE);
9431 if (progress_flag)
9432 fprintf (stderr, "Output automata description...");
9433 output_description ();
9434 output_automaton_descriptions ();
9435 if (progress_flag)
9436 fprintf (stderr, "done\n");
9437 output_statistics (output_description_file);
9439 if (stats_flag)
9440 output_statistics (stderr);
9441 ticker_off (&output_time);
9442 if (time_flag)
9443 output_time_statistics (stderr);
9444 finish_states ();
9445 finish_arcs ();
9446 finish_automata_lists ();
9447 if (time_flag)
9449 fprintf (stderr, "Summary:\n");
9450 fprintf (stderr, " check time ");
9451 print_active_time (stderr, check_time);
9452 fprintf (stderr, ", generation time ");
9453 print_active_time (stderr, generation_time);
9454 fprintf (stderr, ", all time ");
9455 print_active_time (stderr, all_time);
9456 fprintf (stderr, "\n");
9458 /* Finish all work. */
9459 if (output_description_file != NULL)
9461 fflush (output_description_file);
9462 if (ferror (stdout) != 0)
9463 fatal ("Error in writing DFA description file %s: %s",
9464 output_description_file_name, xstrerror (errno));
9465 fclose (output_description_file);
9467 finish_automaton_decl_table ();
9468 finish_insn_decl_table ();
9469 finish_decl_table ();
9470 obstack_free (&irp, NULL);
9471 if (have_error && output_description_file != NULL)
9472 remove (output_description_file_name);
9476 main (int argc, char **argv)
9478 rtx desc;
9480 progname = "genautomata";
9482 if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
9483 return (FATAL_EXIT_CODE);
9485 initiate_automaton_gen (argc, argv);
9486 while (1)
9488 int lineno;
9489 int insn_code_number;
9491 desc = read_md_rtx (&lineno, &insn_code_number);
9492 if (desc == NULL)
9493 break;
9495 switch (GET_CODE (desc))
9497 case DEFINE_CPU_UNIT:
9498 gen_cpu_unit (desc);
9499 break;
9501 case DEFINE_QUERY_CPU_UNIT:
9502 gen_query_cpu_unit (desc);
9503 break;
9505 case DEFINE_BYPASS:
9506 gen_bypass (desc);
9507 break;
9509 case EXCLUSION_SET:
9510 gen_excl_set (desc);
9511 break;
9513 case PRESENCE_SET:
9514 gen_presence_set (desc);
9515 break;
9517 case FINAL_PRESENCE_SET:
9518 gen_final_presence_set (desc);
9519 break;
9521 case ABSENCE_SET:
9522 gen_absence_set (desc);
9523 break;
9525 case FINAL_ABSENCE_SET:
9526 gen_final_absence_set (desc);
9527 break;
9529 case DEFINE_AUTOMATON:
9530 gen_automaton (desc);
9531 break;
9533 case AUTOMATA_OPTION:
9534 gen_automata_option (desc);
9535 break;
9537 case DEFINE_RESERVATION:
9538 gen_reserv (desc);
9539 break;
9541 case DEFINE_INSN_RESERVATION:
9542 gen_insn_reserv (desc);
9543 break;
9545 default:
9546 break;
9550 if (have_error)
9551 return FATAL_EXIT_CODE;
9553 if (VEC_length (decl_t, decls) > 0)
9555 expand_automata ();
9556 if (!have_error)
9558 puts ("/* Generated automatically by the program `genautomata'\n"
9559 " from the machine description file `md'. */\n\n"
9560 "#include \"config.h\"\n"
9561 "#include \"system.h\"\n"
9562 "#include \"coretypes.h\"\n"
9563 "#include \"tm.h\"\n"
9564 "#include \"rtl.h\"\n"
9565 "#include \"tm_p.h\"\n"
9566 "#include \"insn-config.h\"\n"
9567 "#include \"recog.h\"\n"
9568 "#include \"regs.h\"\n"
9569 "#include \"real.h\"\n"
9570 "#include \"output.h\"\n"
9571 "#include \"insn-attr.h\"\n"
9572 "#include \"toplev.h\"\n"
9573 "#include \"flags.h\"\n"
9574 "#include \"function.h\"\n");
9576 write_automata ();
9580 fflush (stdout);
9581 return (ferror (stdout) != 0 || have_error
9582 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);