2011-07-21 François Dumont <francois.cppdevs@free.fr>
[official-gcc.git] / gcc / genautomata.c
blob71809661592f703d2c3440582a8c4de2bf700d74
1 /* Pipeline hazard description translator.
2 Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010
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 (repeat_vect[0]);
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 (allof_vect[0]);
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 (oneof_vect[0]);
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 (sequence_vect[0]);
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 VEC_qsort (alt_state_t, alt_states, alt_state_cmp);
3257 prev_unique_state_ind = 0;
3258 for (i = 1; i < VEC_length (alt_state_t, alt_states); i++)
3259 if (VEC_index (alt_state_t, alt_states, prev_unique_state_ind)->state
3260 != VEC_index (alt_state_t, alt_states, i)->state)
3262 prev_unique_state_ind++;
3263 VEC_replace (alt_state_t, alt_states, prev_unique_state_ind,
3264 VEC_index (alt_state_t, alt_states, i));
3266 VEC_truncate (alt_state_t, alt_states, prev_unique_state_ind + 1);
3268 for (i = 1; i < VEC_length (alt_state_t, alt_states); i++)
3269 VEC_index (alt_state_t, alt_states, i-1)->next_sorted_alt_state
3270 = VEC_index (alt_state_t, alt_states, i);
3271 VEC_last (alt_state_t, alt_states)->next_sorted_alt_state = 0;
3273 result = VEC_index (alt_state_t, alt_states, 0);
3275 VEC_free (alt_state_t, heap, alt_states);
3276 return result;
3279 /* The function checks equality of alt state lists. Remember that the
3280 lists must be already sorted by the previous function. */
3281 static int
3282 alt_states_eq (alt_state_t alt_states_1, alt_state_t alt_states_2)
3284 while (alt_states_1 != NULL && alt_states_2 != NULL
3285 && alt_state_cmp (&alt_states_1, &alt_states_2) == 0)
3287 alt_states_1 = alt_states_1->next_sorted_alt_state;
3288 alt_states_2 = alt_states_2->next_sorted_alt_state;
3290 return alt_states_1 == alt_states_2;
3293 /* Initialization of the abstract data. */
3294 static void
3295 initiate_alt_states (void)
3297 first_free_alt_state = NULL;
3300 /* Finishing work with the abstract data. */
3301 static void
3302 finish_alt_states (void)
3308 /* The page contains macros for work with bits strings. We could use
3309 standard gcc bitmap or sbitmap but it would result in difficulties
3310 of building canadian cross. */
3312 /* Set bit number bitno in the bit string. The macro is not side
3313 effect proof. */
3314 #define SET_BIT(bitstring, bitno) \
3315 ((bitstring)[(bitno) / (sizeof (*(bitstring)) * CHAR_BIT)] |= \
3316 (HOST_WIDE_INT)1 << (bitno) % (sizeof (*(bitstring)) * CHAR_BIT))
3318 #define CLEAR_BIT(bitstring, bitno) \
3319 ((bitstring)[(bitno) / (sizeof (*(bitstring)) * CHAR_BIT)] &= \
3320 ~((HOST_WIDE_INT)1 << (bitno) % (sizeof (*(bitstring)) * 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 ((bitstring)[(bitno) / (sizeof (*(bitstring)) * CHAR_BIT)] >> \
3326 (bitno) % (sizeof (*(bitstring)) * CHAR_BIT) & 1)
3330 /* This page contains abstract data `state'. */
3332 /* Maximal length of reservations in cycles (>= 1). */
3333 static int max_cycles_num;
3335 /* Number of set elements (see type set_el_t) needed for
3336 representation of one cycle reservation. It is depended on units
3337 number. */
3338 static int els_in_cycle_reserv;
3340 /* Number of set elements (see type set_el_t) needed for
3341 representation of maximal length reservation. Deterministic
3342 reservation is stored as set (bit string) of length equal to the
3343 variable value * number of bits in set_el_t. */
3344 static int els_in_reservs;
3346 /* Array of pointers to unit declarations. */
3347 static unit_decl_t *units_array;
3349 /* Temporary reservation of maximal length. */
3350 static reserv_sets_t temp_reserv;
3352 /* The state table itself is represented by the following variable. */
3353 static htab_t state_table;
3355 /* Linked list of free 'state' structures to be recycled. The
3356 next_equiv_class_state pointer is borrowed for a free list. */
3357 static state_t first_free_state;
3359 static int curr_unique_state_num;
3361 #ifndef NDEBUG
3362 /* The following variables is maximal number of allocated nodes
3363 `state'. */
3364 static int allocated_states_num = 0;
3365 #endif
3367 /* Allocate new reservation set. */
3368 static reserv_sets_t
3369 alloc_empty_reserv_sets (void)
3371 reserv_sets_t result;
3373 obstack_blank (&irp, els_in_reservs * sizeof (set_el_t));
3374 result = (reserv_sets_t) obstack_base (&irp);
3375 obstack_finish (&irp);
3376 memset (result, 0, els_in_reservs * sizeof (set_el_t));
3377 return result;
3380 /* Hash value of reservation set. */
3381 static unsigned
3382 reserv_sets_hash_value (reserv_sets_t reservs)
3384 set_el_t hash_value;
3385 unsigned result;
3386 int reservs_num, i;
3387 set_el_t *reserv_ptr;
3389 hash_value = 0;
3390 reservs_num = els_in_reservs;
3391 reserv_ptr = reservs;
3392 i = 0;
3393 while (reservs_num != 0)
3395 reservs_num--;
3396 hash_value += ((*reserv_ptr >> i)
3397 | (*reserv_ptr << (sizeof (set_el_t) * CHAR_BIT - i)));
3398 i++;
3399 if (i == sizeof (set_el_t) * CHAR_BIT)
3400 i = 0;
3401 reserv_ptr++;
3403 if (sizeof (set_el_t) <= sizeof (unsigned))
3404 return hash_value;
3405 result = 0;
3406 for (i = sizeof (set_el_t); i > 0; i -= sizeof (unsigned) - 1)
3408 result += (unsigned) hash_value;
3409 hash_value >>= (sizeof (unsigned) - 1) * CHAR_BIT;
3411 return result;
3414 /* Comparison of given reservation sets. */
3415 static int
3416 reserv_sets_cmp (const_reserv_sets_t reservs_1, const_reserv_sets_t reservs_2)
3418 int reservs_num;
3419 const set_el_t *reserv_ptr_1;
3420 const set_el_t *reserv_ptr_2;
3422 gcc_assert (reservs_1 && reservs_2);
3423 reservs_num = els_in_reservs;
3424 reserv_ptr_1 = reservs_1;
3425 reserv_ptr_2 = reservs_2;
3426 while (reservs_num != 0 && *reserv_ptr_1 == *reserv_ptr_2)
3428 reservs_num--;
3429 reserv_ptr_1++;
3430 reserv_ptr_2++;
3432 if (reservs_num == 0)
3433 return 0;
3434 else if (*reserv_ptr_1 < *reserv_ptr_2)
3435 return -1;
3436 else
3437 return 1;
3440 /* The function checks equality of the reservation sets. */
3441 static int
3442 reserv_sets_eq (const_reserv_sets_t reservs_1, const_reserv_sets_t reservs_2)
3444 return reserv_sets_cmp (reservs_1, reservs_2) == 0;
3447 /* Set up in the reservation set that unit with UNIT_NUM is used on
3448 CYCLE_NUM. */
3449 static void
3450 set_unit_reserv (reserv_sets_t reservs, int cycle_num, int unit_num)
3452 gcc_assert (cycle_num < max_cycles_num);
3453 SET_BIT (reservs, cycle_num * els_in_cycle_reserv
3454 * sizeof (set_el_t) * CHAR_BIT + unit_num);
3457 /* Set up in the reservation set RESERVS that unit with UNIT_NUM is
3458 used on CYCLE_NUM. */
3459 static int
3460 test_unit_reserv (reserv_sets_t reservs, int cycle_num, int unit_num)
3462 gcc_assert (cycle_num < max_cycles_num);
3463 return TEST_BIT (reservs, cycle_num * els_in_cycle_reserv
3464 * sizeof (set_el_t) * CHAR_BIT + unit_num);
3467 /* The function checks that the reservation sets are intersected,
3468 i.e. there is a unit reservation on a cycle in both reservation
3469 sets. */
3470 static int
3471 reserv_sets_are_intersected (reserv_sets_t operand_1,
3472 reserv_sets_t operand_2)
3474 set_el_t *el_ptr_1;
3475 set_el_t *el_ptr_2;
3476 set_el_t *cycle_ptr_1;
3477 set_el_t *cycle_ptr_2;
3479 gcc_assert (operand_1 && operand_2);
3480 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2;
3481 el_ptr_1 < operand_1 + els_in_reservs;
3482 el_ptr_1++, el_ptr_2++)
3483 if (*el_ptr_1 & *el_ptr_2)
3484 return 1;
3485 reserv_sets_or (temp_reserv, operand_1, operand_2);
3486 for (cycle_ptr_1 = operand_1, cycle_ptr_2 = operand_2;
3487 cycle_ptr_1 < operand_1 + els_in_reservs;
3488 cycle_ptr_1 += els_in_cycle_reserv, cycle_ptr_2 += els_in_cycle_reserv)
3490 for (el_ptr_1 = cycle_ptr_1, el_ptr_2 = get_excl_set (cycle_ptr_2);
3491 el_ptr_1 < cycle_ptr_1 + els_in_cycle_reserv;
3492 el_ptr_1++, el_ptr_2++)
3493 if (*el_ptr_1 & *el_ptr_2)
3494 return 1;
3495 if (!check_presence_pattern_sets (cycle_ptr_1, cycle_ptr_2, FALSE))
3496 return 1;
3497 if (!check_presence_pattern_sets (temp_reserv + (cycle_ptr_2
3498 - operand_2),
3499 cycle_ptr_2, TRUE))
3500 return 1;
3501 if (!check_absence_pattern_sets (cycle_ptr_1, cycle_ptr_2, FALSE))
3502 return 1;
3503 if (!check_absence_pattern_sets (temp_reserv + (cycle_ptr_2 - operand_2),
3504 cycle_ptr_2, TRUE))
3505 return 1;
3507 return 0;
3510 /* The function sets up RESULT bits by bits of OPERAND shifted on one
3511 cpu cycle. The remaining bits of OPERAND (representing the last
3512 cycle unit reservations) are not changed. */
3513 static void
3514 reserv_sets_shift (reserv_sets_t result, reserv_sets_t operand)
3516 int i;
3518 gcc_assert (result && operand && result != operand);
3519 for (i = els_in_cycle_reserv; i < els_in_reservs; i++)
3520 result [i - els_in_cycle_reserv] = operand [i];
3523 /* OR of the reservation sets. */
3524 static void
3525 reserv_sets_or (reserv_sets_t result, reserv_sets_t operand_1,
3526 reserv_sets_t operand_2)
3528 set_el_t *el_ptr_1;
3529 set_el_t *el_ptr_2;
3530 set_el_t *result_set_el_ptr;
3532 gcc_assert (result && operand_1 && operand_2);
3533 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2, result_set_el_ptr = result;
3534 el_ptr_1 < operand_1 + els_in_reservs;
3535 el_ptr_1++, el_ptr_2++, result_set_el_ptr++)
3536 *result_set_el_ptr = *el_ptr_1 | *el_ptr_2;
3539 /* AND of the reservation sets. */
3540 static void
3541 reserv_sets_and (reserv_sets_t result, reserv_sets_t operand_1,
3542 reserv_sets_t operand_2)
3544 set_el_t *el_ptr_1;
3545 set_el_t *el_ptr_2;
3546 set_el_t *result_set_el_ptr;
3548 gcc_assert (result && operand_1 && operand_2);
3549 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2, result_set_el_ptr = result;
3550 el_ptr_1 < operand_1 + els_in_reservs;
3551 el_ptr_1++, el_ptr_2++, result_set_el_ptr++)
3552 *result_set_el_ptr = *el_ptr_1 & *el_ptr_2;
3555 /* The function outputs string representation of units reservation on
3556 cycle START_CYCLE in the reservation set. The function uses repeat
3557 construction if REPETITION_NUM > 1. */
3558 static void
3559 output_cycle_reservs (FILE *f, reserv_sets_t reservs, int start_cycle,
3560 int repetition_num)
3562 int unit_num;
3563 int reserved_units_num;
3565 reserved_units_num = 0;
3566 for (unit_num = 0; unit_num < description->units_num; unit_num++)
3567 if (TEST_BIT (reservs, start_cycle * els_in_cycle_reserv
3568 * sizeof (set_el_t) * CHAR_BIT + unit_num))
3569 reserved_units_num++;
3570 gcc_assert (repetition_num > 0);
3571 if (repetition_num != 1 && reserved_units_num > 1)
3572 fprintf (f, "(");
3573 reserved_units_num = 0;
3574 for (unit_num = 0;
3575 unit_num < description->units_num;
3576 unit_num++)
3577 if (TEST_BIT (reservs, start_cycle * els_in_cycle_reserv
3578 * sizeof (set_el_t) * CHAR_BIT + unit_num))
3580 if (reserved_units_num != 0)
3581 fprintf (f, "+");
3582 reserved_units_num++;
3583 fprintf (f, "%s", units_array [unit_num]->name);
3585 if (reserved_units_num == 0)
3586 fprintf (f, NOTHING_NAME);
3587 gcc_assert (repetition_num > 0);
3588 if (repetition_num != 1 && reserved_units_num > 1)
3589 fprintf (f, ")");
3590 if (repetition_num != 1)
3591 fprintf (f, "*%d", repetition_num);
3594 /* The function outputs string representation of units reservation in
3595 the reservation set. */
3596 static void
3597 output_reserv_sets (FILE *f, reserv_sets_t reservs)
3599 int start_cycle = 0;
3600 int cycle;
3601 int repetition_num;
3603 repetition_num = 0;
3604 for (cycle = 0; cycle < max_cycles_num; cycle++)
3605 if (repetition_num == 0)
3607 repetition_num++;
3608 start_cycle = cycle;
3610 else if (memcmp
3611 ((char *) reservs + start_cycle * els_in_cycle_reserv
3612 * sizeof (set_el_t),
3613 (char *) reservs + cycle * els_in_cycle_reserv
3614 * sizeof (set_el_t),
3615 els_in_cycle_reserv * sizeof (set_el_t)) == 0)
3616 repetition_num++;
3617 else
3619 if (start_cycle != 0)
3620 fprintf (f, ", ");
3621 output_cycle_reservs (f, reservs, start_cycle, repetition_num);
3622 repetition_num = 1;
3623 start_cycle = cycle;
3625 if (start_cycle < max_cycles_num)
3627 if (start_cycle != 0)
3628 fprintf (f, ", ");
3629 output_cycle_reservs (f, reservs, start_cycle, repetition_num);
3633 /* The following function returns free node state for AUTOMATON. It
3634 may be new allocated node or node freed earlier. The function also
3635 allocates reservation set if WITH_RESERVS has nonzero value. */
3636 static state_t
3637 get_free_state (int with_reservs, automaton_t automaton)
3639 state_t result;
3641 gcc_assert (max_cycles_num > 0 && automaton);
3642 if (first_free_state)
3644 result = first_free_state;
3645 first_free_state = result->next_equiv_class_state;
3647 result->next_equiv_class_state = NULL;
3648 result->automaton = automaton;
3649 result->first_out_arc = NULL;
3650 result->it_was_placed_in_stack_for_NDFA_forming = 0;
3651 result->it_was_placed_in_stack_for_DFA_forming = 0;
3652 result->component_states = NULL;
3654 else
3656 #ifndef NDEBUG
3657 allocated_states_num++;
3658 #endif
3659 result = XCREATENODE (struct state);
3660 result->automaton = automaton;
3661 result->first_out_arc = NULL;
3662 result->unique_num = curr_unique_state_num;
3663 curr_unique_state_num++;
3665 if (with_reservs)
3667 if (result->reservs == NULL)
3668 result->reservs = alloc_empty_reserv_sets ();
3669 else
3670 memset (result->reservs, 0, els_in_reservs * sizeof (set_el_t));
3672 return result;
3675 /* The function frees node STATE. */
3676 static void
3677 free_state (state_t state)
3679 free_alt_states (state->component_states);
3680 state->next_equiv_class_state = first_free_state;
3681 first_free_state = state;
3684 /* Hash value of STATE. If STATE represents deterministic state it is
3685 simply hash value of the corresponding reservation set. Otherwise
3686 it is formed from hash values of the component deterministic
3687 states. One more key is order number of state automaton. */
3688 static hashval_t
3689 state_hash (const void *state)
3691 unsigned int hash_value;
3692 alt_state_t alt_state;
3694 if (((const_state_t) state)->component_states == NULL)
3695 hash_value = reserv_sets_hash_value (((const_state_t) state)->reservs);
3696 else
3698 hash_value = 0;
3699 for (alt_state = ((const_state_t) state)->component_states;
3700 alt_state != NULL;
3701 alt_state = alt_state->next_sorted_alt_state)
3702 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
3703 | (hash_value << CHAR_BIT))
3704 + alt_state->state->unique_num);
3706 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
3707 | (hash_value << CHAR_BIT))
3708 + ((const_state_t) state)->automaton->automaton_order_num);
3709 return hash_value;
3712 /* Return nonzero value if the states are the same. */
3713 static int
3714 state_eq_p (const void *state_1, const void *state_2)
3716 alt_state_t alt_state_1;
3717 alt_state_t alt_state_2;
3719 if (((const_state_t) state_1)->automaton != ((const_state_t) state_2)->automaton)
3720 return 0;
3721 else if (((const_state_t) state_1)->component_states == NULL
3722 && ((const_state_t) state_2)->component_states == NULL)
3723 return reserv_sets_eq (((const_state_t) state_1)->reservs,
3724 ((const_state_t) state_2)->reservs);
3725 else if (((const_state_t) state_1)->component_states != NULL
3726 && ((const_state_t) state_2)->component_states != NULL)
3728 for (alt_state_1 = ((const_state_t) state_1)->component_states,
3729 alt_state_2 = ((const_state_t) state_2)->component_states;
3730 alt_state_1 != NULL && alt_state_2 != NULL;
3731 alt_state_1 = alt_state_1->next_sorted_alt_state,
3732 alt_state_2 = alt_state_2->next_sorted_alt_state)
3733 /* All state in the list must be already in the hash table.
3734 Also the lists must be sorted. */
3735 if (alt_state_1->state != alt_state_2->state)
3736 return 0;
3737 return alt_state_1 == alt_state_2;
3739 else
3740 return 0;
3743 /* Insert STATE into the state table. */
3744 static state_t
3745 insert_state (state_t state)
3747 void **entry_ptr;
3749 entry_ptr = htab_find_slot (state_table, (void *) state, INSERT);
3750 if (*entry_ptr == NULL)
3751 *entry_ptr = (void *) state;
3752 return (state_t) *entry_ptr;
3755 /* Add reservation of unit with UNIT_NUM on cycle CYCLE_NUM to
3756 deterministic STATE. */
3757 static void
3758 set_state_reserv (state_t state, int cycle_num, int unit_num)
3760 set_unit_reserv (state->reservs, cycle_num, unit_num);
3763 /* Return nonzero value if the deterministic states contains a
3764 reservation of the same cpu unit on the same cpu cycle. */
3765 static int
3766 intersected_state_reservs_p (state_t state1, state_t state2)
3768 gcc_assert (state1->automaton == state2->automaton);
3769 return reserv_sets_are_intersected (state1->reservs, state2->reservs);
3772 /* Return deterministic state (inserted into the table) which
3773 representing the automaton state which is union of reservations of
3774 the deterministic states masked by RESERVS. */
3775 static state_t
3776 states_union (state_t state1, state_t state2, reserv_sets_t reservs)
3778 state_t result;
3779 state_t state_in_table;
3781 gcc_assert (state1->automaton == state2->automaton);
3782 result = get_free_state (1, state1->automaton);
3783 reserv_sets_or (result->reservs, state1->reservs, state2->reservs);
3784 reserv_sets_and (result->reservs, result->reservs, reservs);
3785 state_in_table = insert_state (result);
3786 if (result != state_in_table)
3788 free_state (result);
3789 result = state_in_table;
3791 return result;
3794 /* Return deterministic state (inserted into the table) which
3795 represent the automaton state is obtained from deterministic STATE
3796 by advancing cpu cycle and masking by RESERVS. */
3797 static state_t
3798 state_shift (state_t state, reserv_sets_t reservs)
3800 state_t result;
3801 state_t state_in_table;
3803 result = get_free_state (1, state->automaton);
3804 reserv_sets_shift (result->reservs, state->reservs);
3805 reserv_sets_and (result->reservs, result->reservs, reservs);
3806 state_in_table = insert_state (result);
3807 if (result != state_in_table)
3809 free_state (result);
3810 result = state_in_table;
3812 return result;
3815 /* Initialization of the abstract data. */
3816 static void
3817 initiate_states (void)
3819 decl_t decl;
3820 int i;
3822 if (description->units_num)
3823 units_array = XNEWVEC (unit_decl_t, description->units_num);
3824 else
3825 units_array = 0;
3827 for (i = 0; i < description->decls_num; i++)
3829 decl = description->decls [i];
3830 if (decl->mode == dm_unit)
3831 units_array [DECL_UNIT (decl)->unit_num] = DECL_UNIT (decl);
3833 max_cycles_num = description->max_insn_reserv_cycles;
3834 els_in_cycle_reserv
3835 = ((description->units_num + sizeof (set_el_t) * CHAR_BIT - 1)
3836 / (sizeof (set_el_t) * CHAR_BIT));
3837 els_in_reservs = els_in_cycle_reserv * max_cycles_num;
3838 curr_unique_state_num = 0;
3839 initiate_alt_states ();
3840 state_table = htab_create (1500, state_hash, state_eq_p, (htab_del) 0);
3841 temp_reserv = alloc_empty_reserv_sets ();
3844 /* Finishing work with the abstract data. */
3845 static void
3846 finish_states (void)
3848 free (units_array);
3849 units_array = 0;
3850 htab_delete (state_table);
3851 first_free_state = NULL;
3852 finish_alt_states ();
3857 /* Abstract data `arcs'. */
3859 /* List of free arcs. */
3860 static arc_t first_free_arc;
3862 #ifndef NDEBUG
3863 /* The following variables is maximal number of allocated nodes
3864 `arc'. */
3865 static int allocated_arcs_num = 0;
3866 #endif
3868 /* The function frees node ARC. */
3869 static void
3870 free_arc (arc_t arc)
3872 arc->next_out_arc = first_free_arc;
3873 first_free_arc = arc;
3876 /* The function removes and frees ARC staring from FROM_STATE. */
3877 static void
3878 remove_arc (state_t from_state, arc_t arc)
3880 arc_t prev_arc;
3881 arc_t curr_arc;
3883 gcc_assert (arc);
3884 for (prev_arc = NULL, curr_arc = from_state->first_out_arc;
3885 curr_arc != NULL;
3886 prev_arc = curr_arc, curr_arc = curr_arc->next_out_arc)
3887 if (curr_arc == arc)
3888 break;
3889 gcc_assert (curr_arc);
3890 if (prev_arc == NULL)
3891 from_state->first_out_arc = arc->next_out_arc;
3892 else
3893 prev_arc->next_out_arc = arc->next_out_arc;
3894 from_state->num_out_arcs--;
3895 free_arc (arc);
3898 /* The functions returns arc with given characteristics (or NULL if
3899 the arc does not exist). */
3900 static arc_t
3901 find_arc (state_t from_state, state_t to_state, ainsn_t insn)
3903 arc_t arc;
3905 for (arc = first_out_arc (from_state); arc != NULL; arc = next_out_arc (arc))
3906 if (arc->to_state == to_state && arc->insn == insn)
3907 return arc;
3908 return NULL;
3911 /* The function adds arc from FROM_STATE to TO_STATE marked by AINSN,
3912 unless such an arc already exists. */
3913 static void
3914 add_arc (state_t from_state, state_t to_state, ainsn_t ainsn)
3916 arc_t new_arc;
3918 new_arc = find_arc (from_state, to_state, ainsn);
3919 if (new_arc != NULL)
3920 return;
3921 if (first_free_arc == NULL)
3923 #ifndef NDEBUG
3924 allocated_arcs_num++;
3925 #endif
3926 new_arc = XCREATENODE (struct arc);
3927 new_arc->to_state = NULL;
3928 new_arc->insn = NULL;
3929 new_arc->next_out_arc = NULL;
3931 else
3933 new_arc = first_free_arc;
3934 first_free_arc = first_free_arc->next_out_arc;
3936 new_arc->to_state = to_state;
3937 new_arc->insn = ainsn;
3938 ainsn->arc_exists_p = 1;
3939 new_arc->next_out_arc = from_state->first_out_arc;
3940 from_state->first_out_arc = new_arc;
3941 from_state->num_out_arcs++;
3942 new_arc->next_arc_marked_by_insn = NULL;
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 el;
4178 unsigned int i;
4179 int start_unit_num;
4180 int unit_num;
4182 memset (excl_set, 0, els_in_cycle_reserv * sizeof (set_el_t));
4183 for (el = 0; el < els_in_cycle_reserv; el++)
4184 if (in_set[el])
4185 for (i = 0; i < CHAR_BIT * sizeof (set_el_t); i++)
4186 if ((in_set[el] >> i) & 1)
4188 start_unit_num = el * CHAR_BIT * sizeof (set_el_t) + i;
4189 if (start_unit_num >= description->units_num)
4190 return excl_set;
4191 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4193 excl_set [unit_num]
4194 |= unit_excl_set_table [start_unit_num] [unit_num];
4197 return excl_set;
4202 /* The page contains abstract data for work with presence/absence
4203 pattern sets (see presence_set/absence_set in file rtl.def). */
4205 /* The following arrays contain correspondingly presence, final
4206 presence, absence, and final absence patterns for each unit. */
4207 static pattern_reserv_t *unit_presence_set_table;
4208 static pattern_reserv_t *unit_final_presence_set_table;
4209 static pattern_reserv_t *unit_absence_set_table;
4210 static pattern_reserv_t *unit_final_absence_set_table;
4212 /* The following function forms list of reservation sets for given
4213 PATTERN_LIST. */
4214 static pattern_reserv_t
4215 form_reserv_sets_list (pattern_set_el_t pattern_list)
4217 pattern_set_el_t el;
4218 pattern_reserv_t first, curr, prev;
4219 int i;
4221 prev = first = NULL;
4222 for (el = pattern_list; el != NULL; el = el->next_pattern_set_el)
4224 curr = XCREATENODE (struct pattern_reserv);
4225 curr->reserv = alloc_empty_reserv_sets ();
4226 curr->next_pattern_reserv = NULL;
4227 for (i = 0; i < el->units_num; i++)
4229 SET_BIT (curr->reserv, el->unit_decls [i]->unit_num);
4230 el->unit_decls [i]->in_set_p = TRUE;
4232 if (prev != NULL)
4233 prev->next_pattern_reserv = curr;
4234 else
4235 first = curr;
4236 prev = curr;
4238 return first;
4241 /* The following function forms the array containing presence and
4242 absence pattern sets for each unit. */
4243 static void
4244 initiate_presence_absence_pattern_sets (void)
4246 decl_t decl;
4247 int i;
4249 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4250 unit_presence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4251 obstack_finish (&irp);
4252 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4253 unit_final_presence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4254 obstack_finish (&irp);
4255 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4256 unit_absence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4257 obstack_finish (&irp);
4258 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4259 unit_final_absence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4260 obstack_finish (&irp);
4261 /* Evaluate unit presence/absence sets. */
4262 for (i = 0; i < description->decls_num; i++)
4264 decl = description->decls [i];
4265 if (decl->mode == dm_unit)
4267 unit_presence_set_table [DECL_UNIT (decl)->unit_num]
4268 = form_reserv_sets_list (DECL_UNIT (decl)->presence_list);
4269 unit_final_presence_set_table [DECL_UNIT (decl)->unit_num]
4270 = form_reserv_sets_list (DECL_UNIT (decl)->final_presence_list);
4271 unit_absence_set_table [DECL_UNIT (decl)->unit_num]
4272 = form_reserv_sets_list (DECL_UNIT (decl)->absence_list);
4273 unit_final_absence_set_table [DECL_UNIT (decl)->unit_num]
4274 = form_reserv_sets_list (DECL_UNIT (decl)->final_absence_list);
4279 /* The function checks that CHECKED_SET satisfies all presence pattern
4280 sets for units in ORIGINAL_SET. The function returns TRUE if it
4281 is ok. */
4282 static int
4283 check_presence_pattern_sets (reserv_sets_t checked_set,
4284 reserv_sets_t original_set,
4285 int final_p)
4287 int el;
4288 unsigned int i;
4289 int start_unit_num;
4290 int unit_num;
4291 int presence_p;
4292 pattern_reserv_t pat_reserv;
4294 for (el = 0; el < els_in_cycle_reserv; el++)
4295 if (original_set[el])
4296 for (i = 0; i < CHAR_BIT * sizeof (set_el_t); i++)
4297 if ((original_set[el] >> i) & 1)
4299 start_unit_num = el * CHAR_BIT * sizeof (set_el_t) + i;
4300 if (start_unit_num >= description->units_num)
4301 break;
4302 if ((final_p
4303 && unit_final_presence_set_table [start_unit_num] == NULL)
4304 || (!final_p
4305 && unit_presence_set_table [start_unit_num] == NULL))
4306 continue;
4307 presence_p = FALSE;
4308 for (pat_reserv = (final_p
4309 ? unit_final_presence_set_table [start_unit_num]
4310 : unit_presence_set_table [start_unit_num]);
4311 pat_reserv != NULL;
4312 pat_reserv = pat_reserv->next_pattern_reserv)
4314 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4315 if ((checked_set [unit_num] & pat_reserv->reserv [unit_num])
4316 != pat_reserv->reserv [unit_num])
4317 break;
4318 presence_p = presence_p || unit_num >= els_in_cycle_reserv;
4320 if (!presence_p)
4321 return FALSE;
4323 return TRUE;
4326 /* The function checks that CHECKED_SET satisfies all absence pattern
4327 sets for units in ORIGINAL_SET. The function returns TRUE if it
4328 is ok. */
4329 static int
4330 check_absence_pattern_sets (reserv_sets_t checked_set,
4331 reserv_sets_t original_set,
4332 int final_p)
4334 int el;
4335 unsigned int i;
4336 int start_unit_num;
4337 int unit_num;
4338 pattern_reserv_t pat_reserv;
4340 for (el = 0; el < els_in_cycle_reserv; el++)
4341 if (original_set[el])
4342 for (i = 0; i < CHAR_BIT * sizeof (set_el_t); i++)
4343 if ((original_set[el] >> i) & 1)
4345 start_unit_num = el * CHAR_BIT * sizeof (set_el_t) + i;
4346 if (start_unit_num >= description->units_num)
4347 break;
4348 for (pat_reserv = (final_p
4349 ? unit_final_absence_set_table [start_unit_num]
4350 : unit_absence_set_table [start_unit_num]);
4351 pat_reserv != NULL;
4352 pat_reserv = pat_reserv->next_pattern_reserv)
4354 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4355 if ((checked_set [unit_num] & pat_reserv->reserv [unit_num])
4356 != pat_reserv->reserv [unit_num]
4357 && pat_reserv->reserv [unit_num])
4358 break;
4359 if (unit_num >= els_in_cycle_reserv)
4360 return FALSE;
4363 return TRUE;
4368 /* This page contains code for transformation of original reservations
4369 described in .md file. The main goal of transformations is
4370 simplifying reservation and lifting up all `|' on the top of IR
4371 reservation representation. */
4374 /* The following function makes copy of IR representation of
4375 reservation. The function also substitutes all reservations
4376 defined by define_reservation by corresponding value during making
4377 the copy. */
4378 static regexp_t
4379 copy_insn_regexp (regexp_t regexp)
4381 regexp_t result;
4382 int i;
4384 switch (regexp->mode)
4386 case rm_reserv:
4387 result = copy_insn_regexp (REGEXP_RESERV (regexp)->reserv_decl->regexp);
4388 break;
4390 case rm_unit:
4391 result = XCOPYNODE (struct regexp, regexp);
4392 break;
4394 case rm_repeat:
4395 result = XCOPYNODE (struct regexp, regexp);
4396 REGEXP_REPEAT (result)->regexp
4397 = copy_insn_regexp (REGEXP_REPEAT (regexp)->regexp);
4398 break;
4400 case rm_sequence:
4401 result = XCOPYNODEVAR (struct regexp, regexp,
4402 sizeof (struct regexp) + sizeof (regexp_t)
4403 * (REGEXP_SEQUENCE (regexp)->regexps_num - 1));
4404 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4405 REGEXP_SEQUENCE (result)->regexps [i]
4406 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4407 break;
4409 case rm_allof:
4410 result = XCOPYNODEVAR (struct regexp, regexp,
4411 sizeof (struct regexp) + sizeof (regexp_t)
4412 * (REGEXP_ALLOF (regexp)->regexps_num - 1));
4413 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4414 REGEXP_ALLOF (result)->regexps [i]
4415 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4416 break;
4418 case rm_oneof:
4419 result = XCOPYNODEVAR (struct regexp, regexp,
4420 sizeof (struct regexp) + sizeof (regexp_t)
4421 * (REGEXP_ONEOF (regexp)->regexps_num - 1));
4422 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4423 REGEXP_ONEOF (result)->regexps [i]
4424 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4425 break;
4427 case rm_nothing:
4428 result = XCOPYNODE (struct regexp, regexp);
4429 break;
4431 default:
4432 gcc_unreachable ();
4434 return result;
4437 /* The following variable is set up 1 if a transformation has been
4438 applied. */
4439 static int regexp_transformed_p;
4441 /* The function makes transformation
4442 A*N -> A, A, ... */
4443 static regexp_t
4444 transform_1 (regexp_t regexp)
4446 int i;
4447 int repeat_num;
4448 regexp_t operand;
4449 pos_t pos;
4451 if (regexp->mode == rm_repeat)
4453 repeat_num = REGEXP_REPEAT (regexp)->repeat_num;
4454 gcc_assert (repeat_num > 1);
4455 operand = REGEXP_REPEAT (regexp)->regexp;
4456 pos = regexp->mode;
4457 regexp = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4458 + sizeof (regexp_t) * (repeat_num - 1));
4459 regexp->mode = rm_sequence;
4460 regexp->pos = pos;
4461 REGEXP_SEQUENCE (regexp)->regexps_num = repeat_num;
4462 for (i = 0; i < repeat_num; i++)
4463 REGEXP_SEQUENCE (regexp)->regexps [i] = copy_insn_regexp (operand);
4464 regexp_transformed_p = 1;
4466 return regexp;
4469 /* The function makes transformations
4470 ...,(A,B,...),C,... -> ...,A,B,...,C,...
4471 ...+(A+B+...)+C+... -> ...+A+B+...+C+...
4472 ...|(A|B|...)|C|... -> ...|A|B|...|C|... */
4473 static regexp_t
4474 transform_2 (regexp_t regexp)
4476 if (regexp->mode == rm_sequence)
4478 regexp_t sequence = NULL;
4479 regexp_t result;
4480 int sequence_index = 0;
4481 int i, j;
4483 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4484 if (REGEXP_SEQUENCE (regexp)->regexps [i]->mode == rm_sequence)
4486 sequence_index = i;
4487 sequence = REGEXP_SEQUENCE (regexp)->regexps [i];
4488 break;
4490 if (i < REGEXP_SEQUENCE (regexp)->regexps_num)
4492 gcc_assert (REGEXP_SEQUENCE (sequence)->regexps_num > 1
4493 && REGEXP_SEQUENCE (regexp)->regexps_num > 1);
4494 result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4495 + sizeof (regexp_t)
4496 * (REGEXP_SEQUENCE (regexp)->regexps_num
4497 + REGEXP_SEQUENCE (sequence)->regexps_num
4498 - 2));
4499 result->mode = rm_sequence;
4500 result->pos = regexp->pos;
4501 REGEXP_SEQUENCE (result)->regexps_num
4502 = (REGEXP_SEQUENCE (regexp)->regexps_num
4503 + REGEXP_SEQUENCE (sequence)->regexps_num - 1);
4504 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4505 if (i < sequence_index)
4506 REGEXP_SEQUENCE (result)->regexps [i]
4507 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4508 else if (i > sequence_index)
4509 REGEXP_SEQUENCE (result)->regexps
4510 [i + REGEXP_SEQUENCE (sequence)->regexps_num - 1]
4511 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4512 else
4513 for (j = 0; j < REGEXP_SEQUENCE (sequence)->regexps_num; j++)
4514 REGEXP_SEQUENCE (result)->regexps [i + j]
4515 = copy_insn_regexp (REGEXP_SEQUENCE (sequence)->regexps [j]);
4516 regexp_transformed_p = 1;
4517 regexp = result;
4520 else if (regexp->mode == rm_allof)
4522 regexp_t allof = NULL;
4523 regexp_t result;
4524 int allof_index = 0;
4525 int i, j;
4527 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4528 if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_allof)
4530 allof_index = i;
4531 allof = REGEXP_ALLOF (regexp)->regexps [i];
4532 break;
4534 if (i < REGEXP_ALLOF (regexp)->regexps_num)
4536 gcc_assert (REGEXP_ALLOF (allof)->regexps_num > 1
4537 && REGEXP_ALLOF (regexp)->regexps_num > 1);
4538 result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4539 + sizeof (regexp_t)
4540 * (REGEXP_ALLOF (regexp)->regexps_num
4541 + REGEXP_ALLOF (allof)->regexps_num - 2));
4542 result->mode = rm_allof;
4543 result->pos = regexp->pos;
4544 REGEXP_ALLOF (result)->regexps_num
4545 = (REGEXP_ALLOF (regexp)->regexps_num
4546 + REGEXP_ALLOF (allof)->regexps_num - 1);
4547 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4548 if (i < allof_index)
4549 REGEXP_ALLOF (result)->regexps [i]
4550 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4551 else if (i > allof_index)
4552 REGEXP_ALLOF (result)->regexps
4553 [i + REGEXP_ALLOF (allof)->regexps_num - 1]
4554 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4555 else
4556 for (j = 0; j < REGEXP_ALLOF (allof)->regexps_num; j++)
4557 REGEXP_ALLOF (result)->regexps [i + j]
4558 = copy_insn_regexp (REGEXP_ALLOF (allof)->regexps [j]);
4559 regexp_transformed_p = 1;
4560 regexp = result;
4563 else if (regexp->mode == rm_oneof)
4565 regexp_t oneof = NULL;
4566 regexp_t result;
4567 int oneof_index = 0;
4568 int i, j;
4570 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4571 if (REGEXP_ONEOF (regexp)->regexps [i]->mode == rm_oneof)
4573 oneof_index = i;
4574 oneof = REGEXP_ONEOF (regexp)->regexps [i];
4575 break;
4577 if (i < REGEXP_ONEOF (regexp)->regexps_num)
4579 gcc_assert (REGEXP_ONEOF (oneof)->regexps_num > 1
4580 && REGEXP_ONEOF (regexp)->regexps_num > 1);
4581 result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4582 + sizeof (regexp_t)
4583 * (REGEXP_ONEOF (regexp)->regexps_num
4584 + REGEXP_ONEOF (oneof)->regexps_num - 2));
4585 result->mode = rm_oneof;
4586 result->pos = regexp->pos;
4587 REGEXP_ONEOF (result)->regexps_num
4588 = (REGEXP_ONEOF (regexp)->regexps_num
4589 + REGEXP_ONEOF (oneof)->regexps_num - 1);
4590 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4591 if (i < oneof_index)
4592 REGEXP_ONEOF (result)->regexps [i]
4593 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4594 else if (i > oneof_index)
4595 REGEXP_ONEOF (result)->regexps
4596 [i + REGEXP_ONEOF (oneof)->regexps_num - 1]
4597 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4598 else
4599 for (j = 0; j < REGEXP_ONEOF (oneof)->regexps_num; j++)
4600 REGEXP_ONEOF (result)->regexps [i + j]
4601 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [j]);
4602 regexp_transformed_p = 1;
4603 regexp = result;
4606 return regexp;
4609 /* The function makes transformations
4610 ...,A|B|...,C,... -> (...,A,C,...)|(...,B,C,...)|...
4611 ...+(A|B|...)+C+... -> (...+A+C+...)|(...+B+C+...)|...
4612 ...+(A,B,...)+C+... -> (...+A+C+...),B,...
4613 ...+(A,B,...)+(C,D,...) -> (A+C),(B+D),... */
4614 static regexp_t
4615 transform_3 (regexp_t regexp)
4617 if (regexp->mode == rm_sequence)
4619 regexp_t oneof = NULL;
4620 int oneof_index = 0;
4621 regexp_t result;
4622 regexp_t sequence;
4623 int i, j;
4625 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4626 if (REGEXP_SEQUENCE (regexp)->regexps [i]->mode == rm_oneof)
4628 oneof_index = i;
4629 oneof = REGEXP_SEQUENCE (regexp)->regexps [i];
4630 break;
4632 if (i < REGEXP_SEQUENCE (regexp)->regexps_num)
4634 gcc_assert (REGEXP_ONEOF (oneof)->regexps_num > 1
4635 && REGEXP_SEQUENCE (regexp)->regexps_num > 1);
4636 result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4637 + sizeof (regexp_t)
4638 * (REGEXP_ONEOF (oneof)->regexps_num - 1));
4639 result->mode = rm_oneof;
4640 result->pos = regexp->pos;
4641 REGEXP_ONEOF (result)->regexps_num
4642 = REGEXP_ONEOF (oneof)->regexps_num;
4643 for (i = 0; i < REGEXP_ONEOF (result)->regexps_num; i++)
4645 sequence
4646 = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4647 + sizeof (regexp_t)
4648 * (REGEXP_SEQUENCE (regexp)->regexps_num - 1));
4649 sequence->mode = rm_sequence;
4650 sequence->pos = regexp->pos;
4651 REGEXP_SEQUENCE (sequence)->regexps_num
4652 = REGEXP_SEQUENCE (regexp)->regexps_num;
4653 REGEXP_ONEOF (result)->regexps [i] = sequence;
4654 for (j = 0; j < REGEXP_SEQUENCE (sequence)->regexps_num; j++)
4655 if (j != oneof_index)
4656 REGEXP_SEQUENCE (sequence)->regexps [j]
4657 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [j]);
4658 else
4659 REGEXP_SEQUENCE (sequence)->regexps [j]
4660 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [i]);
4662 regexp_transformed_p = 1;
4663 regexp = result;
4666 else if (regexp->mode == rm_allof)
4668 regexp_t oneof = NULL;
4669 regexp_t seq;
4670 int oneof_index = 0;
4671 int max_seq_length, allof_length;
4672 regexp_t result;
4673 regexp_t allof = NULL;
4674 regexp_t allof_op = NULL;
4675 int i, j;
4677 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4678 if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_oneof)
4680 oneof_index = i;
4681 oneof = REGEXP_ALLOF (regexp)->regexps [i];
4682 break;
4684 if (i < REGEXP_ALLOF (regexp)->regexps_num)
4686 gcc_assert (REGEXP_ONEOF (oneof)->regexps_num > 1
4687 && REGEXP_ALLOF (regexp)->regexps_num > 1);
4688 result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4689 + sizeof (regexp_t)
4690 * (REGEXP_ONEOF (oneof)->regexps_num - 1));
4691 result->mode = rm_oneof;
4692 result->pos = regexp->pos;
4693 REGEXP_ONEOF (result)->regexps_num
4694 = REGEXP_ONEOF (oneof)->regexps_num;
4695 for (i = 0; i < REGEXP_ONEOF (result)->regexps_num; i++)
4697 allof
4698 = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4699 + sizeof (regexp_t)
4700 * (REGEXP_ALLOF (regexp)->regexps_num - 1));
4701 allof->mode = rm_allof;
4702 allof->pos = regexp->pos;
4703 REGEXP_ALLOF (allof)->regexps_num
4704 = REGEXP_ALLOF (regexp)->regexps_num;
4705 REGEXP_ONEOF (result)->regexps [i] = allof;
4706 for (j = 0; j < REGEXP_ALLOF (allof)->regexps_num; j++)
4707 if (j != oneof_index)
4708 REGEXP_ALLOF (allof)->regexps [j]
4709 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [j]);
4710 else
4711 REGEXP_ALLOF (allof)->regexps [j]
4712 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [i]);
4714 regexp_transformed_p = 1;
4715 regexp = result;
4717 max_seq_length = 0;
4718 if (regexp->mode == rm_allof)
4719 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4721 switch (REGEXP_ALLOF (regexp)->regexps [i]->mode)
4723 case rm_sequence:
4724 seq = REGEXP_ALLOF (regexp)->regexps [i];
4725 if (max_seq_length < REGEXP_SEQUENCE (seq)->regexps_num)
4726 max_seq_length = REGEXP_SEQUENCE (seq)->regexps_num;
4727 break;
4729 case rm_unit:
4730 case rm_nothing:
4731 break;
4733 default:
4734 max_seq_length = 0;
4735 goto break_for;
4738 break_for:
4739 if (max_seq_length != 0)
4741 gcc_assert (max_seq_length != 1
4742 && REGEXP_ALLOF (regexp)->regexps_num > 1);
4743 result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4744 + sizeof (regexp_t) * (max_seq_length - 1));
4745 result->mode = rm_sequence;
4746 result->pos = regexp->pos;
4747 REGEXP_SEQUENCE (result)->regexps_num = max_seq_length;
4748 for (i = 0; i < max_seq_length; i++)
4750 allof_length = 0;
4751 for (j = 0; j < REGEXP_ALLOF (regexp)->regexps_num; j++)
4752 switch (REGEXP_ALLOF (regexp)->regexps [j]->mode)
4754 case rm_sequence:
4755 if (i < (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4756 ->regexps [j])->regexps_num))
4758 allof_op
4759 = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4760 ->regexps [j])
4761 ->regexps [i]);
4762 allof_length++;
4764 break;
4765 case rm_unit:
4766 case rm_nothing:
4767 if (i == 0)
4769 allof_op = REGEXP_ALLOF (regexp)->regexps [j];
4770 allof_length++;
4772 break;
4773 default:
4774 break;
4777 if (allof_length == 1)
4778 REGEXP_SEQUENCE (result)->regexps [i] = allof_op;
4779 else
4781 allof = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4782 + sizeof (regexp_t)
4783 * (allof_length - 1));
4784 allof->mode = rm_allof;
4785 allof->pos = regexp->pos;
4786 REGEXP_ALLOF (allof)->regexps_num = allof_length;
4787 REGEXP_SEQUENCE (result)->regexps [i] = allof;
4788 allof_length = 0;
4789 for (j = 0; j < REGEXP_ALLOF (regexp)->regexps_num; j++)
4790 if (REGEXP_ALLOF (regexp)->regexps [j]->mode == rm_sequence
4791 && (i <
4792 (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4793 ->regexps [j])->regexps_num)))
4795 allof_op = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4796 ->regexps [j])
4797 ->regexps [i]);
4798 REGEXP_ALLOF (allof)->regexps [allof_length]
4799 = allof_op;
4800 allof_length++;
4802 else if (i == 0
4803 && (REGEXP_ALLOF (regexp)->regexps [j]->mode
4804 == rm_unit
4805 || (REGEXP_ALLOF (regexp)->regexps [j]->mode
4806 == rm_nothing)))
4808 allof_op = REGEXP_ALLOF (regexp)->regexps [j];
4809 REGEXP_ALLOF (allof)->regexps [allof_length]
4810 = allof_op;
4811 allof_length++;
4815 regexp_transformed_p = 1;
4816 regexp = result;
4819 return regexp;
4822 /* The function traverses IR of reservation and applies transformations
4823 implemented by FUNC. */
4824 static regexp_t
4825 regexp_transform_func (regexp_t regexp, regexp_t (*func) (regexp_t regexp))
4827 int i;
4829 switch (regexp->mode)
4831 case rm_sequence:
4832 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4833 REGEXP_SEQUENCE (regexp)->regexps [i]
4834 = regexp_transform_func (REGEXP_SEQUENCE (regexp)->regexps [i],
4835 func);
4836 break;
4838 case rm_allof:
4839 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4840 REGEXP_ALLOF (regexp)->regexps [i]
4841 = regexp_transform_func (REGEXP_ALLOF (regexp)->regexps [i], func);
4842 break;
4844 case rm_oneof:
4845 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4846 REGEXP_ONEOF (regexp)->regexps [i]
4847 = regexp_transform_func (REGEXP_ONEOF (regexp)->regexps [i], func);
4848 break;
4850 case rm_repeat:
4851 REGEXP_REPEAT (regexp)->regexp
4852 = regexp_transform_func (REGEXP_REPEAT (regexp)->regexp, func);
4853 break;
4855 case rm_nothing:
4856 case rm_unit:
4857 break;
4859 default:
4860 gcc_unreachable ();
4862 return (*func) (regexp);
4865 /* The function applies all transformations for IR representation of
4866 reservation REGEXP. */
4867 static regexp_t
4868 transform_regexp (regexp_t regexp)
4870 regexp = regexp_transform_func (regexp, transform_1);
4873 regexp_transformed_p = 0;
4874 regexp = regexp_transform_func (regexp, transform_2);
4875 regexp = regexp_transform_func (regexp, transform_3);
4877 while (regexp_transformed_p);
4878 return regexp;
4881 /* The function applies all transformations for reservations of all
4882 insn declarations. */
4883 static void
4884 transform_insn_regexps (void)
4886 decl_t decl;
4887 int i;
4889 transform_time = create_ticker ();
4890 add_advance_cycle_insn_decl ();
4891 if (progress_flag)
4892 fprintf (stderr, "Reservation transformation...");
4893 for (i = 0; i < description->decls_num; i++)
4895 decl = description->decls [i];
4896 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
4897 DECL_INSN_RESERV (decl)->transformed_regexp
4898 = transform_regexp (copy_insn_regexp
4899 (DECL_INSN_RESERV (decl)->regexp));
4901 if (progress_flag)
4902 fprintf (stderr, "done\n");
4903 ticker_off (&transform_time);
4908 /* The following variable value is TRUE if the first annotated message
4909 about units to automata distribution has been output. */
4910 static int annotation_message_reported_p;
4912 /* The vector contains all decls which are automata. */
4913 static VEC(decl_t, heap) *automaton_decls;
4915 /* The following structure describes usage of a unit in a reservation. */
4916 struct unit_usage
4918 unit_decl_t unit_decl;
4919 /* The following forms a list of units used on the same cycle in the
4920 same alternative. The list is ordered by the correspdoning unit
4921 declarations and there is no unit declaration duplication in the
4922 list. */
4923 struct unit_usage *next;
4925 typedef struct unit_usage *unit_usage_t;
4927 DEF_VEC_P(unit_usage_t);
4928 DEF_VEC_ALLOC_P(unit_usage_t, heap);
4930 /* Obstack for unit_usage structures. */
4931 static struct obstack unit_usages;
4933 /* VLA for representation of array of pointers to unit usage
4934 structures. There is an element for each combination of
4935 (alternative number, cycle). Unit usages on given cycle in
4936 alternative with given number are referred through element with
4937 index equals to the cycle * number of all alternatives in the
4938 regexp + the alternative number. */
4939 static VEC(unit_usage_t, heap) *cycle_alt_unit_usages;
4941 /* The following function creates the structure unit_usage for UNIT on
4942 CYCLE in REGEXP alternative with ALT_NUM. The structure is made
4943 accessed through cycle_alt_unit_usages. */
4944 static void
4945 store_alt_unit_usage (regexp_t regexp, regexp_t unit, int cycle,
4946 int alt_num)
4948 size_t length;
4949 unit_decl_t unit_decl;
4950 unit_usage_t unit_usage_ptr, curr, prev;
4951 int index;
4953 gcc_assert (regexp && regexp->mode == rm_oneof
4954 && alt_num < REGEXP_ONEOF (regexp)->regexps_num);
4955 unit_decl = REGEXP_UNIT (unit)->unit_decl;
4957 length = (cycle + 1) * REGEXP_ONEOF (regexp)->regexps_num;
4958 while (VEC_length (unit_usage_t, cycle_alt_unit_usages) < length)
4959 VEC_safe_push (unit_usage_t, heap, cycle_alt_unit_usages, 0);
4961 index = cycle * REGEXP_ONEOF (regexp)->regexps_num + alt_num;
4962 prev = NULL;
4963 for (curr = VEC_index (unit_usage_t, cycle_alt_unit_usages, index);
4964 curr != NULL;
4965 prev = curr, curr = curr->next)
4966 if (curr->unit_decl >= unit_decl)
4967 break;
4968 if (curr != NULL && curr->unit_decl == unit_decl)
4969 return;
4970 obstack_blank (&unit_usages, sizeof (struct unit_usage));
4971 unit_usage_ptr = (struct unit_usage *) obstack_base (&unit_usages);
4972 obstack_finish (&unit_usages);
4973 unit_usage_ptr->unit_decl = unit_decl;
4974 unit_decl->last_distribution_check_cycle = -1; /* undefined */
4975 unit_usage_ptr->next = curr;
4976 if (prev == NULL)
4977 VEC_replace (unit_usage_t, cycle_alt_unit_usages, index, unit_usage_ptr);
4978 else
4979 prev->next = unit_usage_ptr;
4982 /* Return true if unit UNIT_DECL is present on the LIST. */
4983 static bool
4984 unit_present_on_list_p (unit_usage_t list, unit_decl_t unit_decl)
4986 while (list != NULL)
4988 if (list->unit_decl == unit_decl)
4989 return true;
4990 list = list->next;
4992 return false;
4995 /* The function returns true if reservations of alternatives ALT1 and
4996 ALT2 are equal after excluding reservations of units of
4997 EXCLUDED_AUTOMATON_DECL. */
4998 static bool
4999 equal_alternatives_p (int alt1, int alt2, int n_alts,
5000 struct automaton_decl *excluded_automaton_decl)
5002 int i;
5003 unit_usage_t list1, list2;
5005 for (i = 0;
5006 i < (int) VEC_length (unit_usage_t, cycle_alt_unit_usages);
5007 i += n_alts)
5009 for (list1 = VEC_index (unit_usage_t, cycle_alt_unit_usages, i + alt1),
5010 list2 = VEC_index (unit_usage_t, cycle_alt_unit_usages, i + alt2);;
5011 list1 = list1->next, list2 = list2->next)
5013 while (list1 != NULL
5014 && list1->unit_decl->automaton_decl == excluded_automaton_decl)
5015 list1 = list1->next;
5016 while (list2 != NULL
5017 && list2->unit_decl->automaton_decl == excluded_automaton_decl)
5018 list2 = list2->next;
5019 if (list1 == NULL || list2 == NULL)
5021 if (list1 != list2)
5022 return false;
5023 else
5024 break;
5026 if (list1->unit_decl != list2->unit_decl)
5027 return false;
5030 return true;
5033 DEF_VEC_I(int);
5034 DEF_VEC_ALLOC_I(int, heap);
5036 /* The function processes given REGEXP to find units with the wrong
5037 distribution. */
5038 static void
5039 check_regexp_units_distribution (const char *insn_reserv_name,
5040 regexp_t regexp)
5042 int i, j, k, cycle, start, n_alts, alt, alt2;
5043 bool annotation_reservation_message_reported_p;
5044 regexp_t seq, allof, unit;
5045 struct unit_usage *unit_usage_ptr;
5046 VEC(int, heap) *marked;
5048 if (regexp == NULL || regexp->mode != rm_oneof)
5049 return;
5050 /* Store all unit usages in the regexp: */
5051 obstack_init (&unit_usages);
5052 cycle_alt_unit_usages = VEC_alloc (unit_usage_t, heap, 10);
5054 for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
5056 seq = REGEXP_ONEOF (regexp)->regexps [i];
5057 switch (seq->mode)
5059 case rm_sequence:
5060 for (j = 0; j < REGEXP_SEQUENCE (seq)->regexps_num; j++)
5062 allof = REGEXP_SEQUENCE (seq)->regexps [j];
5063 switch (allof->mode)
5065 case rm_allof:
5066 for (k = 0; k < REGEXP_ALLOF (allof)->regexps_num; k++)
5068 unit = REGEXP_ALLOF (allof)->regexps [k];
5069 if (unit->mode == rm_unit)
5070 store_alt_unit_usage (regexp, unit, j, i);
5071 else
5072 gcc_assert (unit->mode == rm_nothing);
5074 break;
5076 case rm_unit:
5077 store_alt_unit_usage (regexp, allof, j, i);
5078 break;
5080 case rm_nothing:
5081 break;
5083 default:
5084 gcc_unreachable ();
5087 break;
5089 case rm_allof:
5090 for (k = 0; k < REGEXP_ALLOF (seq)->regexps_num; k++)
5092 unit = REGEXP_ALLOF (seq)->regexps [k];
5093 switch (unit->mode)
5095 case rm_unit:
5096 store_alt_unit_usage (regexp, unit, 0, i);
5097 break;
5099 case rm_nothing:
5100 break;
5102 default:
5103 gcc_unreachable ();
5106 break;
5108 case rm_unit:
5109 store_alt_unit_usage (regexp, seq, 0, i);
5110 break;
5112 case rm_nothing:
5113 break;
5115 default:
5116 gcc_unreachable ();
5119 /* Check distribution: */
5120 for (i = 0; i < (int) VEC_length (unit_usage_t, cycle_alt_unit_usages); i++)
5121 for (unit_usage_ptr = VEC_index (unit_usage_t, cycle_alt_unit_usages, i);
5122 unit_usage_ptr != NULL;
5123 unit_usage_ptr = unit_usage_ptr->next)
5124 unit_usage_ptr->unit_decl->last_distribution_check_cycle = -1;
5125 n_alts = REGEXP_ONEOF (regexp)->regexps_num;
5126 marked = VEC_alloc (int, heap, n_alts);
5127 for (i = 0; i < n_alts; i++)
5128 VEC_safe_push (int, heap, marked, 0);
5129 annotation_reservation_message_reported_p = false;
5130 for (i = 0; i < (int) VEC_length (unit_usage_t, cycle_alt_unit_usages); i++)
5132 cycle = i / n_alts;
5133 start = cycle * n_alts;
5134 for (unit_usage_ptr = VEC_index (unit_usage_t, cycle_alt_unit_usages, i);
5135 unit_usage_ptr != NULL;
5136 unit_usage_ptr = unit_usage_ptr->next)
5138 if (unit_usage_ptr->unit_decl->last_distribution_check_cycle == cycle)
5139 continue;
5140 unit_usage_ptr->unit_decl->last_distribution_check_cycle = cycle;
5141 for (alt = 0; alt < n_alts; alt++)
5142 if (! unit_present_on_list_p (VEC_index (unit_usage_t,
5143 cycle_alt_unit_usages,
5144 start + alt),
5145 unit_usage_ptr->unit_decl))
5146 break;
5147 if (alt >= n_alts)
5148 continue;
5149 memset (VEC_address (int, marked), 0, n_alts * sizeof (int));
5150 for (alt = 0; alt < n_alts; alt++)
5152 if (! unit_present_on_list_p (VEC_index (unit_usage_t,
5153 cycle_alt_unit_usages,
5154 start + alt),
5155 unit_usage_ptr->unit_decl))
5156 continue;
5157 for (j = 0;
5158 j < (int) VEC_length (unit_usage_t, cycle_alt_unit_usages);
5159 j++)
5161 alt2 = j % n_alts;
5162 if (! unit_present_on_list_p
5163 (VEC_index (unit_usage_t, cycle_alt_unit_usages,
5164 start + alt2),
5165 unit_usage_ptr->unit_decl)
5166 && equal_alternatives_p (alt, alt2, n_alts,
5167 unit_usage_ptr
5168 ->unit_decl->automaton_decl))
5170 VEC_replace (int, marked, alt, 1);
5171 VEC_replace (int, marked, alt2, 1);
5175 for (alt = 0; alt < n_alts && VEC_index (int, marked, alt); alt++)
5177 if (alt < n_alts && 0)
5179 if (! annotation_message_reported_p)
5181 fprintf (stderr, "\n");
5182 error ("The following units do not satisfy units-automata distribution rule");
5183 error ("(Unit presence on one alt and its absence on other alt\n");
5184 error (" result in different other automata reservations)");
5185 annotation_message_reported_p = TRUE;
5187 if (! annotation_reservation_message_reported_p)
5189 error ("Reserv %s:", insn_reserv_name);
5190 annotation_reservation_message_reported_p = true;
5192 error (" Unit %s, cycle %d, alt %d, another alt %d",
5193 unit_usage_ptr->unit_decl->name, cycle, i % n_alts, alt);
5197 VEC_free (int, heap, marked);
5198 VEC_free (unit_usage_t, heap, cycle_alt_unit_usages);
5199 obstack_free (&unit_usages, NULL);
5202 /* The function finds units which violates units to automata
5203 distribution rule. If the units exist, report about them. */
5204 static void
5205 check_unit_distributions_to_automata (void)
5207 decl_t decl;
5208 int i;
5210 if (progress_flag)
5211 fprintf (stderr, "Check unit distributions to automata...");
5212 automaton_decls = NULL;
5213 for (i = 0; i < description->decls_num; i++)
5215 decl = description->decls [i];
5216 if (decl->mode == dm_automaton)
5217 VEC_safe_push (decl_t, heap, automaton_decls, decl);
5219 if (VEC_length (decl_t, automaton_decls) > 1)
5221 annotation_message_reported_p = FALSE;
5222 for (i = 0; i < description->decls_num; i++)
5224 decl = description->decls [i];
5225 if (decl->mode == dm_insn_reserv)
5226 check_regexp_units_distribution
5227 (DECL_INSN_RESERV (decl)->name,
5228 DECL_INSN_RESERV (decl)->transformed_regexp);
5231 VEC_free (decl_t, heap, automaton_decls);
5232 if (progress_flag)
5233 fprintf (stderr, "done\n");
5238 /* The page contains code for building alt_states (see comments for
5239 IR) describing all possible insns reservations of an automaton. */
5241 /* Current state being formed for which the current alt_state
5242 refers. */
5243 static state_t state_being_formed;
5245 /* Current alt_state being formed. */
5246 static alt_state_t alt_state_being_formed;
5248 /* This recursive function processes `,' and units in reservation
5249 REGEXP for forming alt_states of AUTOMATON. It is believed that
5250 CURR_CYCLE is start cycle of all reservation REGEXP. */
5251 static int
5252 process_seq_for_forming_states (regexp_t regexp, automaton_t automaton,
5253 int curr_cycle)
5255 int i;
5257 if (regexp == NULL)
5258 return curr_cycle;
5260 switch (regexp->mode)
5262 case rm_unit:
5263 if (REGEXP_UNIT (regexp)->unit_decl->corresponding_automaton_num
5264 == automaton->automaton_order_num)
5265 set_state_reserv (state_being_formed, curr_cycle,
5266 REGEXP_UNIT (regexp)->unit_decl->unit_num);
5267 return curr_cycle;
5269 case rm_sequence:
5270 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
5271 curr_cycle
5272 = process_seq_for_forming_states
5273 (REGEXP_SEQUENCE (regexp)->regexps [i], automaton, curr_cycle) + 1;
5274 return curr_cycle;
5276 case rm_allof:
5278 int finish_cycle = 0;
5279 int cycle;
5281 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
5283 cycle = process_seq_for_forming_states (REGEXP_ALLOF (regexp)
5284 ->regexps [i],
5285 automaton, curr_cycle);
5286 if (finish_cycle < cycle)
5287 finish_cycle = cycle;
5289 return finish_cycle;
5292 case rm_nothing:
5293 return curr_cycle;
5295 default:
5296 gcc_unreachable ();
5300 /* This recursive function finishes forming ALT_STATE of AUTOMATON and
5301 inserts alt_state into the table. */
5302 static void
5303 finish_forming_alt_state (alt_state_t alt_state,
5304 automaton_t automaton ATTRIBUTE_UNUSED)
5306 state_t state_in_table;
5307 state_t corresponding_state;
5309 corresponding_state = alt_state->state;
5310 state_in_table = insert_state (corresponding_state);
5311 if (state_in_table != corresponding_state)
5313 free_state (corresponding_state);
5314 alt_state->state = state_in_table;
5318 /* The following variable value is current automaton insn for whose
5319 reservation the alt states are created. */
5320 static ainsn_t curr_ainsn;
5322 /* This recursive function processes `|' in reservation REGEXP for
5323 forming alt_states of AUTOMATON. List of the alt states should
5324 have the same order as in the description. */
5325 static void
5326 process_alts_for_forming_states (regexp_t regexp, automaton_t automaton,
5327 int inside_oneof_p)
5329 int i;
5331 if (regexp->mode != rm_oneof)
5333 alt_state_being_formed = get_free_alt_state ();
5334 state_being_formed = get_free_state (1, automaton);
5335 alt_state_being_formed->state = state_being_formed;
5336 /* We inserts in reverse order but we process alternatives also
5337 in reverse order. So we have the same order of alternative
5338 as in the description. */
5339 alt_state_being_formed->next_alt_state = curr_ainsn->alt_states;
5340 curr_ainsn->alt_states = alt_state_being_formed;
5341 (void) process_seq_for_forming_states (regexp, automaton, 0);
5342 finish_forming_alt_state (alt_state_being_formed, automaton);
5344 else
5346 gcc_assert (!inside_oneof_p);
5347 /* We processes it in reverse order to get list with the same
5348 order as in the description. See also the previous
5349 commentary. */
5350 for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
5351 process_alts_for_forming_states (REGEXP_ONEOF (regexp)->regexps [i],
5352 automaton, 1);
5356 /* Create nodes alt_state for all AUTOMATON insns. */
5357 static void
5358 create_alt_states (automaton_t automaton)
5360 struct insn_reserv_decl *reserv_decl;
5362 for (curr_ainsn = automaton->ainsn_list;
5363 curr_ainsn != NULL;
5364 curr_ainsn = curr_ainsn->next_ainsn)
5366 reserv_decl = curr_ainsn->insn_reserv_decl;
5367 if (reserv_decl != DECL_INSN_RESERV (advance_cycle_insn_decl))
5369 curr_ainsn->alt_states = NULL;
5370 process_alts_for_forming_states (reserv_decl->transformed_regexp,
5371 automaton, 0);
5372 curr_ainsn->sorted_alt_states
5373 = uniq_sort_alt_states (curr_ainsn->alt_states);
5380 /* The page contains major code for building DFA(s) for fast pipeline
5381 hazards recognition. */
5383 /* The function forms list of ainsns of AUTOMATON with the same
5384 reservation. */
5386 static void
5387 form_ainsn_with_same_reservs (automaton_t automaton)
5389 ainsn_t curr_ainsn;
5390 size_t i;
5391 VEC(ainsn_t, heap) *last_insns = VEC_alloc (ainsn_t, heap, 150);
5393 for (curr_ainsn = automaton->ainsn_list;
5394 curr_ainsn != NULL;
5395 curr_ainsn = curr_ainsn->next_ainsn)
5396 if (curr_ainsn->insn_reserv_decl
5397 == DECL_INSN_RESERV (advance_cycle_insn_decl))
5399 curr_ainsn->next_same_reservs_insn = NULL;
5400 curr_ainsn->first_insn_with_same_reservs = 1;
5402 else
5404 for (i = 0; i < VEC_length (ainsn_t, last_insns); i++)
5405 if (alt_states_eq
5406 (curr_ainsn->sorted_alt_states,
5407 VEC_index (ainsn_t, last_insns, i)->sorted_alt_states))
5408 break;
5409 curr_ainsn->next_same_reservs_insn = NULL;
5410 if (i < VEC_length (ainsn_t, last_insns))
5412 curr_ainsn->first_insn_with_same_reservs = 0;
5413 VEC_index (ainsn_t, last_insns, i)->next_same_reservs_insn
5414 = curr_ainsn;
5415 VEC_replace (ainsn_t, last_insns, i, curr_ainsn);
5417 else
5419 VEC_safe_push (ainsn_t, heap, last_insns, curr_ainsn);
5420 curr_ainsn->first_insn_with_same_reservs = 1;
5423 VEC_free (ainsn_t, heap, last_insns);
5426 /* Forming unit reservations which can affect creating the automaton
5427 states achieved from a given state. It permits to build smaller
5428 automata in many cases. We would have the same automata after
5429 the minimization without such optimization, but the automaton
5430 right after the building could be huge. So in other words, usage
5431 of reservs_matter means some minimization during building the
5432 automaton. */
5433 static reserv_sets_t
5434 form_reservs_matter (automaton_t automaton)
5436 int cycle, unit;
5437 reserv_sets_t reservs_matter = alloc_empty_reserv_sets();
5439 for (cycle = 0; cycle < max_cycles_num; cycle++)
5440 for (unit = 0; unit < description->units_num; unit++)
5441 if (units_array [unit]->automaton_decl
5442 == automaton->corresponding_automaton_decl
5443 && (cycle >= units_array [unit]->min_occ_cycle_num
5444 /* We can not remove queried unit from reservations. */
5445 || units_array [unit]->query_p
5446 /* We can not remove units which are used
5447 `exclusion_set', `presence_set',
5448 `final_presence_set', `absence_set', and
5449 `final_absence_set'. */
5450 || units_array [unit]->in_set_p))
5451 set_unit_reserv (reservs_matter, cycle, unit);
5452 return reservs_matter;
5455 /* The following function creates all states of nondeterministic AUTOMATON. */
5456 static void
5457 make_automaton (automaton_t automaton)
5459 ainsn_t ainsn;
5460 struct insn_reserv_decl *insn_reserv_decl;
5461 alt_state_t alt_state;
5462 state_t state;
5463 state_t start_state;
5464 state_t state2;
5465 ainsn_t advance_cycle_ainsn;
5466 VEC(state_t, heap) *state_stack = VEC_alloc(state_t, heap, 150);
5467 int states_n;
5468 reserv_sets_t reservs_matter = form_reservs_matter (automaton);
5470 /* Create the start state (empty state). */
5471 start_state = insert_state (get_free_state (1, automaton));
5472 automaton->start_state = start_state;
5473 start_state->it_was_placed_in_stack_for_NDFA_forming = 1;
5474 VEC_safe_push (state_t, heap, state_stack, start_state);
5475 states_n = 1;
5476 while (VEC_length (state_t, state_stack) != 0)
5478 state = VEC_pop (state_t, state_stack);
5479 advance_cycle_ainsn = NULL;
5480 for (ainsn = automaton->ainsn_list;
5481 ainsn != NULL;
5482 ainsn = ainsn->next_ainsn)
5483 if (ainsn->first_insn_with_same_reservs)
5485 insn_reserv_decl = ainsn->insn_reserv_decl;
5486 if (insn_reserv_decl != DECL_INSN_RESERV (advance_cycle_insn_decl))
5488 /* We process alt_states in the same order as they are
5489 present in the description. */
5490 for (alt_state = ainsn->alt_states;
5491 alt_state != NULL;
5492 alt_state = alt_state->next_alt_state)
5494 state2 = alt_state->state;
5495 if (!intersected_state_reservs_p (state, state2))
5497 state2 = states_union (state, state2, reservs_matter);
5498 if (!state2->it_was_placed_in_stack_for_NDFA_forming)
5500 state2->it_was_placed_in_stack_for_NDFA_forming
5501 = 1;
5502 VEC_safe_push (state_t, heap, state_stack, state2);
5503 states_n++;
5504 if (progress_flag && states_n % 100 == 0)
5505 fprintf (stderr, ".");
5507 add_arc (state, state2, ainsn);
5508 if (!ndfa_flag)
5509 break;
5513 else
5514 advance_cycle_ainsn = ainsn;
5516 /* Add transition to advance cycle. */
5517 state2 = state_shift (state, reservs_matter);
5518 if (!state2->it_was_placed_in_stack_for_NDFA_forming)
5520 state2->it_was_placed_in_stack_for_NDFA_forming = 1;
5521 VEC_safe_push (state_t, heap, state_stack, state2);
5522 states_n++;
5523 if (progress_flag && states_n % 100 == 0)
5524 fprintf (stderr, ".");
5526 gcc_assert (advance_cycle_ainsn);
5527 add_arc (state, state2, advance_cycle_ainsn);
5529 VEC_free (state_t, heap, state_stack);
5532 /* Form lists of all arcs of STATE marked by the same ainsn. */
5533 static void
5534 form_arcs_marked_by_insn (state_t state)
5536 decl_t decl;
5537 arc_t arc;
5538 int i;
5540 for (i = 0; i < description->decls_num; i++)
5542 decl = description->decls [i];
5543 if (decl->mode == dm_insn_reserv)
5544 DECL_INSN_RESERV (decl)->arcs_marked_by_insn = NULL;
5546 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5548 gcc_assert (arc->insn);
5549 arc->next_arc_marked_by_insn
5550 = arc->insn->insn_reserv_decl->arcs_marked_by_insn;
5551 arc->insn->insn_reserv_decl->arcs_marked_by_insn = arc;
5555 /* The function creates composed state (see comments for IR) from
5556 ORIGINAL_STATE and list of arcs ARCS_MARKED_BY_INSN marked by the
5557 same insn. If the composed state is not in STATE_STACK yet, it is
5558 pushed into STATE_STACK. */
5560 static int
5561 create_composed_state (state_t original_state, arc_t arcs_marked_by_insn,
5562 VEC(state_t, heap) **state_stack)
5564 state_t state;
5565 alt_state_t alt_state, curr_alt_state;
5566 alt_state_t new_alt_state;
5567 arc_t curr_arc;
5568 arc_t next_arc;
5569 state_t state_in_table;
5570 state_t temp_state;
5571 alt_state_t canonical_alt_states_list;
5572 int alts_number;
5573 int new_state_p = 0;
5575 if (arcs_marked_by_insn == NULL)
5576 return new_state_p;
5577 if (arcs_marked_by_insn->next_arc_marked_by_insn == NULL)
5578 state = arcs_marked_by_insn->to_state;
5579 else
5581 gcc_assert (ndfa_flag);
5582 /* Create composed state. */
5583 state = get_free_state (0, arcs_marked_by_insn->to_state->automaton);
5584 curr_alt_state = NULL;
5585 for (curr_arc = arcs_marked_by_insn;
5586 curr_arc != NULL;
5587 curr_arc = curr_arc->next_arc_marked_by_insn)
5588 if (curr_arc->to_state->component_states == NULL)
5590 new_alt_state = get_free_alt_state ();
5591 new_alt_state->next_alt_state = curr_alt_state;
5592 new_alt_state->state = curr_arc->to_state;
5593 curr_alt_state = new_alt_state;
5595 else
5596 for (alt_state = curr_arc->to_state->component_states;
5597 alt_state != NULL;
5598 alt_state = alt_state->next_sorted_alt_state)
5600 new_alt_state = get_free_alt_state ();
5601 new_alt_state->next_alt_state = curr_alt_state;
5602 new_alt_state->state = alt_state->state;
5603 gcc_assert (!alt_state->state->component_states);
5604 curr_alt_state = new_alt_state;
5606 /* There are not identical sets in the alt state list. */
5607 canonical_alt_states_list = uniq_sort_alt_states (curr_alt_state);
5608 if (canonical_alt_states_list->next_sorted_alt_state == NULL)
5610 temp_state = state;
5611 state = canonical_alt_states_list->state;
5612 free_state (temp_state);
5614 else
5616 state->component_states = canonical_alt_states_list;
5617 state_in_table = insert_state (state);
5618 if (state_in_table != state)
5620 gcc_assert
5621 (state_in_table->it_was_placed_in_stack_for_DFA_forming);
5622 free_state (state);
5623 state = state_in_table;
5625 else
5627 gcc_assert (!state->it_was_placed_in_stack_for_DFA_forming);
5628 new_state_p = 1;
5629 for (curr_alt_state = state->component_states;
5630 curr_alt_state != NULL;
5631 curr_alt_state = curr_alt_state->next_sorted_alt_state)
5632 for (curr_arc = first_out_arc (curr_alt_state->state);
5633 curr_arc != NULL;
5634 curr_arc = next_out_arc (curr_arc))
5635 add_arc (state, curr_arc->to_state, curr_arc->insn);
5637 arcs_marked_by_insn->to_state = state;
5638 for (alts_number = 0,
5639 curr_arc = arcs_marked_by_insn->next_arc_marked_by_insn;
5640 curr_arc != NULL;
5641 curr_arc = next_arc)
5643 next_arc = curr_arc->next_arc_marked_by_insn;
5644 remove_arc (original_state, curr_arc);
5645 alts_number++;
5649 if (!state->it_was_placed_in_stack_for_DFA_forming)
5651 state->it_was_placed_in_stack_for_DFA_forming = 1;
5652 VEC_safe_push (state_t, heap, *state_stack, state);
5654 return new_state_p;
5657 /* The function transforms nondeterministic AUTOMATON into
5658 deterministic. */
5660 static void
5661 NDFA_to_DFA (automaton_t automaton)
5663 state_t start_state;
5664 state_t state;
5665 decl_t decl;
5666 VEC(state_t, heap) *state_stack;
5667 int i;
5668 int states_n;
5670 state_stack = VEC_alloc (state_t, heap, 0);
5672 /* Create the start state (empty state). */
5673 start_state = automaton->start_state;
5674 start_state->it_was_placed_in_stack_for_DFA_forming = 1;
5675 VEC_safe_push (state_t, heap, state_stack, start_state);
5676 states_n = 1;
5677 while (VEC_length (state_t, state_stack) != 0)
5679 state = VEC_pop (state_t, state_stack);
5680 form_arcs_marked_by_insn (state);
5681 for (i = 0; i < description->decls_num; i++)
5683 decl = description->decls [i];
5684 if (decl->mode == dm_insn_reserv
5685 && create_composed_state
5686 (state, DECL_INSN_RESERV (decl)->arcs_marked_by_insn,
5687 &state_stack))
5689 states_n++;
5690 if (progress_flag && states_n % 100 == 0)
5691 fprintf (stderr, ".");
5695 VEC_free (state_t, heap, state_stack);
5698 /* The following variable value is current number (1, 2, ...) of passing
5699 graph of states. */
5700 static int curr_state_graph_pass_num;
5702 /* This recursive function passes all states achieved from START_STATE
5703 and applies APPLIED_FUNC to them. */
5704 static void
5705 pass_state_graph (state_t start_state, void (*applied_func) (state_t state))
5707 arc_t arc;
5709 if (start_state->pass_num == curr_state_graph_pass_num)
5710 return;
5711 start_state->pass_num = curr_state_graph_pass_num;
5712 (*applied_func) (start_state);
5713 for (arc = first_out_arc (start_state);
5714 arc != NULL;
5715 arc = next_out_arc (arc))
5716 pass_state_graph (arc->to_state, applied_func);
5719 /* This recursive function passes all states of AUTOMATON and applies
5720 APPLIED_FUNC to them. */
5721 static void
5722 pass_states (automaton_t automaton, void (*applied_func) (state_t state))
5724 curr_state_graph_pass_num++;
5725 pass_state_graph (automaton->start_state, applied_func);
5728 /* The function initializes code for passing of all states. */
5729 static void
5730 initiate_pass_states (void)
5732 curr_state_graph_pass_num = 0;
5735 /* The following vla is used for storing pointers to all achieved
5736 states. */
5737 static VEC(state_t, heap) *all_achieved_states;
5739 /* This function is called by function pass_states to add an achieved
5740 STATE. */
5741 static void
5742 add_achieved_state (state_t state)
5744 VEC_safe_push (state_t, heap, all_achieved_states, state);
5747 /* The function sets up equivalence numbers of insns which mark all
5748 out arcs of STATE by equiv_class_num_1 (if ODD_ITERATION_FLAG has
5749 nonzero value) or by equiv_class_num_2 of the destination state.
5750 The function returns number of out arcs of STATE. */
5751 static void
5752 set_out_arc_insns_equiv_num (state_t state, int odd_iteration_flag)
5754 arc_t arc;
5756 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5758 gcc_assert (!arc->insn->insn_reserv_decl->equiv_class_num);
5759 arc->insn->insn_reserv_decl->equiv_class_num
5760 = (odd_iteration_flag
5761 ? arc->to_state->equiv_class_num_1
5762 : arc->to_state->equiv_class_num_2);
5763 gcc_assert (arc->insn->insn_reserv_decl->equiv_class_num);
5767 /* The function clears equivalence numbers and alt_states in all insns
5768 which mark all out arcs of STATE. */
5769 static void
5770 clear_arc_insns_equiv_num (state_t state)
5772 arc_t arc;
5774 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5775 arc->insn->insn_reserv_decl->equiv_class_num = 0;
5779 /* The following function returns TRUE if STATE reserves the unit with
5780 UNIT_NUM on the first cycle. */
5781 static int
5782 first_cycle_unit_presence (state_t state, int unit_num)
5784 alt_state_t alt_state;
5786 if (state->component_states == NULL)
5787 return test_unit_reserv (state->reservs, 0, unit_num);
5788 else
5790 for (alt_state = state->component_states;
5791 alt_state != NULL;
5792 alt_state = alt_state->next_sorted_alt_state)
5793 if (test_unit_reserv (alt_state->state->reservs, 0, unit_num))
5794 return true;
5796 return false;
5799 /* This fills in the presence_signature[] member of STATE. */
5800 static void
5801 cache_presence (state_t state)
5803 int i, num = 0;
5804 unsigned int sz;
5805 sz = (description->query_units_num + sizeof (int) * CHAR_BIT - 1)
5806 / (sizeof (int) * CHAR_BIT);
5808 state->presence_signature = XCREATENODEVEC (unsigned int, sz);
5809 for (i = 0; i < description->units_num; i++)
5810 if (units_array [i]->query_p)
5812 int presence1_p = first_cycle_unit_presence (state, i);
5813 state->presence_signature[num / (sizeof (int) * CHAR_BIT)]
5814 |= (!!presence1_p) << (num % (sizeof (int) * CHAR_BIT));
5815 num++;
5819 /* The function returns nonzero value if STATE is not equivalent to
5820 ANOTHER_STATE from the same current partition on equivalence
5821 classes. Another state has ANOTHER_STATE_OUT_ARCS_NUM number of
5822 output arcs. Iteration of making equivalence partition is defined
5823 by ODD_ITERATION_FLAG. */
5824 static int
5825 state_is_differed (state_t state, state_t another_state,
5826 int odd_iteration_flag)
5828 arc_t arc;
5829 unsigned int sz, si;
5831 gcc_assert (state->num_out_arcs == another_state->num_out_arcs);
5833 sz = (description->query_units_num + sizeof (int) * CHAR_BIT - 1)
5834 / (sizeof (int) * CHAR_BIT);
5836 for (si = 0; si < sz; si++)
5837 gcc_assert (state->presence_signature[si]
5838 == another_state->presence_signature[si]);
5840 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5842 if ((odd_iteration_flag
5843 ? arc->to_state->equiv_class_num_1
5844 : arc->to_state->equiv_class_num_2)
5845 != arc->insn->insn_reserv_decl->equiv_class_num)
5846 return 1;
5849 return 0;
5852 /* Compares two states pointed to by STATE_PTR_1 and STATE_PTR_2
5853 and return -1, 0 or 1. This function can be used as predicate for
5854 qsort(). It requires the member presence_signature[] of both
5855 states be filled. */
5856 static int
5857 compare_states_for_equiv (const void *state_ptr_1,
5858 const void *state_ptr_2)
5860 const_state_t const s1 = *(const_state_t const*)state_ptr_1;
5861 const_state_t const s2 = *(const_state_t const*)state_ptr_2;
5862 unsigned int sz, si;
5863 if (s1->num_out_arcs < s2->num_out_arcs)
5864 return -1;
5865 else if (s1->num_out_arcs > s2->num_out_arcs)
5866 return 1;
5868 sz = (description->query_units_num + sizeof (int) * CHAR_BIT - 1)
5869 / (sizeof (int) * CHAR_BIT);
5871 for (si = 0; si < sz; si++)
5872 if (s1->presence_signature[si] < s2->presence_signature[si])
5873 return -1;
5874 else if (s1->presence_signature[si] > s2->presence_signature[si])
5875 return 1;
5876 return 0;
5879 /* The function makes initial partition of STATES on equivalent
5880 classes and saves it into *CLASSES. This function requires the input
5881 to be sorted via compare_states_for_equiv(). */
5882 static int
5883 init_equiv_class (VEC(state_t, heap) *states, VEC (state_t, heap) **classes)
5885 size_t i;
5886 state_t prev = 0;
5887 int class_num = 1;
5889 *classes = VEC_alloc (state_t, heap, 150);
5890 for (i = 0; i < VEC_length (state_t, states); i++)
5892 state_t state = VEC_index (state_t, states, i);
5893 if (prev)
5895 if (compare_states_for_equiv (&prev, &state) != 0)
5897 VEC_safe_push (state_t, heap, *classes, prev);
5898 class_num++;
5899 prev = NULL;
5902 state->equiv_class_num_1 = class_num;
5903 state->next_equiv_class_state = prev;
5904 prev = state;
5906 if (prev)
5907 VEC_safe_push (state_t, heap, *classes, prev);
5908 return class_num;
5911 /* The function copies pointers to equivalent states from vla FROM
5912 into vla TO. */
5913 static void
5914 copy_equiv_class (VEC(state_t, heap) **to, VEC(state_t, heap) *from)
5916 VEC_free (state_t, heap, *to);
5917 *to = VEC_copy (state_t, heap, from);
5920 /* The function processes equivalence class given by its first state,
5921 FIRST_STATE, on odd iteration if ODD_ITERATION_FLAG. If there
5922 are not equivalent states, the function partitions the class
5923 removing nonequivalent states and placing them in
5924 *NEXT_ITERATION_CLASSES, increments *NEW_EQUIV_CLASS_NUM_PTR ans
5925 assigns it to the state equivalence number. If the class has been
5926 partitioned, the function returns nonzero value. */
5927 static int
5928 partition_equiv_class (state_t first_state, int odd_iteration_flag,
5929 VEC(state_t, heap) **next_iteration_classes,
5930 int *new_equiv_class_num_ptr)
5932 state_t new_equiv_class;
5933 int partition_p;
5934 state_t curr_state;
5935 state_t prev_state;
5936 state_t next_state;
5938 partition_p = 0;
5940 while (first_state != NULL)
5942 new_equiv_class = NULL;
5943 if (first_state->next_equiv_class_state != NULL)
5945 /* There are more one states in the class equivalence. */
5946 set_out_arc_insns_equiv_num (first_state, odd_iteration_flag);
5947 for (prev_state = first_state,
5948 curr_state = first_state->next_equiv_class_state;
5949 curr_state != NULL;
5950 curr_state = next_state)
5952 next_state = curr_state->next_equiv_class_state;
5953 if (state_is_differed (curr_state, first_state,
5954 odd_iteration_flag))
5956 /* Remove curr state from the class equivalence. */
5957 prev_state->next_equiv_class_state = next_state;
5958 /* Add curr state to the new class equivalence. */
5959 curr_state->next_equiv_class_state = new_equiv_class;
5960 if (new_equiv_class == NULL)
5961 (*new_equiv_class_num_ptr)++;
5962 if (odd_iteration_flag)
5963 curr_state->equiv_class_num_2 = *new_equiv_class_num_ptr;
5964 else
5965 curr_state->equiv_class_num_1 = *new_equiv_class_num_ptr;
5966 new_equiv_class = curr_state;
5967 partition_p = 1;
5969 else
5970 prev_state = curr_state;
5972 clear_arc_insns_equiv_num (first_state);
5974 if (new_equiv_class != NULL)
5975 VEC_safe_push (state_t, heap, *next_iteration_classes, new_equiv_class);
5976 first_state = new_equiv_class;
5978 return partition_p;
5981 /* The function finds equivalent states of AUTOMATON. */
5982 static void
5983 evaluate_equiv_classes (automaton_t automaton,
5984 VEC(state_t, heap) **equiv_classes)
5986 int new_equiv_class_num;
5987 int odd_iteration_flag;
5988 int finish_flag;
5989 VEC (state_t, heap) *next_iteration_classes;
5990 size_t i;
5992 all_achieved_states = VEC_alloc (state_t, heap, 1500);
5993 pass_states (automaton, add_achieved_state);
5994 pass_states (automaton, cache_presence);
5995 VEC_qsort (state_t, all_achieved_states, compare_states_for_equiv);
5997 odd_iteration_flag = 0;
5998 new_equiv_class_num = init_equiv_class (all_achieved_states,
5999 &next_iteration_classes);
6003 odd_iteration_flag = !odd_iteration_flag;
6004 finish_flag = 1;
6005 copy_equiv_class (equiv_classes, next_iteration_classes);
6007 /* Transfer equiv numbers for the next iteration. */
6008 for (i = 0; i < VEC_length (state_t, all_achieved_states); i++)
6009 if (odd_iteration_flag)
6010 VEC_index (state_t, all_achieved_states, i)->equiv_class_num_2
6011 = VEC_index (state_t, all_achieved_states, i)->equiv_class_num_1;
6012 else
6013 VEC_index (state_t, all_achieved_states, i)->equiv_class_num_1
6014 = VEC_index (state_t, all_achieved_states, i)->equiv_class_num_2;
6016 for (i = 0; i < VEC_length (state_t, *equiv_classes); i++)
6017 if (partition_equiv_class (VEC_index (state_t, *equiv_classes, i),
6018 odd_iteration_flag,
6019 &next_iteration_classes,
6020 &new_equiv_class_num))
6021 finish_flag = 0;
6023 while (!finish_flag);
6024 VEC_free (state_t, heap, next_iteration_classes);
6025 VEC_free (state_t, heap, all_achieved_states);
6028 /* The function merges equivalent states of AUTOMATON. */
6029 static void
6030 merge_states (automaton_t automaton, VEC(state_t, heap) *equiv_classes)
6032 state_t curr_state;
6033 state_t new_state;
6034 state_t first_class_state;
6035 alt_state_t alt_states;
6036 alt_state_t alt_state, new_alt_state;
6037 arc_t curr_arc;
6038 arc_t next_arc;
6039 size_t i;
6041 /* Create states corresponding to equivalence classes containing two
6042 or more states. */
6043 for (i = 0; i < VEC_length (state_t, equiv_classes); i++)
6045 curr_state = VEC_index (state_t, equiv_classes, i);
6046 if (curr_state->next_equiv_class_state != NULL)
6048 /* There are more one states in the class equivalence. */
6049 /* Create new compound state. */
6050 new_state = get_free_state (0, automaton);
6051 alt_states = NULL;
6052 first_class_state = curr_state;
6053 for (curr_state = first_class_state;
6054 curr_state != NULL;
6055 curr_state = curr_state->next_equiv_class_state)
6057 curr_state->equiv_class_state = new_state;
6058 if (curr_state->component_states == NULL)
6060 new_alt_state = get_free_alt_state ();
6061 new_alt_state->state = curr_state;
6062 new_alt_state->next_alt_state = alt_states;
6063 alt_states = new_alt_state;
6065 else
6066 for (alt_state = curr_state->component_states;
6067 alt_state != NULL;
6068 alt_state = alt_state->next_sorted_alt_state)
6070 new_alt_state = get_free_alt_state ();
6071 new_alt_state->state = alt_state->state;
6072 new_alt_state->next_alt_state = alt_states;
6073 alt_states = new_alt_state;
6076 /* Its is important that alt states were sorted before and
6077 after merging to have the same querying results. */
6078 new_state->component_states = uniq_sort_alt_states (alt_states);
6080 else
6081 curr_state->equiv_class_state = curr_state;
6084 for (i = 0; i < VEC_length (state_t, equiv_classes); i++)
6086 curr_state = VEC_index (state_t, equiv_classes, i);
6087 if (curr_state->next_equiv_class_state != NULL)
6089 first_class_state = curr_state;
6090 /* Create new arcs output from the state corresponding to
6091 equiv class. */
6092 for (curr_arc = first_out_arc (first_class_state);
6093 curr_arc != NULL;
6094 curr_arc = next_out_arc (curr_arc))
6095 add_arc (first_class_state->equiv_class_state,
6096 curr_arc->to_state->equiv_class_state,
6097 curr_arc->insn);
6098 /* Delete output arcs from states of given class equivalence. */
6099 for (curr_state = first_class_state;
6100 curr_state != NULL;
6101 curr_state = curr_state->next_equiv_class_state)
6103 if (automaton->start_state == curr_state)
6104 automaton->start_state = curr_state->equiv_class_state;
6105 /* Delete the state and its output arcs. */
6106 for (curr_arc = first_out_arc (curr_state);
6107 curr_arc != NULL;
6108 curr_arc = next_arc)
6110 next_arc = next_out_arc (curr_arc);
6111 free_arc (curr_arc);
6115 else
6117 /* Change `to_state' of arcs output from the state of given
6118 equivalence class. */
6119 for (curr_arc = first_out_arc (curr_state);
6120 curr_arc != NULL;
6121 curr_arc = next_out_arc (curr_arc))
6122 curr_arc->to_state = curr_arc->to_state->equiv_class_state;
6127 /* The function sets up new_cycle_p for states if there is arc to the
6128 state marked by advance_cycle_insn_decl. */
6129 static void
6130 set_new_cycle_flags (state_t state)
6132 arc_t arc;
6134 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6135 if (arc->insn->insn_reserv_decl
6136 == DECL_INSN_RESERV (advance_cycle_insn_decl))
6137 arc->to_state->new_cycle_p = 1;
6140 /* The top level function for minimization of deterministic
6141 AUTOMATON. */
6142 static void
6143 minimize_DFA (automaton_t automaton)
6145 VEC(state_t, heap) *equiv_classes = 0;
6147 evaluate_equiv_classes (automaton, &equiv_classes);
6148 merge_states (automaton, equiv_classes);
6149 pass_states (automaton, set_new_cycle_flags);
6151 VEC_free (state_t, heap, equiv_classes);
6154 /* Values of two variables are counted number of states and arcs in an
6155 automaton. */
6156 static int curr_counted_states_num;
6157 static int curr_counted_arcs_num;
6159 /* The function is called by function `pass_states' to count states
6160 and arcs of an automaton. */
6161 static void
6162 incr_states_and_arcs_nums (state_t state)
6164 arc_t arc;
6166 curr_counted_states_num++;
6167 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6168 curr_counted_arcs_num++;
6171 /* The function counts states and arcs of AUTOMATON. */
6172 static void
6173 count_states_and_arcs (automaton_t automaton, int *states_num,
6174 int *arcs_num)
6176 curr_counted_states_num = 0;
6177 curr_counted_arcs_num = 0;
6178 pass_states (automaton, incr_states_and_arcs_nums);
6179 *states_num = curr_counted_states_num;
6180 *arcs_num = curr_counted_arcs_num;
6183 /* The function builds one DFA AUTOMATON for fast pipeline hazards
6184 recognition after checking and simplifying IR of the
6185 description. */
6186 static void
6187 build_automaton (automaton_t automaton)
6189 int states_num;
6190 int arcs_num;
6192 ticker_on (&NDFA_time);
6193 if (progress_flag)
6195 if (automaton->corresponding_automaton_decl == NULL)
6196 fprintf (stderr, "Create anonymous automaton");
6197 else
6198 fprintf (stderr, "Create automaton `%s'",
6199 automaton->corresponding_automaton_decl->name);
6200 fprintf (stderr, " (1 dot is 100 new states):");
6202 make_automaton (automaton);
6203 if (progress_flag)
6204 fprintf (stderr, " done\n");
6205 ticker_off (&NDFA_time);
6206 count_states_and_arcs (automaton, &states_num, &arcs_num);
6207 automaton->NDFA_states_num = states_num;
6208 automaton->NDFA_arcs_num = arcs_num;
6209 ticker_on (&NDFA_to_DFA_time);
6210 if (progress_flag)
6212 if (automaton->corresponding_automaton_decl == NULL)
6213 fprintf (stderr, "Make anonymous DFA");
6214 else
6215 fprintf (stderr, "Make DFA `%s'",
6216 automaton->corresponding_automaton_decl->name);
6217 fprintf (stderr, " (1 dot is 100 new states):");
6219 NDFA_to_DFA (automaton);
6220 if (progress_flag)
6221 fprintf (stderr, " done\n");
6222 ticker_off (&NDFA_to_DFA_time);
6223 count_states_and_arcs (automaton, &states_num, &arcs_num);
6224 automaton->DFA_states_num = states_num;
6225 automaton->DFA_arcs_num = arcs_num;
6226 if (!no_minimization_flag)
6228 ticker_on (&minimize_time);
6229 if (progress_flag)
6231 if (automaton->corresponding_automaton_decl == NULL)
6232 fprintf (stderr, "Minimize anonymous DFA...");
6233 else
6234 fprintf (stderr, "Minimize DFA `%s'...",
6235 automaton->corresponding_automaton_decl->name);
6237 minimize_DFA (automaton);
6238 if (progress_flag)
6239 fprintf (stderr, "done\n");
6240 ticker_off (&minimize_time);
6241 count_states_and_arcs (automaton, &states_num, &arcs_num);
6242 automaton->minimal_DFA_states_num = states_num;
6243 automaton->minimal_DFA_arcs_num = arcs_num;
6249 /* The page contains code for enumeration of all states of an automaton. */
6251 /* Variable used for enumeration of all states of an automaton. Its
6252 value is current number of automaton states. */
6253 static int curr_state_order_num;
6255 /* The function is called by function `pass_states' for enumerating
6256 states. */
6257 static void
6258 set_order_state_num (state_t state)
6260 state->order_state_num = curr_state_order_num;
6261 curr_state_order_num++;
6264 /* The function enumerates all states of AUTOMATON. */
6265 static void
6266 enumerate_states (automaton_t automaton)
6268 curr_state_order_num = 0;
6269 pass_states (automaton, set_order_state_num);
6270 automaton->achieved_states_num = curr_state_order_num;
6275 /* The page contains code for finding equivalent automaton insns
6276 (ainsns). */
6278 /* The function inserts AINSN into cyclic list
6279 CYCLIC_EQUIV_CLASS_INSN_LIST of ainsns. */
6280 static ainsn_t
6281 insert_ainsn_into_equiv_class (ainsn_t ainsn,
6282 ainsn_t cyclic_equiv_class_insn_list)
6284 if (cyclic_equiv_class_insn_list == NULL)
6285 ainsn->next_equiv_class_insn = ainsn;
6286 else
6288 ainsn->next_equiv_class_insn
6289 = cyclic_equiv_class_insn_list->next_equiv_class_insn;
6290 cyclic_equiv_class_insn_list->next_equiv_class_insn = ainsn;
6292 return ainsn;
6295 /* The function deletes equiv_class_insn into cyclic list of
6296 equivalent ainsns. */
6297 static void
6298 delete_ainsn_from_equiv_class (ainsn_t equiv_class_insn)
6300 ainsn_t curr_equiv_class_insn;
6301 ainsn_t prev_equiv_class_insn;
6303 prev_equiv_class_insn = equiv_class_insn;
6304 for (curr_equiv_class_insn = equiv_class_insn->next_equiv_class_insn;
6305 curr_equiv_class_insn != equiv_class_insn;
6306 curr_equiv_class_insn = curr_equiv_class_insn->next_equiv_class_insn)
6307 prev_equiv_class_insn = curr_equiv_class_insn;
6308 if (prev_equiv_class_insn != equiv_class_insn)
6309 prev_equiv_class_insn->next_equiv_class_insn
6310 = equiv_class_insn->next_equiv_class_insn;
6313 /* The function processes AINSN of a state in order to find equivalent
6314 ainsns. INSN_ARCS_ARRAY is table: code of insn -> out arc of the
6315 state. */
6316 static void
6317 process_insn_equiv_class (ainsn_t ainsn, arc_t *insn_arcs_array)
6319 ainsn_t next_insn;
6320 ainsn_t curr_insn;
6321 ainsn_t cyclic_insn_list;
6322 arc_t arc;
6324 gcc_assert (insn_arcs_array [ainsn->insn_reserv_decl->insn_num]);
6325 curr_insn = ainsn;
6326 /* New class of ainsns which are not equivalent to given ainsn. */
6327 cyclic_insn_list = NULL;
6330 next_insn = curr_insn->next_equiv_class_insn;
6331 arc = insn_arcs_array [curr_insn->insn_reserv_decl->insn_num];
6332 if (arc == NULL
6333 || (insn_arcs_array [ainsn->insn_reserv_decl->insn_num]->to_state
6334 != arc->to_state))
6336 delete_ainsn_from_equiv_class (curr_insn);
6337 cyclic_insn_list = insert_ainsn_into_equiv_class (curr_insn,
6338 cyclic_insn_list);
6340 curr_insn = next_insn;
6342 while (curr_insn != ainsn);
6345 /* The function processes STATE in order to find equivalent ainsns. */
6346 static void
6347 process_state_for_insn_equiv_partition (state_t state)
6349 arc_t arc;
6350 arc_t *insn_arcs_array = XCNEWVEC (arc_t, description->insns_num);
6352 /* Process insns of the arcs. */
6353 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6354 insn_arcs_array [arc->insn->insn_reserv_decl->insn_num] = arc;
6355 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6356 process_insn_equiv_class (arc->insn, insn_arcs_array);
6358 free (insn_arcs_array);
6361 /* The function searches for equivalent ainsns of AUTOMATON. */
6362 static void
6363 set_insn_equiv_classes (automaton_t automaton)
6365 ainsn_t ainsn;
6366 ainsn_t first_insn;
6367 ainsn_t curr_insn;
6368 ainsn_t cyclic_insn_list;
6369 ainsn_t insn_with_same_reservs;
6370 int equiv_classes_num;
6372 /* All insns are included in one equivalence class. */
6373 cyclic_insn_list = NULL;
6374 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6375 if (ainsn->first_insn_with_same_reservs)
6376 cyclic_insn_list = insert_ainsn_into_equiv_class (ainsn,
6377 cyclic_insn_list);
6378 /* Process insns in order to make equivalence partition. */
6379 pass_states (automaton, process_state_for_insn_equiv_partition);
6380 /* Enumerate equiv classes. */
6381 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6382 /* Set undefined value. */
6383 ainsn->insn_equiv_class_num = -1;
6384 equiv_classes_num = 0;
6385 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6386 if (ainsn->insn_equiv_class_num < 0)
6388 first_insn = ainsn;
6389 gcc_assert (first_insn->first_insn_with_same_reservs);
6390 first_insn->first_ainsn_with_given_equivalence_num = 1;
6391 curr_insn = first_insn;
6394 for (insn_with_same_reservs = curr_insn;
6395 insn_with_same_reservs != NULL;
6396 insn_with_same_reservs
6397 = insn_with_same_reservs->next_same_reservs_insn)
6398 insn_with_same_reservs->insn_equiv_class_num = equiv_classes_num;
6399 curr_insn = curr_insn->next_equiv_class_insn;
6401 while (curr_insn != first_insn);
6402 equiv_classes_num++;
6404 automaton->insn_equiv_classes_num = equiv_classes_num;
6409 /* This page contains code for creating DFA(s) and calls functions
6410 building them. */
6413 /* The following value is used to prevent floating point overflow for
6414 estimating an automaton bound. The value should be less DBL_MAX on
6415 the host machine. We use here approximate minimum of maximal
6416 double floating point value required by ANSI C standard. It
6417 will work for non ANSI sun compiler too. */
6419 #define MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND 1.0E37
6421 /* The function estimate size of the single DFA used by PHR (pipeline
6422 hazards recognizer). */
6423 static double
6424 estimate_one_automaton_bound (void)
6426 decl_t decl;
6427 double one_automaton_estimation_bound;
6428 double root_value;
6429 int i;
6431 one_automaton_estimation_bound = 1.0;
6432 for (i = 0; i < description->decls_num; i++)
6434 decl = description->decls [i];
6435 if (decl->mode == dm_unit)
6437 root_value = exp (log (DECL_UNIT (decl)->max_occ_cycle_num
6438 - DECL_UNIT (decl)->min_occ_cycle_num + 1.0)
6439 / automata_num);
6440 if (MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND / root_value
6441 > one_automaton_estimation_bound)
6442 one_automaton_estimation_bound *= root_value;
6445 return one_automaton_estimation_bound;
6448 /* The function compares unit declarations according to their maximal
6449 cycle in reservations. */
6450 static int
6451 compare_max_occ_cycle_nums (const void *unit_decl_1,
6452 const void *unit_decl_2)
6454 if ((DECL_UNIT (*(const_decl_t const*) unit_decl_1)->max_occ_cycle_num)
6455 < (DECL_UNIT (*(const_decl_t const*) unit_decl_2)->max_occ_cycle_num))
6456 return 1;
6457 else if ((DECL_UNIT (*(const_decl_t const*) unit_decl_1)->max_occ_cycle_num)
6458 == (DECL_UNIT (*(const_decl_t const*) unit_decl_2)->max_occ_cycle_num))
6459 return 0;
6460 else
6461 return -1;
6464 /* The function makes heuristic assigning automata to units. Actually
6465 efficacy of the algorithm has been checked yet??? */
6467 static void
6468 units_to_automata_heuristic_distr (void)
6470 double estimation_bound;
6471 int automaton_num;
6472 int rest_units_num;
6473 double bound_value;
6474 unit_decl_t *unit_decls;
6475 int i, j;
6477 if (description->units_num == 0)
6478 return;
6479 estimation_bound = estimate_one_automaton_bound ();
6480 unit_decls = XNEWVEC (unit_decl_t, description->units_num);
6482 for (i = 0, j = 0; i < description->decls_num; i++)
6483 if (description->decls[i]->mode == dm_unit)
6484 unit_decls[j++] = DECL_UNIT (description->decls[i]);
6485 gcc_assert (j == description->units_num);
6487 qsort (unit_decls, description->units_num,
6488 sizeof (unit_decl_t), compare_max_occ_cycle_nums);
6490 automaton_num = 0;
6491 bound_value = unit_decls[0]->max_occ_cycle_num;
6492 unit_decls[0]->corresponding_automaton_num = automaton_num;
6494 for (i = 1; i < description->units_num; i++)
6496 rest_units_num = description->units_num - i + 1;
6497 gcc_assert (automata_num - automaton_num - 1 <= rest_units_num);
6498 if (automaton_num < automata_num - 1
6499 && ((automata_num - automaton_num - 1 == rest_units_num)
6500 || (bound_value
6501 > (estimation_bound
6502 / unit_decls[i]->max_occ_cycle_num))))
6504 bound_value = unit_decls[i]->max_occ_cycle_num;
6505 automaton_num++;
6507 else
6508 bound_value *= unit_decls[i]->max_occ_cycle_num;
6509 unit_decls[i]->corresponding_automaton_num = automaton_num;
6511 gcc_assert (automaton_num == automata_num - 1);
6512 free (unit_decls);
6515 /* The functions creates automaton insns for each automata. Automaton
6516 insn is simply insn for given automaton which makes reservation
6517 only of units of the automaton. */
6518 static ainsn_t
6519 create_ainsns (void)
6521 decl_t decl;
6522 ainsn_t first_ainsn;
6523 ainsn_t curr_ainsn;
6524 ainsn_t prev_ainsn;
6525 int i;
6527 first_ainsn = NULL;
6528 prev_ainsn = NULL;
6529 for (i = 0; i < description->decls_num; i++)
6531 decl = description->decls [i];
6532 if (decl->mode == dm_insn_reserv)
6534 curr_ainsn = XCREATENODE (struct ainsn);
6535 curr_ainsn->insn_reserv_decl = DECL_INSN_RESERV (decl);
6536 curr_ainsn->important_p = FALSE;
6537 curr_ainsn->next_ainsn = NULL;
6538 if (prev_ainsn == NULL)
6539 first_ainsn = curr_ainsn;
6540 else
6541 prev_ainsn->next_ainsn = curr_ainsn;
6542 prev_ainsn = curr_ainsn;
6545 return first_ainsn;
6548 /* The function assigns automata to units according to constructions
6549 `define_automaton' in the description. */
6550 static void
6551 units_to_automata_distr (void)
6553 decl_t decl;
6554 int i;
6556 for (i = 0; i < description->decls_num; i++)
6558 decl = description->decls [i];
6559 if (decl->mode == dm_unit)
6561 if (DECL_UNIT (decl)->automaton_decl == NULL
6562 || (DECL_UNIT (decl)->automaton_decl->corresponding_automaton
6563 == NULL))
6564 /* Distribute to the first automaton. */
6565 DECL_UNIT (decl)->corresponding_automaton_num = 0;
6566 else
6567 DECL_UNIT (decl)->corresponding_automaton_num
6568 = (DECL_UNIT (decl)->automaton_decl
6569 ->corresponding_automaton->automaton_order_num);
6574 /* The function creates DFA(s) for fast pipeline hazards recognition
6575 after checking and simplifying IR of the description. */
6576 static void
6577 create_automata (void)
6579 automaton_t curr_automaton;
6580 automaton_t prev_automaton;
6581 decl_t decl;
6582 int curr_automaton_num;
6583 int i;
6585 if (automata_num != 0)
6587 units_to_automata_heuristic_distr ();
6588 for (prev_automaton = NULL, curr_automaton_num = 0;
6589 curr_automaton_num < automata_num;
6590 curr_automaton_num++, prev_automaton = curr_automaton)
6592 curr_automaton = XCREATENODE (struct automaton);
6593 curr_automaton->ainsn_list = create_ainsns ();
6594 curr_automaton->corresponding_automaton_decl = NULL;
6595 curr_automaton->next_automaton = NULL;
6596 curr_automaton->automaton_order_num = curr_automaton_num;
6597 if (prev_automaton == NULL)
6598 description->first_automaton = curr_automaton;
6599 else
6600 prev_automaton->next_automaton = curr_automaton;
6603 else
6605 curr_automaton_num = 0;
6606 prev_automaton = NULL;
6607 for (i = 0; i < description->decls_num; i++)
6609 decl = description->decls [i];
6610 if (decl->mode == dm_automaton
6611 && DECL_AUTOMATON (decl)->automaton_is_used)
6613 curr_automaton = XCREATENODE (struct automaton);
6614 curr_automaton->ainsn_list = create_ainsns ();
6615 curr_automaton->corresponding_automaton_decl
6616 = DECL_AUTOMATON (decl);
6617 curr_automaton->next_automaton = NULL;
6618 DECL_AUTOMATON (decl)->corresponding_automaton = curr_automaton;
6619 curr_automaton->automaton_order_num = curr_automaton_num;
6620 if (prev_automaton == NULL)
6621 description->first_automaton = curr_automaton;
6622 else
6623 prev_automaton->next_automaton = curr_automaton;
6624 curr_automaton_num++;
6625 prev_automaton = curr_automaton;
6628 if (curr_automaton_num == 0)
6630 curr_automaton = XCREATENODE (struct automaton);
6631 curr_automaton->ainsn_list = create_ainsns ();
6632 curr_automaton->corresponding_automaton_decl = NULL;
6633 curr_automaton->next_automaton = NULL;
6634 description->first_automaton = curr_automaton;
6636 units_to_automata_distr ();
6638 NDFA_time = create_ticker ();
6639 ticker_off (&NDFA_time);
6640 NDFA_to_DFA_time = create_ticker ();
6641 ticker_off (&NDFA_to_DFA_time);
6642 minimize_time = create_ticker ();
6643 ticker_off (&minimize_time);
6644 equiv_time = create_ticker ();
6645 ticker_off (&equiv_time);
6646 for (curr_automaton = description->first_automaton;
6647 curr_automaton != NULL;
6648 curr_automaton = curr_automaton->next_automaton)
6650 if (progress_flag)
6652 if (curr_automaton->corresponding_automaton_decl == NULL)
6653 fprintf (stderr, "Prepare anonymous automaton creation ... ");
6654 else
6655 fprintf (stderr, "Prepare automaton `%s' creation...",
6656 curr_automaton->corresponding_automaton_decl->name);
6658 create_alt_states (curr_automaton);
6659 form_ainsn_with_same_reservs (curr_automaton);
6660 if (progress_flag)
6661 fprintf (stderr, "done\n");
6662 build_automaton (curr_automaton);
6663 enumerate_states (curr_automaton);
6664 ticker_on (&equiv_time);
6665 set_insn_equiv_classes (curr_automaton);
6666 ticker_off (&equiv_time);
6672 /* This page contains code for forming string representation of
6673 regexp. The representation is formed on IR obstack. So you should
6674 not work with IR obstack between regexp_representation and
6675 finish_regexp_representation calls. */
6677 /* This recursive function forms string representation of regexp
6678 (without tailing '\0'). */
6679 static void
6680 form_regexp (regexp_t regexp)
6682 int i;
6684 switch (regexp->mode)
6686 case rm_unit: case rm_reserv:
6688 const char *name = (regexp->mode == rm_unit
6689 ? REGEXP_UNIT (regexp)->name
6690 : REGEXP_RESERV (regexp)->name);
6692 obstack_grow (&irp, name, strlen (name));
6693 break;
6696 case rm_sequence:
6697 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
6699 if (i != 0)
6700 obstack_1grow (&irp, ',');
6701 form_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
6703 break;
6705 case rm_allof:
6706 obstack_1grow (&irp, '(');
6707 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
6709 if (i != 0)
6710 obstack_1grow (&irp, '+');
6711 if (REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_sequence
6712 || REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_oneof)
6713 obstack_1grow (&irp, '(');
6714 form_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
6715 if (REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_sequence
6716 || REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_oneof)
6717 obstack_1grow (&irp, ')');
6719 obstack_1grow (&irp, ')');
6720 break;
6722 case rm_oneof:
6723 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
6725 if (i != 0)
6726 obstack_1grow (&irp, '|');
6727 if (REGEXP_ONEOF (regexp)->regexps[i]->mode == rm_sequence)
6728 obstack_1grow (&irp, '(');
6729 form_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
6730 if (REGEXP_ONEOF (regexp)->regexps[i]->mode == rm_sequence)
6731 obstack_1grow (&irp, ')');
6733 break;
6735 case rm_repeat:
6737 char digits [30];
6739 if (REGEXP_REPEAT (regexp)->regexp->mode == rm_sequence
6740 || REGEXP_REPEAT (regexp)->regexp->mode == rm_allof
6741 || REGEXP_REPEAT (regexp)->regexp->mode == rm_oneof)
6742 obstack_1grow (&irp, '(');
6743 form_regexp (REGEXP_REPEAT (regexp)->regexp);
6744 if (REGEXP_REPEAT (regexp)->regexp->mode == rm_sequence
6745 || REGEXP_REPEAT (regexp)->regexp->mode == rm_allof
6746 || REGEXP_REPEAT (regexp)->regexp->mode == rm_oneof)
6747 obstack_1grow (&irp, ')');
6748 sprintf (digits, "*%d", REGEXP_REPEAT (regexp)->repeat_num);
6749 obstack_grow (&irp, digits, strlen (digits));
6750 break;
6753 case rm_nothing:
6754 obstack_grow (&irp, NOTHING_NAME, strlen (NOTHING_NAME));
6755 break;
6757 default:
6758 gcc_unreachable ();
6762 /* The function returns string representation of REGEXP on IR
6763 obstack. */
6764 static const char *
6765 regexp_representation (regexp_t regexp)
6767 form_regexp (regexp);
6768 obstack_1grow (&irp, '\0');
6769 return obstack_base (&irp);
6772 /* The function frees memory allocated for last formed string
6773 representation of regexp. */
6774 static void
6775 finish_regexp_representation (void)
6777 int length = obstack_object_size (&irp);
6779 obstack_blank_fast (&irp, -length);
6784 /* This page contains code for output PHR (pipeline hazards recognizer). */
6786 /* The function outputs minimal C type which is sufficient for
6787 representation numbers in range min_range_value and
6788 max_range_value. Because host machine and build machine may be
6789 different, we use here minimal values required by ANSI C standard
6790 instead of UCHAR_MAX, SHRT_MAX, SHRT_MIN, etc. This is a good
6791 approximation. */
6793 static void
6794 output_range_type (FILE *f, long int min_range_value,
6795 long int max_range_value)
6797 if (min_range_value >= 0 && max_range_value <= 255)
6798 fprintf (f, "unsigned char");
6799 else if (min_range_value >= -127 && max_range_value <= 127)
6800 fprintf (f, "signed char");
6801 else if (min_range_value >= 0 && max_range_value <= 65535)
6802 fprintf (f, "unsigned short");
6803 else if (min_range_value >= -32767 && max_range_value <= 32767)
6804 fprintf (f, "short");
6805 else
6806 fprintf (f, "int");
6809 /* The function outputs all initialization values of VECT. */
6810 static void
6811 output_vect (vla_hwint_t vect)
6813 int els_on_line;
6814 size_t vect_length = VEC_length (vect_el_t, vect);
6815 size_t i;
6817 els_on_line = 1;
6818 if (vect_length == 0)
6819 fputs ("0 /* This is dummy el because the vect is empty */", output_file);
6820 else
6821 for (i = 0; i < vect_length; i++)
6823 fprintf (output_file, "%5ld", (long) VEC_index (vect_el_t, vect, i));
6824 if (els_on_line == 10)
6826 els_on_line = 0;
6827 fputs (",\n", output_file);
6829 else if (i < vect_length-1)
6830 fputs (", ", output_file);
6831 els_on_line++;
6835 /* The following is name of the structure which represents DFA(s) for
6836 PHR. */
6837 #define CHIP_NAME "DFA_chip"
6839 /* The following is name of member which represents state of a DFA for
6840 PHR. */
6841 static void
6842 output_chip_member_name (FILE *f, automaton_t automaton)
6844 if (automaton->corresponding_automaton_decl == NULL)
6845 fprintf (f, "automaton_state_%d", automaton->automaton_order_num);
6846 else
6847 fprintf (f, "%s_automaton_state",
6848 automaton->corresponding_automaton_decl->name);
6851 /* The following is name of temporary variable which stores state of a
6852 DFA for PHR. */
6853 static void
6854 output_temp_chip_member_name (FILE *f, automaton_t automaton)
6856 fprintf (f, "_");
6857 output_chip_member_name (f, automaton);
6860 /* This is name of macro value which is code of pseudo_insn
6861 representing advancing cpu cycle. Its value is used as internal
6862 code unknown insn. */
6863 #define ADVANCE_CYCLE_VALUE_NAME "DFA__ADVANCE_CYCLE"
6865 /* Output name of translate vector for given automaton. */
6866 static void
6867 output_translate_vect_name (FILE *f, automaton_t automaton)
6869 if (automaton->corresponding_automaton_decl == NULL)
6870 fprintf (f, "translate_%d", automaton->automaton_order_num);
6871 else
6872 fprintf (f, "%s_translate", automaton->corresponding_automaton_decl->name);
6875 /* Output name for simple transition table representation. */
6876 static void
6877 output_trans_full_vect_name (FILE *f, automaton_t automaton)
6879 if (automaton->corresponding_automaton_decl == NULL)
6880 fprintf (f, "transitions_%d", automaton->automaton_order_num);
6881 else
6882 fprintf (f, "%s_transitions",
6883 automaton->corresponding_automaton_decl->name);
6886 /* Output name of comb vector of the transition table for given
6887 automaton. */
6888 static void
6889 output_trans_comb_vect_name (FILE *f, automaton_t automaton)
6891 if (automaton->corresponding_automaton_decl == NULL)
6892 fprintf (f, "transitions_%d", automaton->automaton_order_num);
6893 else
6894 fprintf (f, "%s_transitions",
6895 automaton->corresponding_automaton_decl->name);
6898 /* Output name of check vector of the transition table for given
6899 automaton. */
6900 static void
6901 output_trans_check_vect_name (FILE *f, automaton_t automaton)
6903 if (automaton->corresponding_automaton_decl == NULL)
6904 fprintf (f, "check_%d", automaton->automaton_order_num);
6905 else
6906 fprintf (f, "%s_check", automaton->corresponding_automaton_decl->name);
6909 /* Output name of base vector of the transition table for given
6910 automaton. */
6911 static void
6912 output_trans_base_vect_name (FILE *f, automaton_t automaton)
6914 if (automaton->corresponding_automaton_decl == NULL)
6915 fprintf (f, "base_%d", automaton->automaton_order_num);
6916 else
6917 fprintf (f, "%s_base", automaton->corresponding_automaton_decl->name);
6920 /* Output name of simple min issue delay table representation. */
6921 static void
6922 output_min_issue_delay_vect_name (FILE *f, automaton_t automaton)
6924 if (automaton->corresponding_automaton_decl == NULL)
6925 fprintf (f, "min_issue_delay_%d", automaton->automaton_order_num);
6926 else
6927 fprintf (f, "%s_min_issue_delay",
6928 automaton->corresponding_automaton_decl->name);
6931 /* Output name of deadlock vector for given automaton. */
6932 static void
6933 output_dead_lock_vect_name (FILE *f, automaton_t automaton)
6935 if (automaton->corresponding_automaton_decl == NULL)
6936 fprintf (f, "dead_lock_%d", automaton->automaton_order_num);
6937 else
6938 fprintf (f, "%s_dead_lock", automaton->corresponding_automaton_decl->name);
6941 /* Output name of reserved units table for AUTOMATON into file F. */
6942 static void
6943 output_reserved_units_table_name (FILE *f, automaton_t automaton)
6945 if (automaton->corresponding_automaton_decl == NULL)
6946 fprintf (f, "reserved_units_%d", automaton->automaton_order_num);
6947 else
6948 fprintf (f, "%s_reserved_units",
6949 automaton->corresponding_automaton_decl->name);
6952 /* Name of the PHR interface macro. */
6953 #define CPU_UNITS_QUERY_MACRO_NAME "CPU_UNITS_QUERY"
6955 /* Names of an internal functions: */
6956 #define INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME "internal_min_issue_delay"
6958 /* This is external type of DFA(s) state. */
6959 #define STATE_TYPE_NAME "state_t"
6961 #define INTERNAL_TRANSITION_FUNC_NAME "internal_state_transition"
6963 #define INTERNAL_RESET_FUNC_NAME "internal_reset"
6965 #define INTERNAL_DEAD_LOCK_FUNC_NAME "internal_state_dead_lock_p"
6967 #define INTERNAL_INSN_LATENCY_FUNC_NAME "internal_insn_latency"
6969 /* Name of cache of insn dfa codes. */
6970 #define DFA_INSN_CODES_VARIABLE_NAME "dfa_insn_codes"
6972 /* Name of length of cache of insn dfa codes. */
6973 #define DFA_INSN_CODES_LENGTH_VARIABLE_NAME "dfa_insn_codes_length"
6975 /* Names of the PHR interface functions: */
6976 #define SIZE_FUNC_NAME "state_size"
6978 #define TRANSITION_FUNC_NAME "state_transition"
6980 #define MIN_ISSUE_DELAY_FUNC_NAME "min_issue_delay"
6982 #define MIN_INSN_CONFLICT_DELAY_FUNC_NAME "min_insn_conflict_delay"
6984 #define DEAD_LOCK_FUNC_NAME "state_dead_lock_p"
6986 #define RESET_FUNC_NAME "state_reset"
6988 #define INSN_LATENCY_FUNC_NAME "insn_latency"
6990 #define PRINT_RESERVATION_FUNC_NAME "print_reservation"
6992 #define GET_CPU_UNIT_CODE_FUNC_NAME "get_cpu_unit_code"
6994 #define CPU_UNIT_RESERVATION_P_FUNC_NAME "cpu_unit_reservation_p"
6996 #define INSN_HAS_DFA_RESERVATION_P_FUNC_NAME "insn_has_dfa_reservation_p"
6998 #define DFA_CLEAN_INSN_CACHE_FUNC_NAME "dfa_clean_insn_cache"
7000 #define DFA_CLEAR_SINGLE_INSN_CACHE_FUNC_NAME "dfa_clear_single_insn_cache"
7002 #define DFA_START_FUNC_NAME "dfa_start"
7004 #define DFA_FINISH_FUNC_NAME "dfa_finish"
7006 /* Names of parameters of the PHR interface functions. */
7007 #define STATE_NAME "state"
7009 #define INSN_PARAMETER_NAME "insn"
7011 #define INSN2_PARAMETER_NAME "insn2"
7013 #define CHIP_PARAMETER_NAME "chip"
7015 #define FILE_PARAMETER_NAME "f"
7017 #define CPU_UNIT_NAME_PARAMETER_NAME "cpu_unit_name"
7019 #define CPU_CODE_PARAMETER_NAME "cpu_unit_code"
7021 /* Names of the variables whose values are internal insn code of rtx
7022 insn. */
7023 #define INTERNAL_INSN_CODE_NAME "insn_code"
7025 #define INTERNAL_INSN2_CODE_NAME "insn2_code"
7027 /* Names of temporary variables in some functions. */
7028 #define TEMPORARY_VARIABLE_NAME "temp"
7030 #define I_VARIABLE_NAME "i"
7032 /* Name of result variable in some functions. */
7033 #define RESULT_VARIABLE_NAME "res"
7035 /* Name of function (attribute) to translate insn into internal insn
7036 code. */
7037 #define INTERNAL_DFA_INSN_CODE_FUNC_NAME "internal_dfa_insn_code"
7039 /* Name of function (attribute) to translate insn into internal insn
7040 code with caching. */
7041 #define DFA_INSN_CODE_FUNC_NAME "dfa_insn_code"
7043 /* Output C type which is used for representation of codes of states
7044 of AUTOMATON. */
7045 static void
7046 output_state_member_type (FILE *f, automaton_t automaton)
7048 output_range_type (f, 0, automaton->achieved_states_num);
7051 /* Output definition of the structure representing current DFA(s)
7052 state(s). */
7053 static void
7054 output_chip_definitions (void)
7056 automaton_t automaton;
7058 fprintf (output_file, "struct %s\n{\n", CHIP_NAME);
7059 for (automaton = description->first_automaton;
7060 automaton != NULL;
7061 automaton = automaton->next_automaton)
7063 fprintf (output_file, " ");
7064 output_state_member_type (output_file, automaton);
7065 fprintf (output_file, " ");
7066 output_chip_member_name (output_file, automaton);
7067 fprintf (output_file, ";\n");
7069 fprintf (output_file, "};\n\n");
7070 #if 0
7071 fprintf (output_file, "static struct %s %s;\n\n", CHIP_NAME, CHIP_NAME);
7072 #endif
7076 /* The function outputs translate vector of internal insn code into
7077 insn equivalence class number. The equivalence class number is
7078 used to access to table and vectors representing DFA(s). */
7079 static void
7080 output_translate_vect (automaton_t automaton)
7082 ainsn_t ainsn;
7083 int insn_value;
7084 vla_hwint_t translate_vect;
7086 translate_vect = VEC_alloc (vect_el_t, heap, description->insns_num);
7088 for (insn_value = 0; insn_value < description->insns_num; insn_value++)
7089 /* Undefined value */
7090 VEC_quick_push (vect_el_t, translate_vect,
7091 automaton->insn_equiv_classes_num);
7093 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
7094 VEC_replace (vect_el_t, translate_vect,
7095 ainsn->insn_reserv_decl->insn_num,
7096 ainsn->insn_equiv_class_num);
7098 fprintf (output_file,
7099 "/* Vector translating external insn codes to internal ones.*/\n");
7100 fprintf (output_file, "static const ");
7101 output_range_type (output_file, 0, automaton->insn_equiv_classes_num);
7102 fprintf (output_file, " ");
7103 output_translate_vect_name (output_file, automaton);
7104 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7105 output_vect (translate_vect);
7106 fprintf (output_file, "};\n\n");
7107 VEC_free (vect_el_t, heap, translate_vect);
7110 /* The value in a table state x ainsn -> something which represents
7111 undefined value. */
7112 static int undefined_vect_el_value;
7114 /* The following function returns nonzero value if the best
7115 representation of the table is comb vector. */
7116 static int
7117 comb_vect_p (state_ainsn_table_t tab)
7119 return (2 * VEC_length (vect_el_t, tab->full_vect)
7120 > 5 * VEC_length (vect_el_t, tab->comb_vect));
7123 /* The following function creates new table for AUTOMATON. */
7124 static state_ainsn_table_t
7125 create_state_ainsn_table (automaton_t automaton)
7127 state_ainsn_table_t tab;
7128 int full_vect_length;
7129 int i;
7131 tab = XCREATENODE (struct state_ainsn_table);
7132 tab->automaton = automaton;
7134 tab->comb_vect = VEC_alloc (vect_el_t, heap, 10000);
7135 tab->check_vect = VEC_alloc (vect_el_t, heap, 10000);
7137 tab->base_vect = 0;
7138 VEC_safe_grow (vect_el_t, heap, tab->base_vect,
7139 automaton->achieved_states_num);
7141 full_vect_length = (automaton->insn_equiv_classes_num
7142 * automaton->achieved_states_num);
7143 tab->full_vect = VEC_alloc (vect_el_t, heap, full_vect_length);
7144 for (i = 0; i < full_vect_length; i++)
7145 VEC_quick_push (vect_el_t, tab->full_vect, undefined_vect_el_value);
7147 tab->min_base_vect_el_value = 0;
7148 tab->max_base_vect_el_value = 0;
7149 tab->min_comb_vect_el_value = 0;
7150 tab->max_comb_vect_el_value = 0;
7151 return tab;
7154 /* The following function outputs the best C representation of the
7155 table TAB of given TABLE_NAME. */
7156 static void
7157 output_state_ainsn_table (state_ainsn_table_t tab, const char *table_name,
7158 void (*output_full_vect_name_func) (FILE *, automaton_t),
7159 void (*output_comb_vect_name_func) (FILE *, automaton_t),
7160 void (*output_check_vect_name_func) (FILE *, automaton_t),
7161 void (*output_base_vect_name_func) (FILE *, automaton_t))
7163 if (!comb_vect_p (tab))
7165 fprintf (output_file, "/* Vector for %s. */\n", table_name);
7166 fprintf (output_file, "static const ");
7167 output_range_type (output_file, tab->min_comb_vect_el_value,
7168 tab->max_comb_vect_el_value);
7169 fprintf (output_file, " ");
7170 (*output_full_vect_name_func) (output_file, tab->automaton);
7171 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7172 output_vect (tab->full_vect);
7173 fprintf (output_file, "};\n\n");
7175 else
7177 fprintf (output_file, "/* Comb vector for %s. */\n", table_name);
7178 fprintf (output_file, "static const ");
7179 output_range_type (output_file, tab->min_comb_vect_el_value,
7180 tab->max_comb_vect_el_value);
7181 fprintf (output_file, " ");
7182 (*output_comb_vect_name_func) (output_file, tab->automaton);
7183 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7184 output_vect (tab->comb_vect);
7185 fprintf (output_file, "};\n\n");
7186 fprintf (output_file, "/* Check vector for %s. */\n", table_name);
7187 fprintf (output_file, "static const ");
7188 output_range_type (output_file, 0, tab->automaton->achieved_states_num);
7189 fprintf (output_file, " ");
7190 (*output_check_vect_name_func) (output_file, tab->automaton);
7191 fprintf (output_file, "[] = {\n");
7192 output_vect (tab->check_vect);
7193 fprintf (output_file, "};\n\n");
7194 fprintf (output_file, "/* Base vector for %s. */\n", table_name);
7195 fprintf (output_file, "static const ");
7196 output_range_type (output_file, tab->min_base_vect_el_value,
7197 tab->max_base_vect_el_value);
7198 fprintf (output_file, " ");
7199 (*output_base_vect_name_func) (output_file, tab->automaton);
7200 fprintf (output_file, "[] = {\n");
7201 output_vect (tab->base_vect);
7202 fprintf (output_file, "};\n\n");
7206 /* The following function adds vector VECT to table TAB as its line
7207 with number VECT_NUM. */
7208 static void
7209 add_vect (state_ainsn_table_t tab, int vect_num, vla_hwint_t vect)
7211 int vect_length;
7212 size_t real_vect_length;
7213 int comb_vect_index;
7214 int comb_vect_els_num;
7215 int vect_index;
7216 int first_unempty_vect_index;
7217 int additional_els_num;
7218 int no_state_value;
7219 vect_el_t vect_el;
7220 int i;
7221 unsigned long vect_mask, comb_vect_mask;
7223 vect_length = VEC_length (vect_el_t, vect);
7224 gcc_assert (vect_length);
7225 gcc_assert (VEC_last (vect_el_t, vect) != undefined_vect_el_value);
7226 real_vect_length = tab->automaton->insn_equiv_classes_num;
7227 /* Form full vector in the table: */
7229 size_t full_base = tab->automaton->insn_equiv_classes_num * vect_num;
7230 if (VEC_length (vect_el_t, tab->full_vect) < full_base + vect_length)
7231 VEC_safe_grow (vect_el_t, heap, tab->full_vect,
7232 full_base + vect_length);
7233 for (i = 0; i < vect_length; i++)
7234 VEC_replace (vect_el_t, tab->full_vect, full_base + i,
7235 VEC_index (vect_el_t, vect, i));
7237 /* Form comb vector in the table: */
7238 gcc_assert (VEC_length (vect_el_t, tab->comb_vect)
7239 == VEC_length (vect_el_t, tab->check_vect));
7241 comb_vect_els_num = VEC_length (vect_el_t, tab->comb_vect);
7242 for (first_unempty_vect_index = 0;
7243 first_unempty_vect_index < vect_length;
7244 first_unempty_vect_index++)
7245 if (VEC_index (vect_el_t, vect, first_unempty_vect_index)
7246 != undefined_vect_el_value)
7247 break;
7249 /* Search for the place in comb vect for the inserted vect. */
7251 /* Slow case. */
7252 if (vect_length - first_unempty_vect_index >= SIZEOF_LONG * CHAR_BIT)
7254 for (comb_vect_index = 0;
7255 comb_vect_index < comb_vect_els_num;
7256 comb_vect_index++)
7258 for (vect_index = first_unempty_vect_index;
7259 vect_index < vect_length
7260 && vect_index + comb_vect_index < comb_vect_els_num;
7261 vect_index++)
7262 if (VEC_index (vect_el_t, vect, vect_index)
7263 != undefined_vect_el_value
7264 && (VEC_index (vect_el_t, tab->comb_vect,
7265 vect_index + comb_vect_index)
7266 != undefined_vect_el_value))
7267 break;
7268 if (vect_index >= vect_length
7269 || vect_index + comb_vect_index >= comb_vect_els_num)
7270 break;
7272 goto found;
7275 /* Fast case. */
7276 vect_mask = 0;
7277 for (vect_index = first_unempty_vect_index;
7278 vect_index < vect_length;
7279 vect_index++)
7281 vect_mask = vect_mask << 1;
7282 if (VEC_index (vect_el_t, vect, vect_index) != undefined_vect_el_value)
7283 vect_mask |= 1;
7286 /* Search for the place in comb vect for the inserted vect. */
7287 comb_vect_index = 0;
7288 if (comb_vect_els_num == 0)
7289 goto found;
7291 comb_vect_mask = 0;
7292 for (vect_index = first_unempty_vect_index;
7293 vect_index < vect_length && vect_index < comb_vect_els_num;
7294 vect_index++)
7296 comb_vect_mask <<= 1;
7297 if (vect_index + comb_vect_index < comb_vect_els_num
7298 && VEC_index (vect_el_t, tab->comb_vect, vect_index + comb_vect_index)
7299 != undefined_vect_el_value)
7300 comb_vect_mask |= 1;
7302 if ((vect_mask & comb_vect_mask) == 0)
7303 goto found;
7305 for (comb_vect_index = 1, i = vect_length; i < comb_vect_els_num;
7306 comb_vect_index++, i++)
7308 comb_vect_mask = (comb_vect_mask << 1) | 1;
7309 comb_vect_mask ^= (VEC_index (vect_el_t, tab->comb_vect, i)
7310 == undefined_vect_el_value);
7311 if ((vect_mask & comb_vect_mask) == 0)
7312 goto found;
7314 for ( ; comb_vect_index < comb_vect_els_num; comb_vect_index++)
7316 comb_vect_mask <<= 1;
7317 if ((vect_mask & comb_vect_mask) == 0)
7318 goto found;
7321 found:
7322 /* Slot was found. */
7323 additional_els_num = comb_vect_index + real_vect_length - comb_vect_els_num;
7324 if (additional_els_num < 0)
7325 additional_els_num = 0;
7326 /* Expand comb and check vectors. */
7327 vect_el = undefined_vect_el_value;
7328 no_state_value = tab->automaton->achieved_states_num;
7329 while (additional_els_num > 0)
7331 VEC_safe_push (vect_el_t, heap, tab->comb_vect, vect_el);
7332 VEC_safe_push (vect_el_t, heap, tab->check_vect, no_state_value);
7333 additional_els_num--;
7335 gcc_assert (VEC_length (vect_el_t, tab->comb_vect)
7336 >= comb_vect_index + real_vect_length);
7337 /* Fill comb and check vectors. */
7338 for (vect_index = 0; vect_index < vect_length; vect_index++)
7339 if (VEC_index (vect_el_t, vect, vect_index) != undefined_vect_el_value)
7341 vect_el_t x = VEC_index (vect_el_t, vect, vect_index);
7342 gcc_assert (VEC_index (vect_el_t, tab->comb_vect,
7343 comb_vect_index + vect_index)
7344 == undefined_vect_el_value);
7345 gcc_assert (x >= 0);
7346 if (tab->max_comb_vect_el_value < x)
7347 tab->max_comb_vect_el_value = x;
7348 if (tab->min_comb_vect_el_value > x)
7349 tab->min_comb_vect_el_value = x;
7350 VEC_replace (vect_el_t, tab->comb_vect,
7351 comb_vect_index + vect_index, x);
7352 VEC_replace (vect_el_t, tab->check_vect,
7353 comb_vect_index + vect_index, vect_num);
7355 if (tab->max_comb_vect_el_value < undefined_vect_el_value)
7356 tab->max_comb_vect_el_value = undefined_vect_el_value;
7357 if (tab->min_comb_vect_el_value > undefined_vect_el_value)
7358 tab->min_comb_vect_el_value = undefined_vect_el_value;
7359 if (tab->max_base_vect_el_value < comb_vect_index)
7360 tab->max_base_vect_el_value = comb_vect_index;
7361 if (tab->min_base_vect_el_value > comb_vect_index)
7362 tab->min_base_vect_el_value = comb_vect_index;
7364 VEC_replace (vect_el_t, tab->base_vect, vect_num, comb_vect_index);
7367 /* Return number of out arcs of STATE. */
7368 static int
7369 out_state_arcs_num (const_state_t state)
7371 int result;
7372 arc_t arc;
7374 result = 0;
7375 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
7377 gcc_assert (arc->insn);
7378 if (arc->insn->first_ainsn_with_given_equivalence_num)
7379 result++;
7381 return result;
7384 /* Compare number of possible transitions from the states. */
7385 static int
7386 compare_transition_els_num (const void *state_ptr_1,
7387 const void *state_ptr_2)
7389 const int transition_els_num_1
7390 = out_state_arcs_num (*(const_state_t const*) state_ptr_1);
7391 const int transition_els_num_2
7392 = out_state_arcs_num (*(const_state_t const*) state_ptr_2);
7394 if (transition_els_num_1 < transition_els_num_2)
7395 return 1;
7396 else if (transition_els_num_1 == transition_els_num_2)
7397 return 0;
7398 else
7399 return -1;
7402 /* The function adds element EL_VALUE to vector VECT for a table state
7403 x AINSN. */
7404 static void
7405 add_vect_el (vla_hwint_t *vect, ainsn_t ainsn, int el_value)
7407 int equiv_class_num;
7408 int vect_index;
7410 gcc_assert (ainsn);
7411 equiv_class_num = ainsn->insn_equiv_class_num;
7412 for (vect_index = VEC_length (vect_el_t, *vect);
7413 vect_index <= equiv_class_num;
7414 vect_index++)
7415 VEC_safe_push (vect_el_t, heap, *vect, undefined_vect_el_value);
7416 VEC_replace (vect_el_t, *vect, equiv_class_num, el_value);
7419 /* This is for forming vector of states of an automaton. */
7420 static VEC(state_t, heap) *output_states_vect;
7422 /* The function is called by function pass_states. The function adds
7423 STATE to `output_states_vect'. */
7424 static void
7425 add_states_vect_el (state_t state)
7427 VEC_safe_push (state_t, heap, output_states_vect, state);
7430 /* Form and output vectors (comb, check, base or full vector)
7431 representing transition table of AUTOMATON. */
7432 static void
7433 output_trans_table (automaton_t automaton)
7435 size_t i;
7436 arc_t arc;
7437 vla_hwint_t transition_vect = 0;
7439 undefined_vect_el_value = automaton->achieved_states_num;
7440 automaton->trans_table = create_state_ainsn_table (automaton);
7441 /* Create vect of pointers to states ordered by num of transitions
7442 from the state (state with the maximum num is the first). */
7443 output_states_vect = 0;
7444 pass_states (automaton, add_states_vect_el);
7445 VEC_qsort (state_t, output_states_vect, compare_transition_els_num);
7447 for (i = 0; i < VEC_length (state_t, output_states_vect); i++)
7449 VEC_truncate (vect_el_t, transition_vect, 0);
7450 for (arc = first_out_arc (VEC_index (state_t, output_states_vect, i));
7451 arc != NULL;
7452 arc = next_out_arc (arc))
7454 gcc_assert (arc->insn);
7455 if (arc->insn->first_ainsn_with_given_equivalence_num)
7456 add_vect_el (&transition_vect, arc->insn,
7457 arc->to_state->order_state_num);
7459 add_vect (automaton->trans_table,
7460 VEC_index (state_t, output_states_vect, i)->order_state_num,
7461 transition_vect);
7463 output_state_ainsn_table
7464 (automaton->trans_table, "state transitions",
7465 output_trans_full_vect_name, output_trans_comb_vect_name,
7466 output_trans_check_vect_name, output_trans_base_vect_name);
7468 VEC_free (state_t, heap, output_states_vect);
7469 VEC_free (vect_el_t, heap, transition_vect);
7472 /* Form and output vectors representing minimal issue delay table of
7473 AUTOMATON. The table is state x ainsn -> minimal issue delay of
7474 the ainsn. */
7475 static void
7476 output_min_issue_delay_table (automaton_t automaton)
7478 vla_hwint_t min_issue_delay_vect;
7479 vla_hwint_t compressed_min_issue_delay_vect;
7480 ainsn_t ainsn;
7481 size_t i;
7482 size_t min_issue_delay_len, compressed_min_issue_delay_len;
7483 size_t cfactor;
7484 int changed;
7486 /* Create vect of pointers to states ordered by num of transitions
7487 from the state (state with the maximum num is the first). */
7488 output_states_vect = 0;
7489 pass_states (automaton, add_states_vect_el);
7491 min_issue_delay_len = (VEC_length (state_t, output_states_vect)
7492 * automaton->insn_equiv_classes_num);
7493 min_issue_delay_vect = VEC_alloc (vect_el_t, heap, min_issue_delay_len);
7494 for (i = 0; i < min_issue_delay_len; i++)
7495 VEC_quick_push (vect_el_t, min_issue_delay_vect, -1);
7497 automaton->max_min_delay = 0;
7501 size_t state_no;
7503 changed = 0;
7505 for (state_no = 0; state_no < VEC_length (state_t, output_states_vect);
7506 state_no++)
7508 state_t s = VEC_index (state_t, output_states_vect, state_no);
7509 arc_t arc;
7511 for (arc = first_out_arc (s); arc; arc = next_out_arc (arc))
7513 int k;
7515 size_t asn = s->order_state_num
7516 * automaton->insn_equiv_classes_num
7517 + arc->insn->insn_equiv_class_num;
7519 if (VEC_index (vect_el_t, min_issue_delay_vect, asn))
7521 VEC_replace (vect_el_t, min_issue_delay_vect, asn, 0);
7522 changed = 1;
7525 for (k = 0; k < automaton->insn_equiv_classes_num; k++)
7527 size_t n0, n1;
7528 vect_el_t delay0, delay1;
7530 n0 = s->order_state_num
7531 * automaton->insn_equiv_classes_num
7532 + k;
7533 n1 = arc->to_state->order_state_num
7534 * automaton->insn_equiv_classes_num
7535 + k;
7536 delay0 = VEC_index (vect_el_t, min_issue_delay_vect, n0);
7537 delay1 = VEC_index (vect_el_t, min_issue_delay_vect, n1);
7538 if (delay1 != -1)
7540 if (arc->insn->insn_reserv_decl
7541 == DECL_INSN_RESERV (advance_cycle_insn_decl))
7542 delay1++;
7543 if (delay1 < delay0 || delay0 == -1)
7545 VEC_replace (vect_el_t, min_issue_delay_vect, n0, delay1);
7546 changed = 1;
7553 while (changed);
7555 automaton->max_min_delay = 0;
7557 for (ainsn = automaton->ainsn_list; ainsn; ainsn = ainsn->next_ainsn)
7558 if (ainsn->first_ainsn_with_given_equivalence_num)
7560 for (i = 0; i < VEC_length (state_t, output_states_vect); i++)
7562 state_t s = VEC_index (state_t, output_states_vect, i);
7563 size_t np = s->order_state_num
7564 * automaton->insn_equiv_classes_num
7565 + ainsn->insn_equiv_class_num;
7566 vect_el_t x = VEC_index (vect_el_t, min_issue_delay_vect, np);
7568 if (automaton->max_min_delay < x)
7569 automaton->max_min_delay = x;
7570 if (x == -1)
7571 VEC_replace (vect_el_t, min_issue_delay_vect, np, 0);
7575 fprintf (output_file, "/* Vector of min issue delay of insns. */\n");
7576 fprintf (output_file, "static const ");
7577 output_range_type (output_file, 0, automaton->max_min_delay);
7578 fprintf (output_file, " ");
7579 output_min_issue_delay_vect_name (output_file, automaton);
7580 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7581 /* Compress the vector. */
7582 if (automaton->max_min_delay < 2)
7583 cfactor = 8;
7584 else if (automaton->max_min_delay < 4)
7585 cfactor = 4;
7586 else if (automaton->max_min_delay < 16)
7587 cfactor = 2;
7588 else
7589 cfactor = 1;
7590 automaton->min_issue_delay_table_compression_factor = cfactor;
7592 compressed_min_issue_delay_len = (min_issue_delay_len+cfactor-1) / cfactor;
7593 compressed_min_issue_delay_vect
7594 = VEC_alloc (vect_el_t, heap, compressed_min_issue_delay_len);
7596 for (i = 0; i < compressed_min_issue_delay_len; i++)
7597 VEC_quick_push (vect_el_t, compressed_min_issue_delay_vect, 0);
7599 for (i = 0; i < min_issue_delay_len; i++)
7601 size_t ci = i / cfactor;
7602 vect_el_t x = VEC_index (vect_el_t, min_issue_delay_vect, i);
7603 vect_el_t cx = VEC_index (vect_el_t, compressed_min_issue_delay_vect, ci);
7605 cx |= x << (8 - (i % cfactor + 1) * (8 / cfactor));
7606 VEC_replace (vect_el_t, compressed_min_issue_delay_vect, ci, cx);
7608 output_vect (compressed_min_issue_delay_vect);
7609 fprintf (output_file, "};\n\n");
7610 VEC_free (state_t, heap, output_states_vect);
7611 VEC_free (vect_el_t, heap, min_issue_delay_vect);
7612 VEC_free (vect_el_t, heap, compressed_min_issue_delay_vect);
7615 /* Form and output vector representing the locked states of
7616 AUTOMATON. */
7617 static void
7618 output_dead_lock_vect (automaton_t automaton)
7620 size_t i;
7621 arc_t arc;
7622 vla_hwint_t dead_lock_vect = 0;
7624 /* Create vect of pointers to states ordered by num of
7625 transitions from the state (state with the maximum num is the
7626 first). */
7627 automaton->locked_states = 0;
7628 output_states_vect = 0;
7629 pass_states (automaton, add_states_vect_el);
7631 VEC_safe_grow (vect_el_t, heap, dead_lock_vect,
7632 VEC_length (state_t, output_states_vect));
7633 for (i = 0; i < VEC_length (state_t, output_states_vect); i++)
7635 state_t s = VEC_index (state_t, output_states_vect, i);
7636 arc = first_out_arc (s);
7637 gcc_assert (arc);
7638 if (next_out_arc (arc) == NULL
7639 && (arc->insn->insn_reserv_decl
7640 == DECL_INSN_RESERV (advance_cycle_insn_decl)))
7642 VEC_replace (vect_el_t, dead_lock_vect, s->order_state_num, 1);
7643 automaton->locked_states++;
7645 else
7646 VEC_replace (vect_el_t, dead_lock_vect, s->order_state_num, 0);
7648 if (automaton->locked_states == 0)
7649 return;
7651 fprintf (output_file, "/* Vector for locked state flags. */\n");
7652 fprintf (output_file, "static const ");
7653 output_range_type (output_file, 0, 1);
7654 fprintf (output_file, " ");
7655 output_dead_lock_vect_name (output_file, automaton);
7656 fprintf (output_file, "[] = {\n");
7657 output_vect (dead_lock_vect);
7658 fprintf (output_file, "};\n\n");
7659 VEC_free (state_t, heap, output_states_vect);
7660 VEC_free (vect_el_t, heap, dead_lock_vect);
7663 /* Form and output vector representing reserved units of the states of
7664 AUTOMATON. */
7665 static void
7666 output_reserved_units_table (automaton_t automaton)
7668 vla_hwint_t reserved_units_table = 0;
7669 int state_byte_size;
7670 int reserved_units_size;
7671 size_t n;
7672 int i;
7674 if (description->query_units_num == 0)
7675 return;
7677 /* Create vect of pointers to states. */
7678 output_states_vect = 0;
7679 pass_states (automaton, add_states_vect_el);
7680 /* Create vector. */
7681 state_byte_size = (description->query_units_num + 7) / 8;
7682 reserved_units_size = (VEC_length (state_t, output_states_vect)
7683 * state_byte_size);
7685 reserved_units_table = VEC_alloc (vect_el_t, heap, reserved_units_size);
7687 for (i = 0; i < reserved_units_size; i++)
7688 VEC_quick_push (vect_el_t, reserved_units_table, 0);
7689 for (n = 0; n < VEC_length (state_t, output_states_vect); n++)
7691 state_t s = VEC_index (state_t, output_states_vect, n);
7692 for (i = 0; i < description->units_num; i++)
7693 if (units_array [i]->query_p
7694 && first_cycle_unit_presence (s, i))
7696 int ri = (s->order_state_num * state_byte_size
7697 + units_array [i]->query_num / 8);
7698 vect_el_t x = VEC_index (vect_el_t, reserved_units_table, ri);
7700 x += 1 << (units_array [i]->query_num % 8);
7701 VEC_replace (vect_el_t, reserved_units_table, ri, x);
7704 fprintf (output_file, "\n#if %s\n", CPU_UNITS_QUERY_MACRO_NAME);
7705 fprintf (output_file, "/* Vector for reserved units of states. */\n");
7706 fprintf (output_file, "static const ");
7707 output_range_type (output_file, 0, 255);
7708 fprintf (output_file, " ");
7709 output_reserved_units_table_name (output_file, automaton);
7710 fprintf (output_file, "[] = {\n");
7711 output_vect (reserved_units_table);
7712 fprintf (output_file, "};\n#endif /* #if %s */\n\n",
7713 CPU_UNITS_QUERY_MACRO_NAME);
7715 VEC_free (state_t, heap, output_states_vect);
7716 VEC_free (vect_el_t, heap, reserved_units_table);
7719 /* The function outputs all tables representing DFA(s) used for fast
7720 pipeline hazards recognition. */
7721 static void
7722 output_tables (void)
7724 automaton_t automaton;
7726 for (automaton = description->first_automaton;
7727 automaton != NULL;
7728 automaton = automaton->next_automaton)
7730 output_translate_vect (automaton);
7731 output_trans_table (automaton);
7732 output_min_issue_delay_table (automaton);
7733 output_dead_lock_vect (automaton);
7734 output_reserved_units_table (automaton);
7736 fprintf (output_file, "\n#define %s %d\n\n", ADVANCE_CYCLE_VALUE_NAME,
7737 DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
7740 /* The function outputs definition and value of PHR interface variable
7741 `max_insn_queue_index'. Its value is not less than maximal queue
7742 length needed for the insn scheduler. */
7743 static void
7744 output_max_insn_queue_index_def (void)
7746 int i, max, latency;
7747 decl_t decl;
7749 max = description->max_insn_reserv_cycles;
7750 for (i = 0; i < description->decls_num; i++)
7752 decl = description->decls [i];
7753 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
7755 latency = DECL_INSN_RESERV (decl)->default_latency;
7756 if (latency > max)
7757 max = latency;
7759 else if (decl->mode == dm_bypass)
7761 latency = DECL_BYPASS (decl)->latency;
7762 if (latency > max)
7763 max = latency;
7766 for (i = 0; (1 << i) <= max; i++)
7768 gcc_assert (i >= 0);
7769 fprintf (output_file, "\nconst int max_insn_queue_index = %d;\n\n",
7770 (1 << i) - 1);
7773 /* The function outputs switch cases for insn reservations using
7774 function *output_automata_list_code. */
7775 static void
7776 output_insn_code_cases (void (*output_automata_list_code)
7777 (automata_list_el_t))
7779 decl_t decl, decl2;
7780 int i, j;
7782 for (i = 0; i < description->decls_num; i++)
7784 decl = description->decls [i];
7785 if (decl->mode == dm_insn_reserv)
7786 DECL_INSN_RESERV (decl)->processed_p = FALSE;
7788 for (i = 0; i < description->decls_num; i++)
7790 decl = description->decls [i];
7791 if (decl->mode == dm_insn_reserv
7792 && !DECL_INSN_RESERV (decl)->processed_p)
7794 for (j = i; j < description->decls_num; j++)
7796 decl2 = description->decls [j];
7797 if (decl2->mode == dm_insn_reserv
7798 && (DECL_INSN_RESERV (decl2)->important_automata_list
7799 == DECL_INSN_RESERV (decl)->important_automata_list))
7801 DECL_INSN_RESERV (decl2)->processed_p = TRUE;
7802 fprintf (output_file, " case %d: /* %s */\n",
7803 DECL_INSN_RESERV (decl2)->insn_num,
7804 DECL_INSN_RESERV (decl2)->name);
7807 (*output_automata_list_code)
7808 (DECL_INSN_RESERV (decl)->important_automata_list);
7814 /* The function outputs a code for evaluation of a minimal delay of
7815 issue of insns which have reservations in given AUTOMATA_LIST. */
7816 static void
7817 output_automata_list_min_issue_delay_code (automata_list_el_t automata_list)
7819 automata_list_el_t el;
7820 automaton_t automaton;
7822 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
7824 automaton = el->automaton;
7825 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
7826 output_min_issue_delay_vect_name (output_file, automaton);
7827 fprintf (output_file,
7828 (automaton->min_issue_delay_table_compression_factor != 1
7829 ? " [(" : " ["));
7830 output_translate_vect_name (output_file, automaton);
7831 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
7832 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7833 output_chip_member_name (output_file, automaton);
7834 fprintf (output_file, " * %d", automaton->insn_equiv_classes_num);
7835 if (automaton->min_issue_delay_table_compression_factor == 1)
7836 fprintf (output_file, "];\n");
7837 else
7839 fprintf (output_file, ") / %d];\n",
7840 automaton->min_issue_delay_table_compression_factor);
7841 fprintf (output_file, " %s = (%s >> (8 - ((",
7842 TEMPORARY_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
7843 output_translate_vect_name (output_file, automaton);
7844 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
7845 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7846 output_chip_member_name (output_file, automaton);
7847 fprintf (output_file, " * %d)", automaton->insn_equiv_classes_num);
7848 fprintf
7849 (output_file, " %% %d + 1) * %d)) & %d;\n",
7850 automaton->min_issue_delay_table_compression_factor,
7851 8 / automaton->min_issue_delay_table_compression_factor,
7852 (1 << (8 / automaton->min_issue_delay_table_compression_factor))
7853 - 1);
7855 if (el == automata_list)
7856 fprintf (output_file, " %s = %s;\n",
7857 RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
7858 else
7860 fprintf (output_file, " if (%s > %s)\n",
7861 TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
7862 fprintf (output_file, " %s = %s;\n",
7863 RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
7866 fprintf (output_file, " break;\n\n");
7869 /* Output function `internal_min_issue_delay'. */
7870 static void
7871 output_internal_min_issue_delay_func (void)
7873 fprintf (output_file,
7874 "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
7875 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7876 CHIP_NAME, CHIP_PARAMETER_NAME);
7877 fprintf (output_file, "{\n int %s ATTRIBUTE_UNUSED;\n int %s = -1;\n",
7878 TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
7879 fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
7880 output_insn_code_cases (output_automata_list_min_issue_delay_code);
7881 fprintf (output_file,
7882 "\n default:\n %s = -1;\n break;\n }\n",
7883 RESULT_VARIABLE_NAME);
7884 fprintf (output_file, " return %s;\n", RESULT_VARIABLE_NAME);
7885 fprintf (output_file, "}\n\n");
7888 /* The function outputs a code changing state after issue of insns
7889 which have reservations in given AUTOMATA_LIST. */
7890 static void
7891 output_automata_list_transition_code (automata_list_el_t automata_list)
7893 automata_list_el_t el, next_el;
7895 fprintf (output_file, " {\n");
7896 if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
7897 for (el = automata_list;; el = next_el)
7899 next_el = el->next_automata_list_el;
7900 if (next_el == NULL)
7901 break;
7902 fprintf (output_file, " ");
7903 output_state_member_type (output_file, el->automaton);
7904 fprintf (output_file, " ");
7905 output_temp_chip_member_name (output_file, el->automaton);
7906 fprintf (output_file, ";\n");
7908 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
7909 if (comb_vect_p (el->automaton->trans_table))
7911 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
7912 output_trans_base_vect_name (output_file, el->automaton);
7913 fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
7914 output_chip_member_name (output_file, el->automaton);
7915 fprintf (output_file, "] + ");
7916 output_translate_vect_name (output_file, el->automaton);
7917 fprintf (output_file, " [%s];\n", INTERNAL_INSN_CODE_NAME);
7918 fprintf (output_file, " if (");
7919 output_trans_check_vect_name (output_file, el->automaton);
7920 fprintf (output_file, " [%s] != %s->",
7921 TEMPORARY_VARIABLE_NAME, CHIP_PARAMETER_NAME);
7922 output_chip_member_name (output_file, el->automaton);
7923 fprintf (output_file, ")\n");
7924 fprintf (output_file, " return %s (%s, %s);\n",
7925 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7926 CHIP_PARAMETER_NAME);
7927 fprintf (output_file, " else\n");
7928 fprintf (output_file, " ");
7929 if (el->next_automata_list_el != NULL)
7930 output_temp_chip_member_name (output_file, el->automaton);
7931 else
7933 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7934 output_chip_member_name (output_file, el->automaton);
7936 fprintf (output_file, " = ");
7937 output_trans_comb_vect_name (output_file, el->automaton);
7938 fprintf (output_file, " [%s];\n", TEMPORARY_VARIABLE_NAME);
7940 else
7942 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
7943 output_trans_full_vect_name (output_file, el->automaton);
7944 fprintf (output_file, " [");
7945 output_translate_vect_name (output_file, el->automaton);
7946 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
7947 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7948 output_chip_member_name (output_file, el->automaton);
7949 fprintf (output_file, " * %d];\n",
7950 el->automaton->insn_equiv_classes_num);
7951 fprintf (output_file, " if (%s >= %d)\n",
7952 TEMPORARY_VARIABLE_NAME, el->automaton->achieved_states_num);
7953 fprintf (output_file, " return %s (%s, %s);\n",
7954 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7955 CHIP_PARAMETER_NAME);
7956 fprintf (output_file, " else\n ");
7957 if (el->next_automata_list_el != NULL)
7958 output_temp_chip_member_name (output_file, el->automaton);
7959 else
7961 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7962 output_chip_member_name (output_file, el->automaton);
7964 fprintf (output_file, " = %s;\n", TEMPORARY_VARIABLE_NAME);
7966 if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
7967 for (el = automata_list;; el = next_el)
7969 next_el = el->next_automata_list_el;
7970 if (next_el == NULL)
7971 break;
7972 fprintf (output_file, " %s->", CHIP_PARAMETER_NAME);
7973 output_chip_member_name (output_file, el->automaton);
7974 fprintf (output_file, " = ");
7975 output_temp_chip_member_name (output_file, el->automaton);
7976 fprintf (output_file, ";\n");
7978 fprintf (output_file, " return -1;\n");
7979 fprintf (output_file, " }\n");
7982 /* Output function `internal_state_transition'. */
7983 static void
7984 output_internal_trans_func (void)
7986 fprintf (output_file,
7987 "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
7988 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7989 CHIP_NAME, CHIP_PARAMETER_NAME);
7990 fprintf (output_file, "{\n int %s ATTRIBUTE_UNUSED;\n", TEMPORARY_VARIABLE_NAME);
7991 fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
7992 output_insn_code_cases (output_automata_list_transition_code);
7993 fprintf (output_file, "\n default:\n return -1;\n }\n");
7994 fprintf (output_file, "}\n\n");
7997 /* Output code
7999 if (insn != 0)
8001 insn_code = dfa_insn_code (insn);
8002 if (insn_code > DFA__ADVANCE_CYCLE)
8003 return code;
8005 else
8006 insn_code = DFA__ADVANCE_CYCLE;
8008 where insn denotes INSN_NAME, insn_code denotes INSN_CODE_NAME, and
8009 code denotes CODE. */
8010 static void
8011 output_internal_insn_code_evaluation (const char *insn_name,
8012 const char *insn_code_name,
8013 int code)
8015 fprintf (output_file, "\n if (%s != 0)\n {\n", insn_name);
8016 fprintf (output_file, " %s = %s (%s);\n", insn_code_name,
8017 DFA_INSN_CODE_FUNC_NAME, insn_name);
8018 fprintf (output_file, " if (%s > %s)\n return %d;\n",
8019 insn_code_name, ADVANCE_CYCLE_VALUE_NAME, code);
8020 fprintf (output_file, " }\n else\n %s = %s;\n\n",
8021 insn_code_name, ADVANCE_CYCLE_VALUE_NAME);
8025 /* This function outputs `dfa_insn_code' and its helper function
8026 `dfa_insn_code_enlarge'. */
8027 static void
8028 output_dfa_insn_code_func (void)
8030 /* Emacs c-mode gets really confused if there's a { or } in column 0
8031 inside a string, so don't do that. */
8032 fprintf (output_file, "\
8033 static void\n\
8034 dfa_insn_code_enlarge (int uid)\n\
8035 {\n\
8036 int i = %s;\n\
8037 %s = 2 * uid;\n\
8038 %s = XRESIZEVEC (int, %s,\n\
8039 %s);\n\
8040 for (; i < %s; i++)\n\
8041 %s[i] = -1;\n}\n\n",
8042 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8043 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8044 DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
8045 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8046 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8047 DFA_INSN_CODES_VARIABLE_NAME);
8048 fprintf (output_file, "\
8049 static inline int\n%s (rtx %s)\n\
8050 {\n\
8051 int uid = INSN_UID (%s);\n\
8052 int %s;\n\n",
8053 DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME,
8054 INSN_PARAMETER_NAME, INTERNAL_INSN_CODE_NAME);
8056 fprintf (output_file,
8057 " if (uid >= %s)\n dfa_insn_code_enlarge (uid);\n\n",
8058 DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8059 fprintf (output_file, " %s = %s[uid];\n",
8060 INTERNAL_INSN_CODE_NAME, DFA_INSN_CODES_VARIABLE_NAME);
8061 fprintf (output_file, "\
8062 if (%s < 0)\n\
8063 {\n\
8064 %s = %s (%s);\n\
8065 %s[uid] = %s;\n\
8066 }\n",
8067 INTERNAL_INSN_CODE_NAME,
8068 INTERNAL_INSN_CODE_NAME,
8069 INTERNAL_DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME,
8070 DFA_INSN_CODES_VARIABLE_NAME, INTERNAL_INSN_CODE_NAME);
8071 fprintf (output_file, " return %s;\n}\n\n", INTERNAL_INSN_CODE_NAME);
8074 /* The function outputs PHR interface function `state_transition'. */
8075 static void
8076 output_trans_func (void)
8078 fprintf (output_file, "int\n%s (%s %s, rtx %s)\n",
8079 TRANSITION_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME,
8080 INSN_PARAMETER_NAME);
8081 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
8082 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8083 INTERNAL_INSN_CODE_NAME, -1);
8084 fprintf (output_file, " return %s (%s, (struct %s *) %s);\n}\n\n",
8085 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME, STATE_NAME);
8088 /* Output function `min_issue_delay'. */
8089 static void
8090 output_min_issue_delay_func (void)
8092 fprintf (output_file, "int\n%s (%s %s, rtx %s)\n",
8093 MIN_ISSUE_DELAY_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME,
8094 INSN_PARAMETER_NAME);
8095 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
8096 fprintf (output_file, "\n if (%s != 0)\n {\n", INSN_PARAMETER_NAME);
8097 fprintf (output_file, " %s = %s (%s);\n", INTERNAL_INSN_CODE_NAME,
8098 DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME);
8099 fprintf (output_file, " if (%s > %s)\n return 0;\n",
8100 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8101 fprintf (output_file, " }\n else\n %s = %s;\n",
8102 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8103 fprintf (output_file, "\n return %s (%s, (struct %s *) %s);\n",
8104 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8105 CHIP_NAME, STATE_NAME);
8106 fprintf (output_file, "}\n\n");
8109 /* Output function `internal_dead_lock'. */
8110 static void
8111 output_internal_dead_lock_func (void)
8113 automaton_t automaton;
8115 fprintf (output_file, "static int\n%s (struct %s *ARG_UNUSED (%s))\n",
8116 INTERNAL_DEAD_LOCK_FUNC_NAME, CHIP_NAME, CHIP_PARAMETER_NAME);
8117 fprintf (output_file, "{\n");
8118 for (automaton = description->first_automaton;
8119 automaton != NULL;
8120 automaton = automaton->next_automaton)
8121 if (automaton->locked_states)
8123 fprintf (output_file, " if (");
8124 output_dead_lock_vect_name (output_file, automaton);
8125 fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
8126 output_chip_member_name (output_file, automaton);
8127 fprintf (output_file, "])\n return 1/* TRUE */;\n");
8129 fprintf (output_file, " return 0/* FALSE */;\n}\n\n");
8132 /* The function outputs PHR interface function `state_dead_lock_p'. */
8133 static void
8134 output_dead_lock_func (void)
8136 fprintf (output_file, "int\n%s (%s %s)\n",
8137 DEAD_LOCK_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME);
8138 fprintf (output_file, "{\n return %s ((struct %s *) %s);\n}\n\n",
8139 INTERNAL_DEAD_LOCK_FUNC_NAME, CHIP_NAME, STATE_NAME);
8142 /* Output function `internal_reset'. */
8143 static void
8144 output_internal_reset_func (void)
8146 fprintf (output_file, "static inline void\n%s (struct %s *%s)\n",
8147 INTERNAL_RESET_FUNC_NAME, CHIP_NAME, CHIP_PARAMETER_NAME);
8148 fprintf (output_file, "{\n memset (%s, 0, sizeof (struct %s));\n}\n\n",
8149 CHIP_PARAMETER_NAME, CHIP_NAME);
8152 /* The function outputs PHR interface function `state_size'. */
8153 static void
8154 output_size_func (void)
8156 fprintf (output_file, "int\n%s (void)\n", SIZE_FUNC_NAME);
8157 fprintf (output_file, "{\n return sizeof (struct %s);\n}\n\n", CHIP_NAME);
8160 /* The function outputs PHR interface function `state_reset'. */
8161 static void
8162 output_reset_func (void)
8164 fprintf (output_file, "void\n%s (%s %s)\n",
8165 RESET_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME);
8166 fprintf (output_file, "{\n %s ((struct %s *) %s);\n}\n\n", INTERNAL_RESET_FUNC_NAME,
8167 CHIP_NAME, STATE_NAME);
8170 /* Output function `min_insn_conflict_delay'. */
8171 static void
8172 output_min_insn_conflict_delay_func (void)
8174 fprintf (output_file,
8175 "int\n%s (%s %s, rtx %s, rtx %s)\n",
8176 MIN_INSN_CONFLICT_DELAY_FUNC_NAME, STATE_TYPE_NAME,
8177 STATE_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8178 fprintf (output_file, "{\n struct %s %s;\n int %s, %s, transition;\n",
8179 CHIP_NAME, CHIP_NAME, INTERNAL_INSN_CODE_NAME,
8180 INTERNAL_INSN2_CODE_NAME);
8181 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8182 INTERNAL_INSN_CODE_NAME, 0);
8183 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
8184 INTERNAL_INSN2_CODE_NAME, 0);
8185 fprintf (output_file, " memcpy (&%s, %s, sizeof (%s));\n",
8186 CHIP_NAME, STATE_NAME, CHIP_NAME);
8187 fprintf (output_file, " %s (&%s);\n", INTERNAL_RESET_FUNC_NAME, CHIP_NAME);
8188 fprintf (output_file, " transition = %s (%s, &%s);\n",
8189 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME);
8190 fprintf (output_file, " gcc_assert (transition <= 0);\n");
8191 fprintf (output_file, " return %s (%s, &%s);\n",
8192 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN2_CODE_NAME,
8193 CHIP_NAME);
8194 fprintf (output_file, "}\n\n");
8197 /* Output the array holding default latency values. These are used in
8198 insn_latency and maximal_insn_latency function implementations. */
8199 static void
8200 output_default_latencies (void)
8202 int i, j, col;
8203 decl_t decl;
8204 const char *tabletype = "unsigned char";
8206 /* Find the smallest integer type that can hold all the default
8207 latency values. */
8208 for (i = 0; i < description->decls_num; i++)
8209 if (description->decls[i]->mode == dm_insn_reserv)
8211 decl = description->decls[i];
8212 if (DECL_INSN_RESERV (decl)->default_latency > UCHAR_MAX
8213 && tabletype[0] != 'i') /* Don't shrink it. */
8214 tabletype = "unsigned short";
8215 if (DECL_INSN_RESERV (decl)->default_latency > USHRT_MAX)
8216 tabletype = "int";
8219 fprintf (output_file, " static const %s default_latencies[] =\n {",
8220 tabletype);
8222 for (i = 0, j = 0, col = 7; i < description->decls_num; i++)
8223 if (description->decls[i]->mode == dm_insn_reserv
8224 && description->decls[i] != advance_cycle_insn_decl)
8226 if ((col = (col+1) % 8) == 0)
8227 fputs ("\n ", output_file);
8228 decl = description->decls[i];
8229 gcc_assert (j++ == DECL_INSN_RESERV (decl)->insn_num);
8230 fprintf (output_file, "% 4d,",
8231 DECL_INSN_RESERV (decl)->default_latency);
8233 gcc_assert (j == DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
8234 fputs ("\n };\n", output_file);
8237 /* Output function `internal_insn_latency'. */
8238 static void
8239 output_internal_insn_latency_func (void)
8241 int i;
8242 decl_t decl;
8243 struct bypass_decl *bypass;
8245 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",
8246 INTERNAL_INSN_LATENCY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8247 INTERNAL_INSN2_CODE_NAME, INSN_PARAMETER_NAME,
8248 INSN2_PARAMETER_NAME);
8249 fprintf (output_file, "{\n");
8251 if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8253 fputs (" return 0;\n}\n\n", output_file);
8254 return;
8257 fprintf (output_file, " if (%s >= %s || %s >= %s)\n return 0;\n",
8258 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8259 INTERNAL_INSN2_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8261 fprintf (output_file, " switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8262 for (i = 0; i < description->decls_num; i++)
8263 if (description->decls[i]->mode == dm_insn_reserv
8264 && DECL_INSN_RESERV (description->decls[i])->bypass_list)
8266 decl = description->decls [i];
8267 fprintf (output_file,
8268 " case %d:\n switch (%s)\n {\n",
8269 DECL_INSN_RESERV (decl)->insn_num,
8270 INTERNAL_INSN2_CODE_NAME);
8271 for (bypass = DECL_INSN_RESERV (decl)->bypass_list;
8272 bypass != NULL;
8273 bypass = bypass->next)
8275 gcc_assert (bypass->in_insn_reserv->insn_num
8276 != (DECL_INSN_RESERV
8277 (advance_cycle_insn_decl)->insn_num));
8278 fprintf (output_file, " case %d:\n",
8279 bypass->in_insn_reserv->insn_num);
8280 for (;;)
8282 if (bypass->bypass_guard_name == NULL)
8284 gcc_assert (bypass->next == NULL
8285 || (bypass->in_insn_reserv
8286 != bypass->next->in_insn_reserv));
8287 fprintf (output_file, " return %d;\n",
8288 bypass->latency);
8290 else
8292 fprintf (output_file,
8293 " if (%s (%s, %s))\n",
8294 bypass->bypass_guard_name, INSN_PARAMETER_NAME,
8295 INSN2_PARAMETER_NAME);
8296 fprintf (output_file, " return %d;\n",
8297 bypass->latency);
8299 if (bypass->next == NULL
8300 || bypass->in_insn_reserv != bypass->next->in_insn_reserv)
8301 break;
8302 bypass = bypass->next;
8304 if (bypass->bypass_guard_name != NULL)
8305 fprintf (output_file, " break;\n");
8307 fputs (" }\n break;\n", output_file);
8310 fprintf (output_file, " }\n return default_latencies[%s];\n}\n\n",
8311 INTERNAL_INSN_CODE_NAME);
8314 /* Output function `internal_maximum_insn_latency'. */
8315 static void
8316 output_internal_maximal_insn_latency_func (void)
8318 decl_t decl;
8319 struct bypass_decl *bypass;
8320 int i;
8321 int max;
8323 fprintf (output_file, "static int\n%s (int %s ATTRIBUTE_UNUSED,\n\trtx %s ATTRIBUTE_UNUSED)\n",
8324 "internal_maximal_insn_latency", INTERNAL_INSN_CODE_NAME,
8325 INSN_PARAMETER_NAME);
8326 fprintf (output_file, "{\n");
8328 if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8330 fputs (" return 0;\n}\n\n", output_file);
8331 return;
8334 fprintf (output_file, " switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8335 for (i = 0; i < description->decls_num; i++)
8336 if (description->decls[i]->mode == dm_insn_reserv
8337 && DECL_INSN_RESERV (description->decls[i])->bypass_list)
8339 decl = description->decls [i];
8340 max = DECL_INSN_RESERV (decl)->default_latency;
8341 fprintf (output_file,
8342 " case %d: {",
8343 DECL_INSN_RESERV (decl)->insn_num);
8344 for (bypass = DECL_INSN_RESERV (decl)->bypass_list;
8345 bypass != NULL;
8346 bypass = bypass->next)
8348 if (bypass->latency > max)
8349 max = bypass->latency;
8351 fprintf (output_file, " return %d; }\n break;\n", max);
8354 fprintf (output_file, " }\n return default_latencies[%s];\n}\n\n",
8355 INTERNAL_INSN_CODE_NAME);
8358 /* The function outputs PHR interface function `insn_latency'. */
8359 static void
8360 output_insn_latency_func (void)
8362 fprintf (output_file, "int\n%s (rtx %s, rtx %s)\n",
8363 INSN_LATENCY_FUNC_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8364 fprintf (output_file, "{\n int %s, %s;\n",
8365 INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME);
8366 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8367 INTERNAL_INSN_CODE_NAME, 0);
8368 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
8369 INTERNAL_INSN2_CODE_NAME, 0);
8370 fprintf (output_file, " return %s (%s, %s, %s, %s);\n}\n\n",
8371 INTERNAL_INSN_LATENCY_FUNC_NAME,
8372 INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME,
8373 INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8376 /* The function outputs PHR interface function `maximal_insn_latency'. */
8377 static void
8378 output_maximal_insn_latency_func (void)
8380 fprintf (output_file, "int\n%s (rtx %s)\n",
8381 "maximal_insn_latency", INSN_PARAMETER_NAME);
8382 fprintf (output_file, "{\n int %s;\n",
8383 INTERNAL_INSN_CODE_NAME);
8384 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8385 INTERNAL_INSN_CODE_NAME, 0);
8386 fprintf (output_file, " return %s (%s, %s);\n}\n\n",
8387 "internal_maximal_insn_latency",
8388 INTERNAL_INSN_CODE_NAME, INSN_PARAMETER_NAME);
8391 /* The function outputs PHR interface function `print_reservation'. */
8392 static void
8393 output_print_reservation_func (void)
8395 decl_t decl;
8396 int i, j;
8398 fprintf (output_file,
8399 "void\n%s (FILE *%s, rtx %s ATTRIBUTE_UNUSED)\n{\n",
8400 PRINT_RESERVATION_FUNC_NAME, FILE_PARAMETER_NAME,
8401 INSN_PARAMETER_NAME);
8403 if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8405 fprintf (output_file, " fputs (\"%s\", %s);\n}\n\n",
8406 NOTHING_NAME, FILE_PARAMETER_NAME);
8407 return;
8411 fputs (" static const char *const reservation_names[] =\n {",
8412 output_file);
8414 for (i = 0, j = 0; i < description->decls_num; i++)
8416 decl = description->decls [i];
8417 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
8419 gcc_assert (j == DECL_INSN_RESERV (decl)->insn_num);
8420 j++;
8422 fprintf (output_file, "\n \"%s\",",
8423 regexp_representation (DECL_INSN_RESERV (decl)->regexp));
8424 finish_regexp_representation ();
8427 gcc_assert (j == DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
8429 fprintf (output_file, "\n \"%s\"\n };\n int %s;\n\n",
8430 NOTHING_NAME, INTERNAL_INSN_CODE_NAME);
8432 fprintf (output_file, " if (%s == 0)\n %s = %s;\n",
8433 INSN_PARAMETER_NAME,
8434 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8435 fprintf (output_file, " else\n\
8436 {\n\
8437 %s = %s (%s);\n\
8438 if (%s > %s)\n\
8439 %s = %s;\n\
8440 }\n",
8441 INTERNAL_INSN_CODE_NAME, DFA_INSN_CODE_FUNC_NAME,
8442 INSN_PARAMETER_NAME,
8443 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8444 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8446 fprintf (output_file, " fputs (reservation_names[%s], %s);\n}\n\n",
8447 INTERNAL_INSN_CODE_NAME, FILE_PARAMETER_NAME);
8450 /* The following function is used to sort unit declaration by their
8451 names. */
8452 static int
8453 units_cmp (const void *unit1, const void *unit2)
8455 const_unit_decl_t const u1 = *(const_unit_decl_t const*) unit1;
8456 const_unit_decl_t const u2 = *(const_unit_decl_t const*) unit2;
8458 return strcmp (u1->name, u2->name);
8461 /* The following macro value is name of struct containing unit name
8462 and unit code. */
8463 #define NAME_CODE_STRUCT_NAME "name_code"
8465 /* The following macro value is name of table of struct name_code. */
8466 #define NAME_CODE_TABLE_NAME "name_code_table"
8468 /* The following macro values are member names for struct name_code. */
8469 #define NAME_MEMBER_NAME "name"
8470 #define CODE_MEMBER_NAME "code"
8472 /* The following macro values are local variable names for function
8473 `get_cpu_unit_code'. */
8474 #define CMP_VARIABLE_NAME "cmp"
8475 #define LOW_VARIABLE_NAME "l"
8476 #define MIDDLE_VARIABLE_NAME "m"
8477 #define HIGH_VARIABLE_NAME "h"
8479 /* The following function outputs function to obtain internal cpu unit
8480 code by the cpu unit name. */
8481 static void
8482 output_get_cpu_unit_code_func (void)
8484 int i;
8485 unit_decl_t *units;
8487 fprintf (output_file, "int\n%s (const char *%s)\n",
8488 GET_CPU_UNIT_CODE_FUNC_NAME, CPU_UNIT_NAME_PARAMETER_NAME);
8489 fprintf (output_file, "{\n struct %s {const char *%s; int %s;};\n",
8490 NAME_CODE_STRUCT_NAME, NAME_MEMBER_NAME, CODE_MEMBER_NAME);
8491 fprintf (output_file, " int %s, %s, %s, %s;\n", CMP_VARIABLE_NAME,
8492 LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8493 fprintf (output_file, " static struct %s %s [] =\n {\n",
8494 NAME_CODE_STRUCT_NAME, NAME_CODE_TABLE_NAME);
8495 units = XNEWVEC (unit_decl_t, description->units_num);
8496 memcpy (units, units_array, sizeof (unit_decl_t) * description->units_num);
8497 qsort (units, description->units_num, sizeof (unit_decl_t), units_cmp);
8498 for (i = 0; i < description->units_num; i++)
8499 if (units [i]->query_p)
8500 fprintf (output_file, " {\"%s\", %d},\n",
8501 units[i]->name, units[i]->query_num);
8502 fprintf (output_file, " };\n\n");
8503 fprintf (output_file, " /* The following is binary search: */\n");
8504 fprintf (output_file, " %s = 0;\n", LOW_VARIABLE_NAME);
8505 fprintf (output_file, " %s = sizeof (%s) / sizeof (struct %s) - 1;\n",
8506 HIGH_VARIABLE_NAME, NAME_CODE_TABLE_NAME, NAME_CODE_STRUCT_NAME);
8507 fprintf (output_file, " while (%s <= %s)\n {\n",
8508 LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8509 fprintf (output_file, " %s = (%s + %s) / 2;\n",
8510 MIDDLE_VARIABLE_NAME, LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8511 fprintf (output_file, " %s = strcmp (%s, %s [%s].%s);\n",
8512 CMP_VARIABLE_NAME, CPU_UNIT_NAME_PARAMETER_NAME,
8513 NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, NAME_MEMBER_NAME);
8514 fprintf (output_file, " if (%s < 0)\n", CMP_VARIABLE_NAME);
8515 fprintf (output_file, " %s = %s - 1;\n",
8516 HIGH_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
8517 fprintf (output_file, " else if (%s > 0)\n", CMP_VARIABLE_NAME);
8518 fprintf (output_file, " %s = %s + 1;\n",
8519 LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
8520 fprintf (output_file, " else\n");
8521 fprintf (output_file, " return %s [%s].%s;\n }\n",
8522 NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, CODE_MEMBER_NAME);
8523 fprintf (output_file, " return -1;\n}\n\n");
8524 free (units);
8527 /* The following function outputs function to check reservation of cpu
8528 unit (its internal code will be passed as the function argument) in
8529 given cpu state. */
8530 static void
8531 output_cpu_unit_reservation_p (void)
8533 automaton_t automaton;
8535 fprintf (output_file, "int\n%s (%s %s, int %s)\n",
8536 CPU_UNIT_RESERVATION_P_FUNC_NAME,
8537 STATE_TYPE_NAME, STATE_NAME,
8538 CPU_CODE_PARAMETER_NAME);
8539 fprintf (output_file, "{\n gcc_assert (%s >= 0 && %s < %d);\n",
8540 CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME,
8541 description->query_units_num);
8542 if (description->query_units_num > 0)
8543 for (automaton = description->first_automaton;
8544 automaton != NULL;
8545 automaton = automaton->next_automaton)
8547 fprintf (output_file, " if ((");
8548 output_reserved_units_table_name (output_file, automaton);
8549 fprintf (output_file, " [((struct %s *) %s)->", CHIP_NAME, STATE_NAME);
8550 output_chip_member_name (output_file, automaton);
8551 fprintf (output_file, " * %d + %s / 8] >> (%s %% 8)) & 1)\n",
8552 (description->query_units_num + 7) / 8,
8553 CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME);
8554 fprintf (output_file, " return 1;\n");
8556 fprintf (output_file, " return 0;\n}\n\n");
8559 /* The following function outputs a function to check if insn
8560 has a dfa reservation. */
8561 static void
8562 output_insn_has_dfa_reservation_p (void)
8564 fprintf (output_file,
8565 "bool\n%s (rtx %s ATTRIBUTE_UNUSED)\n{\n",
8566 INSN_HAS_DFA_RESERVATION_P_FUNC_NAME,
8567 INSN_PARAMETER_NAME);
8569 if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8571 fprintf (output_file, " return false;\n}\n\n");
8572 return;
8575 fprintf (output_file, " int %s;\n\n", INTERNAL_INSN_CODE_NAME);
8577 fprintf (output_file, " if (%s == 0)\n %s = %s;\n",
8578 INSN_PARAMETER_NAME,
8579 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8580 fprintf (output_file, " else\n\
8581 {\n\
8582 %s = %s (%s);\n\
8583 if (%s > %s)\n\
8584 %s = %s;\n\
8585 }\n\n",
8586 INTERNAL_INSN_CODE_NAME, DFA_INSN_CODE_FUNC_NAME,
8587 INSN_PARAMETER_NAME,
8588 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8589 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8591 fprintf (output_file, " return %s != %s;\n}\n\n",
8592 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8595 /* The function outputs PHR interface functions `dfa_clean_insn_cache'
8596 and 'dfa_clear_single_insn_cache'. */
8597 static void
8598 output_dfa_clean_insn_cache_func (void)
8600 fprintf (output_file,
8601 "void\n%s (void)\n{\n int %s;\n\n",
8602 DFA_CLEAN_INSN_CACHE_FUNC_NAME, I_VARIABLE_NAME);
8603 fprintf (output_file,
8604 " for (%s = 0; %s < %s; %s++)\n %s [%s] = -1;\n}\n\n",
8605 I_VARIABLE_NAME, I_VARIABLE_NAME,
8606 DFA_INSN_CODES_LENGTH_VARIABLE_NAME, I_VARIABLE_NAME,
8607 DFA_INSN_CODES_VARIABLE_NAME, I_VARIABLE_NAME);
8609 fprintf (output_file,
8610 "void\n%s (rtx %s)\n{\n int %s;\n\n",
8611 DFA_CLEAR_SINGLE_INSN_CACHE_FUNC_NAME, INSN_PARAMETER_NAME,
8612 I_VARIABLE_NAME);
8613 fprintf (output_file,
8614 " %s = INSN_UID (%s);\n if (%s < %s)\n %s [%s] = -1;\n}\n\n",
8615 I_VARIABLE_NAME, INSN_PARAMETER_NAME, I_VARIABLE_NAME,
8616 DFA_INSN_CODES_LENGTH_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
8617 I_VARIABLE_NAME);
8620 /* The function outputs PHR interface function `dfa_start'. */
8621 static void
8622 output_dfa_start_func (void)
8624 fprintf (output_file,
8625 "void\n%s (void)\n{\n %s = get_max_uid ();\n",
8626 DFA_START_FUNC_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8627 fprintf (output_file, " %s = XNEWVEC (int, %s);\n",
8628 DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8629 fprintf (output_file, " %s ();\n}\n\n", DFA_CLEAN_INSN_CACHE_FUNC_NAME);
8632 /* The function outputs PHR interface function `dfa_finish'. */
8633 static void
8634 output_dfa_finish_func (void)
8636 fprintf (output_file, "void\n%s (void)\n{\n free (%s);\n}\n\n",
8637 DFA_FINISH_FUNC_NAME, DFA_INSN_CODES_VARIABLE_NAME);
8642 /* The page contains code for output description file (readable
8643 representation of original description and generated DFA(s). */
8645 /* The function outputs string representation of IR reservation. */
8646 static void
8647 output_regexp (regexp_t regexp)
8649 fprintf (output_description_file, "%s", regexp_representation (regexp));
8650 finish_regexp_representation ();
8653 /* Output names of units in LIST separated by comma. */
8654 static void
8655 output_unit_set_el_list (unit_set_el_t list)
8657 unit_set_el_t el;
8659 for (el = list; el != NULL; el = el->next_unit_set_el)
8661 if (el != list)
8662 fprintf (output_description_file, ", ");
8663 fprintf (output_description_file, "%s", el->unit_decl->name);
8667 /* Output patterns in LIST separated by comma. */
8668 static void
8669 output_pattern_set_el_list (pattern_set_el_t list)
8671 pattern_set_el_t el;
8672 int i;
8674 for (el = list; el != NULL; el = el->next_pattern_set_el)
8676 if (el != list)
8677 fprintf (output_description_file, ", ");
8678 for (i = 0; i < el->units_num; i++)
8679 fprintf (output_description_file, (i == 0 ? "%s" : " %s"),
8680 el->unit_decls [i]->name);
8684 /* The function outputs string representation of IR define_reservation
8685 and define_insn_reservation. */
8686 static void
8687 output_description (void)
8689 decl_t decl;
8690 int i;
8692 for (i = 0; i < description->decls_num; i++)
8694 decl = description->decls [i];
8695 if (decl->mode == dm_unit)
8697 if (DECL_UNIT (decl)->excl_list != NULL)
8699 fprintf (output_description_file, "unit %s exclusion_set: ",
8700 DECL_UNIT (decl)->name);
8701 output_unit_set_el_list (DECL_UNIT (decl)->excl_list);
8702 fprintf (output_description_file, "\n");
8704 if (DECL_UNIT (decl)->presence_list != NULL)
8706 fprintf (output_description_file, "unit %s presence_set: ",
8707 DECL_UNIT (decl)->name);
8708 output_pattern_set_el_list (DECL_UNIT (decl)->presence_list);
8709 fprintf (output_description_file, "\n");
8711 if (DECL_UNIT (decl)->final_presence_list != NULL)
8713 fprintf (output_description_file, "unit %s final_presence_set: ",
8714 DECL_UNIT (decl)->name);
8715 output_pattern_set_el_list
8716 (DECL_UNIT (decl)->final_presence_list);
8717 fprintf (output_description_file, "\n");
8719 if (DECL_UNIT (decl)->absence_list != NULL)
8721 fprintf (output_description_file, "unit %s absence_set: ",
8722 DECL_UNIT (decl)->name);
8723 output_pattern_set_el_list (DECL_UNIT (decl)->absence_list);
8724 fprintf (output_description_file, "\n");
8726 if (DECL_UNIT (decl)->final_absence_list != NULL)
8728 fprintf (output_description_file, "unit %s final_absence_set: ",
8729 DECL_UNIT (decl)->name);
8730 output_pattern_set_el_list
8731 (DECL_UNIT (decl)->final_absence_list);
8732 fprintf (output_description_file, "\n");
8736 fprintf (output_description_file, "\n");
8737 for (i = 0; i < description->decls_num; i++)
8739 decl = description->decls [i];
8740 if (decl->mode == dm_reserv)
8742 fprintf (output_description_file, "reservation %s: ",
8743 DECL_RESERV (decl)->name);
8744 output_regexp (DECL_RESERV (decl)->regexp);
8745 fprintf (output_description_file, "\n");
8747 else if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
8749 fprintf (output_description_file, "insn reservation %s ",
8750 DECL_INSN_RESERV (decl)->name);
8751 print_rtl (output_description_file,
8752 DECL_INSN_RESERV (decl)->condexp);
8753 fprintf (output_description_file, ": ");
8754 output_regexp (DECL_INSN_RESERV (decl)->regexp);
8755 fprintf (output_description_file, "\n");
8757 else if (decl->mode == dm_bypass)
8758 fprintf (output_description_file, "bypass %d %s %s\n",
8759 DECL_BYPASS (decl)->latency,
8760 DECL_BYPASS (decl)->out_insn_name,
8761 DECL_BYPASS (decl)->in_insn_name);
8763 fprintf (output_description_file, "\n\f\n");
8766 /* The function outputs name of AUTOMATON. */
8767 static void
8768 output_automaton_name (FILE *f, automaton_t automaton)
8770 if (automaton->corresponding_automaton_decl == NULL)
8771 fprintf (f, "#%d", automaton->automaton_order_num);
8772 else
8773 fprintf (f, "`%s'", automaton->corresponding_automaton_decl->name);
8776 /* Maximal length of line for pretty printing into description
8777 file. */
8778 #define MAX_LINE_LENGTH 70
8780 /* The function outputs units name belonging to AUTOMATON. */
8781 static void
8782 output_automaton_units (automaton_t automaton)
8784 decl_t decl;
8785 const char *name;
8786 int curr_line_length;
8787 int there_is_an_automaton_unit;
8788 int i;
8790 fprintf (output_description_file, "\n Corresponding units:\n");
8791 fprintf (output_description_file, " ");
8792 curr_line_length = 4;
8793 there_is_an_automaton_unit = 0;
8794 for (i = 0; i < description->decls_num; i++)
8796 decl = description->decls [i];
8797 if (decl->mode == dm_unit
8798 && (DECL_UNIT (decl)->corresponding_automaton_num
8799 == automaton->automaton_order_num))
8801 there_is_an_automaton_unit = 1;
8802 name = DECL_UNIT (decl)->name;
8803 if (curr_line_length + strlen (name) + 1 > MAX_LINE_LENGTH )
8805 curr_line_length = strlen (name) + 4;
8806 fprintf (output_description_file, "\n ");
8808 else
8810 curr_line_length += strlen (name) + 1;
8811 fprintf (output_description_file, " ");
8813 fprintf (output_description_file, "%s", name);
8816 if (!there_is_an_automaton_unit)
8817 fprintf (output_description_file, "<None>");
8818 fprintf (output_description_file, "\n\n");
8821 /* The following variable is used for forming array of all possible cpu unit
8822 reservations described by the current DFA state. */
8823 static VEC(reserv_sets_t, heap) *state_reservs;
8825 /* The function forms `state_reservs' for STATE. */
8826 static void
8827 add_state_reservs (state_t state)
8829 alt_state_t curr_alt_state;
8831 if (state->component_states != NULL)
8832 for (curr_alt_state = state->component_states;
8833 curr_alt_state != NULL;
8834 curr_alt_state = curr_alt_state->next_sorted_alt_state)
8835 add_state_reservs (curr_alt_state->state);
8836 else
8837 VEC_safe_push (reserv_sets_t, heap, state_reservs, state->reservs);
8840 /* The function outputs readable representation of all out arcs of
8841 STATE. */
8842 static void
8843 output_state_arcs (state_t state)
8845 arc_t arc;
8846 ainsn_t ainsn;
8847 const char *insn_name;
8848 int curr_line_length;
8850 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
8852 ainsn = arc->insn;
8853 gcc_assert (ainsn->first_insn_with_same_reservs);
8854 fprintf (output_description_file, " ");
8855 curr_line_length = 7;
8856 fprintf (output_description_file, "%2d: ", ainsn->insn_equiv_class_num);
8859 insn_name = ainsn->insn_reserv_decl->name;
8860 if (curr_line_length + strlen (insn_name) > MAX_LINE_LENGTH)
8862 if (ainsn != arc->insn)
8864 fprintf (output_description_file, ",\n ");
8865 curr_line_length = strlen (insn_name) + 6;
8867 else
8868 curr_line_length += strlen (insn_name);
8870 else
8872 curr_line_length += strlen (insn_name);
8873 if (ainsn != arc->insn)
8875 curr_line_length += 2;
8876 fprintf (output_description_file, ", ");
8879 fprintf (output_description_file, "%s", insn_name);
8880 ainsn = ainsn->next_same_reservs_insn;
8882 while (ainsn != NULL);
8883 fprintf (output_description_file, " %d \n",
8884 arc->to_state->order_state_num);
8886 fprintf (output_description_file, "\n");
8889 /* The following function is used for sorting possible cpu unit
8890 reservation of a DFA state. */
8891 static int
8892 state_reservs_cmp (const void *reservs_ptr_1, const void *reservs_ptr_2)
8894 return reserv_sets_cmp (*(const_reserv_sets_t const*) reservs_ptr_1,
8895 *(const_reserv_sets_t const*) reservs_ptr_2);
8898 /* The following function is used for sorting possible cpu unit
8899 reservation of a DFA state. */
8900 static void
8901 remove_state_duplicate_reservs (void)
8903 size_t i, j;
8905 for (i = 1, j = 0; i < VEC_length (reserv_sets_t, state_reservs); i++)
8906 if (reserv_sets_cmp (VEC_index (reserv_sets_t, state_reservs, j),
8907 VEC_index (reserv_sets_t, state_reservs, i)))
8909 j++;
8910 VEC_replace (reserv_sets_t, state_reservs, j,
8911 VEC_index (reserv_sets_t, state_reservs, i));
8913 VEC_truncate (reserv_sets_t, state_reservs, j + 1);
8916 /* The following function output readable representation of DFA(s)
8917 state used for fast recognition of pipeline hazards. State is
8918 described by possible (current and scheduled) cpu unit
8919 reservations. */
8920 static void
8921 output_state (state_t state)
8923 size_t i;
8925 state_reservs = 0;
8927 fprintf (output_description_file, " State #%d", state->order_state_num);
8928 fprintf (output_description_file,
8929 state->new_cycle_p ? " (new cycle)\n" : "\n");
8930 add_state_reservs (state);
8931 VEC_qsort (reserv_sets_t, state_reservs, state_reservs_cmp);
8932 remove_state_duplicate_reservs ();
8933 for (i = 0; i < VEC_length (reserv_sets_t, state_reservs); i++)
8935 fprintf (output_description_file, " ");
8936 output_reserv_sets (output_description_file,
8937 VEC_index (reserv_sets_t, state_reservs, i));
8938 fprintf (output_description_file, "\n");
8940 fprintf (output_description_file, "\n");
8941 output_state_arcs (state);
8942 VEC_free (reserv_sets_t, heap, state_reservs);
8945 /* The following function output readable representation of
8946 DFAs used for fast recognition of pipeline hazards. */
8947 static void
8948 output_automaton_descriptions (void)
8950 automaton_t automaton;
8952 for (automaton = description->first_automaton;
8953 automaton != NULL;
8954 automaton = automaton->next_automaton)
8956 fprintf (output_description_file, "\nAutomaton ");
8957 output_automaton_name (output_description_file, automaton);
8958 fprintf (output_description_file, "\n");
8959 output_automaton_units (automaton);
8960 pass_states (automaton, output_state);
8966 /* The page contains top level function for generation DFA(s) used for
8967 PHR. */
8969 /* The function outputs statistics about work of different phases of
8970 DFA generator. */
8971 static void
8972 output_statistics (FILE *f)
8974 automaton_t automaton;
8975 int states_num;
8976 #ifndef NDEBUG
8977 int transition_comb_vect_els = 0;
8978 int transition_full_vect_els = 0;
8979 int min_issue_delay_vect_els = 0;
8980 int locked_states = 0;
8981 #endif
8983 for (automaton = description->first_automaton;
8984 automaton != NULL;
8985 automaton = automaton->next_automaton)
8987 fprintf (f, "\nAutomaton ");
8988 output_automaton_name (f, automaton);
8989 fprintf (f, "\n %5d NDFA states, %5d NDFA arcs\n",
8990 automaton->NDFA_states_num, automaton->NDFA_arcs_num);
8991 fprintf (f, " %5d DFA states, %5d DFA arcs\n",
8992 automaton->DFA_states_num, automaton->DFA_arcs_num);
8993 states_num = automaton->DFA_states_num;
8994 if (!no_minimization_flag)
8996 fprintf (f, " %5d minimal DFA states, %5d minimal DFA arcs\n",
8997 automaton->minimal_DFA_states_num,
8998 automaton->minimal_DFA_arcs_num);
8999 states_num = automaton->minimal_DFA_states_num;
9001 fprintf (f, " %5d all insns %5d insn equivalence classes\n",
9002 description->insns_num, automaton->insn_equiv_classes_num);
9003 fprintf (f, " %d locked states\n", automaton->locked_states);
9004 #ifndef NDEBUG
9005 fprintf
9006 (f, "%5ld transition comb vector els, %5ld trans table els: %s\n",
9007 (long) VEC_length (vect_el_t, automaton->trans_table->comb_vect),
9008 (long) VEC_length (vect_el_t, automaton->trans_table->full_vect),
9009 (comb_vect_p (automaton->trans_table)
9010 ? "use comb vect" : "use simple vect"));
9011 fprintf
9012 (f, "%5ld min delay table els, compression factor %d\n",
9013 (long) states_num * automaton->insn_equiv_classes_num,
9014 automaton->min_issue_delay_table_compression_factor);
9015 transition_comb_vect_els
9016 += VEC_length (vect_el_t, automaton->trans_table->comb_vect);
9017 transition_full_vect_els
9018 += VEC_length (vect_el_t, automaton->trans_table->full_vect);
9019 min_issue_delay_vect_els
9020 += states_num * automaton->insn_equiv_classes_num;
9021 locked_states
9022 += automaton->locked_states;
9023 #endif
9025 #ifndef NDEBUG
9026 fprintf (f, "\n%5d all allocated states, %5d all allocated arcs\n",
9027 allocated_states_num, allocated_arcs_num);
9028 fprintf (f, "%5d all allocated alternative states\n",
9029 allocated_alt_states_num);
9030 fprintf (f, "%5d all transition comb vector els, %5d all trans table els\n",
9031 transition_comb_vect_els, transition_full_vect_els);
9032 fprintf (f, "%5d all min delay table els\n", min_issue_delay_vect_els);
9033 fprintf (f, "%5d all locked states\n", locked_states);
9034 #endif
9037 /* The function output times of work of different phases of DFA
9038 generator. */
9039 static void
9040 output_time_statistics (FILE *f)
9042 fprintf (f, "\n transformation: ");
9043 print_active_time (f, transform_time);
9044 fprintf (f, (!ndfa_flag ? ", building DFA: " : ", building NDFA: "));
9045 print_active_time (f, NDFA_time);
9046 if (ndfa_flag)
9048 fprintf (f, ", NDFA -> DFA: ");
9049 print_active_time (f, NDFA_to_DFA_time);
9051 fprintf (f, "\n DFA minimization: ");
9052 print_active_time (f, minimize_time);
9053 fprintf (f, ", making insn equivalence: ");
9054 print_active_time (f, equiv_time);
9055 fprintf (f, "\n all automaton generation: ");
9056 print_active_time (f, automaton_generation_time);
9057 fprintf (f, ", output: ");
9058 print_active_time (f, output_time);
9059 fprintf (f, "\n");
9062 /* The function generates DFA (deterministic finite state automaton)
9063 for fast recognition of pipeline hazards. No errors during
9064 checking must be fixed before this function call. */
9065 static void
9066 generate (void)
9068 automata_num = split_argument;
9069 if (description->units_num < automata_num)
9070 automata_num = description->units_num;
9071 initiate_states ();
9072 initiate_arcs ();
9073 initiate_automata_lists ();
9074 initiate_pass_states ();
9075 initiate_excl_sets ();
9076 initiate_presence_absence_pattern_sets ();
9077 automaton_generation_time = create_ticker ();
9078 create_automata ();
9079 ticker_off (&automaton_generation_time);
9084 /* This page mainly contains top level functions of pipeline hazards
9085 description translator. */
9087 /* The following macro value is suffix of name of description file of
9088 pipeline hazards description translator. */
9089 #define STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX ".dfa"
9091 /* The function returns suffix of given file name. The returned
9092 string can not be changed. */
9093 static const char *
9094 file_name_suffix (const char *file_name)
9096 const char *last_period;
9098 for (last_period = NULL; *file_name != '\0'; file_name++)
9099 if (*file_name == '.')
9100 last_period = file_name;
9101 return (last_period == NULL ? file_name : last_period);
9104 /* The function returns base name of given file name, i.e. pointer to
9105 first char after last `/' (or `\' for WIN32) in given file name,
9106 given file name itself if the directory name is absent. The
9107 returned string can not be changed. */
9108 static const char *
9109 base_file_name (const char *file_name)
9111 int directory_name_length;
9113 directory_name_length = strlen (file_name);
9114 #ifdef WIN32
9115 while (directory_name_length >= 0 && file_name[directory_name_length] != '/'
9116 && file_name[directory_name_length] != '\\')
9117 #else
9118 while (directory_name_length >= 0 && file_name[directory_name_length] != '/')
9119 #endif
9120 directory_name_length--;
9121 return file_name + directory_name_length + 1;
9124 /* The following is top level function to initialize the work of
9125 pipeline hazards description translator. */
9126 static void
9127 initiate_automaton_gen (int argc, char **argv)
9129 const char *base_name;
9130 int i;
9132 ndfa_flag = 0;
9133 split_argument = 0; /* default value */
9134 no_minimization_flag = 0;
9135 time_flag = 0;
9136 stats_flag = 0;
9137 v_flag = 0;
9138 w_flag = 0;
9139 progress_flag = 0;
9140 for (i = 2; i < argc; i++)
9141 if (strcmp (argv [i], NO_MINIMIZATION_OPTION) == 0)
9142 no_minimization_flag = 1;
9143 else if (strcmp (argv [i], TIME_OPTION) == 0)
9144 time_flag = 1;
9145 else if (strcmp (argv [i], STATS_OPTION) == 0)
9146 stats_flag = 1;
9147 else if (strcmp (argv [i], V_OPTION) == 0)
9148 v_flag = 1;
9149 else if (strcmp (argv [i], W_OPTION) == 0)
9150 w_flag = 1;
9151 else if (strcmp (argv [i], NDFA_OPTION) == 0)
9152 ndfa_flag = 1;
9153 else if (strcmp (argv [i], PROGRESS_OPTION) == 0)
9154 progress_flag = 1;
9155 else if (strcmp (argv [i], "-split") == 0)
9157 if (i + 1 >= argc)
9158 fatal ("-split has no argument.");
9159 fatal ("option `-split' has not been implemented yet\n");
9160 /* split_argument = atoi (argument_vect [i + 1]); */
9163 /* Initialize IR storage. */
9164 obstack_init (&irp);
9165 initiate_automaton_decl_table ();
9166 initiate_insn_decl_table ();
9167 initiate_decl_table ();
9168 output_file = stdout;
9169 output_description_file = NULL;
9170 base_name = base_file_name (argv[1]);
9171 obstack_grow (&irp, base_name,
9172 strlen (base_name) - strlen (file_name_suffix (base_name)));
9173 obstack_grow (&irp, STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX,
9174 strlen (STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX) + 1);
9175 obstack_1grow (&irp, '\0');
9176 output_description_file_name = obstack_base (&irp);
9177 obstack_finish (&irp);
9180 /* The following function checks existence at least one arc marked by
9181 each insn. */
9182 static void
9183 check_automata_insn_issues (void)
9185 automaton_t automaton;
9186 ainsn_t ainsn, reserv_ainsn;
9188 for (automaton = description->first_automaton;
9189 automaton != NULL;
9190 automaton = automaton->next_automaton)
9192 for (ainsn = automaton->ainsn_list;
9193 ainsn != NULL;
9194 ainsn = ainsn->next_ainsn)
9195 if (ainsn->first_insn_with_same_reservs && !ainsn->arc_exists_p)
9197 for (reserv_ainsn = ainsn;
9198 reserv_ainsn != NULL;
9199 reserv_ainsn = reserv_ainsn->next_same_reservs_insn)
9200 if (automaton->corresponding_automaton_decl != NULL)
9202 if (!w_flag)
9203 error ("Automaton `%s': Insn `%s' will never be issued",
9204 automaton->corresponding_automaton_decl->name,
9205 reserv_ainsn->insn_reserv_decl->name);
9206 else
9207 warning ("Automaton `%s': Insn `%s' will never be issued",
9208 automaton->corresponding_automaton_decl->name,
9209 reserv_ainsn->insn_reserv_decl->name);
9211 else
9213 if (!w_flag)
9214 error ("Insn `%s' will never be issued",
9215 reserv_ainsn->insn_reserv_decl->name);
9216 else
9217 warning ("Insn `%s' will never be issued",
9218 reserv_ainsn->insn_reserv_decl->name);
9224 /* The following vla is used for storing pointers to all achieved
9225 states. */
9226 static VEC(state_t, heap) *automaton_states;
9228 /* This function is called by function pass_states to add an achieved
9229 STATE. */
9230 static void
9231 add_automaton_state (state_t state)
9233 VEC_safe_push (state_t, heap, automaton_states, state);
9236 /* The following function forms list of important automata (whose
9237 states may be changed after the insn issue) for each insn. */
9238 static void
9239 form_important_insn_automata_lists (void)
9241 automaton_t automaton;
9242 decl_t decl;
9243 ainsn_t ainsn;
9244 arc_t arc;
9245 int i;
9246 size_t n;
9248 automaton_states = 0;
9249 /* Mark important ainsns. */
9250 for (automaton = description->first_automaton;
9251 automaton != NULL;
9252 automaton = automaton->next_automaton)
9254 VEC_truncate (state_t, automaton_states, 0);
9255 pass_states (automaton, add_automaton_state);
9256 for (n = 0; n < VEC_length (state_t, automaton_states); n++)
9258 state_t s = VEC_index (state_t, automaton_states, n);
9259 for (arc = first_out_arc (s);
9260 arc != NULL;
9261 arc = next_out_arc (arc))
9262 if (arc->to_state != s)
9264 gcc_assert (arc->insn->first_insn_with_same_reservs);
9265 for (ainsn = arc->insn;
9266 ainsn != NULL;
9267 ainsn = ainsn->next_same_reservs_insn)
9268 ainsn->important_p = TRUE;
9272 VEC_free (state_t, heap, automaton_states);
9274 /* Create automata sets for the insns. */
9275 for (i = 0; i < description->decls_num; i++)
9277 decl = description->decls [i];
9278 if (decl->mode == dm_insn_reserv)
9280 automata_list_start ();
9281 for (automaton = description->first_automaton;
9282 automaton != NULL;
9283 automaton = automaton->next_automaton)
9284 for (ainsn = automaton->ainsn_list;
9285 ainsn != NULL;
9286 ainsn = ainsn->next_ainsn)
9287 if (ainsn->important_p
9288 && ainsn->insn_reserv_decl == DECL_INSN_RESERV (decl))
9290 automata_list_add (automaton);
9291 break;
9293 DECL_INSN_RESERV (decl)->important_automata_list
9294 = automata_list_finish ();
9300 /* The following is top level function to generate automat(a,on) for
9301 fast recognition of pipeline hazards. */
9302 static void
9303 expand_automata (void)
9305 int i;
9307 description = XCREATENODEVAR (struct description,
9308 sizeof (struct description)
9309 /* One entry for cycle advancing insn. */
9310 + sizeof (decl_t) * VEC_length (decl_t, decls));
9311 description->decls_num = VEC_length (decl_t, decls);
9312 description->query_units_num = 0;
9313 for (i = 0; i < description->decls_num; i++)
9315 description->decls [i] = VEC_index (decl_t, decls, i);
9316 if (description->decls [i]->mode == dm_unit
9317 && DECL_UNIT (description->decls [i])->query_p)
9318 DECL_UNIT (description->decls [i])->query_num
9319 = description->query_units_num++;
9321 all_time = create_ticker ();
9322 check_time = create_ticker ();
9323 if (progress_flag)
9324 fprintf (stderr, "Check description...");
9325 check_all_description ();
9326 if (progress_flag)
9327 fprintf (stderr, "done\n");
9328 ticker_off (&check_time);
9329 generation_time = create_ticker ();
9330 if (!have_error)
9332 transform_insn_regexps ();
9333 check_unit_distributions_to_automata ();
9335 if (!have_error)
9337 generate ();
9338 check_automata_insn_issues ();
9340 if (!have_error)
9342 form_important_insn_automata_lists ();
9344 ticker_off (&generation_time);
9347 /* The following is top level function to output PHR and to finish
9348 work with pipeline description translator. */
9349 static void
9350 write_automata (void)
9352 output_time = create_ticker ();
9353 if (progress_flag)
9354 fprintf (stderr, "Forming and outputting automata tables...");
9355 output_tables ();
9356 if (progress_flag)
9358 fprintf (stderr, "done\n");
9359 fprintf (stderr, "Output functions to work with automata...");
9361 output_chip_definitions ();
9362 output_max_insn_queue_index_def ();
9363 output_internal_min_issue_delay_func ();
9364 output_internal_trans_func ();
9365 /* Cache of insn dfa codes: */
9366 fprintf (output_file, "\nstatic int *%s;\n", DFA_INSN_CODES_VARIABLE_NAME);
9367 fprintf (output_file, "\nstatic int %s;\n\n",
9368 DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
9369 output_dfa_insn_code_func ();
9370 output_trans_func ();
9371 output_min_issue_delay_func ();
9372 output_internal_dead_lock_func ();
9373 output_dead_lock_func ();
9374 output_size_func ();
9375 output_internal_reset_func ();
9376 output_reset_func ();
9377 output_min_insn_conflict_delay_func ();
9378 output_default_latencies ();
9379 output_internal_insn_latency_func ();
9380 output_insn_latency_func ();
9381 output_internal_maximal_insn_latency_func ();
9382 output_maximal_insn_latency_func ();
9383 output_print_reservation_func ();
9384 /* Output function get_cpu_unit_code. */
9385 fprintf (output_file, "\n#if %s\n\n", CPU_UNITS_QUERY_MACRO_NAME);
9386 output_get_cpu_unit_code_func ();
9387 output_cpu_unit_reservation_p ();
9388 output_insn_has_dfa_reservation_p ();
9389 fprintf (output_file, "\n#endif /* #if %s */\n\n",
9390 CPU_UNITS_QUERY_MACRO_NAME);
9391 output_dfa_clean_insn_cache_func ();
9392 output_dfa_start_func ();
9393 output_dfa_finish_func ();
9394 if (progress_flag)
9395 fprintf (stderr, "done\n");
9396 if (v_flag)
9398 output_description_file = fopen (output_description_file_name, "w");
9399 if (output_description_file == NULL)
9401 perror (output_description_file_name);
9402 exit (FATAL_EXIT_CODE);
9404 if (progress_flag)
9405 fprintf (stderr, "Output automata description...");
9406 output_description ();
9407 output_automaton_descriptions ();
9408 if (progress_flag)
9409 fprintf (stderr, "done\n");
9410 output_statistics (output_description_file);
9412 if (stats_flag)
9413 output_statistics (stderr);
9414 ticker_off (&output_time);
9415 if (time_flag)
9416 output_time_statistics (stderr);
9417 finish_states ();
9418 finish_arcs ();
9419 finish_automata_lists ();
9420 if (time_flag)
9422 fprintf (stderr, "Summary:\n");
9423 fprintf (stderr, " check time ");
9424 print_active_time (stderr, check_time);
9425 fprintf (stderr, ", generation time ");
9426 print_active_time (stderr, generation_time);
9427 fprintf (stderr, ", all time ");
9428 print_active_time (stderr, all_time);
9429 fprintf (stderr, "\n");
9431 /* Finish all work. */
9432 if (output_description_file != NULL)
9434 fflush (output_description_file);
9435 if (ferror (stdout) != 0)
9436 fatal ("Error in writing DFA description file %s: %s",
9437 output_description_file_name, xstrerror (errno));
9438 fclose (output_description_file);
9440 finish_automaton_decl_table ();
9441 finish_insn_decl_table ();
9442 finish_decl_table ();
9443 obstack_free (&irp, NULL);
9444 if (have_error && output_description_file != NULL)
9445 remove (output_description_file_name);
9449 main (int argc, char **argv)
9451 rtx desc;
9453 progname = "genautomata";
9455 if (!init_rtx_reader_args (argc, argv))
9456 return (FATAL_EXIT_CODE);
9458 initiate_automaton_gen (argc, argv);
9459 while (1)
9461 int lineno;
9462 int insn_code_number;
9464 desc = read_md_rtx (&lineno, &insn_code_number);
9465 if (desc == NULL)
9466 break;
9468 switch (GET_CODE (desc))
9470 case DEFINE_CPU_UNIT:
9471 gen_cpu_unit (desc);
9472 break;
9474 case DEFINE_QUERY_CPU_UNIT:
9475 gen_query_cpu_unit (desc);
9476 break;
9478 case DEFINE_BYPASS:
9479 gen_bypass (desc);
9480 break;
9482 case EXCLUSION_SET:
9483 gen_excl_set (desc);
9484 break;
9486 case PRESENCE_SET:
9487 gen_presence_set (desc);
9488 break;
9490 case FINAL_PRESENCE_SET:
9491 gen_final_presence_set (desc);
9492 break;
9494 case ABSENCE_SET:
9495 gen_absence_set (desc);
9496 break;
9498 case FINAL_ABSENCE_SET:
9499 gen_final_absence_set (desc);
9500 break;
9502 case DEFINE_AUTOMATON:
9503 gen_automaton (desc);
9504 break;
9506 case AUTOMATA_OPTION:
9507 gen_automata_option (desc);
9508 break;
9510 case DEFINE_RESERVATION:
9511 gen_reserv (desc);
9512 break;
9514 case DEFINE_INSN_RESERVATION:
9515 gen_insn_reserv (desc);
9516 break;
9518 default:
9519 break;
9523 if (have_error)
9524 return FATAL_EXIT_CODE;
9526 if (VEC_length (decl_t, decls) > 0)
9528 expand_automata ();
9529 if (!have_error)
9531 puts ("/* Generated automatically by the program `genautomata'\n"
9532 " from the machine description file `md'. */\n\n"
9533 "#include \"config.h\"\n"
9534 "#include \"system.h\"\n"
9535 "#include \"coretypes.h\"\n"
9536 "#include \"tm.h\"\n"
9537 "#include \"rtl.h\"\n"
9538 "#include \"tm_p.h\"\n"
9539 "#include \"insn-config.h\"\n"
9540 "#include \"recog.h\"\n"
9541 "#include \"regs.h\"\n"
9542 "#include \"output.h\"\n"
9543 "#include \"insn-attr.h\"\n"
9544 "#include \"diagnostic-core.h\"\n"
9545 "#include \"flags.h\"\n"
9546 "#include \"function.h\"\n"
9547 "#include \"emit-rtl.h\"\n");
9548 /* FIXME: emit-rtl.h can go away once crtl is in rtl.h. */
9550 write_automata ();
9553 else
9555 puts ("/* Generated automatically by the program `genautomata'\n"
9556 " from the machine description file `md'. */\n\n"
9557 "/* There is no automaton, but ISO C forbids empty\n"
9558 " translation units, so include a header file with some\n"
9559 " declarations, and its pre-requisite header file. */\n"
9560 "#include \"config.h\"\n"
9561 "#include \"system.h\"\n");
9564 fflush (stdout);
9565 return (ferror (stdout) != 0 || have_error
9566 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);