* loop-iv.c (determine_max_iter): New arg OLD_NITER. All callers
[official-gcc/alias-decl.git] / gcc / genautomata.c
blob1d742f4dcb69e1d14e60cf9fef5c53747ba32592
1 /* Pipeline hazard description translator.
2 Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009
3 Free Software Foundation, Inc.
5 Written by Vladimir Makarov <vmakarov@redhat.com>
7 This file is part of GCC.
9 GCC is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by the
11 Free Software Foundation; either version 3, or (at your option) any
12 later version.
14 GCC is distributed in the hope that it will be useful, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 for more details.
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING3. If not see
21 <http://www.gnu.org/licenses/>. */
23 /* References:
25 1. The finite state automaton based pipeline hazard recognizer and
26 instruction scheduler in GCC. V. Makarov. Proceedings of GCC
27 summit, 2003.
29 2. Detecting pipeline structural hazards quickly. T. Proebsting,
30 C. Fraser. Proceedings of ACM SIGPLAN-SIGACT Symposium on
31 Principles of Programming Languages, pages 280--286, 1994.
33 This article is a good start point to understand usage of finite
34 state automata for pipeline hazard recognizers. But I'd
35 recommend the 1st and 3rd article for more deep understanding.
37 3. Efficient Instruction Scheduling Using Finite State Automata:
38 V. Bala and N. Rubin, Proceedings of MICRO-28. This is the best
39 article about usage of finite state automata for pipeline hazard
40 recognizers.
42 The current implementation is described in the 1st article and it
43 is different from the 3rd article in the following:
45 1. New operator `|' (alternative) is permitted in functional unit
46 reservation which can be treated deterministically and
47 non-deterministically.
49 2. Possibility of usage of nondeterministic automata too.
51 3. Possibility to query functional unit reservations for given
52 automaton state.
54 4. Several constructions to describe impossible reservations
55 (`exclusion_set', `presence_set', `final_presence_set',
56 `absence_set', and `final_absence_set').
58 5. No reverse automata are generated. Trace instruction scheduling
59 requires this. It can be easily added in the future if we
60 really need this.
62 6. Union of automaton states are not generated yet. It is planned
63 to be implemented. Such feature is needed to make more accurate
64 interlock insn scheduling to get state describing functional
65 unit reservation in a joint CFG point. */
67 /* This file code processes constructions of machine description file
68 which describes automaton used for recognition of processor pipeline
69 hazards by insn scheduler and can be used for other tasks (such as
70 VLIW insn packing.
72 The translator functions `gen_cpu_unit', `gen_query_cpu_unit',
73 `gen_bypass', `gen_excl_set', `gen_presence_set',
74 `gen_final_presence_set', `gen_absence_set',
75 `gen_final_absence_set', `gen_automaton', `gen_automata_option',
76 `gen_reserv', `gen_insn_reserv' are called from file
77 `genattrtab.c'. They transform RTL constructions describing
78 automata in .md file into internal representation convenient for
79 further processing.
81 The translator major function `expand_automata' processes the
82 description internal representation into finite state automaton.
83 It can be divided on:
85 o checking correctness of the automaton pipeline description
86 (major function is `check_all_description').
88 o generating automaton (automata) from the description (major
89 function is `make_automaton').
91 o optional transformation of nondeterministic finite state
92 automata into deterministic ones if the alternative operator
93 `|' is treated nondeterministically in the description (major
94 function is NDFA_to_DFA).
96 o optional minimization of the finite state automata by merging
97 equivalent automaton states (major function is `minimize_DFA').
99 o forming tables (some as comb vectors) and attributes
100 representing the automata (functions output_..._table).
102 Function `write_automata' outputs the created finite state
103 automaton as different tables and functions which works with the
104 automata to inquire automaton state and to change its state. These
105 function are used by gcc instruction scheduler and may be some
106 other gcc code. */
108 #include "bconfig.h"
109 #include "system.h"
110 #include "coretypes.h"
111 #include "tm.h"
112 #include "rtl.h"
113 #include "obstack.h"
114 #include "errors.h"
115 #include "gensupport.h"
117 #include <math.h>
118 #include "hashtab.h"
119 #include "vec.h"
121 #ifndef CHAR_BIT
122 #define CHAR_BIT 8
123 #endif
125 /* Positions in machine description file. Now they are not used. But
126 they could be used in the future for better diagnostic messages. */
127 typedef int pos_t;
129 /* The following is element of vector of current (and planned in the
130 future) functional unit reservations. */
131 typedef unsigned HOST_WIDE_INT set_el_t;
133 /* Reservations of function units are represented by value of the following
134 type. */
135 typedef set_el_t *reserv_sets_t;
136 typedef const set_el_t *const_reserv_sets_t;
138 /* The following structure describes a ticker. */
139 struct ticker
141 /* The following member value is time of the ticker creation with
142 taking into account time when the ticker is off. Active time of
143 the ticker is current time minus the value. */
144 int modified_creation_time;
145 /* The following member value is time (incremented by one) when the
146 ticker was off. Zero value means that now the ticker is on. */
147 int incremented_off_time;
150 /* The ticker is represented by the following type. */
151 typedef struct ticker ticker_t;
153 /* The following type describes elements of output vectors. */
154 typedef HOST_WIDE_INT vect_el_t;
156 /* Forward declaration of structures of internal representation of
157 pipeline description based on NDFA. */
159 struct unit_decl;
160 struct bypass_decl;
161 struct result_decl;
162 struct automaton_decl;
163 struct unit_pattern_rel_decl;
164 struct reserv_decl;
165 struct insn_reserv_decl;
166 struct decl;
167 struct unit_regexp;
168 struct result_regexp;
169 struct reserv_regexp;
170 struct nothing_regexp;
171 struct sequence_regexp;
172 struct repeat_regexp;
173 struct allof_regexp;
174 struct oneof_regexp;
175 struct regexp;
176 struct description;
177 struct unit_set_el;
178 struct pattern_set_el;
179 struct pattern_reserv;
180 struct state;
181 struct alt_state;
182 struct arc;
183 struct ainsn;
184 struct automaton;
185 struct state_ainsn_table;
187 /* The following typedefs are for brevity. */
188 typedef struct unit_decl *unit_decl_t;
189 typedef const struct unit_decl *const_unit_decl_t;
190 typedef struct decl *decl_t;
191 typedef const struct decl *const_decl_t;
192 typedef struct regexp *regexp_t;
193 typedef struct unit_set_el *unit_set_el_t;
194 typedef struct pattern_set_el *pattern_set_el_t;
195 typedef struct pattern_reserv *pattern_reserv_t;
196 typedef struct alt_state *alt_state_t;
197 typedef struct state *state_t;
198 typedef const struct state *const_state_t;
199 typedef struct arc *arc_t;
200 typedef struct ainsn *ainsn_t;
201 typedef struct automaton *automaton_t;
202 typedef struct automata_list_el *automata_list_el_t;
203 typedef const struct automata_list_el *const_automata_list_el_t;
204 typedef struct state_ainsn_table *state_ainsn_table_t;
206 /* Undefined position. */
207 static pos_t no_pos = 0;
209 /* All IR is stored in the following obstack. */
210 static struct obstack irp;
213 /* Declare vector types for various data structures: */
215 DEF_VEC_P(alt_state_t);
216 DEF_VEC_ALLOC_P(alt_state_t,heap);
217 DEF_VEC_P(ainsn_t);
218 DEF_VEC_ALLOC_P(ainsn_t,heap);
219 DEF_VEC_P(state_t);
220 DEF_VEC_ALLOC_P(state_t,heap);
221 DEF_VEC_P(decl_t);
222 DEF_VEC_ALLOC_P(decl_t,heap);
223 DEF_VEC_P(reserv_sets_t);
224 DEF_VEC_ALLOC_P(reserv_sets_t,heap);
226 DEF_VEC_I(vect_el_t);
227 DEF_VEC_ALLOC_I(vect_el_t, heap);
228 typedef VEC(vect_el_t,heap) *vla_hwint_t;
230 /* Forward declarations of functions used before their definitions, only. */
231 static regexp_t gen_regexp_sequence (const char *);
232 static void reserv_sets_or (reserv_sets_t, reserv_sets_t,
233 reserv_sets_t);
234 static reserv_sets_t get_excl_set (reserv_sets_t);
235 static int check_presence_pattern_sets (reserv_sets_t,
236 reserv_sets_t, int);
237 static int check_absence_pattern_sets (reserv_sets_t, reserv_sets_t,
238 int);
239 static arc_t first_out_arc (const_state_t);
240 static arc_t next_out_arc (arc_t);
244 /* Options with the following names can be set up in automata_option
245 construction. Because the strings occur more one time we use the
246 macros. */
248 #define NO_MINIMIZATION_OPTION "-no-minimization"
249 #define TIME_OPTION "-time"
250 #define STATS_OPTION "-stats"
251 #define V_OPTION "-v"
252 #define W_OPTION "-w"
253 #define NDFA_OPTION "-ndfa"
254 #define PROGRESS_OPTION "-progress"
256 /* The following flags are set up by function `initiate_automaton_gen'. */
258 /* Make automata with nondeterministic reservation by insns (`-ndfa'). */
259 static int ndfa_flag;
261 /* Do not make minimization of DFA (`-no-minimization'). */
262 static int no_minimization_flag;
264 /* Value of this variable is number of automata being generated. The
265 actual number of automata may be less this value if there is not
266 sufficient number of units. This value is defined by argument of
267 option `-split' or by constructions automaton if the value is zero
268 (it is default value of the argument). */
269 static int split_argument;
271 /* Flag of output time statistics (`-time'). */
272 static int time_flag;
274 /* Flag of automata statistics (`-stats'). */
275 static int stats_flag;
277 /* Flag of creation of description file which contains description of
278 result automaton and statistics information (`-v'). */
279 static int v_flag;
281 /* Flag of output of a progress bar showing how many states were
282 generated so far for automaton being processed (`-progress'). */
283 static int progress_flag;
285 /* Flag of generating warning instead of error for non-critical errors
286 (`-w'). */
287 static int w_flag;
290 /* Output file for pipeline hazard recognizer (PHR) being generated.
291 The value is NULL if the file is not defined. */
292 static FILE *output_file;
294 /* Description file of PHR. The value is NULL if the file is not
295 created. */
296 static FILE *output_description_file;
298 /* PHR description file name. */
299 static char *output_description_file_name;
301 /* Value of the following variable is node representing description
302 being processed. This is start point of IR. */
303 static struct description *description;
307 /* This page contains description of IR structure (nodes). */
309 enum decl_mode
311 dm_unit,
312 dm_bypass,
313 dm_automaton,
314 dm_excl,
315 dm_presence,
316 dm_absence,
317 dm_reserv,
318 dm_insn_reserv
321 /* This describes define_cpu_unit and define_query_cpu_unit (see file
322 rtl.def). */
323 struct unit_decl
325 const char *name;
326 /* NULL if the automaton name is absent. */
327 const char *automaton_name;
328 /* If the following value is not zero, the cpu unit reservation is
329 described in define_query_cpu_unit. */
330 char query_p;
332 /* The following fields are defined by checker. */
334 /* The following field value is nonzero if the unit is used in an
335 regexp. */
336 char unit_is_used;
338 /* The following field value is order number (0, 1, ...) of given
339 unit. */
340 int unit_num;
341 /* The following field value is corresponding declaration of
342 automaton which was given in description. If the field value is
343 NULL then automaton in the unit declaration was absent. */
344 struct automaton_decl *automaton_decl;
345 /* The following field value is maximal cycle number (1, ...) on
346 which given unit occurs in insns. Zero value means that given
347 unit is not used in insns. */
348 int max_occ_cycle_num;
349 /* The following field value is minimal cycle number (0, ...) on
350 which given unit occurs in insns. -1 value means that given
351 unit is not used in insns. */
352 int min_occ_cycle_num;
353 /* The following list contains units which conflict with given
354 unit. */
355 unit_set_el_t excl_list;
356 /* The following list contains patterns which are required to
357 reservation of given unit. */
358 pattern_set_el_t presence_list;
359 pattern_set_el_t final_presence_list;
360 /* The following list contains patterns which should be not present
361 in reservation for given unit. */
362 pattern_set_el_t absence_list;
363 pattern_set_el_t final_absence_list;
364 /* The following is used only when `query_p' has nonzero value.
365 This is query number for the unit. */
366 int query_num;
367 /* The following is the last cycle on which the unit was checked for
368 correct distributions of units to automata in a regexp. */
369 int last_distribution_check_cycle;
371 /* The following fields are defined by automaton generator. */
373 /* The following field value is number of the automaton to which
374 given unit belongs. */
375 int corresponding_automaton_num;
376 /* If the following value is not zero, the cpu unit is present in a
377 `exclusion_set' or in right part of a `presence_set',
378 `final_presence_set', `absence_set', and
379 `final_absence_set'define_query_cpu_unit. */
380 char in_set_p;
383 /* This describes define_bypass (see file rtl.def). */
384 struct bypass_decl
386 int latency;
387 const char *out_insn_name;
388 const char *in_insn_name;
389 const char *bypass_guard_name;
391 /* The following fields are defined by checker. */
393 /* output and input insns of given bypass. */
394 struct insn_reserv_decl *out_insn_reserv;
395 struct insn_reserv_decl *in_insn_reserv;
396 /* The next bypass for given output insn. */
397 struct bypass_decl *next;
400 /* This describes define_automaton (see file rtl.def). */
401 struct automaton_decl
403 const char *name;
405 /* The following fields are defined by automaton generator. */
407 /* The following field value is nonzero if the automaton is used in
408 an regexp definition. */
409 char automaton_is_used;
411 /* The following fields are defined by checker. */
413 /* The following field value is the corresponding automaton. This
414 field is not NULL only if the automaton is present in unit
415 declarations and the automatic partition on automata is not
416 used. */
417 automaton_t corresponding_automaton;
420 /* This describes exclusion relations: exclusion_set (see file
421 rtl.def). */
422 struct excl_rel_decl
424 int all_names_num;
425 int first_list_length;
426 char *names [1];
429 /* This describes unit relations: [final_]presence_set or
430 [final_]absence_set (see file rtl.def). */
431 struct unit_pattern_rel_decl
433 int final_p;
434 int names_num;
435 int patterns_num;
436 char **names;
437 char ***patterns;
440 /* This describes define_reservation (see file rtl.def). */
441 struct reserv_decl
443 const char *name;
444 regexp_t regexp;
446 /* The following fields are defined by checker. */
448 /* The following field value is nonzero if the unit is used in an
449 regexp. */
450 char reserv_is_used;
451 /* The following field is used to check up cycle in expression
452 definition. */
453 int loop_pass_num;
456 /* This describes define_insn_reservation (see file rtl.def). */
457 struct insn_reserv_decl
459 rtx condexp;
460 int default_latency;
461 regexp_t regexp;
462 const char *name;
464 /* The following fields are defined by checker. */
466 /* The following field value is order number (0, 1, ...) of given
467 insn. */
468 int insn_num;
469 /* The following field value is list of bypasses in which given insn
470 is output insn. Bypasses with the same input insn stay one after
471 another in the list in the same order as their occurrences in the
472 description but the bypass without a guard stays always the last
473 in a row of bypasses with the same input insn. */
474 struct bypass_decl *bypass_list;
476 /* The following fields are defined by automaton generator. */
478 /* The following field is the insn regexp transformed that
479 the regexp has not optional regexp, repetition regexp, and an
480 reservation name (i.e. reservation identifiers are changed by the
481 corresponding regexp) and all alternations are the top level
482 of the regexp. The value can be NULL only if it is special
483 insn `cycle advancing'. */
484 regexp_t transformed_regexp;
485 /* The following field value is list of arcs marked given
486 insn. The field is used in transformation NDFA -> DFA. */
487 arc_t arcs_marked_by_insn;
488 /* The two following fields are used during minimization of a finite state
489 automaton. */
490 /* The field value is number of equivalence class of state into
491 which arc marked by given insn enters from a state (fixed during
492 an automaton minimization). */
493 int equiv_class_num;
494 /* The following member value is the list to automata which can be
495 changed by the insn issue. */
496 automata_list_el_t important_automata_list;
497 /* The following member is used to process insn once for output. */
498 int processed_p;
501 /* This contains a declaration mentioned above. */
502 struct decl
504 /* What node in the union? */
505 enum decl_mode mode;
506 pos_t pos;
507 union
509 struct unit_decl unit;
510 struct bypass_decl bypass;
511 struct automaton_decl automaton;
512 struct excl_rel_decl excl;
513 struct unit_pattern_rel_decl presence;
514 struct unit_pattern_rel_decl absence;
515 struct reserv_decl reserv;
516 struct insn_reserv_decl insn_reserv;
517 } decl;
520 /* The following structures represent parsed reservation strings. */
521 enum regexp_mode
523 rm_unit,
524 rm_reserv,
525 rm_nothing,
526 rm_sequence,
527 rm_repeat,
528 rm_allof,
529 rm_oneof
532 /* Cpu unit in reservation. */
533 struct unit_regexp
535 const char *name;
536 unit_decl_t unit_decl;
539 /* Define_reservation in a reservation. */
540 struct reserv_regexp
542 const char *name;
543 struct reserv_decl *reserv_decl;
546 /* Absence of reservation (represented by string `nothing'). */
547 struct nothing_regexp
549 /* This used to be empty but ISO C doesn't allow that. */
550 char unused;
553 /* Representation of reservations separated by ',' (see file
554 rtl.def). */
555 struct sequence_regexp
557 int regexps_num;
558 regexp_t regexps [1];
561 /* Representation of construction `repeat' (see file rtl.def). */
562 struct repeat_regexp
564 int repeat_num;
565 regexp_t regexp;
568 /* Representation of reservations separated by '+' (see file
569 rtl.def). */
570 struct allof_regexp
572 int regexps_num;
573 regexp_t regexps [1];
576 /* Representation of reservations separated by '|' (see file
577 rtl.def). */
578 struct oneof_regexp
580 int regexps_num;
581 regexp_t regexps [1];
584 /* Representation of a reservation string. */
585 struct regexp
587 /* What node in the union? */
588 enum regexp_mode mode;
589 pos_t pos;
590 union
592 struct unit_regexp unit;
593 struct reserv_regexp reserv;
594 struct nothing_regexp nothing;
595 struct sequence_regexp sequence;
596 struct repeat_regexp repeat;
597 struct allof_regexp allof;
598 struct oneof_regexp oneof;
599 } regexp;
602 /* Represents description of pipeline hazard description based on
603 NDFA. */
604 struct description
606 int decls_num;
608 /* The following fields are defined by checker. */
610 /* The following fields values are correspondingly number of all
611 units, query units, and insns in the description. */
612 int units_num;
613 int query_units_num;
614 int insns_num;
615 /* The following field value is max length (in cycles) of
616 reservations of insns. The field value is defined only for
617 correct programs. */
618 int max_insn_reserv_cycles;
620 /* The following fields are defined by automaton generator. */
622 /* The following field value is the first automaton. */
623 automaton_t first_automaton;
625 /* The following field is created by pipeline hazard parser and
626 contains all declarations. We allocate additional entry for
627 special insn "cycle advancing" which is added by the automaton
628 generator. */
629 decl_t decls [1];
633 /* The following nodes are created in automaton checker. */
635 /* The following nodes represent exclusion set for cpu units. Each
636 element is accessed through only one excl_list. */
637 struct unit_set_el
639 unit_decl_t unit_decl;
640 unit_set_el_t next_unit_set_el;
643 /* The following nodes represent presence or absence pattern for cpu
644 units. Each element is accessed through only one presence_list or
645 absence_list. */
646 struct pattern_set_el
648 /* The number of units in unit_decls. */
649 int units_num;
650 /* The units forming the pattern. */
651 struct unit_decl **unit_decls;
652 pattern_set_el_t next_pattern_set_el;
656 /* The following nodes are created in automaton generator. */
659 /* The following nodes represent presence or absence pattern for cpu
660 units. Each element is accessed through only one element of
661 unit_presence_set_table or unit_absence_set_table. */
662 struct pattern_reserv
664 reserv_sets_t reserv;
665 pattern_reserv_t next_pattern_reserv;
668 /* The following node type describes state automaton. The state may
669 be deterministic or non-deterministic. Non-deterministic state has
670 several component states which represent alternative cpu units
671 reservations. The state also is used for describing a
672 deterministic reservation of automaton insn. */
673 struct state
675 /* The following member value is nonzero if there is a transition by
676 cycle advancing. */
677 int new_cycle_p;
678 /* The following field is list of processor unit reservations on
679 each cycle. */
680 reserv_sets_t reservs;
681 /* The following field is unique number of given state between other
682 states. */
683 int unique_num;
684 /* The following field value is automaton to which given state
685 belongs. */
686 automaton_t automaton;
687 /* The following field value is the first arc output from given
688 state. */
689 arc_t first_out_arc;
690 unsigned int num_out_arcs;
691 /* The following field is used to form NDFA. */
692 char it_was_placed_in_stack_for_NDFA_forming;
693 /* The following field is used to form DFA. */
694 char it_was_placed_in_stack_for_DFA_forming;
695 /* The following field is used to transform NDFA to DFA and DFA
696 minimization. The field value is not NULL if the state is a
697 compound state. In this case the value of field `unit_sets_list'
698 is NULL. All states in the list are in the hash table. The list
699 is formed through field `next_sorted_alt_state'. We should
700 support only one level of nesting state. */
701 alt_state_t component_states;
702 /* The following field is used for passing graph of states. */
703 int pass_num;
704 /* The list of states belonging to one equivalence class is formed
705 with the aid of the following field. */
706 state_t next_equiv_class_state;
707 /* The two following fields are used during minimization of a finite
708 state automaton. */
709 int equiv_class_num_1, equiv_class_num_2;
710 /* The following field is used during minimization of a finite state
711 automaton. The field value is state corresponding to equivalence
712 class to which given state belongs. */
713 state_t equiv_class_state;
714 unsigned int *presence_signature;
715 /* The following field value is the order number of given state.
716 The states in final DFA is enumerated with the aid of the
717 following field. */
718 int order_state_num;
719 /* This member is used for passing states for searching minimal
720 delay time. */
721 int state_pass_num;
722 /* The following member is used to evaluate min issue delay of insn
723 for a state. */
724 int min_insn_issue_delay;
727 /* Automaton arc. */
728 struct arc
730 /* The following field refers for the state into which given arc
731 enters. */
732 state_t to_state;
733 /* The following field describes that the insn issue (with cycle
734 advancing for special insn `cycle advancing' and without cycle
735 advancing for others) makes transition from given state to
736 another given state. */
737 ainsn_t insn;
738 /* The following field value is the next arc output from the same
739 state. */
740 arc_t next_out_arc;
741 /* List of arcs marked given insn is formed with the following
742 field. The field is used in transformation NDFA -> DFA. */
743 arc_t next_arc_marked_by_insn;
746 /* The following node type describes a deterministic alternative in
747 non-deterministic state which characterizes cpu unit reservations
748 of automaton insn or which is part of NDFA. */
749 struct alt_state
751 /* The following field is a deterministic state which characterizes
752 unit reservations of the instruction. */
753 state_t state;
754 /* The following field refers to the next state which characterizes
755 unit reservations of the instruction. */
756 alt_state_t next_alt_state;
757 /* The following field refers to the next state in sorted list. */
758 alt_state_t next_sorted_alt_state;
761 /* The following node type describes insn of automaton. They are
762 labels of FA arcs. */
763 struct ainsn
765 /* The following field value is the corresponding insn declaration
766 of description. */
767 struct insn_reserv_decl *insn_reserv_decl;
768 /* The following field value is the next insn declaration for an
769 automaton. */
770 ainsn_t next_ainsn;
771 /* The following field is states which characterize automaton unit
772 reservations of the instruction. The value can be NULL only if it
773 is special insn `cycle advancing'. */
774 alt_state_t alt_states;
775 /* The following field is sorted list of states which characterize
776 automaton unit reservations of the instruction. The value can be
777 NULL only if it is special insn `cycle advancing'. */
778 alt_state_t sorted_alt_states;
779 /* The following field refers the next automaton insn with
780 the same reservations. */
781 ainsn_t next_same_reservs_insn;
782 /* The following field is flag of the first automaton insn with the
783 same reservations in the declaration list. Only arcs marked such
784 insn is present in the automaton. This significantly decreases
785 memory requirements especially when several automata are
786 formed. */
787 char first_insn_with_same_reservs;
788 /* The following member has nonzero value if there is arc from state of
789 the automaton marked by the ainsn. */
790 char arc_exists_p;
791 /* Cyclic list of insns of an equivalence class is formed with the
792 aid of the following field. */
793 ainsn_t next_equiv_class_insn;
794 /* The following field value is nonzero if the insn declaration is
795 the first insn declaration with given equivalence number. */
796 char first_ainsn_with_given_equivalence_num;
797 /* The following field is number of class of equivalence of insns.
798 It is necessary because many insns may be equivalent with the
799 point of view of pipeline hazards. */
800 int insn_equiv_class_num;
801 /* The following member value is TRUE if there is an arc in the
802 automaton marked by the insn into another state. In other
803 words, the insn can change the state of the automaton. */
804 int important_p;
807 /* The following describes an automaton for PHR. */
808 struct automaton
810 /* The following field value is the list of insn declarations for
811 given automaton. */
812 ainsn_t ainsn_list;
813 /* The following field value is the corresponding automaton
814 declaration. This field is not NULL only if the automatic
815 partition on automata is not used. */
816 struct automaton_decl *corresponding_automaton_decl;
817 /* The following field value is the next automaton. */
818 automaton_t next_automaton;
819 /* The following field is start state of FA. There are not unit
820 reservations in the state. */
821 state_t start_state;
822 /* The following field value is number of equivalence classes of
823 insns (see field `insn_equiv_class_num' in
824 `insn_reserv_decl'). */
825 int insn_equiv_classes_num;
826 /* The following field value is number of states of final DFA. */
827 int achieved_states_num;
828 /* The following field value is the order number (0, 1, ...) of
829 given automaton. */
830 int automaton_order_num;
831 /* The following fields contain statistics information about
832 building automaton. */
833 int NDFA_states_num, DFA_states_num;
834 /* The following field value is defined only if minimization of DFA
835 is used. */
836 int minimal_DFA_states_num;
837 int NDFA_arcs_num, DFA_arcs_num;
838 /* The following field value is defined only if minimization of DFA
839 is used. */
840 int minimal_DFA_arcs_num;
841 /* The following member refers for two table state x ainsn -> int.
842 ??? Above sentence is incomprehensible. */
843 state_ainsn_table_t trans_table;
844 /* The following member value is maximal value of min issue delay
845 for insns of the automaton. */
846 int max_min_delay;
847 /* Usually min issue delay is small and we can place several (2, 4,
848 8) elements in one vector element. So the compression factor can
849 be 1 (no compression), 2, 4, 8. */
850 int min_issue_delay_table_compression_factor;
851 /* Total number of locked states in this automaton. */
852 int locked_states;
855 /* The following is the element of the list of automata. */
856 struct automata_list_el
858 /* The automaton itself. */
859 automaton_t automaton;
860 /* The next automata set element. */
861 automata_list_el_t next_automata_list_el;
864 /* The following structure describes a table state X ainsn -> int(>= 0). */
865 struct state_ainsn_table
867 /* Automaton to which given table belongs. */
868 automaton_t automaton;
869 /* The following tree vectors for comb vector implementation of the
870 table. */
871 vla_hwint_t comb_vect;
872 vla_hwint_t check_vect;
873 vla_hwint_t base_vect;
874 /* This is simple implementation of the table. */
875 vla_hwint_t full_vect;
876 /* Minimal and maximal values of the previous vectors. */
877 int min_comb_vect_el_value, max_comb_vect_el_value;
878 int min_base_vect_el_value, max_base_vect_el_value;
881 /* Macros to access members of unions. Use only them for access to
882 union members of declarations and regexps. */
884 #if defined ENABLE_CHECKING && (GCC_VERSION >= 2007)
886 #define DECL_UNIT(d) __extension__ \
887 (({ __typeof (d) const _decl = (d); \
888 if (_decl->mode != dm_unit) \
889 decl_mode_check_failed (_decl->mode, "dm_unit", \
890 __FILE__, __LINE__, __FUNCTION__); \
891 &(_decl)->decl.unit; }))
893 #define DECL_BYPASS(d) __extension__ \
894 (({ __typeof (d) const _decl = (d); \
895 if (_decl->mode != dm_bypass) \
896 decl_mode_check_failed (_decl->mode, "dm_bypass", \
897 __FILE__, __LINE__, __FUNCTION__); \
898 &(_decl)->decl.bypass; }))
900 #define DECL_AUTOMATON(d) __extension__ \
901 (({ __typeof (d) const _decl = (d); \
902 if (_decl->mode != dm_automaton) \
903 decl_mode_check_failed (_decl->mode, "dm_automaton", \
904 __FILE__, __LINE__, __FUNCTION__); \
905 &(_decl)->decl.automaton; }))
907 #define DECL_EXCL(d) __extension__ \
908 (({ __typeof (d) const _decl = (d); \
909 if (_decl->mode != dm_excl) \
910 decl_mode_check_failed (_decl->mode, "dm_excl", \
911 __FILE__, __LINE__, __FUNCTION__); \
912 &(_decl)->decl.excl; }))
914 #define DECL_PRESENCE(d) __extension__ \
915 (({ __typeof (d) const _decl = (d); \
916 if (_decl->mode != dm_presence) \
917 decl_mode_check_failed (_decl->mode, "dm_presence", \
918 __FILE__, __LINE__, __FUNCTION__); \
919 &(_decl)->decl.presence; }))
921 #define DECL_ABSENCE(d) __extension__ \
922 (({ __typeof (d) const _decl = (d); \
923 if (_decl->mode != dm_absence) \
924 decl_mode_check_failed (_decl->mode, "dm_absence", \
925 __FILE__, __LINE__, __FUNCTION__); \
926 &(_decl)->decl.absence; }))
928 #define DECL_RESERV(d) __extension__ \
929 (({ __typeof (d) const _decl = (d); \
930 if (_decl->mode != dm_reserv) \
931 decl_mode_check_failed (_decl->mode, "dm_reserv", \
932 __FILE__, __LINE__, __FUNCTION__); \
933 &(_decl)->decl.reserv; }))
935 #define DECL_INSN_RESERV(d) __extension__ \
936 (({ __typeof (d) const _decl = (d); \
937 if (_decl->mode != dm_insn_reserv) \
938 decl_mode_check_failed (_decl->mode, "dm_insn_reserv", \
939 __FILE__, __LINE__, __FUNCTION__); \
940 &(_decl)->decl.insn_reserv; }))
942 static const char *decl_name (enum decl_mode);
943 static void decl_mode_check_failed (enum decl_mode, const char *,
944 const char *, int, const char *)
945 ATTRIBUTE_NORETURN;
947 /* Return string representation of declaration mode MODE. */
948 static const char *
949 decl_name (enum decl_mode mode)
951 static char str [100];
953 if (mode == dm_unit)
954 return "dm_unit";
955 else if (mode == dm_bypass)
956 return "dm_bypass";
957 else if (mode == dm_automaton)
958 return "dm_automaton";
959 else if (mode == dm_excl)
960 return "dm_excl";
961 else if (mode == dm_presence)
962 return "dm_presence";
963 else if (mode == dm_absence)
964 return "dm_absence";
965 else if (mode == dm_reserv)
966 return "dm_reserv";
967 else if (mode == dm_insn_reserv)
968 return "dm_insn_reserv";
969 else
970 sprintf (str, "unknown (%d)", (int) mode);
971 return str;
974 /* The function prints message about unexpected declaration and finish
975 the program. */
976 static void
977 decl_mode_check_failed (enum decl_mode mode, const char *expected_mode_str,
978 const char *file, int line, const char *func)
980 fprintf
981 (stderr,
982 "\n%s: %d: error in %s: DECL check: expected decl %s, have %s\n",
983 file, line, func, expected_mode_str, decl_name (mode));
984 exit (1);
988 #define REGEXP_UNIT(r) __extension__ \
989 (({ struct regexp *const _regexp = (r); \
990 if (_regexp->mode != rm_unit) \
991 regexp_mode_check_failed (_regexp->mode, "rm_unit", \
992 __FILE__, __LINE__, __FUNCTION__); \
993 &(_regexp)->regexp.unit; }))
995 #define REGEXP_RESERV(r) __extension__ \
996 (({ struct regexp *const _regexp = (r); \
997 if (_regexp->mode != rm_reserv) \
998 regexp_mode_check_failed (_regexp->mode, "rm_reserv", \
999 __FILE__, __LINE__, __FUNCTION__); \
1000 &(_regexp)->regexp.reserv; }))
1002 #define REGEXP_SEQUENCE(r) __extension__ \
1003 (({ struct regexp *const _regexp = (r); \
1004 if (_regexp->mode != rm_sequence) \
1005 regexp_mode_check_failed (_regexp->mode, "rm_sequence", \
1006 __FILE__, __LINE__, __FUNCTION__); \
1007 &(_regexp)->regexp.sequence; }))
1009 #define REGEXP_REPEAT(r) __extension__ \
1010 (({ struct regexp *const _regexp = (r); \
1011 if (_regexp->mode != rm_repeat) \
1012 regexp_mode_check_failed (_regexp->mode, "rm_repeat", \
1013 __FILE__, __LINE__, __FUNCTION__); \
1014 &(_regexp)->regexp.repeat; }))
1016 #define REGEXP_ALLOF(r) __extension__ \
1017 (({ struct regexp *const _regexp = (r); \
1018 if (_regexp->mode != rm_allof) \
1019 regexp_mode_check_failed (_regexp->mode, "rm_allof", \
1020 __FILE__, __LINE__, __FUNCTION__); \
1021 &(_regexp)->regexp.allof; }))
1023 #define REGEXP_ONEOF(r) __extension__ \
1024 (({ struct regexp *const _regexp = (r); \
1025 if (_regexp->mode != rm_oneof) \
1026 regexp_mode_check_failed (_regexp->mode, "rm_oneof", \
1027 __FILE__, __LINE__, __FUNCTION__); \
1028 &(_regexp)->regexp.oneof; }))
1030 static const char *regexp_name (enum regexp_mode);
1031 static void regexp_mode_check_failed (enum regexp_mode, const char *,
1032 const char *, int,
1033 const char *) ATTRIBUTE_NORETURN;
1036 /* Return string representation of regexp mode MODE. */
1037 static const char *
1038 regexp_name (enum regexp_mode mode)
1040 switch (mode)
1042 case rm_unit:
1043 return "rm_unit";
1044 case rm_reserv:
1045 return "rm_reserv";
1046 case rm_nothing:
1047 return "rm_nothing";
1048 case rm_sequence:
1049 return "rm_sequence";
1050 case rm_repeat:
1051 return "rm_repeat";
1052 case rm_allof:
1053 return "rm_allof";
1054 case rm_oneof:
1055 return "rm_oneof";
1056 default:
1057 gcc_unreachable ();
1061 /* The function prints message about unexpected regexp and finish the
1062 program. */
1063 static void
1064 regexp_mode_check_failed (enum regexp_mode mode,
1065 const char *expected_mode_str,
1066 const char *file, int line, const char *func)
1068 fprintf
1069 (stderr,
1070 "\n%s: %d: error in %s: REGEXP check: expected decl %s, have %s\n",
1071 file, line, func, expected_mode_str, regexp_name (mode));
1072 exit (1);
1075 #else /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */
1077 #define DECL_UNIT(d) (&(d)->decl.unit)
1078 #define DECL_BYPASS(d) (&(d)->decl.bypass)
1079 #define DECL_AUTOMATON(d) (&(d)->decl.automaton)
1080 #define DECL_EXCL(d) (&(d)->decl.excl)
1081 #define DECL_PRESENCE(d) (&(d)->decl.presence)
1082 #define DECL_ABSENCE(d) (&(d)->decl.absence)
1083 #define DECL_RESERV(d) (&(d)->decl.reserv)
1084 #define DECL_INSN_RESERV(d) (&(d)->decl.insn_reserv)
1086 #define REGEXP_UNIT(r) (&(r)->regexp.unit)
1087 #define REGEXP_RESERV(r) (&(r)->regexp.reserv)
1088 #define REGEXP_SEQUENCE(r) (&(r)->regexp.sequence)
1089 #define REGEXP_REPEAT(r) (&(r)->regexp.repeat)
1090 #define REGEXP_ALLOF(r) (&(r)->regexp.allof)
1091 #define REGEXP_ONEOF(r) (&(r)->regexp.oneof)
1093 #endif /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */
1095 #define XCREATENODE(T) ((T *) create_node (sizeof (T)))
1096 #define XCREATENODEVEC(T, N) ((T *) create_node (sizeof (T) * (N)))
1097 #define XCREATENODEVAR(T, S) ((T *) create_node ((S)))
1099 #define XCOPYNODE(T, P) ((T *) copy_node ((P), sizeof (T)))
1100 #define XCOPYNODEVEC(T, P, N) ((T *) copy_node ((P), sizeof (T) * (N)))
1101 #define XCOPYNODEVAR(T, P, S) ((T *) copy_node ((P), (S)))
1103 /* Create IR structure (node). */
1104 static void *
1105 create_node (size_t size)
1107 void *result;
1109 obstack_blank (&irp, size);
1110 result = obstack_base (&irp);
1111 obstack_finish (&irp);
1112 /* Default values of members are NULL and zero. */
1113 memset (result, 0, size);
1114 return result;
1117 /* Copy IR structure (node). */
1118 static void *
1119 copy_node (const void *from, size_t size)
1121 void *const result = create_node (size);
1122 memcpy (result, from, size);
1123 return result;
1126 /* The function checks that NAME does not contain quotes (`"'). */
1127 static const char *
1128 check_name (const char * name, pos_t pos ATTRIBUTE_UNUSED)
1130 const char *str;
1132 for (str = name; *str != '\0'; str++)
1133 if (*str == '\"')
1134 error ("Name `%s' contains quotes", name);
1135 return name;
1138 /* Pointers to all declarations during IR generation are stored in the
1139 following. */
1140 static VEC(decl_t,heap) *decls;
1142 /* Given a pointer to a (char *) and a separator, return an alloc'ed
1143 string containing the next separated element, taking parentheses
1144 into account if PAR_FLAG has nonzero value. Advance the pointer to
1145 after the string scanned, or the end-of-string. Return NULL if at
1146 end of string. */
1147 static char *
1148 next_sep_el (const char **pstr, int sep, int par_flag)
1150 char *out_str;
1151 const char *p;
1152 int pars_num;
1153 int n_spaces;
1155 /* Remove leading whitespaces. */
1156 while (ISSPACE ((int) **pstr))
1157 (*pstr)++;
1159 if (**pstr == '\0')
1160 return NULL;
1162 n_spaces = 0;
1163 for (pars_num = 0, p = *pstr; *p != '\0'; p++)
1165 if (par_flag && *p == '(')
1166 pars_num++;
1167 else if (par_flag && *p == ')')
1168 pars_num--;
1169 else if (pars_num == 0 && *p == sep)
1170 break;
1171 if (pars_num == 0 && ISSPACE ((int) *p))
1172 n_spaces++;
1173 else
1175 for (; n_spaces != 0; n_spaces--)
1176 obstack_1grow (&irp, p [-n_spaces]);
1177 obstack_1grow (&irp, *p);
1180 obstack_1grow (&irp, '\0');
1181 out_str = obstack_base (&irp);
1182 obstack_finish (&irp);
1184 *pstr = p;
1185 if (**pstr == sep)
1186 (*pstr)++;
1188 return out_str;
1191 /* Given a string and a separator, return the number of separated
1192 elements in it, taking parentheses into account if PAR_FLAG has
1193 nonzero value. Return 0 for the null string, -1 if parentheses is
1194 not balanced. */
1195 static int
1196 n_sep_els (const char *s, int sep, int par_flag)
1198 int n;
1199 int pars_num;
1201 if (*s == '\0')
1202 return 0;
1204 for (pars_num = 0, n = 1; *s; s++)
1205 if (par_flag && *s == '(')
1206 pars_num++;
1207 else if (par_flag && *s == ')')
1208 pars_num--;
1209 else if (pars_num == 0 && *s == sep)
1210 n++;
1212 return (pars_num != 0 ? -1 : n);
1215 /* Given a string and a separator, return vector of strings which are
1216 elements in the string and number of elements through els_num.
1217 Take parentheses into account if PAREN_P has nonzero value. The
1218 function also inserts the end marker NULL at the end of vector.
1219 Return 0 for the null string, -1 if parentheses are not balanced. */
1220 static char **
1221 get_str_vect (const char *str, int *els_num, int sep, int paren_p)
1223 int i;
1224 char **vect;
1225 const char **pstr;
1226 char *trail;
1228 *els_num = n_sep_els (str, sep, paren_p);
1229 if (*els_num <= 0)
1230 return NULL;
1231 obstack_blank (&irp, sizeof (char *) * (*els_num + 1));
1232 vect = (char **) obstack_base (&irp);
1233 obstack_finish (&irp);
1234 pstr = &str;
1235 for (i = 0; i < *els_num; i++)
1236 vect [i] = next_sep_el (pstr, sep, paren_p);
1237 trail = next_sep_el (pstr, sep, paren_p);
1238 gcc_assert (!trail);
1239 vect [i] = NULL;
1240 return vect;
1243 /* Process a DEFINE_CPU_UNIT.
1245 This gives information about a unit contained in CPU. We fill a
1246 struct unit_decl with information used later by `expand_automata'. */
1247 static void
1248 gen_cpu_unit (rtx def)
1250 decl_t decl;
1251 char **str_cpu_units;
1252 int vect_length;
1253 int i;
1255 str_cpu_units = get_str_vect (XSTR (def, 0), &vect_length, ',', FALSE);
1256 if (str_cpu_units == NULL)
1257 fatal ("invalid string `%s' in define_cpu_unit", XSTR (def, 0));
1258 for (i = 0; i < vect_length; i++)
1260 decl = XCREATENODE (struct decl);
1261 decl->mode = dm_unit;
1262 decl->pos = 0;
1263 DECL_UNIT (decl)->name = check_name (str_cpu_units [i], decl->pos);
1264 DECL_UNIT (decl)->automaton_name = XSTR (def, 1);
1265 DECL_UNIT (decl)->query_p = 0;
1266 DECL_UNIT (decl)->min_occ_cycle_num = -1;
1267 DECL_UNIT (decl)->in_set_p = 0;
1268 VEC_safe_push (decl_t,heap, decls, decl);
1272 /* Process a DEFINE_QUERY_CPU_UNIT.
1274 This gives information about a unit contained in CPU. We fill a
1275 struct unit_decl with information used later by `expand_automata'. */
1276 static void
1277 gen_query_cpu_unit (rtx def)
1279 decl_t decl;
1280 char **str_cpu_units;
1281 int vect_length;
1282 int i;
1284 str_cpu_units = get_str_vect (XSTR (def, 0), &vect_length, ',',
1285 FALSE);
1286 if (str_cpu_units == NULL)
1287 fatal ("invalid string `%s' in define_query_cpu_unit", XSTR (def, 0));
1288 for (i = 0; i < vect_length; i++)
1290 decl = XCREATENODE (struct decl);
1291 decl->mode = dm_unit;
1292 decl->pos = 0;
1293 DECL_UNIT (decl)->name = check_name (str_cpu_units [i], decl->pos);
1294 DECL_UNIT (decl)->automaton_name = XSTR (def, 1);
1295 DECL_UNIT (decl)->query_p = 1;
1296 VEC_safe_push (decl_t,heap, decls, decl);
1300 /* Process a DEFINE_BYPASS.
1302 This gives information about a unit contained in the CPU. We fill
1303 in a struct bypass_decl with information used later by
1304 `expand_automata'. */
1305 static void
1306 gen_bypass (rtx def)
1308 decl_t decl;
1309 char **out_insns;
1310 int out_length;
1311 char **in_insns;
1312 int in_length;
1313 int i, j;
1315 out_insns = get_str_vect (XSTR (def, 1), &out_length, ',', FALSE);
1316 if (out_insns == NULL)
1317 fatal ("invalid string `%s' in define_bypass", XSTR (def, 1));
1318 in_insns = get_str_vect (XSTR (def, 2), &in_length, ',', FALSE);
1319 if (in_insns == NULL)
1320 fatal ("invalid string `%s' in define_bypass", XSTR (def, 2));
1321 for (i = 0; i < out_length; i++)
1322 for (j = 0; j < in_length; j++)
1324 decl = XCREATENODE (struct decl);
1325 decl->mode = dm_bypass;
1326 decl->pos = 0;
1327 DECL_BYPASS (decl)->latency = XINT (def, 0);
1328 DECL_BYPASS (decl)->out_insn_name = out_insns [i];
1329 DECL_BYPASS (decl)->in_insn_name = in_insns [j];
1330 DECL_BYPASS (decl)->bypass_guard_name = XSTR (def, 3);
1331 VEC_safe_push (decl_t,heap, decls, decl);
1335 /* Process an EXCLUSION_SET.
1337 This gives information about a cpu unit conflicts. We fill a
1338 struct excl_rel_decl (excl) with information used later by
1339 `expand_automata'. */
1340 static void
1341 gen_excl_set (rtx def)
1343 decl_t decl;
1344 char **first_str_cpu_units;
1345 char **second_str_cpu_units;
1346 int first_vect_length;
1347 int length;
1348 int i;
1350 first_str_cpu_units
1351 = get_str_vect (XSTR (def, 0), &first_vect_length, ',', FALSE);
1352 if (first_str_cpu_units == NULL)
1353 fatal ("invalid first string `%s' in exclusion_set", XSTR (def, 0));
1354 second_str_cpu_units = get_str_vect (XSTR (def, 1), &length, ',',
1355 FALSE);
1356 if (second_str_cpu_units == NULL)
1357 fatal ("invalid second string `%s' in exclusion_set", XSTR (def, 1));
1358 length += first_vect_length;
1359 decl = XCREATENODEVAR (struct decl, sizeof (struct decl) + (length - 1) * sizeof (char *));
1360 decl->mode = dm_excl;
1361 decl->pos = 0;
1362 DECL_EXCL (decl)->all_names_num = length;
1363 DECL_EXCL (decl)->first_list_length = first_vect_length;
1364 for (i = 0; i < length; i++)
1365 if (i < first_vect_length)
1366 DECL_EXCL (decl)->names [i] = first_str_cpu_units [i];
1367 else
1368 DECL_EXCL (decl)->names [i]
1369 = second_str_cpu_units [i - first_vect_length];
1370 VEC_safe_push (decl_t,heap, decls, decl);
1373 /* Process a PRESENCE_SET, a FINAL_PRESENCE_SET, an ABSENCE_SET,
1374 FINAL_ABSENCE_SET (it is depended on PRESENCE_P and FINAL_P).
1376 This gives information about a cpu unit reservation requirements.
1377 We fill a struct unit_pattern_rel_decl with information used later
1378 by `expand_automata'. */
1379 static void
1380 gen_presence_absence_set (rtx def, int presence_p, int final_p)
1382 decl_t decl;
1383 char **str_cpu_units;
1384 char **str_pattern_lists;
1385 char ***str_patterns;
1386 int cpu_units_length;
1387 int length;
1388 int patterns_length;
1389 int i;
1391 str_cpu_units = get_str_vect (XSTR (def, 0), &cpu_units_length, ',',
1392 FALSE);
1393 if (str_cpu_units == NULL)
1394 fatal ((presence_p
1395 ? (final_p
1396 ? "invalid first string `%s' in final_presence_set"
1397 : "invalid first string `%s' in presence_set")
1398 : (final_p
1399 ? "invalid first string `%s' in final_absence_set"
1400 : "invalid first string `%s' in absence_set")),
1401 XSTR (def, 0));
1402 str_pattern_lists = get_str_vect (XSTR (def, 1),
1403 &patterns_length, ',', FALSE);
1404 if (str_pattern_lists == NULL)
1405 fatal ((presence_p
1406 ? (final_p
1407 ? "invalid second string `%s' in final_presence_set"
1408 : "invalid second string `%s' in presence_set")
1409 : (final_p
1410 ? "invalid second string `%s' in final_absence_set"
1411 : "invalid second string `%s' in absence_set")), XSTR (def, 1));
1412 str_patterns = XOBNEWVEC (&irp, char **, patterns_length);
1413 for (i = 0; i < patterns_length; i++)
1415 str_patterns [i] = get_str_vect (str_pattern_lists [i],
1416 &length, ' ', FALSE);
1417 gcc_assert (str_patterns [i]);
1419 decl = XCREATENODE (struct decl);
1420 decl->pos = 0;
1421 if (presence_p)
1423 decl->mode = dm_presence;
1424 DECL_PRESENCE (decl)->names_num = cpu_units_length;
1425 DECL_PRESENCE (decl)->names = str_cpu_units;
1426 DECL_PRESENCE (decl)->patterns = str_patterns;
1427 DECL_PRESENCE (decl)->patterns_num = patterns_length;
1428 DECL_PRESENCE (decl)->final_p = final_p;
1430 else
1432 decl->mode = dm_absence;
1433 DECL_ABSENCE (decl)->names_num = cpu_units_length;
1434 DECL_ABSENCE (decl)->names = str_cpu_units;
1435 DECL_ABSENCE (decl)->patterns = str_patterns;
1436 DECL_ABSENCE (decl)->patterns_num = patterns_length;
1437 DECL_ABSENCE (decl)->final_p = final_p;
1439 VEC_safe_push (decl_t,heap, decls, decl);
1442 /* Process a PRESENCE_SET.
1444 This gives information about a cpu unit reservation requirements.
1445 We fill a struct unit_pattern_rel_decl (presence) with information
1446 used later by `expand_automata'. */
1447 static void
1448 gen_presence_set (rtx def)
1450 gen_presence_absence_set (def, TRUE, FALSE);
1453 /* Process a FINAL_PRESENCE_SET.
1455 This gives information about a cpu unit reservation requirements.
1456 We fill a struct unit_pattern_rel_decl (presence) with information
1457 used later by `expand_automata'. */
1458 static void
1459 gen_final_presence_set (rtx def)
1461 gen_presence_absence_set (def, TRUE, TRUE);
1464 /* Process an ABSENCE_SET.
1466 This gives information about a cpu unit reservation requirements.
1467 We fill a struct unit_pattern_rel_decl (absence) with information
1468 used later by `expand_automata'. */
1469 static void
1470 gen_absence_set (rtx def)
1472 gen_presence_absence_set (def, FALSE, FALSE);
1475 /* Process a FINAL_ABSENCE_SET.
1477 This gives information about a cpu unit reservation requirements.
1478 We fill a struct unit_pattern_rel_decl (absence) with information
1479 used later by `expand_automata'. */
1480 static void
1481 gen_final_absence_set (rtx def)
1483 gen_presence_absence_set (def, FALSE, TRUE);
1486 /* Process a DEFINE_AUTOMATON.
1488 This gives information about a finite state automaton used for
1489 recognizing pipeline hazards. We fill a struct automaton_decl
1490 with information used later by `expand_automata'. */
1491 static void
1492 gen_automaton (rtx def)
1494 decl_t decl;
1495 char **str_automata;
1496 int vect_length;
1497 int i;
1499 str_automata = get_str_vect (XSTR (def, 0), &vect_length, ',', FALSE);
1500 if (str_automata == NULL)
1501 fatal ("invalid string `%s' in define_automaton", XSTR (def, 0));
1502 for (i = 0; i < vect_length; i++)
1504 decl = XCREATENODE (struct decl);
1505 decl->mode = dm_automaton;
1506 decl->pos = 0;
1507 DECL_AUTOMATON (decl)->name = check_name (str_automata [i], decl->pos);
1508 VEC_safe_push (decl_t,heap, decls, decl);
1512 /* Process an AUTOMATA_OPTION.
1514 This gives information how to generate finite state automaton used
1515 for recognizing pipeline hazards. */
1516 static void
1517 gen_automata_option (rtx def)
1519 if (strcmp (XSTR (def, 0), NO_MINIMIZATION_OPTION + 1) == 0)
1520 no_minimization_flag = 1;
1521 else if (strcmp (XSTR (def, 0), TIME_OPTION + 1) == 0)
1522 time_flag = 1;
1523 else if (strcmp (XSTR (def, 0), STATS_OPTION + 1) == 0)
1524 stats_flag = 1;
1525 else if (strcmp (XSTR (def, 0), V_OPTION + 1) == 0)
1526 v_flag = 1;
1527 else if (strcmp (XSTR (def, 0), W_OPTION + 1) == 0)
1528 w_flag = 1;
1529 else if (strcmp (XSTR (def, 0), NDFA_OPTION + 1) == 0)
1530 ndfa_flag = 1;
1531 else if (strcmp (XSTR (def, 0), PROGRESS_OPTION + 1) == 0)
1532 progress_flag = 1;
1533 else
1534 fatal ("invalid option `%s' in automata_option", XSTR (def, 0));
1537 /* Name in reservation to denote absence reservation. */
1538 #define NOTHING_NAME "nothing"
1540 /* The following string contains original reservation string being
1541 parsed. */
1542 static const char *reserv_str;
1544 /* Parse an element in STR. */
1545 static regexp_t
1546 gen_regexp_el (const char *str)
1548 regexp_t regexp;
1549 char *dstr;
1550 int len;
1552 if (*str == '(')
1554 len = strlen (str);
1555 if (str [len - 1] != ')')
1556 fatal ("garbage after ) in reservation `%s'", reserv_str);
1557 dstr = XALLOCAVAR (char, len - 1);
1558 memcpy (dstr, str + 1, len - 2);
1559 dstr [len-2] = '\0';
1560 regexp = gen_regexp_sequence (dstr);
1562 else if (strcmp (str, NOTHING_NAME) == 0)
1564 regexp = XCREATENODE (struct regexp);
1565 regexp->mode = rm_nothing;
1567 else
1569 regexp = XCREATENODE (struct regexp);
1570 regexp->mode = rm_unit;
1571 REGEXP_UNIT (regexp)->name = str;
1573 return regexp;
1576 /* Parse construction `repeat' in STR. */
1577 static regexp_t
1578 gen_regexp_repeat (const char *str)
1580 regexp_t regexp;
1581 regexp_t repeat;
1582 char **repeat_vect;
1583 int els_num;
1584 int i;
1586 repeat_vect = get_str_vect (str, &els_num, '*', TRUE);
1587 if (repeat_vect == NULL)
1588 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1589 if (els_num > 1)
1591 regexp = gen_regexp_el (repeat_vect [0]);
1592 for (i = 1; i < els_num; i++)
1594 repeat = XCREATENODE (struct regexp);
1595 repeat->mode = rm_repeat;
1596 REGEXP_REPEAT (repeat)->regexp = regexp;
1597 REGEXP_REPEAT (repeat)->repeat_num = atoi (repeat_vect [i]);
1598 if (REGEXP_REPEAT (repeat)->repeat_num <= 1)
1599 fatal ("repetition `%s' <= 1 in reservation `%s'",
1600 str, reserv_str);
1601 regexp = repeat;
1603 return regexp;
1605 else
1606 return gen_regexp_el (str);
1609 /* Parse reservation STR which possibly contains separator '+'. */
1610 static regexp_t
1611 gen_regexp_allof (const char *str)
1613 regexp_t allof;
1614 char **allof_vect;
1615 int els_num;
1616 int i;
1618 allof_vect = get_str_vect (str, &els_num, '+', TRUE);
1619 if (allof_vect == NULL)
1620 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1621 if (els_num > 1)
1623 allof = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
1624 + sizeof (regexp_t) * (els_num - 1));
1625 allof->mode = rm_allof;
1626 REGEXP_ALLOF (allof)->regexps_num = els_num;
1627 for (i = 0; i < els_num; i++)
1628 REGEXP_ALLOF (allof)->regexps [i] = gen_regexp_repeat (allof_vect [i]);
1629 return allof;
1631 else
1632 return gen_regexp_repeat (str);
1635 /* Parse reservation STR which possibly contains separator '|'. */
1636 static regexp_t
1637 gen_regexp_oneof (const char *str)
1639 regexp_t oneof;
1640 char **oneof_vect;
1641 int els_num;
1642 int i;
1644 oneof_vect = get_str_vect (str, &els_num, '|', TRUE);
1645 if (oneof_vect == NULL)
1646 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1647 if (els_num > 1)
1649 oneof = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
1650 + sizeof (regexp_t) * (els_num - 1));
1651 oneof->mode = rm_oneof;
1652 REGEXP_ONEOF (oneof)->regexps_num = els_num;
1653 for (i = 0; i < els_num; i++)
1654 REGEXP_ONEOF (oneof)->regexps [i] = gen_regexp_allof (oneof_vect [i]);
1655 return oneof;
1657 else
1658 return gen_regexp_allof (str);
1661 /* Parse reservation STR which possibly contains separator ','. */
1662 static regexp_t
1663 gen_regexp_sequence (const char *str)
1665 regexp_t sequence;
1666 char **sequence_vect;
1667 int els_num;
1668 int i;
1670 sequence_vect = get_str_vect (str, &els_num, ',', TRUE);
1671 if (els_num > 1)
1673 sequence = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
1674 + sizeof (regexp_t) * (els_num - 1));
1675 sequence->mode = rm_sequence;
1676 REGEXP_SEQUENCE (sequence)->regexps_num = els_num;
1677 for (i = 0; i < els_num; i++)
1678 REGEXP_SEQUENCE (sequence)->regexps [i]
1679 = gen_regexp_oneof (sequence_vect [i]);
1680 return sequence;
1682 else
1683 return gen_regexp_oneof (str);
1686 /* Parse construction reservation STR. */
1687 static regexp_t
1688 gen_regexp (const char *str)
1690 reserv_str = str;
1691 return gen_regexp_sequence (str);;
1694 /* Process a DEFINE_RESERVATION.
1696 This gives information about a reservation of cpu units. We fill
1697 in a struct reserv_decl with information used later by
1698 `expand_automata'. */
1699 static void
1700 gen_reserv (rtx def)
1702 decl_t decl;
1704 decl = XCREATENODE (struct decl);
1705 decl->mode = dm_reserv;
1706 decl->pos = 0;
1707 DECL_RESERV (decl)->name = check_name (XSTR (def, 0), decl->pos);
1708 DECL_RESERV (decl)->regexp = gen_regexp (XSTR (def, 1));
1709 VEC_safe_push (decl_t,heap, decls, decl);
1712 /* Process a DEFINE_INSN_RESERVATION.
1714 This gives information about the reservation of cpu units by an
1715 insn. We fill a struct insn_reserv_decl with information used
1716 later by `expand_automata'. */
1717 static void
1718 gen_insn_reserv (rtx def)
1720 decl_t decl;
1722 decl = XCREATENODE (struct decl);
1723 decl->mode = dm_insn_reserv;
1724 decl->pos = 0;
1725 DECL_INSN_RESERV (decl)->name
1726 = check_name (XSTR (def, 0), decl->pos);
1727 DECL_INSN_RESERV (decl)->default_latency = XINT (def, 1);
1728 DECL_INSN_RESERV (decl)->condexp = XEXP (def, 2);
1729 DECL_INSN_RESERV (decl)->regexp = gen_regexp (XSTR (def, 3));
1730 VEC_safe_push (decl_t,heap, decls, decl);
1735 /* The function evaluates hash value (0..UINT_MAX) of string. */
1736 static unsigned
1737 string_hash (const char *string)
1739 unsigned result, i;
1741 for (result = i = 0;*string++ != '\0'; i++)
1742 result += ((unsigned char) *string << (i % CHAR_BIT));
1743 return result;
1748 /* This page contains abstract data `table of automaton declarations'.
1749 Elements of the table is nodes representing automaton declarations.
1750 Key of the table elements is name of given automaton. Remember
1751 that automaton names have own space. */
1753 /* The function evaluates hash value of an automaton declaration. The
1754 function is used by abstract data `hashtab'. The function returns
1755 hash value (0..UINT_MAX) of given automaton declaration. */
1756 static hashval_t
1757 automaton_decl_hash (const void *automaton_decl)
1759 const_decl_t const decl = (const_decl_t) automaton_decl;
1761 gcc_assert (decl->mode != dm_automaton
1762 || DECL_AUTOMATON (decl)->name);
1763 return string_hash (DECL_AUTOMATON (decl)->name);
1766 /* The function tests automaton declarations on equality of their
1767 keys. The function is used by abstract data `hashtab'. The
1768 function returns 1 if the declarations have the same key, 0
1769 otherwise. */
1770 static int
1771 automaton_decl_eq_p (const void* automaton_decl_1,
1772 const void* automaton_decl_2)
1774 const_decl_t const decl1 = (const_decl_t) automaton_decl_1;
1775 const_decl_t const decl2 = (const_decl_t) automaton_decl_2;
1777 gcc_assert (decl1->mode == dm_automaton
1778 && DECL_AUTOMATON (decl1)->name
1779 && decl2->mode == dm_automaton
1780 && DECL_AUTOMATON (decl2)->name);
1781 return strcmp (DECL_AUTOMATON (decl1)->name,
1782 DECL_AUTOMATON (decl2)->name) == 0;
1785 /* The automaton declaration table itself is represented by the
1786 following variable. */
1787 static htab_t automaton_decl_table;
1789 /* The function inserts automaton declaration into the table. The
1790 function does nothing if an automaton declaration with the same key
1791 exists already in the table. The function returns automaton
1792 declaration node in the table with the same key as given automaton
1793 declaration node. */
1794 static decl_t
1795 insert_automaton_decl (decl_t automaton_decl)
1797 void **entry_ptr;
1799 entry_ptr = htab_find_slot (automaton_decl_table, automaton_decl, 1);
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, 1);
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, 1);
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
2318 (0, "unit `%s' excludes and requires presence of `%s'",
2319 dst->unit_decl->name, unit->name);
2322 else if (pat->units_num == 1)
2323 for (curr_pat_el = dst->unit_decl->presence_list;
2324 curr_pat_el != NULL;
2325 curr_pat_el = curr_pat_el->next_pattern_set_el)
2326 if (curr_pat_el->units_num == 1
2327 && unit == curr_pat_el->unit_decls [0])
2329 if (!w_flag)
2331 error
2332 ("unit `%s' requires absence and presence of `%s'",
2333 dst->unit_decl->name, unit->name);
2334 no_error_flag = 0;
2336 else
2337 warning
2338 (0, "unit `%s' requires absence and presence of `%s'",
2339 dst->unit_decl->name, unit->name);
2341 if (no_error_flag)
2343 for (prev_el = (presence_p
2344 ? (final_p
2345 ? dst->unit_decl->final_presence_list
2346 : dst->unit_decl->final_presence_list)
2347 : (final_p
2348 ? dst->unit_decl->final_absence_list
2349 : dst->unit_decl->absence_list));
2350 prev_el != NULL && prev_el->next_pattern_set_el != NULL;
2351 prev_el = prev_el->next_pattern_set_el)
2353 copy = XCOPYNODE (struct pattern_set_el, pat);
2354 copy->next_pattern_set_el = NULL;
2355 if (prev_el == NULL)
2357 if (presence_p)
2359 if (final_p)
2360 dst->unit_decl->final_presence_list = copy;
2361 else
2362 dst->unit_decl->presence_list = copy;
2364 else if (final_p)
2365 dst->unit_decl->final_absence_list = copy;
2366 else
2367 dst->unit_decl->absence_list = copy;
2369 else
2370 prev_el->next_pattern_set_el = copy;
2377 /* The function inserts BYPASS in the list of bypasses of the
2378 corresponding output insn. The order of bypasses in the list is
2379 decribed in a comment for member `bypass_list' (see above). If
2380 there is already the same bypass in the list the function reports
2381 this and does nothing. */
2382 static void
2383 insert_bypass (struct bypass_decl *bypass)
2385 struct bypass_decl *curr, *last;
2386 struct insn_reserv_decl *out_insn_reserv = bypass->out_insn_reserv;
2387 struct insn_reserv_decl *in_insn_reserv = bypass->in_insn_reserv;
2389 for (curr = out_insn_reserv->bypass_list, last = NULL;
2390 curr != NULL;
2391 last = curr, curr = curr->next)
2392 if (curr->in_insn_reserv == in_insn_reserv)
2394 if ((bypass->bypass_guard_name != NULL
2395 && curr->bypass_guard_name != NULL
2396 && ! strcmp (bypass->bypass_guard_name, curr->bypass_guard_name))
2397 || bypass->bypass_guard_name == curr->bypass_guard_name)
2399 if (bypass->bypass_guard_name == NULL)
2401 if (!w_flag)
2402 error ("the same bypass `%s - %s' is already defined",
2403 bypass->out_insn_name, bypass->in_insn_name);
2404 else
2405 warning (0, "the same bypass `%s - %s' is already defined",
2406 bypass->out_insn_name, bypass->in_insn_name);
2408 else if (!w_flag)
2409 error ("the same bypass `%s - %s' (guard %s) is already defined",
2410 bypass->out_insn_name, bypass->in_insn_name,
2411 bypass->bypass_guard_name);
2412 else
2413 warning
2414 (0, "the same bypass `%s - %s' (guard %s) is already defined",
2415 bypass->out_insn_name, bypass->in_insn_name,
2416 bypass->bypass_guard_name);
2417 return;
2419 if (curr->bypass_guard_name == NULL)
2420 break;
2421 if (curr->next == NULL || curr->next->in_insn_reserv != in_insn_reserv)
2423 last = curr;
2424 break;
2428 if (last == NULL)
2430 bypass->next = out_insn_reserv->bypass_list;
2431 out_insn_reserv->bypass_list = bypass;
2433 else
2435 bypass->next = last->next;
2436 last->next = bypass;
2440 /* The function processes pipeline description declarations, checks
2441 their correctness, and forms exclusion/presence/absence sets. */
2442 static void
2443 process_decls (void)
2445 decl_t decl;
2446 decl_t automaton_decl;
2447 decl_t decl_in_table;
2448 decl_t out_insn_reserv;
2449 decl_t in_insn_reserv;
2450 int automaton_presence;
2451 int i;
2453 /* Checking repeated automata declarations. */
2454 automaton_presence = 0;
2455 for (i = 0; i < description->decls_num; i++)
2457 decl = description->decls [i];
2458 if (decl->mode == dm_automaton)
2460 automaton_presence = 1;
2461 decl_in_table = insert_automaton_decl (decl);
2462 if (decl_in_table != decl)
2464 if (!w_flag)
2465 error ("repeated declaration of automaton `%s'",
2466 DECL_AUTOMATON (decl)->name);
2467 else
2468 warning (0, "repeated declaration of automaton `%s'",
2469 DECL_AUTOMATON (decl)->name);
2473 /* Checking undeclared automata, repeated declarations (except for
2474 automata) and correctness of their attributes (insn latency times
2475 etc.). */
2476 for (i = 0; i < description->decls_num; i++)
2478 decl = description->decls [i];
2479 if (decl->mode == dm_insn_reserv)
2481 if (DECL_INSN_RESERV (decl)->default_latency < 0)
2482 error ("define_insn_reservation `%s' has negative latency time",
2483 DECL_INSN_RESERV (decl)->name);
2484 DECL_INSN_RESERV (decl)->insn_num = description->insns_num;
2485 description->insns_num++;
2486 decl_in_table = insert_insn_decl (decl);
2487 if (decl_in_table != decl)
2488 error ("`%s' is already used as insn reservation name",
2489 DECL_INSN_RESERV (decl)->name);
2491 else if (decl->mode == dm_bypass)
2493 if (DECL_BYPASS (decl)->latency < 0)
2494 error ("define_bypass `%s - %s' has negative latency time",
2495 DECL_BYPASS (decl)->out_insn_name,
2496 DECL_BYPASS (decl)->in_insn_name);
2498 else if (decl->mode == dm_unit || decl->mode == dm_reserv)
2500 if (decl->mode == dm_unit)
2502 DECL_UNIT (decl)->automaton_decl = NULL;
2503 if (DECL_UNIT (decl)->automaton_name != NULL)
2505 automaton_decl
2506 = find_automaton_decl (DECL_UNIT (decl)->automaton_name);
2507 if (automaton_decl == NULL)
2508 error ("automaton `%s' is not declared",
2509 DECL_UNIT (decl)->automaton_name);
2510 else
2512 DECL_AUTOMATON (automaton_decl)->automaton_is_used = 1;
2513 DECL_UNIT (decl)->automaton_decl
2514 = DECL_AUTOMATON (automaton_decl);
2517 else if (automaton_presence)
2518 error ("define_unit `%s' without automaton when one defined",
2519 DECL_UNIT (decl)->name);
2520 DECL_UNIT (decl)->unit_num = description->units_num;
2521 description->units_num++;
2522 if (strcmp (DECL_UNIT (decl)->name, NOTHING_NAME) == 0)
2524 error ("`%s' is declared as cpu unit", NOTHING_NAME);
2525 continue;
2527 decl_in_table = find_decl (DECL_UNIT (decl)->name);
2529 else
2531 if (strcmp (DECL_RESERV (decl)->name, NOTHING_NAME) == 0)
2533 error ("`%s' is declared as cpu reservation", NOTHING_NAME);
2534 continue;
2536 decl_in_table = find_decl (DECL_RESERV (decl)->name);
2538 if (decl_in_table == NULL)
2539 decl_in_table = insert_decl (decl);
2540 else
2542 if (decl->mode == dm_unit)
2543 error ("repeated declaration of unit `%s'",
2544 DECL_UNIT (decl)->name);
2545 else
2546 error ("repeated declaration of reservation `%s'",
2547 DECL_RESERV (decl)->name);
2551 /* Check bypasses and form list of bypasses for each (output)
2552 insn. */
2553 for (i = 0; i < description->decls_num; i++)
2555 decl = description->decls [i];
2556 if (decl->mode == dm_bypass)
2558 out_insn_reserv = find_insn_decl (DECL_BYPASS (decl)->out_insn_name);
2559 in_insn_reserv = find_insn_decl (DECL_BYPASS (decl)->in_insn_name);
2560 if (out_insn_reserv == NULL)
2561 error ("there is no insn reservation `%s'",
2562 DECL_BYPASS (decl)->out_insn_name);
2563 else if (in_insn_reserv == NULL)
2564 error ("there is no insn reservation `%s'",
2565 DECL_BYPASS (decl)->in_insn_name);
2566 else
2568 DECL_BYPASS (decl)->out_insn_reserv
2569 = DECL_INSN_RESERV (out_insn_reserv);
2570 DECL_BYPASS (decl)->in_insn_reserv
2571 = DECL_INSN_RESERV (in_insn_reserv);
2572 insert_bypass (DECL_BYPASS (decl));
2577 /* Check exclusion set declarations and form exclusion sets. */
2578 for (i = 0; i < description->decls_num; i++)
2580 decl = description->decls [i];
2581 if (decl->mode == dm_excl)
2583 unit_set_el_t unit_set_el_list;
2584 unit_set_el_t unit_set_el_list_2;
2586 unit_set_el_list
2587 = process_excls (DECL_EXCL (decl)->names,
2588 DECL_EXCL (decl)->first_list_length, decl->pos);
2589 unit_set_el_list_2
2590 = process_excls (&DECL_EXCL (decl)->names
2591 [DECL_EXCL (decl)->first_list_length],
2592 DECL_EXCL (decl)->all_names_num
2593 - DECL_EXCL (decl)->first_list_length,
2594 decl->pos);
2595 add_excls (unit_set_el_list, unit_set_el_list_2, decl->pos);
2596 add_excls (unit_set_el_list_2, unit_set_el_list, decl->pos);
2600 /* Check presence set declarations and form presence sets. */
2601 for (i = 0; i < description->decls_num; i++)
2603 decl = description->decls [i];
2604 if (decl->mode == dm_presence)
2606 unit_set_el_t unit_set_el_list;
2607 pattern_set_el_t pattern_set_el_list;
2609 unit_set_el_list
2610 = process_presence_absence_names
2611 (DECL_PRESENCE (decl)->names, DECL_PRESENCE (decl)->names_num,
2612 decl->pos, TRUE, DECL_PRESENCE (decl)->final_p);
2613 pattern_set_el_list
2614 = process_presence_absence_patterns
2615 (DECL_PRESENCE (decl)->patterns,
2616 DECL_PRESENCE (decl)->patterns_num,
2617 decl->pos, TRUE, DECL_PRESENCE (decl)->final_p);
2618 add_presence_absence (unit_set_el_list, pattern_set_el_list,
2619 decl->pos, TRUE,
2620 DECL_PRESENCE (decl)->final_p);
2624 /* Check absence set declarations and form absence sets. */
2625 for (i = 0; i < description->decls_num; i++)
2627 decl = description->decls [i];
2628 if (decl->mode == dm_absence)
2630 unit_set_el_t unit_set_el_list;
2631 pattern_set_el_t pattern_set_el_list;
2633 unit_set_el_list
2634 = process_presence_absence_names
2635 (DECL_ABSENCE (decl)->names, DECL_ABSENCE (decl)->names_num,
2636 decl->pos, FALSE, DECL_ABSENCE (decl)->final_p);
2637 pattern_set_el_list
2638 = process_presence_absence_patterns
2639 (DECL_ABSENCE (decl)->patterns,
2640 DECL_ABSENCE (decl)->patterns_num,
2641 decl->pos, FALSE, DECL_ABSENCE (decl)->final_p);
2642 add_presence_absence (unit_set_el_list, pattern_set_el_list,
2643 decl->pos, FALSE,
2644 DECL_ABSENCE (decl)->final_p);
2649 /* The following function checks that declared automaton is used. If
2650 the automaton is not used, the function fixes error/warning. The
2651 following function must be called only after `process_decls'. */
2652 static void
2653 check_automaton_usage (void)
2655 decl_t decl;
2656 int i;
2658 for (i = 0; i < description->decls_num; i++)
2660 decl = description->decls [i];
2661 if (decl->mode == dm_automaton
2662 && !DECL_AUTOMATON (decl)->automaton_is_used)
2664 if (!w_flag)
2665 error ("automaton `%s' is not used", DECL_AUTOMATON (decl)->name);
2666 else
2667 warning (0, "automaton `%s' is not used",
2668 DECL_AUTOMATON (decl)->name);
2673 /* The following recursive function processes all regexp in order to
2674 fix usage of units or reservations and to fix errors of undeclared
2675 name. The function may change unit_regexp onto reserv_regexp.
2676 Remember that reserv_regexp does not exist before the function
2677 call. */
2678 static regexp_t
2679 process_regexp (regexp_t regexp)
2681 decl_t decl_in_table;
2682 regexp_t new_regexp;
2683 int i;
2685 switch (regexp->mode)
2687 case rm_unit:
2688 decl_in_table = find_decl (REGEXP_UNIT (regexp)->name);
2689 if (decl_in_table == NULL)
2690 error ("undeclared unit or reservation `%s'",
2691 REGEXP_UNIT (regexp)->name);
2692 else
2693 switch (decl_in_table->mode)
2695 case dm_unit:
2696 DECL_UNIT (decl_in_table)->unit_is_used = 1;
2697 REGEXP_UNIT (regexp)->unit_decl = DECL_UNIT (decl_in_table);
2698 break;
2700 case dm_reserv:
2701 DECL_RESERV (decl_in_table)->reserv_is_used = 1;
2702 new_regexp = XCREATENODE (struct regexp);
2703 new_regexp->mode = rm_reserv;
2704 new_regexp->pos = regexp->pos;
2705 REGEXP_RESERV (new_regexp)->name = REGEXP_UNIT (regexp)->name;
2706 REGEXP_RESERV (new_regexp)->reserv_decl
2707 = DECL_RESERV (decl_in_table);
2708 regexp = new_regexp;
2709 break;
2711 default:
2712 gcc_unreachable ();
2714 break;
2715 case rm_sequence:
2716 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
2717 REGEXP_SEQUENCE (regexp)->regexps [i]
2718 = process_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
2719 break;
2720 case rm_allof:
2721 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
2722 REGEXP_ALLOF (regexp)->regexps [i]
2723 = process_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
2724 break;
2725 case rm_oneof:
2726 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
2727 REGEXP_ONEOF (regexp)->regexps [i]
2728 = process_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
2729 break;
2730 case rm_repeat:
2731 REGEXP_REPEAT (regexp)->regexp
2732 = process_regexp (REGEXP_REPEAT (regexp)->regexp);
2733 break;
2734 case rm_nothing:
2735 break;
2736 default:
2737 gcc_unreachable ();
2739 return regexp;
2742 /* The following function processes regexp of define_reservation and
2743 define_insn_reservation with the aid of function
2744 `process_regexp'. */
2745 static void
2746 process_regexp_decls (void)
2748 decl_t decl;
2749 int i;
2751 for (i = 0; i < description->decls_num; i++)
2753 decl = description->decls [i];
2754 if (decl->mode == dm_reserv)
2755 DECL_RESERV (decl)->regexp
2756 = process_regexp (DECL_RESERV (decl)->regexp);
2757 else if (decl->mode == dm_insn_reserv)
2758 DECL_INSN_RESERV (decl)->regexp
2759 = process_regexp (DECL_INSN_RESERV (decl)->regexp);
2763 /* The following function checks that declared unit is used. If the
2764 unit is not used, the function fixes errors/warnings. The
2765 following function must be called only after `process_decls',
2766 `process_regexp_decls'. */
2767 static void
2768 check_usage (void)
2770 decl_t decl;
2771 int i;
2773 for (i = 0; i < description->decls_num; i++)
2775 decl = description->decls [i];
2776 if (decl->mode == dm_unit && !DECL_UNIT (decl)->unit_is_used)
2778 if (!w_flag)
2779 error ("unit `%s' is not used", DECL_UNIT (decl)->name);
2780 else
2781 warning (0, "unit `%s' is not used", DECL_UNIT (decl)->name);
2783 else if (decl->mode == dm_reserv && !DECL_RESERV (decl)->reserv_is_used)
2785 if (!w_flag)
2786 error ("reservation `%s' is not used", DECL_RESERV (decl)->name);
2787 else
2788 warning (0, "reservation `%s' is not used", DECL_RESERV (decl)->name);
2793 /* The following variable value is number of reservation being
2794 processed on loop recognition. */
2795 static int curr_loop_pass_num;
2797 /* The following recursive function returns nonzero value if REGEXP
2798 contains given decl or reservations in given regexp refers for
2799 given decl. */
2800 static int
2801 loop_in_regexp (regexp_t regexp, decl_t start_decl)
2803 int i;
2805 if (regexp == NULL)
2806 return 0;
2807 switch (regexp->mode)
2809 case rm_unit:
2810 return 0;
2812 case rm_reserv:
2813 if (start_decl->mode == dm_reserv
2814 && REGEXP_RESERV (regexp)->reserv_decl == DECL_RESERV (start_decl))
2815 return 1;
2816 else if (REGEXP_RESERV (regexp)->reserv_decl->loop_pass_num
2817 == curr_loop_pass_num)
2818 /* declaration has been processed. */
2819 return 0;
2820 else
2822 REGEXP_RESERV (regexp)->reserv_decl->loop_pass_num
2823 = curr_loop_pass_num;
2824 return loop_in_regexp (REGEXP_RESERV (regexp)->reserv_decl->regexp,
2825 start_decl);
2828 case rm_sequence:
2829 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
2830 if (loop_in_regexp (REGEXP_SEQUENCE (regexp)->regexps [i], start_decl))
2831 return 1;
2832 return 0;
2834 case rm_allof:
2835 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
2836 if (loop_in_regexp (REGEXP_ALLOF (regexp)->regexps [i], start_decl))
2837 return 1;
2838 return 0;
2840 case rm_oneof:
2841 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
2842 if (loop_in_regexp (REGEXP_ONEOF (regexp)->regexps [i], start_decl))
2843 return 1;
2844 return 0;
2846 case rm_repeat:
2847 return loop_in_regexp (REGEXP_REPEAT (regexp)->regexp, start_decl);
2849 case rm_nothing:
2850 return 0;
2852 default:
2853 gcc_unreachable ();
2857 /* The following function fixes errors "cycle in definition ...". The
2858 function uses function `loop_in_regexp' for that. */
2859 static void
2860 check_loops_in_regexps (void)
2862 decl_t decl;
2863 int i;
2865 for (i = 0; i < description->decls_num; i++)
2867 decl = description->decls [i];
2868 if (decl->mode == dm_reserv)
2869 DECL_RESERV (decl)->loop_pass_num = 0;
2871 for (i = 0; i < description->decls_num; i++)
2873 decl = description->decls [i];
2874 curr_loop_pass_num = i;
2876 if (decl->mode == dm_reserv)
2878 DECL_RESERV (decl)->loop_pass_num = curr_loop_pass_num;
2879 if (loop_in_regexp (DECL_RESERV (decl)->regexp, decl))
2881 gcc_assert (DECL_RESERV (decl)->regexp);
2882 error ("cycle in definition of reservation `%s'",
2883 DECL_RESERV (decl)->name);
2889 /* The function recursively processes IR of reservation and defines
2890 max and min cycle for reservation of unit. */
2891 static void
2892 process_regexp_cycles (regexp_t regexp, int max_start_cycle,
2893 int min_start_cycle, int *max_finish_cycle,
2894 int *min_finish_cycle)
2896 int i;
2898 switch (regexp->mode)
2900 case rm_unit:
2901 if (REGEXP_UNIT (regexp)->unit_decl->max_occ_cycle_num < max_start_cycle)
2902 REGEXP_UNIT (regexp)->unit_decl->max_occ_cycle_num = max_start_cycle;
2903 if (REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num > min_start_cycle
2904 || REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num == -1)
2905 REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num = min_start_cycle;
2906 *max_finish_cycle = max_start_cycle;
2907 *min_finish_cycle = min_start_cycle;
2908 break;
2910 case rm_reserv:
2911 process_regexp_cycles (REGEXP_RESERV (regexp)->reserv_decl->regexp,
2912 max_start_cycle, min_start_cycle,
2913 max_finish_cycle, min_finish_cycle);
2914 break;
2916 case rm_repeat:
2917 for (i = 0; i < REGEXP_REPEAT (regexp)->repeat_num; i++)
2919 process_regexp_cycles (REGEXP_REPEAT (regexp)->regexp,
2920 max_start_cycle, min_start_cycle,
2921 max_finish_cycle, min_finish_cycle);
2922 max_start_cycle = *max_finish_cycle + 1;
2923 min_start_cycle = *min_finish_cycle + 1;
2925 break;
2927 case rm_sequence:
2928 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
2930 process_regexp_cycles (REGEXP_SEQUENCE (regexp)->regexps [i],
2931 max_start_cycle, min_start_cycle,
2932 max_finish_cycle, min_finish_cycle);
2933 max_start_cycle = *max_finish_cycle + 1;
2934 min_start_cycle = *min_finish_cycle + 1;
2936 break;
2938 case rm_allof:
2940 int max_cycle = 0;
2941 int min_cycle = 0;
2943 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
2945 process_regexp_cycles (REGEXP_ALLOF (regexp)->regexps [i],
2946 max_start_cycle, min_start_cycle,
2947 max_finish_cycle, min_finish_cycle);
2948 if (max_cycle < *max_finish_cycle)
2949 max_cycle = *max_finish_cycle;
2950 if (i == 0 || min_cycle > *min_finish_cycle)
2951 min_cycle = *min_finish_cycle;
2953 *max_finish_cycle = max_cycle;
2954 *min_finish_cycle = min_cycle;
2956 break;
2958 case rm_oneof:
2960 int max_cycle = 0;
2961 int min_cycle = 0;
2963 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
2965 process_regexp_cycles (REGEXP_ONEOF (regexp)->regexps [i],
2966 max_start_cycle, min_start_cycle,
2967 max_finish_cycle, min_finish_cycle);
2968 if (max_cycle < *max_finish_cycle)
2969 max_cycle = *max_finish_cycle;
2970 if (i == 0 || min_cycle > *min_finish_cycle)
2971 min_cycle = *min_finish_cycle;
2973 *max_finish_cycle = max_cycle;
2974 *min_finish_cycle = min_cycle;
2976 break;
2978 case rm_nothing:
2979 *max_finish_cycle = max_start_cycle;
2980 *min_finish_cycle = min_start_cycle;
2981 break;
2983 default:
2984 gcc_unreachable ();
2988 /* The following function is called only for correct program. The
2989 function defines max reservation of insns in cycles. */
2990 static void
2991 evaluate_max_reserv_cycles (void)
2993 int max_insn_cycles_num;
2994 int min_insn_cycles_num;
2995 decl_t decl;
2996 int i;
2998 description->max_insn_reserv_cycles = 0;
2999 for (i = 0; i < description->decls_num; i++)
3001 decl = description->decls [i];
3002 if (decl->mode == dm_insn_reserv)
3004 process_regexp_cycles (DECL_INSN_RESERV (decl)->regexp, 0, 0,
3005 &max_insn_cycles_num, &min_insn_cycles_num);
3006 if (description->max_insn_reserv_cycles < max_insn_cycles_num)
3007 description->max_insn_reserv_cycles = max_insn_cycles_num;
3010 description->max_insn_reserv_cycles++;
3013 /* The following function calls functions for checking all
3014 description. */
3015 static void
3016 check_all_description (void)
3018 process_decls ();
3019 check_automaton_usage ();
3020 process_regexp_decls ();
3021 check_usage ();
3022 check_loops_in_regexps ();
3023 if (!have_error)
3024 evaluate_max_reserv_cycles ();
3029 /* The page contains abstract data `ticker'. This data is used to
3030 report time of different phases of building automata. It is
3031 possibly to write a description for which automata will be built
3032 during several minutes even on fast machine. */
3034 /* The following function creates ticker and makes it active. */
3035 static ticker_t
3036 create_ticker (void)
3038 ticker_t ticker;
3040 ticker.modified_creation_time = get_run_time ();
3041 ticker.incremented_off_time = 0;
3042 return ticker;
3045 /* The following function switches off given ticker. */
3046 static void
3047 ticker_off (ticker_t *ticker)
3049 if (ticker->incremented_off_time == 0)
3050 ticker->incremented_off_time = get_run_time () + 1;
3053 /* The following function switches on given ticker. */
3054 static void
3055 ticker_on (ticker_t *ticker)
3057 if (ticker->incremented_off_time != 0)
3059 ticker->modified_creation_time
3060 += get_run_time () - ticker->incremented_off_time + 1;
3061 ticker->incremented_off_time = 0;
3065 /* The following function returns current time in milliseconds since
3066 the moment when given ticker was created. */
3067 static int
3068 active_time (ticker_t ticker)
3070 if (ticker.incremented_off_time != 0)
3071 return ticker.incremented_off_time - 1 - ticker.modified_creation_time;
3072 else
3073 return get_run_time () - ticker.modified_creation_time;
3076 /* The following function returns string representation of active time
3077 of given ticker. The result is string representation of seconds
3078 with accuracy of 1/100 second. Only result of the last call of the
3079 function exists. Therefore the following code is not correct
3081 printf ("parser time: %s\ngeneration time: %s\n",
3082 active_time_string (parser_ticker),
3083 active_time_string (generation_ticker));
3085 Correct code has to be the following
3087 printf ("parser time: %s\n", active_time_string (parser_ticker));
3088 printf ("generation time: %s\n",
3089 active_time_string (generation_ticker));
3092 static void
3093 print_active_time (FILE *f, ticker_t ticker)
3095 int msecs;
3097 msecs = active_time (ticker);
3098 fprintf (f, "%d.%06d", msecs / 1000000, msecs % 1000000);
3103 /* The following variable value is number of automaton which are
3104 really being created. This value is defined on the base of
3105 argument of option `-split'. If the variable has zero value the
3106 number of automata is defined by the constructions `%automaton'.
3107 This case occurs when option `-split' is absent or has zero
3108 argument. If constructions `define_automaton' is absent only one
3109 automaton is created. */
3110 static int automata_num;
3112 /* The following variable values are times of
3113 o transformation of regular expressions
3114 o building NDFA (DFA if !ndfa_flag)
3115 o NDFA -> DFA (simply the same automaton if !ndfa_flag)
3116 o DFA minimization
3117 o building insn equivalence classes
3118 o all previous ones
3119 o code output */
3120 static ticker_t transform_time;
3121 static ticker_t NDFA_time;
3122 static ticker_t NDFA_to_DFA_time;
3123 static ticker_t minimize_time;
3124 static ticker_t equiv_time;
3125 static ticker_t automaton_generation_time;
3126 static ticker_t output_time;
3128 /* The following variable values are times of
3129 all checking
3130 all generation
3131 all pipeline hazard translator work */
3132 static ticker_t check_time;
3133 static ticker_t generation_time;
3134 static ticker_t all_time;
3138 /* Pseudo insn decl which denotes advancing cycle. */
3139 static decl_t advance_cycle_insn_decl;
3140 static void
3141 add_advance_cycle_insn_decl (void)
3143 advance_cycle_insn_decl = XCREATENODE (struct decl);
3144 advance_cycle_insn_decl->mode = dm_insn_reserv;
3145 advance_cycle_insn_decl->pos = no_pos;
3146 DECL_INSN_RESERV (advance_cycle_insn_decl)->regexp = NULL;
3147 DECL_INSN_RESERV (advance_cycle_insn_decl)->name = "$advance_cycle";
3148 DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num
3149 = description->insns_num;
3150 description->decls [description->decls_num] = advance_cycle_insn_decl;
3151 description->decls_num++;
3152 description->insns_num++;
3156 /* Abstract data `alternative states' which represents
3157 nondeterministic nature of the description (see comments for
3158 structures alt_state and state). */
3160 /* List of free states. */
3161 static alt_state_t first_free_alt_state;
3163 #ifndef NDEBUG
3164 /* The following variables is maximal number of allocated nodes
3165 alt_state. */
3166 static int allocated_alt_states_num = 0;
3167 #endif
3169 /* The following function returns free node alt_state. It may be new
3170 allocated node or node freed earlier. */
3171 static alt_state_t
3172 get_free_alt_state (void)
3174 alt_state_t result;
3176 if (first_free_alt_state != NULL)
3178 result = first_free_alt_state;
3179 first_free_alt_state = first_free_alt_state->next_alt_state;
3181 else
3183 #ifndef NDEBUG
3184 allocated_alt_states_num++;
3185 #endif
3186 result = XCREATENODE (struct alt_state);
3188 result->state = NULL;
3189 result->next_alt_state = NULL;
3190 result->next_sorted_alt_state = NULL;
3191 return result;
3194 /* The function frees node ALT_STATE. */
3195 static void
3196 free_alt_state (alt_state_t alt_state)
3198 if (alt_state == NULL)
3199 return;
3200 alt_state->next_alt_state = first_free_alt_state;
3201 first_free_alt_state = alt_state;
3204 /* The function frees list started with node ALT_STATE_LIST. */
3205 static void
3206 free_alt_states (alt_state_t alt_states_list)
3208 alt_state_t curr_alt_state;
3209 alt_state_t next_alt_state;
3211 for (curr_alt_state = alt_states_list;
3212 curr_alt_state != NULL;
3213 curr_alt_state = next_alt_state)
3215 next_alt_state = curr_alt_state->next_alt_state;
3216 free_alt_state (curr_alt_state);
3220 /* The function compares unique numbers of alt states. */
3221 static int
3222 alt_state_cmp (const void *alt_state_ptr_1, const void *alt_state_ptr_2)
3224 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 0;
3227 else if ((*(const alt_state_t *) alt_state_ptr_1)->state->unique_num
3228 < (*(const alt_state_t *) alt_state_ptr_2)->state->unique_num)
3229 return -1;
3230 else
3231 return 1;
3234 /* The function sorts ALT_STATES_LIST and removes duplicated alt
3235 states from the list. The comparison key is alt state unique
3236 number. */
3238 static alt_state_t
3239 uniq_sort_alt_states (alt_state_t alt_states_list)
3241 alt_state_t curr_alt_state;
3242 VEC(alt_state_t,heap) *alt_states;
3243 size_t i;
3244 size_t prev_unique_state_ind;
3245 alt_state_t result;
3247 if (alt_states_list == 0)
3248 return 0;
3249 if (alt_states_list->next_alt_state == 0)
3250 return alt_states_list;
3252 alt_states = VEC_alloc (alt_state_t,heap, 150);
3253 for (curr_alt_state = alt_states_list;
3254 curr_alt_state != NULL;
3255 curr_alt_state = curr_alt_state->next_alt_state)
3256 VEC_safe_push (alt_state_t,heap, alt_states, curr_alt_state);
3258 qsort (VEC_address (alt_state_t, alt_states),
3259 VEC_length (alt_state_t, alt_states),
3260 sizeof (alt_state_t), alt_state_cmp);
3262 prev_unique_state_ind = 0;
3263 for (i = 1; i < VEC_length (alt_state_t, alt_states); i++)
3264 if (VEC_index (alt_state_t, alt_states, prev_unique_state_ind)->state
3265 != VEC_index (alt_state_t, alt_states, i)->state)
3267 prev_unique_state_ind++;
3268 VEC_replace (alt_state_t, alt_states, prev_unique_state_ind,
3269 VEC_index (alt_state_t, alt_states, i));
3271 VEC_truncate (alt_state_t, alt_states, prev_unique_state_ind + 1);
3273 for (i = 1; i < VEC_length (alt_state_t, alt_states); i++)
3274 VEC_index (alt_state_t, alt_states, i-1)->next_sorted_alt_state
3275 = VEC_index (alt_state_t, alt_states, i);
3276 VEC_last (alt_state_t, alt_states)->next_sorted_alt_state = 0;
3278 result = VEC_index (alt_state_t, alt_states, 0);
3280 VEC_free (alt_state_t,heap, alt_states);
3281 return result;
3284 /* The function checks equality of alt state lists. Remember that the
3285 lists must be already sorted by the previous function. */
3286 static int
3287 alt_states_eq (alt_state_t alt_states_1, alt_state_t alt_states_2)
3289 while (alt_states_1 != NULL && alt_states_2 != NULL
3290 && alt_state_cmp (&alt_states_1, &alt_states_2) == 0)
3292 alt_states_1 = alt_states_1->next_sorted_alt_state;
3293 alt_states_2 = alt_states_2->next_sorted_alt_state;
3295 return alt_states_1 == alt_states_2;
3298 /* Initialization of the abstract data. */
3299 static void
3300 initiate_alt_states (void)
3302 first_free_alt_state = NULL;
3305 /* Finishing work with the abstract data. */
3306 static void
3307 finish_alt_states (void)
3313 /* The page contains macros for work with bits strings. We could use
3314 standard gcc bitmap or sbitmap but it would result in difficulties
3315 of building canadian cross. */
3317 /* Set bit number bitno in the bit string. The macro is not side
3318 effect proof. */
3319 #define SET_BIT(bitstring, bitno) \
3320 (((char *) (bitstring)) [(bitno) / CHAR_BIT] |= 1 << (bitno) % CHAR_BIT)
3322 #define CLEAR_BIT(bitstring, bitno) \
3323 (((char *) (bitstring)) [(bitno) / CHAR_BIT] &= ~(1 << (bitno) % CHAR_BIT))
3325 /* Test if bit number bitno in the bitstring is set. The macro is not
3326 side effect proof. */
3327 #define TEST_BIT(bitstring, bitno) \
3328 (((char *) (bitstring)) [(bitno) / CHAR_BIT] >> (bitno) % CHAR_BIT & 1)
3332 /* This page contains abstract data `state'. */
3334 /* Maximal length of reservations in cycles (>= 1). */
3335 static int max_cycles_num;
3337 /* Number of set elements (see type set_el_t) needed for
3338 representation of one cycle reservation. It is depended on units
3339 number. */
3340 static int els_in_cycle_reserv;
3342 /* Number of set elements (see type set_el_t) needed for
3343 representation of maximal length reservation. Deterministic
3344 reservation is stored as set (bit string) of length equal to the
3345 variable value * number of bits in set_el_t. */
3346 static int els_in_reservs;
3348 /* Array of pointers to unit declarations. */
3349 static unit_decl_t *units_array;
3351 /* Temporary reservation of maximal length. */
3352 static reserv_sets_t temp_reserv;
3354 /* The state table itself is represented by the following variable. */
3355 static htab_t state_table;
3357 /* Linked list of free 'state' structures to be recycled. The
3358 next_equiv_class_state pointer is borrowed for a free list. */
3359 static state_t first_free_state;
3361 static int curr_unique_state_num;
3363 #ifndef NDEBUG
3364 /* The following variables is maximal number of allocated nodes
3365 `state'. */
3366 static int allocated_states_num = 0;
3367 #endif
3369 /* Allocate new reservation set. */
3370 static reserv_sets_t
3371 alloc_empty_reserv_sets (void)
3373 reserv_sets_t result;
3375 obstack_blank (&irp, els_in_reservs * sizeof (set_el_t));
3376 result = (reserv_sets_t) obstack_base (&irp);
3377 obstack_finish (&irp);
3378 memset (result, 0, els_in_reservs * sizeof (set_el_t));
3379 return result;
3382 /* Hash value of reservation set. */
3383 static unsigned
3384 reserv_sets_hash_value (reserv_sets_t reservs)
3386 set_el_t hash_value;
3387 unsigned result;
3388 int reservs_num, i;
3389 set_el_t *reserv_ptr;
3391 hash_value = 0;
3392 reservs_num = els_in_reservs;
3393 reserv_ptr = reservs;
3394 i = 0;
3395 while (reservs_num != 0)
3397 reservs_num--;
3398 hash_value += ((*reserv_ptr >> i)
3399 | (*reserv_ptr << (sizeof (set_el_t) * CHAR_BIT - i)));
3400 i++;
3401 if (i == sizeof (set_el_t) * CHAR_BIT)
3402 i = 0;
3403 reserv_ptr++;
3405 if (sizeof (set_el_t) <= sizeof (unsigned))
3406 return hash_value;
3407 result = 0;
3408 for (i = sizeof (set_el_t); i > 0; i -= sizeof (unsigned) - 1)
3410 result += (unsigned) hash_value;
3411 hash_value >>= (sizeof (unsigned) - 1) * CHAR_BIT;
3413 return result;
3416 /* Comparison of given reservation sets. */
3417 static int
3418 reserv_sets_cmp (const_reserv_sets_t reservs_1, const_reserv_sets_t reservs_2)
3420 int reservs_num;
3421 const set_el_t *reserv_ptr_1;
3422 const set_el_t *reserv_ptr_2;
3424 gcc_assert (reservs_1 && reservs_2);
3425 reservs_num = els_in_reservs;
3426 reserv_ptr_1 = reservs_1;
3427 reserv_ptr_2 = reservs_2;
3428 while (reservs_num != 0 && *reserv_ptr_1 == *reserv_ptr_2)
3430 reservs_num--;
3431 reserv_ptr_1++;
3432 reserv_ptr_2++;
3434 if (reservs_num == 0)
3435 return 0;
3436 else if (*reserv_ptr_1 < *reserv_ptr_2)
3437 return -1;
3438 else
3439 return 1;
3442 /* The function checks equality of the reservation sets. */
3443 static int
3444 reserv_sets_eq (const_reserv_sets_t reservs_1, const_reserv_sets_t reservs_2)
3446 return reserv_sets_cmp (reservs_1, reservs_2) == 0;
3449 /* Set up in the reservation set that unit with UNIT_NUM is used on
3450 CYCLE_NUM. */
3451 static void
3452 set_unit_reserv (reserv_sets_t reservs, int cycle_num, int unit_num)
3454 gcc_assert (cycle_num < max_cycles_num);
3455 SET_BIT (reservs, cycle_num * els_in_cycle_reserv
3456 * sizeof (set_el_t) * CHAR_BIT + unit_num);
3459 /* Set up in the reservation set RESERVS that unit with UNIT_NUM is
3460 used on CYCLE_NUM. */
3461 static int
3462 test_unit_reserv (reserv_sets_t reservs, int cycle_num, int unit_num)
3464 gcc_assert (cycle_num < max_cycles_num);
3465 return TEST_BIT (reservs, cycle_num * els_in_cycle_reserv
3466 * sizeof (set_el_t) * CHAR_BIT + unit_num);
3469 /* The function checks that the reservation sets are intersected,
3470 i.e. there is a unit reservation on a cycle in both reservation
3471 sets. */
3472 static int
3473 reserv_sets_are_intersected (reserv_sets_t operand_1,
3474 reserv_sets_t operand_2)
3476 set_el_t *el_ptr_1;
3477 set_el_t *el_ptr_2;
3478 set_el_t *cycle_ptr_1;
3479 set_el_t *cycle_ptr_2;
3481 gcc_assert (operand_1 && operand_2);
3482 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2;
3483 el_ptr_1 < operand_1 + els_in_reservs;
3484 el_ptr_1++, el_ptr_2++)
3485 if (*el_ptr_1 & *el_ptr_2)
3486 return 1;
3487 reserv_sets_or (temp_reserv, operand_1, operand_2);
3488 for (cycle_ptr_1 = operand_1, cycle_ptr_2 = operand_2;
3489 cycle_ptr_1 < operand_1 + els_in_reservs;
3490 cycle_ptr_1 += els_in_cycle_reserv, cycle_ptr_2 += els_in_cycle_reserv)
3492 for (el_ptr_1 = cycle_ptr_1, el_ptr_2 = get_excl_set (cycle_ptr_2);
3493 el_ptr_1 < cycle_ptr_1 + els_in_cycle_reserv;
3494 el_ptr_1++, el_ptr_2++)
3495 if (*el_ptr_1 & *el_ptr_2)
3496 return 1;
3497 if (!check_presence_pattern_sets (cycle_ptr_1, cycle_ptr_2, FALSE))
3498 return 1;
3499 if (!check_presence_pattern_sets (temp_reserv + (cycle_ptr_2
3500 - operand_2),
3501 cycle_ptr_2, TRUE))
3502 return 1;
3503 if (!check_absence_pattern_sets (cycle_ptr_1, cycle_ptr_2, FALSE))
3504 return 1;
3505 if (!check_absence_pattern_sets (temp_reserv + (cycle_ptr_2 - operand_2),
3506 cycle_ptr_2, TRUE))
3507 return 1;
3509 return 0;
3512 /* The function sets up RESULT bits by bits of OPERAND shifted on one
3513 cpu cycle. The remaining bits of OPERAND (representing the last
3514 cycle unit reservations) are not changed. */
3515 static void
3516 reserv_sets_shift (reserv_sets_t result, reserv_sets_t operand)
3518 int i;
3520 gcc_assert (result && operand && result != operand);
3521 for (i = els_in_cycle_reserv; i < els_in_reservs; i++)
3522 result [i - els_in_cycle_reserv] = operand [i];
3525 /* OR of the reservation sets. */
3526 static void
3527 reserv_sets_or (reserv_sets_t result, reserv_sets_t operand_1,
3528 reserv_sets_t operand_2)
3530 set_el_t *el_ptr_1;
3531 set_el_t *el_ptr_2;
3532 set_el_t *result_set_el_ptr;
3534 gcc_assert (result && operand_1 && operand_2);
3535 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2, result_set_el_ptr = result;
3536 el_ptr_1 < operand_1 + els_in_reservs;
3537 el_ptr_1++, el_ptr_2++, result_set_el_ptr++)
3538 *result_set_el_ptr = *el_ptr_1 | *el_ptr_2;
3541 /* AND of the reservation sets. */
3542 static void
3543 reserv_sets_and (reserv_sets_t result, reserv_sets_t operand_1,
3544 reserv_sets_t operand_2)
3546 set_el_t *el_ptr_1;
3547 set_el_t *el_ptr_2;
3548 set_el_t *result_set_el_ptr;
3550 gcc_assert (result && operand_1 && operand_2);
3551 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2, result_set_el_ptr = result;
3552 el_ptr_1 < operand_1 + els_in_reservs;
3553 el_ptr_1++, el_ptr_2++, result_set_el_ptr++)
3554 *result_set_el_ptr = *el_ptr_1 & *el_ptr_2;
3557 /* The function outputs string representation of units reservation on
3558 cycle START_CYCLE in the reservation set. The function uses repeat
3559 construction if REPETITION_NUM > 1. */
3560 static void
3561 output_cycle_reservs (FILE *f, reserv_sets_t reservs, int start_cycle,
3562 int repetition_num)
3564 int unit_num;
3565 int reserved_units_num;
3567 reserved_units_num = 0;
3568 for (unit_num = 0; unit_num < description->units_num; unit_num++)
3569 if (TEST_BIT (reservs, start_cycle * els_in_cycle_reserv
3570 * sizeof (set_el_t) * CHAR_BIT + unit_num))
3571 reserved_units_num++;
3572 gcc_assert (repetition_num > 0);
3573 if (repetition_num != 1 && reserved_units_num > 1)
3574 fprintf (f, "(");
3575 reserved_units_num = 0;
3576 for (unit_num = 0;
3577 unit_num < description->units_num;
3578 unit_num++)
3579 if (TEST_BIT (reservs, start_cycle * els_in_cycle_reserv
3580 * sizeof (set_el_t) * CHAR_BIT + unit_num))
3582 if (reserved_units_num != 0)
3583 fprintf (f, "+");
3584 reserved_units_num++;
3585 fprintf (f, "%s", units_array [unit_num]->name);
3587 if (reserved_units_num == 0)
3588 fprintf (f, NOTHING_NAME);
3589 gcc_assert (repetition_num > 0);
3590 if (repetition_num != 1 && reserved_units_num > 1)
3591 fprintf (f, ")");
3592 if (repetition_num != 1)
3593 fprintf (f, "*%d", repetition_num);
3596 /* The function outputs string representation of units reservation in
3597 the reservation set. */
3598 static void
3599 output_reserv_sets (FILE *f, reserv_sets_t reservs)
3601 int start_cycle = 0;
3602 int cycle;
3603 int repetition_num;
3605 repetition_num = 0;
3606 for (cycle = 0; cycle < max_cycles_num; cycle++)
3607 if (repetition_num == 0)
3609 repetition_num++;
3610 start_cycle = cycle;
3612 else if (memcmp
3613 ((char *) reservs + start_cycle * els_in_cycle_reserv
3614 * sizeof (set_el_t),
3615 (char *) reservs + cycle * els_in_cycle_reserv
3616 * sizeof (set_el_t),
3617 els_in_cycle_reserv * sizeof (set_el_t)) == 0)
3618 repetition_num++;
3619 else
3621 if (start_cycle != 0)
3622 fprintf (f, ", ");
3623 output_cycle_reservs (f, reservs, start_cycle, repetition_num);
3624 repetition_num = 1;
3625 start_cycle = cycle;
3627 if (start_cycle < max_cycles_num)
3629 if (start_cycle != 0)
3630 fprintf (f, ", ");
3631 output_cycle_reservs (f, reservs, start_cycle, repetition_num);
3635 /* The following function returns free node state for AUTOMATON. It
3636 may be new allocated node or node freed earlier. The function also
3637 allocates reservation set if WITH_RESERVS has nonzero value. */
3638 static state_t
3639 get_free_state (int with_reservs, automaton_t automaton)
3641 state_t result;
3643 gcc_assert (max_cycles_num > 0 && automaton);
3644 if (first_free_state)
3646 result = first_free_state;
3647 first_free_state = result->next_equiv_class_state;
3649 result->next_equiv_class_state = NULL;
3650 result->automaton = automaton;
3651 result->first_out_arc = NULL;
3652 result->it_was_placed_in_stack_for_NDFA_forming = 0;
3653 result->it_was_placed_in_stack_for_DFA_forming = 0;
3654 result->component_states = NULL;
3656 else
3658 #ifndef NDEBUG
3659 allocated_states_num++;
3660 #endif
3661 result = XCREATENODE (struct state);
3662 result->automaton = automaton;
3663 result->first_out_arc = NULL;
3664 result->unique_num = curr_unique_state_num;
3665 curr_unique_state_num++;
3667 if (with_reservs)
3669 if (result->reservs == NULL)
3670 result->reservs = alloc_empty_reserv_sets ();
3671 else
3672 memset (result->reservs, 0, els_in_reservs * sizeof (set_el_t));
3674 return result;
3677 /* The function frees node STATE. */
3678 static void
3679 free_state (state_t state)
3681 free_alt_states (state->component_states);
3682 state->next_equiv_class_state = first_free_state;
3683 first_free_state = state;
3686 /* Hash value of STATE. If STATE represents deterministic state it is
3687 simply hash value of the corresponding reservation set. Otherwise
3688 it is formed from hash values of the component deterministic
3689 states. One more key is order number of state automaton. */
3690 static hashval_t
3691 state_hash (const void *state)
3693 unsigned int hash_value;
3694 alt_state_t alt_state;
3696 if (((const_state_t) state)->component_states == NULL)
3697 hash_value = reserv_sets_hash_value (((const_state_t) state)->reservs);
3698 else
3700 hash_value = 0;
3701 for (alt_state = ((const_state_t) state)->component_states;
3702 alt_state != NULL;
3703 alt_state = alt_state->next_sorted_alt_state)
3704 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
3705 | (hash_value << CHAR_BIT))
3706 + alt_state->state->unique_num);
3708 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
3709 | (hash_value << CHAR_BIT))
3710 + ((const_state_t) state)->automaton->automaton_order_num);
3711 return hash_value;
3714 /* Return nonzero value if the states are the same. */
3715 static int
3716 state_eq_p (const void *state_1, const void *state_2)
3718 alt_state_t alt_state_1;
3719 alt_state_t alt_state_2;
3721 if (((const_state_t) state_1)->automaton != ((const_state_t) state_2)->automaton)
3722 return 0;
3723 else if (((const_state_t) state_1)->component_states == NULL
3724 && ((const_state_t) state_2)->component_states == NULL)
3725 return reserv_sets_eq (((const_state_t) state_1)->reservs,
3726 ((const_state_t) state_2)->reservs);
3727 else if (((const_state_t) state_1)->component_states != NULL
3728 && ((const_state_t) state_2)->component_states != NULL)
3730 for (alt_state_1 = ((const_state_t) state_1)->component_states,
3731 alt_state_2 = ((const_state_t) state_2)->component_states;
3732 alt_state_1 != NULL && alt_state_2 != NULL;
3733 alt_state_1 = alt_state_1->next_sorted_alt_state,
3734 alt_state_2 = alt_state_2->next_sorted_alt_state)
3735 /* All state in the list must be already in the hash table.
3736 Also the lists must be sorted. */
3737 if (alt_state_1->state != alt_state_2->state)
3738 return 0;
3739 return alt_state_1 == alt_state_2;
3741 else
3742 return 0;
3745 /* Insert STATE into the state table. */
3746 static state_t
3747 insert_state (state_t state)
3749 void **entry_ptr;
3751 entry_ptr = htab_find_slot (state_table, (void *) state, 1);
3752 if (*entry_ptr == NULL)
3753 *entry_ptr = (void *) state;
3754 return (state_t) *entry_ptr;
3757 /* Add reservation of unit with UNIT_NUM on cycle CYCLE_NUM to
3758 deterministic STATE. */
3759 static void
3760 set_state_reserv (state_t state, int cycle_num, int unit_num)
3762 set_unit_reserv (state->reservs, cycle_num, unit_num);
3765 /* Return nonzero value if the deterministic states contains a
3766 reservation of the same cpu unit on the same cpu cycle. */
3767 static int
3768 intersected_state_reservs_p (state_t state1, state_t state2)
3770 gcc_assert (state1->automaton == state2->automaton);
3771 return reserv_sets_are_intersected (state1->reservs, state2->reservs);
3774 /* Return deterministic state (inserted into the table) which
3775 representing the automaton state which is union of reservations of
3776 the deterministic states masked by RESERVS. */
3777 static state_t
3778 states_union (state_t state1, state_t state2, reserv_sets_t reservs)
3780 state_t result;
3781 state_t state_in_table;
3783 gcc_assert (state1->automaton == state2->automaton);
3784 result = get_free_state (1, state1->automaton);
3785 reserv_sets_or (result->reservs, state1->reservs, state2->reservs);
3786 reserv_sets_and (result->reservs, result->reservs, reservs);
3787 state_in_table = insert_state (result);
3788 if (result != state_in_table)
3790 free_state (result);
3791 result = state_in_table;
3793 return result;
3796 /* Return deterministic state (inserted into the table) which
3797 represent the automaton state is obtained from deterministic STATE
3798 by advancing cpu cycle and masking by RESERVS. */
3799 static state_t
3800 state_shift (state_t state, reserv_sets_t reservs)
3802 state_t result;
3803 state_t state_in_table;
3805 result = get_free_state (1, state->automaton);
3806 reserv_sets_shift (result->reservs, state->reservs);
3807 reserv_sets_and (result->reservs, result->reservs, reservs);
3808 state_in_table = insert_state (result);
3809 if (result != state_in_table)
3811 free_state (result);
3812 result = state_in_table;
3814 return result;
3817 /* Initialization of the abstract data. */
3818 static void
3819 initiate_states (void)
3821 decl_t decl;
3822 int i;
3824 if (description->units_num)
3825 units_array = XNEWVEC (unit_decl_t, description->units_num);
3826 else
3827 units_array = 0;
3829 for (i = 0; i < description->decls_num; i++)
3831 decl = description->decls [i];
3832 if (decl->mode == dm_unit)
3833 units_array [DECL_UNIT (decl)->unit_num] = DECL_UNIT (decl);
3835 max_cycles_num = description->max_insn_reserv_cycles;
3836 els_in_cycle_reserv
3837 = ((description->units_num + sizeof (set_el_t) * CHAR_BIT - 1)
3838 / (sizeof (set_el_t) * CHAR_BIT));
3839 els_in_reservs = els_in_cycle_reserv * max_cycles_num;
3840 curr_unique_state_num = 0;
3841 initiate_alt_states ();
3842 state_table = htab_create (1500, state_hash, state_eq_p, (htab_del) 0);
3843 temp_reserv = alloc_empty_reserv_sets ();
3846 /* Finishing work with the abstract data. */
3847 static void
3848 finish_states (void)
3850 free (units_array);
3851 units_array = 0;
3852 htab_delete (state_table);
3853 first_free_state = NULL;
3854 finish_alt_states ();
3859 /* Abstract data `arcs'. */
3861 /* List of free arcs. */
3862 static arc_t first_free_arc;
3864 #ifndef NDEBUG
3865 /* The following variables is maximal number of allocated nodes
3866 `arc'. */
3867 static int allocated_arcs_num = 0;
3868 #endif
3870 /* The function frees node ARC. */
3871 static void
3872 free_arc (arc_t arc)
3874 arc->next_out_arc = first_free_arc;
3875 first_free_arc = arc;
3878 /* The function removes and frees ARC staring from FROM_STATE. */
3879 static void
3880 remove_arc (state_t from_state, arc_t arc)
3882 arc_t prev_arc;
3883 arc_t curr_arc;
3885 gcc_assert (arc);
3886 for (prev_arc = NULL, curr_arc = from_state->first_out_arc;
3887 curr_arc != NULL;
3888 prev_arc = curr_arc, curr_arc = curr_arc->next_out_arc)
3889 if (curr_arc == arc)
3890 break;
3891 gcc_assert (curr_arc);
3892 if (prev_arc == NULL)
3893 from_state->first_out_arc = arc->next_out_arc;
3894 else
3895 prev_arc->next_out_arc = arc->next_out_arc;
3896 from_state->num_out_arcs--;
3897 free_arc (arc);
3900 /* The functions returns arc with given characteristics (or NULL if
3901 the arc does not exist). */
3902 static arc_t
3903 find_arc (state_t from_state, state_t to_state, ainsn_t insn)
3905 arc_t arc;
3907 for (arc = first_out_arc (from_state); arc != NULL; arc = next_out_arc (arc))
3908 if (arc->to_state == to_state && arc->insn == insn)
3909 return arc;
3910 return NULL;
3913 /* The function adds arc from FROM_STATE to TO_STATE marked by AINSN.
3914 The function returns added arc (or already existing arc). */
3915 static arc_t
3916 add_arc (state_t from_state, state_t to_state, ainsn_t ainsn)
3918 arc_t new_arc;
3920 new_arc = find_arc (from_state, to_state, ainsn);
3921 if (new_arc != NULL)
3922 return new_arc;
3923 if (first_free_arc == NULL)
3925 #ifndef NDEBUG
3926 allocated_arcs_num++;
3927 #endif
3928 new_arc = XCREATENODE (struct arc);
3929 new_arc->to_state = NULL;
3930 new_arc->insn = NULL;
3931 new_arc->next_out_arc = NULL;
3933 else
3935 new_arc = first_free_arc;
3936 first_free_arc = first_free_arc->next_out_arc;
3938 new_arc->to_state = to_state;
3939 new_arc->insn = ainsn;
3940 ainsn->arc_exists_p = 1;
3941 new_arc->next_out_arc = from_state->first_out_arc;
3942 from_state->first_out_arc = new_arc;
3943 from_state->num_out_arcs++;
3944 new_arc->next_arc_marked_by_insn = NULL;
3945 return new_arc;
3948 /* The function returns the first arc starting from STATE. */
3949 static arc_t
3950 first_out_arc (const_state_t state)
3952 return state->first_out_arc;
3955 /* The function returns next out arc after ARC. */
3956 static arc_t
3957 next_out_arc (arc_t arc)
3959 return arc->next_out_arc;
3962 /* Initialization of the abstract data. */
3963 static void
3964 initiate_arcs (void)
3966 first_free_arc = NULL;
3969 /* Finishing work with the abstract data. */
3970 static void
3971 finish_arcs (void)
3977 /* Abstract data `automata lists'. */
3979 /* List of free states. */
3980 static automata_list_el_t first_free_automata_list_el;
3982 /* The list being formed. */
3983 static automata_list_el_t current_automata_list;
3985 /* Hash table of automata lists. */
3986 static htab_t automata_list_table;
3988 /* The following function returns free automata list el. It may be
3989 new allocated node or node freed earlier. */
3990 static automata_list_el_t
3991 get_free_automata_list_el (void)
3993 automata_list_el_t result;
3995 if (first_free_automata_list_el != NULL)
3997 result = first_free_automata_list_el;
3998 first_free_automata_list_el
3999 = first_free_automata_list_el->next_automata_list_el;
4001 else
4002 result = XCREATENODE (struct automata_list_el);
4003 result->automaton = NULL;
4004 result->next_automata_list_el = NULL;
4005 return result;
4008 /* The function frees node AUTOMATA_LIST_EL. */
4009 static void
4010 free_automata_list_el (automata_list_el_t automata_list_el)
4012 if (automata_list_el == NULL)
4013 return;
4014 automata_list_el->next_automata_list_el = first_free_automata_list_el;
4015 first_free_automata_list_el = automata_list_el;
4018 /* The function frees list AUTOMATA_LIST. */
4019 static void
4020 free_automata_list (automata_list_el_t automata_list)
4022 automata_list_el_t curr_automata_list_el;
4023 automata_list_el_t next_automata_list_el;
4025 for (curr_automata_list_el = automata_list;
4026 curr_automata_list_el != NULL;
4027 curr_automata_list_el = next_automata_list_el)
4029 next_automata_list_el = curr_automata_list_el->next_automata_list_el;
4030 free_automata_list_el (curr_automata_list_el);
4034 /* Hash value of AUTOMATA_LIST. */
4035 static hashval_t
4036 automata_list_hash (const void *automata_list)
4038 unsigned int hash_value;
4039 const_automata_list_el_t curr_automata_list_el;
4041 hash_value = 0;
4042 for (curr_automata_list_el = (const_automata_list_el_t) automata_list;
4043 curr_automata_list_el != NULL;
4044 curr_automata_list_el = curr_automata_list_el->next_automata_list_el)
4045 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
4046 | (hash_value << CHAR_BIT))
4047 + curr_automata_list_el->automaton->automaton_order_num);
4048 return hash_value;
4051 /* Return nonzero value if the automata_lists are the same. */
4052 static int
4053 automata_list_eq_p (const void *automata_list_1, const void *automata_list_2)
4055 const_automata_list_el_t automata_list_el_1;
4056 const_automata_list_el_t automata_list_el_2;
4058 for (automata_list_el_1 = (const_automata_list_el_t) automata_list_1,
4059 automata_list_el_2 = (const_automata_list_el_t) automata_list_2;
4060 automata_list_el_1 != NULL && automata_list_el_2 != NULL;
4061 automata_list_el_1 = automata_list_el_1->next_automata_list_el,
4062 automata_list_el_2 = automata_list_el_2->next_automata_list_el)
4063 if (automata_list_el_1->automaton != automata_list_el_2->automaton)
4064 return 0;
4065 return automata_list_el_1 == automata_list_el_2;
4068 /* Initialization of the abstract data. */
4069 static void
4070 initiate_automata_lists (void)
4072 first_free_automata_list_el = NULL;
4073 automata_list_table = htab_create (1500, automata_list_hash,
4074 automata_list_eq_p, (htab_del) 0);
4077 /* The following function starts new automata list and makes it the
4078 current one. */
4079 static void
4080 automata_list_start (void)
4082 current_automata_list = NULL;
4085 /* The following function adds AUTOMATON to the current list. */
4086 static void
4087 automata_list_add (automaton_t automaton)
4089 automata_list_el_t el;
4091 el = get_free_automata_list_el ();
4092 el->automaton = automaton;
4093 el->next_automata_list_el = current_automata_list;
4094 current_automata_list = el;
4097 /* The following function finishes forming the current list, inserts
4098 it into the table and returns it. */
4099 static automata_list_el_t
4100 automata_list_finish (void)
4102 void **entry_ptr;
4104 if (current_automata_list == NULL)
4105 return NULL;
4106 entry_ptr = htab_find_slot (automata_list_table,
4107 (void *) current_automata_list, 1);
4108 if (*entry_ptr == NULL)
4109 *entry_ptr = (void *) current_automata_list;
4110 else
4111 free_automata_list (current_automata_list);
4112 current_automata_list = NULL;
4113 return (automata_list_el_t) *entry_ptr;
4116 /* Finishing work with the abstract data. */
4117 static void
4118 finish_automata_lists (void)
4120 htab_delete (automata_list_table);
4125 /* The page contains abstract data for work with exclusion sets (see
4126 exclusion_set in file rtl.def). */
4128 /* The following variable refers to an exclusion set returned by
4129 get_excl_set. This is bit string of length equal to cpu units
4130 number. If exclusion set for given unit contains 1 for a unit,
4131 then simultaneous reservation of the units is prohibited. */
4132 static reserv_sets_t excl_set;
4134 /* The array contains exclusion sets for each unit. */
4135 static reserv_sets_t *unit_excl_set_table;
4137 /* The following function forms the array containing exclusion sets
4138 for each unit. */
4139 static void
4140 initiate_excl_sets (void)
4142 decl_t decl;
4143 reserv_sets_t unit_excl_set;
4144 unit_set_el_t el;
4145 int i;
4147 obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4148 excl_set = (reserv_sets_t) obstack_base (&irp);
4149 obstack_finish (&irp);
4150 obstack_blank (&irp, description->units_num * sizeof (reserv_sets_t));
4151 unit_excl_set_table = (reserv_sets_t *) obstack_base (&irp);
4152 obstack_finish (&irp);
4153 /* Evaluate unit exclusion sets. */
4154 for (i = 0; i < description->decls_num; i++)
4156 decl = description->decls [i];
4157 if (decl->mode == dm_unit)
4159 obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4160 unit_excl_set = (reserv_sets_t) obstack_base (&irp);
4161 obstack_finish (&irp);
4162 memset (unit_excl_set, 0, els_in_cycle_reserv * sizeof (set_el_t));
4163 for (el = DECL_UNIT (decl)->excl_list;
4164 el != NULL;
4165 el = el->next_unit_set_el)
4167 SET_BIT (unit_excl_set, el->unit_decl->unit_num);
4168 el->unit_decl->in_set_p = TRUE;
4170 unit_excl_set_table [DECL_UNIT (decl)->unit_num] = unit_excl_set;
4175 /* The function sets up and return EXCL_SET which is union of
4176 exclusion sets for each unit in IN_SET. */
4177 static reserv_sets_t
4178 get_excl_set (reserv_sets_t in_set)
4180 int excl_char_num;
4181 int chars_num;
4182 int i;
4183 int start_unit_num;
4184 int unit_num;
4186 chars_num = els_in_cycle_reserv * sizeof (set_el_t);
4187 memset (excl_set, 0, chars_num);
4188 for (excl_char_num = 0; excl_char_num < chars_num; excl_char_num++)
4189 if (((unsigned char *) in_set) [excl_char_num])
4190 for (i = CHAR_BIT - 1; i >= 0; i--)
4191 if ((((unsigned char *) in_set) [excl_char_num] >> i) & 1)
4193 start_unit_num = excl_char_num * CHAR_BIT + i;
4194 if (start_unit_num >= description->units_num)
4195 return excl_set;
4196 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4198 excl_set [unit_num]
4199 |= unit_excl_set_table [start_unit_num] [unit_num];
4202 return excl_set;
4207 /* The page contains abstract data for work with presence/absence
4208 pattern sets (see presence_set/absence_set in file rtl.def). */
4210 /* The following arrays contain correspondingly presence, final
4211 presence, absence, and final absence patterns for each unit. */
4212 static pattern_reserv_t *unit_presence_set_table;
4213 static pattern_reserv_t *unit_final_presence_set_table;
4214 static pattern_reserv_t *unit_absence_set_table;
4215 static pattern_reserv_t *unit_final_absence_set_table;
4217 /* The following function forms list of reservation sets for given
4218 PATTERN_LIST. */
4219 static pattern_reserv_t
4220 form_reserv_sets_list (pattern_set_el_t pattern_list)
4222 pattern_set_el_t el;
4223 pattern_reserv_t first, curr, prev;
4224 int i;
4226 prev = first = NULL;
4227 for (el = pattern_list; el != NULL; el = el->next_pattern_set_el)
4229 curr = XCREATENODE (struct pattern_reserv);
4230 curr->reserv = alloc_empty_reserv_sets ();
4231 curr->next_pattern_reserv = NULL;
4232 for (i = 0; i < el->units_num; i++)
4234 SET_BIT (curr->reserv, el->unit_decls [i]->unit_num);
4235 el->unit_decls [i]->in_set_p = TRUE;
4237 if (prev != NULL)
4238 prev->next_pattern_reserv = curr;
4239 else
4240 first = curr;
4241 prev = curr;
4243 return first;
4246 /* The following function forms the array containing presence and
4247 absence pattern sets for each unit. */
4248 static void
4249 initiate_presence_absence_pattern_sets (void)
4251 decl_t decl;
4252 int i;
4254 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4255 unit_presence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4256 obstack_finish (&irp);
4257 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4258 unit_final_presence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4259 obstack_finish (&irp);
4260 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4261 unit_absence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4262 obstack_finish (&irp);
4263 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4264 unit_final_absence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4265 obstack_finish (&irp);
4266 /* Evaluate unit presence/absence sets. */
4267 for (i = 0; i < description->decls_num; i++)
4269 decl = description->decls [i];
4270 if (decl->mode == dm_unit)
4272 unit_presence_set_table [DECL_UNIT (decl)->unit_num]
4273 = form_reserv_sets_list (DECL_UNIT (decl)->presence_list);
4274 unit_final_presence_set_table [DECL_UNIT (decl)->unit_num]
4275 = form_reserv_sets_list (DECL_UNIT (decl)->final_presence_list);
4276 unit_absence_set_table [DECL_UNIT (decl)->unit_num]
4277 = form_reserv_sets_list (DECL_UNIT (decl)->absence_list);
4278 unit_final_absence_set_table [DECL_UNIT (decl)->unit_num]
4279 = form_reserv_sets_list (DECL_UNIT (decl)->final_absence_list);
4284 /* The function checks that CHECKED_SET satisfies all presence pattern
4285 sets for units in ORIGINAL_SET. The function returns TRUE if it
4286 is ok. */
4287 static int
4288 check_presence_pattern_sets (reserv_sets_t checked_set,
4289 reserv_sets_t original_set,
4290 int final_p)
4292 int char_num;
4293 int chars_num;
4294 int i;
4295 int start_unit_num;
4296 int unit_num;
4297 int presence_p;
4298 pattern_reserv_t pat_reserv;
4300 chars_num = els_in_cycle_reserv * sizeof (set_el_t);
4301 for (char_num = 0; char_num < chars_num; char_num++)
4302 if (((unsigned char *) original_set) [char_num])
4303 for (i = CHAR_BIT - 1; i >= 0; i--)
4304 if ((((unsigned char *) original_set) [char_num] >> i) & 1)
4306 start_unit_num = char_num * CHAR_BIT + i;
4307 if (start_unit_num >= description->units_num)
4308 break;
4309 if ((final_p
4310 && unit_final_presence_set_table [start_unit_num] == NULL)
4311 || (!final_p
4312 && unit_presence_set_table [start_unit_num] == NULL))
4313 continue;
4314 presence_p = FALSE;
4315 for (pat_reserv = (final_p
4316 ? unit_final_presence_set_table [start_unit_num]
4317 : unit_presence_set_table [start_unit_num]);
4318 pat_reserv != NULL;
4319 pat_reserv = pat_reserv->next_pattern_reserv)
4321 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4322 if ((checked_set [unit_num] & pat_reserv->reserv [unit_num])
4323 != pat_reserv->reserv [unit_num])
4324 break;
4325 presence_p = presence_p || unit_num >= els_in_cycle_reserv;
4327 if (!presence_p)
4328 return FALSE;
4330 return TRUE;
4333 /* The function checks that CHECKED_SET satisfies all absence pattern
4334 sets for units in ORIGINAL_SET. The function returns TRUE if it
4335 is ok. */
4336 static int
4337 check_absence_pattern_sets (reserv_sets_t checked_set,
4338 reserv_sets_t original_set,
4339 int final_p)
4341 int char_num;
4342 int chars_num;
4343 int i;
4344 int start_unit_num;
4345 int unit_num;
4346 pattern_reserv_t pat_reserv;
4348 chars_num = els_in_cycle_reserv * sizeof (set_el_t);
4349 for (char_num = 0; char_num < chars_num; char_num++)
4350 if (((unsigned char *) original_set) [char_num])
4351 for (i = CHAR_BIT - 1; i >= 0; i--)
4352 if ((((unsigned char *) original_set) [char_num] >> i) & 1)
4354 start_unit_num = char_num * CHAR_BIT + i;
4355 if (start_unit_num >= description->units_num)
4356 break;
4357 for (pat_reserv = (final_p
4358 ? unit_final_absence_set_table [start_unit_num]
4359 : unit_absence_set_table [start_unit_num]);
4360 pat_reserv != NULL;
4361 pat_reserv = pat_reserv->next_pattern_reserv)
4363 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4364 if ((checked_set [unit_num] & pat_reserv->reserv [unit_num])
4365 != pat_reserv->reserv [unit_num]
4366 && pat_reserv->reserv [unit_num])
4367 break;
4368 if (unit_num >= els_in_cycle_reserv)
4369 return FALSE;
4372 return TRUE;
4377 /* This page contains code for transformation of original reservations
4378 described in .md file. The main goal of transformations is
4379 simplifying reservation and lifting up all `|' on the top of IR
4380 reservation representation. */
4383 /* The following function makes copy of IR representation of
4384 reservation. The function also substitutes all reservations
4385 defined by define_reservation by corresponding value during making
4386 the copy. */
4387 static regexp_t
4388 copy_insn_regexp (regexp_t regexp)
4390 regexp_t result;
4391 int i;
4393 switch (regexp->mode)
4395 case rm_reserv:
4396 result = copy_insn_regexp (REGEXP_RESERV (regexp)->reserv_decl->regexp);
4397 break;
4399 case rm_unit:
4400 result = XCOPYNODE (struct regexp, regexp);
4401 break;
4403 case rm_repeat:
4404 result = XCOPYNODE (struct regexp, regexp);
4405 REGEXP_REPEAT (result)->regexp
4406 = copy_insn_regexp (REGEXP_REPEAT (regexp)->regexp);
4407 break;
4409 case rm_sequence:
4410 result = XCOPYNODEVAR (struct regexp, regexp,
4411 sizeof (struct regexp) + sizeof (regexp_t)
4412 * (REGEXP_SEQUENCE (regexp)->regexps_num - 1));
4413 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4414 REGEXP_SEQUENCE (result)->regexps [i]
4415 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4416 break;
4418 case rm_allof:
4419 result = XCOPYNODEVAR (struct regexp, regexp,
4420 sizeof (struct regexp) + sizeof (regexp_t)
4421 * (REGEXP_ALLOF (regexp)->regexps_num - 1));
4422 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4423 REGEXP_ALLOF (result)->regexps [i]
4424 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4425 break;
4427 case rm_oneof:
4428 result = XCOPYNODEVAR (struct regexp, regexp,
4429 sizeof (struct regexp) + sizeof (regexp_t)
4430 * (REGEXP_ONEOF (regexp)->regexps_num - 1));
4431 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4432 REGEXP_ONEOF (result)->regexps [i]
4433 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4434 break;
4436 case rm_nothing:
4437 result = XCOPYNODE (struct regexp, regexp);
4438 break;
4440 default:
4441 gcc_unreachable ();
4443 return result;
4446 /* The following variable is set up 1 if a transformation has been
4447 applied. */
4448 static int regexp_transformed_p;
4450 /* The function makes transformation
4451 A*N -> A, A, ... */
4452 static regexp_t
4453 transform_1 (regexp_t regexp)
4455 int i;
4456 int repeat_num;
4457 regexp_t operand;
4458 pos_t pos;
4460 if (regexp->mode == rm_repeat)
4462 repeat_num = REGEXP_REPEAT (regexp)->repeat_num;
4463 gcc_assert (repeat_num > 1);
4464 operand = REGEXP_REPEAT (regexp)->regexp;
4465 pos = regexp->mode;
4466 regexp = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4467 + sizeof (regexp_t) * (repeat_num - 1));
4468 regexp->mode = rm_sequence;
4469 regexp->pos = pos;
4470 REGEXP_SEQUENCE (regexp)->regexps_num = repeat_num;
4471 for (i = 0; i < repeat_num; i++)
4472 REGEXP_SEQUENCE (regexp)->regexps [i] = copy_insn_regexp (operand);
4473 regexp_transformed_p = 1;
4475 return regexp;
4478 /* The function makes transformations
4479 ...,(A,B,...),C,... -> ...,A,B,...,C,...
4480 ...+(A+B+...)+C+... -> ...+A+B+...+C+...
4481 ...|(A|B|...)|C|... -> ...|A|B|...|C|... */
4482 static regexp_t
4483 transform_2 (regexp_t regexp)
4485 if (regexp->mode == rm_sequence)
4487 regexp_t sequence = NULL;
4488 regexp_t result;
4489 int sequence_index = 0;
4490 int i, j;
4492 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4493 if (REGEXP_SEQUENCE (regexp)->regexps [i]->mode == rm_sequence)
4495 sequence_index = i;
4496 sequence = REGEXP_SEQUENCE (regexp)->regexps [i];
4497 break;
4499 if (i < REGEXP_SEQUENCE (regexp)->regexps_num)
4501 gcc_assert (REGEXP_SEQUENCE (sequence)->regexps_num > 1
4502 && REGEXP_SEQUENCE (regexp)->regexps_num > 1);
4503 result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4504 + sizeof (regexp_t)
4505 * (REGEXP_SEQUENCE (regexp)->regexps_num
4506 + REGEXP_SEQUENCE (sequence)->regexps_num
4507 - 2));
4508 result->mode = rm_sequence;
4509 result->pos = regexp->pos;
4510 REGEXP_SEQUENCE (result)->regexps_num
4511 = (REGEXP_SEQUENCE (regexp)->regexps_num
4512 + REGEXP_SEQUENCE (sequence)->regexps_num - 1);
4513 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4514 if (i < sequence_index)
4515 REGEXP_SEQUENCE (result)->regexps [i]
4516 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4517 else if (i > sequence_index)
4518 REGEXP_SEQUENCE (result)->regexps
4519 [i + REGEXP_SEQUENCE (sequence)->regexps_num - 1]
4520 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4521 else
4522 for (j = 0; j < REGEXP_SEQUENCE (sequence)->regexps_num; j++)
4523 REGEXP_SEQUENCE (result)->regexps [i + j]
4524 = copy_insn_regexp (REGEXP_SEQUENCE (sequence)->regexps [j]);
4525 regexp_transformed_p = 1;
4526 regexp = result;
4529 else if (regexp->mode == rm_allof)
4531 regexp_t allof = NULL;
4532 regexp_t result;
4533 int allof_index = 0;
4534 int i, j;
4536 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4537 if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_allof)
4539 allof_index = i;
4540 allof = REGEXP_ALLOF (regexp)->regexps [i];
4541 break;
4543 if (i < REGEXP_ALLOF (regexp)->regexps_num)
4545 gcc_assert (REGEXP_ALLOF (allof)->regexps_num > 1
4546 && REGEXP_ALLOF (regexp)->regexps_num > 1);
4547 result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4548 + sizeof (regexp_t)
4549 * (REGEXP_ALLOF (regexp)->regexps_num
4550 + REGEXP_ALLOF (allof)->regexps_num - 2));
4551 result->mode = rm_allof;
4552 result->pos = regexp->pos;
4553 REGEXP_ALLOF (result)->regexps_num
4554 = (REGEXP_ALLOF (regexp)->regexps_num
4555 + REGEXP_ALLOF (allof)->regexps_num - 1);
4556 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4557 if (i < allof_index)
4558 REGEXP_ALLOF (result)->regexps [i]
4559 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4560 else if (i > allof_index)
4561 REGEXP_ALLOF (result)->regexps
4562 [i + REGEXP_ALLOF (allof)->regexps_num - 1]
4563 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4564 else
4565 for (j = 0; j < REGEXP_ALLOF (allof)->regexps_num; j++)
4566 REGEXP_ALLOF (result)->regexps [i + j]
4567 = copy_insn_regexp (REGEXP_ALLOF (allof)->regexps [j]);
4568 regexp_transformed_p = 1;
4569 regexp = result;
4572 else if (regexp->mode == rm_oneof)
4574 regexp_t oneof = NULL;
4575 regexp_t result;
4576 int oneof_index = 0;
4577 int i, j;
4579 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4580 if (REGEXP_ONEOF (regexp)->regexps [i]->mode == rm_oneof)
4582 oneof_index = i;
4583 oneof = REGEXP_ONEOF (regexp)->regexps [i];
4584 break;
4586 if (i < REGEXP_ONEOF (regexp)->regexps_num)
4588 gcc_assert (REGEXP_ONEOF (oneof)->regexps_num > 1
4589 && REGEXP_ONEOF (regexp)->regexps_num > 1);
4590 result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4591 + sizeof (regexp_t)
4592 * (REGEXP_ONEOF (regexp)->regexps_num
4593 + REGEXP_ONEOF (oneof)->regexps_num - 2));
4594 result->mode = rm_oneof;
4595 result->pos = regexp->pos;
4596 REGEXP_ONEOF (result)->regexps_num
4597 = (REGEXP_ONEOF (regexp)->regexps_num
4598 + REGEXP_ONEOF (oneof)->regexps_num - 1);
4599 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4600 if (i < oneof_index)
4601 REGEXP_ONEOF (result)->regexps [i]
4602 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4603 else if (i > oneof_index)
4604 REGEXP_ONEOF (result)->regexps
4605 [i + REGEXP_ONEOF (oneof)->regexps_num - 1]
4606 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4607 else
4608 for (j = 0; j < REGEXP_ONEOF (oneof)->regexps_num; j++)
4609 REGEXP_ONEOF (result)->regexps [i + j]
4610 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [j]);
4611 regexp_transformed_p = 1;
4612 regexp = result;
4615 return regexp;
4618 /* The function makes transformations
4619 ...,A|B|...,C,... -> (...,A,C,...)|(...,B,C,...)|...
4620 ...+(A|B|...)+C+... -> (...+A+C+...)|(...+B+C+...)|...
4621 ...+(A,B,...)+C+... -> (...+A+C+...),B,...
4622 ...+(A,B,...)+(C,D,...) -> (A+C),(B+D),... */
4623 static regexp_t
4624 transform_3 (regexp_t regexp)
4626 if (regexp->mode == rm_sequence)
4628 regexp_t oneof = NULL;
4629 int oneof_index = 0;
4630 regexp_t result;
4631 regexp_t sequence;
4632 int i, j;
4634 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4635 if (REGEXP_SEQUENCE (regexp)->regexps [i]->mode == rm_oneof)
4637 oneof_index = i;
4638 oneof = REGEXP_SEQUENCE (regexp)->regexps [i];
4639 break;
4641 if (i < REGEXP_SEQUENCE (regexp)->regexps_num)
4643 gcc_assert (REGEXP_ONEOF (oneof)->regexps_num > 1
4644 && REGEXP_SEQUENCE (regexp)->regexps_num > 1);
4645 result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4646 + sizeof (regexp_t)
4647 * (REGEXP_ONEOF (oneof)->regexps_num - 1));
4648 result->mode = rm_oneof;
4649 result->pos = regexp->pos;
4650 REGEXP_ONEOF (result)->regexps_num
4651 = REGEXP_ONEOF (oneof)->regexps_num;
4652 for (i = 0; i < REGEXP_ONEOF (result)->regexps_num; i++)
4654 sequence
4655 = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4656 + sizeof (regexp_t)
4657 * (REGEXP_SEQUENCE (regexp)->regexps_num - 1));
4658 sequence->mode = rm_sequence;
4659 sequence->pos = regexp->pos;
4660 REGEXP_SEQUENCE (sequence)->regexps_num
4661 = REGEXP_SEQUENCE (regexp)->regexps_num;
4662 REGEXP_ONEOF (result)->regexps [i] = sequence;
4663 for (j = 0; j < REGEXP_SEQUENCE (sequence)->regexps_num; j++)
4664 if (j != oneof_index)
4665 REGEXP_SEQUENCE (sequence)->regexps [j]
4666 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [j]);
4667 else
4668 REGEXP_SEQUENCE (sequence)->regexps [j]
4669 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [i]);
4671 regexp_transformed_p = 1;
4672 regexp = result;
4675 else if (regexp->mode == rm_allof)
4677 regexp_t oneof = NULL;
4678 regexp_t seq;
4679 int oneof_index = 0;
4680 int max_seq_length, allof_length;
4681 regexp_t result;
4682 regexp_t allof = NULL;
4683 regexp_t allof_op = NULL;
4684 int i, j;
4686 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4687 if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_oneof)
4689 oneof_index = i;
4690 oneof = REGEXP_ALLOF (regexp)->regexps [i];
4691 break;
4693 if (i < REGEXP_ALLOF (regexp)->regexps_num)
4695 gcc_assert (REGEXP_ONEOF (oneof)->regexps_num > 1
4696 && REGEXP_ALLOF (regexp)->regexps_num > 1);
4697 result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4698 + sizeof (regexp_t)
4699 * (REGEXP_ONEOF (oneof)->regexps_num - 1));
4700 result->mode = rm_oneof;
4701 result->pos = regexp->pos;
4702 REGEXP_ONEOF (result)->regexps_num
4703 = REGEXP_ONEOF (oneof)->regexps_num;
4704 for (i = 0; i < REGEXP_ONEOF (result)->regexps_num; i++)
4706 allof
4707 = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4708 + sizeof (regexp_t)
4709 * (REGEXP_ALLOF (regexp)->regexps_num - 1));
4710 allof->mode = rm_allof;
4711 allof->pos = regexp->pos;
4712 REGEXP_ALLOF (allof)->regexps_num
4713 = REGEXP_ALLOF (regexp)->regexps_num;
4714 REGEXP_ONEOF (result)->regexps [i] = allof;
4715 for (j = 0; j < REGEXP_ALLOF (allof)->regexps_num; j++)
4716 if (j != oneof_index)
4717 REGEXP_ALLOF (allof)->regexps [j]
4718 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [j]);
4719 else
4720 REGEXP_ALLOF (allof)->regexps [j]
4721 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [i]);
4723 regexp_transformed_p = 1;
4724 regexp = result;
4726 max_seq_length = 0;
4727 if (regexp->mode == rm_allof)
4728 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4730 switch (REGEXP_ALLOF (regexp)->regexps [i]->mode)
4732 case rm_sequence:
4733 seq = REGEXP_ALLOF (regexp)->regexps [i];
4734 if (max_seq_length < REGEXP_SEQUENCE (seq)->regexps_num)
4735 max_seq_length = REGEXP_SEQUENCE (seq)->regexps_num;
4736 break;
4738 case rm_unit:
4739 case rm_nothing:
4740 break;
4742 default:
4743 max_seq_length = 0;
4744 goto break_for;
4747 break_for:
4748 if (max_seq_length != 0)
4750 gcc_assert (max_seq_length != 1
4751 && REGEXP_ALLOF (regexp)->regexps_num > 1);
4752 result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4753 + sizeof (regexp_t) * (max_seq_length - 1));
4754 result->mode = rm_sequence;
4755 result->pos = regexp->pos;
4756 REGEXP_SEQUENCE (result)->regexps_num = max_seq_length;
4757 for (i = 0; i < max_seq_length; i++)
4759 allof_length = 0;
4760 for (j = 0; j < REGEXP_ALLOF (regexp)->regexps_num; j++)
4761 switch (REGEXP_ALLOF (regexp)->regexps [j]->mode)
4763 case rm_sequence:
4764 if (i < (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4765 ->regexps [j])->regexps_num))
4767 allof_op
4768 = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4769 ->regexps [j])
4770 ->regexps [i]);
4771 allof_length++;
4773 break;
4774 case rm_unit:
4775 case rm_nothing:
4776 if (i == 0)
4778 allof_op = REGEXP_ALLOF (regexp)->regexps [j];
4779 allof_length++;
4781 break;
4782 default:
4783 break;
4786 if (allof_length == 1)
4787 REGEXP_SEQUENCE (result)->regexps [i] = allof_op;
4788 else
4790 allof = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4791 + sizeof (regexp_t)
4792 * (allof_length - 1));
4793 allof->mode = rm_allof;
4794 allof->pos = regexp->pos;
4795 REGEXP_ALLOF (allof)->regexps_num = allof_length;
4796 REGEXP_SEQUENCE (result)->regexps [i] = allof;
4797 allof_length = 0;
4798 for (j = 0; j < REGEXP_ALLOF (regexp)->regexps_num; j++)
4799 if (REGEXP_ALLOF (regexp)->regexps [j]->mode == rm_sequence
4800 && (i <
4801 (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4802 ->regexps [j])->regexps_num)))
4804 allof_op = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4805 ->regexps [j])
4806 ->regexps [i]);
4807 REGEXP_ALLOF (allof)->regexps [allof_length]
4808 = allof_op;
4809 allof_length++;
4811 else if (i == 0
4812 && (REGEXP_ALLOF (regexp)->regexps [j]->mode
4813 == rm_unit
4814 || (REGEXP_ALLOF (regexp)->regexps [j]->mode
4815 == rm_nothing)))
4817 allof_op = REGEXP_ALLOF (regexp)->regexps [j];
4818 REGEXP_ALLOF (allof)->regexps [allof_length]
4819 = allof_op;
4820 allof_length++;
4824 regexp_transformed_p = 1;
4825 regexp = result;
4828 return regexp;
4831 /* The function traverses IR of reservation and applies transformations
4832 implemented by FUNC. */
4833 static regexp_t
4834 regexp_transform_func (regexp_t regexp, regexp_t (*func) (regexp_t regexp))
4836 int i;
4838 switch (regexp->mode)
4840 case rm_sequence:
4841 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4842 REGEXP_SEQUENCE (regexp)->regexps [i]
4843 = regexp_transform_func (REGEXP_SEQUENCE (regexp)->regexps [i],
4844 func);
4845 break;
4847 case rm_allof:
4848 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4849 REGEXP_ALLOF (regexp)->regexps [i]
4850 = regexp_transform_func (REGEXP_ALLOF (regexp)->regexps [i], func);
4851 break;
4853 case rm_oneof:
4854 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4855 REGEXP_ONEOF (regexp)->regexps [i]
4856 = regexp_transform_func (REGEXP_ONEOF (regexp)->regexps [i], func);
4857 break;
4859 case rm_repeat:
4860 REGEXP_REPEAT (regexp)->regexp
4861 = regexp_transform_func (REGEXP_REPEAT (regexp)->regexp, func);
4862 break;
4864 case rm_nothing:
4865 case rm_unit:
4866 break;
4868 default:
4869 gcc_unreachable ();
4871 return (*func) (regexp);
4874 /* The function applies all transformations for IR representation of
4875 reservation REGEXP. */
4876 static regexp_t
4877 transform_regexp (regexp_t regexp)
4879 regexp = regexp_transform_func (regexp, transform_1);
4882 regexp_transformed_p = 0;
4883 regexp = regexp_transform_func (regexp, transform_2);
4884 regexp = regexp_transform_func (regexp, transform_3);
4886 while (regexp_transformed_p);
4887 return regexp;
4890 /* The function applies all transformations for reservations of all
4891 insn declarations. */
4892 static void
4893 transform_insn_regexps (void)
4895 decl_t decl;
4896 int i;
4898 transform_time = create_ticker ();
4899 add_advance_cycle_insn_decl ();
4900 if (progress_flag)
4901 fprintf (stderr, "Reservation transformation...");
4902 for (i = 0; i < description->decls_num; i++)
4904 decl = description->decls [i];
4905 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
4906 DECL_INSN_RESERV (decl)->transformed_regexp
4907 = transform_regexp (copy_insn_regexp
4908 (DECL_INSN_RESERV (decl)->regexp));
4910 if (progress_flag)
4911 fprintf (stderr, "done\n");
4912 ticker_off (&transform_time);
4917 /* The following variable value is TRUE if the first annotated message
4918 about units to automata distribution has been output. */
4919 static int annotation_message_reported_p;
4921 /* The following structure describes usage of a unit in a reservation. */
4922 struct unit_usage
4924 unit_decl_t unit_decl;
4925 /* The following forms a list of units used on the same cycle in the
4926 same alternative. */
4927 struct unit_usage *next;
4929 typedef struct unit_usage *unit_usage_t;
4931 DEF_VEC_P(unit_usage_t);
4932 DEF_VEC_ALLOC_P(unit_usage_t,heap);
4934 /* Obstack for unit_usage structures. */
4935 static struct obstack unit_usages;
4937 /* VLA for representation of array of pointers to unit usage
4938 structures. There is an element for each combination of
4939 (alternative number, cycle). Unit usages on given cycle in
4940 alternative with given number are referred through element with
4941 index equals to the cycle * number of all alternatives in the regexp
4942 + the alternative number. */
4943 static VEC(unit_usage_t,heap) *cycle_alt_unit_usages;
4945 /* The following function creates the structure unit_usage for UNIT on
4946 CYCLE in REGEXP alternative with ALT_NUM. The structure is made
4947 accessed through cycle_alt_unit_usages. */
4948 static void
4949 store_alt_unit_usage (regexp_t regexp, regexp_t unit, int cycle,
4950 int alt_num)
4952 size_t length;
4953 unit_decl_t unit_decl;
4954 unit_usage_t unit_usage_ptr;
4955 int index;
4957 gcc_assert (regexp && regexp->mode == rm_oneof
4958 && alt_num < REGEXP_ONEOF (regexp)->regexps_num);
4959 unit_decl = REGEXP_UNIT (unit)->unit_decl;
4961 length = (cycle + 1) * REGEXP_ONEOF (regexp)->regexps_num;
4962 while (VEC_length (unit_usage_t, cycle_alt_unit_usages) < length)
4963 VEC_safe_push (unit_usage_t,heap, cycle_alt_unit_usages, 0);
4965 obstack_blank (&unit_usages, sizeof (struct unit_usage));
4966 unit_usage_ptr = (struct unit_usage *) obstack_base (&unit_usages);
4967 obstack_finish (&unit_usages);
4968 unit_usage_ptr->unit_decl = unit_decl;
4969 index = cycle * REGEXP_ONEOF (regexp)->regexps_num + alt_num;
4970 unit_usage_ptr->next = VEC_index (unit_usage_t, cycle_alt_unit_usages, index);
4971 VEC_replace (unit_usage_t, cycle_alt_unit_usages, index, unit_usage_ptr);
4972 unit_decl->last_distribution_check_cycle = -1; /* undefined */
4975 /* The function processes given REGEXP to find units with the wrong
4976 distribution. */
4977 static void
4978 check_regexp_units_distribution (const char *insn_reserv_name,
4979 regexp_t regexp)
4981 int i, j, k, cycle;
4982 regexp_t seq, allof, unit;
4983 struct unit_usage *unit_usage_ptr, *other_unit_usage_ptr;
4985 if (regexp == NULL || regexp->mode != rm_oneof)
4986 return;
4987 /* Store all unit usages in the regexp: */
4988 obstack_init (&unit_usages);
4989 cycle_alt_unit_usages = 0;
4991 for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
4993 seq = REGEXP_ONEOF (regexp)->regexps [i];
4994 switch (seq->mode)
4996 case rm_sequence:
4997 for (j = 0; j < REGEXP_SEQUENCE (seq)->regexps_num; j++)
4999 allof = REGEXP_SEQUENCE (seq)->regexps [j];
5000 switch (allof->mode)
5002 case rm_allof:
5003 for (k = 0; k < REGEXP_ALLOF (allof)->regexps_num; k++)
5005 unit = REGEXP_ALLOF (allof)->regexps [k];
5006 if (unit->mode == rm_unit)
5007 store_alt_unit_usage (regexp, unit, j, i);
5008 else
5009 gcc_assert (unit->mode == rm_nothing);
5011 break;
5013 case rm_unit:
5014 store_alt_unit_usage (regexp, allof, j, i);
5015 break;
5017 case rm_nothing:
5018 break;
5020 default:
5021 gcc_unreachable ();
5024 break;
5026 case rm_allof:
5027 for (k = 0; k < REGEXP_ALLOF (seq)->regexps_num; k++)
5029 unit = REGEXP_ALLOF (seq)->regexps [k];
5030 switch (unit->mode)
5032 case rm_unit:
5033 store_alt_unit_usage (regexp, unit, 0, i);
5034 break;
5036 case rm_nothing:
5037 break;
5039 default:
5040 gcc_unreachable ();
5043 break;
5045 case rm_unit:
5046 store_alt_unit_usage (regexp, seq, 0, i);
5047 break;
5049 case rm_nothing:
5050 break;
5052 default:
5053 gcc_unreachable ();
5056 /* Check distribution: */
5057 for (i = 0; i < (int) VEC_length (unit_usage_t, cycle_alt_unit_usages); i++)
5059 cycle = i / REGEXP_ONEOF (regexp)->regexps_num;
5060 for (unit_usage_ptr = VEC_index (unit_usage_t, cycle_alt_unit_usages, i);
5061 unit_usage_ptr != NULL;
5062 unit_usage_ptr = unit_usage_ptr->next)
5063 if (cycle != unit_usage_ptr->unit_decl->last_distribution_check_cycle)
5065 unit_usage_ptr->unit_decl->last_distribution_check_cycle = cycle;
5066 for (k = cycle * REGEXP_ONEOF (regexp)->regexps_num;
5067 k < (int) VEC_length (unit_usage_t, cycle_alt_unit_usages)
5068 && k == cycle * REGEXP_ONEOF (regexp)->regexps_num;
5069 k++)
5071 for (other_unit_usage_ptr
5072 = VEC_index (unit_usage_t, cycle_alt_unit_usages, k);
5073 other_unit_usage_ptr != NULL;
5074 other_unit_usage_ptr = other_unit_usage_ptr->next)
5075 if (unit_usage_ptr->unit_decl->automaton_decl
5076 == other_unit_usage_ptr->unit_decl->automaton_decl)
5077 break;
5078 if (other_unit_usage_ptr == NULL
5079 && (VEC_index (unit_usage_t, cycle_alt_unit_usages, k)
5080 != NULL))
5081 break;
5083 if (k < (int) VEC_length (unit_usage_t, cycle_alt_unit_usages)
5084 && k == cycle * REGEXP_ONEOF (regexp)->regexps_num)
5086 if (!annotation_message_reported_p)
5088 fprintf (stderr, "\n");
5089 error ("The following units do not satisfy units-automata distribution rule");
5090 error (" (A unit of given unit automaton should be on each reserv. altern.)");
5091 annotation_message_reported_p = TRUE;
5093 error ("Unit %s, reserv. %s, cycle %d",
5094 unit_usage_ptr->unit_decl->name, insn_reserv_name,
5095 cycle);
5099 VEC_free (unit_usage_t,heap, cycle_alt_unit_usages);
5100 obstack_free (&unit_usages, NULL);
5103 /* The function finds units which violates units to automata
5104 distribution rule. If the units exist, report about them. */
5105 static void
5106 check_unit_distributions_to_automata (void)
5108 decl_t decl;
5109 int i;
5111 if (progress_flag)
5112 fprintf (stderr, "Check unit distributions to automata...");
5113 annotation_message_reported_p = FALSE;
5114 for (i = 0; i < description->decls_num; i++)
5116 decl = description->decls [i];
5117 if (decl->mode == dm_insn_reserv)
5118 check_regexp_units_distribution
5119 (DECL_INSN_RESERV (decl)->name,
5120 DECL_INSN_RESERV (decl)->transformed_regexp);
5122 if (progress_flag)
5123 fprintf (stderr, "done\n");
5128 /* The page contains code for building alt_states (see comments for
5129 IR) describing all possible insns reservations of an automaton. */
5131 /* Current state being formed for which the current alt_state
5132 refers. */
5133 static state_t state_being_formed;
5135 /* Current alt_state being formed. */
5136 static alt_state_t alt_state_being_formed;
5138 /* This recursive function processes `,' and units in reservation
5139 REGEXP for forming alt_states of AUTOMATON. It is believed that
5140 CURR_CYCLE is start cycle of all reservation REGEXP. */
5141 static int
5142 process_seq_for_forming_states (regexp_t regexp, automaton_t automaton,
5143 int curr_cycle)
5145 int i;
5147 if (regexp == NULL)
5148 return curr_cycle;
5150 switch (regexp->mode)
5152 case rm_unit:
5153 if (REGEXP_UNIT (regexp)->unit_decl->corresponding_automaton_num
5154 == automaton->automaton_order_num)
5155 set_state_reserv (state_being_formed, curr_cycle,
5156 REGEXP_UNIT (regexp)->unit_decl->unit_num);
5157 return curr_cycle;
5159 case rm_sequence:
5160 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
5161 curr_cycle
5162 = process_seq_for_forming_states
5163 (REGEXP_SEQUENCE (regexp)->regexps [i], automaton, curr_cycle) + 1;
5164 return curr_cycle;
5166 case rm_allof:
5168 int finish_cycle = 0;
5169 int cycle;
5171 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
5173 cycle = process_seq_for_forming_states (REGEXP_ALLOF (regexp)
5174 ->regexps [i],
5175 automaton, curr_cycle);
5176 if (finish_cycle < cycle)
5177 finish_cycle = cycle;
5179 return finish_cycle;
5182 case rm_nothing:
5183 return curr_cycle;
5185 default:
5186 gcc_unreachable ();
5190 /* This recursive function finishes forming ALT_STATE of AUTOMATON and
5191 inserts alt_state into the table. */
5192 static void
5193 finish_forming_alt_state (alt_state_t alt_state,
5194 automaton_t automaton ATTRIBUTE_UNUSED)
5196 state_t state_in_table;
5197 state_t corresponding_state;
5199 corresponding_state = alt_state->state;
5200 state_in_table = insert_state (corresponding_state);
5201 if (state_in_table != corresponding_state)
5203 free_state (corresponding_state);
5204 alt_state->state = state_in_table;
5208 /* The following variable value is current automaton insn for whose
5209 reservation the alt states are created. */
5210 static ainsn_t curr_ainsn;
5212 /* This recursive function processes `|' in reservation REGEXP for
5213 forming alt_states of AUTOMATON. List of the alt states should
5214 have the same order as in the description. */
5215 static void
5216 process_alts_for_forming_states (regexp_t regexp, automaton_t automaton,
5217 int inside_oneof_p)
5219 int i;
5221 if (regexp->mode != rm_oneof)
5223 alt_state_being_formed = get_free_alt_state ();
5224 state_being_formed = get_free_state (1, automaton);
5225 alt_state_being_formed->state = state_being_formed;
5226 /* We inserts in reverse order but we process alternatives also
5227 in reverse order. So we have the same order of alternative
5228 as in the description. */
5229 alt_state_being_formed->next_alt_state = curr_ainsn->alt_states;
5230 curr_ainsn->alt_states = alt_state_being_formed;
5231 (void) process_seq_for_forming_states (regexp, automaton, 0);
5232 finish_forming_alt_state (alt_state_being_formed, automaton);
5234 else
5236 gcc_assert (!inside_oneof_p);
5237 /* We processes it in reverse order to get list with the same
5238 order as in the description. See also the previous
5239 commentary. */
5240 for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
5241 process_alts_for_forming_states (REGEXP_ONEOF (regexp)->regexps [i],
5242 automaton, 1);
5246 /* Create nodes alt_state for all AUTOMATON insns. */
5247 static void
5248 create_alt_states (automaton_t automaton)
5250 struct insn_reserv_decl *reserv_decl;
5252 for (curr_ainsn = automaton->ainsn_list;
5253 curr_ainsn != NULL;
5254 curr_ainsn = curr_ainsn->next_ainsn)
5256 reserv_decl = curr_ainsn->insn_reserv_decl;
5257 if (reserv_decl != DECL_INSN_RESERV (advance_cycle_insn_decl))
5259 curr_ainsn->alt_states = NULL;
5260 process_alts_for_forming_states (reserv_decl->transformed_regexp,
5261 automaton, 0);
5262 curr_ainsn->sorted_alt_states
5263 = uniq_sort_alt_states (curr_ainsn->alt_states);
5270 /* The page contains major code for building DFA(s) for fast pipeline
5271 hazards recognition. */
5273 /* The function forms list of ainsns of AUTOMATON with the same
5274 reservation. */
5276 static void
5277 form_ainsn_with_same_reservs (automaton_t automaton)
5279 ainsn_t curr_ainsn;
5280 size_t i;
5281 VEC(ainsn_t,heap) *last_insns = VEC_alloc (ainsn_t,heap, 150);
5283 for (curr_ainsn = automaton->ainsn_list;
5284 curr_ainsn != NULL;
5285 curr_ainsn = curr_ainsn->next_ainsn)
5286 if (curr_ainsn->insn_reserv_decl
5287 == DECL_INSN_RESERV (advance_cycle_insn_decl))
5289 curr_ainsn->next_same_reservs_insn = NULL;
5290 curr_ainsn->first_insn_with_same_reservs = 1;
5292 else
5294 for (i = 0; i < VEC_length (ainsn_t, last_insns); i++)
5295 if (alt_states_eq
5296 (curr_ainsn->sorted_alt_states,
5297 VEC_index (ainsn_t, last_insns, i)->sorted_alt_states))
5298 break;
5299 curr_ainsn->next_same_reservs_insn = NULL;
5300 if (i < VEC_length (ainsn_t, last_insns))
5302 curr_ainsn->first_insn_with_same_reservs = 0;
5303 VEC_index (ainsn_t, last_insns, i)->next_same_reservs_insn
5304 = curr_ainsn;
5305 VEC_replace (ainsn_t, last_insns, i, curr_ainsn);
5307 else
5309 VEC_safe_push (ainsn_t, heap, last_insns, curr_ainsn);
5310 curr_ainsn->first_insn_with_same_reservs = 1;
5313 VEC_free (ainsn_t,heap, last_insns);
5316 /* Forming unit reservations which can affect creating the automaton
5317 states achieved from a given state. It permits to build smaller
5318 automata in many cases. We would have the same automata after
5319 the minimization without such optimization, but the automaton
5320 right after the building could be huge. So in other words, usage
5321 of reservs_matter means some minimization during building the
5322 automaton. */
5323 static reserv_sets_t
5324 form_reservs_matter (automaton_t automaton)
5326 int cycle, unit;
5327 reserv_sets_t reservs_matter = alloc_empty_reserv_sets();
5329 for (cycle = 0; cycle < max_cycles_num; cycle++)
5330 for (unit = 0; unit < description->units_num; unit++)
5331 if (units_array [unit]->automaton_decl
5332 == automaton->corresponding_automaton_decl
5333 && (cycle >= units_array [unit]->min_occ_cycle_num
5334 /* We can not remove queried unit from reservations. */
5335 || units_array [unit]->query_p
5336 /* We can not remove units which are used
5337 `exclusion_set', `presence_set',
5338 `final_presence_set', `absence_set', and
5339 `final_absence_set'. */
5340 || units_array [unit]->in_set_p))
5341 set_unit_reserv (reservs_matter, cycle, unit);
5342 return reservs_matter;
5345 /* The following function creates all states of nondeterministic AUTOMATON. */
5346 static void
5347 make_automaton (automaton_t automaton)
5349 ainsn_t ainsn;
5350 struct insn_reserv_decl *insn_reserv_decl;
5351 alt_state_t alt_state;
5352 state_t state;
5353 state_t start_state;
5354 state_t state2;
5355 ainsn_t advance_cycle_ainsn;
5356 arc_t added_arc;
5357 VEC(state_t,heap) *state_stack = VEC_alloc(state_t,heap, 150);
5358 int states_n;
5359 reserv_sets_t reservs_matter = form_reservs_matter (automaton);
5361 /* Create the start state (empty state). */
5362 start_state = insert_state (get_free_state (1, automaton));
5363 automaton->start_state = start_state;
5364 start_state->it_was_placed_in_stack_for_NDFA_forming = 1;
5365 VEC_safe_push (state_t,heap, state_stack, start_state);
5366 states_n = 1;
5367 while (VEC_length (state_t, state_stack) != 0)
5369 state = VEC_pop (state_t, state_stack);
5370 advance_cycle_ainsn = NULL;
5371 for (ainsn = automaton->ainsn_list;
5372 ainsn != NULL;
5373 ainsn = ainsn->next_ainsn)
5374 if (ainsn->first_insn_with_same_reservs)
5376 insn_reserv_decl = ainsn->insn_reserv_decl;
5377 if (insn_reserv_decl != DECL_INSN_RESERV (advance_cycle_insn_decl))
5379 /* We process alt_states in the same order as they are
5380 present in the description. */
5381 added_arc = NULL;
5382 for (alt_state = ainsn->alt_states;
5383 alt_state != NULL;
5384 alt_state = alt_state->next_alt_state)
5386 state2 = alt_state->state;
5387 if (!intersected_state_reservs_p (state, state2))
5389 state2 = states_union (state, state2, reservs_matter);
5390 if (!state2->it_was_placed_in_stack_for_NDFA_forming)
5392 state2->it_was_placed_in_stack_for_NDFA_forming
5393 = 1;
5394 VEC_safe_push (state_t,heap, state_stack, state2);
5395 states_n++;
5396 if (progress_flag && states_n % 100 == 0)
5397 fprintf (stderr, ".");
5399 added_arc = add_arc (state, state2, ainsn);
5400 if (!ndfa_flag)
5401 break;
5404 if (!ndfa_flag && added_arc != NULL)
5406 for (alt_state = ainsn->alt_states;
5407 alt_state != NULL;
5408 alt_state = alt_state->next_alt_state)
5409 state2 = alt_state->state;
5412 else
5413 advance_cycle_ainsn = ainsn;
5415 /* Add transition to advance cycle. */
5416 state2 = state_shift (state, reservs_matter);
5417 if (!state2->it_was_placed_in_stack_for_NDFA_forming)
5419 state2->it_was_placed_in_stack_for_NDFA_forming = 1;
5420 VEC_safe_push (state_t,heap, state_stack, state2);
5421 states_n++;
5422 if (progress_flag && states_n % 100 == 0)
5423 fprintf (stderr, ".");
5425 gcc_assert (advance_cycle_ainsn);
5426 add_arc (state, state2, advance_cycle_ainsn);
5428 VEC_free (state_t,heap, state_stack);
5431 /* Form lists of all arcs of STATE marked by the same ainsn. */
5432 static void
5433 form_arcs_marked_by_insn (state_t state)
5435 decl_t decl;
5436 arc_t arc;
5437 int i;
5439 for (i = 0; i < description->decls_num; i++)
5441 decl = description->decls [i];
5442 if (decl->mode == dm_insn_reserv)
5443 DECL_INSN_RESERV (decl)->arcs_marked_by_insn = NULL;
5445 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5447 gcc_assert (arc->insn);
5448 arc->next_arc_marked_by_insn
5449 = arc->insn->insn_reserv_decl->arcs_marked_by_insn;
5450 arc->insn->insn_reserv_decl->arcs_marked_by_insn = arc;
5454 /* The function creates composed state (see comments for IR) from
5455 ORIGINAL_STATE and list of arcs ARCS_MARKED_BY_INSN marked by the
5456 same insn. If the composed state is not in STATE_STACK yet, it is
5457 pushed into STATE_STACK. */
5459 static int
5460 create_composed_state (state_t original_state, arc_t arcs_marked_by_insn,
5461 VEC(state_t,heap) **state_stack)
5463 state_t state;
5464 alt_state_t alt_state, curr_alt_state;
5465 alt_state_t new_alt_state;
5466 arc_t curr_arc;
5467 arc_t next_arc;
5468 state_t state_in_table;
5469 state_t temp_state;
5470 alt_state_t canonical_alt_states_list;
5471 int alts_number;
5472 int new_state_p = 0;
5474 if (arcs_marked_by_insn == NULL)
5475 return new_state_p;
5476 if (arcs_marked_by_insn->next_arc_marked_by_insn == NULL)
5477 state = arcs_marked_by_insn->to_state;
5478 else
5480 gcc_assert (ndfa_flag);
5481 /* Create composed state. */
5482 state = get_free_state (0, arcs_marked_by_insn->to_state->automaton);
5483 curr_alt_state = NULL;
5484 for (curr_arc = arcs_marked_by_insn;
5485 curr_arc != NULL;
5486 curr_arc = curr_arc->next_arc_marked_by_insn)
5487 if (curr_arc->to_state->component_states == NULL)
5489 new_alt_state = get_free_alt_state ();
5490 new_alt_state->next_alt_state = curr_alt_state;
5491 new_alt_state->state = curr_arc->to_state;
5492 curr_alt_state = new_alt_state;
5494 else
5495 for (alt_state = curr_arc->to_state->component_states;
5496 alt_state != NULL;
5497 alt_state = alt_state->next_sorted_alt_state)
5499 new_alt_state = get_free_alt_state ();
5500 new_alt_state->next_alt_state = curr_alt_state;
5501 new_alt_state->state = alt_state->state;
5502 gcc_assert (!alt_state->state->component_states);
5503 curr_alt_state = new_alt_state;
5505 /* There are not identical sets in the alt state list. */
5506 canonical_alt_states_list = uniq_sort_alt_states (curr_alt_state);
5507 if (canonical_alt_states_list->next_sorted_alt_state == NULL)
5509 temp_state = state;
5510 state = canonical_alt_states_list->state;
5511 free_state (temp_state);
5513 else
5515 state->component_states = canonical_alt_states_list;
5516 state_in_table = insert_state (state);
5517 if (state_in_table != state)
5519 gcc_assert
5520 (state_in_table->it_was_placed_in_stack_for_DFA_forming);
5521 free_state (state);
5522 state = state_in_table;
5524 else
5526 gcc_assert (!state->it_was_placed_in_stack_for_DFA_forming);
5527 new_state_p = 1;
5528 for (curr_alt_state = state->component_states;
5529 curr_alt_state != NULL;
5530 curr_alt_state = curr_alt_state->next_sorted_alt_state)
5531 for (curr_arc = first_out_arc (curr_alt_state->state);
5532 curr_arc != NULL;
5533 curr_arc = next_out_arc (curr_arc))
5534 add_arc (state, curr_arc->to_state, curr_arc->insn);
5536 arcs_marked_by_insn->to_state = state;
5537 for (alts_number = 0,
5538 curr_arc = arcs_marked_by_insn->next_arc_marked_by_insn;
5539 curr_arc != NULL;
5540 curr_arc = next_arc)
5542 next_arc = curr_arc->next_arc_marked_by_insn;
5543 remove_arc (original_state, curr_arc);
5544 alts_number++;
5548 if (!state->it_was_placed_in_stack_for_DFA_forming)
5550 state->it_was_placed_in_stack_for_DFA_forming = 1;
5551 VEC_safe_push (state_t,heap, *state_stack, state);
5553 return new_state_p;
5556 /* The function transforms nondeterministic AUTOMATON into
5557 deterministic. */
5559 static void
5560 NDFA_to_DFA (automaton_t automaton)
5562 state_t start_state;
5563 state_t state;
5564 decl_t decl;
5565 VEC(state_t,heap) *state_stack;
5566 int i;
5567 int states_n;
5569 state_stack = VEC_alloc (state_t,heap, 0);
5571 /* Create the start state (empty state). */
5572 start_state = automaton->start_state;
5573 start_state->it_was_placed_in_stack_for_DFA_forming = 1;
5574 VEC_safe_push (state_t,heap, state_stack, start_state);
5575 states_n = 1;
5576 while (VEC_length (state_t, state_stack) != 0)
5578 state = VEC_pop (state_t, state_stack);
5579 form_arcs_marked_by_insn (state);
5580 for (i = 0; i < description->decls_num; i++)
5582 decl = description->decls [i];
5583 if (decl->mode == dm_insn_reserv
5584 && create_composed_state
5585 (state, DECL_INSN_RESERV (decl)->arcs_marked_by_insn,
5586 &state_stack))
5588 states_n++;
5589 if (progress_flag && states_n % 100 == 0)
5590 fprintf (stderr, ".");
5594 VEC_free (state_t,heap, state_stack);
5597 /* The following variable value is current number (1, 2, ...) of passing
5598 graph of states. */
5599 static int curr_state_graph_pass_num;
5601 /* This recursive function passes all states achieved from START_STATE
5602 and applies APPLIED_FUNC to them. */
5603 static void
5604 pass_state_graph (state_t start_state, void (*applied_func) (state_t state))
5606 arc_t arc;
5608 if (start_state->pass_num == curr_state_graph_pass_num)
5609 return;
5610 start_state->pass_num = curr_state_graph_pass_num;
5611 (*applied_func) (start_state);
5612 for (arc = first_out_arc (start_state);
5613 arc != NULL;
5614 arc = next_out_arc (arc))
5615 pass_state_graph (arc->to_state, applied_func);
5618 /* This recursive function passes all states of AUTOMATON and applies
5619 APPLIED_FUNC to them. */
5620 static void
5621 pass_states (automaton_t automaton, void (*applied_func) (state_t state))
5623 curr_state_graph_pass_num++;
5624 pass_state_graph (automaton->start_state, applied_func);
5627 /* The function initializes code for passing of all states. */
5628 static void
5629 initiate_pass_states (void)
5631 curr_state_graph_pass_num = 0;
5634 /* The following vla is used for storing pointers to all achieved
5635 states. */
5636 static VEC(state_t,heap) *all_achieved_states;
5638 /* This function is called by function pass_states to add an achieved
5639 STATE. */
5640 static void
5641 add_achieved_state (state_t state)
5643 VEC_safe_push (state_t,heap, all_achieved_states, state);
5646 /* The function sets up equivalence numbers of insns which mark all
5647 out arcs of STATE by equiv_class_num_1 (if ODD_ITERATION_FLAG has
5648 nonzero value) or by equiv_class_num_2 of the destination state.
5649 The function returns number of out arcs of STATE. */
5650 static void
5651 set_out_arc_insns_equiv_num (state_t state, int odd_iteration_flag)
5653 arc_t arc;
5655 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5657 gcc_assert (!arc->insn->insn_reserv_decl->equiv_class_num);
5658 arc->insn->insn_reserv_decl->equiv_class_num
5659 = (odd_iteration_flag
5660 ? arc->to_state->equiv_class_num_1
5661 : arc->to_state->equiv_class_num_2);
5662 gcc_assert (arc->insn->insn_reserv_decl->equiv_class_num);
5666 /* The function clears equivalence numbers and alt_states in all insns
5667 which mark all out arcs of STATE. */
5668 static void
5669 clear_arc_insns_equiv_num (state_t state)
5671 arc_t arc;
5673 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5674 arc->insn->insn_reserv_decl->equiv_class_num = 0;
5678 /* The following function returns TRUE if STATE reserves the unit with
5679 UNIT_NUM on the first cycle. */
5680 static int
5681 first_cycle_unit_presence (state_t state, int unit_num)
5683 alt_state_t alt_state;
5685 if (state->component_states == NULL)
5686 return test_unit_reserv (state->reservs, 0, unit_num);
5687 else
5689 for (alt_state = state->component_states;
5690 alt_state != NULL;
5691 alt_state = alt_state->next_sorted_alt_state)
5692 if (test_unit_reserv (alt_state->state->reservs, 0, unit_num))
5693 return true;
5695 return false;
5698 /* This fills in the presence_signature[] member of STATE. */
5699 static void
5700 cache_presence (state_t state)
5702 int i, num = 0;
5703 unsigned int sz;
5704 sz = (description->query_units_num + sizeof (int) * CHAR_BIT - 1)
5705 / (sizeof (int) * CHAR_BIT);
5707 state->presence_signature = XCREATENODEVEC (unsigned int, sz);
5708 for (i = 0; i < description->units_num; i++)
5709 if (units_array [i]->query_p)
5711 int presence1_p = first_cycle_unit_presence (state, i);
5712 state->presence_signature[num / (sizeof (int) * CHAR_BIT)]
5713 |= (!!presence1_p) << (num % (sizeof (int) * CHAR_BIT));
5714 num++;
5718 /* The function returns nonzero value if STATE is not equivalent to
5719 ANOTHER_STATE from the same current partition on equivalence
5720 classes. Another state has ANOTHER_STATE_OUT_ARCS_NUM number of
5721 output arcs. Iteration of making equivalence partition is defined
5722 by ODD_ITERATION_FLAG. */
5723 static int
5724 state_is_differed (state_t state, state_t another_state,
5725 int odd_iteration_flag)
5727 arc_t arc;
5728 unsigned int sz, si;
5730 gcc_assert (state->num_out_arcs == another_state->num_out_arcs);
5732 sz = (description->query_units_num + sizeof (int) * CHAR_BIT - 1)
5733 / (sizeof (int) * CHAR_BIT);
5735 for (si = 0; si < sz; si++)
5736 gcc_assert (state->presence_signature[si]
5737 == another_state->presence_signature[si]);
5739 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5741 if ((odd_iteration_flag
5742 ? arc->to_state->equiv_class_num_1
5743 : arc->to_state->equiv_class_num_2)
5744 != arc->insn->insn_reserv_decl->equiv_class_num)
5745 return 1;
5748 return 0;
5751 /* Compares two states pointed to by STATE_PTR_1 and STATE_PTR_2
5752 and return -1, 0 or 1. This function can be used as predicate for
5753 qsort(). It requires the member presence_signature[] of both
5754 states be filled. */
5755 static int
5756 compare_states_for_equiv (const void *state_ptr_1,
5757 const void *state_ptr_2)
5759 const_state_t const s1 = *(const_state_t const*)state_ptr_1;
5760 const_state_t const s2 = *(const_state_t const*)state_ptr_2;
5761 unsigned int sz, si;
5762 if (s1->num_out_arcs < s2->num_out_arcs)
5763 return -1;
5764 else if (s1->num_out_arcs > s2->num_out_arcs)
5765 return 1;
5767 sz = (description->query_units_num + sizeof (int) * CHAR_BIT - 1)
5768 / (sizeof (int) * CHAR_BIT);
5770 for (si = 0; si < sz; si++)
5771 if (s1->presence_signature[si] < s2->presence_signature[si])
5772 return -1;
5773 else if (s1->presence_signature[si] > s2->presence_signature[si])
5774 return 1;
5775 return 0;
5778 /* The function makes initial partition of STATES on equivalent
5779 classes and saves it into *CLASSES. This function requires the input
5780 to be sorted via compare_states_for_equiv(). */
5781 static int
5782 init_equiv_class (VEC(state_t,heap) *states, VEC (state_t,heap) **classes)
5784 size_t i;
5785 state_t prev = 0;
5786 int class_num = 1;
5788 *classes = VEC_alloc (state_t,heap, 150);
5789 for (i = 0; i < VEC_length (state_t, states); i++)
5791 state_t state = VEC_index (state_t, states, i);
5792 if (prev)
5794 if (compare_states_for_equiv (&prev, &state) != 0)
5796 VEC_safe_push (state_t,heap, *classes, prev);
5797 class_num++;
5798 prev = NULL;
5801 state->equiv_class_num_1 = class_num;
5802 state->next_equiv_class_state = prev;
5803 prev = state;
5805 if (prev)
5806 VEC_safe_push (state_t,heap, *classes, prev);
5807 return class_num;
5810 /* The function copies pointers to equivalent states from vla FROM
5811 into vla TO. */
5812 static void
5813 copy_equiv_class (VEC(state_t,heap) **to, VEC(state_t,heap) *from)
5815 VEC_free (state_t,heap, *to);
5816 *to = VEC_copy (state_t,heap, from);
5819 /* The function processes equivalence class given by its first state,
5820 FIRST_STATE, on odd iteration if ODD_ITERATION_FLAG. If there
5821 are not equivalent states, the function partitions the class
5822 removing nonequivalent states and placing them in
5823 *NEXT_ITERATION_CLASSES, increments *NEW_EQUIV_CLASS_NUM_PTR ans
5824 assigns it to the state equivalence number. If the class has been
5825 partitioned, the function returns nonzero value. */
5826 static int
5827 partition_equiv_class (state_t first_state, int odd_iteration_flag,
5828 VEC(state_t,heap) **next_iteration_classes,
5829 int *new_equiv_class_num_ptr)
5831 state_t new_equiv_class;
5832 int partition_p;
5833 state_t curr_state;
5834 state_t prev_state;
5835 state_t next_state;
5837 partition_p = 0;
5839 while (first_state != NULL)
5841 new_equiv_class = NULL;
5842 if (first_state->next_equiv_class_state != NULL)
5844 /* There are more one states in the class equivalence. */
5845 set_out_arc_insns_equiv_num (first_state, odd_iteration_flag);
5846 for (prev_state = first_state,
5847 curr_state = first_state->next_equiv_class_state;
5848 curr_state != NULL;
5849 curr_state = next_state)
5851 next_state = curr_state->next_equiv_class_state;
5852 if (state_is_differed (curr_state, first_state,
5853 odd_iteration_flag))
5855 /* Remove curr state from the class equivalence. */
5856 prev_state->next_equiv_class_state = next_state;
5857 /* Add curr state to the new class equivalence. */
5858 curr_state->next_equiv_class_state = new_equiv_class;
5859 if (new_equiv_class == NULL)
5860 (*new_equiv_class_num_ptr)++;
5861 if (odd_iteration_flag)
5862 curr_state->equiv_class_num_2 = *new_equiv_class_num_ptr;
5863 else
5864 curr_state->equiv_class_num_1 = *new_equiv_class_num_ptr;
5865 new_equiv_class = curr_state;
5866 partition_p = 1;
5868 else
5869 prev_state = curr_state;
5871 clear_arc_insns_equiv_num (first_state);
5873 if (new_equiv_class != NULL)
5874 VEC_safe_push (state_t,heap, *next_iteration_classes, new_equiv_class);
5875 first_state = new_equiv_class;
5877 return partition_p;
5880 /* The function finds equivalent states of AUTOMATON. */
5881 static void
5882 evaluate_equiv_classes (automaton_t automaton,
5883 VEC(state_t,heap) **equiv_classes)
5885 int new_equiv_class_num;
5886 int odd_iteration_flag;
5887 int finish_flag;
5888 VEC (state_t,heap) *next_iteration_classes;
5889 size_t i;
5891 all_achieved_states = VEC_alloc (state_t,heap, 1500);
5892 pass_states (automaton, add_achieved_state);
5893 pass_states (automaton, cache_presence);
5894 qsort (VEC_address (state_t, all_achieved_states),
5895 VEC_length (state_t, all_achieved_states),
5896 sizeof (state_t), compare_states_for_equiv);
5898 odd_iteration_flag = 0;
5899 new_equiv_class_num = init_equiv_class (all_achieved_states,
5900 &next_iteration_classes);
5904 odd_iteration_flag = !odd_iteration_flag;
5905 finish_flag = 1;
5906 copy_equiv_class (equiv_classes, next_iteration_classes);
5908 /* Transfer equiv numbers for the next iteration. */
5909 for (i = 0; i < VEC_length (state_t, all_achieved_states); i++)
5910 if (odd_iteration_flag)
5911 VEC_index (state_t, all_achieved_states, i)->equiv_class_num_2
5912 = VEC_index (state_t, all_achieved_states, i)->equiv_class_num_1;
5913 else
5914 VEC_index (state_t, all_achieved_states, i)->equiv_class_num_1
5915 = VEC_index (state_t, all_achieved_states, i)->equiv_class_num_2;
5917 for (i = 0; i < VEC_length (state_t, *equiv_classes); i++)
5918 if (partition_equiv_class (VEC_index (state_t, *equiv_classes, i),
5919 odd_iteration_flag,
5920 &next_iteration_classes,
5921 &new_equiv_class_num))
5922 finish_flag = 0;
5924 while (!finish_flag);
5925 VEC_free (state_t,heap, next_iteration_classes);
5926 VEC_free (state_t,heap, all_achieved_states);
5929 /* The function merges equivalent states of AUTOMATON. */
5930 static void
5931 merge_states (automaton_t automaton, VEC(state_t,heap) *equiv_classes)
5933 state_t curr_state;
5934 state_t new_state;
5935 state_t first_class_state;
5936 alt_state_t alt_states;
5937 alt_state_t alt_state, new_alt_state;
5938 arc_t curr_arc;
5939 arc_t next_arc;
5940 size_t i;
5942 /* Create states corresponding to equivalence classes containing two
5943 or more states. */
5944 for (i = 0; i < VEC_length (state_t, equiv_classes); i++)
5946 curr_state = VEC_index (state_t, equiv_classes, i);
5947 if (curr_state->next_equiv_class_state != NULL)
5949 /* There are more one states in the class equivalence. */
5950 /* Create new compound state. */
5951 new_state = get_free_state (0, automaton);
5952 alt_states = NULL;
5953 first_class_state = curr_state;
5954 for (curr_state = first_class_state;
5955 curr_state != NULL;
5956 curr_state = curr_state->next_equiv_class_state)
5958 curr_state->equiv_class_state = new_state;
5959 if (curr_state->component_states == NULL)
5961 new_alt_state = get_free_alt_state ();
5962 new_alt_state->state = curr_state;
5963 new_alt_state->next_alt_state = alt_states;
5964 alt_states = new_alt_state;
5966 else
5967 for (alt_state = curr_state->component_states;
5968 alt_state != NULL;
5969 alt_state = alt_state->next_sorted_alt_state)
5971 new_alt_state = get_free_alt_state ();
5972 new_alt_state->state = alt_state->state;
5973 new_alt_state->next_alt_state = alt_states;
5974 alt_states = new_alt_state;
5977 /* Its is important that alt states were sorted before and
5978 after merging to have the same querying results. */
5979 new_state->component_states = uniq_sort_alt_states (alt_states);
5981 else
5982 curr_state->equiv_class_state = curr_state;
5985 for (i = 0; i < VEC_length (state_t, equiv_classes); i++)
5987 curr_state = VEC_index (state_t, equiv_classes, i);
5988 if (curr_state->next_equiv_class_state != NULL)
5990 first_class_state = curr_state;
5991 /* Create new arcs output from the state corresponding to
5992 equiv class. */
5993 for (curr_arc = first_out_arc (first_class_state);
5994 curr_arc != NULL;
5995 curr_arc = next_out_arc (curr_arc))
5996 add_arc (first_class_state->equiv_class_state,
5997 curr_arc->to_state->equiv_class_state,
5998 curr_arc->insn);
5999 /* Delete output arcs from states of given class equivalence. */
6000 for (curr_state = first_class_state;
6001 curr_state != NULL;
6002 curr_state = curr_state->next_equiv_class_state)
6004 if (automaton->start_state == curr_state)
6005 automaton->start_state = curr_state->equiv_class_state;
6006 /* Delete the state and its output arcs. */
6007 for (curr_arc = first_out_arc (curr_state);
6008 curr_arc != NULL;
6009 curr_arc = next_arc)
6011 next_arc = next_out_arc (curr_arc);
6012 free_arc (curr_arc);
6016 else
6018 /* Change `to_state' of arcs output from the state of given
6019 equivalence class. */
6020 for (curr_arc = first_out_arc (curr_state);
6021 curr_arc != NULL;
6022 curr_arc = next_out_arc (curr_arc))
6023 curr_arc->to_state = curr_arc->to_state->equiv_class_state;
6028 /* The function sets up new_cycle_p for states if there is arc to the
6029 state marked by advance_cycle_insn_decl. */
6030 static void
6031 set_new_cycle_flags (state_t state)
6033 arc_t arc;
6035 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6036 if (arc->insn->insn_reserv_decl
6037 == DECL_INSN_RESERV (advance_cycle_insn_decl))
6038 arc->to_state->new_cycle_p = 1;
6041 /* The top level function for minimization of deterministic
6042 AUTOMATON. */
6043 static void
6044 minimize_DFA (automaton_t automaton)
6046 VEC(state_t,heap) *equiv_classes = 0;
6048 evaluate_equiv_classes (automaton, &equiv_classes);
6049 merge_states (automaton, equiv_classes);
6050 pass_states (automaton, set_new_cycle_flags);
6052 VEC_free (state_t,heap, equiv_classes);
6055 /* Values of two variables are counted number of states and arcs in an
6056 automaton. */
6057 static int curr_counted_states_num;
6058 static int curr_counted_arcs_num;
6060 /* The function is called by function `pass_states' to count states
6061 and arcs of an automaton. */
6062 static void
6063 incr_states_and_arcs_nums (state_t state)
6065 arc_t arc;
6067 curr_counted_states_num++;
6068 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6069 curr_counted_arcs_num++;
6072 /* The function counts states and arcs of AUTOMATON. */
6073 static void
6074 count_states_and_arcs (automaton_t automaton, int *states_num,
6075 int *arcs_num)
6077 curr_counted_states_num = 0;
6078 curr_counted_arcs_num = 0;
6079 pass_states (automaton, incr_states_and_arcs_nums);
6080 *states_num = curr_counted_states_num;
6081 *arcs_num = curr_counted_arcs_num;
6084 /* The function builds one DFA AUTOMATON for fast pipeline hazards
6085 recognition after checking and simplifying IR of the
6086 description. */
6087 static void
6088 build_automaton (automaton_t automaton)
6090 int states_num;
6091 int arcs_num;
6093 ticker_on (&NDFA_time);
6094 if (progress_flag)
6096 if (automaton->corresponding_automaton_decl == NULL)
6097 fprintf (stderr, "Create anonymous automaton");
6098 else
6099 fprintf (stderr, "Create automaton `%s'",
6100 automaton->corresponding_automaton_decl->name);
6101 fprintf (stderr, " (1 dot is 100 new states):");
6103 make_automaton (automaton);
6104 if (progress_flag)
6105 fprintf (stderr, " done\n");
6106 ticker_off (&NDFA_time);
6107 count_states_and_arcs (automaton, &states_num, &arcs_num);
6108 automaton->NDFA_states_num = states_num;
6109 automaton->NDFA_arcs_num = arcs_num;
6110 ticker_on (&NDFA_to_DFA_time);
6111 if (progress_flag)
6113 if (automaton->corresponding_automaton_decl == NULL)
6114 fprintf (stderr, "Make anonymous DFA");
6115 else
6116 fprintf (stderr, "Make DFA `%s'",
6117 automaton->corresponding_automaton_decl->name);
6118 fprintf (stderr, " (1 dot is 100 new states):");
6120 NDFA_to_DFA (automaton);
6121 if (progress_flag)
6122 fprintf (stderr, " done\n");
6123 ticker_off (&NDFA_to_DFA_time);
6124 count_states_and_arcs (automaton, &states_num, &arcs_num);
6125 automaton->DFA_states_num = states_num;
6126 automaton->DFA_arcs_num = arcs_num;
6127 if (!no_minimization_flag)
6129 ticker_on (&minimize_time);
6130 if (progress_flag)
6132 if (automaton->corresponding_automaton_decl == NULL)
6133 fprintf (stderr, "Minimize anonymous DFA...");
6134 else
6135 fprintf (stderr, "Minimize DFA `%s'...",
6136 automaton->corresponding_automaton_decl->name);
6138 minimize_DFA (automaton);
6139 if (progress_flag)
6140 fprintf (stderr, "done\n");
6141 ticker_off (&minimize_time);
6142 count_states_and_arcs (automaton, &states_num, &arcs_num);
6143 automaton->minimal_DFA_states_num = states_num;
6144 automaton->minimal_DFA_arcs_num = arcs_num;
6150 /* The page contains code for enumeration of all states of an automaton. */
6152 /* Variable used for enumeration of all states of an automaton. Its
6153 value is current number of automaton states. */
6154 static int curr_state_order_num;
6156 /* The function is called by function `pass_states' for enumerating
6157 states. */
6158 static void
6159 set_order_state_num (state_t state)
6161 state->order_state_num = curr_state_order_num;
6162 curr_state_order_num++;
6165 /* The function enumerates all states of AUTOMATON. */
6166 static void
6167 enumerate_states (automaton_t automaton)
6169 curr_state_order_num = 0;
6170 pass_states (automaton, set_order_state_num);
6171 automaton->achieved_states_num = curr_state_order_num;
6176 /* The page contains code for finding equivalent automaton insns
6177 (ainsns). */
6179 /* The function inserts AINSN into cyclic list
6180 CYCLIC_EQUIV_CLASS_INSN_LIST of ainsns. */
6181 static ainsn_t
6182 insert_ainsn_into_equiv_class (ainsn_t ainsn,
6183 ainsn_t cyclic_equiv_class_insn_list)
6185 if (cyclic_equiv_class_insn_list == NULL)
6186 ainsn->next_equiv_class_insn = ainsn;
6187 else
6189 ainsn->next_equiv_class_insn
6190 = cyclic_equiv_class_insn_list->next_equiv_class_insn;
6191 cyclic_equiv_class_insn_list->next_equiv_class_insn = ainsn;
6193 return ainsn;
6196 /* The function deletes equiv_class_insn into cyclic list of
6197 equivalent ainsns. */
6198 static void
6199 delete_ainsn_from_equiv_class (ainsn_t equiv_class_insn)
6201 ainsn_t curr_equiv_class_insn;
6202 ainsn_t prev_equiv_class_insn;
6204 prev_equiv_class_insn = equiv_class_insn;
6205 for (curr_equiv_class_insn = equiv_class_insn->next_equiv_class_insn;
6206 curr_equiv_class_insn != equiv_class_insn;
6207 curr_equiv_class_insn = curr_equiv_class_insn->next_equiv_class_insn)
6208 prev_equiv_class_insn = curr_equiv_class_insn;
6209 if (prev_equiv_class_insn != equiv_class_insn)
6210 prev_equiv_class_insn->next_equiv_class_insn
6211 = equiv_class_insn->next_equiv_class_insn;
6214 /* The function processes AINSN of a state in order to find equivalent
6215 ainsns. INSN_ARCS_ARRAY is table: code of insn -> out arc of the
6216 state. */
6217 static void
6218 process_insn_equiv_class (ainsn_t ainsn, arc_t *insn_arcs_array)
6220 ainsn_t next_insn;
6221 ainsn_t curr_insn;
6222 ainsn_t cyclic_insn_list;
6223 arc_t arc;
6225 gcc_assert (insn_arcs_array [ainsn->insn_reserv_decl->insn_num]);
6226 curr_insn = ainsn;
6227 /* New class of ainsns which are not equivalent to given ainsn. */
6228 cyclic_insn_list = NULL;
6231 next_insn = curr_insn->next_equiv_class_insn;
6232 arc = insn_arcs_array [curr_insn->insn_reserv_decl->insn_num];
6233 if (arc == NULL
6234 || (insn_arcs_array [ainsn->insn_reserv_decl->insn_num]->to_state
6235 != arc->to_state))
6237 delete_ainsn_from_equiv_class (curr_insn);
6238 cyclic_insn_list = insert_ainsn_into_equiv_class (curr_insn,
6239 cyclic_insn_list);
6241 curr_insn = next_insn;
6243 while (curr_insn != ainsn);
6246 /* The function processes STATE in order to find equivalent ainsns. */
6247 static void
6248 process_state_for_insn_equiv_partition (state_t state)
6250 arc_t arc;
6251 arc_t *insn_arcs_array = XCNEWVEC (arc_t, description->insns_num);
6253 /* Process insns of the arcs. */
6254 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6255 insn_arcs_array [arc->insn->insn_reserv_decl->insn_num] = arc;
6256 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6257 process_insn_equiv_class (arc->insn, insn_arcs_array);
6259 free (insn_arcs_array);
6262 /* The function searches for equivalent ainsns of AUTOMATON. */
6263 static void
6264 set_insn_equiv_classes (automaton_t automaton)
6266 ainsn_t ainsn;
6267 ainsn_t first_insn;
6268 ainsn_t curr_insn;
6269 ainsn_t cyclic_insn_list;
6270 ainsn_t insn_with_same_reservs;
6271 int equiv_classes_num;
6273 /* All insns are included in one equivalence class. */
6274 cyclic_insn_list = NULL;
6275 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6276 if (ainsn->first_insn_with_same_reservs)
6277 cyclic_insn_list = insert_ainsn_into_equiv_class (ainsn,
6278 cyclic_insn_list);
6279 /* Process insns in order to make equivalence partition. */
6280 pass_states (automaton, process_state_for_insn_equiv_partition);
6281 /* Enumerate equiv classes. */
6282 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6283 /* Set undefined value. */
6284 ainsn->insn_equiv_class_num = -1;
6285 equiv_classes_num = 0;
6286 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6287 if (ainsn->insn_equiv_class_num < 0)
6289 first_insn = ainsn;
6290 gcc_assert (first_insn->first_insn_with_same_reservs);
6291 first_insn->first_ainsn_with_given_equivalence_num = 1;
6292 curr_insn = first_insn;
6295 for (insn_with_same_reservs = curr_insn;
6296 insn_with_same_reservs != NULL;
6297 insn_with_same_reservs
6298 = insn_with_same_reservs->next_same_reservs_insn)
6299 insn_with_same_reservs->insn_equiv_class_num = equiv_classes_num;
6300 curr_insn = curr_insn->next_equiv_class_insn;
6302 while (curr_insn != first_insn);
6303 equiv_classes_num++;
6305 automaton->insn_equiv_classes_num = equiv_classes_num;
6310 /* This page contains code for creating DFA(s) and calls functions
6311 building them. */
6314 /* The following value is used to prevent floating point overflow for
6315 estimating an automaton bound. The value should be less DBL_MAX on
6316 the host machine. We use here approximate minimum of maximal
6317 double floating point value required by ANSI C standard. It
6318 will work for non ANSI sun compiler too. */
6320 #define MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND 1.0E37
6322 /* The function estimate size of the single DFA used by PHR (pipeline
6323 hazards recognizer). */
6324 static double
6325 estimate_one_automaton_bound (void)
6327 decl_t decl;
6328 double one_automaton_estimation_bound;
6329 double root_value;
6330 int i;
6332 one_automaton_estimation_bound = 1.0;
6333 for (i = 0; i < description->decls_num; i++)
6335 decl = description->decls [i];
6336 if (decl->mode == dm_unit)
6338 root_value = exp (log (DECL_UNIT (decl)->max_occ_cycle_num
6339 - DECL_UNIT (decl)->min_occ_cycle_num + 1.0)
6340 / automata_num);
6341 if (MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND / root_value
6342 > one_automaton_estimation_bound)
6343 one_automaton_estimation_bound *= root_value;
6346 return one_automaton_estimation_bound;
6349 /* The function compares unit declarations according to their maximal
6350 cycle in reservations. */
6351 static int
6352 compare_max_occ_cycle_nums (const void *unit_decl_1,
6353 const void *unit_decl_2)
6355 if ((DECL_UNIT (*(const_decl_t const*) unit_decl_1)->max_occ_cycle_num)
6356 < (DECL_UNIT (*(const_decl_t const*) unit_decl_2)->max_occ_cycle_num))
6357 return 1;
6358 else if ((DECL_UNIT (*(const_decl_t const*) unit_decl_1)->max_occ_cycle_num)
6359 == (DECL_UNIT (*(const_decl_t const*) unit_decl_2)->max_occ_cycle_num))
6360 return 0;
6361 else
6362 return -1;
6365 /* The function makes heuristic assigning automata to units. Actually
6366 efficacy of the algorithm has been checked yet??? */
6368 static void
6369 units_to_automata_heuristic_distr (void)
6371 double estimation_bound;
6372 int automaton_num;
6373 int rest_units_num;
6374 double bound_value;
6375 unit_decl_t *unit_decls;
6376 int i, j;
6378 if (description->units_num == 0)
6379 return;
6380 estimation_bound = estimate_one_automaton_bound ();
6381 unit_decls = XNEWVEC (unit_decl_t, description->units_num);
6383 for (i = 0, j = 0; i < description->decls_num; i++)
6384 if (description->decls[i]->mode == dm_unit)
6385 unit_decls[j++] = DECL_UNIT (description->decls[i]);
6386 gcc_assert (j == description->units_num);
6388 qsort (unit_decls, description->units_num,
6389 sizeof (unit_decl_t), compare_max_occ_cycle_nums);
6391 automaton_num = 0;
6392 bound_value = unit_decls[0]->max_occ_cycle_num;
6393 unit_decls[0]->corresponding_automaton_num = automaton_num;
6395 for (i = 1; i < description->units_num; i++)
6397 rest_units_num = description->units_num - i + 1;
6398 gcc_assert (automata_num - automaton_num - 1 <= rest_units_num);
6399 if (automaton_num < automata_num - 1
6400 && ((automata_num - automaton_num - 1 == rest_units_num)
6401 || (bound_value
6402 > (estimation_bound
6403 / unit_decls[i]->max_occ_cycle_num))))
6405 bound_value = unit_decls[i]->max_occ_cycle_num;
6406 automaton_num++;
6408 else
6409 bound_value *= unit_decls[i]->max_occ_cycle_num;
6410 unit_decls[i]->corresponding_automaton_num = automaton_num;
6412 gcc_assert (automaton_num == automata_num - 1);
6413 free (unit_decls);
6416 /* The functions creates automaton insns for each automata. Automaton
6417 insn is simply insn for given automaton which makes reservation
6418 only of units of the automaton. */
6419 static ainsn_t
6420 create_ainsns (void)
6422 decl_t decl;
6423 ainsn_t first_ainsn;
6424 ainsn_t curr_ainsn;
6425 ainsn_t prev_ainsn;
6426 int i;
6428 first_ainsn = NULL;
6429 prev_ainsn = NULL;
6430 for (i = 0; i < description->decls_num; i++)
6432 decl = description->decls [i];
6433 if (decl->mode == dm_insn_reserv)
6435 curr_ainsn = XCREATENODE (struct ainsn);
6436 curr_ainsn->insn_reserv_decl = DECL_INSN_RESERV (decl);
6437 curr_ainsn->important_p = FALSE;
6438 curr_ainsn->next_ainsn = NULL;
6439 if (prev_ainsn == NULL)
6440 first_ainsn = curr_ainsn;
6441 else
6442 prev_ainsn->next_ainsn = curr_ainsn;
6443 prev_ainsn = curr_ainsn;
6446 return first_ainsn;
6449 /* The function assigns automata to units according to constructions
6450 `define_automaton' in the description. */
6451 static void
6452 units_to_automata_distr (void)
6454 decl_t decl;
6455 int i;
6457 for (i = 0; i < description->decls_num; i++)
6459 decl = description->decls [i];
6460 if (decl->mode == dm_unit)
6462 if (DECL_UNIT (decl)->automaton_decl == NULL
6463 || (DECL_UNIT (decl)->automaton_decl->corresponding_automaton
6464 == NULL))
6465 /* Distribute to the first automaton. */
6466 DECL_UNIT (decl)->corresponding_automaton_num = 0;
6467 else
6468 DECL_UNIT (decl)->corresponding_automaton_num
6469 = (DECL_UNIT (decl)->automaton_decl
6470 ->corresponding_automaton->automaton_order_num);
6475 /* The function creates DFA(s) for fast pipeline hazards recognition
6476 after checking and simplifying IR of the description. */
6477 static void
6478 create_automata (void)
6480 automaton_t curr_automaton;
6481 automaton_t prev_automaton;
6482 decl_t decl;
6483 int curr_automaton_num;
6484 int i;
6486 if (automata_num != 0)
6488 units_to_automata_heuristic_distr ();
6489 for (prev_automaton = NULL, curr_automaton_num = 0;
6490 curr_automaton_num < automata_num;
6491 curr_automaton_num++, prev_automaton = curr_automaton)
6493 curr_automaton = XCREATENODE (struct automaton);
6494 curr_automaton->ainsn_list = create_ainsns ();
6495 curr_automaton->corresponding_automaton_decl = NULL;
6496 curr_automaton->next_automaton = NULL;
6497 curr_automaton->automaton_order_num = curr_automaton_num;
6498 if (prev_automaton == NULL)
6499 description->first_automaton = curr_automaton;
6500 else
6501 prev_automaton->next_automaton = curr_automaton;
6504 else
6506 curr_automaton_num = 0;
6507 prev_automaton = NULL;
6508 for (i = 0; i < description->decls_num; i++)
6510 decl = description->decls [i];
6511 if (decl->mode == dm_automaton
6512 && DECL_AUTOMATON (decl)->automaton_is_used)
6514 curr_automaton = XCREATENODE (struct automaton);
6515 curr_automaton->ainsn_list = create_ainsns ();
6516 curr_automaton->corresponding_automaton_decl
6517 = DECL_AUTOMATON (decl);
6518 curr_automaton->next_automaton = NULL;
6519 DECL_AUTOMATON (decl)->corresponding_automaton = curr_automaton;
6520 curr_automaton->automaton_order_num = curr_automaton_num;
6521 if (prev_automaton == NULL)
6522 description->first_automaton = curr_automaton;
6523 else
6524 prev_automaton->next_automaton = curr_automaton;
6525 curr_automaton_num++;
6526 prev_automaton = curr_automaton;
6529 if (curr_automaton_num == 0)
6531 curr_automaton = XCREATENODE (struct automaton);
6532 curr_automaton->ainsn_list = create_ainsns ();
6533 curr_automaton->corresponding_automaton_decl = NULL;
6534 curr_automaton->next_automaton = NULL;
6535 description->first_automaton = curr_automaton;
6537 units_to_automata_distr ();
6539 NDFA_time = create_ticker ();
6540 ticker_off (&NDFA_time);
6541 NDFA_to_DFA_time = create_ticker ();
6542 ticker_off (&NDFA_to_DFA_time);
6543 minimize_time = create_ticker ();
6544 ticker_off (&minimize_time);
6545 equiv_time = create_ticker ();
6546 ticker_off (&equiv_time);
6547 for (curr_automaton = description->first_automaton;
6548 curr_automaton != NULL;
6549 curr_automaton = curr_automaton->next_automaton)
6551 if (progress_flag)
6553 if (curr_automaton->corresponding_automaton_decl == NULL)
6554 fprintf (stderr, "Prepare anonymous automaton creation ... ");
6555 else
6556 fprintf (stderr, "Prepare automaton `%s' creation...",
6557 curr_automaton->corresponding_automaton_decl->name);
6559 create_alt_states (curr_automaton);
6560 form_ainsn_with_same_reservs (curr_automaton);
6561 if (progress_flag)
6562 fprintf (stderr, "done\n");
6563 build_automaton (curr_automaton);
6564 enumerate_states (curr_automaton);
6565 ticker_on (&equiv_time);
6566 set_insn_equiv_classes (curr_automaton);
6567 ticker_off (&equiv_time);
6573 /* This page contains code for forming string representation of
6574 regexp. The representation is formed on IR obstack. So you should
6575 not work with IR obstack between regexp_representation and
6576 finish_regexp_representation calls. */
6578 /* This recursive function forms string representation of regexp
6579 (without tailing '\0'). */
6580 static void
6581 form_regexp (regexp_t regexp)
6583 int i;
6585 switch (regexp->mode)
6587 case rm_unit: case rm_reserv:
6589 const char *name = (regexp->mode == rm_unit
6590 ? REGEXP_UNIT (regexp)->name
6591 : REGEXP_RESERV (regexp)->name);
6593 obstack_grow (&irp, name, strlen (name));
6594 break;
6597 case rm_sequence:
6598 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
6600 if (i != 0)
6601 obstack_1grow (&irp, ',');
6602 form_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
6604 break;
6606 case rm_allof:
6607 obstack_1grow (&irp, '(');
6608 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
6610 if (i != 0)
6611 obstack_1grow (&irp, '+');
6612 if (REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_sequence
6613 || REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_oneof)
6614 obstack_1grow (&irp, '(');
6615 form_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
6616 if (REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_sequence
6617 || REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_oneof)
6618 obstack_1grow (&irp, ')');
6620 obstack_1grow (&irp, ')');
6621 break;
6623 case rm_oneof:
6624 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
6626 if (i != 0)
6627 obstack_1grow (&irp, '|');
6628 if (REGEXP_ONEOF (regexp)->regexps[i]->mode == rm_sequence)
6629 obstack_1grow (&irp, '(');
6630 form_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
6631 if (REGEXP_ONEOF (regexp)->regexps[i]->mode == rm_sequence)
6632 obstack_1grow (&irp, ')');
6634 break;
6636 case rm_repeat:
6638 char digits [30];
6640 if (REGEXP_REPEAT (regexp)->regexp->mode == rm_sequence
6641 || REGEXP_REPEAT (regexp)->regexp->mode == rm_allof
6642 || REGEXP_REPEAT (regexp)->regexp->mode == rm_oneof)
6643 obstack_1grow (&irp, '(');
6644 form_regexp (REGEXP_REPEAT (regexp)->regexp);
6645 if (REGEXP_REPEAT (regexp)->regexp->mode == rm_sequence
6646 || REGEXP_REPEAT (regexp)->regexp->mode == rm_allof
6647 || REGEXP_REPEAT (regexp)->regexp->mode == rm_oneof)
6648 obstack_1grow (&irp, ')');
6649 sprintf (digits, "*%d", REGEXP_REPEAT (regexp)->repeat_num);
6650 obstack_grow (&irp, digits, strlen (digits));
6651 break;
6654 case rm_nothing:
6655 obstack_grow (&irp, NOTHING_NAME, strlen (NOTHING_NAME));
6656 break;
6658 default:
6659 gcc_unreachable ();
6663 /* The function returns string representation of REGEXP on IR
6664 obstack. */
6665 static const char *
6666 regexp_representation (regexp_t regexp)
6668 form_regexp (regexp);
6669 obstack_1grow (&irp, '\0');
6670 return obstack_base (&irp);
6673 /* The function frees memory allocated for last formed string
6674 representation of regexp. */
6675 static void
6676 finish_regexp_representation (void)
6678 int length = obstack_object_size (&irp);
6680 obstack_blank_fast (&irp, -length);
6685 /* This page contains code for output PHR (pipeline hazards recognizer). */
6687 /* The function outputs minimal C type which is sufficient for
6688 representation numbers in range min_range_value and
6689 max_range_value. Because host machine and build machine may be
6690 different, we use here minimal values required by ANSI C standard
6691 instead of UCHAR_MAX, SHRT_MAX, SHRT_MIN, etc. This is a good
6692 approximation. */
6694 static void
6695 output_range_type (FILE *f, long int min_range_value,
6696 long int max_range_value)
6698 if (min_range_value >= 0 && max_range_value <= 255)
6699 fprintf (f, "unsigned char");
6700 else if (min_range_value >= -127 && max_range_value <= 127)
6701 fprintf (f, "signed char");
6702 else if (min_range_value >= 0 && max_range_value <= 65535)
6703 fprintf (f, "unsigned short");
6704 else if (min_range_value >= -32767 && max_range_value <= 32767)
6705 fprintf (f, "short");
6706 else
6707 fprintf (f, "int");
6710 /* The function outputs all initialization values of VECT. */
6711 static void
6712 output_vect (vla_hwint_t vect)
6714 int els_on_line;
6715 size_t vect_length = VEC_length (vect_el_t, vect);
6716 size_t i;
6718 els_on_line = 1;
6719 if (vect_length == 0)
6720 fputs ("0 /* This is dummy el because the vect is empty */", output_file);
6721 else
6722 for (i = 0; i < vect_length; i++)
6724 fprintf (output_file, "%5ld", (long) VEC_index (vect_el_t, vect, i));
6725 if (els_on_line == 10)
6727 els_on_line = 0;
6728 fputs (",\n", output_file);
6730 else if (i < vect_length-1)
6731 fputs (", ", output_file);
6732 els_on_line++;
6736 /* The following is name of the structure which represents DFA(s) for
6737 PHR. */
6738 #define CHIP_NAME "DFA_chip"
6740 /* The following is name of member which represents state of a DFA for
6741 PHR. */
6742 static void
6743 output_chip_member_name (FILE *f, automaton_t automaton)
6745 if (automaton->corresponding_automaton_decl == NULL)
6746 fprintf (f, "automaton_state_%d", automaton->automaton_order_num);
6747 else
6748 fprintf (f, "%s_automaton_state",
6749 automaton->corresponding_automaton_decl->name);
6752 /* The following is name of temporary variable which stores state of a
6753 DFA for PHR. */
6754 static void
6755 output_temp_chip_member_name (FILE *f, automaton_t automaton)
6757 fprintf (f, "_");
6758 output_chip_member_name (f, automaton);
6761 /* This is name of macro value which is code of pseudo_insn
6762 representing advancing cpu cycle. Its value is used as internal
6763 code unknown insn. */
6764 #define ADVANCE_CYCLE_VALUE_NAME "DFA__ADVANCE_CYCLE"
6766 /* Output name of translate vector for given automaton. */
6767 static void
6768 output_translate_vect_name (FILE *f, automaton_t automaton)
6770 if (automaton->corresponding_automaton_decl == NULL)
6771 fprintf (f, "translate_%d", automaton->automaton_order_num);
6772 else
6773 fprintf (f, "%s_translate", automaton->corresponding_automaton_decl->name);
6776 /* Output name for simple transition table representation. */
6777 static void
6778 output_trans_full_vect_name (FILE *f, automaton_t automaton)
6780 if (automaton->corresponding_automaton_decl == NULL)
6781 fprintf (f, "transitions_%d", automaton->automaton_order_num);
6782 else
6783 fprintf (f, "%s_transitions",
6784 automaton->corresponding_automaton_decl->name);
6787 /* Output name of comb vector of the transition table for given
6788 automaton. */
6789 static void
6790 output_trans_comb_vect_name (FILE *f, automaton_t automaton)
6792 if (automaton->corresponding_automaton_decl == NULL)
6793 fprintf (f, "transitions_%d", automaton->automaton_order_num);
6794 else
6795 fprintf (f, "%s_transitions",
6796 automaton->corresponding_automaton_decl->name);
6799 /* Output name of check vector of the transition table for given
6800 automaton. */
6801 static void
6802 output_trans_check_vect_name (FILE *f, automaton_t automaton)
6804 if (automaton->corresponding_automaton_decl == NULL)
6805 fprintf (f, "check_%d", automaton->automaton_order_num);
6806 else
6807 fprintf (f, "%s_check", automaton->corresponding_automaton_decl->name);
6810 /* Output name of base vector of the transition table for given
6811 automaton. */
6812 static void
6813 output_trans_base_vect_name (FILE *f, automaton_t automaton)
6815 if (automaton->corresponding_automaton_decl == NULL)
6816 fprintf (f, "base_%d", automaton->automaton_order_num);
6817 else
6818 fprintf (f, "%s_base", automaton->corresponding_automaton_decl->name);
6821 /* Output name of simple min issue delay table representation. */
6822 static void
6823 output_min_issue_delay_vect_name (FILE *f, automaton_t automaton)
6825 if (automaton->corresponding_automaton_decl == NULL)
6826 fprintf (f, "min_issue_delay_%d", automaton->automaton_order_num);
6827 else
6828 fprintf (f, "%s_min_issue_delay",
6829 automaton->corresponding_automaton_decl->name);
6832 /* Output name of deadlock vector for given automaton. */
6833 static void
6834 output_dead_lock_vect_name (FILE *f, automaton_t automaton)
6836 if (automaton->corresponding_automaton_decl == NULL)
6837 fprintf (f, "dead_lock_%d", automaton->automaton_order_num);
6838 else
6839 fprintf (f, "%s_dead_lock", automaton->corresponding_automaton_decl->name);
6842 /* Output name of reserved units table for AUTOMATON into file F. */
6843 static void
6844 output_reserved_units_table_name (FILE *f, automaton_t automaton)
6846 if (automaton->corresponding_automaton_decl == NULL)
6847 fprintf (f, "reserved_units_%d", automaton->automaton_order_num);
6848 else
6849 fprintf (f, "%s_reserved_units",
6850 automaton->corresponding_automaton_decl->name);
6853 /* Name of the PHR interface macro. */
6854 #define CPU_UNITS_QUERY_MACRO_NAME "CPU_UNITS_QUERY"
6856 /* Names of an internal functions: */
6857 #define INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME "internal_min_issue_delay"
6859 /* This is external type of DFA(s) state. */
6860 #define STATE_TYPE_NAME "state_t"
6862 #define INTERNAL_TRANSITION_FUNC_NAME "internal_state_transition"
6864 #define INTERNAL_RESET_FUNC_NAME "internal_reset"
6866 #define INTERNAL_DEAD_LOCK_FUNC_NAME "internal_state_dead_lock_p"
6868 #define INTERNAL_INSN_LATENCY_FUNC_NAME "internal_insn_latency"
6870 /* Name of cache of insn dfa codes. */
6871 #define DFA_INSN_CODES_VARIABLE_NAME "dfa_insn_codes"
6873 /* Name of length of cache of insn dfa codes. */
6874 #define DFA_INSN_CODES_LENGTH_VARIABLE_NAME "dfa_insn_codes_length"
6876 /* Names of the PHR interface functions: */
6877 #define SIZE_FUNC_NAME "state_size"
6879 #define TRANSITION_FUNC_NAME "state_transition"
6881 #define MIN_ISSUE_DELAY_FUNC_NAME "min_issue_delay"
6883 #define MIN_INSN_CONFLICT_DELAY_FUNC_NAME "min_insn_conflict_delay"
6885 #define DEAD_LOCK_FUNC_NAME "state_dead_lock_p"
6887 #define RESET_FUNC_NAME "state_reset"
6889 #define INSN_LATENCY_FUNC_NAME "insn_latency"
6891 #define PRINT_RESERVATION_FUNC_NAME "print_reservation"
6893 #define GET_CPU_UNIT_CODE_FUNC_NAME "get_cpu_unit_code"
6895 #define CPU_UNIT_RESERVATION_P_FUNC_NAME "cpu_unit_reservation_p"
6897 #define INSN_HAS_DFA_RESERVATION_P_FUNC_NAME "insn_has_dfa_reservation_p"
6899 #define DFA_CLEAN_INSN_CACHE_FUNC_NAME "dfa_clean_insn_cache"
6901 #define DFA_CLEAR_SINGLE_INSN_CACHE_FUNC_NAME "dfa_clear_single_insn_cache"
6903 #define DFA_START_FUNC_NAME "dfa_start"
6905 #define DFA_FINISH_FUNC_NAME "dfa_finish"
6907 /* Names of parameters of the PHR interface functions. */
6908 #define STATE_NAME "state"
6910 #define INSN_PARAMETER_NAME "insn"
6912 #define INSN2_PARAMETER_NAME "insn2"
6914 #define CHIP_PARAMETER_NAME "chip"
6916 #define FILE_PARAMETER_NAME "f"
6918 #define CPU_UNIT_NAME_PARAMETER_NAME "cpu_unit_name"
6920 #define CPU_CODE_PARAMETER_NAME "cpu_unit_code"
6922 /* Names of the variables whose values are internal insn code of rtx
6923 insn. */
6924 #define INTERNAL_INSN_CODE_NAME "insn_code"
6926 #define INTERNAL_INSN2_CODE_NAME "insn2_code"
6928 /* Names of temporary variables in some functions. */
6929 #define TEMPORARY_VARIABLE_NAME "temp"
6931 #define I_VARIABLE_NAME "i"
6933 /* Name of result variable in some functions. */
6934 #define RESULT_VARIABLE_NAME "res"
6936 /* Name of function (attribute) to translate insn into internal insn
6937 code. */
6938 #define INTERNAL_DFA_INSN_CODE_FUNC_NAME "internal_dfa_insn_code"
6940 /* Name of function (attribute) to translate insn into internal insn
6941 code with caching. */
6942 #define DFA_INSN_CODE_FUNC_NAME "dfa_insn_code"
6944 /* Output C type which is used for representation of codes of states
6945 of AUTOMATON. */
6946 static void
6947 output_state_member_type (FILE *f, automaton_t automaton)
6949 output_range_type (f, 0, automaton->achieved_states_num);
6952 /* Output definition of the structure representing current DFA(s)
6953 state(s). */
6954 static void
6955 output_chip_definitions (void)
6957 automaton_t automaton;
6959 fprintf (output_file, "struct %s\n{\n", CHIP_NAME);
6960 for (automaton = description->first_automaton;
6961 automaton != NULL;
6962 automaton = automaton->next_automaton)
6964 fprintf (output_file, " ");
6965 output_state_member_type (output_file, automaton);
6966 fprintf (output_file, " ");
6967 output_chip_member_name (output_file, automaton);
6968 fprintf (output_file, ";\n");
6970 fprintf (output_file, "};\n\n");
6971 #if 0
6972 fprintf (output_file, "static struct %s %s;\n\n", CHIP_NAME, CHIP_NAME);
6973 #endif
6977 /* The function outputs translate vector of internal insn code into
6978 insn equivalence class number. The equivalence class number is
6979 used to access to table and vectors representing DFA(s). */
6980 static void
6981 output_translate_vect (automaton_t automaton)
6983 ainsn_t ainsn;
6984 int insn_value;
6985 vla_hwint_t translate_vect;
6987 translate_vect = VEC_alloc (vect_el_t,heap, description->insns_num);
6989 for (insn_value = 0; insn_value < description->insns_num; insn_value++)
6990 /* Undefined value */
6991 VEC_quick_push (vect_el_t, translate_vect,
6992 automaton->insn_equiv_classes_num);
6994 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6995 VEC_replace (vect_el_t, translate_vect,
6996 ainsn->insn_reserv_decl->insn_num,
6997 ainsn->insn_equiv_class_num);
6999 fprintf (output_file,
7000 "/* Vector translating external insn codes to internal ones.*/\n");
7001 fprintf (output_file, "static const ");
7002 output_range_type (output_file, 0, automaton->insn_equiv_classes_num);
7003 fprintf (output_file, " ");
7004 output_translate_vect_name (output_file, automaton);
7005 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7006 output_vect (translate_vect);
7007 fprintf (output_file, "};\n\n");
7008 VEC_free (vect_el_t,heap, translate_vect);
7011 /* The value in a table state x ainsn -> something which represents
7012 undefined value. */
7013 static int undefined_vect_el_value;
7015 /* The following function returns nonzero value if the best
7016 representation of the table is comb vector. */
7017 static int
7018 comb_vect_p (state_ainsn_table_t tab)
7020 return (2 * VEC_length (vect_el_t, tab->full_vect)
7021 > 5 * VEC_length (vect_el_t, tab->comb_vect));
7024 /* The following function creates new table for AUTOMATON. */
7025 static state_ainsn_table_t
7026 create_state_ainsn_table (automaton_t automaton)
7028 state_ainsn_table_t tab;
7029 int full_vect_length;
7030 int i;
7032 tab = XCREATENODE (struct state_ainsn_table);
7033 tab->automaton = automaton;
7035 tab->comb_vect = VEC_alloc (vect_el_t,heap, 10000);
7036 tab->check_vect = VEC_alloc (vect_el_t,heap, 10000);
7038 tab->base_vect = 0;
7039 VEC_safe_grow (vect_el_t,heap, tab->base_vect,
7040 automaton->achieved_states_num);
7042 full_vect_length = (automaton->insn_equiv_classes_num
7043 * automaton->achieved_states_num);
7044 tab->full_vect = VEC_alloc (vect_el_t,heap, full_vect_length);
7045 for (i = 0; i < full_vect_length; i++)
7046 VEC_quick_push (vect_el_t, tab->full_vect, undefined_vect_el_value);
7048 tab->min_base_vect_el_value = 0;
7049 tab->max_base_vect_el_value = 0;
7050 tab->min_comb_vect_el_value = 0;
7051 tab->max_comb_vect_el_value = 0;
7052 return tab;
7055 /* The following function outputs the best C representation of the
7056 table TAB of given TABLE_NAME. */
7057 static void
7058 output_state_ainsn_table (state_ainsn_table_t tab, const char *table_name,
7059 void (*output_full_vect_name_func) (FILE *, automaton_t),
7060 void (*output_comb_vect_name_func) (FILE *, automaton_t),
7061 void (*output_check_vect_name_func) (FILE *, automaton_t),
7062 void (*output_base_vect_name_func) (FILE *, automaton_t))
7064 if (!comb_vect_p (tab))
7066 fprintf (output_file, "/* Vector for %s. */\n", table_name);
7067 fprintf (output_file, "static const ");
7068 output_range_type (output_file, tab->min_comb_vect_el_value,
7069 tab->max_comb_vect_el_value);
7070 fprintf (output_file, " ");
7071 (*output_full_vect_name_func) (output_file, tab->automaton);
7072 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7073 output_vect (tab->full_vect);
7074 fprintf (output_file, "};\n\n");
7076 else
7078 fprintf (output_file, "/* Comb vector for %s. */\n", table_name);
7079 fprintf (output_file, "static const ");
7080 output_range_type (output_file, tab->min_comb_vect_el_value,
7081 tab->max_comb_vect_el_value);
7082 fprintf (output_file, " ");
7083 (*output_comb_vect_name_func) (output_file, tab->automaton);
7084 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7085 output_vect (tab->comb_vect);
7086 fprintf (output_file, "};\n\n");
7087 fprintf (output_file, "/* Check vector for %s. */\n", table_name);
7088 fprintf (output_file, "static const ");
7089 output_range_type (output_file, 0, tab->automaton->achieved_states_num);
7090 fprintf (output_file, " ");
7091 (*output_check_vect_name_func) (output_file, tab->automaton);
7092 fprintf (output_file, "[] = {\n");
7093 output_vect (tab->check_vect);
7094 fprintf (output_file, "};\n\n");
7095 fprintf (output_file, "/* Base vector for %s. */\n", table_name);
7096 fprintf (output_file, "static const ");
7097 output_range_type (output_file, tab->min_base_vect_el_value,
7098 tab->max_base_vect_el_value);
7099 fprintf (output_file, " ");
7100 (*output_base_vect_name_func) (output_file, tab->automaton);
7101 fprintf (output_file, "[] = {\n");
7102 output_vect (tab->base_vect);
7103 fprintf (output_file, "};\n\n");
7107 /* The following function adds vector VECT to table TAB as its line
7108 with number VECT_NUM. */
7109 static void
7110 add_vect (state_ainsn_table_t tab, int vect_num, vla_hwint_t vect)
7112 int vect_length;
7113 size_t real_vect_length;
7114 int comb_vect_index;
7115 int comb_vect_els_num;
7116 int vect_index;
7117 int first_unempty_vect_index;
7118 int additional_els_num;
7119 int no_state_value;
7120 vect_el_t vect_el;
7121 int i;
7122 unsigned long vect_mask, comb_vect_mask;
7124 vect_length = VEC_length (vect_el_t, vect);
7125 gcc_assert (vect_length);
7126 gcc_assert (VEC_last (vect_el_t, vect) != undefined_vect_el_value);
7127 real_vect_length = tab->automaton->insn_equiv_classes_num;
7128 /* Form full vector in the table: */
7130 size_t full_base = tab->automaton->insn_equiv_classes_num * vect_num;
7131 if (VEC_length (vect_el_t, tab->full_vect) < full_base + vect_length)
7132 VEC_safe_grow (vect_el_t,heap, tab->full_vect,
7133 full_base + vect_length);
7134 for (i = 0; i < vect_length; i++)
7135 VEC_replace (vect_el_t, tab->full_vect, full_base + i,
7136 VEC_index (vect_el_t, vect, i));
7138 /* Form comb vector in the table: */
7139 gcc_assert (VEC_length (vect_el_t, tab->comb_vect)
7140 == VEC_length (vect_el_t, tab->check_vect));
7142 comb_vect_els_num = VEC_length (vect_el_t, tab->comb_vect);
7143 for (first_unempty_vect_index = 0;
7144 first_unempty_vect_index < vect_length;
7145 first_unempty_vect_index++)
7146 if (VEC_index (vect_el_t, vect, first_unempty_vect_index)
7147 != undefined_vect_el_value)
7148 break;
7150 /* Search for the place in comb vect for the inserted vect. */
7152 /* Slow case. */
7153 if (vect_length - first_unempty_vect_index >= SIZEOF_LONG * CHAR_BIT)
7155 for (comb_vect_index = 0;
7156 comb_vect_index < comb_vect_els_num;
7157 comb_vect_index++)
7159 for (vect_index = first_unempty_vect_index;
7160 vect_index < vect_length
7161 && vect_index + comb_vect_index < comb_vect_els_num;
7162 vect_index++)
7163 if (VEC_index (vect_el_t, vect, vect_index)
7164 != undefined_vect_el_value
7165 && (VEC_index (vect_el_t, tab->comb_vect,
7166 vect_index + comb_vect_index)
7167 != undefined_vect_el_value))
7168 break;
7169 if (vect_index >= vect_length
7170 || vect_index + comb_vect_index >= comb_vect_els_num)
7171 break;
7173 goto found;
7176 /* Fast case. */
7177 vect_mask = 0;
7178 for (vect_index = first_unempty_vect_index;
7179 vect_index < vect_length;
7180 vect_index++)
7182 vect_mask = vect_mask << 1;
7183 if (VEC_index (vect_el_t, vect, vect_index) != undefined_vect_el_value)
7184 vect_mask |= 1;
7187 /* Search for the place in comb vect for the inserted vect. */
7188 comb_vect_index = 0;
7189 if (comb_vect_els_num == 0)
7190 goto found;
7192 comb_vect_mask = 0;
7193 for (vect_index = first_unempty_vect_index;
7194 vect_index < vect_length && vect_index < comb_vect_els_num;
7195 vect_index++)
7197 comb_vect_mask <<= 1;
7198 if (vect_index + comb_vect_index < comb_vect_els_num
7199 && VEC_index (vect_el_t, tab->comb_vect, vect_index + comb_vect_index)
7200 != undefined_vect_el_value)
7201 comb_vect_mask |= 1;
7203 if ((vect_mask & comb_vect_mask) == 0)
7204 goto found;
7206 for (comb_vect_index = 1, i = vect_length; i < comb_vect_els_num;
7207 comb_vect_index++, i++)
7209 comb_vect_mask = (comb_vect_mask << 1) | 1;
7210 comb_vect_mask ^= (VEC_index (vect_el_t, tab->comb_vect, i)
7211 == undefined_vect_el_value);
7212 if ((vect_mask & comb_vect_mask) == 0)
7213 goto found;
7215 for ( ; comb_vect_index < comb_vect_els_num; comb_vect_index++)
7217 comb_vect_mask <<= 1;
7218 if ((vect_mask & comb_vect_mask) == 0)
7219 goto found;
7222 found:
7223 /* Slot was found. */
7224 additional_els_num = comb_vect_index + real_vect_length - comb_vect_els_num;
7225 if (additional_els_num < 0)
7226 additional_els_num = 0;
7227 /* Expand comb and check vectors. */
7228 vect_el = undefined_vect_el_value;
7229 no_state_value = tab->automaton->achieved_states_num;
7230 while (additional_els_num > 0)
7232 VEC_safe_push (vect_el_t,heap, tab->comb_vect, vect_el);
7233 VEC_safe_push (vect_el_t,heap, tab->check_vect, no_state_value);
7234 additional_els_num--;
7236 gcc_assert (VEC_length (vect_el_t, tab->comb_vect)
7237 >= comb_vect_index + real_vect_length);
7238 /* Fill comb and check vectors. */
7239 for (vect_index = 0; vect_index < vect_length; vect_index++)
7240 if (VEC_index (vect_el_t, vect, vect_index) != undefined_vect_el_value)
7242 vect_el_t x = VEC_index (vect_el_t, vect, vect_index);
7243 gcc_assert (VEC_index (vect_el_t, tab->comb_vect,
7244 comb_vect_index + vect_index)
7245 == undefined_vect_el_value);
7246 gcc_assert (x >= 0);
7247 if (tab->max_comb_vect_el_value < x)
7248 tab->max_comb_vect_el_value = x;
7249 if (tab->min_comb_vect_el_value > x)
7250 tab->min_comb_vect_el_value = x;
7251 VEC_replace (vect_el_t, tab->comb_vect,
7252 comb_vect_index + vect_index, x);
7253 VEC_replace (vect_el_t, tab->check_vect,
7254 comb_vect_index + vect_index, vect_num);
7256 if (tab->max_comb_vect_el_value < undefined_vect_el_value)
7257 tab->max_comb_vect_el_value = undefined_vect_el_value;
7258 if (tab->min_comb_vect_el_value > undefined_vect_el_value)
7259 tab->min_comb_vect_el_value = undefined_vect_el_value;
7260 if (tab->max_base_vect_el_value < comb_vect_index)
7261 tab->max_base_vect_el_value = comb_vect_index;
7262 if (tab->min_base_vect_el_value > comb_vect_index)
7263 tab->min_base_vect_el_value = comb_vect_index;
7265 VEC_replace (vect_el_t, tab->base_vect, vect_num, comb_vect_index);
7268 /* Return number of out arcs of STATE. */
7269 static int
7270 out_state_arcs_num (const_state_t state)
7272 int result;
7273 arc_t arc;
7275 result = 0;
7276 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
7278 gcc_assert (arc->insn);
7279 if (arc->insn->first_ainsn_with_given_equivalence_num)
7280 result++;
7282 return result;
7285 /* Compare number of possible transitions from the states. */
7286 static int
7287 compare_transition_els_num (const void *state_ptr_1,
7288 const void *state_ptr_2)
7290 const int transition_els_num_1
7291 = out_state_arcs_num (*(const_state_t const*) state_ptr_1);
7292 const int transition_els_num_2
7293 = out_state_arcs_num (*(const_state_t const*) state_ptr_2);
7295 if (transition_els_num_1 < transition_els_num_2)
7296 return 1;
7297 else if (transition_els_num_1 == transition_els_num_2)
7298 return 0;
7299 else
7300 return -1;
7303 /* The function adds element EL_VALUE to vector VECT for a table state
7304 x AINSN. */
7305 static void
7306 add_vect_el (vla_hwint_t *vect, ainsn_t ainsn, int el_value)
7308 int equiv_class_num;
7309 int vect_index;
7311 gcc_assert (ainsn);
7312 equiv_class_num = ainsn->insn_equiv_class_num;
7313 for (vect_index = VEC_length (vect_el_t, *vect);
7314 vect_index <= equiv_class_num;
7315 vect_index++)
7316 VEC_safe_push (vect_el_t,heap, *vect, undefined_vect_el_value);
7317 VEC_replace (vect_el_t, *vect, equiv_class_num, el_value);
7320 /* This is for forming vector of states of an automaton. */
7321 static VEC(state_t,heap) *output_states_vect;
7323 /* The function is called by function pass_states. The function adds
7324 STATE to `output_states_vect'. */
7325 static void
7326 add_states_vect_el (state_t state)
7328 VEC_safe_push (state_t,heap, output_states_vect, state);
7331 /* Form and output vectors (comb, check, base or full vector)
7332 representing transition table of AUTOMATON. */
7333 static void
7334 output_trans_table (automaton_t automaton)
7336 size_t i;
7337 arc_t arc;
7338 vla_hwint_t transition_vect = 0;
7340 undefined_vect_el_value = automaton->achieved_states_num;
7341 automaton->trans_table = create_state_ainsn_table (automaton);
7342 /* Create vect of pointers to states ordered by num of transitions
7343 from the state (state with the maximum num is the first). */
7344 output_states_vect = 0;
7345 pass_states (automaton, add_states_vect_el);
7346 qsort (VEC_address (state_t, output_states_vect),
7347 VEC_length (state_t, output_states_vect),
7348 sizeof (state_t), compare_transition_els_num);
7350 for (i = 0; i < VEC_length (state_t, output_states_vect); i++)
7352 VEC_truncate (vect_el_t, transition_vect, 0);
7353 for (arc = first_out_arc (VEC_index (state_t, output_states_vect, i));
7354 arc != NULL;
7355 arc = next_out_arc (arc))
7357 gcc_assert (arc->insn);
7358 if (arc->insn->first_ainsn_with_given_equivalence_num)
7359 add_vect_el (&transition_vect, arc->insn,
7360 arc->to_state->order_state_num);
7362 add_vect (automaton->trans_table,
7363 VEC_index (state_t, output_states_vect, i)->order_state_num,
7364 transition_vect);
7366 output_state_ainsn_table
7367 (automaton->trans_table, "state transitions",
7368 output_trans_full_vect_name, output_trans_comb_vect_name,
7369 output_trans_check_vect_name, output_trans_base_vect_name);
7371 VEC_free (state_t,heap, output_states_vect);
7372 VEC_free (vect_el_t,heap, transition_vect);
7375 /* The current number of passing states to find minimal issue delay
7376 value for an ainsn and state. */
7377 static int curr_state_pass_num;
7379 /* This recursive function passes states to find minimal issue delay
7380 value for AINSN. The state being visited is STATE. The function
7381 returns minimal issue delay value for AINSN in STATE or -1 if we
7382 enter into a loop. */
7383 static int
7384 min_issue_delay_pass_states (state_t state, ainsn_t ainsn)
7386 arc_t arc;
7387 int min_insn_issue_delay, insn_issue_delay;
7389 if (state->state_pass_num == curr_state_pass_num
7390 || state->min_insn_issue_delay != -1)
7391 /* We've entered into a loop or already have the correct value for
7392 given state and ainsn. */
7393 return state->min_insn_issue_delay;
7394 state->state_pass_num = curr_state_pass_num;
7395 min_insn_issue_delay = -1;
7396 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
7397 if (arc->insn == ainsn)
7399 min_insn_issue_delay = 0;
7400 break;
7402 else
7404 insn_issue_delay = min_issue_delay_pass_states (arc->to_state, ainsn);
7405 if (insn_issue_delay != -1)
7407 if (arc->insn->insn_reserv_decl
7408 == DECL_INSN_RESERV (advance_cycle_insn_decl))
7409 insn_issue_delay++;
7410 if (min_insn_issue_delay == -1
7411 || min_insn_issue_delay > insn_issue_delay)
7413 min_insn_issue_delay = insn_issue_delay;
7414 if (insn_issue_delay == 0)
7415 break;
7419 return min_insn_issue_delay;
7422 /* The function searches minimal issue delay value for AINSN in STATE.
7423 The function can return negative value if we can not issue AINSN. We
7424 will report about it later. */
7425 static int
7426 min_issue_delay (state_t state, ainsn_t ainsn)
7428 curr_state_pass_num++;
7429 state->min_insn_issue_delay = min_issue_delay_pass_states (state, ainsn);
7430 return state->min_insn_issue_delay;
7433 /* The function initiates code for finding minimal issue delay values.
7434 It should be called only once. */
7435 static void
7436 initiate_min_issue_delay_pass_states (void)
7438 curr_state_pass_num = 0;
7441 /* Form and output vectors representing minimal issue delay table of
7442 AUTOMATON. The table is state x ainsn -> minimal issue delay of
7443 the ainsn. */
7444 static void
7445 output_min_issue_delay_table (automaton_t automaton)
7447 vla_hwint_t min_issue_delay_vect;
7448 vla_hwint_t compressed_min_issue_delay_vect;
7449 vect_el_t min_delay;
7450 ainsn_t ainsn;
7451 size_t i, min_issue_delay_len;
7452 size_t compressed_min_issue_delay_len;
7453 size_t cfactor;
7455 /* Create vect of pointers to states ordered by num of transitions
7456 from the state (state with the maximum num is the first). */
7457 output_states_vect = 0;
7458 pass_states (automaton, add_states_vect_el);
7460 min_issue_delay_len = (VEC_length (state_t, output_states_vect)
7461 * automaton->insn_equiv_classes_num);
7462 min_issue_delay_vect = VEC_alloc (vect_el_t,heap, min_issue_delay_len);
7463 for (i = 0; i < min_issue_delay_len; i++)
7464 VEC_quick_push (vect_el_t, min_issue_delay_vect, 0);
7466 automaton->max_min_delay = 0;
7467 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
7468 if (ainsn->first_ainsn_with_given_equivalence_num)
7470 for (i = 0; i < VEC_length (state_t, output_states_vect); i++)
7471 VEC_index (state_t, output_states_vect, i)->min_insn_issue_delay = -1;
7472 for (i = 0; i < VEC_length (state_t, output_states_vect); i++)
7474 state_t s = VEC_index (state_t, output_states_vect, i);
7475 min_delay = min_issue_delay (s, ainsn);
7476 if (automaton->max_min_delay < min_delay)
7477 automaton->max_min_delay = min_delay;
7478 VEC_replace (vect_el_t, min_issue_delay_vect,
7479 s->order_state_num
7480 * automaton->insn_equiv_classes_num
7481 + ainsn->insn_equiv_class_num,
7482 min_delay);
7485 fprintf (output_file, "/* Vector of min issue delay of insns. */\n");
7486 fprintf (output_file, "static const ");
7487 output_range_type (output_file, 0, automaton->max_min_delay);
7488 fprintf (output_file, " ");
7489 output_min_issue_delay_vect_name (output_file, automaton);
7490 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7491 /* Compress the vector. */
7492 if (automaton->max_min_delay < 2)
7493 cfactor = 8;
7494 else if (automaton->max_min_delay < 4)
7495 cfactor = 4;
7496 else if (automaton->max_min_delay < 16)
7497 cfactor = 2;
7498 else
7499 cfactor = 1;
7500 automaton->min_issue_delay_table_compression_factor = cfactor;
7502 compressed_min_issue_delay_len = (min_issue_delay_len+cfactor-1) / cfactor;
7503 compressed_min_issue_delay_vect
7504 = VEC_alloc (vect_el_t,heap, compressed_min_issue_delay_len);
7506 for (i = 0; i < compressed_min_issue_delay_len; i++)
7507 VEC_quick_push (vect_el_t, compressed_min_issue_delay_vect, 0);
7509 for (i = 0; i < min_issue_delay_len; i++)
7511 size_t ci = i / cfactor;
7512 vect_el_t x = VEC_index (vect_el_t, min_issue_delay_vect, i);
7513 vect_el_t cx = VEC_index (vect_el_t, compressed_min_issue_delay_vect, ci);
7515 cx |= x << (8 - (i % cfactor + 1) * (8 / cfactor));
7516 VEC_replace (vect_el_t, compressed_min_issue_delay_vect, ci, cx);
7518 output_vect (compressed_min_issue_delay_vect);
7519 fprintf (output_file, "};\n\n");
7520 VEC_free (state_t,heap, output_states_vect);
7521 VEC_free (vect_el_t,heap, min_issue_delay_vect);
7522 VEC_free (vect_el_t,heap, compressed_min_issue_delay_vect);
7525 /* Form and output vector representing the locked states of
7526 AUTOMATON. */
7527 static void
7528 output_dead_lock_vect (automaton_t automaton)
7530 size_t i;
7531 arc_t arc;
7532 vla_hwint_t dead_lock_vect = 0;
7534 /* Create vect of pointers to states ordered by num of
7535 transitions from the state (state with the maximum num is the
7536 first). */
7537 automaton->locked_states = 0;
7538 output_states_vect = 0;
7539 pass_states (automaton, add_states_vect_el);
7541 VEC_safe_grow (vect_el_t,heap, dead_lock_vect,
7542 VEC_length (state_t, output_states_vect));
7543 for (i = 0; i < VEC_length (state_t, output_states_vect); i++)
7545 state_t s = VEC_index (state_t, output_states_vect, i);
7546 arc = first_out_arc (s);
7547 gcc_assert (arc);
7548 if (next_out_arc (arc) == NULL
7549 && (arc->insn->insn_reserv_decl
7550 == DECL_INSN_RESERV (advance_cycle_insn_decl)))
7552 VEC_replace (vect_el_t, dead_lock_vect, s->order_state_num, 1);
7553 automaton->locked_states++;
7555 else
7556 VEC_replace (vect_el_t, dead_lock_vect, s->order_state_num, 0);
7558 if (automaton->locked_states == 0)
7559 return;
7561 fprintf (output_file, "/* Vector for locked state flags. */\n");
7562 fprintf (output_file, "static const ");
7563 output_range_type (output_file, 0, 1);
7564 fprintf (output_file, " ");
7565 output_dead_lock_vect_name (output_file, automaton);
7566 fprintf (output_file, "[] = {\n");
7567 output_vect (dead_lock_vect);
7568 fprintf (output_file, "};\n\n");
7569 VEC_free (state_t,heap, output_states_vect);
7570 VEC_free (vect_el_t,heap, dead_lock_vect);
7573 /* Form and output vector representing reserved units of the states of
7574 AUTOMATON. */
7575 static void
7576 output_reserved_units_table (automaton_t automaton)
7578 vla_hwint_t reserved_units_table = 0;
7579 int state_byte_size;
7580 int reserved_units_size;
7581 size_t n;
7582 int i;
7584 if (description->query_units_num == 0)
7585 return;
7587 /* Create vect of pointers to states. */
7588 output_states_vect = 0;
7589 pass_states (automaton, add_states_vect_el);
7590 /* Create vector. */
7591 state_byte_size = (description->query_units_num + 7) / 8;
7592 reserved_units_size = (VEC_length (state_t, output_states_vect)
7593 * state_byte_size);
7595 reserved_units_table = VEC_alloc (vect_el_t,heap, reserved_units_size);
7597 for (i = 0; i < reserved_units_size; i++)
7598 VEC_quick_push (vect_el_t, reserved_units_table, 0);
7599 for (n = 0; n < VEC_length (state_t, output_states_vect); n++)
7601 state_t s = VEC_index (state_t, output_states_vect, n);
7602 for (i = 0; i < description->units_num; i++)
7603 if (units_array [i]->query_p
7604 && first_cycle_unit_presence (s, i))
7606 int ri = (s->order_state_num * state_byte_size
7607 + units_array [i]->query_num / 8);
7608 vect_el_t x = VEC_index (vect_el_t, reserved_units_table, ri);
7610 x += 1 << (units_array [i]->query_num % 8);
7611 VEC_replace (vect_el_t, reserved_units_table, ri, x);
7614 fprintf (output_file, "\n#if %s\n", CPU_UNITS_QUERY_MACRO_NAME);
7615 fprintf (output_file, "/* Vector for reserved units of states. */\n");
7616 fprintf (output_file, "static const ");
7617 output_range_type (output_file, 0, 255);
7618 fprintf (output_file, " ");
7619 output_reserved_units_table_name (output_file, automaton);
7620 fprintf (output_file, "[] = {\n");
7621 output_vect (reserved_units_table);
7622 fprintf (output_file, "};\n#endif /* #if %s */\n\n",
7623 CPU_UNITS_QUERY_MACRO_NAME);
7625 VEC_free (state_t,heap, output_states_vect);
7626 VEC_free (vect_el_t,heap, reserved_units_table);
7629 /* The function outputs all tables representing DFA(s) used for fast
7630 pipeline hazards recognition. */
7631 static void
7632 output_tables (void)
7634 automaton_t automaton;
7636 initiate_min_issue_delay_pass_states ();
7637 for (automaton = description->first_automaton;
7638 automaton != NULL;
7639 automaton = automaton->next_automaton)
7641 output_translate_vect (automaton);
7642 output_trans_table (automaton);
7643 output_min_issue_delay_table (automaton);
7644 output_dead_lock_vect (automaton);
7645 output_reserved_units_table (automaton);
7647 fprintf (output_file, "\n#define %s %d\n\n", ADVANCE_CYCLE_VALUE_NAME,
7648 DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
7651 /* The function outputs definition and value of PHR interface variable
7652 `max_insn_queue_index'. Its value is not less than maximal queue
7653 length needed for the insn scheduler. */
7654 static void
7655 output_max_insn_queue_index_def (void)
7657 int i, max, latency;
7658 decl_t decl;
7660 max = description->max_insn_reserv_cycles;
7661 for (i = 0; i < description->decls_num; i++)
7663 decl = description->decls [i];
7664 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
7666 latency = DECL_INSN_RESERV (decl)->default_latency;
7667 if (latency > max)
7668 max = latency;
7670 else if (decl->mode == dm_bypass)
7672 latency = DECL_BYPASS (decl)->latency;
7673 if (latency > max)
7674 max = latency;
7677 for (i = 0; (1 << i) <= max; i++)
7679 gcc_assert (i >= 0);
7680 fprintf (output_file, "\nconst int max_insn_queue_index = %d;\n\n",
7681 (1 << i) - 1);
7684 /* The function outputs switch cases for insn reservations using
7685 function *output_automata_list_code. */
7686 static void
7687 output_insn_code_cases (void (*output_automata_list_code)
7688 (automata_list_el_t))
7690 decl_t decl, decl2;
7691 int i, j;
7693 for (i = 0; i < description->decls_num; i++)
7695 decl = description->decls [i];
7696 if (decl->mode == dm_insn_reserv)
7697 DECL_INSN_RESERV (decl)->processed_p = FALSE;
7699 for (i = 0; i < description->decls_num; i++)
7701 decl = description->decls [i];
7702 if (decl->mode == dm_insn_reserv
7703 && !DECL_INSN_RESERV (decl)->processed_p)
7705 for (j = i; j < description->decls_num; j++)
7707 decl2 = description->decls [j];
7708 if (decl2->mode == dm_insn_reserv
7709 && (DECL_INSN_RESERV (decl2)->important_automata_list
7710 == DECL_INSN_RESERV (decl)->important_automata_list))
7712 DECL_INSN_RESERV (decl2)->processed_p = TRUE;
7713 fprintf (output_file, " case %d: /* %s */\n",
7714 DECL_INSN_RESERV (decl2)->insn_num,
7715 DECL_INSN_RESERV (decl2)->name);
7718 (*output_automata_list_code)
7719 (DECL_INSN_RESERV (decl)->important_automata_list);
7725 /* The function outputs a code for evaluation of a minimal delay of
7726 issue of insns which have reservations in given AUTOMATA_LIST. */
7727 static void
7728 output_automata_list_min_issue_delay_code (automata_list_el_t automata_list)
7730 automata_list_el_t el;
7731 automaton_t automaton;
7733 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
7735 automaton = el->automaton;
7736 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
7737 output_min_issue_delay_vect_name (output_file, automaton);
7738 fprintf (output_file,
7739 (automaton->min_issue_delay_table_compression_factor != 1
7740 ? " [(" : " ["));
7741 output_translate_vect_name (output_file, automaton);
7742 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
7743 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7744 output_chip_member_name (output_file, automaton);
7745 fprintf (output_file, " * %d", automaton->insn_equiv_classes_num);
7746 if (automaton->min_issue_delay_table_compression_factor == 1)
7747 fprintf (output_file, "];\n");
7748 else
7750 fprintf (output_file, ") / %d];\n",
7751 automaton->min_issue_delay_table_compression_factor);
7752 fprintf (output_file, " %s = (%s >> (8 - (",
7753 TEMPORARY_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
7754 output_translate_vect_name (output_file, automaton);
7755 fprintf
7756 (output_file, " [%s] %% %d + 1) * %d)) & %d;\n",
7757 INTERNAL_INSN_CODE_NAME,
7758 automaton->min_issue_delay_table_compression_factor,
7759 8 / automaton->min_issue_delay_table_compression_factor,
7760 (1 << (8 / automaton->min_issue_delay_table_compression_factor))
7761 - 1);
7763 if (el == automata_list)
7764 fprintf (output_file, " %s = %s;\n",
7765 RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
7766 else
7768 fprintf (output_file, " if (%s > %s)\n",
7769 TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
7770 fprintf (output_file, " %s = %s;\n",
7771 RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
7774 fprintf (output_file, " break;\n\n");
7777 /* Output function `internal_min_issue_delay'. */
7778 static void
7779 output_internal_min_issue_delay_func (void)
7781 fprintf (output_file,
7782 "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
7783 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7784 CHIP_NAME, CHIP_PARAMETER_NAME);
7785 fprintf (output_file, "{\n int %s ATTRIBUTE_UNUSED;\n int %s = -1;\n",
7786 TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
7787 fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
7788 output_insn_code_cases (output_automata_list_min_issue_delay_code);
7789 fprintf (output_file,
7790 "\n default:\n %s = -1;\n break;\n }\n",
7791 RESULT_VARIABLE_NAME);
7792 fprintf (output_file, " return %s;\n", RESULT_VARIABLE_NAME);
7793 fprintf (output_file, "}\n\n");
7796 /* The function outputs a code changing state after issue of insns
7797 which have reservations in given AUTOMATA_LIST. */
7798 static void
7799 output_automata_list_transition_code (automata_list_el_t automata_list)
7801 automata_list_el_t el, next_el;
7803 fprintf (output_file, " {\n");
7804 if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
7805 for (el = automata_list;; el = next_el)
7807 next_el = el->next_automata_list_el;
7808 if (next_el == NULL)
7809 break;
7810 fprintf (output_file, " ");
7811 output_state_member_type (output_file, el->automaton);
7812 fprintf (output_file, " ");
7813 output_temp_chip_member_name (output_file, el->automaton);
7814 fprintf (output_file, ";\n");
7816 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
7817 if (comb_vect_p (el->automaton->trans_table))
7819 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
7820 output_trans_base_vect_name (output_file, el->automaton);
7821 fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
7822 output_chip_member_name (output_file, el->automaton);
7823 fprintf (output_file, "] + ");
7824 output_translate_vect_name (output_file, el->automaton);
7825 fprintf (output_file, " [%s];\n", INTERNAL_INSN_CODE_NAME);
7826 fprintf (output_file, " if (");
7827 output_trans_check_vect_name (output_file, el->automaton);
7828 fprintf (output_file, " [%s] != %s->",
7829 TEMPORARY_VARIABLE_NAME, CHIP_PARAMETER_NAME);
7830 output_chip_member_name (output_file, el->automaton);
7831 fprintf (output_file, ")\n");
7832 fprintf (output_file, " return %s (%s, %s);\n",
7833 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7834 CHIP_PARAMETER_NAME);
7835 fprintf (output_file, " else\n");
7836 fprintf (output_file, " ");
7837 if (el->next_automata_list_el != NULL)
7838 output_temp_chip_member_name (output_file, el->automaton);
7839 else
7841 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7842 output_chip_member_name (output_file, el->automaton);
7844 fprintf (output_file, " = ");
7845 output_trans_comb_vect_name (output_file, el->automaton);
7846 fprintf (output_file, " [%s];\n", TEMPORARY_VARIABLE_NAME);
7848 else
7850 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
7851 output_trans_full_vect_name (output_file, el->automaton);
7852 fprintf (output_file, " [");
7853 output_translate_vect_name (output_file, el->automaton);
7854 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
7855 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7856 output_chip_member_name (output_file, el->automaton);
7857 fprintf (output_file, " * %d];\n",
7858 el->automaton->insn_equiv_classes_num);
7859 fprintf (output_file, " if (%s >= %d)\n",
7860 TEMPORARY_VARIABLE_NAME, el->automaton->achieved_states_num);
7861 fprintf (output_file, " return %s (%s, %s);\n",
7862 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7863 CHIP_PARAMETER_NAME);
7864 fprintf (output_file, " else\n ");
7865 if (el->next_automata_list_el != NULL)
7866 output_temp_chip_member_name (output_file, el->automaton);
7867 else
7869 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7870 output_chip_member_name (output_file, el->automaton);
7872 fprintf (output_file, " = %s;\n", TEMPORARY_VARIABLE_NAME);
7874 if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
7875 for (el = automata_list;; el = next_el)
7877 next_el = el->next_automata_list_el;
7878 if (next_el == NULL)
7879 break;
7880 fprintf (output_file, " %s->", CHIP_PARAMETER_NAME);
7881 output_chip_member_name (output_file, el->automaton);
7882 fprintf (output_file, " = ");
7883 output_temp_chip_member_name (output_file, el->automaton);
7884 fprintf (output_file, ";\n");
7886 fprintf (output_file, " return -1;\n");
7887 fprintf (output_file, " }\n");
7890 /* Output function `internal_state_transition'. */
7891 static void
7892 output_internal_trans_func (void)
7894 fprintf (output_file,
7895 "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
7896 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7897 CHIP_NAME, CHIP_PARAMETER_NAME);
7898 fprintf (output_file, "{\n int %s ATTRIBUTE_UNUSED;\n", TEMPORARY_VARIABLE_NAME);
7899 fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
7900 output_insn_code_cases (output_automata_list_transition_code);
7901 fprintf (output_file, "\n default:\n return -1;\n }\n");
7902 fprintf (output_file, "}\n\n");
7905 /* Output code
7907 if (insn != 0)
7909 insn_code = dfa_insn_code (insn);
7910 if (insn_code > DFA__ADVANCE_CYCLE)
7911 return code;
7913 else
7914 insn_code = DFA__ADVANCE_CYCLE;
7916 where insn denotes INSN_NAME, insn_code denotes INSN_CODE_NAME, and
7917 code denotes CODE. */
7918 static void
7919 output_internal_insn_code_evaluation (const char *insn_name,
7920 const char *insn_code_name,
7921 int code)
7923 fprintf (output_file, "\n if (%s != 0)\n {\n", insn_name);
7924 fprintf (output_file, " %s = %s (%s);\n", insn_code_name,
7925 DFA_INSN_CODE_FUNC_NAME, insn_name);
7926 fprintf (output_file, " if (%s > %s)\n return %d;\n",
7927 insn_code_name, ADVANCE_CYCLE_VALUE_NAME, code);
7928 fprintf (output_file, " }\n else\n %s = %s;\n\n",
7929 insn_code_name, ADVANCE_CYCLE_VALUE_NAME);
7933 /* This function outputs `dfa_insn_code' and its helper function
7934 `dfa_insn_code_enlarge'. */
7935 static void
7936 output_dfa_insn_code_func (void)
7938 /* Emacs c-mode gets really confused if there's a { or } in column 0
7939 inside a string, so don't do that. */
7940 fprintf (output_file, "\
7941 static void\n\
7942 dfa_insn_code_enlarge (int uid)\n\
7943 {\n\
7944 int i = %s;\n\
7945 %s = 2 * uid;\n\
7946 %s = XRESIZEVEC (int, %s,\n\
7947 %s);\n\
7948 for (; i < %s; i++)\n\
7949 %s[i] = -1;\n}\n\n",
7950 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
7951 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
7952 DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
7953 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
7954 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
7955 DFA_INSN_CODES_VARIABLE_NAME);
7956 fprintf (output_file, "\
7957 static inline int\n%s (rtx %s)\n\
7958 {\n\
7959 int uid = INSN_UID (%s);\n\
7960 int %s;\n\n",
7961 DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME,
7962 INSN_PARAMETER_NAME, INTERNAL_INSN_CODE_NAME);
7964 fprintf (output_file,
7965 " if (uid >= %s)\n dfa_insn_code_enlarge (uid);\n\n",
7966 DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
7967 fprintf (output_file, " %s = %s[uid];\n",
7968 INTERNAL_INSN_CODE_NAME, DFA_INSN_CODES_VARIABLE_NAME);
7969 fprintf (output_file, "\
7970 if (%s < 0)\n\
7971 {\n\
7972 %s = %s (%s);\n\
7973 %s[uid] = %s;\n\
7974 }\n",
7975 INTERNAL_INSN_CODE_NAME,
7976 INTERNAL_INSN_CODE_NAME,
7977 INTERNAL_DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME,
7978 DFA_INSN_CODES_VARIABLE_NAME, INTERNAL_INSN_CODE_NAME);
7979 fprintf (output_file, " return %s;\n}\n\n", INTERNAL_INSN_CODE_NAME);
7982 /* The function outputs PHR interface function `state_transition'. */
7983 static void
7984 output_trans_func (void)
7986 fprintf (output_file, "int\n%s (%s %s, rtx %s)\n",
7987 TRANSITION_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME,
7988 INSN_PARAMETER_NAME);
7989 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
7990 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
7991 INTERNAL_INSN_CODE_NAME, -1);
7992 fprintf (output_file, " return %s (%s, (struct %s *) %s);\n}\n\n",
7993 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME, STATE_NAME);
7996 /* Output function `min_issue_delay'. */
7997 static void
7998 output_min_issue_delay_func (void)
8000 fprintf (output_file, "int\n%s (%s %s, rtx %s)\n",
8001 MIN_ISSUE_DELAY_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME,
8002 INSN_PARAMETER_NAME);
8003 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
8004 fprintf (output_file, "\n if (%s != 0)\n {\n", INSN_PARAMETER_NAME);
8005 fprintf (output_file, " %s = %s (%s);\n", INTERNAL_INSN_CODE_NAME,
8006 DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME);
8007 fprintf (output_file, " if (%s > %s)\n return 0;\n",
8008 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8009 fprintf (output_file, " }\n else\n %s = %s;\n",
8010 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8011 fprintf (output_file, "\n return %s (%s, (struct %s *) %s);\n",
8012 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8013 CHIP_NAME, STATE_NAME);
8014 fprintf (output_file, "}\n\n");
8017 /* Output function `internal_dead_lock'. */
8018 static void
8019 output_internal_dead_lock_func (void)
8021 automaton_t automaton;
8023 fprintf (output_file, "static int\n%s (struct %s *ARG_UNUSED (%s))\n",
8024 INTERNAL_DEAD_LOCK_FUNC_NAME, CHIP_NAME, CHIP_PARAMETER_NAME);
8025 fprintf (output_file, "{\n");
8026 for (automaton = description->first_automaton;
8027 automaton != NULL;
8028 automaton = automaton->next_automaton)
8029 if (automaton->locked_states)
8031 fprintf (output_file, " if (");
8032 output_dead_lock_vect_name (output_file, automaton);
8033 fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
8034 output_chip_member_name (output_file, automaton);
8035 fprintf (output_file, "])\n return 1/* TRUE */;\n");
8037 fprintf (output_file, " return 0/* FALSE */;\n}\n\n");
8040 /* The function outputs PHR interface function `state_dead_lock_p'. */
8041 static void
8042 output_dead_lock_func (void)
8044 fprintf (output_file, "int\n%s (%s %s)\n",
8045 DEAD_LOCK_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME);
8046 fprintf (output_file, "{\n return %s ((struct %s *) %s);\n}\n\n",
8047 INTERNAL_DEAD_LOCK_FUNC_NAME, CHIP_NAME, STATE_NAME);
8050 /* Output function `internal_reset'. */
8051 static void
8052 output_internal_reset_func (void)
8054 fprintf (output_file, "static inline void\n%s (struct %s *%s)\n",
8055 INTERNAL_RESET_FUNC_NAME, CHIP_NAME, CHIP_PARAMETER_NAME);
8056 fprintf (output_file, "{\n memset (%s, 0, sizeof (struct %s));\n}\n\n",
8057 CHIP_PARAMETER_NAME, CHIP_NAME);
8060 /* The function outputs PHR interface function `state_size'. */
8061 static void
8062 output_size_func (void)
8064 fprintf (output_file, "int\n%s (void)\n", SIZE_FUNC_NAME);
8065 fprintf (output_file, "{\n return sizeof (struct %s);\n}\n\n", CHIP_NAME);
8068 /* The function outputs PHR interface function `state_reset'. */
8069 static void
8070 output_reset_func (void)
8072 fprintf (output_file, "void\n%s (%s %s)\n",
8073 RESET_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME);
8074 fprintf (output_file, "{\n %s ((struct %s *) %s);\n}\n\n", INTERNAL_RESET_FUNC_NAME,
8075 CHIP_NAME, STATE_NAME);
8078 /* Output function `min_insn_conflict_delay'. */
8079 static void
8080 output_min_insn_conflict_delay_func (void)
8082 fprintf (output_file,
8083 "int\n%s (%s %s, rtx %s, rtx %s)\n",
8084 MIN_INSN_CONFLICT_DELAY_FUNC_NAME, STATE_TYPE_NAME,
8085 STATE_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8086 fprintf (output_file, "{\n struct %s %s;\n int %s, %s, transition;\n",
8087 CHIP_NAME, CHIP_NAME, INTERNAL_INSN_CODE_NAME,
8088 INTERNAL_INSN2_CODE_NAME);
8089 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8090 INTERNAL_INSN_CODE_NAME, 0);
8091 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
8092 INTERNAL_INSN2_CODE_NAME, 0);
8093 fprintf (output_file, " memcpy (&%s, %s, sizeof (%s));\n",
8094 CHIP_NAME, STATE_NAME, CHIP_NAME);
8095 fprintf (output_file, " %s (&%s);\n", INTERNAL_RESET_FUNC_NAME, CHIP_NAME);
8096 fprintf (output_file, " transition = %s (%s, &%s);\n",
8097 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME);
8098 fprintf (output_file, " gcc_assert (transition <= 0);\n");
8099 fprintf (output_file, " return %s (%s, &%s);\n",
8100 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN2_CODE_NAME,
8101 CHIP_NAME);
8102 fprintf (output_file, "}\n\n");
8105 /* Output the array holding default latency values. These are used in
8106 insn_latency and maximal_insn_latency function implementations. */
8107 static void
8108 output_default_latencies (void)
8110 int i, j, col;
8111 decl_t decl;
8112 const char *tabletype = "unsigned char";
8114 /* Find the smallest integer type that can hold all the default
8115 latency values. */
8116 for (i = 0; i < description->decls_num; i++)
8117 if (description->decls[i]->mode == dm_insn_reserv)
8119 decl = description->decls[i];
8120 if (DECL_INSN_RESERV (decl)->default_latency > UCHAR_MAX
8121 && tabletype[0] != 'i') /* Don't shrink it. */
8122 tabletype = "unsigned short";
8123 if (DECL_INSN_RESERV (decl)->default_latency > USHRT_MAX)
8124 tabletype = "int";
8127 fprintf (output_file, " static const %s default_latencies[] =\n {",
8128 tabletype);
8130 for (i = 0, j = 0, col = 7; i < description->decls_num; i++)
8131 if (description->decls[i]->mode == dm_insn_reserv
8132 && description->decls[i] != advance_cycle_insn_decl)
8134 if ((col = (col+1) % 8) == 0)
8135 fputs ("\n ", output_file);
8136 decl = description->decls[i];
8137 gcc_assert (j++ == DECL_INSN_RESERV (decl)->insn_num);
8138 fprintf (output_file, "% 4d,",
8139 DECL_INSN_RESERV (decl)->default_latency);
8141 gcc_assert (j == DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
8142 fputs ("\n };\n", output_file);
8145 /* Output function `internal_insn_latency'. */
8146 static void
8147 output_internal_insn_latency_func (void)
8149 int i;
8150 decl_t decl;
8151 struct bypass_decl *bypass;
8153 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",
8154 INTERNAL_INSN_LATENCY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8155 INTERNAL_INSN2_CODE_NAME, INSN_PARAMETER_NAME,
8156 INSN2_PARAMETER_NAME);
8157 fprintf (output_file, "{\n");
8159 if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8161 fputs (" return 0;\n}\n\n", output_file);
8162 return;
8165 fprintf (output_file, " if (%s >= %s || %s >= %s)\n return 0;\n",
8166 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8167 INTERNAL_INSN2_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8169 fprintf (output_file, " switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8170 for (i = 0; i < description->decls_num; i++)
8171 if (description->decls[i]->mode == dm_insn_reserv
8172 && DECL_INSN_RESERV (description->decls[i])->bypass_list)
8174 decl = description->decls [i];
8175 fprintf (output_file,
8176 " case %d:\n switch (%s)\n {\n",
8177 DECL_INSN_RESERV (decl)->insn_num,
8178 INTERNAL_INSN2_CODE_NAME);
8179 for (bypass = DECL_INSN_RESERV (decl)->bypass_list;
8180 bypass != NULL;
8181 bypass = bypass->next)
8183 gcc_assert (bypass->in_insn_reserv->insn_num
8184 != (DECL_INSN_RESERV
8185 (advance_cycle_insn_decl)->insn_num));
8186 fprintf (output_file, " case %d:\n",
8187 bypass->in_insn_reserv->insn_num);
8188 for (;;)
8190 if (bypass->bypass_guard_name == NULL)
8192 gcc_assert (bypass->next == NULL
8193 || (bypass->in_insn_reserv
8194 != bypass->next->in_insn_reserv));
8195 fprintf (output_file, " return %d;\n",
8196 bypass->latency);
8198 else
8200 fprintf (output_file,
8201 " if (%s (%s, %s))\n",
8202 bypass->bypass_guard_name, INSN_PARAMETER_NAME,
8203 INSN2_PARAMETER_NAME);
8204 fprintf (output_file, " return %d;\n",
8205 bypass->latency);
8207 if (bypass->next == NULL
8208 || bypass->in_insn_reserv != bypass->next->in_insn_reserv)
8209 break;
8210 bypass = bypass->next;
8212 if (bypass->bypass_guard_name != NULL)
8213 fprintf (output_file, " break;\n");
8215 fputs (" }\n break;\n", output_file);
8218 fprintf (output_file, " }\n return default_latencies[%s];\n}\n\n",
8219 INTERNAL_INSN_CODE_NAME);
8222 /* Output function `internal_maximum_insn_latency'. */
8223 static void
8224 output_internal_maximal_insn_latency_func (void)
8226 decl_t decl;
8227 struct bypass_decl *bypass;
8228 int i;
8229 int max;
8231 fprintf (output_file, "static int\n%s (int %s ATTRIBUTE_UNUSED,\n\trtx %s ATTRIBUTE_UNUSED)\n",
8232 "internal_maximal_insn_latency", INTERNAL_INSN_CODE_NAME,
8233 INSN_PARAMETER_NAME);
8234 fprintf (output_file, "{\n");
8236 if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8238 fputs (" return 0;\n}\n\n", output_file);
8239 return;
8242 fprintf (output_file, " switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8243 for (i = 0; i < description->decls_num; i++)
8244 if (description->decls[i]->mode == dm_insn_reserv
8245 && DECL_INSN_RESERV (description->decls[i])->bypass_list)
8247 decl = description->decls [i];
8248 max = DECL_INSN_RESERV (decl)->default_latency;
8249 fprintf (output_file,
8250 " case %d: {",
8251 DECL_INSN_RESERV (decl)->insn_num);
8252 for (bypass = DECL_INSN_RESERV (decl)->bypass_list;
8253 bypass != NULL;
8254 bypass = bypass->next)
8256 if (bypass->latency > max)
8257 max = bypass->latency;
8259 fprintf (output_file, " return %d; }\n break;\n", max);
8262 fprintf (output_file, " }\n return default_latencies[%s];\n}\n\n",
8263 INTERNAL_INSN_CODE_NAME);
8266 /* The function outputs PHR interface function `insn_latency'. */
8267 static void
8268 output_insn_latency_func (void)
8270 fprintf (output_file, "int\n%s (rtx %s, rtx %s)\n",
8271 INSN_LATENCY_FUNC_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8272 fprintf (output_file, "{\n int %s, %s;\n",
8273 INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME);
8274 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8275 INTERNAL_INSN_CODE_NAME, 0);
8276 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
8277 INTERNAL_INSN2_CODE_NAME, 0);
8278 fprintf (output_file, " return %s (%s, %s, %s, %s);\n}\n\n",
8279 INTERNAL_INSN_LATENCY_FUNC_NAME,
8280 INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME,
8281 INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8284 /* The function outputs PHR interface function `maximal_insn_latency'. */
8285 static void
8286 output_maximal_insn_latency_func (void)
8288 fprintf (output_file, "int\n%s (rtx %s)\n",
8289 "maximal_insn_latency", INSN_PARAMETER_NAME);
8290 fprintf (output_file, "{\n int %s;\n",
8291 INTERNAL_INSN_CODE_NAME);
8292 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8293 INTERNAL_INSN_CODE_NAME, 0);
8294 fprintf (output_file, " return %s (%s, %s);\n}\n\n",
8295 "internal_maximal_insn_latency",
8296 INTERNAL_INSN_CODE_NAME, INSN_PARAMETER_NAME);
8299 /* The function outputs PHR interface function `print_reservation'. */
8300 static void
8301 output_print_reservation_func (void)
8303 decl_t decl;
8304 int i, j;
8306 fprintf (output_file,
8307 "void\n%s (FILE *%s, rtx %s ATTRIBUTE_UNUSED)\n{\n",
8308 PRINT_RESERVATION_FUNC_NAME, FILE_PARAMETER_NAME,
8309 INSN_PARAMETER_NAME);
8311 if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8313 fprintf (output_file, " fputs (\"%s\", %s);\n}\n\n",
8314 NOTHING_NAME, FILE_PARAMETER_NAME);
8315 return;
8319 fputs (" static const char *const reservation_names[] =\n {",
8320 output_file);
8322 for (i = 0, j = 0; i < description->decls_num; i++)
8324 decl = description->decls [i];
8325 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
8327 gcc_assert (j == DECL_INSN_RESERV (decl)->insn_num);
8328 j++;
8330 fprintf (output_file, "\n \"%s\",",
8331 regexp_representation (DECL_INSN_RESERV (decl)->regexp));
8332 finish_regexp_representation ();
8335 gcc_assert (j == DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
8337 fprintf (output_file, "\n \"%s\"\n };\n int %s;\n\n",
8338 NOTHING_NAME, INTERNAL_INSN_CODE_NAME);
8340 fprintf (output_file, " if (%s == 0)\n %s = %s;\n",
8341 INSN_PARAMETER_NAME,
8342 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8343 fprintf (output_file, " else\n\
8344 {\n\
8345 %s = %s (%s);\n\
8346 if (%s > %s)\n\
8347 %s = %s;\n\
8348 }\n",
8349 INTERNAL_INSN_CODE_NAME, DFA_INSN_CODE_FUNC_NAME,
8350 INSN_PARAMETER_NAME,
8351 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8352 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8354 fprintf (output_file, " fputs (reservation_names[%s], %s);\n}\n\n",
8355 INTERNAL_INSN_CODE_NAME, FILE_PARAMETER_NAME);
8358 /* The following function is used to sort unit declaration by their
8359 names. */
8360 static int
8361 units_cmp (const void *unit1, const void *unit2)
8363 const_unit_decl_t const u1 = *(const_unit_decl_t const*) unit1;
8364 const_unit_decl_t const u2 = *(const_unit_decl_t const*) unit2;
8366 return strcmp (u1->name, u2->name);
8369 /* The following macro value is name of struct containing unit name
8370 and unit code. */
8371 #define NAME_CODE_STRUCT_NAME "name_code"
8373 /* The following macro value is name of table of struct name_code. */
8374 #define NAME_CODE_TABLE_NAME "name_code_table"
8376 /* The following macro values are member names for struct name_code. */
8377 #define NAME_MEMBER_NAME "name"
8378 #define CODE_MEMBER_NAME "code"
8380 /* The following macro values are local variable names for function
8381 `get_cpu_unit_code'. */
8382 #define CMP_VARIABLE_NAME "cmp"
8383 #define LOW_VARIABLE_NAME "l"
8384 #define MIDDLE_VARIABLE_NAME "m"
8385 #define HIGH_VARIABLE_NAME "h"
8387 /* The following function outputs function to obtain internal cpu unit
8388 code by the cpu unit name. */
8389 static void
8390 output_get_cpu_unit_code_func (void)
8392 int i;
8393 unit_decl_t *units;
8395 fprintf (output_file, "int\n%s (const char *%s)\n",
8396 GET_CPU_UNIT_CODE_FUNC_NAME, CPU_UNIT_NAME_PARAMETER_NAME);
8397 fprintf (output_file, "{\n struct %s {const char *%s; int %s;};\n",
8398 NAME_CODE_STRUCT_NAME, NAME_MEMBER_NAME, CODE_MEMBER_NAME);
8399 fprintf (output_file, " int %s, %s, %s, %s;\n", CMP_VARIABLE_NAME,
8400 LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8401 fprintf (output_file, " static struct %s %s [] =\n {\n",
8402 NAME_CODE_STRUCT_NAME, NAME_CODE_TABLE_NAME);
8403 units = XNEWVEC (unit_decl_t, description->units_num);
8404 memcpy (units, units_array, sizeof (unit_decl_t) * description->units_num);
8405 qsort (units, description->units_num, sizeof (unit_decl_t), units_cmp);
8406 for (i = 0; i < description->units_num; i++)
8407 if (units [i]->query_p)
8408 fprintf (output_file, " {\"%s\", %d},\n",
8409 units[i]->name, units[i]->query_num);
8410 fprintf (output_file, " };\n\n");
8411 fprintf (output_file, " /* The following is binary search: */\n");
8412 fprintf (output_file, " %s = 0;\n", LOW_VARIABLE_NAME);
8413 fprintf (output_file, " %s = sizeof (%s) / sizeof (struct %s) - 1;\n",
8414 HIGH_VARIABLE_NAME, NAME_CODE_TABLE_NAME, NAME_CODE_STRUCT_NAME);
8415 fprintf (output_file, " while (%s <= %s)\n {\n",
8416 LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8417 fprintf (output_file, " %s = (%s + %s) / 2;\n",
8418 MIDDLE_VARIABLE_NAME, LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8419 fprintf (output_file, " %s = strcmp (%s, %s [%s].%s);\n",
8420 CMP_VARIABLE_NAME, CPU_UNIT_NAME_PARAMETER_NAME,
8421 NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, NAME_MEMBER_NAME);
8422 fprintf (output_file, " if (%s < 0)\n", CMP_VARIABLE_NAME);
8423 fprintf (output_file, " %s = %s - 1;\n",
8424 HIGH_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
8425 fprintf (output_file, " else if (%s > 0)\n", CMP_VARIABLE_NAME);
8426 fprintf (output_file, " %s = %s + 1;\n",
8427 LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
8428 fprintf (output_file, " else\n");
8429 fprintf (output_file, " return %s [%s].%s;\n }\n",
8430 NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, CODE_MEMBER_NAME);
8431 fprintf (output_file, " return -1;\n}\n\n");
8432 free (units);
8435 /* The following function outputs function to check reservation of cpu
8436 unit (its internal code will be passed as the function argument) in
8437 given cpu state. */
8438 static void
8439 output_cpu_unit_reservation_p (void)
8441 automaton_t automaton;
8443 fprintf (output_file, "int\n%s (%s %s, int %s)\n",
8444 CPU_UNIT_RESERVATION_P_FUNC_NAME,
8445 STATE_TYPE_NAME, STATE_NAME,
8446 CPU_CODE_PARAMETER_NAME);
8447 fprintf (output_file, "{\n gcc_assert (%s >= 0 && %s < %d);\n",
8448 CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME,
8449 description->query_units_num);
8450 if (description->query_units_num > 0)
8451 for (automaton = description->first_automaton;
8452 automaton != NULL;
8453 automaton = automaton->next_automaton)
8455 fprintf (output_file, " if ((");
8456 output_reserved_units_table_name (output_file, automaton);
8457 fprintf (output_file, " [((struct %s *) %s)->", CHIP_NAME, STATE_NAME);
8458 output_chip_member_name (output_file, automaton);
8459 fprintf (output_file, " * %d + %s / 8] >> (%s %% 8)) & 1)\n",
8460 (description->query_units_num + 7) / 8,
8461 CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME);
8462 fprintf (output_file, " return 1;\n");
8464 fprintf (output_file, " return 0;\n}\n\n");
8467 /* The following function outputs a function to check if insn
8468 has a dfa reservation. */
8469 static void
8470 output_insn_has_dfa_reservation_p (void)
8472 fprintf (output_file,
8473 "bool\n%s (rtx %s ATTRIBUTE_UNUSED)\n{\n",
8474 INSN_HAS_DFA_RESERVATION_P_FUNC_NAME,
8475 INSN_PARAMETER_NAME);
8477 if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8479 fprintf (output_file, " return false;\n}\n\n");
8480 return;
8483 fprintf (output_file, " int %s;\n\n", INTERNAL_INSN_CODE_NAME);
8485 fprintf (output_file, " if (%s == 0)\n %s = %s;\n",
8486 INSN_PARAMETER_NAME,
8487 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8488 fprintf (output_file, " else\n\
8489 {\n\
8490 %s = %s (%s);\n\
8491 if (%s > %s)\n\
8492 %s = %s;\n\
8493 }\n\n",
8494 INTERNAL_INSN_CODE_NAME, DFA_INSN_CODE_FUNC_NAME,
8495 INSN_PARAMETER_NAME,
8496 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8497 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8499 fprintf (output_file, " return %s != %s;\n}\n\n",
8500 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8503 /* The function outputs PHR interface functions `dfa_clean_insn_cache'
8504 and 'dfa_clear_single_insn_cache'. */
8505 static void
8506 output_dfa_clean_insn_cache_func (void)
8508 fprintf (output_file,
8509 "void\n%s (void)\n{\n int %s;\n\n",
8510 DFA_CLEAN_INSN_CACHE_FUNC_NAME, I_VARIABLE_NAME);
8511 fprintf (output_file,
8512 " for (%s = 0; %s < %s; %s++)\n %s [%s] = -1;\n}\n\n",
8513 I_VARIABLE_NAME, I_VARIABLE_NAME,
8514 DFA_INSN_CODES_LENGTH_VARIABLE_NAME, I_VARIABLE_NAME,
8515 DFA_INSN_CODES_VARIABLE_NAME, I_VARIABLE_NAME);
8517 fprintf (output_file,
8518 "void\n%s (rtx %s)\n{\n int %s;\n\n",
8519 DFA_CLEAR_SINGLE_INSN_CACHE_FUNC_NAME, INSN_PARAMETER_NAME,
8520 I_VARIABLE_NAME);
8521 fprintf (output_file,
8522 " %s = INSN_UID (%s);\n if (%s < %s)\n %s [%s] = -1;\n}\n\n",
8523 I_VARIABLE_NAME, INSN_PARAMETER_NAME, I_VARIABLE_NAME,
8524 DFA_INSN_CODES_LENGTH_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
8525 I_VARIABLE_NAME);
8528 /* The function outputs PHR interface function `dfa_start'. */
8529 static void
8530 output_dfa_start_func (void)
8532 fprintf (output_file,
8533 "void\n%s (void)\n{\n %s = get_max_uid ();\n",
8534 DFA_START_FUNC_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8535 fprintf (output_file, " %s = XNEWVEC (int, %s);\n",
8536 DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8537 fprintf (output_file, " %s ();\n}\n\n", DFA_CLEAN_INSN_CACHE_FUNC_NAME);
8540 /* The function outputs PHR interface function `dfa_finish'. */
8541 static void
8542 output_dfa_finish_func (void)
8544 fprintf (output_file, "void\n%s (void)\n{\n free (%s);\n}\n\n",
8545 DFA_FINISH_FUNC_NAME, DFA_INSN_CODES_VARIABLE_NAME);
8550 /* The page contains code for output description file (readable
8551 representation of original description and generated DFA(s). */
8553 /* The function outputs string representation of IR reservation. */
8554 static void
8555 output_regexp (regexp_t regexp)
8557 fprintf (output_description_file, "%s", regexp_representation (regexp));
8558 finish_regexp_representation ();
8561 /* Output names of units in LIST separated by comma. */
8562 static void
8563 output_unit_set_el_list (unit_set_el_t list)
8565 unit_set_el_t el;
8567 for (el = list; el != NULL; el = el->next_unit_set_el)
8569 if (el != list)
8570 fprintf (output_description_file, ", ");
8571 fprintf (output_description_file, "%s", el->unit_decl->name);
8575 /* Output patterns in LIST separated by comma. */
8576 static void
8577 output_pattern_set_el_list (pattern_set_el_t list)
8579 pattern_set_el_t el;
8580 int i;
8582 for (el = list; el != NULL; el = el->next_pattern_set_el)
8584 if (el != list)
8585 fprintf (output_description_file, ", ");
8586 for (i = 0; i < el->units_num; i++)
8587 fprintf (output_description_file, (i == 0 ? "%s" : " %s"),
8588 el->unit_decls [i]->name);
8592 /* The function outputs string representation of IR define_reservation
8593 and define_insn_reservation. */
8594 static void
8595 output_description (void)
8597 decl_t decl;
8598 int i;
8600 for (i = 0; i < description->decls_num; i++)
8602 decl = description->decls [i];
8603 if (decl->mode == dm_unit)
8605 if (DECL_UNIT (decl)->excl_list != NULL)
8607 fprintf (output_description_file, "unit %s exclusion_set: ",
8608 DECL_UNIT (decl)->name);
8609 output_unit_set_el_list (DECL_UNIT (decl)->excl_list);
8610 fprintf (output_description_file, "\n");
8612 if (DECL_UNIT (decl)->presence_list != NULL)
8614 fprintf (output_description_file, "unit %s presence_set: ",
8615 DECL_UNIT (decl)->name);
8616 output_pattern_set_el_list (DECL_UNIT (decl)->presence_list);
8617 fprintf (output_description_file, "\n");
8619 if (DECL_UNIT (decl)->final_presence_list != NULL)
8621 fprintf (output_description_file, "unit %s final_presence_set: ",
8622 DECL_UNIT (decl)->name);
8623 output_pattern_set_el_list
8624 (DECL_UNIT (decl)->final_presence_list);
8625 fprintf (output_description_file, "\n");
8627 if (DECL_UNIT (decl)->absence_list != NULL)
8629 fprintf (output_description_file, "unit %s absence_set: ",
8630 DECL_UNIT (decl)->name);
8631 output_pattern_set_el_list (DECL_UNIT (decl)->absence_list);
8632 fprintf (output_description_file, "\n");
8634 if (DECL_UNIT (decl)->final_absence_list != NULL)
8636 fprintf (output_description_file, "unit %s final_absence_set: ",
8637 DECL_UNIT (decl)->name);
8638 output_pattern_set_el_list
8639 (DECL_UNIT (decl)->final_absence_list);
8640 fprintf (output_description_file, "\n");
8644 fprintf (output_description_file, "\n");
8645 for (i = 0; i < description->decls_num; i++)
8647 decl = description->decls [i];
8648 if (decl->mode == dm_reserv)
8650 fprintf (output_description_file, "reservation %s: ",
8651 DECL_RESERV (decl)->name);
8652 output_regexp (DECL_RESERV (decl)->regexp);
8653 fprintf (output_description_file, "\n");
8655 else if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
8657 fprintf (output_description_file, "insn reservation %s ",
8658 DECL_INSN_RESERV (decl)->name);
8659 print_rtl (output_description_file,
8660 DECL_INSN_RESERV (decl)->condexp);
8661 fprintf (output_description_file, ": ");
8662 output_regexp (DECL_INSN_RESERV (decl)->regexp);
8663 fprintf (output_description_file, "\n");
8665 else if (decl->mode == dm_bypass)
8666 fprintf (output_description_file, "bypass %d %s %s\n",
8667 DECL_BYPASS (decl)->latency,
8668 DECL_BYPASS (decl)->out_insn_name,
8669 DECL_BYPASS (decl)->in_insn_name);
8671 fprintf (output_description_file, "\n\f\n");
8674 /* The function outputs name of AUTOMATON. */
8675 static void
8676 output_automaton_name (FILE *f, automaton_t automaton)
8678 if (automaton->corresponding_automaton_decl == NULL)
8679 fprintf (f, "#%d", automaton->automaton_order_num);
8680 else
8681 fprintf (f, "`%s'", automaton->corresponding_automaton_decl->name);
8684 /* Maximal length of line for pretty printing into description
8685 file. */
8686 #define MAX_LINE_LENGTH 70
8688 /* The function outputs units name belonging to AUTOMATON. */
8689 static void
8690 output_automaton_units (automaton_t automaton)
8692 decl_t decl;
8693 const char *name;
8694 int curr_line_length;
8695 int there_is_an_automaton_unit;
8696 int i;
8698 fprintf (output_description_file, "\n Corresponding units:\n");
8699 fprintf (output_description_file, " ");
8700 curr_line_length = 4;
8701 there_is_an_automaton_unit = 0;
8702 for (i = 0; i < description->decls_num; i++)
8704 decl = description->decls [i];
8705 if (decl->mode == dm_unit
8706 && (DECL_UNIT (decl)->corresponding_automaton_num
8707 == automaton->automaton_order_num))
8709 there_is_an_automaton_unit = 1;
8710 name = DECL_UNIT (decl)->name;
8711 if (curr_line_length + strlen (name) + 1 > MAX_LINE_LENGTH )
8713 curr_line_length = strlen (name) + 4;
8714 fprintf (output_description_file, "\n ");
8716 else
8718 curr_line_length += strlen (name) + 1;
8719 fprintf (output_description_file, " ");
8721 fprintf (output_description_file, "%s", name);
8724 if (!there_is_an_automaton_unit)
8725 fprintf (output_description_file, "<None>");
8726 fprintf (output_description_file, "\n\n");
8729 /* The following variable is used for forming array of all possible cpu unit
8730 reservations described by the current DFA state. */
8731 static VEC(reserv_sets_t,heap) *state_reservs;
8733 /* The function forms `state_reservs' for STATE. */
8734 static void
8735 add_state_reservs (state_t state)
8737 alt_state_t curr_alt_state;
8739 if (state->component_states != NULL)
8740 for (curr_alt_state = state->component_states;
8741 curr_alt_state != NULL;
8742 curr_alt_state = curr_alt_state->next_sorted_alt_state)
8743 add_state_reservs (curr_alt_state->state);
8744 else
8745 VEC_safe_push (reserv_sets_t,heap, state_reservs, state->reservs);
8748 /* The function outputs readable representation of all out arcs of
8749 STATE. */
8750 static void
8751 output_state_arcs (state_t state)
8753 arc_t arc;
8754 ainsn_t ainsn;
8755 const char *insn_name;
8756 int curr_line_length;
8758 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
8760 ainsn = arc->insn;
8761 gcc_assert (ainsn->first_insn_with_same_reservs);
8762 fprintf (output_description_file, " ");
8763 curr_line_length = 7;
8764 fprintf (output_description_file, "%2d: ", ainsn->insn_equiv_class_num);
8767 insn_name = ainsn->insn_reserv_decl->name;
8768 if (curr_line_length + strlen (insn_name) > MAX_LINE_LENGTH)
8770 if (ainsn != arc->insn)
8772 fprintf (output_description_file, ",\n ");
8773 curr_line_length = strlen (insn_name) + 6;
8775 else
8776 curr_line_length += strlen (insn_name);
8778 else
8780 curr_line_length += strlen (insn_name);
8781 if (ainsn != arc->insn)
8783 curr_line_length += 2;
8784 fprintf (output_description_file, ", ");
8787 fprintf (output_description_file, "%s", insn_name);
8788 ainsn = ainsn->next_same_reservs_insn;
8790 while (ainsn != NULL);
8791 fprintf (output_description_file, " %d \n",
8792 arc->to_state->order_state_num);
8794 fprintf (output_description_file, "\n");
8797 /* The following function is used for sorting possible cpu unit
8798 reservation of a DFA state. */
8799 static int
8800 state_reservs_cmp (const void *reservs_ptr_1, const void *reservs_ptr_2)
8802 return reserv_sets_cmp (*(const_reserv_sets_t const*) reservs_ptr_1,
8803 *(const_reserv_sets_t const*) reservs_ptr_2);
8806 /* The following function is used for sorting possible cpu unit
8807 reservation of a DFA state. */
8808 static void
8809 remove_state_duplicate_reservs (void)
8811 size_t i, j;
8813 for (i = 1, j = 0; i < VEC_length (reserv_sets_t, state_reservs); i++)
8814 if (reserv_sets_cmp (VEC_index (reserv_sets_t, state_reservs, j),
8815 VEC_index (reserv_sets_t, state_reservs, i)))
8817 j++;
8818 VEC_replace (reserv_sets_t, state_reservs, j,
8819 VEC_index (reserv_sets_t, state_reservs, i));
8821 VEC_truncate (reserv_sets_t, state_reservs, j + 1);
8824 /* The following function output readable representation of DFA(s)
8825 state used for fast recognition of pipeline hazards. State is
8826 described by possible (current and scheduled) cpu unit
8827 reservations. */
8828 static void
8829 output_state (state_t state)
8831 size_t i;
8833 state_reservs = 0;
8835 fprintf (output_description_file, " State #%d", state->order_state_num);
8836 fprintf (output_description_file,
8837 state->new_cycle_p ? " (new cycle)\n" : "\n");
8838 add_state_reservs (state);
8839 qsort (VEC_address (reserv_sets_t, state_reservs),
8840 VEC_length (reserv_sets_t, state_reservs),
8841 sizeof (reserv_sets_t), state_reservs_cmp);
8842 remove_state_duplicate_reservs ();
8843 for (i = 1; i < VEC_length (reserv_sets_t, state_reservs); i++)
8845 fprintf (output_description_file, " ");
8846 output_reserv_sets (output_description_file,
8847 VEC_index (reserv_sets_t, state_reservs, i));
8848 fprintf (output_description_file, "\n");
8850 fprintf (output_description_file, "\n");
8851 output_state_arcs (state);
8852 VEC_free (reserv_sets_t,heap, state_reservs);
8855 /* The following function output readable representation of
8856 DFAs used for fast recognition of pipeline hazards. */
8857 static void
8858 output_automaton_descriptions (void)
8860 automaton_t automaton;
8862 for (automaton = description->first_automaton;
8863 automaton != NULL;
8864 automaton = automaton->next_automaton)
8866 fprintf (output_description_file, "\nAutomaton ");
8867 output_automaton_name (output_description_file, automaton);
8868 fprintf (output_description_file, "\n");
8869 output_automaton_units (automaton);
8870 pass_states (automaton, output_state);
8876 /* The page contains top level function for generation DFA(s) used for
8877 PHR. */
8879 /* The function outputs statistics about work of different phases of
8880 DFA generator. */
8881 static void
8882 output_statistics (FILE *f)
8884 automaton_t automaton;
8885 int states_num;
8886 #ifndef NDEBUG
8887 int transition_comb_vect_els = 0;
8888 int transition_full_vect_els = 0;
8889 int min_issue_delay_vect_els = 0;
8890 int locked_states = 0;
8891 #endif
8893 for (automaton = description->first_automaton;
8894 automaton != NULL;
8895 automaton = automaton->next_automaton)
8897 fprintf (f, "\nAutomaton ");
8898 output_automaton_name (f, automaton);
8899 fprintf (f, "\n %5d NDFA states, %5d NDFA arcs\n",
8900 automaton->NDFA_states_num, automaton->NDFA_arcs_num);
8901 fprintf (f, " %5d DFA states, %5d DFA arcs\n",
8902 automaton->DFA_states_num, automaton->DFA_arcs_num);
8903 states_num = automaton->DFA_states_num;
8904 if (!no_minimization_flag)
8906 fprintf (f, " %5d minimal DFA states, %5d minimal DFA arcs\n",
8907 automaton->minimal_DFA_states_num,
8908 automaton->minimal_DFA_arcs_num);
8909 states_num = automaton->minimal_DFA_states_num;
8911 fprintf (f, " %5d all insns %5d insn equivalence classes\n",
8912 description->insns_num, automaton->insn_equiv_classes_num);
8913 fprintf (f, " %d locked states\n", automaton->locked_states);
8914 #ifndef NDEBUG
8915 fprintf
8916 (f, "%5ld transition comb vector els, %5ld trans table els: %s\n",
8917 (long) VEC_length (vect_el_t, automaton->trans_table->comb_vect),
8918 (long) VEC_length (vect_el_t, automaton->trans_table->full_vect),
8919 (comb_vect_p (automaton->trans_table)
8920 ? "use comb vect" : "use simple vect"));
8921 fprintf
8922 (f, "%5ld min delay table els, compression factor %d\n",
8923 (long) states_num * automaton->insn_equiv_classes_num,
8924 automaton->min_issue_delay_table_compression_factor);
8925 transition_comb_vect_els
8926 += VEC_length (vect_el_t, automaton->trans_table->comb_vect);
8927 transition_full_vect_els
8928 += VEC_length (vect_el_t, automaton->trans_table->full_vect);
8929 min_issue_delay_vect_els
8930 += states_num * automaton->insn_equiv_classes_num;
8931 locked_states
8932 += automaton->locked_states;
8933 #endif
8935 #ifndef NDEBUG
8936 fprintf (f, "\n%5d all allocated states, %5d all allocated arcs\n",
8937 allocated_states_num, allocated_arcs_num);
8938 fprintf (f, "%5d all allocated alternative states\n",
8939 allocated_alt_states_num);
8940 fprintf (f, "%5d all transition comb vector els, %5d all trans table els\n",
8941 transition_comb_vect_els, transition_full_vect_els);
8942 fprintf (f, "%5d all min delay table els\n", min_issue_delay_vect_els);
8943 fprintf (f, "%5d all locked states\n", locked_states);
8944 #endif
8947 /* The function output times of work of different phases of DFA
8948 generator. */
8949 static void
8950 output_time_statistics (FILE *f)
8952 fprintf (f, "\n transformation: ");
8953 print_active_time (f, transform_time);
8954 fprintf (f, (!ndfa_flag ? ", building DFA: " : ", building NDFA: "));
8955 print_active_time (f, NDFA_time);
8956 if (ndfa_flag)
8958 fprintf (f, ", NDFA -> DFA: ");
8959 print_active_time (f, NDFA_to_DFA_time);
8961 fprintf (f, "\n DFA minimization: ");
8962 print_active_time (f, minimize_time);
8963 fprintf (f, ", making insn equivalence: ");
8964 print_active_time (f, equiv_time);
8965 fprintf (f, "\n all automaton generation: ");
8966 print_active_time (f, automaton_generation_time);
8967 fprintf (f, ", output: ");
8968 print_active_time (f, output_time);
8969 fprintf (f, "\n");
8972 /* The function generates DFA (deterministic finite state automaton)
8973 for fast recognition of pipeline hazards. No errors during
8974 checking must be fixed before this function call. */
8975 static void
8976 generate (void)
8978 automata_num = split_argument;
8979 if (description->units_num < automata_num)
8980 automata_num = description->units_num;
8981 initiate_states ();
8982 initiate_arcs ();
8983 initiate_automata_lists ();
8984 initiate_pass_states ();
8985 initiate_excl_sets ();
8986 initiate_presence_absence_pattern_sets ();
8987 automaton_generation_time = create_ticker ();
8988 create_automata ();
8989 ticker_off (&automaton_generation_time);
8994 /* This page mainly contains top level functions of pipeline hazards
8995 description translator. */
8997 /* The following macro value is suffix of name of description file of
8998 pipeline hazards description translator. */
8999 #define STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX ".dfa"
9001 /* The function returns suffix of given file name. The returned
9002 string can not be changed. */
9003 static const char *
9004 file_name_suffix (const char *file_name)
9006 const char *last_period;
9008 for (last_period = NULL; *file_name != '\0'; file_name++)
9009 if (*file_name == '.')
9010 last_period = file_name;
9011 return (last_period == NULL ? file_name : last_period);
9014 /* The function returns base name of given file name, i.e. pointer to
9015 first char after last `/' (or `\' for WIN32) in given file name,
9016 given file name itself if the directory name is absent. The
9017 returned string can not be changed. */
9018 static const char *
9019 base_file_name (const char *file_name)
9021 int directory_name_length;
9023 directory_name_length = strlen (file_name);
9024 #ifdef WIN32
9025 while (directory_name_length >= 0 && file_name[directory_name_length] != '/'
9026 && file_name[directory_name_length] != '\\')
9027 #else
9028 while (directory_name_length >= 0 && file_name[directory_name_length] != '/')
9029 #endif
9030 directory_name_length--;
9031 return file_name + directory_name_length + 1;
9034 /* The following is top level function to initialize the work of
9035 pipeline hazards description translator. */
9036 static void
9037 initiate_automaton_gen (int argc, char **argv)
9039 const char *base_name;
9040 int i;
9042 ndfa_flag = 0;
9043 split_argument = 0; /* default value */
9044 no_minimization_flag = 0;
9045 time_flag = 0;
9046 stats_flag = 0;
9047 v_flag = 0;
9048 w_flag = 0;
9049 progress_flag = 0;
9050 for (i = 2; i < argc; i++)
9051 if (strcmp (argv [i], NO_MINIMIZATION_OPTION) == 0)
9052 no_minimization_flag = 1;
9053 else if (strcmp (argv [i], TIME_OPTION) == 0)
9054 time_flag = 1;
9055 else if (strcmp (argv [i], STATS_OPTION) == 0)
9056 stats_flag = 1;
9057 else if (strcmp (argv [i], V_OPTION) == 0)
9058 v_flag = 1;
9059 else if (strcmp (argv [i], W_OPTION) == 0)
9060 w_flag = 1;
9061 else if (strcmp (argv [i], NDFA_OPTION) == 0)
9062 ndfa_flag = 1;
9063 else if (strcmp (argv [i], PROGRESS_OPTION) == 0)
9064 progress_flag = 1;
9065 else if (strcmp (argv [i], "-split") == 0)
9067 if (i + 1 >= argc)
9068 fatal ("-split has no argument.");
9069 fatal ("option `-split' has not been implemented yet\n");
9070 /* split_argument = atoi (argument_vect [i + 1]); */
9073 /* Initialize IR storage. */
9074 obstack_init (&irp);
9075 initiate_automaton_decl_table ();
9076 initiate_insn_decl_table ();
9077 initiate_decl_table ();
9078 output_file = stdout;
9079 output_description_file = NULL;
9080 base_name = base_file_name (argv[1]);
9081 obstack_grow (&irp, base_name,
9082 strlen (base_name) - strlen (file_name_suffix (base_name)));
9083 obstack_grow (&irp, STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX,
9084 strlen (STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX) + 1);
9085 obstack_1grow (&irp, '\0');
9086 output_description_file_name = obstack_base (&irp);
9087 obstack_finish (&irp);
9090 /* The following function checks existence at least one arc marked by
9091 each insn. */
9092 static void
9093 check_automata_insn_issues (void)
9095 automaton_t automaton;
9096 ainsn_t ainsn, reserv_ainsn;
9098 for (automaton = description->first_automaton;
9099 automaton != NULL;
9100 automaton = automaton->next_automaton)
9102 for (ainsn = automaton->ainsn_list;
9103 ainsn != NULL;
9104 ainsn = ainsn->next_ainsn)
9105 if (ainsn->first_insn_with_same_reservs && !ainsn->arc_exists_p)
9107 for (reserv_ainsn = ainsn;
9108 reserv_ainsn != NULL;
9109 reserv_ainsn = reserv_ainsn->next_same_reservs_insn)
9110 if (automaton->corresponding_automaton_decl != NULL)
9112 if (!w_flag)
9113 error ("Automaton `%s': Insn `%s' will never be issued",
9114 automaton->corresponding_automaton_decl->name,
9115 reserv_ainsn->insn_reserv_decl->name);
9116 else
9117 warning
9118 (0, "Automaton `%s': Insn `%s' will never be issued",
9119 automaton->corresponding_automaton_decl->name,
9120 reserv_ainsn->insn_reserv_decl->name);
9122 else
9124 if (!w_flag)
9125 error ("Insn `%s' will never be issued",
9126 reserv_ainsn->insn_reserv_decl->name);
9127 else
9128 warning (0, "Insn `%s' will never be issued",
9129 reserv_ainsn->insn_reserv_decl->name);
9135 /* The following vla is used for storing pointers to all achieved
9136 states. */
9137 static VEC(state_t,heap) *automaton_states;
9139 /* This function is called by function pass_states to add an achieved
9140 STATE. */
9141 static void
9142 add_automaton_state (state_t state)
9144 VEC_safe_push (state_t,heap, automaton_states, state);
9147 /* The following function forms list of important automata (whose
9148 states may be changed after the insn issue) for each insn. */
9149 static void
9150 form_important_insn_automata_lists (void)
9152 automaton_t automaton;
9153 decl_t decl;
9154 ainsn_t ainsn;
9155 arc_t arc;
9156 int i;
9157 size_t n;
9159 automaton_states = 0;
9160 /* Mark important ainsns. */
9161 for (automaton = description->first_automaton;
9162 automaton != NULL;
9163 automaton = automaton->next_automaton)
9165 VEC_truncate (state_t, automaton_states, 0);
9166 pass_states (automaton, add_automaton_state);
9167 for (n = 0; n < VEC_length (state_t, automaton_states); n++)
9169 state_t s = VEC_index (state_t, automaton_states, n);
9170 for (arc = first_out_arc (s);
9171 arc != NULL;
9172 arc = next_out_arc (arc))
9173 if (arc->to_state != s)
9175 gcc_assert (arc->insn->first_insn_with_same_reservs);
9176 for (ainsn = arc->insn;
9177 ainsn != NULL;
9178 ainsn = ainsn->next_same_reservs_insn)
9179 ainsn->important_p = TRUE;
9183 VEC_free (state_t,heap, automaton_states);
9185 /* Create automata sets for the insns. */
9186 for (i = 0; i < description->decls_num; i++)
9188 decl = description->decls [i];
9189 if (decl->mode == dm_insn_reserv)
9191 automata_list_start ();
9192 for (automaton = description->first_automaton;
9193 automaton != NULL;
9194 automaton = automaton->next_automaton)
9195 for (ainsn = automaton->ainsn_list;
9196 ainsn != NULL;
9197 ainsn = ainsn->next_ainsn)
9198 if (ainsn->important_p
9199 && ainsn->insn_reserv_decl == DECL_INSN_RESERV (decl))
9201 automata_list_add (automaton);
9202 break;
9204 DECL_INSN_RESERV (decl)->important_automata_list
9205 = automata_list_finish ();
9211 /* The following is top level function to generate automat(a,on) for
9212 fast recognition of pipeline hazards. */
9213 static void
9214 expand_automata (void)
9216 int i;
9218 description = XCREATENODEVAR (struct description,
9219 sizeof (struct description)
9220 /* One entry for cycle advancing insn. */
9221 + sizeof (decl_t) * VEC_length (decl_t, decls));
9222 description->decls_num = VEC_length (decl_t, decls);
9223 description->query_units_num = 0;
9224 for (i = 0; i < description->decls_num; i++)
9226 description->decls [i] = VEC_index (decl_t, decls, i);
9227 if (description->decls [i]->mode == dm_unit
9228 && DECL_UNIT (description->decls [i])->query_p)
9229 DECL_UNIT (description->decls [i])->query_num
9230 = description->query_units_num++;
9232 all_time = create_ticker ();
9233 check_time = create_ticker ();
9234 if (progress_flag)
9235 fprintf (stderr, "Check description...");
9236 check_all_description ();
9237 if (progress_flag)
9238 fprintf (stderr, "done\n");
9239 ticker_off (&check_time);
9240 generation_time = create_ticker ();
9241 if (!have_error)
9243 transform_insn_regexps ();
9244 check_unit_distributions_to_automata ();
9246 if (!have_error)
9248 generate ();
9249 check_automata_insn_issues ();
9251 if (!have_error)
9253 form_important_insn_automata_lists ();
9255 ticker_off (&generation_time);
9258 /* The following is top level function to output PHR and to finish
9259 work with pipeline description translator. */
9260 static void
9261 write_automata (void)
9263 output_time = create_ticker ();
9264 if (progress_flag)
9265 fprintf (stderr, "Forming and outputting automata tables...");
9266 output_tables ();
9267 if (progress_flag)
9269 fprintf (stderr, "done\n");
9270 fprintf (stderr, "Output functions to work with automata...");
9272 output_chip_definitions ();
9273 output_max_insn_queue_index_def ();
9274 output_internal_min_issue_delay_func ();
9275 output_internal_trans_func ();
9276 /* Cache of insn dfa codes: */
9277 fprintf (output_file, "\nstatic int *%s;\n", DFA_INSN_CODES_VARIABLE_NAME);
9278 fprintf (output_file, "\nstatic int %s;\n\n",
9279 DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
9280 output_dfa_insn_code_func ();
9281 output_trans_func ();
9282 output_min_issue_delay_func ();
9283 output_internal_dead_lock_func ();
9284 output_dead_lock_func ();
9285 output_size_func ();
9286 output_internal_reset_func ();
9287 output_reset_func ();
9288 output_min_insn_conflict_delay_func ();
9289 output_default_latencies ();
9290 output_internal_insn_latency_func ();
9291 output_insn_latency_func ();
9292 output_internal_maximal_insn_latency_func ();
9293 output_maximal_insn_latency_func ();
9294 output_print_reservation_func ();
9295 /* Output function get_cpu_unit_code. */
9296 fprintf (output_file, "\n#if %s\n\n", CPU_UNITS_QUERY_MACRO_NAME);
9297 output_get_cpu_unit_code_func ();
9298 output_cpu_unit_reservation_p ();
9299 output_insn_has_dfa_reservation_p ();
9300 fprintf (output_file, "\n#endif /* #if %s */\n\n",
9301 CPU_UNITS_QUERY_MACRO_NAME);
9302 output_dfa_clean_insn_cache_func ();
9303 output_dfa_start_func ();
9304 output_dfa_finish_func ();
9305 if (progress_flag)
9306 fprintf (stderr, "done\n");
9307 if (v_flag)
9309 output_description_file = fopen (output_description_file_name, "w");
9310 if (output_description_file == NULL)
9312 perror (output_description_file_name);
9313 exit (FATAL_EXIT_CODE);
9315 if (progress_flag)
9316 fprintf (stderr, "Output automata description...");
9317 output_description ();
9318 output_automaton_descriptions ();
9319 if (progress_flag)
9320 fprintf (stderr, "done\n");
9321 output_statistics (output_description_file);
9323 if (stats_flag)
9324 output_statistics (stderr);
9325 ticker_off (&output_time);
9326 if (time_flag)
9327 output_time_statistics (stderr);
9328 finish_states ();
9329 finish_arcs ();
9330 finish_automata_lists ();
9331 if (time_flag)
9333 fprintf (stderr, "Summary:\n");
9334 fprintf (stderr, " check time ");
9335 print_active_time (stderr, check_time);
9336 fprintf (stderr, ", generation time ");
9337 print_active_time (stderr, generation_time);
9338 fprintf (stderr, ", all time ");
9339 print_active_time (stderr, all_time);
9340 fprintf (stderr, "\n");
9342 /* Finish all work. */
9343 if (output_description_file != NULL)
9345 fflush (output_description_file);
9346 if (ferror (stdout) != 0)
9347 fatal ("Error in writing DFA description file %s: %s",
9348 output_description_file_name, xstrerror (errno));
9349 fclose (output_description_file);
9351 finish_automaton_decl_table ();
9352 finish_insn_decl_table ();
9353 finish_decl_table ();
9354 obstack_free (&irp, NULL);
9355 if (have_error && output_description_file != NULL)
9356 remove (output_description_file_name);
9360 main (int argc, char **argv)
9362 rtx desc;
9364 progname = "genautomata";
9366 if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
9367 return (FATAL_EXIT_CODE);
9369 initiate_automaton_gen (argc, argv);
9370 while (1)
9372 int lineno;
9373 int insn_code_number;
9375 desc = read_md_rtx (&lineno, &insn_code_number);
9376 if (desc == NULL)
9377 break;
9379 switch (GET_CODE (desc))
9381 case DEFINE_CPU_UNIT:
9382 gen_cpu_unit (desc);
9383 break;
9385 case DEFINE_QUERY_CPU_UNIT:
9386 gen_query_cpu_unit (desc);
9387 break;
9389 case DEFINE_BYPASS:
9390 gen_bypass (desc);
9391 break;
9393 case EXCLUSION_SET:
9394 gen_excl_set (desc);
9395 break;
9397 case PRESENCE_SET:
9398 gen_presence_set (desc);
9399 break;
9401 case FINAL_PRESENCE_SET:
9402 gen_final_presence_set (desc);
9403 break;
9405 case ABSENCE_SET:
9406 gen_absence_set (desc);
9407 break;
9409 case FINAL_ABSENCE_SET:
9410 gen_final_absence_set (desc);
9411 break;
9413 case DEFINE_AUTOMATON:
9414 gen_automaton (desc);
9415 break;
9417 case AUTOMATA_OPTION:
9418 gen_automata_option (desc);
9419 break;
9421 case DEFINE_RESERVATION:
9422 gen_reserv (desc);
9423 break;
9425 case DEFINE_INSN_RESERVATION:
9426 gen_insn_reserv (desc);
9427 break;
9429 default:
9430 break;
9434 if (have_error)
9435 return FATAL_EXIT_CODE;
9437 puts ("/* Generated automatically by the program `genautomata'\n"
9438 " from the machine description file `md'. */\n\n"
9439 "#include \"config.h\"\n"
9440 "#include \"system.h\"\n"
9441 "#include \"coretypes.h\"\n"
9442 "#include \"tm.h\"\n"
9443 "#include \"rtl.h\"\n"
9444 "#include \"tm_p.h\"\n"
9445 "#include \"insn-config.h\"\n"
9446 "#include \"recog.h\"\n"
9447 "#include \"regs.h\"\n"
9448 "#include \"real.h\"\n"
9449 "#include \"output.h\"\n"
9450 "#include \"insn-attr.h\"\n"
9451 "#include \"toplev.h\"\n"
9452 "#include \"flags.h\"\n"
9453 "#include \"function.h\"\n");
9455 if (VEC_length (decl_t, decls) > 0)
9457 expand_automata ();
9458 write_automata ();
9461 fflush (stdout);
9462 return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);